ScrollWindow()函数

来源:互联网 发布:C语言的算术表达式 编辑:程序博客网 时间:2024/05/17 09:22

 在学习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 0
原创粉丝点击