4 * Copyright 1998 Marcel Baur <mbaur@g26.ethz.ch>
6 * Clock is partially based on
7 * - Program Manager by Ulrich Schmied
8 * - rolex.c by Jim Peterson
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.
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.
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
34 #define INITIAL_WINDOW_SIZE 200
37 CLOCK_GLOBALS Globals
;
39 static VOID
WineLicense(HWND Wnd
)
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
);
47 static VOID
WineWarranty(HWND Wnd
)
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
);
55 static VOID
CLOCK_UpdateMenuCheckmarks(VOID
)
57 HMENU hPropertiesMenu
;
58 hPropertiesMenu
= GetSubMenu(Globals
.hMainMenu
, 0);
65 CheckMenuRadioItem(hPropertiesMenu
, IDM_ANALOG
, IDM_DIGITAL
, IDM_ANALOG
, MF_CHECKED
);
66 EnableMenuItem(hPropertiesMenu
, IDM_FONT
, MF_GRAYED
);
71 CheckMenuRadioItem(hPropertiesMenu
, IDM_ANALOG
, IDM_DIGITAL
, IDM_DIGITAL
, MF_CHECKED
);
72 EnableMenuItem(hPropertiesMenu
, IDM_FONT
, 0);
75 CheckMenuItem(hPropertiesMenu
, IDM_NOTITLE
, (Globals
.bWithoutTitle
? MF_CHECKED
: MF_UNCHECKED
));
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
));
82 static VOID
CLOCK_UpdateWindowCaption(VOID
)
84 CHAR szCaption
[MAX_STRING_LEN
];
87 /* Set frame caption */
89 chars
= GetDateFormat(LOCALE_USER_DEFAULT
, DATE_LONGDATE
, NULL
, NULL
,
90 szCaption
, sizeof(szCaption
));
93 szCaption
[chars
++] = ' ';
94 szCaption
[chars
++] = '-';
95 szCaption
[chars
++] = ' ';
96 szCaption
[chars
] = '\0';
99 LoadString(0, IDS_CLOCK
, szCaption
+ chars
, sizeof(szCaption
) - chars
);
100 SetWindowText(Globals
.hMainWnd
, szCaption
);
103 /***********************************************************************
107 static BOOL
CLOCK_ResetTimer(void)
109 UINT period
; /* milliseconds */
111 KillTimer(Globals
.hMainWnd
, TIMER_ID
);
113 if (Globals
.bSeconds
)
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
);
130 /***********************************************************************
134 static VOID
CLOCK_ResetFont(VOID
)
137 HDC dc
= GetDC(Globals
.hMainWnd
);
138 newfont
= SizeFont(dc
, Globals
.MaxX
, Globals
.MaxY
, Globals
.bSeconds
, &Globals
.logfont
);
140 DeleteObject(Globals
.hFont
);
141 Globals
.hFont
= newfont
;
144 ReleaseDC(Globals
.hMainWnd
, dc
);
148 /***********************************************************************
152 static VOID
CLOCK_ChooseFont(VOID
)
156 memset(&cf
, 0, sizeof(cf
));
157 lf
= Globals
.logfont
;
158 cf
.lStructSize
= sizeof(cf
);
159 cf
.hwndOwner
= Globals
.hMainWnd
;
161 cf
.Flags
= CF_SCREENFONTS
| CF_INITTOLOGFONTSTRUCT
;
162 if (ChooseFont(&cf
)) {
163 Globals
.logfont
= lf
;
168 /***********************************************************************
172 static VOID
CLOCK_ToggleTitle(VOID
)
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);
181 style
= (style
& ~(WS_POPUP
|WS_THICKFRAME
)) | WS_OVERLAPPEDWINDOW
;
182 SetMenu(Globals
.hMainWnd
, Globals
.hMainMenu
);
183 SetWindowRgn(Globals
.hMainWnd
, 0, TRUE
);
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
);
189 CLOCK_UpdateMenuCheckmarks();
190 CLOCK_UpdateWindowCaption();
193 /***********************************************************************
197 static VOID
CLOCK_ToggleOnTop(VOID
)
199 if ((Globals
.bAlwaysOnTop
= !Globals
.bAlwaysOnTop
)) {
200 SetWindowPos(Globals
.hMainWnd
, HWND_TOPMOST
, 0,0,0,0,
201 SWP_NOMOVE
|SWP_NOSIZE
);
204 SetWindowPos(Globals
.hMainWnd
, HWND_NOTOPMOST
, 0,0,0,0,
205 SWP_NOMOVE
|SWP_NOSIZE
);
207 CLOCK_UpdateMenuCheckmarks();
209 /***********************************************************************
213 * All handling of main menu events
216 static int CLOCK_MenuCommand (WPARAM wParam
)
218 CHAR szApp
[MAX_STRING_LEN
];
219 CHAR szAppRelease
[MAX_STRING_LEN
];
221 /* switch to analog */
223 Globals
.bAnalog
= TRUE
;
224 CLOCK_UpdateMenuCheckmarks();
226 InvalidateRect(Globals
.hMainWnd
, NULL
, FALSE
);
229 /* switch to digital */
231 Globals
.bAnalog
= FALSE
;
232 CLOCK_UpdateMenuCheckmarks();
235 InvalidateRect(Globals
.hMainWnd
, NULL
, FALSE
);
253 /* show or hide seconds */
255 Globals
.bSeconds
= !Globals
.bSeconds
;
256 CLOCK_UpdateMenuCheckmarks();
258 if (!Globals
.bAnalog
)
260 InvalidateRect(Globals
.hMainWnd
, NULL
, FALSE
);
263 /* show or hide date */
265 Globals
.bDate
= !Globals
.bDate
;
266 CLOCK_UpdateMenuCheckmarks();
267 CLOCK_UpdateWindowCaption();
272 WineLicense(Globals
.hMainWnd
);
275 /* show warranties */
276 case IDM_NOWARRANTY
: {
277 WineWarranty(Globals
.hMainWnd
);
280 /* show "about" box */
282 LoadString(Globals
.hInstance
, IDS_CLOCK
, szApp
, sizeof(szApp
));
283 lstrcpy(szAppRelease
,szApp
);
284 ShellAbout(Globals
.hMainWnd
, szApp
, szAppRelease
, 0);
291 /***********************************************************************
295 static VOID
CLOCK_Paint(HWND hWnd
)
299 HBITMAP bmMem
, bmOld
;
301 dc
= BeginPaint(hWnd
, &ps
);
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
);
308 bmOld
= SelectObject(dcMem
, bmMem
);
310 SetViewportOrgEx(dcMem
, -ps
.rcPaint
.left
, -ps
.rcPaint
.top
, NULL
);
311 /* Erase the background */
312 FillRect(dcMem
, &ps
.rcPaint
, GetStockObject(LTGRAY_BRUSH
));
315 AnalogClock(dcMem
, Globals
.MaxX
, Globals
.MaxY
, Globals
.bSeconds
, Globals
.bWithoutTitle
);
317 DigitalClock(dcMem
, Globals
.MaxX
, Globals
.MaxY
, Globals
.bSeconds
, Globals
.hFont
);
319 /* Blit the changes to the screen */
321 ps
.rcPaint
.left
, ps
.rcPaint
.top
,
322 ps
.rcPaint
.right
- ps
.rcPaint
.left
, ps
.rcPaint
.bottom
- ps
.rcPaint
.top
,
324 ps
.rcPaint
.left
, ps
.rcPaint
.top
,
327 SelectObject(dcMem
, bmOld
);
334 /***********************************************************************
339 static LRESULT WINAPI
CLOCK_WndProc (HWND hWnd
, UINT msg
, WPARAM wParam
, LPARAM lParam
)
342 /* L button drag moves the window */
344 LRESULT ret
= DefWindowProc (hWnd
, msg
, wParam
, lParam
);
350 case WM_NCLBUTTONDBLCLK
:
351 case WM_LBUTTONDBLCLK
: {
363 Globals
.MaxX
= LOWORD(lParam
);
364 Globals
.MaxY
= HIWORD(lParam
);
365 if (Globals
.bAnalog
&& Globals
.bWithoutTitle
)
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
);
383 CLOCK_MenuCommand(wParam
);
388 /* Could just invalidate what has changed,
389 * but it doesn't really seem worth the effort
391 InvalidateRect(Globals
.hMainWnd
, NULL
, FALSE
);
401 return DefWindowProc (hWnd
, msg
, wParam
, lParam
);
407 /***********************************************************************
412 int PASCAL
WinMain (HINSTANCE hInstance
, HINSTANCE prev
, LPSTR cmdline
, int show
)
417 static const char szClassName
[] = "CLClass"; /* To make sure className >= 0x10000 */
418 static const char szWinName
[] = "Clock";
421 memset(&Globals
.hFont
, 0, sizeof (Globals
.hFont
));
422 Globals
.bAnalog
= TRUE
;
423 Globals
.bSeconds
= TRUE
;
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
;
438 if (!RegisterClass (&class)) return FALSE
;
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,
446 if (!CLOCK_ResetTimer())
449 Globals
.hMainMenu
= LoadMenu(0, MAKEINTRESOURCE(MAIN_MENU
));
450 SetMenu(Globals
.hMainWnd
, Globals
.hMainMenu
);
451 CLOCK_UpdateMenuCheckmarks();
452 CLOCK_UpdateWindowCaption();
454 ShowWindow (Globals
.hMainWnd
, show
);
455 UpdateWindow (Globals
.hMainWnd
);
457 while (GetMessage(&msg
, 0, 0, 0)) {
458 TranslateMessage(&msg
);
459 DispatchMessage(&msg
);
462 KillTimer(Globals
.hMainWnd
, TIMER_ID
);
463 DeleteObject(Globals
.hFont
);