当程序运行,窗口已经加载后,如果修改屏幕分辨率,会影响窗口的正常显示。
举个案例:
悬浮窗口,显示在屏幕右下角。当分辨率、文本显示比例变更后,窗口位置可能会超出屏幕范围。
所以当屏幕变更时,我们需要知道准确的时机,然后针对的处理。
通过窗口消息监听屏幕显示变更
对窗口添加钩子
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”是屏幕分辨率以及文本显示比例变更对应的消息标识。
通过系统事件监听屏幕显示变更
上面通过钩子来判断相应的窗口消息,其实也有系统事件封装了这类的处理:
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 }
屏幕变更时,回调事件参数如下:

这个系统静态事件和窗口消息是一样的,触发次数和时机一样。调试发现触发顺序:窗口消息->系统静态事件。
更新窗口位置
屏幕显示变更的时机有了,可以根据时间添加相应的操作:
1 private void SetLocation()
2 {
3 using (Graphics currentGraphics = Graphics.FromHwnd(new WindowInteropHelper(this).Handle))
4 {
5 double dpixRatioX = currentGraphics.DpiX / 96;
6 double dpixRatioY = currentGraphics.DpiY / 96;
7
8 var intPtr = new WindowInteropHelper(this).Handle;//获取当前窗口的句柄
9 var screen = Screen.FromHandle(intPtr);//获取当前屏幕
10 var locationX = (screen.Bounds.Width - 300) / dpixRatioX;
11 var locationY = (screen.Bounds.Height - 300) / dpixRatioY;
12 Left = locationX;
13 Top = locationY;
14 }
15 }
获取对应屏幕的DPI信息,并转换成WPF的DPI比例,计算出窗口的最新位置。
关键字:监听分辨率、分辨率变更
作者:唐宋元明清2188
出处:http://www.cnblogs.com/kybs0/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须在文章页面给出原文连接,否则保留追究法律责任的权利。