1

我有一个窗口,里面有两个文本字段。

如何使用 WinAPI 调用获取两个文本字段的句柄?

注意:两个文本框属于不同的应用程序(我在应用程序 A 中进行 WinAPI 调用,文本框位于应用程序 B 中)。

更新1:

Invalid window handle调用时收到消息GetClassName

我想我的回调函数声明有问题。

EnumChildWindows从以下方法之一调用TMyClass

EnumChildWindows(handle, @TMyClass.CBList, 0);

这是回调函数的代码。

function TMyClass.CBList(Win: THandle; lp: LPARAM): Boolean; stdcall;
var
  ClassName:array [1..1024] of Char;
begin
  GetClassName(Win, PChar(@ClassName), 1024);
  OutputDebugString(PChar('SysErrorMessage(GetLastError): '));

  result := true;
end;
4

1 回答 1

5
  1. 使用 FindWindow 或 EnumWindows 查找目标应用程序的顶级窗口。
  2. 调用 EnumChildWindows 枚举顶级窗口的所有子级。
  3. 在枚举回调中,使用 GetClassName 检查所需的窗口类。例如,对于原始 Win32 编辑窗口,它将是 EDIT。

使用 Spy++ 之类的工具来了解目标应用程序的结构,并找出它使用的精确窗口类名称。


你在评论中关于如何打电话的问题GetClassName让我思考。如果您使用的是 XE3,您可以编写一个简单的类型记录帮助器,HWND以便在语法上更清晰地获取类名:

type
  THWNDHelper = record helper for HWND
  private
    function GetClassName: string;
  public
    property ClassName: string read GetClassName;
  end;

function THWNDHelper.GetClassName: string;
var
  Buffer: array [0..255] of Char;
begin
  if Winapi.Windows.GetClassName(Self, @Buffer, Length(Buffer))=0 then
    RaiseLastOSError;
  Result := Buffer;
end;

然后你可以写hwnd.ClassName来获取窗口类名。当然,如果你不使用 XE3,你可以这样做:

function GetWindowClassName(hwnd: HWND): string;
var
  Buffer: array [0..255] of Char;
begin
  if GetClassName(hwnd, @Buffer, Length(Buffer))=0 then
    RaiseLastOSError;
  Result := Buffer;
end;

请注意,我使用的缓冲区长度为 256,因为窗口类名称长度被限制为不超过该长度。


关于更新中的代码,您不能使用实例方法进行回调。回调必须像这样声明:

function EnumChildWindowsCallback(hwnd: HWND; lParam: LPARAM): BOOL; stdcall;
begin
  OutputDebugString(PChar(GetWindowClassName(hwnd)));
  Result := True;
end;

这在文档中有明确说明。不幸的是EnumChildWindowsin的声明Windows.pas完全放弃了回调函数的类型安全。所以你必须在没有编译器帮助的情况下把它做好。

还要注意HWNDTHandle不是一回事。不要把它们混在一起。

于 2012-10-17T07:26:19.963 回答