Question

How can i read a listbox items in another application's window? I could get the window's handle but i dont know a clear way to access components within.

Was it helpful?

Solution

You can try to get something from the following project, where is shown, how to enumerate child windows, filter them for a given class name and how to get the items of a list box. I would comment it, but this would be a long story, so please take it as a temporary post...

Unit1.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.

Unit1.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

Project1.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.

OTHER TIPS

Get list of child controls with EnumChildWindows (when main window handle is already known).

Then look at the LB_GETTEXT Message on MSDN (or Delphi WinSDK Help). Don't forget to check for string length (LB_GETTEXTLEN) and allocate memory buffer

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top