[How to] Hook on to Shell to receive its messages?
But please, do more comments in the code, it's hardly readable for newbies like me.
What I have going on is a software I run pops up a window when i go to an action that wants to confirm that's what I really want to do. I want to detect that small prompt window and always press the yes button.
So, I've been copy/pasting code from this thread and trying different things. It's a bit frustrating because I don't really understand all the stuff in the code. I've not got it to work yet; however, I'm wondering if this is because it might be a child window as I read in this thread somewhere from someone who wanted to work with a Save As window.
Any ideas for me on this?
Thanks for any help.
<!-- l --><a class="postlink-local" href="http://www.autohotkey.com/community/viewtopic.php?f=2&t=93074">viewtopic.php?f=2&t=93074</a><!-- l -->
Also, the window you might be trying to catch isn't being created, but just activated (from hidden state).
Hook also might be overkill for your needs. You can use SetTimer to search for the active window like 4 times a second, which is usually fast enough but does not hog too many resources.
Checkout the following <!-- l --><a class="postlink-local" href="http://www.autohotkey.com/community/viewtopic.php?f=2&t=63673">viewtopic.php?f=2&t=63673</a><!-- l -->
ehmmm ... I think using hooks instead of having an endless checking loop that has up to %PeriodTime% delay is the whole point of the idea here, isn't it?!
why could this be an overkill?
I really have no idea of the performance implications here. :roll:
but thanks for the lib link. I'm trying that one now.. seems there are similar versions on the forums though..
@SKAN Excellent thread...I'm new to Autohotkey and not a developer, so this thread was priceless to me
I use an application that works primarily with caps lock on (!) and it's a real pain when switching between apps and remembering to toggle it on and off, so I thought I would try to write a script that would do it for me automatically every time I switched to and from the application. I persisted with trying to get it to work and the bit that really helped me out was the shellspy script to identify what was going on behind the scenes.
Anyway, I though I'd just post up my simple code that, so far, flawlessly toggles caps lock on and off when switching between applications in case it is of use to anyone else ast some point in time. Equally, if there's a better way of doing it, I'd love to hear about it.
; script to toggle Caps lock on and off when switching between Sun and other applications #Persistent SetBatchLines, -1 Process, Priority,, High Gui +LastFound hWnd := WinExist() DllCall( "RegisterShellHookWindow", UInt,hWnd ) MsgNum := DllCall( "RegisterWindowMessage", Str,"SHELLHOOK" ) OnMessage( MsgNum, "ShellMessage" ) Return ShellMessage( wParam,lParam ) { If ( wParam = 32772 or WParam = 4) ; HSHELL_WINDOWACTIVATED := 4 or 32772 WinGetActiveTitle, Title If ( Title = "sun 4 - foxtrot - Remote Desktop Connection" ) SetCapsLockState, on else SetCapsLockState, off }
I was playing around with this, and noticed if you include more variables in the shellmessage definition, more infmoration is passed, e.g.
ShellMessage(wParam, lParam, 3 := "", 4 := "") { ToolTip, | %wParam% | %lParam% | %3% | %4% }
I can't seem to find where these are defined on MSDN.
interesting....
I’m looking at this thread to solve a problem with a third-party program.
Cylog’s WildRename is a great batch-renaming program, but for some reason the developers neglected to set the app window’s Maximize-box style setting (below). This seems more like a bug than a (baffling) design choice because the window is stretchable and does correctly adjust, it just doesn’t have the maximize box enabled.
The program is no longer updated, so I tried looking into hacking the binary to enable the maximize box, but that hasn’t panned out.
I figured that maybe AutoHotkey could do handle the task; it’s certainly capable of changing the style of the program’s window, but the trick is to do it automatically. Unfortunately it turns out that the window-existence abilities can only check for existing windows rather than trigger when a window is created. Searching for a solution lead me here.
This thread looks promising and it certainly works for other things like Calculator, but WildRename is a Delphi program that seems to be a little odd and won’t work.
After doing some tests, it looks like what’s happening is that when WildRename runs, it creates a master window, but the window we see is a secondary one that is created afterwards. Worse, the visible window looks to be created with a placeholder title which gets changed after it reads the version number. As such, this thread’s window-creation hook doesn't pick up the correct window.
For now, I have resorted to using a script from a different thread here that triggers whenever the window becomes active, but that is not ideal because it runs every time any window grabs focus, and if it detects that it is WildRename, then it adds the maximize-box style, even if it is already set.
Does anybody have any ideas on how to get this to work, that is, how to detect when the target window is created, grab its HWND, and add the style?
what’s happening is that when WildRename runs, it creates a master window, but the window we see is a secondary one that is created afterwards. Worse, the visible window looks to be created with a placeholder title which gets changed after it reads the version number. As such, this thread’s window-creation hook doesn't pick up the correct window.
-> Detect creation of Master Window
-> Wait for Secondary Window
-> Apply WS_MAXIMIZEBOX style to the Secondary window
#SingleInstance, Force DllCall( "RegisterShellHookWindow", UInt,A_ScriptHwnd ) MsgNum := DllCall( "RegisterWindowMessage", Str,"SHELLHOOK" ) OnMessage( MsgNum, "ShellMessage" ) Return ; // end of auto-execute section // ShellMessage( wParam,lParam ) { If ( wParam = 1 ) ; HSHELL_WINDOWCREATED := 1 { If ( lparam = WinExist( "WildRename ahk_class TApplication" ) ) { WinWaitActive, WildRename ahk_class TfrmMain WinSet, Style, +0x10000 ; enable WS_MAXIMIZEBOX } } }Tested!
Interestingly I found that an undocumented ( AFAIK ) value of 0x8006 ( 32774 ) is received by the Shell whenever a Window is Flashing its Titlebar/Taskbar button. The following code activates a window that is flashing: ( not sure whether it will work for everyone ) :Gui +LastFound hWnd := WinExist() , DllCall( "RegisterShellHookWindow", UInt,hWnd ) MsgNum := DllCall( "RegisterWindowMessage", Str,"SHELLHOOK" ) OnMessage( MsgNum, "ShellMessage" ) Return ; // End of Auto-Execute Section // ShellMessage( wParam,lParam ) { If ( wParam = 0x8006 ) ; 0x8006 is 32774 as shown in Spy! { WinActivate, ahk_id %lParam% } }
you are a gotdamn hero of the internets and should be commended for this discovery!
it has been one of my lifelong vendettas to expose the source of this flashing, and destroy it. though I tried all sorts of shell and registry hacks my abilities and google fu had failed me, until I found your tutorial.
not sure what microsoft's fetish is for pissing people off with trivial shell events, but certain apps especially those written in java will trigger this flashing every damn time the window loses focus! now I will smite this flashing, and achieve victory over this evil corporations deliberate attempt to harass me.
you are a gotdamn hero of the internets and should be commended for this discovery!
it has been one of my lifelong vendettas to expose the source of this flashing, and destroy it. though I tried all sorts of shell and registry hacks my abilities and google fu had failed me, until I found your tutorial.
To the hall of fame....
Abandon the forum. The community has decided in a democratic vote to leave this website because of inactive and perverse administration.
Very few of the contributing members remain here.
yea I feel like it should be enshrined in like a permanent sticky or something, this info is just invaluable.
would anyone be interested in defining a simple template for a callback procedure, for those who want to monitor specific messages in this tut one at a time? checked around and see mention of this but I don't know enough to figure out the syntax, which would be calling SetWIndowsHookEx and/or ShellProc as far as I can tell.
basically what I want to do is watch for something like HSHELL_WINDOWCREATED and hand that over to ahk, instead of using winwait to detect new windows (see this bumbling thread on my experience with that). the WindowProc method here works pefectly for me in this case, though not ideal since it keeps interrupting my script to evaluate just the one param I want, every time it receives a window message.