WinTitle with multiple ahk_id uses only last one

Report problems with documented functionality
Descolada
Posts: 1141
Joined: 23 Dec 2021, 02:30

WinTitle with multiple ahk_id uses only last one

24 Mar 2024, 06:48

Not sure if this is expected behavior or a bug, but a WinTitle with multiple ahk_id's only uses the last one:

Code: Select all

list := WinGetList()
hwnd1 := WinGetList()[1]
hwnd2 := WinGetList()[2]
MsgBox WinExist("ahk_id " hwnd1 " ahk_id " hwnd2)
outputs hwnd2, whereas I would've have expected 0 (a window can't have multiple different handles).

I encountered this when trying to determine whether a window with a specific hWnd matches WinTitle criteria. Eg

Code: Select all

HwndMatchesWin(hWnd, WinTitle:="", WinText:="", ExcludeTitle:="", ExcludeText:="") => WinExist((IsObject(WinTitle) ? "ahk_id " WinTitle.hWnd : (IsInteger(WinTitle) ? "ahk_id " : "") WinTitle) " ahk_id " hWnd, WinText, ExcludeTitle, ExcludeText)
which doesn't work as expected if the user passes a WinTitle containing ahk_id.
iseahound
Posts: 1447
Joined: 13 Aug 2016, 21:04
Contact:

Re: WinTitle with multiple ahk_id uses only last one

24 Mar 2024, 11:53

This sounds like a regular expression parser that uses backtracking to find "ahk_id". In any case it has the nice property of allowing the user to concatenate using the ".=" operator, and to override previous choices with new ones. Since it's not clear what the expected behavior should be, it's not a bug.
User avatar
lmstearn
Posts: 695
Joined: 11 Aug 2016, 02:32
Contact:

Re: WinTitle with multiple ahk_id uses only last one

24 Mar 2024, 23:44

How odd, the second window is chosen if a space is prefixed to the second ahk_id string, otherwise it's the first id (as expected :P ):

Code: Select all

list := WinGetList()
hwnd1 := list[1]
hwnd2 := list[2]
MsgBox "hwnd1 is " hwnd1 ", Ist element of WinGetList, no space : " WinExist("ahk_id " hwnd1 "ahk_id " hwnd2)
MsgBox "hwnd1 is " hwnd1 ", Ist element of WinGetList, space: " WinExist("ahk_id " hwnd1 " ahk_id " hwnd2)
:arrow: itros "ylbbub eht tuO kaerB" a ni kcuts m'I pleH
lexikos
Posts: 9592
Joined: 30 Sep 2013, 04:07
Contact:

Re: WinTitle with multiple ahk_id uses only last one

25 Mar 2024, 07:49

It is by design. WinExist wasn't intended to be used that way.
Checks if the specified window exists
Use ahk_id HWND ... to identify a window or control by its unique ID.
The ahk_id criterion can also be combined with other criteria that the given window must match.
You can't specify multiple windows. It's not explicitly stated that each criterion can only be used once, probably because the authors never considered specifying multiple.

WinTitle is not interpreted directly by WinExist or any other public function, but by an internal shared function (WindowSearch::SetCriteria). The string is parsed exactly once for each call to WinExist, forming a set of criteria stored in a binary structure (WindowSearch). The criteria are then evaluated against each top-level window. There can be many windows to evaluate, and WinTitles can be evaluated very frequently, so the separation of parsing from window evaluation is probably very important for performance.

The behaviour you are expecting would be useful to have. It seems a shortcut can be made specifically for ahk_id: if two different IDs are present, there can never be a match, so there is no need to store multiple IDs or even evaluate any windows.


@lmstearn that is exactly as expected, because "123ahk_id" has no special meaning in the WinTitle parameter.
Specify one or more of the following ahk_ criteria (optionally in addition to a window's title), each separated from the next with exactly one space or tab
User avatar
lmstearn
Posts: 695
Joined: 11 Aug 2016, 02:32
Contact:

Re: WinTitle with multiple ahk_id uses only last one

25 Mar 2024, 12:51

Thanks, that explains it. :)
In the linked function there is CRITERION_ID, first thought it was a stub for some kind of recursive dissection of the ahk_criteria of the criteria id, there's more to it. For instance the comments note it can crop up with WinActive(), ahk_id in ahk_group - and others, fair bit of testing done on it.
The next line is:
// Note that this can validly be the HWND of a child window; i.e. ahk_id %ChildWindowHwnd% is supported.
It's clear from that child windows should fail, tried out a test for parent & child, didn't pick up the child at all- apologies, new to this style:

Code: Select all

MyGui := Gui(, "Title of Window")
MyGui.Opt("-Disabled +SysMenu +Owner")
MyGui.Show("NoActivate")
MyGui.OnEvent("Close", ProcessUserInput)
MyGuiChild := Gui(, "Title of Window")
MyGuiChild.Opt("-Disabled +SysMenu")
MyGuiChild.Add("Button", "default", "OK").OnEvent("Click", ProcessUserInput)
MyGuiChild.Show("NoActivate")  ; NoActivate avoids deactivating the currently active window.
MyGui.Opt("+Parent" MyGuiChild.Hwnd)
MyGuiChild.OnEvent("Close", ProcessUserInput)
ProcessUserInput(*)
{
hwnd1 := MyGui.Hwnd
hwnd2 := MyGuiChild.Hwnd

MsgBox "MyGui.Hwnd " hwnd1 ", MyGuiChild.Hwnd " hwnd2 ", `n`nWinexist(MyGui.Hwnd, MyGuiChild.Hwnd) is " WinExist("ahk_id " hwnd1 " ahk_id " hwnd2) "`nWinexist(MyGuiChild.Hwnd, MyGui.Hwnd) is " WinExist("ahk_id " hwnd2 " ahk_id " hwnd1)
Exitapp
}
:arrow: itros "ylbbub eht tuO kaerB" a ni kcuts m'I pleH
lexikos
Posts: 9592
Joined: 30 Sep 2013, 04:07
Contact:

Re: WinTitle with multiple ahk_id uses only last one

25 Mar 2024, 17:08

@lmstearn I don't know what you're on about. I already explained why specifying ahk_id multiple times will not work.

Return to “Bug Reports”

Who is online

Users browsing this forum: No registered users and 87 guests