├── StdAfx.cpp ├── Timekeeper.rc ├── res ├── about.ico ├── arrow_r.bmp ├── datetime.ico ├── finger.cur ├── BandEnable.bmp ├── BandEnable.pdn └── company_logo.bmp ├── ConfigureDlg.cpp ├── help ├── de_flag.gif ├── configure.png ├── toolbars.png ├── 12noon-89x97.gif ├── context_menu.png ├── timekeeper.png ├── tk_multiline.png ├── tk_calendar_1x3.png ├── tk_calendar_2x1.png ├── tk_calendar_2x2.png ├── tk_calendar_3x1.png ├── tk_multiline_red.png ├── Overview.md └── Documentation.md ├── COMToys ├── BandObj.h ├── 1999-11 MSJ BandObj.pdf ├── 1999-12 MSJ COMToys.pdf ├── 1999-12 MSJ1299 COMToys.pdf ├── src │ ├── cty.def │ ├── StdAfx.cpp │ ├── Persist.cpp │ ├── OleWin.cpp │ ├── ComToys.cpp │ ├── DockWin.cpp │ ├── StdAfx.h │ ├── IniFile.cpp │ ├── InputObj.cpp │ ├── PersistStrm.cpp │ ├── ComObj.cpp │ ├── PersistFile.cpp │ ├── Module.cpp │ ├── MfcModule.cpp │ ├── MenuInit.cpp │ ├── Fact.cpp │ ├── MfcMenu.cpp │ └── Subclass.cpp ├── NonClient.h ├── BandObj.rgs ├── IniFile.h ├── MenuInit.h ├── COMtoysLink.h ├── DllEntry.cpp ├── Subclass.h ├── ComToys.vcxproj.filters ├── Debug.h └── TraceWin3.h ├── Shared ├── 12noon.bmp ├── Finger.cur ├── internal.h ├── utility.h ├── RegistryMonitor.h ├── utility.cpp ├── stl.h ├── skstUtil.h ├── Graphics_MyWin.h ├── Graphics_MyMFC.h ├── Graphics_MyMFC.cpp ├── ColorChooser.h ├── RegistryMonitor.cpp ├── Aboutdlg.h ├── StaticColor.h ├── VersionInfo.h ├── StatLink.h ├── Graphics_MyWin.cpp ├── Helper.cpp ├── ColorChooser.cpp ├── PMSRes.h ├── VersionInfo.cpp ├── misc.h ├── Registry.h ├── GetProcAddress.h ├── MyLog.h ├── StatLink.cpp ├── Aboutdlg.cpp ├── StaticColor.cpp ├── MyLog.cpp ├── PMSRes.rc ├── skstTools.h └── ToolTipCtrl.h ├── TimekeeperUnregister.reg ├── installer ├── Timekeeper.nsi └── build_installer.cmd ├── .gitignore ├── .github └── dependabot.yml ├── Timekeeper.def ├── targetver.h ├── LICENSE ├── StdAfx.h ├── Calendar.h ├── Timekeeper.sln ├── README.md ├── ConfigureDlg.h ├── MyBands.h ├── resource.h └── Timekeeper.vcxproj.filters /StdAfx.cpp: -------------------------------------------------------------------------------- 1 | #include "stdafx.h" 2 | 3 | 4 | -------------------------------------------------------------------------------- /Timekeeper.rc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/12noonLLC/Timekeeper/HEAD/Timekeeper.rc -------------------------------------------------------------------------------- /res/about.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/12noonLLC/Timekeeper/HEAD/res/about.ico -------------------------------------------------------------------------------- /ConfigureDlg.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/12noonLLC/Timekeeper/HEAD/ConfigureDlg.cpp -------------------------------------------------------------------------------- /help/de_flag.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/12noonLLC/Timekeeper/HEAD/help/de_flag.gif -------------------------------------------------------------------------------- /res/arrow_r.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/12noonLLC/Timekeeper/HEAD/res/arrow_r.bmp -------------------------------------------------------------------------------- /res/datetime.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/12noonLLC/Timekeeper/HEAD/res/datetime.ico -------------------------------------------------------------------------------- /res/finger.cur: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/12noonLLC/Timekeeper/HEAD/res/finger.cur -------------------------------------------------------------------------------- /COMToys/BandObj.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/12noonLLC/Timekeeper/HEAD/COMToys/BandObj.h -------------------------------------------------------------------------------- /Shared/12noon.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/12noonLLC/Timekeeper/HEAD/Shared/12noon.bmp -------------------------------------------------------------------------------- /Shared/Finger.cur: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/12noonLLC/Timekeeper/HEAD/Shared/Finger.cur -------------------------------------------------------------------------------- /help/configure.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/12noonLLC/Timekeeper/HEAD/help/configure.png -------------------------------------------------------------------------------- /help/toolbars.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/12noonLLC/Timekeeper/HEAD/help/toolbars.png -------------------------------------------------------------------------------- /res/BandEnable.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/12noonLLC/Timekeeper/HEAD/res/BandEnable.bmp -------------------------------------------------------------------------------- /res/BandEnable.pdn: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/12noonLLC/Timekeeper/HEAD/res/BandEnable.pdn -------------------------------------------------------------------------------- /help/12noon-89x97.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/12noonLLC/Timekeeper/HEAD/help/12noon-89x97.gif -------------------------------------------------------------------------------- /help/context_menu.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/12noonLLC/Timekeeper/HEAD/help/context_menu.png -------------------------------------------------------------------------------- /help/timekeeper.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/12noonLLC/Timekeeper/HEAD/help/timekeeper.png -------------------------------------------------------------------------------- /help/tk_multiline.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/12noonLLC/Timekeeper/HEAD/help/tk_multiline.png -------------------------------------------------------------------------------- /res/company_logo.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/12noonLLC/Timekeeper/HEAD/res/company_logo.bmp -------------------------------------------------------------------------------- /TimekeeperUnregister.reg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/12noonLLC/Timekeeper/HEAD/TimekeeperUnregister.reg -------------------------------------------------------------------------------- /help/tk_calendar_1x3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/12noonLLC/Timekeeper/HEAD/help/tk_calendar_1x3.png -------------------------------------------------------------------------------- /help/tk_calendar_2x1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/12noonLLC/Timekeeper/HEAD/help/tk_calendar_2x1.png -------------------------------------------------------------------------------- /help/tk_calendar_2x2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/12noonLLC/Timekeeper/HEAD/help/tk_calendar_2x2.png -------------------------------------------------------------------------------- /help/tk_calendar_3x1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/12noonLLC/Timekeeper/HEAD/help/tk_calendar_3x1.png -------------------------------------------------------------------------------- /help/tk_multiline_red.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/12noonLLC/Timekeeper/HEAD/help/tk_multiline_red.png -------------------------------------------------------------------------------- /installer/Timekeeper.nsi: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/12noonLLC/Timekeeper/HEAD/installer/Timekeeper.nsi -------------------------------------------------------------------------------- /COMToys/1999-11 MSJ BandObj.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/12noonLLC/Timekeeper/HEAD/COMToys/1999-11 MSJ BandObj.pdf -------------------------------------------------------------------------------- /COMToys/1999-12 MSJ COMToys.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/12noonLLC/Timekeeper/HEAD/COMToys/1999-12 MSJ COMToys.pdf -------------------------------------------------------------------------------- /COMToys/1999-12 MSJ1299 COMToys.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/12noonLLC/Timekeeper/HEAD/COMToys/1999-12 MSJ1299 COMToys.pdf -------------------------------------------------------------------------------- /COMToys/src/cty.def: -------------------------------------------------------------------------------- 1 | LIBRARY CTY 2 | DESCRIPTION 'ComToys MFC Extensions' 3 | EXPORTS 4 | ; Explicit exports can go here 5 | -------------------------------------------------------------------------------- /COMToys/src/StdAfx.cpp: -------------------------------------------------------------------------------- 1 | #include "StdAfx.h" 2 | 3 | // The following symbol used to force inclusion of this module 4 | extern "C" { int _ctForceLinkSTDAFX; } 5 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | desktop.ini 2 | Thumbs.db 3 | 4 | *.aps 5 | *.bak 6 | *.diff 7 | *.lib 8 | *.pdb 9 | *.user 10 | 11 | **/.vs/ 12 | **/Win32/ 13 | **/x64/ 14 | 15 | help/Windows 2000/ 16 | help/Windows XP/ 17 | installer/files*/ 18 | TestFormat/ 19 | 20 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | # https://docs.github.com/github/administering-a-repository/configuration-options-for-dependency-updates 2 | 3 | version: 2 4 | updates: 5 | - package-ecosystem: "github-actions" 6 | directory: "/" 7 | schedule: 8 | interval: "weekly" 9 | -------------------------------------------------------------------------------- /Timekeeper.def: -------------------------------------------------------------------------------- 1 | LIBRARY "Timekeeper" 2 | ;DESCRIPTION '12noon Timekeeper' 3 | 4 | EXPORTS 5 | ; Explicit exports can go here 6 | DllCanUnloadNow PRIVATE 7 | DllGetClassObject PRIVATE 8 | DllRegisterServer PRIVATE 9 | DllUnregisterServer PRIVATE 10 | DllInstall PRIVATE 11 | -------------------------------------------------------------------------------- /COMToys/NonClient.h: -------------------------------------------------------------------------------- 1 | ////////////////// 2 | // Get NONCLIENTMETRICS info: ctor calls SystemParametersInfo. 3 | // 4 | class CNonClientMetrics : public NONCLIENTMETRICS { 5 | public: 6 | CNonClientMetrics() { 7 | cbSize = sizeof(NONCLIENTMETRICS); 8 | SystemParametersInfo(SPI_GETNONCLIENTMETRICS,0,this,0); 9 | } 10 | }; 11 | 12 | -------------------------------------------------------------------------------- /targetver.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | // Including SDKDDKVer.h defines the highest available Windows platform. 4 | 5 | // If you wish to build your application for a previous Windows platform, include WinSDKVer.h and 6 | // set the _WIN32_WINNT macro to the platform you wish to support before including SDKDDKVer.h. 7 | 8 | #include 9 | -------------------------------------------------------------------------------- /Shared/internal.h: -------------------------------------------------------------------------------- 1 | //--------------------------------------------------------------------------- 2 | // (c) 2002-2009 12noon, Stefan K. S. Tucker 3 | // (c) 2001-2002 Perpetual Motion Software, Stefan K. S. Tucker 4 | //--------------------------------------------------------------------------- 5 | 6 | extern tstring _MyFormatArgList(LPCTSTR szFormat, const va_list& argList); 7 | -------------------------------------------------------------------------------- /Shared/utility.h: -------------------------------------------------------------------------------- 1 | //--------------------------------------------------------------------------- 2 | // (c) 2006 12noon, Stefan K. S. Tucker 3 | //--------------------------------------------------------------------------- 4 | 5 | #pragma once 6 | 7 | namespace MyWin 8 | { 9 | 10 | extern inline int RoundToNearestMultiple(const int n, const int denominator); 11 | 12 | } 13 | -------------------------------------------------------------------------------- /COMToys/BandObj.rgs: -------------------------------------------------------------------------------- 1 | HKCR 2 | { 3 | NoRemove CLSID 4 | { 5 | ForceRemove %CLSID% = s '%ClassName%' 6 | { 7 | InprocServer32 = s '%MODULE%' 8 | { 9 | val ThreadingModel = s '%ThreadingModel%' 10 | } 11 | } 12 | } 13 | NoRemove 'Component Categories' 14 | { 15 | NoRemove {00021492-0000-0000-C000-000000000046} 16 | { 17 | Delete Enum 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /Shared/RegistryMonitor.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | class RegistryMonitor 6 | { 7 | protected: 8 | HKEY _hKeyMonitor; // The key to monitor 9 | CEvent _evtNotify; // Signalled when registry key changes 10 | 11 | public: 12 | RegistryMonitor(); 13 | virtual ~RegistryMonitor(); 14 | 15 | void Monitor(HKEY hAppKey, LPCTSTR szKeyName); 16 | bool IsModified() const; 17 | 18 | protected: 19 | void Close(); 20 | }; 21 | -------------------------------------------------------------------------------- /COMToys/IniFile.h: -------------------------------------------------------------------------------- 1 | ////////////////// 2 | // CInitFile lets you put profile settings in a .INI file instead 3 | // of the registry. To use it, write: 4 | // 5 | // CIniFile::Use(this, CIniFile::WindowsINI); // put INI file in \WINDOWS dir 6 | // CIniFile::Use(this, CIniFile::LocalINI); // put it in same dir as pgm 7 | // 8 | // where "this" is a ptr to your CWinApp/ 9 | // Normally do this in your app's InitInstance fn. 10 | // 11 | class CIniFile { 12 | public: 13 | enum INI_LOCATION { WinDir, LocalDir }; 14 | static void Use(CWinApp *pApp, const INI_LOCATION where, LPCTSTR szProfileName = NULL); 15 | }; 16 | -------------------------------------------------------------------------------- /Shared/utility.cpp: -------------------------------------------------------------------------------- 1 | //--------------------------------------------------------------------------- 2 | // (c) 2006 12noon, Stefan K. S. Tucker 3 | //--------------------------------------------------------------------------- 4 | 5 | #include "stdafx.h" 6 | 7 | #include "skstUtil.h" 8 | #include "utility.h" 9 | 10 | /* 11 | This function rounds the passed number so that the result 12 | is the nearest multiple of the passed denominator. 13 | */ 14 | int MyWin::RoundToNearestMultiple(const int n, const int denominator) 15 | { 16 | assert(denominator != 0); 17 | return (n + (denominator / 2)) / denominator * denominator; 18 | } 19 | -------------------------------------------------------------------------------- /Shared/stl.h: -------------------------------------------------------------------------------- 1 | //--------------------------------------------------------------------------- 2 | // (c) 2002-2009 12noon, Stefan K. S. Tucker 3 | // (c) 2001-2002 Perpetual Motion Software, Stefan K. S. Tucker 4 | //--------------------------------------------------------------------------- 5 | 6 | #pragma once 7 | 8 | #include // warning numbers get enabled in yvals.h 9 | 10 | #include 11 | 12 | #include 13 | 14 | #include 15 | #include 16 | #include 17 | #include 18 | 19 | #include 20 | 21 | #include 22 | 23 | #include 24 | #include 25 | -------------------------------------------------------------------------------- /COMToys/src/Persist.cpp: -------------------------------------------------------------------------------- 1 | //////////////////////////////////////////////////////////////// 2 | // ComToys(TM) Copyright 1999 Paul DiLascia 3 | // If this code works, it was written by Paul DiLascia. 4 | // If not, I don't know who wrote it. 5 | // 6 | #include "StdAfx.h" 7 | #include "COMtoys/ComToys.h" 8 | 9 | #ifdef _DEBUG 10 | #define new DEBUG_NEW 11 | #undef THIS_FILE 12 | static char THIS_FILE[] = __FILE__; 13 | #endif 14 | 15 | CTPersist::CTPersist(const CLSID& clsid) : m_clsid(clsid) 16 | { 17 | } 18 | 19 | CTPersist::~CTPersist() 20 | { 21 | } 22 | 23 | STDMETHODIMP CTPersist::GetClassID(LPCLSID pClassID) 24 | { 25 | CTTRACEFN(_T("CTPersist::GetClassID\n")); 26 | return pClassID ? (*pClassID=m_clsid, S_OK) : E_UNEXPECTED; 27 | } 28 | -------------------------------------------------------------------------------- /Shared/skstUtil.h: -------------------------------------------------------------------------------- 1 | //--------------------------------------------------------------------------- 2 | // (c) 2001-2017 12noon, Perpetual Motion Software, Stefan K. S. Tucker 3 | //--------------------------------------------------------------------------- 4 | 5 | #pragma once 6 | 7 | #if defined(ASSERT) 8 | #undef assert 9 | #define assert ASSERT 10 | #else 11 | #include 12 | #endif 13 | 14 | #include // HDROP ::GetDroppedFilePath 15 | 16 | 17 | /* 18 | Create flexible string class. 19 | http://msdn.microsoft.com/en-us/magazine/cc188714.aspx 20 | */ 21 | #if defined(_UNICODE) 22 | typedef std::wstring tstring; 23 | #else 24 | typedef std::string tstring; 25 | #endif 26 | -------------------------------------------------------------------------------- /COMToys/src/OleWin.cpp: -------------------------------------------------------------------------------- 1 | //////////////////////////////////////////////////////////////// 2 | // ComToys(TM) Copyright 1999 Paul DiLascia 3 | // If this code works, it was written by Paul DiLascia. 4 | // If not, I don't know who wrote it. 5 | // 6 | #include "StdAfx.h" 7 | #include "COMtoys/ComToys.h" 8 | 9 | #ifdef _DEBUG 10 | #define new DEBUG_NEW 11 | #undef THIS_FILE 12 | static char THIS_FILE[] = __FILE__; 13 | #endif 14 | 15 | DEBUG_BEGIN_INTERFACE_NAMES() 16 | DEBUG_INTERFACE_NAME(IOleWindow) 17 | DEBUG_END_INTERFACE_NAMES(); 18 | 19 | STDMETHODIMP CTOleWindow::GetWindow(HWND* pHwnd) 20 | { 21 | if (pHwnd) 22 | *pHwnd = m_hWndOleWindow; 23 | return S_OK; 24 | } 25 | 26 | STDMETHODIMP CTOleWindow::ContextSensitiveHelp (BOOL) 27 | { 28 | return E_NOTIMPL; // sorry, not yet 29 | } 30 | -------------------------------------------------------------------------------- /COMToys/MenuInit.h: -------------------------------------------------------------------------------- 1 | //////////////////////////////////////////////////////////////// 2 | // PixieLib(TM) Copyright 1997-1998 Paul DiLascia 3 | // If this code works, it was written by Paul DiLascia. 4 | // If not, I don't know who wrote it. 5 | // 6 | #pragma once 7 | 8 | #include "Subclass.h" 9 | 10 | class CPopupMenuInit { 11 | public: 12 | static void Init(CCmdTarget* pTarg, 13 | CMenu* pMenu, BOOL bAutoMenuEnable=TRUE); 14 | }; 15 | 16 | class CPopupMenuInitHandler: public CSubclassWnd { 17 | public: 18 | BOOL m_bAutoMenuEnable; 19 | CPopupMenuInitHandler(); 20 | virtual ~CPopupMenuInitHandler(); 21 | 22 | BOOL Install(CWnd* pWnd) { 23 | return HookWindow(pWnd); 24 | } 25 | void Remove() { 26 | HookWindow((HWND)NULL); 27 | } 28 | 29 | protected: 30 | virtual void OnMenuInitPopup(CMenu* pMenu, UINT nIndex, BOOL bSysMenu); 31 | virtual LRESULT WindowProc(UINT msg, WPARAM wp, LPARAM lp); 32 | }; -------------------------------------------------------------------------------- /installer/build_installer.cmd: -------------------------------------------------------------------------------- 1 | @echo off 2 | 3 | setlocal 4 | 5 | set versionApp=1.62.9.0 6 | 7 | echo. 8 | echo Remember to set the version in this script... 9 | echo Version set to %versionApp%. 10 | echo. 11 | pause 12 | 13 | cd "%~dp0" 14 | cd 15 | 16 | md files >nul: 17 | del /q files\*.* 18 | 19 | copy /y ..\Win32\Release\Timekeeper.dll files 20 | copy /y ..\x64\Release\Timekeeper.dll files\Timekeeper64.dll 21 | copy /y ..\help\*.htm files 22 | copy /y ..\help\*.png files 23 | copy /y ..\help\*.gif files 24 | copy /y ..\LICENSE files 25 | 26 | attrib -r files\*.* 27 | 28 | if EXIST timekeeper-setup.exe del /q timekeeper-setup.exe 29 | 30 | set pathEXE=makensis.exe 31 | if not exist "%pathEXE%" ( 32 | echo. 33 | echo Unable to find NSIS. Please install from http://nsis.sourceforge.net. 34 | echo. 35 | goto :EOF 36 | ) 37 | 38 | "%pathEXE%" -DgVerInstaller=%versionApp% Timekeeper.nsi 39 | 40 | endlocal 41 | -------------------------------------------------------------------------------- /Shared/Graphics_MyWin.h: -------------------------------------------------------------------------------- 1 | //--------------------------------------------------------------------------- 2 | // (c) 2006 12noon, Stefan K. S. Tucker 3 | //--------------------------------------------------------------------------- 4 | 5 | #pragma once 6 | 7 | /* 8 | Microsoft's versions of these macros (wingdi.h) fail the compiler's 9 | smaller-type-conversion test. You have to cast off the leading 10 | bits so that it isn't losing data when it's downcast. Sheesh. 11 | Thanks, Microsoft. 12 | */ 13 | #define MyGetRValue(rgb) ((BYTE)((rgb) & 0xFF)) 14 | #define MyGetGValue(rgb) ((BYTE)(((WORD)((rgb) & 0xFF00)) >> 8)) 15 | #define MyGetBValue(rgb) ((BYTE)(((rgb) & 0xFF0000) >> 16)) 16 | 17 | 18 | namespace MyWin 19 | { 20 | 21 | extern void MoveRectangleInsideScreen(RECT& r); 22 | extern void MoveRectangleInsideWorkarea(RECT& r); 23 | extern void MoveRectangleInsideRectangle(const RECT& rBig, RECT& rSmall); 24 | 25 | } 26 | -------------------------------------------------------------------------------- /Shared/Graphics_MyMFC.h: -------------------------------------------------------------------------------- 1 | //--------------------------------------------------------------------------- 2 | // (c) 2006 12noon, Stefan K. S. Tucker 3 | //--------------------------------------------------------------------------- 4 | 5 | #pragma once 6 | 7 | namespace MyMFC 8 | { 9 | 10 | extern CSize CalculateTextSize(LPCTSTR szText, CFont& font); 11 | extern CSize CalculateTextSize(LPCTSTR szText, HFONT hFont); 12 | 13 | ///////////////////////////////////////////////////////////////////////////// 14 | ///////////////////////////////////////////////////////////////////////////// 15 | 16 | /* 17 | This little class forces the dialog to the foreground. 18 | 19 | Example: 20 | CForegroundDlg(IDD_MY_DIALOG).DoModal(); 21 | */ 22 | class CForegroundDlg : public CDialog 23 | { 24 | public: 25 | CForegroundDlg(const UINT id) : CDialog(id) {} 26 | BOOL OnInitDialog() 27 | { 28 | SetForegroundWindow(); 29 | return CDialog::OnInitDialog(); 30 | } 31 | }; 32 | 33 | } 34 | -------------------------------------------------------------------------------- /COMToys/src/ComToys.cpp: -------------------------------------------------------------------------------- 1 | //////////////////////////////////////////////////////////////// 2 | // ComToys(TM) Copyright 1999 Paul DiLascia 3 | // If this code works, it was written by Paul DiLascia. 4 | // If not, I don't know who wrote it. 5 | // 6 | #include "StdAfx.h" 7 | //VS.NET #include 8 | #include "COMtoys/ComToys.h" 9 | 10 | #ifdef _DEBUG 11 | #define new DEBUG_NEW 12 | #undef THIS_FILE 13 | static char THIS_FILE[] = __FILE__; 14 | #endif 15 | 16 | // To turn debugging on, set this TRUE 17 | BOOL ComToys::bTRACE = FALSE; 18 | 19 | ////////////////// 20 | // Helper function to allocate memory using IMalloc 21 | // 22 | DLLFUNC HRESULT CTOleAlloc(ULONG cb, LPVOID* ppv) 23 | { 24 | CTCHECKARG(ppv); 25 | CComPtr spMalloc; 26 | 27 | HRESULT hr = ::CoGetMalloc(MEMCTX_TASK, &spMalloc); 28 | if (FAILED(hr)) { 29 | *ppv = NULL; 30 | TRACE(_T("***Warning: CoGetMalloc failed %08lx"), hr); 31 | } else { 32 | *ppv=spMalloc->Alloc(cb); 33 | } 34 | return FAILED(hr) ? hr : *ppv==NULL ? E_OUTOFMEMORY : S_OK; 35 | } 36 | 37 | -------------------------------------------------------------------------------- /COMToys/src/DockWin.cpp: -------------------------------------------------------------------------------- 1 | //////////////////////////////////////////////////////////////// 2 | // ComToys(TM) Copyright 1999 Paul DiLascia 3 | // If this code works, it was written by Paul DiLascia. 4 | // If not, I don't know who wrote it. 5 | // 6 | #include "StdAfx.h" 7 | #include "COMtoys/ComToys.h" 8 | 9 | #ifdef _DEBUG 10 | #define new DEBUG_NEW 11 | #undef THIS_FILE 12 | static char THIS_FILE[] = __FILE__; 13 | #endif 14 | 15 | DEBUG_BEGIN_INTERFACE_NAMES() 16 | DEBUG_INTERFACE_NAME(IDockingWindow) 17 | DEBUG_END_INTERFACE_NAMES() 18 | 19 | STDMETHODIMP CTDockingWindow::ShowDW(BOOL fShow) 20 | { 21 | if (m_hWndDockingWindow) 22 | ::ShowWindow(m_hWndDockingWindow, fShow ? SW_SHOW : SW_HIDE); 23 | return S_OK; 24 | } 25 | 26 | STDMETHODIMP CTDockingWindow::CloseDW(DWORD dwReserved) 27 | { 28 | if (m_hWndDockingWindow) 29 | ::SendMessage(m_hWndDockingWindow, WM_CLOSE, 0, 0); 30 | return S_OK; 31 | } 32 | 33 | STDMETHODIMP CTDockingWindow::ResizeBorderDW(LPCRECT prcBorder, 34 | IUnknown* punkDWSite, BOOL fReserved) 35 | { 36 | return E_NOTIMPL; // Not yet 37 | } 38 | 39 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | (c) 2004-2025 12noon LLC 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /StdAfx.h: -------------------------------------------------------------------------------- 1 | // stdafx.h : include file for standard system include files, 2 | // or project specific include files that are used frequently, but 3 | // are changed infrequently 4 | // 5 | 6 | /* 7 | 8.1 0x0603 8 | 8 0x0602 9 | 7 0x0601 10 | Vista 0x0600 11 | 2003 0x0502 12 | XP 0x0501 13 | 2K/Me 0x0500 14 | 98 0x0410 15 | 95 0x0400 16 | */ 17 | #include 18 | 19 | //#define _WIN32_WINDOWS 0x0600 20 | //#define WINVER 0x0600 21 | 22 | #define _WIN32_WINNT 0x0601 23 | 24 | #ifndef VC_EXTRALEAN 25 | #define VC_EXTRALEAN // Exclude rarely-used stuff from Windows headers 26 | #endif 27 | 28 | #include "targetver.h" 29 | 30 | 31 | #define _ATL_CSTRING_EXPLICIT_CONSTRUCTORS // some CString constructors will be explicit 32 | 33 | #include // MFC core and standard components 34 | #include // You must #include before ANY shlobj.h (e.g., afxdisp.h, afxdtctl.h) 35 | #include // For COleDateTime (in afxcomtime.h) 36 | #include // For Unicode conversion macros 37 | 38 | #include "Shared/stl.h" 39 | #include 40 | -------------------------------------------------------------------------------- /Shared/Graphics_MyMFC.cpp: -------------------------------------------------------------------------------- 1 | //--------------------------------------------------------------------------- 2 | // (c) 2006 12noon, Stefan K. S. Tucker 3 | //--------------------------------------------------------------------------- 4 | 5 | #include "stdafx.h" 6 | #include 7 | 8 | #include "Graphics_MyMFC.h" 9 | 10 | /* 11 | Calculate the size (in pixels) of a passed string for a passed font. 12 | */ 13 | CSize MyMFC::CalculateTextSize(LPCTSTR szText, CFont& font) 14 | { 15 | return CalculateTextSize(szText, (HFONT) font); 16 | } 17 | 18 | CSize MyMFC::CalculateTextSize(LPCTSTR szText, HFONT hFont) 19 | { 20 | // create a DC for the font 21 | CDC dc; 22 | dc.CreateCompatibleDC(nullptr); 23 | // use the passed font 24 | HFONT hFontOld = SelectFont(dc.GetSafeHdc(), hFont); 25 | 26 | // calc the size 27 | // const CSize sz(dc.GetOutputTextExtent(szText)); 28 | CRect r; 29 | dc.DrawText(szText, &r, DT_CALCRECT); 30 | const CSize sz(r.Width(), r.Height()); 31 | 32 | SelectFont(dc.GetSafeHdc(), hFontOld); 33 | 34 | // TRACE(_T("\tText extent of \"%s\": %dx%d\n"), szText, sz.cx, sz.cy); 35 | return sz; 36 | } 37 | -------------------------------------------------------------------------------- /COMToys/src/StdAfx.h: -------------------------------------------------------------------------------- 1 | /* 2 | 8.1 0x0603 3 | 8 0x0602 4 | 7 0x0601 5 | Vista 0x0600 6 | 2003 0x0502 7 | XP 0x0501 8 | 2K/Me 0x0500 9 | 98 0x0410 10 | 95 0x0400 11 | */ 12 | //#define _WIN32_WINDOWS 0x0600 13 | //#define WINVER 0x0600 14 | 15 | #define _WIN32_WINNT 0x0601 16 | 17 | #ifndef VC_EXTRALEAN 18 | #define VC_EXTRALEAN // Exclude rarely-used stuff from Windows headers 19 | #endif 20 | 21 | #include 22 | 23 | 24 | #include // MFC core and standard components 25 | #include // MFC OLE automation classes 26 | #include // For Unicode conversion macros 27 | #include // control stuff 28 | #include // Multithreading 29 | #include //VS.NET 30 | /* 31 | VCInstallDir = C:\Program Files\Microsoft Visual Studio 8\VC\ 32 | We need the comdef.h in the MS Platform SDK at 33 | C:\Program Files\Microsoft Platform SDK\Include\ComDef.h 34 | */ 35 | //#include <\Program Files\Microsoft Platform SDK\Include\ComDef.h> 36 | #include // basic COM defs (_bstr_t etc., includes comutil.h) 37 | #include // for IDeskBand ettc 38 | #include // ATL stuff 39 | -------------------------------------------------------------------------------- /Shared/ColorChooser.h: -------------------------------------------------------------------------------- 1 | //--------------------------------------------------------------------------- 2 | // (c) 2006-2009 12noon, Stefan K. S. Tucker 3 | //--------------------------------------------------------------------------- 4 | 5 | #pragma once 6 | 7 | #include "Shared/Registry.h" 8 | 9 | namespace PMS 10 | { 11 | 12 | class ColorChooserDlg : public CColorDialog 13 | { 14 | DECLARE_DYNAMIC(ColorChooserDlg) 15 | 16 | protected: 17 | /* 18 | [optional] Where to store this info in the Registry 19 | */ 20 | static skst::Registry::EType _eRegKeyType; 21 | static tstring _strPathKey; 22 | 23 | // most recently used color 24 | static COLORREF _crMRU; 25 | // up to 16 custom colors from the user 26 | static COLORREF _crCustom[16]; // doc for CHOOSECOLOR struct says there are 16 27 | 28 | public: 29 | ColorChooserDlg(CWnd* pParentWnd, const COLORREF& crColor); 30 | virtual ~ColorChooserDlg() {} 31 | 32 | // optional: set up where to save information in the Registry 33 | static _declspec(deprecated) void SetRegistryLocation(const skst::Registry::EType eType, LPCTSTR szKey); 34 | 35 | protected: 36 | DECLARE_MESSAGE_MAP() 37 | virtual BOOL OnColorOK(); 38 | }; 39 | 40 | } 41 | -------------------------------------------------------------------------------- /Shared/RegistryMonitor.cpp: -------------------------------------------------------------------------------- 1 | #include "StdAfx.h" 2 | #include "RegistryMonitor.h" 3 | 4 | RegistryMonitor::RegistryMonitor() 5 | { 6 | _hKeyMonitor = nullptr; 7 | } 8 | 9 | 10 | RegistryMonitor::~RegistryMonitor() 11 | { 12 | Close(); 13 | } 14 | 15 | void RegistryMonitor::Close() 16 | { 17 | if (_hKeyMonitor != nullptr) 18 | ::RegCloseKey(_hKeyMonitor); 19 | } 20 | 21 | 22 | void RegistryMonitor::Monitor(HKEY hkeyRoot, LPCTSTR szKeyName) 23 | { 24 | Close(); 25 | 26 | /* 27 | monitor the registry key for changes 28 | */ 29 | VERIFY(::RegOpenKeyEx(hkeyRoot, szKeyName, NULL, KEY_NOTIFY, &_hKeyMonitor) == ERROR_SUCCESS); 30 | VERIFY(::RegNotifyChangeKeyValue(_hKeyMonitor, FALSE /*watch subtree*/, REG_NOTIFY_CHANGE_LAST_SET, _evtNotify, TRUE /*asynch*/) == ERROR_SUCCESS); 31 | } 32 | 33 | 34 | bool RegistryMonitor::IsModified() const 35 | { 36 | if (_hKeyMonitor == nullptr) 37 | return false; 38 | 39 | // if there's a change in the monitored registry key, re-load the format 40 | if (::WaitForSingleObject(_evtNotify, 0) == WAIT_OBJECT_0) 41 | { 42 | // monitor the registry key again 43 | VERIFY(::RegNotifyChangeKeyValue(_hKeyMonitor, FALSE /*watch subtree*/, REG_NOTIFY_CHANGE_LAST_SET, _evtNotify, TRUE /*asynch*/) == ERROR_SUCCESS); 44 | return true; 45 | } 46 | 47 | return false; 48 | } 49 | -------------------------------------------------------------------------------- /COMToys/src/IniFile.cpp: -------------------------------------------------------------------------------- 1 | //////////////////////////////////////////////////////////////// 2 | // Copyright 1998 Paul DiLascia 3 | // If this program works, it was written by Paul DiLascia. 4 | // If not, I don't know who wrote it. 5 | // 6 | #include "StdAfx.h" 7 | #include "COMtoys/IniFile.h" 8 | 9 | #ifdef _DEBUG 10 | #define new DEBUG_NEW 11 | #undef THIS_FILE 12 | static char THIS_FILE[] = __FILE__; 13 | #endif 14 | 15 | void CIniFile::Use(CWinApp *pApp, const INI_LOCATION where, LPCTSTR szProfileName) 16 | { 17 | TCHAR buf[_MAX_PATH]; 18 | // For some reason, this gets the 8.3 path, even though MS's doc says that only happens on 9x/Me. 19 | // Thanks, Microsoft. 20 | VERIFY(::GetModuleFileName(pApp->m_hInstance, buf, sizeof buf)); 21 | LPTSTR ext = _tcsrchr(buf, _T('.')); // points to ".exe" 22 | ASSERT(ext); 23 | _tcscpy_s(ext, ::_tcslen(ext) + 1, _T(".INI")); // now .INI 24 | 25 | LPTSTR name = _tcsrchr(buf, _T('\\')); // points to "foo.ini" 26 | VERIFY(name++); 27 | if (szProfileName != NULL) 28 | _tcscpy_s(name, ::_tcslen(name) + 1, szProfileName); 29 | 30 | szProfileName = (where == LocalDir) ? buf : name; 31 | 32 | // set the name 33 | free((void*)pApp->m_pszProfileName); 34 | pApp->m_pszProfileName = _tcsdup(szProfileName); 35 | free((void*)pApp->m_pszRegistryKey); 36 | pApp->m_pszRegistryKey = NULL; 37 | } 38 | -------------------------------------------------------------------------------- /Shared/Aboutdlg.h: -------------------------------------------------------------------------------- 1 | //--------------------------------------------------------------------------- 2 | // (c) 2002-2009 12noon, Stefan K. S. Tucker 3 | // (c) 1994-2001 Perpetual Motion Software, Stefan K. S. Tucker 4 | //--------------------------------------------------------------------------- 5 | 6 | #pragma once 7 | 8 | #include "PMSlib.h" 9 | #include "PMSRes.h" 10 | #include "StatLink.h" 11 | 12 | class CAboutDlg : public CDialog 13 | { 14 | protected: 15 | LPCTSTR m_sIcon; // name (OR "makeint") of icon to use in dlg box 16 | CImageList m_ilLogo; 17 | CString m_cExtraString; // extra string to display (e.g., registration) 18 | HINSTANCE m_hAppInst; 19 | CStaticHyperlink m_web; 20 | CStaticHyperlink m_mailto; 21 | 22 | public: 23 | CAboutDlg(HINSTANCE hAppInst, CWnd *pParent, LPCTSTR lpIconName, 24 | const CString& cReg, BOOL bRegString); 25 | 26 | // Dialog Data 27 | //{{AFX_DATA(CAboutDlg) 28 | enum { IDD = IDD_PMS_ABOUT }; 29 | // NOTE: the ClassWizard will add data members here 30 | //}}AFX_DATA 31 | 32 | protected: 33 | virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support 34 | 35 | // Generated message map functions 36 | //{{AFX_MSG(CAboutDlg) 37 | virtual BOOL OnInitDialog(); 38 | afx_msg void OnPaint(); 39 | //}}AFX_MSG 40 | DECLARE_MESSAGE_MAP() 41 | }; 42 | 43 | -------------------------------------------------------------------------------- /COMToys/src/InputObj.cpp: -------------------------------------------------------------------------------- 1 | //////////////////////////////////////////////////////////////// 2 | // ComToys(TM) Copyright 1999 Paul DiLascia 3 | // If this code works, it was written by Paul DiLascia. 4 | // If not, I don't know who wrote it. 5 | // 6 | #include "StdAfx.h" 7 | #include "COMtoys/ComToys.h" 8 | 9 | #ifdef _DEBUG 10 | #define new DEBUG_NEW 11 | #undef THIS_FILE 12 | static char THIS_FILE[] = __FILE__; 13 | #endif 14 | 15 | DEBUG_BEGIN_INTERFACE_NAMES() 16 | DEBUG_INTERFACE_NAME(IInputObject) 17 | DEBUG_END_INTERFACE_NAMES() 18 | 19 | STDMETHODIMP CTInputObject::UIActivateIO(BOOL fActivate, LPMSG pMsg) 20 | { 21 | if (fActivate && m_hWndInputObj) 22 | ::SetFocus(m_hWndInputObj); 23 | return S_OK; 24 | } 25 | 26 | STDMETHODIMP CTInputObject::HasFocusIO() 27 | { 28 | HWND hwndFocus = ::GetFocus(); 29 | HWND hwndMe = m_hWndInputObj; 30 | return (hwndFocus==hwndMe || ::IsChild(hwndMe, hwndFocus)) ? S_OK : S_FALSE; 31 | } 32 | 33 | STDMETHODIMP CTInputObject::TranslateAcceleratorIO(LPMSG pMsg) 34 | { 35 | if (WM_KEYFIRST<=pMsg->message && pMsg->message<=WM_KEYLAST) { 36 | // You can override GetDefaultAccelerator to provide dynamic accels 37 | HACCEL hAccel = m_hAccel; 38 | if (hAccel) { 39 | HWND hwndMe = m_hWndInputObj; 40 | if (hwndMe && ::TranslateAccelerator(hwndMe, hAccel, pMsg)) 41 | return S_OK; 42 | } 43 | } 44 | return S_FALSE; 45 | } 46 | -------------------------------------------------------------------------------- /COMToys/src/PersistStrm.cpp: -------------------------------------------------------------------------------- 1 | //////////////////////////////////////////////////////////////// 2 | // ComToys(TM) Copyright 1999 Paul DiLascia 3 | // If this code works, it was written by Paul DiLascia. 4 | // If not, I don't know who wrote it. 5 | // 6 | #include "StdAfx.h" 7 | #include "COMtoys/ComToys.h" 8 | 9 | #ifdef _DEBUG 10 | #define new DEBUG_NEW 11 | #undef THIS_FILE 12 | static char THIS_FILE[] = __FILE__; 13 | #endif 14 | 15 | CTPersistStream::CTPersistStream(BOOL& bModified) : m_bModified(bModified) 16 | { 17 | } 18 | 19 | CTPersistStream::~CTPersistStream() 20 | { 21 | } 22 | 23 | STDMETHODIMP CTPersistStream::IsDirty() 24 | { 25 | return m_bModified ? S_OK : S_FALSE; 26 | } 27 | 28 | STDMETHODIMP CTPersistStream::Load(LPSTREAM) 29 | { 30 | return S_OK; // not implemented yet 31 | } 32 | 33 | STDMETHODIMP CTPersistStream::Save(LPSTREAM lpStream, BOOL bClearDirty) 34 | { 35 | if (bClearDirty) 36 | m_bModified = FALSE; 37 | return S_OK; // not implemented yet 38 | } 39 | 40 | STDMETHODIMP CTPersistStream::GetSizeMax(ULARGE_INTEGER* pcbSize) 41 | { 42 | if (pcbSize) 43 | pcbSize->LowPart = pcbSize->HighPart = 0; 44 | return S_OK; 45 | } 46 | 47 | //////////////// IPersistStreamInit //////////////// 48 | 49 | CTPersistStreamInit::CTPersistStreamInit(BOOL& bModified) : 50 | CTPersistStream(bModified) 51 | { 52 | } 53 | 54 | CTPersistStreamInit::~CTPersistStreamInit() 55 | { 56 | } 57 | 58 | STDMETHODIMP CTPersistStreamInit::InitNew() 59 | { 60 | return S_OK; 61 | } 62 | 63 | -------------------------------------------------------------------------------- /COMToys/COMtoysLink.h: -------------------------------------------------------------------------------- 1 | #if defined(_WIN64) 2 | #if defined(_AFXDLL) 3 | #error __FILE__ ": We don't support MFC Shared library" 4 | #else 5 | #if defined(_UNICODE) 6 | #if defined(_DEBUG) 7 | #pragma message("Using COMtoys library Unicode 64-bit Debug...") 8 | #pragma comment(lib, "ctoysx64UD.lib") 9 | #else 10 | #pragma message("Using COMtoys library Unicode 64-bit Release...") 11 | #pragma comment(lib, "ctoysx64U.lib") 12 | #endif 13 | #else 14 | #if defined(_DEBUG) 15 | #pragma message("Using COMtoys library 64-bit Debug...") 16 | #pragma comment(lib, "ctoysx64D.lib") 17 | #else 18 | #pragma message("Using COMtoys library 64-bit Release...") 19 | #pragma comment(lib, "ctoysx64.lib") 20 | #endif 21 | #endif 22 | #endif 23 | #else 24 | #if defined(_AFXDLL) 25 | #error __FILE__ ": We don't support MFC Shared library" 26 | #else 27 | #if defined(_UNICODE) 28 | #if defined(_DEBUG) 29 | #pragma message("Using COMtoys library Unicode 32-bit Debug...") 30 | #pragma comment(lib, "ctoysUD.lib") 31 | #else 32 | #pragma message("Using COMtoys library Unicode 32-bit Release...") 33 | #pragma comment(lib, "ctoysU.lib") 34 | #endif 35 | #else 36 | #if defined(_DEBUG) 37 | #pragma message("Using COMtoys library 32-bit Debug...") 38 | #pragma comment(lib, "ctoysD.lib") 39 | #else 40 | #pragma message("Using COMtoys library 32-bit Release...") 41 | #pragma comment(lib, "ctoys.lib") 42 | #endif 43 | #endif 44 | #endif 45 | #endif 46 | -------------------------------------------------------------------------------- /COMToys/src/ComObj.cpp: -------------------------------------------------------------------------------- 1 | //////////////////////////////////////////////////////////////// 2 | // ComToys(TM) Copyright 1999 Paul DiLascia 3 | // If this code works, it was written by Paul DiLascia. 4 | // If not, I don't know who wrote it. 5 | // 6 | #include "StdAfx.h" 7 | #include "COMtoys/ComToys.h" 8 | 9 | #ifdef _DEBUG 10 | #define new DEBUG_NEW 11 | #undef THIS_FILE 12 | static char THIS_FILE[] = __FILE__; 13 | #endif 14 | 15 | //////////////// 16 | // CTComObj is a do-nothing base class for now. 17 | // 18 | CTComObj::CTComObj() 19 | { 20 | m_dwRef=1; 21 | } 22 | 23 | CTComObj::~CTComObj() 24 | { 25 | } 26 | 27 | void CTComObj::OnFinalRelease() 28 | { 29 | } 30 | 31 | STDMETHODIMP_ (ULONG) CTComObj::AddRef() 32 | { 33 | CTTRACEFN(_T("CTComObj::AddRef, returning %d\n"),m_dwRef+1); 34 | return ++m_dwRef; 35 | } 36 | 37 | STDMETHODIMP_ (ULONG) CTComObj::Release() 38 | { 39 | CTTRACEFN(_T("CTComObj::Release, returning %d\n"),m_dwRef-1); 40 | ASSERT(m_dwRef>0); 41 | m_dwRef--; 42 | if (m_dwRef==0) 43 | OnFinalRelease(); 44 | return m_dwRef; 45 | } 46 | 47 | STDMETHODIMP CTComObj::QueryInterface(REFIID iid, LPVOID* ppv) 48 | { 49 | CTTRACEFN(_T("CTComObj::QueryInterface(%s)\n"),DbgName(iid)); 50 | *ppv = GetInterface(iid); 51 | HRESULT hr = *ppv ? (AddRef(), S_OK) : E_NOINTERFACE; 52 | CTTRACE(_T(">CTComObj::QueryInterface returns %s, *ppv=%p, count=%d\n"), 53 | DbgName(hr), *ppv, m_dwRef); 54 | return hr; 55 | } 56 | 57 | LPUNKNOWN CTComObj::GetInterface(REFIID iid) 58 | { 59 | if (iid==IID_IUnknown) 60 | return (IUnknown*)this; 61 | return NULL; 62 | } 63 | -------------------------------------------------------------------------------- /COMToys/DllEntry.cpp: -------------------------------------------------------------------------------- 1 | //////////////////////////////////////////////////////////////// 2 | // ComToys(TM) Copyright 1999 Paul DiLascia 3 | // If this code works, it was written by Paul DiLascia. 4 | // If not, I don't know who wrote it. 5 | // 6 | 7 | ///////////////////////////////////////////////////////////////////////////// 8 | // Special entry points required for inproc servers. Implementation passes 9 | // control to equivalent DLL object methods, so you can override behavior. 10 | // You should include this file in your main module .cpp file (the one that 11 | // implements your CWinApp-derived class.) 12 | 13 | extern "C" 14 | { 15 | 16 | _Check_return_ 17 | STDAPI DllGetClassObject(_In_ REFCLSID rclsid, _In_ REFIID riid, _Outptr_ LPVOID FAR* ppv) 18 | { 19 | MFCENTRY; 20 | CTCHECKARG(ppv); 21 | CTTRACEFN(_T("DllGetClassObject(%s, %s)\n"),_TR(rclsid),_TR(riid)); 22 | SCODE sc = CTModule::GetModule()->OnGetClassObject(rclsid, riid, ppv); 23 | CTTRACE(_T(" DllGetClassObject returns %s\n"), _TR(sc)); 24 | return sc; 25 | } 26 | 27 | __control_entrypoint(DllExport) 28 | STDAPI DllCanUnloadNow() 29 | { 30 | MFCENTRYTR("DllCanUnloadNow\n"); 31 | HRESULT hr = CTModule::GetModule()->OnCanUnloadNow(); 32 | CTTRACE(">DllCanUnloadNow returns %s\n",_TR(hr)); 33 | return hr; 34 | } 35 | 36 | STDAPI DllRegisterServer() 37 | { 38 | MFCENTRYTR("DllRegisterServer\n"); 39 | return CTModule::GetModule()->OnRegisterServer(TRUE); 40 | } 41 | 42 | STDAPI DllUnregisterServer() 43 | { 44 | MFCENTRYTR("DllUnregisterServer\n"); 45 | return CTModule::GetModule()->OnRegisterServer(FALSE); 46 | } 47 | 48 | STDAPI DllInstall(BOOL bInstall, _In_opt_ LPCWSTR pszCmdLine) 49 | { 50 | MFCENTRYTR("DllInstall\n"); 51 | return CTModule::GetModule()->OnInstall(bInstall, pszCmdLine); 52 | } 53 | 54 | } 55 | -------------------------------------------------------------------------------- /Shared/StaticColor.h: -------------------------------------------------------------------------------- 1 | //--------------------------------------------------------------------------- 2 | // (c) 2006 Stefan K. S. Tucker, 12noon 3 | //--------------------------------------------------------------------------- 4 | 5 | #pragma once 6 | 7 | namespace MyMFC 8 | { 9 | 10 | /* 11 | N.B. If two StaticColor controls overlap, 12 | the lower one (in the Z-order) receives all mouse events. 13 | Not sure why. See "Static Controls." It even receives 14 | WM_NCHITTEST so we can't change it--apparently. 15 | */ 16 | 17 | class StaticColor : public CStatic 18 | { 19 | public: 20 | enum class EColor 21 | { 22 | COLOR_DEFAULT, // the color is the corresponding Windows system color 23 | COLOR_SET, // the color is specified 24 | COLOR_TRANSPARENT, // the "color" is transparent 25 | }; 26 | 27 | protected: 28 | bool _bTextColorSet; 29 | COLORREF _rgbText; 30 | 31 | EColor _eBgColor; 32 | CBrush _brushBG; 33 | 34 | public: 35 | StaticColor() 36 | { 37 | _bTextColorSet = false; 38 | _rgbText = 0x0000'0000; 39 | _eBgColor = EColor::COLOR_DEFAULT; 40 | } 41 | virtual ~StaticColor() {} 42 | 43 | void SetWindowText(LPCTSTR sz); 44 | void SetFont(CFont *pFont, BOOL bRedraw = TRUE); 45 | 46 | static COLORREF GetTextColorDefault(); 47 | void SetTextColorDefault(); 48 | void SetTextColor(const BYTE r, const BYTE g, const BYTE b) { SetTextColor(RGB(r,g,b)); } 49 | void SetTextColor(const COLORREF rgb); 50 | 51 | void SetBgColorDefault(); 52 | void SetBgColorTransparent(); 53 | void SetBgColor(const BYTE r, const BYTE g, const BYTE b) { SetBgColor(RGB(r,g,b)); } 54 | void SetBgColor(const int ixSysColor); 55 | void SetBgColor(const COLORREF rgb); 56 | 57 | protected: 58 | void DrawParentBackground(); 59 | 60 | afx_msg HBRUSH CtlColor(CDC* pDC, UINT nCtlColor); 61 | 62 | DECLARE_MESSAGE_MAP() 63 | }; 64 | 65 | } 66 | -------------------------------------------------------------------------------- /Shared/VersionInfo.h: -------------------------------------------------------------------------------- 1 | //--------------------------------------------------------------------------- 2 | // (c) 2003-2014 12noon, Stefan K. S. Tucker 3 | // (c) 1994-2002 Perpetual Motion Software, Stefan K. S. Tucker 4 | //--------------------------------------------------------------------------- 5 | 6 | #pragma once 7 | 8 | #include "skstutil.h" 9 | 10 | namespace skst 11 | { 12 | 13 | class VersionInfo 14 | { 15 | protected: 16 | BYTE *_pVerInfo; // ptr to ver info (allocated) 17 | // NULL if no ver info block (or error) 18 | struct TLangCharSet 19 | { 20 | WORD wLang, wCharSet; 21 | } *_ptLangInfo; // ptr to language info block 22 | 23 | VS_FIXEDFILEINFO *_pFileInfo; // file's version info 24 | 25 | public: 26 | VersionInfo(const HINSTANCE hInst); 27 | virtual ~VersionInfo(); 28 | 29 | void GetFileVersion(DWORD& dwMS, DWORD& dwLS) const 30 | { 31 | dwMS = _pFileInfo->dwFileVersionMS; 32 | dwLS = _pFileInfo->dwFileVersionLS; 33 | } 34 | 35 | std::wstring GetProductName() const { return GetInfo(_T("ProductName")); } 36 | std::wstring GetProductVersion() const { return GetInfo(_T("ProductVersion")); } 37 | std::wstring GetFileVersion() const { return GetInfo(_T("FileVersion")); } 38 | std::wstring GetCompanyName() const { return GetInfo(_T("CompanyName")); } 39 | std::wstring GetCopyright() const { return GetInfo(_T("LegalCopyright")); } 40 | 41 | std::wstring GetInfo(LPCTSTR szKey) const 42 | { 43 | LPCTSTR szValue; 44 | GetInfo(szKey, &szValue); 45 | return (szValue == nullptr) ? std::wstring() : szValue; 46 | } 47 | 48 | //----------------------------------------------------------------- 49 | // The second parameter is simply the address of a string; because 50 | // the function merely sets the ptr to point into the version 51 | // info block, there is no need to allocate storage for a string. 52 | //----------------------------------------------------------------- 53 | void GetInfo(LPCTSTR szKey, LPCTSTR *pszValue) const; 54 | }; 55 | 56 | } 57 | -------------------------------------------------------------------------------- /Shared/StatLink.h: -------------------------------------------------------------------------------- 1 | //--------------------------------------------------------------------------- 2 | // Copyright (c) 1997-2001, All Rights Reserved 3 | // Perpetual Motion Software, Stefan K. S. Tucker. 4 | //--------------------------------------------------------------------------- 5 | 6 | //------------------------------------------------------------------------- 7 | // This is modified from Microsoft Systems Journal, December 1997 v12 n12, 8 | // Q&A C++, by Paul DiLascia, pp. 104-108. 9 | //------------------------------------------------------------------------- 10 | // The article also added features such as a member string to set as the 11 | // link -- if the static control's text itself wasn't the URL. 12 | // It allows icons to be links. 13 | // It saved a bool as a 'visited' flag, and changed the text color 14 | // accordingly. 15 | //----------------------------------------------------------------------- 16 | 17 | #pragma once 18 | 19 | ///////////////////////////////////////////////////////////////////////////// 20 | // CStaticHyperlink window 21 | 22 | class CStaticHyperlink : public CStatic 23 | { 24 | protected: 25 | HCURSOR _hCursor; 26 | CString _strURL; // optional: if empty, uses text 27 | int _idError1; 28 | 29 | public: 30 | CStaticHyperlink(const int idCursor = 0); 31 | virtual ~CStaticHyperlink() {} 32 | 33 | void SetURL(const int id) { _strURL.LoadString(id); } 34 | void SetErrorID(const int id) { _idError1 = id; } 35 | 36 | public: 37 | // Overrides 38 | // ClassWizard generated virtual function overrides 39 | //{{AFX_VIRTUAL(CStaticHyperlink) 40 | //}}AFX_VIRTUAL 41 | 42 | protected: 43 | // Generated message map functions 44 | //{{AFX_MSG(CStaticHyperlink) 45 | afx_msg HBRUSH CtlColor(CDC* pDC, UINT nCtlColor); 46 | afx_msg void OnClicked(); 47 | afx_msg BOOL OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message); 48 | //}}AFX_MSG 49 | 50 | DECLARE_MESSAGE_MAP() 51 | }; 52 | 53 | ///////////////////////////////////////////////////////////////////////////// 54 | 55 | //{{AFX_INSERT_LOCATION}} 56 | // Microsoft Developer Studio will insert additional declarations immediately before the previous line. 57 | 58 | -------------------------------------------------------------------------------- /Shared/Graphics_MyWin.cpp: -------------------------------------------------------------------------------- 1 | //--------------------------------------------------------------------------- 2 | // (c) 2006 12noon, Stefan K. S. Tucker 3 | //--------------------------------------------------------------------------- 4 | 5 | #include "stdafx.h" 6 | 7 | #include "Graphics_MyWin.h" 8 | 9 | //-------------------------------------------------------------------------------------------- 10 | 11 | 12 | /* 13 | Ensure the passed rectangle is completely on-screen. 14 | The rectangle's dimensions aren't changed. 15 | */ 16 | void MyWin::MoveRectangleInsideScreen(RECT& r) 17 | { 18 | RECT rBig; 19 | rBig.left = 0; 20 | rBig.right = ::GetSystemMetrics(SM_CXSCREEN); 21 | rBig.top = 0; 22 | rBig.bottom = ::GetSystemMetrics(SM_CYSCREEN); 23 | MyWin::MoveRectangleInsideRectangle(rBig, r); 24 | } 25 | 26 | /* 27 | Ensure the passed rectangle is completely inside the workarea (not the taskbar). 28 | The rectangle's dimensions aren't changed. 29 | */ 30 | void MyWin::MoveRectangleInsideWorkarea(RECT& r) 31 | { 32 | RECT rcWorkArea; 33 | ::SystemParametersInfo(SPI_GETWORKAREA, 0, &rcWorkArea, 0); 34 | MyWin::MoveRectangleInsideRectangle(rcWorkArea, r); 35 | } 36 | 37 | /* 38 | Ensure the passed rectangle is completely inside another rectangle. 39 | The rectangle's dimensions aren't changed. 40 | */ 41 | void MyWin::MoveRectangleInsideRectangle(const RECT& rBig, RECT& rSmall) 42 | { 43 | if (::IsRectEmpty(&rSmall)) 44 | return; 45 | 46 | // ensure width of rect is fully on-screen 47 | const int w = rSmall.right - rSmall.left; 48 | const int cxBig = rBig.right - rBig.left; 49 | if (rSmall.left + w >= cxBig) 50 | ::OffsetRect(&rSmall, (cxBig - w) - rSmall.left, 0); 51 | 52 | // ensure height of rect is fully on-screen 53 | const int h = rSmall.bottom - rSmall.top; 54 | const int cyBig = rBig.bottom - rBig.top; 55 | if (rSmall.top + h >= cyBig) 56 | ::OffsetRect(&rSmall, 0, (cyBig - h) - rSmall.top); 57 | 58 | // more important that the upper-left corner be in the rect, so we do this last 59 | if (rSmall.left < 0) 60 | ::OffsetRect(&rSmall, -rSmall.left, 0); 61 | if (rSmall.top < 0) 62 | ::OffsetRect(&rSmall, 0, -rSmall.top); 63 | } 64 | -------------------------------------------------------------------------------- /COMToys/src/PersistFile.cpp: -------------------------------------------------------------------------------- 1 | //////////////////////////////////////////////////////////////// 2 | // ComToys(TM) Copyright 1999 Paul DiLascia 3 | // If this code works, it was written by Paul DiLascia. 4 | // If not, I don't know who wrote it. 5 | // 6 | #include "StdAfx.h" 7 | #include "COMtoys/ComToys.h" 8 | 9 | #ifdef _DEBUG 10 | #define new DEBUG_NEW 11 | #undef THIS_FILE 12 | static char THIS_FILE[] = __FILE__; 13 | #endif 14 | 15 | CTPersistFile::CTPersistFile(BOOL& bModified) 16 | : m_bModified(bModified) 17 | { 18 | } 19 | 20 | CTPersistFile::~CTPersistFile() 21 | { 22 | } 23 | 24 | STDMETHODIMP CTPersistFile::IsDirty() 25 | { 26 | CTTRACEFN(_T("CTPersistFile::IsDirty\n")); 27 | return m_bModified ? S_OK : S_FALSE; 28 | } 29 | 30 | STDMETHODIMP CTPersistFile::Load(LPCOLESTR pszFileName, DWORD dwMode) 31 | { 32 | CTTRACEFN(_T("CTPersistFile::Load\n")); 33 | return E_NOTIMPL; // not implemented yet--you must override 34 | } 35 | 36 | STDMETHODIMP CTPersistFile::Save(LPCOLESTR pszFileName, BOOL fRemember) 37 | { 38 | CTTRACEFN(_T("CTPersistFile::Save\n")); 39 | return E_NOTIMPL; // not implemented yet--you must overrride 40 | } 41 | 42 | STDMETHODIMP CTPersistFile::SaveCompleted(LPCOLESTR pszFileName) 43 | { 44 | CTTRACEFN(_T("CTPersistFile::SaveCompleted\n")); 45 | return S_OK; 46 | } 47 | 48 | ////////////////// 49 | // Get filename -- calls v fn to get LPCTSTR, then copy to new OLESTR 50 | // 51 | STDMETHODIMP CTPersistFile::GetCurFile(LPOLESTR __RPC_FAR *ppFileName) 52 | { 53 | CTTRACEFN(_T("CTPersistFile::GetCurFile\n")); 54 | 55 | if (!ppFileName) 56 | return E_UNEXPECTED; 57 | 58 | *ppFileName = NULL; 59 | 60 | // get path name 61 | CString s = OnGetPathName(); 62 | if (s.IsEmpty()) 63 | return E_FAIL; 64 | 65 | // allocate a new string 66 | LPVOID pMem = NULL; 67 | int len = (s.GetLength() + 1)*sizeof(OLECHAR); 68 | HRESULT hr = CTOleAlloc(len, &pMem); 69 | if (FAILED(hr)) 70 | return hr; 71 | 72 | // Convert to wide char and copy to caller's buffer 73 | USES_CONVERSION; 74 | *ppFileName=(LPOLESTR)pMem; 75 | wcscpy_s(*ppFileName, len, T2COLE((PCTSTR)s)); 76 | 77 | return NOERROR; 78 | } 79 | 80 | LPCTSTR CTPersistFile::OnGetPathName() 81 | { 82 | return NULL; // not implemented yet 83 | } -------------------------------------------------------------------------------- /Shared/Helper.cpp: -------------------------------------------------------------------------------- 1 | //--------------------------------------------------------------------------- 2 | // (c) 2002-2010 12noon, Stefan K. S. Tucker 3 | // (c) 1991-2002 Perpetual Motion Software, Stefan K. S. Tucker 4 | //--------------------------------------------------------------------------- 5 | 6 | #include "stdafx.h" 7 | 8 | #include "pmslib.h" 9 | 10 | 11 | /* 12 | This function opens a passed URL in the appropriate application. 13 | */ 14 | bool 15 | PMS::OpenURL(LPCTSTR szURL) 16 | { 17 | //skst::MyLog::GetLog().LogV(_T(__FUNCTION__) _T("(%s)"), szURL); 18 | const HINSTANCE h = ::ShellExecute(nullptr, _T("open"), 19 | szURL, nullptr /*args*/, nullptr /*dir*/, 20 | SW_SHOWNORMAL); 21 | return (h >= HINSTANCE(HINSTANCE_ERROR)); 22 | } 23 | 24 | 25 | //--------------------------------------------------------------------------- 26 | /* 27 | This routine exchanges dialog data for a spin button. 28 | */ 29 | //--------------------------------------------------------------------------- 30 | 31 | void PMS::DDX_SpinButton(CDataExchange *pDX, int nIDC, int& value) 32 | { 33 | HWND hWndCtrl = pDX->PrepareCtrl(nIDC); 34 | if (pDX->m_bSaveAndValidate) 35 | value = (int) LOWORD(::SendMessage(hWndCtrl, UDM_GETPOS, 0, 0l)); 36 | else 37 | ::SendMessage(hWndCtrl, UDM_SETPOS, 0, MAKELPARAM((short) value, 0)); 38 | } 39 | 40 | void PMS::DDX_Check(CDataExchange* pDX, int nIDC, bool& value) 41 | { 42 | pDX->PrepareCtrl(nIDC); 43 | HWND hWndCtrl; 44 | pDX->m_pDlgWnd->GetDlgItem(nIDC, &hWndCtrl); 45 | if (pDX->m_bSaveAndValidate) 46 | { 47 | const int n = (int)::SendMessage(hWndCtrl, BM_GETCHECK, 0, 0L); 48 | if (n == BST_UNCHECKED) 49 | value = false; 50 | else if (n == BST_CHECKED) 51 | value = true; 52 | else 53 | ASSERT(FALSE); 54 | } 55 | else 56 | { 57 | if (value == BST_UNCHECKED) 58 | ::SendMessage(hWndCtrl, BM_SETCHECK, 0, 0L); 59 | else if (value == BST_CHECKED) 60 | ::SendMessage(hWndCtrl, BM_SETCHECK, 1, 0L); 61 | else 62 | { 63 | TRACE(traceAppMsg, 0, "Warning: dialog data checkbox value (%d) out of range.\n", value); 64 | value = 0; // default to off 65 | ::SendMessage(hWndCtrl, BM_SETCHECK, 0, 0L); 66 | } 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /COMToys/Subclass.h: -------------------------------------------------------------------------------- 1 | //////////////////////////////////////////////////////////////// 2 | // PixieLib(TM) Copyright 1997-1998 Paul DiLascia 3 | // If this code works, it was written by Paul DiLascia. 4 | // If not, I don't know who wrote it. 5 | // 6 | #ifndef _SUBCLASSW_H 7 | #define _SUBCLASSW_H 8 | 9 | ////////////////// 10 | // Generic class to hook messages on behalf of a CWnd. 11 | // Once hooked, all messages go to CSubclassWnd::WindowProc before going 12 | // to the window. Specific subclasses can trap messages and do something. 13 | // 14 | // To use: 15 | // 16 | // * Derive a class from CSubclassWnd. 17 | // 18 | // * Override CSubclassWnd::WindowProc to handle messages. Make sure you call 19 | // CSubclassWnd::WindowProc if you don't handle the message, or your 20 | // window will never get messages. If you write seperate message handlers, 21 | // you can call Default() to pass the message to the window. 22 | // 23 | // * Instantiate your derived class somewhere and call HookWindow(pWnd) 24 | // to hook your window, AFTER it has been created. 25 | // To unhook, call Unhook or HookWindow(NULL). 26 | // 27 | // This is a very important class, crucial to many of the widgets Window 28 | // widgets implemented in PixieLib. To see how it works, look at the HOOK 29 | // sample program. 30 | // 31 | class CSubclassWnd : public CObject { 32 | public: 33 | CSubclassWnd(); 34 | ~CSubclassWnd(); 35 | 36 | // Subclass a window. Hook(NULL) to unhook (automatic on WM_NCDESTROY) 37 | BOOL HookWindow(HWND hwnd); 38 | BOOL HookWindow(CWnd* pWnd) { return HookWindow(pWnd->GetSafeHwnd()); } 39 | void Unhook() { HookWindow((HWND)NULL); } 40 | BOOL IsHooked() { return m_hWnd!=NULL; } 41 | 42 | friend LRESULT CALLBACK HookWndProc(HWND, UINT, WPARAM, LPARAM); 43 | friend class CSubclassWndMap; 44 | 45 | virtual LRESULT WindowProc(UINT msg, WPARAM wp, LPARAM lp); 46 | LRESULT Default(); // call this at the end of handler fns 47 | 48 | #ifdef _DEBUG 49 | virtual void AssertValid() const; 50 | virtual void Dump(CDumpContext& dc) const; 51 | #endif 52 | 53 | protected: 54 | HWND m_hWnd; // the window hooked 55 | WNDPROC m_pOldWndProc; // ..and original window proc 56 | CSubclassWnd* m_pNext; // next in chain of hooks for this window 57 | 58 | DECLARE_DYNAMIC(CSubclassWnd); 59 | }; 60 | 61 | #endif // _SUBCLASSW_H 62 | 63 | -------------------------------------------------------------------------------- /Calendar.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | 4 | class CalendarWindow : public CMonthCalCtrl 5 | { 6 | DECLARE_DYNAMIC(CalendarWindow) 7 | 8 | protected: 9 | bool _bShowToday; 10 | bool _bShowWeekNums; 11 | 12 | bool _bSavePosition; 13 | int _xPos; 14 | int _yPos; 15 | 16 | bool _bSaveSize; 17 | int _nNumMonthsX; 18 | int _nNumMonthsY; 19 | 20 | LOGFONT _lfFont; 21 | CFont _font; 22 | /* 23 | WM_SETFONT 24 | The application should call the DeleteObject function to delete the font 25 | when it is no longer needed; for example, after it destroys the control. 26 | */ 27 | 28 | CSize _sizeMinClient; // the minimum size of the client area of a 1x1 calendar 29 | 30 | public: 31 | CalendarWindow(); 32 | virtual ~CalendarWindow() {} 33 | 34 | bool Create(); 35 | bool Create(const int xPos, const int yPos, const int nNumMonthsX, const int nNumMonthsY, const bool bShowToday, const bool bShowWeekNums); 36 | 37 | bool SavePosition() const { return _bSavePosition; } 38 | inline void SavePositionEnable() { _SavePosition(true); } 39 | inline void SavePositionDisable() { _SavePosition(false); } 40 | 41 | bool SaveSize() const { return _bSaveSize; } 42 | inline void SaveSizeEnable() { _SaveSize(true); } 43 | inline void SaveSizeDisable() { _SaveSize(false); } 44 | 45 | bool ShowToday() const { return _bShowToday; } 46 | inline void TodayShow() { _TodayShow(true); } 47 | inline void TodayHide() { _TodayShow(false); } 48 | 49 | bool ShowWeekNumbers() const { return _bShowWeekNums; } 50 | inline void WeekNumbersShow() { _WeekNumbersShow(true); } 51 | inline void WeekNumbersHide() { _WeekNumbersShow(false); } 52 | 53 | void ChooseFont(); 54 | 55 | protected: 56 | void _TodayShow(const bool b); 57 | void _WeekNumbersShow(const bool b); 58 | void _SavePosition(const bool b); 59 | void _SaveSize(const bool b); 60 | 61 | CSize GetRequiredDimensions(const int nNumMonthsX, const int nNumMonthsY); 62 | void Resize(); 63 | void CalculateMinimumClientArea(); 64 | 65 | DECLARE_MESSAGE_MAP() 66 | 67 | afx_msg void OnDestroy(); 68 | afx_msg void OnGetMinMaxInfo(MINMAXINFO* lpMMI); 69 | afx_msg void OnSizing(UINT fwSide, LPRECT pRect); 70 | afx_msg void OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags); 71 | afx_msg void OnWindowPosChanged(WINDOWPOS* lpwndpos); 72 | }; 73 | -------------------------------------------------------------------------------- /COMToys/src/Module.cpp: -------------------------------------------------------------------------------- 1 | //////////////////////////////////////////////////////////////// 2 | // ComToys(TM) Copyright 1999 Paul DiLascia 3 | // If this code works, it was written by Paul DiLascia. 4 | // If not, I don't know who wrote it. 5 | // 6 | #include "StdAfx.h" 7 | #include "COMtoys/ComToys.h" 8 | 9 | #ifdef _DEBUG 10 | #define new DEBUG_NEW 11 | #undef THIS_FILE 12 | static char THIS_FILE[] = __FILE__; 13 | #endif 14 | 15 | CTModule* CTModule::g_pModule = NULL; 16 | 17 | CTModule::CTModule() 18 | { 19 | ASSERT(g_pModule==NULL); // only one allowed! 20 | g_pModule = this; 21 | m_dwLock = 0; 22 | } 23 | 24 | CTModule::~CTModule() 25 | { 26 | } 27 | 28 | LONG CTModule::Lock() 29 | { 30 | return InterlockedIncrement(&m_dwLock); 31 | } 32 | 33 | LONG CTModule::Unlock() 34 | { 35 | return InterlockedDecrement(&m_dwLock); 36 | } 37 | 38 | ///////////////// 39 | // Currently, InitInstance and ExitInstance are *NOT* automatically 40 | // called in DLL_PROCESS_ATTACH/DETACH, so you have to call them manually-- 41 | // but only if you're not using MFC. CTMfcModule::InitInstance automatically 42 | // calls CTModule::InitInstance. 43 | // 44 | BOOL CTModule::InitInstance(HINSTANCE hInstance) 45 | { 46 | CTTRACEFN(_T(__FUNCTION__) _T("\n")); 47 | m_hInstance = hInstance; 48 | return TRUE; 49 | } 50 | 51 | int CTModule::ExitInstance() 52 | { 53 | CTFactory::DeleteAll(); // delete all factories 54 | return 0; 55 | } 56 | 57 | ///////////////////////////////////////////////////////////////////////////// 58 | // Default implementation for special CTModule entry points 59 | // For now, CTModule isn't implemented. This class exists only to have 60 | // a non-MFC module class some day, and provide a base class for CTMfcModule. 61 | // 62 | HRESULT CTModule::OnGetClassObject(REFCLSID clsid, REFIID iid, LPVOID* ppv) 63 | { 64 | CTTRACEFN(_T("CTModule::OnGetClassObject\n")); 65 | return CLASS_E_CLASSNOTAVAILABLE; // for now 66 | } 67 | 68 | HRESULT CTModule::OnCanUnloadNow(void) 69 | { 70 | CTTRACEFN(_T("CTModule::OnCanUnloadNow\n")); 71 | return S_OK; 72 | } 73 | 74 | HRESULT CTModule::OnRegisterServer(BOOL bRegister) 75 | { 76 | CTTRACEFN(_T("CTModule::OnRegisterServer\n")); 77 | return CTFactory::OnRegisterAll(bRegister) ? S_OK : SELFREG_E_CLASS; 78 | } 79 | 80 | HRESULT CTModule::OnInstall(BOOL bInstall, LPCWSTR pszCmdLine) 81 | { 82 | CTTRACEFN(_T("CTModule::OnInstall\n")); 83 | return S_OK; 84 | } 85 | -------------------------------------------------------------------------------- /Timekeeper.sln: -------------------------------------------------------------------------------- 1 | Microsoft Visual Studio Solution File, Format Version 12.00 2 | # Visual Studio Version 17 3 | VisualStudioVersion = 17.12.35707.178 4 | MinimumVisualStudioVersion = 10.0.40219.1 5 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Timekeeper", "Timekeeper.vcxproj", "{17FFC676-A235-42AA-A838-0566BEABE3A6}" 6 | EndProject 7 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ComToys", "COMToys\ComToys.vcxproj", "{C37DF566-A97F-4E69-9EDC-6BF670251441}" 8 | EndProject 9 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{20A6195C-056F-4707-9A1E-2413DDA060D8}" 10 | ProjectSection(SolutionItems) = preProject 11 | installer\build_installer.cmd = installer\build_installer.cmd 12 | help\Documentation.md = help\Documentation.md 13 | LICENSE = LICENSE 14 | README.md = README.md 15 | help\Overview.md = help\Overview.md 16 | installer\Timekeeper.nsi = installer\Timekeeper.nsi 17 | EndProjectSection 18 | EndProject 19 | Global 20 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 21 | Debug|Win32 = Debug|Win32 22 | Debug|x64 = Debug|x64 23 | Release|Win32 = Release|Win32 24 | Release|x64 = Release|x64 25 | EndGlobalSection 26 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 27 | {17FFC676-A235-42AA-A838-0566BEABE3A6}.Debug|Win32.ActiveCfg = Debug|Win32 28 | {17FFC676-A235-42AA-A838-0566BEABE3A6}.Debug|Win32.Build.0 = Debug|Win32 29 | {17FFC676-A235-42AA-A838-0566BEABE3A6}.Debug|x64.ActiveCfg = Debug|x64 30 | {17FFC676-A235-42AA-A838-0566BEABE3A6}.Debug|x64.Build.0 = Debug|x64 31 | {17FFC676-A235-42AA-A838-0566BEABE3A6}.Release|Win32.ActiveCfg = Release|Win32 32 | {17FFC676-A235-42AA-A838-0566BEABE3A6}.Release|Win32.Build.0 = Release|Win32 33 | {17FFC676-A235-42AA-A838-0566BEABE3A6}.Release|x64.ActiveCfg = Release|x64 34 | {17FFC676-A235-42AA-A838-0566BEABE3A6}.Release|x64.Build.0 = Release|x64 35 | {C37DF566-A97F-4E69-9EDC-6BF670251441}.Debug|Win32.ActiveCfg = Debug|Win32 36 | {C37DF566-A97F-4E69-9EDC-6BF670251441}.Debug|Win32.Build.0 = Debug|Win32 37 | {C37DF566-A97F-4E69-9EDC-6BF670251441}.Debug|x64.ActiveCfg = Debug|x64 38 | {C37DF566-A97F-4E69-9EDC-6BF670251441}.Debug|x64.Build.0 = Debug|x64 39 | {C37DF566-A97F-4E69-9EDC-6BF670251441}.Release|Win32.ActiveCfg = Release|Win32 40 | {C37DF566-A97F-4E69-9EDC-6BF670251441}.Release|Win32.Build.0 = Release|Win32 41 | {C37DF566-A97F-4E69-9EDC-6BF670251441}.Release|x64.ActiveCfg = Release|x64 42 | {C37DF566-A97F-4E69-9EDC-6BF670251441}.Release|x64.Build.0 = Release|x64 43 | EndGlobalSection 44 | GlobalSection(SolutionProperties) = preSolution 45 | HideSolutionNode = FALSE 46 | EndGlobalSection 47 | GlobalSection(ExtensibilityGlobals) = postSolution 48 | SolutionGuid = {43B9990D-B186-4EA8-AA16-197F11FF259A} 49 | EndGlobalSection 50 | EndGlobal 51 | -------------------------------------------------------------------------------- /COMToys/src/MfcModule.cpp: -------------------------------------------------------------------------------- 1 | //////////////////////////////////////////////////////////////// 2 | // ComToys(TM) Copyright 1999 Paul DiLascia 3 | // If this code works, it was written by Paul DiLascia. 4 | // If not, I don't know who wrote it. 5 | // 6 | #include "StdAfx.h" 7 | #include "COMtoys/ComToys.h" 8 | 9 | #ifdef _DEBUG 10 | #define new DEBUG_NEW 11 | #undef THIS_FILE 12 | static char THIS_FILE[] = __FILE__; 13 | #endif 14 | 15 | IMPLEMENT_DYNAMIC(CTMfcModule, COleControlModule); 16 | 17 | CTMfcModule::CTMfcModule() 18 | { 19 | } 20 | 21 | CTMfcModule::~CTMfcModule() 22 | { 23 | } 24 | 25 | BOOL CTMfcModule::InitInstance() 26 | { 27 | CTTRACEFN(_T(__FUNCTION__) _T("\n")); 28 | 29 | //skst 30 | /* 31 | CTRegistrar uses IRegistrar--a completely undocumented ATL interface. 32 | What's also undocumented is that it requires atl.dll, which is not 33 | present on Windows 98 with IE 5.0. It is present after we install 34 | IE 6.0. Who knows about IE 5.5? 35 | Thanks, Microsoft. 36 | */ 37 | CTTRACE(_T("\tbefore CTRegistrar ctor\n")); 38 | CTRegistrar r; 39 | CTTRACE(_T("\tafter CTRegistrar ctor\n")); 40 | if (!r) 41 | { 42 | ::AfxMessageBox(_T("This requires Microsoft Internet Explorer 6.0.")); 43 | return FALSE; 44 | } 45 | //skst 46 | 47 | if (!CTModule::InitInstance(CWinApp::m_hInstance)) 48 | return FALSE; 49 | return COleControlModule::InitInstance(); 50 | } 51 | 52 | int CTMfcModule::ExitInstance() 53 | { 54 | CTTRACEFN(_T("CTMfcModule::ExitInstance\n")); 55 | CTModule::ExitInstance(); 56 | return COleControlModule::ExitInstance(); 57 | } 58 | 59 | ///////////////////////////////////////////////////////////////////////////// 60 | // Implementation special DLL entry points. 61 | // Call MFC to do the work. 62 | 63 | HRESULT CTMfcModule::OnGetClassObject(REFCLSID clsid, REFIID iid, LPVOID* ppv) 64 | { 65 | CTTRACEFN(_T("CTMfcModule::OnGetClassObject\n")); 66 | HRESULT hr = AfxDllGetClassObject(clsid, iid, ppv); 67 | if (*ppv==NULL) { 68 | TRACE(_T("***CTMfcModule::OnGetClassObject failed\n")); 69 | TRACE(_T("***Did you create factories before calling CTMfcModule::InitInstance?\n")); 70 | } 71 | return hr; 72 | } 73 | 74 | HRESULT CTMfcModule::OnCanUnloadNow(void) 75 | { 76 | CTTRACEFN(_T("CTMfcModule::OnCanUnloadNow\n")); 77 | return AfxDllCanUnloadNow(); 78 | } 79 | 80 | HRESULT CTMfcModule::OnRegisterServer(BOOL bRegister) 81 | { 82 | CTTRACEFN(_T("CTMfcModule::OnRegisterServer\n")); 83 | HRESULT hr =CTModule::OnRegisterServer(bRegister); 84 | if (hr!=S_OK) 85 | return hr; 86 | return COleObjectFactory::UpdateRegistryAll(bRegister) 87 | ? S_OK : SELFREG_E_CLASS; 88 | } 89 | 90 | HRESULT CTMfcModule::OnInstall(BOOL bInstall, LPCWSTR pszCmdLine) 91 | { 92 | CTTRACEFN(_T("CTMfcModule::OnInstall\n")); 93 | return CTModule::OnInstall(bInstall, pszCmdLine); 94 | } 95 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Timekeeper by [12noon LLC](https://12noon.com) 2 | 3 | [![MSBuild](https://github.com/skst/Timekeeper/actions/workflows/msbuild.yml/badge.svg)](https://github.com/skst/Timekeeper/actions/workflows/msbuild.yml) 4 | 5 | A desktop tool to display the current date/time on the Windows 6 | task bar in your custom format. 7 | 8 | (Unfortunately, Microsoft has dropped support for desk bands when they rewrote the task bar for Windows 11.) 9 | 10 | ## Additional Documentation 11 | 12 | [Overview](help/Overview.md) 13 | 14 | [Documentation](help/Documentation.md) 15 | 16 | ## .: Features :. 17 | 18 | Click on the clock with the primary mouse button to display a calendar. 19 | Click on the clock with the secondary mouse button to display context menu. 20 | 21 | Can format clock's display, including: 22 | - Font 23 | - Text color 24 | - Background color 25 | - Alignment: left, center, right 26 | - Data displayed: date format, time format, text, etc. 27 | - Line separators for a multi-line display 28 | - Some pre-formatted date/time entries included, to get the user started. 29 | 30 | Timekeeper displays the locale's long date/time in its tooltip. 31 | 32 | ## .: Calendar :. 33 | 34 | Calendar displays current date/time in the caption. 35 | The calendar edges can be dragged to resize the window and display more or fewer months. 36 | You can select a series of dates. 37 | Close the calendar by clicking on the 'x' in the caption or pressing ALT+F4 or ESC. 38 | 39 | ### Keys 40 | Key | Action 41 | :------------- | :----- 42 | Home | First day of current month 43 | End | Last day of current month 44 | CTRL+Home | First day of first month on display 45 | CTRL+End | Last day of last month on display 46 | PageUp | Move back one month 47 | PageDown | Move ahead one month 48 | CTRL+PageUp | Move back one year 49 | CTRL+PageDown | Move ahead one year 50 | ALT+F4 | Close the calendar 51 | ESC | Close the calendar 52 | 53 | ### Calendar options include: 54 | 55 | - Show today 56 | - Show week numbers 57 | - Remember calendar's position 58 | - Remember calendar's size 59 | 60 | ## .: Advanced Features:. 61 | 62 | Timekeeper reloads the display format when it notices that it's changed. 63 | You can use this to display your own dynamic value on the desk band. 64 | 65 | HKCU\12noon\Timekeeper\Clock\ 66 | Format [string] = Display format 67 | 68 | You can set this data value to any text you'd like to have displayed on the 69 | Timekeeper's desk band. Use it to display the weather, a reminder, whatever. 70 | 71 | 72 | ## .: Building Timekeeper :. 73 | 74 | Timekeeper is built with *Visual Studio*. 75 | 76 | ### Installer 77 | 78 | The `build_installer.cmd` script builds the installer using these tools: 79 | 80 | - [NSIS3](https://nsis.sourceforge.io) 81 | - [SysInternals SigCheck](https://docs.microsoft.com/en-us/sysinternals/downloads/sigcheck) 82 | 83 | The build script assumes they are installed in these folders in the project folder: 84 | - `NSIS3\` 85 | - `SysInternals\` 86 | -------------------------------------------------------------------------------- /Shared/ColorChooser.cpp: -------------------------------------------------------------------------------- 1 | #include "stdafx.h" 2 | #include 3 | #include 4 | 5 | #include "ColorChooser.h" 6 | using PMS::ColorChooserDlg; 7 | 8 | IMPLEMENT_DYNAMIC(ColorChooserDlg, CColorDialog) 9 | 10 | skst::Registry::EType ColorChooserDlg::_eRegKeyType = skst::Registry::ETYPE_USER; 11 | tstring ColorChooserDlg::_strPathKey; 12 | 13 | COLORREF ColorChooserDlg::_crMRU = RGB(0,0,0); 14 | COLORREF ColorChooserDlg::_crCustom[] = { RGB(0,0,0), RGB(0,0,0), RGB(0,0,0), RGB(0,0,0), 15 | RGB(0,0,0), RGB(0,0,0), RGB(0,0,0), RGB(0,0,0), 16 | RGB(0,0,0), RGB(0,0,0), RGB(0,0,0), RGB(0,0,0), 17 | RGB(0,0,0), RGB(0,0,0), RGB(0,0,0), RGB(0,0,0), }; 18 | 19 | void ColorChooserDlg::SetRegistryLocation(const skst::Registry::EType eType, LPCTSTR szKey) 20 | { 21 | _eRegKeyType = eType; 22 | _strPathKey = szKey; 23 | } 24 | 25 | 26 | ColorChooserDlg::ColorChooserDlg(CWnd* pParentWnd, const COLORREF& crColor) 27 | : CColorDialog(crColor, CC_RGBINIT | CC_SOLIDCOLOR, pParentWnd) 28 | { 29 | /* 30 | LOAD from Registry 31 | */ 32 | if (!_strPathKey.empty()) 33 | { 34 | // pass default value so we can create the key if it doesn't exist 35 | skst::Registry keyOptions(_eRegKeyType, _strPathKey.c_str(), _T("")); 36 | 37 | // load MRU color from Registry 38 | _crMRU = keyOptions.GetDWORD(_T("MRU"), _crMRU); 39 | 40 | // load 16 custom colors from Registry 41 | for (int i = 0; i < _countof(_crCustom); ++i) 42 | { 43 | #if defined(_UNICODE) 44 | std::wostringstream str; 45 | str << _T("Custom") << std::setw(2) << i << _T('\0'); // strstream doesn't terminate 46 | #else 47 | std::ostringstream str; 48 | str << _T("Custom") << std::setw(2) << std::setfill('0') << i << _T('\0'); // strstream doesn't terminate 49 | #endif 50 | _crCustom[i] = keyOptions.GetDWORD(str.str().c_str(), _crCustom[i]); 51 | } 52 | } 53 | 54 | m_cc.rgbResult = _crMRU; 55 | m_cc.lpCustColors = _crCustom; 56 | } 57 | 58 | BEGIN_MESSAGE_MAP(ColorChooserDlg, CColorDialog) 59 | END_MESSAGE_MAP() 60 | 61 | // ColorChooserDlg message handlers 62 | 63 | BOOL ColorChooserDlg::OnColorOK() 64 | { 65 | _crMRU = GetColor(); 66 | 67 | /* 68 | SAVE to Registry 69 | */ 70 | if (!_strPathKey.empty()) 71 | { 72 | skst::Registry keyOptions(_eRegKeyType, _strPathKey.c_str(), _T("")); 73 | 74 | // save MRU color to Registry 75 | keyOptions.SetDWORD(_T("MRU"), _crMRU); 76 | 77 | // save 16 custom colors to Registry 78 | for (int i = 0; i < (sizeof _crCustom / sizeof _crCustom[0]); ++i) 79 | { 80 | #if defined(_UNICODE) 81 | std::wostringstream str; 82 | str << _T("Custom") << std::setw(2) << i << _T('\0'); // strstream doesn't terminate 83 | keyOptions.SetDWORD(str.str().c_str(), _crCustom[i]); 84 | #else 85 | std::ostrstream str; 86 | str << "Custom" << std::setw(2) << std::setfill('0') << i << '\0'; // strstream doesn't terminate 87 | keyOptions.SetDWORD(str.str(), _crCustom[i]); 88 | #endif 89 | } 90 | } 91 | 92 | return CColorDialog::OnColorOK(); 93 | } 94 | -------------------------------------------------------------------------------- /Shared/PMSRes.h: -------------------------------------------------------------------------------- 1 | //{{NO_DEPENDENCIES}} 2 | // Microsoft Visual C++ generated include file. 3 | // Used by PMSRes.rc 4 | // 5 | #define IDC_FINGER 101 6 | #define IDC_PMS_PRODNAME 102 7 | #define IDC_PMS_VERSION 103 8 | #define IDC_PMS_COMPANY 104 9 | #define IDC_PMS_COPYRIGHT 105 10 | #define IDC_PMS_EXTRASTRING 106 11 | #define IDB_12NOON 106 12 | #define IDD_PMS_LOG_WINDOW 129 13 | #define IDI_KEY 2000 14 | #define IDC_PMS_APPICON 2001 15 | #define IDC_TEXT 2002 16 | #define IDC_ERASE 2003 17 | #define IDC_PMS_NAME 2004 18 | #define IDC_URL_WEB 2005 19 | #define IDC_PMS_KEY 2006 20 | #define IDC_URL_MAILTO 2007 21 | #define IDC_BAR 2008 22 | #define IDC_BROWSE 2010 23 | #define IDC_STATUS 2011 24 | #define IDC_ACTIVITY 2012 25 | #define IDC_BITMAP 2013 26 | #define IDC_BULB 2076 27 | #define IDD_PMS_ABOUT 10000 28 | #define IDD_PMS_REGISTER 10002 29 | #define IDD_PROGRESS 10003 30 | #define IDS_INI_WNDWPLACEMENT_SECTION 20010 31 | #define IDS_INI_WNDWPLACEMENT_LEN 20011 32 | #define IDS_INI_WNDWPLACEMENT_FGS 20012 33 | #define IDS_INI_WNDWPLACEMENT_SHOW 20013 34 | #define IDS_INI_WNDWPLACEMENT_MIN_X 20014 35 | #define IDS_INI_WNDWPLACEMENT_MIN_Y 20015 36 | #define IDS_INI_WNDWPLACEMENT_MAX_X 20016 37 | #define IDS_INI_WNDWPLACEMENT_MAX_Y 20017 38 | #define IDS_INI_WNDWPLACEMENT_NORM_L 20018 39 | #define IDS_INI_WNDWPLACEMENT_NORM_T 20019 40 | #define IDS_INI_WNDWPLACEMENT_NORM_R 20020 41 | #define IDS_INI_WNDWPLACEMENT_NORM_B 20021 42 | #define IDS_PMS_REGISTER 40000 43 | #define PMS_IDS_COMPANYNAME_KEY 40001 44 | #define IDS_REG_OK 40002 45 | #define IDS_REG_FAIL 40003 46 | #define PMS_IDS_WEB_PMS 40004 47 | #define IDP_ERR_LAUNCH_BROWSER1 40005 48 | #define PMS_IDS_MAILTO_PMS 40006 49 | #define IDS_BROWSE_REG 40007 50 | #define IDS_FILTERS_REG 40008 51 | #define IDS_EXT_REG 40009 52 | #define PMS_IDS_WEB_CHECK_UPDATE7 40010 53 | #define PMS_IDP_WEB_NO_CXN 40011 54 | #define IDS_REG_FAIL_VERSION2 40012 55 | #define PMS_IDS_WEB_SITE 40013 56 | #define IDP_HTTP_VER_FAIL 40020 57 | #define IDP_HTTP_VER_LATEST2 40021 58 | #define IDP_HTTP_VER_OUTOFDATE3 40022 59 | #define IDP_MAIL_NOADDRESS 40104 60 | #define IDS_INI_VIEW_SORT_COLIX 40200 61 | #define IDS_INI_VIEW_SORT_ASCENDING 40201 62 | #define IDS_INI_VIEW_NUM_COLS 40202 63 | #define IDS_INI_VIEW_COL_ORDER1 40203 64 | #define IDS_INI_VIEW_COL_WIDTH1 40204 65 | #define IDS_INI_VIEW_COL_ALIGNMENT1 40205 66 | 67 | // Next default values for new objects 68 | // 69 | #ifdef APSTUDIO_INVOKED 70 | #ifndef APSTUDIO_READONLY_SYMBOLS 71 | #define _APS_NEXT_RESOURCE_VALUE 111 72 | #define _APS_NEXT_COMMAND_VALUE 40001 73 | #define _APS_NEXT_CONTROL_VALUE 1015 74 | #define _APS_NEXT_SYMED_VALUE 101 75 | #endif 76 | #endif 77 | -------------------------------------------------------------------------------- /Shared/VersionInfo.cpp: -------------------------------------------------------------------------------- 1 | //--------------------------------------------------------------------------- 2 | // (c) 2003-2010 12noon, Stefan K. S. Tucker 3 | // (c) 1994-2002 Perpetual Motion Software, Stefan K. S. Tucker 4 | //--------------------------------------------------------------------------- 5 | 6 | #include "stdafx.h" 7 | #include 8 | #include 9 | #pragma comment(lib, "version.lib") 10 | 11 | #include "skstutil.h" 12 | #include "misc.h" 13 | #include "VersionInfo.h" 14 | 15 | using skst::VersionInfo; 16 | 17 | VersionInfo::VersionInfo(const HINSTANCE hInst) 18 | { 19 | //----------------- 20 | // Get path to app 21 | //----------------- 22 | TCHAR s[_MAX_PATH]; 23 | ::GetModuleFileName(hInst, s, _MAX_PATH); 24 | 25 | // determine size of app's version information 26 | DWORD dwZero; 27 | const DWORD cbVerSize = ::GetFileVersionInfoSize(s, &dwZero); 28 | if (cbVerSize == 0) 29 | { 30 | _pVerInfo = nullptr; 31 | ::OutputDebugString(skst::MyFormatV(_T("Unable to retrieve size of version information from %s.\n"), s).c_str()); 32 | return; 33 | } 34 | 35 | // retrieve the app's version information 36 | _pVerInfo = new BYTE [cbVerSize]; 37 | assert(_pVerInfo != nullptr); 38 | if (!::GetFileVersionInfo(s, dwZero, cbVerSize, _pVerInfo)) 39 | { 40 | ::OutputDebugString(_T("Unable to retrieve version information.\n")); 41 | return; 42 | } 43 | 44 | // get fixed file version info 45 | UINT uiInfoSize; // size of requested info 46 | if (!::VerQueryValue(_pVerInfo, _T("\\"), 47 | (VOID **) &_pFileInfo, &uiInfoSize)) 48 | { 49 | ::OutputDebugString(_T("Unable to retrieve fixed file information.\n")); 50 | } 51 | 52 | // get the language type 53 | if (!::VerQueryValue(_pVerInfo, _T("\\VarFileInfo\\Translation"), 54 | (VOID **) &_ptLangInfo, &uiInfoSize)) 55 | { 56 | ::OutputDebugString(_T("Unable to retrieve language information.\n")); 57 | } 58 | } 59 | 60 | 61 | VersionInfo::~VersionInfo() 62 | { 63 | if (_pVerInfo != nullptr) 64 | { 65 | delete [] _pVerInfo; 66 | _pVerInfo = nullptr; 67 | } 68 | } 69 | 70 | 71 | //--------------------------------------------------------------------------- 72 | // This routine returns a pointer to the value of the passed key. 73 | // It simply sets the second parameter to the address of a LPSTR; 74 | // because the function only sets the LPSTR to point into the version 75 | // info block, there is no need to allocate storage for a string. 76 | // The string pointer is set to NULL if there is no version information 77 | // block or there was an error in retrieving it (see ctor). 78 | //--------------------------------------------------------------------------- 79 | void 80 | VersionInfo::GetInfo(PCTSTR szKey, 81 | PCTSTR *pszValue) 82 | const 83 | { 84 | if (_pVerInfo == nullptr) // if no ver info block (or error) 85 | { 86 | *pszValue = nullptr; 87 | return; 88 | } 89 | 90 | // format language information 91 | TCHAR s[200]; 92 | // http://msdn.microsoft.com/en-us/library/ms647464(VS.85).aspx 93 | StringCchPrintf(s, _countof(s), _T("\\StringFileInfo\\%04x%04x\\%s"), 94 | _ptLangInfo->wLang, _ptLangInfo->wCharSet, szKey); 95 | 96 | UINT uiInfoSize; // size of requested info 97 | ::VerQueryValue(_pVerInfo, s, (VOID **) pszValue, &uiInfoSize); 98 | } 99 | -------------------------------------------------------------------------------- /Shared/misc.h: -------------------------------------------------------------------------------- 1 | //--------------------------------------------------------------------------- 2 | // (c) 2002-2009 12noon, Stefan K. S. Tucker 3 | // (c) 2002 Perpetual Motion Software, Stefan K. S. Tucker 4 | //--------------------------------------------------------------------------- 5 | 6 | #pragma once 7 | 8 | #include 9 | 10 | #include "skstutil.h" 11 | 12 | namespace skst 13 | { 14 | 15 | //------------------------------ 16 | // MSJ Nov 97 v12 n11 Win32 Q&A 17 | //-------------------------------------------------- 18 | // Example: 19 | // #pragma MSG("Add err-checking later") 20 | // 21 | // Output: 22 | // c:\Project\fish.cpp(296): Add err-checking later 23 | //---------------------------------------------------------------------------- 24 | // was: #define chMSG(desc) message(__FILE__ "(" chSTR2(__LINE__) "):" #desc) 25 | // #pragma chMSG(Add err-checking later) 26 | //---------------------------------------------------------------------------- 27 | 28 | #define chSTR(x) #x 29 | #define chSTR2(x) chSTR(x) 30 | #define MSG(desc) message(__FILE__ "(" chSTR2(__LINE__) "): " desc) 31 | 32 | /* 33 | display various Windows defines 34 | */ 35 | #define EMIT_VALUE(def) message(#def _T(" = ") chSTR2(def)) 36 | 37 | // displays macro name itself if not defined 38 | //#pragma EMIT_VALUE(WINVER) 39 | //#pragma EMIT_VALUE(_WIN32_WINDOWS) 40 | //#pragma EMIT_VALUE(_WIN32_WINNT) 41 | //#pragma EMIT_VALUE(_WIN32_IE) 42 | 43 | 44 | ///////////////////////////////////////////////////////////////////////////// 45 | // Miscellaneous functions 46 | 47 | extern HICON LoadIconSmall(const HINSTANCE hInst, const UINT id); 48 | 49 | extern tstring GetAppPath(const HINSTANCE hInst); 50 | extern tstring GetAppPathOnly(const HINSTANCE hInst); 51 | extern tstring GetAppOnly(const HINSTANCE hInst); 52 | extern tstring GetFileNameWithNewExtension(const HINSTANCE hInst, LPCTSTR szExt); 53 | extern tstring GetLocalPath(const HINSTANCE hInst, LPCTSTR szFilename); 54 | 55 | extern tstring GetLocaleInfoString(LCTYPE lcType); 56 | extern tstring GetDroppedFilePath(HDROP h, UINT ix); 57 | extern tstring MyGetFolderPath(const int iType); 58 | 59 | extern tstring IntToString(const int i); 60 | 61 | extern BSTR ASCIItoBSTR(LPCSTR str); 62 | extern std::string BSTRtoASCII(const BSTR bstr); 63 | 64 | extern void AddEllipsis(LPTSTR szDest, LPCTSTR szSrc, const int nchSize); 65 | 66 | extern tstring MyFormatV(LPCTSTR szFormat, ...); 67 | 68 | extern void DeleteSelf(); 69 | extern void BeepSpeaker(DWORD dwFreq, DWORD dwDuration); 70 | 71 | extern void CloseScreenSaver(); 72 | 73 | /* 74 | These functions can be integrated into the 'registry_key' class: 75 | 76 | registry_key keySrc(HKCU, "Software\\Perpetual Motion"); 77 | registry_key keyDest(HKCU, "Software\\12noon"); 78 | keySrc.Move("Alarm++", keyDest, "Alarm++"); 79 | 80 | or they could just be called by such functions. 81 | */ 82 | extern bool RegKeyCopy(HKEY hKeyRootSrc, LPCTSTR szPathParentSrc, LPCTSTR szKeyNameSrc, 83 | HKEY hKeyRootDest, LPCTSTR szPathParentDest, LPCTSTR szKeyNameDest); 84 | extern bool RegKeyMove(HKEY hKeyRootSrc, LPCTSTR szPathParentSrc, LPCTSTR szKeyNameSrc, 85 | HKEY hKeyRootDest, LPCTSTR szPathParentDest, LPCTSTR szKeyNameDest); 86 | 87 | // from md5.cpp 88 | extern bool DigestMD5(LPCTSTR sz, tstring& strDigest); 89 | extern bool DigestMD5_ANSI(LPCSTR sz, tstring& strDigest); 90 | 91 | } 92 | -------------------------------------------------------------------------------- /Shared/Registry.h: -------------------------------------------------------------------------------- 1 | //--------------------------------------------------------------------------- 2 | // (c) 2003-2009 12noon, Stefan K. S. Tucker 3 | // (c) 2001-2002 Perpetual Motion Software, Stefan K. S. Tucker 4 | //--------------------------------------------------------------------------- 5 | 6 | #pragma once 7 | 8 | #include 9 | #include 10 | 11 | #include "skstutil.h" 12 | 13 | namespace skst 14 | { 15 | 16 | class Registry 17 | { 18 | protected: 19 | HKEY _hKey; 20 | DWORD _dwKeyIndex; // enum index for keys 21 | 22 | public: 23 | enum EType 24 | { 25 | ETYPE_USER, // use HKCU hive 26 | ETYPE_MACHINE, // use HKLM hive 27 | ETYPE_MACHINE_THEN_USER, // try HKLM hive, if fail, try HKCU 28 | }; 29 | 30 | // ctor for sound events 31 | Registry(LPCTSTR szAppKeyName, // key name in registry 32 | LPCTSTR szAppName, // readable name in Control Panel 33 | LPCTSTR szEventKeyName, // key name in registry 34 | LPCTSTR szEventName); // readable name in Control Panel 35 | 36 | // ctor for company settings - open key only if it exists 37 | Registry(EType eType, 38 | LPCTSTR szSubKeyTrailer); // e.g., "\\Options" 39 | 40 | // ctor for company settings - open key and create if necessary 41 | Registry(EType eType, 42 | LPCTSTR szSubKeyTrailer, // e.g., "\\Options" 43 | LPCTSTR szDefaultValue); // can be empty 44 | 45 | // ctor for any path - open key only if it exists 46 | Registry(HKEY hRoot, LPCTSTR szKeyPath); 47 | 48 | // ctor for any path - open key and create if necessary 49 | Registry(HKEY hRoot, LPCTSTR szKeyPath, LPCTSTR szDefaultValue); 50 | 51 | virtual ~Registry(); 52 | 53 | bool Exists() const { return (_hKey != nullptr); } 54 | 55 | static void DeleteSoundKey(LPCTSTR szAppKeyName, 56 | LPCTSTR szEventKeyName); 57 | void DeleteKey(); 58 | 59 | void DeleteValue(LPCTSTR szValueName); 60 | 61 | void SetString(LPCTSTR szValueName, LPCTSTR szValue) const; 62 | tstring GetString(LPCTSTR szValueName, LPCTSTR szDefaultValue) const; 63 | 64 | void SetDWORD(LPCTSTR szValueName, DWORD dwValue) const; 65 | DWORD GetDWORD(LPCTSTR szValueName, DWORD dwDefaultValue) const; 66 | 67 | void SetBoolean(LPCTSTR szValueName, bool bValue) const 68 | { SetDWORD(szValueName, DWORD(bValue ? 1 : 0)); } 69 | bool GetBoolean(LPCTSTR szValueName, bool bDefaultValue) const 70 | { return GetDWORD(szValueName, DWORD(bDefaultValue ? 1 : 0)) ? true : false; } 71 | 72 | void SetBOOL(LPCTSTR szValueName, BOOL bValue) const 73 | { SetDWORD(szValueName, DWORD(bValue)); } 74 | BOOL GetBOOL(LPCTSTR szValueName, BOOL bDefaultValue) const 75 | { return GetDWORD(szValueName, DWORD(bDefaultValue)); } 76 | 77 | void SetBinary(LPCTSTR szValueName, const std::vector& vData) const; 78 | void GetBinary(LPCTSTR szValueName, std::vector& vData) const; 79 | 80 | void EnumKeys(tstring& strName); 81 | 82 | protected: 83 | void CommonCtor(); 84 | HKEY GetKeyType(EType eType) const; 85 | void OpenKey(HKEY hMainKey, LPCTSTR szSubKey); 86 | void CreateKey(HKEY hMainKey, LPCTSTR szSubKey, LPCTSTR szDefaultValue); 87 | void CloseKey(); 88 | }; 89 | 90 | } 91 | 92 | -------------------------------------------------------------------------------- /ConfigureDlg.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "Shared/Pmslib.h" 4 | #include "Shared/StaticColor.h" 5 | #include "Shared/RegistryMonitor.h" 6 | 7 | #include "resource.h" 8 | 9 | /* 10 | POTENTIAL BUG: 11 | 12 | Note that some functions, updating control's text and formatting a control, 13 | use the member data of this class. Some of that member data is modified 14 | when the dialog is active (e.g., alignment and text color) so it can affect 15 | callers who use these functions while this dlg is active. Perhaps they 16 | should be moved to an internal/external member data strategy. 17 | 18 | */ 19 | 20 | class ConfigureDlg : public CDialog 21 | { 22 | DECLARE_DYNAMIC(ConfigureDlg) 23 | 24 | public: 25 | enum class Alignment 26 | { 27 | ALIGN_LEFT = SS_LEFT, 28 | ALIGN_CENTER = SS_CENTER, 29 | ALIGN_RIGHT = SS_RIGHT, 30 | }; 31 | 32 | protected: 33 | bool _bFontDefault; 34 | LOGFONT _lfFontClock; 35 | CFont _font; // to delete font on dtor 36 | 37 | CMenu _menuBar; 38 | CMenu *_pMenuFormats; 39 | 40 | RegistryMonitor _regmonClock; 41 | 42 | 43 | MyMFC::StaticColor _ctlSample; 44 | 45 | CEdit _ctlFormat; 46 | CString _strFormat; // format of date/time/whatever displayed in band (in strftime() format) 47 | 48 | MyMFC::StaticColor _ctlSwatchText; 49 | MyMFC::StaticColor _ctlSwatchBG; 50 | 51 | bool _bColorDefaultText; 52 | COLORREF _crColorText; 53 | 54 | bool _bColorTransparentBG; 55 | bool _bColorDefaultBG; 56 | COLORREF _crColorBG; 57 | 58 | PMS::CBox _ctlAlignment; 59 | Alignment _eAlignmentStyle; // SS_LEFT, SS_CENTER, SS_RIGHT 60 | 61 | public: 62 | ConfigureDlg(CWnd* pParent); 63 | virtual ~ConfigureDlg() {} 64 | 65 | CString UpdateControlText(MyMFC::StaticColor& ctl); 66 | 67 | const LOGFONT& GetFont() const { return _lfFontClock; } 68 | 69 | bool IsClockColorTextDefault() const { return _bColorDefaultText; } 70 | const COLORREF& GetClockColorText() const { return _crColorText; } 71 | 72 | bool IsClockColorBgTransparent() const { return _bColorTransparentBG; } 73 | bool IsClockColorBgDefault() const { return _bColorDefaultBG; } 74 | const COLORREF& GetClockColorBG() const { return _crColorBG; } 75 | 76 | Alignment GetAlignmentStyle() const { return _eAlignmentStyle; } 77 | 78 | void LoadFormat(); 79 | 80 | protected: 81 | enum { IDD = IDD_CONFIGURE }; 82 | 83 | virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support 84 | 85 | static ConfigureDlg *_pDlgFontPicker; 86 | static UINT_PTR CALLBACK FctHookFontDlg(HWND hdlg, UINT uiMsg, WPARAM wParam, LPARAM lParam); 87 | void OnFontApply(const LOGFONT& lf); 88 | 89 | void LoadOptions(); 90 | static CString UpdateControlText(MyMFC::StaticColor& ctl, LPCTSTR szFormat, const COleDateTime& dt); 91 | void FormatSample(); 92 | void FormatStaticControl(MyMFC::StaticColor& ctl, const Alignment& eAlignmentStyle, const bool bColorTransparentBG); 93 | void SetNewFont(MyMFC::StaticColor& ctl, const LOGFONT& lf); 94 | 95 | DECLARE_MESSAGE_MAP() 96 | virtual BOOL OnInitDialog(); 97 | virtual void OnOK(); 98 | virtual void OnCancel(); 99 | afx_msg void OnBnClickedFont(); 100 | afx_msg void OnBnClickedDefault(); 101 | afx_msg void OnStnClickedColorTextSwatch(); 102 | afx_msg void OnStnClickedColorBgSwatch(); 103 | afx_msg void OnCbnSelchangeAlignment(); 104 | afx_msg void OnEnChangeFormat(); 105 | afx_msg void OnBnClickedTransparentBg(); 106 | afx_msg void OnBnClickedFormats(); 107 | afx_msg void OnClockFormats(); 108 | }; 109 | -------------------------------------------------------------------------------- /COMToys/ComToys.vcxproj.filters: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | {498838bd-bebc-42d1-8431-abd040eae2db} 6 | cpp;c;cxx;rc;def;r;odl;hpj;bat;for;f90 7 | 8 | 9 | {3e7244d1-83a5-4f66-9464-92040131251b} 10 | h;hpp;hxx;hm;inl;fi;fd 11 | 12 | 13 | 14 | 15 | Source Files 16 | 17 | 18 | Source Files 19 | 20 | 21 | Source Files 22 | 23 | 24 | Source Files 25 | 26 | 27 | Source Files 28 | 29 | 30 | Source Files 31 | 32 | 33 | Source Files 34 | 35 | 36 | Source Files 37 | 38 | 39 | Source Files 40 | 41 | 42 | Source Files 43 | 44 | 45 | Source Files 46 | 47 | 48 | Source Files 49 | 50 | 51 | Source Files 52 | 53 | 54 | Source Files 55 | 56 | 57 | Source Files 58 | 59 | 60 | Source Files 61 | 62 | 63 | Source Files 64 | 65 | 66 | Source Files 67 | 68 | 69 | Header Files 70 | 71 | 72 | 73 | 74 | Header Files 75 | 76 | 77 | Header Files 78 | 79 | 80 | Header Files 81 | 82 | 83 | Header Files 84 | 85 | 86 | Header Files 87 | 88 | 89 | Header Files 90 | 91 | 92 | Header Files 93 | 94 | 95 | Header Files 96 | 97 | 98 | Header Files 99 | 100 | 101 | Header Files 102 | 103 | 104 | Header Files 105 | 106 | 107 | 108 | 109 | 110 | -------------------------------------------------------------------------------- /Shared/GetProcAddress.h: -------------------------------------------------------------------------------- 1 | //--------------------------------------------------------------------------- 2 | // (c) 2003-2020 12noon, Stefan K. S. Tucker 3 | // (c) 2001-2002 Perpetual Motion Software, Stefan K. S. Tucker 4 | //--------------------------------------------------------------------------- 5 | 6 | #pragma once 7 | 8 | #include "Shared/MyLog.h" 9 | 10 | namespace skst 11 | { 12 | typedef BOOL (WINAPI * FCT_AnimateWindow)(IN HWND, IN DWORD, IN DWORD); 13 | typedef BOOL (WINAPI * FCT_ChangeWindowMessageFilter)(UINT, DWORD); 14 | typedef HRESULT (STDAPICALLTYPE * FCT_CloseThemeData)(HTHEME hTheme); 15 | typedef HRESULT (STDAPICALLTYPE * FCT_DrawThemeBackground)(HTHEME hTheme, HDC hdc, int iPartId, int iStateId, const RECT *pRect, OPTIONAL const RECT *pClipRect); 16 | typedef HWND (STDAPICALLTYPE * FCT_GetConsoleWindow)(); 17 | typedef LANGID (WINAPI * FCT_GetSystemDefaultUILanguage)(); 18 | typedef LANGID (WINAPI * FCT_GetUserDefaultUILanguage)(); 19 | typedef BOOL (WINAPI * FCT_IsThemeActive)(); 20 | typedef HDESK (WINAPI * FCT_OpenDesktop)(LPTSTR, DWORD, BOOL, ACCESS_MASK); 21 | typedef HTHEME (STDAPICALLTYPE * FCT_OpenThemeData)(HWND hwnd, LPCWSTR pszClassList); 22 | typedef /*WINUSERAPI*/ BOOL (WINAPI * FCT_SetLayeredWindowAttributes)(HWND, COLORREF, BYTE, DWORD); 23 | typedef HRESULT (STDAPICALLTYPE * FCT_SHGetFolderPath)(HWND, int, HANDLE, DWORD, LPTSTR); 24 | typedef BOOL (WINAPI * FCT_SHGetSpecialFolderPath)(HWND hwndOwner, LPTSTR lpszPath, int nFolder, BOOL fCreate); 25 | 26 | /* 27 | Normally you have to dynamically load procedure addresses like this: 28 | 29 | HINSTANCE hShell = ::LoadLibrary("shell32.dll"); 30 | typedef BOOL (STDAPICALLTYPE * FCT_SHGetDiskFreeSpace)(PCTSTR, ULARGE_INTEGER *, ULARGE_INTEGER *, ULARGE_INTEGER *); 31 | FCT_SHGetDiskFreeSpace fctSHGetDiskFreeSpace = (FCT_SHGetDiskFreeSpace) ::GetProcAddress(hShell, "SHGetDiskFreeSpaceA"); 32 | if (fctSHGetDiskFreeSpace == NULL) 33 | throw 0; 34 | if (hShell != NULL) 35 | ::FreeLibrary(hShell); 36 | 37 | This class provides a nice wrapper around ::GetProcAddress(). 38 | It's designed to be used like this, one object per function: 39 | 40 | typedef BOOL (STDAPICALLTYPE * FCT_SHGetDiskFreeSpace)(PCTSTR, ULARGE_INTEGER *, ULARGE_INTEGER *, ULARGE_INTEGER *); 41 | 42 | GetProcAddress gpa("shell32.dll", "SHGetDiskFreeSpaceA"); 43 | if (gpa) 44 | { 45 | if (!(*gpa)(_T("c:\\"), &i64BytesFree, &i64, NULL)) 46 | throw 0; 47 | } 48 | 49 | OR 50 | 51 | // BOOL SetLayeredWindowAttributes(HWND hwnd, COLORREF crKey, BYTE bAlpha, DWORD dwFlags); 52 | typedef BOOL (*FCT_SetLayeredWindowAttributes)(HWND, COLORREF, BYTE, DWORD); 53 | 54 | GetProcAddress gpa("user32.dll", "SetLayeredWindowAttributes"); 55 | if (gpa) 56 | (*gpa)(h, RGB(0, 0, 0), 0xD0, 0); 57 | */ 58 | 59 | template class GetProcAddress 60 | { 61 | protected: 62 | HMODULE _hLib; 63 | F _fct; 64 | 65 | public: 66 | GetProcAddress(PCTSTR strNameLib, PCSTR strNameFct) 67 | { 68 | _fct = nullptr; 69 | 70 | _hLib = ::LoadLibrary(strNameLib); 71 | if (_hLib == nullptr) 72 | { 73 | skst::MyLog::GetLog().LogV(_T("Loading %s failed"), strNameLib); 74 | return; 75 | } 76 | 77 | _fct = (F) ::GetProcAddress(_hLib, strNameFct); 78 | if (_fct == nullptr) 79 | skst::MyLog::GetLog().LogV(_T("Loading %hs() failed"), strNameFct); 80 | } 81 | 82 | virtual ~GetProcAddress() 83 | { 84 | if (_hLib != nullptr) 85 | { 86 | ::FreeLibrary(_hLib); 87 | _hLib = nullptr; 88 | _fct = nullptr; 89 | } 90 | } 91 | 92 | operator bool() const 93 | { 94 | return (_fct != nullptr); 95 | } 96 | 97 | F& operator *() { return _fct; } 98 | }; 99 | 100 | } 101 | 102 | -------------------------------------------------------------------------------- /MyBands.h: -------------------------------------------------------------------------------- 1 | //--------------------------------------------------------------------------- 2 | // (c) 2006-2020 12noon, Stefan K. S. Tucker 3 | //--------------------------------------------------------------------------- 4 | 5 | #pragma once 6 | 7 | #include "Shared/ToolTipCtrl.h" 8 | 9 | #include "COMtoys/BandObj.h" 10 | 11 | #include "Shared/StaticColor.h" 12 | 13 | #include "Calendar.h" 14 | #include "ConfigureDlg.h" 15 | #include "Resource.h" 16 | 17 | 18 | /* 19 | Use this to add a Logo on the left/top. 20 | */ 21 | //#define _LOGO 22 | /* 23 | It can be either an icon or a bitmap. 24 | */ 25 | //#define _LOGO_ICON 26 | #if defined(_LOGO) 27 | //#if defined(_LOGO_ICON) 28 | // #pragma message("LOGO ICON enabled") 29 | //#else 30 | // #pragma message("LOGO BITMAP enabled") 31 | //#endif 32 | #pragma message("LOGO enabled") 33 | #endif 34 | 35 | ////////////////// 36 | // Application class: derive from CBandObjApp 37 | // 38 | class CMyBandsDll : public CBandObjDll 39 | { 40 | public: 41 | CMyBandsDll() 42 | { 43 | #if defined(_DEBUG) 44 | # if 1 45 | CBandObj::bTRACE = FALSE; 46 | ComToys::bTRACE = FALSE; 47 | # endif 48 | #endif 49 | } 50 | virtual ~CMyBandsDll() {} 51 | virtual BOOL InitInstance(); 52 | 53 | protected: 54 | DECLARE_MESSAGE_MAP() 55 | }; 56 | 57 | 58 | ////////////////// 59 | // Desk band lives in task bar 60 | // 61 | class CMyDeskBand : public CBandObj 62 | { 63 | protected: 64 | skst::MyToolTipCtrl _tips; 65 | 66 | #if defined(_LOGO) 67 | CStatic _ctlAbout; 68 | CSize _sizeAbout; 69 | #endif 70 | 71 | UINT_PTR _idTimerUpdateDisplay; 72 | 73 | // clock support 74 | MyMFC::StaticColor _ctlClock; 75 | 76 | CSize _sizeClockText; 77 | 78 | // text properties (from Registry) 79 | ConfigureDlg _dlgConfiguration; 80 | CFont _fontClock; 81 | 82 | // calendar support 83 | CalendarWindow _cal; 84 | 85 | public: 86 | CMyDeskBand(); 87 | virtual ~CMyDeskBand() {} 88 | 89 | protected: 90 | void BuildContextMenu(); 91 | 92 | // override 93 | virtual BOOL PreCreateWindow(CREATESTRUCT& cs) override; 94 | virtual BOOL OnCmdMsg(UINT nID, int nCode, void* pExtra, AFX_CMDHANDLERINFO* pHandlerInfo) override; 95 | 96 | virtual void IPersistStreamGetSizeMax(ULARGE_INTEGER *pcbSize) override; 97 | virtual HRESULT IPersistStreamSave(IStream *pStream) override; 98 | virtual HRESULT IPersistStreamLoad(IStream *pStream) override; 99 | 100 | virtual STDMETHODIMP SetCompositionState(BOOL fCompositionEnabled) override 101 | { 102 | if (fCompositionEnabled != m_bCompositionEnabled) 103 | { 104 | __super::SetCompositionState(fCompositionEnabled); 105 | FormatClock(); 106 | UpdateClockText(); 107 | } 108 | return S_OK; 109 | } 110 | 111 | 112 | virtual void DoSize(UINT nType, int cx, int cy); 113 | 114 | void SetBandSizes(); 115 | void UpdateClockText(); 116 | void FormatClock(); 117 | 118 | afx_msg void OnSetFocus(CWnd* pOldWnd); 119 | afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct); 120 | afx_msg void OnDestroy(); 121 | afx_msg void OnTimer(UINT_PTR idEvent); 122 | afx_msg BOOL OnToolTipNotify(UINT id, NMHDR *pNMHDR, LRESULT *pResult); 123 | afx_msg void OnProducts(); 124 | afx_msg void OnHelp(); 125 | afx_msg void OnAbout(); 126 | afx_msg void OnClockOptions(); 127 | afx_msg void OnCalendar(); 128 | afx_msg void OnUpdateCalendarShowToday(CCmdUI *pCmdUI); 129 | afx_msg void OnCalendarShowToday(); 130 | afx_msg void OnUpdateCalShowWeekNums(CCmdUI *pCmdUI); 131 | afx_msg void OnCalShowWeekNums(); 132 | afx_msg void OnUpdateCalSaveLastPos(CCmdUI *pCmdUI); 133 | afx_msg void OnCalSaveLastPos(); 134 | afx_msg void OnUpdateCalSaveLastSize(CCmdUI *pCmdUI); 135 | afx_msg void OnCalSaveLastSize(); 136 | afx_msg void OnCalSelectFont(); 137 | DECLARE_MESSAGE_MAP(); 138 | DECLARE_DYNCREATE(CMyDeskBand) 139 | public: 140 | afx_msg void OnAdjustDateTime(); 141 | afx_msg void OnSettingChange(UINT uFlags, LPCTSTR lpszSection); 142 | }; 143 | -------------------------------------------------------------------------------- /help/Overview.md: -------------------------------------------------------------------------------- 1 | # Timekeeper by [12noon LLC](https://12noon.com/) 2 | 3 | Display the date and time on your taskbar in any format and color (including transparent). 4 | Get rid of that tiny, useless Windows clock. Pop up a calendar when you need one. 5 | Resize it to show as many or as few months as you want. 6 | Move Timekeeper around and it'll remember its position and size, or not—your choice). 7 | 8 | Timekeeper is a deskband (like the taskbar) that displays the current date and 9 | time in whatever format you specify. When you click on it with your mouse, 10 | it displays a calendar that you can resize to display as many months as you want. 11 | 12 | ![Default](timekeeper.png) 13 | ![Multiline Red](tk_multiline_red.png) 14 | ![Multiline](tk_multiline.png) 15 | 16 | You can drag Timekeeper wherever you want it—even vertically—just like your other deskbands. 17 | 18 | I was inspired to write Timekeeper because of TClockEx. 19 | Even in 2000, it was an interesting (but fragile) solution and hasn't been updated since. 20 | When Windows introduced the concept of deskbands, small bars that can be hidden, displayed, 21 | resized, floated, and moved. I wrote Timekeeper to take advantage of these modern features. 22 | 23 | ![German](de_flag.gif) Timekeeper is in English and has been translated into German. 24 | 25 | Windows 11 removed support for desk bands (such as Timekeeper) when they rewrote File Manager. 26 | In addition, now that Windows 11 and 10 display the date in the taskbar, I have invested less 27 | effort into updating Timekeeper. Since there is still considerable interest in it, 28 | I released Timekeeper as open source under the MIT license. 29 | 30 | ## Calendar 31 | 32 | ![Calendar](tk_calendar_2x1.png) 33 | 34 | When you click on Timekeeper with your mouse, it displays a calendar. 35 | 36 | Note: the Windows calendar control follows this rule for numbering the weeks of the year: 37 | ["Week 1 is defined as the first week that contains at least four days."](https://learn.microsoft.com/en-us/windows/win32/controls/month-calendar-control-styles) 38 | 39 | ## Configuration 40 | 41 | To access Timekeeper's menu, right-click on Timekeeper. The menu allows you to perform the following functions: 42 | 43 | * Obtain information about 12noon Products. 44 | * Display this Help document. 45 | * Display the About window. 46 | * Configure the date/time display. 47 | * Adjust the system date/time. 48 | * Specify whether the calendar should highlight today's date. 49 | * Specify whether the calendar should display week numbers. 50 | * Specify whether the calendar should remember its position. 51 | * Specify whether the calendar should remember its size. 52 | * Specify the calendar's font. 53 | 54 | ## Requirements 55 | 56 | Timekeeper runs on Microsoft® Windows® 11 and 10. 57 | The Timekeeper installer contains both 32-bit and 64-bit versions. 58 | (Microsoft has ended mainstream support for Windows 8.1, 8, 7, XP 59 | and Server 2003, so those platforms are no longer officially supported.) 60 | 61 | ## Known Issues 62 | 63 | Transparency does not work well. Use a black background instead. 64 | 65 | ## History 66 | 67 | **1.62.9:** Built with latest Microsoft Windows SDK and Visual Studio 2022 runtime. 68 | 69 | **1.62.4:** Built with latest Microsoft Windows SDK and Visual Studio 2020 runtime. 70 | 71 | **1.62.3:** Built with latest Microsoft Windows SDK and Visual Studio 2017 (15.4.1) runtime. 72 | 73 | **1.62.2:** Built with latest Microsoft Windows SDK and Visual Studio 2015 Update 3 runtime. (Last version to officially support Windows 7 and 8.1.) 74 | 75 | **1.62.0:** Removed compatibility warning. Changed default to be opaque (not transparent). Improved handling of Windows translucency. 76 | 77 | **1.61.0:** Fixed issue with composition. Known issue: transparency does not work well. Use a black background instead. 78 | 79 | **1.60.0:** Added support for Windows 7 and later. Removed support for Windows XP themes. 80 | 81 | **1.44.0:** Updated installer for 64-bit. 82 | 83 | **1.42:** Fixed calendar not displaying (because mouse click went to tooltip). 84 | 85 | **1.41:** Eliminated tooltip flickering. Fixed menu display error in rare occasions. Renamed 64-bit DLL. 86 | 87 | **1.40:** Auto-reload format. Added %T and %V. 88 | 89 | **1.32:** Added Adjust Date/Time command. 90 | -------------------------------------------------------------------------------- /COMToys/src/MenuInit.cpp: -------------------------------------------------------------------------------- 1 | #include "stdafx.h" 2 | #include "COMtoys/MenuInit.h" 3 | 4 | #ifdef _DEBUG 5 | #define new DEBUG_NEW 6 | #undef THIS_FILE 7 | static char THIS_FILE[] = __FILE__; 8 | #endif 9 | 10 | ////////////////// 11 | // This static function can be sed to initialize any menu 12 | // when you get WM_INITMENUPOPUP 13 | // 14 | void CPopupMenuInit::Init(CCmdTarget* pTarg, 15 | CMenu* pMenu, BOOL bAutoMenuEnable) 16 | { 17 | CCmdUI state; 18 | state.m_pMenu = pMenu; 19 | ASSERT(state.m_pOther == NULL); 20 | ASSERT(state.m_pParentMenu == NULL); 21 | 22 | CWnd *pWnd = DYNAMIC_DOWNCAST(CWnd, pTarg); 23 | if (pWnd) { 24 | 25 | // determine if menu is popup in top-level menu and set m_pOther to 26 | // it if so (m_pParentMenu == NULL indicates that it is secondary popup) 27 | HMENU hParentMenu; 28 | if (AfxGetThreadState()->m_hTrackingMenu == pMenu->m_hMenu) 29 | state.m_pParentMenu = pMenu; // parent == child for tracking popup 30 | else if ((hParentMenu = ::GetMenu(*pWnd)) != NULL) 31 | { 32 | CWnd* pParent = pWnd->GetTopLevelParent(); 33 | // child windows don't have menus -- need to go to the top! 34 | if (pParent != NULL && 35 | (hParentMenu = ::GetMenu(pParent->m_hWnd)) != NULL) 36 | { 37 | int nIndexMax = ::GetMenuItemCount(hParentMenu); 38 | for (int nIndex = 0; nIndex < nIndexMax; nIndex++) 39 | { 40 | if (::GetSubMenu(hParentMenu, nIndex) == pMenu->m_hMenu) 41 | { 42 | // when popup is found, m_pParentMenu is containing menu 43 | state.m_pParentMenu = CMenu::FromHandle(hParentMenu); 44 | break; 45 | } 46 | } 47 | } 48 | } 49 | } 50 | 51 | state.m_nIndexMax = pMenu->GetMenuItemCount(); 52 | for (state.m_nIndex = 0; state.m_nIndex < state.m_nIndexMax; 53 | state.m_nIndex++) 54 | { 55 | state.m_nID = pMenu->GetMenuItemID(state.m_nIndex); 56 | if (state.m_nID == 0) 57 | continue; // menu separator or invalid cmd - ignore it 58 | 59 | ASSERT(state.m_pOther == NULL); 60 | ASSERT(state.m_pMenu != NULL); 61 | if (state.m_nID == (UINT)-1) 62 | { 63 | // possibly a popup menu, route to first item of that popup 64 | state.m_pSubMenu = pMenu->GetSubMenu(state.m_nIndex); 65 | if (state.m_pSubMenu == NULL || 66 | (state.m_nID = state.m_pSubMenu->GetMenuItemID(0)) == 0 || 67 | state.m_nID == (UINT)-1) 68 | { 69 | continue; // first item of popup can't be routed to 70 | } 71 | state.DoUpdate(pTarg, FALSE); // popups are never auto disabled 72 | } 73 | else 74 | { 75 | // normal menu item 76 | // Auto enable/disable if 'bAutoMenuEnable' 77 | // and command is _not_ a system command. 78 | state.m_pSubMenu = NULL; 79 | state.DoUpdate(pTarg, bAutoMenuEnable && state.m_nID < 0xF000); 80 | } 81 | 82 | // adjust for menu deletions and additions 83 | UINT nCount = pMenu->GetMenuItemCount(); 84 | if (nCount < state.m_nIndexMax) 85 | { 86 | state.m_nIndex -= (state.m_nIndexMax - nCount); 87 | while (state.m_nIndex < nCount && 88 | pMenu->GetMenuItemID(state.m_nIndex) == state.m_nID) 89 | { 90 | state.m_nIndex++; 91 | } 92 | } 93 | state.m_nIndexMax = nCount; 94 | } 95 | } 96 | 97 | CPopupMenuInitHandler::CPopupMenuInitHandler() 98 | { 99 | m_bAutoMenuEnable=TRUE; 100 | } 101 | 102 | CPopupMenuInitHandler::~CPopupMenuInitHandler() 103 | { 104 | } 105 | 106 | LRESULT CPopupMenuInitHandler::WindowProc(UINT msg, WPARAM wp, LPARAM lp) 107 | { 108 | if (msg==WM_INITMENUPOPUP) { 109 | OnMenuInitPopup(CMenu::FromHandle((HMENU)wp), LOWORD(lp), HIWORD(lp)); 110 | } 111 | return CSubclassWnd::WindowProc(msg, wp, lp); 112 | } 113 | 114 | ////////////////// 115 | // This function is mostly copied from CFrameWnd::OnMenuInitPopup 116 | // 117 | void CPopupMenuInitHandler::OnMenuInitPopup(CMenu* pMenu, 118 | UINT nIndex, BOOL bSysMenu) 119 | { 120 | if (bSysMenu) 121 | return; // don't support system menu 122 | 123 | ASSERT(pMenu); 124 | // check the enabled state of various menu items 125 | 126 | CWnd* pWnd = CWnd::FromHandle(m_hWnd); 127 | CPopupMenuInit::Init(pWnd, pMenu, m_bAutoMenuEnable); 128 | } 129 | 130 | -------------------------------------------------------------------------------- /Shared/MyLog.h: -------------------------------------------------------------------------------- 1 | //--------------------------------------------------------------------------- 2 | // (c) 2000-2009 12noon, Perpetual Motion Software, Stefan K. S. Tucker 3 | //--------------------------------------------------------------------------- 4 | 5 | #pragma once 6 | 7 | #include 8 | #include 9 | 10 | #include "skstutil.h" 11 | 12 | namespace skst 13 | { 14 | 15 | /* 16 | based on MFC's CCriticalSection (needed for MyLog) 17 | */ 18 | 19 | class CriticalSection : public CRITICAL_SECTION 20 | { 21 | public: 22 | CriticalSection() 23 | { 24 | ::InitializeCriticalSection(this); 25 | } 26 | 27 | virtual ~CriticalSection() 28 | { 29 | ::DeleteCriticalSection(this); 30 | } 31 | 32 | void Lock() 33 | { 34 | ::EnterCriticalSection(this); 35 | } 36 | 37 | void Unlock() 38 | { 39 | ::LeaveCriticalSection(this); 40 | } 41 | }; 42 | 43 | ///////////////////////////////////////////////////////////////////////////// 44 | ///////////////////////////////////////////////////////////////////////////// 45 | 46 | class MyLog 47 | { 48 | protected: 49 | static bool _bStarted; 50 | static MyLog _log; // only one log per app 51 | 52 | static tstring _strLogFile; 53 | static bool _bLogEnabled; 54 | 55 | CriticalSection _cs; 56 | HANDLE _hFile; 57 | 58 | public: 59 | static void SetLogFilePath(LPCTSTR szLogFilePath); 60 | static void SetLogging(const bool b) { _bLogEnabled = b; } 61 | 62 | virtual ~MyLog(); 63 | 64 | static MyLog& GetLog() 65 | { 66 | if (!_bStarted) 67 | { 68 | // TODO: Construct() calls skst::TraceVersions() which calls GetLog() ... BEFORE we've fully constructed. 69 | _log.Construct(); 70 | } 71 | 72 | return _log; 73 | } 74 | 75 | void Erase() const; 76 | 77 | void Log(LPCTSTR s); 78 | void LogV(LPCTSTR szFormat, ...); 79 | 80 | protected: 81 | MyLog() : _hFile(INVALID_HANDLE_VALUE) {} 82 | void Construct(); 83 | 84 | void Append(LPCTSTR s); 85 | void OpenForAppend(); // throw(CFileException); 86 | }; 87 | 88 | ///////////////////////////////////////////////////////////////////////////// 89 | ///////////////////////////////////////////////////////////////////////////// 90 | 91 | // internal function for LogInOut 92 | inline tstring Timestamp() 93 | { 94 | __time64_t ltime; 95 | _time64(<ime); 96 | TCHAR sz[50]; 97 | tstring str; 98 | if (_tctime64_s(sz, _countof(sz), <ime)) 99 | { 100 | str = sz; 101 | // remove the trailing newline ('\n') 102 | str.erase(str.end() - 1); 103 | } 104 | return str; 105 | } 106 | 107 | /* 108 | This class outputs a function trace on the way in and on the way out. 109 | It also keeps track of the nesting depth and indents appropriately. 110 | 111 | sample usage: 112 | 113 | void fish(int i) 114 | { 115 | LogInOut io("fish"); 116 | // do some stuff 117 | } 118 | 119 | OR 120 | 121 | void MyClass::Fish(int i) 122 | { 123 | LogInOut io(__FUNCTION__); 124 | // do some stuff 125 | } 126 | */ 127 | class LogInOut 128 | { 129 | protected: 130 | static int _iLevel; 131 | tstring _strFct; 132 | const bool _bTimeStamp; 133 | 134 | public: 135 | LogInOut(LPCTSTR szFct, const bool bTimeStamp = false) 136 | : _strFct(szFct) 137 | , _bTimeStamp(bTimeStamp) 138 | { 139 | if (_bTimeStamp) 140 | skst::MyLog::GetLog().LogV(_T("[%s] "), Timestamp().c_str()); 141 | 142 | skst::MyLog::GetLog().LogV(_T(" -->%*s[%s()]"), _iLevel * 2, _T(""), szFct); 143 | ++_iLevel; 144 | } 145 | virtual ~LogInOut() 146 | { 147 | --_iLevel; 148 | 149 | if (_bTimeStamp) 150 | skst::MyLog::GetLog().LogV(_T("[%s] "), Timestamp().c_str()); 151 | 152 | skst::MyLog::GetLog().LogV(_T("<-- %*s[%s()]"), _iLevel * 2, _T(""), _strFct.c_str()); 153 | } 154 | 155 | protected: 156 | LogInOut(const LogInOut& a) : _strFct(a._strFct), _bTimeStamp(a._bTimeStamp) {} 157 | LogInOut& operator=(const LogInOut& /*a*/) 158 | { 159 | // these are const members and we never use the assignment operator anyway 160 | // _strFct = a._strFct; 161 | // _bTimeStamp = a._bTimeStamp; 162 | } 163 | }; 164 | 165 | } 166 | 167 | -------------------------------------------------------------------------------- /COMToys/Debug.h: -------------------------------------------------------------------------------- 1 | //////////////////////////////////////////////////////////////// 2 | // PixieLib(TM) Copyright 1997-1999 Paul DiLascia 3 | // If this code works, it was written by Paul DiLascia. 4 | // If not, I don't know who wrote it. 5 | // 6 | // --- 7 | // General purpose debugging utilities. 8 | // 9 | #ifndef DEBUG_H 10 | #define DEBUG_H 11 | 12 | #ifndef countof 13 | #define countof(x) (sizeof(x)/sizeof(x[0])) 14 | #endif 15 | 16 | #ifdef _DEBUG 17 | 18 | // tell linker to look in ole32 lib (for StringFromClsid) 19 | #pragma comment(linker, "/defaultlib:ole32.lib") 20 | 21 | // This macro lets you put a debug test into your, so you can write 22 | // 23 | // DEBUG_IF((x=5),TRACE("Something is rotten here.\n")); 24 | // 25 | // instead of 26 | // 27 | // #ifdef _DEBUG 28 | // if (x=5) 29 | // TRACE("Something is rotten here.\n"); 30 | // #endif 31 | // 32 | #define DEBUG_IF(condition, action) if (condition) action; 33 | 34 | ////////////////// 35 | // TRACEFN is a macro that lets you generate indented TRACE output so you 36 | // can see the call stack. To use it: 37 | // 38 | // SomeFn(...) 39 | // { 40 | // TRACEFN("Entering SomeFn...\n"); 41 | // . 42 | // . 43 | // } 44 | // 45 | // Now all trace output after TRACEFN will be indented one space, until SomeFn 46 | // returns. You can put TRACEFN in multiple functions to see indented trace 47 | // output. For an example of this, see the HOOK sample program. 48 | // 49 | // NOTE: YOU MUST NOT USE TRACEFN IN A ONE-LINE IF STATEMENT! 50 | // This will fail: 51 | // 52 | // if (foo) 53 | // TRACEFN(...) 54 | // 55 | // Instead, you must enclose the TRACE in squiggle-brackets 56 | // 57 | // if (foo) { 58 | // TRACEFN(...) 59 | // } 60 | // 61 | #define TRACEFN CTraceFn __fooble; TRACE 62 | // 63 | // This class implements TRACEFN. Don't ever use directly! 64 | // 65 | class DLLCLASS CTraceFn { 66 | private: 67 | static int nIndent; // current indent level 68 | friend void AFX_CDECL AfxTrace(LPCTSTR lpszFormat, ...); 69 | public: 70 | CTraceFn() { nIndent++; } // constructor bumps indent 71 | ~CTraceFn() { nIndent--; } // destructor restores it 72 | }; 73 | 74 | ////////////////// 75 | // The following stuff is for getting human-readable names of things so 76 | // you can show them in TRACE statements. For example, 77 | // 78 | // TRACE("Window is: %s\n", _TR(pWnd)); 79 | // 80 | // Will generate output showing the name and title of the window, etc. 81 | // 82 | 83 | // Macro _TR casts _DbgName(x) to LPCTSTR for use with in printf so you 84 | // can write 85 | // 86 | // TRACE("Message is %s\n", _TR(uMsg)); 87 | // 88 | // instead of 89 | // 90 | // TRACE("Message is %s\n", (LPCTSTR)_DbgName(uMsg)); 91 | // 92 | #define _TR(x) (LPCTSTR)_DbgName(x) 93 | 94 | // overloaded fns to get names of things. 95 | extern DLLFUNC CString _DbgName(CWnd* pWnd); // get name of window 96 | extern DLLFUNC CString _DbgName(UINT uMsg); // ... WM_ message 97 | extern DLLFUNC CString _DbgName(REFIID iid); // get name of COM interface 98 | extern DLLFUNC CString _DbgName(SCODE sc); // get name of COM SCODE 99 | 100 | // To debug the names of COM interfaces, just write 101 | // lines to your program: 102 | // 103 | // DEBUG_BEGIN_INTERFACE_NAMES() 104 | // DEBUG_INTERFACE_NAME(IFoo) 105 | // DEBUG_INTERFACE_NAME(IBar) 106 | // ... 107 | // DEBUG_END_INTERFACE_NAMES(); 108 | // 109 | // PixieLib already knows the names of many common interfaces (see Debug.cpp) 110 | // 111 | struct DBGINTERFACENAME { 112 | const IID* piid; // ptr to GUID 113 | PCTSTR name; // human-readable name of interface 114 | }; 115 | 116 | // Used to add interface names to global list -- Use macro 117 | class DLLCLASS CInterfaceNames { 118 | protected: 119 | static CInterfaceNames* s_pFirst; 120 | CInterfaceNames* m_pNext; 121 | DBGINTERFACENAME* m_pEntries; 122 | UINT m_nEntries; 123 | public: 124 | CInterfaceNames(DBGINTERFACENAME* pdin, UINT n); 125 | static const DBGINTERFACENAME* FindEntry(REFIID iid); 126 | }; 127 | 128 | #define DEBUG_BEGIN_INTERFACE_NAMES() \ 129 | static DBGINTERFACENAME _myDBI[] = { \ 130 | 131 | #define DEBUG_INTERFACE_NAME(iface) \ 132 | { &IID_##iface, _T(#iface) }, \ 133 | 134 | #define DEBUG_END_INTERFACE_NAMES() \ 135 | }; \ 136 | static CInterfaceNames _initMyDBI(_myDBI, countof(_myDBI)); \ 137 | 138 | // Macro casts to LPCTSTR for use with TRACE/printf/CString::Format 139 | // 140 | #define DbgName(x) (LPCTSTR)_DbgName(x) 141 | 142 | #else // Below NOT _DEBUG ---------------------------------------------------- 143 | 144 | #define DEBUG_IF(cond, action) ; 145 | #define _TR(x) ((LPCTSTR)NULL) 146 | #define DbgName(x) ((LPCTSTR)NULL) 147 | #define TRACEFN TRACE 148 | 149 | #define DEBUG_BEGIN_INTERFACE_NAMES() 150 | #define DEBUG_END_INTERFACE_NAMES() 151 | #define DEBUG_INTERFACE_NAME(iface) 152 | 153 | #endif // _DEBUG 154 | 155 | #endif // DEBUG_H 156 | -------------------------------------------------------------------------------- /Shared/StatLink.cpp: -------------------------------------------------------------------------------- 1 | //--------------------------------------------------------------------------- 2 | // Copyright (c) 2002-2009 12noon, Stefan K. S. Tucker. 3 | // Copyright (c) 1997-2002 Perpetual Motion Software, Stefan K. S. Tucker. 4 | //--------------------------------------------------------------------------- 5 | 6 | #include "stdafx.h" 7 | #include 8 | #include 9 | 10 | #include "pmslib.h" 11 | #include "pmsres.h" 12 | #include "StatLink.h" 13 | 14 | #ifdef _DEBUG 15 | #undef THIS_FILE 16 | static char THIS_FILE[] = __FILE__; 17 | #endif 18 | 19 | ///////////////////////////////////////////////////////////////////////////// 20 | // CStaticHyperlink 21 | 22 | CStaticHyperlink::CStaticHyperlink(const int idCursor) 23 | { 24 | _idError1 = 0; 25 | 26 | // only defined for >=Win2000 27 | #if !defined(IDC_HAND) 28 | #define IDC_HAND MAKEINTRESOURCE(32649) 29 | #endif 30 | /* 31 | if the cursor id is 0, we use a system cursor 32 | */ 33 | HINSTANCE hRes = nullptr; 34 | LPTSTR pCursor = MAKEINTRESOURCE(idCursor); 35 | if (idCursor == 0) 36 | pCursor = IDC_HAND; 37 | else 38 | hRes = ::AfxGetResourceHandle(); 39 | 40 | _hCursor = (HCURSOR) ::LoadImage(hRes, pCursor, IMAGE_CURSOR, 0, 0, LR_DEFAULTSIZE | LR_SHARED); 41 | } 42 | 43 | 44 | BEGIN_MESSAGE_MAP(CStaticHyperlink, CStatic) 45 | //{{AFX_MSG_MAP(CStaticHyperlink) 46 | ON_WM_CTLCOLOR_REFLECT() 47 | ON_CONTROL_REFLECT(STN_CLICKED, OnClicked) 48 | ON_WM_SETCURSOR() 49 | //}}AFX_MSG_MAP 50 | END_MESSAGE_MAP() 51 | 52 | ///////////////////////////////////////////////////////////////////////////// 53 | // CStaticHyperlink message handlers 54 | 55 | HBRUSH CStaticHyperlink::CtlColor(CDC* pDC, UINT nCtlColor) 56 | { 57 | UNUSED(nCtlColor); 58 | ASSERT(nCtlColor == CTLCOLOR_STATIC); 59 | 60 | //------------------------------------------------------------------ 61 | // make sure the Notify style is set -- otherwise, we won't get any 62 | // mouse clicks (the default for static controls is HitTransparent) 63 | //------------------------------------------------------------------ 64 | DWORD dwStyle = GetStyle(); 65 | if (!(dwStyle & SS_NOTIFY)) 66 | { 67 | ::SetWindowLong(GetSafeHwnd(), GWL_STYLE, dwStyle | SS_NOTIFY); 68 | } 69 | 70 | //----------------------------------------------------------------- 71 | // if there's no window text, don't bother changing font and color 72 | //----------------------------------------------------------------- 73 | CString cText; 74 | GetWindowText(cText); 75 | if (cText.IsEmpty()) 76 | return nullptr; 77 | 78 | //-------------------------------------- 79 | // Change any attributes of the DC here 80 | //-------------------------------------- 81 | 82 | //-------------------------- 83 | // change font to underline 84 | //-------------------------- 85 | CFont font; 86 | LOGFONT lf; 87 | GetFont()->GetObject(sizeof(lf), &lf); 88 | lf.lfUnderline = TRUE; 89 | font.CreateFontIndirect(&lf); 90 | pDC->SelectObject(&font); 91 | 92 | //------------------------------------------------------------ 93 | // try to get link color settings from IE 94 | // 95 | // HKCU \ Software \ Microsoft \ Internet Explorer \ Settings 96 | // AnchorColor = red,green,blue 97 | // AnchorColorVisited = red,green,blue 98 | // 99 | // (we don't know the paths for other browsers) 100 | //------------------------------------------------------------ 101 | COLORREF crAnchor = RGB(0, 0, 0xff); // default 102 | CSettingsStore store(FALSE /*admin*/, TRUE /*read-only*/); 103 | if (store.Open(_T("Software\\Microsoft\\Internet Explorer\\Settings"))) 104 | { 105 | CString s; 106 | if (store.Read(_T("Anchor Color"), s) && !s.IsEmpty()) 107 | { 108 | UINT r, g, b; 109 | if (_stscanf_s((LPCTSTR) s, _T("%u,%u,%u"), &r, &g, &b) == 3) 110 | crAnchor = RGB(r, g, b); 111 | } 112 | } 113 | pDC->SetTextColor(crAnchor); 114 | pDC->SetBkMode(TRANSPARENT); 115 | 116 | //---------------------------------------------------------------------- 117 | // return a non-NULL brush if the parent's handler should not be called 118 | //---------------------------------------------------------------------- 119 | // return transparent brush to preserve parent bg color 120 | return (HBRUSH) ::GetStockObject(HOLLOW_BRUSH); 121 | } 122 | 123 | void CStaticHyperlink::OnClicked() 124 | { 125 | // if there is no stored URL, use the control's text 126 | CString strURL; 127 | if (_strURL.IsEmpty()) 128 | GetWindowText(strURL); 129 | else 130 | strURL = _strURL; 131 | 132 | if (!PMS::OpenURL(strURL)) 133 | { 134 | if (_idError1 > 0) 135 | { 136 | CString s; 137 | ::AfxFormatString1(s, _idError1, strURL); 138 | ::AfxMessageBox(s, MB_OK | MB_ICONEXCLAMATION, _idError1); 139 | } 140 | else 141 | ::MessageBeep(UINT(-1)); 142 | } 143 | } 144 | 145 | 146 | BOOL CStaticHyperlink::OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message) 147 | { 148 | if (_hCursor == nullptr) 149 | return CStatic::OnSetCursor(pWnd, nHitTest, message); 150 | 151 | ::SetCursor(_hCursor); 152 | return TRUE; 153 | } 154 | 155 | -------------------------------------------------------------------------------- /resource.h: -------------------------------------------------------------------------------- 1 | //{{NO_DEPENDENCIES}} 2 | // Microsoft Visual C++ generated include file. 3 | // Used by Timekeeper.rc 4 | // 5 | #define IDR_DESKBAND 1 6 | #define IDR_MAINFRAME 7 7 | #define IDS_INI_DEBUG 100 8 | #define IDS_INI_SHOW_HELP 101 9 | #define IDB_ABOUT 107 10 | #define IDS_INI_SECTION_CLOCK 110 11 | #define IDD_BAND_ENABLE 111 12 | #define IDS_INI_IDEAL_CX 111 13 | #define IDB_BAND_ENABLE 112 14 | #define ID_CLOCK_OPTIONS 112 15 | #define IDS_INI_IDEAL_CY 112 16 | #define IDD_CONFIGURE 113 17 | #define IDS_INI_COLOR_TEXT 113 18 | #define IDM_FORMATS 114 19 | #define IDS_INI_COLOR_BG 114 20 | #define IDB_ARROW_R 115 21 | #define IDS_INI_CLOCK_FORMAT 115 22 | #define IDS_INI_COLOR_BG_TRANSPARENT 116 23 | #define IDS_INI_COLOR_TEXT_DEFAULT 117 24 | #define IDS_INI_COLOR_BG_DEFAULT 118 25 | #define IDS_INI_CLOCK_FONT 119 26 | #define IDS_INI_ALIGNMENT 120 27 | #define IDS_INI_CLOCK_FONT_DEFAULT 121 28 | #define ID_CLOCKFORMATS_SHORTDATETIME 130 29 | #define ID_CLOCKFORMATS_LONGDATETIME 131 30 | #define ID_CLOCKFORMATS_SHORTDATE 132 31 | #define ID_CLOCKFORMATS_LONGDATE 133 32 | #define ID_CLOCKFORMATS_TIME 134 33 | #define ID_CLOCKFORMATS_H024 135 34 | #define ID_CLOCKFORMATS_H24 136 35 | #define ID_CLOCKFORMATS_H012 137 36 | #define ID_CLOCKFORMATS_H12 138 37 | #define ID_CLOCKFORMATS_M0 139 38 | #define ID_CLOCKFORMATS_M 140 39 | #define ID_CLOCKFORMATS_S0 141 40 | #define ID_CLOCKFORMATS_S 142 41 | #define ID_CLOCKFORMATS_AMPM 143 42 | #define ID_CLOCKFORMATS_ABBREVIATEDWEEKDAYNAME 144 43 | #define ID_CLOCKFORMATS_FULLWEEKDAYNAME 145 44 | #define ID_CLOCKFORMATS_WEEKDAYASNUMBER 146 45 | #define ID_CLOCKFORMATS_ABBREVIATEDMONTHNAME 147 46 | #define ID_CLOCKFORMATS_FULLMONTHNAME 148 47 | #define ID_CLOCKFORMATS_MONTH0 149 48 | #define ID_CLOCKFORMATS_MONTH 150 49 | #define IDS_ALIGN_LEFT 150 50 | #define ID_CLOCKFORMATS_D0 151 51 | #define IDS_ALIGN_CENTER 151 52 | #define ID_CLOCKFORMATS_D 152 53 | #define IDS_ALIGN_RIGHT 152 54 | #define ID_CLOCKFORMATS_YEARWITHOUTCENTURY0 153 55 | #define ID_CLOCKFORMATS_YEARWITHOUTCENTURY 154 56 | #define ID_CLOCKFORMATS_YEARWITHCENTURY0 155 57 | #define ID_CLOCKFORMATS_YEARWITHCENTURY 156 58 | #define ID_CLOCKFORMATS_YEARDAY0 157 59 | #define ID_CLOCKFORMATS_YEARDAY 158 60 | #define ID_CLOCKFORMATS_WEEKOFYEAR_SUNDAY0 159 61 | #define ID_CLOCKFORMATS_WEEKOFYEAR_SUNDAY 160 62 | #define ID_CLOCKFORMATS_WEEKOFYEAR_MONDAY0 161 63 | #define ID_CLOCKFORMATS_WEEKOFYEAR_MONDAY 162 64 | #define ID_CLOCKFORMATS_TZ 163 65 | #define ID_CLOCKFORMATS_PERCENTSIGN 164 66 | #define ID_CAL_SHOWWEEKNUMS 170 67 | #define ID_CAL_SAVELASTPOS 171 68 | #define ID_CAL_SAVELASTSIZE 172 69 | #define ID_CAL_SELECTFONT 173 70 | #define ID_CLOCKFORMATS_LINESEPARATOR 174 71 | #define ID_CLOCKFORMATS_24MMSS 176 72 | #define ID_CLOCKFORMATS_12MMSS 177 73 | #define ID_CLOCKFORMATS_12MMAMPM 179 74 | #define ID_CLOCKFORMATS_DAYDMMM 181 75 | #define ID_CLOCKFORMATS_DAYMMMMDYYYY 182 76 | #define ID_CLOCKFORMATS_MDYYYY 183 77 | #define ID_CLOCKFORMATS_YYYYMMDD 184 78 | #define IDI_ABOUT 185 79 | #define IDS_HELP_FILE 203 80 | #define IDC_FONT 1001 81 | #define IDC_FORMAT 1002 82 | #define ID_PRODUCTS 1003 83 | #define IDC_SAMPLE 1003 84 | #define IDC_COLOR_TEXT_SWATCH 1005 85 | #define IDC_COLOR_BG_SWATCH 1006 86 | #define IDC_DEFAULT 1007 87 | #define ID_ABOUT 1008 88 | #define IDC_ALIGNMENT 1008 89 | #define ID_MYHELP 1009 90 | #define ID_CAL_SHOW_TODAY 1010 91 | #define IDC_TRANSPARENT_BG 1010 92 | #define IDC_FORMATS 1011 93 | #define ID_CLOCK_ADJUSTDATETIME 1012 94 | #define ID_DATE_WEEKOFYEARWITHSUNDAYASFIRSTDAYOFWEEK 1013 95 | #define ID_DATE_WEEKOFYEARWITHSUNDAYASFIRSTDAYOFWEEK1014 1014 96 | #define ID_CLOCKFORMATS_WEEKOFYEAR_SUNDAY00 1015 97 | #define ID_CLOCKFORMATS_WEEKOFYEAR_SUNDAY1 1016 98 | #define ID_CLOCKFORMATS_WEEKOFYEAR_SUNDAY01 1017 99 | #define ID_DATE_WEEKOFYEARWITHMONDAYASFIRSTDAYOFWEEK 1018 100 | #define ID_DATE_WEEKOFYEARWITHMONDAYASFIRSTDAYOFWEEK1019 1019 101 | #define ID_CLOCKFORMATS_WEEKOFYEAR_MONDAY00 1020 102 | #define ID_CLOCKFORMATS_WEEKOFYEAR_MONDAY01 1021 103 | #define ID_CLOCKFORMATS_WEEKOFYEAR_MONDAY1 1022 104 | 105 | // Next default values for new objects 106 | // 107 | #ifdef APSTUDIO_INVOKED 108 | #ifndef APSTUDIO_READONLY_SYMBOLS 109 | #define _APS_NEXT_RESOURCE_VALUE 186 110 | #define _APS_NEXT_COMMAND_VALUE 1023 111 | #define _APS_NEXT_CONTROL_VALUE 1013 112 | #define _APS_NEXT_SYMED_VALUE 101 113 | #endif 114 | #endif 115 | -------------------------------------------------------------------------------- /COMToys/TraceWin3.h: -------------------------------------------------------------------------------- 1 | //////////////////////////////////////////////////////////////// 2 | // TraceWin Copyright 1995-1999 Paul DiLascia 3 | // If this program works, it was written by Paul DiLascia. 4 | // If not, I don't know who wrote it. 5 | // 6 | // NOTE: If you're using PixieLib, you don't need to include this file. 7 | // It's already included by the library. 8 | // 9 | // *************************************************************************** 10 | // TraceWin is a tool that displays MFC diagnostic (afxDump, TRACE) output 11 | // in the window of the TraceWin applet. 12 | // 13 | // To use TraceWin, you must #include this file somewhere in your main program 14 | // file (typically where you implement your CWinApp). Since this file contains 15 | // code, you should #include it in only once--i.e. NOT in StdAfx.h--or you'll 16 | // get multiply-defined symbol errors in the linker. This file contains an 17 | // auto-initializing static variable that works in most cases; but you may miss 18 | // some TRACE output from constructors of static objects. If so, you can 19 | // manually call PxlTraceInit before your first TRACE call. 20 | // 21 | // To see the output, you also need the TraceWin applet, TraceWin.exe, which 22 | // you can download http://pobox.com/~dilascia 23 | // 24 | // *************************************************************************** 25 | // 26 | #ifdef _DEBUG 27 | 28 | // Window class name used by the main window of the TRACEWIN applet. 29 | #define TRACEWND_CLASSNAME _T("TraceWin TRACE Window") 30 | #define OLDTRACEWND_CLASSNAME _T("MfxTraceWindow") // backwards compat 31 | 32 | // ID sent as COPYDATASRUCT::dwData to identify the WM_COPYDATA message 33 | // as coming from an app using TraceWin. 34 | #define ID_COPYDATA_TRACEMSG MAKELONG(MAKEWORD('t','w'),MAKEWORD('i','n')) 35 | 36 | ////////////////// 37 | // CFileTrace is a CFile that "writes" to the trace window 38 | // 39 | class CFileTrace : public CFile { 40 | DECLARE_DYNAMIC(CFileTrace) 41 | CFileTrace() { m_strFileName = _T("Mfx File Tracer"); } 42 | static BOOL autoInit; 43 | virtual void Write(const void* lpBuf, UINT nCount); 44 | public: 45 | static BOOL Init(); 46 | }; 47 | IMPLEMENT_DYNAMIC(CFileTrace, CFile) 48 | 49 | ////////////////// 50 | // Override to write to TraceWin applet instead of file. 51 | // 52 | void CFileTrace::Write(const void* lpBuf, UINT nCount) 53 | { 54 | if (!afxTraceEnabled) 55 | return; // MFC tracing not enabled 56 | 57 | HWND hTraceWnd = ::FindWindow(TRACEWND_CLASSNAME, NULL); 58 | if (hTraceWnd==NULL) 59 | hTraceWnd = ::FindWindow(OLDTRACEWND_CLASSNAME, NULL); 60 | if (hTraceWnd) { 61 | // Found Trace window: send string with WM_COPYDATA 62 | // Must copy to make me the owner of the string; otherwise 63 | // barfs when called from MFC with traceMultiApp on 64 | // 65 | static char mybuf[1024]; 66 | 67 | #ifdef _UNICODE 68 | BOOL bDefCharUsed; 69 | ::WideCharToMultiByte(CP_ACP,0,LPCWSTR(lpBuf), 70 | -1, mybuf, 1024, NULL, &bDefCharUsed); 71 | #else 72 | memcpy(mybuf, lpBuf, nCount); 73 | #endif 74 | 75 | COPYDATASTRUCT cds; 76 | cds.dwData = ID_COPYDATA_TRACEMSG; 77 | cds.cbData = nCount; 78 | cds.lpData = mybuf; 79 | CWinApp* pApp = AfxGetApp(); 80 | HWND hWnd = pApp ? pApp->m_pMainWnd->GetSafeHwnd() : NULL; 81 | ::SendMessage(hTraceWnd, WM_COPYDATA, (WPARAM)hWnd, (LPARAM)&cds); 82 | } 83 | // Also do normal debug thing 84 | ::OutputDebugString((LPCTSTR)lpBuf); 85 | } 86 | 87 | ///////////////// 88 | // Initialize tracing. Replace global afxDump.m_pFile with CFileTrace object. 89 | // In VC 5.0, you shouldn't need to call this, since it's called from an 90 | // auto-initializing static object autoInit below. But if you don't see 91 | // any TRACE output in the TraceWin window, you should try calling 92 | // PxlTraceInit any time before your first TRACE message. 93 | // 94 | BOOL CFileTrace::Init() 95 | { 96 | if (afxDump.m_pFile==NULL) { 97 | // Initialize tracing: replace afxDump.m_pFile w/my own CFile object 98 | // 99 | // It's important to allocate with "new" here, not a static object, 100 | // because CFileTrace is virtual--i.e., called through a pointer in 101 | // the object's vtbl--and the compiler will zero out the virtual 102 | // function table with a NOP function when a static object 103 | // goes out of scope. But I want my CFileTrace to stay around to 104 | // display memory leak diagnostics even after all static objects 105 | // have been destructed. So I allocate the object with new and 106 | // never delete it. I don't want this allocation to itself generate 107 | // a reported memory leak, so I turn off memory tracking before I 108 | // allocate, then on again after. 109 | // 110 | BOOL bEnable = AfxEnableMemoryTracking(FALSE); 111 | afxDump.m_pFile = new CFileTrace; 112 | AfxEnableMemoryTracking(bEnable); 113 | return TRUE; 114 | } 115 | return FALSE; 116 | } 117 | 118 | ////////////////// 119 | // This object does nothing but call CFileTrace::Init, so all you have to 120 | // do is #include this file. Because afxDump is defined in a module with 121 | // 122 | // #pragma init_seg(lib) 123 | // 124 | // afxDump gets initialized before the "user" segment which is where your 125 | // app (and autoInit) is by default. If you need to use init_seg(lib), 126 | // or you have other objects whose constructors call TRACE that get 127 | // initialized before CFileTrace::bInitialized, you will have to call 128 | // CFileTrace::Init yourself, before your first TRACE statement. 129 | // 130 | BOOL CFileTrace::autoInit = CFileTrace::Init(); 131 | 132 | // This symbol defined so you can call it and have it 133 | // compile to nothing in non-debug build 134 | #define PxlTraceInit() CFileTrace::Init(); 135 | 136 | #else 137 | 138 | #define PxlTraceInit() 139 | 140 | #endif // _DEBUG 141 | -------------------------------------------------------------------------------- /Shared/Aboutdlg.cpp: -------------------------------------------------------------------------------- 1 | //--------------------------------------------------------------------------- 2 | // (c) 2002 12noon, Stefan K. S. Tucker. 3 | // (c) 1996-2002 Perpetual Motion Software, Stefan K. S. Tucker. 4 | // All Rights Reserved 5 | //--------------------------------------------------------------------------- 6 | 7 | #include "stdafx.h" 8 | #include 9 | 10 | #include "Shared/VersionInfo.h" 11 | 12 | #include "aboutdlg.h" 13 | 14 | //--------------------------------------------------------------------------- 15 | /* 16 | This routine displays a PMS Standard About box. 17 | 18 | hAppInst - application instance handle 19 | hWnd - parent window handle 20 | lpIconName - icon (name of result of MAKEINTRESOURCE()) 21 | lpszString - A pointer to the name of the registered user. 22 | An empty string displays "EVALUATION COPY". 23 | Or a normal string. (See flag below.) 24 | NULL displays nothing (and ignores the below flag). 25 | bRegString - a flag indicating if the string is to be treated as 26 | a registration string (name or EVALUATION COPY) (TRUE) or 27 | as a "normal" string (displayed verbatim) (FALSE). 28 | */ 29 | //--------------------------------------------------------------------------- 30 | void PMS::PMSAbout(HINSTANCE hAppInst, 31 | HWND hParent, 32 | LPCTSTR lpIconName, 33 | LPCTSTR szString, 34 | BOOL bRegString) 35 | { 36 | if (hAppInst == nullptr) 37 | { 38 | TRACE("PMSAbout(): The application instance handle cannot be NULL.\n"); 39 | ::MessageBeep(MB_ICONEXCLAMATION); 40 | } 41 | else 42 | { 43 | CWnd *pcWnd = CWnd::FromHandle(hParent); 44 | 45 | if (szString == nullptr) 46 | bRegString = FALSE; 47 | 48 | CAboutDlg(hAppInst, pcWnd, lpIconName, szString, bRegString).DoModal(); 49 | } 50 | } 51 | 52 | ///////////////////////////////////////////////////////////////////////////// 53 | // CAboutDlg dialog 54 | 55 | CAboutDlg::CAboutDlg(HINSTANCE hAppInst, 56 | CWnd *pParent, 57 | LPCTSTR lpIconName, 58 | const CString& cReg, 59 | BOOL bRegString) : 60 | CDialog(CAboutDlg::IDD, pParent), 61 | m_web(IDC_FINGER), 62 | m_mailto(IDC_FINGER) 63 | { 64 | m_hAppInst = hAppInst; 65 | m_sIcon = lpIconName; 66 | 67 | //--------------------------------------------------------------- 68 | // determine what string to display at the bottom of the dlg box 69 | //--------------------------------------------------------------- 70 | if (cReg.IsEmpty()) 71 | m_cExtraString = "EVALUATION COPY"; 72 | else if (!bRegString) 73 | m_cExtraString = cReg; 74 | else 75 | m_cExtraString = CString("Registered to ") + cReg; 76 | 77 | //{{AFX_DATA_INIT(CAboutDlg) 78 | // NOTE: the ClassWizard will add member initialization here 79 | //}}AFX_DATA_INIT 80 | } 81 | 82 | void CAboutDlg::DoDataExchange(CDataExchange* pDX) 83 | { 84 | CDialog::DoDataExchange(pDX); 85 | //{{AFX_DATA_MAP(CAboutDlg) 86 | // NOTE: the ClassWizard will add DDX and DDV calls here 87 | //}}AFX_DATA_MAP 88 | } 89 | 90 | BEGIN_MESSAGE_MAP(CAboutDlg, CDialog) 91 | //{{AFX_MSG_MAP(CAboutDlg) 92 | ON_WM_PAINT() 93 | //}}AFX_MSG_MAP 94 | END_MESSAGE_MAP() 95 | 96 | ///////////////////////////////////////////////////////////////////////////// 97 | // CAboutDlg message handlers 98 | 99 | BOOL CAboutDlg::OnInitDialog() 100 | { 101 | CenterWindow(); 102 | 103 | /* 104 | setup URL controls 105 | */ 106 | m_web.SetErrorID(IDP_ERR_LAUNCH_BROWSER1); 107 | m_mailto.SetErrorID(IDP_ERR_LAUNCH_BROWSER1); 108 | 109 | // we load the bmp ourselves because it's 24-bit color 110 | CBitmap bmp; 111 | bmp.LoadBitmap(IDB_12NOON); // IDB_PMS (24-color) 112 | BITMAP bmInfo; 113 | bmp.GetObject(sizeof bmInfo, &bmInfo); 114 | 115 | // m_ilLogo.Create(bmInfo.bmWidth, bmInfo.bmHeight, ILC_COLOR24 | ILC_MASK, 1 /*initial*/, 1 /*grow*/); 116 | m_ilLogo.Create(bmInfo.bmWidth, bmInfo.bmHeight, ILC_COLOR | ILC_MASK, 1 /*initial*/, 1 /*grow*/); 117 | m_ilLogo.Add(&bmp, RGB(0xff, 0xff, 0xff) /*white is transparent*/); 118 | 119 | // setup links 120 | m_web.SubclassDlgItem(IDC_URL_WEB, this); 121 | m_web.SetWindowText(CString(MAKEINTRESOURCE(PMS_IDS_WEB_SITE))); 122 | m_web.SetURL(PMS_IDS_WEB_PMS); 123 | 124 | m_mailto.SubclassDlgItem(IDC_URL_MAILTO, this); 125 | m_mailto.SetWindowText(CString(MAKEINTRESOURCE(PMS_IDS_MAILTO_PMS))); 126 | 127 | // 128 | SetDlgItemText(IDC_PMS_EXTRASTRING, m_cExtraString); 129 | 130 | // load version info 131 | skst::VersionInfo cVer(m_hAppInst); 132 | 133 | GetDlgItem(IDC_PMS_PRODNAME)->SetWindowText(cVer.GetProductName().c_str()); 134 | GetDlgItem(IDC_PMS_VERSION)->SetWindowText(cVer.GetProductVersion().c_str()); 135 | GetDlgItem(IDC_PMS_COMPANY)->SetWindowText(cVer.GetCompanyName().c_str()); 136 | GetDlgItem(IDC_PMS_COPYRIGHT)->SetWindowText(cVer.GetCopyright().c_str()); 137 | 138 | // set the About box icon 139 | ASSERT(m_sIcon != nullptr); 140 | HICON hIcon = ::LoadIcon(m_hAppInst, m_sIcon); 141 | if (hIcon != nullptr) 142 | { 143 | ASSERT(GetDlgItem(IDC_PMS_APPICON) != nullptr); 144 | ((CStatic *) GetDlgItem(IDC_PMS_APPICON))->SetIcon(hIcon); 145 | DestroyIcon(hIcon); 146 | } 147 | 148 | return CDialog::OnInitDialog(); 149 | } 150 | 151 | 152 | void CAboutDlg::OnPaint() 153 | { 154 | CPaintDC dc(this); // device context for painting 155 | 156 | // get top-left coord from frame control 157 | // (we can't destroy it afterwards because we need it every time, so the control is invisible) 158 | CRect rect; 159 | CWnd *pLocation = GetDlgItem(IDC_BITMAP); 160 | ASSERT(!pLocation->IsWindowVisible()); 161 | pLocation->GetClientRect(rect); 162 | pLocation->MapWindowPoints(this, rect); 163 | 164 | m_ilLogo.Draw(&dc, 0 /*index*/, rect.TopLeft(), ILD_TRANSPARENT); 165 | 166 | // Do not call CDialog::OnPaint() for painting messages 167 | } 168 | 169 | -------------------------------------------------------------------------------- /Shared/StaticColor.cpp: -------------------------------------------------------------------------------- 1 | //--------------------------------------------------------------------------- 2 | // (c) 2006 Stefan K. S. Tucker, 12noon 3 | //--------------------------------------------------------------------------- 4 | 5 | #pragma once 6 | 7 | #include "stdafx.h" 8 | 9 | #include "Shared/Graphics_MyWin.h" 10 | 11 | /* 12 | Without the Alternate method, calling SetFont() draws the text (in the 13 | modified font) OVER the "old" text--without erasing the background. 14 | The Alternate method erases the bg, but at the cost of some flicker. 15 | And, apparently, by screwing up the existing background and even(!!) 16 | the border of Edit controls?! (Not fixed by doing Invalidate(FALSE).) 17 | 18 | These changes are the Alternate method: 19 | 20 | StaticColor::SetWindowText 21 | { 22 | ... 23 | 24 | Invalidate(); // w/o this, new text overlaps old text 25 | CStatic::SetWindowText(sz); 26 | } 27 | 28 | 29 | / 30 | We have to do this for those cases where something occurs 31 | that requires the background to be erased, but doesn't change 32 | the text (via SetWindowText()) such as WM_SETFONT. 33 | / 34 | 35 | BOOL StaticColor::OnEraseBkgnd(CDC* pDC) 36 | { 37 | if (_eBgColor == COLOR_TRANSPARENT) 38 | { 39 | DrawParentBackground(); 40 | GetParent()->UpdateWindow(); // we have to do this after DrawParentBackground() or there's an infinite loop of WM_ERASEBKGNDs 41 | // BUT it causes a small flicker 42 | return TRUE; 43 | } 44 | 45 | return CStatic::OnEraseBkgnd(pDC); 46 | } 47 | */ 48 | 49 | #include "StaticColor.h" 50 | 51 | BEGIN_MESSAGE_MAP(MyMFC::StaticColor, CStatic) 52 | ON_WM_CTLCOLOR_REFLECT() 53 | END_MESSAGE_MAP() 54 | 55 | 56 | COLORREF MyMFC::StaticColor::GetTextColorDefault() 57 | { 58 | DWORD dwColor = ::GetSysColor(COLOR_BTNTEXT); 59 | return RGB(MyGetRValue(dwColor), MyGetGValue(dwColor), MyGetBValue(dwColor)); 60 | } 61 | 62 | 63 | void MyMFC::StaticColor::SetTextColorDefault() 64 | { 65 | _bTextColorSet = false; 66 | Invalidate(FALSE); 67 | } 68 | 69 | void MyMFC::StaticColor::SetTextColor(const COLORREF rgb) 70 | { 71 | _bTextColorSet = true; 72 | _rgbText = rgb; 73 | Invalidate(FALSE); 74 | } 75 | 76 | 77 | void MyMFC::StaticColor::SetBgColorDefault() 78 | { 79 | _brushBG.DeleteObject(); 80 | 81 | _eBgColor = EColor::COLOR_DEFAULT; 82 | 83 | Invalidate(FALSE); 84 | } 85 | 86 | /* 87 | Of course, setting the bg to transparent means 88 | that we need to draw the background ourselves. 89 | (If the background is not redrawn, the 90 | text simply overwrites any previous text.) 91 | */ 92 | void MyMFC::StaticColor::SetBgColorTransparent() 93 | { 94 | _brushBG.DeleteObject(); 95 | 96 | _eBgColor = EColor::COLOR_TRANSPARENT; 97 | _brushBG.CreateStockObject(NULL_BRUSH); 98 | 99 | DrawParentBackground(); 100 | } 101 | 102 | void MyMFC::StaticColor::SetBgColor(const int ixSysColor) 103 | { 104 | SetBgColor(::GetSysColor(ixSysColor)); 105 | } 106 | 107 | void MyMFC::StaticColor::SetBgColor(const COLORREF rgb) 108 | { 109 | _brushBG.DeleteObject(); 110 | 111 | _eBgColor = EColor::COLOR_SET; 112 | _brushBG.CreateSolidBrush(rgb); 113 | 114 | Invalidate(FALSE); 115 | } 116 | 117 | 118 | /* 119 | In order to set the text in a transparent control, we have to 120 | invalidate the part of the parent that contains this control 121 | (to make the parent draw its background again). 122 | 123 | We have to do this because our WM_CTLCONTROL handler returns 124 | a null (transparent) brush, which causes Windows to not 125 | paint the background. 126 | 127 | N.B.: This makes transparent backgrouccnds inappropriate for 128 | controls that frequently update their text. 129 | */ 130 | void MyMFC::StaticColor::SetWindowText(LPCTSTR sz) 131 | { 132 | // if the bg is NOT transparent, just set the text normally 133 | if (_eBgColor != EColor::COLOR_TRANSPARENT) 134 | { 135 | CStatic::SetWindowText(sz); 136 | return; 137 | } 138 | 139 | /* 140 | We turn redraw off and then on so that the new text is 141 | not momentarily displayed as overwriting the old text. 142 | */ 143 | SetRedraw(FALSE); 144 | CStatic::SetWindowText(sz); 145 | SetRedraw(TRUE); 146 | DrawParentBackground(); 147 | } 148 | 149 | 150 | /* 151 | Have to "override" (it's not virtual) this function so that we can erase 152 | the background if it's transparent. We've tried working with 153 | WM_ERASEBKGND, but it flickers too much. 154 | */ 155 | void MyMFC::StaticColor::SetFont(CFont *pFont, BOOL bRedraw) 156 | { 157 | CStatic::SetFont(pFont, bRedraw); 158 | DrawParentBackground(); 159 | } 160 | 161 | 162 | /* 163 | We need to do this when we switch to a transparent background. 164 | That's because a transparent background draws *nothing* so we 165 | have to tell the parent to draw *its* background (which is 166 | really *our* background). Got it? 167 | */ 168 | void MyMFC::StaticColor::DrawParentBackground() 169 | { 170 | /* 171 | Convert this window's client coords to the coord system 172 | of the parent and tell the parent to repaint that area. 173 | */ 174 | CRect r; 175 | GetClientRect(r); 176 | ASSERT(GetParent() != nullptr); 177 | MapWindowPoints(GetParent(), r); 178 | GetParent()->InvalidateRect(r, TRUE); // needs to be TRUE to trigger WM_ERASEBKGND, which might be where the parent draws its bg 179 | } 180 | 181 | 182 | 183 | ///////////////////////////////////////////////////////////////////////////// 184 | // StaticColor message handlers 185 | 186 | HBRUSH MyMFC::StaticColor::CtlColor(CDC* pDC, UINT nCtlColor) 187 | { 188 | if (nCtlColor != CTLCOLOR_STATIC) 189 | return HBRUSH(FALSE); // parent handles this msg 190 | 191 | /* 192 | N.B.: If the bg color IS default, we STILL have to return SOMETHING 193 | so that we handle the msg (else text color is ignored). 194 | */ 195 | HBRUSH hBrush; 196 | if (_eBgColor == EColor::COLOR_DEFAULT) 197 | hBrush = (HBRUSH) Default(); // can't call CStatic::OnCtlColor (recursive) 198 | else 199 | hBrush = _brushBG; 200 | 201 | pDC->SetBkMode(TRANSPARENT); 202 | 203 | if (_bTextColorSet) 204 | pDC->SetTextColor(_rgbText); 205 | 206 | return hBrush; 207 | } 208 | -------------------------------------------------------------------------------- /Shared/MyLog.cpp: -------------------------------------------------------------------------------- 1 | //--------------------------------------------------------------------------- 2 | // (c) 2002-2009 12noon, Stefan K. S. Tucker 3 | // (c) 2000-2002 Perpetual Motion Software, Stefan K. S. Tucker 4 | //--------------------------------------------------------------------------- 5 | 6 | #include "stdafx.h" 7 | 8 | #include "skstutil.h" 9 | #include "skstTools.h" 10 | #include "internal.h" 11 | #include "mylog.h" 12 | #include "misc.h" 13 | 14 | using skst::MyLog; 15 | using skst::CriticalSection; 16 | 17 | // storage for static data members 18 | bool MyLog::_bStarted = false; 19 | MyLog MyLog::_log; 20 | tstring MyLog::_strLogFile; 21 | 22 | int skst::LogInOut::_iLevel = 0; 23 | 24 | #if defined(_DEBUG) 25 | bool MyLog::_bLogEnabled = true; // default to logging if Debug 26 | #else 27 | bool MyLog::_bLogEnabled = false; // default to no logging if Release 28 | #endif 29 | 30 | 31 | void MyLog::SetLogFilePath(LPCTSTR szLogFilePath) 32 | { 33 | if (_strLogFile.empty()) 34 | { 35 | _strLogFile = szLogFilePath; 36 | ::OutputDebugString(skst::MyFormatV(_T("Log file: %s\n"), _strLogFile.c_str()).c_str()); 37 | } 38 | else 39 | ::OutputDebugString(skst::MyFormatV(_T("Warning: log file path already set to %s.\n\tNot setting it to %s.\n"), _strLogFile.c_str(), szLogFilePath).c_str()); 40 | } 41 | 42 | 43 | void MyLog::Construct() 44 | { 45 | _bStarted = true; 46 | 47 | /* 48 | If the log file name hasn't been set yet, save it with the executable. 49 | */ 50 | SetLogFilePath(skst::GetFileNameWithNewExtension(nullptr, _T(".log")).c_str()); 51 | 52 | /* 53 | If we're logging in a Release build, delete the previous log file. 54 | */ 55 | #if !defined(_DEBUG) 56 | // Leave any pre-existing log file if logging isn't turned on 57 | if (_bLogEnabled) 58 | Erase(); // delete log file 59 | #endif 60 | 61 | //------------------ 62 | // log startup info 63 | //------------------ 64 | ::OutputDebugString(skst::MyFormatV(_T("\nLogging to %s\n"), _strLogFile.c_str()).c_str()); 65 | 66 | LogV(_T("*** Executable: %s"), skst::GetAppPath(nullptr).c_str()); 67 | 68 | // date/time created 69 | /* 70 | Get formatted creation date/time string. 71 | Same as: 72 | 73 | CFileStatus fs; 74 | if (CFile::GetStatus(::GetAppPath(), fs)) 75 | { 76 | return COleDateTime(fs.m_mtime.GetTime()).Format(); 77 | } 78 | */ 79 | WIN32_FIND_DATA tData; 80 | if (::FindFirstFile(skst::GetAppPath(nullptr).c_str(), &tData) != INVALID_HANDLE_VALUE) 81 | { 82 | skst::MyTime dt(tData.ftCreationTime); 83 | LogV(_T("\tCreated: %s"), dt.Format().c_str()); 84 | dt = tData.ftLastWriteTime; 85 | LogV(_T("\tModified: %s"), dt.Format().c_str()); 86 | } 87 | 88 | //skst::TraceVersions(); 89 | 90 | /* 91 | Display language information 92 | */ 93 | // BUG: "%#04lx" outputs "0x409" NOT "0x0409" 94 | //Not in Windows NT4 95 | // LogV(_T("System default UI language = 0x%04lx"), ::GetSystemDefaultUILanguage()); 96 | // LogV(_T("User default UI language = 0x%04lx"), ::GetUserDefaultUILanguage()); 97 | LogV(_T("System default UI language = 0x%04lx"), ::GetSystemDefaultUILanguage()); 98 | LogV(_T("User default UI language = 0x%04lx"), ::GetUserDefaultUILanguage()); 99 | } 100 | 101 | 102 | MyLog::~MyLog() 103 | { 104 | if (_strLogFile.empty()) 105 | return; 106 | 107 | // can't Log anything from here 108 | } 109 | 110 | 111 | void MyLog::Erase() const 112 | { 113 | Recycle bin; 114 | if (bin.RecycleFile(_strLogFile.c_str())) 115 | { 116 | ::OutputDebugString(skst::MyFormatV(_T("Error recycling file: %s. Trying to delete...\n"), _strLogFile.c_str()).c_str()); 117 | if (!::DeleteFile(_strLogFile.c_str())) 118 | ::OutputDebugString(skst::MyFormatV(_T("Error deleting file: %s\n"), _strLogFile.c_str()).c_str()); 119 | } 120 | } 121 | 122 | 123 | /* 124 | The Log*() functions add a newline to the end and output the 125 | formatted string to both OutputDebugString() and the log file. 126 | */ 127 | void 128 | MyLog::LogV(LPCTSTR szFormat, ...) 129 | { 130 | if (!_bLogEnabled) 131 | return; 132 | 133 | va_list argList; 134 | va_start(argList, szFormat); 135 | const tstring strFormatted(::_MyFormatArgList(szFormat, argList)); 136 | va_end(argList); 137 | 138 | Log(strFormatted.c_str()); 139 | } 140 | 141 | void 142 | MyLog::Log(LPCTSTR s) 143 | { 144 | if (!_bLogEnabled) 145 | return; 146 | 147 | const tstring msg(skst::MyFormatV(_T("[%s] %s\r\n"), skst::MyTime().Format().c_str(), s)); 148 | ::OutputDebugString(msg.c_str()); 149 | Append(msg.c_str()); 150 | } 151 | 152 | 153 | void 154 | MyLog::Append(LPCTSTR s) 155 | { 156 | _cs.Lock(); 157 | 158 | try 159 | { 160 | OpenForAppend(); 161 | 162 | const DWORD dwBytes = (DWORD)_tcslen(s) * sizeof TCHAR; 163 | DWORD dwBytesWritten; 164 | ::WriteFile(_hFile, s, dwBytes, &dwBytesWritten, nullptr); 165 | if (dwBytesWritten != dwBytes) 166 | ::OutputDebugString(skst::MyFormatV(_T("Error writing %ld bytes (only wrote %ld).\n"), dwBytes, dwBytesWritten).c_str()); 167 | 168 | ::CloseHandle(_hFile); 169 | _hFile = INVALID_HANDLE_VALUE; 170 | } 171 | catch (...) 172 | { 173 | ::OutputDebugString(skst::MyFormatV(_T("LOG ERROR: %s\n"), s).c_str()); 174 | } 175 | 176 | _cs.Unlock(); 177 | } 178 | 179 | 180 | // TODO: fix MyLog::DumpStack() issue 181 | /* 182 | void 183 | MyLog::DumpStack() 184 | { 185 | #if defined(_DEBUG) 186 | m_cs.Lock(); 187 | 188 | CFile *p = NULL; 189 | try 190 | { 191 | OpenForAppend(); 192 | 193 | p = afxDump.m_pFile; 194 | afxDump.m_pFile = this; 195 | 196 | ::AfxDumpStack(); // to the "redirected" CFile 197 | 198 | // to ::OutputDebugString 199 | ::AfxDumpStack(AFX_STACK_DUMP_TARGET_ODS); 200 | 201 | Close(); 202 | } 203 | catch (CFileException *px) 204 | { 205 | TCHAR sz[200]; 206 | px->GetErrorMessage(sz, sizeof sz); 207 | TRACE(_T("LOG ERROR: %s\n"), sz); 208 | delete px; 209 | } 210 | catch (...) 211 | { 212 | } 213 | 214 | if (p != NULL) 215 | { 216 | afxDump.m_pFile = p; 217 | p = NULL; 218 | } 219 | 220 | m_cs.Unlock(); 221 | #endif 222 | } 223 | */ 224 | 225 | 226 | void 227 | MyLog::OpenForAppend() 228 | { 229 | // don't open it twice 230 | if (_hFile != INVALID_HANDLE_VALUE) 231 | return; 232 | 233 | _hFile = ::CreateFile(_strLogFile.c_str(), GENERIC_WRITE, FILE_SHARE_READ, nullptr /*sec*/, 234 | OPEN_ALWAYS, 235 | FILE_ATTRIBUTE_NORMAL | FILE_ATTRIBUTE_NOT_CONTENT_INDEXED, nullptr); 236 | if (_hFile == INVALID_HANDLE_VALUE) 237 | { 238 | ::OutputDebugString(skst::MyFormatV(_T("Error opening file: %s\n"), _strLogFile.c_str()).c_str()); 239 | return; 240 | } 241 | 242 | // seek to end 243 | ::SetFilePointer(_hFile, 0, 0, FILE_END); 244 | } 245 | 246 | -------------------------------------------------------------------------------- /Shared/PMSRes.rc: -------------------------------------------------------------------------------- 1 | // Microsoft Visual C++ generated resource script. 2 | // 3 | #include "pmsres.h" 4 | 5 | #define APSTUDIO_READONLY_SYMBOLS 6 | ///////////////////////////////////////////////////////////////////////////// 7 | // 8 | // Generated from the TEXTINCLUDE 2 resource. 9 | // 10 | #define APSTUDIO_HIDDEN_SYMBOLS 11 | #include "windows.h" 12 | #undef APSTUDIO_HIDDEN_SYMBOLS 13 | #include "afxres.h" 14 | #include "pmsres.h" 15 | 16 | ///////////////////////////////////////////////////////////////////////////// 17 | #undef APSTUDIO_READONLY_SYMBOLS 18 | 19 | ///////////////////////////////////////////////////////////////////////////// 20 | // English (United States) resources 21 | 22 | #if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) 23 | LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US 24 | #pragma code_page(1252) 25 | 26 | ///////////////////////////////////////////////////////////////////////////// 27 | // 28 | // Dialog 29 | // 30 | 31 | IDD_PMS_ABOUT DIALOGEX 32, 32, 244, 117 32 | STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU 33 | CAPTION "About" 34 | FONT 8, "MS Sans Serif", 0, 0, 0x0 35 | BEGIN 36 | CONTROL IDC_PMS_EXTRASTRING,IDC_BITMAP,"Static",SS_BITMAP | NOT WS_VISIBLE,184,32,50,46 37 | ICON "",IDC_PMS_APPICON,8,8,20,20 38 | LTEXT "(product name)",IDC_PMS_PRODNAME,40,8,140,8,NOT WS_GROUP 39 | LTEXT "(product version)",IDC_PMS_VERSION,40,16,140,8,NOT WS_GROUP 40 | LTEXT "(company)",IDC_PMS_COMPANY,40,28,140,8,NOT WS_GROUP 41 | LTEXT "(copyright)",IDC_PMS_COPYRIGHT,40,40,140,24,NOT WS_GROUP 42 | LTEXT "(web site)",IDC_URL_WEB,40,68,140,8,NOT WS_GROUP 43 | LTEXT "(mailto)",IDC_URL_MAILTO,40,80,192,8,NOT WS_GROUP 44 | LTEXT "(extra string)",IDC_PMS_EXTRASTRING,40,96,192,16,NOT WS_GROUP 45 | DEFPUSHBUTTON "Close",IDOK,184,8,50,14 46 | END 47 | 48 | ///////////////////////////////////////////////////////////////////////////// 49 | // 50 | // DESIGNINFO 51 | // 52 | 53 | #ifdef APSTUDIO_INVOKED 54 | GUIDELINES DESIGNINFO 55 | BEGIN 56 | IDD_PMS_ABOUT, DIALOG 57 | BEGIN 58 | RIGHTMARGIN, 242 59 | BOTTOMMARGIN, 116 60 | END 61 | END 62 | #endif // APSTUDIO_INVOKED 63 | 64 | 65 | ///////////////////////////////////////////////////////////////////////////// 66 | // 67 | // Bitmap 68 | // 69 | 70 | IDB_12NOON BITMAP "Shared/12noon.bmp" 71 | 72 | #ifdef APSTUDIO_INVOKED 73 | ///////////////////////////////////////////////////////////////////////////// 74 | // 75 | // TEXTINCLUDE 76 | // 77 | 78 | 1 TEXTINCLUDE 79 | BEGIN 80 | "pmsres.h\0" 81 | END 82 | 83 | 2 TEXTINCLUDE 84 | BEGIN 85 | "#define APSTUDIO_HIDDEN_SYMBOLS\r\n" 86 | "#include ""windows.h""\r\n" 87 | "#undef APSTUDIO_HIDDEN_SYMBOLS\r\n" 88 | "#include ""afxres.h""\r\n" 89 | "#include ""pmsres.h""\r\n" 90 | "\0" 91 | END 92 | 93 | 3 TEXTINCLUDE 94 | BEGIN 95 | "\r\n" 96 | "\0" 97 | END 98 | 99 | #endif // APSTUDIO_INVOKED 100 | 101 | 102 | ///////////////////////////////////////////////////////////////////////////// 103 | // 104 | // Cursor 105 | // 106 | 107 | IDC_FINGER CURSOR "Shared/Finger.cur" 108 | 109 | ///////////////////////////////////////////////////////////////////////////// 110 | // 111 | // String Table 112 | // 113 | 114 | STRINGTABLE 115 | BEGIN 116 | IDS_PMS_REGISTER "Please register quality software." 117 | PMS_IDS_COMPANYNAME_KEY "12noon" 118 | IDS_REG_OK "Thank you for registering this application." 119 | IDS_REG_FAIL "That is not a valid registration. You may have mistyped the name or key. You may have used an invalid key or a key for a previous version of the application.\n\nPlease try again, contact your system administrator, or contact 12noon for a new key." 120 | PMS_IDS_WEB_PMS "http://12noon.com" 121 | IDP_ERR_LAUNCH_BROWSER1 "Unable to open the Web site %1. You can open the Web site by typing its address into your browser manually." 122 | PMS_IDS_MAILTO_PMS "mailto:sales@12noon.com" 123 | IDS_BROWSE_REG "Select Registration File" 124 | IDS_FILTERS_REG "Registrations (*.ini)|*.ini|All Files (*.*)|*.*||" 125 | IDS_EXT_REG "ini" 126 | PMS_IDS_WEB_CHECK_UPDATE7 127 | "http://www.12noon.com/cgi-bin/keys/check_version.pl?os=%1&app=%2®=%3!u!&ver=%4!lu!,%5!lu!,%6!lu!,%7!lu!" 128 | PMS_IDP_WEB_NO_CXN "No Internet connection is available. Alarm++ requires an Internet connection in order to check for an update. Please establish an Internet connection and try this command again." 129 | IDS_REG_FAIL_VERSION2 "The registration version (%1) doesn't match the application version (%2).\n\nPlease use the registration information for this version of the application. You may need to contact 12noon for new registration information." 130 | PMS_IDS_WEB_SITE "12noon.com" 131 | END 132 | 133 | STRINGTABLE 134 | BEGIN 135 | IDP_MAIL_NOADDRESS "Unable to open address book. If you use Outlook and only have Contacts, you need to create a Personal Address Book." 136 | END 137 | 138 | STRINGTABLE 139 | BEGIN 140 | IDS_INI_VIEW_SORT_COLIX "SortColumnIndex" 141 | IDS_INI_VIEW_SORT_ASCENDING "SortAscending" 142 | IDS_INI_VIEW_NUM_COLS "NumberColumns" 143 | IDS_INI_VIEW_COL_ORDER1 "ColumnOrder%d" 144 | IDS_INI_VIEW_COL_WIDTH1 "ColumnWidth%d" 145 | IDS_INI_VIEW_COL_ALIGNMENT1 "ColumnAlignment%d" 146 | END 147 | 148 | STRINGTABLE 149 | BEGIN 150 | IDP_HTTP_VER_FAIL "Unable to check the version on 12noon Web site. Please try again later." 151 | IDP_HTTP_VER_LATEST2 "You are running the latest version of %1, which is %2." 152 | IDP_HTTP_VER_OUTOFDATE3 "You are running %1 %2. The latest version of %1 is %3. Would you like to visit the 12noon Web site to upgrade?" 153 | END 154 | 155 | STRINGTABLE 156 | BEGIN 157 | IDS_INI_WNDWPLACEMENT_SECTION "WindowPlacementMain" 158 | IDS_INI_WNDWPLACEMENT_LEN "WindowPlacementLength" 159 | IDS_INI_WNDWPLACEMENT_FGS "WindowPlacementFlags" 160 | IDS_INI_WNDWPLACEMENT_SHOW "WindowPlacementShow" 161 | IDS_INI_WNDWPLACEMENT_MIN_X "WindowPlacementMinX" 162 | IDS_INI_WNDWPLACEMENT_MIN_Y "WindowPlacementMinY" 163 | END 164 | 165 | STRINGTABLE 166 | BEGIN 167 | IDS_INI_WNDWPLACEMENT_MAX_X "WindowPlacementMaxX" 168 | IDS_INI_WNDWPLACEMENT_MAX_Y "WindowPlacementMaxY" 169 | IDS_INI_WNDWPLACEMENT_NORM_L "WindowPlacementNormalLeft" 170 | IDS_INI_WNDWPLACEMENT_NORM_T "WindowPlacementNormalTop" 171 | IDS_INI_WNDWPLACEMENT_NORM_R "WindowPlacementNormalRight" 172 | IDS_INI_WNDWPLACEMENT_NORM_B "WindowPlacementNormalBottom" 173 | END 174 | 175 | #endif // English (United States) resources 176 | ///////////////////////////////////////////////////////////////////////////// 177 | 178 | 179 | 180 | #ifndef APSTUDIO_INVOKED 181 | ///////////////////////////////////////////////////////////////////////////// 182 | // 183 | // Generated from the TEXTINCLUDE 3 resource. 184 | // 185 | 186 | 187 | ///////////////////////////////////////////////////////////////////////////// 188 | #endif // not APSTUDIO_INVOKED 189 | 190 | -------------------------------------------------------------------------------- /Timekeeper.vcxproj.filters: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | {515a72db-a420-4fc6-ac16-b65cf4827d92} 6 | h;hpp;hxx;hm;inl;fi;fd 7 | 8 | 9 | {8f52feaf-c68c-4b83-b9cf-a36cdcbf2484} 10 | ico;cur;bmp;dlg;rc2;rct;bin;cnt;rtf;gif;jpg;jpeg;jpe 11 | 12 | 13 | {cb7c111f-80d9-4bf6-a1cb-e5ee67582065} 14 | 15 | 16 | {0b88357b-1fe3-4fd0-a47b-2efd71a83739} 17 | cpp;c;cxx;rc;def;r;odl;hpj;bat;for;f90 18 | 19 | 20 | {5675780e-2690-4d87-992e-053930a27288} 21 | 22 | 23 | 24 | 25 | Header Files 26 | 27 | 28 | Header Files 29 | 30 | 31 | Header Files 32 | 33 | 34 | Header Files 35 | 36 | 37 | Resource Files 38 | 39 | 40 | Header Files 41 | 42 | 43 | Shared 44 | 45 | 46 | Shared 47 | 48 | 49 | Shared 50 | 51 | 52 | Shared 53 | 54 | 55 | Shared 56 | 57 | 58 | Shared 59 | 60 | 61 | Shared 62 | 63 | 64 | Shared 65 | 66 | 67 | Shared 68 | 69 | 70 | Shared 71 | 72 | 73 | Shared 74 | 75 | 76 | Shared 77 | 78 | 79 | Shared 80 | 81 | 82 | Shared 83 | 84 | 85 | Shared 86 | 87 | 88 | Shared 89 | 90 | 91 | Shared 92 | 93 | 94 | Shared 95 | 96 | 97 | Shared 98 | 99 | 100 | Shared 101 | 102 | 103 | 104 | 105 | Resource Files 106 | 107 | 108 | Resource Files 109 | 110 | 111 | Resource Files 112 | 113 | 114 | Resource Files 115 | 116 | 117 | Resource Files 118 | 119 | 120 | Resource Files 121 | 122 | 123 | Resource Files 124 | 125 | 126 | Help Files 127 | 128 | 129 | Source Files 130 | 131 | 132 | 133 | Shared 134 | 135 | 136 | Source Files 137 | 138 | 139 | Help Files 140 | 141 | 142 | 143 | 144 | Resource Files 145 | 146 | 147 | 148 | 149 | Source Files 150 | 151 | 152 | Source Files 153 | 154 | 155 | Source Files 156 | 157 | 158 | Source Files 159 | 160 | 161 | Shared 162 | 163 | 164 | Shared 165 | 166 | 167 | Shared 168 | 169 | 170 | Shared 171 | 172 | 173 | Shared 174 | 175 | 176 | Shared 177 | 178 | 179 | Shared 180 | 181 | 182 | Shared 183 | 184 | 185 | Shared 186 | 187 | 188 | Shared 189 | 190 | 191 | Shared 192 | 193 | 194 | Shared 195 | 196 | 197 | Shared 198 | 199 | 200 | Shared 201 | 202 | 203 | 204 | 205 | Shared 206 | 207 | 208 | -------------------------------------------------------------------------------- /Shared/skstTools.h: -------------------------------------------------------------------------------- 1 | //--------------------------------------------------------------------------- 2 | // (c) 2010 12noon, Perpetual Motion Software, Stefan K. S. Tucker 3 | //--------------------------------------------------------------------------- 4 | 5 | #pragma once 6 | 7 | #include "misc.h" 8 | #include "mylog.h" 9 | #include "versioninfo.h" 10 | #include "registry.h" 11 | 12 | ///////////////////////////////////////////////////////////////////////////// 13 | // skst Namespace 14 | namespace skst 15 | { 16 | 17 | ///////////////////////////////////////////////////////////////////////////// 18 | // Templates 19 | 20 | /* 21 | Template function to cast data to a smaller 22 | type and ensure we don't lose anything. 23 | */ 24 | template 25 | inline Small size_cast(Big const& b) 26 | { 27 | // Cast into a local, so that the debugger can look at it 28 | const Small s = static_cast(b); 29 | // Check that we don't lose data this way 30 | assert(b == static_cast(s)); 31 | return s; 32 | } 33 | 34 | 35 | /* 36 | from VC6SP4 37 | */ 38 | // TEMPLATE CLASS auto_ptr_array (from auto_ptr) 39 | template 40 | class auto_ptr_array { 41 | public: 42 | typedef _Ty element_type; 43 | explicit auto_ptr_array(_Ty *_P = 0) 44 | : _Owns(_P != 0), _Ptr(_P) {} 45 | auto_ptr_array(const auto_ptr_array<_Ty>& _Y) 46 | : _Owns(_Y._Owns), _Ptr(_Y.release()) {} 47 | auto_ptr_array<_Ty>& operator=(const auto_ptr_array<_Ty>& _Y) 48 | {if (this != &_Y) 49 | {if (_Ptr != _Y.get()) 50 | {if (_Owns) 51 | delete [] _Ptr; // skst 52 | _Owns = _Y._Owns; } 53 | else if (_Y._Owns) 54 | _Owns = true; 55 | _Ptr = _Y.release(); } 56 | return (*this); } 57 | ~auto_ptr_array() 58 | {if (_Owns) 59 | delete [] _Ptr; } // skst 60 | _Ty& operator*() const 61 | {return (*get()); } 62 | #pragma warning(push) 63 | #pragma warning(disable : 4284) 64 | _Ty *operator->() const 65 | {return (get()); } 66 | #pragma warning(pop) 67 | _Ty *get() const 68 | {return (_Ptr); } 69 | _Ty *release() const 70 | {((auto_ptr_array<_Ty> *)this)->_Owns = false; 71 | return (_Ptr); } 72 | 73 | //------------------------ 74 | // my assignment operator 75 | //------------------------ 76 | void operator=(_Ty *p) 77 | { 78 | // free existing ptr 79 | delete [] _Ptr; 80 | 81 | _Ptr = p; 82 | } 83 | 84 | //---------------------------- 85 | // my element access operator 86 | //---------------------------- 87 | _Ty& operator[](int i) 88 | const 89 | { 90 | assert(_Ptr != nullptr); 91 | assert(i >= 0); 92 | 93 | return _Ptr[i]; 94 | } 95 | 96 | private: 97 | bool _Owns; 98 | _Ty *_Ptr; 99 | }; 100 | 101 | ///////////////////////////////////////////////////////////////////////////// 102 | ///////////////////////////////////////////////////////////////////////////// 103 | 104 | /* 105 | This class is used to automatically init/uninit COM. Just declare a 106 | global variable. 107 | 108 | CoInitializeEx() is only included 109 | #if (_WIN32_WINNT >= 0x0400 ) || defined(_WIN32_DCOM) // DCOM 110 | So, we use CoInitialize() instead 111 | */ 112 | class StartCOM 113 | { 114 | public: 115 | StartCOM() 116 | { 117 | ::CoInitialize(nullptr); // aka ::CoInitializeEx(NULL, COINIT_APARTMENTTHREADED); 118 | } 119 | ~StartCOM() 120 | { 121 | ::CoUninitialize(); 122 | } 123 | }; 124 | 125 | ///////////////////////////////////////////////////////////////////////////// 126 | ///////////////////////////////////////////////////////////////////////////// 127 | 128 | /* 129 | This class is used when we want to do something for only a limited time 130 | 131 | const skst::TimeLimit cTimeLimit(250); 132 | while (!cTimeLimit.TimesUp()) 133 | { 134 | // do something 135 | } 136 | */ 137 | 138 | class Timer 139 | { 140 | protected: 141 | DWORD _dwStart; // msecs 142 | DWORD _dwDuration; // # of msecs after which "time's up" 143 | 144 | public: 145 | Timer(const DWORD dwMilliseconds) 146 | { 147 | Restart(dwMilliseconds); 148 | } 149 | virtual ~Timer() {} 150 | 151 | // restart the timer w/new # of msecs 152 | void Restart(const DWORD dwMilliseconds) 153 | { 154 | _dwDuration = dwMilliseconds; 155 | _dwStart = ::GetTickCount(); 156 | } 157 | 158 | // restart the timer 159 | void Restart() 160 | { 161 | _dwStart = ::GetTickCount(); 162 | } 163 | 164 | // has the time expired? 165 | bool TimesUp() const 166 | { 167 | return (::GetTickCount() >= _dwStart + _dwDuration); 168 | } 169 | 170 | // how many msecs have elapsed already? 171 | DWORD Elapsed() const 172 | { 173 | return ::GetTickCount() - _dwStart; 174 | } 175 | }; 176 | 177 | ///////////////////////////////////////////////////////////////////////////// 178 | ///////////////////////////////////////////////////////////////////////////// 179 | 180 | class MyTime 181 | { 182 | protected: 183 | SYSTEMTIME _dt; 184 | 185 | public: 186 | MyTime() 187 | { 188 | ::GetLocalTime(&_dt); 189 | } 190 | 191 | MyTime(const FILETIME& ft) 192 | { 193 | // convert UTC to local time and then to system time 194 | FILETIME ftLocal; 195 | ::FileTimeToLocalFileTime(&ft, &ftLocal); 196 | ::FileTimeToSystemTime(&ftLocal, &_dt); 197 | } 198 | virtual ~MyTime() {} 199 | 200 | tstring Format() const 201 | { 202 | // format date/time 203 | TCHAR szDate[50]; 204 | ::GetDateFormat(LOCALE_USER_DEFAULT, 0, &_dt, _T("ddd dd MMM yyyy"), szDate, sizeof szDate); 205 | 206 | TCHAR szTime[20]; 207 | //This is only used in MyLog, so we can just change it. 208 | // ::GetTimeFormat(LOCALE_USER_DEFAULT, TIME_NOSECONDS, &_dt, _T("hh:mmt"), szTime, sizeof szTime); 209 | ::GetTimeFormat(LOCALE_USER_DEFAULT, 0, &_dt, _T("HH:mm:ss"), szTime, sizeof szTime); 210 | 211 | tstring str(szDate); 212 | str += _T(" "); 213 | str += szTime; 214 | 215 | return str; 216 | } 217 | }; 218 | 219 | ///////////////////////////////////////////////////////////////////////////// 220 | ///////////////////////////////////////////////////////////////////////////// 221 | 222 | /* 223 | Based on the CRecycleFile class MSDNmag April 2001 article 224 | by Paul DiLascia. 225 | 226 | It can delete files and folders -- and send them to the Recycle Bin. 227 | 228 | Suggested use: 229 | Recycle bin; 230 | bin.RecycleFile("c:\\fish\\delme.txt"); // del file 231 | if (bin.RecycleFile("c:\\delme")) // del folder 232 | ; // failed 233 | */ 234 | class Recycle : public SHFILEOPSTRUCT 235 | { 236 | public: 237 | Recycle() 238 | { 239 | pTo = nullptr; 240 | wFunc = FO_DELETE; 241 | // no confirmation means "Yes to All" for all msgs, such as "Too big to fit. Do it anyway?" 242 | fFlags = FOF_ALLOWUNDO | FOF_SILENT | FOF_NOCONFIRMATION | FOF_NOERRORUI; 243 | lpszProgressTitle = nullptr; 244 | fAnyOperationsAborted = FALSE; 245 | hwnd = nullptr; 246 | hNameMappings = nullptr; 247 | } 248 | 249 | virtual ~Recycle() {} 250 | 251 | int RecycleFile(LPCTSTR szFile) 252 | { 253 | TCHAR szDel[_MAX_PATH + 1]; 254 | _tcscpy_s(szDel, _countof(szDel), szFile); 255 | szDel[_tcslen(szDel) + 1] = _T('\0'); 256 | pFrom = szDel; 257 | 258 | skst::MyLog::GetLog().LogV(_T("Recycling %s..."), szDel); 259 | 260 | return ::SHFileOperation(this); // success == 0 261 | } 262 | }; 263 | 264 | ///////////////////////////////////////////////////////////////////////////// 265 | ///////////////////////////////////////////////////////////////////////////// 266 | 267 | } // namespace 268 | -------------------------------------------------------------------------------- /COMToys/src/Fact.cpp: -------------------------------------------------------------------------------- 1 | //////////////////////////////////////////////////////////////// 2 | // ComToys(TM) Copyright 1999 Paul DiLascia 3 | // If this code works, it was written by Paul DiLascia. 4 | // If not, I don't know who wrote it. 5 | // 6 | #include "StdAfx.h" 7 | #include "COMtoys/ComToys.h" 8 | 9 | #ifdef _DEBUG 10 | #define new DEBUG_NEW 11 | #undef THIS_FILE 12 | static char THIS_FILE[] = __FILE__; 13 | #endif 14 | 15 | DEBUG_BEGIN_INTERFACE_NAMES() 16 | DEBUG_INTERFACE_NAME(IClassFactory) 17 | DEBUG_INTERFACE_NAME(IClassFactory2) 18 | DEBUG_END_INTERFACE_NAMES(); 19 | 20 | CPtrList CTFactory::g_lsFactories; // master list 21 | CCriticalSection CTFactory::g_mydata; // lock to protect it 22 | 23 | CTFactory::CTFactory(REFCLSID clsid, UINT nResID, UINT tm) : m_clsid(clsid) 24 | { 25 | CTTRACEFN(_T("CTFactory(%p)::CTFactory (%s)\n"), this, DbgName(clsid)); 26 | ASSERT(TMNONE<=tm && tm<=TMBOTH); 27 | m_nThreadingModel = tm; 28 | m_nIDRes = nResID; 29 | m_bAutoDel = TRUE; 30 | 31 | // add to list of factories, but lock global data first 32 | CTLockData lock(g_mydata); 33 | g_lsFactories.AddHead(this); 34 | } 35 | 36 | ////////////////// 37 | // Destroy: remove myself from global list 38 | // 39 | CTFactory::~CTFactory() 40 | { 41 | CTTRACEFN(_T("CTFactory(%p)::~CTFactory\n"), this); 42 | CTLockData lock(g_mydata); 43 | POSITION pos = g_lsFactories.Find(this); 44 | ASSERT(pos); 45 | g_lsFactories.RemoveAt(pos); 46 | } 47 | 48 | ////////////////// 49 | // Delete all factories in global list 50 | // 51 | void CTFactory::DeleteAll() 52 | { 53 | CTLockData lock(g_mydata); 54 | while (!g_lsFactories.IsEmpty()) { 55 | CTFactory* pf = (CTFactory*)g_lsFactories.GetHead(); 56 | ASSERT(pf); 57 | if (pf->m_bAutoDel) 58 | delete pf; 59 | } 60 | g_lsFactories.RemoveAll(); 61 | } 62 | 63 | ////////////////// 64 | // Get factory from class ID 65 | // 66 | CTFactory* CTFactory::GetFactory(REFCLSID clsid) 67 | { 68 | CTLockData lock(g_mydata); 69 | POSITION pos = g_lsFactories.GetHeadPosition(); 70 | while (pos) { 71 | CTFactory* pf = (CTFactory*)g_lsFactories.GetNext(pos); 72 | if (pf->GetClassID()==clsid) 73 | return pf; 74 | } 75 | return NULL; 76 | } 77 | 78 | ////////////////// 79 | // This is like MFC: registter all the factories 80 | // 81 | BOOL CTFactory::OnRegisterAll(BOOL bRegister) 82 | { 83 | CTLockData lock(g_mydata); 84 | POSITION pos = g_lsFactories.GetHeadPosition(); 85 | while (pos) { 86 | CTFactory* pf = (CTFactory*)g_lsFactories.GetNext(pos); 87 | if (!pf->OnRegister(bRegister)) 88 | return FALSE; 89 | } 90 | return TRUE; 91 | } 92 | 93 | ////////////////// 94 | // Standard registration fn looks for resource registry script 95 | // with same resource ID as the factory 96 | // 97 | BOOL CTFactory::OnRegister(BOOL bRegister) 98 | { 99 | CTTRACEFN(_T("CTFactory(%p)::OnRegister(%d)\n"), this, bRegister); 100 | 101 | static const LPOLESTR RT_REGISTRY = OLESTR("REGISTRY"); 102 | 103 | UINT nID = GetResourceID(); 104 | if (nID==0) 105 | return TRUE; 106 | 107 | HINSTANCE hInst = CTModule::GetModule()->GetInstanceHandle(); 108 | if (!::FindResource(hInst, MAKEINTRESOURCE(nID), CString(RT_REGISTRY))) 109 | return FALSE; 110 | 111 | // initialize registry variables 112 | CTRegistrar iReg; 113 | OnInitRegistryVariables(iReg); 114 | 115 | // register/unregister script 116 | USES_CONVERSION; 117 | CTModuleName modname(hInst); 118 | LPCOLESTR lposModuleName = T2COLE(modname); 119 | HRESULT hr = bRegister ? 120 | iReg->ResourceRegister (lposModuleName, nID, RT_REGISTRY) : 121 | iReg->ResourceUnregister(lposModuleName, nID, RT_REGISTRY); 122 | if (FAILED(hr)) { 123 | TRACE(_T("*** CTMfcFactory: un/register failed: %s\n"), _TR(hr)); 124 | if (bRegister) 125 | return FALSE; 126 | } 127 | 128 | if (bRegister==FALSE) { 129 | // IRegistrar doesn't always delete top-level key right, so delete it 130 | CString sClsid; 131 | sClsid = StringFromCLSID(CTFactory::GetClassID()); 132 | if (!sClsid.IsEmpty()) { // for extra-safety! don't delete CLSID !! 133 | CString sKey; 134 | sKey.Format(_T("CLSID\\%s"), (LPCTSTR)sClsid); 135 | CTDelRegTree(HKEY_CLASSES_ROOT, sKey); 136 | } 137 | } 138 | return TRUE; 139 | } 140 | 141 | ////////////////// 142 | // Initialize standard built-in variables 143 | // 144 | // %CLSID% = class ID (GUID) (COleObjectFactory::m_clsid) 145 | // %MODULE% = full pathname of DLL 146 | // %Title% = title (resource substring 0) 147 | // %ClassName% = human-readable COM class name (resource substring 1) 148 | // %ProgID% = ProgID (resource substring 2) 149 | // %ThreadingModel% = "Apartment", "Free", or "Both" (m_nThreadingModel) 150 | // 151 | // You can override to add your own in addition 152 | // 153 | BOOL CTFactory::OnInitRegistryVariables(IRegistrar* pReg) 154 | { 155 | USES_CONVERSION; 156 | 157 | HINSTANCE hInst = CTModule::GetModule()->GetInstanceHandle(); 158 | VERIFY(pReg->AddReplacement(OLESTR("CLSID"), 159 | StringFromCLSID(CTFactory::GetClassID()))==S_OK); 160 | 161 | VERIFY(pReg->AddReplacement(OLESTR("MODULE"), 162 | T2COLE(CTModuleName(hInst)))==S_OK); 163 | 164 | VERIFY(pReg->AddReplacement(OLESTR("Title"), 165 | T2COLE(GetTitle()))==S_OK); 166 | 167 | VERIFY(pReg->AddReplacement(OLESTR("ClassName"), 168 | T2COLE(GetClassName()))==S_OK); 169 | 170 | VERIFY(pReg->AddReplacement(OLESTR("ProgID"), 171 | T2COLE(GetClassName()))==S_OK); 172 | 173 | // threading model from m_nThreadingModel enum 174 | static LPOLESTR tmstrs[4] = { 175 | OLESTR(""), OLESTR("Apartment"), OLESTR("Free"), OLESTR("Both") }; 176 | VERIFY(pReg->AddReplacement(OLESTR("ThreadingModel"), 177 | tmstrs[m_nThreadingModel])==S_OK); 178 | 179 | return TRUE; 180 | } 181 | 182 | //////////////// following copied from MFC appui2.cpp //////////////// 183 | // Under Win32, a reg key may not be deleted unless it is empty. 184 | // Thus, to delete a tree, one must recursively enumerate and 185 | // delete all of the sub-keys. 186 | // 187 | static LONG AFXAPI DelRegTreeHelper(HKEY hParentKey, const CString& strKeyName) 188 | { 189 | TCHAR szSubKeyName[256]; 190 | HKEY hCurrentKey; 191 | DWORD dwResult; 192 | 193 | if (strKeyName.IsEmpty()) 194 | return ERROR_BADKEY; // safety 195 | 196 | if ((dwResult = RegOpenKey(hParentKey, strKeyName, &hCurrentKey)) == 197 | ERROR_SUCCESS) { 198 | // Remove all subkeys of the key to delete 199 | while ((dwResult = RegEnumKey(hCurrentKey, 0, szSubKeyName, 255)) == 200 | ERROR_SUCCESS) { 201 | if ((dwResult = AfxDelRegTreeHelper(hCurrentKey, szSubKeyName)) != ERROR_SUCCESS) 202 | break; 203 | } 204 | // If all went well, we should now be able to delete the requested key 205 | if ((dwResult == ERROR_NO_MORE_ITEMS) || (dwResult == ERROR_BADKEY)) { 206 | dwResult = RegDeleteKey(hParentKey, strKeyName); 207 | } 208 | } 209 | RegCloseKey(hCurrentKey); 210 | return dwResult; 211 | } 212 | 213 | DLLFUNC LONG CTDelRegTree(HKEY hParentKey, const CString& strKeyName) 214 | { 215 | return DelRegTreeHelper(hParentKey, strKeyName); 216 | } 217 | 218 | 219 | 220 | ///////////////////////////////////////////////////////////////////////////// 221 | // Default implementation for special CTFactory entry points 222 | // For now, CTFactory isn't implemented. This class exists only to have 223 | // a non-MFC IClassFactory some day. 224 | // 225 | STDMETHODIMP CTFactory::CreateInstance(LPUNKNOWN, REFIID, LPVOID*) 226 | { 227 | return E_NOTIMPL; 228 | } 229 | 230 | STDMETHODIMP CTFactory::LockServer(BOOL) 231 | { 232 | return E_NOTIMPL; 233 | } 234 | 235 | STDMETHODIMP CTFactory::GetLicInfo(LPLICINFO) 236 | { 237 | return E_NOTIMPL; 238 | } 239 | 240 | STDMETHODIMP CTFactory::RequestLicKey(DWORD, BSTR*) 241 | { 242 | return E_NOTIMPL; 243 | } 244 | 245 | STDMETHODIMP CTFactory::CreateInstanceLic(LPUNKNOWN, 246 | LPUNKNOWN, REFIID, BSTR, LPVOID*) 247 | { 248 | return E_NOTIMPL; 249 | } 250 | -------------------------------------------------------------------------------- /COMToys/src/MfcMenu.cpp: -------------------------------------------------------------------------------- 1 | //////////////////////////////////////////////////////////////// 2 | // ComToys(TM) Copyright 1999 Paul DiLascia 3 | // If this code works, it was written by Paul DiLascia. 4 | // If not, I don't know who wrote it. 5 | // 6 | #include "StdAfx.h" 7 | #include "COMtoys/ComToys.h" 8 | 9 | #ifdef _DEBUG 10 | #define new DEBUG_NEW 11 | #undef THIS_FILE 12 | static char THIS_FILE[] = __FILE__; 13 | #endif 14 | 15 | DEBUG_BEGIN_INTERFACE_NAMES() 16 | DEBUG_INTERFACE_NAME(IContextMenu) 17 | DEBUG_INTERFACE_NAME(IContextMenu2) 18 | DEBUG_INTERFACE_NAME(IContextMenu3) 19 | DEBUG_END_INTERFACE_NAMES(); 20 | 21 | CTMfcContextMenu::CTMfcContextMenu(CCmdTarget* pTarg, CMenu& menu) 22 | : m_ctxMenu(menu) 23 | { 24 | m_pCmdTarget = pTarg; 25 | m_bMenuSeperator = FALSE; // add separator after appending menu? 26 | m_bAutoMenuEnable = TRUE; // like MFC frame: disable cmds with no handler 27 | } 28 | 29 | ////////////////// 30 | // Get menu string: default is resource string 31 | // 32 | CString CTMfcContextMenu::OnGetMenuString(UINT nID) 33 | { 34 | CString s; 35 | s.LoadString(nID); 36 | return s; 37 | } 38 | 39 | ////////////////// 40 | // Add menu items to client's menu 41 | // 42 | STDMETHODIMP CTMfcContextMenu::QueryContextMenu(HMENU hmenu, UINT index, 43 | UINT idCmdFirst, UINT idCmdLast, UINT uFlags) 44 | { 45 | CTTRACEFN(_T("CTMfcContextMenu::QueryContextMenu(0x%x,i=%d,first=%d,last=%d,flags=0x%x)\n"), 46 | hmenu, index, idCmdFirst, idCmdLast, uFlags); 47 | /* 48 | This occurs if you select everything in My Documents and right-click. 49 | */ 50 | ASSERT(idCmdFirst <= idCmdLast); // If this happens, it's a Windows bug 51 | 52 | /* 53 | The offset is wrong. From the doc: "value set to the OFFSET of the 54 | LARGEST command identifier that was assigned, plus one". 55 | Previously, this code assumed the last id was the largest. 56 | 57 | Mr. Dilascia misunderstood how menu IDs work in this function. 58 | We have to return, basically, the number of menu command IDs 59 | we've consumed--the largest ID minus the smallest ID + 1. 60 | 61 | -skst (26 Dec 2007) 62 | */ 63 | //USHORT uSmallest = 0; 64 | //USHORT uLargest = 0; 65 | UINT nMyNewID = idCmdFirst; 66 | if (m_ctxMenu && !(uFlags & CMF_DEFAULTONLY)) 67 | { 68 | for (int i=0; iGetMenuItemID(0)) == 0 || 118 | state.m_nID == (UINT)-1) { 119 | // first item of popup can't be routed to 120 | } 121 | state.DoUpdate(pTarg, FALSE); // popups are never auto disabled 122 | 123 | } else { 124 | // normal menu item 125 | // Auto enable/disable if 'm_bAutoMenuEnable' 126 | // and command is _not_ a system command. 127 | state.m_pSubMenu = NULL; 128 | state.DoUpdate(pTarg, m_bAutoMenuEnable); 129 | } 130 | } 131 | 132 | ////////////////// 133 | // Invoke a context menu command 134 | // 135 | STDMETHODIMP CTMfcContextMenu::InvokeCommand(LPCMINVOKECOMMANDINFO lpcmi) 136 | { 137 | CTTRACE(_T("CTMfcContextMenu::InvokeCommand\n")); 138 | if (HIWORD(lpcmi->lpVerb)==0) { 139 | // save CMINVOKECOMMANDINFO so caller can use it if needed 140 | // 141 | m_cmi = *lpcmi; 142 | 143 | /* 144 | MSDN IContextmenu::InvokeCommand() documentation: 145 | "The command can be specified by its menu identifier offset ..." 146 | This is not an ID but an offset into the menu. 147 | So we look up the offset we saved in the map. 148 | */ 149 | const UINT idReal = _mapMenuIDs[LOWORD(lpcmi->lpVerb)]; 150 | if (idReal == 0) 151 | return E_FAIL; 152 | 153 | // Simulate WM_COMMAND. MFC will route to appropriate cmd target 154 | // 155 | m_pCmdTarget->OnCmdMsg(idReal, CN_COMMAND, NULL, NULL); 156 | return NOERROR; 157 | } 158 | return E_NOTIMPL; 159 | } 160 | 161 | ////////////////// 162 | // Copy command string or help text into caller's buffer 163 | // 164 | STDMETHODIMP CTMfcContextMenu::GetCommandString(UINT_PTR nID, UINT uFlags, 165 | UINT*, LPSTR pszName, UINT cchMax) 166 | { 167 | CTTRACE(_T("CTMfcContextMenu::GetCommandString(%u, %u)\n"), (const unsigned int) nID, uFlags); 168 | HRESULT hr = E_INVALIDARG; 169 | 170 | ASSERT(m_ctxMenu); 171 | 172 | CString str; 173 | BOOL bCopy = TRUE; // assume I will return the string 174 | // skst: Fix flag comparison--it's a bitmask, not a value 175 | if (uFlags & GCS_HELPTEXT) 176 | { 177 | // get prompt string 178 | const CString sRes(OnGetMenuString((const UINT) nID)); 179 | AfxExtractSubString(str, sRes, 0); 180 | hr = S_OK; // skst: need to say it's ok 181 | CTTRACE(_T("GCS_HELPTEXT: \"%s\"\n"), (LPCTSTR) str); 182 | } 183 | else if ((uFlags & GCS_VERB) || (uFlags & GCS_VALIDATE)) 184 | { 185 | // get menu item itself 186 | if (m_ctxMenu.GetMenuString((const UINT) nID, str, MF_BYCOMMAND)) 187 | { 188 | if (uFlags & GCS_VALIDATE) 189 | { 190 | CTTRACE(_T("GCS_VALIDATE\n")); 191 | // don't copy for GCS_VALIDATE 192 | bCopy = FALSE; 193 | } 194 | hr = S_OK; 195 | CTTRACE(_T("GCS_VERB || GCS_VALIDATE: \"%s\"\n"), (LPCTSTR) str); 196 | } 197 | } 198 | if (bCopy) 199 | { 200 | // skst 201 | /* 202 | "Even though pszName is declared as an LPSTR, you must cast it to UINT_PTR 203 | and return a Unicode string if uFlags is set to either GCS_HELPTEXTW or 204 | GCS_VERBW. GCS_UNICODE can be used as a bitmask to test uFlags for 'W' and 205 | 'A' versions of the flag it contains." 206 | REF: http://msdn.microsoft.com/en-us/library/windows/desktop/bb776094.aspx 207 | */ 208 | /* 209 | Even if we haven't compiled for Unicode, 210 | Windows (XP anyway) can call with the GCS_UNICODE 211 | flag to indicate it wants the string in Unicode. 212 | So we convert the ASCII string we've retrieved. 213 | -skst (21 Oct 2007) 214 | */ 215 | if (uFlags & GCS_UNICODE) 216 | { 217 | const CStringW wstr(str); // convert ASCII string to Unicode 218 | WCHAR *pwsz = (WCHAR*)(UINT_PTR)pszName; 219 | wcsncpy_s(pwsz, cchMax, wstr, cchMax / (sizeof TCHAR)); 220 | } 221 | else 222 | { 223 | const CStringA astr(str); 224 | strncpy_s(pszName, cchMax, astr, cchMax); 225 | } 226 | 227 | pszName[cchMax-1]=0; 228 | } 229 | 230 | return hr; 231 | } 232 | 233 | -------------------------------------------------------------------------------- /Shared/ToolTipCtrl.h: -------------------------------------------------------------------------------- 1 | //--------------------------------------------------------------------------- 2 | // (c) 2006 12noon, Stefan K. S. Tucker 3 | //--------------------------------------------------------------------------- 4 | 5 | #pragma once 6 | 7 | #include 8 | 9 | //TODO: save passed LPCTSTR text in a vector of strings and point TOOLINFO to *that*. 10 | //TODO: allow passing inst/id for text 11 | 12 | /* 13 | There are a number of different ways to use tooltips: 14 | 15 | Static text 16 | The text is hardcoded for the window (or area). 17 | Dynamic text 18 | The text changes every time the tip is displayed. 19 | 20 | If the text is dynamic, the notification messages can be processed 21 | by the same window (the control) or by a different window (unless 22 | specifying a rectangular area--see below). 23 | 24 | Whole window 25 | A tooltip is assigned to a window's client area. 26 | Rectangular areas 27 | A tooltip is assigned to a rectangular area of a window's client area. 28 | 29 | When specifying a window's rectangular area for the tool, the 30 | notification messages must be processed by that window. This is because 31 | the "id" field is used to indicate a separate window or a tool id and 32 | a tool id is required when specifying a rectangular area. 33 | 34 | Fixed tooltip 35 | The tooltip is displayed when the cursor enters the window (or area) 36 | and doesn't move or change until the cursor leaves. 37 | Tracking tooltip 38 | The tooltip is displayed when the cursor enters the window (or area) 39 | and tooltip window moves and the text changes as the cursor moves 40 | around within the window (or area). 41 | 42 | 43 | N.B. MFC's "support" for tooltips requires the controls' parent window 44 | to process the notification messages. Attempting to get around that 45 | by overriding OnHitText() sort of works, but only for one control. 46 | Tooltips are disabled for other windows. Weird. 47 | */ 48 | 49 | /* 50 | These calls indicate either a FIXED tooltip--it doesn't move--or a TRACKING tooltip--it moves with the mouse. 51 | For the fixed version, call the version without "Track" at the end of the function name. 52 | For the tracking version, call the version with "Track" at the end of the function name. 53 | 54 | AddToolTextStatic[Track] 55 | The tooltip's text doesn't change 56 | The tooltip is displayed over the window with the passed HWND 57 | OR, the tooltip is displayed over an area, so pass the area's unique id and a RECT 58 | 59 | AddToolTextDynamic[Track] 60 | The tooltip's text changes (via the notification function of the sink's HWND, or the control's HWND if no sink is specified) 61 | The tooltip is displayed over the window with the passed HWND 62 | 63 | AddToolTextDynamic[Track] 64 | The tooltip's text changes (via the notification function of the control's HWND) 65 | The tooltip is displayed over an area, so pass the area's unique id and a RECT 66 | */ 67 | 68 | /* 69 | One window can receive the WM_NOTIFY messages while the cursor is over 70 | another window. The control is the window that displays a tooltip when 71 | the mouse hovers over it (and causes notification messages to be sent). 72 | The two windows can be the same, in which case the control window 73 | processes its own notification messages. 74 | 75 | The drawback is that the tooltip doesn't move and change based on the 76 | mouse's position inside the window. To do that, we have to use TTF_TRACK 77 | and process the WM_MOUSEMOVE ourselves, rather than use TTF_SUBCLASS. 78 | */ 79 | 80 | /* 81 | Example of handling notification messages: 82 | 83 | [window sink class derived from CWnd] 84 | 85 | :: sink.h :: 86 | afx_msg BOOL OnToolTipNotify(UINT id, NMHDR *pNMHDR, LRESULT *pResult); 87 | 88 | :: sink.cpp :: 89 | ON_NOTIFY_EX(TTN_GETDISPINFO, 0, OnToolTipNotify) 90 | // ON_NOTIFY_EX_RANGE(TTN_GETDISPINFO, 0, 0xFFFF, OnToolTipNotify) 91 | 92 | BOOL WndSink::OnToolTipNotify(UINT id, NMHDR *pNMHDR, LRESULT *pResult) 93 | { 94 | ASSERT(id == 0); 95 | NMTTDISPINFO *pttDispInfo = reinterpret_cast(pNMHDR); 96 | *pResult = 0; 97 | 98 | // pttDispInfo->hdr.hwndFrom is the associated tool wndw 99 | 100 | POINT pt; 101 | ::GetCursorPos(&pt); 102 | ::ScreenToClient(GetSafeHwnd(), &pt); 103 | _snprintf(pttDispInfo->szText, sizeof pttDispInfo->szText, "WindowSink::OnToolTipNotify(%#x) (%d,%d)", pttDispInfo->hdr.idFrom, pt.x, pt.y); 104 | TRACE(_T("%s\n"), pttDispInfo->szText); 105 | 106 | return TRUE; 107 | } 108 | */ 109 | 110 | // Yes, this class can be derived from CWnd. See the //CWnd comments. 111 | 112 | namespace skst 113 | { 114 | 115 | class MyToolTipCtrl //CWnd : public CWnd 116 | { 117 | public: 118 | typedef std::vector Instances; 119 | 120 | protected: 121 | HWND m_hWnd;//CWnd 122 | const bool _bOnlyShowTipsIfActive; // if set, we only display tooltips if the app is active 123 | 124 | UINT_PTR _idTimer; // remember if a wndw is being tracked for WM_MOUSELEAVE 125 | static HWND _hWndTrack; // there's only one tip at a time, so this can be static 126 | 127 | static HHOOK _hMsgHook; 128 | static Instances _instances; 129 | 130 | static RECT rectNull; 131 | 132 | public: 133 | MyToolTipCtrl(const bool bOnlyShowTipsIfActive = true); 134 | virtual ~MyToolTipCtrl(); 135 | 136 | MyToolTipCtrl& operator=(const MyToolTipCtrl& a) 137 | { 138 | if (this == &a) 139 | return *this; 140 | 141 | m_hWnd = a.m_hWnd; 142 | // these are const members and we never use the assignment operator anyway 143 | //const _bOnlyShowTipsIfActive = a._bOnlyShowTipsIfActive; 144 | _idTimer = a._idTimer; 145 | 146 | // the other members are static 147 | 148 | return *this; 149 | } 150 | 151 | bool Create(const bool bBalloon = false); 152 | 153 | HWND GetSafeHwnd() { return m_hWnd; }//CWnd 154 | 155 | // ** FIXED 156 | // * static (window or rect) 157 | void AddToolTextStatic(const HWND hWndControl, LPTSTR szTooltip, const UINT id = 0, const RECT& rect = rectNull); 158 | // * dynamic (window) 159 | void AddToolTextDynamic(const HWND hWndControl, HWND hWndSink = nullptr); 160 | // * dynamic (rect) 161 | void AddToolTextDynamic(const HWND hWndControl, const UINT id, const RECT& rect); 162 | 163 | // ** TRACKING 164 | // * static (window vs rect) 165 | void AddToolTextStaticTrack(const HWND hWndControl, LPTSTR szTooltip, const UINT id = 0, const RECT& rect = rectNull); 166 | // * dynamic (window) 167 | void AddToolTextDynamicTrack(const HWND hWndControl, HWND hWndSink = nullptr); 168 | // * dynamic (rect) 169 | void AddToolTextDynamicTrack(const HWND hWndControl, const UINT id, const RECT& rect); 170 | 171 | void DeleteTools(); 172 | void DeleteTool(const HWND hWndSink, const UINT_PTR id = 0); 173 | 174 | void SetFont(const LOGFONT *lplf); 175 | void SetTipTextColor(COLORREF clr); 176 | void SetBkTipColor(COLORREF clr); 177 | //TODO: what are the units of width??! Geez, Microsoft doc is awful. 178 | void SetMaxTipWidth(const int iWidth); 179 | 180 | protected: 181 | void AddTool(const bool bTrack, const HWND hWndControl, HWND hWndSink, const UINT id = 0, const RECT& rect = rectNull, LPTSTR szToolTip = LPSTR_TEXTCALLBACK); 182 | 183 | int GetToolCount() const { return (int) ::SendMessage(m_hWnd, TTM_GETTOOLCOUNT, 0, 0); } 184 | 185 | bool HitTooltipControl(HWND hWnd, const POINT& pt); 186 | bool HitTool(const TOOLINFO& ti, const HWND hWnd, const POINT& pt); 187 | void ActivateTooltip(const TOOLINFO& ti, bool bActivate); 188 | 189 | static LRESULT CALLBACK MouseProcTrack(int nCode, WPARAM wParam, LPARAM lParam); 190 | static VOID CALLBACK TimerProcTrack(HWND /*hwnd*/, UINT /*uMsg*/, UINT_PTR /*idEvent*/, DWORD /*dwTime*/); 191 | 192 | // Overrides 193 | // ClassWizard generated virtual function overrides 194 | //{{AFX_VIRTUAL(MyToolTipCtrl) 195 | //}}AFX_VIRTUAL 196 | 197 | // Generated message map functions 198 | // //{{AFX_MSG(MyToolTipCtrl) 199 | // // NOTE - the ClassWizard will add and remove member functions here. 200 | // //}}AFX_MSG 201 | //CWnd DECLARE_MESSAGE_MAP() 202 | }; 203 | 204 | } 205 | -------------------------------------------------------------------------------- /help/Documentation.md: -------------------------------------------------------------------------------- 1 | # Timekeeper Documentation by [12noon LLC](https://12noon.com/) 2 | 3 | Timekeeper provides you with more information about the date and time than the 4 | simple Windows clock in your taskbar notification area. 5 | Timekeeper also gives you quick and easy access to a calendar. 6 | 7 | Timekeeper conveniently displays the date and time in whatever format you want on your Windows taskbar. 8 | It can also display the date and time on any edge of your desktop. 9 | Timekeeper doesn't obscure what you're working on or use valuable screen real estate. 10 | 11 | If you hover the mouse over the clock display, Timekeeper displays the date and 12 | time in a tooltip (formatted in the “long format” for the current locale). 13 | 14 | These images show some of the different ways Timekeeper can be configured. 15 | The first example shows how Timekeeper can display information on multiple lines. 16 | 17 | ![Default](timekeeper.png) 18 | ![Multiline Red](tk_multiline_red.png) 19 | ![Multiline](tk_multiline.png) 20 | 21 | Timekeeper displays its information on your main Windows desktop toolbar by default. 22 | You can make Timekeeper wider or narrower by dragging the “grip” control to left of the clock. 23 | When you hover the cursor over the grip control, the cursor will change to a 24 | two-headed-arrow resize cursor to indicate that you can now resize the toolbar. 25 | 26 | You can drag Timekeeper somewhere else on the deskband or change it to a vertical deskband. 27 | To move the Timekeeper toolbar, click and drag it by the left of the clock. 28 | When you click, the cursor will change to a four-headed-arrow move cursor to 29 | indicate that you can now drag the toolbar. 30 | 31 | ## Enable Timekeeper 32 | 33 | To enable or disable Timekeeper, right-click on an empty spot on your toolbar. 34 | Select _Toolbars_ and click on _12noon Timekeeper_. 35 | 36 | ![Screenshot of how to enable Timekeeper](toolbars.png) 37 | 38 | ## Configure Timekeeper 39 | 40 | You can configure Timekeeper's display to use your own date or time formats, 41 | text, font, text color, background color, and alignment. 42 | This option is available on the context menu. (See below.) 43 | 44 | ![Timekeeper configure screenshot](configure.png) The **Format** field is 45 | where you specify what information Timekeeper will display. 46 | Click the arrow to the right of the field to see the special characters that 47 | you can use to specify various date and time components (and other values). 48 | You can also enter plain text for Timekeeper to display, such as colons to 49 | separate the time fields or a label for the week number. 50 | There are some predefined time and date formats in the menu that you can select. 51 | If you wish, you can then edit them to create your own custom format. 52 | 53 | Click the **Text color** or **Background** control to display a window where 54 | you can choose a predefined color or create a custom color for the clock's text and background. 55 | You can select a transparent background for the clock by checking **Transparent background**. 56 | 57 | **Known issue:** Transparency might not work well. Use a black background instead. 58 | 59 | ### Formats 60 | 61 | | Code | Description | Example | 62 | | --- | --- | --- | 63 | | %#I:%M:%S | 12-hour time | 12:08:14 | 64 | | %#I:%M %p | 12-hour time with meridian | 12:08 PM | 65 | | %H%M%S | 24-hour time | 020814 | 66 | | %#m/%#d/%Y | Short date | 9/7/2005 | 67 | | %Y.%m.%d | Short date, year first | 2005.09.07 | 68 | | %a %#d %b | | Wed 7 Sep | 69 | | %A, %B %#d, %Y | | Wednesday, September 7, 2005 | 70 | | %c | Short date and time format for locale | (depends on locale) | 71 | | %#c | Long date and time format for locale | (depends on locale) | 72 | | %x | Short date format for locale | (depends on locale) | 73 | | %#x | Long date format for locale | (depends on locale) | 74 | | %X | Time format for current locale | (depends on locale) | 75 | | **Time Formats** | | | 76 | | %H | Hour in 24-hour format with zero (00-23) | 08 23 | 77 | | %#H | Hour in 24-hour format without zero (0-23) | 8 23 | 78 | | %I | Hour in 12-hour format with zero (01-12) | 08 11 | 79 | | %#I | Hour in 12-hour format without zero (1-12) | 8 11 | 80 | | %M | Minute with leading zero (00-59) | 06 | 81 | | %#M | Minute without leading zero (0-59) | 6 | 82 | | %S | Second with leading zero (00-59) | 04 | 83 | | %#S | Second without leading zero (0-59) | 4 | 84 | | %p | Locale's A.M/P.M. indicator | AM PM | 85 | | %z | Time zone name or abbreviation | Central CST | 86 | | **Date Formats** | | | 87 | | %a | Abbreviated weekday name | Thu | 88 | | %A | Full weekday name | Thursday | 89 | | %w | Weekday as number (0-6, Sunday is 0) | 5 | 90 | | %b | Abbreviated month name | Dec | 91 | | %B | Full month name | December | 92 | | %m | Month (01-12) | 09 | 93 | | %#m | Month (1-12) | 9 | 94 | | %d | Date with leading zero (01-31) | 08 | 95 | | %#d | Date without leading zero (1-31) | 8 | 96 | | %y | Year without century with leading zero (00-99) | 0097 | 97 | | %#y | Year without century without leading zero (0-99) | 97 | 98 | | %Y | Year with century with leading zero | 0397 | 99 | | %#Y | Year with century without leading zero | 2021 | 100 | | %j | Day of year with leading zero (001-366) | 024 | 101 | | %#j | Day of year without leading zero (1-366) | 24 | 102 | | %T | Week of year with Sunday as first day of week (01-54) | 02 | 103 | | %#T | Week of year with Sunday as first day of week (1-54) | 2 | 104 | | %U | Week of year with Sunday as first day of week (00-53) | 07 | 105 | | %#U | Week of year with Sunday as first day of week (0-53) | 7 | 106 | | %V | Week of year with Monday as first day of week (01-54) | 05 | 107 | | %#V | Week of year with Monday as first day of week (1-54) | 5 | 108 | | %W | Week of year with Monday as first day of week (00-53) | 06 | 109 | | %#W | Week of year with Monday as first day of week (0-53) | 6 | 110 | | **Special Characters** | | | 111 | | %% | Percent sign (%) | | 112 | | \\n | Line separator | 18:52 Central 5 Jun 2021 | 113 | 114 | ## Calendar 115 | 116 | Timekeeper can display a calendar so that you can easily plan meetings, vacations, 117 | or see when you should make your next haircut appointment. 118 | Click the primary mouse button (usually the left one) anywhere on Timekeeper's 119 | date/time display, and it will display a calendar. 120 | You can drag any edge or corner of the calendar and enlarge or shrink the window 121 | to show more months (up to four across or four down). 122 | 123 | You can select a series of dates to make it easier for you to refer back to them. 124 | (Timekeeper does not remember the selection after you close the calendar.) 125 | 126 | The calendar displays current date and time in the caption. 127 | 128 | Close the calendar by clicking the ‘x' in the caption or by pressing **ALT+F4**. 129 | 130 | ![Calendar 1x3](tk_calendar_1x3.png) 131 | 132 | The following keys can help you navigate the calendar: 133 | 134 | | Hotkey | Action | 135 | | ------ | ------ | 136 | | Home | Select first day of current month | 137 | | End | Select last day of current month | 138 | | CTRL+Home | Select first day of first month on display | 139 | | CTRL+End | Select last day of last month on display | 140 | | PageUp | Move back one month | 141 | | PageDown | Move forward one month | 142 | | CTRL+PageUp | Move back one year | 143 | | CTRL+PageDown | Move forward one year | 144 | 145 | Other calendar options include specifying the font, hiding the _Today_ information, 146 | displaying the week numbers, remembering the calendar's position, and remembering the calendar's size. 147 | 148 | **Known issue:** If you reduce the size of the font, the calendar is not resized immediately. 149 | The band must be closed and re-opened to use the new size. This is a Windows limitation. 150 | 151 | ![Calendar 2x1](tk_calendar_2x1.png) 152 | ![Calendar 2x2](tk_calendar_2x2.png) 153 | ![Calendar 3x1](tk_calendar_3x1.png) 154 | 155 | ## More Options 156 | 157 | To access the **context menu**, right-click on the Timekeeper deskband. 158 | The menu allows you to perform the following functions: 159 | 160 | * Obtain information about 12noon LLC Products. 161 | * Display this Help document. 162 | * Display the About window. 163 | * Configure the date/time display. 164 | * Adjust the system date/time. 165 | * Specify whether the calendar should highlight today's date. 166 | * Specify whether the calendar should display week numbers. 167 | * Specify whether the calendar should remember its position. 168 | * Specify whether the calendar should remember its size. 169 | * Specify the calendar's font. 170 | 171 | The other commands are standard Windows commands. For example, you can use 172 | the _Show Title_ command to hide the deskband's _Timekeeper_ title. 173 | 174 | ![Context Menu](context_menu.png) 175 | 176 | ## Known Issues 177 | 178 | If the size of the calendar font is made smaller, the calendar is not resized. 179 | The band must be closed and re-opened to see the new size. This is a Windows limitation. 180 | -------------------------------------------------------------------------------- /COMToys/src/Subclass.cpp: -------------------------------------------------------------------------------- 1 | //////////////////////////////////////////////////////////////// 2 | // PixieLib(TM) Copyright 1997-1998 Paul DiLascia 3 | // If this code works, it was written by Paul DiLascia. 4 | // If not, I don't know who wrote it. 5 | // 6 | // CSubclassWnd is a generic class for hooking another window's messages. 7 | 8 | #include "StdAfx.h" 9 | #include "COMtoys/Subclass.h" 10 | 11 | #ifdef _DEBUG 12 | #define new DEBUG_NEW 13 | #undef THIS_FILE 14 | static char THIS_FILE[] = __FILE__; 15 | #endif 16 | 17 | ////////////////// 18 | // The message hook map is derived from CMapPtrToPtr, which associates 19 | // a pointer with another pointer. It maps an HWND to a CSubclassWnd, like 20 | // the way MFC's internal maps map HWND's to CWnd's. The first CSubclassWnd 21 | // attached to a window is stored in the map; all other CSubclassWnd's for that 22 | // window are then chained via CSubclassWnd::m_pNext. 23 | // 24 | class CSubclassWndMap : private CMapPtrToPtr { 25 | public: 26 | CSubclassWndMap(); 27 | ~CSubclassWndMap(); 28 | static CSubclassWndMap& GetHookMap(); 29 | void Add(HWND hwnd, CSubclassWnd* pSubclassWnd); 30 | void Remove(CSubclassWnd* pSubclassWnd); 31 | void RemoveAll(HWND hwnd); 32 | CSubclassWnd* Lookup(HWND hwnd); 33 | }; 34 | 35 | // This trick is used so the hook map isn't 36 | // instantiated until someone actually requests it. 37 | // 38 | #define theHookMap (CSubclassWndMap::GetHookMap()) 39 | 40 | IMPLEMENT_DYNAMIC(CSubclassWnd, CWnd); 41 | 42 | CSubclassWnd::CSubclassWnd() 43 | { 44 | m_pNext = NULL; 45 | m_pOldWndProc = NULL; 46 | m_hWnd = NULL; 47 | } 48 | 49 | CSubclassWnd::~CSubclassWnd() 50 | { 51 | if (m_hWnd) 52 | HookWindow((HWND)NULL); // unhook window 53 | } 54 | 55 | ////////////////// 56 | // Hook a window. 57 | // This installs a new window proc that directs messages to the CSubclassWnd. 58 | // pWnd=NULL to remove. 59 | // 60 | BOOL CSubclassWnd::HookWindow(HWND hwnd) 61 | { 62 | ASSERT_VALID(this); 63 | if (hwnd) { 64 | // Hook the window 65 | ASSERT(m_hWnd==NULL); 66 | ASSERT(::IsWindow(hwnd)); 67 | theHookMap.Add(hwnd, this); // Add to map of hooks 68 | 69 | } else if (m_hWnd) { 70 | // Unhook the window 71 | theHookMap.Remove(this); // Remove from map 72 | m_pOldWndProc = NULL; 73 | } 74 | m_hWnd = hwnd; 75 | return TRUE; 76 | } 77 | 78 | ////////////////// 79 | // Window proc-like virtual function which specific CSubclassWnds will 80 | // override to do stuff. Default passes the message to the next hook; 81 | // the last hook passes the message to the original window. 82 | // You MUST call this at the end of your WindowProc if you want the real 83 | // window to get the message. This is just like CWnd::WindowProc, except that 84 | // a CSubclassWnd is not a window. 85 | // 86 | LRESULT CSubclassWnd::WindowProc(UINT msg, WPARAM wp, LPARAM lp) 87 | { 88 | // ASSERT_VALID(this); // removed for speed 89 | ASSERT(m_pOldWndProc); 90 | return m_pNext ? m_pNext->WindowProc(msg, wp, lp) : 91 | ::CallWindowProc(m_pOldWndProc, m_hWnd, msg, wp, lp); 92 | } 93 | 94 | ////////////////// 95 | // Like calling base class WindowProc, but with no args, so individual 96 | // message handlers can do the default thing. Like CWnd::Default 97 | // 98 | LRESULT CSubclassWnd::Default() 99 | { 100 | // MFC stores current MSG in thread state 101 | MSG& curMsg = AfxGetThreadState()->m_lastSentMsg; 102 | // Note: must explicitly call CSubclassWnd::WindowProc to avoid infinte 103 | // recursion on virtual function 104 | return CSubclassWnd::WindowProc(curMsg.message, curMsg.wParam, curMsg.lParam); 105 | } 106 | 107 | #ifdef _DEBUG 108 | void CSubclassWnd::AssertValid() const 109 | { 110 | CObject::AssertValid(); 111 | ASSERT(m_hWnd==NULL || ::IsWindow(m_hWnd)); 112 | if (m_hWnd) { 113 | CSubclassWnd* p = NULL; //skst: enforce for scoping 114 | for (p = theHookMap.Lookup(m_hWnd); p; p=p->m_pNext) { 115 | if (p==this) 116 | break; 117 | } 118 | ASSERT(p); // should have found it! 119 | } 120 | } 121 | 122 | void CSubclassWnd::Dump(CDumpContext& dc) const 123 | { 124 | CObject::Dump(dc); 125 | } 126 | 127 | #endif 128 | 129 | ////////////////// 130 | // Subclassed window proc for message hooks. Replaces AfxWndProc (or whatever 131 | // else was there before.) 132 | // 133 | LRESULT CALLBACK 134 | HookWndProc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp) 135 | { 136 | #ifdef _USRDLL 137 | // If this is a DLL, need to set up MFC state 138 | AFX_MANAGE_STATE(AfxGetStaticModuleState()); 139 | #endif 140 | 141 | // Set up MFC message state just in case anyone wants it 142 | // This is just like AfxCallWindowProc, but we can't use that because 143 | // a CSubclassWnd is not a CWnd. 144 | // 145 | MSG& curMsg = AfxGetThreadState()->m_lastSentMsg; 146 | MSG oldMsg = curMsg; // save for nesting 147 | curMsg.hwnd = hwnd; 148 | curMsg.message = msg; 149 | curMsg.wParam = wp; 150 | curMsg.lParam = lp; 151 | 152 | // Get hook object for this window. Get from hook map 153 | CSubclassWnd* pSubclassWnd = theHookMap.Lookup(hwnd); 154 | ASSERT(pSubclassWnd); 155 | 156 | LRESULT lr; 157 | if (msg==WM_NCDESTROY) { 158 | // Window is being destroyed: unhook all hooks (for this window) 159 | // and pass msg to orginal window proc 160 | // 161 | WNDPROC wndproc = pSubclassWnd->m_pOldWndProc; 162 | theHookMap.RemoveAll(hwnd); 163 | lr = ::CallWindowProc(wndproc, hwnd, msg, wp, lp); 164 | 165 | } else { 166 | // pass to msg hook 167 | lr = pSubclassWnd->WindowProc(msg, wp, lp); 168 | } 169 | curMsg = oldMsg; // pop state 170 | return lr; 171 | } 172 | 173 | //////////////////////////////////////////////////////////////// 174 | // CSubclassWndMap implementation 175 | // 176 | CSubclassWndMap::CSubclassWndMap() 177 | { 178 | } 179 | 180 | CSubclassWndMap::~CSubclassWndMap() 181 | { 182 | // This assert bombs when posting WM_QUIT, so I've deleted it. 183 | // ASSERT(IsEmpty()); // all hooks should be removed! 184 | } 185 | 186 | ////////////////// 187 | // Get the one and only global hook map 188 | // 189 | CSubclassWndMap& CSubclassWndMap::GetHookMap() 190 | { 191 | // By creating theMap here, C++ doesn't instantiate it until/unless 192 | // it's ever used! This is a good trick to use in C++, to 193 | // instantiate/initialize a static object the first time it's used. 194 | // 195 | static CSubclassWndMap theMap; 196 | return theMap; 197 | } 198 | 199 | ///////////////// 200 | // Add hook to map; i.e., associate hook with window 201 | // 202 | void CSubclassWndMap::Add(HWND hwnd, CSubclassWnd* pSubclassWnd) 203 | { 204 | ASSERT(hwnd && ::IsWindow(hwnd)); 205 | 206 | // Add to front of list 207 | pSubclassWnd->m_pNext = Lookup(hwnd); 208 | SetAt(hwnd, pSubclassWnd); 209 | 210 | if (pSubclassWnd->m_pNext==NULL) { 211 | // If this is the first hook added, subclass the window 212 | pSubclassWnd->m_pOldWndProc = 213 | (WNDPROC) ::SetWindowLongPtr(hwnd, GCLP_WNDPROC, (LONG_PTR) HookWndProc); //skst: use appropriate function 214 | 215 | } else { 216 | // just copy wndproc from next hook 217 | pSubclassWnd->m_pOldWndProc = pSubclassWnd->m_pNext->m_pOldWndProc; 218 | } 219 | ASSERT(pSubclassWnd->m_pOldWndProc); 220 | } 221 | 222 | ////////////////// 223 | // Remove hook from map 224 | // 225 | void CSubclassWndMap::Remove(CSubclassWnd* pUnHook) 226 | { 227 | HWND hwnd = pUnHook->m_hWnd; 228 | ASSERT(hwnd && ::IsWindow(hwnd)); 229 | 230 | CSubclassWnd* pHook = Lookup(hwnd); 231 | ASSERT(pHook); 232 | if (pHook==pUnHook) { 233 | // hook to remove is the one in the hash table: replace w/next 234 | if (pHook->m_pNext) 235 | SetAt(hwnd, pHook->m_pNext); 236 | else { 237 | // This is the last hook for this window: restore wnd proc 238 | RemoveKey(hwnd); 239 | ::SetWindowLongPtr(hwnd, GCLP_WNDPROC, (LONG_PTR) pHook->m_pOldWndProc); //skst: use appropriate function 240 | } 241 | } else { 242 | // Hook to remove is in the middle: just remove from linked list 243 | while (pHook->m_pNext!=pUnHook) 244 | pHook = pHook->m_pNext; 245 | ASSERT(pHook && pHook->m_pNext==pUnHook); 246 | pHook->m_pNext = pUnHook->m_pNext; 247 | } 248 | } 249 | 250 | ////////////////// 251 | // Remove all the hooks for a window 252 | // 253 | void CSubclassWndMap::RemoveAll(HWND hwnd) 254 | { 255 | CSubclassWnd* pSubclassWnd; 256 | while ((pSubclassWnd = Lookup(hwnd))!=NULL) 257 | pSubclassWnd->HookWindow((HWND)NULL); // (unhook) 258 | } 259 | 260 | ///////////////// 261 | // Find first hook associate with window 262 | // 263 | CSubclassWnd* CSubclassWndMap::Lookup(HWND hwnd) 264 | { 265 | CSubclassWnd* pFound = NULL; 266 | if (!CMapPtrToPtr::Lookup(hwnd, (void*&)pFound)) 267 | return NULL; 268 | ASSERT_KINDOF(CSubclassWnd, pFound); 269 | return pFound; 270 | } 271 | 272 | --------------------------------------------------------------------------------