Solved

WM_GETTEXT problem

Posted on 2013-01-01
6
1,413 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 26

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
DevOps Toolchain Recommendations

Read this Gartner Research Note and discover how your IT organization can automate and optimize DevOps processes using a toolchain architecture.

 

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 500 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

Is Your AD Toolbox Looking More Like a Toybox?

Managing Active Directory can get complicated.  Often, the native tools for managing AD are just not up to the task.  The largest Active Directory installations in the world have relied on one tool to manage their day-to-day administration tasks: Hyena. Start your trial today.

Question has a verified solution.

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

Suggested Solutions

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…
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…
Along with being a a promotional video for my three-day Annielytics Dashboard Seminor, this Micro Tutorial is an intro to Google Analytics API data.
This video shows how to use Hyena, from SystemTools Software, to bulk import 100 user accounts from an external text file. View in 1080p for best video quality.

809 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