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

为何无模式对话框中滚动条滑块会恢复至初始位置?

无模式对话框滚动条滑块复位问题解决

问题描述

编写无模式对话框中滚动DIB位图区域的程序时,已创建水平、垂直两个滚动条控件,但拖动滑块后,滑块无法停留在最终位置,会自动恢复到初始位置。

相关代码

创建滚动条的代码

// 创建垂直滚动条
tmphndwindow2 = CreateWindowA(WC_SCROLLBAR, 
                NULL, 
                WS_CHILD | 
                WS_VISIBLE | 
                SBS_VERT,
                409, 
                100, 
                16, 
                500, 
                tmphndwindow, 
                (HMENU)5, 
                GLB_HInstance, 
                NULL);

// 设置垂直滚动条范围
SetScrollRange(tmphndwindow2, 
               SB_VERT, 
               0, 
               500, 
               TRUE);

// 创建水平滚动条
tmphndwindow2 = CreateWindowA(WC_SCROLLBAR, 
                              NULL, 
                              WS_CHILD | 
                              WS_VISIBLE | 
                              SBS_HORZ,
                              8, 
                              601, 
                              400, 
                              16, 
                              tmphndwindow, 
                              (HMENU)6, 
                              GLB_HInstance, 
                              NULL);

// 设置水平滚动条范围
SetScrollRange(tmphndwindow2, 
               SB_HORZ, 
               0, 
               400, 
               TRUE);

注:tmphndwindow为对话框窗口句柄

WM_HSCROLL消息处理代码

// 处理WM_HSCROLL消息
if(tmpmsg == WM_HSCROLL){

  // 获取水平滚动操作类型
  tmpn = (tmpwparam & 0xFFFF);

  // 向右滚动一个单位
  if(tmpn == SB_LINERIGHT){
   tmphscroll = (tmphscroll + 1);
  }

  // 向左滚动一个单位
  if(tmpn == SB_LINELEFT){
   tmphscroll = (tmphscroll - 1);
  }

  // 拖动滑块
  if(tmpn == SB_THUMBTRACK){
   tmphscroll = (tmpwparam >> 16);
  }

  // 获取水平滚动条控件句柄
  tmphndwindow2 = GetDlgItem(GLB_HWndMainDialog, 
                             6);

  // 设置SCROLLINFO结构体参数
  tmpscrollinfo.cbSize = sizeof(SCROLLINFO);
  tmpscrollinfo.fMask = SIF_POS;
  tmpscrollinfo.nPos = tmphscroll;

  // 设置滑块位置
  SetScrollInfo(tmphndwindow2, 
                SB_HORZ, 
                &tmpscrollinfo, 
                TRUE);

  return FALSE;
}

问题分析与解决方法

核心问题

  1. 滚动位置变量未持久化:如果tmphscroll是消息处理函数内的局部变量,每次处理WM_HSCROLL时变量会被重新初始化,导致滑块位置无法保留。
  2. 无边界检查:修改tmphscroll后未限制其在滚动条的合法范围(0到400)内,超出范围时SetScrollInfo会拒绝设置,滑块自动复位到初始位置。
  3. 新旧API混用:SetScrollRange是较旧的API,与SetScrollInfo混用可能导致滚动条状态不一致。

修复步骤

  1. 持久化滚动位置变量:将tmphscroll(垂直滚动对应tmpvscroll)声明为全局变量,或通过SetWindowLongPtr存储为对话框窗口的自定义数据,确保每次消息处理时能读取上一次的位置。
  2. 添加边界检查:修改tmphscroll后,强制将其限制在合法范围内:
// 水平滚动条范围为0-400,处理后修正边界
tmphscroll = max(0, min(tmphscroll, 400));
  1. 统一使用SetScrollInfo初始化:替换SetScrollRange,用SetScrollInfo同时设置滚动条范围和初始位置,确保状态一致:
// 水平滚动条初始化示例
SCROLLINFO si = {0};
si.cbSize = sizeof(SCROLLINFO);
si.fMask = SIF_RANGE | SIF_POS;
si.nMin = 0;
si.nMax = 400;
si.nPos = 0; // 初始位置
SetScrollInfo(tmphndwindow2, SB_HORZ, &si, TRUE);
  1. 完善消息处理:可补充处理SB_PAGELEFT、SB_PAGERIGHT等滚动类型,同时每次设置位置后触发位图重绘,更新显示区域。

内容的提问来源于stack exchange,提问作者Thema Guishard

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.15 22:47:48