Solved

Retrieving strings from a ListBox in another app

Posted on 2002-05-12
4
591 Views
Last Modified: 2008-03-10
Hi

I am trying to get the handle of a ListBox in another application and then read the strings into my own ListBox.  The following code does not work:

function EnumProc ( H:THandle; Par:Word):Boolean; StdCall;
var ca:Array[1..250] of char; N: Integer;
Begin
     Result := True;
     GetClassName(H,@Ca,SizeOf(ca));
     If Copy(ca,1,7) = 'ListBox' then
     begin
          MyClass := ca;
          Result := False;
     end;
End;

procedure TForm1.GetSearchWindow;
var HDlg : THandle; Count,N,TextLen: LongInt; ItemText: String;
    Strbuf: Array[0..255] of Char;
begin
     ListBox1.Items.Clear;
     HDlg := FindWindow(PChar(0),StrPCopy(Strbuf,'Search Results'));
     If hDlg > 0 then
     begin
          enumChildWindows (hdlg,@EnumProc,0);
          hDlg := FindWindow(StrPCopy(Strbuf,MyClass),PChar(0));
          Count := SendMessage(hDlg,LB_GETCOUNT,0,0);
          For N := 0 to Count-1 do
          begin
               TextLen := SendMessage(hDlg,LB_GETTEXTLEN,N,0);
               TextLen := TextLen+1;
               SetLength(ItemText,TextLen);
               SendMessage(hDlg,LB_GETTEXT,N,longint(@ItemText[1]));
               ListBox1.Items.Add(ItemText);
          end;
     end;
end;

The 'Search Results'  window is found, but  hDlg returns 0 on the next FindWindow trying to find the ListBox.  The variable MyClass returns 'ListBox' from the EnumProc function.

What am I doing wrong?

John
0
Comment
Question by:jdthedj
  • 2
4 Comments
 
LVL 34

Accepted Solution

by:
Slick812 earned 50 total points
ID: 7005287
hello jdthedj , if there is only ONE List box, then the code below should work, If the list box Items could be longer than 4096 charaters, then increase CharBuffer


procedure TForm1.sbut_FindListBClick(Sender: TObject);
var
hApp, hList: THandle;
Count, i: Integer;
CharBuffer: array[0..4096] of Char;
begin
ListBox1.Items.Clear;
hApp := FindWindow(nil,'Search Results);
if hApp <> 0 then
  begin
  hList := FindWindowEx(hApp,0,'LISTBOX',nil);
  Count := SendMessage(hList,LB_GETCOUNT,0,0);
  for i := 0 to Count-1 do
    begin;
    SendMessage(hList, LB_GETTEXT, i, Integer(@CharBuffer));
    ListBox2.Items.Add(CharBuffer);
    end;
  end;
end;
0
 
LVL 17

Expert Comment

by:geobul
ID: 7005304
Hi John,

>hDlg := FindWindow(StrPCopy(Strbuf,MyClass),PChar(0));

You can't get a child window handle using FindWindow function.

Add a new global var MyHandle: THandle; similar to MyClass.
Then in EnumProc write:

...
    If Copy(ca,1,7) = 'ListBox' then
    begin
         MyClass := ca;
         MyHandle := H;
         Result := False;
    end;
...

In GetSearchWindow write:

...
enumChildWindows (hdlg,@EnumProc,0);
if MyHandle > 0 then begin
  Count := SendMessage(hDlg,LB_GETCOUNT,0,0);
...

Regards, Geo
0
 
LVL 34

Expert Comment

by:Slick812
ID: 7006825
if you really want to use the EnumChildWindows function then


procedure TForm1.sbut_FindListBClick(Sender: TObject);
var
Count, i, hApp, hList: Integer;
CharBuffer: array[0..1024] of Char;

function EnumChildren(hChild: Integer; Pnt2Int:PInteger): Boolean; StdCall;
var
Buffer: array[0..10] of Char;
begin
{in this function the parameter variable Pnt2Int can not be declared as a var type
so if you want to get a value BACK to the EnumChildWindows( ) function, you will
need to use the Pointer type PInteger and Dereference it
(Pnt2Int^ := hChild) to change it's value outside of this fuction}
Result := True;
GetClassName(hChild,Buffer,9);
if CompareText(Buffer, 'LISTBOX')= 0 then
  begin
  Result := False;
  Pnt2Int^ := hChild;
  end else Pnt2Int^ := 0;
end;

begin
ListBox2.Items.Clear;
hApp := FindWindow(nil,'Menus and List Boxes');
if hApp <> 0 then
  begin
  hList := 0;
  {a more conventonal (API) way to get a value from an API callback
  func is to send the address of the variable (hList) and read it's
  value after the call}
  EnumChildWindows(hApp,@EnumChildren,Integer(@hList));
  if hList <> 0 then
    begin
    Count := SendMessage(hList,LB_GETCOUNT,0,0);
    for i := 0 to Count-1 do
      begin;
      SendMessage(hList, LB_GETTEXT, i, Integer(@CharBuffer));
      ListBox2.Items.Add(CharBuffer);
      end;
    end else
      ShowMessage('The ListBox does not exist');
  end else
  ShowMessage('The window does not exist');
end;
0
 
LVL 3

Author Comment

by:jdthedj
ID: 7007047
Thanks for the replies

Slick812:  Your first suggestion works, so I am accepting that as the answer.  Thanks!

Geo:  Thanks for your input too!

John
0

Featured Post

Free Tool: Port Scanner

Check which ports are open to the outside world. Helps make sure that your firewall rules are working as intended.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

In this tutorial I will show you how to use the Windows Speech API in Delphi. I will only cover basic functions such as text to speech and controlling the speed of the speech. SAPI Installation First you need to install the SAPI type library, th…
Introduction I have seen many questions in this Delphi topic area where queries in threads are needed or suggested. I know bumped into a similar need. This article will address some of the concepts when dealing with a multithreaded delphi database…
Finds all prime numbers in a range requested and places them in a public primes() array. I've demostrated a template size of 30 (2 * 3 * 5) but larger templates can be built such 210  (2 * 3 * 5 * 7) or 2310  (2 * 3 * 5 * 7 * 11). The larger templa…

839 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question