Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there a way to get a VCL Control's name through the windows API?

Tags:

winapi

delphi

I have the Hwnd of a VCL Control that is located on another process' window. Is there a way to get its VCL name (TControl.Name property) of that control through the windows API? I need the name because there are several TEdits on that window and I need to identify the one I want in order to send a WM_SETTEXT message to it.

Both applications were built with Delphi 2010.

like image 257
Daniel Santos Avatar asked Mar 20 '13 20:03

Daniel Santos


1 Answers

Delphi has builtin function FindControl() which returns TWinControl of specified hWnd. But it works for the same instance of VCL. I think you should investigate it. After you have pointer to TWinControl object its name (string) located at +8 offset. You can try ReadProcessMemory for read it. The main problem here is to create version of FindControl() suits your needs.

Edit: (Finally got it :D ) Call GetWinControlName function

// Get Pointer to TWinControl in another process
function GetWinControl(Wnd: HWND; out ProcessId: THandle): Pointer;
var
  WindowAtomString: String;
  WindowAtom: ATOM;
begin
  if GetWindowThreadProcessId(Wnd, ProcessId) = 0 then RaiseLastOSError;

  // This is atom for remote process (See controls.pas for details on this)
  WindowAtomString := Format('Delphi%.8X',[ProcessID]);
  WindowAtom := GlobalFindAtom(PChar(WindowAtomString));
  if WindowAtom = 0 then RaiseLastOSError;

  Result := Pointer(GetProp(Wnd, MakeIntAtom(WindowAtom)));
end;

function GetWinControlName(Wnd: HWND): string;
var
  ProcessId: THandle;
  ObjSelf: Pointer;
  Buf: Pointer;
  bytes: Cardinal;
  destProcess: THandle;
begin
  ObjSelf := GetWinControl(Wnd, ProcessId);

  destProcess := OpenProcess(PROCESS_VM_READ, TRUE, ProcessId);
  if destProcess = 0 then RaiseLastOSError;

  try
    GetMem(Buf, 256);
    try
      if not ReadProcessMemory(destProcess, Pointer(Cardinal(ObjSelf) + 8), Buf, 4, bytes) then RaiseLastOSError;
      if not ReadProcessMemory(destProcess, Pointer(Cardinal(Buf^)), Buf, 256, bytes) then RaiseLastOSError;
      Result := PChar(Buf);
    finally
      FreeMem(Buf);
    end;
  finally
    CloseHandle(destProcess);
  end;
end;
like image 50
Samaliani Avatar answered Sep 30 '22 20:09

Samaliani