Hook : Menu without dll pure ahk code

Post your working scripts, libraries and tools for AHK v1.1 and older
GS SAHU
Posts: 37
Joined: 29 Sep 2014, 12:18

Hook : Menu without dll pure ahk code

30 Oct 2015, 03:41

I make a hook.ahk library file for hooking any menus or buttons from any other application with help of hook.dll
copy hook.ahk and hook.dll in you lib folder

code: hook.ahk

Code: Select all

global WM_USER:=1024
global UM_ADDMESSAGE := WM_USER + 0x100
global WH_CALLWNDPROC:=4
global WH_GETMESSAGE:=3
global WM_COMMAND:=273
global hWndTarget
global iThreadIdTarget, hWndLocal, hModule

hook(hWndTarget)
{
iThreadIdTarget := DllCall("GetWindowThreadProcessId", "Int", hWndTarget, "Int", 0)

; Install Filter(s)
hModule := DllCall("LoadLibrary", "Str", "hook.dll", "Ptr")
hook := DllCall("hook.dll\InstallFilterDLL", "Int", WH_CALLWNDPROC, "Int", iThreadIdTarget, "Int", hWndTarget) ; 0 = Ok
hookG := DllCall("hook.dll\InstallFilterDLL", "Int", WH_GETMESSAGE, "Int", iThreadIdTarget, "Int", hWndTarget) ; 0 = Ok

if (!hook || !hookG)
{
; Register WM_COMMAND
GUI, +LASTFOUND
;Gui, show
hWndLocal := WinExist()
DllCall("SendMessage", "Int", hWndTarget, "Int" , UM_ADDMESSAGE, "Int", WM_COMMAND, "Int", hWndLocal)
}
else
{
	MsgBox failed hook : %hook% hookG %hookG%
	DllCall("hook.dll\UnInstallFilterDLL", "Int", iThreadIdTarget, "Int", hWndTarget, "Int", hWndLocal)
	DllCall("FreeLibrary" , "Ptr", hModule)
}

}

unhook(hWndTarget)
{
	DllCall("hook.dll\UnInstallFilterDLL", "Int", iThreadIdTarget, "Int", hWndTarget, "Int", hWndLocal)
	DllCall("FreeLibrary" , "Ptr", hModule)
}

example of using hook.ahk

Code: Select all

#Include hook.ahk


Run, Calc.exe,,, pid
WinWait, Calculator

hWndTarget := WinExist("ahk_pid" . pid)

WinMove, ahk_id %hWndTarget%,,50,50,600,400

_CreateMenu(hWndTarget)
_CreateButton(hWndTarget)

hook(hWndTarget)
OnMessage(WM_COMMAND, "_FILTER")

return

;Message Fileter function call by OnMessage
_Filter(COMMAND_ID, iMsg, wParam, lParam)
{
;MsgBox % "commandid " . COMMAND_ID . " iMsg " . iMsg . " wParam " . wParam . " lParam " . lParam
if (COMMAND_ID = 1000 AND wParam=273)
	MsgBox  Menu Click
else if (COMMAND_ID = 4001 AND wParam=273)
	MsgBox Button Click
}

;Create Menu
_CreateMenu(hWndTarget)
{
IDM_TEST := 1000
STR_TEST := "AHK"
hMenu := DllCall("GetMenu", Int, hWndTarget)
Result := DllCall("AppendMenu", Int,hMenu, Int,0x0, Int,IDM_TEST, Str,STR_TEST)
DllCall("DrawMenuBar", "Int", hWndTarget)
}

;Create Button
_CreateButton(hWndTarget)
{
IDB_TEST := 4001
STRB_TEST := "Button1"
WS_VISIBLE := 0x10000000
WS_CHILD := 0x40000000
DllCall("CreateWindowEx", "Uint", 0, "str", "Button", "str", STRB_TEST, "Uint", WS_CHILD | WS_VISIBLE , "int", 490, "int", 40, "int", 60, "int", 40, "Uint", hWndTarget, "Uint", IDB_TEST, "Uint", 0, "Uint", 0)
}

Esc::
unhook(hWndTarget)
ExitApp
hook.dll link
Last edited by GS SAHU on 04 Nov 2015, 14:57, edited 1 time in total.
User avatar
evilC
Posts: 4823
Joined: 27 Feb 2014, 12:30

Re: Hook : Menu and Button with AHK

30 Oct 2015, 15:28

Hi, apologies for hijacking your thread somewhat, but HotkeyIt and I are in the process of trying to write an enhanced hotkey library for AHK (eg allow hotkeys of any number of keys etc) using SetWindowsHookEx and low-level hooks, but the learning curve is very steep.
I did basically get it working but the big issue now is debugging my application while the hooks are running - if the hook callback is the AHK script, keyboard and mouse lock up when you try to debug the script - in fact even if you only hook mouse, the keyboard will lock up too when you debug the script.
I did some reading around, and it seemed that people were recommending to put the hook code in a DLL - is that the reason for your hook.dll?

Any help or advice you could lend would be greatly appreciated.
GS SAHU
Posts: 37
Joined: 29 Sep 2014, 12:18

Re: Hook : Menu and Button with AHK

01 Nov 2015, 05:37

evilC wrote:Hi, apologies for hijacking your thread somewhat, but HotkeyIt and I are in the process of trying to write an enhanced hotkey library for AHK (eg allow hotkeys of any number of keys etc) using SetWindowsHookEx and low-level hooks, but the learning curve is very steep.
I did basically get it working but the big issue now is debugging my application while the hooks are running - if the hook callback is the AHK script, keyboard and mouse lock up when you try to debug the script - in fact even if you only hook mouse, the keyboard will lock up too when you debug the script.
I did some reading around, and it seemed that people were recommending to put the hook code in a DLL - is that the reason for your hook.dll?

Any help or advice you could lend would be greatly appreciated.
Welcome to enhancement for hotkey library.

actually hook.dll in not mine. there is a problem. if i am using hook menu and buttons together.
1. keyboard and mouse are not lock if use only menu or buttons.
2. in menu function not have interactive code like run notepad.exe so lock problem not active.
i am also finding solution for these problem.

hooking use always dll because wm_command can not hook directly. i think dll inject to target window for getting wm_command message from target window.
GS SAHU
Posts: 37
Joined: 29 Sep 2014, 12:18

Re: Hook : Menu and Button with AHK

01 Nov 2015, 07:13

keyboard,mouse lock problem has been fix.
use code in following way.

Code: Select all

#Include hook.ahk
OnExit, onexit
global ID
Run, Calc.exe,,, pid
WinWait, Calculator

hWndTarget := WinExist("ahk_pid" . pid)
WinMove, ahk_id %hWndTarget%,,50,50,600,400

_CreateMenu(hWndTarget)
_CreateButton(hWndTarget,"Button1", 490, 40,4001)
_CreateButton(hWndTarget,"Button2", 490, 90,4002)
hook(hWndTarget)
OnMessage(WM_COMMAND, "_FILTER")

while, WINEXIST("AHK_PID" . PID)
{
IF (ID == 4001)
	MsgBox BUTTON1
else IF (ID== 4002)
	MsgBox BUTTON2
else IF (ID==50001)
	MsgBox MENU ITEM1
else IF (ID==50002)
	MsgBox MENU ITEM2
ID := 0
Sleep 10
}
gosub onexit

;Message Fileter function call by OnMessage
_Filter(COMMAND_ID, iMsg, wParam, lParam)
{
if (wParam == 273)
{
	ID := COMMAND_ID
}

}

;Create Menu
_CreateMenu(hWndTarget)
{
IDM_TEST := 0
STR_TEST := "AHK"
MF_BYPOSITION = 0x400
MF_SEPARATOR = 0x800
MF_STRING = 0x000
MF_POPUP:=16
hMenu := DllCall("GetMenu", Int, hWndTarget)
hItem1 := DllCall("CreateMenu")
Result := DllCall("AppendMenu", Int, hMenu, Int, MF_POPUP, "Ptr", hItem1, Str, "Ahk")
DllCall("InsertMenu", "int", hItem1, "int", 0, "int", MF_BYPOSITION | MF_STRING, "int", 50001, "str", "item1")
DllCall("InsertMenu", "int", hItem1, "int", 1, "int", MF_BYPOSITION | MF_STRING, "int", 50002, "str", "item2")
DllCall("SetMenu", "Ptr", hItem1,"Ptr", hMenu)
DllCall("DrawMenuBar", "Int", hWndTarget)
}

;Create Button
_CreateButton(hWndTarget, name,x, y,id)
{
IDB_TEST := 4001

WS_VISIBLE := 0x10000000
WS_CHILD := 0x40000000
BS_PUSHBUTTON:=0
DEFAULT_GUI_FONT:=17
WM_SETFONT:=48
DllCall("CreateWindowEx", "Uint", 0, "str", "Button", "str", name, "Uint", BS_PUSHBUTTON | WS_CHILD | WS_VISIBLE , "int", x, "int", y, "int", 60, "int", 40, "Uint", hWndTarget, "Uint", ID, "Uint", 0, "Uint", 0)
getstock := DllCall("GetStockObject", int, DEFAULT_GUI_FONT)
DllCall("SendMessage", int, hButton, int, WM_SETFONT, int, getstock, int, TRUE)

}


OnExit:
unhook(hWndTarget)
ExitApp

hook64

Re: Hook : Menu and Button with AHK

01 Nov 2015, 07:53

I'm on Win8/64 bit and only works if I run the script with AutoHotkeyU32.exe. So it seems it is not working with the 64 but version of AHK?
GS SAHU
Posts: 37
Joined: 29 Sep 2014, 12:18

Re: Hook : Menu and Button with AHK

01 Nov 2015, 08:21

hook64 wrote:I'm on Win8/64 bit and only works if I run the script with AutoHotkeyU32.exe. So it seems it is not working with the 64 but version of AHK?
hook.dll not written by me. i know only 32bit function name of this dll. so hook.ahk wrapper write on 32bit base.
guest3456
Posts: 3462
Joined: 09 Oct 2013, 10:31

Re: Hook : Menu and Button with AHK

02 Nov 2015, 11:12

how about a link to where you found the hook.dll?

it looks like it links to AutoIT but i cant find it

GS SAHU
Posts: 37
Joined: 29 Sep 2014, 12:18

Re: Hook : Menu and Button with AHK

02 Nov 2015, 12:35

guest3456 wrote:how about a link to where you found the hook.dll?

it looks like it links to AutoIT but i cant find it
yes it links from AutoIt. and Autoit Script also attached in zip file.
GS SAHU
Posts: 37
Joined: 29 Sep 2014, 12:18

Re: Hook : Menu and Button with AHK

02 Nov 2015, 13:10

i have AutoIt script part that hook menu without dll. but i can not success use of two function.
_GUICtrlMenu_GetMenuBarInfo()
_GUICtrlMenu_GetItemHighlighted()

if you have know use of above function pls tell me. i want to both function in ahk.

following code successfully hook menu of other application

Code: Select all

While 1

    ; Check status of Notepad menubar
    $aInfo = _GUICtrlMenu_GetMenuBarInfo($hWnd)

    ; If menu is active
    If $aInfo[6] = True Then
        ; Run through our added items to see if they are active
        $sCurrent_Item = ""
        For $i = 0 To 3
            If _GUICtrlMenu_GetItemHighlighted($hMenu, $aCmdID[$i][1], False) Then
                ; If active, get text
                If $aCmdID[$i][0] <> $sCurrent_Item Then $sCurrent_Item = $aCmdID[$i][0]
            EndIf
        Next
    EndIf

    ; If one of our menu items was selected
    If $sCurrent_Item <> "" Then
        ; If mouse clicked or Enter pressed
        If _IsPressed("01", $dll) Or _IsPressed("0D", $dll) Then
            ; This is where you do what the selection is there for!!!!!!!!!
            ConsoleWrite("You selected " & $sCurrent_Item & @CRLF)
            ; Prevent "double tap"
            $sCurrent_Item = ""
            ; Wait until mouse/Enter released
            While _IsPressed("0D", $dll) Or _IsPressed("01", $dll)
                Sleep(10)
            WEnd
        EndIf
    EndIf

    Sleep(10)

    ; Exit if Notepad is closed
    If Not WinExists("[CLASS:Notepad]") Then _OnExit()

WEnd

GS SAHU
Posts: 37
Joined: 29 Sep 2014, 12:18

Hook : Menu with/without dll

04 Nov 2015, 14:54

Menu hook without dll pure AHK code

Code: Select all

#SingleInstance,Force
SetBatchLInes,-1
AutoTrim,Off 
DllCall("AllocConsole")
global stdout
global current_id
Run, Notepad.exe,,, pid
WinWait, Untitled - Notepad
hWnd := WinExist("ahk_pid" . pid)
hModule := DllCall("LoadLibrary", "Str", "user32.dll", "Ptr")
hMenu:=DllCall("user32\GetMenu","UInt",hWnd)
_CreateMenu(hWnd)
#IfWinActive, ahk_pid  pid
  while  WinExist("ahk_pid" . pid)
      GETMENU(hMenu)

Return
Esc::
DllCall("FreeLibrary", "Ptr", hModule)
ExitApp

GETMENU(hMenu)
{
stdout :=FileOpen("*", "w `n")
nMaxCount=100
  uFlag:=0x0400  ;MF_BYPOSITION
  menuitemcount:=DllCall("GetMenuItemCount",UInt,hMenu)
  Loop,%menuitemcount%
  {
    nPos:=A_Index-1

	hSubMenu:=DllCall("user32\GetSubMenu","UInt",hMenu,"int",nPos) 
    If hSubMenu>0
    {
      GETMENU(hSubMenu)
    }
    else
    {
    state := MenuState(hMenu,nPos)
  
    if (state = 128)
	{
	nID := DllCall("GetMenuItemID", "Uint", hMenu, "Uint", nPos)
    VarSetCapacity(lpString,100,0)
    length:=DllCall("user32\GetMenuString","UInt",hMenu,"UINT",nPos,"STR",lpString,"int",nMaxCount,"UINT",uFlag) 
	 
      if (current_id <> nID)
      {
       stdout.Write( nPos	. "state " . state . lpString . " " . nID . "`n")
      state := 0
      current_id := nID
        
      }
     
	}
    
    If (current_id <> 0)
    {
        ; If mouse clicked or Enter pressed
        
        If (_IsPressed("01") || _IsPressed("0D") || GetKeyState("Enter","P") || GetKeyState("LButton","P"))
        {       
            ; This is where you do what the selection is there for!!!!!!!!!
            stdout.Write("You selected " . current_id . "`n")
            ; Prevent "double tap"
            current_id := 0
            keystate := ""
            ; Wait until mouse/Enter released
            While, (_IsPressed("0D") || _IsPressed("01"))
                Sleep 10
            
        }
    }
     
    
    }
  }
  
}

MenuState(hSubMenu, index)
{
VarSetCapacity(mii,48,0)
NumPut(48, mii, 0)
; Set the mask to whatever you want to retrieve.
; In this case I set it to MIIM_STATE=1.
NumPut(1, mii, 4)
; Note that menu item positions are zero-based.
DllCall("GetMenuItemInfo", "UInt", hSubMenu, "UInt", index, "UInt", true, "UInt", &mii)
; Get the state field out of the struct.
fState := NumGet(mii, 12)
return fState
}

_IsPressed(sHexKey)
{
	; $hexKey must be the value of one of the keys.
	; _Is_Key_Pressed will return 0 if the key is not pressed, 1 if it is.
	Rt := DllCall("GetAsyncKeyState", "int", "0x" . sHexKey)
	Return (RT & 0x8000) <> 0
}

;Create Menu
_CreateMenu(hWndTarget)
{
IDM_TEST := 0
STR_TEST := "AHK"
MF_BYPOSITION = 0x400
MF_SEPARATOR = 0x800
MF_STRING = 0x000
MF_POPUP:=16
hMenu := DllCall("GetMenu", Int, hWndTarget)
hItem1 := DllCall("CreateMenu")
Result := DllCall("AppendMenu", Int, hMenu, Int, MF_POPUP, "Ptr", hItem1, Str, "Ahk")
DllCall("InsertMenu", "int", hItem1, "int", 0, "int", MF_BYPOSITION | MF_STRING, "int", 50001, "str", "item1")
DllCall("InsertMenu", "int", hItem1, "int", 1, "int", MF_BYPOSITION | MF_STRING, "int", 50002, "str", "item2")
DllCall("SetMenu", "Ptr", hItem1,"Ptr", hMenu)
DllCall("DrawMenuBar", "Int", hWndTarget)
}
above code successfully hook menu. but there is two problem.
1. use cpu in large amount.
2. which menu reflect check status(8) i can not got hilight value(128).

if you have any help pls. tell me.
podlesnick
Posts: 1
Joined: 08 Sep 2017, 16:38

Re: Hook : Menu without dll pure ahk code

08 Sep 2017, 16:47

Guys, this is a great script, but I need to adjust a program's Window menu. So I changed this:

Code: Select all

hMenu := DllCall("GetMenu", Int, hWndTarget)
to this:

Code: Select all

hMenu := DllCall("GetSystemMenu","UInt",hWndTarget,"UInt",0)

This way, the menu is added not to main menu, but to the Window menu, beside resize, move etc...
The problem is that script doesn't receive messages from WM_COMMAND, so it doesn't know when the new menuitem is pressed.

Any idea?

Return to “Scripts and Functions (v1)”

Who is online

Users browsing this forum: gongnl, vrbest and 51 guests