Go Premium for a chance to win a PS4. Enter to Win

x
?
Solved

WM_GETTEXT problem

Posted on 2013-01-01
6
Medium Priority
?
1,556 Views
Last Modified: 2013-01-03
Hi Everyone,
I have program that should read both textboxes and textlabels from another program. I'm retrieving the handle for the controls with EnumWindows and EnumChildWindows. First I tried the GetWindowsText which worked fine, but not with the Edit Boxes. So I'm now trying to use the WM_GETTEXT directly but with no better success.. I'm not getting any text at all..

Here is the code used:
function EnumTextChildProc(AHandle: hWnd; AnObject: TObject): BOOL; stdcall;
var
  caption: array[0..3000] of Char;
  s: string;
begin
  Result := True;
  SendMessage(AHandle, WM_GETTEXT, Sizeof(caption), integer(@caption));
  s := Caption;
  ShowMessage(s);
end;


Any solutions or workarounds for this problem?

(using Win 8 and Delphi XE3)
0
Comment
Question by:hakanfa
  • 3
  • 2
6 Comments
 
LVL 28

Expert Comment

by:Sinisa Vuk
ID: 38735053
http://www.delphifaq.com/faq/delphi/windows_GUI/f451_0.htm

Your example works ok for me when used as:
procedure TForm1.BitBtn1Click(Sender: TObject);
begin
  EnumChildWindows(Self.Handle, @EnumTextChildProc, 0);
end;

Open in new window

(i put edit and button component on form)

http://borland.public.delphi.winapi.narkive.com/Qw0wAIR1/wm-gettext-doesn-t-work-in-the-icq-chat-window
0
 
LVL 19

Expert Comment

by:Thommy
ID: 38736651
Download Winhandles.zip

Try out this wonderful example of getting text from any control of all running processes and applications...
0
 
LVL 19

Expert Comment

by:Thommy
ID: 38739474
Check my below demo code to see how to get edit text from another program using Windows message WM_GETTEXT... (Finding child windows in other applications by ClassName)

unit Unit1;

interface

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

type
  TForm1 = class(TForm)
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
  private
    { Private-Deklarationen }
    function nGetChildHandle: Integer;
  public
    { Public-Deklarationen }
  end;

function EIFindChildWindow(hwndParent: HWnd; ClassName: PChar): HWnd;
function EIGetWindowClass(const nHandle: HWnd): string;

var
  Form1: TForm1;

implementation

var
  hwndFindChildWindow : HWND;


{$R *.dfm}

function EnumTextChildProc(AHandle: hWnd): BOOL; stdcall;
var
  AText: array[0..255] of Char;
  s: string;
begin
  Result := True;
  PostMessage(AHandle, WM_GETTEXT, Sizeof(AText), integer(@AText));
  s := strpas(AText);
  ShowMessage(s);
end;

function GetTextFromHandle(wndhandle: HWnd): string;
var
 textlength: integer;
 text: PChar;
begin
   result := '';
   if wndhandle = 0 then Exit;
   textlength := SendMessage(wndhandle, WM_GETTEXTLENGTH, 0, 0);
   if textlength <> 0 then
     begin
       GetMem(Text, textlength+1);
       SendMessage(wndhandle, WM_GETTEXT, textlength+1, Integer(text));
       Result := text;
       FreeMem(text);
     end;

end;

function EIGetWindowClass(const nHandle: HWnd): string;
var
  szClassName: array[0..255] of char;
begin
  GetClassName(nHandle, szClassName, 255);
  Result := szClassName;
end;

function EnumWindowsForFindChildWindowProc(WHandle: HWND; lParam: LPARAM): BOOL; export; stdcall;
const
  MAX_WINDOW_NAME_LEN = 80;
var
  sTargetClassName: string;
  nHandle: HWnd;
  sCurrClassName: string;
  bResult: Boolean;
begin
  if (hwndFindChildWindow<>0) then
    exit;
  sTargetClassName := PChar(lParam);
  sCurrClassName := EIGetWindowClass(WHandle);
  bResult := CompareText(sCurrClassName, sTargetClassName) = 0;
  If (bResult) then
    hwndFindChildWindow := WHandle
  else
    EIFindChildWindow(WHandle, PChar(lParam));
end;

function EIFindChildWindow(hwndParent: HWnd; ClassName: PChar) : HWnd;
begin
  try
    EnumChildWindows(hwndParent, @EnumWindowsForFindChildWindowProc, LongInt(PChar(ClassName)));
    Result := hwndFindChildWindow;
  except
    on Exception do
      Result := 0;
  end;
end;

function TForm1.nGetChildHandle: Integer;
var
  nParentHandle: HWnd;
  nChildHandle: HWnd;
begin
  //Find parent window
  nParentHandle := FindWindow(nil, PChar('Your window title'));
  if nParentHandle = 0 then
    raise Exception.Create('Couldn''t find the main window !');

  //Find child window (TEdit)
  nChildHandle := EIFindChildWindow(nParentHandle, PChar('TEdit'));
  if nChildHandle = 0 then
    raise Exception.Create('Couldn''t find the child window !');

  Result := nChildHandle;
end;

procedure TForm1.Button1Click(Sender: TObject);
var
  TheChildHandle: hwnd;
begin
  TheChildHandle:=nGetChildHandle;
end;

end.

Open in new window

0
Independent Software Vendors: We Want Your Opinion

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 

Author Comment

by:hakanfa
ID: 38740512
Hi Tommy, thanks for the pice of code. Works fine with small modifications for own needs. Though one question, you use both send-message and post-message command, any specific reason for that? Anyhow, works fine, thanks!

-Hokki
0
 
LVL 19

Accepted Solution

by:
Thommy earned 2000 total points
ID: 38741581
What is the difference between PostMessage and SendMessage?

For WM_GETTEXT you should prefer using SendMessage (synchronous version) to make sure that your program waits until the message has been proccessed.

PostMessage just places the message into the message queue and returns regardless if the message has been processed or not. Especially in case of high message loads there is no garantuee that the return parameter of the Postmessage function is correctly set in time.

Postmessage is good in multithreading apps: with PostMessage you can deliver messages to any thread in the system without waiting for the result. The message is just placed onto the message queue of the receiving thread and stays there until the receiving thread comes to life. At that time the message is handled. All that time your thread continues to run...
0
 

Author Closing Comment

by:hakanfa
ID: 38741617
Excellent, thank you very much!
0

Featured Post

Concerto Cloud for Software Providers & ISVs

Can Concerto Cloud Services help you focus on evolving your application offerings, while delivering the best cloud experience to your customers? From DevOps to revenue models and customer support, the answer is yes!

Learn how Concerto can help you.

Question has a verified solution.

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

Creating an auto free TStringList The TStringList is a basic and frequently used object in Delphi. On many occasions, you may want to create a temporary list, process some items in the list and be done with the list. In such cases, you have to…
Have you ever had your Delphi form/application just hanging while waiting for data to load? This is the article to read if you want to learn some things about adding threads for data loading in the background. First, I'll setup a general applica…
this video summaries big data hadoop online training demo (http://onlineitguru.com/big-data-hadoop-online-training-placement.html) , and covers basics in big data hadoop .
Look below the covers at a subform control , and the form that is inside it. Explore properties and see how easy it is to aggregate, get statistics, and synchronize results for your data. A Microsoft Access subform is used to show relevant calcul…
Suggested Courses

916 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