1 /*
2 * Clock
3 *
4 * Copyright 1998 Marcel Baur <mbaur@g26.ethz.ch>
5 *
6 * Clock is partially based on
7 * - Program Manager by Ulrich Schmied
8 * - rolex.c by Jim Peterson
9 *
10 *
11 * This library is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU Lesser General Public
13 * License as published by the Free Software Foundation; either
14 * version 2.1 of the License, or (at your option) any later version.
15 *
16 * This library is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 * Lesser General Public License for more details.
20 *
21 * You should have received a copy of the GNU Lesser General Public
22 * License along with this library; if not, write to the Free Software
23 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
24 */
25
26 #include <stdio.h>
27
28 #include "windows.h"
29 #include "commdlg.h"
30
31 #include "main.h"
32 #include "winclock.h"
33
34 #define INITIAL_WINDOW_SIZE 200
35 #define TIMER_ID 1
36
37 CLOCK_GLOBALS Globals;
38
39 static VOID WineLicense(HWND Wnd)
40 {
41 char cap[20], text[1024];
42 LoadString(Globals.hInstance, IDS_LICENSE, text, sizeof text);
43 LoadString(Globals.hInstance, IDS_LICENSE_CAPTION, cap, sizeof cap);
44 MessageBox(Wnd, text, cap, MB_ICONINFORMATION | MB_OK);
45 }
46
47 static VOID WineWarranty(HWND Wnd)
48 {
49 char cap[20], text[1024];
50 LoadString(Globals.hInstance, IDS_WARRANTY, text, sizeof text);
51 LoadString(Globals.hInstance, IDS_WARRANTY_CAPTION, cap, sizeof cap);
52 MessageBox(Wnd, text, cap, MB_ICONEXCLAMATION | MB_OK);
53 }
54
55 static VOID CLOCK_UpdateMenuCheckmarks(VOID)
56 {
57 HMENU hPropertiesMenu;
58 hPropertiesMenu = GetSubMenu(Globals.hMainMenu, 0);
59 if (!hPropertiesMenu)
60 return;
61
62 if(Globals.bAnalog) {
63
64 /* analog clock */
65 CheckMenuRadioItem(hPropertiesMenu, IDM_ANALOG, IDM_DIGITAL, IDM_ANALOG, MF_CHECKED);
66 EnableMenuItem(hPropertiesMenu, IDM_FONT, MF_GRAYED);
67 }
68 else
69 {
70 /* digital clock */
71 CheckMenuRadioItem(hPropertiesMenu, IDM_ANALOG, IDM_DIGITAL, IDM_DIGITAL, MF_CHECKED);
72 EnableMenuItem(hPropertiesMenu, IDM_FONT, 0);
73 }
74
75 CheckMenuItem(hPropertiesMenu, IDM_NOTITLE, (Globals.bWithoutTitle ? MF_CHECKED : MF_UNCHECKED));
76
77 CheckMenuItem(hPropertiesMenu, IDM_ONTOP, (Globals.bAlwaysOnTop ? MF_CHECKED : MF_UNCHECKED));
78 CheckMenuItem(hPropertiesMenu, IDM_SECONDS, (Globals.bSeconds ? MF_CHECKED : MF_UNCHECKED));
79 CheckMenuItem(hPropertiesMenu, IDM_DATE, (Globals.bDate ? MF_CHECKED : MF_UNCHECKED));
80 }
81
82 static VOID CLOCK_UpdateWindowCaption(VOID)
83 {
84 CHAR szCaption[MAX_STRING_LEN];
85 int chars = 0;
86
87 /* Set frame caption */
88 if (Globals.bDate) {
89 chars = GetDateFormat(LOCALE_USER_DEFAULT, DATE_LONGDATE, NULL, NULL,
90 szCaption, sizeof(szCaption));
91 if (chars) {
92 --chars;
93 szCaption[chars++] = ' ';
94 szCaption[chars++] = '-';
95 szCaption[chars++] = ' ';
96 szCaption[chars] = '\0';
97 }
98 }
99 LoadString(0, IDS_CLOCK, szCaption + chars, sizeof(szCaption) - chars);
100 SetWindowText(Globals.hMainWnd, szCaption);
101 }
102
103 /***********************************************************************
104 *
105 * CLOCK_ResetTimer
106 */
107 static BOOL CLOCK_ResetTimer(void)
108 {
109 UINT period; /* milliseconds */
110
111 KillTimer(Globals.hMainWnd, TIMER_ID);
112
113 if (Globals.bSeconds)
114 if (Globals.bAnalog)
115 period = 50;
116 else
117 period = 500;
118 else
119 period = 1000;
120
121 if (!SetTimer (Globals.hMainWnd, TIMER_ID, period, NULL)) {
122 CHAR szApp[MAX_STRING_LEN];
123 LoadString(Globals.hInstance, IDS_CLOCK, szApp, sizeof(szApp));
124 MessageBox(0, "No available timers", szApp, MB_ICONEXCLAMATION | MB_OK);
125 return FALSE;
126 }
127 return TRUE;
128 }
129
130 /***********************************************************************
131 *
132 * CLOCK_ResetFont
133 */
134 static VOID CLOCK_ResetFont(VOID)
135 {
136 HFONT newfont;
137 HDC dc = GetDC(Globals.hMainWnd);
138 newfont = SizeFont(dc, Globals.MaxX, Globals.MaxY, Globals.bSeconds, &Globals.logfont);
139 if (newfont) {
140 DeleteObject(Globals.hFont);
141 Globals.hFont = newfont;
142 }
143
144 ReleaseDC(Globals.hMainWnd, dc);
145 }
146
147
148 /***********************************************************************
149 *
150 * CLOCK_ChooseFont
151 */
152 static VOID CLOCK_ChooseFont(VOID)
153 {
154 LOGFONT lf;
155 CHOOSEFONT cf;
156 memset(&cf, 0, sizeof(cf));
157 lf = Globals.logfont;
158 cf.lStructSize = sizeof(cf);
159 cf.hwndOwner = Globals.hMainWnd;
160 cf.lpLogFont = &lf;
161 cf.Flags = CF_SCREENFONTS | CF_INITTOLOGFONTSTRUCT;
162 if (ChooseFont(&cf)) {
163 Globals.logfont = lf;
164 CLOCK_ResetFont();
165 }
166 }
167
168 /***********************************************************************
169 *
170 * CLOCK_ToggleTitle
171 */
172 static VOID CLOCK_ToggleTitle(VOID)
173 {
174 /* Also shows/hides the menu */
175 LONG style = GetWindowLong(Globals.hMainWnd, GWL_STYLE);
176 if ((Globals.bWithoutTitle = !Globals.bWithoutTitle)) {
177 style = (style & ~WS_OVERLAPPEDWINDOW) | WS_POPUP|WS_THICKFRAME;
178 SetMenu(Globals.hMainWnd, 0);
179 }
180 else {
181 style = (style & ~(WS_POPUP|WS_THICKFRAME)) | WS_OVERLAPPEDWINDOW;
182 SetMenu(Globals.hMainWnd, Globals.hMainMenu);
183 SetWindowRgn(Globals.hMainWnd, 0, TRUE);
184 }
185 SetWindowLong(Globals.hMainWnd, GWL_STYLE, style);
186 SetWindowPos(Globals.hMainWnd, 0,0,0,0,0,
187 SWP_DRAWFRAME|SWP_NOMOVE|SWP_NOSIZE|SWP_NOZORDER);
188
189 CLOCK_UpdateMenuCheckmarks();
190 CLOCK_UpdateWindowCaption();
191 }
192
193 /***********************************************************************
194 *
195 * CLOCK_ToggleOnTop
196 */
197 static VOID CLOCK_ToggleOnTop(VOID)
198 {
199 if ((Globals.bAlwaysOnTop = !Globals.bAlwaysOnTop)) {
200 SetWindowPos(Globals.hMainWnd, HWND_TOPMOST, 0,0,0,0,
201 SWP_NOMOVE|SWP_NOSIZE);
202 }
203 else {
204 SetWindowPos(Globals.hMainWnd, HWND_NOTOPMOST, 0,0,0,0,
205 SWP_NOMOVE|SWP_NOSIZE);
206 }
207 CLOCK_UpdateMenuCheckmarks();
208 }
209 /***********************************************************************
210 *
211 * CLOCK_MenuCommand
212 *
213 * All handling of main menu events
214 */
215
216 static int CLOCK_MenuCommand (WPARAM wParam)
217 {
218 CHAR szApp[MAX_STRING_LEN];
219 CHAR szAppRelease[MAX_STRING_LEN];
220 switch (wParam) {
221 /* switch to analog */
222 case IDM_ANALOG: {
223 Globals.bAnalog = TRUE;
224 CLOCK_UpdateMenuCheckmarks();
225 CLOCK_ResetTimer();
226 InvalidateRect(Globals.hMainWnd, NULL, FALSE);
227 break;
228 }
229 /* switch to digital */
230 case IDM_DIGITAL: {
231 Globals.bAnalog = FALSE;
232 CLOCK_UpdateMenuCheckmarks();
233 CLOCK_ResetTimer();
234 CLOCK_ResetFont();
235 InvalidateRect(Globals.hMainWnd, NULL, FALSE);
236 break;
237 }
238 /* change font */
239 case IDM_FONT: {
240 CLOCK_ChooseFont();
241 break;
242 }
243 /* hide title bar */
244 case IDM_NOTITLE: {
245 CLOCK_ToggleTitle();
246 break;
247 }
248 /* always on top */
249 case IDM_ONTOP: {
250 CLOCK_ToggleOnTop();
251 break;
252 }
253 /* show or hide seconds */
254 case IDM_SECONDS: {
255 Globals.bSeconds = !Globals.bSeconds;
256 CLOCK_UpdateMenuCheckmarks();
257 CLOCK_ResetTimer();
258 if (!Globals.bAnalog)
259 CLOCK_ResetFont();
260 InvalidateRect(Globals.hMainWnd, NULL, FALSE);
261 break;
262 }
263 /* show or hide date */
264 case IDM_DATE: {
265 Globals.bDate = !Globals.bDate;
266 CLOCK_UpdateMenuCheckmarks();
267 CLOCK_UpdateWindowCaption();
268 break;
269 }
270 /* show license */
271 case IDM_LICENSE: {
272 WineLicense(Globals.hMainWnd);
273 break;
274 }
275 /* show warranties */
276 case IDM_NOWARRANTY: {
277 WineWarranty(Globals.hMainWnd);
278 break;
279 }
280 /* show "about" box */
281 case IDM_ABOUT: {
282 LoadString(Globals.hInstance, IDS_CLOCK, szApp, sizeof(szApp));
283 lstrcpy(szAppRelease,szApp);
284 ShellAbout(Globals.hMainWnd, szApp, szAppRelease, 0);
285 break;
286 }
287 }
288 return 0;
289 }
290
291 /***********************************************************************
292 *
293 * CLOCK_Paint
294 */
295 static VOID CLOCK_Paint(HWND hWnd)
296 {
297 PAINTSTRUCT ps;
298 HDC dcMem, dc;
299 HBITMAP bmMem, bmOld;
300
301 dc = BeginPaint(hWnd, &ps);
302
303 /* Use an offscreen dc to avoid flicker */
304 dcMem = CreateCompatibleDC(dc);
305 bmMem = CreateCompatibleBitmap(dc, ps.rcPaint.right - ps.rcPaint.left,
306 ps.rcPaint.bottom - ps.rcPaint.top);
307
308 bmOld = SelectObject(dcMem, bmMem);
309
310 SetViewportOrgEx(dcMem, -ps.rcPaint.left, -ps.rcPaint.top, NULL);
311 /* Erase the background */
312 FillRect(dcMem, &ps.rcPaint, GetSysColorBrush(COLOR_3DFACE));
313
314 if(Globals.bAnalog)
315 AnalogClock(dcMem, Globals.MaxX, Globals.MaxY, Globals.bSeconds, Globals.bWithoutTitle);
316 else
317 DigitalClock(dcMem, Globals.MaxX, Globals.MaxY, Globals.bSeconds, Globals.hFont);
318
319 /* Blit the changes to the screen */
320 BitBlt(dc,
321 ps.rcPaint.left, ps.rcPaint.top,
322 ps.rcPaint.right - ps.rcPaint.left, ps.rcPaint.bottom - ps.rcPaint.top,
323 dcMem,
324 ps.rcPaint.left, ps.rcPaint.top,
325 SRCCOPY);
326
327 SelectObject(dcMem, bmOld);
328 DeleteObject(bmMem);
329 DeleteDC(dcMem);
330
331 EndPaint(hWnd, &ps);
332 }
333
334 /***********************************************************************
335 *
336 * CLOCK_WndProc
337 */
338
339 static LRESULT WINAPI CLOCK_WndProc (HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
340 {
341 switch (msg) {
342 /* L button drag moves the window */
343 case WM_NCHITTEST: {
344 LRESULT ret = DefWindowProc (hWnd, msg, wParam, lParam);
345 if (ret == HTCLIENT)
346 ret = HTCAPTION;
347 return ret;
348 }
349
350 case WM_NCLBUTTONDBLCLK:
351 case WM_LBUTTONDBLCLK: {
352 CLOCK_ToggleTitle();
353 break;
354 }
355
356 case WM_PAINT: {
357 CLOCK_Paint(hWnd);
358 break;
359
360 }
361
362 case WM_SIZE: {
363 Globals.MaxX = LOWORD(lParam);
364 Globals.MaxY = HIWORD(lParam);
365 if (Globals.bAnalog && Globals.bWithoutTitle)
366 {
367 RECT rect;
368 INT diameter = min( Globals.MaxX, Globals.MaxY );
369 HRGN hrgn = CreateEllipticRgn( (Globals.MaxX - diameter) / 2,
370 (Globals.MaxY - diameter) / 2,
371 (Globals.MaxX + diameter) / 2,
372 (Globals.MaxY + diameter) / 2 );
373 GetWindowRect( hWnd, &rect );
374 MapWindowPoints( 0, hWnd, (LPPOINT)&rect, 2 );
375 OffsetRgn( hrgn, -rect.left, -rect.top );
376 SetWindowRgn( Globals.hMainWnd, hrgn, TRUE );
377 }
378 CLOCK_ResetFont();
379 break;
380 }
381
382 case WM_COMMAND: {
383 CLOCK_MenuCommand(wParam);
384 break;
385 }
386
387 case WM_TIMER: {
388 /* Could just invalidate what has changed,
389 * but it doesn't really seem worth the effort
390 */
391 InvalidateRect(Globals.hMainWnd, NULL, FALSE);
392 break;
393 }
394
395 case WM_DESTROY: {
396 PostQuitMessage (0);
397 break;
398 }
399
400 default:
401 return DefWindowProc (hWnd, msg, wParam, lParam);
402 }
403 return 0;
404 }
405
406
407 /***********************************************************************
408 *
409 * WinMain
410 */
411
412 int PASCAL WinMain (HINSTANCE hInstance, HINSTANCE prev, LPSTR cmdline, int show)
413 {
414 MSG msg;
415 WNDCLASS class;
416
417 static const char szClassName[] = "CLClass"; /* To make sure className >= 0x10000 */
418 static const char szWinName[] = "Clock";
419
420 /* Setup Globals */
421 memset(&Globals.hFont, 0, sizeof (Globals.hFont));
422 Globals.bAnalog = TRUE;
423 Globals.bSeconds = TRUE;
424
425 if (!prev){
426 class.style = CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS;
427 class.lpfnWndProc = CLOCK_WndProc;
428 class.cbClsExtra = 0;
429 class.cbWndExtra = 0;
430 class.hInstance = hInstance;
431 class.hIcon = LoadIcon (0, IDI_APPLICATION);
432 class.hCursor = LoadCursor (0, IDC_ARROW);
433 class.hbrBackground = 0;
434 class.lpszMenuName = 0;
435 class.lpszClassName = szClassName;
436 }
437
438 if (!RegisterClass (&class)) return FALSE;
439
440 Globals.MaxX = Globals.MaxY = INITIAL_WINDOW_SIZE;
441 Globals.hMainWnd = CreateWindow (szClassName, szWinName, WS_OVERLAPPEDWINDOW,
442 CW_USEDEFAULT, CW_USEDEFAULT,
443 Globals.MaxX, Globals.MaxY, 0,
444 0, hInstance, 0);
445
446 if (!CLOCK_ResetTimer())
447 return FALSE;
448
449 Globals.hMainMenu = LoadMenu(0, MAKEINTRESOURCE(MAIN_MENU));
450 SetMenu(Globals.hMainWnd, Globals.hMainMenu);
451 CLOCK_UpdateMenuCheckmarks();
452 CLOCK_UpdateWindowCaption();
453
454 ShowWindow (Globals.hMainWnd, show);
455 UpdateWindow (Globals.hMainWnd);
456
457 while (GetMessage(&msg, 0, 0, 0)) {
458 TranslateMessage(&msg);
459 DispatchMessage(&msg);
460 }
461
462 KillTimer(Globals.hMainWnd, TIMER_ID);
463 DeleteObject(Globals.hFont);
464
465 return 0;
466 }
467
This page was automatically generated by the
LXR engine.
Visit the LXR main site for more
information.