Pobranie nazwy komponentu z obcej aplikacji

0

Mam funkcję pobierającą nazwę [NAME] kontrolki innej aplikacji:

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

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

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

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

  destProcess := OpenProcess(PROCESS_VM_READ, TRUE, ProcessId);
  GetMem(Buf, 256);
  try
    if ReadProcessMemory(destProcess, Pointer(Cardinal(ObjSelf) + 8), Buf, 4, bytes) then
    begin
      ReadProcessMemory(destProcess, Pointer(Cardinal(Buf^)), Buf, 256, bytes);
      Result := PChar(Buf);
    end;
  finally
    FreeMem(Buf);
    CloseHandle(destProcess);
  end;
end;

Wszystko pięknie, ładnie, ale działa tylko na aplikacjach, które zostały przekompilowane (tak mi się wydaje) w wersji środowiska XE+.
Mam wiele programów napisanych w Delphi XE3 i ten kod działa właśnie dla tych programów. Natomiast dla programów pisanych w wersjach delphi niższych np. Delphi 7, 2007 wyświetla chińskie znaki i znaki ASCII.

Jaka może być tego przyczyna?

0

Jeżeli chcesz tylko pobrać nazwę kontrolki, to do tego celu służy funkcja WinAPI z modułu Windows: GetClassName.

0

Olesio, nie nazwę klasy, tylko nazwę komponentu - wartość Name z object inspectora

0

Aha, no to jest taki moduł, który pod 32 bitowym IDE, a testowałem to na Delphi 7, pozwala pobrać tekst ze statusbara obcej aplikacji, co normalnie, jest niemożliwe. Może dzięki niemu dostęp do danych w pamięci obcego procesu będzie odbywał się tak jak tego oczekujesz.

Za kodem tego modułu musisz sam pogooglować, bo nie mam dostępu do swoich źródeł nie siedząc na PC. A dopiero jutro pod wieczór będę mógł go tuaj dołączyć, więc do tego czasu sam go znajdziesz.

Jednak udało się mi znależć Ustawianie tekstu przez SB_SETTEXT dla elementu innego niż o indeksie 0 w obcym programie. powinno być w kodzie dołączonym do mojego posta. Jeżeli to nie pomoże, to nie mam innych pomysłów, może ktoś jeszcze coś doradzi.

2

Nie działa bo dopiero w nowych Delphi jest Unicode a w funkcji autor (Ty?) śmiało zakłada że okno jest Unicode gdy jednak nie jest (jak w starszych Delphi) to z takiego rzutowania AnsiString na WideString dostaniesz szlaczki. Poprawiona funkcja:

function GetWinControlName(Wnd: HWND): WideString;
var
  ProcessID: THandle;
  ObjSelf: Pointer;
  Buf: Pointer;
  {$IF CompilerVersion >= 22} //chyba od Delphi XE ma być NativeUInt 
  bytes: NativeUInt;
  {$ELSE}
  bytes: Cardinal;
  {$IFEND}
  destProcess: THandle;
begin
  ObjSelf := GetWinControl(Wnd, ProcessId);

  destProcess := OpenProcess(PROCESS_VM_READ, TRUE, ProcessId);
  GetMem(Buf, 256);
  try
    if ReadProcessMemory(destProcess, Pointer(Cardinal(ObjSelf) + 8), Buf, 4, bytes) then
    begin
      ReadProcessMemory(destProcess, Pointer(Cardinal(Buf^)), Buf, 256, bytes);
    if IsWindowUnicode(Wnd) then
      Result := PWideChar(Buf)
    else
      Result:= WideString(PAnsiChar(Buf));
    end;
  finally
    FreeMem(Buf);
    CloseHandle(destProcess);
  end;
end;

EDIT Troszkę poprawiłem kod aby poprawnie się kompilował w starych i nowych wersjach Delphi

0

TAAAAK!!! :) Ogromne dzięki Ci milordzie!

1 użytkowników online, w tym zalogowanych: 0, gości: 1