简体   繁体   English

当用户在作为 ShowDialog 启动的 window 之外单击时显示消息

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

I have Sample Wpf application where I am launching a Window from the Main Window that is launched in full screen.我有示例 Wpf 应用程序,我正在从全屏启动的主 Window 启动 Window。 Whenever the user clicks outside of the child Window thats launched I want to show a messagebox.每当用户在启动的子 Window 之外单击时,我想显示一个消息框。 I actually referred to this post how to close a WPF Dialog Window when the user clicks outside it .我实际上提到了这篇文章如何在用户单击外部时关闭 WPF 对话框 Window

But the problem is the Deactivated in my case only gets raised when the child window is closed in this case.但问题是,在我的情况下,仅当子 window 在这种情况下关闭时才会出现。 Please help how I can achieve this.请帮助我如何实现这一目标。 Edit: Note I want to ShowDialog as I want the child window to be a blocking 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");
        }

Here I'm using the using System.Windows.Input InputManager PreProcessInput event to preview a Mouse input event, filtered by e.StagingItem.Input , generated on a defined element ( Window ).在这里,我使用使用System.Windows.Input InputManager PreProcessInput事件来预览鼠标输入事件,由e.StagingItem.Input过滤,在定义的元素( Window )上生成。

Then, calculate the position of a Mouse Left click with element.RestoreBounds.Contains(element.PointToScreen(e.GetPosition(element))) .然后,使用element.RestoreBounds.Contains(element.PointToScreen(e.GetPosition(element)))计算鼠标左键单击的 position。
If the click is generated outside the element Bounds , the Window shows a message, then closes (or quits the app).如果点击是在元素Bounds之外生成的,则 Window 会显示一条消息,然后关闭(或退出应用程序)。

The Mouse capture is activated using UIElement.CaptureMouse() and released on a MouseDown event with UIElement.ReleaseMouseCapture .使用UIElement.CaptureMouse()激活鼠标捕获并使用UIElement.ReleaseMouseCaptureMouseDown事件上释放。
It's more or less the same as using Mouse.Capture() .它或多或少与使用Mouse.Capture()相同。

Note that you can click on your Window controls, but if you drag the Window using its TitleBar , the MouseUp event is not rised (by default it's eaten).请注意,您可以单击 Window 控件,但如果您使用其TitleBar拖动Window ,则不会触发MouseUp事件(默认情况下它已被吃掉)。
If this is an issue, create a logic that detects whether the mouse event was generated in that area and restore the capture after the MouseDown has completed.如果这是一个问题,请创建一个逻辑来检测是否在该区域中生成了鼠标事件,并在完成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();
    }
}

I found another way with a few steps done.我找到了另一种方法,完成了几个步骤。 You could create an eventhandler of parent inside the child view.. and don't call ShowDialog() just call Dialog()您可以在子视图中创建父事件处理程序。不要调用ShowDialog()只需调用Dialog()

This is the parent window, where you shouldn't click once child window opens.这是父 window,一旦子 window 打开,您不应该单击此处。

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

This is child window, acts as a dialog and prevents user the click on parent.这是子 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);
    }
}

Use利用

w.Show();

Because earlier one is modal dialog ( Showdialog() ), you can not go further until you close it.因为较早的一个是模态对话框( Showdialog() ),所以在关闭它之前,您不能进一步 go 。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM