使用 FindWindowEx() 查找编辑框的正确句柄

Finding correct handle for edit box with FindWindowEx()

我正在尝试 post 一些文本到 windows 树上第 3 层的编辑框。 以下代码适用于记事本 (vrr02) 但不适用于另一个程序 (Var03).

procedure TEcr01.Button1Click(Sender: TObject);
var Var01, Var02, Var03, vrr01, vrr02: HWND;
    MyTxt : string;
begin
  Var01 := FindWindow('#32770', nil);
  Var02 := FindWindowEx(Var01, 0, '#32770', nil);
  Var03 := FindWindowEx(Var01, Var02, 'Edit', nil);
  vrr01 := FindWindow('notepad', nil);
  vrr02 := FindWindowEx(vrr01, 0, 'edit', nil);
  MyTxt := 'This is some text.';
  SendMessage(Var03, WM_SETTEXT, 0, integer(MyTxt));
  SendMessage(vrr02, WM_SETTEXT, 0, integer(MyTxt));
end;

下图有蓝色的 编辑 我想 post 但那里什么也没有显示。我在这里做错了什么?

谢谢。

使用您当前的代码,您无法确定是否在任何阶段都获得了您想要的 window 句柄。

“#32770”是标准对话框 class,在用户 session 的任何给定时间可以有多个 window 这个 class。您在 FindWindow 调用中为 lpWindowName 参数传递了 nil,文档指出:

lpWindowName [in, optional]
Type: LPCTSTR


The window name (the window's title). If this parameter is NULL, all window names match.

所以有可能您在 Var01 有一个完全不同的 window 句柄,它具有相同的 class 但不同的 window 标题。

或 none。这就是为什么你必须在每次 API 调用后检查函数是否失败。有关操作方法,请参阅函数的文档。


Var01 := FindWindow('#32770', 'Object Properties');
Win32Check(Var01 <> 0);

上述调用同时指定了 class 名称和 window 标题,这尽可能保证该函数将 return 您想要的 window 句柄。

Var02 := FindWindowEx(Var01, 0, '#32770', nil);
Win32Check(Var02 <> 0);

Var02 的调用看起来没问题。但是 Var03 的 parent 是 Var02,所以第三个调用又错了。

Var03 := FindWindowEx(Var02, 0, 'Edit', nil);
Win32Check(Var03 <> 0);

这将检索第一个编辑,即隐藏的编辑。你必须再次调用 FindWindowEx 来检索你想要的 child,将之前的 window 指定为 ChildAfter 参数。

Var03 := FindWindowEx(Var02, Var03, 'Edit', nil);
Win32Check(Var03 <> 0);

另请注意 SendMessage 的第四个参数不是整数,请始终参考文档。

总而言之:

Var01 := FindWindow('#32770', 'Object Properties');
Win32Check(Var01 <> 0);
Var02 := FindWindowEx(Var01, 0, '#32770', nil);
Win32Check(Var02 <> 0);
Var03 := FindWindowEx(Var02, 0, 'Edit', nil);
Win32Check(Var03 <> 0);
Var03 := FindWindowEx(Var02, Var03, 'Edit', nil);
Win32Check(Var03 <> 0);
MyTxt := 'This is some text.';
SendMessage(Var03, WM_SETTEXT, 0, LPARAM(MyTxt));
SendMessage(vrr02, WM_SETTEXT, 0, LPARAM(MyTxt));