windows程序设计读书笔记4——字符显示3

在之前的一章里我们使用InvalidateRect函数,生成窗口重绘消息进行重绘,但是并没有在处理滚动条消息时直接绘制,这样的代码效率并不高。

这里作者使用了UpdateWindow函数,直接进行窗口的重绘。同时使用新的滚动条函数 SetScrollInfo 和 GetScrollInfo。

这两个函数不仅包括上一篇中使用的四个函数,而且还增加了两个新功能:调整滑块大小、指定滑块位置。

int SetScrollInfo(

  __in  HWND hwnd,

  __in  int fnBar,

  __in  LPCSCROLLINFO lpsi,

  __in  BOOL fRedraw

);
BOOL GetScrollInfo(

  __in     HWND hwnd,

  __in     int fnBar,

  __inout  LPSCROLLINFO lpsi

);

第二个参数是指定类型的滚动条,可以是下面的值:

Value Meaning
SB_CTL

Retrieves the parameters for a scroll bar control. The hwnd parameter must be the handle to the scroll bar control.

SB_HORZ

Retrieves the parameters for the window's standard horizontal scroll bar.

SB_VERT

Retrieves the parameters for the window's standard vertical scroll bar.

第三个参数是一个结构体

typedef struct tagSCROLLINFO {

  UINT cbSize;

  UINT fMask;

  int  nMin;

  int  nMax;

  UINT nPage;

  int  nPos;

  int  nTrackPos;

} SCROLLINFO, **LPCSCROLLINFO;

第四个参数是bool型,表示是否需要根据新的信息重绘滚动条。

下面是代码:

#define WINVER 0x0500

#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 ("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 vertial 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 vertial 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[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].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) ;

}

 

你可能感兴趣的:(windows)