find a hwnd via the windows executable (filename)
or windows title.
Re-tracing my findings:
https://stackoverflow.com/questions/412 ... files-name
post by @Remy Lebeau excellent structural advise
viewtopic.php?p=1510&hilit=getwindowtext#p1510
posting by @chaos regrettably could not get it to work
viewtopic.php?p=8778&hilit=getwindowtext#p8778
posting by @jofers very useful
viewtopic.php?t=6246
posting by @michaelW almost there needed tweak for iteration
https://stackoverflow.com/questions/425 ... 6#42589826
posting by @Gil123 excellent and sly, bingo translate to FB
update 18/06/2022
added rudimentary check on openprocess
and closed the handle
excellent point made by @adeyblue
update 16/07/2022
forgot to reinitialize f and t
Code: Select all
' search a window on title or filename
' based on https://stackoverflow.com/questions/42589496/getting-a-list-of-all-open-windows-in-c-and-storing-them/42589826#42589826
' c++ code from Gil123
' tweaked for fb by Thrive4 2022
#include once "windows.bi"
' needed for process and path related api calls
#include once "win\psapi.bi"
' ghetto work around for GetProcessImageFileName
' returning drive as mount aka \device\hardiskvolume<nr>
' shell "echo list volume | diskpart > vol.tmp"
' parse vol.tmp for drive letters
' tricky be carefull with diskpart
' match window to filename
function matchwindowbyfilename(needle as string) as hwnd
dim h as hwnd
dim o as handle
dim p as dword
dim l as integer
dim t as zstring * 100 ' title
dim c as zstring * 100 ' class
dim f as zstring * 100 ' filename
' init window count
h = GetTopWindow(NULL)
' iterate through windows with GetNextWindow
' IsWindowVisible(h) = false show non visible windows
' defenition https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-iswindowvisible
do
if IsWindowVisible(h) then
f = ""
t = ""
l = GetWindowTextLength(h)
GetWindowText(h, @t, 100)
GetClassName(h, @c, 100)
GetWindowThreadProcessId(h, @p)
o = OpenProcess(PROCESS_QUERY_INFORMATION or PROCESS_QUERY_LIMITED_INFORMATION, FALSE, p)
if o <> null then
GetProcessImageFileName(o, @f, 100)
CloseHandle(o)
else
print "could not open process with WindowThreadProcessId " & p
end if
if f = "" then
print "no process image for " + t
end if
if t = "" then
print "no title for " & h
end if
if needle = "" then
print "title : " + t
print "hwnd : " & h
print "file : " + f
print "class : " + c
print "hwnd : " & h
print "----------"
end if
if instr(lcase(t), lcase(needle)) > 0 then
print "match on file with ";
print "needle : " + needle
print "title : " + t
print "hwnd : " & h
print "file : " + f
print "class : " + c
print "hwnd : " & h
print "----------"
return h
end if
end if
h = GetNextWindow(h, GW_HWNDNEXT)
loop until GetNextWindow(h, GW_HWNDNEXT) = 0
return 0
end function
' match window to window title
function matchwindowbytitle(needle as string) as hwnd
dim h as hwnd
dim o as handle
dim p as dword
dim l as integer
dim t as zstring * 100 ' title
dim c as zstring * 100 ' class
dim f as zstring * 100 ' filename
' init window count
h = GetTopWindow(NULL)
' iterate through windows with GetNextWindow
' IsWindowVisible(h) = false show non visible windows
' defenition https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-iswindowvisible
do
if IsWindowVisible(h) then
f = ""
t = ""
l = GetWindowTextLength(h)
GetWindowText(h, @t, 100)
GetClassName(h, @c, 100)
GetWindowThreadProcessId(h, @p)
if needle = "" then
print "title : " + t
print "hwnd : " & h
print "file : " + f
print "class : " + c
print "hwnd : " & h
print "----------"
end if
if instr(lcase(t), lcase(needle)) > 0 then
print "match on title with ";
print "needle : " + needle
print "title : " + t
print "hwnd : " & h
print "file : " + f
print "class : " + c
print "hwnd : " & h
print "----------"
return h
end if
end if
h = GetNextWindow(h, GW_HWNDNEXT)
loop until GetNextWindow(h, GW_HWNDNEXT) = 0
return 0
end function
matchwindowbyfilename("")
'matchwindowbytitle("")
sleep
end
/' some notes:
QueryFullProcessImageName returns the drive letter
as c:\, d:\ etc
how ever can not get it to work
QueryFullProcessImageName(1, 0, @f, 100)
print _WIN32_WINNT
print cint(&h0600)
' see line 2970 and 2976 in \win\winabse.ini
#if defined(UNICODE) and (_WIN32_WINNT >= &h0600)
print "unicode and higher w32version"
'declare function QueryFullProcessImageName alias "QueryFullProcessImageNameW"(byval hProcess as HANDLE, byval dwFlags as DWORD, byval lpExeName as LPWSTR, byval lpdwSize as PDWORD) as WINBOOL
#elseif (not defined(UNICODE)) and (_WIN32_WINNT >= &h0600)
print "no unicode and higher w32version"
'declare function QueryFullProcessImageName alias "QueryFullProcessImageNameA"(byval hProcess as HANDLE, byval dwFlags as DWORD, byval lpExeName as LPSTR, byval lpdwSize as PDWORD) as WINBOOL
#endif
' gets the path of calling app aka this app aka exepath with exename
'GetWindowModuleFileName(h, @f, 100)
'/
matchwindowbyfilename("")
or, example with search criteria
matchwindowbytitle("winfbe")
For the record matching windows via a title or filename
is in practice quite error prone due to the nature of
the windows title see as example suggestion by coderJeff:
viewtopic.php?t=31586
with the filename things can get funky to, for example
with games, there is a splash screen, then there can be a
dxproxy window, etc.
*) See notes on GetProcessImageFileName vs QueryFullProcessImageName