Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people, just like you, are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
Solved

WM_GETTEXT problem

Posted on 2013-01-01
6
1,429 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
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.

 

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

Active Directory Webinar

We all know we need to protect and secure our privileges, but where to start? Join Experts Exchange and ManageEngine on Tuesday, April 11, 2017 10:00 AM PDT to learn how to track and secure privileged users in Active Directory.

Question has a verified solution.

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

Suggested Solutions

The uses clause is one of those things that just tends to grow and grow. Most of the time this is in the main form, as it's from this form that all others are called. If you have a big application (including many forms), the uses clause in the in…
Objective: - This article will help user in how to convert their numeric value become words. How to use 1. You can copy this code in your Unit as function 2. than you can perform your function by type this code The Code   (CODE) The Im…
With Secure Portal Encryption, the recipient is sent a link to their email address directing them to the email laundry delivery page. From there, the recipient will be required to enter a user name and password to enter the page. Once the recipient …
The Email Laundry PDF encryption service allows companies to send confidential encrypted  emails to anybody. The PDF document can also contain attachments that are embedded in the encrypted PDF. The password is randomly generated by The Email Laundr…

829 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