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

单击数值调节控件一次却触发两次WM_VSCROLL消息的原因

解决Spin控件WM_VSCROLL消息重复触发问题

你的问题根源是:Spin控件点击一次箭头时,会发送两次WM_VSCROLL消息——一次是按下箭头时的滚动操作通知(SB_LINEUP/SB_LINEDOWN),另一次是释放鼠标时的滚动结束通知(SB_ENDSCROLL)。你的代码没有区分这两种消息,导致每次点击都执行了两次取值逻辑。

修改方案1:过滤WM_VSCROLL的滚动码

只处理实际触发数值变化的滚动操作消息,忽略结束通知:

case WM_VSCROLL:
{
    UINT scrollCode = LOWORD(wParam);
    // 仅处理上/下箭头的滚动操作,跳过结束滚动的消息
    if (scrollCode != SB_LINEUP && scrollCode != SB_LINEDOWN) {
        return TRUE;
    }

    switch (GetDlgCtrlID((HWND)lParam)) {
    case JOB_SPIN:
    {
        UINT spin_pos = SendDlgItemMessage(hDlg, JOB_SPIN, UDM_GETPOS32, 0, 0);
        OutputDebugString(Mem->ToString(spin_pos).c_str());
    }
    break; // 避免case穿透,必须添加
    }
    return TRUE;
}

更优方案:改用UDN_DELTAPOS通知

WM_VSCROLL是滚动条通用消息,Spin控件有专门的数值变化通知UDN_DELTAPOS,在WM_NOTIFY消息中处理更准确,不会出现重复触发:

case WM_NOTIFY:
{
    NMHDR* pNMHDR = (NMHDR*)lParam;
    if (pNMHDR->idFrom == JOB_SPIN && pNMHDR->code == UDN_DELTAPOS) {
        // 获取数值变化信息
        NMUPDOWN* pNMUpDown = (NMUPDOWN*)lParam;
        // 直接读取最新值,或者用pNMUpDown->iPos + pNMUpDown->iDelta计算
        UINT spin_pos = SendDlgItemMessage(hDlg, JOB_SPIN, UDM_GETPOS32, 0, 0);
        OutputDebugString(Mem->ToString(spin_pos).c_str());
        return TRUE;
    }
    break;
}

内容的提问来源于stack exchange,提问作者Lion King

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.12 14:00:15