diff options
Diffstat (limited to 'program/MonitorDlg.cpp')
-rw-r--r-- | program/MonitorDlg.cpp | 266 |
1 files changed, 266 insertions, 0 deletions
diff --git a/program/MonitorDlg.cpp b/program/MonitorDlg.cpp new file mode 100644 index 0000000..3ffc53f --- /dev/null +++ b/program/MonitorDlg.cpp @@ -0,0 +1,266 @@ +// +// AUTHOR +// N. Nielsen +// +// LICENSE +// This software is in the public domain. +// +// The software is provided "as is", without warranty of any kind, +// express or implied, including but not limited to the warranties +// of merchantability, fitness for a particular purpose, and +// noninfringement. In no event shall the author(s) be liable for any +// claim, damages, or other liability, whether in an action of +// contract, tort, or otherwise, arising from, out of, or in connection +// with the software or the use or other dealings in the software. +// +// SUPPORT +// Send bug reports to: <nielsen@memberwebs.com> +// + +#include "stdafx.h" +#include "MonitorDlg.h" + +#include "../hook/hook.h" + + +///////////////////////////////////////////////////////////////////////////// +// CMonitorDlg + +CMonitorDlg::CMonitorDlg() + : m_Icon(ID_TRAY_WPM, _Module.GetResourceInstance()), + m_settings(HKEY_CURRENT_USER, _T("SOFTWARE\\WPM\\")), + CPersistPosWindow<CMonitorDlg>("Window") +{ + m_hIcon = NULL; + m_szIcon.cx = ::GetSystemMetrics(SM_CXSMICON); + m_szIcon.cy = ::GetSystemMetrics(SM_CYSMICON); + memset(&m_aSpeeds, 0, sizeof(m_aSpeeds)); + m_nIndex = 0; +} + +CMonitorDlg::~CMonitorDlg() +{ + if(m_hIcon) + ::DestroyIcon(m_hIcon); + + // Remove Icon just in case + m_Icon.SetIcon(0); +} + +// Points in the icon to draw different counters +const POINT kHundreds = { 1, 1 }; +const POINT kTens = { 6, 1 }; +const POINT kOnes = { 11, 1 }; +const POINT kHundredsAv = { 1, 10 }; +const POINT kTensAv = { 6, 10 }; +const POINT kOnesAv = { 11, 10 }; + +bool CMonitorDlg::CreateIcon(long lSpeed, long lAverage) +{ + bool bRet = false; + + if(m_hIcon) + ::DestroyIcon(m_hIcon); + + HDC hScreenDC = ::GetDC(NULL); + HDC hDC = ::CreateCompatibleDC(hScreenDC); + + if(hScreenDC && hDC) + { + if(SetStretchBltMode(hDC, HALFTONE)) + { + if(SetBrushOrgEx(hDC, 0, 0, NULL)) + { + ICONINFO info; + info.fIcon = TRUE; + + info.hbmColor = ::CreateCompatibleBitmap(hScreenDC, m_szIcon.cx, m_szIcon.cy); + info.hbmMask = ::CreateCompatibleBitmap(hDC, m_szIcon.cx, m_szIcon.cy); + + if(info.hbmColor && info.hbmMask) + { + HBITMAP hOldBm = (HBITMAP)SelectObject(hDC, info.hbmMask); + ::PatBlt(hDC, 0, 0, m_szIcon.cx, m_szIcon.cy, WHITENESS); + + int nHundreds = lSpeed / 100; + if(nHundreds >= 10) nHundreds = 9; + + int nTens = (lSpeed - (100 * nHundreds)) / 10; + ATLASSERT(nTens < 10); + + int nOnes = (lSpeed - (100 * nHundreds) - (10 * nTens)); + ATLASSERT(nOnes < 10); + + m_imgList.Draw(hDC, nHundreds, kHundreds, ILD_TRANSPARENT); + m_imgList.Draw(hDC, nTens, kTens, ILD_TRANSPARENT); + m_imgList.Draw(hDC, nOnes, kOnes, ILD_TRANSPARENT); + + + nHundreds = lAverage / 100; + if(nHundreds >= 10) nHundreds = 9; + + nTens = (lAverage - (100 * nHundreds)) / 10; + ATLASSERT(nTens < 10); + + nOnes = (lAverage - (100 * nHundreds) - (10 * nTens)); + ATLASSERT(nOnes < 10); + + m_imgList.Draw(hDC, nHundreds, kHundredsAv, ILD_TRANSPARENT); + m_imgList.Draw(hDC, nTens, kTensAv, ILD_TRANSPARENT); + m_imgList.Draw(hDC, nOnes, kOnesAv, ILD_TRANSPARENT); + + ::SelectObject(hDC, info.hbmColor); + + RECT rc = { 0, 0, m_szIcon.cx, m_szIcon.cy }; + ::FillRect(hDC, &rc, (HBRUSH)(COLOR_WINDOWTEXT + 1)); + + m_hIcon = CreateIconIndirect(&info); + + DeleteObject(info.hbmColor); + DeleteObject(info.hbmMask); + + ::SelectObject(hDC, hOldBm); + + bRet = m_hIcon != NULL; + } + } + } + + ::DeleteDC(hDC); + ::ReleaseDC(NULL, hScreenDC); + } + + return bRet; + +} + +LRESULT CMonitorDlg::OnTop(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled) +{ + SetWindowPos(IsDlgButtonChecked(IDC_ONTOP) ? HWND_TOPMOST : HWND_NOTOPMOST, + 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE); + + return 0; +} + + +LRESULT CMonitorDlg::OnInitDialog(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) +{ + BOOL ret = m_imgList.Create(MAKEINTRESOURCE(IDB_NUMBERS), 4, 0, RGB(255, 255, 255)); + ATLASSERT(ret); + + InstallSpeedHook(); + SetTimer(100, TIME_LAPSE); + + // Setup Tray Icon (Actual setting of current icon is done by + // UpdateControls + m_Icon.SetNotificationWnd(*this, WM_TRAYICON); + m_Icon.SetIcon(ID_TRAY_WPM); + ShowWindow(SW_HIDE); + + LoadPosition(m_settings); + ShowWindow(SW_HIDE); + + return 1; // Let the system set the focus +} + +LRESULT CMonitorDlg::OnOK(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled) +{ + ShowWindow(SW_HIDE); + return 0; +} + +LRESULT CMonitorDlg::OnCancel(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled) +{ + ShowWindow(SW_HIDE); + return 0; +} + +long CMonitorDlg::GetAverage(long lSpeed) +{ + ATLASSERT(m_nIndex >= 0 && m_nIndex < LAPSE_PER_MIN); + + m_aSpeeds[m_nIndex] = lSpeed; + + if(++m_nIndex >= LAPSE_PER_MIN) + m_nIndex = 0; + + int cnt = 0; + int total = 0; + + for(int i = 0; i < LAPSE_PER_MIN; i++) + { + if(m_aSpeeds[i] > 0) + { + cnt++; + total += m_aSpeeds[i]; + } + } + + if(cnt == 0) + return 0; + + return total / cnt; +} + +const TCHAR kTitle[] = "%d WPM"; +const TCHAR kTip[] = "%d WPM (%d average)"; + +LRESULT CMonitorDlg::OnTimer(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) +{ + USES_CONVERSION; + + // Get the amount of characters it the lapse and reset + LONG lSpeed = GetCurSpeedCount(); + ClearSpeedCount(); + + // Multiply it so we don't loose too much detail in + // decimals + lSpeed *= 10000; + + // Divide by the word size (The Multiple is used ditto above) + lSpeed /= CHARS_PER_WORD; + lSpeed *= CHARS_MULTIPLE; + + // Multiply to get per minute + lSpeed *= LAPSE_PER_MIN; + + // Divide back to get the WPM + lSpeed /= 10000; + + long lAverage = GetAverage(lSpeed); + + SetDlgItemInt(IDC_VALUE, lSpeed, TRUE); + SetDlgItemInt(IDC_AVERAGE, lAverage, TRUE); + + string sMessage; + sMessage.format(kTitle, lSpeed); + SetWindowText(sMessage); + + sMessage.format(kTip, lSpeed, lAverage); + + if(CreateIcon(lSpeed, lAverage)) + m_Icon.SetIcon(m_hIcon, sMessage); + + return 0; +} + +LRESULT CMonitorDlg::OnDestroy(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) +{ + RemoveSpeedHook(); + KillTimer(100); + SavePosition(m_settings); + return 0; +} + +LRESULT CMonitorDlg::OnShow(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled) +{ + ShowWindow(SW_SHOW); + SetForegroundWindow(m_hWnd); + return 1; +} + +LRESULT CMonitorDlg::OnExit(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled) +{ + PostQuitMessage(0); + return 1; +} |