Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenclock.c
Go to the documentation of this file.
00001 /* 00002 * PROJECT: ReactOS Timedate Control Panel 00003 * LICENSE: GPL - See COPYING in the top level directory 00004 * FILE: dll/cpl/timedate/clock.c 00005 * PURPOSE: Draws the analog clock 00006 * COPYRIGHT: Copyright 2006 Ged Murphy <gedmurphy@gmail.com> 00007 * Copyright 2007 Eric Kohl 00008 */ 00009 00010 /* Code based on clock.c from Programming Windows, Charles Petzold */ 00011 00012 #include <timedate.h> 00013 00014 typedef struct _CLOCKDATA 00015 { 00016 HBRUSH hGreyBrush; 00017 HPEN hGreyPen; 00018 INT cxClient; 00019 INT cyClient; 00020 SYSTEMTIME stCurrent; 00021 SYSTEMTIME stPrevious; 00022 BOOL bTimer; 00023 } CLOCKDATA, *PCLOCKDATA; 00024 00025 00026 #define TWOPI (2 * 3.14159) 00027 00028 static const WCHAR szClockWndClass[] = L"ClockWndClass"; 00029 00030 static VOID 00031 RotatePoint(POINT pt[], INT iNum, INT iAngle) 00032 { 00033 INT i; 00034 POINT ptTemp; 00035 00036 for (i = 0 ; i < iNum ; i++) 00037 { 00038 ptTemp.x = (INT) (pt[i].x * cos (TWOPI * iAngle / 360) + 00039 pt[i].y * sin (TWOPI * iAngle / 360)); 00040 00041 ptTemp.y = (INT) (pt[i].y * cos (TWOPI * iAngle / 360) - 00042 pt[i].x * sin (TWOPI * iAngle / 360)); 00043 00044 pt[i] = ptTemp; 00045 } 00046 } 00047 00048 00049 static INT 00050 DrawClock(HDC hdc, PCLOCKDATA pClockData) 00051 { 00052 INT iAngle,Radius; 00053 POINT pt[3]; 00054 HBRUSH hBrushOld; 00055 HPEN hPenOld = NULL; 00056 00057 /* Grey brush to fill the dots */ 00058 hBrushOld = SelectObject(hdc, pClockData->hGreyBrush); 00059 00060 hPenOld = GetCurrentObject(hdc, OBJ_PEN); 00061 00062 // TODO: Check if this conversion is correct resp. usable 00063 Radius = min(pClockData->cxClient,pClockData->cyClient) * 2; 00064 00065 for (iAngle = 0; iAngle < 360; iAngle += 6) 00066 { 00067 /* Starting coords */ 00068 pt[0].x = 0; 00069 pt[0].y = Radius; 00070 00071 /* Rotate start coords */ 00072 RotatePoint(pt, 1, iAngle); 00073 00074 /* Determine whether it's a big dot or a little dot 00075 * i.e. 1-4 or 5, 6-9 or 10, 11-14 or 15 */ 00076 if (iAngle % 5) 00077 { 00078 pt[2].x = pt[2].y = 7; 00079 SelectObject(hdc, pClockData->hGreyPen); 00080 } 00081 else 00082 { 00083 pt[2].x = pt[2].y = 16; 00084 SelectObject(hdc, GetStockObject(BLACK_PEN)); 00085 } 00086 00087 pt[0].x -= pt[2].x / 2; 00088 pt[0].y -= pt[2].y / 2; 00089 00090 pt[1].x = pt[0].x + pt[2].x; 00091 pt[1].y = pt[0].y + pt[2].y; 00092 00093 Ellipse(hdc, pt[0].x, pt[0].y, pt[1].x, pt[1].y); 00094 } 00095 00096 SelectObject(hdc, hBrushOld); 00097 SelectObject(hdc, hPenOld); 00098 return Radius; 00099 } 00100 00101 00102 static VOID 00103 DrawHands(HDC hdc, SYSTEMTIME * pst, BOOL fChange, INT Radius) 00104 { 00105 POINT pt[3][5] = { {{0, (INT)-Radius/6}, {(INT)Radius/9, 0}, 00106 {0, (INT)Radius/1.8}, {(INT)-Radius/9, 0}, {0, (INT)-Radius/6}}, 00107 {{0, (INT)-Radius/4.5}, {(INT)Radius/18, 0}, {0, (INT) Radius*0.89}, 00108 {(INT)-Radius/18, 0}, {0, (INT)-Radius/4.5}}, 00109 {{0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, (INT) Radius*0.89}} }; 00110 INT i, iAngle[3]; 00111 POINT ptTemp[3][5]; 00112 00113 /* Black pen for outline, white brush for fill */ 00114 SelectObject(hdc, GetStockObject(BLACK_PEN)); 00115 SelectObject(hdc, GetStockObject(WHITE_BRUSH)); 00116 00117 iAngle[0] = (pst->wHour * 30) % 360 + pst->wMinute / 2; 00118 iAngle[1] = pst->wMinute * 6; 00119 iAngle[2] = pst->wSecond * 6; 00120 00121 CopyMemory(ptTemp, pt, sizeof(pt)); 00122 00123 for (i = fChange ? 0 : 2; i < 3; i++) 00124 { 00125 RotatePoint(ptTemp[i], 5, iAngle[i]); 00126 00127 Polygon(hdc, ptTemp[i], 5); 00128 } 00129 } 00130 00131 00132 static LRESULT CALLBACK 00133 ClockWndProc(HWND hwnd, 00134 UINT uMsg, 00135 WPARAM wParam, 00136 LPARAM lParam) 00137 { 00138 PCLOCKDATA pClockData; 00139 HDC hdc, hdcMem; 00140 PAINTSTRUCT ps; 00141 00142 pClockData = (PCLOCKDATA)GetWindowLongPtrW(hwnd, GWLP_USERDATA); 00143 00144 switch (uMsg) 00145 { 00146 case WM_CREATE: 00147 pClockData = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(CLOCKDATA)); 00148 SetWindowLongPtrW(hwnd, GWLP_USERDATA, (LONG_PTR)pClockData); 00149 00150 pClockData->hGreyPen = CreatePen(PS_SOLID, 1, RGB(128, 128, 128)); 00151 pClockData->hGreyBrush = CreateSolidBrush(RGB(128, 128, 128)); 00152 00153 SetTimer(hwnd, ID_TIMER, 1000, NULL); 00154 pClockData->bTimer = TRUE; 00155 GetLocalTime(&pClockData->stCurrent); 00156 pClockData->stPrevious = pClockData->stCurrent; 00157 break; 00158 00159 case WM_SIZE: 00160 pClockData->cxClient = LOWORD(lParam); 00161 pClockData->cyClient = HIWORD(lParam); 00162 break; 00163 00164 case WM_TIMER: 00165 GetLocalTime(&pClockData->stCurrent); 00166 InvalidateRect(hwnd, NULL, FALSE); 00167 pClockData->stPrevious = pClockData->stCurrent; 00168 break; 00169 00170 case WM_PAINT: 00171 hdc = BeginPaint(hwnd, &ps); 00172 00173 hdcMem = CreateCompatibleDC(hdc); 00174 if (hdcMem) 00175 { 00176 HBITMAP hBmp, hBmpOld; 00177 00178 hBmp = CreateCompatibleBitmap(hdc, 00179 pClockData->cxClient, 00180 pClockData->cyClient); 00181 if (hBmp) 00182 { 00183 HBRUSH hWinBrush, hWinBrushOld; 00184 INT oldMap, Radius; 00185 POINT oldOrg; 00186 00187 hBmpOld = SelectObject(hdcMem, hBmp); 00188 00189 hWinBrush = GetSysColorBrush(COLOR_BTNFACE); 00190 hWinBrushOld = SelectObject(hdcMem, hWinBrush); 00191 PatBlt(hdcMem, 00192 0, 00193 0, 00194 pClockData->cxClient, 00195 pClockData->cyClient, 00196 PATCOPY); 00197 00198 oldMap = SetMapMode(hdcMem, MM_ISOTROPIC); 00199 SetWindowExtEx(hdcMem, 3600, 2700, NULL); 00200 SetViewportExtEx(hdcMem, 800, -600, NULL); 00201 SetViewportOrgEx(hdcMem, 00202 pClockData->cxClient / 2, 00203 pClockData->cyClient / 2, 00204 &oldOrg); 00205 00206 Radius = DrawClock(hdcMem, pClockData); 00207 DrawHands(hdcMem, &pClockData->stPrevious, TRUE, Radius); 00208 00209 SetMapMode(hdcMem, oldMap); 00210 SetViewportOrgEx(hdcMem, oldOrg.x, oldOrg.y, NULL); 00211 00212 BitBlt(hdc, 00213 0, 00214 0, 00215 pClockData->cxClient, 00216 pClockData->cyClient, 00217 hdcMem, 00218 0, 00219 0, 00220 SRCCOPY); 00221 00222 SelectObject(hdcMem, hWinBrushOld); 00223 SelectObject(hdcMem, hBmpOld); 00224 DeleteObject(hBmp); 00225 } 00226 00227 DeleteDC(hdcMem); 00228 } 00229 00230 EndPaint(hwnd, &ps); 00231 break; 00232 00233 case WM_DESTROY: 00234 DeleteObject(pClockData->hGreyPen); 00235 DeleteObject(pClockData->hGreyBrush); 00236 00237 if (pClockData->bTimer) 00238 KillTimer(hwnd, ID_TIMER); 00239 00240 HeapFree(GetProcessHeap(), 0, pClockData); 00241 break; 00242 00243 case CLM_STOPCLOCK: 00244 if (pClockData->bTimer) 00245 { 00246 KillTimer(hwnd, ID_TIMER); 00247 pClockData->bTimer = FALSE; 00248 } 00249 break; 00250 00251 case CLM_STARTCLOCK: 00252 if (!pClockData->bTimer) 00253 { 00254 SetTimer(hwnd, ID_TIMER, 1000, NULL); 00255 pClockData->bTimer = TRUE; 00256 } 00257 break; 00258 00259 default: 00260 DefWindowProcW(hwnd, 00261 uMsg, 00262 wParam, 00263 lParam); 00264 } 00265 00266 return TRUE; 00267 } 00268 00269 00270 BOOL 00271 RegisterClockControl(VOID) 00272 { 00273 WNDCLASSEXW wc = {0}; 00274 00275 wc.cbSize = sizeof(WNDCLASSEXW); 00276 wc.lpfnWndProc = ClockWndProc; 00277 wc.hInstance = hApplet; 00278 wc.hCursor = LoadCursorW(NULL, IDC_ARROW); 00279 wc.hbrBackground = (HBRUSH)(COLOR_BTNFACE + 1); 00280 wc.lpszClassName = szClockWndClass; 00281 00282 return RegisterClassExW(&wc) != (ATOM)0; 00283 } 00284 00285 00286 VOID 00287 UnregisterClockControl(VOID) 00288 { 00289 UnregisterClassW(szClockWndClass, 00290 hApplet); 00291 } Generated on Thu May 24 2012 04:21:24 for ReactOS by
1.7.6.1
|