单击数值调节控件一次却触发两次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
相关产品推荐
相关产品推荐

