dotnet 读 WPF 源代码 Popup 的 StaysOpen 为 false 将会吃掉其他窗口的首次激活

本文主要是介绍dotnet 读 WPF 源代码 Popup 的 StaysOpen 为 false 将会吃掉其他窗口的首次激活,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

在 WPF 中,使用 Popup 控件,可以设置 StaysOpen 属性来控制是否在 Popup 失去焦点时,也就是点击界面空白处,自动收起 Popup 控件。但如果有两个窗口,在设置 Popup 控件的 StaysOpen 属性为 false 那么将会吃掉在点击其他窗口的第一次交互,如鼠标点击或触摸点击时将不会让本进程的其他窗口 Activate 激活

在 WPF 中,通过 Popup 控件可以方便设置浮出的窗口,本质上 Popup 控件也是一个窗口,只是这是一个特殊的窗口。但是在使用 Popup 控件时,如果通过设置 Popup 控件的 StaysOpen 属性为 false 的方式让 Popup 在点击非 Popup 范围内,包括点击窗口其他空白部分,或者点击其他应用程序或桌面等,自动收起。那么 Popup 将会在点击本进程内的其他窗口时,点击的交互被 Popup 吃掉,而让其他窗口收不到一次交互

行为如下:

假定有两个窗口,其中一个是 MainWindows 主窗口,另一个是用来承载 Popup 的 Window1 窗口。 其中 Windows1 窗口有一个按钮,点击按钮时将会弹出一个 Popup 控件,代码过于简单,我就不将所有代码全部写在博客。所有代码放在 github 和 gitee 欢迎小伙伴访问

以下是 Windows1 的界面,有一个按钮,和一个 Popup 控件,点击按钮自动弹出 Popup 控件

    <Grid><Button x:Name="OpenPopupButton" HorizontalAlignment="Center" VerticalAlignment="Center"Content="Open Popup" Click="OpenPopupButton_OnClick"></Button><Popup x:Name="Popup" StaysOpen="False" PlacementTarget="{x:Reference OpenPopupButton}"><Grid Background="Gray" Width="100" Height="100"><TextBlock HorizontalAlignment="Center" VerticalAlignment="Center">The popup</TextBlock></Grid></Popup></Grid>  

以下是 Windows1 点击按钮的代码

        private void OpenPopupButton_OnClick(object sender, RoutedEventArgs e){Popup.IsOpen = true;}

在 MainWindow 里,在 Loaded 事件里面弹出 Windows1 请看代码

        public MainWindow(){InitializeComponent();Loaded += MainWindow_Loaded;}private void MainWindow_Loaded(object sender, RoutedEventArgs e){var window1 = new Window1();window1.Show();}

请运行代码,可以看到打开两个窗口,此时如果点击 MainWindows 那么可以让 MainWindows 获取焦点。接下来请点击 Window1 的空白,然后点击 Open Popup 按钮,此时将会弹出 Popup 控件。再点击 MainWindows 的空白,可以看到 MainWindows 只是获取到鼠标按下和抬起事件,但是没有被激活没有获取到焦点,依然焦点是 Windows1 窗口

在 MainWindows 上添加一些代码,这样可以方便在 VisualStudio 的输出窗口里面,看到窗口的各个事件

    public partial class MainWindow : Window{public MainWindow(){InitializeComponent();Loaded += MainWindow_Loaded;MouseDown += MainWindow_MouseDown;MouseUp += MainWindow_MouseUp;Activated += MainWindow_Activated;Deactivated += MainWindow_Deactivated;LostFocus += MainWindow_LostFocus;}private void MainWindow_Loaded(object sender, RoutedEventArgs e){var window1 = new Window1();window1.Show();}private void MainWindow_MouseUp(object sender, MouseButtonEventArgs e){Debug.WriteLine($"MainWindow_MouseUp");}private void MainWindow_MouseDown(object sender, MouseButtonEventArgs e){Debug.WriteLine($"MainWindow_MouseDown");}private void MainWindow_Activated(object sender, EventArgs e){Debug.WriteLine($"MainWindow_Activated");}private void MainWindow_Deactivated(object sender, EventArgs e){Debug.WriteLine($"MainWindow_Deactivated");}private void MainWindow_LostFocus(object sender, RoutedEventArgs e){Debug.WriteLine($"MainWindow_LostFocus");}}

下面来执行以下两个不同的动作,了解一下弹出 Popup 对进程内的其他窗口的行为

动作1的步骤:

  • 运行代码,默认焦点是在 Window1 上
  • 点击 MainWindow 的空白

此时可以看到 VisualStudio 输出的内容如下

MainWindow_Activated
MainWindow_DeactivatedMainWindow_Activated
MainWindow_MouseDown
MainWindow_MouseUp

第一次 MainWindow_Activated 和 MainWindow_Deactivated 是在 MainWindows 的 Loaded 弹出 Window1 而激活和失去焦点的

第二次的 MainWindow_Activated 和鼠标按下和抬起是在点击 MainWindow 的空白,这是符合预期的

动作2的步骤:

  • 运行代码,默认焦点是在 Window1 上
  • 点击 Window1 的 Open Popup 按钮
  • 点击 MainWindow 的空白

此时可以看到 VisualStudio 输出的内容如下

MainWindow_Activated
MainWindow_DeactivatedMainWindow_MouseDown
MainWindow_MouseUp

对比可以了解,在点击 Window1 的 Open Popup 按钮弹出 Popup 控件之后,下一次点击 MainWindow 是不会激活 MainWindow 只是收到鼠标的按下和抬起

那为什么 Popup 会影响进程的其他窗口的行为?下面来阅读 Popup 的源代码

在 Popup 的 OnLostMouseCapture 方法里面,触发的定义如下

        static Popup(){EventManager.RegisterClassHandler(typeof(Popup), Mouse.LostMouseCaptureEvent, new MouseEventHandler(OnLostMouseCapture));// 忽略其他代码}private static void OnLostMouseCapture(object sender, MouseEventArgs e){Popup popup = sender as Popup;if (!popup.StaysOpen){PopupRoot root = popup._popupRoot.Value;// Reestablish capture if an element within us lost capture// (hence we receive the LostCapture routed event) and capture// is not being acquired anywhere else.//// Note we do not reestablish capture if we are losing capture// ourselves.bool reestablishCapture = e.OriginalSource != root && Mouse.Captured == null && MS.Win32.SafeNativeMethods.GetCapture() == IntPtr.Zero;if(reestablishCapture){popup.EstablishPopupCapture();e.Handled = true;}else{// 忽略其他代码}}}

在点击 MainWindow 的空白,将会触发到 Popup 的 OnLostMouseCapture 方法,接着进入 EstablishPopupCapture 方法

        private void EstablishPopupCapture(bool isRestoringCapture=false){if (!_cacheValid[(int)CacheBits.CaptureEngaged] && (_popupRoot.Value != null) &&(!StaysOpen)){IInputElement capturedElement = Mouse.Captured;PopupRoot parentPopupRoot = capturedElement as PopupRoot;if (parentPopupRoot != null){if (isRestoringCapture){// if the other PopupRoot is restoring capture back to this// popup, ignore mouse button events until both buttons have been// released.  Otherwise a mouse click outside a chain of// "nested" popups would dismiss two of them - one on MouseDown// and another on MouseUp.if (Mouse.LeftButton != MouseButtonState.Released ||Mouse.RightButton != MouseButtonState.Released){_cacheValid[(int)CacheBits.IsIgnoringMouseEvents] = true;}}else{// this is a "nested" popup, invoked while another popup is open.// We need to restore capture to the previous popup root when// we're doneParentPopupRootField.SetValue(this, parentPopupRoot);}// in either case, taking capture away from the other PopupRoot is OK.capturedElement = null;}if (capturedElement == null){// When the mouse is not already captured, we will consider the following:// In all cases but Modeless, we want the popup and subtree to receive// mouse events and prevent other elements from receiving those messages.Mouse.Capture(_popupRoot.Value, CaptureMode.SubTree);_cacheValid[(int)CacheBits.CaptureEngaged] = true;}}}

在 EstablishPopupCapture 方法里面重新调用了 Mouse.Capture 将会让本进程内的其他窗口没有被激活

以上是大琛告诉我的,我只是记录的工具人

我搭建了自己的博客 https://blog.lindexi.com/ 欢迎大家访问,里面有很多新的博客。只有在我看到博客写成熟之后才会放在csdn或博客园,但是一旦发布了就不再更新

如果在博客看到有任何不懂的,欢迎交流,我搭建了 dotnet 职业技术学院 欢迎大家加入

如有不方便在博客评论的问题,可以加我 QQ 2844808902 交流

知识共享许可协议
本作品采用知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议进行许可。欢迎转载、使用、重新发布,但务必保留文章署名林德熙(包含链接:http://blog.csdn.net/lindexi_gd ),不得用于商业目的,基于本文修改后的作品务必以相同的许可发布。如有任何疑问,请与我联系。

这篇关于dotnet 读 WPF 源代码 Popup 的 StaysOpen 为 false 将会吃掉其他窗口的首次激活的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/630931

相关文章

SWAP作物生长模型安装教程、数据制备、敏感性分析、气候变化影响、R模型敏感性分析与贝叶斯优化、Fortran源代码分析、气候数据降尺度与变化影响分析

查看原文>>>全流程SWAP农业模型数据制备、敏感性分析及气候变化影响实践技术应用 SWAP模型是由荷兰瓦赫宁根大学开发的先进农作物模型,它综合考虑了土壤-水分-大气以及植被间的相互作用;是一种描述作物生长过程的一种机理性作物生长模型。它不但运用Richard方程,使其能够精确的模拟土壤中水分的运动,而且耦合了WOFOST作物模型使作物的生长描述更为科学。 本文让更多的科研人员和农业工作者

使用JS/Jquery获得父窗口的几个方法(笔记)

<pre name="code" class="javascript">取父窗口的元素方法:$(selector, window.parent.document);那么你取父窗口的父窗口的元素就可以用:$(selector, window.parent.parent.document);如题: $(selector, window.top.document);//获得顶级窗口里面的元素 $(

专题二_滑动窗口_算法专题详细总结

目录 滑动窗口,引入: 滑动窗口,本质:就是同向双指针; 1.⻓度最⼩的⼦数组(medium) 1.解析:给我们一个数组nums,要我们找出最小子数组的和==target,首先想到的就是暴力解法 1)暴力: 2)优化,滑动窗口: 1.进窗口 2.出窗口 3.更新值 2.⽆重复字符的最⻓⼦串(medium) 1)仍然是暴力解法: 2)优化: 进窗口:hash[s[rig

运营版开源代码 多语言跨境商城 跨境电商平台

默认中英双语 后台带翻译接口 支持133种语言自动翻译 支持多商户联盟 一键部署版本 伪静态+后台登陆后缀 源码下载:https://download.csdn.net/download/m0_66047725/89722389 更多资源下载:关注我。

hot100刷题第1-9题,三个专题哈希,双指针,滑动窗口

求满足条件的子数组,一般是前缀和、滑动窗口,经常结合哈希表; 区间操作元素,一般是前缀和、差分数组 数组有序,更大概率会用到二分搜索 目前已经掌握一些基本套路,重零刷起leetcode hot 100, 套路题按套路来,非套路题适当参考gpt解法。 一、梦开始的地方, 两数之和 class Solution:#注意要返回的是数组下标def twoSum(self, nums: Lis

主窗口的设计与开发(二)

主窗口的设计与开发(二) 前言         在上一集当中,我们完成了主窗口的初始化,主窗口包括了左中右三个区域。我们还完成了对左窗口的初始化,左窗口包括了用户头像、会话标签页按钮、好友标签页按钮以及好友申请标签页按钮。对于切换每个标签页,我们还做了初始化信号槽的内容。最后我们将整个MainWidget类设置为单例模式。         那么这一集我们将继续完成主窗口的设计与开发,这一集我

QtC++截图支持窗口获取

介绍 在截图工具中你会发现,接触到窗口后会自动圈出目标窗口,个别强大一点的还能进行元素识别可以自动圈出元素,那么今天简单分析一下QTc++如何获取窗口并圈出当前鼠标下的窗口。 介绍1.如何获取所有窗口2.比较函数3.实现窗口判断 结尾 1.如何获取所有窗口 1.我们需要调用windows接口EnumWindowsProc回调函数来获取所有顶级窗口,需要包含windows.

运行.bat文件,如何在Dos窗口里面得到该文件的路径

把java代码打包成.jar文件,编写一个.bat文件,执行该文件,编译.jar包;(.bat,.jar放在同一个文件夹下) 运行.bat文件,如何在Dos窗口里面得到该文件的路径,并运行.jar文件: echo 当前盘符:%~d0 echo 当前路径:%cd% echo 当前执行命令行:%0 echo 当前bat文件路径:%~dp0 echo 当前bat文件短路径:%~sdp0 nc

WPF入门到跪下 第十三章 3D绘图 - 3D绘图基础

3D绘图基础 四大要点 WPF中的3D绘图涉及4个要点: 视口,用来驻留3D内容3D对象照亮部分或整个3D场景的光源摄像机,提供在3D场景中进行观察的视点 一、视口 要展示3D内容,首先需要一个容器来装载3D内容。在WPF中,这个容器就是Viewport3D(3D视口),它继承自FrameworkElement,因此可以像其他元素那样在XAML中使用。 Viewport3D与其他元素相

类codepen的实现可拖拽窗口demo

首先说下思想 flex或者其他布局方式,实现左右分割布局,主盒子宽度100%,左右布局中包含一个分割条(可在布局容器中,也可以单独定义)为分隔条绑定鼠标点击事件,为document绑定鼠标移动事件和鼠标放开事件,通过监听鼠标移动事件和上一个状态保存下来的鼠标位置作对比,判断当前鼠标移动方向(往左还是往右)然后计算当前鼠标位置和鼠标点击位置的距离,来计算左右容器的变化,然后通过dom的方式设置宽度