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);
184 SetWindowLong(Globals.hMainWnd, GWL_STYLE, style);
185 SetWindowPos(Globals.hMainWnd, 0,0,0,0,0,
186 SWP_DRAWFRAME|SWP_NOMOVE|SWP_NOSIZE|SWP_NOZORDER);
188 CLOCK_UpdateMenuCheckmarks();
189 CLOCK_UpdateWindowCaption();
192 /***********************************************************************
196 static VOID CLOCK_ToggleOnTop(VOID)
198 if ((Globals.bAlwaysOnTop = !Globals.bAlwaysOnTop)) {
199 SetWindowPos(Globals.hMainWnd, HWND_TOPMOST, 0,0,0,0,
200 SWP_NOMOVE|SWP_NOSIZE);
203 SetWindowPos(Globals.hMainWnd, HWND_NOTOPMOST, 0,0,0,0,
204 SWP_NOMOVE|SWP_NOSIZE);
206 CLOCK_UpdateMenuCheckmarks();
208 /***********************************************************************
212 * All handling of main menu events
215 static int CLOCK_MenuCommand (WPARAM wParam)
217 CHAR szApp[MAX_STRING_LEN];
218 CHAR szAppRelease[MAX_STRING_LEN];
220 /* switch to analog */
222 Globals.bAnalog = TRUE;
223 CLOCK_UpdateMenuCheckmarks();
225 InvalidateRect(Globals.hMainWnd, NULL, FALSE);
228 /* switch to digital */
230 Globals.bAnalog = FALSE;
231 CLOCK_UpdateMenuCheckmarks();
234 InvalidateRect(Globals.hMainWnd, NULL, FALSE);
252 /* show or hide seconds */
254 Globals.bSeconds = !Globals.bSeconds;
255 CLOCK_UpdateMenuCheckmarks();
257 if (!Globals.bAnalog)
259 InvalidateRect(Globals.hMainWnd, NULL, FALSE);
262 /* show or hide date */
264 Globals.bDate = !Globals.bDate;
265 CLOCK_UpdateMenuCheckmarks();
266 CLOCK_UpdateWindowCaption();
271 WineLicense(Globals.hMainWnd);
274 /* show warranties */
275 case IDM_NOWARRANTY: {
276 WineWarranty(Globals.hMainWnd);
279 /* show "about" box */
281 LoadString(Globals.hInstance, IDS_CLOCK, szApp, sizeof(szApp));
282 lstrcpy(szAppRelease,szApp);
283 ShellAbout(Globals.hMainWnd, szApp, szAppRelease, 0);
290 /***********************************************************************
294 static VOID CLOCK_Paint(HWND hWnd)
298 HBITMAP bmMem, bmOld;
300 dc = BeginPaint(hWnd, &ps);
302 /* Use an offscreen dc to avoid flicker */
303 dcMem = CreateCompatibleDC(dc);
304 bmMem = CreateCompatibleBitmap(dc, ps.rcPaint.right - ps.rcPaint.left,
305 ps.rcPaint.bottom - ps.rcPaint.top);
307 bmOld = SelectObject(dcMem, bmMem);
309 SetViewportOrgEx(dcMem, -ps.rcPaint.left, -ps.rcPaint.top, NULL);
310 /* Erase the background */
311 FillRect(dcMem, &ps.rcPaint, GetStockObject(LTGRAY_BRUSH));
314 AnalogClock(dcMem, Globals.MaxX, Globals.MaxY, Globals.bSeconds);
316 DigitalClock(dcMem, Globals.MaxX, Globals.MaxY, Globals.bSeconds, Globals.hFont);
318 /* Blit the changes to the screen */
320 ps.rcPaint.left, ps.rcPaint.top,
321 ps.rcPaint.right - ps.rcPaint.left, ps.rcPaint.bottom - ps.rcPaint.top,
323 ps.rcPaint.left, ps.rcPaint.top,
326 SelectObject(dcMem, bmOld);
333 /***********************************************************************
338 static LRESULT WINAPI CLOCK_WndProc (HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
341 /* L button drag moves the window */
343 LRESULT ret = DefWindowProc (hWnd, msg, wParam, lParam);
349 case WM_NCLBUTTONDBLCLK:
350 case WM_LBUTTONDBLCLK: {
362 Globals.MaxX = LOWORD(lParam);
363 Globals.MaxY = HIWORD(lParam);
369 CLOCK_MenuCommand(wParam);
374 /* Could just invalidate what has changed,
375 * but it doesn't really seem worth the effort
377 InvalidateRect(Globals.hMainWnd, NULL, FALSE);
387 return DefWindowProc (hWnd, msg, wParam, lParam);
393 /***********************************************************************
398 int PASCAL WinMain (HINSTANCE hInstance, HINSTANCE prev, LPSTR cmdline, int show)
403 static const char szClassName[] = "CLClass"; /* To make sure className >= 0x10000 */
404 static const char szWinName[] = "Clock";
407 memset(&Globals.hFont, 0, sizeof (Globals.hFont));
408 Globals.bAnalog = TRUE;
409 Globals.bSeconds = TRUE;
412 class.style = CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS;
413 class.lpfnWndProc = CLOCK_WndProc;
414 class.cbClsExtra = 0;
415 class.cbWndExtra = 0;
416 class.hInstance = hInstance;
417 class.hIcon = LoadIcon (0, IDI_APPLICATION);
418 class.hCursor = LoadCursor (0, IDC_ARROW);
419 class.hbrBackground = 0;
420 class.lpszMenuName = 0;
421 class.lpszClassName = szClassName;
424 if (!RegisterClass (&class)) return FALSE;
426 Globals.MaxX = Globals.MaxY = INITIAL_WINDOW_SIZE;
427 Globals.hMainWnd = CreateWindow (szClassName, szWinName, WS_OVERLAPPEDWINDOW,
428 CW_USEDEFAULT, CW_USEDEFAULT,
429 Globals.MaxX, Globals.MaxY, 0,
432 if (!CLOCK_ResetTimer())
435 Globals.hMainMenu = LoadMenu(0, MAKEINTRESOURCE(MAIN_MENU));
436 SetMenu(Globals.hMainWnd, Globals.hMainMenu);
437 CLOCK_UpdateMenuCheckmarks();
438 CLOCK_UpdateWindowCaption();
440 ShowWindow (Globals.hMainWnd, show);
441 UpdateWindow (Globals.hMainWnd);
443 while (GetMessage(&msg, 0, 0, 0)) {
444 TranslateMessage(&msg);
445 DispatchMessage(&msg);
448 KillTimer(Globals.hMainWnd, TIMER_ID);
449 DeleteObject(Globals.hFont);