Win32学习笔记Timer篇之一 DIGCLOCK程序分析

类别:VC语言 点击:0 评论:0 推荐:

废话少叙。

理解DisplayTime( )是理解本程序的核心!

此函数如下所示:

 

void DisplayTime (HDC hdc, BOOL f24Hour, BOOL fSuppress)

{

  SYSTEMTIME st ;

  GetLocalTime(&st) ;

  if (f24Hour)

         DisplayTwoDigits (hdc, st.wHour, fSuppress) ;

  else

  DisplayTwoDigits (hdc, (st.wHour %= 12) ? st.wHour : 12, fSuppress) ;

  DisplayColon (hdc) ;

  DisplayTwoDigits (hdc, st.wMinute, FALSE) ;

  DisplayColon (hdc) ;

  DisplayTwoDigits (hdc, st.wSecond, FALSE) ;

}

 

首先,此函数用GetLocalTime(&st)取得当前的时间,st的结构如下:

 

typedef struct _SYSTEMTIME {  // st 

    WORD wYear;

    WORD wMonth;

    WORD wDayOfWeek;

    WORD wDay;

    WORD wHour;

    WORD wMinute;

    WORD wSecond;

    WORD wMilliseconds;

} SYSTEMTIME;

 

Oh, 一看就明白,wHour保存小时;wMinute保存分钟;wSecond保存秒数。

 

接着这句;

if( f24Hour)

DisplayTwoDigits (hdc, st.wHour, fSuppress) ;

此时f24Hour的值是什么呢?

如果你的电脑是以24 hour显示,那么它等于1。

为什么呢?因为:

 

case        WM_CREATE:

                    hBrushRed = CreateSolidBrush (RGB (255, 0, 0)) ;

                    SetTimer (hwnd, ID_TIMER, 1000, NULL) ;// fall through

 

  case      WM_SETTINGCHANGE:

         GetLocaleInfo (LOCALE_USER_DEFAULT, LOCALE_ITIME, szBuffer, 2) ;

         f24Hour = (szBuffer[0] == '1') ;

 

你看到了,第一个case并未与 break搭配,这意味着在收到WM_CREATE时,将会顺序执行接下来的语句,而WM_SETTINGCHANGE将被略去, f24Hour 将被赋值为 1。

 

接下来是:

 

DisplayTwoDigits (hdc, st.wHour, fSuppress) ;

 

好再看一看它的定义:

 

void DisplayTwoDigits (HDC hdc, int iNumber, BOOL fSuppress)

{

           if (!fSuppress || (iNumber / 10 != 0))

                    DisplayDigit (hdc, iNumber / 10) ;

           OffsetWindowOrgEx (hdc, -42, 0, NULL) ;

           DisplayDigit (hdc, iNumber % 10) ;

           OffsetWindowOrgEx (hdc, -42, 0, NULL) ;

}

if (!fSuppress || (iNumber / 10 != 0))

                    DisplayDigit (hdc, iNumber / 10) ;

 

这句在做什么呢?fSuppress标志着是否禁止显示03:46前面的零,假如为1,则03:46à 3:46;

再假设现在的时间是13:56:23。

好了,不管fSuppress等于多少,肯定if(TRUE)了,这回看出iNumber / 10 != 0的作用了,它设置了DisplayTwoDigits (HDC hdc, int iNumber, BOOL fSuppress)显示两个数字的条件。接下来DisplayDigit (hdc, iNumber / 10)将显示数字1。如何显示呢?

 

void DisplayDigit (HDC hdc, int iNumber)

{

           static BOOL  fSevenSegment [10][7] = {

                         1, 1,       1,   0,   1,   1,   1,             // 0

                         0, 0,       1,   0,   0,   1,   0,             // 1

                         1, 0,       1,   1,   1,   0,   1,             // 2

                         1, 0,       1,   1,   0,   1,   1,             // 3

                         0, 1,       1,   1,   0,   1,   0,             // 4

                         1, 1,       0,   1,   0,   1,   1,             // 5

                         1, 1,       0,   1,   1,   1,   1,             // 6

                         1, 0,       1,   0,   0,   1,   0,             // 7

                         1, 1,       1,   1,   1,   1,   1,             // 8

                         1, 1,       1,   1,   0,   1,   1 } ;              // 9

           static POINT ptSegment [7][6] = {

                              7,  6,  11,  2,  31,  2, 35,  6,  31, 10, 11, 10,

                    6,  7,  10, 11, 10, 31, 6,   35, 2,  31, 2,  11,

                    36, 7,  40, 11, 40, 31, 36,  35, 32, 31, 32, 11,

                    7 , 36, 11, 32, 31, 32, 35,  36, 31, 40, 11, 40,

                    6 , 37, 10, 41, 10, 61, 6,   65, 2,  61, 2,  41,

                    36, 37, 40, 41, 40, 61, 36,  65, 32, 61, 32, 41,

                    7 , 66, 11, 62, 31, 62, 35,  66, 31, 70, 11, 70 } ;

  int           iSeg ;

           for (iSeg = 0 ; iSeg < 7 ; iSeg++)

                    if (fSevenSegment [iNumber][iSeg])

                                           Polygon (hdc, ptSegment [iSeg], 6) ;

}

 

以上大家可要看好了,这可是鬼花活呀!不太好讲,好比绣花。你还不知道查尔斯的全称吗?他的全称是—插尔死·西方不败·败怎的?

 

我说:“Hans, 名字后面不好用 ?吧!”

Hans:“少插嘴,不知道入乡随俗吗?”

“很好!,很好。”

 

再接下来,OffsetWindowOrgEx (hdc, -42, 0, NULL) 上场了,它是做何工作的呢?

 

The OffsetWindowOrgEx function modifies the window origin for a device context using the specified horizontal and vertical offsets.

 

其定义:

 

BOOL OffsetWindowOrgEx(

 

    HDC hdc,      // handle to device context

    int nXOffset,   // horizontal offset

    int nYOffset,   // vertical offset

    LPPOINT lpPoint       // pointer to structure receiving the original origin 

   );

 

good!

此函数调整window origin 。

那原来的原点在哪里呢?在这里:

 

case        WM_PAINT:

                    hdc = BeginPaint (hwnd, &ps) ;

                    SetMapMode (hdc, MM_ISOTROPIC) ;

                    SetWindowExtEx (hdc, 276, 72, NULL) ;

                    SetViewportExtEx (hdc, cxClient, cyClient, NULL) ;

                    SetWindowOrgEx (hdc, 138, 36, NULL) ;

                    SetViewportOrgEx (hdc, cxClient / 2, cyClient / 2, NULL) ;

OK.            

SetMapMode (hdc, MM_ISOTROPIC) ;

SetWindowExtEx (hdc, 276, 72, NULL) ;

 

这两个语句建立了一个逻辑横坐标为276个单位,纵坐标为72个单位的坐标系。

逻辑是什么意思?意思是“世上本没有路,走的人多了也就成了路。”

 

我说:“Hans,离谱了吧!”

Hans:  我哪里知道我会想起这句话,坐标非坐标,是名坐标。

我说:“阿弥陀佛!少跟我玩这个!”

这句话什么意思呢?我个人的理解是:在人脑中要显示的东西,在人脑中的坐标!

哈哈哈哈,它当然与在显示设备上的东西有差别,比如我想起一艘航空母舰,如果要显示在显示设备上,不可能用1:1的比例吧,至少现在不可能。

 

SetViewportExtEx (hdc, cxClient, cyClient, NULL) ;

SetWindowOrgEx (hdc, 138, 36, NULL) ;

SetViewportOrgEx (hdc, cxClient / 2, cyClient / 2, NULL) ;

 

好的,SetViewportExtEx (hdc, cxClient, cyClient, NULL) 把整个客户区都当成显示区;

SetWindowOrgEx (hdc, 138, 36, NULL) ;把逻辑中心移到了原来逻辑坐标系的中心,原来的中心在哪?当然在那个左上角呀!同志们,这就是我那艘航空母舰的几何中心啊!

 

SetViewportOrgEx (hdc, cxClient / 2, cyClient / 2, NULL);把显示的中心设在了客户区的中心,同志们,这就是我们的视口的中心呀,哈哈哈哈,我只听过大口小口,从未听过视口,嘴能吃饭也能吐饭,视口能吃图象也能吐图像吗?我不知道,你知道吗?

你当然也看出来了“心口如一”呀,不是如一而是绝对是一!我那艘航空母舰的几何中心和我那张视口的中心那是“一心一意”的!

就这样,哈哈,这几条语句把坐标的中心移到了时间最左上的数字角,你若问我具体在哪里呢那你还不如打死我,我没有计算过,我只知道我的航空母舰肯定在窗口的中心,并且心心相印,想起这四个字,Hans想说:“我们的大学生活是多没好呀!”大学生活好不好与心心相印有关吗?我说:Hans你跑题了吧?

 

本文地址:http://com.8s8s.com/it/it1118.htm