繁体   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