2009-05-21 29 views
3

活動窗口我有一個C#/。NET應用程序,我想實現以下行爲:確定是否計劃在.NET

我有一個彈出式菜單。每當用戶點擊任何內的的應用程序是而不是彈出式菜單,我想彈出式菜單關閉。

但是,每當用戶不在應用程序中,我不希望發生任何事情。

我試圖通過LostFocus事件來管理這一點,但我無法確定我的應用程序是否爲活動窗口。代碼看起來像這樣。

private void Button_LostFocus(object sender, System.EventArgs e) 
    { 
     if (InActiveWindow()) { 
      CloseMenu() 
     } 
     else { 
      // not in active window, do nothing 
     } 
    } 

我需要知道的是如何實現InActiveWindow()方法。

回答

4

你可以P/Invoke到GetForegroundWindow(),並比較HWND返回到應用程序的form.Handle屬性。

一旦你有了句柄,你也可以P/Invoke GetAncestor()來獲得根擁有者窗口。這應該是應用程序主啓動窗口的句柄,如果這在應用程序中。

1

這似乎是最大的原因,這是棘手的,因爲彈出窗口失去焦點的主要形式被關閉之前,所以活動窗口總是會在該事件發生時的應用。真的,你想知道事件結束後它是否仍然是活動窗口。

你可以建立某種機制,在那裏你記住,一個彈出窗口失去焦點,拋開事實,你將需要關閉它,並在LostFocusDeactivate事件的應用程序的主要形式取消注意告訴你需要關閉它;但問題是您何時會處理該筆記?

我在想這可能會更容易,至少如果彈出窗口是主窗體的直接子窗體(我懷疑您的情況可能會)鉤住主窗體的Focus或甚至Click事件並在打開彈出窗口時關閉彈出窗口(可能通過掃描任何實現了ICloseOnLostFocus接口的子窗體列表,以便彈出窗口有機會參與決策並執行其他任何需要的操作)。

我希望我知道一個更好的文檔解釋什麼是所有這些事件實際上意味着,他們是如何與尊重測序彼此,MSDN葉在描述他們很多有待改進。

2

我偶然發現了你的問題在一個項目工作,並根據Reed Copsey's answer同時,我寫了這個簡單的代碼,這似乎把工作做好。

下面的代碼:

Public Class Form1 
    '''<summary> 
    '''Returns a handle to the foreground window. 
    '''</summary> 
    <Runtime.InteropServices.DllImport("user32.dll", SetLastError:=True)> _ 
    Private Shared Function GetForegroundWindow() As IntPtr 
    End Function 

    '''<summary> 
    '''Gets a value indicating whether this instance is foreground window. 
    '''</summary> 
    '''<value> 
    '''<c>true</c> if this is the foreground window; otherwise, <c>false</c>. 
    '''</value> 
    Private ReadOnly Property IsForegroundWindow As Boolean 
     Get 
      Dim foreWnd = GetForegroundWindow() 
      Return ((From f In Me.MdiChildren Select f.Handle).Union(
        From f In Me.OwnedForms Select f.Handle).Union(
        {Me.Handle})).Contains(foreWnd) 
     End Get 
    End Property 
End Class 

我沒有太多的時間來將其轉換爲C#,因爲我在2天內處理的項目加上一個期限,但我相信你可以迅速做轉換。

這裏是VB.NET代碼的C#版本:

public partial class Form1 : Form 
{ 
    public Form1() 
    { 
     InitializeComponent(); 
    } 

    [System.Runtime.InteropServices.DllImport("user32.dll")] 
    private static extern IntPtr GetForegroundWindow(); 

    ///<summary>Gets a value indicating whether this instance is foreground window.</summary> 
    ///<value><c>true</c> if this is the foreground window; otherwise, <c>false</c>.</value> 
    private bool IsForegroundWindow 
    { 
     get 
     { 
      var foreWnd = GetForegroundWindow(); 
      return ((from f in this.MdiChildren select f.Handle) 
       .Union(from f in this.OwnedForms select f.Handle) 
       .Union(new IntPtr[] { this.Handle })).Contains(foreWnd); 
     } 
    } 
}