![]() |
Das Handle eines Fensters herausfinden
Handles auf Objekte in sichtbaren Fenstern kann man mit EnumWindows recht einfach finden. Komplizierter sieht es schon aus, wenn das Programm im Hintergrund läuft und z. B. in die Tray minmimiert ist.
Da ich in den letzten Wochen dies das ein oder andere Mal gebraucht habe und dabei wieder dank der netten Leute hier einiges über die WinAPI & nonVCL-Programmierung gelernt hab, schreib ich diesen Tip. Es ist wohl nicht der sicherste Code, ich habe keine try..finally-Blöcke etc. verwendet wie ich es vielleicht hätte tun sollen, aber es funktioniert und vielleicht liefere ich die nach. Folgendermaßen funnktioniert das Ganze: 1.
Delphi-Quellcode:
Hier wird an die Funktion der Name + Pfad des Programms übergeben, in dem nach dem Handle gesucht werden soll. Das Programm sollte nur einmal laufen. Diese Funktion liefert die IDs aller Threads des gesuchten Prozesses.
type DWordArray = Array of DWord;
function GetThreadID(const FileName: String): DWordArray; var ToolHnd, MToolHnd: HWND; PE32: TProcessEntry32; ME32: TModuleEntry32; TE32: TThreadEntry32; PIDArray, TIDArray: DWordArray; PID: DWord; a: Byte; begin Result := nil; PIDArray := nil; TIDArray := nil; ToolHnd := CreateToolHelp32Snapshot(TH32CS_SNAPPROCESS or TH32CS_SNAPTHREAD, 0); if ToolHnd <> ERROR_INVALID_HANDLE then begin PE32.dwSize := SizeOf(ProcessEntry32); if Process32First(ToolHnd, PE32) then begin repeat if CompareText(ExtractFileName(FileName), PE32.szExeFile) = 0 then begin SetLength(PIDArray, Length(PIDArray) + 1); PIDArray[Length(PIDArray)-1] := PE32.th32ProcessID; end; until not Process32Next(ToolHnd, PE32); end else begin Result := nil; Exit; end; PID := 0; if Length(PIDArray) = 0 then begin Result := nil; Exit; end; for a := 0 to Length(PIDArray) - 1 do begin MToolHnd := CreateToolHelp32Snapshot(TH32CS_SNAPMODULE, PIDArray[a]); if MToolHnd <> ERROR_INVALID_HANDLE then begin ME32.dwSize := SizeOf(ModuleEntry32); if Module32First(MToolHnd, ME32) then begin repeat if CompareText(FileName, ME32.szExePath) = 0 then begin PID := ME32.th32ProcessID; break; end; until not Module32Next(MToolHnd, ME32); end else begin Result := nil; Exit; end; end; CloseHandle(MToolHnd); end; end else begin Result := nil; Exit; end; TE32.dwSize := Sizeof(ThreadEntry32); if Thread32First(ToolHnd, TE32) then begin repeat if TE32.th32OwnerProcessID = PID then begin SetLength(TIDArray, Length(TIDArray) + 1); TIDArray[Length(TIDArray)-1] := TE32.th32ThreadID; end; until not Thread32Next(ToolHnd, TE32); end else begin Result := nil; Exit; end; if Length(TIDArray) = 0 then begin Result := nil; Exit; end; CloseHandle(ToolHnd); if Length(TIDArray) <> 0 then Result := TIDArray; end; 2. Wir enumerieren die Fenster jedes Threads
Delphi-Quellcode:
Die Callback-Funktion:
for a := 0 to Length(TIDArray) - 1 do
begin EnumThreadWindows(TIDArray[a], @EnumWndProc, LabelHnd); end;
Delphi-Quellcode:
Dazu werden folgende globalen Variablen benötigt:
{ Thread-Window-Callback-Funktion }
function EnumWndProc(Hnd: HWND; lParam: LParam): Boolean; stdcall; var Buf: array[0..1024] of Char; ClassName, WindowText: string; begin Result := True; SetString(ClassName, Buf, GetClassName(Hnd, Buf, 1024)); SetLength(WindowText, SendMessage(Hnd, WM_GETTEXTLENGTH, 0, 0)); if ClassName = ClassName_gesucht then if WindowText = WindowText_gesucht then begin Result := False; Hnd_gesucht := Hnd; end; EnumChildWindows(Hnd, @EnumChildProc, lParam); end;
Delphi-Quellcode:
Wenn man z. B. den Button Button1 suchen will, muss man für ClassName TButton und für WindowText die Caption des Buttons einsetzen.
var
Hnd_gesucht: HWND; //unser gesuchtes Handle ClassName_gesucht: String; //Der Klassentyp des gesuchten Objekts WindowText_gesucht: String; //Die Caption des gesuchten Objekts 3. Wenn in der ThreadWindow-Funktion das Fenster nicht gefunden wird, kann es noch ein Kind-Fenster eines Threadfensters sein. Um das herauszufinden, wird in der obigen Callback-Funktion die EnumChildWindows-Funktion aufgerufenn. Die Callback-Funktion dieser Funktion ist wiederum fast identisch mit der anderen Callback-Funktion, da ja nach dem gleichen gesucht wird:
Delphi-Quellcode:
Jetzt haben wir entweder das Handle des Objekts oder das Objekt existert nicht und Hnd_gesucht erfährt keine Wertänderung.
var
Buf: array[0..1024] of Char; ClassName, WindowText: string; begin Result := True; SetString(ClassName, Buf, GetClassName(Hnd, Buf, 1024)); SetLength(WindowText, SendMessage(Hnd, WM_GETTEXTLENGTH, 0, 0)); if ClassName = ClassName_gesucht then if WindowText = WindowText_gesucht then begin Result := False; Hnd_gesucht := Hnd; end; end; [edit=Matze][ code ] durch [ delphi ]-Tags ersetzt. Mfg, Matze[/edit] [edit=Phoenix]Versuch, den Syntax-Highlighter nochmal anzustubbsen. Mfg, Phoenix[/edit] |
Alle Zeitangaben in WEZ +1. Es ist jetzt 00:20 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz