AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Thema durchsuchen
Ansicht
Themen-Optionen

ShellExecute und Vordergrund

Ein Thema von Schwedenbitter · begonnen am 10. Jan 2011 · letzter Beitrag vom 12. Jan 2011
Antwort Antwort
Schwedenbitter

Registriert seit: 22. Mär 2003
Ort: Finsterwalde
622 Beiträge
 
Turbo Delphi für Win32
 
#1

ShellExecute und Vordergrund

  Alt 10. Jan 2011, 14:26
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:
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;
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.

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
Alex Winzer
  Mit Zitat antworten Zitat
Benutzerbild von Luckie
Luckie

Registriert seit: 29. Mai 2002
37.621 Beiträge
 
Delphi 2006 Professional
 
#2

AW: ShellExecute und Vordergrund

  Alt 10. Jan 2011, 15:33
Wie komme ich über das von ShellExecute zurückgegebene HInst an das Handle des Fensters heran?
Shellexecute gibt nur einen Fehlercode zurück nicht mehr und nicht weniger.

Nimm entweder CreateProcess oder ShellexecuteEx.
Michael
Ein Teil meines Codes würde euch verunsichern.
  Mit Zitat antworten Zitat
Schwedenbitter

Registriert seit: 22. Mär 2003
Ort: Finsterwalde
622 Beiträge
 
Turbo Delphi für Win32
 
#3

AW: ShellExecute und Vordergrund

  Alt 11. Jan 2011, 10:06
Nimm entweder CreateProcess oder ShellexecuteEx.
Danke für den Tip. Ich habe das so versucht und ich habe auch schon die DP durchstöbert:
Delphi-Quellcode:
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;
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?

ShExecInfo.Wnd , wie man anhand dieses Posts annehmen sollte, dürfte es nicht sein. Denn bei mir ist das immer 0. Und mit diesem Code (function GetWndHandle(ProcessId: DWORD): HWND; ) erhalte ich auch immer nur 0.
Wenn ich das richtig verstehe, muss ich "nur" die Handles aller Fenster ermitteln, deren Process-IDs mittels GetWindowThreadProcessId() herausbekommen. Wenn dann eine der ermittelten mit ShExecInfo.hProcess ü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 EnumWindows 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...

Wenn ich die Themen hier richtig verstanden habe, muss ich dann am Schluss auch noch CloseHandle(ShExecInfo.hProcess); aufrufen, oder?

Gruß, Alex
Alex Winzer
  Mit Zitat antworten Zitat
Schwedenbitter

Registriert seit: 22. Mär 2003
Ort: Finsterwalde
622 Beiträge
 
Turbo Delphi für Win32
 
#4

AW: ShellExecute und Vordergrund

  Alt 11. Jan 2011, 11:25
Ich habe mich bemüht, mich hieran orientiert und es scheinbar zum Laufen bekommen:
Delphi-Quellcode:
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;
FindHandle bleibt aber immer 0. Was mache ich denn nun wieder verkehrt?
Alex Winzer
  Mit Zitat antworten Zitat
Benutzerbild von rollstuhlfahrer
rollstuhlfahrer

Registriert seit: 1. Aug 2007
Ort: Ludwigshafen am Rhein
1.529 Beiträge
 
Delphi 7 Professional
 
#5

AW: ShellExecute und Vordergrund

  Alt 11. Jan 2011, 15:52
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
Bernhard
Iliacos intra muros peccatur et extra!
  Mit Zitat antworten Zitat
Benutzerbild von DeddyH
DeddyH

Registriert seit: 17. Sep 2006
Ort: Barchfeld
27.540 Beiträge
 
Delphi 11 Alexandria
 
#6

AW: ShellExecute und Vordergrund

  Alt 12. Jan 2011, 08:01
Ich habe dazu ein kurzes Beispiel "heruntergeschlumpert" (d.h. ohne Gewähr, PID ist ein privates DWORD-Feld des Formulars):
Delphi-Quellcode:
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;
[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]
Detlef
"Ich habe Angst vor dem Tag, an dem die Technologie unsere menschlichen Interaktionen übertrumpft. Die Welt wird eine Generation von Idioten bekommen." (Albert Einstein)
Dieser Tag ist längst gekommen

Geändert von DeddyH (12. Jan 2011 um 08:19 Uhr)
  Mit Zitat antworten Zitat
Antwort Antwort


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 02:27 Uhr.
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz