《Windows程序设计》读书笔记------------->>基本滚动条<<

一、滚动条的建立:
在CreateWindow的第三个参数中包括窗口样式(WS)标识符WS_VSCROLL(垂直卷动)和/或WS_HSCROLL(水平卷动)即可。 

二、需要做的:

Windows对滚动条的处理:
  • 处理所有滚动条鼠标事件
     
  • 当使用者在滚动条内单击鼠标时,提供一种「反相显示」的闪烁
     
  • 当使用者在滚动条内拖动卷动方块时,移动卷动方块
     
  • 为包含滚动条窗口的窗口消息处理程序发送滚动条消息
     

程序写作者应该完成的工作:

  • 初始化滚动条的范围和位置

1、范围

 SetScrollRange (hwnd, iBar, iMin, iMax, bRedraw) ;

参数iBar为SB_VERT或者SB_HORZ,iMin和iMax分别是范围的最小值和最大值。如果想要Windows根据新范围重画滚动条,则设置bRedraw为TRUE(如果在呼叫SetScrollRange后,呼叫了影响滚动条位置的其它函数,则应该将bRedraw设定为FALSE以避免过多的重画)。
 一般情况下,最小值和最大值应该是与文本紧密关联的内容,以方便操作。
 
2、位置

 SetScrollPos (hwnd, iBar, iPos, bRedraw) ;

 参数iPos是新位置,它必须在iMin至iMax的范围内。Windows提供了类似的函数(GetScrollRange和GetScrollPos)来取得滚动条的目前范围和位置。
 

  • 处理窗口消息处理程序的滚动条消息

在用鼠标单击滚动条或者拖动卷动方块时,Windows给窗口消息处理程序发送WM_VSCROLL(供上下移动)和WM_HSCROLL(供左右移动)消息。在滚动条上的每个鼠标动作都至少产生两个消息,一条在按下鼠标按钮时产生,一条在释放按钮时产生。

和所有的消息一样,WM_VSCROLL和WM_HSCROLL也带有wParam和lParam消息参数。wParam消息参数被分为一个低字组和一个高字组。wParam的低字组是一个数值,它指出了鼠标对滚动条进行的操作。

这些操作有:

#define  SB_LINEUP       0
        
#define  SB_LINELEFT           0
        
#define  SB_LINEDOWN           1
        
#define  SB_LINERIGHT          1
        
#define  SB_PAGEUP         2
        
#define  SB_PAGELEFT           2
        
#define  SB_PAGEDOWN           3
        
#define  SB_PAGERIGHT          3
        
#define  SB_THUMBPOSITION   4
        
#define  SB_THUMBTRACK         5
        
#define  SB_TOP                6
        
#define  SB_LEFT           6
        
#define  SB_BOTTOM        7
        
#define  SB_RIGHT          7
        
#define  SB_ENDSCROLL          8

在wParam的低字组是SB_THUMBTRACK时,wParam的高字组是使用者在拖动卷动方块时的目前位置。

PS:取得低字组的方法是使用LOWORD(wParam),取得高字组的方法是使用HIWORD(wParam)。

  • 更新滚动条内卷动方块的位置

Windows不会去改变卷动方块的位置,而您可以在程序中呼叫SetScrollPos来改变卷动方块的位置。
 

  • 更改显示区域的内容以响应对滚动条的更改(看注释)
/*------------------------------------------------------------------
        
    SYSMETS2.C -- System Metrics Display Program No. 2
        
            (c) Charles Petzold, 1998
        
------------------------------------------------------------------
*/

        
#include 
< windows.h >
        
#include 
" sysmets.h "
        
LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ;
        
int  WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
        
                 PSTR szCmdLine, 
int  iCmdShow)
        
{
        
    
static TCHAR szAppName[] = TEXT ("SysMets2") ;
        
    HWND   hwnd ;
        
    MSG    msg ;
        
    WNDCLASS wndclass ;
        
    wndclass.style           
= CS_HREDRAW | CS_VREDRAW ;
        
    wndclass.lpfnWndProc  
= WndProc ;
        
    wndclass.cbClsExtra   
= 0 ;
        
    wndclass.cbWndExtra   
= 0 ;
        
    wndclass.hInstance       
= hInstance ;
        
    wndclass.hIcon        
= LoadIcon (NULL, IDI_APPLICATION) ;
        
    wndclass.hCursor         
= LoadCursor (NULL, IDC_ARROW) ;
        
    wndclass.hbrBackground        
= (HBRUSH) GetStockObject (WHITE_BRUSH) ;
        
    wndclass.lpszMenuName         
= NULL ;
        
    wndclass.lpszClassName        
= szAppName ;
        

    
if (!RegisterClass (&wndclass))
        
    
{
        
    MessageBox (NULL, TEXT (
"This program requires Windows NT!"),
        
           szAppName, MB_ICONERROR) ;
        
    
return 0 ;
        
    }

        

    hwnd 
= CreateWindow (szAppName, TEXT ("Get System Metrics No. 2"),
        
                   WS_OVERLAPPEDWINDOW 
| WS_VSCROLL,        //建立竖直滚动条
        
                   CW_USEDEFAULT, CW_USEDEFAULT,
        
                   CW_USEDEFAULT, CW_USEDEFAULT,
        
                   NULL, NULL, hInstance, NULL) ;
        
    ShowWindow (hwnd, iCmdShow) ;
        
    UpdateWindow (hwnd) ;
        

    
while (GetMessage (&msg, NULL, 00))
        
    
{
        
       TranslateMessage (
&msg) ;
        
        DispatchMessage (
&msg) ;
        
    }

        
    
return msg.wParam ;
        
}

        
LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
        
{
        
    
static int  cxChar, cxCaps, cyChar, cyClient, iVscrollPos ;
        
    HDC         hdc ;    
        
    
int         i, y ;   
        
    PAINTSTRUCT ps ;
        
    TCHAR       szBuffer[
10] ;   
        
    TEXTMETRIC  tm ;     
        
    
switch (message)     
        
    
{
        
case WM_CREATE:
        
    hdc 
= GetDC (hwnd) ;
        
    GetTextMetrics (hdc, 
&tm) ;
        
    cxChar 
= tm.tmAveCharWidth ;
        
    cxCaps 
= (tm.tmPitchAndFamily & 1 ? 3 : 2* cxChar / 2 ;//这个就不太看得懂了........
        
    cyChar 
= tm.tmHeight + tm.tmExternalLeading ;
        

    ReleaseDC (hwnd, hdc) ;
        
    SetScrollRange (hwnd, SB_VERT, 
0, NUMLINES - 1, FALSE) ;//初始化滚动条
        
    SetScrollPos   (hwnd, SB_VERT, iVscrollPos, TRUE) ;
//初始化位置
        
            
return 0 ;
        

    
case WM_SIZE:
        
            cyClient 
= HIWORD (lParam) ;        //取得窗口大小
        
            
return 0 ;
        

    
//滚动条处理函数
    case WM_VSCROLL:
        
            
switch (LOWORD (wParam))
        
         
{
        
    
case SB_LINEUP:
        
          iVscrollPos 
-= 1 ;//滚动条和文章移动的方向实际是相反的
        
            
break ;
        
   
        
    
case SB_LINEDOWN:
        
            iVscrollPos 
+= 1 ;
        
            
break ;
        

    
case SB_PAGEUP:
        
            iVscrollPos 
-= cyClient / cyChar ;
        
            
break ;
        
   
        
    
case SB_PAGEDOWN:
        
            iVscrollPos 
+= cyClient / cyChar ;
        
            
break ;
        
   
        
    
case SB_THUMBPOSITION:
        
            iVscrollPos 
= HIWORD (wParam) ;
        
            
break ;
        
   
        
    
default :
        
            
break ;
        
         }

        

    iVscrollPos 
= max (0, min (iVscrollPos, NUMLINES - 1)) ;//非常精彩的宏!控制了iVscrollPos不会超过ScrollRange 
        
    
if (iVscrollPos != GetScrollPos (hwnd, SB_VERT))
        
         
{
        
            SetScrollPos (hwnd, SB_VERT, iVscrollPos, TRUE) ;
        
            InvalidateRect (hwnd, NULL, TRUE) ;
//将窗口设置为无效,使之重画
        
         }

        
            
return 0 ;
        
    
case WM_PAINT:
        
            hdc 
= BeginPaint (hwnd, &ps) ;
        
            
for (i = 0 ; i < NUMLINES ; i++)
        
            
{
        
                   y 
= cyChar * (i - iVscrollPos) ;//iVscrollPos中记录了偏移的大小,所以y需要重新计算
        
                   TextOut (hdc, 
0, y,
        
                           sysmetrics[i].szLabel,
        
                           lstrlen (sysmetrics[i].szLabel)) ;
        
   
        
                   TextOut (hdc, 
22 * cxCaps, y,
        
                           sysmetrics[i].szDesc,
        
                           lstrlen (sysmetrics[i].szDesc)) ;
        
   
        
                   SetTextAlign (hdc, TA_RIGHT 
| TA_TOP) ;
        
                   TextOut (hdc, 
22 * cxCaps + 40 * cxChar, y, szBuffer,
        
                           wsprintf (szBuffer, TEXT (
"%5d"),
        
                                          GetSystemMetrics (sysmetrics[i].iIndex))) ;
        
                   SetTextAlign (hdc, TA_LEFT 
| TA_TOP) ;
        
        }

        
            EndPaint (hwnd, 
&ps) ;
        
            
return 0 ;
        

    
case WM_DESTROY:
        
            PostQuitMessage (
0) ;
        
            
return 0 ;
        
    }

        
    
return DefWindowProc (hwnd, message, wParam, lParam) ;
        
}

 

如果仔细看了这些代码,会发现很多是一种经验的积累,它的处理方式清晰简洁,也是学习的一种方法呢!

 


 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值