--- mstools/samples/ddeml/clock/clock.c 2018/08/09 18:20:38 1.1.1.1 +++ mstools/samples/ddeml/clock/clock.c 2018/08/09 18:23:19 1.1.1.3 @@ -1,6 +1,28 @@ + +/******************************************************************************\ +* This is a part of the Microsoft Source Code Samples. +* Copyright (C) 1993 Microsoft Corporation. +* All rights reserved. +* This source code is only intended as a supplement to +* Microsoft Development Tools and/or WinHelp documentation. +* See these sources for detailed information regarding the +* Microsoft samples programs. +\******************************************************************************/ + /* - * CLOCK.C - Windows Clock + * CLOCK.C - Windows DDEML Clock + * + * DDE Transactions: + * ---------------- + * Service: Clock + * Topic : Time + * Item : Now * + * Use Request or Advise to get the time or use Poke to change the time. + * Time Format Hour:Minute:Seconds where + * Hour = 0-23 + * Minute = 0-59 + * Seconds = 0-59 */ #include @@ -8,85 +30,14 @@ #include #include #include "windows.h" -#include "windowsx.h" #include #include "clock.h" -// #include "shellapi.h" -DWORD idInst = 0; -BOOL bIconic = FALSE; -BOOL bColor = TRUE; -BOOL bNewFont = TRUE; +DWORD idInst = 0; CLOCKDISPSTRUCT ClockDisp; -TRIG CirTab[] = { // circle sin, cos, table - { 0, -7999 }, - { 836, -7956 }, - { 1663, -7825 }, - { 2472, -7608 }, - { 3253, -7308 }, - { 3999, -6928 }, - { 4702, -6472 }, - { 5353, -5945 }, - { 5945, -5353 }, - { 6472, -4702 }, - { 6928, -4000 }, - { 7308, -3253 }, - { 7608, -2472 }, - { 7825, -1663 }, - { 7956, -836 }, - - { 8000, 0 }, - { 7956, 836 }, - { 7825, 1663 }, - { 7608, 2472 }, - { 7308, 3253 }, - { 6928, 4000 }, - { 6472, 4702 }, - { 5945, 5353 }, - { 5353, 5945 }, - { 4702, 6472 }, - { 3999, 6928 }, - { 3253, 7308 }, - { 2472, 7608 }, - { 1663, 7825 }, - { 836, 7956 }, - - { 0, 7999 }, - { -836, 7956 }, - { -1663, 7825 }, - { -2472, 7608 }, - { -3253, 7308 }, - { -4000, 6928 }, - { -4702, 6472 }, - { -5353, 5945 }, - { -5945, 5353 }, - { -6472, 4702 }, - { -6928, 3999 }, - { -7308, 3253 }, - { -7608, 2472 }, - { -7825, 1663 }, - { -7956, 836 }, - - { -7999, -0 }, - { -7956, -836 }, - { -7825, -1663 }, - { -7608, -2472 }, - { -7308, -3253 }, - { -6928, -4000 }, - { -6472, -4702 }, - { -5945, -5353 }, - { -5353, -5945 }, - { -4702, -6472 }, - { -3999, -6928 }, - { -3253, -7308 }, - { -2472, -7608 }, - { -1663, -7825 }, - { -836 , -7956 } -}; - HANDLE hInst; HWND hWindow; @@ -119,7 +70,7 @@ TIME oTime; RECT clockRect; RECT rCoordRect; -HDDEDATA EXPENTRY DdeCallback(WORD usType, WORD usFmt, HCONV hConv, HSZ hsz1, +HDDEDATA CALLBACK DdeCallback(WORD usType, WORD usFmt, HCONV hConv, HSZ hsz1, HSZ hsz2, HDDEDATA hData, DWORD lData1, DWORD lData2); HSZ hszTime, hszNow, hszClock; /* Hszs for DDEML use */ @@ -127,7 +78,7 @@ HSZ hszTime, hszNow, hszClock; /* Hsz * Function Prototypes */ -LONG APIENTRY ClockWndProc(register HWND hWnd, UINT message, WPARAM wParam, LONG lParam); +LONG APIENTRY ClockWndProc(register HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam); void NEAR PASCAL ClockCreate(HWND hWnd); BOOL NEAR PASCAL ClockInit(HANDLE hInstance); @@ -143,7 +94,7 @@ void NEAR PASCAL DrawHand(register HDC h void NEAR PASCAL DrawFatHand(register HDC hDC, INT pos, HPEN hPen, BOOL hHand); void NEAR PASCAL FormatInit(register HANDLE hInstance, BOOL fModeChange); void NEAR PASCAL SizeFont(HWND hWnd, INT newHeight, INT newWidth, INT wlen); - +void NEAR PASCAL SetMenuBar( HWND hWnd ); /* @@ -190,8 +141,7 @@ LOGFONT FontStruct; hDC = GetDC(hWnd); GetTextMetrics(hDC, &tm); - if (ClockDisp.wFormat == IDM_DIGITAL) - { + if (ClockDisp.wFormat == IDM_DIGITAL) { if (hFont != NULL) DeleteObject(hFont); @@ -206,8 +156,7 @@ LOGFONT FontStruct; /* Note that the numbers used in this formula depend on the * size of the numbers in the fonts which are 12 vert, 7 horz. */ - if (!bIconic) - { + if (!ClockDisp.bIconic) { FontStruct.lfHeight = (SHORT)min(newHeight/2, 45); /* The formula at the end is somewhat empirical. */ @@ -221,12 +170,11 @@ LOGFONT FontStruct; */ if (FontStruct.lfWidth != 25 && FontStruct.lfHeight == 45) FontStruct.lfHeight = 40; - } - else - { + } + else { FontStruct.lfHeight = (SHORT)(newHeight/3); FontStruct.lfWidth = (SHORT)(newWidth/5); - } + } FontStruct.lfCharSet = ANSI_CHARSET; FontStruct.lfQuality = DRAFT_QUALITY; @@ -265,18 +213,16 @@ register INT tHeight; tWidth = clockRect.right - clockRect.left; tHeight = clockRect.bottom - clockRect.top; - if (tWidth > (INT)((tHeight * aspectD) / aspectN)) - { + if (tWidth > (INT)((tHeight * aspectD) / aspectN)) { i = (INT)((tHeight * aspectD) / aspectN); clockRect.left += (tWidth - i) >> 1; clockRect.right = clockRect.left + i; - } - else - { + } + else { i = (INT)((tWidth * aspectN) / aspectD); clockRect.top += (tHeight - i) >> 1; clockRect.bottom = clockRect.top + i; - } + } } @@ -292,20 +238,18 @@ void NEAR PASCAL ClockSize(register HWND SetRect((LPRECT)&(clockRect), 0, 0, newWidth, newHeight); CompClockDim(); - if (SizeWord == SIZEICONIC) - { + if (SizeWord == SIZEICONIC) { /* Update once every 1/2 minute in the iconic state */ KillTimer(hWnd, TimerID); - SetTimer(hWnd, TimerID, (WORD)ICON_TLEN, 0L); - bIconic = TRUE; - } - else if (bIconic) - { + SetTimer(hWnd, TimerID, (WORD)ICON_TLEN, 0L); + ClockDisp.bIconic = TRUE; + } + else if (ClockDisp.bIconic) { /* Update every 1/2 second in the opened state. */ KillTimer(hWnd, TimerID); SetTimer(hWnd, TimerID, OPEN_TLEN, 0L); - bIconic = FALSE; - } + ClockDisp.bIconic = FALSE; + } /* Compute where the digital readout should go. */ SizeFont(hWnd, newHeight, newWidth, ClockDisp.wDigTimeLen); @@ -323,8 +267,8 @@ HPEN hPen; GetClientRect(hWnd, (LPRECT) &Rect); - hPen = CreatePen(PS_SOLID, (bIconic) ? 1 : 2, - (bColor) ? RGB(255,0,0) : RGB(255,255,255)); + hPen = CreatePen(PS_SOLID, (ClockDisp.bIconic) ? 1 : 2, + (ClockDisp.bColor) ? RGB(255,0,0) : RGB(255,255,255)); SelectObject(hDC, hPen); Rectangle(hDC, Rect.left+1, Rect.top+1, Rect.right, Rect.bottom); @@ -333,14 +277,13 @@ HPEN hPen; DeleteObject(hPen); /* Draw an external black border on an icon without killing the client area. */ - if (bIconic) - { - MoveToEx(hDC, Rect.left, Rect.top, NULL); + if (ClockDisp.bIconic) { + MoveToEx(hDC, Rect.left, Rect.top, NULL); LineTo(hDC, Rect.left, Rect.bottom); LineTo(hDC, Rect.right, Rect.bottom); LineTo(hDC, Rect.right, Rect.top); LineTo(hDC, Rect.left, Rect.top); - } + } } @@ -369,29 +312,25 @@ INT blobHeight, blobWidth; clockCenter.y = clockRect.top + ((clockRect.bottom - clockRect.top) >> 1); clockCenter.x = clockRect.left + clockRadius+3; - for (i=0; i < 60; i++) - { + for (i=0; i < 60; i++) { tRect.top = (INT)(((LONG)(CirTab[i].cos) * clockRadius) / CLKSCALE + clockCenter.y); tRect.left = (INT)(((LONG)(CirTab[i].sin) * clockRadius) / CLKSCALE + clockCenter.x); - if (i % 5) - { + if (i % 5) { /* Draw a dot. */ - if (blobWidth > 2 && blobHeight >= 2) - { + if (blobWidth > 2 && blobHeight >= 2) { tRect.right = tRect.left + 1; tRect.bottom = tRect.top + 1; FillRect(hDC, (LPRECT)&tRect, hbrForeground); - } } - else - { + } + else { tRect.right = tRect.left + blobWidth; tRect.bottom = tRect.top + blobHeight; OffsetRect((LPRECT)&tRect, -(blobWidth >> 1) , -(blobHeight >> 1)); FillRect(hDC, (LPRECT)&tRect, hbrForeground); - } } + } InflateRect((LPRECT)&clockRect, (blobHeight >> 1), (blobWidth >> 1)); } @@ -480,10 +419,8 @@ HBRUSH hBr; GetTime(&nTime); - if (ClockDisp.wFormat == IDM_DIGITAL) /* Digital Display */ - { - if (hint == REPAINT || bIconic) - { + if (ClockDisp.wFormat == IDM_DIGITAL) { /* Digital Display */ + if (hint == REPAINT || ClockDisp.bIconic) { SelectObject(hDC, GetStockObject(BLACK_BRUSH)); DrawBorder(hWnd, hDC); @@ -491,10 +428,9 @@ HBRUSH hBr; oTime.hour24 = 25; oTime.minute = 60; oTime.ampm = 2; - } + } - if (oTime.hour24 != nTime.hour24) - { + if (oTime.hour24 != nTime.hour24) { if (ClockDisp.wTimeFormat) hour = nTime.hour24; else @@ -502,13 +438,12 @@ HBRUSH hBr; ClockDisp.szDigTime[0] = (CHAR)('0' + hour / 10); ClockDisp.szDigTime[1] = (CHAR)('0' + hour % 10); - } + } - if (oTime.minute != nTime.minute) - { + if (oTime.minute != nTime.minute) { ClockDisp.szDigTime[3] = (CHAR)('0' + nTime.minute / 10); ClockDisp.szDigTime[4] = (CHAR)('0' + nTime.minute % 10); - } + } /* Kill Leading zero if needed. */ if (nLeadZero == 0 && ClockDisp.szDigTime[0] == '0') @@ -516,19 +451,18 @@ HBRUSH hBr; else pszTime = ClockDisp.szDigTime; - SetTextColor(hDC, (bColor) ? RGB(0,255,0) : RGB(255,255,255)); + SetTextColor(hDC, (ClockDisp.bColor) ? RGB(0,255,0) : RGB(255,255,255)); SetBkColor(hDC, 0L); SetTextAlign(hDC, TA_CENTER); - ClockDisp.wDigTimeLen = (WORD)((bIconic ? 5 : 8) + ClockDisp.szDigTime - pszTime); + ClockDisp.wDigTimeLen = (WORD)((ClockDisp.bIconic ? 5 : 8) + ClockDisp.szDigTime - pszTime); /* Is the font ready yet? */ - if (hFont == 0 || bNewFont) - { + if (hFont == 0 || ClockDisp.bNewFont) { /* Create a suitable font */ SizeFont(hWnd, Rect.bottom - Rect.top, Rect.right - Rect.left, ClockDisp.wDigTimeLen); - bNewFont = FALSE; - } + ClockDisp.bNewFont = FALSE; + } SelectObject(hDC, hFont); ClockDisp.szDigTime[6] = (CHAR)('0' + nTime.second / 10); @@ -539,15 +473,13 @@ HBRUSH hBr; Rect.top = ClockDisp.line1.y; Rect.bottom = ClockDisp.yline2; ExtTextOut(hDC, ClockDisp.line1.x, ClockDisp.line1.y, ETO_OPAQUE | ETO_CLIPPED, - (LPRECT) &Rect, pszTime, (DWORD)ClockDisp.wDigTimeLen, NULL); + (LPRECT)&Rect, pszTime, (UINT)ClockDisp.wDigTimeLen, (LPINT)NULL); SelectObject(hDC, GetStockObject(SYSTEM_FONT)); } - else - { + else { /* Analog display */ SetBkMode(hDC, TRANSPARENT); - if (hint == REPAINT) - { + if (hint == REPAINT) { SetBkMode(hDC, OPAQUE); /* When switching from Digital to analog, the brush selected * continued to be black; So, the current background is to be @@ -573,38 +505,34 @@ HBRUSH hBr; DrawFatHand(hDC, oTime.hour * 5 + (oTime.minute / 12), hpenForeground, HHAND); DrawFatHand(hDC, oTime.minute, hpenForeground, MHAND); - if (!bIconic) /* Draw the second hand. */ + if (!ClockDisp.bIconic) /* Draw the second hand. */ DrawHand(hDC, oTime.second, hpenBackground, SECONDSCALE, R2_NOT); /* NOTE: Don't update oTime in this case! */ return; - } - else if (hint == HANDPAINT) - { - if ((!bIconic) && nTime.second != oTime.second) /* Erase the old second hand. */ - DrawHand(hDC, oTime.second, hpenBackground, SECONDSCALE, R2_NOT); - - if (nTime.minute != oTime.minute || nTime.hour != oTime.hour) - { - if (bIconic) - { - DrawHand(hDC, oTime.minute, hpenBackground, MINUTESCALE, R2_COPYPEN); - DrawHand(hDC, oTime.hour * 5 + (oTime.minute / 12), hpenBackground, HOURSCALE, R2_COPYPEN); - DrawHand(hDC, nTime.minute, hpenForeground, MINUTESCALE, R2_COPYPEN); - DrawHand(hDC, nTime.hour * 5 + (nTime.minute / 12), hpenForeground, HOURSCALE, R2_COPYPEN); + } + else if (hint == HANDPAINT) { + if ((!ClockDisp.bIconic) && nTime.second != oTime.second) /* Erase the old second hand. */ + DrawHand(hDC, oTime.second, hpenBackground, SECONDSCALE, R2_NOT); + + if (nTime.minute != oTime.minute || nTime.hour != oTime.hour) { + if (ClockDisp.bIconic) { + DrawHand(hDC, oTime.minute, hpenBackground, MINUTESCALE, R2_COPYPEN); + DrawHand(hDC, oTime.hour * 5 + (oTime.minute / 12), hpenBackground, HOURSCALE, R2_COPYPEN); + DrawHand(hDC, nTime.minute, hpenForeground, MINUTESCALE, R2_COPYPEN); + DrawHand(hDC, nTime.hour * 5 + (nTime.minute / 12), hpenForeground, HOURSCALE, R2_COPYPEN); } - else - { - DrawFatHand(hDC, oTime.minute, hpenBackground, MHAND); - DrawFatHand(hDC, oTime.hour*5+(oTime.minute/12), hpenBackground, HHAND); - DrawFatHand(hDC, nTime.minute, hpenForeground, MHAND); - DrawFatHand(hDC, (nTime.hour) * 5 + (nTime.minute / 12), hpenForeground, HHAND ); + else { + DrawFatHand(hDC, oTime.minute, hpenBackground, MHAND); + DrawFatHand(hDC, oTime.hour*5+(oTime.minute/12), hpenBackground, HHAND); + DrawFatHand(hDC, nTime.minute, hpenForeground, MHAND); + DrawFatHand(hDC, (nTime.hour) * 5 + (nTime.minute / 12), hpenForeground, HHAND ); } } - if (!bIconic && nTime.second != oTime.second) /* Draw new second hand */ - DrawHand(hDC, nTime.second, hpenBackground, SECONDSCALE, R2_NOT); + if (!ClockDisp.bIconic && nTime.second != oTime.second) /* Draw new second hand */ + DrawHand(hDC, nTime.second, hpenBackground, SECONDSCALE, R2_NOT); } } oTime = nTime; @@ -630,7 +558,7 @@ TIME nTime; /* It's possible to change any part of the system at any time * through the Control Panel. So we check everything. */ - if (((nTime.second == oTime.second) || bIconic) && + if (((nTime.second == oTime.second) || ClockDisp.bIconic) && (nTime.minute == oTime.minute) && (nTime.hour24 == oTime.hour24)) return; @@ -639,7 +567,7 @@ TIME nTime; ClockPaint(hWnd, hDC, HANDPAINT); ReleaseDC(hWnd, hDC); DdePostAdvise(idInst, hszTime, hszNow); - UNREFERENCED_PARAMETER(msg); + UNREFERENCED_PARAMETER(msg); } @@ -731,7 +659,7 @@ CHAR szWinHeader[21], szKeyName[21], szR if (!ClockDisp.wTimeFormat) ClockDisp.wDigTimeLen += ((i > ii) ? (i) : (ii)); - } +} /* @@ -741,18 +669,20 @@ CHAR szWinHeader[21], szKeyName[21], szR BOOL NEAR PASCAL ClockInit(HANDLE hInstance) { HDC hDC; -static WNDCLASS ClockClass; +WNDCLASS ClockClass; FormatInit(hInstance, TRUE); - ClockClass.lpszClassName = (LPSTR)szBuffer; - ClockClass.lpszMenuName = (LPSTR)szBuffer; - ClockClass.hbrBackground = (HBRUSH)NULL; - ClockClass.style = CS_VREDRAW | CS_HREDRAW; - ClockClass.hInstance = hInstance; + ClockClass.style = CS_VREDRAW | CS_HREDRAW | CS_DBLCLKS; ClockClass.lpfnWndProc = ClockWndProc; - ClockClass.hCursor = LoadCursor(NULL, IDC_ARROW); + ClockClass.cbClsExtra = 0; + ClockClass.cbWndExtra = 0; + ClockClass.hInstance = hInstance; ClockClass.hIcon = NULL; + ClockClass.hCursor = LoadCursor(NULL, IDC_ARROW); + ClockClass.hbrBackground = (HBRUSH) NULL; + ClockClass.lpszMenuName = (LPSTR)"Clock"; + ClockClass.lpszClassName = (LPSTR)"Clock"; if (!RegisterClass((LPWNDCLASS)&ClockClass)) return(FALSE); @@ -762,66 +692,126 @@ static WNDCLASS ClockClass; /* Check the number of colors that the display is capable of. */ hDC = CreateDC("DISPLAY", NULL, NULL, NULL); - bColor = (GetDeviceCaps(hDC, NUMCOLORS) > 2); - bColor = FALSE; + ClockDisp.bColor = (GetDeviceCaps(hDC, NUMCOLORS) > 2); + ClockDisp.bColor = FALSE; DeleteDC(hDC); + ClockDisp.bTmpHide = FALSE; + ClockDisp.bNewFont = FALSE; + ClockDisp.bColor = TRUE; + ClockDisp.bNewFont = TRUE; + return(TRUE); } +/* + * SetMenuBar() - places or removes the menu bar, etc. + * + * Based on the flag ClockDisp.bNoTitle (ie: do we want a menu/title + * bar or not?), adds or removes the window title and menu bar: + * Gets current style, toggles the bits, and re-sets the style. + * Must then resize the window frame and show it. + */ + +void NEAR PASCAL SetMenuBar( HWND hWnd ) +{ + static DWORD wID; + DWORD dwStyle; + + dwStyle = GetWindowLong( hWnd, GWL_STYLE ); + if( ClockDisp.bNoTitle ) { + /* remove caption & menu bar, etc. */ + dwStyle &= ~(WS_DLGFRAME | WS_SYSMENU | + WS_MINIMIZEBOX | WS_MAXIMIZEBOX ); + wID = SetWindowLong( hWnd, GWL_ID, 0 ); + } + else { + /* put menu bar & caption back in */ + dwStyle = WS_TILEDWINDOW | dwStyle; + SetWindowLong( hWnd, GWL_ID, wID ); + } + SetWindowLong( hWnd, GWL_STYLE, dwStyle ); + SetWindowPos( hWnd, NULL, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | + SWP_NOZORDER | SWP_FRAMECHANGED ); + ShowWindow( hWnd, SW_SHOW ); +} + +/* + * AboutDlgProc() + */ + +BOOL APIENTRY AboutDlgProc ( hwnd, msg, wParam, lParam ) +HWND hwnd; +UINT msg; +WPARAM wParam; +LPARAM lParam; +{ + switch (msg) { + case WM_INITDIALOG: + /* nothing to initialize */ + break; + + case WM_COMMAND: + switch (LOWORD(wParam)) { + case IDOK: + case IDCANCEL: + EndDialog(hwnd, 0); + break; + + default: + return FALSE; + } + break; + + default: + return(FALSE); + } + + return TRUE; +} + + /* * ClockWndProc() */ -LONG APIENTRY ClockWndProc(register HWND hWnd, UINT message, WPARAM wParam, LONG lParam) +LONG APIENTRY ClockWndProc(register HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { -HMENU hMenu; -CHAR szInt[2]; /* space for int to str conversion */ -static CHAR szAppName[12]; /* application name buffer */ +HMENU hMenu; +static CHAR szAppName[12]; /* application name buffer */ PAINTSTRUCT ps; - switch (message) - { + switch (message) { case WM_COMMAND: - switch (wParam) - { + switch (wParam) { + case IDM_ANALOG: case IDM_DIGITAL: - if (wParam != ClockDisp.wFormat) - { + if ((WORD)wParam != ClockDisp.wFormat) { /* Switch flag to other choice */ hMenu = GetMenu(hWnd); CheckMenuItem(hMenu, ClockDisp.wFormat, MF_BYCOMMAND | MF_UNCHECKED); - CheckMenuItem(hMenu, ClockDisp.wFormat = (WORD)wParam, MF_BYCOMMAND | MF_CHECKED); - InvalidateRect(hWnd, (LPRECT)NULL, TRUE); - - /* Write new configuration to CLOCK.INI */ - LoadString(hInst, IDS_USNAME, (LPSTR)szAppName, 8); - LoadString(hInst, IDS_CLKFORMAT, (LPSTR)szBuffer, BUFLEN-1); - szInt[0] = (CHAR)('0' + (ClockDisp.wFormat == IDM_ANALOG)); - szInt[1] = 0; - WritePrivateProfileString((LPSTR)szAppName, - (LPSTR)szBuffer, - (LPSTR)szInt, - (LPSTR)szIniFile); + CheckMenuItem(hMenu, ClockDisp.wFormat = (WORD) wParam, MF_BYCOMMAND | MF_CHECKED); + InvalidateRect(hWnd, (LPRECT) NULL, TRUE); } break; - case IDM_ABOUT: - { - LoadString(hInst, IDS_USNAME, (LPSTR)szAppName, 8); - // Add this when 3.1 stuff comes in. ShellAbout(hWnd, szAppName, (LPSTR)"", LoadIcon(hInst, (LPSTR)"cckk")); + case IDM_NOTITLE: + goto toggle_title; + + case IDM_ABOUT: { + DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUT), hWnd, (DLGPROC)AboutDlgProc); break; - } + } default: goto defproc; - } + } break; case WM_SIZE: - bNewFont = TRUE; + ClockDisp.bNewFont = TRUE; ClockSize(hWnd, LOWORD(lParam), HIWORD(lParam), (WORD)wParam); UpdateWindow(hWnd); break; @@ -829,8 +819,12 @@ PAINTSTRUCT ps; case WM_QUERYDRAGICON: return (LONG)LoadIcon(hInst, "cckk"); - case WM_DESTROY: - { + case WM_CLOSE: + case WM_ENDSESSION: + DestroyWindow( hWnd ); + break; + + case WM_DESTROY: { CHAR szInt[10]; HCURSOR hTempCursor; @@ -846,36 +840,54 @@ PAINTSTRUCT ps; if (!(IsIconic(hWnd) || IsZoomed(hWnd))) GetWindowRect(hWnd, &rCoordRect); + /* Write new configuration to DDEMLCLK.INI */ + LoadString(hInst, IDS_CLKFORMAT, (LPSTR)szBuffer, BUFLEN-1); + szInt[0] = (CHAR)('0' + (ClockDisp.wFormat == IDM_ANALOG)); + szInt[1] = 0; + WritePrivateProfileString((LPSTR)szSection, + (LPSTR)szBuffer, + (LPSTR)szInt, + (LPSTR)szIniFile); wsprintf((LPSTR)szInt, (LPSTR)"%i", (INT)IsIconic(hWnd)); WritePrivateProfileString((LPSTR)szSection, - (LPSTR)"Minimized", - (LPSTR)szInt, - (LPSTR)szIniFile); + (LPSTR)"Minimized", + (LPSTR)szInt, + (LPSTR)szIniFile); wsprintf((LPSTR)szInt, (LPSTR)"%i", (INT)IsZoomed(hWnd)); WritePrivateProfileString((LPSTR)szSection, - (LPSTR)"Maximized", - (LPSTR)szInt, - (LPSTR)szIniFile); + (LPSTR)"Maximized", + (LPSTR)szInt, + (LPSTR)szIniFile); wsprintf((LPSTR)szInt, (LPSTR)"%i", (INT)rCoordRect.left); WritePrivateProfileString((LPSTR)szSection, - (LPSTR)"Left", - (LPSTR)szInt, - (LPSTR)szIniFile); + (LPSTR)"Left", + (LPSTR)szInt, + (LPSTR)szIniFile); wsprintf((LPSTR)szInt, (LPSTR)"%i", (INT)rCoordRect.top); WritePrivateProfileString((LPSTR)szSection, - (LPSTR)"Top", - (LPSTR)szInt, - (LPSTR)szIniFile); + (LPSTR)"Top", + (LPSTR)szInt, + (LPSTR)szIniFile); wsprintf((LPSTR)szInt, (LPSTR)"%i", (INT)rCoordRect.right); WritePrivateProfileString((LPSTR)szSection, - (LPSTR)"Right", - (LPSTR)szInt, - (LPSTR)szIniFile); + (LPSTR)"Right", + (LPSTR)szInt, + (LPSTR)szIniFile); wsprintf((LPSTR)szInt, (LPSTR)"%i", (INT)rCoordRect.bottom); WritePrivateProfileString((LPSTR)szSection, - (LPSTR)"Bottom", - (LPSTR)szInt, - (LPSTR)szIniFile); + (LPSTR)"Bottom", + (LPSTR)szInt, + (LPSTR)szIniFile); + wsprintf((LPSTR)szInt, (LPSTR)"%i", (INT)ClockDisp.bTopMost); + WritePrivateProfileString((LPSTR)szSection, + (LPSTR)"TopMost", + (LPSTR)szInt, + (LPSTR)szIniFile); + wsprintf((LPSTR)szInt, (LPSTR)"%i", (INT)ClockDisp.bNoTitle); + WritePrivateProfileString((LPSTR)szSection, + (LPSTR)"NoTitle", + (LPSTR)szInt, + (LPSTR)szIniFile); PostQuitMessage(0); break; } @@ -887,18 +899,17 @@ PAINTSTRUCT ps; break; case WM_PAINT: - /* 25-Mar-1987. Added to force total repaint to solve + /* Added to force total repaint to solve * problem of garbage under second hand when hidden * by menu or popup. */ InvalidateRect(hWnd, (LPRECT)NULL, TRUE); BeginPaint(hWnd, (LPPAINTSTRUCT)&ps); - if (ClockDisp.wFormat == IDM_DIGITAL) - { + if (ClockDisp.wFormat == IDM_DIGITAL) { hbrBackground = hbrColorBlack; FillRect(ps.hdc, (LPRECT)&clockRect, hbrBackground); - } + } else hbrBackground=hbrColorWindow; @@ -915,34 +926,137 @@ PAINTSTRUCT ps; break; case WM_SYSCOMMAND: - switch (wParam) - { + switch (wParam) { + case SC_MINIMIZE: if (!IsZoomed(hWnd)) GetWindowRect(hWnd, (LPRECT)&rCoordRect); + ClockDisp.bMinimized = TRUE; + ClockDisp.bMaximized = FALSE; break; case SC_MAXIMIZE: if (!IsIconic(hWnd)) GetWindowRect(hWnd, (LPRECT)&rCoordRect); + ClockDisp.bMinimized = FALSE; + ClockDisp.bMaximized = TRUE; + break; + + case IDM_TOPMOST: { + /* toggles topmost option + */ + hMenu = GetSystemMenu(hWnd, FALSE); + if( ClockDisp.bTopMost ) { + CheckMenuItem( hMenu, IDM_TOPMOST, MF_BYCOMMAND | MF_UNCHECKED ); + SetWindowPos( hWnd, HWND_NOTOPMOST, 0, 0, 0, 0, + SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE); + ClockDisp.bTopMost = FALSE; + } + else { + CheckMenuItem( hMenu, IDM_TOPMOST, MF_BYCOMMAND | MF_CHECKED ); + SetWindowPos( hWnd, HWND_TOPMOST, 0, 0, 0, 0, + SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE); + ClockDisp.bTopMost = TRUE; + } break; + } + } return(DefWindowProc(hWnd, message, wParam, lParam)); break; + case WM_MOUSEACTIVATE: + /* right button temporarily hides the window if topmost is + * enabled (window re-appears when right button is released). + * When this happens, we don't want to activate the clock window + * just before hiding it (it would look really bad), so we + * intercept the activate message. + */ + if( GetAsyncKeyState( VK_RBUTTON ) & 0x8000 ) + return( MA_NOACTIVATE ); + else + goto defproc; + break; + + case WM_RBUTTONDOWN: + case WM_NCRBUTTONDOWN: + /* right button temporarily hides the window, if the window + * is topmost, and if no menu is currently "active" + */ + if( !ClockDisp.bTmpHide && ClockDisp.bTopMost ) { + ShowWindow( hWnd, SW_HIDE ); + SetCapture( hWnd ); + ClockDisp.bTmpHide = TRUE; + } + break; + + case WM_RBUTTONUP: + case WM_NCRBUTTONUP: + /* if window is currently hidden, right button up brings it + * back. Must make sure we show it in its previous state - ie: + * minimized, maximized or normal. + */ + if( ClockDisp.bTmpHide ) { + ReleaseCapture(); + if( IsIconic(hWnd) ) + ShowWindow( hWnd, SW_SHOWMINNOACTIVE ); + else if( IsZoomed( hWnd ) ) + ShowWindow( hWnd, SW_SHOWMAXIMIZED ); + else + ShowWindow( hWnd, SW_SHOWNOACTIVATE ); + ClockDisp.bTmpHide = FALSE; + } + break; + + case WM_KEYDOWN: + /* ESC key toggles the menu/title bar (just like a double click + * on the client area of the window. + */ + if( (wParam == VK_ESCAPE) && !(HIWORD( lParam ) & 0x4000) ) + goto toggle_title; + break; + + case WM_NCLBUTTONDBLCLK: + if( !ClockDisp.bNoTitle ) + /* if we have title bars etc. let the normal stuff take place */ + goto defproc; + + /* else: no title bars, then this is actually a request to bring + * the title bars back... + */ + + /* fall through */ + + case WM_LBUTTONDBLCLK: +toggle_title: + ClockDisp.bNoTitle = (ClockDisp.bNoTitle ? FALSE : TRUE ); + SetMenuBar( hWnd ); + break; + + case WM_NCHITTEST: + /* if we have no title/menu bar, clicking and dragging the client + * area moves the window. To do this, return HTCAPTION. + * Note dragging not allowed if window maximized, or if caption + * bar is present. + */ + wParam = DefWindowProc(hWnd, message, wParam, lParam); + if( ClockDisp.bNoTitle && (wParam == HTCLIENT) && !IsZoomed(hWnd) ) + return HTCAPTION; + else + return wParam; + case WM_SYSCOLORCHANGE: DeleteTools(); CreateTools(); break; - case WM_ERASEBKGND: - { + case WM_ERASEBKGND: { RECT rect; GetClientRect(hWnd, (LPRECT)&rect); SelectObject((HDC)wParam, hbrBackground); FillRect((HDC)wParam, (LPRECT)&rect, hbrBackground); break; - } + } default: defproc: @@ -952,23 +1066,22 @@ defproc: } - /* * WinMain() */ -int APIENTRY WinMain( - HANDLE hInstance, - HANDLE hPrev, - LPSTR lpCmdLine, - int cmdShow - ) +INT PASCAL WinMain( +HINSTANCE hInstance, +HINSTANCE hPrev, +LPSTR lpszCmdLine, +INT cmdShow) { register HWND hWnd; -MSG msg; -TIME nTime; -PSTR szTooMany; -INT iMinimized, iMaximized; +MSG msg; +TIME nTime; +PSTR szTooMany; +HMENU hMenu; +CHAR szTopmost[80]; LoadString(hInstance, IDS_USNAME, (LPSTR)szBuffer, BUFLEN); LoadString(hInstance, IDS_INIFILE, (LPSTR)szIniFile, 20); @@ -983,26 +1096,26 @@ INT iMinimized, iMaximized; rCoordRect.top=GetPrivateProfileInt((LPSTR)szSection, (LPSTR)"Top", - (DWORD)-1, (LPSTR)szIniFile); + (DWORD)-1, (LPSTR)szIniFile); rCoordRect.left=GetPrivateProfileInt((LPSTR)szSection, (LPSTR)"Left", - (DWORD)-1, (LPSTR)szIniFile); + (DWORD)-1, (LPSTR)szIniFile); rCoordRect.right=GetPrivateProfileInt((LPSTR)szSection, (LPSTR)"Right", - (DWORD)-1, (LPSTR)szIniFile); + (DWORD)-1, (LPSTR)szIniFile); rCoordRect.bottom=GetPrivateProfileInt((LPSTR)szSection, (LPSTR)"Bottom", - (DWORD)-1, (LPSTR)szIniFile); + (DWORD)-1, (LPSTR)szIniFile); - hWnd = CreateWindow((LPSTR)"Clock", /* The class name. */ - (LPSTR)szBuffer, /* The window instance name. */ + hWnd = CreateWindow((LPSTR)"Clock", /* The class name. */ + (LPSTR)szBuffer, /* The window instance name. */ WS_TILEDWINDOW, (rCoordRect.left < 0) ? CW_USEDEFAULT : rCoordRect.left, (rCoordRect.top < 0) ? CW_USEDEFAULT : rCoordRect.top, - (rCoordRect.left < 0) ? (INT)( (HorzRes/3) + GetSystemMetrics(SM_CXFRAME)*2 ) - : rCoordRect.right - rCoordRect.left, - (rCoordRect.left < 0) ? (INT)( (((HorzRes/3)*aspectN)/aspectD)+GetSystemMetrics(SM_CYCAPTION)+GetSystemMetrics(SM_CYFRAME)*2 ) - : rCoordRect.bottom - rCoordRect.top, + (rCoordRect.left < 0) ? (INT)( (HorzRes/3) + GetSystemMetrics(SM_CXFRAME)*2 ) + : rCoordRect.right - rCoordRect.left, + (rCoordRect.left < 0) ? (INT)( (((HorzRes/3)*aspectN)/aspectD)+GetSystemMetrics(SM_CYCAPTION)+GetSystemMetrics(SM_CYFRAME)*2 ) + : rCoordRect.bottom - rCoordRect.top, NULL, NULL, hInstance, @@ -1017,8 +1130,7 @@ INT iMinimized, iMaximized; } while (nTime.second == oTime.second && nTime.minute == oTime.minute && nTime.hour24 == oTime.hour24); - if (!SetTimer(hWnd, TimerID, OPEN_TLEN, 0L)) - { + if (!SetTimer(hWnd, TimerID, OPEN_TLEN, 0L) ) { /* Windows only supports 16 public timers */ szTooMany = (PSTR)LocalAlloc(LPTR, 160); LoadString(hInstance, IDS_TOOMANY, (LPSTR)szTooMany, 160); @@ -1027,23 +1139,48 @@ INT iMinimized, iMaximized; return(FALSE); } + /* Add the topmost system menu item */ + hMenu = GetSystemMenu( hWnd, FALSE ); + AppendMenu( hMenu, MF_SEPARATOR, 0, NULL ); + LoadString(hInstance, IDS_TOPMOST, szTopmost, 79); + + /* Check the default setting to the clock as topmost or not */ + ClockDisp.bTopMost=GetPrivateProfileInt((LPSTR)szSection, + (LPSTR)"TopMost", + 0, (LPSTR)szIniFile); + if( ClockDisp.bTopMost ) { + AppendMenu( hMenu, MF_ENABLED | MF_CHECKED | MF_STRING, IDM_TOPMOST, + szTopmost ); + SetWindowPos( hWnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE); + } + else + AppendMenu( hMenu, MF_ENABLED | MF_UNCHECKED | MF_STRING, IDM_TOPMOST, + szTopmost ); + /* Check the default menu item either analog or digital */ CheckMenuItem(GetMenu(hWnd), ClockDisp.wFormat, MF_BYCOMMAND | MF_CHECKED); + /* Check the default setting to show title bar or not */ + ClockDisp.bNoTitle=GetPrivateProfileInt((LPSTR)szSection, + (LPSTR)"NoTitle", + 0, (LPSTR)szIniFile); + if( ClockDisp.bNoTitle ) { + SetMenuBar( hWnd ); + } + hInst = hInstance; - iMinimized=GetPrivateProfileInt((LPSTR)szSection, + /* Check the default minimized state, minimized or not */ + ClockDisp.bMinimized=GetPrivateProfileInt((LPSTR)szSection, (LPSTR)"Minimized", 0, (LPSTR)szIniFile); - if (!iMinimized) - { - iMaximized=GetPrivateProfileInt((LPSTR)szSection, + if (!ClockDisp.bMinimized) { + ClockDisp.bMaximized=GetPrivateProfileInt((LPSTR)szSection, (LPSTR)"Maximized", 0, (LPSTR)szIniFile); - if (iMaximized) + if (ClockDisp.bMaximized) ShowWindow(hWnd, SW_MAXIMIZE); - else - { + else { ShowWindow(hWnd, cmdShow); GetWindowRect(hWnd, (LPRECT)&rCoordRect); } @@ -1053,18 +1190,17 @@ INT iMinimized, iMaximized; DdeInitialize(&idInst, (PFNCALLBACK)MakeProcInstance((FARPROC)DdeCallback, hInstance), CBF_FAIL_EXECUTES | CBF_SKIP_ALLNOTIFICATIONS, 0L); - - hszTime = DdeCreateStringHandle(idInst, "Time", 0); hszNow = DdeCreateStringHandle(idInst, "Now", 0); hszClock = DdeCreateStringHandle(idInst, "Clock", 0); DdeNameService(idInst, hszClock, 0L, DNS_REGISTER); - while (GetMessage((LPMSG)&msg, NULL, 0, 0)) - { + + + while (GetMessage((LPMSG)&msg, NULL, 0, 0) ) { TranslateMessage((LPMSG)&msg); DispatchMessage((LPMSG)&msg); - } + } DdeUninitialize(idInst); @@ -1072,6 +1208,10 @@ INT iMinimized, iMaximized; } +/* + * GetTime() + */ + VOID GetTime( TIME *ptime) { @@ -1089,7 +1229,11 @@ TIME *ptime) } -HDDEDATA EXPENTRY DdeCallback( +/* + * DdeCallback() + */ + +HDDEDATA CALLBACK DdeCallback( WORD usType, WORD usFmt, HCONV hConv, @@ -1099,6 +1243,11 @@ HDDEDATA hData, DWORD lData1, DWORD lData2) { + +static HANDLE hToken; +static TOKEN_PRIVILEGES tp; +static LUID luid; + if (usType == XTYP_CONNECT) { return(TRUE); } @@ -1144,17 +1293,30 @@ DWORD lData2) SYSTEMTIME SysTime; DdeGetData(hData, (LPBYTE)sz, 40L, 0L); - GetSystemTime(&SysTime); - sscanf(sz, "%d:%d:%d", &SysTime.wHour, &SysTime.wMinute, &SysTime.wSecond); - SetSystemTime(&SysTime); + GetLocalTime(&SysTime); + sscanf(sz, "%2d:%2d:%2d", &SysTime.wHour, &SysTime.wMinute, &SysTime.wSecond); + + /* enable system-time privilege, set time, disable privilege */ + OpenProcessToken( GetCurrentProcess(), + TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken ) ; + LookupPrivilegeValue( NULL, "SeSystemTimePrivilege", &luid ); + tp.PrivilegeCount = 1; + tp.Privileges[0].Luid = luid; + tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; + AdjustTokenPrivileges( hToken, FALSE, &tp, + sizeof(TOKEN_PRIVILEGES), NULL, NULL ); + SetLocalTime(&SysTime); + AdjustTokenPrivileges( hToken, TRUE, &tp, + sizeof(TOKEN_PRIVILEGES), NULL, NULL ); + DdePostAdvise(idInst, hszTime, hszNow); return(DDE_FACK); } } } return(0); - UNREFERENCED_PARAMETER(lData1); - UNREFERENCED_PARAMETER(lData2); - UNREFERENCED_PARAMETER(hConv); -} + UNREFERENCED_PARAMETER(lData1); + UNREFERENCED_PARAMETER(lData2); + UNREFERENCED_PARAMETER(hConv); +}