ScrollWindow()函数

 在学习windows编程第五版时,介绍scrollbar时,改进的程序用到了ScrollWindow()函数。按照我的理解,如果使用了UpdateWindow()函数可以

不使用ScrollWindow()函数。因为UpdateWindow()函数会产生一个WM_PAINT消息。为了搞清楚ScrollWindow()函数的作用,我将代码加了些调试

代码

/*------------------------------------------------------------------
        
SYSMETS1.C -- System Metrics Display Program No. 1
        
                 (c) Charles Petzold, 1998
        
----------------------------------------------------------------*/
#define WINVER 0x0501//---------added later
        
//SYSMETS3.C
        
/*------------------------------------------------------------------
        
  SYSMETS3.C -- System Metrics Display Program No. 3
        
                 (c) Charles Petzold, 1998
        
----------------------------------------------------------------*/
        
#include <windows.h>
        
#include "SYSMETS.h"
#include <tchar.h>

#include <stdio.h>
#include <wtypes.h>
#include <stdarg.h>
#include <tchar.h>




//@tbuff_numsz 指tbuff数组个数
int CDECL fmtstr(TCHAR *ptbuff,UINT tbuff_numsz,LPCTSTR pszFormat, ...)
{
	if(ptbuff==NULL)
	{
		return -1;
	}
	
	va_list pArgs;
    va_start( pArgs, pszFormat );
    _vsntprintf( ptbuff, tbuff_numsz, pszFormat, pArgs );
    va_end( pArgs );
	return 0;
}



void CDECL LogTrace(LPCTSTR pszFormat, ...)
{
    va_list pArgs;
	
    TCHAR szMessageBuffer[16380]={0};
    va_start( pArgs, pszFormat );
    _vsntprintf( szMessageBuffer, 16380, pszFormat, pArgs );
    va_end( pArgs );
	
    OutputDebugString(szMessageBuffer);
}


int CDECL MessageBoxPrintf(TCHAR *szCaption,TCHAR *szFormat,...)
{
	TCHAR szBuffer[1024];
	va_list pArgList;
	va_start(pArgList,szFormat);

	_vsntprintf(szBuffer,sizeof(szBuffer)/sizeof(TCHAR),
		szFormat,pArgList);
	
	va_end(pArgList);
	return MessageBox(NULL,szBuffer,szCaption,0);
}



        
LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ;
        
int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
        
            PSTR szCmdLine, int iCmdShow)
        
{


	
    static TCHAR szAppName[] = TEXT ("SysMets3") ;
        
    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 ("Program requires Windows NT!"),
        
         szAppName, MB_ICONERROR) ;
        
           return 0 ;
        
    }
        

    hwnd = CreateWindow (szAppName, TEXT ("Get System Metrics No. 3"),
        
                   WS_OVERLAPPEDWINDOW | WS_VSCROLL | WS_HSCROLL,
        
                   CW_USEDEFAULT, CW_USEDEFAULT,
        
                   CW_USEDEFAULT, CW_USEDEFAULT,
        
                   NULL, NULL, hInstance, NULL) ;
        
    ShowWindow (hwnd, iCmdShow) ;
        
    UpdateWindow (hwnd) ;
        
   
        
    while (GetMessage (&msg, NULL, 0, 0))
        
    {
        
            TranslateMessage (&msg) ;
        
            DispatchMessage (&msg) ;
        
    }
        
    return msg.wParam ;
        
}
        

LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
        
{
        
    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 ;
        
   
        
    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) ;
        
            // Save the width of the three columns
        
    iMaxWidth = 40 * cxChar + 22 * cxCaps ;
        
    return 0 ;
        

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)
        
  {                  
        
			//-------------------------------------------------------------------------------------------
			LogTrace(_T("WM_VSCROLL event :%d\r\n"),si.nPos);

			ScrollWindow (hwnd, 0, cyChar * (iVertPos - si.nPos),NULL, NULL) ;
        
            UpdateWindow (hwnd) ;
			//InvalidateRect(hwnd, NULL, TRUE); 
        
    }
        
    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) ;
			//UpdateWindow (hwnd) ;
        
    }
        
            return 0 ;
        
    case WM_PAINT :
        
            hdc = BeginPaint (hwnd, &ps) ;
        
            // Get vertical scroll bar position
        
    si.cbSize = sizeof (si) ;
        
    si.fMask  = SIF_POS ;
        
    GetScrollInfo (hwnd, SB_VERT, &si) ;
        
    iVertPos = si.nPos ;

	//-------------------------------------------------------------------------------------------
	LogTrace(_T("WM_PAINT event :%d\r\n"),si.nPos);
	

       // Get horizontal scroll bar position
        
    GetScrollInfo (hwnd, SB_HORZ, &si) ;
        
    iHorzPos = si.nPos ;
        
            // Find painting limits
        
    iPaintBeg = max (0, iVertPos + ps.rcPaint.top / cyChar) ;
        
    iPaintEnd = min (     NUMLINES - 1,
        
                   iVertPos + ps.rcPaint.bottom / cyChar) ;
        
        
        
    for (i = iPaintBeg ; i <= iPaintEnd ; i++)
        
    {
        
            x = cxChar * (1 - iHorzPos) ;
        
            y = cyChar * (i - iVertPos) ;
        
             
        
            TextOut (hdc, x, y,
        
                   sysmetrics[i].szLabel,
        
                   lstrlen (sysmetrics[i].szLabel)) ;
        
             
        
            TextOut (hdc, x + 22 * cxCaps, y,
        
                   sysmetrics[i].szDesc,
        
                   lstrlen (sysmetrics[i].szDesc)) ;
        
             
        
            SetTextAlign (hdc, TA_RIGHT | TA_TOP) ;
        
            TextOut (hdc, x + 22 * cxCaps + 40 * cxChar, y, szBuffer,
        
                   wsprintf (szBuffer, TEXT ("%5d"),
        
                   GetSystemMetrics (sysmetrics[i].Index))) ;
        

            SetTextAlign (hdc, TA_LEFT | TA_TOP) ;
        
    }
        

            EndPaint (hwnd, &ps) ;
        
            return 0 ;
        
        
        
    case   WM_DESTROY :
        
            PostQuitMessage (0) ;
        
            return 0 ;
        
}
        
    return DefWindowProc (hwnd, message, wParam, lParam) ;
        
}
     

上面主要在执行WM_VSCROLL消息时加入logTrace()函数

在执行WM_PAINT消息时也加入logTrace()函数。然后调试代码,拖动滚动条看:程序处理WM_VSCROLL和WM_PAINT之间的关系


如果在WM_VSCROLL消息处理中注释掉 scrollWindow()函数,拖动垂直滚动条,看不到WM_PAINT消息处理中的logTrace信息。

感觉像是UpdateWindow()没有产生WM_PAINT消息。而且程序不会翻页。

如果将UpdateWindow()改成InvalidateRect()函数,可以发现程序可以正常运行,翻页。不过刷新有闪烁现象。


所以可以得到如下结论:scrollWindow()函数会改变UpdateWindow()执行的环境,当执行完scrollWindow()时,UpadteWinow会得到一个无效区域

然后执行UpadteWinow(),windows才会产生一个WM_PAINT消息。同时scrollWindow()函数会改善滚动效果。如果直接使用InvalidateRect()函数

会让程序翻页时产生闪烁现象。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值