Monitoring window (de-)activation without shell messages

Get help with using AutoHotkey (v1.1 and older) and its commands and hotkeys
mozmax
Posts: 10
Joined: 02 Sep 2014, 10:56

Monitoring window (de-)activation without shell messages

09 Feb 2015, 11:39

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!
strobo
Posts: 125
Joined: 30 Sep 2013, 15:24

Re: Monitoring window (de-)activation without shell messages

09 Feb 2015, 15:15

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
}
guest3456
Posts: 3463
Joined: 09 Oct 2013, 10:31

Re: Monitoring window (de-)activation without shell messages

09 Feb 2015, 15:37

i dont know of any other way, besides shell hook or timer/loop

Coco
Posts: 771
Joined: 29 Sep 2013, 20:37
Contact:

Re: Monitoring window (de-)activation without shell messages

09 Feb 2015, 17:05

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)
}
User avatar
empardopo
Posts: 336
Joined: 06 Oct 2013, 12:50
Location: Spain
Contact:

Re: Monitoring window (de-)activation without shell messages

10 Feb 2015, 06:28

Coco 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)
}
I get this message

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!
User avatar
empardopo
Posts: 336
Joined: 06 Oct 2013, 12:50
Location: Spain
Contact:

Re: Monitoring window (de-)activation without shell messages

10 Feb 2015, 06:47

Coco wrote:You would need AHK v1.1.17+ for Format
I'm afraid to change the version of Autohotkey. Is It possible to have installed two different versions of Autohotkey?
Thanks!
Everything is possible!
Coco
Posts: 771
Joined: 29 Sep 2013, 20:37
Contact:

Re: Monitoring window (de-)activation without shell messages

10 Feb 2015, 06:53

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?
User avatar
empardopo
Posts: 336
Joined: 06 Oct 2013, 12:50
Location: Spain
Contact:

Re: Monitoring window (de-)activation without shell messages

10 Feb 2015, 07:02

Coco 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?
My version is 1.1.14.03
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!
Coco
Posts: 771
Joined: 29 Sep 2013, 20:37
Contact:

Re: Monitoring window (de-)activation without shell messages

10 Feb 2015, 07:12

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.
User avatar
empardopo
Posts: 336
Joined: 06 Oct 2013, 12:50
Location: Spain
Contact:

Re: Monitoring window (de-)activation without shell messages

10 Feb 2015, 07:30

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.
Wow!! Fantastic! I didn't know that I could rename the ahk name to myscript.exe! Thanks!
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!
Coco
Posts: 771
Joined: 29 Sep 2013, 20:37
Contact:

Re: Monitoring window (de-)activation without shell messages

10 Feb 2015, 07:46

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
User avatar
empardopo
Posts: 336
Joined: 06 Oct 2013, 12:50
Location: Spain
Contact:

Re: Monitoring window (de-)activation without shell messages

10 Feb 2015, 07:54

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
Thanks! I've done a backup of the full directory of Autohotkey. Better safe! :lolno:

Coming back to your script.
Open notepad but nothing else happens.

Thanks in advance.
Attachments
foto.png
Everything is possible!
Coco
Posts: 771
Joined: 29 Sep 2013, 20:37
Contact:

Re: Monitoring window (de-)activation without shell messages

10 Feb 2015, 08:26

No MsgBox? Works every time for me...
User avatar
empardopo
Posts: 336
Joined: 06 Oct 2013, 12:50
Location: Spain
Contact:

Re: Monitoring window (de-)activation without shell messages

10 Feb 2015, 09:40

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?
Everything is possible!
guest3456
Posts: 3463
Joined: 09 Oct 2013, 10:31

Re: Monitoring window (de-)activation without shell messages

10 Feb 2015, 16:42

Coco wrote:Proof of concept using child script and custom window message
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

Coco
Posts: 771
Joined: 29 Sep 2013, 20:37
Contact:

Re: Monitoring window (de-)activation without shell messages

10 Feb 2015, 19:42

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
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.
Coco
Posts: 771
Joined: 29 Sep 2013, 20:37
Contact:

Re: Monitoring window (de-)activation without shell messages

10 Feb 2015, 20:18

empardopo wrote:Have you seen the photo? It appears text in pink colour and I don't know why?
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:

Code: Select all

str := " ; notice the "
(
Auto
Hot
key
)"
I have customized my language file(for the editor I'm using) to support this and also distinguish string continuation sections(shown above) from expression continuation as shown next:

Code: Select all

expr := [
(Join, Q C ; Q option for v2
    "Auto"
    "Hot"
    "key"
)]
Based on the cold folding markers, I assume your using S4AHK. You can set it to v2 to avoid the invalid string highlighting. Nonetheless, it's just text editor highlighting and shouldn't affect the script.
mozmax
Posts: 10
Joined: 02 Sep 2014, 10:56

Re: Monitoring window (de-)activation without shell messages

10 Feb 2015, 22:11

Coco wrote:
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
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.
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.
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! :)
strobo
Posts: 125
Joined: 30 Sep 2013, 15:24

Re: Monitoring window (de-)activation without shell messages

10 Feb 2015, 22:52

You probably didn't understand that this

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
}
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.

Return to “Ask for Help (v1)”

Who is online

Users browsing this forum: Noitalommi_2, ulysim and 307 guests