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

.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%)均无异常

代码示例

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.20 10:27:24