当程序运行,窗口已经加载后,如果修改屏幕分辨率,会影响窗口的正常显示。
举个案例:
悬浮窗口,显示在屏幕右下角。当分辨率、文本显示比例变更后,窗口位置可能会超出屏幕范围。
所以当屏幕变更时,我们需要知道准确的时机,然后针对的处理。
对窗口添加钩子
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 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比例,计算出窗口的最新位置。
关键字:监听分辨率、分辨率变更