Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
wine-mirror
GitHub Repository: wine-mirror/wine
Path: blob/master/programs/clock/main.c
4389 views
1
/*
2
* Clock
3
*
4
* Copyright 1998 Marcel Baur <[email protected]>
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 "commctrl.h"
30
#include "commdlg.h"
31
#include "shellapi.h"
32
33
#include "main.h"
34
#include "winclock.h"
35
36
#define INITIAL_WINDOW_SIZE 200
37
#define TIMER_ID 1
38
39
CLOCK_GLOBALS Globals;
40
41
static VOID CLOCK_UpdateMenuCheckmarks(VOID)
42
{
43
HMENU hPropertiesMenu;
44
hPropertiesMenu = GetSubMenu(Globals.hMainMenu, 0);
45
if (!hPropertiesMenu)
46
return;
47
48
if(Globals.bAnalog) {
49
50
/* analog clock */
51
CheckMenuRadioItem(hPropertiesMenu, IDM_ANALOG, IDM_DIGITAL, IDM_ANALOG, MF_CHECKED);
52
EnableMenuItem(hPropertiesMenu, IDM_FONT, MF_GRAYED);
53
}
54
else
55
{
56
/* digital clock */
57
CheckMenuRadioItem(hPropertiesMenu, IDM_ANALOG, IDM_DIGITAL, IDM_DIGITAL, MF_CHECKED);
58
EnableMenuItem(hPropertiesMenu, IDM_FONT, 0);
59
}
60
61
CheckMenuItem(hPropertiesMenu, IDM_NOTITLE, (Globals.bWithoutTitle ? MF_CHECKED : MF_UNCHECKED));
62
63
CheckMenuItem(hPropertiesMenu, IDM_ONTOP, (Globals.bAlwaysOnTop ? MF_CHECKED : MF_UNCHECKED));
64
CheckMenuItem(hPropertiesMenu, IDM_SECONDS, (Globals.bSeconds ? MF_CHECKED : MF_UNCHECKED));
65
CheckMenuItem(hPropertiesMenu, IDM_DATE, (Globals.bDate ? MF_CHECKED : MF_UNCHECKED));
66
}
67
68
static VOID CLOCK_UpdateWindowCaption(VOID)
69
{
70
WCHAR szCaption[MAX_STRING_LEN];
71
int chars = 0;
72
73
/* Set frame caption */
74
if (Globals.bDate) {
75
chars = GetDateFormatW(LOCALE_USER_DEFAULT, DATE_LONGDATE, NULL, NULL,
76
szCaption, ARRAY_SIZE(szCaption));
77
if (chars) {
78
--chars;
79
szCaption[chars++] = ' ';
80
szCaption[chars++] = '-';
81
szCaption[chars++] = ' ';
82
szCaption[chars] = '\0';
83
}
84
}
85
LoadStringW(0, IDS_CLOCK, szCaption + chars, MAX_STRING_LEN - chars);
86
SetWindowTextW(Globals.hMainWnd, szCaption);
87
}
88
89
/***********************************************************************
90
*
91
* CLOCK_ResetTimer
92
*/
93
static BOOL CLOCK_ResetTimer(void)
94
{
95
UINT period; /* milliseconds */
96
97
KillTimer(Globals.hMainWnd, TIMER_ID);
98
99
if (Globals.bSeconds)
100
if (Globals.bAnalog)
101
period = 50;
102
else
103
period = 500;
104
else
105
period = 1000;
106
107
if (!SetTimer (Globals.hMainWnd, TIMER_ID, period, NULL)) {
108
WCHAR szApp[MAX_STRING_LEN];
109
LoadStringW(Globals.hInstance, IDS_CLOCK, szApp, MAX_STRING_LEN);
110
MessageBoxW(0, L"No available timers", szApp, MB_ICONEXCLAMATION | MB_OK);
111
return FALSE;
112
}
113
return TRUE;
114
}
115
116
/***********************************************************************
117
*
118
* CLOCK_ResetFont
119
*/
120
static VOID CLOCK_ResetFont(VOID)
121
{
122
HFONT newfont;
123
HDC dc = GetDC(Globals.hMainWnd);
124
newfont = SizeFont(dc, Globals.MaxX, Globals.MaxY, Globals.bSeconds, &Globals.logfont);
125
if (newfont) {
126
DeleteObject(Globals.hFont);
127
Globals.hFont = newfont;
128
}
129
130
ReleaseDC(Globals.hMainWnd, dc);
131
}
132
133
134
/***********************************************************************
135
*
136
* CLOCK_ChooseFont
137
*/
138
static VOID CLOCK_ChooseFont(VOID)
139
{
140
LOGFONTW lf;
141
CHOOSEFONTW cf;
142
memset(&cf, 0, sizeof(cf));
143
lf = Globals.logfont;
144
cf.lStructSize = sizeof(cf);
145
cf.hwndOwner = Globals.hMainWnd;
146
cf.lpLogFont = &lf;
147
cf.Flags = CF_SCREENFONTS | CF_INITTOLOGFONTSTRUCT | CF_NOVERTFONTS;
148
if (ChooseFontW(&cf)) {
149
Globals.logfont = lf;
150
CLOCK_ResetFont();
151
}
152
}
153
154
/***********************************************************************
155
*
156
* CLOCK_ToggleTitle
157
*/
158
static VOID CLOCK_ToggleTitle(VOID)
159
{
160
/* Also shows/hides the menu */
161
LONG style = GetWindowLongW(Globals.hMainWnd, GWL_STYLE);
162
if ((Globals.bWithoutTitle = !Globals.bWithoutTitle)) {
163
style = (style & ~WS_OVERLAPPEDWINDOW) | WS_POPUP|WS_THICKFRAME;
164
SetMenu(Globals.hMainWnd, 0);
165
}
166
else {
167
style = (style & ~(WS_POPUP|WS_THICKFRAME)) | WS_OVERLAPPEDWINDOW;
168
SetMenu(Globals.hMainWnd, Globals.hMainMenu);
169
SetWindowRgn(Globals.hMainWnd, 0, TRUE);
170
}
171
SetWindowLongW(Globals.hMainWnd, GWL_STYLE, style);
172
SetWindowPos(Globals.hMainWnd, 0,0,0,0,0,
173
SWP_DRAWFRAME|SWP_NOMOVE|SWP_NOSIZE|SWP_NOZORDER);
174
175
CLOCK_UpdateMenuCheckmarks();
176
CLOCK_UpdateWindowCaption();
177
}
178
179
/***********************************************************************
180
*
181
* CLOCK_ToggleOnTop
182
*/
183
static VOID CLOCK_ToggleOnTop(VOID)
184
{
185
if ((Globals.bAlwaysOnTop = !Globals.bAlwaysOnTop)) {
186
SetWindowPos(Globals.hMainWnd, HWND_TOPMOST, 0,0,0,0,
187
SWP_NOMOVE|SWP_NOSIZE);
188
}
189
else {
190
SetWindowPos(Globals.hMainWnd, HWND_NOTOPMOST, 0,0,0,0,
191
SWP_NOMOVE|SWP_NOSIZE);
192
}
193
CLOCK_UpdateMenuCheckmarks();
194
}
195
/***********************************************************************
196
*
197
* CLOCK_MenuCommand
198
*
199
* All handling of main menu events
200
*/
201
202
static int CLOCK_MenuCommand (WPARAM wParam)
203
{
204
WCHAR szApp[MAX_STRING_LEN];
205
WCHAR szAppRelease[MAX_STRING_LEN];
206
switch (wParam) {
207
/* switch to analog */
208
case IDM_ANALOG: {
209
Globals.bAnalog = TRUE;
210
CLOCK_UpdateMenuCheckmarks();
211
CLOCK_ResetTimer();
212
InvalidateRect(Globals.hMainWnd, NULL, FALSE);
213
break;
214
}
215
/* switch to digital */
216
case IDM_DIGITAL: {
217
Globals.bAnalog = FALSE;
218
CLOCK_UpdateMenuCheckmarks();
219
CLOCK_ResetTimer();
220
CLOCK_ResetFont();
221
InvalidateRect(Globals.hMainWnd, NULL, FALSE);
222
break;
223
}
224
/* change font */
225
case IDM_FONT: {
226
CLOCK_ChooseFont();
227
break;
228
}
229
/* hide title bar */
230
case IDM_NOTITLE: {
231
CLOCK_ToggleTitle();
232
break;
233
}
234
/* always on top */
235
case IDM_ONTOP: {
236
CLOCK_ToggleOnTop();
237
break;
238
}
239
/* show or hide seconds */
240
case IDM_SECONDS: {
241
Globals.bSeconds = !Globals.bSeconds;
242
CLOCK_UpdateMenuCheckmarks();
243
CLOCK_ResetTimer();
244
if (!Globals.bAnalog)
245
CLOCK_ResetFont();
246
InvalidateRect(Globals.hMainWnd, NULL, FALSE);
247
break;
248
}
249
/* show or hide date */
250
case IDM_DATE: {
251
Globals.bDate = !Globals.bDate;
252
CLOCK_UpdateMenuCheckmarks();
253
CLOCK_UpdateWindowCaption();
254
break;
255
}
256
/* show "about" box */
257
case IDM_ABOUT: {
258
LoadStringW(Globals.hInstance, IDS_CLOCK, szApp, ARRAY_SIZE(szApp));
259
lstrcpyW(szAppRelease,szApp);
260
ShellAboutW(Globals.hMainWnd, szApp, szAppRelease, 0);
261
break;
262
}
263
}
264
return 0;
265
}
266
267
/***********************************************************************
268
*
269
* CLOCK_Paint
270
*/
271
static VOID CLOCK_Paint(HWND hWnd)
272
{
273
PAINTSTRUCT ps;
274
HDC dcMem, dc;
275
HBITMAP bmMem, bmOld;
276
277
dc = BeginPaint(hWnd, &ps);
278
279
/* Use an offscreen dc to avoid flicker */
280
dcMem = CreateCompatibleDC(dc);
281
bmMem = CreateCompatibleBitmap(dc, ps.rcPaint.right - ps.rcPaint.left,
282
ps.rcPaint.bottom - ps.rcPaint.top);
283
284
bmOld = SelectObject(dcMem, bmMem);
285
286
SetViewportOrgEx(dcMem, -ps.rcPaint.left, -ps.rcPaint.top, NULL);
287
/* Erase the background */
288
FillRect(dcMem, &ps.rcPaint, GetSysColorBrush(COLOR_3DFACE));
289
290
if(Globals.bAnalog)
291
AnalogClock(dcMem, Globals.MaxX, Globals.MaxY, Globals.bSeconds, Globals.bWithoutTitle);
292
else
293
DigitalClock(dcMem, Globals.MaxX, Globals.MaxY, Globals.bSeconds, Globals.hFont);
294
295
/* Blit the changes to the screen */
296
BitBlt(dc,
297
ps.rcPaint.left, ps.rcPaint.top,
298
ps.rcPaint.right - ps.rcPaint.left, ps.rcPaint.bottom - ps.rcPaint.top,
299
dcMem,
300
ps.rcPaint.left, ps.rcPaint.top,
301
SRCCOPY);
302
303
SelectObject(dcMem, bmOld);
304
DeleteObject(bmMem);
305
DeleteDC(dcMem);
306
307
EndPaint(hWnd, &ps);
308
}
309
310
/***********************************************************************
311
*
312
* CLOCK_WndProc
313
*/
314
315
static LRESULT WINAPI CLOCK_WndProc (HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
316
{
317
switch (msg) {
318
/* L button drag moves the window */
319
case WM_NCHITTEST: {
320
LRESULT ret = DefWindowProcW(hWnd, msg, wParam, lParam);
321
if (ret == HTCLIENT)
322
ret = HTCAPTION;
323
return ret;
324
}
325
326
case WM_NCLBUTTONDBLCLK:
327
case WM_LBUTTONDBLCLK: {
328
CLOCK_ToggleTitle();
329
break;
330
}
331
332
case WM_PAINT: {
333
CLOCK_Paint(hWnd);
334
break;
335
336
}
337
338
case WM_SIZE: {
339
Globals.MaxX = LOWORD(lParam);
340
Globals.MaxY = HIWORD(lParam);
341
if (Globals.bAnalog && Globals.bWithoutTitle)
342
{
343
RECT rect;
344
INT diameter = min( Globals.MaxX, Globals.MaxY );
345
HRGN hrgn = CreateEllipticRgn( (Globals.MaxX - diameter) / 2,
346
(Globals.MaxY - diameter) / 2,
347
(Globals.MaxX + diameter) / 2,
348
(Globals.MaxY + diameter) / 2 );
349
GetWindowRect( hWnd, &rect );
350
MapWindowPoints( 0, hWnd, (LPPOINT)&rect, 2 );
351
OffsetRgn( hrgn, -rect.left, -rect.top );
352
SetWindowRgn( Globals.hMainWnd, hrgn, TRUE );
353
}
354
CLOCK_ResetFont();
355
break;
356
}
357
358
case WM_COMMAND: {
359
CLOCK_MenuCommand(wParam);
360
break;
361
}
362
363
case WM_TIMER: {
364
/* Could just invalidate what has changed,
365
* but it doesn't really seem worth the effort
366
*/
367
InvalidateRect(Globals.hMainWnd, NULL, FALSE);
368
break;
369
}
370
371
case WM_DESTROY: {
372
PostQuitMessage (0);
373
break;
374
}
375
376
default:
377
return DefWindowProcW(hWnd, msg, wParam, lParam);
378
}
379
return 0;
380
}
381
382
383
/***********************************************************************
384
*
385
* WinMain
386
*/
387
388
int PASCAL WinMain (HINSTANCE hInstance, HINSTANCE prev, LPSTR cmdline, int show)
389
{
390
MSG msg;
391
WNDCLASSW class;
392
393
InitCommonControls();
394
395
/* Setup Globals */
396
memset(&Globals.hFont, 0, sizeof (Globals.hFont));
397
Globals.bAnalog = TRUE;
398
Globals.bSeconds = TRUE;
399
400
if (!prev){
401
class.style = CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS;
402
class.lpfnWndProc = CLOCK_WndProc;
403
class.cbClsExtra = 0;
404
class.cbWndExtra = 0;
405
class.hInstance = hInstance;
406
class.hIcon = LoadIconW(0, (LPCWSTR)IDI_APPLICATION);
407
class.hCursor = LoadCursorW(0, (LPCWSTR)IDC_ARROW);
408
class.hbrBackground = 0;
409
class.lpszMenuName = 0;
410
class.lpszClassName = L"CLClass";
411
}
412
413
if (!RegisterClassW(&class)) return FALSE;
414
415
Globals.MaxX = Globals.MaxY = INITIAL_WINDOW_SIZE;
416
Globals.hMainWnd = CreateWindowW(L"CLClass", L"Clock", WS_OVERLAPPEDWINDOW,
417
CW_USEDEFAULT, CW_USEDEFAULT,
418
Globals.MaxX, Globals.MaxY, 0,
419
0, hInstance, 0);
420
421
if (!CLOCK_ResetTimer())
422
return FALSE;
423
424
Globals.hMainMenu = LoadMenuW(0, MAKEINTRESOURCEW(MAIN_MENU));
425
SetMenu(Globals.hMainWnd, Globals.hMainMenu);
426
CLOCK_UpdateMenuCheckmarks();
427
CLOCK_UpdateWindowCaption();
428
429
ShowWindow (Globals.hMainWnd, show);
430
UpdateWindow (Globals.hMainWnd);
431
432
while (GetMessageW(&msg, 0, 0, 0)) {
433
TranslateMessage(&msg);
434
DispatchMessageW(&msg);
435
}
436
437
KillTimer(Globals.hMainWnd, TIMER_ID);
438
DeleteObject(Globals.hFont);
439
440
return 0;
441
}
442
443