2009-01-14 24 views
16

Tôi có một ứng dụng mà chỉ có thể có một thể hiện của chính nó mở tại một thời điểm. Để thực thi điều này, tôi sử dụng mã này:Làm thế nào để tập trung vào một cửa sổ nước ngoài?

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

Nó hoạt động tốt. Tôi cũng muốn nó có thể tập trung vào hình thức của bản sao đã chạy. Đó là, trước khi trở về, tôi muốn đưa ví dụ khác của ứng dụng này vào nền trước.

Tôi làm như thế nào?

Re: SetForegroundWindow:

SetForegroundWindow hoạt động, đến một điểm:

[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; 
       } 
    //... 

này mang lại các cửa sổ để foreground nếu nó không được giảm thiểu. Tuyệt vời. Nếu cửa sổ IS được thu nhỏ, tuy nhiên, nó vẫn được thu nhỏ.

Nó cần phải giảm thiểu.

Solution qua SwitchToThisWindow (trình!):

[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

Kiểm tra xem cửa sổ IsIconic, nếu có thì gọi ShowWindow http://msdn.microsoft.com/en-us/library/ms633527(VS.85).aspx http: // MSDN. microsoft.com/en-us/library/ms633548(VS.85).aspx – cmsjr

Trả lời

10

Tôi gặp vấn đề tương tự và SwitchToThisWindow() đã làm việc tốt nhất cho tôi. Hạn chế duy nhất là bạn phải cài đặt XP sp1. Tôi chơi với SetForegroundWindow, ShowWindow, và cả hai đều có vấn đề kéo cửa sổ vào xem.

+1

Hãy lưu ý, mặc dù, trang MSDN được liên kết cho biết "[Chức năng này không nhằm mục đích sử dụng chung. Nó có thể bị thay đổi hoặc không có sẵn trong các phiên bản Windows tiếp theo.]" –

0

Bạn có thể lấy tài sản MainWindowHandle của đối tượng Process và gửi nó một WM_USER thông điệp mà bạn có thể giải thích là "một số trường hợp khác muốn đưa tôi đến phía trước".

+0

Có thể làm điều đó, mặc dù có vẻ xấu xí. Nó có thể là một lựa chọn tốt nếu SetForegroundWindow không pan ra. –

2

Hoàn Side Note ...

Bạn có thể sử dụng

Process.GetProcessesByName(me.ProcessName) 

thay vì lặp qua tất cả các tiến trình đang chạy trên hệ thống ...

CẬP NHẬT

PInvoke Quy tắc cho loại điều này ...

3

Giống như OP, tôi thấy rằng chỉ riêng SetForegroundWindow là không đủ khi cửa sổ được thu nhỏ. Vì tôi không muốn sử dụng SwitchToThisWindow, tôi đã chọn ShowWindow theo sau là SetForegroundWindow.

Hoạt động tốt cho tôi!

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# tương đương với câu trả lời của Tom Juergens. Làm việc như một sự quyến rũ đối với tôi.

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

làm cách nào để đơn giản hóa việc khởi chạy nhanh ứng dụng đã chạy? – DeerSpotter

Các vấn đề liên quan