Amate Posted December 4, 2009 Share Posted December 4, 2009 (edited) I made a hook to an application and this application crashes for some reason. I do not understand why. Cannot find what am I doing wrong. Declaration. Global Const $tagCWPRETSTRUCT = "lresult lResult;lparam lParam;wparam wParam;uint message;hwnd hwnd" Global Const $WM_MEASUREITEM = 0x002C Global $hHook Here i registered a hook. MessageCaptured = 0 $MyNULL = 0 $hStub_GetMenuTextProc = DllCallbackRegister("_GetMenuTextProc", "lresult", "int;wparam;lparam") $hmod = _WinAPI_GetModuleHandle(0) $hHook = _WinAPI_SetWindowsHookEx($WH_CALLWNDPROCRET, DllCallbackGetPtr($hStub_GetMenuTextProc), $hmod, _WinAPI_GetWindowThreadProcessId(WinGetHandle($WT_Main), $MyNULL)) Callback and freeing. Func _GetMenuTextProc($nCode, $wParam, $lParam) Local $tRETSTRUCT $tRETSTRUCT = DllStructCreate($tagCWPRETSTRUCT, $lParam) If $nCode < 0 Then Return _WinAPI_CallNextHookEx($hHook, $nCode, $wParam, $lParam) EndIf If DllStructGetData($tRETSTRUCT, "message") = $WM_MEASUREITEM Then $MessageCaptured = 1 EndIf Return _WinAPI_CallNextHookEx($hHook, $nCode, $wParam, $lParam) EndFunc ;==>_GetMenuTextProc Func OnAutoItExit() _WinAPI_UnhookWindowsHookEx($hHook) DllCallbackFree($hStub_GetMenuTextProc) EndFunc ;==>OnAutoItExit Edited December 4, 2009 by Amate Link to comment Share on other sites More sharing options...
Authenticity Posted December 4, 2009 Share Posted December 4, 2009 (edited) Is the thread of the $WT_Main window belongs to a different process, other than yours? If so, the hook procedure must reside in a DLL file. Also, the structure is not correct, it should be:Global Const $tagCWPRETSTRUCT = "int_ptr lResult;int_ptr lParam;uint_ptr wParam;uint message;hwnd hwnd"You could check if the dll struct is correct by inspecting the @error value or using DllStructGetSize(). Refer to this topic about the hooking process, just scroll down to the accepted solution. You can ignore the shared data segment as it's not a system-wide procedure, nonetheless, the hook procedure must reside in a DLL (if I'm not wrong) Edited December 4, 2009 by Authenticity Link to comment Share on other sites More sharing options...
Amate Posted December 7, 2009 Author Share Posted December 7, 2009 Is the thread of the $WT_Main window belongs to a different process, other than yours? Yes, That is right.If so, the hook procedure must reside in a DLL file. That is not the only solution. It is enough that all the handles are in shared section. I have no idea how to do it with AutoIT. Please advice.Also, the structure is not correct, it should be:Global Const $tagCWPRETSTRUCT = "int_ptr lResult;int_ptr lParam;uint_ptr wParam;uint message;hwnd hwnd"You could check if the dll struct is correct by inspecting the @error value or using DllStructGetSize(). Thank you. I've corrected my code. But this is not the reason why $WT_Main application crashes.Refer to this topic about the hooking process, just scroll down to the accepted solution. You can ignore the shared data segment as it's not a system-wide procedure, nonetheless, the hook procedure must reside in a DLL (if I'm not wrong)I cannot view the solution. I cannot use trial period because they demand credit card and do not accept my Visa Electron. Please copy\paste the solution here. Link to comment Share on other sites More sharing options...
Amate Posted December 7, 2009 Author Share Posted December 7, 2009 I reviewed the solution. How can I make DLL with AutoIT? How can I manage shared memory with AutoIT? Please advice. Is there any way I could perform my task with AutoIT only? My task is as follows. I need to get main menu item names from Delphi written application. Main menu control items set as owner drawn. So I need to intercept WM_MEASUREITEM message on return from owner so I can get long pointer to MEASUREITEMSTRUCT. expandcollapse popup/---------- // Main.cpp //---------- #include <windows.h> #include <iostream.h> #include <stdlib.h> #include <conio.h> bool setHook(DWORD threadId); bool removeHook(); void main(int argc,char* argv[]) { if(setHook(0)) { cout<<"Press Enter to quit"<<endl; _getch(); cout<<removeHook()<<endl; } } //---------- // Hook.dll //---------- // Cannot use WH_GETMESSAGE, because WM_NCPAINT is *sent*, but not *posted*. #include <windows.h> #pragma data_seg(".shared") HHOOK hHook=0; #pragma data_seg() #pragma comment(linker,"/SECTION:.shared,RWS") HINSTANCE hDll; void onNCPaint(CWPRETSTRUCT& msg) { // Do whatever you want. } LRESULT CALLBACK hookProc(int code,WPARAM wParam,LPARAM lParam) { if(code==HC_ACTION) { CWPRETSTRUCT* msg=(CWPRETSTRUCT*)(lParam); if(msg->message==WM_NCPAINT) { onNCPaint(*msg); } } return CallNextHookEx(hHook,code,wParam,lParam); } BOOL WINAPI DllMain(HINSTANCE hinstDLL,DWORD fdwReason,LPVOID) { if(fdwReason==DLL_PROCESS_ATTACH) hDll=hinstDLL; return TRUE; } _declspec(dllexport) bool setHook(DWORD threadId) { if(hHook==0) hHook=SetWindowsHookEx(WH_CALLWNDPROCRET,hookProc,hDll,threadId); return hHook!=0; } _declspec(dllexport) bool removeHook() { bool r=true; if(hHook) { r=UnhookWindowsHookEx(hHook); hHook=0; } return r; } Link to comment Share on other sites More sharing options...
Authenticity Posted December 7, 2009 Share Posted December 7, 2009 Currently, you can't write dlls in AutoIt (and maybe not so currently). You can use the free ones though, including BloodShed, Code::Blocks, or VS2008 or VS2005 the express edition. Do you want to intercept the message to be able to get the data (string) because it's an owner-drawn and otherwise you can't? Link to comment Share on other sites More sharing options...
Amate Posted December 8, 2009 Author Share Posted December 8, 2009 Do you want to intercept the message to be able to get the data (string) because it's an owner-drawn and otherwise you can't? Seems I cannot do it bacause the structure contains mainly size of the owner drawn item but not the string, but anyway i can get itemID and custom data from itemData field and this allows me to identify the menu item unambiguously. I need this bacause for some reason the menu items may be ordered different ways on different computers so i cannot use zero position id and be sure I execute the same menu item on different computers. My current code for menu follows. $hMenu = _GUICtrlMenu_GetMenu(WinGetHandle($WT_Main)) $hDoc = _GUICtrlMenu_GetItemSubMenu($hMenu, $MM_Doc) $hCash = _GUICtrlMenu_GetItemSubMenu($hDoc, $MM_Cash) _GUICtrlMenu_SetItemText($hMenu, $MM_Doc, "Doc") _GUICtrlMenu_SetItemText($hDoc, $MM_Cash, "Cash") _GUICtrlMenu_SetItemText($hCash, $MM_Credit, "Credit") WinMenuSelectItem($WT_Main, "", "Doc", "Cash", "Credit") This code works in different ways on different computers because it uses zero bazed index ($MM_Credit). I need to make it work the same way on any computer. Link to comment Share on other sites More sharing options...
Authenticity Posted December 8, 2009 Share Posted December 8, 2009 You can get the menu and sub-menus items and items ids into a two-dimensional array and use the ID instead, assuming the items strings don't change. #include <GUIMenu.au3> Local $hWnd = WinGetHandle("") Local $hMenu = _GUICtrlMenu_GetMenu($hWnd) Local $hSubMenu For $i = 0 To _GUICtrlMenu_GetItemCount($hMenu)-1 ConsoleWrite(_GUICtrlMenu_GetItemText($hMenu, $i) & @CRLF) $hSubMenu = _GUICtrlMenu_GetItemSubMenu($hMenu, $i) For $j = 0 To _GUICtrlMenu_GetItemCount($hSubMenu)-1 ConsoleWrite(@TAB & _GUICtrlMenu_GetItemText($hSubMenu, $j) & " " & _GUICtrlMenu_GetItemID($hSubMenu, $j) & @CRLF) Next Next Link to comment Share on other sites More sharing options...
Amate Posted December 8, 2009 Author Share Posted December 8, 2009 As I mentioned above this is owner drawn menu, so _GUICtrlMenu_GetItemText returns "". That is the reason I must name menu items myself to select menu item. Anyway _GUICtrlMenu_GetItemID returns valid ID so I'll try using it. Thank you for you time. Link to comment Share on other sites More sharing options...
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now