zapline 发表于 2009-2-8 23:11

win程序设计笔记4

上次看到了System Metrics Display Program No. 1

在视窗大小改变时,Windows给视窗讯息处理程式发送一个WM_SIZE讯息。传给视窗讯息处理程式的lParam参数的低字组中包含显示区域的宽度,高字组中包含显示区域的高度。要保存这些尺寸,需要在视窗讯息处理程式中定义两个静态变数:
static int cxClient, cyClient ;
处理WM_SIZE的方法如下:
case        WM_SIZE:
        cxClient = LOWORD (lParam) ;
        cyClient = HIWORD (lParam) ;
        return 0 ;

滚动条的使用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)) ;
        if (iVscrollPos != GetScrollPos (hwnd, SB_VERT))
          {
                SetScrollPos (hwnd, SB_VERT, iVscrollPos, TRUE) ;
                InvalidateRect (hwnd, NULL, TRUE) ;
          }
                return 0 ;
改进版:LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
        static intcxChar, cxCaps, cyChar, cxClient, cyClient, iMaxWidth ;
        HDC        hdc ;
        int        i, x, y, iVertPos, iHorzPos, iPaintBeg, iPaintEnd ;
        PAINTSTRUCT ps ;
        SCROLLINFOsi ;
        TCHAR       szBuffer ;
        TEXTMETRICtm ;
   
        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)
           {                  
                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 ;
        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 ;

                // 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.szLabel,
                        lstrlen (sysmetrics.szLabel)) ;
               
                TextOut (hdc, x + 22 * cxCaps, y,
                        sysmetrics.szDesc,
                        lstrlen (sysmetrics.szDesc)) ;
               
                SetTextAlign (hdc, TA_RIGHT | TA_TOP) ;
                TextOut (hdc, x + 22 * cxCaps + 40 * cxChar, y, szBuffer,
                        wsprintf (szBuffer, TEXT ("%5d"),
                        GetSystemMetrics (sysmetrics.iIndex))) ;

                SetTextAlign (hdc, TA_LEFT | TA_TOP) ;
        }

                EndPaint (hwnd, &ps) ;
                return 0 ;
         
        case        WM_DESTROY :
                PostQuitMessage (0) ;
                return 0 ;
}
使用了SetScrollInfo和GetScrollInfo函数:
SetScrollInfo (hwnd, iBar, &si, bRedraw) ;
GetScrollInfo (hwnd, iBar, &si) ;
第三个参数SCROLLINFO结构:
typedef struct tagSCROLLINFO
{
        UINT cbSize ;        // set to sizeof (SCROLLINFO)
        UINT fMask ;        // values to set or get
        intnMin ;          // minimum range value
        intnMax ;         // maximum range value
        UINT nPage ;        // page size
        intnPos ;         // current position
        intnTrackPos ;// current tracking position
}
SCROLLINFO, * PSCROLLINFO ;

总结:滚动条的两种使用方法
1,        SetScrollRange (hwnd, SB_VERT, 0, NUMLINES - 1, FALSE) ;
        SetScrollPos   (hwnd, SB_VERT, iVscrollPos, TRUE) ;
设置范围和位置
        iVscrollPos = max (0, min (iVscrollPos, NUMLINES - 1)) ;
        if (iVscrollPos != GetScrollPos (hwnd, SB_VERT))
          {
                SetScrollPos (hwnd, SB_VERT, iVscrollPos, TRUE) ;
                InvalidateRect (hwnd, NULL, TRUE) ;
          }
判断位置是否有误
2,        SCROLLINFOsi ;
建立SCROLLINFO结构对象
        SetScrollInfo (hwnd, SB_VERT, &si, TRUE) ;
        GetScrollInfo (hwnd, SB_VERT, &si) ;
SetScrollInfo和GetScrollInfo函数来获得与修改滚动条得属性
1,2都对WM_VSCROLL进行处理以实现滚动条的功能
页: [1]
查看完整版本: win程序设计笔记4