拓冰建站拓冰建站
首页 / 资讯中心 / 正文

Jot多显示器适配:用屏幕分辨率命名空间防止窗口状态错乱

Jot多显示器适配用屏幕分辨率命名空间防止窗口状态错乱【免费下载链接】JotJot is a library for persisting and applying .NET application state.项目地址: https://gitcode.com/gh_mirrors/jot1/JotJot多显示器适配是 .NET 桌面应用开发中容易被忽视、却又直接影响用户体验的环节。Jot 是一款轻量级的 .NET 应用状态持久化库能在窗口关闭时自动保存大小与位置下次启动时精准还原。但如果用户使用多显示器普通的窗口状态保存方案会频繁翻车拔掉外接屏后窗口被恢复到屏幕之外的黑洞里用户甚至找不到它。本文手把手教你用屏幕分辨率命名空间这一招彻底根治多显示器下的窗口状态错乱。多显示器环境下窗口状态为什么容易错乱先看两个最常见的真实场景屏幕被拔掉笔记本合盖或拔掉外接显示器后应用记住了副屏上的坐标。下次启动时副屏已不存在窗口就被恢复到了可见区域之外用户只能靠 AltTab 盲猜窗口位置。分辨率变化从 4K 屏换到 1080p 屏窗口坐标和尺寸超出新屏幕的范围出现窗口过大、超出屏幕边缘等问题。传统方案是把 Left、Top、Width、Height 写死在 .settings 文件里问题在于它完全不感知当前是哪种显示环境。Jot 的解法非常优雅——把屏幕分辨率作为窗口标识的一部分让同一个窗口在不同分辨率下各自维护一套独立的状态。Jot多显示器适配核心原理把分辨率写进 Id 命名空间Jot 中每个被跟踪对象都有一个唯一的存储 Id默认由类型名和窗口名组成。关键在于Id()方法支持传入一个params object[]参数这些参数会被自动ToString()后拼接到 Id 中形成一个命名空间。在TrackingConfiguration的Id方法实现中可以看到命名空间只是简单地拼进字符串[类型] 命名空间 Id当我们把SystemInformation.VirtualScreen.Size虚拟屏幕尺寸传进去后1920x1080 和 2560x1440 两种分辨率下同一个窗口就会被 Jot 当作两个不同的对象分别保存状态。切换分辨率时自动读取对应的一套配置互不干扰。1920x1080 → [MainWindow]1920x1080.MainWindow.json 2560x1440 → [MainWindow]2560x1440.MainWindow.json即使屏幕被拔掉新会话也会以当前实际分辨率去查数据——查不到就不恢复坐标窗口老老实实出现在屏幕中央绝不会飞到屏幕外面。WPF 窗口多显示器适配最快配置方法WPF 下只需要在启动类中配置一次之后所有窗口实例都能自动享受多显示器适配。完整示例见 Demo/TestWPF/Services.csTracker .ConfigureWindow() // 关键把屏幕分辨率加进 Id 命名空间 .Id(w w.Name, SystemInformation.VirtualScreen.Size) .Properties(w new { w.Top, w.Width, w.Height, w.Left, w.WindowState }) .PersistOn(nameof(Window.Closing)) .StopTrackingOn(nameof(Window.Closing));然后每个窗口只需一行代码即可接入跟踪见 MainWindow.xaml.csServices.Tracker.Track(this);SystemInformation在System.Windows.Forms命名空间下WPF 项目需要手动引用该程序集。WinForms 窗口状态保存比 WPF 多注意两个坑WinForms 场景有两个额外坑Jot 官方示例Demo/TestWinForms/Services.cs给出了完整解法最大化/最小化时不能保存尺寸此时 Top/Left/Width/Height 返回的是虚假值必须用WhenPersistingProperty取消保存。不能在构造函数里恢复位置WinForms 构造后还会覆写 Top/Left因此Track(this)要放到OnLoad中执行。Tracker .ConfigureForm() .Id(f f.Name, SystemInformation.VirtualScreen.Size) // 分辨率命名空间 .Properties(f new { f.Top, f.Width, f.Height, f.Left, f.WindowState }) .PersistOn(nameof(Form.Move), nameof(Form.Resize), nameof(Form.FormClosing)) // 最小化/最大化时不要保存位置和尺寸 .WhenPersistingProperty((f, p) p.Cancel f.WindowState ! FormWindowState.Normal (p.Property nameof(Form.Height) || p.Property nameof(Form.Width) || p.Property nameof(Form.Top) || p.Property nameof(Form.Left))) .StopTrackingOn(nameof(Form.FormClosing)); // 关闭后不再持久化防止保存空值Avalonia 多显示器适配配置技巧Avalonia 中思路一致但屏幕信息需要从Window实例获取而非静态属性并且要把所有屏幕的工作区拼接成命名空间见 README.md 中的 Avalonia 章节var trackerNamespace string.Join(_, Screens.All.Select(s s.WorkingArea.Size.ToString()));另外 Avalonia 还有两个小坑最小化退出会导致下次启动也是最小化最小化时位置会返回负值需要在加载时检测并纠正Position.X -1时恢复初始位置否则窗口可能跑到屏幕外。三张表记住多显示器适配要点框架命名空间来源恢复时机特殊处理WPFSystemInformation.VirtualScreen.Size构造函数无WinFormsSystemInformation.VirtualScreen.SizeOnLoad事件最大化/最小化时取消保存Avalonia所有屏幕工作区拼接构造函数纠正最小化与负坐标结语多显示器下的窗口状态错乱本质是状态没有绑定到产生它的环境。Jot 用屏幕分辨率命名空间这一个巧妙设计就把这个问题化解于无形——不需要写任何if (Screen.AllScreens...)判断逻辑配置一次全应用受益。如果你也想在项目中快速落地这套方案只需两步先通过 NuGet 安装Jotinstall-package Jot再照本文示例在启动类中配置好Id命名空间即可。想让所有窗口自动恢复大小和位置就是这么简单。【免费下载链接】JotJot is a library for persisting and applying .NET application state.项目地址: https://gitcode.com/gh_mirrors/jot1/Jot创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
分享:

看完干货,该让你的企业上线了

免费需求沟通 · 48 小时内出具建站方案 · 河南本地可上门