Page 1 of 1
Wait for a specific window
Posted: Sat Oct 22, 2022 8:16 am
by BarryG
I need my app to wait until a specific window opens at desktop position 1692,697 (X/Y). I can't identify the window by any other method, so position is the only matching factor, and it may or may not have the focus at the time (so I can't check with GetForegroundWindow_() or use a callback to wait for a new window to be activated). It also doesn't always start at those positions, but moves there after a moment (due to loading media). With all this in mind, what's the best way to know when it appears at that position?
Here's a loop I'm using, but it's brute-force and sometimes slow to react when the window opens, so is there a quicker/better/cleaner way? Thanks.
Code: Select all
; This is runnable code - just replace the left/right values with any window's position that you open after running it.
hWnd=0
Repeat
w=GetWindow_(GetDesktopWindow_(),#GW_CHILD)
Repeat
If IsWindowVisible_(w)
GetWindowRect_(w,win.RECT)
If win\left=1692 And win\top=697
hWnd=w
Break 2
EndIf
EndIf
w=GetWindow_(w,#GW_HWNDNEXT)
Until w=0 Or hWnd
Until hWnd
Re: Wait for a specific window
Posted: Sat Oct 22, 2022 10:57 am
by breeze4me
It works well on Windows 10.
Add the code to exclude windows in your app. Or use #WINEVENT_SKIPOWNPROCESS flag.
BTW, to get the exact location of the window above Windows Vista, it would be better to use the DwmGetWindowAttribute function with #DWMWA_EXTENDED_FRAME_BOUNDS attribute.
Code: Select all
#EVENT_SYSTEM_MOVESIZEEND = $000B
#WINEVENT_OUTOFCONTEXT = 0
#WINEVENT_SKIPOWNPROCESS = 2
Procedure WinEventProc(hWinEventHook, event.l, hwnd, idObject.l, idChild.l, idEventThread.l, dwmsEventTime.l)
If event = #EVENT_SYSTEM_MOVESIZEEND
If GetParent_(hwnd) = 0 And IsWindowVisible_(hwnd)
GetWindowRect_(hwnd, win.RECT)
;If win\left=1692 And win\top=697
If (win\left > 1600 And win\left < 1692) And (win\top > 600 And win\top < 697)
Debug hwnd
EndIf
EndIf
EndIf
EndProcedure
hHook = SetWinEventHook_(#EVENT_SYSTEM_MOVESIZEEND, #EVENT_SYSTEM_MOVESIZEEND, 0, @WinEventProc(), 0, 0, #WINEVENT_OUTOFCONTEXT | #WINEVENT_SKIPOWNPROCESS)
OpenWindow(0, 0, 0, 222, 200, "", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
OpenWindow(1, 1600, 600, 92, 97, "", #PB_Window_BorderLess)
RunProgram("notepad")
Repeat : Until WaitWindowEvent() = #PB_Event_CloseWindow
If hHook
UnhookWinEvent_(hHook)
EndIf
Re: Wait for a specific window
Posted: Sat Oct 22, 2022 11:18 am
by BarryG
It only gets visible windows, and my app is hidden during it, so all good there.
As for the position, I don't need to check with DwmGetWindowAttribute because the top-left corner pixel is the same regardless. Doesn't matter if I can't see it; the position is there anyway, if you follow me? The top-left corner is at 1692,697 even if the border is invisible, so a match is made.
Good to know that the speed is fine for you. On my PC, sometimes it's like another 500ms (half-second) before the loop "notices". Strange.
Your code looks good, and avoids a loop. Does it detect an existing window, though? Sometimes the window exists before I need to detect it, because I'm not actually launching the app that opens it.
Re: Wait for a specific window
Posted: Sat Oct 22, 2022 11:27 am
by breeze4me
BarryG wrote: Sat Oct 22, 2022 11:18 am
Your code looks good, and avoids a loop. Does it detect an existing window, though? Sometimes the window exists before I need to detect it, because I'm not actually launching the app that opens it.
No, you need the brute-force check once.
Re: Wait for a specific window
Posted: Sat Oct 22, 2022 11:33 am
by BarryG
Dang it. Thanks!
Re: Wait for a specific window
Posted: Sat Oct 22, 2022 11:55 am
by breeze4me
breeze4me wrote: Sat Oct 22, 2022 11:27 am
BarryG wrote: Sat Oct 22, 2022 11:18 am
Your code looks good, and avoids a loop. Does it detect an existing window, though? Sometimes the window exists before I need to detect it, because I'm not actually launching the app that opens it.
No, you need the brute-force check once.
Oh, I completely forgot the WindowFromPoint function.
Try it. If it works, no need the brute-force way.
Re: Wait for a specific window
Posted: Sat Oct 22, 2022 12:02 pm
by BarryG
WindowFromPoint? No, the mouse won't be over it. Just literally need to know when the window is at that position on the desktop, no matter which other app I'm using at the time.
Re: Wait for a specific window
Posted: Sat Oct 22, 2022 12:14 pm
by breeze4me
BarryG wrote: Sat Oct 22, 2022 12:02 pm
WindowFromPoint? No, the mouse won't be over it. Just literally need to know when the window is at that position on the desktop, no matter which other app I'm using at the time.
The function is independent of the mouse position.
You can do it as below.
Code: Select all
;First, check if the existing window is at a specific coordinate.
pt.POINT\x = 1692
pt\y = 697
hwnd = WindowFromPoint_(PeekQ(pt))
If hwnd And GetParent_(hwnd) = 0
GetWindowRect_(hwnd, win.RECT)
If win\left=1692 And win\top=697
;Do something...
EndIf
EndIf
hHook = SetWinEventHook_(#EVENT_SYSTEM_MOVESIZEEND, #EVENT_SYSTEM_MOVESIZEEND, 0, @WinEventProc(), 0, 0, #WINEVENT_OUTOFCONTEXT | #WINEVENT_SKIPOWNPROCESS)
......
Of course, if the windows are overlapped at the position, only the brute-force way is available.
So, use a method that suits your situation.
EDIT:
If you also want to detect the location of a window that is moved automatically (i.e., programmatically), you can do the following
Code: Select all
#EVENT_SYSTEM_MOVESIZESTART = $000A
#EVENT_SYSTEM_MOVESIZEEND = $000B
#EVENT_OBJECT_SHOW = $8002
#EVENT_OBJECT_LOCATIONCHANGE = $800B
#WINEVENT_OUTOFCONTEXT = 0
#WINEVENT_SKIPOWNPROCESS = 2
Procedure WinEventProc(hWinEventHook, event.l, hwnd, idObject.l, idChild.l, idEventThread.l, dwmsEventTime.l)
Static MoveByUser
If event = #EVENT_SYSTEM_MOVESIZESTART
MoveByUser = 1
ProcedureReturn
EndIf
If event = #EVENT_SYSTEM_MOVESIZEEND Or (MoveByUser = 0 And (event = #EVENT_OBJECT_LOCATIONCHANGE Or event = #EVENT_OBJECT_SHOW))
MoveByUser = 0
If GetParent_(hwnd) = 0 And IsWindowVisible_(hwnd)
GetWindowRect_(hwnd, win.RECT)
If win\left=1692 And win\top=697
Debug hwnd
EndIf
EndIf
EndIf
EndProcedure
;First, check if the existing window is at a specific coordinate.
pt.POINT\x = 1692
pt\y = 697
hwnd = WindowFromPoint_(PeekQ(pt))
If hwnd And GetParent_(hwnd) = 0
GetWindowRect_(hwnd, win.RECT)
If win\left=1692 And win\top=697
;Do something...
EndIf
EndIf
hHook = SetWinEventHook_(#EVENT_SYSTEM_MOVESIZESTART, #EVENT_OBJECT_LOCATIONCHANGE, 0, @WinEventProc(), 0, 0, #WINEVENT_OUTOFCONTEXT | #WINEVENT_SKIPOWNPROCESS)
......