2011-07-16 89 views
2

在標題中很難解釋這一點,如果有人想改變它就沒關係。WPF:在沒有「程序員」干預的情況下關閉應用程序關閉時的輔助窗口

我有一種情況,在WPF中,我爲程序員創建了一個「隱藏」窗口,它是透明的。 我的意思是這個窗口是在靜態構造函數中創建的,隱藏並移動到屏幕之外,它的寬度和高度都是0.這是因爲我使用這個窗口來執行一些互操作,並允許一些處理程序所有的WndProcs都會覆蓋某人可能需要的地方(有一個委託列表處理應該覆蓋WndProc的方法)。我的問題是,當我創建一個WPF項目並啓動它時,如果我關閉主窗口(這不是創建的透明地創建的窗口)給程序員),我想讓我的應用程序關閉。但是,我創建的代碼除了使用Application.Current.Shutdown();

有沒有辦法解決這個問題,而不調用該方法?我想要一種透明的方式,其他程序員甚至不應該注意到(這是一個lib,不應該以這種方式改變工作程序的行爲)。

感謝您的任何建議,在這裏你可以看到一些代碼片段:

由LIB創建的窗口

public class InteropWindow : Window 
{ 
    public HwndSource Source { get; protected set; } 

    private static InteropWindow _Instance; 

    static InteropWindow() 
    { 
     _WndProcs = new LinkedList<WndProcHandler>(); 
     _Instance = new InteropWindow(); 
    } 

    private static WindowInteropHelper _InteropHelper; 
    public static WindowInteropHelper InteropHelper 
    { 
     get 
     { 
      if (_InteropHelper == null) 
      { 
       _InteropHelper = new WindowInteropHelper(_Instance); 
       _InteropHelper.EnsureHandle(); 
      } 
      return _InteropHelper; 
     } 
    } 

    public static IntPtr Handle { get { return InteropHelper.Handle; } } 

    private InteropWindow() 
    { 
     Opacity = 0.0; 
     //We have to "show" the window in order to obtain hwnd to process WndProc messages in WPF 
     Top = -10; 
     Left = -10; 
     Width = 0; 
     Height = 0; 
     WindowStyle = WindowStyle.None; 
     ShowInTaskbar = false; 
     ShowActivated = false; 
     Show(); 
     Hide(); 
    } 

    private static LinkedList<WndProcHandler> _WndProcs; 
    public static void AddWndProcHandler(WndProcHandler handler) 
    { 
     _WndProcs.AddLast(handler); 
    } 
    public static void RemoveWndProcHandler(WndProcHandler handler) 
    { 
     _WndProcs.Remove(handler); 
    } 

    private static IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled) 
    { 
     IntPtr result = IntPtr.Zero; 
     foreach (WndProcHandler handler in _WndProcs) 
     { 
      IntPtr tmp = handler(hwnd, msg, wParam, lParam, ref handled); 
      if (tmp != IntPtr.Zero) 
      { 
       if (result != IntPtr.Zero) 
        throw new InvalidOperationException(string.Format("result should be zero if tmp is non-zero:\nresult: {0}\ntmp: {1}", result.ToInt64().ToString(), tmp.ToInt64().ToString())); 
       result = tmp; 
      } 
     } 
     return result; 
    } 

    protected override void OnSourceInitialized(EventArgs e) 
    { 
     base.OnSourceInitialized(e); 
     Source = PresentationSource.FromVisual(this) as HwndSource; 
     Source.AddHook(WndProc); 
     OnWindowInitialized(null, e); 
    } 

    protected override void OnClosed(EventArgs e) 
    { 
     base.OnClosed(e); 
     if (Source != null) 
      Source.RemoveHook(WndProc); 
     OnWindowClosed(null, e); 
    } 

    private static void OnWindowInitialized(object sender, EventArgs e) 
    { 
     if (WindowInitialized != null) WindowInitialized(sender, e); 
    } 

    private static void OnWindowClosed(object sender, EventArgs e) 
    { 
     if (WindowClosed != null) WindowClosed(sender, e); 
    } 

    public static event EventHandler WindowInitialized; 

    public static event EventHandler WindowClosed; 
} 

使用WPF(從項目創建的基本窗口)創建一個正常的窗口

public partial class MainWindow : Window 
{ 
    public MainWindow() 
    { 
     InitializeComponent(); 
     ExClipboard.ClipboardUpdate += new RoutedEventHandler(ExClipboard_ClipboardUpdate); 
     Closed += new EventHandler(MainWindow_Closed); 
    } 

    private void MainWindow_Closed(object sender, EventArgs e) 
    { 
     //InteropWindow.Dispose(); 
     App.Current.Shutdown(0); 
    } 
} 

更新1:

爲了回答你的答案,我不希望避免程序員使用我的庫進行任何干預,所以理想的解決方案是,在我的庫中我訂閱了一些Application.Exit事件並關閉了我的窗口,顯然我可以不使用Application.Exit是因爲應用程序沒有關閉,因爲我的窗口沒有關閉

也許有一種方法可以計算屬於應用程序的所有窗口嗎?我也可以這樣做

回答

2

這是一個便宜的黑客攻擊,但我認爲這可能會達到你的目標。

在你的lib,您將需要引用XAML依賴(PresentationCore,PresentationFramework,System.Xaml和WindowsBase)

在靜態構造函數的lib中,那麼你可以添加類似

Application.Current.MainWindow.Closed += new EventHandler(MainWindow_Closed); 

static void MainWindow_Closed(object sender, EventArgs e) 
{ 
    Dispose(); 
} 

哪裏配置關閉你的窗口(_Instance.Close()),並處理任何其他清理電話

+0

良好的工作伴侶,你的黑客工作很大,正是我一直在尋找:) –

+0

在應用程序中設置ShutDownMode。 xaml到OnMainWindow關。 –

+0

@JesseSeger這個想法(在這種情況下)是讓它在lib中處理,而不是依賴最終的開發人員干預。爲這個問題提供的其他答案將是通常做到這一點的最佳方式,但不適用於此特定情況。 – fatty

1

從概念上講,唯一想到的是事件消息通知服務,其中第二個窗口正在偵聽或等待消息關閉,第一個窗口發送消息給它將被關閉。這也需要使用MVVM模式。我完全不確定這一點,我也不確定這是否屬於你不讓其他程序員知道的想法。

這裏就可以了博客文章: Sending notifications in WPF MVVM applications

相關問題