Sign in to follow this  
Followers 0
kristo

How can I detect clicks in injected system menu

20 posts in this topic

#1 ·  Posted (edited)

I'm trying to add an item to the system menu of another application. No problem.

But the following pice of code works without returning any menu items.

I don't think that the problem has been adressed this way anywhere else.

At least i couldn't find something usable.

We had an example with a standard menu (the example used was modified from that)

and there's AnyGui, but that does not offer the desired functions.

This seems quite a bit of a challenge.

Here's the code:

#include <GUIConstantsEx.au3>
#include <WindowsConstants.au3>
#include <GuiMenu.au3>


Run("Notepad.exe")
WinWaitActive("[CLASS:Notepad]")
$hGUI = WinGetHandle("[CLASS:Notepad]")

$hSystemMenu = _GUICtrlMenu_GetSystemMenu($hGUI)
_GUICtrlMenu_AppendMenu($hSystemMenu, $MF_SEPARATOR, 0, "")
_GUICtrlMenu_AppendMenu($hSystemMenu, $MF_STRING, 0x3000, "New Sysmenu Item")

GUIRegisterMsg($WM_SYSCOMMAND, "_WM_SYSCOMMAND")

$sMenuSelection = ""

While WinExists($hGUI)

     If $sMenuSelection <> "" Then
         MsgBox(0, "New Menu", "You selected " & $sMenuSelection)
         $sMenuSelection = ""
     EndIf

WEnd

Func _WM_SYSCOMMAND($hGUI, $iMsg, $wParam, $lParam)

If $iMsg = $WM_SYSCOMMAND Then
     If _WinAPI_LoWord($wParam) = 0x3000 Then
         $sMenuSelection = "New Sysmenu Item"
     EndIf
EndIf

EndFunc
Edited by kristo

Cheap, Fast, Good - Choose any two

Share this post


Link to post
Share on other sites



Hi,

You can not register the WM of an external application using the GUIRegisterMsg function.

The trick is to hook the events, take a look

Br, FireFox.


 

OS : Win XP SP2 (32 bits) / Win 7 SP1 (64 bits) / Win 8 (64 bits) | Autoit version: latest stable / beta.
Hardware : Intel(R) Core(TM) i5-2400 CPU @ 3.10Ghz / 8 GiB RAM DDR3.

My UDFs : Skype UDF | TrayIconEx UDF | GUI Panel UDF | Excel XML UDF | Is_Pressed_UDF

My Projects : YouTube Multi-downloader | FTP Easy-UP | Lock'n | WinKill | AVICapture | Skype TM | Tap Maker | ShellNew | Scriptner | Const Replacer | FT_Pocket | Chrome theme maker

My Examples : Capture toolIP Camera | Crosshair | Draw Captured Region | Picture Screensaver | Jscreenfix | Drivetemp | Picture viewer

My Snippets : Basic TCP | Systray_GetIconIndex | Intercept End task | Winpcap various | Advanced HotKeySet | Transparent Edit control

 

Share this post


Link to post
Share on other sites

; Original and maybe better code by Melba
#include <WindowsConstants.au3>
#include <GuiMenu.au3>
#include <Misc.au3>

Global $hWnd, $hMenu, $sCurrent_Item = ""
Local $hDLL = DllOpen("user32.dll")

Global $Items_IDs[6][2] = [["SubItem &1", 0x1001],["SubItem &2", 0x1002],["Item &1", 0],["Item &2", 0x2001],["Item &3", 0x2002],["Item &4", 0x2003]]

Run("Notepad.exe")
WinWaitActive("[CLASS:Notepad]")
$hWnd = WinGetHandle("[CLASS:Notepad]")
$hMenu = _GUICtrlMenu_GetMenu($hWnd)

$hItem1 = _GUICtrlMenu_CreateMenu()
_GUICtrlMenu_InsertMenuItem($hItem1, 0, $Items_IDs[0][0], $Items_IDs[0][1])
_GUICtrlMenu_InsertMenuItem($hItem1, 1, $Items_IDs[1][0], $Items_IDs[1][1])

$hItem2 = _GUICtrlMenu_CreateMenu()
_GUICtrlMenu_InsertMenuItem($hItem2, 0, $Items_IDs[2][0], $Items_IDs[2][1], $hItem1)
_GUICtrlMenu_InsertMenuItem($hItem2, 1, $Items_IDs[3][0], $Items_IDs[3][1])
_GUICtrlMenu_InsertMenuItem($hItem2, 2, "", 0)
_GUICtrlMenu_InsertMenuItem($hItem2, 3, $Items_IDs[4][0], $Items_IDs[4][1])
_GUICtrlMenu_InsertMenuItem($hItem2, 4, $Items_IDs[5][0], $Items_IDs[5][1])
_GUICtrlMenu_InsertMenuItem($hMenu, 6, "&My Menu", 0, $hItem2)
_GUICtrlMenu_DrawMenuBar($hWnd)

While WinGetHandle("[CLASS:Notepad]") <> ""
$aInfo = _GUICtrlMenu_GetMenuBarInfo($hWnd)
If $aInfo[6] = True Then
  $sCurrent_Item = ""
  For $i = 0 To UBound($Items_IDs, 1) - 1
   If _GUICtrlMenu_GetItemHighlighted($hMenu, $Items_IDs[$i][1], False) Then
    If $Items_IDs[$i][0] <> $sCurrent_Item Then $sCurrent_Item = $Items_IDs[$i][0]
   EndIf
  Next
EndIf
If $sCurrent_Item <> "" Then
  If _IsPressed("01", $hDLL) Or _IsPressed("0D", $hDLL) Then
   ConsoleWrite($sCurrent_Item & " is clicked" & @CRLF)
   $sCurrent_Item = ""
   While _IsPressed("0D", $hDLL) Or _IsPressed("01", $hDLL)
    Sleep(10)
   WEnd
  EndIf
EndIf
Sleep(100)
WEnd

If WinGetHandle("[CLASS:Notepad]") = "" Then
DllClose($hDLL)
Exit
EndIf

Share this post


Link to post
Share on other sites

#4 ·  Posted (edited)

Ah, thanks so far FireFox.

Hi,

You can not register the WM of an external application using the GUIRegisterMsg function.

The trick is to hook the events, take a look

This at least gives me some respond to the menu events.

But how can I finally determine WHICH item was selected?

There seems to be no specific event per item.

My code looke now like this:

#include
#include

#include
#include
#include
#include
Global $hDLL, $hWinEventProc, $hHook

Global Const $EVENT_SYSTEM_SOUND = 0x0001 ;An MSAA event indicating that a sound was played.
Global Const $EVENT_SYSTEM_ALERT = 0x0002 ;An MSAA event indicating that an alert was generated.
Global Const $EVENT_SYSTEM_FOREGROUND = 0x0003 ;An MSAA event indicating that the foreground window changed.
Global Const $EVENT_SYSTEM_MENUSTART = 0x0004 ;An MSAA event indicating that a menu item on the menu bar was selected.
Global Const $EVENT_SYSTEM_MENUEND = 0x0005 ;An MSAA event indicating that a menu from the menu bar was closed.
Global Const $EVENT_SYSTEM_MENUPOPUPSTART = 0x0006 ;An MSAA event indicating that a pop-up menu was displayed.
Global Const $EVENT_SYSTEM_MENUPOPUPEND = 0x0007 ;An MSAA event indicating that a pop-up menu was closed.
Global Const $EVENT_SYSTEM_CAPTURESTART = 0x0008 ;An MSAA event indicating that a window has received mouse capture.
Global Const $EVENT_SYSTEM_CAPTUREEND = 0x0009 ;An MSAA event indicating that a window has lost mouse capture.
Global Const $EVENT_SYSTEM_DIALOGSTART = 0x0010 ;An MSAA event indicating that a dialog box was displayed.
Global Const $EVENT_SYSTEM_DIALOGEND = 0x0011 ;An MSAA event indicating that a dialog box was closed.
Global Const $EVENT_SYSTEM_SCROLLINGSTART = 0x0012 ;An MSAA event indicating that scrolling has started on a scroll bar.
Global Const $EVENT_SYSTEM_SCROLLINGEND = 0x0013 ;An MSAA event indicating that scrolling has ended on a scroll bar.
Global Const $EVENT_SYSTEM_SWITCHSTART = 0x0014 ;An MSAA event indicating that the user pressed ALT+TAB, which activates the switch window.
Global Const $EVENT_SYSTEM_SWITCHEND = 0x0015 ;An MSAA event indicating that the user released ALT+TAB.
Global Const $EVENT_SYSTEM_MINIMIZESTART = 0x0016 ;An MSAA event indicating that a window object is about to be minimized or maximized.
Global Const $EVENT_SYSTEM_MINIMIZEEND = 0x0017 ;An MSAA event indicating that a window object was minimized or maximized.
Global Const $EVENT_SYSTEM_MOVESIZESTART = 0x000A ;An MSAA event indicating that a window is being moved or resized.
Global Const $EVENT_SYSTEM_MOVESIZEEND = 0x000B ;An MSAA event indicating that the movement or resizing of a window is finished.
Global Const $EVENT_SYSTEM_CONTEXTHELPSTART = 0x000C ;An MSAA event indicating that a window entered context-sensitive Help mode.
Global Const $EVENT_SYSTEM_CONTEXTHELPEND = 0x000D ;An MSAA event indicating that a window exited context-sensitive Help mode.
Global Const $EVENT_SYSTEM_DRAGDROPSTART = 0x000E ;An MSAA event indicating that an application is about to enter drag-and-drop mode.
Global Const $EVENT_SYSTEM_DRAGDROPEND = 0x000F ;An MSAA event indicating that an application is about to exit drag-and-drop mode.

; EVENT_OBJECT events are triggered quite often, handle with care...
Global Const $EVENT_OBJECT_CREATE = 0x8000 ;An MSAA event indicating that an object was created.
Global Const $EVENT_OBJECT_DESTROY = 0x8001 ;An MSAA event indicating that an object was destroyed.
Global Const $EVENT_OBJECT_SHOW = 0x8002 ;An MSAA event indicating that a hidden object is being shown.
Global Const $EVENT_OBJECT_HIDE = 0x8003 ;An MSAA event indicating that an object is being hidden.
Global Const $EVENT_OBJECT_REORDER = 0x8004 ;An MSAA event indicating that a container object has added, removed, or reordered its children.
Global Const $EVENT_OBJECT_FOCUS = 0x8005 ;An MSAA event indicating that an object has received the keyboard focus.
Global Const $EVENT_OBJECT_SELECTION = 0x8006 ;An MSAA event indicating that the selection within a container object changed.
Global Const $EVENT_OBJECT_SELECTIONADD = 0x8007 ;An MSAA event indicating that an item within a container object was added to the selection.
Global Const $EVENT_OBJECT_SELECTIONREMOVE = 0x8008 ;An MSAA event indicating that an item within a container object was removed from the selection.
Global Const $EVENT_OBJECT_SELECTIONWITHIN = 0x8009 ;An MSAA event indicating that numerous selection changes occurred within a container object.
Global Const $EVENT_OBJECT_HELPCHANGE = 0x8010 ;An MSAA event indicating that an object's MSAA Help property changed.
Global Const $EVENT_OBJECT_DEFACTIonchange = 0x8011 ;An MSAA event indicating that an object's MSAA DefaultAction property changed.
Global Const $EVENT_OBJECT_ACCELERATORCHANGE = 0x8012 ;An MSAA event indicating that an object's MSAA KeyboardShortcut property changed.
Global Const $EVENT_OBJECT_INVOKED = 0x8013 ;An MSAA event indicating that an object has been invoked; for example, the user has clicked a button.
Global Const $EVENT_OBJECT_TEXTSELECTIonchangeD = 0x8014 ;An MSAA event indicating that an object's text selection has changed.
Global Const $EVENT_OBJECT_CONTENTSCROLLED = 0x8015 ;An MSAA event indicating that the scrolling of a window object has ended.
Global Const $EVENT_OBJECT_STATECHANGE = 0x800A ;An MSAA event indicating that an object's state has changed.
Global Const $EVENT_OBJECT_LOCATIonchange = 0x800B ;An MSAA event indicating that an object has changed location, shape, or size.
Global Const $EVENT_OBJECT_NAMECHANGE = 0x800C ;An MSAA event indicating that an object's MSAA Name property changed.
Global Const $EVENT_OBJECT_DESCRIPTIonchange = 0x800D ;An MSAA event indicating that an object's MSAA Description property changed.
Global Const $EVENT_OBJECT_VALUECHANGE = 0x800E ;An MSAA event indicating that an object's MSAA Value property changed.
Global Const $EVENT_OBJECT_PARENTCHANGE = 0x800F ;An MSAA event indicating that an object has a new parent object.

;minimum and maximum events
;to monitor one event type only use same event for min/max
Global $EVENT_Min = $EVENT_SYSTEM_SOUND
Global $EVENT_Max = $EVENT_OBJECT_PARENTCHANGE

Run("Notepad.exe")
WinWaitActive("[CLASS:Notepad]")
$hGUI = WinGetHandle("[CLASS:Notepad]")

$hSystemMenu = _GUICtrlMenu_GetSystemMenu($hGUI)
_GUICtrlMenu_GetItemCount($hSystemMenu)
_GUICtrlMenu_AppendMenu($hSystemMenu, $MF_SEPARATOR, 0, "")
_GUICtrlMenu_AppendMenu($hSystemMenu, $MF_STRING, 0x3000, "New System Menu Item1")
_GUICtrlMenu_AppendMenu($hSystemMenu, $MF_STRING, 0x3001, "New System Menu Item2")

$hDLL = DllOpen("User32.dll")
$hWinEventProc = DllCallbackRegister("_WinEventProc", "none", "hwnd;int;hwnd;long;long;int;int")
if @error then
MsgBox(16+262144,"Error","DllCallbackRegister(_WinEventProc) did not succeed.")
Exit
endif

$hHook = _SetWinEventHook($EVENT_Min, $EVENT_Max, $hDLL)
if @error then
MsgBox(16+262144,"Error","_SetWinEventHook() did not succeed.")
Exit
endif


While WinExists($hGUI)
Sleep(10)
WEnd
AutoItExit()

Func _WinEventProc($hHook, $iEvent, $hWnd, $idObject, $idChild, $iEventThread, $iEventTime)
Local $PID = WinGetProcess($hWnd)
local $sEventProcName = _ProcessGetName($PID)

if $hWnd=$hGUI then
ConsoleWrite($iEventTime & @tab & $idObject & @tab & $idChild & @tab & "Event: " & $iEvent & @TAB & $hHook & @crlf)
endif
; Your own event handling code here...

EndFunc ;==>_WinEventProc

Func _SetWinEventHook($iEventMin, $iEventMax, $hDLLUser32)

Local $aRet
Local Const $WINEVENT_OUTOFCONTEXT = 0x0
Local Const $WINEVENT_SKIPOWNPROCESS = 0x2
If Not $hDLLUser32 Or $hDLLUser32 = -1 Then $hDLLUser32 = "User32.dll"
$aRet = DllCall($hDLLUser32, "hwnd", "SetWinEventHook", _
"uint", $iEventMin, _
"uint", $iEventMax, _
"hwnd", 0, _
"ptr", DllCallbackGetPtr($hWinEventProc), _
"int", 0, _
"int", 0, _
"uint", BitOR($WINEVENT_OUTOFCONTEXT, $WINEVENT_SKIPOWNPROCESS))
If @error Then Return SetError(@error, 0, 0)
Return $aRet[0]

EndFunc ;==>_SetWinEventHook

Func AutoItExit()
If $hWinEventProc Then
Beep(3000, 5)
DllCallbackFree($hWinEventProc)
EndIf
If $hHook Then DllCall("User32.dll", "int", "UnhookWinEvent", "hwnd", $hHook)
If $hDLL Then DllClose($hDLL)
EndFunc ;==>OnAutoItExit

Did I miss something here?

Cheers

Kristo

Edited by kristo

Cheap, Fast, Good - Choose any two

Share this post


Link to post
Share on other sites

Hi John,

Thanks. I already tried this. But that does not seem to work with the sysmenu.

Seems to be a tricky task somehow :ermm:


Cheap, Fast, Good - Choose any two

Share this post


Link to post
Share on other sites

Yes, I don't know. You can get the item clicked based on the mouse position but it's crap.


 

OS : Win XP SP2 (32 bits) / Win 7 SP1 (64 bits) / Win 8 (64 bits) | Autoit version: latest stable / beta.
Hardware : Intel(R) Core(TM) i5-2400 CPU @ 3.10Ghz / 8 GiB RAM DDR3.

My UDFs : Skype UDF | TrayIconEx UDF | GUI Panel UDF | Excel XML UDF | Is_Pressed_UDF

My Projects : YouTube Multi-downloader | FTP Easy-UP | Lock'n | WinKill | AVICapture | Skype TM | Tap Maker | ShellNew | Scriptner | Const Replacer | FT_Pocket | Chrome theme maker

My Examples : Capture toolIP Camera | Crosshair | Draw Captured Region | Picture Screensaver | Jscreenfix | Drivetemp | Picture viewer

My Snippets : Basic TCP | Systray_GetIconIndex | Intercept End task | Winpcap various | Advanced HotKeySet | Transparent Edit control

 

Share this post


Link to post
Share on other sites

#7 ·  Posted (edited)

All right! Solved it :thumbsup:

All I had to do was use this:

$item=_GUICtrlMenu_MenuItemFromPoint($hWnd,$hSystemMenu)

After that I have the menu item number which was selected.

Defintely solved.

Thanks FireFox.

Great community!

Kristo

Edited by kristo

Cheap, Fast, Good - Choose any two

Share this post


Link to post
Share on other sites

Nice, I thought about get window from point but I didn't know this one :)


 

OS : Win XP SP2 (32 bits) / Win 7 SP1 (64 bits) / Win 8 (64 bits) | Autoit version: latest stable / beta.
Hardware : Intel(R) Core(TM) i5-2400 CPU @ 3.10Ghz / 8 GiB RAM DDR3.

My UDFs : Skype UDF | TrayIconEx UDF | GUI Panel UDF | Excel XML UDF | Is_Pressed_UDF

My Projects : YouTube Multi-downloader | FTP Easy-UP | Lock'n | WinKill | AVICapture | Skype TM | Tap Maker | ShellNew | Scriptner | Const Replacer | FT_Pocket | Chrome theme maker

My Examples : Capture toolIP Camera | Crosshair | Draw Captured Region | Picture Screensaver | Jscreenfix | Drivetemp | Picture viewer

My Snippets : Basic TCP | Systray_GetIconIndex | Intercept End task | Winpcap various | Advanced HotKeySet | Transparent Edit control

 

Share this post


Link to post
Share on other sites

#9 ·  Posted (edited)

Kristo,

Well done :thumbsup:

_GUICtrlMenu_MenuItemFromPoint determine item under the cursor, then need to use _IsPressed for the mouse click, better solution then the arrays of the previus example.

Edited by johnmcloud

Share this post


Link to post
Share on other sites

Seemed to good to be true :

Everything seemed to work fine... until I move the window.

After moving the window just a little bit _GUICtrlMenu_MenuItemFromPoint does not seem to work anymore.

:mad2: Help!

Kristo


Cheap, Fast, Good - Choose any two

Share this post


Link to post
Share on other sites

Kristo i bet 1000$ you don't have put _GUICtrlMenu_MenuItemFromPoint in a loop...

While 1
$item = _GUICtrlMenu_MenuItemFromPoint($hWnd,$hSystemMenu)
; Your code
WEnd

Share this post


Link to post
Share on other sites

Kristo i bet 1000$

Bad idea... I give you my paypal email.

 

OS : Win XP SP2 (32 bits) / Win 7 SP1 (64 bits) / Win 8 (64 bits) | Autoit version: latest stable / beta.
Hardware : Intel(R) Core(TM) i5-2400 CPU @ 3.10Ghz / 8 GiB RAM DDR3.

My UDFs : Skype UDF | TrayIconEx UDF | GUI Panel UDF | Excel XML UDF | Is_Pressed_UDF

My Projects : YouTube Multi-downloader | FTP Easy-UP | Lock'n | WinKill | AVICapture | Skype TM | Tap Maker | ShellNew | Scriptner | Const Replacer | FT_Pocket | Chrome theme maker

My Examples : Capture toolIP Camera | Crosshair | Draw Captured Region | Picture Screensaver | Jscreenfix | Drivetemp | Picture viewer

My Snippets : Basic TCP | Systray_GetIconIndex | Intercept End task | Winpcap various | Advanced HotKeySet | Transparent Edit control

 

Share this post


Link to post
Share on other sites

#13 ·  Posted (edited)

>_<

I have tested by myself, work fine also if you move the window. It's like MouseGetPos(), if you don't put in a loop you have only the mouse position at the script startup, not if you move it after the extecution of the script

Edited by johnmcloud

Share this post


Link to post
Share on other sites

So why don't you use the MouseGetPos function?


 

OS : Win XP SP2 (32 bits) / Win 7 SP1 (64 bits) / Win 8 (64 bits) | Autoit version: latest stable / beta.
Hardware : Intel(R) Core(TM) i5-2400 CPU @ 3.10Ghz / 8 GiB RAM DDR3.

My UDFs : Skype UDF | TrayIconEx UDF | GUI Panel UDF | Excel XML UDF | Is_Pressed_UDF

My Projects : YouTube Multi-downloader | FTP Easy-UP | Lock'n | WinKill | AVICapture | Skype TM | Tap Maker | ShellNew | Scriptner | Const Replacer | FT_Pocket | Chrome theme maker

My Examples : Capture toolIP Camera | Crosshair | Draw Captured Region | Picture Screensaver | Jscreenfix | Drivetemp | Picture viewer

My Snippets : Basic TCP | Systray_GetIconIndex | Intercept End task | Winpcap various | Advanced HotKeySet | Transparent Edit control

 

Share this post


Link to post
Share on other sites

#15 ·  Posted (edited)

Wait, with MouseGetPos do you know if your mouse is "over a item menu" of non-standard autoit GUI without use coordinate?

The _GUICtrlMenu_MenuItemFromPoint return the menu position if the mouse is over on a item menu ( 1 for the first, 2 for the second etc. ), more manageable to use.

Edited by johnmcloud

Share this post


Link to post
Share on other sites

Hi guys,

now here's how I solved the problem.

Thanks for all the suggestions so far :bye:

It took me a while for everything to work smoothly and all in all it was a little bit more complex than I thought :x ,but now I can inject menu items into the system menu and I'm able to detect the menu selection successfully afterwards.

In this test case I tried to inject a menu into the IF text adventure runner gargoyle which is famous for running lots of text adventures created with inform, alan or TADS.

I wanted to be able to integrate manuals and hint files into the system menu and also add a context menu to the gargoyle interface with the same options. Also there's now some athmo background music while playing the game.

Two problems remain though. But first here's the code:

#NoTrayIcon
Opt('MustDeclareVars', 1)
Opt('WinTitleMatchMode', 2)

#AutoIt3Wrapper_Icon=standard.ico
#AutoIt3Wrapper_Outfile=adventure.exe
#AutoIt3Wrapper_UseX64=n

#include "_EventHook.au3"
#include <GuiMenu.au3>
#include <GUIConstantsEx.au3>
#include <WinAPI.au3>
#include <WindowsConstants.au3>
#include <Misc.au3>


Global $hWnd, $hGUI, $msg, $menuID
Global $hSystemMenu
global $userMenuCount=0

Global Const $MSG_CLICKSYSMENUITEM = 0x5000
Global Enum $eventShowManual = 1001, $eventShowClues, $eventShowAbout
global $userMenuItem[3][3] = [["Show Manual",$eventShowManual],["Show Clues",$eventShowClues],["About",$eventShowAbout]]

global $gamefile="adventure.z5"
global $winTitle=$gamefile & " - Bocfel"

Run(@ScriptDir & "\runtime\gargoyle.exe " & $gamefile, @ScriptDir & "\runtime")
WinWaitActive("[TITLE:" & $winTitle & "]")
$hGUI = WinGetHandle("[TITLE:" & $winTitle & "]")
WinSetTitle($hGUI,"","MyInformAdventure")

InjectMenu(6)

RegisterHookEvents($EVENT_SYSTEM_SOUND, $EVENT_OBJECT_PARENTCHANGE)
AddEventHook($hGUI, $EVENT_SYSTEM_CAPTUREEND, $MSG_CLICKSYSMENUITEM) 

dim $pos,$var,$ret
While WinExists($hGUI)

    PlayTracks()
    Sleep(50)

    if _IsPressed(0x02) Then
        $var=WinGetPos($hGUI)
        $pos=MouseGetPos()
        if $pos[0]>=$var[0]+40 and $pos[0]<=$var[0]+$var[2]-40 and $pos[1]>=$var[1]+40 and $pos[1]<= $var[1]+$var[3]-40 then
            if WinActive($hWnd) then
                $menuID=PopUpMenu()
            endif
        endif
        $msg = -1
    Else
        $msg = EVENTGetMsg()
    endif

    Switch $msg
        Case $MSG_CLICKSYSMENUITEM
            $menuID=GetMenuID()
        case -1
            ;skip to $menuID Switch
        case else
            ContinueLoop
    EndSwitch

    Switch $menuID
        case 61440
        case $eventShowManual   ;Manual
            ConsoleWrite("Manual" & @CRLF)
            run(@ScriptDir & '\runtime\SumatraPDF.exe runtime\manual.pdf')
        case $eventShowClues    ;Clues
            run(@ScriptDir & "\runtime\gargoyle.exe runtime\hints.z5")
        case $eventShowAbout    ;About
            msgbox(0,"About this game","MyAdventure",0,$hGUI)
        case Else
    EndSwitch

WEnd
UnhookEvents()

func PlayTracks()
static $sndID,$fileNr

    if IsArray($sndID) Then
        if _SoundStatus($sndID)="playing" then
            return(0)
        endif
    endif

    SRandom (StringRight(TimerInit(),6))
    $fileNr=Random(1,5,1)

    $sndID=_SoundOpen (@ScriptDir & "\runtime\" & $fileNr & ".mp3")
    if IsArray($sndID) Then
        _SoundPlay($sndID,0)
    endif

EndFunc

func GetMenuID()
local $var, $pos

    $pos = MouseGetPos()
    for $i= 0 to $userMenuCount

        $var = _GUICtrlMenu_GetItemRect($hGUI, $hSystemMenu,$userMenuItem[$i][2])
        If $pos[1] >= $var[1] And $pos[1] <= $var[3] Then
            return($userMenuItem[$i][1])
        EndIf
    next
    return(0)

EndFunc

Func InjectMenu($ItemPos=0, $InsertSeparator=true)
local $ret, $count

    ;Position zum einfügen der Items bestimmen
    $hSystemMenu = _GUICtrlMenu_GetSystemMenu($hGUI)
    $count=_GUICtrlMenu_GetItemCount($hSystemMenu)
    if $ItemPos=0 Then
        $ItemPos=$count+1
    EndIf

    ;Trenner einfügen
    if $InsertSeparator then
        _GUICtrlMenu_InsertMenuItem($hSystemMenu, $ItemPos, "")
    endif

    ;Menuitems einfügen
    for $x=0 to ubound($userMenuItem)-1
        _GUICtrlMenu_InsertMenuItem($hSystemMenu,$ItemPos,$userMenuItem[$x][0],$userMenuItem[$x][1])
    next

    ;und dann mit ID identifizieren
    $count=_GUICtrlMenu_GetItemCount($hSystemMenu)
    $userMenuCount=ubound($userMenuItem)-1

    for $i= 0 to $count
        $ret=_GUICtrlMenu_GetItemID($hSystemMenu,$i)
        for $x=0 to $userMenuCount
            if $ret=$userMenuItem[$x][1] then
                $userMenuItem[$x][2]=$i
                ExitLoop
            endif
        next
    next

EndFunc   ;==>InjectMenu


func PopUpMenu()
    local $hMenu,$dummy,$ret

    $dummy=GUICreate("",1,1,0,0)
    $hMenu = _GUICtrlMenu_CreatePopup (16)

        _GUICtrlMenu_InsertMenuItem ($hMenu, 0, "Show Manual", $eventShowManual)
        _GUICtrlMenu_InsertMenuItem ($hMenu, 1, "Show Clues", $eventShowClues)
        _GUICtrlMenu_InsertMenuItem ($hMenu, 3, "", 0)
        _GUICtrlMenu_InsertMenuItem ($hMenu, 3, "About", $eventShowAbout)

    $ret=_GUICtrlMenu_TrackPopupMenu ($hMenu, $dummy,-1,-1,1,1,2)

    _GUICtrlMenu_DestroyMenu ($hMenu)
    GUIDelete($dummy)
    return($ret)

EndFunc

; Handle WM_COMMAND messages
Func WM_COMMAND($hWnd, $iMsg, $iwParam, $ilParam)
    Switch $iwParam
        Case $eventShowManual
            _WinAPI_ShowMsg ("Show Manual")
        Case $eventShowClues
            _WinAPI_ShowMsg ("Show Clues")
        Case $eventShowAbout
            _WinAPI_ShowMsg ("About")
    EndSwitch
EndFunc   ;==>WM_COMMAND

; Handle WM_CONTEXTMENU messages
Func WM_CONTEXTMENU($hWnd, $iMsg, $iwParam, $ilParam)
    Local $hMenu

    $hMenu = _GUICtrlMenu_CreatePopup ()
    _GUICtrlMenu_InsertMenuItem ($hMenu, 0, "Show Manual", $eventShowManual)
    _GUICtrlMenu_InsertMenuItem ($hMenu, 1, "Show Clues", $eventShowClues)
    _GUICtrlMenu_InsertMenuItem ($hMenu, 3, "", 0)
    _GUICtrlMenu_InsertMenuItem ($hMenu, 3, "About", $eventShowAbout)
    _GUICtrlMenu_TrackPopupMenu ($hMenu, 0)
    _GUICtrlMenu_DestroyMenu ($hMenu)
    Return True
EndFunc   ;==>WM_CONTEXTMENU

And the _EventHook routines:

#NoTrayIcon
#include-once
#include <Array.au3>

Global Const $EVENT_SYSTEM_SOUND = 0x0001 ;An MSAA event indicating that a sound was played.
Global Const $EVENT_SYSTEM_ALERT = 0x0002 ;An MSAA event indicating that an alert was generated.
Global Const $EVENT_SYSTEM_FOREGROUND = 0x0003 ;An MSAA event indicating that the foreground window changed.
Global Const $EVENT_SYSTEM_MENUSTART = 0x0004 ;An MSAA event indicating that a menu item on the menu bar was selected.
Global Const $EVENT_SYSTEM_MENUEND = 0x0005 ;An MSAA event indicating that a menu from the menu bar was closed.
Global Const $EVENT_SYSTEM_MENUPOPUPSTART = 0x0006 ;An MSAA event indicating that a pop-up menu was displayed.
Global Const $EVENT_SYSTEM_MENUPOPUPEND = 0x0007 ;An MSAA event indicating that a pop-up menu was closed.
Global Const $EVENT_SYSTEM_CAPTURESTART = 0x0008 ;An MSAA event indicating that a window has received mouse capture.
Global Const $EVENT_SYSTEM_CAPTUREEND = 0x0009 ;An MSAA event indicating that a window has lost mouse capture.
Global Const $EVENT_SYSTEM_DIALOGSTART = 0x0010 ;An MSAA event indicating that a dialog box was displayed.
Global Const $EVENT_SYSTEM_DIALOGEND = 0x0011 ;An MSAA event indicating that a dialog box was closed.
Global Const $EVENT_SYSTEM_SCROLLINGSTART = 0x0012 ;An MSAA event indicating that scrolling has started on a scroll bar.
Global Const $EVENT_SYSTEM_SCROLLINGEND = 0x0013 ;An MSAA event indicating that scrolling has ended on a scroll bar.
Global Const $EVENT_SYSTEM_SWITCHSTART = 0x0014 ;An MSAA event indicating that the user pressed ALT+TAB, which activates the switch window.
Global Const $EVENT_SYSTEM_SWITCHEND = 0x0015 ;An MSAA event indicating that the user released ALT+TAB.
Global Const $EVENT_SYSTEM_MINIMIZESTART = 0x0016 ;An MSAA event indicating that a window object is about to be minimized or maximized.
Global Const $EVENT_SYSTEM_MINIMIZEEND = 0x0017 ;An MSAA event indicating that a window object was minimized or maximized.
Global Const $EVENT_SYSTEM_MOVESIZESTART = 0x000A ;An MSAA event indicating that a window is being moved or resized.
Global Const $EVENT_SYSTEM_MOVESIZEEND = 0x000B ;An MSAA event indicating that the movement or resizing of a window is finished.
Global Const $EVENT_SYSTEM_CONTEXTHELPSTART = 0x000C ;An MSAA event indicating that a window entered context-sensitive Help mode.
Global Const $EVENT_SYSTEM_CONTEXTHELPEND = 0x000D  ;An MSAA event indicating that a window exited context-sensitive Help mode.
Global Const $EVENT_SYSTEM_DRAGDROPSTART = 0x000E ;An MSAA event indicating that an application is about to enter drag-and-drop mode.
Global Const $EVENT_SYSTEM_DRAGDROPEND = 0x000F ;An MSAA event indicating that an application is about to exit drag-and-drop mode.

; EVENT_OBJECT events are triggered quite often, handle with care...
Global Const $EVENT_OBJECT_CREATE = 0x8000 ;An MSAA event indicating that an object was created.
Global Const $EVENT_OBJECT_DESTROY = 0x8001 ;An MSAA event indicating that an object was destroyed.
Global Const $EVENT_OBJECT_SHOW = 0x8002 ;An MSAA event indicating that a hidden object is being shown.
Global Const $EVENT_OBJECT_HIDE = 0x8003 ;An MSAA event indicating that an object is being hidden.
Global Const $EVENT_OBJECT_REORDER = 0x8004 ;An MSAA event indicating that a container object has added, removed, or reordered its children.
Global Const $EVENT_OBJECT_FOCUS = 0x8005 ;An MSAA event indicating that an object has received the keyboard focus.
Global Const $EVENT_OBJECT_SELECTION = 0x8006 ;An MSAA event indicating that the selection within a container object changed.
Global Const $EVENT_OBJECT_SELECTIONADD = 0x8007 ;An MSAA event indicating that an item within a container object was added to the selection.
Global Const $EVENT_OBJECT_SELECTIONREMOVE = 0x8008 ;An MSAA event indicating that an item within a container object was removed from the selection.
Global Const $EVENT_OBJECT_SELECTIONWITHIN = 0x8009 ;An MSAA event indicating that numerous selection changes occurred within a container object.
Global Const $EVENT_OBJECT_HELPCHANGE = 0x8010 ;An MSAA event indicating that an object's MSAA Help property changed.
Global Const $EVENT_OBJECT_DEFACTIonchange = 0x8011 ;An MSAA event indicating that an object's MSAA DefaultAction property changed.
Global Const $EVENT_OBJECT_ACCELERATORCHANGE = 0x8012 ;An MSAA event indicating that an object's MSAA KeyboardShortcut property changed.
Global Const $EVENT_OBJECT_INVOKED = 0x8013 ;An MSAA event indicating that an object has been invoked; for example, the user has clicked a button.
Global Const $EVENT_OBJECT_TEXTSELECTIonchangeD = 0x8014 ;An MSAA event indicating that an object's text selection has changed.
Global Const $EVENT_OBJECT_CONTENTSCROLLED = 0x8015 ;An MSAA event indicating that the scrolling of a window object has ended.
Global Const $EVENT_OBJECT_STATECHANGE = 0x800A ;An MSAA event indicating that an object's state has changed.
Global Const $EVENT_OBJECT_LOCATIonchange = 0x800B ;An MSAA event indicating that an object has changed location, shape, or size.
Global Const $EVENT_OBJECT_NAMECHANGE = 0x800C ;An MSAA event indicating that an object's MSAA Name property changed.
Global Const $EVENT_OBJECT_DESCRIPTIonchange = 0x800D ;An MSAA event indicating that an object's MSAA Description property changed.
Global Const $EVENT_OBJECT_VALUECHANGE = 0x800E ;An MSAA event indicating that an object's MSAA Value property changed.
Global Const $EVENT_OBJECT_PARENTCHANGE = 0x800F ;An MSAA event indicating that an object has a new parent object.

global $LISTENING_MESSAGES[1][3]
global $MESSAGE_STACK[1]
Global $hDLL, $hWinEventProc, $hHook, $hWnd

func AddEventHook($winHandle,$msgNumner, $eventUserID)

    local $count=ubound($LISTENING_MESSAGES)+1
    redim $LISTENING_MESSAGES[$count+1][3]

    $LISTENING_MESSAGES[$count][0]=$winHandle
    $LISTENING_MESSAGES[$count][1]=$msgNumner
    $LISTENING_MESSAGES[$count][2]=$eventUserID

    $LISTENING_MESSAGES[0][0]=$count

EndFunc

Func _SetWinEventHook($iEventMin, $iEventMax, $hDLLUser32)

    Local $aRet
    Local Const $WINEVENT_OUTOFCONTEXT = 0x0
    Local Const $WINEVENT_SKIPOWNPROCESS = 0x2
    If Not $hDLLUser32 Or $hDLLUser32 = -1 Then $hDLLUser32 = "User32.dll"
    $aRet = DllCall($hDLLUser32, "hwnd", "SetWinEventHook", _
            "uint", $iEventMin, _
            "uint", $iEventMax, _
            "hwnd", 0, _
            "ptr", DllCallbackGetPtr($hWinEventProc), _
            "int", 0, _
            "int", 0, _
            "uint", BitOR($WINEVENT_OUTOFCONTEXT, $WINEVENT_SKIPOWNPROCESS))
    If @error Then Return SetError(@error, 0, 0)
    Return $aRet[0]

EndFunc   ;==>_SetWinEventHook

func RegisterHookEvents($fromEvent,$toEvent)

    $hDLL = DllOpen("User32.dll")
    $hWinEventProc = DllCallbackRegister("_WinEventProc", "none", "hwnd;int;hwnd;long;long;int;int")
    if @error then
        MsgBox(16+262144,"Error","DllCallbackRegister(_WinEventProc) did not succeed.")
        Exit
    endif

    $hHook = _SetWinEventHook($fromEvent, $toEvent, $hDLL)
    if @error then
        MsgBox(16+262144,"Error","_SetWinEventHook() did not succeed.")
        Exit
    endif

EndFunc

func EVENTGetMsg()
local $SendMsg=""
local $count=ubound($MESSAGE_STACK)

    if $count>1 Then
        $SendMsg=$MESSAGE_STACK[1]
        _ArrayDelete($MESSAGE_STACK,1)
        return($SendMsg)
    endif

EndFunc

Func _WinEventProc($hHook, $iEvent, $hWnd, $idObject, $idChild, $iEventThread, $iEventTime)
local $count

    for $i=1 to $LISTENING_MESSAGES[0][0]
        if ($hWnd=$LISTENING_MESSAGES[$i][0]) then

            ;ConsoleWrite("Event: " & $iEvent & @TAB & $idObject & @CRLF)

            if ($iEvent = $LISTENING_MESSAGES[$i][1]) Then

                $count=ubound($MESSAGE_STACK)+1
                redim $MESSAGE_STACK[$count+1]

                $MESSAGE_STACK[$count]=$LISTENING_MESSAGES[$i][2]
                $MESSAGE_STACK[0]=$count

                ;ConsoleWrite("Event: " & $iEvent & " = " & $MESSAGE_STACK[$count] & @CRLF)
            endif
        endif
    next

EndFunc   ;==>_WinEventProc


Func UnhookEvents()
    If $hWinEventProc Then
        Beep(3000, 5)
        DllCallbackFree($hWinEventProc)
    EndIf
    If $hHook Then DllCall("User32.dll", "int", "UnhookWinEvent", "hwnd", $hHook)
    If $hDLL Then DllClose($hDLL)
EndFunc   ;==>OnAutoItExit

The remaining problems are:

1. I want to adjust the music volume and make it play very softly in the background, although I didn't find a way to do this without adjusting the overall system volumes.

2. When showing the context menu on the gargoyle GUI I did not find a way to detect a click outside the context menu. While the menu is there I'm stuck in the internal autoit routines, although I suspect there's surely a way in modyfing the original context menu module. For now you HAVE TO choose a context menu item to leave the menu. There's no other way to exit the menu.

 

Thanks for all your suggestions so far.

Kristo :sorcerer:


Cheap, Fast, Good - Choose any two

Share this post


Link to post
Share on other sites

...

1. I want to adjust the music volume and make it play very softly in the background, although I didn't find a way to do this without adjusting the overall system volumes.

...

 

Does the application have its own volume control?  If not, then it's going to depend on your operating system.  Everything before Windows 7 just sets an overall system volume.  Windows 7 lets you set a volume level for the system and also for each running application.

Share this post


Link to post
Share on other sites

#18 ·  Posted (edited)

kristo,

In this test case I tried to inject a menu into the IF text adventure runner gargoyle which is famous for running lots of text adventures created with inform, alan or TADS.

Unfortunately you appear to have missed the Forum rules during your stay so far. Please read them now (there is also a link at bottom right of each page) - particularly the bit about not discussing game interaction.  I strongly suggest you find other test cases from now on. :naughty:

M23

Edited by Melba23
Typo

Any of my own code posted anywhere on the forum is available for use by others without any restriction of any kind._______My UDFs:

Spoiler

ArrayMultiColSort ---- Sort arrays on multiple columns
ChooseFileFolder ---- Single and multiple selections from specified path treeview listing
Date_Time_Convert -- Easily convert date/time formats, including the language used
ExtMsgBox --------- A highly customisable replacement for MsgBox
GUIExtender -------- Extend and retract multiple sections within a GUI
GUIFrame ---------- Subdivide GUIs into many adjustable frames
GUIListViewEx ------- Insert, delete, move, drag, sort, edit and colour ListView items
GUITreeViewEx ------ Check/clear parent and child checkboxes in a TreeView
Marquee ----------- Scrolling tickertape GUIs
NoFocusLines ------- Remove the dotted focus lines from buttons, sliders, radios and checkboxes
Notify ------------- Small notifications on the edge of the display
Scrollbars ----------Automatically sized scrollbars with a single command
StringSize ---------- Automatically size controls to fit text
Toast -------------- Small GUIs which pop out of the notification area

 

Share this post


Link to post
Share on other sites

Hi Melba,

I know the rules. Sorry if this looks like one of those stupid bot cheating things to you.

But in this case It's not a standard game, but an interactive fiction player. o:)

Gargoyle is widespread and in itself open source. It is used to run all the interactive fiction stories written in inform, tads or Alan. And everyone's welcome to modify it. The commonly used authoring tools mentioned above are also mostly open source.

Also I'm writing my own IF stories using Alan and Inform.

Since I'm not a very good C programmer, the quickest way to add my own IF manuals and hintbooks to the gargoyle GUI was using AutoIt.

I didn't mean to offend the rules :bye:  but I seriously think that in this case it's not what the "no gaming" rule was ment to be for.

Cheers

Kristo

kristo,


Unfortunately you appear to have missed the Forum rules during your stay so far. Please read them now (there is also a link at bottom right of each page) - particularly the bit about not discussing game interaction.  I strongly suggest you find other test cases from now on. :naughty:

M23


Cheap, Fast, Good - Choose any two

Share this post


Link to post
Share on other sites

kristo,

 

It's not a standard game, but an interactive fiction player

Google tells me:

 

"Gargoyle is an IF player that supports all the major interactive fiction formats.

Most interactive fiction is distributed as portable game files. These portable game files come in many formats."

Sounds like a game to me. The screenshots look like games to me.

 

I seriously think that in this case it's not what the "no gaming" rule was ment to be for

Well, I seriously think the opposite. Thread closed. :naughty:

M23


Any of my own code posted anywhere on the forum is available for use by others without any restriction of any kind._______My UDFs:

Spoiler

ArrayMultiColSort ---- Sort arrays on multiple columns
ChooseFileFolder ---- Single and multiple selections from specified path treeview listing
Date_Time_Convert -- Easily convert date/time formats, including the language used
ExtMsgBox --------- A highly customisable replacement for MsgBox
GUIExtender -------- Extend and retract multiple sections within a GUI
GUIFrame ---------- Subdivide GUIs into many adjustable frames
GUIListViewEx ------- Insert, delete, move, drag, sort, edit and colour ListView items
GUITreeViewEx ------ Check/clear parent and child checkboxes in a TreeView
Marquee ----------- Scrolling tickertape GUIs
NoFocusLines ------- Remove the dotted focus lines from buttons, sliders, radios and checkboxes
Notify ------------- Small notifications on the edge of the display
Scrollbars ----------Automatically sized scrollbars with a single command
StringSize ---------- Automatically size controls to fit text
Toast -------------- Small GUIs which pop out of the notification area

 

Share this post


Link to post
Share on other sites
Guest
This topic is now closed to further replies.
Sign in to follow this  
Followers 0