欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

windows的滚动条使用

程序员文章站 2024-03-01 11:55:52
...

背景

在毕业快一年的工作时间中,对windows编程的某些特性并不够熟悉,例如滚动条的使用。在一次需求中需要用到滚动条,在开发过程中走了不少弯路,因此需要做一些笔记总结一下学习到的内容。

先推荐几个写的特别好的博客:

Windows编程之滚动条—滚动条消息
C语言Windows程序设计-> 第八天-> 滚动条
三、Windows编程之滚动条—滚动条信息函数

基本滚动条的使用是非常简单的,无法就那么几个步骤

  • 判断是否需要滚动条,并初始化滚动条,比如页面大小等变量。

如: EnableScrollBarCtrlSetScrollInfo等API, SetScrollInfo用于设置滚动条的相关参数, 包括滚动范围的最大值和最小值, 页面大小, 滑块的位置。

  typedef struct tagSCROLLINFO 
  { 
    UINT cbSize ;            //设置为sizeof (SCROLLINFO), 表示该结构的大小
    UINT fMask ;           //要设置或获取的值
    int nMin ;               //滚动条范围的最小值
    int nMax ;                //滚动条范围的最大值
    UINT nPage ;          //页面大小
    int nPos ;               //当前位置 
    int nTrackPos ;           //当前追踪位置 
  }SCROLLINFO;

fMask中我们常用的是 SIF_ALL(是SIF_RANGE、SIF_POS、SIF_PAGE和SIF_TRACKPOS的组合),

在win32中,滚动条的长度和窗口的长度是成一定比例的。如下公式所控制:
windows的滚动条使用

  • 对滚动条的消息处理,例如几个典型的消息:SB_LINEDOWNSB_LINEUPSB_THUMBPOSITIONSB_THUMBTRACK; 以及SB_PAGEDOWN等之类的消息。主要逻辑就是在滚动条移动时,要更新子窗口相对于父窗口的位置(如,调用MoveWindow函数等)。
    鼠标滑轮的消息,在MFC的CWnd窗口中,捕获滑轮消息,转发滚动条消息:
BOOL CxxxxWnd::OnMouseWheel(UINT nFlags, short zDelta, CPoint pt)
{
    if (m_bEnableVScroll)
    {
        if (zDelta > 0)
        {
            PostMessage(WM_VSCROLL, SB_LINEUP, 0);
        }
        else
        {
            PostMessage(WM_VSCROLL, SB_LINEDOWN, 0);
        }
    }

    return __super::OnMouseWheel(nFlags, zDelta, pt);
}

常用的滚动条消息如下:
windows的滚动条使用

开发过程中遇到的问题

  • 带滚动条的窗口的窗口结构
    之前不太晓得带滚动条的窗口的窗口结构,带滚动条的窗口一定是有子窗口的。滑动的时候,改变子窗口的相对位置。参考一张图:
    windows的滚动条使用

  • 如何使滚动条可以拖拽?
    主要是对 SB_THUMBPOSITIONSB_THUMBTRACK消息的处理。当把鼠标的光标放在卷动方块上并按住鼠标键时,您就可以移动卷动方块。这样就产生了带有SB_THUMBTRACKSB_THUMBPOSITION通知码的滚动条消息。在wParam的低字组是SB_THUMBTRACK时,wParam的高字组是使用者在拖动卷动方块时的目前位置。该位置位于卷动列范围的最小值和最大值之间。在wParam的低字组是SB_THUMBPOSITION时,wParam的高字组是使用者释放鼠标键后卷动方块的最终位置。
    case SB_THUMBPOSITION:
    case SB_THUMBTRACK:
    {
        bSuccess = GetScrollInfo(SB_VERT, &si);
        si.fMask = SIF_POS;
        si.nPos = si.nTrackPos;
        bSuccess = SetScrollInfo(SB_VERT, &si);
        //按照成员变量nPos的消息移动子窗口位置即可....
        Invalidate();
    }
        break;