window下的SCROLLbar的使用技巧(转)

windows的组件中,可以说,滚动条是最难的。难就难在如何设置滚动信息上。

首先,在初始化的时候,需要设置SCROLLINFO结构,其中有nMin,nMax,和Page,Pos几个信息。

nMin,nPos一般都设置为0.对于nMax和Page设置就有些技巧。关键是在对page的理解上。page其实就是可见部分的大小。比如,对于一个有滚动条的窗口,page的大小就是客户区(对于垂直滚动条,就是窗口的高度,对于水平滚动条,就是窗口的宽度)。而nMax呢,则是全部要显示的区域。比如对于一个显示文章的程序,如果显示一篇文章,需要1000像素的高度,而窗口只有300像素,那么就可以设置nMax=1000,nPage=300。实际上,我们在滚动条上看到的滑块,就代表者一个页,也就是当前我们看到的窗口。滑块的位置对应的是nPos,大小对应的nPage。

滚动条必须自己处理滚动过程,而窗口的滚动位置、大小都可能变化,所以处理起来也比较麻烦,但是还是有很好的技巧的。

windows发送WM_HSCROLL或者WM_VSCROLL消息来让程序处理滚动。我们可以利用GetScrollInfo获取当前的Pos:即没有发生滚动前的位置。根据滚动的动作:滚动一行、一页或者拖动,我们就可以确定新的位置,用这个位置减去老的位置,就获得偏移量,这个偏移量,就是给ScrollWindow函数调用的。

对于滚动行,用户必须另外指定行的大小

还以上面的为例,简单介绍一下垂直滚动的例子(伪代码,不能编译):

int line=10; //自己定义的行的大小,可以是任何合理的值或者公式
case WM_HSCROLL: 
SCROLLINFO si; 
si.fMask = SIF_ALL: 
si.cbSize = sizeof(si); 
GetSCrollInfo(hwnd,SB_VRET,&si); //获得滚动条的信息
int nPos=si.nPos;   
switch(LOWORD(wParam))  //wParam的低字是滚动条的动作
{ 
     case SB_LINEUP: 
           nPos -= line; 
           break; 
     case SB_LINEDOWN: 
          nPos += line; 
          break; 
     case SB_PAGEUP: 
         nPos -= si.nPage; 
         break; 
    case SB_PAGEDOWN: 
         nPos += si.nPage; 
        break; 
    case SB_THUMBPOSITION: 
        nPos = HIWORD(wParam); //wParam的高位是用户拖动的地址
       break; 
 } 
 //防止越界
if(nPos>si.nMax) nPos = si.nMax; 
if(nPos<si.nMin) nPos = si.nMin; 
//滚动窗口
ScrollWindow(hWnd,0,si.nPos-nPos,NULL,NULL); //如果是向下滚动,则偏移量为负值,向上滚动,则是正值
si.nPos = nPos; //设置新的值
SetScrollInfo(hwnd,SB_VRET,&si,FALSE); 

如果窗口的大小发生了变化,SCROLLINFO可能需要调整。但是这时nPos的位置可能不是0。其实,Pos的值根本不用变化。因为我们使用的都是像素,无论窗口的大小如何变化,即:nPage如何变化,nMax是不变的:除非文章发生变化,所以nPos根本不需要变化。对于一些可变编辑的文章,文章的长度时时变化,也就是nMax在变化,那么我们只要保证nPos不会超出nMin~nMax就可以了。

posted @ 2009-10-29 10:24  木瓜脑袋  阅读(1176)  评论(0编辑  收藏  举报