CosmicDan Posted November 20, 2009 Share Posted November 20, 2009 (edited) 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.Oh wow... that's a little over my head but thanks for the reply. I think I will be better off relying on Visual Studio to create this program after all... you can see a detailed subclassing/menu hooking example via this thread - http://www.vbforums.com/showthread.php?t=322261 ...Maybe I can use this precompiled C++ DLL to inject in the active window's process and handle the communication with AutoIt? I don't want to use an ugly ActiveX control, plus I think it's a bad idea using anything VB6 in Windows Vista/7! Regardless, the "HookControl" DLL in that thread has an included Readme.htm that is very interesting.EDIT: Hey wait - couldn't I use _GUICtrlMenu_GetItemState to check for state 16? I know it says 'highlighted' via AutoIt help, but upon a quick test I did just now it only triggers that on click - and not on mouse over. Alas, I can only get that to work in MessageLoop mode and with no sleep (otherwise it misses the fired click) and it obviously eats the CPU. Ah, maybe not... that's a sloppy method I guess. Hmm... Edited November 20, 2009 by DanielC CosmicDan.com Link to comment Share on other sites More sharing options...
Authenticity Posted November 20, 2009 Share Posted November 20, 2009 expandcollapse popup#include <GuiMenu.au3> #include <WindowsConstants.au3> #include "WinEventHook.au3" HotKeySet('{ESC}', '_EXIT') If Not IsDeclared("WM_LBUTTONDOWN") Then Global Const $WM_LBUTTONDOWN = 0x0201 Global Const $tagMSLLHOOKSTRUCT = $tagPOINT & ";uint mouseData;uint flags;uint time;uint_ptr dwExtraInfo;" Global Const $w00t = 0x8765 Global $hHookFunc, $hMouseFunc, $pFunc Global $hWinHook, $hMouseHook Global $hgMenu $hMouseFunc = DllCallbackRegister("_MouseHook", "int", "int;wparam;lparam") $pFunc = DllCallbackGetPtr($hMouseFunc) $hMouseHook = _WinAPI_SetWindowsHookEx($WH_MOUSE_LL, $pFunc, _WinAPI_GetModuleHandle(0)) $hHookFunc = DllCallbackRegister('_WinEventProc', 'none', 'ptr;uint;hwnd;int;int;uint;uint') $pFunc = DllCallbackGetPtr($hHookFunc) $hWinHook = _SetWinEventHook($EVENT_MIN, $EVENT_MAX, 0, $pFunc, 0, 0, _ BitOR($WINEVENT_SKIPOWNPROCESS, $WINEVENT_OUTOFCONTEXT)) If $hWinHook = 0 Then Exit MsgBox(0x10, 'Error', 'Could not register callback procedure') While 1 Sleep(20) WEnd Func _EXIT() Exit EndFunc Func OnAutoItExit() _WinAPI_UnhookWindowsHookEx($hMouseHook) DllCallbackFree($hMouseFunc) _UnhookWinEvent($hWinHook) DllCallbackFree($hHookFunc) EndFunc Func _WinEventProc($hHook, $iEvent, $hWnd, $iObjectID, $iChildID, $iEventThread, $imsEventTime) Local $hMenu If $iEvent = $EVENT_SYSTEM_MENUPOPUPSTART Then $hMenu = _SendMessage($hWnd, 0x01E1) $hgMenu = $hMenu If _GUICtrlMenu_IsMenu($hMenu) Then _GUICtrlMenu_InsertMenuItem($hMenu, _GUICtrlMenu_GetItemCount($hMenu), "w00t", $w00t) EndIf ElseIf $iEvent = $EVENT_SYSTEM_MENUPOPUPEND Then $hgMenu = 0 EndIf EndFunc Func _MouseHook($iCode, $iwParam, $ilParam) Local $tMouseInfo If $iCode >= 0 Then If $hgMenu And $iwParam = $WM_LBUTTONDOWN Then If _GUICtrlMenu_GetItemHighlighted($hgMenu, $w00t, False) Then ConsoleWrite("W00t :)" & @CRLF) EndIf EndIf Return _WinAPI_CallNextHookEx($hMouseHook, $iCode, $iwParam, $ilParam) EndFuncWinEventHook.au3 Link to comment Share on other sites More sharing options...
wraithdu Posted November 20, 2009 Share Posted November 20, 2009 (edited) Well I'll be damned...that's a nice trick EDIT - One thing to add: ElseIf $iEvent = $EVENT_SYSTEM_MENUPOPUPEND Then _GUICtrlMenu_RemoveMenu($hgMenu, $w00t, False) $hgMenu = 0 EndIf Edited November 20, 2009 by wraithdu Link to comment Share on other sites More sharing options...
Authenticity Posted November 20, 2009 Share Posted November 20, 2009 You don't need it, as the menu item is added on the fly so it won't be added to the added menu item the next time. Also, by the time you get $EVENT_SYSTEM_MENUPOPUPEND event, the $hgMenu is not pointing to an existing menu. Link to comment Share on other sites More sharing options...
wraithdu Posted November 20, 2009 Share Posted November 20, 2009 (edited) Mmm, not true for menu bar menus (File, View, etc). For context menus, no, you don't need it. I had to add it or I was getting 5..6..7 w00t's added to the bottom of all my menus. And it is removed correctly as well. Edited November 20, 2009 by wraithdu Link to comment Share on other sites More sharing options...
Authenticity Posted November 20, 2009 Share Posted November 20, 2009 Heh you learn new things every day. I didn't knew it works on other menu as well. Thanks for clarifying. Link to comment Share on other sites More sharing options...
CosmicDan Posted November 20, 2009 Share Posted November 20, 2009 (edited) Wow very nice use of a mouse hook, thanks a lot Authenticity! wraithdu too, that's a much better way of cleaning up than I was doing it (keeping an array of previous $hWnd vars and comparing to the active window) That WinEventHook include is full of candy, and this is a great example of hooking all those notifications... ooohhhoohooo crack for coders right there; much respect to the god who created such art for the AutoIt people...Further reading for other users/thread watchers:Mouse Input Notifications on MSDN (Use of others apart from WM_LBUTTONDOWN/Left-Click for added menu item triggers/fired events... many possibilities!) [EDIT: @ WM_NCHITTEST]Windows Event Constants on MSDN (Helpful descriptions of all the Constants in WinEventHook.au3)Yes indeed it adds a menu item to every single popup menu but referencing the original post it shouldn't be too hard to trigger it for only $WM_SYSCOMMAND events. Thanks again guys Edited November 21, 2009 by DanielC CosmicDan.com Link to comment Share on other sites More sharing options...
CosmicDan Posted November 21, 2009 Share Posted November 21, 2009 (edited) Thought this is also worth mentioning. Authenticity's method of injecting Menu Items into the Window Menu (System Menu) not only applies to a wide range of other menu's (like the Taskbar context for example), but if you're on a 64-bit Windows host then that alternative method only seems to insert the menu item for 64-bit processes. The OP's Shell Hook only works for 32-bit processes, the opposite.This is very very good.... one of the flaws of the original PowerMenu was that it only worked for 32-bit processes.EDIT: Thanks again guys, apologies for hijacking the thread Edited November 21, 2009 by DanielC CosmicDan.com Link to comment Share on other sites More sharing options...
JohnnyThrash Posted June 2, 2010 Share Posted June 2, 2010 You need a window which will be receiving the messages. It doesn't have to be visible. So you need GUICreate.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.According to msdn SHELL_WINDOWDESTROYED should return the handle of the closed window through the wparameter, this in theory works because the message is sent before the window is actually closed.Although, i'll grant you, for reasons unknown to me the wparam (or lparam) do not return the handle of the closed window. Any thoughts?I'm currently writing a shell replacement for windows so this type of information would be endlessly useful. Link to comment Share on other sites More sharing options...
JohnnyThrash Posted June 7, 2010 Share Posted June 7, 2010 According to msdn SHELL_WINDOWDESTROYED should return the handle of the closed window through the wparameter, this in theory works because the message is sent before the window is actually closed.Although, i'll grant you, for reasons unknown to me the wparam (or lparam) do not return the handle of the closed window. Any thoughts?I'm currently writing a shell replacement for windows so this type of information would be endlessly useful.I actually did get this working. I have a hge question though. Can this in anyway possible work without explorer.exe? I'm making a shell and everything was going great. Until a recent routine check to see how it'd operate independantly of explorer.exe. It seems the shell hooking doesn't work without it. =(Any thoughts? Link to comment Share on other sites More sharing options...
wraithdu Posted June 7, 2010 Share Posted June 7, 2010 You're hooking messages from the windows shell... that IS explorer.exe. If explorer is not running, you can't use this method. Your shell replacement is what should actually be generating and broadcasting these messages. Link to comment Share on other sites More sharing options...
JohnnyThrash Posted June 7, 2010 Share Posted June 7, 2010 You're hooking messages from the windows shell... that IS explorer.exe. If explorer is not running, you can't use this method. Your shell replacement is what should actually be generating and broadcasting these messages.Is that possible? How could that be done? Link to comment Share on other sites More sharing options...
wraithdu Posted June 7, 2010 Share Posted June 7, 2010 (edited) You're the one creating the shell replacement... you tell us. I don't think you quite understand all that the 'shell' is supposed to do. It's window management, messaging, everything that you see. Edited June 7, 2010 by wraithdu Link to comment Share on other sites More sharing options...
JohnnyThrash Posted June 7, 2010 Share Posted June 7, 2010 (edited) You're the one creating the shell replacement... you tell us. I don't think you quite understand all that the 'shell' is supposed to do. It's window management, messaging, everything that you see.Yes, I don't think "Shell Replacement" puts such a fine point on what I mean. I'm using it more as the term it has become, since what I'm creating isn't an entire shell replacement. It's simply an interface similar to the once provided by the windows shell (ie. desktop, taskbar, file browser, etc.) that runs independantly of explorer.exe, that is the so explorer.exe is intended to not be running. With that said is there any way I can incorporate the functionality of explorer's shell hooking with explorer.exe running? Or is there maybe even a way to run explorer.exe without anything superfluous running? Like the taskbar, and start menu, desktop, and etc?Also, for what it's worth, bear in mind Window's windows can still exist without explorer.exe. My trick now will be in detecting how the are interacted with, without explorer.exe running if that's possible. Edited June 7, 2010 by JohnnyThrash Link to comment Share on other sites More sharing options...
picea892 Posted June 7, 2010 Share Posted June 7, 2010 Probably best to take this discussion off the examples forum and reconvene in General help. See my taskbar in signature for an example Perhaps this script will also help. Should hide taskbar, start menu and desktop for 3 seconds (works on XP and Vista) #include <Winapi.au3> _ShowTaskBar(1) WinSetTrans("[CLASS:Progman]","",0) WinSetTrans("Start","",0) sleep(2000) WinSetTrans("[CLASS:Progman]","",255) WinSetTrans("Start","",255) _ShowTaskBar(0) Func _ShowTaskBar($fShow) Local $hTaskBar If @OSVersion = "WIN_VISTA" Then _ShowStartButton($fShow) $hTaskBar = _WinAPI_FindWindow("Shell_TrayWnd", "") If $fShow=0 Then _WinAPI_ShowWindow($hTaskBar, @SW_SHOW) Else _WinAPI_ShowWindow($hTaskBar, @SW_HIDE) EndIf EndFunc ;==>_ShowTaskBar Func _ShowStartButton($fShow ) Local $hTaskBar, $hStartButton If @OSVersion = "WIN_VISTA" Then $hStartButton = _WinAPI_FindWindow("Button", "Start") Else $hTaskBar = _WinAPI_FindWindow("Shell_TrayWnd", "") $hStartButton = ControlGetHandle($hTaskBar, "", "Button1") EndIf If $fShow=0 Then _WinAPI_ShowWindow($hStartButton, @SW_SHOW) Else _WinAPI_ShowWindow($hStartButton, @SW_HIDE) EndIf EndFunc ;==>_ShowStartButton Link to comment Share on other sites More sharing options...
JohnnyThrash Posted June 8, 2010 Share Posted June 8, 2010 Probably best to take this discussion off the examples forum and reconvene in General help. See my taskbar in signature for an example Perhaps this script will also help. Should hide taskbar, start menu and desktop for 3 seconds (works on XP and Vista) #include <Winapi.au3> _ShowTaskBar(1) WinSetTrans("[CLASS:Progman]","",0) WinSetTrans("Start","",0) sleep(2000) WinSetTrans("[CLASS:Progman]","",255) WinSetTrans("Start","",255) _ShowTaskBar(0) Func _ShowTaskBar($fShow) Local $hTaskBar If @OSVersion = "WIN_VISTA" Then _ShowStartButton($fShow) $hTaskBar = _WinAPI_FindWindow("Shell_TrayWnd", "") If $fShow=0 Then _WinAPI_ShowWindow($hTaskBar, @SW_SHOW) Else _WinAPI_ShowWindow($hTaskBar, @SW_HIDE) EndIf EndFunc ;==>_ShowTaskBar Func _ShowStartButton($fShow ) Local $hTaskBar, $hStartButton If @OSVersion = "WIN_VISTA" Then $hStartButton = _WinAPI_FindWindow("Button", "Start") Else $hTaskBar = _WinAPI_FindWindow("Shell_TrayWnd", "") $hStartButton = ControlGetHandle($hTaskBar, "", "Button1") EndIf If $fShow=0 Then _WinAPI_ShowWindow($hStartButton, @SW_SHOW) Else _WinAPI_ShowWindow($hStartButton, @SW_HIDE) EndIf EndFunc ;==>_ShowStartButton I'm sorry, you're right I should not have hijacked the topic, that wasn't my intention. Thanks for your script above. That should help if it becomes necessary to run my shell along side explorer.exe. Your taskbar example suffers from the same problem as mine unfortunately. Shell Hooking, like checking to see if a window is created or destroyed only works if explorer.exe is running, near as I can tell. I'm starting another topic for this it can be found here: http://www.autoitscript.com/forum/index.php?showtopic=115520 Link to comment Share on other sites More sharing options...
CountyIT Posted November 17, 2012 Share Posted November 17, 2012 Sorry about posting in a two year old topic but I am not sure what else to do. The original script is an X-L-Ant piece of work. It is exactly what I am interested in but there is a problem. When I have a tray icon (for example TeamView) and I right mouse click on it and do an "about" a windows pops up in the middle of the screen with the "about" information yet the Hooks don't pick up anything being created or activated. It seems like all the tray icons are like that. Is there any way to detect Windows opened from tray icon items like the problem I stated? Link to comment Share on other sites More sharing options...
argumentum Posted October 29 Share Posted October 29 (edited) Global Const $HSHELL_MONITORCHANGED = 16 ; https://chromium.googlesource.com/chromium/deps/perl/+/master/c/i686-w64-mingw32/include/winuser.h Global Const $HSHELL_WINDOW_FullScreenEnter = 0x35 Global Const $HSHELL_WINDOW_FullScreenExit = 0x36 ; https://github.com/dechamps/RudeWindowFixer I think the best place to have these, are on this post. These are to have a few less "Unknown ShellHook message". Edited October 29 by argumentum added reference Follow the link to my code contribution ( and other things too ). FAQ - Please Read Before Posting. 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