Annotation of mstools/samples/ddeml/clock/clock.c, revision 1.1.1.3

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

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.