如何获取具有相同类名的不同控件的句柄



我正在尝试使用 delphi 编程访问第三方应用程序的"文本框",因此我需要使用 FindWindowEx(...( 函数找到每个"文本框"的句柄。

问题是,由于所有文本框都具有与"NO窗口名称"相同的类名,因此此函数只能给我第一个TextBOx句柄!

如何在文本框没有名称的情况下获取其余句柄?

提前谢谢。

可以使用

EnumChildWindows枚举第三方应用程序窗口的所有子窗口,并测试每个枚举窗口的类名,以查看它是否是"文本框"类。 示例:

function EnumChildren(hwnd: HWND; lParam: LPARAM): BOOL; stdcall;
const
  TextBoxClass = 'EDIT'; (?)
var
  ClassName: array[0..259] of Char;
begin
  Result := True;
  GetClassName(hwnd, ClassName, Length(ClassName));
  if ClassName = TextBoxClass then
    TStrings(lParam).Add(IntToHex(hwnd, 8));
end;
procedure TForm1.Button1Click(Sender: TObject);
begin
  Memo1.Clear;
  EnumChildWindows(OtherAppWnd, @EnumChildren, UINT_PTR(Memo1.Lines));
end;
为了

有效地使用FindWindowEx(),您需要提前了解窗口UI的结构,例如通过Spy++,Winspector或其他类似工具。 这样,您就知道有多少个控件具有相同的类类型,它们的父/子关系如何,等等,以便您可以相应地编写FindWindowEx()代码。 或者,如果目标 UI 使用对话框 ID(VCL 不使用,但Microsoft通常使用(,则可以改用GetDlgItem()直接获取所需控件的句柄,而无需在代码中查找它们(同样,Spy++ 和类似工具可以显示这些 ID 是什么,以便您可以对它们进行编码(。

基于 @Sertac Akyus my Delphi 7 (2002( Windows 10 64 位 Pro 的 32 位代码远程(本地桌面(应用程序:(注意:我不知道为什么,但是SO上的所有代码都不起作用@s!:
|Win32API |德斯卡。||:-------- |----- ||GetClassName(winHandle, @s, Length(s(+1(; |这似乎行不通!||GetClassName(winHandle, PChar(s(, Length(s(+1(; |这行得通!|

unit Unit1;
interface
uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, ComCtrls;
type
  TForm1 = class(TForm)
    Button1: TButton;
    ListBox1: TListBox;
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
    winHandle: HWND;
    winTitle : string;
  end;
var
  Form1: TForm1;
implementation
{$R *.dfm}
var
  s: String;
function EnumChildren(hwnd: HWND; lParam: LPARAM): BOOL; stdcall;
var
  ClassName: array[0..259] of Char;
begin
  Result := True;
  GetClassName(hwnd, ClassName, Length(ClassName));
  Form1.ListBox1.Items.Add(IntToHex(hwnd,8) + ' ' + ClassName);
end;
procedure TForm1.Button1Click(Sender: TObject);
begin
  ListBox1.Items.Clear;
  // ---------------------------------
  // 1. try to find main window hwnd:
  // ---------------------------------
  winHandle := FindWindow('TwinMain', nil);
  if winHandle < 1 then begin
  ListBox1.Items.Add('Error: 1.'); exit; end else
  ListBox1.Items.Add('win: 0x' + IntToHex(winHandle,8));
  // ---------------------------------
  // 2. try to find window title:
  // ---------------------------------
  SetLength(winTitle, GetWindowTextLength(winHandle));
  GetWindowText(winHandle, PChar(winTitle), Length(winTitle)+1);
  if Length(Trim(winTitle)) < 2 then begin
  ListBox1.Items.Add('Error: 2.'); exit; end else
  ListBox1.Items.Add('title: ' + winTitle);
  // ---------------------------------
  // 3. cross check: try to get class:
  // ---------------------------------
  SetLength(s, 100);
  GetClassName(winHandle, PChar(s), Length(s)+1);
  if Length(Trim(s)) < 2 then begin
  ListBox1.Items.Add('Error: 3.'); exit; end else
  ListBox1.Items.Add('class: ' + s);
  EnumChildWindows(winHandle, @EnumChildren, 0);
end;
(* here comes the form1.dfm file: *)
object Form1: TForm1
  Left = 192
  Top = 125
  Width = 389
  Height = 328
  Caption = 'Form1'
  Color = clBtnFace
  Font.Charset = DEFAULT_CHARSET
  Font.Color = clWindowText
  Font.Height = -11
  Font.Name = 'MS Sans Serif'
  Font.Style = []
  OldCreateOrder = False
  PixelsPerInch = 96
  TextHeight = 13
  object Button1: TButton
    Left = 56
    Top = 48
    Width = 75
    Height = 25
    Caption = 'Button1'
    TabOrder = 0
    OnClick = Button1Click
  end
  object ListBox1: TListBox
    Left = 24
    Top = 112
    Width = 305
    Height = 145
    ItemHeight = 13
    TabOrder = 1
  end
end

希望这比许多其他关于SO的文章更有帮助。乔, 延斯

最新更新