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

时间:2012-10-17 06:59:42

标签: delphi winapi

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

如何使用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;

1 个答案:

答案 0 :(得分:5)

  1. 使用FindWindow或EnumWindows查找目标应用程序的顶级窗口。
  2. 调用EnumChildWindows枚举顶级窗口的所有子项。
  3. 在枚举回调中,使用GetClassName检查所需的窗口类。例如,对于原始的Win32编辑窗口,它将是EDIT。
  4. 使用像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;
    

    documentation清楚地表明了这一点。不幸的是,EnumChildWindowsWindows.pas的声明完全放弃了回调函数的类型安全性。所以你必须在没有编译器帮助的情况下做到正确。

    另请注意,HWNDTHandle不是一回事。不要混淆它们。