WPF 获取全局所有窗口的创建显示事件 监控窗口打开
本文将告诉大家如何在 WPF 里面进行全局监控任意的窗口创建显示打开,可以获取到每个 WPF 窗口的打开的时机。如此可以用来辅助定位问题和输出日志
这篇博客是有背景的,老司机告诉我说他的应用不响应鼠标和键盘点击了,于是我和他调查了半天才发现有一个 Dialog 窗口显示出来,导致消息循环被切到了一个 Dialog 窗口里面去了。然而这个 Dialog 窗口是藏起来的,在屏幕上刚好没有能看见他
此时我就好奇了,为什么我的应用就不会存在如此的逗比代码,但是老司机的应用就可能存在如此难以调试的问题。于是我就在自己的应用上写了一个逗比代码,强行弹出一个 Dialog 窗口出来,结果我就发现监控模块告诉了我有一个在白名单之外的窗口弹出了,如果确定这是符合开发预期的,那就需要手动修改白名单。这是一个开发时的辅助机制,用来让开发者不要随便弹出窗口,我又好奇这个监控模块是如何监控到我弹出一个窗口的,学习了监控模块的机制,就写了这个博客
在 WPF 里面,可以通过 EventManager 监听全局的路由事件,刚好窗口创建显示时,将会触发一些路径事件。通过路由事件监听,即可了解是哪个窗口正在准备弹出。于是就可以进行监控窗口创建显示
监听窗口的 SizeChangedEvent 路由事件是比较靠谱的方式,这个有一点点违反开发者的想法,开发者默认想的是使用 LoadedEvent 事件。但是在 WPF 里面做了一些性能优化,如果一个窗口没有 XAML 或者是没有任何代码监听了 Loaded 事件,那将不触发 LoadedEvent 路由事件。因此这里就监听窗口一定会触发的 SizeChangedEvent 事件
代码如下
public App()
{
EventManager.RegisterClassHandler(typeof(Window), Window.LoadedEvent, new RoutedEventHandler(Window_OnLoaded));
EventManager.RegisterClassHandler(typeof(Window), Window.SizeChangedEvent, new RoutedEventHandler(Window_SizeChanged));
}
private void Window_OnLoaded(object sender, RoutedEventArgs e)
{
// 如果窗口没有 XAML 或者没有监听 Loaded 事件,将不会被触发
}
private void Window_SizeChanged(object sender, RoutedEventArgs e)
{
// 所有窗口都会触发
}
窗口创建的时候,将会进入 Window_SizeChanged 事件。通过 sender 参数即可了解是哪个窗口对象被创建,接着就可以方便进行日志或者是提示开发者不要随便创建窗口等
可以自己测试一下代码,例如在 MainWindow 里面再次创建一个空窗口
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
Loaded += MainWindow_Loaded;
}
private void MainWindow_Loaded(object sender, RoutedEventArgs e)
{
var window = new Window();
window.Show();
}
}
运行以上的代码,可以看到 Window_SizeChanged 被进入两次,分别是 MainWindow 和在 MainWindow 里面创建显示的窗口。而 Window_OnLoaded 只会进入一次,在 MainWindow 准备显示时进入
我推荐在自己的项目里面,在 Debug 下加上此机制,至少输出一下窗口显示的日志,方便了解显示了哪些窗口。如果可以的话,也可以加上白名单机制,如果一个窗口是新写的之类的,可以提示开发者阅读必要的文档之后加入到白名单里面。也可以在事件里面对每个窗口注入一些有趣的逻辑,或者是监听窗口的各个事件,输出更多日志,让开发者可以通过日志了解到当前有哪些窗口依然还在显示
这是另一位大佬写的代码,请看 https://gist.github.com/mwisnicki/3104963
WPF 获取全局所有窗口的创建显示事件 监控窗口打开的更多相关文章
- 获取全局上下文(getApplicationContext)_创建Shared Preference工具类_实现自动登录
获取全局上下文(getApplicationContext)_创建Shared Preference工具类_实现自动登录 ===========================获取全局上下文(getA ...
- uCGUI窗口的创建过程分析
一.相关结构体和变量 窗口管理结构体 /* 窗口管理结构体 共30个字节 */ struct WM_Obj { GUI_RECT Rect; //窗口尺寸(x0,y0,x1,y1) 8个字节 GUI_ ...
- Add an Action that Displays a Pop-up Window 添加显示弹出窗口按钮
In this lesson, you will learn how to create an Action that shows a pop-up window. This type of Acti ...
- 有谁知道Delphi中"窗口"的创建过程?
求助:有谁知道Delphi中窗口的创建过程,此“窗口”不仅仅指 TForm 类型, 还包括一般的窗口控件,如TButton,TEdit等等,希望有能够十分详细的运作 过程,比如说CreatPara ...
- system调用命令行命令而不显示命令行窗口
system调用命令行命令而不显示命令行窗口 通常用system调用命令行命令时都会弹出黑底白字的命令行窗口,下面的代码可以不显示弹出的命令行窗口. 代码如下 #pragma comment( lin ...
- Android窗口管理服务WindowManagerService对壁纸窗口(Wallpaper Window)的管理分析
文章转载至CSDN社区罗升阳的安卓之旅,原文地址:http://blog.csdn.net/luoshengyang/article/details/8550820 Android系统中,壁纸窗口和输 ...
- WPF 获取应用的所有窗口
原文:WPF 获取应用的所有窗口 本文告诉大家如何获取应用内的所有窗口,无论这些窗口有没显示 在 WPF 可以通过 Application.Current.Windows 列举应用的所有窗口 fore ...
- WPF 获取元素(Visual)相对于屏幕设备的缩放比例,可用于清晰显示图片
原文:WPF 获取元素(Visual)相对于屏幕设备的缩放比例,可用于清晰显示图片 我们知道,在 WPF 中的坐标单位不是屏幕像素单位,所以如果需要知道某个控件的像素尺寸,以便做一些与屏幕像素尺寸相关 ...
- QT+创建两个不相干的窗口实现一个显示一个不显示
因为两个窗口互不相干,所以需要重新创建一个窗口类subWidget subWidget.cpp文件 #ifndef SUBWIDGET_H #define SUBWIDGET_H #include & ...
- WPF 获取鼠标屏幕位置、窗口位置、控件位置
原文:WPF 获取鼠标屏幕位置.窗口位置.控件位置 public struct POINT { public int X; public int Y; public POINT(int x, int ...
随机推荐
- JavaScript自定义响应式对象
1. 引言 这里的响应式对象是指JavaScript中的变量与HTML中的内容相绑定,变量更新则内容更新,也叫数据绑定 此时不得不说MVVM架构,MVVM架构思想的实现步骤如下: 模型(Model): ...
- TorchV的RAG实践分享(二):基于ElasticSearch的混合检索实战&原理分析
概述 在昨天员外分享的<TorchV的RAG实践分享(1)--RAG的定位.技术选型和RAG技术文章目录>一文中介绍了TorchV的由来,也分享了我们的几个基线产品和应用架构的方向,我们想 ...
- 开发必会系列:hibernate事务
一 事务定义及特性 1.数据库事务的定义:数据库事务(Database Transaction) 是指由一个或多个SQL语句组成的工作单元,这个工作单元中的SQL语句相互依赖,如果有一个SQL语句执 ...
- C# 人脸检测 人脸比对 活体检测 口罩检测 年龄预测 性别预测 眼睛状态检测
基于以下开源软件做了一个Demo GitHub - ViewFaceCore/ViewFaceCore: C# 超简单的离线人脸识别库.( 基于 SeetaFace6 ) 效果 代码 using Sy ...
- java中 YYYY与yyyy 区别
大多数情况下格式日期都是用的SimpleDateFormat,比如说把一个日期格式成"yyyy-MM-dd"的形式. 对于年份来说,大写的Y和小写的y其意义是不同的. y 是Yea ...
- linux安装jdk压缩包版
1.下载压缩包可以选择国内大厂的jdk镜像网站下载速度很快, 比如华为的:https://repo.huaweicloud.com/java/jdk/ 2.查看Linux系统是否有自带的jdk: 输入 ...
- quartus中的时序约束常用方法
quartus中的时序约束常用方法 一.约束操作 quartus中有三种时序约束方法: 1️⃣Timing Setting 2️⃣Wizards/Timing Wizard 3️⃣Assignment ...
- ResNet-RS:谷歌领衔调优ResNet,性能全面超越EfficientNet系列 | 2021 arxiv
论文重新审视了ResNet的结构.训练方法以及缩放策略,提出了性能全面超越EfficientNet的ResNet-RS系列.从实验效果来看性能提升挺高的,值得参考 来源:晓飞的算法工程笔记 公众号 ...
- IPv4地址的结构体与网络字节序
IPv4地址的结构体 /* Fixed-size types, underlying types depend on word size and compiler. */ typedef signed ...
- MySQL联结
创建联结 mysql> SELECT vend_name,prod_name,prod_price FROM vendors,products WHERE vendors.vend_id=pro ...