Siao Posted November 6, 2007 Share Posted November 6, 2007 (edited) Well, forum search on this didn't return anything noteworthy for me, so here we go. Shell hooking is monitoring window activity, which helps when automating apps. This particular method is pretty similar to installing WH_SHELL hook with SetWindowsHookEx, but instead of callback proc it makes use of window's proc, so GuiRegisterMsg() can be used. How to set it up: First we have to register unique message - RegisterWindowMessage("SHELLHOOK") Then GuiRegisterMsg() the message with a handler function, and of course hook up our GUI with RegisterShellHookWindow (and unregister when not needed anymore). And that's pretty much it. What it does: $HSHELL_WINDOWCREATED, $HSHELL_WINDOWACTIVATED, $SHELL_WINDOWDESTROYED Notifies when some window is created, activated or destroyed. Gives window handle. $HSHELL_REDRAW Notifies when some window (taskbar button?) is redrawed, mainly due to change of its title. Gives window handle. $HSHELL_FLASH Notifies when some window is flashing (is followed with $HSHELL_REDRAW). Gives window handle. $HSHELL_GETMINRECT Happens when some window is minimized/maximized, and is supposed to give rectangle coords with SHELLHOOKINFO structure, but that part isn't working for me, only window handle is. $HSHELL_ACCESSIBILITYSTATE Notifies when some accessibility options change... $HSHELL_SYSMENU Notifies when some window's system menu is brought up by right clicking its taskbar button. Gives window handle. Other codes never triggered for me, but YMMV. Much of this functionality can be achieved by polling WinActivate, WinExists and etc., but that is so uncool (not to mention CPU usage it may take if you want to monitor all windows). I threw this together when I was experimenting with various ways to keep other apps from stealing keyboard focus from my text editor. Would be possible to write some taskbar-like utility using these too. expandcollapse popup#include <GuiConstants.au3> #include <Misc.au3> #NoTrayIcon Opt("GUICloseOnESC", 0) Opt("GUIOnEventMode", 1) Opt("WinWaitDelay", 0) Global Const $WM_SYSCOMMAND = 0x0112 Global Const $SC_MOVE = 0xF010 Global Const $SC_SIZE = 0xF000 Global Const $SC_CLOSE = 0xF060 ;ShellHook notification codes: Global Const $HSHELL_WINDOWCREATED = 1; Global Const $HSHELL_WINDOWDESTROYED = 2; Global Const $HSHELL_ACTIVATESHELLWINDOW = 3; Global Const $HSHELL_WINDOWACTIVATED = 4; Global Const $HSHELL_GETMINRECT = 5; Global Const $HSHELL_REDRAW = 6; Global Const $HSHELL_TASKMAN = 7; Global Const $HSHELL_LANGUAGE = 8; Global Const $HSHELL_SYSMENU = 9; Global Const $HSHELL_ENDTASK = 10; Global Const $HSHELL_ACCESSIBILITYSTATE = 11; Global Const $HSHELL_APPCOMMAND = 12; Global Const $HSHELL_WINDOWREPLACED = 13; Global Const $HSHELL_WINDOWREPLACING = 14; Global Const $HSHELL_RUDEAPPACTIVATED = 32772; Global Const $HSHELL_FLASH = 32774; Global $bHook = 1 ;GUI stuff: Global $iGuiW = 400, $iGuiH = 50, $sTitle = "Shell Hooker", $aBtnText[2] = ["START", "STOP"] $hGui = GUICreate($sTitle, $iGuiW, $iGuiH, -1, 0, $WS_POPUP+$WS_BORDER, $WS_EX_TOPMOST) GUISetOnEvent($GUI_EVENT_CLOSE, "SysEvents") GUISetOnEvent($GUI_EVENT_PRIMARYDOWN, "SysEvents") GUIRegisterMsg($WM_SYSCOMMAND, "On_WM_SYSCOMMAND") $cBtnMini = GUICtrlCreateButton("v", $iGuiW-$iGuiH, 0, $iGuiH/2, $iGuiH/2) GUICtrlSetOnEvent(-1, "CtrlEvents") GUICtrlSetTip(-1, "Minimize") $cBtnClose = GUICtrlCreateButton("X", $iGuiW-$iGuiH/2, 0, $iGuiH/2, $iGuiH/2) GUICtrlSetOnEvent(-1, "CtrlEvents") GUICtrlSetTip(-1, "Exit") $cBtnHook = GUICtrlCreateButton("", $iGuiW-$iGuiH, $iGuiH/2, $iGuiH, $iGuiH/2) GUICtrlSetData(-1, $aBtnText[$bHook]) GUICtrlSetTip(-1, "Hook/Unhook Shell") GUICtrlSetOnEvent(-1, "CtrlEvents") $cList = GUICtrlCreateList("", 0, 0, $iGuiW-$iGuiH-1, $iGuiH, $LBS_NOINTEGRALHEIGHT+$WS_VSCROLL) GUICtrlSetOnEvent(-1, "CtrlEvents") ;Hook stuff: GUIRegisterMsg(RegisterWindowMessage("SHELLHOOK"), "HShellWndProc") ShellHookWindow($hGui, $bHook) GUISetState() While 1 Sleep(1000) WEnd Func SysEvents() Switch @GUI_CtrlId Case $GUI_EVENT_CLOSE Exit Case $GUI_EVENT_PRIMARYDOWN ;CTRL + Left click to drag GUI If _IsPressed("11") Then DllCall("user32.dll", "int", "ReleaseCapture") DllCall("user32.dll", "int", "SendMessage", "hWnd", $hGui, "int", 0xA1, "int", 2, "int", 0) EndIf EndSwitch EndFunc Func CtrlEvents() Switch @GUI_CtrlId Case $cBtnMini GUISetState(@SW_MINIMIZE) Case $cBtnClose _SendMessage($hGui, $WM_SYSCOMMAND, $SC_CLOSE, 0) Case $cBtnHook $bHook = BitXOR($bHook, 1) ShellHookWindow($hGui, $bHook) GUICtrlSetData($cBtnHook, $aBtnText[$bHook]) EndSwitch EndFunc Func HShellWndProc($hWnd, $Msg, $wParam, $lParam) Switch $wParam Case $HSHELL_WINDOWCREATED MsgPrint("Window created: " & $lParam & " (" & WinGetTitle($lParam) & ")") Case $HSHELL_WINDOWDESTROYED MsgPrint("Window destroyed: " & $lParam) Case $HSHELL_ACTIVATESHELLWINDOW MsgPrint("HSHELL_ACTIVATESHELLWINDOW: Not used."); Case $HSHELL_WINDOWACTIVATED MsgPrint("Window activated: " & $lParam & " (" & WinGetTitle($lParam) & ")") Case $HSHELL_GETMINRECT Local $tSHELLHOOKINFO = DllStructCreate("hwnd hwnd;int left;long top;long right;long bottom", $lParam) MsgPrint("HSHELL_GETMINRECT: " & HWnd(DllStructGetData($tSHELLHOOKINFO, "hwnd")) & ' (' & _ DllStructGetData($tSHELLHOOKINFO, "left") & ',' & _ DllStructGetData($tSHELLHOOKINFO, "top") & ',' & _ DllStructGetData($tSHELLHOOKINFO, "right") & ',' & _ DllStructGetData($tSHELLHOOKINFO, "bottom") & ')') Case $HSHELL_REDRAW MsgPrint("Window redraw: " & $lParam & " (" & WinGetTitle($lParam) & ")") Case $HSHELL_TASKMAN MsgPrint("HSHELL_TASKMAN: Can be ignored."); Case $HSHELL_LANGUAGE MsgPrint("HSHELL_LANGUAGE: " & $lParam); Case $HSHELL_SYSMENU MsgPrint("HSHELL_SYSMENU: " & $lParam); Case $HSHELL_ENDTASK MsgPrint("Window needs to be closed: " & $lParam & " (" & WinGetTitle($lParam) & ")") Case $HSHELL_ACCESSIBILITYSTATE MsgPrint("HSHELL_ACCESSIBILITYSTATE: " & $lParam); Case $HSHELL_APPCOMMAND MsgPrint("HSHELL_APPCOMMAND: " & $lParam); Case $HSHELL_WINDOWREPLACED MsgPrint("Window replaced: " & $lParam & " (" & WinGetTitle($lParam) & ")") Case $HSHELL_WINDOWREPLACING MsgPrint("Window replacing: " & $lParam & " (" & WinGetTitle($lParam) & ")") Case $HSHELL_RUDEAPPACTIVATED MsgPrint("HSHELL_RUDEAPPACTIVATED: " & $lParam); Case $HSHELL_FLASH MsgPrint("Window flash: " & $lParam & " (" & WinGetTitle($lParam) & ")") Case Else MsgPrint("Unknown ShellHook message: " & $wParam & " , " & $lParam) EndSwitch EndFunc ;register/unregister ShellHook Func ShellHookWindow($hWnd, $bFlag) Local $sFunc = 'DeregisterShellHookWindow' If $bFlag Then $sFunc = 'RegisterShellHookWindow' Local $aRet = DllCall('user32.dll', 'int', $sFunc, 'hwnd', $hWnd) MsgPrint($sFunc & ' = ' & $aRet[0]) Return $aRet[0] EndFunc Func MsgPrint($sText) ConsoleWrite($sText & @CRLF) GUICtrlSendMsg($cList, $LB_SETCURSEL, GUICtrlSendMsg($cList, $LB_ADDSTRING, 0, $sText), 0) EndFunc ;register window message Func RegisterWindowMessage($sText) Local $aRet = DllCall('user32.dll', 'int', 'RegisterWindowMessage', 'str', $sText) Return $aRet[0] EndFunc Func On_WM_SYSCOMMAND($hWnd, $Msg, $wParam, $lParam) Switch BitAND($wParam, 0xFFF0) Case $SC_MOVE, $SC_SIZE Case $SC_CLOSE ShellHookWindow($hGui, 0) Return $GUI_RUNDEFMSG ;Exit EndSwitch EndFuncShellHookWindow.au3 Edited November 6, 2007 by Siao "be smart, drink your wine" Link to comment Share on other sites More sharing options...
A. Percy Posted November 6, 2007 Share Posted November 6, 2007 Nice! Good work! Só o que posso lhe dizer, bom é quando faz mal!My work:Au3Irrlicht - Irrlicht for AutoItMsAgentLib - An UDF for MSAgentAu3GlPlugin T2 - A 3D plugin for AutoIt...OpenGl Plugin - The old version of Au3GlPlugin.MAC Address Changer - Changes the MAC AddressItCopter - A dragonfly R/C helicopter simulator VW Bug user Pinheiral (Pinewood) city: http://pt.wikipedia.org/wiki/Pinheiral Link to comment Share on other sites More sharing options...
zfisherdrums Posted November 6, 2007 Share Posted November 6, 2007 Very nice!!! I will enjoy using the functionality you have demonstrated in our automation framework(s). Thank you so very much for sharing this! Zach... Identify .NET controls by their design time namesLazyReader© could have read all this for you. Unit Testing for AutoItFolder WatcherWord Doc ComparisonThis here blog... Link to comment Share on other sites More sharing options...
JohnBailey Posted November 6, 2007 Share Posted November 6, 2007 AMAZING!!!! WELL DONE A decision is a powerful thing Link to comment Share on other sites More sharing options...
JohnBailey Posted November 6, 2007 Share Posted November 6, 2007 You answered a problem I had! See: http://www.autoitscript.com/forum/index.php?showtopic=56129THANK YOU THANK YOU THANK YOU A decision is a powerful thing Link to comment Share on other sites More sharing options...
magician13134 Posted November 13, 2007 Share Posted November 13, 2007 (edited) Very good work! My only question is how to use this without a GUI. I tried commenting out everything that looked like GUI stuff, but then it didn't work (go figure ) I want to use these hooks in a program I'm writing, so I just want your script to alert my program anytime one of these events happens. Thanks for any help! Also, is there any way to grab the name of a window before it gets closed? Edited November 13, 2007 by magician13134 Visit Magic Soft Inc. for some of my software Link to comment Share on other sites More sharing options...
Siao Posted November 14, 2007 Author Share Posted November 14, 2007 Very good work! My only question is how to use this without a GUI. I tried commenting out everything that looked like GUI stuff, but then it didn't work (go figure )I want to use these hooks in a program I'm writing, so I just want your script to alert my program anytime one of these events happens. Thanks for any help!You need a window which will be receiving the messages. It doesn't have to be visible. So you need GUICreate.Also, is there any way to grab the name of a window before it gets closed?Using this method?I assume these notifications are received post factum. So when you receive "window destroyed" notification, there's no such window to get the title from anymore.Keep a list, array or whatever, of handles and titles from $HSHELL_WINDOWCREATED, $HSHELL_REDRAW (and possibly $HSHELL_WINDOWACTIVATED). This will allow you to get the last known window title by the handle you get from $SHELL_WINDOWDESTROYED. "be smart, drink your wine" Link to comment Share on other sites More sharing options...
magician13134 Posted November 14, 2007 Share Posted November 14, 2007 Ok, cool, thanks for your answers. Also, I'm using a pre-stored WinList() array that gets updated every time a window is created or destroyed to find the name of the hWnd. Thanks for all your help. Visit Magic Soft Inc. for some of my software Link to comment Share on other sites More sharing options...
Armand Posted November 24, 2007 Share Posted November 24, 2007 OVERWHELMING WORK !!!! p.s - where can i find all the windows msgs ?! [u]My Au3 Scripts:[/u]____________(E)Lephant, A Share download manager (RS/MU etc)Http1.1 Console, The Ez Way!Internet Reconnection Automation Suite & A Macro Recording Tool.SK's Alarm Clock, Playing '.MP3 & .Wav' Files._________________Is GOD a mistake of the Humanity Or the Humanity is a mistake of GOD ?! Link to comment Share on other sites More sharing options...
Fossil Rock Posted January 3, 2008 Share Posted January 3, 2008 Would something like this be able to "grab" text from a textbox while the app is minimized or would it require something completely different? Basically intercepting the messages before getting to the textbox. Agreement is not necessary - thinking for one's self is! Link to comment Share on other sites More sharing options...
Oldschool Posted March 18, 2008 Share Posted March 18, 2008 OMG, I just found this Siao...great work. 4 months later... Link to comment Share on other sites More sharing options...
koushik Posted June 24, 2008 Share Posted June 24, 2008 good work!! Thanks for sharing Link to comment Share on other sites More sharing options...
Skrip Posted June 25, 2008 Share Posted June 25, 2008 very nice. [left][sub]We're trapped in the belly of this horrible machine.[/sub][sup]And the machine is bleeding to death...[/sup][sup][/sup][/left] Link to comment Share on other sites More sharing options...
rasim Posted July 3, 2008 Share Posted July 3, 2008 Very nice and useful! Five stars! Thank you Siao muttley Link to comment Share on other sites More sharing options...
Zedna Posted July 3, 2008 Share Posted July 3, 2008 Very nice siao. Your examples are really good! Resources UDF Â ResourcesEx UDF Â AutoIt Forum Search Link to comment Share on other sites More sharing options...
sandin Posted July 4, 2008 Share Posted July 4, 2008 This is soo cool!!, I want this to use in my script, but it's not hooking all windows like task manager. Is it possible to make it hook all windows? oO Some cool glass and image menu | WinLIRC remote controler | Happy Holidays to all... | Bounce the sun, a game in which you must save the sun from falling by bouncing it back into the sky | Hook Leadtek WinFast TV Card Remote Control Msges | GDI+ sliding toolbar | MIDI Keyboard (early alpha stage, with lots of bugs to fix) | Alt+Tab replacement | CPU Benchmark with pretty GUI | Ini Editor - Edit/Create your ini files with great ease | Window Manager (take total control of your windows) Pretty GUI! | Pop-Up window from a button | Box slider for toolbar | Display sound volume on desktop | Switch hotkeys with mouse scroll Link to comment Share on other sites More sharing options...
Guest Posted February 2, 2009 Share Posted February 2, 2009 I have the same question: Nearly all window creation events of the system control windows are not recognized. Interesting enough, destroying the windows is always recognized... Any hints? Link to comment Share on other sites More sharing options...
CosmicDan Posted February 3, 2009 Share Posted February 3, 2009 Would this allow me to add items to the system menu (context menu of a programs' taskbar)? I can't figure it out... if so, WOW. CosmicDan.com Link to comment Share on other sites More sharing options...
CosmicDan Posted November 19, 2009 Share Posted November 19, 2009 Once we add a new menu item (for example, in an external System Menu), how does one get the Control ID of the new clicked MenuItem? I can't seem to get it to send a message back to the AutoIt script/GUI. I tried a few things; a new WM_SYSCOMMAND case, the DummyGUI method, some other random nonsense and experimentation... couldn't get anything to fire as far as Winspector could tell. Maybe it's a problem with On Event mode? Or unique to Windows 7? UAC is off for this machine though. Any tips or pointers would be totally awesome - I'm not asking for an example, but if someone knows a specific function I should try out let me know For all those wondering, I'm basically trying to create a script like PowerMenu - only better/extensible since it will be open source (the original creator of the amazing PowerMenu prog has disappeared for years and kept it closed source...) - I would of posted what I have so far but it's largely identical to the OP's example with pretty much some extra Menu UDF commands (that part works) and cheap method of hooking any active window (it works for CMD.EXE and Task Manager!). Cheers! CosmicDan.com Link to comment Share on other sites More sharing options...
wraithdu Posted November 19, 2009 Share Posted November 19, 2009 You won't like the answer. Here's what I think you'd have to do: Inject a DLL into the target process, subclass the main window procedure so you can intercept the process's window messages, then set up some interprocess communication with your AutoIt script. 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