.NET Core 6在Windows 11自定义高DPI下OnDoubleClick未触发问题
.NET Core 6 自定义高DPI(≥196%)下OnDoubleClick事件无响应问题
问题描述
- 基于.NET Core 6开发类库组件,已标记
PerMonitorV2和Windows 10兼容性ID - Windows 11环境下的异常表现:
- 自定义DPI设置为195%(187dpi)及以下时,
OnDoubleClick事件可正常触发 - 自定义DPI≥196%(如200%)时,
OnClick事件正常,但OnDoubleClick完全无响应 - 系统预设DPI(100%/125%/150%/175%)均无异常
- 自定义DPI设置为195%(187dpi)及以下时,
代码示例
protected override void OnClick(EventArgs e) { Debug.Print("OnClick triggered"); base.OnClick(e); } protected override void OnDoubleClick(EventArgs e) { Debug.Print("OnDoubleClick triggered"); base.OnDoubleClick(e); }
可能原因分析
这问题大概率是.NET Core 6在PerMonitorV2模式下,对高DPI场景的双击检测阈值缩放处理出了bug:
- Windows判断双击的核心依据是两次点击的像素距离差和时间间隔,默认距离阈值为4个物理像素
- 当自定义DPI超过195%时,.NET的缩放逻辑错误地将物理像素阈值转换为逻辑像素,导致实际允许的双击位置偏差被压得极小——哪怕双击时鼠标轻微移动,都会被判定为超出阈值,直接跳过双击事件
- 预设DPI(最高175%)和195%以内的自定义DPI,缩放后的阈值仍在合理范围,因此双击检测正常
解决方案
1. 手动覆盖双击距离阈值
通过P/Invoke调用Windows API,直接设置当前窗口的双击检测距离阈值,绕过.NET的错误缩放逻辑:
using System.Runtime.InteropServices; public class CustomControl : Control { [DllImport("user32.dll", SetLastError = true)] private static extern bool SetDoubleClickSize(IntPtr hWnd, int cx, int cy); public CustomControl() { // 初始化后设置双击阈值为8物理像素(可根据高DPI场景调整) SetDoubleClickSize(this.Handle, 8, 8); } protected override void OnClick(EventArgs e) { Debug.Print("OnClick triggered"); base.OnClick(e); } protected override void OnDoubleClick(EventArgs e) { Debug.Print("OnDoubleClick triggered"); base.OnDoubleClick(e); } }
2. 自定义双击检测逻辑
如果修改系统阈值不可行,可在OnClick事件中自行实现双击检测逻辑:
private DateTime _lastClickTime; private Point _lastClickLocation; // 双击时间间隔(默认Windows为500ms,可按需调整) private const int DoubleClickInterval = 500; // 双击物理像素距离阈值 private const int DoubleClickPixelThreshold = 8; protected override void OnClick(EventArgs e) { Debug.Print("OnClick triggered"); var currentTime = DateTime.Now; var currentLocation = this.PointToClient(MousePosition); // 转换为适配当前DPI的逻辑像素阈值 var scaledThreshold = (int)(DoubleClickPixelThreshold * (this.DeviceDpi / 96.0)); if ((currentTime - _lastClickTime).TotalMilliseconds <= DoubleClickInterval && Math.Abs(currentLocation.X - _lastClickLocation.X) <= scaledThreshold && Math.Abs(currentLocation.Y - _lastClickLocation.Y) <= scaledThreshold) { // 触发双击事件 Debug.Print("Custom OnDoubleClick triggered"); OnDoubleClick(e); } _lastClickTime = currentTime; _lastClickLocation = currentLocation; base.OnClick(e); } protected override void OnDoubleClick(EventArgs e) { Debug.Print("OnDoubleClick triggered"); base.OnDoubleClick(e); }
3. 升级.NET版本
该问题可能是.NET Core 6的高DPI兼容性bug,尝试升级到.NET Core 6的最新补丁版本,或迁移到.NET 7/8——新版本对PerMonitorV2模式的支持更为完善。
内容的提问来源于stack exchange,提问作者Jonney
相关产品推荐
相关产品推荐

