滚动条(2)

来源:互联网 发布:如何卸载mysql数据库 编辑:程序博客网 时间:2024/05/17 06:42

参考《window程序设计》例子,按code顺序分析,跳过window进入点函数,仅仅除了CreateWindow第三个参数稍有差异。创建窗口:

    hwnd=CreateWindow(szAppName,TEXT("Get System Mertrics No3"),        WS_OVERLAPPEDWINDOW | WS_HSCROLL|WS_VSCROLL,//创建垂直,水平滚动条        CW_USEDEFAULT,CW_USEDEFAULT,        CW_USEDEFAULT,CW_USEDEFAULT,        NULL,NULL,hInstance,NULL);

跳到
窗口处理程序函数:

LRESULT CALLBACK WndProc(HWND hwnd,UINT message,WPARAM wParam,LPARAM lParam);

里面关于滚动条的两个主要函数:

SetScrollInfo(HWND,iBar,SCROLLINFO,bRedraw);GetScrollInfo(HWND,iBar,SCROLLINFO);

之前的SetScrollPos,SetScrollRange,GetScrollPos,GeScrollRange早已过时。但仍然可以使用。
上面的两个函数就可包含之前的几个函数的全部功能,还增加了两个特性。

1.增加了滑块的大小控制。2.通过GetScrollInfo可以取得32位值。
1:有一个计算公式: 卷动方块大小比滚动长度 约等于 页面大小比范围就是说页面的大小和滑块大小成正比。巧合,在SetScrollInfo可以设置页面大小,和它的第三个参数SCROLLINFO有关。   扯到SCROLLINFO,那就详细介绍吧。   两个函数的第三个参数都是它,它是一个结构,定义如下:   typedef struct tagSCROLLINFO   {     UINT cbSize;     UINT fMask;     int nMin;     int nMax;     UINT nPage;     int nPos;     int nTrackPos;     }  SCROLLINFO,*PSCROLLINFO;     就是说可以通过此结构的UINT nPage来设置页面大小

2:GetscrollInfo函数尽管WM_HSCROLL和WM_VSCROLL指出了滚动条消息,却提供了16位数据,而函数SetScrollInfo和GetScrollInfo则提供了32位的滚动数据。因而,当应用程序在处理WM_VSCROLL时,要获得32位滚动条位置的数据时,则要调用GetscrollInfo函数。在WM_HSCROLL或WM_VSROLL消息中SB_THUMBTRACK通知过程中,为了获得32位的滚动盒位置,需要调用GetScrollInfo函数以得到结构SCROLLINFO成员fMask中的SCROLLINFO值。
函数返回在结构SCROLLINFO成员nTrackPos中指出的滚动盒跟踪位置的值。这将允许当用户移动滚动盒时得到其位置

WinProc程序中定义static数据:

    static int cxChar,cxCaps,cyChar,cxClient,cyClient,iMaxWidth;    HDC hdc;    int i,x,y,iVertPos,iHorzPos,iPaintBeg,iPaintEnd;    PAINTSTRUCT ps;    SCROLLINFO si;    TCHAR szBuffer[10];    TEXTMETRIC tm;

有部分数据是在 WM_SIZE消息中初始化的:
穿件窗口之后会产生此消息,可得到客户端的宽度和高度分别存储在
lParam的低位和高位中(在此设置SCROLLINFO结构字段)。:

case WM_SIZE:    cxClient=LOWORD(lParam);    cyClient=HIWORD(lParam);    //Set vertical scroll bar range and page size    si.cbSize=sizeof(si);    si.fMask=SIF_RANGE | SIF_PAGE;    si.nMin=0;    si.nMax=NUMLINES-1;    si.nPage=cyClient/cyChar;    SetScrollInfo(hwnd,SB_VERT,&si,TRUE);    //set horizontal scroll bar range and page size    si.cbSize=sizeof(si);    si.fMask=SIF_RANGE | SIF_PAGE;    si.nMin=0;    si.nMax=2+iMaxWidth/cxChar;    si.nPage=cxClient/cxChar;    SetScrollInfo(hwnd,SB_HORZ,&si,TRUE);    return 0;

滚动消息:

case WM_VSCROLL:        si.cbSize=sizeof(si);        si.fMask=SIF_ALL;        GetScrollInfo(hwnd,SB_VERT,&si);        iVertPos=si.nPos;  //暂存当前的滑块位置,用以下面判断是否发生移动。        switch(LOWORD(wParam))        {        case SB_TOP:            si.nPos=si.nMin;            break;        case SB_BOTTOM:            si.nPos=si.nMax;            break;        case SB_LINEUP:            si.nPos-=1;            break;        case SB_LINEDOWN:            si.nPos+=1;            break;        case SB_PAGEUP:            si.nPos-=si.nPage;            break;        case SB_PAGEDOWN:            si.nPos+=si.nPage;            break;        case SB_THUMBTRACK:            si.nPos=si.nTrackPos;            break;        default:            break;        }        //Set the position then retrieve it, Due to adjustment        //by Winddows it may not be the  same as the value set          si.fMask=SIF_POS;          SetScrollInfo(hwnd,SB_VERT,&si,TRUE);          GetScrollInfo(hwnd,SB_VERT,&si);          //if the position has change,scroll the window          if(si.nPos!=iVertPos)          {               ScrollWindow(hwnd,0,cyChar*(iVertPos-si.nPos),NULL,NULL);              UpdateWindow(hwnd);          }          return 0;
1:由此可以发现在呼叫SetScrollInfo或GetScrollInfo函数前必须将cbSize字段设定为结构大小如 si.cbSize=sizeof(SCROLLINFO) 或sizeof(si);还有,要提前将fMask字段设定为一个以上以SIF前缀开头的旗标;以说明下面的SetScrollInfo或GetScrollInfo函数将要设置或者传回的字段。2:当每次滑动后,都要保存滑动,语句如下:          si.fMask=SIF_POS; //阐述如一          SetScrollInfo(hwnd,SB_VERT,&si,TRUE);          GetScrollInfo(hwnd,SB_VERT,&si);如果不进行滑块位置保存(SetScrollInfo函数),滑块就会“弹”回,然后再取出位置(GetScrollInfo函数),和滑动前iVertPos位置相比:      if(si.nPos!=iVertPos)            {               ScrollWindow(hwnd,0,cyChar*(iVertPos-si.nPos),NULL,NULL);              UpdateWindow(hwnd);          }

在这里不得不提ScrollWindow函数,使用它在显示区域卷动信息而不是重画它。第二个参数给出了水平卷动显示区域的数值,第三个参数给出了垂直卷动显示区域的信息,单位都是图素。最后两个参数都为NULL,说明卷动整个显示区域。Windows自动把显示区域未被卷动操作覆盖的矩形设为无效,这会产生WM_PAINT消息,而不再需要InvaildateRect函数使之无效。它不是GDI函数,因为它不需要句柄。

原创粉丝点击