The window handle or class name or exe name or processid can be returned, or all the info (for more advanced users).
The comments are a tad sparse, but hopefully they plus the example is enough to make you understand the code.
This was just some code I had laying around, I checked it/tweaked it to make sure it works with PureBasic 5.20.
Code: Select all
;The following is hereby placed in the public domain.
;v1.0 by Rescator on PureBasic forum.
EnableExplicit
Structure Find_Program_Struct ;For the programmer/other code to read
hwnd.i
title$
class$
exe$
processid.i
EndStructure
Structure Find_Program_Window_EnumWindowsStructure ;internal use only
result.Find_Program_Struct
processid.i
currentprocessid.i
findtitle$
findclass$
findexe$
matchlimit.i
match.i
*QueryFullProcessImageName
*GetProcessImageFileName
casematch.i
all.i
EndStructure
;internal use only
Procedure.l Find_Program_Window_callback(hwnd.i,*param.Find_Program_Window_EnumWindowsStructure)
Protected result.l=#True,text$,length.i,processid.i=#Null,modulehandle.i,ok.i
*param\match=0
*param\result\processid=0
If *param\findtitle$ Or *param\all
*param\result\title$=""
GetWindowThreadProcessId_(hwnd,@processid)
If processid<>*param\currentprocessid ;We need to check this, getting the window title for a window in our own program in the same thread could cause a deadlock.
ok=#False
text$=Space(#MAX_PATH)
length=GetWindowText_(hwnd,@text$,Len(text$))
If length
*param\result\title$=Left(text$,length)
EndIf
EndIf
If *param\findtitle$
ok=#False
If *param\casematch=#False
text$=LCase(*param\result\title$)
EndIf
If FindString(text$,*param\findtitle$)
*param\match+1
ok=#True
EndIf
EndIf
Else
ok=#True
EndIf
If (*param\findclass$ And ok) Or *param\all
*param\result\class$=""
text$=Space(#MAX_PATH)
length=GetClassName_(hwnd,@text$,Len(text$))
If length
*param\result\class$=Left(text$,length)
EndIf
If (*param\findclass$ And ok)
ok=#False
If *param\casematch=#False
text$=LCase(*param\result\class$)
EndIf
If FindString(text$,*param\findclass$)
*param\match+1
ok=#True
EndIf
EndIf
Else
ok=#True
EndIf
If (*param\findexe$ And ok) Or *param\all
*param\result\exe$=""
If *param\GetProcessImageFileName Or *param\QueryFullProcessImageName
If processid=#Null
GetWindowThreadProcessId_(hwnd,@processid)
EndIf
If processid
modulehandle=OpenProcess_(#PROCESS_QUERY_INFORMATION,#False,processid)
If modulehandle
text$=Space(#MAX_PATH)
If *param\QueryFullProcessImageName ;Windows 6.x
length=Len(text$)
CallFunctionFast(*param\QueryFullProcessImageName,modulehandle,#Null,@text$,@length)
Else ;Windows 5.x/6.0
length=CallFunctionFast(*param\GetProcessImageFileName,modulehandle,@text$,Len(text$))
EndIf
If length
*param\result\exe$=Left(text$,length)
EndIf
CloseHandle_(modulehandle)
EndIf
*param\result\processid=processid
EndIf
If (*param\findexe$ And ok)
ok=#False
If *param\casematch=#False
text$=LCase(*param\result\exe$)
EndIf
If FindString(text$,*param\findexe$)
*param\match+1
ok=#True
EndIf
EndIf
EndIf
EndIf
If *param\match=*param\matchlimit
*param\result\hwnd=hwnd
result=#False
EndIf
ProcedureReturn result
EndProcedure
;Returns pointer to result structure. Returns #Null on no match/failure.
Procedure.i Find_Program(*result.Find_Program_Struct,title$,class$,exe$,casematch.i=#False,all.i=#True)
Protected processid.l,matchlimit.i,dll_psapi.i,dll_kernel32.i,param.Find_Program_Window_EnumWindowsStructure
Protected *pos.Character,*GetLogicalDriveStrings,*QueryDosDevice,text$,devices$,length.l,device$
If title$
param\findtitle$=LCase(title$)
matchlimit+1
EndIf
If class$
param\findclass$=LCase(class$)
matchlimit+1
EndIf
If exe$
param\findexe$=LCase(exe$)
matchlimit+1
EndIf
If matchlimit
param\all=all
param\casematch=casematch
If param\findexe$ Or param\all
dll_kernel32=OpenLibrary(#PB_Any,"kernel32.dll")
If dll_kernel32
;Windows 6.x
CompilerIf #PB_Compiler_Unicode
param\QueryFullProcessImageName=GetFunction(dll_kernel32,"QueryFullProcessImageNameW")
CompilerElse
param\QueryProcessImageFileName=GetFunction(dll_kernel32,"QueryFullProcessImageNameA")
CompilerEndIf
If Not param\QueryFullProcessImageName ;Windows 6.1
CompilerIf #PB_Compiler_Unicode
param\GetProcessImageFileName=GetFunction(dll_kernel32,"K32GetProcessImageFileNameW")
CompilerElse
param\GetProcessImageFileName=GetFunction(dll_kernel32,"K32GetProcessImageFileNameA")
CompilerEndIf
EndIf
EndIf
If (param\GetProcessImageFileName|param\QueryFullProcessImageName)=#Null ;Windows 5.x/Windows 6.0
dll_psapi=OpenLibrary(#PB_Any,"psapi.dll")
If dll_psapi
CompilerIf #PB_Compiler_Unicode
param\GetProcessImageFileName=GetFunction(dll_kernel32,"GetProcessImageFileNameW")
CompilerElse
param\GetProcessImageFileName=GetFunction(dll_kernel32,"GetProcessImageFileNameA")
CompilerEndIf
EndIf
EndIf
EndIf
param\currentprocessid=GetCurrentProcessId_()
param\result\hwnd=#Null
param\matchlimit=matchlimit
EnumWindows_(@Find_Program_Window_callback(),param)
If param\match=matchlimit
*result\hwnd=param\result\hwnd
*result\class$=param\result\class$
*result\processid=param\result\processid
*result\title$=param\result\title$
If param\QueryFullProcessImageName ;Windows 6.x
*result\exe$=param\result\exe$
Else ;Windows 5.x/Windows 6.0
If LCase(Left(param\result\exe$,8))="\device\"
CompilerIf #PB_Compiler_Unicode
*GetLogicalDriveStrings=GetFunction(dll_kernel32,"GetLogicalDriveStringsW")
*QueryDosDevice=GetFunction(dll_kernel32,"QueryDosDeviceW")
CompilerElse
*GetLogicalDriveStrings=GetFunction(dll_kernel32,"GetLogicalDriveStringsA")
*QueryDosDevice=GetFunction(dll_kernel32,"QueryDosDeviceA")
CompilerEndIf
If *GetLogicalDriveStrings And *QueryDosDevice
length=0
length=CallFunctionFast(*GetLogicalDriveStrings,length,@devices$)
devices$=Space(length+1)
length=CallFunctionFast(*GetLogicalDriveStrings,length,@devices$)
If length
*pos=@devices$
Repeat
text$=PeekS(*pos,#MAX_PATH)
If Right(text$,1)="\"
device$=Left(text$,Len(text$)-1)
Else
device$=text$
EndIf
text$=Space(#MAX_PATH+1)
length=CallFunctionFast(*QueryDosDevice,@device$,@text$,length)
length=Len(text$)
If Left(param\result\exe$,length)=text$
*result\exe$=device$+Right(param\result\exe$,Len(param\result\exe$)-length)
Break
EndIf
*pos=*pos+StringByteLength(text$)+SizeOf(Character)
Until *pos\c=#Null
EndIf
EndIf
EndIf
EndIf
Else
*result=#Null
EndIf
If dll_kernel32
CloseLibrary(dll_kernel32)
EndIf
If dll_psapi
CloseLibrary(dll_psapi)
EndIf
Else
*result=#Null
EndIf
ProcedureReturn *result
EndProcedure
;Returns a pointer to window handle. Returns #Null on no match/failure.
Procedure.i Find_Program_Window(title$,class$,exe$,casematch.i=#False)
Protected result.i,results.Find_Program_Struct
If Find_Program(results,title$,class$,exe$,casematch,#False) ;#False means to only return the window handle (instead of all info), this saves some CPU.
result=results\hwnd
EndIf
ProcedureReturn result
EndProcedure
;Returns a string with exe name (may also have a incomplete path so using GetrFilePart() may be wise). Returns empty string on no match/failure.
Procedure.s Find_Program_Exe(title$,class$,exe$,casematch.i=#False)
Protected result$,results.Find_Program_Struct
If Find_Program(results,title$,class$,exe$,casematch,#True)
result$=results\exe$
EndIf
ProcedureReturn result$
EndProcedure
;Returns string with window title. Returns empty string on no match/failure.
Procedure.s Find_Program_Title(title$,class$,exe$,casematch.i=#False)
Protected result$,results.Find_Program_Struct
If Find_Program(results,title$,class$,exe$,casematch,#True)
result$=results\title$
EndIf
ProcedureReturn result$
EndProcedure
;Returns string with window class name. Returns empty string on no match/failure.
Procedure.s Find_Program_Class(title$,class$,exe$,casematch.i=#False)
Protected result$,results.Find_Program_Struct
If Find_Program(results,title$,class$,exe$,casematch,#True)
result$=results\class$
EndIf
ProcedureReturn result$
EndProcedure
;Returns process id (as seen in Task Manager), returns 0 if no match/failure.
Procedure.i Find_Program_ProcessID(title$,class$,exe$,casematch.i=#False)
Protected result.i,results.Find_Program_Struct
If Find_Program(results,title$,class$,exe$,casematch,#True)
result=results\processid
EndIf
ProcedureReturn result
EndProcedure
; ***** Examples *****
Define result.Find_Program_Struct
Debug "Populate results with first match to exact/partial 'foobar' window title"
If Find_Program(result,"foobar2000","","",#False)
Debug "Exe: "+result\exe$
Debug "Title: "+result\title$
Debug "Class: "+result\class$
Debug "Process ID: "+Str(result\processid)
Debug "Window Handle: "+Str(result\hwnd)
Else
Debug "no match"
EndIf
Define hwnd.i
Debug ""
Debug "Return window handle based on exact/partial match to window title and class and exe."
hwnd=Find_Program_Window("foobar","{97E27FAA-C0B3-4b8e-A693-ED7881E99FC1}","foobar2000.exe")
If hwnd
Debug "Window Handle: "+Str(hwnd)
Else
Debug "no match"
EndIf
Keywords: Windows, Win32, PB5.20