2009-01-14 28 views
16

Ich habe eine Anwendung, die nur eine Instanz von sich selbst geöffnet haben kann. Um dies zu erzwingen, verwende ich diesen Code:Wie fokussiere ich ein fremdes Fenster?

 System.Diagnostics.Process[] myProcesses = System.Diagnostics.Process.GetProcesses(); 
     System.Diagnostics.Process me = System.Diagnostics.Process.GetCurrentProcess(); 
     foreach (System.Diagnostics.Process p in myProcesses) 
     { 
      if (p.ProcessName == me.ProcessName) 
       if (p.Id != me.Id) 
       { 
        //if already running, abort this copy. 
        return; 
       } 
     } 
     //launch the application. 
     //... 

Es funktioniert gut. Ich möchte auch, dass es in der Lage ist, die Form der bereits laufenden Kopie zu fokussieren. Bevor ich zurückkomme, möchte ich die andere Instanz dieser Anwendung in den Vordergrund bringen.

Wie mache ich das?

Re: SetForegroundWindow:

SetForegroundWindow arbeitet, bis zu einem Punkt:

[System.Runtime.InteropServices.DllImport("user32.dll")] 
    public static extern bool SetForegroundWindow(IntPtr hWnd); 

    //... 
       if (p.Id != me.Id) 
       { 
        //if already running, focus it, and then abort this copy. 
        SetForegroundWindow(p.MainWindowHandle); 
        return; 
       } 
    //... 

Dieses aus dem Fenster in den Vordergrund bringt, wenn es nicht minimiert wird. Genial. Wenn das Fenster minimiert ist, bleibt es minimiert.

Es muss nicht minimiert werden.

Lösung über SwitchToThisWindow (Works!):

[System.Runtime.InteropServices.DllImport("user32.dll")] 
    public static extern void SwitchToThisWindow(IntPtr hWnd, bool fAltTab); 

    [STAThread] 
    static void Main() 
    { 
     System.Diagnostics.Process me = System.Diagnostics.Process.GetCurrentProcess(); 
     System.Diagnostics.Process[] myProcesses = System.Diagnostics.Process.GetProcessesByName(me.ProcessName); 
     foreach (System.Diagnostics.Process p in myProcesses) 
     { 
      if (p.Id != me.Id) 
      { 
       SwitchToThisWindow(p.MainWindowHandle, true); 
       return; 
      } 
     } 
     //now go ahead and start our application ;-) 
+1

Überprüfen Sie, ob das Fenster IsIconic, wenn so nennen Showwindow http://msdn.microsoft.com/en-us/library/ms633527(VS.85).aspx http: // msdn. microsoft.com/en-us/library/ms633548(VS.85).aspx – cmsjr

Antwort

10

Ich hatte das gleiche Problem und SwitchToThisWindow() arbeitete das Beste für mich. Die einzige Einschränkung ist, dass Sie XP SP1 installiert haben müssen. Ich spielte mit SetForegroundWindow, ShowWindow, und beide hatten Probleme, das Fenster in den Blick zu ziehen.

+1

Beachten Sie jedoch, dass die verknüpfte MSDN-Seite sagt: „[Diese Funktion ist nicht für den allgemeinen Gebrauch bestimmt. Es verändert oder nicht verfügbar in den folgenden Versionen von Windows werden kann.]“ –

0

Können Sie Mainwindowhandle Eigenschaft des Objekts Process verwenden möchten packen und es eine WM_USER senden eine Nachricht, die du interpretieren kannst als "eine andere Instanz möchte mich an die Front bringen".

+0

Könnte das tun, scheint aber hässlich. Es könnte eine gute Alternative sein, wenn SetForegroundWindow nicht funktioniert. –

2

komplette Randnotiz ...

Sie

verwenden können
Process.GetProcessesByName(me.ProcessName) 

statt Schleifen über alle Prozesse auf dem System laufen ...

UPDATE

PInvoke Regeln für diese Art von Sache ...

3

Wie OP, fand ich, dass SetForegroundWindow allein nicht genug war, wenn das Fenster minimiert wurde. Da ich SwitchToThisWindow nicht verwenden wollte, wählte ich ShowWindow, gefolgt von SetForegroundWindow.

Funktioniert gut für mich!

private const SW_SHOWNORMAL = 1 

<DllImport("user32.dll", SetLastError:=True, CharSet:=CharSet.Auto)> _ 
Private Function ShowWindow(ByVal hwnd As IntPtr, ByVal nCmdShow As integer) As Boolean 
End Function 

<DllImport("user32.dll", SetLastError:=True)> _ 
Private Function SetForegroundWindow(ByVal hwnd As IntPtr) As Boolean 
End Function 

Sub SetForeground() 
    Dim processes As Process() = Process.GetProcessesByName("myprocess") 

    For Each p as Process in processes 
     ShowWindow(p.MainWindowHandle, SW_SHOWNORMAL) 
     SetForegroundWindow(p.MainWindowHandle) 
    Next 
End Sub 
2

C# entspricht der Antwort von Tom Jürgens. Funktioniert wie ein Zauber für mich.

private const int SW_SHOWNORMAL = 1; 

    [DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)] 
    private static extern bool ShowWindow(IntPtr hwnd, int nCmdShow); 


    [DllImport("user32.dll", SetLastError = true)] 
    private static extern bool SetForegroundWindow(IntPtr hwnd); 

    public void SetForeground() 
    { 
     Process[] processes = Process.GetProcessesByName("process name"); 

     foreach (Process p in processes) { 
      ShowWindow(p.MainWindowHandle, SW_SHOWNORMAL); 
      SetForegroundWindow(p.MainWindowHandle); 
     } 
    } 
+0

wie können wir die oben nur den schnellen Start der Anwendung vereinfachen das läuft schon? – DeerSpotter

Verwandte Themen