0

グリッドを使用して Delphi にアプリケーションがあります。

別のアプリケーションを作成する必要があります。

a) グリッドからデータを読み取り、b) グリッドにデータを書き込みます。

つまり、人間のユーザーのアクションをエミュレートします。

テーブルからデータを読み取るために、次のコードを使用します。

Procedure TForm1.Button1Click(Sender: TObject);
type
  PForm = ^TForm;
  PClass = ^TClass;
var
  formPtr : PForm;
  I: Integer;
  msg : string;
  windowHandle : HWND;
begin
  windowHandle := FindWindow('TForm1', 'FORMSSSSS');
  formPtr := PForm(GetVCLObjectAddr(windowHandle) + 4);
  if (not Assigned(formPtr)) then Exit;
  for I := 0 to formPtr^.ControlCount - 1 do // Error
  begin
    msg := msg + formPtr^.Controls[i].Name;
    if formPtr^.Controls[i].Name = 'StringGrid1' then
    begin
      msg := TStringGrid(formPtr^.Controls[i]).Cells[1, 1];
    end;

  end;
  ShowMessage(msg);
end;


function GetVCLObjectAddr(AHandle: HWND): DWORD;
var
  pid: DWORD;
begin
  pid := 0;
  GetWindowThreadProcessId(AHandle, pid);
  if (pid =0) then
  begin
    Result := 0;
    Exit;
  end;
  Result := GetPropW(AHandle, PWideChar(WideString(Format('Delphi%.8X', [PID]))))
end;

「エラー」コメントの行で、次の問題が発生します。

プロジェクト Project1.exe は、例外クラス EAccessViolation を発生させ、メッセージ「モジュール 'Project1.exe' のアドレス 0046C8C3 でアクセス違反が発生しました。アドレス 01262984' の読み取り。

その行にブレークポイントを配置し、「ウォッチ」タブで式「formPtr^」の値を調べると、「値にアクセスできません」というメッセージが表示されます。

グリッドからデータを読み取れるようにするには、コードをどのように変更する必要がありますか?

更新:

コードを以下のバージョンに変更すると、メモリの問題はなくなります。しかし、別の問題が発生します - コントロールカウントがゼロに等しいです。

Procedure TForm1.Button1Click(Sender: TObject);
var
  formPtr : TForm;
  I: Integer;
  msg : string;
  windowHandle : HWND;
begin
  windowHandle := FindWindow('TForm1', 'FORMSSSSS');
  formPtr := TForm(GetVCLObjectAddr(windowHandle) + 4);
  if (not Assigned(formPtr)) then Exit;
  for I := 0 to formPtr.ControlCount - 1 do
  begin
    msg := msg + formPtr.Controls[i].Name;
    if formPtr.Controls[i].Name = 'StringGrid1' then
    begin
      msg := TStringGrid(formPtr.Controls[i]).Cells[1, 1];
    end;    
  end;
  ShowMessage(msg);
end;
4

1 に答える 1

1

そのアプローチは機能しません。2 つのプロセスのアドレス空間は分離されています。アドレス、つまりオブジェクトは、そのアドレスまたはオブジェクトを所有するプロセスのコンテキストでのみ意味があります。プロセスに存在するオブジェクトのメソッドのみを呼び出すことができます。

于 2012-09-17T10:19:34.930 に答える