13

別のプロセスのウィンドウにあるVCLコントロールのHwndがあります。Windows APIを介してそのコントロールのVCL名(TControl.Nameプロパティ)を取得する方法はありますか?WM_SETTEXTそのウィンドウにはいくつかのTEditがあり、メッセージを送信するために必要なTEditを識別する必要があるため、名前が必要です。

どちらのアプリケーションもDelphi2010で構築されています。

4

2 に答える 2

14

Delphiには、指定されたhWndFindControl()を返す関数が組み込まれています。TWinControlただし、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

いいえ、コントロールの名前を生成するWindowsAPI関数はありません。これは、Delphiのプライベート実装の詳細です。

ターゲットプロセスのコードを制御する場合は、明らかに、問題を解決するために何らかの形式のIPCを実装できます。それ以外の場合、コントロール名を生成するソリューションには、かなり下品なハッキングが含まれます。1つのアプローチは、同じバージョンのランタイムでビルドされたDLLをプロセスに挿入することです。そのDLLを取得して、HWNDからVCLコントロール参照を見つけ、名前を読み取ります。これには多くのバリエーションがあり、ReadProcessMemory@ Samalianiの答えによって提供されるうまく行われたトリックは、あなたが飛び越えなければならないフープの典型です。

しかし、私はあなたの問題に対するはるかに簡単な解決策を考えることができます。すべての編集コントロールのハンドルを見つけ、それらのハンドルを使用してコントロールの座標を受け取ります。編集コントロールの相対的な位置は、どれが目的のターゲットであるかを識別するのに十分です。そして、いくつかのより有用な考えについては、以下の@dthorpeのコメントを読んでください。

于 2013-03-20T20:40:12.263 に答える