You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

AvalonDock(Dirkster版本):在ILayoutUpdateStrategy中设置浮动LayoutDocument至鼠标光标位置遇多显示器坐标匹配问题

AvalonDock(Dirkster版本):在ILayoutUpdateStrategy中设置浮动LayoutDocument至鼠标光标位置遇多显示器坐标匹配问题

我太懂你这种踩坐标坑的崩溃感了——AvalonDock(Dirkster版)的浮动窗口坐标逻辑和Windows系统的虚拟桌面坐标完全不是一套体系,多显示器分辨率不一样的时候,错位简直离谱。

你之前的思路其实没毛病:通过FloatingWidth/FloatingHeight/FloatingLeft/FloatingTop来定义窗口大小和位置,但核心矛盾点你也摸准了:

  • Windows的Cursor.Position返回的是虚拟桌面坐标:把所有显示器拼成一个大画布的全局坐标,不管每个显示器实际分辨率多少
  • 而AvalonDock的FloatingLeft/FloatingTop用的是单显示器的绝对物理像素坐标:以目标显示器左上角为原点的本地坐标

这就导致你直接赋值后,窗口会跑到完全不对的位置,尤其是多显示器分辨率差异大的时候。

给你个直接能用的解决方案,分步骤走:


第一步:把光标虚拟坐标转成目标屏幕的相对物理坐标

我们需要先找到光标当前所在的显示器,再计算光标相对于这个显示器左上角的偏移量,这样就能和AvalonDock的坐标体系对齐了。

代码示例(记得先引用System.Windows.Forms程序集):

int floatingWindowWidth = 500;
int floatingWindowHeight = 300;

// 1. 获取光标当前的虚拟坐标
var cursorWinPoint = new System.Drawing.Point(Cursor.Position.X, Cursor.Position.Y);
// 2. 找到光标所在的显示器
var targetScreen = System.Windows.Forms.Screen.FromPoint(cursorWinPoint);
// 3. 计算光标相对于目标显示器左上角的偏移量(这就是AvalonDock能识别的坐标基准)
var relativeX = cursorWinPoint.X - targetScreen.Bounds.X;
var relativeY = cursorWinPoint.Y - targetScreen.Bounds.Y;

// 4. 让窗口中心对准光标,赋值给LayoutDocument
layoutDocument.FloatingLeft = relativeX - floatingWindowWidth / 2;
layoutDocument.FloatingTop = relativeY - floatingWindowHeight / 2;
layoutDocument.FloatingWidth = floatingWindowWidth;
layoutDocument.FloatingHeight = floatingWindowHeight;

第二步:(可选但重要)适配高DPI显示器

如果你的显示器开了DPI缩放(比如125%、150%),直接用物理像素会导致窗口大小/位置还是有偏差,这时候需要把物理坐标转换成WPF的设备独立像素(DIP):

// 先拿到当前窗口的DPI缩放比例(如果ILayoutUpdateStrategy里拿不到MainWindow,可以用LayoutDocument对应的Visual)
var mainWindow = Application.Current.MainWindow;
var dpiScale = VisualTreeHelper.GetDpi(mainWindow);
var scaleX = dpiScale.DpiScaleX;
var scaleY = dpiScale.DpiScaleY;

// 把物理坐标和大小转换成DIP后再赋值
layoutDocument.FloatingLeft = (relativeX - floatingWindowWidth / 2) / scaleX;
layoutDocument.FloatingTop = (relativeY - floatingWindowHeight / 2) / scaleY;
layoutDocument.FloatingWidth = floatingWindowWidth / scaleX;
layoutDocument.FloatingHeight = floatingWindowHeight / scaleY;

额外优化:防止窗口超出屏幕边界

如果光标太靠近屏幕边缘,窗口可能会被切到屏幕外面,可以加个简单的边界判断:

// 确保窗口左边界不超出屏幕
layoutDocument.FloatingLeft = Math.Max(0, layoutDocument.FloatingLeft);
// 确保窗口上边界不超出屏幕
layoutDocument.FloatingTop = Math.Max(0, layoutDocument.FloatingTop);
// 确保窗口右边界不超出屏幕
layoutDocument.FloatingLeft = Math.Min(targetScreen.Bounds.Width - floatingWindowWidth, layoutDocument.FloatingLeft);
// 确保窗口下边界不超出屏幕
layoutDocument.FloatingTop = Math.Min(targetScreen.Bounds.Height - floatingWindowHeight, layoutDocument.FloatingTop);

这样调整后,浮动窗口就能精准地出现在光标位置,不管你有多少台分辨率不一样的显示器,都不会再错位了。

备注:内容来源于stack exchange,提问作者niyou

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.15 12:23:07