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:
        
            // Get all the vertical scroll bar information
        
    si.cbSize     = sizeof (si) ;
        
    si.fMask      = SIF_ALL ;
        
    GetScrollInfo (hwnd, SB_VERT, &si) ;
        
            // Save the position for comparison later on    
    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 and then retrieve it.  Due to adjustments
        
            //  by Windows 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 changed, scroll the window and update it
        
    if (si.nPos != iVertPos)
        
  {                  
        
            ScrollWindow (hwnd, 0, cyChar * (iVertPos - si.nPos),
        
                                          NULL, NULL) ;
            UpdateWindow (hwnd) ;   
    }
        
    return 0 ;
        
    case WM_HSCROLL:
        
                   // Get all the vertical scroll bar information
        
            si.cbSize = sizeof (si) ;
        
            si.fMask  = SIF_ALL ;                   // Save the position for comparison later on
        
            GetScrollInfo (hwnd, SB_HORZ, &si) ;
        
            iHorzPos = si.nPos ;
            switch (LOWORD (wParam))
        
            {
        
    case   SB_LINELEFT:
        
            si.nPos -= 1 ;
        
            break ;
         
    case   SB_LINERIGHT:
        
            si.nPos += 1 ;
        
            break ;    case   SB_PAGELEFT:
        
            si.nPos -= si.nPage ;
        
            break ;
        
    case   SB_PAGERIGHT:
        
            si.nPos += si.nPage ;
        
            break ;
        
 
    case   SB_THUMBPOSITION:
        
            si.nPos = si.nTrackPos ;
        
            break ;            default :
        
            break ;      
    }
        
            // Set the position and then retrieve it.  Due to adjustments
        
            //   by Windows it may not be the same as the value set.            si.fMask = SIF_POS ;
        
            SetScrollInfo (hwnd, SB_HORZ, &si, TRUE) ;
        
            GetScrollInfo (hwnd, SB_HORZ, &si) ;
                    // If the position has changed, scroll the window
            if (si.nPos != iHorzPos)
        
    {        
            ScrollWindow (hwnd, cxChar * (iHorzPos - si.nPos), 0,
                                      NULL, NULL) ;   
    }
        
            return 0 ;
        
这段代码是《windows程序设计》第四章说滚动条的时候出现的最后一个示例程序。
我把它粘在win7下的VC里,编译后运行。并没有出现水平滚动条,但是有垂直滚动条。
我设了几个断点如上所示:
单步执行,先从第一个断点到最后一个断点,继续单步执行它又回到第一个断点,一直单步到最后一个断点,再单步一次就到了return 0 了。我不明白为什么第一次单步到最后一个断点的时候不跳到return 0,却回去再执行一次。难道是因为nPage大小变了引起重绘所以又执行一次?期间我跟踪了一下nPage的值: 29 141 3435973836 30 141,如果是重绘引起的话它应该永久循环下去才是啊。
还有就是为什么水平滚动条没有显示,但是如果把 si.nPage= cxClient / cxChar ;这一条语句去掉的话就出现水平滚动条了。把这句去掉或是换成si.nPage = cyClient / cyChar ;的话都能出现。
或是把SetScrollInfo (hwnd, SB_VERT, &si, TRUE) ; 
 SetScrollInfo (hwnd, SB_VERT, &si, TRUE) ;
这两句之间的东西都删掉都可以。如果不到si重新赋值的话,水平滚动条所用的si不就是旧有的吗,这个时候水平滚动条的移动范围准确不?实在不明白为什么,大侠指教,谢谢。