根据进程名获取对应窗口大小,为什么会失败呢?请求帮助!!!
代码片段:
var
hCurrentWindow: THandle;
MyHandle: THandle;
WinRect,WinRect2: TRect;
{使用GetForegroundWindow方法得到当前窗口句柄后可以获取到正确的大小}
hCurrentWindow := GetForegroundWindow();
GetWindowRect(hCurrentWindow, WinRect);
{而通过进程名得到句柄后却不能获取正确的窗口大小,为什么呢?}
MyHandle := GetProcess('Project1.exe'); //GetProcess为自定义获取进程句柄的函数
GetWindowRect(MyHandle, WinRect2);
而且发现这两种方法得到的句柄值也不同,在我本机测试数据如下:
hCurrentWindow=1248932
MyHandle=1708
请问是什么原因呢?这2个句柄有何区别,又该如何解决呢?请高手指点一二,感激不尽!
以下是完整的代码(Unit1.pas):
****************************************************************************************
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, SvcMgr, Dialogs,
ExtCtrls, Registry, ScktComp, PsAPI, Forms, WinInet, Sockets, StdCtrls;
type
TForm1 = class(TForm)
Button1: TButton;
procedure Button1Click(Sender: TObject);
function GetProcess(aProcessName: String):THandle;
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
procedure TForm1.Button1Click(Sender: TObject);
var
hCurrentWindow: THandle;
MyHandle: THandle;
WinRect,WinRect2: TRect;
begin
hCurrentWindow := GetForegroundWindow();
GetWindowRect(hCurrentWindow, WinRect);
showmessage('Handle1=' + inttostr(hCurrentWindow)
+ ',size1=' + inttostr(WinRect.Right - WinRect.Left) + ','
+ inttostr(WinRect.Bottom - WinRect.Top));
MyHandle := GetProcess('Project1.exe');
GetWindowRect(MyHandle, WinRect2);
showmessage('Handle2=' + inttostr(MyHandle)
+ ',size2=' + inttostr(WinRect2.Right - WinRect2.Left) + ','
+ inttostr(WinRect2.Bottom - WinRect2.Top));
end;
//¸ù¾Ý½ø³ÌÃû»ñÈ¡¶ÔÓ¦½ø³ÌµÄhandle
function TForm1.GetProcess(aProcessName: String):THandle;
type
integer = DWORD;
var
i,pidNeeded: Integer;
PIDList: array[0..1000] of Integer;
PIDName: array[0..MAX_PATH - 1] of char;
PH: THandle;
begin
Result := 0;
if not PsAPI.EnumProcesses(@PIDList, 1000, pidNeeded) then
begin
exit;
end;
for i := 0 to (pidNeeded div sizeof(Integer) - 1) do
begin
PH := OpenProcess(PROCESS_QUERY_INFORMATION or PROCESS_VM_READ, False, PIDList[i]);
if PH <> 0 then
begin
if PsAPI.GetModuleBaseName(PH, 0, PIDName, sizeof(PIDName)) > 0 then
if aProcessName = pidName then
begin
Result := PH;
end;
if PH > 0 then closeHandle(PH);
if Result = PH then break;
end;
end;
end;
end.
****************************************************************************************
[解决办法]
晕,进程句柄和窗体句柄简直就是风马牛不相及
[解决办法]
根据我的经验
应该把一个窗体句柄分为两个来看
一个是在本进程映射的句柄
一个是在全局中映射的句柄
两个句柄的值是不一样的
[解决办法]
function EnumWinFun(AHandle: THandle; AID: DWORD):boolean; stdcall;
var
m_Caption: array[0..255] of char;
m_WinRect, m_ClientRect: TRect;
begin
if (GetWindowThreadProcessId(AHandle, nil) = AID) then
begin
GetWindowText(AHadle, m_Caption, 256);
//GetWindowRect(AHandle, m_WinRect); //获取窗体矩形区域
//GetClientRect(AHandle, m_ClientRect);//获取窗体客户区域
MessageBox(0, PChar(m_Caption), 'Find Window!', MB_OK);
end;
Result:= true;
end;
//枚举当前进程中所有的窗体
procedure TForm1.Button1Click(Sender: TObject);
begin
//这里,更改第二个参数(改为你想获取窗体的进程句柄),就可以枚举其他进程的窗体,
EnumWindows(@EnumWinFun, GetCurrentProcessID);
end;
[解决办法]
EnumWindows(@EnumWinFun, GetProcess( "Project1.exe "));
GetProcess函数传递的应是PROCESSID 是ID 不是句柄,晕!
AID====GetCurrentProcessID
if (GetWindowThreadProcessId(AHandle, nil) = AID) then
[解决办法]
agree with lxtnt
Enumberate all window handles, use GetWindowThreadProcessID to get the process id