4

如何在另一个应用程序的窗口中读取列表框项目?我可以获得窗口的句柄,但我不知道访问内部组件的清晰方法。

4

2 回答 2

8

您可以尝试从以下项目中获取一些东西,其中显示了,如何枚举子窗口,为给定的类名过滤它们以及如何获取列表框的项目。我会评论它,但这将是一个漫长的故事,所以请把它当作一个临时帖子......

单元1.pas

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls;

type
  TEnumData = class
    ClassName: string;
    HandleItems: TStrings;
  end;

type
  TForm1 = class(TForm)
    CloneListBox: TListBox;
    HandleEdit: TEdit;
    HandleListBox: TListBox;
    HandleEnumButton: TButton;
    procedure HandleEnumButtonClick(Sender: TObject);
    procedure HandleListBoxClick(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

function EnumCallback(Handle: HWND; EnumData: TEnumData): BOOL; stdcall;
var
  Buffer: array[0..255] of Char;
begin
  Result := True;
  if GetClassName(Handle, Buffer, 256) <> 0 then
    if Buffer = EnumData.ClassName then
      EnumData.HandleItems.Add(IntToStr(Handle));
end;

procedure GetListBoxItems(Handle: HWND; Target: TListBox);
var
  I: Integer;
  ItemCount: Integer;
  TextBuffer: string;
  TextLength: Integer;
begin
  ItemCount := SendMessage(Handle, LB_GETCOUNT, 0, 0);
  if ItemCount <> LB_ERR then
  begin
    Target.Items.BeginUpdate;
    try
      Target.Clear;
      for I := 0 to ItemCount - 1 do
      begin
        TextLength := SendMessage(Handle, LB_GETTEXTLEN, I, 0);
        SetLength(TextBuffer, TextLength);
        SendMessage(Handle, LB_GETTEXT, I, LPARAM(PChar(TextBuffer)));
        Target.Items.Add(TextBuffer);
      end;
    finally
      Target.Items.EndUpdate;
    end;
  end;
end;

procedure TForm1.HandleEnumButtonClick(Sender: TObject);
var
  EnumData: TEnumData;
begin
  EnumData := TEnumData.Create;
  try
    EnumData.ClassName := 'TListBox';
    EnumData.HandleItems := HandleListBox.Items;
    EnumChildWindows(StrToInt(HandleEdit.Text), @EnumCallback, LPARAM(EnumData));
  finally
    EnumData.Free;
  end;
end;

procedure TForm1.HandleListBoxClick(Sender: TObject);
var
  SourceHandle: Integer;
begin
  if TryStrToInt(HandleListBox.Items[HandleListBox.ItemIndex], SourceHandle) then
    GetListBoxItems(SourceHandle, CloneListBox);
end;

end.

单元1.dfm

object Form1: TForm1
  Left = 0
  Top = 0
  Caption = 'Form1'
  ClientHeight = 259
  ClientWidth = 460
  Color = clBtnFace
  Font.Charset = DEFAULT_CHARSET
  Font.Color = clWindowText
  Font.Height = -11
  Font.Name = 'Tahoma'
  Font.Style = []
  OldCreateOrder = False
  PixelsPerInch = 96
  TextHeight = 13
  object CloneListBox: TListBox
    Left = 224
    Top = 8
    Width = 228
    Height = 243
    ItemHeight = 13
    TabOrder = 0
  end
  object HandleEnumButton: TButton
    Left = 127
    Top = 8
    Width = 88
    Height = 25
    Caption = 'Enumerate'
    TabOrder = 1
    OnClick = HandleEnumButtonClick
  end
  object HandleListBox: TListBox
    Left = 8
    Top = 40
    Width = 207
    Height = 211
    ItemHeight = 13
    TabOrder = 2
    OnClick = HandleListBoxClick
  end
  object HandleEdit: TEdit
    Left = 8
    Top = 8
    Width = 113
    Height = 21
    TabOrder = 3
    Text = '0'
  end
end

项目1.dpr

program Project1;

uses
  Forms,
  Unit1 in 'Unit1.pas' {Form1};

{$R *.res}

begin
  Application.Initialize;
  Application.MainFormOnTaskbar := True;
  Application.CreateForm(TForm1, Form1);
  Application.Run;
end.
于 2012-08-22T10:53:42.703 回答
5

使用 EnumChildWindows 获取子控件列表(当主窗口句柄已知时)。

然后查看MSDN上的 LB_GETTEXT Message (或 Delphi WinSDK Help)。不要忘记检查字符串长度(LB_GETTEXTLEN)并分配内存缓冲区

于 2012-08-22T10:43:28.643 回答