Title: Finding child windows in other applications by ClassName
Question: Just say you want to get the text of an edit control in another application... How do you get it from your app ? Here's how:
Answer:
Hey folks;
Here's some code that I used to find a child window in another application *by windows class* the other day, and it worked great for me. It needs a parent window handle, and it recursively enumerates the children of the parent handle until it finds the window it was looking for... I did try and use FindWindowEx, but it didn't seem to do the trick...
For example: The code below is a working demo of hiding/showing the main text entry field of a new instance of Notepad.
Regards,
Brad Parks.
// begin Unit1.pas
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
StdCtrls;
type
TForm1 = class(TForm)
Button1: TButton;
ParentCaption: TEdit;
ChildClass: TEdit;
Label1: TLabel;
Label2: TLabel;
Button2: TButton;
Button3: TButton;
procedure Button1Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
procedure Button3Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
function nGetChildHandle: Integer;
end;
var
Form1: TForm1;
function EIFindChildWindow(hwndParent: HWnd; ClassName: PChar): HWnd;
function EIGetWindowClass(const nHandle: HWnd): string;
procedure EISetWinText(nHandle: Integer; const sNewText: string);
function EIGetWinText(nHandle: Integer): string;
function EIGetFocusedChildWindow: HWnd;
function EIGetFocusedWindowFromParent(ParentWnd:HWnd):HWnd;
procedure EISetForegroundWindow(const nHandle: HWnd);
implementation
{$R *.DFM}
var
hwndFindChildWindow : HWND;
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;
procedure EISetForegroundWindow(const nHandle: HWnd);
begin
if (IsIconic(nHandle)) then
begin
SendMessage(nHandle, WM_SYSCOMMAND, SC_HOTKEY, nHandle);
SendMessage(nHandle, WM_SYSCOMMAND, SC_RESTORE, nHandle);
end;
SetForegroundWindow(nHandle);
end;
function EIGetFocusedWindowFromParent(ParentWnd:HWnd):HWnd;
var
OtherThread,
Buffer : DWord;
idCurrThread: DWord;
begin
OtherThread := GetWindowThreadProcessID(ParentWnd, @Buffer);
idCurrThread := GetCurrentThreadID;
if AttachThreadInput(idCurrThread, OtherThread, true) then begin
Result := GetFocus;
AttachThreadInput(idCurrThread, OtherThread, false);
end
else
Result:= GetFocus;
end;
function EIGetFocusedChildWindow: HWnd;
begin
Result := EIGetFocusedWindowFromParent(GetForegroundWindow);
end;
function EIGetWinText(nHandle: Integer): string;
var
pcText: array[0..32768] of char;
begin
SendMessage(nHandle, WM_GETTEXT, 32768, LongInt(@pcText));
Result := pcText;
end;
procedure EISetWinText(nHandle: Integer; const sNewText: string);
begin
SendMessage(nHandle, WM_SETTEXT, Length(sNewText), LongInt(PChar(Trim(sNewText))));
end;
function EIGetWindowClass(const nHandle: HWnd): string;
var
szClassName: array[0..255] of char;
begin
GetClassName(nHandle, szClassName, 255);
Result := szClassName;
end;
procedure TForm1.Button1Click(Sender: TObject);
begin
ShowMessage('The child window handle is :' + IntToStr(nGetChildHandle));
end;
function TForm1.nGetChildHandle: Integer;
var
nParentHandle: HWnd;
nChildHandle: HWnd;
begin
nParentHandle := FindWindow(nil, PChar(ParentCaption.Text));
if nParentHandle = 0 then
raise Exception.Create('Couldn''t find the main window !');
nChildHandle := EIFindChildWindow(nParentHandle, PChar(ChildClass.Text));
if nChildHandle = 0 then
raise Exception.Create('Couldn''t find the child window !');
Result := nChildHandle;
end;
procedure TForm1.Button2Click(Sender: TObject);
begin
ShowWindow(nGetChildHandle, sw_Hide);
end;
procedure TForm1.Button3Click(Sender: TObject);
begin
ShowWindow(nGetChildHandle, sw_ShowNormal);
end;
end.
// End Unit1.pas
// Begin Unit1.dfm
object Form1: TForm1
Left = 253
Top = 124
Width = 304
Height = 195
Caption = 'Find Window'
Font.Charset = DEFAULT_CHARSET
Font.Color = clWindowText
Font.Height = -11
Font.Name = 'MS Sans Serif'
Font.Style = []
Position = poScreenCenter
PixelsPerInch = 96
TextHeight = 13
object Label1: TLabel
Left = 8
Top = 8
Width = 73
Height = 13
Caption = 'Parent Caption:'
end
object Label2: TLabel
Left = 8
Top = 36
Width = 54
Height = 13
Caption = 'Child Class:'
end
object Button1: TButton
Left = 216
Top = 4
Width = 75
Height = 25
Caption = 'Find It'
TabOrder = 0
OnClick = Button1Click
end
object ParentCaption: TEdit
Left = 84
Top = 4
Width = 121
Height = 21
TabOrder = 1
Text = 'Untitled - Notepad'
end
object ChildClass: TEdit
Left = 84
Top = 32
Width = 121
Height = 21
TabOrder = 2
Text = 'Edit'
end
object Button2: TButton
Left = 84
Top = 92
Width = 157
Height = 25
Caption = 'Hide the child window'
TabOrder = 3
OnClick = Button2Click
end
object Button3: TButton
Left = 84
Top = 124
Width = 157
Height = 25
Caption = 'Show the child window'
TabOrder = 4
OnClick = Button3Click
end
end
// end Unit1.dfm