summaryrefslogtreecommitdiff
path: root/program/MonitorDlg.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'program/MonitorDlg.cpp')
-rw-r--r--program/MonitorDlg.cpp266
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;
+}