13

我有一个位于另一个进程窗口上的 VCL 控件的 Hwnd。有没有办法TControl.Name通过 Windows API 获取该控件的 VCL 名称(属性)?我需要这个名称,因为该窗口上有几个 TEdit,我需要确定我想要的那个以便向WM_SETTEXT它发送消息。

这两个应用程序都是使用 Delphi 2010 构建的。

4

2 回答 2

14

Delphi 具有FindControl()返回TWinControl指定 hWnd 的内置函数。但它适用于同一个 VCL 实例。我觉得你应该调查一下。在您拥有指向 TWinControl 对象的指针后,其名称(字符串)位于+8偏移处。您可以尝试 ReadProcessMemory 来读取它。这里的主要问题是创建适合您需要的 FindControl() 版本。

编辑:(终于明白了:D)调用GetWinControlName函数

// 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;
于 2013-03-21T09:09:21.233 回答
7

不,没有可以产生控件名称的 Windows API 函数。那是一个私有的 Delphi 实现细节。

如果您控制目标进程的代码,那么显然您可以实现某种形式的 IPC 来解决问题。否则,任何产生控件名称的解决方案都将涉及相当卑鄙的黑客攻击。一种方法是将使用相同版本的运行时构建的 DLL 注入进程。获取该 DLL 以从 HWND 中找到 VCL 控件引用并读出名称。这方面有很多变体ReadProcessMemory,@Samaliani 的回答提供的巧妙技巧是您必须跳过的典型环节。

但是,我可以想到一个更简单的解决方案来解决您的问题。找到所有编辑控件的句柄并使用这些句柄接收控件的坐标。编辑控件的相对位置将足以确定哪个是所需的目标。请阅读下面@dthorpe 的评论,了解更多有用的想法。

于 2013-03-20T20:40:12.263 回答