Toon posts:

[Delphi/WIN32] Window handle opvragen met hProcess*

Pagina: 1
Acties:

Verwijderd

Topicstarter
Met ShellExecuteEX open ik een programma. Nu wil ik controleren of de gemaakte window ook toplevel is en zo niet, dan moet hij top level worden. Helaas heb ik geen window handle maar alleen een hProcess. Hoe kan ik met die hProcess een window handle krijgen? Als ik ga zoeken kom ik continu op EnumWindows uit. Maar dat moet toch wel anders op te lossen zijn?

Ik heb de volgende code in delphi:

Delphi:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
procedure TStartUpProgram.execute;
var
  ShellExInfo: TShellExecuteInfo;
  h : HWND;
  LInput: TLastInputInfo;
  TimeTest : Cardinal;
  sl : TstringList;
begin
  try
    LInput.cbSize := SizeOf(TLastInputInfo);
    GetLastInputInfo(LInput);
    TimeTest := LInput.dwTime;
    FillChar(ShellExInfo, SizeOf(ShellExInfo), 0);
    with ShellExInfo do begin
      cbSize := SizeOf(ShellExInfo);
      fMask := SEE_MASK_FLAG_NO_UI or SEE_MASK_NOCLOSEPROCESS;
      //Wnd := form1.Handle;
      lpFile := PChar(prog);
      nShow := SW_SHOWMAXIMIZED;
    end;
    ShellExecuteEx(@ShellExInfo);
    while (ShellExInfo.HProcess = 0) do begin
      sleep(1);
    end;
    HprocessApp := ShellExInfo.HProcess;
    sl :=TStringList.Create;
    FoundWindow1 := false;
    //sleep(5000);
    HprocessApp := findwindow(nil,'PowerPoint Slide Show - [test.pps]');
    while (foundwindow1 <> true) do begin
      beep;
      sl.Clear;
      enumwindows(@StartAndContinueCode.nextwindow,lparam(sl));
      //EnumChildWindows
      //EnumThreadWindows
    end;
    sl.Free;
    //HprocessApp := GetActiveWindow();
    while (WaitForSingleObject (ShellExInfo.HProcess,100) = WAIT_TIMEOUT) do begin
      SetWindowPos(HprocessApp,HWND_TOPMOST,0,0,screen.Width,screen.Height,0);
      //beep;
      Application.ProcessMessages;
      GetLastInputInfo(LInput);
      if (LInput.dwTime <> TimeTest) then begin
        KillProcess(ShellExInfo.hProcess);
      end;
      if (Application.Terminated) then begin
        Break;
      end;
    end;
    closehandle(ShellExInfo.HProcess);
    BlockForm3Popup := 0;
  except
    BlockForm3Popup := 0;
    exit;
  end;
end;

[ Voor 32% gewijzigd door Verwijderd op 22-04-2005 14:52 ]


Verwijderd

Verwijderd schreef op woensdag 20 april 2005 @ 19:26:
Met ShellExecuteEX open ik een programma. Nu wil ik controleren of de gemaakte window ook toplevel is en zo niet, dan moet hij top level worden. Helaas heb ik geen window handle maar alleen een hProcess. Hoe kan ik met die hProcess een window handle krijgen? Als ik ga zoeken kom ik continu op EnumWindows uit. Maar dat moet toch wel anders op te lossen zijn?
Nee, want niet elk proces hoeft een window te hebben.
Wat je ook zou kunnen doen:
- alle handles van het proces doorlopen en checken of het een window-handle is.
- voordat je de applicatie start een shell hook activeren en dan de window-creatie onderscheppen en daarin de TOP_MOST vlag activeren.
Ik heb de volgende code in delphi:

Delphi:
1
    while WaitForSingleObject(ShellExInfo.HProcess, 800) = WAIT_TIMEOUT do begin
Kijk ook eens naar WaitForInputIdle

Edit:
Ik heb hier nog wat oude code uit een van mijn projecten opgeduikeld.
code:
1
2
3
4
5
6
7
8
9
10
ForeGroundWindow := GetForeGroundWindow;
if (ForeGroundWindow <> GetDesktopWindow) and (ForeGroundWindow <> 0) then
begin
  WindowLong := GetWindowLong(ForeGroundWindow,GWL_STYLE);
  if not ((WindowLong and WS_CHILD) = WS_CHILD) then
  begin

    SetWindowPos(ForeGroundWindow,HWND_TOPMOST,0,0,0,0,SWP_NOMOVE OR SWP_NOSIZE OR SWP_NOOWNERZORDER);
  end;  // if not ((WindowLong and WS_CHILD) = WS_CHILD) then
end;  // if (ForeGroundWindow <> GetDesktopWindow) and (ForeGroundWindow <> 0) then

Het helpt je nog steeds niet met je window-handle, maar wellicht heb je er wat aan...

[ Voor 26% gewijzigd door Verwijderd op 20-04-2005 22:33 ]


  • LordLarry
  • Registratie: Juli 2001
  • Niet online

LordLarry

Aut disce aut discede

PS: HWND_TOPMOST <> Top Level

We adore chaos because we like to restore order - M.C. Escher


  • MrBucket
  • Registratie: Juli 2003
  • Laatst online: 29-10-2022
Verwijderd schreef op woensdag 20 april 2005 @ 19:26:
Hoe kan ik met die hProcess een window handle krijgen? Als ik ga zoeken kom ik continu op EnumWindows uit. Maar dat moet toch wel anders op te lossen zijn?
Bij mijn weten niet, en wel om de volgende redenen:
a) Je kan er geen API-call over vinden :P
b) Een proces kan meerdere windows hebben. Dus een process handle is niet uniek te koppelen aan 1 window handle (vice versa wel, lijkt me).

Dus nee, er zit niks anders op dan alle windows te enumeraten die de gegeven process handle hebben, en de juiste eruit te pikken (in jouw geval ws. maar 1). Trouwens, je moet alleen een callback-functie implementeren - zoveel werk is dat toch niet?

Verwijderd

Topicstarter
Nee, echt veel werk is het niet. Maar ik dacht dat er misschien wel een api call was die specifiek de window handles van een hprocess kon tonen.

Nu moet je telkens de hele lijst doorlopen totdat je je window gevonden hebt. Niet dat ik daar echt wakker van lig. Zolang het maar mogelijk is om het doel te bereiken ;).

At LordLarry:

Het staat er niet helemaal juist inderdaad. De top level window van het process moet bovenaan de z-order staan en de focus hebben. (focus code staat er niet in)

Bedankt in ieder geval. Hoef ik ook niet meer verder te zoeken.

[ Voor 3% gewijzigd door Verwijderd op 21-04-2005 11:26 ]


Verwijderd

Topicstarter
Na wat tests kom ik er nog niet helemaal uit. Uit de code in mijn eerste post krijg ik dus een hProcess. Deze wil ik gaan testen aan de process handle van de windows uit mijn enumWindow functie. Dit doe ik met de volgende code:

Delphi:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
function GetWindowExeName(Handle : THandle) : HWND;
var
  ProcessId: THandle;
begin
 //ProcessId := GetWindowLong(Handle,GWL_HINSTANCE);
 GetWindowThreadProcessId(Handle,ProcessId);
 if (HprocessApp = handle) then begin
   result := Handle;
   FoundWindow := true;
 end else begin
   result := 0;
   FoundWindow := false;
 end;
end;

function NextWindow(wnd : Thandle; list : Tstringlist):boolean;  stdcall;
begin
  HWindowStartedApp := GetWindowExeName(wnd);
  if (HWindowStartedApp <> 0) then begin
    HWindowStartedApp1 := HWindowStartedApp;
    FoundWindow1 := FoundWindow;
    result := false;
    exit;
  end;
  beep;
  result:=true;
end;


Helaas is de waarde die ik uit GetWindowThreadProcessId krijg nooit gelijk aan mijn hprocess. Met alle gevolgen van dien. Dus kennelijk is die GetWindowThreadProcessId functie niet goed en moet ik iets anders gebruiken.

Ik zat zelf aan CreateProcess (daar krijg je een threadID) te denken maar aangezien deze nogal wat moelijkheden met zich meebrengt heb ik liever een andere oplossing. Maar ik zou eigenlijk niet meer weten waar ik naar moet zoeken. Nu dus de hamvraag; wie wel? ;)
Pagina: 1