|
Win32学习笔记Timer篇之一 DIGCLOCK程序分析(1)
废话少叙。XML:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" /> 理解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你跑题了吧?
|