![]() |
ShellExecute und Vordergrund
Hallo,
zu ShellExecute gibt es eine Menge Themen. Möglicherweise zu viel, als dass ich meine Lösung finden konnte. Ich habe eine Server-/Client-Anwendung. Üblicher Weise sendet der Server den Clients Pfad + Datei und der Client öffnet das. Es sind meistens OpenOffice-Dateien. Ich benutze daher ShellExecute, weil es mir zu kompliziert ist, in der Registry etc. pp. nach der Verknüpfung für die entsprechenden Dateiendungen zu suchen. Wir haben bei uns aber auch eine TK-Anlage, die Faxe empfängt und diese unglückseeliger Weise als exe-Dateien ablegt. Genau darin besteht mein Problem: Ich lasse den Client Pfad + Namen dieser exe-Dateien zukommen und sie werden über ShellExecute ebenfalls gestartet. Nur leider verschwindet das dann angezeigte Fenster der Fax-Anwendung immer hinter dem Fenster meiner Anwendung und es nervt, dieses über die Taskleiste in den Vordergrund holen zu müssen. Ich halte das für einen Fehler im Programm, was mir aber nicht weiterhilft. Gibt es eine Möglichkeit, dass mit ShellExecute zu machen? Ich habe jetzt mal ganz plmup folgendes probiert, was aber nicht funktioniert:
Delphi-Quellcode:
Wenn ich als Alternative das ForceToFront zuvor aufrufe, dann klappt es. Allerdings habe ich dann das Problem, dass damit das Hauptfenster meiner Applikation ebenfalls im Vordergrund ist, was ich nicht will.
Procedure ForceToFront(Value: HWND);
Var Th1, Th2 : Cardinal; Begin Th1:=GetCurrentThreadId; Th2:=GetWindowThreadProcessId(GetForegroundWindow, nil); AttachThreadInput(Th2, Th1, True); Try SetForegroundWindow(Value); Finally AttachThreadInput(Th2, Th1, False); End; End; Procedure TWFOpen.HandleFiles(Sender: TObject); Var S : String; Done : Boolean; Inst : HInst; Begin Done:=(OpenFiles.Count = 0); While Not Done Do Begin S:=OpenFiles.Strings[0]; // Alternative: // ForceToFront(self.Handle); Inst:=ShellExecuteA(self.Handle, 'open', PChar(S), nil, nil, SW_SHOWDEFAULT); ForceToFront(Inst); OpenFiles.Delete(0); Done:=(OpenFiles.Count = 0); End; End; Ich habe auch schon herausgefunden, dass Inst nicht dasselbe wie das Fensterhandle ist und es schon deshalb nicht funktionieren kann. Allerdings könnte man meine Frage daher ggf. auch so umformulieren: Wie komme ich über das von ShellExecute zurückgegebene HInst an das Handle des Fensters heran? Gruß, Alex |
AW: ShellExecute und Vordergrund
Zitat:
Nimm entweder CreateProcess oder ShellexecuteEx. |
AW: ShellExecute und Vordergrund
Zitat:
Delphi-Quellcode:
Wenn ich das richtig verstehe, dann habe ich jetzt die Process-ID. Wie komme ich aber an das Fenster-Handle ran, damit ich mit den mir bekannten Funktionen das Fenster in den Vordergrund zwingen kann?
procedure TForm1.Memo1Click(Sender: TObject);
var ShExecInfo : SHELLEXECUTEINFO; begin FillChar(ShExecInfo, SizeOf(SHELLEXECUTEINFO), 0); ShExecInfo.cbSize:=SizeOf(SHELLEXECUTEINFO); ShExecInfo.fMask:= SEE_MASK_NOCLOSEPROCESS; ShExecInfo.Wnd:= self.Handle; ShExecInfo.lpVerb:='open'; ShExecInfo.lpFile:=PChar('calc.exe'); ShExecInfo.nShow:= SW_NORMAL Or SW_SHOWDEFAULT; ShellExecuteEx(@ShExecInfo); Memo1.Lines.Append('ShellExecuteEx:' + #09 + IntToStr(ShExecInfo.hProcess)); end;
Delphi-Quellcode:
, wie man anhand
ShExecInfo.Wnd
![]() ![]()
Delphi-Quellcode:
) erhalte ich auch immer nur 0.
function GetWndHandle(ProcessId: DWORD): HWND;
Wenn ich ![]()
Delphi-Quellcode:
herausbekommen. Wenn dann eine der ermittelten mit
GetWindowThreadProcessId()
Delphi-Quellcode:
übereinstimmt, habe ich mein Handle? Kann mir da bitte, bitte jemand mal Code oder einen Links posten? Ich habe bereits mehrere Themen dazu durchgelesen, steige aber nicht wirklich dahinter, wie ich
ShExecInfo.hProcess
Delphi-Quellcode:
verwenden muss. Ich habe zwar Code gefunden, wie man Fenster schließen kann, schaffe es aber nicht, den so umzustellen, dass ich stattdessen das Handle erhalte...
EnumWindows
Wenn ich die Themen hier richtig verstanden habe, muss ich dann am Schluss auch noch
Delphi-Quellcode:
aufrufen, oder?
CloseHandle(ShExecInfo.hProcess);
Gruß, Alex |
AW: ShellExecute und Vordergrund
Ich habe mich bemüht, mich
![]()
Delphi-Quellcode:
FindHandle bleibt aber immer 0. Was mache ich denn nun wieder verkehrt?
Function FindHandle(Const ProcessId: THandle): HWND;
Function EnumWindowsProc(hWnd: HWND; lParam: LPARAM): BOOL; Stdcall; Begin TList(lParam).Add(Pointer(hWnd)); Result:=True; End; Var hList : TList; PID : DWord; Begin Result:=0; hList:=TList.Create; Try EnumWindows(@EnumWindowsProc, LPARAM(hList)); While (hList.Count > 0) Do Begin If (GetWindowThreadProcessId(HWND(hList.Items[0]), @PID) > 0) And (ProcessId = PID) Then Begin Result:=HWND(hList.Items[0]); Break; End; hList.Delete(0); End; Finally hList.Free; End; End; |
AW: ShellExecute und Vordergrund
Weil du keine ProzessID bekommst. Du bekommst ein Handle auf einen Prozess zurück, welches genauso funktioniert, wie das, was OpenProcess zurückliefert.
Du könntest ja mal versuchen, deinem Programm zu sagen, dass es einfach einen Schritt nach hinten machen soll. Somit müsste automatisch das Fax-Anzeige-Programm nach vorne kommen, oder ist das noch weiter hinten? - Dann mal doch CreateProcess anschauen, weil das viel mehr möglichkeiten bietet und gar nicht so schwer ist. Bernhard |
AW: ShellExecute und Vordergrund
Ich habe dazu ein kurzes Beispiel "heruntergeschlumpert" (d.h. ohne Gewähr, PID ist ein privates DWORD-Feld des Formulars):
Delphi-Quellcode:
[edit] Wobei das zu Problemen führen kann, wenn der Prozess mehrere Fenster geöffnet hat, da ich einfach das zuerst gefundene nach vorn hole und dann aus der Schleife austrete. Vermutlich gibt es einen Weg, das MainForm zu ermitteln, leider kenne ich ihn nicht :( [/edit]
procedure TForm1.Button1Click(Sender: TObject);
var StartupInfo: TStartupInfo; ProcessInfo: TProcessInformation; begin ZeroMemory(@StartupInfo,SizeOf(StartupInfo)); StartupInfo.cb := SizeOf(StartupInfo); StartupInfo.dwFlags := STARTF_USESHOWWINDOW; StartupInfo.wShowWindow := SW_SHOW; if CreateProcess(nil, 'calc.exe', nil, nil, false, CREATE_NEW_CONSOLE or NORMAL_PRIORITY_CLASS, nil, nil, StartupInfo, ProcessInfo) then try PID := ProcessInfo.dwProcessId; finally CloseHandle(ProcessInfo.hProcess); CloseHandle(ProcessInfo.hThread); end; end; function EnumWindowsProc(Wnd: HWnd; aPID: DWORD): BOOL; stdcall; var hProcess: DWORD; begin GetWindowThreadProcessID(Wnd,hProcess); Result := hProcess <> aPID; if not Result then SetForegroundWindow(Wnd); end; procedure TForm1.Button2Click(Sender: TObject); begin if PID <> 0 then EnumWindows(@EnumWindowsProc,PID); end; |
Alle Zeitangaben in WEZ +1. Es ist jetzt 20:50 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz