How to check focused control changes with OnMessage() rather than gLabel SetTimer? Topic is solved

Get help with using AutoHotkey (v1.1 and older) and its commands and hotkeys
DRocks
Posts: 565
Joined: 08 May 2018, 10:20

How to check focused control changes with OnMessage() rather than gLabel SetTimer?

07 Oct 2018, 09:34

hello guys,

I can't find what Windows Message is relevant to checking for currently focused control in the active window, and if there is such an option.
So for now I am using a SetTimer gLabel repeating every 30ms to do that.

Code: Select all

...
SetTimer, _CheckFocusedControl, 30
return

_CheckFocusedControl:
LastFocusedControl:= FocusedControl
GuiControlGet, FocusedControl, FocusV
...
But how would you use OnMessage() to do this instead of a Timer Loop?

I think its abusive with a SetTimer so fast because of the number of repetitions and the amount of things it checks for at every intervals.
Wouldn't OnMessage() be more appropriate since it probably only reacts when the control focus is changing rather than every 30ms like I'm currently doing?

Please help me sort this out its been a while since I'm looking for that info in vain.

Thanks in advance for your time :)
wolf_II
Posts: 2688
Joined: 08 Feb 2015, 20:55

Re: How to check focused control changes with OnMessage() rather than gLabel SetTimer?  Topic is solved

08 Oct 2018, 03:46

Maybe you could try to set WinEvent hooks instead.

Code: Select all

DllCall("SetWinEventHook","UInt",0x8005,"UInt",0x8005,"Ptr",0,"Ptr",RegisterCallback("THE_HOOK","F"),"UInt",DllCall("GetCurrentProcessId"),"UInt",0,"UInt",0)
CoordMode ToolTip,Client
Gui Add,Edit
Gui Add,Button,,OK
Gui Show
TT_Off:
ToolTip
Esc::
GuiClose:
ExitApp
THE_HOOK(handle,Event,hWnd){
GuiControlGet Pos,Pos,%hWnd%
ToolTip Focus received!,PosX,PosY-20
SetTimer TT_Off,-250
}
DRocks
Posts: 565
Joined: 08 May 2018, 10:20

Re: How to check focused control changes with OnMessage() rather than gLabel SetTimer?

08 Oct 2018, 15:58

Hey wolf

Thanks so much, in your example it does what I want.

To help me understand better, I've read the microsoft "SetWinEventHook" documentation but I am still not sure how to interpret the way it works.
Can you confirm that it does not act like a SetTimer loop that is constantly repeating no matter what?
In other words, this WinEventHook is only reacting and using CPU ressources when prompted on a window event?
DRocks
Posts: 565
Joined: 08 May 2018, 10:20

Re: How to check focused control changes with OnMessage() rather than gLabel SetTimer?

08 Oct 2018, 17:03

I think its exactly want I need! This is how I tested your example and think will be used in the script.

Code: Select all

DllCall("SetWinEventHook","UInt",0x8005,"UInt",0x8005,"Ptr",0,"Ptr",RegisterCallback("THE_HOOK","F"),"UInt",DllCall("GetCurrentProcessId"),"UInt",0,"UInt",0)

Gui Add,Text, ,vEdit1
Gui Add,Edit, vEdit1
Gui Add,Text, ,vEdit2
Gui Add,Edit, vEdit2
Gui Add,Text, ,vEdit3
Gui Add,Edit, vEdit3
Gui Add,Button,,OK
Gui Add,Button,x+1,CANCEL
Gui Show

TT_Off:
ToolTip
Esc::
GuiClose:
ExitApp

THE_HOOK(){
	global 
	PrevFocusedCtrl:=FocusedCtrl
	GuiControlGet, FocusedCtrl, FocusV
	ToolTip, % "PrevFocusedCtrl: " PrevFocusedCtrl "`n`n" "FocusedCtrl: " FocusedCtrl
	SetTimer TT_Off,-3000
}
Thanks alot man, until further testing this will be what I will try to implement.
wolf_II
Posts: 2688
Joined: 08 Feb 2015, 20:55

Re: How to check focused control changes with OnMessage() rather than gLabel SetTimer?

08 Oct 2018, 20:37

DRocks wrote:Can you confirm that it does not act like a SetTimer loop that is constantly repeating no matter what?
In other words, this WinEventHook is only reacting and using CPU ressources when prompted on a window event?
Yes. That is my understanding of a callback function.
User avatar
FanaticGuru
Posts: 1906
Joined: 30 Sep 2013, 22:25

Re: How to check focused control changes with OnMessage() rather than gLabel SetTimer?

08 Oct 2018, 21:46

DRocks wrote:I can't find what Windows Message is relevant to checking for currently focused control in the active window, and if there is such an option.
So for now I am using a SetTimer gLabel repeating every 30ms to do that.

But how would you use OnMessage() to do this instead of a Timer Loop?
Below is an example from another forum post:

Code: Select all

; https://autohotkey.com/board/topic/26054-how-to-detect-loss-of-focus-in-edit-control-solved/

WM_COMMAND=0x111
EN_SETFOCUS=0x100
EN_KILLFOCUS=0x200

SetFormat, Integer, Hex

Gui, Add, Edit, vEdit1 hWndhEdit1, Edit1
Gui, Add, Edit, vEdit2 hWndhEdit2, Edit2

Gui, Add, Text, xm, Window handle:
Gui, Add, Text, x100 yp vWindowHandle w100,
Gui, Add, Text, xm, Edit1 handle: 
Gui, Add, Text, x100 yp vEdit1Handle w100, %hEdit1%
Gui, Add, Text, xm, Edit2 handle: 
Gui, Add, Text, x100 yp vEdit2Handle w100, %hEdit2%
Gui, Add, Text, xm, MsgNum: 
Gui, Add, Text, x100 yp vMsgNumText w100
Gui, Add, Text, xm, Parm1:
Gui, Add, Text, x100 yp vParm1Text w100
Gui, Add, Text, xm+10, Word1:
Gui, Add, Text, x110 yp vWord1Text w100
Gui, Add, Text, xm+10, Word2:
Gui, Add, Text, x110 yp vWord2Text w100
Gui, Add, Text, xm, Parm2:
Gui, Add, Text, x100 yp vParm2Text w100
Gui, Add, Text, xm, Parm3:
Gui, Add, Text, x100 yp vParm3Text w100
Gui, Add, Text, xm, Parm4:
Gui, Add, Text, x100 yp vParm4Text w100

Gui, Add, Text, xm +Hidden vBlank, Edit 1 blank

Gui, Show, w200
hWindow:=WinExist("A")
GuiControl,,WindowHandle, %hWindow%

GuiControl,,MsgNumText, %WM_COMMAND%

OnMessage(WM_COMMAND,"MessageHandler")

Return

MessageHandler(Parm1,Parm2,Parm3,Parm4)
{
  global
  GuiControl,,Parm1Text, %Parm1%                        ; wParam
    Word1:=(Parm1&0xFFFF0000)>>16                       ; NotificationNum - EN_KillFocus=200
    GuiControl,,Word1Text, %Word1%
    GuiControl,,Word2Text, % (Parm1&0x0000FFFF)         ; Control identifier ??
  GuiControl,,Parm2Text, %Parm2%                        ; lParam - Control window_handle
  GuiControl,,Parm3Text, %Parm3%                        ; Message ID
  GuiControl,,Parm4Text, %Parm4%                        ; Window handle
  
  GuiControlGet, Edit1
  ; MsgBox
  If Parm2=%hEdit1%
    If Word1=%EN_KILLFOCUS%
      If Edit1=
        GuiControl, Show, Blank
      Else
        GuiControl, Hide, Blank
}


GuiClose:
GuiEscape:
ExitApp
This is displaying lots of information for testing. This could be trimmed down quite a bit for actual use.

You really just need something like this:

Code: Select all

OnMessage(0x111,"MessageHandler")

MessageHandler(Parm1,Parm2,Parm3,Parm4)
{
	global
	if (Parm2 <> hEdit1)
		ToolTip Edit1 Control Does NOT Have Focus
	else
		ToolTip Edit1 Control DOES Have Focus Even If Its Window Does Not
}
I also ran into the same problem as in this thread with not being able to get WM_KILLFOCUS to work. With Spy++ I can see that message get sent each time a control loses focus but I never could get the AHK code right to detect WM_KILLFOCUS.

FG
Hotkey Help - Help Dialog for Currently Running AHK Scripts
AHK Startup - Consolidate Multiply AHK Scripts with one Tray Icon
Hotstring Manager - Create and Manage Hotstrings
[Class] WinHook - Create Window Shell Hooks and Window Event Hooks
DRocks
Posts: 565
Joined: 08 May 2018, 10:20

Re: How to check focused control changes with OnMessage() rather than gLabel SetTimer?

09 Oct 2018, 06:32

Thank you FG!!

I will also test this method today. Then will update post for feedback :)
just me
Posts: 9432
Joined: 02 Oct 2013, 08:51
Location: Germany

Re: How to check focused control changes with OnMessage() rather than gLabel SetTimer?

09 Oct 2018, 06:49

FanaticGuru wrote:I also ran into the same problem as in this thread with not being able to get WM_KILLFOCUS to work.

Code: Select all

#NoEnv
WM_COMMAND := 0x111
OnMessage(WM_COMMAND, "MessageHandler")
Gui, +AlwaysOnTop
Gui, Add, Edit, w200 vEdit1 hWndhEdit1, Initial value!
Gui, Add, Edit, w200 vEdit2 hWndhEdit2, Initial value!
Gui, Show, , Test
Return

GuiClose:
GuiEscape:
ExitApp

MessageHandler(wParam, HCTL, Msg, HWND) {
   ; EN_SETFOCUS = 0x100, EN_KILLFOCUS = 0x200
   NC := (wParam >> 16) & 0xFFFF ; notification code
   GuiControl, , %HCTL%, % (NC = 0x0100 ? "EN_SETFOCUS" : (NC = 0x0200 ? "EN_KILLFOCUS" : "Other notification!"))
}
... is working fine here.
DRocks
Posts: 565
Joined: 08 May 2018, 10:20

Re: How to check focused control changes with OnMessage() rather than gLabel SetTimer?

09 Oct 2018, 07:35

just me wrote:
FanaticGuru wrote:I also ran into the same problem as in this thread with not being able to get WM_KILLFOCUS to work.

Code: Select all

#NoEnv
WM_COMMAND := 0x111
OnMessage(WM_COMMAND, "MessageHandler")
Gui, +AlwaysOnTop
Gui, Add, Edit, w200 vEdit1 hWndhEdit1, Initial value!
Gui, Add, Edit, w200 vEdit2 hWndhEdit2, Initial value!
Gui, Show, , Test
Return

GuiClose:
GuiEscape:
ExitApp

MessageHandler(wParam, HCTL, Msg, HWND) {
   ; EN_SETFOCUS = 0x100, EN_KILLFOCUS = 0x200
   NC := (wParam >> 16) & 0xFFFF ; notification code
   GuiControl, , %HCTL%, % (NC = 0x0100 ? "EN_SETFOCUS" : (NC = 0x0200 ? "EN_KILLFOCUS" : "Other notification!"))
}
... is working fine here.

dang you guys gave me alot of good solutions!!
Thanks so much for taking time.

I'll be testing the two newer solutions and compare. I won't be able to help out if someone wants to know which one performs better cpu wise but I'll see which one is easier to implement and expand

EDIT: while we are on this topic, can anyone confirm that using Windows Messages \ SetWinEventHook is more appropriate than my previous "SetTimer gLabel" looping every 30ms? What I am looking for is professionalism, CPU efficiency, expandability and management of control focus messages so take some actions relating to this. thanks again :bravo:
DRocks
Posts: 565
Joined: 08 May 2018, 10:20

Re: How to check focused control changes with OnMessage() rather than gLabel SetTimer?

09 Oct 2018, 10:55

Microsoft docs:

Code: Select all

Message Source		   wParam (high word)	                          wParam (low word)	             lParam
Control	               Control-defined notification code	          Control identifier	         Handle to the control window
Is the wParam Low Word (control identifier) any useful?

Would you be able to use any of these without defining hWnd and only using GUI's vControlVariables to validate focus / killfocus?
User avatar
FanaticGuru
Posts: 1906
Joined: 30 Sep 2013, 22:25

Re: How to check focused control changes with OnMessage() rather than gLabel SetTimer?

09 Oct 2018, 11:26

DRocks wrote:Microsoft docs:

Code: Select all

Message Source		   wParam (high word)	                          wParam (low word)	             lParam
Control	               Control-defined notification code	          Control identifier	         Handle to the control window
Is the wParam Low Word (control identifier) any useful?

Would you be able to use any of these without defining hWnd and only using GUI's vControlVariables to validate focus / killfocus?

Code: Select all

 GuiControl,,Parm1Text, %Parm1%                        ; wParam
    Word1:=(Parm1&0xFFFF0000)>>16                       ; NotificationNum - EN_KillFocus=200
    GuiControl,,Word1Text, %Word1%
    GuiControl,,Word2Text, % (Parm1&0x0000FFFF)         ; Control identifier ??
  GuiControl,,Parm2Text, %Parm2%                        ; lParam - Control window_handle
  GuiControl,,Parm3Text, %Parm3%                        ; Message ID
  GuiControl,,Parm4Text, %Parm4%                        ; Window handle
The Control Identifier could be useful. It seems to be an index number like 1, 2, 3, 4, etc which is stable and consistant but I am not sure how the control numbers index is determined. It could be hard to predict. I mean you could find it out in development and hard code that index number into your script but if you changed your Gui the index numbers could change.

You can use GuiControlGet to get control Hwnd from control variable if you don't want to store the Hwnd when the control is created.

To your question of processor efficiency and professionalism, yes onmessage is both more efficient and more professional. The whole system of messages is setup by the operating system to give professionals an efficient way to monitor for events and have processes communicate.

There is a swarm of messages constantly going on but it is all coded at a low level in very fast code and that swarm is going on regardless of whether you tap into it or not. The tapping in to it takes very little additional resources.

FG
Hotkey Help - Help Dialog for Currently Running AHK Scripts
AHK Startup - Consolidate Multiply AHK Scripts with one Tray Icon
Hotstring Manager - Create and Manage Hotstrings
[Class] WinHook - Create Window Shell Hooks and Window Event Hooks
DRocks
Posts: 565
Joined: 08 May 2018, 10:20

Re: How to check focused control changes with OnMessage() rather than gLabel SetTimer?

09 Oct 2018, 11:53

awesome, thank you very much for the latest reply FG. I'll keep studying and testing
DRocks
Posts: 565
Joined: 08 May 2018, 10:20

Re: How to check focused control changes with OnMessage() rather than gLabel SetTimer?

09 Oct 2018, 21:22

Good evening guys,

After testing your great options tonight,
this is a comparative test simplifying both methods side by side. To compare one or the other, all you have to do is comment out either the DllCall or the OnMessage()
I still don't know which one of the two I prefer but for your information, here is the comparison that might be useful to others also. Thanks :)

Code: Select all

#NoEnv  ; Recommended for performance and compatibility with future AutoHotkey releases.
SendMode Input  ; Recommended for new scripts due to its superior speed and reliability.
SetWorkingDir %A_ScriptDir%  ; Ensures a consistent starting directory.
#SingleInstance, Force ; Prevent double execution of this script

; wolf_II
DllCall("SetWinEventHook","UInt",0x8005,"UInt",0x8005,"Ptr",0,"Ptr",RegisterCallback("WinEventHook","Fast"),"UInt",DllCall("GetCurrentProcessId"),"UInt",0,"UInt",0)

;OnMessage(0x111, "WM_COMMAND") 

Gui Add,Edit, vEdit1
Gui Add,Edit, vEdit2
Gui Show

TT_Off:
ToolTip
Esc::
GuiClose:
ExitApp

;--------------------------------------------------------------------------------
WinEventHook() { ; DllCall method
;--------------------------------------------------------------------------------
	global 
	PrevFocusedCtrl:=FocusedCtrl
	GuiControlGet, FocusedCtrl, FocusV
	ToolTip, % "FocusedCtrl: " FocusedCtrl "`n`n" "PrevFocusedCtrl: " PrevFocusedCtrl
	SetTimer TT_Off,-3000
}

;--------------------------------------------------------------------------------
WM_COMMAND(wParam) { ; OnMessage() method
;--------------------------------------------------------------------------------
	global
	NC := (wParam >> 16) & 0xFFFF ; NC= notification code
	if (NC = 0x0100) { ; if the message is "EN_SETFOCUS = 0x100"
		GuiControlGet, FocusedCtrl, FocusV ; The current Focused Control
		ToolTip, % "FocusedCtrl: " FocusedCtrl "`n`n" "PrevFocusedCtrl: " PrevFocusedCtrl
		SetTimer,TT_Off,-2500
	}
	if (NC = 0x0200) { ; if the message is "EN_KILLFOCUS = 0x200"
		PrevFocusedCtrl:=FocusedCtrl ; The previous Focused control just lost focus, so store vName before a new one receives Focus
	}
}
User avatar
FanaticGuru
Posts: 1906
Joined: 30 Sep 2013, 22:25

Re: How to check focused control changes with OnMessage() rather than gLabel SetTimer?

09 Oct 2018, 22:40

DRocks wrote:After testing your great options tonight,
this is a comparative test simplifying both methods side by side. To compare one or the other, all you have to do is comment out either the DllCall or the OnMessage()
I still don't know which one of the two I prefer but for your information, here is the comparison that might be useful to others also. Thanks :)

Code: Select all

#NoEnv  ; Recommended for performance and compatibility with future AutoHotkey releases.
SendMode Input  ; Recommended for new scripts due to its superior speed and reliability.
SetWorkingDir %A_ScriptDir%  ; Ensures a consistent starting directory.
#SingleInstance, Force ; Prevent double execution of this script

; wolf_II
DllCall("SetWinEventHook","UInt",0x8005,"UInt",0x8005,"Ptr",0,"Ptr",RegisterCallback("WinEventHook","Fast"),"UInt",DllCall("GetCurrentProcessId"),"UInt",0,"UInt",0)

;OnMessage(0x111, "WM_COMMAND") 

Gui Add,Edit, vEdit1
Gui Add,Edit, vEdit2
Gui Show

TT_Off:
ToolTip
Esc::
GuiClose:
ExitApp

;--------------------------------------------------------------------------------
WinEventHook() { ; DllCall method
;--------------------------------------------------------------------------------
	global 
	PrevFocusedCtrl:=FocusedCtrl
	GuiControlGet, FocusedCtrl, FocusV
	ToolTip, % "FocusedCtrl: " FocusedCtrl "`n`n" "PrevFocusedCtrl: " PrevFocusedCtrl
	SetTimer TT_Off,-3000
}

;--------------------------------------------------------------------------------
WM_COMMAND(wParam) { ; OnMessage() method
;--------------------------------------------------------------------------------
	global
	NC := (wParam >> 16) & 0xFFFF ; NC= notification code
	if (NC = 0x0100) { ; if the message is "EN_SETFOCUS = 0x100"
		GuiControlGet, FocusedCtrl, FocusV ; The current Focused Control
		ToolTip, % "FocusedCtrl: " FocusedCtrl "`n`n" "PrevFocusedCtrl: " PrevFocusedCtrl
		SetTimer,TT_Off,-2500
	}
	if (NC = 0x0200) { ; if the message is "EN_KILLFOCUS = 0x200"
		PrevFocusedCtrl:=FocusedCtrl ; The previous Focused control just lost focus, so store vName before a new one receives Focus
	}
}
Nice job with the caparison!

It appears with the WM_COMMAND, you are breaking it up into two events that may not be needed. If you do this:

Code: Select all

;--------------------------------------------------------------------------------
WM_COMMAND(wParam) { ; OnMessage() method
;--------------------------------------------------------------------------------
	global
	NC := (wParam >> 16) & 0xFFFF ; NC= notification code
	if (NC = 0x0100) { ; if the message is "EN_SETFOCUS = 0x100"
		PrevFocusedCtrl:=FocusedCtrl ; The previous Focused control just lost focus, so store vName before a new one receives 
		GuiControlGet, FocusedCtrl, FocusV ; The current Focused Control
		ToolTip, % "FocusedCtrl: " FocusedCtrl "`n`n" "PrevFocusedCtrl: " PrevFocusedCtrl
		SetTimer,TT_Off,-2500
	}
}
Then the two methods are doing close to the same thing. Maybe not exactly the same but close.

WinEventHook 0x8005 EVENT_OBJECT_FOCUS is very simliar to WM_COMMAND 0x100 EN_SETFOCUS. Both are triggered when something receives keyboard focus.

The WinEventHook gets alot of messages where you filter for 0x8005. WM_COMMAND also gets alot of messages where you filter for 0x100.

With WM_COMMAND you probably don't need to check for both losing focus and gaining focus. Those are pretty much going to occur back to back in a pair.

Although they both overlap on the gaining focus detection, in general WinEventHook has more events for things that happen to windows where as WM_COMMAND has more events that have to do with edit controls.

FG
Hotkey Help - Help Dialog for Currently Running AHK Scripts
AHK Startup - Consolidate Multiply AHK Scripts with one Tray Icon
Hotstring Manager - Create and Manage Hotstrings
[Class] WinHook - Create Window Shell Hooks and Window Event Hooks
DRocks
Posts: 565
Joined: 08 May 2018, 10:20

Re: How to check focused control changes with OnMessage() rather than gLabel SetTimer?

10 Oct 2018, 15:32

Good afternoon all,

So after alot of trial and error I've been concluding that the easiest way to accurately maintain Gui Control Focus events is with the DllCall method.
The problem with WM_COMMAND is that it reacts to many different Notification Codes which make it impossible (for me) to acheive desired results. By this I mean that the fact that EN_SETFOCUS / EN_KILLFOCUS and other notifications are received we need to filter it out like FG mentionned clearly. But the problem is that it doesnt react the same to ComboBoxes which are part of my GUI. And I've tried all I can to use it but the PrevControl is always messing with the current FocusedControl. It ends up to be equal and can't be compared.

So as for now I will stick with DllCall and if in the meantime I learn proper way to use it I will update and keep others informed of how to do it.

This is the function that is part of a whole. It doesn't work in standalone but you can see how I am using it currently for info :)
Thanks to all of you guys, it is working much better than my previous SetTimer loop @ every 30ms lol :D

Code: Select all

;--------------------------------------------------------------------------------
WinEventHook() { ; DllCall method by wolf_II ;https://autohotkey.com/boards/viewtopic.php?f=76&t=57152#p242656
;--------------------------------------------------------------------------------
	global 
	IniReading:=False
	PrevCtrl:=FocusedCtrl
	GuiControlGet, FocusedCtrl, FocusV
	;ToolTip("PrevCtrl was: " PrevCtrl "`n`nFocusedCtrl: " FocusedCtrl)
	if PrevCtrl contains Cb1_Nom,LB1_Noms 
	{
		if FocusedCtrl not contains Cb1_Nom,LB1_Noms
		{
			CRITICAL
			GuiControlGet, Cb1_Nom
			IniReading:=True
			IniRead, AutoFill, Data\Depenses.ini, %Cb1_Nom%, AutoFill
			;--------------------------------------------------------------------------------
			Loop, Parse, % AutoFill, "|"
			{
				if (A_Index = 1) {
					GuiControl, ChooseString, CODETAXE_1, %A_LoopField%
					if ErrorLevel
						GuiControl, Choose, CODETAXE_1, 0
				}
				if (A_Index = 2)
					GuiControl, ChooseString, CATEGORIE_1, %A_LoopField%
				if (A_Index = 3)
					GuiControl, , DESCRIPTION_1, %A_LoopField%
			}
			;--------------------------------------------------------------------------------
			CRITICAL, off
		}
	}
}
What this does is - when I'm choosing a Name from either ComboBox1 or ListBox1 (both are working together for custom autocomplete) - it will detect if we were in one of those controls, and are now NOT in these anymore. As soon as these conditions are met, it will AutoFill values attributed to the Name in other parts of the GUI.
Why the double condition check? because otherwise it would trigger too often and I only need it to trigger when the name choice is confirmed (by leaving the control)
DRocks
Posts: 565
Joined: 08 May 2018, 10:20

Re: How to check focused control changes with OnMessage() rather than gLabel SetTimer?

23 Jan 2019, 23:09

I am bumping this topic by asking a related question.

How do you effectively filter what message the SetWinEventHook passes to the function?
Or how do you know what message is received when inside the function?

My problem is that focusing a control will.always triger more than one time the function.
I noticed that edit controls trigger the function twice and comboboxes 4 times.
But what I am trying to do only needs one action per each new control focusing happening inside my Gui.

So,
Id need to know how to use ONLY relevant messages which are reporting each new control receiving focus.
Ive read the docs and the microsoft help file but dealing with c++ things is a complete other mindset and im lost.

Can you please point to me how you would do it?

Thanks in advance
User avatar
FanaticGuru
Posts: 1906
Joined: 30 Sep 2013, 22:25

Re: How to check focused control changes with OnMessage() rather than gLabel SetTimer?

24 Jan 2019, 13:59

DRocks wrote:
23 Jan 2019, 23:09
How do you effectively filter what message the SetWinEventHook passes to the function?
Or how do you know what message is received when inside the function?

Can you please point to me how you would do it?
You might want to use this class WinHook at: https://www.autohotkey.com/boards/viewtopic.php?t=59149&p=249149

The basic DllCall hook setup lets you filter the range of event messages. This is the two 0x8005 in the DllCall. Meaning only call the function on events from 0x8005 to 0x8005 which is the number for EVENT_OBJECT_FOCUS.

Then when the function that is called it is passed these parameters:

Code: Select all

Desc: Function Called on Event
;			FuncOrMethod(event, hwnd, idObject, idChild, dwEventThread, dwmsEventTime)
;		
;		Parameters:
;   		1) {event}						Event that occurred. This value is one of the event constants
;   		2) {hwnd}						Handle to the window that generates the event.
;   		3) {idObject}					Identifies the object that is associated with the event.
;   		4) {idChild}					Child ID if the event was triggered by a child element.
;   		5) {dwEventThread}		Identifies the thread that generated the event.
;   		6) {dwmsEventTime}	Specifies the time, in milliseconds, that the event was generated.
Those are the things that Windows sends to the function on an event hook.

Normally I am only dealing with windows. I have never used the idObject and IdChild. Those might contain some information about controls within a window but I don't know. You can probably get more information about those parameters in the MSDN docs.

FG
Hotkey Help - Help Dialog for Currently Running AHK Scripts
AHK Startup - Consolidate Multiply AHK Scripts with one Tray Icon
Hotstring Manager - Create and Manage Hotstrings
[Class] WinHook - Create Window Shell Hooks and Window Event Hooks
DRocks
Posts: 565
Joined: 08 May 2018, 10:20

Re: How to check focused control changes with OnMessage() rather than gLabel SetTimer?

24 Jan 2019, 19:58

DRocks wrote:
23 Jan 2019, 23:09
My problem is that focusing a control will.always triger more than one time the function.
I noticed that edit controls trigger the function twice and comboboxes 4 times.
But what I am trying to do only needs one action per each new control focusing happening inside my Gui.
I found the cause and it was not caused by SetWinEventHook itself! :headwall:
There was a double registration in my script at start-up which did not catch my attention for a long time trying to find out why the eck it was receiving double calls lol..

To make SURE that there is no double registration of SetWinEventHook in a script that Registers and UnRegister the function a few times, I now decided to ask a condition before registering it back. This way is its already registered then dont do it again.
Thus has eliminated the double calls which was driving me close to mad lol.

Return to “Ask for Help (v1)”

Who is online

Users browsing this forum: Billykid, KruschenZ, Rohwedder and 185 guests