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