Reputation: 18730
I have a window with two text fields inside it.
How can I get the handles of both text fields using WinAPI calls?
Note: Both text boxes belong to a different application (I make the WinAPI calls in application A and the text boxes are located in application B).
Update 1:
I get Invalid window handle
message when invoking GetClassName
.
I suppose that something is wrong with my declaration of the callback function.
EnumChildWindows
is invoked from one of the methods of TMyClass
like this:
EnumChildWindows(handle, @TMyClass.CBList, 0);
Here's the code of the callback function.
function TMyClass.CBList(Win: THandle; lp: LPARAM): Boolean; stdcall;
var
ClassName:array [1..1024] of Char;
begin
GetClassName(Win, PChar(@ClassName), 1024);
OutputDebugString(PChar('SysErrorMessage(GetLastError): '));
result := true;
end;
Upvotes: 1
Views: 4041
Reputation: 613382
Use a tool like Spy++ to understand the structure of the target app, and find out the precise window class names that it uses.
Your questions in the comments about how to call GetClassName
got me thinking. If you are using XE3, you could write a simple type record helper for HWND
to make it syntactically cleaner to get hold of the class name:
type
THWNDHelper = record helper for HWND
private
function GetClassName: string;
public
property ClassName: string read GetClassName;
end;
function THWNDHelper.GetClassName: string;
var
Buffer: array [0..255] of Char;
begin
if Winapi.Windows.GetClassName(Self, @Buffer, Length(Buffer))=0 then
RaiseLastOSError;
Result := Buffer;
end;
And then you can write hwnd.ClassName
to obtain the window class name. Of course, if you are not using XE3 you can do it like this:
function GetWindowClassName(hwnd: HWND): string;
var
Buffer: array [0..255] of Char;
begin
if GetClassName(hwnd, @Buffer, Length(Buffer))=0 then
RaiseLastOSError;
Result := Buffer;
end;
Note that I am using a buffer length of 256 since window class name lengths are limited to be no longer than that.
Regarding the code in the update, you must not use an instance method for the callback. The callback must be declared like this:
function EnumChildWindowsCallback(hwnd: HWND; lParam: LPARAM): BOOL; stdcall;
begin
OutputDebugString(PChar(GetWindowClassName(hwnd)));
Result := True;
end;
This is made clear in the documentation. Unfortunately the declaration of EnumChildWindows
in Windows.pas
completely abandons type safety of the callback function. So you have to get it right without help from the compiler.
Note also that HWND
and THandle
are not the same thing. Don't mix them up.
Upvotes: 5