Detect events in other apps?
Detect events in other apps?
Is it possible to detect events in other apps? I basically want to add menus
to another app's window (which I can do) but then have my app know when
these menus are selected.
to another app's window (which I can do) but then have my app know when
these menus are selected.
Hi,
You need to write a hook function (never done it myself but have looked into it.....)
look here for something to get you started.....
http://msdn.microsoft.com/library/defau ... ooks32.asp
You need to write a hook function (never done it myself but have looked into it.....)
look here for something to get you started.....
http://msdn.microsoft.com/library/defau ... ooks32.asp
Facing the challenge you presented, I've put together a hook/dll that works fine here on WinXP. I'm still cleaning this up a bit so I'm not posting the entire code at this time. I figured I'd post this, hoping it helps you in getting started.
This was my first attempt at creating a DLL and my first attempt using a hook/DLL. I must say that PB and jaPBe both make it easier than I had expected
My main app (menutext.pb) uses
Then the DLL I created (mnutxt.dll), handles the menu messages and then sends back the menu text to the app that created the hook.
Inside the DLL I used the following:
There's most likely more than one way to get the results you are looking for, so don't take mine as the last word. 

This was my first attempt at creating a DLL and my first attempt using a hook/DLL. I must say that PB and jaPBe both make it easier than I had expected


My main app (menutext.pb) uses
Code: Select all
hDLL = OpenLibrary(0, "mnutxt.dll")
hmyHook = SetWindowsHookEx_(#WH_MSGFILTER, GetProcAddress_(hDLL, "MyMessageProc"), hDLL, 0)
...
...
...
End
UnhookWindowsHookEx_(hmyHook)
CloseLibrary(0)
Inside the DLL I used the following:
Code: Select all
ProcedureDLL MyMessageProc(code.l, wParam.l, lParam.l)
MENUITEMINFO ;- structure needed for GetMenuItemInfo_()
FindWindow_() ;- to find my app to display menu text
GetMenu_() ;- to get handle to menu being selected
GetMenuItemInfo_() ;- to get the menu item text
FindWindowEx_() ;- to find my TextGadget for displaying the menu text found
SendMessage_() ;- to send text to my TextGadget
CallNextHookEx_() ;- for procedure return

What goes around comes around.
PB 5.21 LTS (x86) - Windows 8.1
PB 5.21 LTS (x86) - Windows 8.1
Hi Sparkie,
I also had a play with writing a hook the same way pretty much.. except I have some exported DLL functions to install and remove the hook. I give the DLL a callback function to call my App with when a message is passed through... trouble is it's not working as I expected - it appears that my hook function is only getting messages that are destined for my own app window - and not for all apps under the desktop thread as the MSDN docs suggest. Any ideas what I've done wrong without me posting the code?
I also had a play with writing a hook the same way pretty much.. except I have some exported DLL functions to install and remove the hook. I give the DLL a callback function to call my App with when a message is passed through... trouble is it's not working as I expected - it appears that my hook function is only getting messages that are destined for my own app window - and not for all apps under the desktop thread as the MSDN docs suggest. Any ideas what I've done wrong without me posting the code?
@BrendanE
The code for the hook I'm using works pretty good so far. It works on most windows, but not all.
Right now it's set up so it only catches menu item clicks on menu items whose content is of the string type.
I should have it cleaned up enough to post some code later tonight or early tomorrow. I'm new to DLL's and hooks, so my code will definately need some expert clean up. Even so, maybe it will help you in your project.
As for your current problem, it's hard to say what the problem is without seeing some of the code. I do know (I think) that in order for the hook to work outside your app, you must use a shared DLL.
Whst type of hook are you specifying in SetWindowsHookEx_() idHook parameter?
The code for the hook I'm using works pretty good so far. It works on most windows, but not all.

I should have it cleaned up enough to post some code later tonight or early tomorrow. I'm new to DLL's and hooks, so my code will definately need some expert clean up. Even so, maybe it will help you in your project.

As for your current problem, it's hard to say what the problem is without seeing some of the code. I do know (I think) that in order for the hook to work outside your app, you must use a shared DLL.
Whst type of hook are you specifying in SetWindowsHookEx_() idHook parameter?
What goes around comes around.
PB 5.21 LTS (x86) - Windows 8.1
PB 5.21 LTS (x86) - Windows 8.1
Sparkie,
Thanks for that - yes I've done it just as you have - the hook function is in a shared dll - as is the installHook function below...
my hook function simply check for any #MSGF_MENU code and calls back a callback function (which is in my app).... which works fine for the app events themselves - but I see nothing for event desitined for any other windows.... very puzzling.
I'm not writing any specific app - it was an intruiging learning excercise - seems like I still have to learn a few things
Thanks for that - yes I've done it just as you have - the hook function is in a shared dll - as is the installHook function below...
Code: Select all
ProcedureDLL.l installHook(hDLL, *hookFunction)
hHook = SetWindowsHookEx_(#WH_MSGFILTER, *hookFunction, hDLL, 0)
EndProcedure
ProcedureDLL.l MenuFilter(code.l, wParam.l, lParam.l)
If *callBackFunction <> 0
*msg.MSG = lParam
If code = #MSGF_MENU
If *msg\message = #WM_MENUSELECT
; a menu item has been selected
CallFunctionFast(*callBackFunction, *msg\hwnd, *msg\wParam, *msg\lParam)
EndIf
EndIf
EndIf
ProcedureReturn CallNextHookEx_(hHook, code, wParam, lParam)
EndProcedure
.............. in my app I'm calling this to set up the hook
CallFunction(0, "installHook", hDLL, GetProcAddress_(hDLL, "MenuFilter"))
my hook function simply check for any #MSGF_MENU code and calls back a callback function (which is in my app).... which works fine for the app events themselves - but I see nothing for event desitined for any other windows.... very puzzling.
I'm not writing any specific app - it was an intruiging learning excercise - seems like I still have to learn a few things

@BrendanE - Here's what I have so far. It's not complete but it is 85% functional in that not all menu items are being detected at this time. Tested and working on WinXP with PB3.91F
I'm posting this so you can see what is working for me and maybe it will give you a clue as to what might be going wrong in your code.
This is my dll...
mnutxt.dll
And my main app. Not much to look at but then this is just a learn-to-hook project for me. 
menuhook.pb
I'm posting this so you can see what is working for me and maybe it will give you a clue as to what might be going wrong in your code.
This is my dll...
mnutxt.dll
Code: Select all
ProcedureDLL MyMessageProc(code.l, wParam.l, lParam.l)
#MIIM_ID = $2
#MIIM_TYPE = $10
#MF_POPUP = $10
#MSGF_MENU = $2
#WM_MENUSELECT = $11F
winText$ = Space(256) ; init buffer for window text
mItem.MENUITEMINFO ; Structure for menu info
mItem\cbSize = SizeOf(MENUITEMINFO) ; required
mItem\fMask = #MIIM_TYPE | #MIIM_ID ; mask flag(s)
hMyWin = FindWindow_("WindowClass_0","Get_Menu_Info") ; our window for displaying results
*mymsg.MSG = lParam ; MSG structure holds info
menuMessage = *mymsg\message ; get menu message
If code = #MSGF_MENU And menuMessage = #WM_MENUSELECT ; only concerned with menu being selected
hMenu = *mymsg\lParam ; handle to menu
menuType = *mymsg\wParam>>16 & $FFFF ; hiword of wparam = menuitem with or without submenu?
menuIndex = *mymsg\wParam & $FFFF ; loword of wparam = menu index or menuitem ID
If menuType&#MF_POPUP <>0 ; determine if menuitem is a popup
subYN.l = #True ; item is a popup
Else
subYN.l = #False ; item is not a popup
EndIf
menuText$ = "" ; init string holder to null
mItem\dwTypeData = @menuText$ ; init null string into mItem
GetMenuItemInfo_(hMenu, menuIndex, subYN, @mItem) ; first call gets the string size
menuText$ = Space(mItem\cch+1) ; add 1 to string size
mItem\dwTypeData = @menuText$ ; put sized string into mItem
mItem\cch +1 ; add one to string size (SDK says so)
GetMenuItemInfo_(hMenu, menuIndex, subYN, @mItem) ; second call puts the text into mItem
GetWindowText_(*mymsg\hwnd, @winText$, 256) ; get text of calling window for display
hWinHndGadget = ChildWindowFromPoint_(hMyWin, 120, 10) ; locate TextGgadget to display window handle
SendMessage_(hWinHndGadget, #WM_SETTEXT, 0, Str(*mymsg\hwnd)) ; send window handle to my app gadget
hWinTxtGadget = ChildWindowFromPoint_(hMyWin, 120, 30) ; locate TextGadget to display window text
SendMessage_(hWinTxtGadget, #WM_SETTEXT, 0, winText$) ; send window text to my app gadget
hMnuIdGadget = ChildWindowFromPoint_(hMyWin, 120, 70) ; locate TextGadget to display Menu ID
SendMessage_(hMnuIdGadget, #WM_SETTEXT, 0, Str(mItem\wID)) ; send menu id to my app gadget
hMenuTxtGadget = ChildWindowFromPoint_(hMyWin, 120, 90) ; locate TextGadget to display Menu text
SendMessage_(hMenuTxtGadget, #WM_SETTEXT, 0, menuText$) ; send menu text to my app gadget
EndIf
ProcedureReturn CallNextHookEx_(@MyMessageProc(), code, wParam, lParam)
EndProcedure

menuhook.pb
Code: Select all
Enumeration
#Window_0
EndEnumeration
Enumeration
#Window_Handle_Label
#Window_Handle
#Window_Text_Label
#Window_Text
#Menu_ID_Label
#Menu_ID
#Menu_Text_Label
#Menu_Text
#Button_Hook
#Button_Quit
EndEnumeration
If OpenWindow(#Window_0, 0, 0, 550, 160, #PB_Window_ScreenCentered | #PB_Window_SystemMenu, "Get_Menu_Info")
If CreateGadgetList(WindowID(0))
TextGadget(#Window_Handle_Label, 10, 10, 100, 20, "Window Handle:")
TextGadget(#Window_Handle, 120, 10, 420, 20, "")
TextGadget(#Window_Text_Label, 10, 30, 100, 20, "Window Text:")
TextGadget(#Window_Text, 120, 30, 420, 40, "")
TextGadget(#Menu_ID_Label, 10, 70, 100, 20, "Menu Item ID:")
TextGadget(#Menu_ID, 120, 70, 420, 20, "")
TextGadget(#Menu_Text_Label, 10, 90, 100, 20, "Menu Item Text:")
TextGadget(#Menu_Text, 120, 90, 420, 20, "")
ButtonGadget(#Button_Hook, 10, 130, 150, 20, "Start hooking menus")
ButtonGadget(#Button_Quit, 470, 130, 70, 20, "Quit")
EndIf
SetWindowPos_(WindowID(#Window_0),#HWND_TOPMOST,0,0,0,0,#SWP_NOMOVE|#SWP_NOSIZE) ; keep window on top
EndIf
Repeat
Event = WaitWindowEvent()
Select Event
Case #PB_Event_Gadget
Select EventGadgetID()
Case #Button_Hook
If GetGadgetText(#Button_Hook) = "Start hooking menus"
hDLL = OpenLibrary(0, "mnutxt.dll")
If hDLL
hmyHook = SetWindowsHookEx_(#WH_MSGFILTER, GetProcAddress_(hDLL, "MyMessageProc"), hDLL, 0)
SetGadgetText(#Button_Hook, "Stop hooking menus")
Else
MessageRequester("Error", "Not able to open file: mnutxt.dll", #MB_ICONERROR)
EndIf
ElseIf EventGadgetID() = #Button_Hook And GetGadgetText(#Button_Hook) = "Stop hooking menus"
UnhookWindowsHookEx_(hmyHook)
CloseLibrary(0)
hDLL = #False
SetGadgetText(#Window_Handle, "")
SetGadgetText(#Window_Text, "")
SetGadgetText(#Menu_ID, "")
SetGadgetText(#Menu_Text, "")
SetGadgetText(#Button_Hook, "Start hooking menus")
EndIf
Case #Button_Quit
quit = #True
EndSelect
Case #PB_Event_CloseWindow
quit = #True
EndSelect
Until quit = #True
UnhookWindowsHookEx_(hmyHook)
CloseLibrary(0)
hDLL = #False
End
What goes around comes around.
PB 5.21 LTS (x86) - Windows 8.1
PB 5.21 LTS (x86) - Windows 8.1
-
- User
- Posts: 11
- Joined: Wed Apr 26, 2006 9:27 pm
Hi Sparkie,
it's long time ago that you have entered this code but only now I have read it
and maybe you can give me a short assist.
I would like to check buttons but I don't find any information about it.
Do you know if it is possible? And if yes, where I can find more information
about it?
Many thanks in advance,
Daniel
BTW, is it possible to check if the text from a button is truncated or not.
[ Save ]
-> truncated
[ Sav ]
it's long time ago that you have entered this code but only now I have read it
and maybe you can give me a short assist.
I would like to check buttons but I don't find any information about it.
Do you know if it is possible? And if yes, where I can find more information
about it?
Many thanks in advance,
Daniel
BTW, is it possible to check if the text from a button is truncated or not.
[ Save ]
-> truncated
[ Sav ]