How to retrieve the hwnd of the window to which a control belongs? Topic is solved

Get help with using AutoHotkey (v1.1 and older) and its commands and hotkeys
A_AhkUser
Posts: 1147
Joined: 06 Mar 2017, 16:18
Location: France
Contact:

How to retrieve the hwnd of the window to which a control belongs?

21 May 2018, 11:38

Given a control, is it possible to retrieve the hwnd of the window to which it belongs? I did search on the forum - but to no avail.
Thanks for your knowledge and your time.
my scripts
User avatar
jeeswg
Posts: 6902
Joined: 19 Dec 2016, 01:58
Location: UK

Re: How to retrieve the hwnd of the window to which a control belongs?  Topic is solved

21 May 2018, 11:54

Perhaps this. Cheers.

Code: Select all

q:: ;window get parent (e.g. test on Notepad)
ControlGet, hCtl, Hwnd,, Edit1, A
hWnd := DllCall("user32\GetAncestor", Ptr,hCtl, UInt,1, Ptr) ;GA_PARENT := 1
WinGetClass, vWinClass, % "ahk_id " hWnd
MsgBox, % vWinClass
return

;for the owner:
hWnd := DllCall("user32\GetWindow", Ptr,hCtl, UInt,4, Ptr) ;GW_OWNER = 4
homepage | tutorials | wish list | fun threads | donate
WARNING: copy your posts/messages before hitting Submit as you may lose them due to CAPTCHA
A_AhkUser
Posts: 1147
Joined: 06 Mar 2017, 16:18
Location: France
Contact:

Re: How to retrieve the hwnd of the window to which a control belongs?

21 May 2018, 13:30

jeeswg strikes again!! :D The getAncestor function is exactly what I was looking for (a while now: finally, I have decided to ask how to). So, it seems that 'parent' is the adequate way to word it; cheers for also implicitly pointing out the nuance between parent and owner. In that respect, does, in the following example, class21 always supposed to contain the class of classNN?

Code: Select all

q::
cue := "some message"
Gui Add, ComboBox, +Sort hwndchild, a|b|c|d ; child 'window'?
grandChild := DllCall("GetWindow", "Ptr", child, "Uint", 5) ; GW_CHILD
SendMessage, 0x1501, true, &cue,, % "ahk_id  " . grandChild ; EM_SETCUEBANNER - grand child 'window'?
; ---------------------- ComboBox ----------------------
parent1 := DllCall("user32\GetAncestor", "Ptr", grandChild, "UInt", 1, "Ptr") ; GA_PARENT := 1
WinGetClass, class1, % "ahk_id " parent1
MsgBox, % class1 ; displays ComboBox
Gui Show, AutoSize, Window ; parent?
; ---------------------- AutohotkeyGUI ----------------------
parent2 := DllCall("user32\GetAncestor", "Ptr", child, "UInt", 1, "Ptr") ; GA_PARENT := 1
WinGetClass, class2, % "ahk_id " parent2
MsgBox, % class2
return
In any event thanks much ;)
my scripts
User avatar
jeeswg
Posts: 6902
Joined: 19 Dec 2016, 01:58
Location: UK

Re: How to retrieve the hwnd of the window to which a control belongs?

21 May 2018, 14:45

- I'm not sure what exactly you're asking. [EDIT:] 'child' is of the form 'ComboBoxNN', 'grandchild' is its child, 'child' is the parent of 'grandchild', so I would expect class1 to be 'ComboBox'.
- One thing I would point out is that GA_ROOT is pretty useful. If you apply WinGet-ControlList to an hWnd and get the root for each control, the root should be the hWnd.

Code: Select all

q:: ;controls get parent/root/owner windows (e.g. test on Notepad/Internet Explorer)
WinGet, hWnd, ID, A
WinGet, vCtlList, ControlList, % "ahk_id " hWnd
vOutput := ""
Loop, Parse, vCtlList, `n
{
	vCtlClassNN := A_LoopField
	ControlGet, hCtl, Hwnd,, % vCtlClassNN, % "ahk_id " hWnd
	hWndParent := DllCall("user32\GetAncestor", Ptr,hCtl, UInt,1, Ptr) ;GA_PARENT := 1
	hWndRoot := DllCall("user32\GetAncestor", Ptr,hCtl, UInt,2, Ptr) ;GA_ROOT := 2
	hWndOwner := DllCall("user32\GetWindow", Ptr,hCtl, UInt,4, Ptr) ;GW_OWNER = 4
	WinGetClass, vWinClass1, % "ahk_id " hWndParent
	WinGetClass, vWinClass2, % "ahk_id " hWndRoot
	WinGetClass, vWinClass3, % "ahk_id " hWndOwner
	vOutput .= vCtlClassNN "|" vWinClass1 "|" vWinClass2 "|" vWinClass3 "`r`n"
}
Clipboard := vOutput
MsgBox, % vOutput
return
- A control 'ClassNN' cf. a class. Might be worth pointing out. When AutoHotkey refers to a control by a 'ClassNN', it enumerates the controls in a window, gets the class for each, and assigns an 'NN' for each.

Code: Select all

w:: ;ClassNN to class (e.g. test on Notepad: 'Edit1' to 'Edit')
vCtlClassNN := "Edit1"
ControlGet, hCtl, Hwnd,, % vCtlClassNN, A
WinGetClass, vCtlClass, % "ahk_id " hCtl
MsgBox, % vCtlClass
return
- Add this to the bottom of your script, as a way to list controls within controls:

Code: Select all

e:: ;control, list controls within it
ControlGet, hCtl, Hwnd,, ComboBox1, A
WinGet, vCtlList, ControlList, % "ahk_id " hCtl
vOutput := ""
Loop, Parse, vCtlList, `n
{
	vCtlClassNN := A_LoopField
	;ControlGet, hCtl, Hwnd,, % vCtlClassNN, % "ahk_id " hWnd
	vOutput .= vCtlClassNN "`r`n"
}
Clipboard := vOutput
MsgBox, % vOutput
return
- Here's an example of finding the children of a window, and then the children of one of the children. (Note: the same controls may have different ClassNNs in each loop, since the NNs are relative to the main window/control.)
How to account for changing ClassNN info - AutoHotkey Community
https://autohotkey.com/boards/viewtopic ... 71#p183171
homepage | tutorials | wish list | fun threads | donate
WARNING: copy your posts/messages before hitting Submit as you may lose them due to CAPTCHA
A_AhkUser
Posts: 1147
Joined: 06 Mar 2017, 16:18
Location: France
Contact:

Re: How to retrieve the hwnd of the window to which a control belongs?

21 May 2018, 15:33

Yea sorry: the way I worded it was kinda confusing. :crazy: But your examples illustrate with mastery what I had in mind: you call WinGetClass to retrieve a control's class. It is not so much the 'combobox' string that was unexpected for me but the fact you use the WinGetClass command - although after all that makes sense because 'controls' are in fact 'windows' (but I always forget it).
my scripts
User avatar
jeeswg
Posts: 6902
Joined: 19 Dec 2016, 01:58
Location: UK

Re: How to retrieve the hwnd of the window to which a control belongs?

21 May 2018, 16:59

- Windows and controls both have hWnds: WinGet-ID and ControlGet-Hwnd.
- WinGetPos, for example, is good for use on controls also. All these subtle points and hacks!
homepage | tutorials | wish list | fun threads | donate
WARNING: copy your posts/messages before hitting Submit as you may lose them due to CAPTCHA
User avatar
jeeswg
Posts: 6902
Joined: 19 Dec 2016, 01:58
Location: UK

Re: How to retrieve the hwnd of the window to which a control belongs?

07 Jun 2018, 23:59

Here's a simple example for a ComboBox, to get the handle to the Edit control.

Code: Select all

q:: ;ComboBox get handle to Edit control
DetectHiddenWindows, On
Gui, New, +HwndhGui, MyWinTitle
Gui, Add, ComboBox, R8 +HwndhCbx, abc||def|ghi|jkl
Gui, Show

ControlGet, hEdit, Hwnd,, Edit1, % "ahk_id " hCbx
ControlGetText, vText,, % "ahk_id " hEdit
MsgBox, % vText

;confirm that parent of Edit control is ComboBox:
;hParent := DllCall("user32\GetAncestor", "Ptr",hEdit, "UInt",1, "Ptr") ;GA_PARENT := 1
;MsgBox, % (hCbx+0) "`r`n" hParent
return

;==================================================

w:: ;Notepad ComboBox get handle to Edit control
ControlGet, hCbx, Hwnd,, ComboBox1, A
ControlGet, hEdit, Hwnd,, Edit1, % "ahk_id " hCbx
ControlGetText, vText,, % "ahk_id " hEdit
MsgBox, % vText
return
homepage | tutorials | wish list | fun threads | donate
WARNING: copy your posts/messages before hitting Submit as you may lose them due to CAPTCHA
User avatar
jeeswg
Posts: 6902
Joined: 19 Dec 2016, 01:58
Location: UK

Re: How to retrieve the hwnd of the window to which a control belongs?

29 Oct 2019, 10:12

Does anyone have any definition info for GA_ROOT?
GA_ROOT vs GA_ROOTOWNER - Google Groups
https://groups.google.com/a/chromium.org/forum/?nomobile=true#!topic/chromium-dev/Hirr_DkuZdw
GetParent versus GetDesktop and GetAncestor(parent) - AutoIt General Help and Support - AutoIt Forums
https://www.autoitscript.com/forum/topic/189979-getparent-versus-getdesktop-and-getancestorparent/

Can GA_ROOT be relied upon, or do we need GetNonChildParent?

The source code has a function called GetNonChildParent, which I've tried to recreate:

Code: Select all

q:: ;test GetNonChildParent and GA_ROOT on Internet Explorer
ControlGet, hCtl, Hwnd,, Internet Explorer_Server1, A
hWnd1 := GetNonChildParent(hCtl)
hWnd2 := DllCall("user32\GetAncestor", "Ptr",hCtl, "UInt",2, "Ptr") ;GA_ROOT := 2
WinGetClass, vWinClass1, % "ahk_id " hWnd1
WinGetClass, vWinClass2, % "ahk_id " hWnd2
MsgBox, % vWinClass1 "`r`n" vWinClass2
return

;==================================================

;based on the AHK source code's GetNonChildParent (window.cpp)
GetNonChildParent(hWnd)
{
	local
	if !hWnd
		return 0
	hParent := 0
	hParentPrev := hWnd
	Loop
	{
		;GWL_STYLE := -16 ;WS_CHILD := 0x40000000
		if !(DllCall("user32\GetWindowLong" (A_PtrSize=8?"Ptr":""), "Ptr",hParentPrev, "Int",-16, "Ptr") & 0x40000000)
			return hParentPrev ;found the first non-child parent
		if !(hParent := DllCall("user32\GetParent", "Ptr",hParentPrev, "Ptr"))
			return hParentPrev ;has no parent
		hParentPrev := hParent
	}
}
Related thread to this one:
Identifying the class EditNN for a comboBox control - AutoHotkey Community
https://autohotkey.com/boards/viewtopic.php?f=5&t=69158
homepage | tutorials | wish list | fun threads | donate
WARNING: copy your posts/messages before hitting Submit as you may lose them due to CAPTCHA

Return to “Ask for Help (v1)”

Who is online

Users browsing this forum: No registered users and 96 guests