C# 监听窗口分辨率/DPI变更
当程序运行,窗口已经加载后,如果修改屏幕分辨率,会影响窗口的正常显示。
举个案例:
悬浮窗口,显示在屏幕右下角。当分辨率、文本显示比例变更后,窗口位置可能会超出屏幕范围。
所以当屏幕变更时,我们需要知道准确的时机,然后针对的处理。
通过窗口消息监听屏幕显示变更
对窗口添加钩子
1 var windowInteropHelper = new WindowInteropHelper(this);
2 var hwnd = windowInteropHelper.Handle;
3 HwndSource source = HwndSource.FromHwnd(hwnd);
4 source?.AddHook(Hook);
对窗口消息添加处理
1 private const int WmDisplayChange = 0x007e;
2 private IntPtr Hook(IntPtr hwnd, int msg, IntPtr wparam, IntPtr lparam, ref bool handled)
3 {
4 if (msg == WmDisplayChange)
5 {
6 SetLocation();
7 }
8 return IntPtr.Zero;
9 }
“0x007e”是屏幕分辨率以及文本显示比例变更对应的消息标识。
“0x02E0”是文本显示比例变更的消息标识。这个标识更具体,但需要在程序未开启DPI感知后,才会收到0x02E0消息。
通过系统事件监听屏幕显示变更
上面通过钩子来判断相应的窗口消息,其实也有系统事件封装了这类的处理:
1 public MainWindow()
2 {
3 InitializeComponent();
4 Microsoft.Win32.SystemEvents.DisplaySettingsChanged += SystemEvents_DisplaySettingsChanged;
5 }
6 private void SystemEvents_DisplaySettingsChanged(object sender, EventArgs e)
7 {
8
9 }
屏幕变更时,回调事件参数如下:

这个系统静态事件和窗口消息是一样的,触发次数和时机一样。调试发现触发顺序:窗口消息->系统静态事件。
因为这个事件没有任何实际的数据,所以只能通过其它方式获取DPI。
更新窗口位置
屏幕显示变更的时机有了,可以根据时间添加相应的操作:
1 private void SetLocation()
2 {
3 var dpiForWindow = GetDpiForWindow(new WindowInteropHelper(this).Handle);
4 var windowRatio = (double)dpiForWindow / 96.0;
5
6 var intPtr = new WindowInteropHelper(this).Handle;//获取当前窗口的句柄
7 var screen = Screen.FromHandle(intPtr);//获取当前屏幕
8 var locationX = (screen.Bounds.Width - 300) / windowRatio;
9 var locationY = (screen.Bounds.Height - 300) / windowRatio;
10 Left = locationX;
11 Top = locationY;
12 }
获取对应屏幕的DPI信息,并转换成WPF的DPI比例,计算出窗口的最新位置。

其它的获取方式,可以见:C# 获取当前屏幕DPI - 唐宋元明清2188 - 博客园 (cnblogs.com)
程序开启DPI感知
如果你通过上面代码,获取的DPI依旧是1,那应该是没有开启DPI感知,请按如下添加就行了:
true/pm,意思是开启屏幕DPI感知。具体的dpiAware参数介绍,可以了解下毅仔的博客:支持 Windows 10 最新 PerMonitorV2 特性的 WPF 多屏高 DPI 应用开发 - walterlv
参考文章:
- Windows 下的高 DPI 应用开发(UWP / WPF / Windows Forms / Win32) - walterlv
- Windows DPI Awareness for WPF - walterlv
关键字:监听分辨率、分辨率变更
C# 监听窗口分辨率/DPI变更的更多相关文章
- vue项目如何监听窗口变化,达到页面自适应?
[自适应]向来是前端工程师需要解决的一大问题--即便作为当今非常火热的vue框架,也无法摆脱--虽然elementui.iview等开源UI组件库层出不穷,但官方库毕竟不可能满足全部需求,因此我们可以 ...
- Java面板Panel的使用,监听窗口关闭事件
面板Panel的使用 待解决问题: 1.设计模式:适配器模式 2.frame.setLayout(null); package GUI; import javax.swing.*; import ja ...
- vue 中监听窗口发生变化,触发监听事件, window.onresize && window.addEventListener('resize',fn) ,window.onresize无效的处理方式
// 开始这样写,不执行 window.onresize = function() { console.log('窗口发生变化') } // 改成window监听事件 window.addEventL ...
- React监听窗口变化事件
功能说明:本例子采用MUI table组件 + React实现. 需求描述:固定表头,列表高度随浏览器窗口的改变而改变.(本例中当窗口高度小于472像素后,便不作限制) 实现简介:1.监听浏览器窗口, ...
- 第35天学习打卡(输入框 TextField监听 简易计算器,组合+内部类回顾复习 画笔 鼠标监听 窗口监听 键盘监听)
1.输入框 TextField监听 package com.kuang.lesson02; import java.awt.*; import java.awt.event.ActionEven ...
- js判断是否安装某个android app,没有安装下载该应用(websocket通信,监听窗口失去焦点事件)
现在经常有写场景需要提示用户下载app, 但是如果用户已经安装,我们希望是直接打开app. 实际上,js是没有判断app是否已经安装的方法的,我们只能曲线救国. 首先,我们需要有call起app的sc ...
- Python窗口学习之监听窗口变化触发函数
在窗口大小发生变化后,往往组件也需要调整 代码: #空间适应屏幕 def window_resiz(self,event=None): print(window.winfo_height()) pri ...
- openlayers 3监听地图分辨率变化事件
map.getView().on('change:resolution',checkZoom);//checkZoom为调用的函数 function checkZoom() { // alert(&q ...
- js 监听窗口变化
window.onresize = function () {.....}jquery $(window).resize(function)
随机推荐
- Ubuntu系统Root用户无法登录解决办法
默认 系统 root 登录 图形界面,出现 登录失败.解决方法如下: 1,登录普通用户, 打开终端执行命令, 使用su root或sudo -i切换到root用户(必须) su root 按照提示输入 ...
- 持续集成环境(4)-Jenkins凭证管理
凭据可以用来存储需要密文保护的数据库密码.Gitlab密码信息.Docker私有仓库密码等,以便 Jenkins可以和这些第三方的应用进行交互. 安装Credentials Binding插件 要在J ...
- ELK集群基础环境初始化
集群基础环境初始化 1.准备虚拟机 192.168.1.7 192.168.1.6192.168.1.183 2.切换为国内centos源 3.修改sshd服务优化 [root@elk01 ~]# s ...
- java中的4种引用和GC Roots
https://juejin.im/post/5d06de9d51882559ee6f4212?utm_source=gold_browser_extension 1.首先,四种引用如下: Final ...
- loadrunner入门(关联)
左右边界:提取第一个id web_reg_save_param_ex( "ParamName=Id", "LB=//OK[ ...
- avx
编译选项: CXXFLAGS += -mavx2 #include <immintrin.h> #include <cmath> void reset_xy(int *x, i ...
- 使用Wireshark查看HTTPS中TLS握手过程
通过使用Wireshark抓包分析TLS握手的过程,可以更容易理解和验证TLS协议,本文将先介绍Wireshark解密HTTPS流量的方法,然后分别验证TLS握手过程和TLS会话恢复的过程. 一.使用 ...
- OS基础-四大基本特征
现代计算机操作系统的四大基本特性(并发/共享/虚拟/异步) 1.并发性 1.1.并发与并行区别 并发是指宏观上在一段时间内能同时运行多个程序,而并行则指同一时刻能运行多个指令.并发需要硬件支持,如多流 ...
- modbus通讯协议详解
1.Modbus 协议简介 Modbus协议是一种已广泛应用于当今工业控制领域的通用通讯协议.通过此协议,控制器相互之间.或控制器经由网络(如以太网)可以和其它设备之间进行通信.Modbus协议使用 ...
- 《MySQL是怎样运行的》第三章小结