请教:查找进程中的句柄与用findwindow查找的结果不一致的原因

tgbd 2011-10-14 12:00:17
最近有个应用需要查找进程中的句柄,搜索了一些有价值的代码,但在使用时发现一个奇怪的现象,不知
各位老大有没有遇到过,或者是我处理不当造成的,还望指点。

测试用例:
1、先新建立一个空白的表单,表单的caption:='TestForm',编译成Test1.exe 测试结果两者相同

2、在表单上放置一个TtreeView控件,编译成Test1.exe 测试结果不一样

测试的主程序主要代码如下:


type
// 存储窗体信息
PProcessWindow = ^TProcessWindow;
TProcessWindow = record
ProcessID: Cardinal;
FoundWindow: hWnd;
end;

// 窗体枚举函数

function EnumWindowsProc(Wnd: HWND; ProcWndInfo: PProcessWindow): BOOL; stdcall;
var
WndProcessID: Cardinal;
begin
GetWindowThreadProcessId(Wnd, @WndProcessID);
if WndProcessID = ProcWndInfo^.ProcessID then begin
ProcWndInfo^.FoundWindow := Wnd;
Result := False;
end
else
Result := True;
end;

// 由 ProcessID 查找窗体 Handle

function GetProcessWindow(ProcessID: Cardinal): HWND;
var
ProcWndInfo: TProcessWindow;
begin
ProcWndInfo.ProcessID := ProcessID;
ProcWndInfo.FoundWindow := 0;
EnumWindows(@EnumWindowsProc, Integer(@ProcWndInfo)); // 查找窗体
Result := ProcWndInfo.FoundWindow;
end;

function GetAppHandle(const AppFileName: string):HWND; //获取进程中的句柄
var
si: STARTUPINFO;
pi: TProcessInformation;
begin
// 启动进程
FillChar(si, SizeOf(si), 0);
si.cb := SizeOf(si);
si.wShowWindow := SW_SHOW;
if not CreateProcess(nil, PChar(AppFileName), nil, nil, true,
CREATE_NEW_CONSOLE or NORMAL_PRIORITY_CLASS, nil, nil, si, pi) then Exit;

// 等待进程启动
WaitForInputIdle(pi.hProcess, 10000);

// 取得进程的 Handle
result := GetProcessWindow(pi.dwProcessID);
// 释放 Handle
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
end;

//当Test1.exe主表单中没有ttreeview控件时,两者值相同
//当Test1.exe主表单中有ttreeview控件时,两者的值不一样,

procedure TFm_main.Button1Click(Sender: TObject);
begin
showmessage(intToStr(GetAppHandle('Test1.exe')));
end;

procedure TFm_main.Button2Click(Sender: TObject);
begin
showmessage(intToStr(FindWindow(nil,'TestForm')));
end;


问题:为什么会因为窗体中多了一个Ttreeview控件,而出现两种方法读取的句柄值不一样?
...全文
374 10 打赏 收藏 转发到动态 举报
写回复
用AI写文章
10 条回复
切换为时间正序
请发表友善的回复…
发表回复
jingtuzhong 2011-10-14
  • 打赏
  • 举报
回复
xuexi
tgbd 2011-10-14
  • 打赏
  • 举报
回复
再次感谢 funxu的指点。

问题解决了,十分感谢!
funxu 2011-10-14
  • 打赏
  • 举报
回复
[Quote=引用 7 楼 tgbd 的回复:]
回6楼
刚才试了一下,有TreeView控件的,取不到标题,而没有Ttreevie……
[/Quote]

枚举窗体时,是会枚举到无标题的窗体的,所以这里要筛选掉,加上一个判断如果标题为TestForm则返回false,如果不是则返回true
tgbd 2011-10-14
  • 打赏
  • 举报
回复
回6楼

----------------------------------------
这里加一句判断,看看取得的标题是否是TestForm然后再返回
GetWindowText(hwnd, buf, SizeOf(buf));
------------------------------------

刚才试了一下,有TreeView控件的,取不到标题,而没有Ttreeview控件的,能取到为TestForm
funxu 2011-10-14
  • 打赏
  • 举报
回复
刚仔细看了下代码
// 窗体枚举函数

function EnumWindowsProc(Wnd: HWND; ProcWndInfo: PProcessWindow): BOOL; stdcall;
var
WndProcessID: Cardinal;
begin
GetWindowThreadProcessId(Wnd, @WndProcessID);
if WndProcessID = ProcWndInfo^.ProcessID then begin
----------------------------------------
这里加一句判断,看看取得的标题是否是TestForm然后再返回
GetWindowText(hwnd, buf, SizeOf(buf));
------------------------------------
ProcWndInfo^.FoundWindow := Wnd;
Result := False;
end
tgbd 2011-10-14
  • 打赏
  • 举报
回复
谢谢楼上两位的参与。

1楼的建议刚才试了一下,问题依旧。
funxu 2011-10-14
  • 打赏
  • 举报
回复
收回2L的意见 更正下错误,刚才没仔细看参数囧

CreateProcess(nil, PChar(AppFileName), nil, nil, true, ..................
funxu 2011-10-14
  • 打赏
  • 举报
回复
换成这个api获取进程id看看
GetCurrentProcessID
funxu 2011-10-14
  • 打赏
  • 举报
回复
LZ看下windows进程管理器,里面启动了几个test1.exe?
createprocess是创建进程吧
ysai 2011-10-14
  • 打赏
  • 举报
回复
测试时关掉DELPHI

或者,你在窗体的oncreate事件中设置
caption := '{一个GUID}';
然后查找GUID

1,184

社区成员

发帖
与我相关
我的任务
社区描述
Delphi Windows SDK/API
社区管理员
  • Windows SDK/API社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧