|
|
1.1 root 1: /*
2: * CLOCK.C - Windows Clock
3: *
4: */
5:
6: #include <time.h>
7: #include <stdlib.h>
8: #include <stdio.h>
9: #include <string.h>
10: #include "windows.h"
11: #include "windowsx.h"
12: #include <ddeml.h>
13: #include "clock.h"
14: // #include "shellapi.h"
15:
16:
17: DWORD idInst = 0;
18: BOOL bIconic = FALSE;
19: BOOL bColor = TRUE;
20: BOOL bNewFont = TRUE;
21:
22: CLOCKDISPSTRUCT ClockDisp;
23:
24: TRIG CirTab[] = { // circle sin, cos, table
25: { 0, -7999 },
26: { 836, -7956 },
27: { 1663, -7825 },
28: { 2472, -7608 },
29: { 3253, -7308 },
30: { 3999, -6928 },
31: { 4702, -6472 },
32: { 5353, -5945 },
33: { 5945, -5353 },
34: { 6472, -4702 },
35: { 6928, -4000 },
36: { 7308, -3253 },
37: { 7608, -2472 },
38: { 7825, -1663 },
39: { 7956, -836 },
40:
41: { 8000, 0 },
42: { 7956, 836 },
43: { 7825, 1663 },
44: { 7608, 2472 },
45: { 7308, 3253 },
46: { 6928, 4000 },
47: { 6472, 4702 },
48: { 5945, 5353 },
49: { 5353, 5945 },
50: { 4702, 6472 },
51: { 3999, 6928 },
52: { 3253, 7308 },
53: { 2472, 7608 },
54: { 1663, 7825 },
55: { 836, 7956 },
56:
57: { 0, 7999 },
58: { -836, 7956 },
59: { -1663, 7825 },
60: { -2472, 7608 },
61: { -3253, 7308 },
62: { -4000, 6928 },
63: { -4702, 6472 },
64: { -5353, 5945 },
65: { -5945, 5353 },
66: { -6472, 4702 },
67: { -6928, 3999 },
68: { -7308, 3253 },
69: { -7608, 2472 },
70: { -7825, 1663 },
71: { -7956, 836 },
72:
73: { -7999, -0 },
74: { -7956, -836 },
75: { -7825, -1663 },
76: { -7608, -2472 },
77: { -7308, -3253 },
78: { -6928, -4000 },
79: { -6472, -4702 },
80: { -5945, -5353 },
81: { -5353, -5945 },
82: { -4702, -6472 },
83: { -3999, -6928 },
84: { -3253, -7308 },
85: { -2472, -7608 },
86: { -1663, -7825 },
87: { -836 , -7956 }
88: };
89:
90: HANDLE hInst;
91: HWND hWindow;
92:
93: HBRUSH hbrBackground;
94: HBRUSH hbrColorWindow;
95: HBRUSH hbrColorBlack;
96: HBRUSH hbrForeground;
97: HFONT hFont;
98: HPEN hpenForeground;
99: HPEN hpenBackground;
100:
101: INT nLeadZero = 0;
102: INT TimerID = 1; /* number used for timer-id */
103: INT clockRadius;
104: INT HorzRes;
105: INT VertRes;
106:
107: LONG aspectD;
108: LONG aspectN;
109:
110: CHAR szBuffer[BUFLEN]; /* buffer for stringtable stuff */
111: CHAR szFontFile[20];
112: CHAR szIniFile[20];
113: CHAR szSection[30];
114:
115: POINT clockCenter;
116:
117: TIME oTime;
118:
119: RECT clockRect;
120: RECT rCoordRect;
121:
122: HDDEDATA EXPENTRY DdeCallback(WORD usType, WORD usFmt, HCONV hConv, HSZ hsz1,
123: HSZ hsz2, HDDEDATA hData, DWORD lData1, DWORD lData2);
124: HSZ hszTime, hszNow, hszClock; /* Hszs for DDEML use */
125:
126: /*
127: * Function Prototypes
128: */
129:
130: LONG APIENTRY ClockWndProc(register HWND hWnd, UINT message, WPARAM wParam, LONG lParam);
131:
132: void NEAR PASCAL ClockCreate(HWND hWnd);
133: BOOL NEAR PASCAL ClockInit(HANDLE hInstance);
134: void NEAR PASCAL ClockPaint(HWND hWnd, register HDC hDC, INT hint);
135: void NEAR PASCAL ClockSize(register HWND hWnd,INT newWidth,INT newHeight, WORD SizeWord);
136: void NEAR PASCAL ClockTimer(HWND hWnd, UINT msg);
137: void NEAR PASCAL CompClockDim(void);
138: void NEAR PASCAL CreateTools(void);
139: void NEAR PASCAL DeleteTools(void);
140: void NEAR PASCAL DrawBorder(HWND hWnd, register HDC hDC);
141: void NEAR PASCAL DrawFace(HDC hDC);
142: void NEAR PASCAL DrawHand(register HDC hDC, INT pos, HPEN hPen, INT scale, INT patMode);
143: void NEAR PASCAL DrawFatHand(register HDC hDC, INT pos, HPEN hPen, BOOL hHand);
144: void NEAR PASCAL FormatInit(register HANDLE hInstance, BOOL fModeChange);
145: void NEAR PASCAL SizeFont(HWND hWnd, INT newHeight, INT newWidth, INT wlen);
146:
147:
148:
149: /*
150: * CreateTools()
151: */
152:
153: void NEAR PASCAL CreateTools(void)
154:
155: {
156: hbrForeground = CreateSolidBrush(GetSysColor(COLOR_WINDOWTEXT));
157: hbrColorWindow = CreateSolidBrush(GetSysColor(COLOR_WINDOW));
158: hbrColorBlack = CreateSolidBrush(0L);
159: hbrBackground = hbrColorWindow;
160: hpenForeground = CreatePen(0, 1, GetSysColor(COLOR_WINDOWTEXT));
161: hpenBackground = CreatePen(0, 1, GetSysColor(COLOR_WINDOW));
162: }
163:
164:
165: /*
166: * DeleteTools()
167: */
168:
169: void NEAR PASCAL DeleteTools(void)
170:
171: {
172: DeleteObject(hbrForeground);
173: DeleteObject(hbrColorWindow);
174: DeleteObject(hbrColorBlack);
175: DeleteObject(hpenForeground);
176: DeleteObject(hpenBackground);
177: }
178:
179:
180: /*
181: * SizeFont() - size font according to window size
182: */
183:
184: void NEAR PASCAL SizeFont(HWND hWnd, INT newHeight, INT newWidth, INT wlen)
185: {
186: register HDC hDC;
187: TEXTMETRIC tm;
188: LOGFONT FontStruct;
189:
190: hDC = GetDC(hWnd);
191: GetTextMetrics(hDC, &tm);
192:
193: if (ClockDisp.wFormat == IDM_DIGITAL)
194: {
195: if (hFont != NULL)
196: DeleteObject(hFont);
197:
198: FontStruct.lfUnderline = FALSE;
199: FontStruct.lfStrikeOut = FALSE;
200: FontStruct.lfItalic = FALSE;
201: FontStruct.lfEscapement = FALSE;
202: FontStruct.lfOrientation = FALSE;
203: FontStruct.lfOutPrecision = OUT_DEFAULT_PRECIS;
204: FontStruct.lfClipPrecision = CLIP_DEFAULT_PRECIS;
205:
206: /* Note that the numbers used in this formula depend on the
207: * size of the numbers in the fonts which are 12 vert, 7 horz.
208: */
209: if (!bIconic)
210: {
211: FontStruct.lfHeight = (SHORT)min(newHeight/2, 45);
212:
213: /* The formula at the end is somewhat empirical. */
214: FontStruct.lfWidth = (SHORT)min(25, newWidth/(wlen*3/2));
215:
216: /* This if is here because of a problem where: if a clock
217: * existed with a maximum size font, any new clock with a
218: * smaller client area would get the same font that would not
219: * fit in the Window. So here, if the width does not match
220: * maximum font dimensions, don't use the maximum height.
221: */
222: if (FontStruct.lfWidth != 25 && FontStruct.lfHeight == 45)
223: FontStruct.lfHeight = 40;
224: }
225: else
226: {
227: FontStruct.lfHeight = (SHORT)(newHeight/3);
228: FontStruct.lfWidth = (SHORT)(newWidth/5);
229: }
230:
231: FontStruct.lfCharSet = ANSI_CHARSET;
232: FontStruct.lfQuality = DRAFT_QUALITY;
233: FontStruct.lfWeight = FW_NORMAL;
234: FontStruct.lfPitchAndFamily = VARIABLE_PITCH | FF_SWISS;
235:
236: lstrcpy(FontStruct.lfFaceName, "DIGITAL");
237:
238: hFont = CreateFontIndirect(&FontStruct);
239:
240: SelectObject(hDC, hFont);
241: GetTextMetrics(hDC, &tm);
242: SelectObject(hDC, GetStockObject(SYSTEM_FONT));
243: }
244:
245: ReleaseDC(hWnd, hDC);
246:
247: /* Compute placement for digital text. */
248: ClockDisp.line1.x = (newWidth) / 2;
249: ClockDisp.line1.y = (newHeight - (tm.tmHeight)) / 2;
250: ClockDisp.yline2 = ClockDisp.line1.y + tm.tmHeight;
251: }
252:
253:
254: /*
255: * CompClockDim() - Recompute the clock's dimensions.
256: */
257:
258: void NEAR PASCAL CompClockDim(void)
259:
260: {
261: INT i;
262: register INT tWidth;
263: register INT tHeight;
264:
265: tWidth = clockRect.right - clockRect.left;
266: tHeight = clockRect.bottom - clockRect.top;
267:
268: if (tWidth > (INT)((tHeight * aspectD) / aspectN))
269: {
270: i = (INT)((tHeight * aspectD) / aspectN);
271: clockRect.left += (tWidth - i) >> 1;
272: clockRect.right = clockRect.left + i;
273: }
274: else
275: {
276: i = (INT)((tWidth * aspectN) / aspectD);
277: clockRect.top += (tHeight - i) >> 1;
278: clockRect.bottom = clockRect.top + i;
279: }
280: }
281:
282:
283: /*
284: * ClockSize()
285: */
286:
287: void NEAR PASCAL ClockSize(register HWND hWnd,
288: INT newWidth,
289: INT newHeight,
290: WORD SizeWord)
291: {
292: SetRect((LPRECT)&(clockRect), 0, 0, newWidth, newHeight);
293: CompClockDim();
294:
295: if (SizeWord == SIZEICONIC)
296: {
297: /* Update once every 1/2 minute in the iconic state */
298: KillTimer(hWnd, TimerID);
299: SetTimer(hWnd, TimerID, (WORD)ICON_TLEN, 0L);
300: bIconic = TRUE;
301: }
302: else if (bIconic)
303: {
304: /* Update every 1/2 second in the opened state. */
305: KillTimer(hWnd, TimerID);
306: SetTimer(hWnd, TimerID, OPEN_TLEN, 0L);
307: bIconic = FALSE;
308: }
309:
310: /* Compute where the digital readout should go. */
311: SizeFont(hWnd, newHeight, newWidth, ClockDisp.wDigTimeLen);
312: }
313:
314:
315: /*
316: * DrawBorder() - Draws a Red Border around either clock.
317: */
318:
319: void NEAR PASCAL DrawBorder(HWND hWnd, register HDC hDC)
320: {
321: RECT Rect;
322: HPEN hPen;
323:
324: GetClientRect(hWnd, (LPRECT) &Rect);
325:
326: hPen = CreatePen(PS_SOLID, (bIconic) ? 1 : 2,
327: (bColor) ? RGB(255,0,0) : RGB(255,255,255));
328:
329: SelectObject(hDC, hPen);
330: Rectangle(hDC, Rect.left+1, Rect.top+1, Rect.right, Rect.bottom);
331: SelectObject(hDC, GetStockObject(BLACK_PEN));
332:
333: DeleteObject(hPen);
334:
335: /* Draw an external black border on an icon without killing the client area. */
336: if (bIconic)
337: {
338: MoveToEx(hDC, Rect.left, Rect.top, NULL);
339: LineTo(hDC, Rect.left, Rect.bottom);
340: LineTo(hDC, Rect.right, Rect.bottom);
341: LineTo(hDC, Rect.right, Rect.top);
342: LineTo(hDC, Rect.left, Rect.top);
343: }
344: }
345:
346:
347: /*
348: * DrawFace()
349: */
350:
351: void NEAR PASCAL DrawFace(HDC hDC)
352: {
353: INT i;
354: RECT tRect;
355: INT blobHeight, blobWidth;
356:
357: blobWidth = (INT)((MAXBLOBWIDTH * (LONG)(clockRect.right - clockRect.left)) / HorzRes);
358: blobHeight = (INT)((blobWidth * aspectN) / aspectD);
359:
360: if (blobHeight < 2)
361: blobHeight = 1;
362:
363: if (blobWidth < 2)
364: blobWidth = 2;
365:
366: InflateRect((LPRECT)&clockRect, -(blobHeight >> 1), -(blobWidth >> 1));
367:
368: clockRadius = (clockRect.right - clockRect.left-6) >> 1;
369: clockCenter.y = clockRect.top + ((clockRect.bottom - clockRect.top) >> 1);
370: clockCenter.x = clockRect.left + clockRadius+3;
371:
372: for (i=0; i < 60; i++)
373: {
374: tRect.top = (INT)(((LONG)(CirTab[i].cos) * clockRadius) / CLKSCALE + clockCenter.y);
375: tRect.left = (INT)(((LONG)(CirTab[i].sin) * clockRadius) / CLKSCALE + clockCenter.x);
376:
377: if (i % 5)
378: {
379: /* Draw a dot. */
380: if (blobWidth > 2 && blobHeight >= 2)
381: {
382: tRect.right = tRect.left + 1;
383: tRect.bottom = tRect.top + 1;
384: FillRect(hDC, (LPRECT)&tRect, hbrForeground);
385: }
386: }
387: else
388: {
389: tRect.right = tRect.left + blobWidth;
390: tRect.bottom = tRect.top + blobHeight;
391: OffsetRect((LPRECT)&tRect, -(blobWidth >> 1) , -(blobHeight >> 1));
392: FillRect(hDC, (LPRECT)&tRect, hbrForeground);
393: }
394: }
395: InflateRect((LPRECT)&clockRect, (blobHeight >> 1), (blobWidth >> 1));
396: }
397:
398:
399: /*
400: * DrawHand() - Draw the second hand using XOR mode.
401: */
402:
403: void NEAR PASCAL DrawHand(register HDC hDC,
404: INT pos,
405: HPEN hPen,
406: INT scale,
407: INT patMode)
408: {
409: INT radius;
410:
411: MoveToEx(hDC, clockCenter.x, clockCenter.y, NULL);
412: radius = (INT)(((LONG)clockRadius * scale) / 100);
413: SetROP2(hDC, patMode);
414: SelectObject(hDC, hPen);
415:
416: LineTo(hDC, clockCenter.x + (INT)(((LONG)(CirTab[pos].sin) * (radius)) / CLKSCALE),
417: clockCenter.y + (INT)(((LONG)(CirTab[pos].cos) * (radius)) / CLKSCALE));
418: }
419:
420:
421: /*
422: * DrawFatHand() - Draws either hour or minute hand.
423: */
424:
425: void NEAR PASCAL DrawFatHand(register HDC hDC, INT pos, HPEN hPen, BOOL hHand)
426: {
427: register INT m;
428: INT n;
429: INT scale;
430: POINT tip;
431: POINT stip;
432:
433: SetROP2(hDC, R2_COPYPEN);
434:
435: SelectObject(hDC, hPen);
436:
437: scale = hHand ? 7 : 5;
438:
439: n = (pos+15)%60;
440: m = (INT)((((LONG)clockRadius*scale) / 100));
441: stip.y = (INT)((LONG)(CirTab[n].cos) * m / CLKSCALE);
442: stip.x = (INT)((LONG)(CirTab[n].sin) * m / CLKSCALE);
443:
444: scale = hHand ? 65 : 80;
445: tip.y = (INT)((LONG)(CirTab[pos].cos) * (((LONG)clockRadius * scale) / 100) / CLKSCALE);
446: tip.x = (INT)((LONG)(CirTab[pos].sin) * (((LONG)clockRadius * scale) / 100) / CLKSCALE);
447:
448: MoveToEx(hDC, clockCenter.x+stip.x, clockCenter.y+stip.y, NULL);
449: LineTo(hDC, clockCenter.x+tip.x, clockCenter.y+tip.y);
450: MoveToEx(hDC, clockCenter.x-stip.x, clockCenter.y-stip.y, NULL);
451: LineTo(hDC, clockCenter.x+tip.x, clockCenter.y+tip.y);
452:
453: scale = hHand ? 15 : 20;
454:
455: n = (pos + 30) % 60;
456: m = (INT)(((LONG)clockRadius * scale) / 100);
457: tip.y = (INT)((LONG)(CirTab[n].cos) * m / CLKSCALE);
458: tip.x = (INT)((LONG)(CirTab[n].sin) * m / CLKSCALE);
459: MoveToEx(hDC, clockCenter.x+stip.x, clockCenter.y+stip.y, NULL);
460: LineTo(hDC, clockCenter.x+tip.x, clockCenter.y+tip.y);
461: MoveToEx(hDC, clockCenter.x-stip.x, clockCenter.y-stip.y, NULL);
462: LineTo(hDC, clockCenter.x+tip.x, clockCenter.y+tip.y);
463: }
464:
465:
466: /*
467: * ClockPaint()
468: */
469:
470: void NEAR PASCAL ClockPaint(HWND hWnd, register HDC hDC, INT hint)
471: {
472: INT hour;
473: CHAR *pszTime;
474: RECT Rect;
475: TIME nTime;
476: DWORD rgbCol;
477: HBRUSH hBr;
478:
479: GetClientRect(hWnd, (LPRECT) &Rect);
480:
481: GetTime(&nTime);
482:
483: if (ClockDisp.wFormat == IDM_DIGITAL) /* Digital Display */
484: {
485: if (hint == REPAINT || bIconic)
486: {
487: SelectObject(hDC, GetStockObject(BLACK_BRUSH));
488: DrawBorder(hWnd, hDC);
489:
490: /* Set old values as undefined, so entire clock updated. */
491: oTime.hour24 = 25;
492: oTime.minute = 60;
493: oTime.ampm = 2;
494: }
495:
496: if (oTime.hour24 != nTime.hour24)
497: {
498: if (ClockDisp.wTimeFormat)
499: hour = nTime.hour24;
500: else
501: hour = nTime.hour12;
502:
503: ClockDisp.szDigTime[0] = (CHAR)('0' + hour / 10);
504: ClockDisp.szDigTime[1] = (CHAR)('0' + hour % 10);
505: }
506:
507: if (oTime.minute != nTime.minute)
508: {
509: ClockDisp.szDigTime[3] = (CHAR)('0' + nTime.minute / 10);
510: ClockDisp.szDigTime[4] = (CHAR)('0' + nTime.minute % 10);
511: }
512:
513: /* Kill Leading zero if needed. */
514: if (nLeadZero == 0 && ClockDisp.szDigTime[0] == '0')
515: pszTime = ClockDisp.szDigTime + 1;
516: else
517: pszTime = ClockDisp.szDigTime;
518:
519: SetTextColor(hDC, (bColor) ? RGB(0,255,0) : RGB(255,255,255));
520: SetBkColor(hDC, 0L);
521: SetTextAlign(hDC, TA_CENTER);
522:
523: ClockDisp.wDigTimeLen = (WORD)((bIconic ? 5 : 8) + ClockDisp.szDigTime - pszTime);
524:
525: /* Is the font ready yet? */
526: if (hFont == 0 || bNewFont)
527: {
528: /* Create a suitable font */
529: SizeFont(hWnd, Rect.bottom - Rect.top, Rect.right - Rect.left, ClockDisp.wDigTimeLen);
530: bNewFont = FALSE;
531: }
532:
533: SelectObject(hDC, hFont);
534: ClockDisp.szDigTime[6] = (CHAR)('0' + nTime.second / 10);
535: ClockDisp.szDigTime[7] = (CHAR)('0' + nTime.second % 10);
536:
537: Rect.left += 4;
538: Rect.right -= 4;
539: Rect.top = ClockDisp.line1.y;
540: Rect.bottom = ClockDisp.yline2;
541: ExtTextOut(hDC, ClockDisp.line1.x, ClockDisp.line1.y, ETO_OPAQUE | ETO_CLIPPED,
542: (LPRECT) &Rect, pszTime, (DWORD)ClockDisp.wDigTimeLen, NULL);
543: SelectObject(hDC, GetStockObject(SYSTEM_FONT));
544: }
545: else
546: {
547: /* Analog display */
548: SetBkMode(hDC, TRANSPARENT);
549: if (hint == REPAINT)
550: {
551: SetBkMode(hDC, OPAQUE);
552: /* When switching from Digital to analog, the brush selected
553: * continued to be black; So, the current background is to be
554: * selected;
555: * Fix for Bug #6385 -- SANKAR -- 11-26-89 */
556: SelectObject(hDC, hbrBackground);
557:
558: /* Make a temp brush to color the background. This is to
559: * force use of a solid color so the hand motion is painted
560: * correctly.
561: */
562: rgbCol = GetNearestColor(hDC, GetSysColor(COLOR_WINDOW));
563: hBr = CreateSolidBrush(rgbCol);
564:
565: FillRect(hDC, &Rect, hBr);
566:
567: DeleteObject(hBr);
568:
569: SetBkMode(hDC, TRANSPARENT);
570:
571: DrawBorder(hWnd, hDC);
572: DrawFace(hDC);
573: DrawFatHand(hDC, oTime.hour * 5 + (oTime.minute / 12), hpenForeground, HHAND);
574: DrawFatHand(hDC, oTime.minute, hpenForeground, MHAND);
575:
576: if (!bIconic) /* Draw the second hand. */
577: DrawHand(hDC, oTime.second, hpenBackground, SECONDSCALE, R2_NOT);
578:
579: /* NOTE: Don't update oTime in this case! */
580:
581: return;
582: }
583: else if (hint == HANDPAINT)
584: {
585: if ((!bIconic) && nTime.second != oTime.second) /* Erase the old second hand. */
586: DrawHand(hDC, oTime.second, hpenBackground, SECONDSCALE, R2_NOT);
587:
588: if (nTime.minute != oTime.minute || nTime.hour != oTime.hour)
589: {
590: if (bIconic)
591: {
592: DrawHand(hDC, oTime.minute, hpenBackground, MINUTESCALE, R2_COPYPEN);
593: DrawHand(hDC, oTime.hour * 5 + (oTime.minute / 12), hpenBackground, HOURSCALE, R2_COPYPEN);
594: DrawHand(hDC, nTime.minute, hpenForeground, MINUTESCALE, R2_COPYPEN);
595: DrawHand(hDC, nTime.hour * 5 + (nTime.minute / 12), hpenForeground, HOURSCALE, R2_COPYPEN);
596: }
597: else
598: {
599: DrawFatHand(hDC, oTime.minute, hpenBackground, MHAND);
600: DrawFatHand(hDC, oTime.hour*5+(oTime.minute/12), hpenBackground, HHAND);
601: DrawFatHand(hDC, nTime.minute, hpenForeground, MHAND);
602: DrawFatHand(hDC, (nTime.hour) * 5 + (nTime.minute / 12), hpenForeground, HHAND );
603: }
604: }
605:
606: if (!bIconic && nTime.second != oTime.second) /* Draw new second hand */
607: DrawHand(hDC, nTime.second, hpenBackground, SECONDSCALE, R2_NOT);
608: }
609: }
610: oTime = nTime;
611: }
612:
613:
614: /*
615: * ClockTimer()
616: *
617: * msg - timer ID
618: *
619: * Called by windows to tell CLOCK there has been a time change.
620: *
621: */
622:
623: void NEAR PASCAL ClockTimer(HWND hWnd, UINT msg)
624: {
625: HDC hDC;
626: TIME nTime;
627:
628: GetTime(&nTime);
629:
630: /* It's possible to change any part of the system at any time
631: * through the Control Panel. So we check everything.
632: */
633: if (((nTime.second == oTime.second) || bIconic) &&
634: (nTime.minute == oTime.minute) &&
635: (nTime.hour24 == oTime.hour24))
636: return;
637:
638: hDC = GetDC(hWnd);
639: ClockPaint(hWnd, hDC, HANDPAINT);
640: ReleaseDC(hWnd, hDC);
641: DdePostAdvise(idInst, hszTime, hszNow);
642: UNREFERENCED_PARAMETER(msg);
643: }
644:
645:
646: /*
647: * ClockCreate()
648: */
649:
650: void NEAR PASCAL ClockCreate(HWND hWnd)
651: {
652: INT i;
653: register HDC hDC;
654: INT HorzSize;
655: INT VertSize;
656:
657: hDC = GetDC(hWnd);
658: VertRes = GetDeviceCaps(hDC, VERTRES);
659: HorzRes = GetDeviceCaps(hDC, HORZRES);
660: VertSize= GetDeviceCaps(hDC, VERTSIZE);
661: HorzSize= GetDeviceCaps(hDC, HORZSIZE);
662: ReleaseDC(hWnd, hDC);
663:
664: aspectN = ((LONG)VertRes * 100) / (LONG)VertSize;
665: aspectD = ((LONG)HorzRes * 100) / (LONG)HorzSize;
666:
667: CreateTools();
668:
669: /* Scale sines for aspect ratio if this is the first instance */
670: for (i=0; i < 60; i++) {
671: CirTab[i].sin = (SHORT)((CirTab[i].sin * aspectN) / aspectD);
672: }
673: }
674:
675:
676:
677: /*
678: * FormatInit() - International initialization.
679: */
680:
681: void NEAR PASCAL FormatInit(register HANDLE hInstance, BOOL fModeChange)
682: {
683: WORD i, ii;
684: CHAR szWinHeader[21], szKeyName[21], szRetVal[21];
685:
686: for (i=0; i < 11; i++)
687: ClockDisp.szDigTime[i] = ' ';
688:
689: LoadString(hInstance, IDS_INTL, (LPSTR)szWinHeader, 20);
690:
691: LoadString(hInstance, IDS_ITIME, (LPSTR)szKeyName, 20);
692: ClockDisp.wTimeFormat = (WORD)GetProfileInt((LPSTR)szWinHeader, (LPSTR)szKeyName, 0);
693:
694: LoadString(hInstance, IDS_S1159, (LPSTR)szKeyName, 20);
695: LoadString(hInstance, IDS_1159, (LPSTR)szRetVal, 20);
696: i = (WORD)GetProfileString((LPSTR)szWinHeader, (LPSTR)szKeyName, (LPSTR)szRetVal, (LPSTR)&ClockDisp.szAMPM[0][0], 7);
697:
698: LoadString(hInstance, IDS_S2359, (LPSTR)szKeyName, 20);
699: LoadString(hInstance, IDS_2359, (LPSTR)szRetVal, 20);
700: ii = (WORD)GetProfileString((LPSTR)szWinHeader, (LPSTR)szKeyName, (LPSTR)szRetVal, (LPSTR)&ClockDisp.szAMPM[1][0], 7);
701:
702: nLeadZero = GetProfileInt((LPSTR)szWinHeader, "iTLzero", 0);
703:
704: LoadString(hInstance, IDS_STIME, (LPSTR)szKeyName, 20);
705: LoadString(hInstance, IDS_TIMESEP, (LPSTR)szRetVal, 20);
706:
707: GetProfileString((LPSTR)szWinHeader, (LPSTR)szKeyName, (LPSTR)szRetVal, (LPSTR)szRetVal, 20);
708: ClockDisp.cTimeSep = szRetVal[0];
709:
710: ClockDisp.szDigTime[2] = ClockDisp.cTimeSep;
711: ClockDisp.szDigTime[5] = ClockDisp.cTimeSep;
712:
713: LoadString(hInstance, IDS_USNAME, (LPSTR)szWinHeader, 20);
714: LoadString(hInstance, IDS_CLKFORMAT, (LPSTR)szKeyName, 20);
715:
716: /* We will read the new mode (DIGITAL/ANALOG) only during init time. */
717: if (fModeChange)
718: {
719: if (GetPrivateProfileInt((LPSTR)szWinHeader, (LPSTR)szKeyName, 1, (LPSTR)szIniFile))
720: ClockDisp.wFormat = IDM_ANALOG;
721: else
722: ClockDisp.wFormat = IDM_DIGITAL;
723: }
724:
725: if (ClockDisp.wFormat == IDM_ANALOG)
726: hbrBackground = hbrColorWindow;
727: else
728: hbrBackground = hbrColorBlack;
729:
730: ClockDisp.wDigTimeLen = 2+1+2+1+2+1;
731:
732: if (!ClockDisp.wTimeFormat)
733: ClockDisp.wDigTimeLen += ((i > ii) ? (i) : (ii));
734: }
735:
736:
737: /*
738: * ClockInit()
739: */
740:
741: BOOL NEAR PASCAL ClockInit(HANDLE hInstance)
742: {
743: HDC hDC;
744: static WNDCLASS ClockClass;
745:
746: FormatInit(hInstance, TRUE);
747:
748: ClockClass.lpszClassName = (LPSTR)szBuffer;
749: ClockClass.lpszMenuName = (LPSTR)szBuffer;
750: ClockClass.hbrBackground = (HBRUSH)NULL;
751: ClockClass.style = CS_VREDRAW | CS_HREDRAW;
752: ClockClass.hInstance = hInstance;
753: ClockClass.lpfnWndProc = ClockWndProc;
754: ClockClass.hCursor = LoadCursor(NULL, IDC_ARROW);
755: ClockClass.hIcon = NULL;
756:
757: if (!RegisterClass((LPWNDCLASS)&ClockClass))
758: return(FALSE);
759:
760: LoadString(hInstance, IDS_FONTFILE, (LPSTR)szFontFile, 20);
761: AddFontResource(szFontFile);
762:
763: /* Check the number of colors that the display is capable of. */
764: hDC = CreateDC("DISPLAY", NULL, NULL, NULL);
765: bColor = (GetDeviceCaps(hDC, NUMCOLORS) > 2);
766: bColor = FALSE;
767: DeleteDC(hDC);
768:
769: return(TRUE);
770: }
771:
772:
773: /*
774: * ClockWndProc()
775: */
776:
777: LONG APIENTRY ClockWndProc(register HWND hWnd, UINT message, WPARAM wParam, LONG lParam)
778: {
779: HMENU hMenu;
780: CHAR szInt[2]; /* space for int to str conversion */
781: static CHAR szAppName[12]; /* application name buffer */
782: PAINTSTRUCT ps;
783:
784: switch (message)
785: {
786: case WM_COMMAND:
787: switch (wParam)
788: {
789: case IDM_ANALOG:
790: case IDM_DIGITAL:
791: if (wParam != ClockDisp.wFormat)
792: {
793: /* Switch flag to other choice */
794: hMenu = GetMenu(hWnd);
795: CheckMenuItem(hMenu, ClockDisp.wFormat, MF_BYCOMMAND | MF_UNCHECKED);
796: CheckMenuItem(hMenu, ClockDisp.wFormat = (WORD)wParam, MF_BYCOMMAND | MF_CHECKED);
797: InvalidateRect(hWnd, (LPRECT)NULL, TRUE);
798:
799: /* Write new configuration to CLOCK.INI */
800: LoadString(hInst, IDS_USNAME, (LPSTR)szAppName, 8);
801: LoadString(hInst, IDS_CLKFORMAT, (LPSTR)szBuffer, BUFLEN-1);
802: szInt[0] = (CHAR)('0' + (ClockDisp.wFormat == IDM_ANALOG));
803: szInt[1] = 0;
804: WritePrivateProfileString((LPSTR)szAppName,
805: (LPSTR)szBuffer,
806: (LPSTR)szInt,
807: (LPSTR)szIniFile);
808: }
809: break;
810:
811: case IDM_ABOUT:
812: {
813: LoadString(hInst, IDS_USNAME, (LPSTR)szAppName, 8);
814: // Add this when 3.1 stuff comes in. ShellAbout(hWnd, szAppName, (LPSTR)"", LoadIcon(hInst, (LPSTR)"cckk"));
815: break;
816: }
817:
818: default:
819: goto defproc;
820: }
821: break;
822:
823: case WM_SIZE:
824: bNewFont = TRUE;
825: ClockSize(hWnd, LOWORD(lParam), HIWORD(lParam), (WORD)wParam);
826: UpdateWindow(hWnd);
827: break;
828:
829: case WM_QUERYDRAGICON:
830: return (LONG)LoadIcon(hInst, "cckk");
831:
832: case WM_DESTROY:
833: {
834: CHAR szInt[10];
835: HCURSOR hTempCursor;
836:
837: KillTimer(hWnd, TimerID);
838: DeleteTools();
839: if (hFont)
840: DeleteObject(hFont);
841: RemoveFontResource(szFontFile);
842:
843: SetCapture(hWnd);
844: hTempCursor=SetCursor(LoadCursor(NULL, IDC_WAIT));
845:
846: if (!(IsIconic(hWnd) || IsZoomed(hWnd)))
847: GetWindowRect(hWnd, &rCoordRect);
848:
849: wsprintf((LPSTR)szInt, (LPSTR)"%i", (INT)IsIconic(hWnd));
850: WritePrivateProfileString((LPSTR)szSection,
851: (LPSTR)"Minimized",
852: (LPSTR)szInt,
853: (LPSTR)szIniFile);
854: wsprintf((LPSTR)szInt, (LPSTR)"%i", (INT)IsZoomed(hWnd));
855: WritePrivateProfileString((LPSTR)szSection,
856: (LPSTR)"Maximized",
857: (LPSTR)szInt,
858: (LPSTR)szIniFile);
859: wsprintf((LPSTR)szInt, (LPSTR)"%i", (INT)rCoordRect.left);
860: WritePrivateProfileString((LPSTR)szSection,
861: (LPSTR)"Left",
862: (LPSTR)szInt,
863: (LPSTR)szIniFile);
864: wsprintf((LPSTR)szInt, (LPSTR)"%i", (INT)rCoordRect.top);
865: WritePrivateProfileString((LPSTR)szSection,
866: (LPSTR)"Top",
867: (LPSTR)szInt,
868: (LPSTR)szIniFile);
869: wsprintf((LPSTR)szInt, (LPSTR)"%i", (INT)rCoordRect.right);
870: WritePrivateProfileString((LPSTR)szSection,
871: (LPSTR)"Right",
872: (LPSTR)szInt,
873: (LPSTR)szIniFile);
874: wsprintf((LPSTR)szInt, (LPSTR)"%i", (INT)rCoordRect.bottom);
875: WritePrivateProfileString((LPSTR)szSection,
876: (LPSTR)"Bottom",
877: (LPSTR)szInt,
878: (LPSTR)szIniFile);
879: PostQuitMessage(0);
880: break;
881: }
882:
883: case WM_WININICHANGE:
884: /* FALSE indicates that we don't want to change the display format */
885: FormatInit(hInst, FALSE);
886: InvalidateRect(hWnd, (LPRECT)NULL, TRUE);
887: break;
888:
889: case WM_PAINT:
890: /* 25-Mar-1987. Added to force total repaint to solve
891: * problem of garbage under second hand when hidden
892: * by menu or popup.
893: */
894: InvalidateRect(hWnd, (LPRECT)NULL, TRUE);
895: BeginPaint(hWnd, (LPPAINTSTRUCT)&ps);
896:
897: if (ClockDisp.wFormat == IDM_DIGITAL)
898: {
899: hbrBackground = hbrColorBlack;
900: FillRect(ps.hdc, (LPRECT)&clockRect, hbrBackground);
901: }
902: else
903: hbrBackground=hbrColorWindow;
904:
905: ClockPaint(hWnd, ps.hdc, REPAINT);
906: EndPaint(hWnd, (LPPAINTSTRUCT)&ps);
907: break;
908:
909: case WM_TIMECHANGE:
910: /* Redraw. */
911: InvalidateRect(hWnd, (LPRECT)NULL, TRUE);
912:
913: case WM_TIMER:
914: ClockTimer(hWnd, (WORD)wParam);
915: break;
916:
917: case WM_SYSCOMMAND:
918: switch (wParam)
919: {
920: case SC_MINIMIZE:
921: if (!IsZoomed(hWnd))
922: GetWindowRect(hWnd, (LPRECT)&rCoordRect);
923: break;
924: case SC_MAXIMIZE:
925: if (!IsIconic(hWnd))
926: GetWindowRect(hWnd, (LPRECT)&rCoordRect);
927: break;
928: }
929: return(DefWindowProc(hWnd, message, wParam, lParam));
930: break;
931:
932: case WM_SYSCOLORCHANGE:
933: DeleteTools();
934: CreateTools();
935: break;
936:
937: case WM_ERASEBKGND:
938: {
939: RECT rect;
940:
941: GetClientRect(hWnd, (LPRECT)&rect);
942: SelectObject((HDC)wParam, hbrBackground);
943: FillRect((HDC)wParam, (LPRECT)&rect, hbrBackground);
944: break;
945: }
946:
947: default:
948: defproc:
949: return(DefWindowProc(hWnd, message, wParam, lParam));
950: }
951: return(0L);
952: }
953:
954:
955:
956: /*
957: * WinMain()
958: */
959:
960: int APIENTRY WinMain(
961: HANDLE hInstance,
962: HANDLE hPrev,
963: LPSTR lpCmdLine,
964: int cmdShow
965: )
966: {
967: register HWND hWnd;
968: MSG msg;
969: TIME nTime;
970: PSTR szTooMany;
971: INT iMinimized, iMaximized;
972:
973: LoadString(hInstance, IDS_USNAME, (LPSTR)szBuffer, BUFLEN);
974: LoadString(hInstance, IDS_INIFILE, (LPSTR)szIniFile, 20);
975: LoadString(hInstance, IDS_USNAME, (LPSTR)szSection, 30);
976:
977: if (!ClockInit(hInstance))
978: return(FALSE);
979:
980: ClockCreate((HWND)NULL);
981:
982: LoadString(hInstance, IDS_APPNAME, (LPSTR)szBuffer, BUFLEN);
983:
984: rCoordRect.top=GetPrivateProfileInt((LPSTR)szSection,
985: (LPSTR)"Top",
986: (DWORD)-1, (LPSTR)szIniFile);
987: rCoordRect.left=GetPrivateProfileInt((LPSTR)szSection,
988: (LPSTR)"Left",
989: (DWORD)-1, (LPSTR)szIniFile);
990: rCoordRect.right=GetPrivateProfileInt((LPSTR)szSection,
991: (LPSTR)"Right",
992: (DWORD)-1, (LPSTR)szIniFile);
993: rCoordRect.bottom=GetPrivateProfileInt((LPSTR)szSection,
994: (LPSTR)"Bottom",
995: (DWORD)-1, (LPSTR)szIniFile);
996:
997: hWnd = CreateWindow((LPSTR)"Clock", /* The class name. */
998: (LPSTR)szBuffer, /* The window instance name. */
999: WS_TILEDWINDOW,
1000: (rCoordRect.left < 0) ? CW_USEDEFAULT : rCoordRect.left,
1001: (rCoordRect.top < 0) ? CW_USEDEFAULT : rCoordRect.top,
1002: (rCoordRect.left < 0) ? (INT)( (HorzRes/3) + GetSystemMetrics(SM_CXFRAME)*2 )
1003: : rCoordRect.right - rCoordRect.left,
1004: (rCoordRect.left < 0) ? (INT)( (((HorzRes/3)*aspectN)/aspectD)+GetSystemMetrics(SM_CYCAPTION)+GetSystemMetrics(SM_CYFRAME)*2 )
1005: : rCoordRect.bottom - rCoordRect.top,
1006: NULL,
1007: NULL,
1008: hInstance,
1009: (LPSTR)NULL);
1010:
1011: hWindow=hWnd;
1012:
1013: // Loop if control panel time being changed.
1014: GetTime((TIME *)&nTime);
1015: do {
1016: GetTime((TIME *)&oTime);
1017: } while (nTime.second == oTime.second && nTime.minute == oTime.minute &&
1018: nTime.hour24 == oTime.hour24);
1019:
1020: if (!SetTimer(hWnd, TimerID, OPEN_TLEN, 0L))
1021: {
1022: /* Windows only supports 16 public timers */
1023: szTooMany = (PSTR)LocalAlloc(LPTR, 160);
1024: LoadString(hInstance, IDS_TOOMANY, (LPSTR)szTooMany, 160);
1025: MessageBox((HWND)NULL, (LPSTR)szTooMany, (LPSTR)szBuffer, MB_OK | MB_ICONHAND | MB_SYSTEMMODAL);
1026: DeleteTools();
1027: return(FALSE);
1028: }
1029:
1030: /* Check the default menu item either analog or digital */
1031: CheckMenuItem(GetMenu(hWnd), ClockDisp.wFormat, MF_BYCOMMAND | MF_CHECKED);
1032:
1033: hInst = hInstance;
1034:
1035: iMinimized=GetPrivateProfileInt((LPSTR)szSection,
1036: (LPSTR)"Minimized",
1037: 0, (LPSTR)szIniFile);
1038: if (!iMinimized)
1039: {
1040: iMaximized=GetPrivateProfileInt((LPSTR)szSection,
1041: (LPSTR)"Maximized",
1042: 0, (LPSTR)szIniFile);
1043: if (iMaximized)
1044: ShowWindow(hWnd, SW_MAXIMIZE);
1045: else
1046: {
1047: ShowWindow(hWnd, cmdShow);
1048: GetWindowRect(hWnd, (LPRECT)&rCoordRect);
1049: }
1050: }
1051: else
1052: ShowWindow(hWnd, SW_MINIMIZE);
1053:
1054: DdeInitialize(&idInst, (PFNCALLBACK)MakeProcInstance((FARPROC)DdeCallback, hInstance),
1055: CBF_FAIL_EXECUTES | CBF_SKIP_ALLNOTIFICATIONS, 0L);
1056:
1057:
1058: hszTime = DdeCreateStringHandle(idInst, "Time", 0);
1059: hszNow = DdeCreateStringHandle(idInst, "Now", 0);
1060: hszClock = DdeCreateStringHandle(idInst, "Clock", 0);
1061: DdeNameService(idInst, hszClock, 0L, DNS_REGISTER);
1062:
1063: while (GetMessage((LPMSG)&msg, NULL, 0, 0))
1064: {
1065: TranslateMessage((LPMSG)&msg);
1066: DispatchMessage((LPMSG)&msg);
1067: }
1068:
1069: DdeUninitialize(idInst);
1070:
1071: return(msg.wParam);
1072: }
1073:
1074:
1075: VOID GetTime(
1076: TIME *ptime)
1077: {
1078: time_t t;
1079: struct tm *ptm;
1080:
1081: time(&t);
1082: ptm = localtime(&t);
1083: ptime->second = ptm->tm_sec;
1084: ptime->minute = ptm->tm_min;
1085: ptime->hour12 =
1086: ptime->hour = ptm->tm_hour > 12 ? ptm->tm_hour - 12 : ptm->tm_hour;
1087: ptime->hour24 = ptm->tm_hour;
1088: ptime->ampm = ptm->tm_hour > 12 ? 1 : 0;
1089: }
1090:
1091:
1092: HDDEDATA EXPENTRY DdeCallback(
1093: WORD usType,
1094: WORD usFmt,
1095: HCONV hConv,
1096: HSZ hsz1,
1097: HSZ hsz2,
1098: HDDEDATA hData,
1099: DWORD lData1,
1100: DWORD lData2)
1101: {
1102: if (usType == XTYP_CONNECT) {
1103: return(TRUE);
1104: }
1105:
1106: if (usType == XTYP_WILDCONNECT) {
1107: HDDEDATA hData;
1108: HSZPAIR FAR *phszp;
1109: DWORD cb;
1110:
1111: if ((!hsz1 || hsz1 == hszTime) && (!hsz2 || hsz2 == hszClock)) {
1112: if ((hData = DdeCreateDataHandle(idInst, NULL,
1113: 2 * sizeof(HSZPAIR), 0L, 0, 0, 0))) {
1114: phszp = (HSZPAIR FAR *)DdeAccessData(hData, &cb);
1115: phszp[0].hszSvc = hszClock;
1116: phszp[0].hszTopic = hszTime;
1117: phszp[1].hszSvc = phszp[1].hszTopic = 0;
1118: DdeUnaccessData(hData);
1119: return(hData);
1120: }
1121: }
1122: return(0);
1123: }
1124:
1125: if (usFmt == CF_TEXT) {
1126: CHAR sz[40];
1127:
1128: if (usType == XTYP_ADVSTART || usType == XTYP_ADVSTOP) {
1129: return(TRUE);
1130: }
1131:
1132: if (hsz1 == hszTime && hsz2 == hszNow) {
1133: if (usType == XTYP_REQUEST || usType == XTYP_ADVREQ) {
1134:
1135: itoa(oTime.hour, sz, 10);
1136: strcat(sz, ":");
1137: itoa(oTime.minute, &sz[strlen(sz)], 10);
1138: strcat(sz, ":");
1139: itoa(oTime.second, &sz[strlen(sz)], 10);
1140: return(DdeCreateDataHandle(idInst, (LPBYTE)sz, strlen(sz) + 1, 0L,
1141: hszNow, CF_TEXT, 0));
1142: }
1143: if (usType == XTYP_POKE) {
1144: SYSTEMTIME SysTime;
1145:
1146: DdeGetData(hData, (LPBYTE)sz, 40L, 0L);
1147: GetSystemTime(&SysTime);
1148: sscanf(sz, "%d:%d:%d", &SysTime.wHour, &SysTime.wMinute, &SysTime.wSecond);
1149: SetSystemTime(&SysTime);
1150: DdePostAdvise(idInst, hszTime, hszNow);
1151: return(DDE_FACK);
1152: }
1153: }
1154: }
1155: return(0);
1156: UNREFERENCED_PARAMETER(lData1);
1157: UNREFERENCED_PARAMETER(lData2);
1158: UNREFERENCED_PARAMETER(hConv);
1159: }
1160:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.