Is it possible to detect window activation/deactivation without relying on the shell hook messages (HSHELL_*)? Btw, I did consider using a timer but it somehow looks inelegant to me since I would be executing code which would most of the time just return the same result (no activation/deactivation detected) thus using resources in vain. I ask this because I'm trying to completely replace the default shell explorer.exe, and the shell hook messages don't work when I kill explorer.exe.
Off topic, I'd like to thank all of the AHK team and the community for the great work you all put into this language. I absolutely love it, especially AHK v2.0. I've been a AHK programmer for some 3-4 years now though not an expert yet. At the time, I didn't have a chance to post here, but now I can finally give the little that I have back to the community that gave (and continues to give) me so much. Thank you again!
Monitoring window (de-)activation without shell messages
Re: Monitoring window (de-)activation without shell messages
Code: Select all
loop {
id := winexist("A")
if (id = ""){ ; seems to be not necessary...
sleep 10
continue
}
wingettitle, t,% "ahk_id " .id
msgbox,% t
winwaitnotactive,% "ahk_id " . id
}
Re: Monitoring window (de-)activation without shell messages
i dont know of any other way, besides shell hook or timer/loop
Re: Monitoring window (de-)activation without shell messages
Proof of concept using child script and custom window message (function can be improved):
Code: Select all
OnWinEvent("OnNotepadActivate", "Untitled - Notepad")
Sleep 1000 ; for demo
Run notepad ; should activate notepad
return
OnNotepadActivate(args*)
{
MsgBox Notepad activated!!
ExitApp
}
OnWinEvent(CbProc, WinTitle, event:=1)
{
static min := 0x800 + 1, max := 0xBFFF
Random nMsg, %min%, %max%
child := Format("
(LTrim Join`n
DetectHiddenWindows On
WinTitle := {1}{2}{1}
nMsg := {3}
hWnd := {4}
event := {5}
if event
gosub WaitActivate
else
gosub WaitDeactivate
return
WaitActivate:
while !WinActive(WinTitle)
continue
SendMessage `%nMsg`%, 1, `% WinExist(WinTitle),, ahk_id `%hWnd`%
ExitApp
WaitDeactivate:
while WinActive(WinTitle)
continue
SendMessage `%nMsg`%, 0, `% WinExist(WinTitle),, ahk_id `%hWnd`%
ExitApp
)", Chr(34), WinTitle, nMsg, A_ScriptHwnd, event)
_OnWinEvent(A_ThisFunc, CbProc, nMsg)
OnMessage(nMsg, "_OnWinEvent")
WshShell := ComObjCreate("WScript.Shell")
exec := WshShell.Exec(A_AhkPath . " *")
exec.StdIn.Write(child), exec.StdIn.Close()
}
_OnWinEvent(wParam, lParam, nMsg, hWnd:=0)
{
static callbacks := {}
if (wParam = "OnWinEvent")
{
callbacks[nMsg] := IsObject(lParam) ? lParam : Func(lParam)
return
}
callback := callbacks[nMsg]
%callback%(wParam, lParam)
}
Re: Monitoring window (de-)activation without shell messages
I get this messageCoco wrote:Proof of concept using child script and custom window message (function can be improved):Code: Select all
OnWinEvent("OnNotepadActivate", "Untitled - Notepad") Sleep 1000 ; for demo Run notepad ; should activate notepad return OnNotepadActivate(args*) { MsgBox Notepad activated!! ExitApp } OnWinEvent(CbProc, WinTitle, event:=1) { static min := 0x800 + 1, max := 0xBFFF Random nMsg, %min%, %max% child := Format(" (LTrim Join`n DetectHiddenWindows On WinTitle := {1}{2}{1} nMsg := {3} hWnd := {4} event := {5} if event gosub WaitActivate else gosub WaitDeactivate return WaitActivate: while !WinActive(WinTitle) continue SendMessage `%nMsg`%, 1, `% WinExist(WinTitle),, ahk_id `%hWnd`% ExitApp WaitDeactivate: while WinActive(WinTitle) continue SendMessage `%nMsg`%, 0, `% WinExist(WinTitle),, ahk_id `%hWnd`% ExitApp )", Chr(34), WinTitle, nMsg, A_ScriptHwnd, event) _OnWinEvent(A_ThisFunc, CbProc, nMsg) OnMessage(nMsg, "_OnWinEvent") WshShell := ComObjCreate("WScript.Shell") exec := WshShell.Exec(A_AhkPath . " *") exec.StdIn.Write(child), exec.StdIn.Close() } _OnWinEvent(wParam, lParam, nMsg, hWnd:=0) { static callbacks := {} if (wParam = "OnWinEvent") { callbacks[nMsg] := IsObject(lParam) ? lParam : Func(lParam) return } callback := callbacks[nMsg] %callback%(wParam, lParam) }
Code: Select all
>"C:\Program Files\AutoHotkey\AutoHotkey.exe" /ErrorStdOut "E:\Empardopo\Autohotkey\Programas-Y-Fuentes\FicherosRetos\Monitoring.ahk"
E:\Empardopo\Autohotkey\Programas-Y-Fuentes\FicherosRetos\Monitoring.ahk (18) : ==> Call to nonexistent function.
Specifically: Format("DetectHiddenWindows On
WinTitle := {1}{2}{1}
nMsg := {3}
hWnd := {4}
event := {5}
if event
gosub WaitActivate
else
gosub WaitDeactivate
return
WaitActivate:
while !WinActive(WinTitle)
continue
SendMessage %nMsg%, 1, % WinExist(WinTitle),, ahk_id %hWnd%
ExitApp
WaitDeactivate:
while WinActive(WinTitle)
continue
SendMessage %nMsg%, 0, % WinExist(WinTitle),, ahk_id %hWnd%
ExitApp", Chr(34), WinTitle, nMsg, A_ScriptHwnd, event)
>Exit code: 2 Time: 0.1624
Everything is possible!
Re: Monitoring window (de-)activation without shell messages
You would need AHK v1.1.17+ for Format
Re: Monitoring window (de-)activation without shell messages
I'm afraid to change the version of Autohotkey. Is It possible to have installed two different versions of Autohotkey?Coco wrote:You would need AHK v1.1.17+ for Format
Thanks!
Everything is possible!
Re: Monitoring window (de-)activation without shell messages
What version are you using right now? You can have multiple version of AHK but only one can be installed. An option is to save new scripts with a different extension, say .ahkx and associate it with the newer AHK exe. Why are you afraid to update? Are you using some legacy scripts?
Re: Monitoring window (de-)activation without shell messages
My version is 1.1.14.03Coco wrote:What version are you using right now? You can have multiple version of AHK but only one can be installed. An option is to save new scripts with a different extension, say .ahkx and associate it with the newer AHK exe. Why are you afraid to update? Are you using some legacy scripts?
Now, I am working with the below version; how can I have that and the last version on my computer?
Legacy scripts? I suppose not but I am not sure!
Thanks
Everything is possible!
Re: Monitoring window (de-)activation without shell messages
You can use v1.1.14.03 in a portable manner by copying the exe and use it for your currently existing scripts. Install the latest version and use it moving forward. Then test your existing scripts with the latest version of AHK, if something isn't working, use v1.1.14.03 for that particular script. For those non-compatible scripts, you can put each in their own directory along with a copy of AHK v1.1.14.03 renamed to YourScript.exe, when you run the said exe, it should automatically run the script in the same directory with the said/same name. Otherwise if a script is working with the latest version of AHK, then your good to go.
Re: Monitoring window (de-)activation without shell messages
Wow!! Fantastic! I didn't know that I could rename the ahk name to myscript.exe! Thanks!Coco wrote:You can use v1.1.14.03 in a portable manner by copying the exe and use it for your currently existing scripts. Install the latest version and use it moving forward. Then test your existing scripts with the latest version of AHK, if something isn't working, use v1.1.14.03 for that particular script. For those non-compatible scripts, you can put each in their own directory along with a copy of AHK v1.1.14.03 renamed to YourScript.exe, when you run the said exe, it should automatically run the script in the same directory with the said/same name. Otherwise if a script is working with the latest version of AHK, then your good to go.
I suppose that too It's possible to compile with old version of ahk,don't you?
I'm going to install the last version to check it, although I have too many scripts to check!
Thanks very much!
Everything is possible!
Re: Monitoring window (de-)activation without shell messages
You can compile old scripts using the appropriate / respective version of AutoHotkeySC.bin, copy it first before you install the new version. You can find it in C:\Program Files\AutoHotkey\Compiler
Re: Monitoring window (de-)activation without shell messages
Thanks! I've done a backup of the full directory of Autohotkey. Better safe!Coco wrote:You can compile old scripts using the appropriate / respective version of AutoHotkeySC.bin, copy it first before you install the new version. You can find it in C:\Program Files\AutoHotkey\Compiler
Coming back to your script.
Open notepad but nothing else happens.
Thanks in advance.
Everything is possible!
Re: Monitoring window (de-)activation without shell messages
No MsgBox? Works every time for me...
Re: Monitoring window (de-)activation without shell messages
No. I just copied your script and I've executed.
Have you seen the photo? It appears text in pink colour and I don't know why?
Have you seen the photo? It appears text in pink colour and I don't know why?
Everything is possible!
Re: Monitoring window (de-)activation without shell messages
its clever but how is it any different from using a loop/timer in a regular script? you are still doing continuous polling with whileCoco wrote:Proof of concept using child script and custom window message
Re: Monitoring window (de-)activation without shell messages
Newly launched threads (timers, hotkeys, GUI events) in the main/master script won't be able to interrupt it since it's in its own thread/process.guest3456 wrote:its clever but how is it any different from using a loop/timer in a regular script? you are still doing continuous polling with while
Re: Monitoring window (de-)activation without shell messages
The pink background at the opening " and at the closing " I assume indicates an invalid string, but don't panic, the string is valid it's just that your editor does not support continuation sections written in this manner:empardopo wrote:Have you seen the photo? It appears text in pink colour and I don't know why?
Code: Select all
str := " ; notice the "
(
Auto
Hot
key
)"
Code: Select all
expr := [
(Join, Q C ; Q option for v2
"Auto"
"Hot"
"key"
)]
Re: Monitoring window (de-)activation without shell messages
Perhaps I didn't make myself clear but I think guest3456 understood me better. I don't care so much about interruption but I am mainly worried about the inefficiency of constant polling especially since I intend to use my "(sort of) shell replacement" 24/7.Coco wrote:Newly launched threads (timers, hotkeys, GUI events) in the main/master script won't be able to interrupt it since it's in its own thread/process.guest3456 wrote:its clever but how is it any different from using a loop/timer in a regular script? you are still doing continuous polling with while
That's the main reason I prefer hooks over constant polling. When using hooks, all the responsibility is on the system. The system will know when to broadcast the messages. It guarantees, at least, some acceptable performance when used 24/7 I guess.
Still, I really liked your script, Coco, and if I can't find another solution I will probably use it but I'm not sure yet.
The ideal for me would be to set shell hooks as we do with normal shell hook messages but without having to rely on explorer.exe.
I read a lot about custom shell-related stuff in MSDN and apparently it's not possible to do what I want without some very deep research.
It appears the system actually uses a shell window to keep track of shell messages. So I would have to set my own shell window and couldn't even find a function to do that, only GetShellWindow() was there. Quite a lot of trouble just to detect window activation/deactivation.
I also read about SetWindowsHookEx and WH_CBT hooks but without success.
Well, if anyone has any deeper knowledge of Windows intricacies (my knowledge is, admittedly, VERY limited), any help here would be very much appreciated.
By the way, I can't register (through registry settings) my own application as a custom shell because the computer I'm using is not mine, so I have to keep explorer.exe available for other people. I used to kill it whenever I entered my own account, but then I started using shell hook messages.
Well, in the worst case, I'll probably just keep explorer.exe active and will kill the taskbar and start button on Windows startup.
For any help, thanks in advance!
Re: Monitoring window (de-)activation without shell messages
You probably didn't understand that this
waits (at winwaitnotactive). winwaitnotactive does not cause much cpu load, at least if I remember correct. 1 extra ahk-thread + (1 command + 1 function call + 1 call-back call) / focus-change isnt exactly bloated/inelegant.
Code: Select all
loop {
id := winexist("A")
if (id = ""){ ; seems to be not necessary...
sleep 10
continue
}
wingettitle, t,% "ahk_id " .id
msgbox,% a_index . " " . t
winwaitnotactive,% "ahk_id " . id
}
Who is online
Users browsing this forum: Noitalommi_2, ulysim and 307 guests