windows的滚动条使用

背景

在毕业快一年的工作时间中,对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中,滚动条的长度和窗口的长度是成一定比例的。如下公式所控制:
1370668-20190324155631047-471321893.png

  • 对滚动条的消息处理,例如几个典型的消息: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);
}

常用的滚动条消息如下:
1370668-20190324161238682-932226610.jpg

开发过程中遇到的问题

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

  • 如何使滚动条可以拖拽?
    主要是对 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;

转载于:https://www.cnblogs.com/HelloGreen/p/10588565.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是一个 Windows 滚动条的示例代码: ```c++ #include <windows.h> LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam); int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) { // 注册窗口类 WNDCLASS wc = {0}; wc.lpfnWndProc = WndProc; wc.hInstance = hInstance; wc.hCursor = LoadCursor(NULL, IDC_ARROW); wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1); wc.lpszClassName = TEXT("ScrollDemo"); RegisterClass(&wc); // 创建窗口 HWND hwnd = CreateWindow(TEXT("ScrollDemo"), TEXT("Scroll Demo"), WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, 400, 300, NULL, NULL, hInstance, NULL); // 显示窗口 ShowWindow(hwnd, nCmdShow); UpdateWindow(hwnd); // 消息循环 MSG msg; while (GetMessage(&msg, NULL, 0, 0)) { TranslateMessage(&msg); DispatchMessage(&msg); } return (int)msg.wParam; } LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { static int yPos; static SCROLLINFO si = {0}; si.cbSize = sizeof(si); si.fMask = SIF_RANGE | SIF_POS | SIF_PAGE | SIF_TRACKPOS; si.nMin = 0; si.nMax = 1000; si.nPos = 0; si.nPage = 100; switch (msg) { case WM_CREATE: SetScrollInfo(hwnd, SB_VERT, &si, TRUE); break; case WM_VSCROLL: switch (LOWORD(wParam)) { case SB_LINEUP: yPos = si.nPos - 10; break; case SB_LINEDOWN: yPos = si.nPos + 10; break; case SB_PAGEUP: yPos = si.nPos - si.nPage; break; case SB_PAGEDOWN: yPos = si.nPos + si.nPage; break; case SB_THUMBTRACK: yPos = HIWORD(wParam); break; default: break; } yPos = max(0, yPos); yPos = min(si.nMax - (int)si.nPage + 1, yPos); if (yPos != si.nPos) { si.nPos = yPos; SetScrollInfo(hwnd, SB_VERT, &si, TRUE); ScrollWindow(hwnd, 0, -(si.nPos - yPos), NULL, NULL); } break; case WM_PAINT: { PAINTSTRUCT ps; HDC hdc = BeginPaint(hwnd, &ps); RECT rc; GetClientRect(hwnd, &rc); for (int i = 0; i < 100; i++) { TCHAR buf[16]; wsprintf(buf, TEXT("%d"), i); TextOut(hdc, rc.left + 10, rc.top + i * 20 - si.nPos, buf, lstrlen(buf)); } EndPaint(hwnd, &ps); } break; case WM_DESTROY: PostQuitMessage(0); break; default: return DefWindowProc(hwnd, msg, wParam, lParam); } return 0; }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值