delphi - Oprettelse af en funktion til at grave til Windows Handle efter kun Classname (s)

Indlæg af Hanne Mølgaard Plasc

Problem



Så jeg fik lige svar på mit spørgsmål om at få Skype Chatbox håndtaget.


Jeg forsøger nu at skabe en simpel funktion, der graver til et håndtag. Her er hvordan jeg håber at kunne bruge det:


MyHWND := DigForHandle(['Notepad','Edit'],['Untitled - Notepad','']);


Parametre:


1) Striben String: Indeholder klassen Hierachy.


2) Strålingsrække: Holder vinduesskiltet Hierachy.


Som du ser, er 2. indtastning i 2. parameter tom, da klassen Edit ikke har en Window Caption.


Ville det være muligt at oprette en sådan funktion? :)

Bedste reference


Prøv dette


uses
  Windows, Messages, TlHelp32, SysUtils;

type
  PGetWindowParam = ^TGetWindowParam;
  TGetWindowParam = record
    ProcID: DWORD;
    WindowCaption: string;
    Result: HWND;
  end;

function DigForHandle(const ProcName, Caption: string; const Hierachy: array of string): HWND;
function FindPID(const ExeFileName: string): DWORD;

implementation

function FindPID(const ExeFileName: string): DWORD;
var
  ContinueLoop: BOOL;
  ProcessEntry32: TProcessEntry32;
  SnapshotHandle: THandle;
  TempExeFileName: string;
begin
  Result := 0;
  SnapshotHandle := CreateToolhelp32Snapshot(TH32CS\_SNAPPROCESS, 0);
  if SnapshotHandle <> 0 then
  begin
    FillChar(ProcessEntry32, SizeOf(ProcessEntry32), 0);
    ProcessEntry32.dwSize := Sizeof(ProcessEntry32);
    ContinueLoop := Process32First(SnapshotHandle, ProcessEntry32);
    while ContinueLoop do
    begin
      TempExeFileName := ExtractFileName(ProcessEntry32.szExeFile);
      if SameText(TempExeFileName, ExeFileName) then
      begin
        Result := ProcessEntry32.th32ProcessID;
        Break;
      end;

      ContinueLoop := Process32Next(SnapshotHandle, ProcessEntry32);
    end;
    CloseHandle(SnapshotHandle);
  end;
end;

function GetWindow(Wnd: HWND; P: LParam): BOOL; stdcall;
var
  Param: PGetWindowParam;
  ProcID: DWORD;
  WindowTitle: array[0..256] of Char;
begin
  Result := True; // assume it doesn't match; keep searching
  Param := PGetWindowParam(P);

  ProcID := 0;
  GetWindowThreadProcessID(Wnd, @ProcID);
  if ProcID <> Param^.ProcID then
    Exit;

  FillChar(WindowTitle, SizeOf(WindowTitle), 0);
  if SendMessage(Wnd, WM\_GETTEXT, SizeOf(WindowTitle) - SizeOf(Char), LPARAM(@WindowTitle[0])) <= 0 then
    Exit;

  if AnsiSameStr(WindowTitle, Param^.WindowCaption) then
  begin
    Param^.Result := Wnd;
    Result := False;
  end;
end;

function DigForHandle(const ProcName, Caption: string; const Hierachy: array of string): HWND;
var
  Param: TGetWindowParam;
  I: Integer;
  ParentWnd: HWND;
begin
  Result := 0;

  FillChar(Param, SizeOf(Param), 0);
  Param.ProcID := FindPID(ProcName);
  if Param.ProcID = 0 then
    Exit;

  Param.Result := 0;
  Param.WindowCaption := Caption;
  EnumWindows(@GetWindow, LPARAM(@Param));
  if Param.Result = 0 then
    Exit;

  I := 0;
  ParentWnd := Param.Result;
  while (ParentWnd <> 0) and (I < Length(Hierachy)) do
  begin
    Param.Result := 0;
    Param.WindowCaption := Hierachy[I];
    EnumChildWindows(ParentWnd, @GetWindow, LPARAM(@Param));
    if Param.Result = 0 then
      Break;
    ParentWnd := Param.Result;
    Inc(I);
  end;

  if I >= Length(Hierachy) then
    Result := Param.Result;
end;

Andre referencer 1


Da jeg tænkte på det, indså jeg, at det faktisk var ret simpelt - koden jeg havde dog var 'forvirrende' for mig, hvorfor jeg stillede et spørgsmål her. Efter at have prøvet det, fandt jeg ud af at gøre det på denne måde, det er meget lettere at læse og ikke så kompliceret (IMO).


Function DigForHandle(ClassHierachy, TextHierachy : Array of String):HWND;
Var
 Handle : HWND;
 I : Integer;
 PClass,PText : PChar;

Begin

 Result := 0;

 I := 0;
 while (I <= Length(ClassHierachy)-1) do
 begin
   PClass := PChar(ClassHierachy[I]);
   PText  := PChar(TextHierachy[I]);

   if PClass = '' then PClass := Nil;
   if PText = '' then PText := Nil;


   Result := FindWindowEx(Result,0,PClass,PText);

   Inc(I);
 end;



End;