Jak odczytać ProcessName z Uchwytu kontrolki?

0

Witam,

tak jak w temacie czyli mamy otwartą obcą aplikację, która aktualnie ma otwarte jakieś okienko typu ShowModal, następnie na tym oknie jest Panel a w nim Button.
I teraz, jak na podstawie uchwytu tej kontrolki odczytaj ProcessName/ID? Jak to wszystko iterować...?

Dla ułatwienia dodam, że nie znam tytułu okna i zakładamy, że caption formy głównej jak i okien nadrzędnych może się zmieniać podczas działania programu.

1

Już zacząłem patrzeć na swoje kody w podkatalogu USEFUL_WINAPI. Coż tam wymodziłem do uzyskiwania PID'ów i uchwytów. Enumeracji. I nic nie ma. Chwileczkę, bo padł gol dla Niemiaszków. No już po replay'u - ładna bramka, także kontynuuję :) Także zastanawiałem się, co chcesz uzyskać. Ale jeśli masz jakiś uchwyt kontrolki. I na jego podstawie chcesz mieć PID procesu rodzica, to najzwyczajniej w świecie użyj wedle mnie najprostszego rozwiązania. Czyli funkcji GetWindowThreadProcessId.

Według mnie żadna enumeracja nie jest tutaj potrzebna. Można ją przeprowadzić oczywiście. Ale mogła by trwać zbędne kilkaset milisekund dla wielu procesów. A po co? Trzeba korzystać według mnie z tego, co udostępniają twórcy systemu. Także mam nadzieję, że o to chodziło. Ale piszę po całodziennej posiadówie nad jeziorem przy grillu i po pływaniu w jeziorze. Oraz znacznej ilości wypitych procentów. Także z lekkiego zmęczenia mogę się mylić lub źle Ciebie zrozumieć w tym, co chcesz osiągnąć :) Wtedy doprecyzuj proszę.

0

Hehe rozumiem :) Już doprecyzowuję:

Tworzę repozytorium wybranych kontrolek danej aplikacji tzn:

Kiedy kliknę na przycisk przykładowo w aplikacji napisanej pod Delphi do Virtual String Tree zostanie utworzony poniższy wpis:

  • ProgramTestowy (nazwa procesu)
    • TfrmMain (okno w którym znajduje się kontrolka)
      • TButton (kontrolka)
      • TEdit
    • TfrmEdycja
      • TButton

Schemat działania:
Klikam LPM na dowolnej kontrolce aplikacji Win32 i odczytuję kontrolkę pod kursorem, pobieram jej uchwyt, klasę, text oraz VCL Name następnie tworzę z tego powyższe drzewko.

Głównym problemem jest aby odczytać parametry głównego okna kontrolki leżącej na innch pod oknach:

TForm1-> Button -> Pokaż Form2
TForm2 -> Button -> pokaż Form3
TForm3 -> Button -> Kliknięcie myszką w ten button powinień zwrócić mi PID i nazwę procesu.

Mam nadzieję, że zrozumiałe

Czy

GetWindowThreadProcessId

mi wystarczy?

0

Według mnie, do uzyskania PID'u wystarczy wspomniana funkcja. W zmiennej typu liczbowego, przekazanej jako drugi parametr, zwróci ona PID procesu, do którego należy kontrolka o uchwycie HWND, podanym jako pierwszy parametr. Zresztą zapoznaj się z opism na MSDNie.

Co do dodatkowych kombinacji, to mogę Tobie zapodać moje unity pisane pod kątem WinAPI i enumeracji kontrolek oraz procesów. Jest tam na przykład uzyskiwanie HWND z główngo okna procesu o wskazanym PID, uzyskiwanie zawsze uchwytu podstawowego rodzica i tym podobne. Jednak do tych źródeł będę miał swobodny dostęp z PC dopiero jutro po pracy. pewnie po południu lub wieczorem.

Natomiast jestem ciekaw, jak rozwiążesz kwestie wyboru kontrolki po prawokliku. Ja napisałem sobie kiedyś program, który na zasadzie globalnego hooka, po środkowym kliknięciu na standardową kontrolkę edycyjną pokazuje menu, gdzie można wybrać case liter jej tekstu. Są też skróty klawoszowe do tych opcji. Ponieważ niestety pomimo wielu kombinacji, nie udało się mi dodać własnych pozycji do systemowego menu dla wytnij, kopiuj i wklej pod prawo klikiem. Jest to chyba niemożliwe.

0

Wykombinowałem to w ten sposób:

function GetWindowProcessName(aWnd: HWND): string;
  function GetProcessNameByID(PID: integer): string;
  var
    proc: TPROCESSENTRY32;
    hSnap: HWND;
    Looper: BOOL;
    PName: string;
  begin
     proc.dwSize := SizeOf(Proc);
     hSnap := CreateToolhelp32Snapshot(TH32CS_SNAPALL, 0);
     try
       Looper := Process32First(hSnap, proc);
       while Integer(Looper) <> 0 do
       begin
          if PID = Int64(proc.th32ProcessID) then
             PName := proc.szExeFile;
          Looper := Process32Next(hSnap, proc);
       end;
     finally
       CloseHandle(hSnap);
     end;
     Result := PName;
  end;
var
  PID: Cardinal;
begin
  GetWindowThreadProcessID(aWnd, PID);

  Result := ExtractFileName(GetProcessNameByID(PID));
end;

Działa tak jak należy, wielkie dzięki @olesio za nakierowanie, obejdzie się bez źródeł pokombinuję coś samemu.

0

@user322 - czy nie możesz użyć zmiennej Looper w pętli bez rzutowania?

while Looper do
begin
  // code here
end;

Nie musisz tego rzutować, bo nawet jeśli liczbowa wartość tej zmiennej jest większa od 1, to pętla i tak będzie działać prawidłowo; Poza tym niepotrzebnie zrobiłeś sobie funkcję zagnieżdżoną, skoro ona w tym przypadku nic nie daje - używasz jej raz, a główny blok funkcji nadrzędnej zawiera tylko wywołanie funkcji i zwrócenie wyniku; Zmniejszyłeś sobie czytelność kodu, praktycznie nic nie zyskując;

Poza tym pętlę While możesz zamienić na Repeat i w ogóle pozbyć się dodatkowej zmiennej (PName przy okazji też):

function GetWindowProcessName(AWnd: HWND): String;
var
  proc: TPROCESSENTRY32;
  hSnap: HWND;
  PID: Cardinal;
begin
  GetWindowThreadProcessID(AWnd, PID);
  proc.dwSize := SizeOf(proc);
  hSnap := CreateToolhelp32Snapshot(TH32CS_SNAPALL, 0);
  try
    if Process32First(hSnap, proc) then
    repeat
      if PID = Int64(proc.th32ProcessID) then
        Result := proc.szExeFile;
    until not Process32Next(hSnap, proc);
  finally
    CloseHandle(hSnap);
  end;
  Result := ExtractFileName(Result);
end;

To samo, a znacznie czytelniejsze i krótsze - przetestuj sobie.

0

Też mam rozwiązane takowe szukanie coś w ten deseń. Po prostu ktoś raz to zakodził i zapodał na faq czy forum dawno temu. A teraz wszyscy bez wnikania powielają. Chyba to rzutowanie było kiedyś potrzebne by unikać warningów.

0

Widziałem te FAQ - sprawdziłem skąd w ogóle wzięła się zmienna Looper i znalazłem sporo powielonych kodów;

Niezgodność mogła wynikać z dawnego 4-bajtowego bool z WinAPI (zgodnego rozmiarem z typem int), kiedy w Delphi Boolean był 1-bajtowy; To oczywiście także nie stanowiło problemu, bo Delphi od pradawnych czasów ma typy rozszerzone - 2-bajtowy WordBool i 4-bajtowy LongBool; W nowych kompilatorach (Visual C++ 5.0 i późniejszych) typ bool już jest jednobajtowy;


W każdym razie kopiowane kody też trzeba analizować i wiedzieć jak działają, bo nie zawsze są idealne (choć działające).

0

Macie racje, o wiele czytelniejsze i wydajniejsze. Analiza nie boli a czasem pomaga :) Jeszcze raz dzięki Wam.

0

@olesio

Ponieważ niestety pomimo wielu kombinacji, nie udało się mi dodać własnych pozycji do systemowego menu dla wytnij, kopiuj i wklej pod prawo klikiem. Jest to chyba niemożliwe.

W jakim sensie dla systemowego menu? Możesz sprecyzować? Chodzi Ci o menu pod prawym przyciskiem np. na pulpicie? Bo jeśli tak, to się da.

0

Ty wspomniałeś, że kombinujesz z menu pod prawoklikiem na dowolnej okienkowej kontrolce jakiejś obcej aplikacji. Tak zrozumiałem przynajmniej. To da się zrobić, przechwtująć Hookiem globalnym na myszkę, wyświetlając swoje menu i blokując odpowiednim Resultem wykonanie innej reakcji na Twój prawo klik.

A mi chodziło, o czym wyraźnie pisałem o menu dla kontrolek edycyjnych z polecewniami wytnij, kopiuj, wklej i tym podobne. To, że się do menu exploratora dodać pozycje to oczywiste. No i z tym nie ma problemy. Chyba, że wiesz jak dodać do tego menu o którym ja piszę, to chętnie zobacze przykładowy kod w Delphi, który to umożliwia.

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