如何在窗口中查找所有文本字段?

DP_*_*DP_ 1 delphi winapi

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

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

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

更新1:

Invalid window handle在调用时收到消息GetClassName.

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

EnumChildWindows从这样的方法之一调用TMyClass:

EnumChildWindows(handle, @TMyClass.CBList, 0);
Run Code Online (Sandbox Code Playgroud)

这是回调函数的代码.

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;
Run Code Online (Sandbox Code Playgroud)

Dav*_*nan 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;
Run Code Online (Sandbox Code Playgroud)

然后您可以编写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;
Run Code Online (Sandbox Code Playgroud)

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


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

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

这在文档中已明确说明.不幸的声明EnumChildWindowsWindows.pas完全放弃键入回调函数的安全性.所以你必须在没有编译器帮助的情况下做到正确.

还要注意HWND并且THandle不是一回事.不要混淆它们.