Windowsプログラム設計読書ノート3——文字表示2

11847 ワード

表示される文字が不完全になる可能性があるため、スクロールバーを使用することが容易に考えられます.
まずコードを見てから分析します.
/*----------------------------------------------------

   SYSMETS2.C -- System Metrics Display Program No. 2

                 (c) Charles Petzold, 1998

  ----------------------------------------------------*/



#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 ("SysMets2") ;

     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 ("This program requires Windows NT!"), 

                      szAppName, MB_ICONERROR) ;

          return 0 ;

     }



     hwnd = CreateWindow (szAppName, TEXT ("Get System Metrics No. 2"),

                          WS_OVERLAPPEDWINDOW | WS_VSCROLL ,

                          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, cyClient, iVscrollPos ;

     HDC         hdc ;

     int         i, y ;

     PAINTSTRUCT ps ;

     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) ;



          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 ;



     case WM_PAINT:

          hdc = BeginPaint (hwnd, &ps) ;

     

          for (i = 0 ; i < NUMLINES ; i++)

          {

               y = cyChar * (i - iVscrollPos) ;

     

               TextOut (hdc, 0, y,

                        sysmetrics[i].szLabel,

                        lstrlen (sysmetrics[i].szLabel)) ;

     

               TextOut (hdc, 22 * cxCaps, y,

                        sysmetrics[i].szDesc,

                        lstrlen (sysmetrics[i].szDesc)) ;

     

               SetTextAlign (hdc, TA_RIGHT | TA_TOP) ;

     

               TextOut (hdc, 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) ;

}

CreateWindow関数の3番目のパラメータに WS_VCROLLは垂直スクロールバーです.
同時にWM_CREATEに追加:
SetScrollRange (hwnd, SB_VERT, 0, NUMLINES - 1, FALSE) ;

SetScrollPos   (hwnd, SB_VERT, iVscrollPos, TRUE) ;

SetScrrollRangeはスクロールバーの範囲を設定し、NUMLINESはヘッダファイルで定義された行数であり、
スクロールバーの位置ごとに1行のテキストが対応します.
iVscrollPos変数は、このスライダの現在位置を記録します.
マウスでスライダをドラッグするとWM_が生成されますVCROLLメッセージは、iVscrollPos変数に対して値付け操作を行う.
もう1つの変更点はY座標です. y = cyChar * (i - iVscrollPos) ; これにより、スライド後、現在位置より小さい文字が画面に出力されないことが保証されます(Y座標が負であるため).
スクロールバーをスライドさせるとき:
if (iVscrollPos != GetScrollPos (hwnd, SB_VERT))

          {

               SetScrollPos (hwnd, SB_VERT, iVscrollPos, TRUE) ;

               InvalidateRect (hwnd, NULL, TRUE) ;

          }

スクロールバーの位置が変更されると、InvalidateRect関数を使用してウィンドウを無効にし、WM_を生成します.PAINTメッセージ、ウィンドウを再描画します.