Welcome toVigges Developer Community-Open, Learning,Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
1.1k views
in Technique[技术] by (71.8m points)

delphi - Main window Handle by process name

Delphi Xe, Win7x64

How do I get the Main Window Handle, or at least a class, or a window name (if that process has only one window) from the process name (a full path to exe-file).

Example:

 function MyGetWinHandle(path:String):HWND;
 ...
 handle := MyGetWinHandle('c:windowssystem32
otepad.exe');
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

I agree with Petesh that you would need to enumerate the top level windows and check the module file name of the process that created it. To help you get started on enumerating top level windows here is a delphi implementation of doing it.

First you need some way of communicating with the EnumWindows method when it calls back to you. Declare a record for that, which will hold the file name of the module you want to find and a handle to the process when it is found:

TFindWindowRec = record
  ModuleToFind: string;
  FoundHWnd: HWND;
end;

Then you need to declare and implement the call back function that the EnumWindows method is going to call for each top level window:

function EnumWindowsCallBack(Handle: hWnd; var FindWindowRec: TFindWindowRec): BOOL; stdcall;

Please note the stdcall; at the end of the declaration. This specifies the calling convention which is important because Delphi's default calling convention is different from the Windows API's calling convention.

The implementation of your call back function could look like:

function EnumWindowsCallBack(Handle: hWnd; var FindWindowRec: TFindWindowRec): BOOL; stdcall;
const
  C_FileNameLength = 256;
var
  WinFileName: string;
  PID, hProcess: DWORD;
  Len: Byte;
begin
  Result := True;
  SetLength(WinFileName, C_FileNameLength);
  GetWindowThreadProcessId(Handle, PID);
  hProcess := OpenProcess(PROCESS_ALL_ACCESS, False, PID);
  Len := GetModuleFileNameEx(hProcess, 0, PChar(WinFileName), C_FileNameLength);
  if Len > 0 then
  begin
    SetLength(WinFileName, Len);
    if SameText(WinFileName, FindWindowRec.ModuleToFind) then
    begin
      Result := False;
      FindWindowRec.FoundHWnd := Handle;
    end;
  end;
end;

Handle is the handle of the top level window currently being processed by EnumWindows. You use it to get the module's file name of that window. The result of the call back determines whether EnumWindows should continue enumerating windows or not. Return false when you have found what you are looking for.

Of course you still need to set the whole enumeration operation in motion:

var
  FindWindowRec: TFindWindowRec;

function IsNotePadOpen: Boolean;
begin
  FindWindowRec.ModuleToFind := 'c:windowssystem32
otepad.exe';
  FindWindowRec.FoundHWnd := 0;
  EnumWindows(@EnumWindowsCallback, integer(@FindWindowRec));
  Result := FindWindowRec.FoundHWnd <> 0;
end;

Please note that the above code will find the first notepad window enumerated by the EnumWindows method, there may be more, there may be none. It's up to you to decide how to handle those situations.

The Main window can be invisible so you could add and (IsWindowInvisble(Handle)) after If (Len > 0) in the call back function.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to Vigges Developer Community for programmer and developer-Open, Learning and Share
...