簡體   English   中英

當用戶在作為 ShowDialog 啟動的 window 之外單擊時顯示消息

[英]Show a message when user clicks outside a window thats launched as ShowDialog

我有示例 Wpf 應用程序,我正在從全屏啟動的主 Window 啟動 Window。 每當用戶在啟動的子 Window 之外單擊時,我想顯示一個消息框。 我實際上提到了這篇文章如何在用戶單擊外部時關閉 WPF 對話框 Window

但問題是,在我的情況下,僅當子 window 在這種情況下關閉時才會出現。 請幫助我如何實現這一目標。 編輯:注意我想 ShowDialog 因為我希望孩子 window 成為阻塞 window。

private void Button_Click(object sender, RoutedEventArgs e)
        {
            Window w = new Window();
            w.Height = 990;
            w.Width = 1840;
            w.MaxHeight = 990;
            w.Width = 1840;
            w.WindowStartupLocation = WindowStartupLocation.Manual;
            w.Top = this.Height - w.Height;
            w.Left = this.Width - w.Width;
            w.Deactivated += W_Deactivated;
            w.ShowDialog();
        }

        private void W_Deactivated(object sender, EventArgs e)
        {
            MessageBox.Show("You clicked out");
        }

在這里,我使用使用System.Windows.Input InputManager PreProcessInput事件來預覽鼠標輸入事件,由e.StagingItem.Input過濾,在定義的元素( Window )上生成。

然后,使用element.RestoreBounds.Contains(element.PointToScreen(e.GetPosition(element)))計算鼠標左鍵單擊的 position。
如果點擊是在元素Bounds之外生成的,則 Window 會顯示一條消息,然后關閉(或退出應用程序)。

使用UIElement.CaptureMouse()激活鼠標捕獲並使用UIElement.ReleaseMouseCaptureMouseDown事件上釋放。
它或多或少與使用Mouse.Capture()相同。

請注意,您可以單擊 Window 控件,但如果您使用其TitleBar拖動Window ,則不會觸發MouseUp事件(默認情況下它已被吃掉)。
如果這是一個問題,請創建一個邏輯來檢測是否在該區域中生成了鼠標事件,並在完成MouseDown后恢復捕獲。

using System.Windows;
using System.Windows.Input;

public partial class YourWindow : Window
{
    MouseCapturePreview MouseCaptureHandler;
    //(...)

    private void Window_Loaded(object sender, RoutedEventArgs e)
    {
        MouseCaptureHandler = new MouseCapturePreview(this);
        //(...)
    }

    public class MouseCapturePreview
    {
        public MouseCapturePreview(Window element)
        {
            InputManager.Current.PreProcessInput += (s, e) => {
                if (e.StagingItem.Input is MouseButtonEventArgs)
                    Handler(s, (MouseButtonEventArgs)e.StagingItem.Input);
            };

            void Handler(object sender, MouseButtonEventArgs e)
            {
                Console.WriteLine("Event Received");
                if (e.LeftButton == MouseButtonState.Pressed) {
                    Console.WriteLine("Mouse Released");
                    element.ReleaseMouseCapture();
                    Mouse.Capture(element);
                    if (!element.RestoreBounds.Contains(element.PointToScreen(e.GetPosition(element))))
                    {
                        Console.WriteLine("Clicked outside");
                        MessageBox.Show("You clicked outside, time to close.");
                        //Application.Current.Shutdown();
                        element.Close();
                    }
                } else {
                    Console.WriteLine("Mouse Captured");
                    element.CaptureMouse();
                }
            }
        }
    }

    private void Window_Activated(object sender, EventArgs e)
    {
        Console.WriteLine("Activated");
        this.CaptureMouse();
    }
}

我找到了另一種方法,完成了幾個步驟。 您可以在子視圖中創建父事件處理程序。不要調用ShowDialog()只需調用Dialog()

這是父 window,一旦子 window 打開,您不應該單擊此處。

public partial class Parent : Window
{
    private void OpenDialog_Clicked(object sender, RoutedEventArgs e)
    {
          Child child = new Child(this);
          child.Show();
    }
}

這是子 window,充當對話框並阻止用戶單擊父級。

public partial class Child : Window
{
    private Parent _parent;

    public Child(Parent parent)
    {
        InitializeComponent();
        _parent = parent;
        parent.PreviewMouseDown += new MouseButtonEventHandler(this.ParentWindow_PreviewMouseDown);       
        this.Closed += new System.EventHandler(this.Window_Closed);         
    }

    // If you click the parent, you get a message and child window will be top most again
    private void ParentWindow_PreviewMouseDown(object sender, MouseButtonEventArgs e)
    {
        MessageBox.Show("na ah");
        this.Topmost = true;
    }

    // If you forget this, you will keep getting that "na ah" message even after closing child window.
    private void Window_Closed(object sender, EventArgs e)
    {
        _parent.PreviewMouseDown -= new MouseButtonEventHandler(ParentWindow_PreviewMouseDown);
    }
}

利用

w.Show();

因為較早的一個是模態對話框( Showdialog() ),所以在關閉它之前,您不能進一步 go 。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM