Windows 程序设计 第四章 sysmets2

67 篇文章 0 订阅

 




/*----------------------------------------------------
   SYSMETS2.C -- System Metrics Display Program No. 2
                 (c) Charles Petzold, 1998
  ----------------------------------------------------*/

/*
第一次编译的时候出现下面的提示,后来就没有出现了

--------------------Configuration: chap04sysmets2 - Win32 Debug--------------------
Compiling...
sysmets2.c
NOTE: WINVER has been defined as 0x0500 or greater which enables
Windows NT 5.0 and Windows 98 features. When these headers were released,
Windows NT 5.0 beta 1 and Windows 98 beta 2.1 were the current versions.
For this release when WINVER is defined as 0x0500 or greater, you can only
build beta or test applications.  To build a retail application,
set WINVER to 0x0400 or visit http://www.microsoft.com/msdn/sdk
to see if retail Windows NT 5.0 or Windows 98 headers are available.
See the SDK release notes for more information.

sysmets2.obj - 0 error(s), 0 warning(s)

  */

// #define WINVER 0x0500  
#define WINVER 0x0501   
#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 /*=1 */ ;
     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) ;  // 设置滚动条的范围 0 -- NUMLINES - 1
          SetScrollPos   (hwnd, SB_VERT, iVscrollPos, TRUE) ;      //  设置(更新) 滚动条的位置, 在创建窗口是iVscrollPos=0 即滑块在最上顶上
          return 0 ;

     case WM_SIZE:
          cyClient = HIWORD (lParam) ;  // 在WM_SIZE消息中, lParam的低位字 是客户区的宽度,高字位是高度  cyClient  高度
          return 0 ;

     case WM_VSCROLL:
          switch (LOWORD (wParam)) // 在WM_VSCROLL 消息中,wParam的低位字是鼠标在滚动条上的动作,这个值是通知码,有SB_开头
          {
          case SB_LINEUP:          // 鼠标点击滚动条最上的那个三角箭 ,点击一下,iVscrollPos 减一.
               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) ;// 对于SB_THUMBPOSITION而言, wParam的高位字是滑块的位置
               break ;
     
          default :
               break ;
          }

          iVscrollPos = max (0, min (iVscrollPos, NUMLINES - 1)) ;  // 限定iVscrolPos 在0到NUMLINES - 1 取值范围内

          if (iVscrollPos != GetScrollPos (hwnd, SB_VERT))  // 如果iVscrollPos的值变了,则更新其位置,并设置 窗口无效
          {
               SetScrollPos (hwnd, SB_VERT, iVscrollPos, TRUE) ;
               InvalidateRect (hwnd, NULL, TRUE) ;  //  客户区无效,则产生 WM_PAINT 消息,TRUE 使其后调用的BeginPaint擦除原有的背景.
          }
          return 0 ;

     case WM_PAINT:
          hdc = BeginPaint (hwnd, &ps) ;
     
          for (i = 0 ; i < NUMLINES ; i++)
          {
			   // y是每一行的坐标,为负数时该行文字实际输出到客户区的外面了
			   // 大于0时,才是输出到 客户区 ,即 i > iVscrollPos时,也就是那些行数位于滑块的下面部分才输出更新吗?
			   // 假设滑块是向下拉,实际是原来滑块下面的内容在上升,就是这部分需要重绘 ?
			   /* 测试了发现: 如果滑块在最底下,即iVscrollPos = NUMLINES-1,
			       在for循环中,i取0到NUMLINES-2时,y都为负数,客户区没有输出,当 i = NUMLINES-1时,
				    y= 0,此刻y对应客户区的第一行,显示的内容对应是sysmetrics[i] 即 sysmetrics的最后一行.
			   */
			   

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


如果iVscrollPos初始化为1 则创建窗口时滑块的位置如下:

 

-----

 

 

//-------------------------------

 

//---  如果把滑块拉到底,则显示的是 原库文件中 最后一行(最后一个元素).....如下图:

-----

 

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值