Jak odczytać ProcessName z Uchwytu kontrolki?

Jak odczytać ProcessName z Uchwytu kontrolki?
U3
  • Rejestracja:prawie 13 lat
  • Ostatnio:prawie 2 lata
  • Postów:196
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.

olesio
  • Rejestracja:około 17 lat
  • Ostatnio:około 3 lata
  • Lokalizacja:Szczecin
  • Postów:4191
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ę.


Pozdrawiam.
edytowany 1x, ostatnio: olesio
U3
  • Rejestracja:prawie 13 lat
  • Ostatnio:prawie 2 lata
  • Postów:196
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

Kopiuj
GetWindowThreadProcessId

mi wystarczy?

olesio
  • Rejestracja:około 17 lat
  • Ostatnio:około 3 lata
  • Lokalizacja:Szczecin
  • Postów:4191
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.


Pozdrawiam.
U3
  • Rejestracja:prawie 13 lat
  • Ostatnio:prawie 2 lata
  • Postów:196
0

Wykombinowałem to w ten sposób:

Kopiuj
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.

flowCRANE
Moderator Delphi/Pascal
  • Rejestracja:ponad 13 lat
  • Ostatnio:około 3 godziny
  • Lokalizacja:Tuchów
  • Postów:12171
0

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

Kopiuj
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ż):

Kopiuj
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.


Pracuję nad własną, arcade'ową, docelowo komercyjną grą z gatunku action/adventure w stylu retro (pixel art), programując silnik i powłokę gry od zupełnych podstaw, przy użyciu Free Pascala i SDL3. Więcej informacji znajdziesz na moim mikroblogu.
edytowany 7x, ostatnio: flowCRANE
olesio
  • Rejestracja:około 17 lat
  • Ostatnio:około 3 lata
  • Lokalizacja:Szczecin
  • Postów:4191
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.


Pozdrawiam.
flowCRANE
To co podałem, zapisane jest na kształt używania funkcji FindFirst i FindNext - po prostu najprościej i najkrócej jest użyć do tego celu pętli repeat i jednego warunku, bez dodatkowych zmiennych; Podobnie ze zmienną PName - w odróżnieniu od cplusplusowatego return, do ukrytego Result można sobie coś wrzucić, by później z tego skorzystać; To zwykła zmienna, więc można śmiało z niej korzystać;
flowCRANE
Moderator Delphi/Pascal
  • Rejestracja:ponad 13 lat
  • Ostatnio:około 3 godziny
  • Lokalizacja:Tuchów
  • Postów:12171
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).


Pracuję nad własną, arcade'ową, docelowo komercyjną grą z gatunku action/adventure w stylu retro (pixel art), programując silnik i powłokę gry od zupełnych podstaw, przy użyciu Free Pascala i SDL3. Więcej informacji znajdziesz na moim mikroblogu.
edytowany 3x, ostatnio: flowCRANE
U3
  • Rejestracja:prawie 13 lat
  • Ostatnio:prawie 2 lata
  • Postów:196
0

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

U3
  • Rejestracja:prawie 13 lat
  • Ostatnio:prawie 2 lata
  • Postów:196
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.

olesio
  • Rejestracja:około 17 lat
  • Ostatnio:około 3 lata
  • Lokalizacja:Szczecin
  • Postów:4191
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.


Pozdrawiam.
flowCRANE
Ja jestem tego zdania, że zrobić można wszystko, jednak niektóre rzeczy są po prostu zbyt trudne aby je ogarnąć; Trzeba więc sporo czytać i kombinować, aby znaleźć rozwiązanie, a nie zawsze chce się lub opłaca się;
olesio
Nie pamiętam czy próbowałem Globalny Hook na CreatePopupMenu czy tam TrackPopupMenu. Ale zdaje się mi, że tak. I też nie pomogło. Może to względy bezpieczeństwa uniemożliwiają takie modyfikacje.
flowCRANE
Na pewno jakieś ograniczenia istnieją, bo inaczej łatwo można by wpływać na działanie aplikacji; Ale jak to mówią, nie ma rzeczy niemożliwych - ogranicza nas jedynie brak wiedzy i umiejętności :)

Zarejestruj się i dołącz do największej społeczności programistów w Polsce.

Otrzymaj wsparcie, dziel się wiedzą i rozwijaj swoje umiejętności z najlepszymi.