8.3 定时器用于时钟 建立数字时钟 #include <windows.h> #define ID_TIMER 1 LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ; int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow) { static TCHAR szAppName[] = TEXT ("DigClock") ; 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 ("Digital Clock"), WS_OVERLAPPEDWINDOW, 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 ; } 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 //ptSegment数组是一个POINT结构的数组,指出了7个段中每个点的图形坐标 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) ; } void DisplayTwoDigits (HDC hdc, int iNumber, BOOL fSuppress) { //在每次呼叫OffsetWindowOrgEx后, //将窗口原点向右移动42个单位 if (!fSuppress || (iNumber / 10 != 0)) DisplayDigit (hdc, iNumber / 10) ; OffsetWindowOrgEx (hdc, -42, 0, NULL) ; DisplayDigit (hdc, iNumber % 10) ; OffsetWindowOrgEx (hdc, -42, 0, NULL) ; } //画冒号 void DisplayColon (HDC hdc) { POINT ptColon [2][4] = {2, 21, 6, 17, 10, 21, 6, 25, 2, 51, 6, 47, 10, 51, 6, 55 }; Polygon (hdc, ptColon [0], 4) ; Polygon (hdc, ptColon [1], 4) ; OffsetWindowOrgEx (hdc, -12, 0, NULL) ; } 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) ; } LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam,LPARAM lParam) { static BOOL f24Hour, fSuppress ; static HBRUSH hBrushRed ; static int cxClient, cyClient ; HDC hdc ; PAINTSTRUCT ps ; TCHAR szBuffer [2] ; switch (message) { case WM_CREATE: //红色 hBrushRed = CreateSolidBrush (RGB (255, 0, 0)) ; //一个1秒触发一次的定时器 SetTimer (hwnd, ID_TIMER, 1000, NULL) ; // fall through case WM_SETTINGCHANGE: //取得与指定“地方”有关的信息 GetLocaleInfo (LOCALE_USER_DEFAULT, LOCALE_ITIME, szBuffer, 2) ; f24Hour = (szBuffer[0] == '1') ; GetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_ITLZERO, szBuffer, 2) ; fSuppress = (szBuffer[0] == '0') ; InvalidateRect (hwnd, NULL, TRUE) ; return 0 ; case WM_SIZE: cxClient = LOWORD (lParam) ; cyClient = HIWORD (lParam) ; return 0 ; case WM_TIMER: InvalidateRect (hwnd, NULL, TRUE) ; return 0 ; case WM_PAINT: hdc = BeginPaint (hwnd, &ps) ; SetMapMode (hdc, MM_ISOTROPIC) ; //数字是42个单位宽,冒号是12个单位宽, //因此6个数字与2个冒号,总宽度是276个单位 SetWindowExtEx (hdc, 276, 72, NULL) ; SetViewportExtEx (hdc, cxClient, cyClient, NULL) ; //该函数用指定的坐标设置设备环境的窗口原点 SetWindowOrgEx (hdc, 138, 36, NULL) ; //明哪个设备点映射到窗口原点(0,0) SetViewportOrgEx (hdc, cxClient / 2, cyClient / 2, NULL) ; SelectObject (hdc, GetStockObject (NULL_PEN)) ; SelectObject (hdc, hBrushRed) ; DisplayTime (hdc, f24Hour, fSuppress) ; EndPaint (hwnd, &ps) ; return 0 ; case WM_DESTROY: KillTimer (hwnd, ID_TIMER) ; DeleteObject (hBrushRed) ; PostQuitMessage (0) ; return 0 ; } return DefWindowProc (hwnd, message, wParam, lParam) ; } 建立模拟时钟 #include <windows.h> #include <math.h> #define ID_TIMER 1 #define TWOPI (2 * 3.14159) LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ; int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow) { static TCHAR szAppName[] = TEXT ("Clock") ; 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 = NULL ; 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 ("Analog Clock"), WS_OVERLAPPEDWINDOW, 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 ; } //等方性的 void SetIsotropic (HDC hdc, int cxClient, int cyClient) { //设置指定设备环境的映射方式 SetMapMode (hdc, MM_ISOTROPIC) ; SetWindowExtEx (hdc, 1000, 1000, NULL) ; SetViewportExtEx (hdc, cxClient / 2, - cyClient / 2, NULL) ; SetViewportOrgEx (hdc, cxClient / 2, cyClient / 2, NULL) ; } void RotatePoint (POINT pt[], int iNum, int iAngle) { int i ; POINT ptTemp ; for (i = 0 ; i < iNum ; i++) { ptTemp.x = (int) (pt[i].x * cos (TWOPI * iAngle / 360) + pt[i].y * sin (TWOPI * iAngle / 360)) ; ptTemp.y = (int) (pt[i].y * cos (TWOPI * iAngle / 360) - pt[i].x * sin (TWOPI * iAngle / 360)) ; pt[i] = ptTemp ; } } void DrawClock (HDC hdc) { int iAngle ; POINT pt[3] ; for (iAngle = 0 ; iAngle < 360 ; iAngle += 6) { pt[0].x = 0 ; pt[0].y = 900 ; RotatePoint (pt, 1, iAngle) ; pt[2].x = pt[2].y = iAngle % 5 ? 33 : 100 ; pt[0].x -= pt[2].x / 2 ; pt[0].y -= pt[2].y / 2 ; pt[1].x = pt[0].x + pt[2].x ; pt[1].y = pt[0].y + pt[2].y ; SelectObject (hdc, GetStockObject(BLACK_BRUSH)) ; //定义椭圆是一种圆锥曲线 Ellipse(hdc, pt[0].x, pt[0].y, pt[1].x, pt[1].y) ; } } void DrawHands (HDC hdc, SYSTEMTIME * pst, BOOL fChange) { static POINT pt[3][5] ={0, -150, 100, 0, 0, 600, -100, 0, 0, -150, 0, -200, 50, 0, 0, 800, -50, 0, 0,-200, 0,0, 0, 0, 0, 0, 0, 0, 0, 800 } ; int i, iAngle[3] ; POINT ptTemp[3][5] ; iAngle[0] = (pst->wHour * 30) % 360 + pst->wMinute / 2 ; iAngle[1] = pst->wMinute * 6 ; iAngle[2] = pst->wSecond * 6 ; memcpy (ptTemp, pt, sizeof (pt)) ; for (i = fChange ? 0 : 2 ; i < 3 ; i++) { RotatePoint (ptTemp[i], 5, iAngle[i]) ; Polyline (hdc, ptTemp[i], 5) ;//用当前画笔描绘一系列线段 } } LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam,LPARAM lParam) { static int cxClient, cyClient ; static SYSTEMTIME stPrevious ; BOOL fChange ; HDC hdc ; PAINTSTRUCT ps ; SYSTEMTIME st ; switch (message) { case WM_CREATE: SetTimer (hwnd, ID_TIMER, 1000, NULL) ; GetLocalTime (&st) ; stPrevious = st ; return 0 ; case WM_SIZE : cxClient = LOWORD (lParam) ; cyClient = HIWORD (lParam) ; return 0 ; case WM_TIMER : GetLocalTime (&st) ; //时间是否改变 fChange = st.wHour != stPrevious.wHour || st.wMinute != stPrevious.wMinute ; hdc = GetDC (hwnd) ; SetIsotropic (hdc, cxClient, cyClient) ; SelectObject (hdc, GetStockObject (WHITE_PEN)) ; DrawHands (hdc, &stPrevious, fChange) ; SelectObject (hdc, GetStockObject (BLACK_PEN)) ; DrawHands (hdc, &st, TRUE) ; ReleaseDC (hwnd, hdc) ; stPrevious = st ; return 0 ; case WM_PAINT : hdc = BeginPaint (hwnd, &ps) ; SetIsotropic (hdc, cxClient, cyClient) ; DrawClock (hdc) ; DrawHands (hdc, &stPrevious, TRUE) ; EndPaint (hwnd, &ps) ; return 0 ; case WM_DESTROY : KillTimer (hwnd, ID_TIMER) ; PostQuitMessage (0) ; return 0 ; } return DefWindowProc (hwnd, message, wParam, lParam) ; } 8.4 以定时器进行状态报告 #include <windows.h> #define ID_TIMER 1 void FindWindowSize (int *, int *) ; LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ; int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow) { static TCHAR szAppName[] = TEXT ("WhatClr") ; HWND hwnd ; int cxWindow, cyWindow ; 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 ; } FindWindowSize (&cxWindow, &cyWindow) ; hwnd = CreateWindow (szAppName, TEXT ("What Color"), WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_BORDER, CW_USEDEFAULT, CW_USEDEFAULT, cxWindow, cyWindow, NULL, NULL, hInstance, NULL) ; ShowWindow (hwnd, iCmdShow) ; UpdateWindow (hwnd) ; while (GetMessage (&msg, NULL, 0, 0)) { TranslateMessage (&msg) ; DispatchMessage (&msg) ; } return msg.wParam ; } void FindWindowSize (int * pcxWindow, int * pcyWindow) { HDC hdcScreen ; TEXTMETRIC tm ; hdcScreen = CreateIC (TEXT ("DISPLAY"), NULL, NULL, NULL) ; GetTextMetrics (hdcScreen, &tm) ; DeleteDC (hdcScreen) ; * pcxWindow = 2 * GetSystemMetrics (SM_CXBORDER) + 12 * tm.tmAveCharWidth ; * pcyWindow = 2 * GetSystemMetrics (SM_CYBORDER) + GetSystemMetrics (SM_CYCAPTION) + 2 * tm.tmHeight ; } LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam,LPARAM lParam) { static COLORREF cr, crLast ; static HDC hdcScreen ; HDC hdc ; PAINTSTRUCT ps ; POINT pt ; RECT rc ; TCHAR szBuffer [16] ; switch (message) { case WM_CREATE: //呼叫CreateDC建立了用于整个视讯显示的设备内容。 hdcScreen = CreateDC (TEXT ("DISPLAY"), NULL, NULL, NULL) ; SetTimer (hwnd, ID_TIMER, 100, NULL) ; return 0 ; case WM_TIMER: //取得目前鼠标光标位置 GetCursorPos (&pt) ; //取得目前鼠标光标位置的图素 cr = GetPixel (hdcScreen, pt.x, pt.y) ; //SetPixel (hdcScreen, pt.x, pt.y, 0) ; if (cr != crLast) { crLast = cr ; InvalidateRect (hwnd, NULL, FALSE) ; } return 0 ; case WM_PAINT: hdc = BeginPaint (hwnd, &ps) ; GetClientRect (hwnd, &rc) ; //R:((BYTE)(((DWORD_PTR)(w)) & 0xff)) //G:(((BYTE)(((DWORD_PTR)(w)) & 0xff)) >> 8))) //B:(((BYTE)(((DWORD_PTR)(w)) & 0xff)) >> 16))) wsprintf (szBuffer, TEXT (" %02X %02X %02X "), GetRValue (cr), GetGValue (cr), GetBValue (cr)) ; DrawText (hdc, szBuffer, -1, &rc, DT_SINGLELINE | DT_CENTER | DT_VCENTER) ; EndPaint (hwnd, &ps) ; return 0 ; case WM_DESTROY: DeleteDC (hdcScreen) ; KillTimer (hwnd, ID_TIMER) ; PostQuitMessage (0) ; return 0 ; } return DefWindowProc (hwnd, message, wParam, lParam) ; }