2009-05-21 3 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, возвращенный в форму заявки. Handle.

Как только у вас есть ручка, вы также можете вызвать P/Invoke GetAncestor(), чтобы получить окно владельца корня. Это должно быть дескриптором основного окна запуска приложения, если оно находится в вашем приложении.

1

Похоже, самая большая причина, по которой это сложно, заключается в том, что всплывающее окно теряет фокус до того, как основная форма деактивирована, поэтому активное окно всегда будет в приложении во время этого события. Действительно, вы хотите узнать, будет ли это все еще активным окно после окончания события.

Вы можете настроить какую-то схему, в которой вы помните, что всплывающее окно теряет фокус, отменит тот факт, что вам нужно будет закрыть его, а в событииили Deactivate событие основной формы приложения отменит примечание, говорит вам, что вам нужно закрыть его; но проблема в том, когда вы будете обрабатывать заметку?

Я думаю, что это может быть проще, по крайней мере, если всплывающее окно является прямым ребенком основной формы (что, я подозреваю, в вашем случае это может быть), чтобы зацепить 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-х дней, но я верю, что вы можете быстро сделайте преобразование.

Здесь C# версия кода VB.NET:

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); 
     } 
    } 
} 
Смежные вопросы