Page 1 of 1

WinGetHandle()

Posted: Wed Feb 22, 2023 4:50 pm
by AZJIO
WinGetHandle is a very frequently used function in AutoIt3 and I need it in some programs.
But the function in AutoIt3 also accepts window sizes and regular expressions to search for the title as search criteria. I did not complicate this with additional parameters, since this is rarely used.

Code: Select all

EnableExplicit

Structure ResStr
	s.s
	r.s
	slen.i
	rlen.i
	hwnd.l
	match.l
	type.l
	instance.l
EndStructure

Enumeration
	#Title
	#Class
EndEnumeration

; Finding Window
Procedure.l enumChildren(hwnd.l, *s.ResStr)
	Static n.l = 0
	If hwnd
		Select *s\type
			Case 0
				GetWindowText_(hwnd, @*s\r, *s\rlen)
			Case 1
				GetClassName_(hwnd, @*s\r, *s\rlen)
		EndSelect
		Select *s\match
			Case 0
				If *s\r = *s\s
					n + 1
					If n = *s\instance
						n = 0
						Debug *s\r
						*s\hwnd = hwnd
						ProcedureReturn 0
					EndIf
				EndIf
			Case 1
				If Left(*s\r, *s\slen) = *s\s
					n + 1
					If n = *s\instance
						n = 0
						Debug *s\r
						*s\hwnd = hwnd
						ProcedureReturn 0
					EndIf
				EndIf
			Case 2
				If FindString(*s\r, *s\s, 1, #PB_String_NoCase)
					n + 1
					If n = *s\instance
						n = 0
						Debug *s\r
						*s\hwnd = hwnd
						ProcedureReturn 0
					EndIf
				EndIf
		EndSelect
		ProcedureReturn 1
	EndIf
	n = 0
	ProcedureReturn 0
EndProcedure

; type
; 	0 - Title
; 	1 - Class
; match
; 	0 - exact match
; 	1 - match from start
; 	2 - the word occurs in the title
Procedure.l WinGetHandle(hwnd, text.s, instance = 1, type = 0, match = 0)
	Protected s.ResStr
	s\rlen = 256
	s\r = Space(s\rlen)
	s\s = text
	s\slen = Len(text)
	s\match = match
	s\type = type
	s\instance = instance
	EnumChildWindows_(hwnd, @enumChildren(), @s)
	ProcedureReturn s\hwnd
EndProcedure

Define hwnd
; Debug WinGetHandle(0, "PureBasic", 1, #Title)
; Debug WinGetHandle(0, "LTS", 1, #Title, 2)

; hwnd = WinGetHandle(0, "WindowClass_2", 1, #Class, 0) ; PureBasic
; Debug Hex(hwnd)
; If hwnd
; 	hwnd = WinGetHandle(hwnd, "Scintilla", 1, #Class, 0)  ; PureBasic -> Scintilla
; 	Debug Hex(hwnd)
; EndIf

hwnd = WinGetHandle(0, "Properties", 1, #Title, 1) ; Properties
; hwnd = WinGetHandle(0, "#32770", 1, #Class, 0) ; #32770
Debug Hex(hwnd)
If hwnd
	hwnd = WinGetHandle(hwnd, "Button", 4, #Class, 0)  ; Properties -> Others
	Debug Hex(hwnd)
EndIf
; SendMessage_(hwnd, #BM_CLICK, 0, 0)

; Add a size check
; Define win.RECT
; GetWindowRect_(hwnd, win)
; If class = "#32770" And (win\bottom - win\top) = 111 And (win\right - win\left) = 333
; EndIf

Re: WinGetHandle()

Posted: Wed Feb 22, 2023 7:06 pm
by Caronte3D
Very useful, thanks! :wink:

Re: WinGetHandle()

Posted: Wed Feb 22, 2023 10:19 pm
by ChrisR
Thanks for sharing, it can be useful
The instance is missing in the example:

Code: Select all

Debug WinGetHandle(0, "PureBasic", 1, #Title, 1)
Debug WinGetHandle(0, "LTS", 1, #Title, 2)
Up to you, I would have put the type before the instance

Code: Select all

Procedure.l WinGetHandle(hwnd, text.s, type = #Title, instance = 1, match = 0)

Re: WinGetHandle()

Posted: Tue Jun 03, 2025 12:49 am
by Randy Walker
AZJIO wrote: Wed Feb 22, 2023 4:50 pm WinGetHandle is a very frequently used function in AutoIt3 and I need it in some programs.
But the function in AutoIt3 also accepts window sizes and regular expressions to search for the title as search criteria. I did not complicate this with additional parameters, since this is rarely used.
I don't know about all that window sizes and regular expressions stuff, but just searching for an app based on it's title does not require all that code. I use this in my apps to prevent more than one instance. using "notepad" here just to illustrate, so test with and without a blank Notepad running. Change AppName value to suit your needs:

Code: Select all

Global hWin.i, AppName.s

AppName.s = "Notepad"
Procedure.l EnumWindows(WindowHandle.l, Parameter.l) 
  
 Title$ = Space(200) 
 GetWindowText_(WindowHandle, @Title$, 200) 
 
 If FindString(Title$, AppName, 1, #PB_String_NoCase ) <> 0
   HwndDebug = WindowHandle
   hWin.i = WindowHandle
  ProcedureReturn #False
 Else 
  ProcedureReturn #True
 EndIf 
 
EndProcedure
EnumWindows_(@EnumWindows(), 0)
If hWin.i
  Debug "HERE IS YOUR Window Handle: "+Str(hwin.i)
  SetForegroundWindow_(hWin.i) ; and bring current instance into foreground.
  ShowWindow_(hWin.i, #SW_RESTORE)
  Delay(250)
  End ; Quit from this duplicate instance.
Else 
  Debug "NO, there is NO "+AppName
EndIf 

Re: WinGetHandle()

Posted: Tue Jun 03, 2025 1:07 am
by idle
to get a window by name though it will only get the 1st instance

Code: Select all

Procedure FindWindowByName(name.s) 
  
  Protected hwnd,TitleSize.l,Title.s  
  
  hwnd = GetWindow_(GetDesktopWindow_(), #GW_CHILD)
  While hwnd
	TitleSize.l = GetWindowTextLength_(hwnd) + 2
	Title = Space(TitleSize)
	GetWindowText_(hwnd, Title, TitleSize)
	If FindString(LCase(Title), LCase(name))
		If hwnd <> WindowID(mhwnd) 
		   ProcedureReturn hwnd
		EndIf   
	EndIf
	hwnd = GetWindow_(hwnd, #GW_HWNDNEXT)
Wend

EndProcedure   

Re: WinGetHandle()

Posted: Tue Jun 03, 2025 6:49 am
by AZJIO
Randy Walker wrote: Tue Jun 03, 2025 12:49 am I don't know about all that window sizes and regular expressions stuff, but just searching for an app based on it's title does not require all that code.
Simplified version
EnumWindows
EnumChildWindows