主窗口按进程名称处理 [英] Main window Handle by process name

查看:148
本文介绍了主窗口按进程名称处理的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

Delphi Xe,Win7x64



如何获得主窗口句柄,或至少一个类或窗口名称(如果该进程只有一个窗口)从进程名称(完整路径到exe文件)。



示例:

 code> function MyGetWinHandle(path:String):HWND; 
...
句柄:= MyGetWinHandle('c:\windows\system32\\\
otepad.exe');


解决方案

我同意Petesh你需要列举顶级窗口,并检查创建它的进程的模块文件名。为了帮助您开始枚举顶级窗口,这里是一个delphi实现。



首先,您需要一些与EnumWindows方法通信的方法,当它回调到您。声明一个记录,它将保存要查找的模块的文件名,并找到该进程的句柄:

  TFindWindowRec = record 
ModuleToFind:string;
FoundHWnd:HWND;
结束

然后,您需要声明并实现EnumWindows方法将为每个调用的回调函数顶级窗口:

 函数EnumWindowsCallBack(Handle:hWnd; var FindWindowRec:TFindWindowRec):BOOL;标准

请注意最终的 stdcall; 的声明。这指定了调用约定,这很重要,因为Delphi的默认调用约定与Windows API的调用约定不同。



您的回调函数的实现可能如下所示: p>

 函数EnumWindowsCallBack(Handle:hWnd; var FindWindowRec:TFindWindowRec):BOOL;标准
const
C_FileNameLength = 256;
var
WinFileName:string;
PID,hProcess:DWORD;
Len:Byte;
begin
结果:= True;
SetLength(WinFileName,C_FileNameLength);
GetWindowThreadProcessId(Handle,PID);
hProcess:= OpenProcess(PROCESS_ALL_ACCESS,False,PID);
Len:= GetModuleFileNameEx(hProcess,0,PChar(WinFileName),C_FileNameLength);
如果Len> 0然后
begin
SetLength(WinFileName,Len);
如果SameText(WinFileName,FindWindowRec.ModuleToFind)然后
开始
结果:= False;
FindWindowRec.FoundHWnd:= Handle;
结束
结束
结束

句柄是当前由EnumWindows处理的顶级窗口的句柄。您可以使用它来获取该窗口的模块文件名。回调的结果决定了EnumWindows是否应该继续枚举窗口。当您找到所需的内容时,返回false。



当然,您仍然需要设置整个枚举操作:

  var 
FindWindowRec:TFindWindowRec;

函数IsNotePadOpen:Boolean;
begin
FindWindowRec.ModuleToFind:='c:\windows\system32\\\
otepad.exe';
FindWindowRec.FoundHWnd:= 0;
EnumWindows(@EnumWindowsCallback,integer(@FindWindowRec));
结果:= FindWindowRec.FoundHWnd<> 0;
结束

请注意,上述代码将会找到EnumWindows方法枚举的第一个记事本窗口,可能会有更多,可能没有。主要窗口可以是不可见的,所以你可以添加和(IsWindowInvisble(Handle)),这样你可以决定如何处理这些情况。



如果(Len> 0)在回叫功能。


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:\windows\system32\notepad.exe');

解决方案

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:\windows\system32\notepad.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.

这篇关于主窗口按进程名称处理的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆