summaryrefslogtreecommitdiff
path: root/program
diff options
context:
space:
mode:
Diffstat (limited to 'program')
-rw-r--r--program/MonitorDlg.cpp266
-rw-r--r--program/MonitorDlg.h93
-rw-r--r--program/Program.cpp57
-rw-r--r--program/Program.dsp143
-rw-r--r--program/Program.rc190
-rw-r--r--program/StdAfx.cpp31
-rw-r--r--program/StdAfx.h46
-rw-r--r--program/bitmap1.bmpbin0 -> 218 bytes
-rw-r--r--program/ico00001.icobin0 -> 318 bytes
-rw-r--r--program/icon1.icobin0 -> 766 bytes
-rw-r--r--program/resource.h36
11 files changed, 862 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;
+}
diff --git a/program/MonitorDlg.h b/program/MonitorDlg.h
new file mode 100644
index 0000000..ebbae76
--- /dev/null
+++ b/program/MonitorDlg.h
@@ -0,0 +1,93 @@
+//
+// 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>
+//
+
+#ifndef __MONITORDLG_H_
+#define __MONITORDLG_H_
+
+#include "resource.h" // main symbols
+
+#include "trayicon.h"
+#define WM_TRAYICON (WM_APP + 38L)
+
+#include "regsettings.h"
+#include "persistwinpos.h"
+
+#define TIME_LAPSE 4000
+#define LAPSE_PER_MIN 15
+#define CHARS_PER_WORD 544
+#define CHARS_MULTIPLE 100
+
+/////////////////////////////////////////////////////////////////////////////
+// CMonitorDlg
+
+class CMonitorDlg :
+ public CDialogImpl<CMonitorDlg>,
+ public CPersistPosWindow<CMonitorDlg>
+{
+public:
+ CMonitorDlg();
+ ~CMonitorDlg();
+
+ enum { IDD = IDD_MONITORDLG };
+
+BEGIN_MSG_MAP(CMonitorDlg)
+ MESSAGE_HANDLER(WM_INITDIALOG, OnInitDialog)
+ COMMAND_HANDLER(IDC_ONTOP, BN_CLICKED, OnTop)
+ COMMAND_ID_HANDLER(IDOK, OnOK)
+ COMMAND_ID_HANDLER(IDCANCEL, OnCancel)
+ MESSAGE_HANDLER(WM_TIMER, OnTimer)
+ MESSAGE_HANDLER(WM_DESTROY, OnDestroy)
+ COMMAND_ID_HANDLER(ID_TRAY_EXIT, OnExit)
+ COMMAND_ID_HANDLER(ID_TRAY_SHOW, OnShow)
+ MESSAGE_HANDLER(WM_TRAYICON, OnTrayIcon)
+END_MSG_MAP()
+
+// Handler prototypes:
+// LRESULT MessageHandler(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
+// LRESULT CommandHandler(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled);
+// LRESULT NotifyHandler(int idCtrl, LPNMHDR pnmh, BOOL& bHandled);
+
+ LRESULT OnTop(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled);
+ LRESULT OnInitDialog(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
+ LRESULT OnOK(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled);
+ LRESULT OnCancel(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled);
+ LRESULT OnTimer(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
+ LRESULT OnDestroy(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
+ LRESULT OnShow(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled);
+ LRESULT OnExit(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled);
+
+ // Notification from Icon
+ LRESULT OnTrayIcon(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
+ { return m_Icon.OnTrayNotification(wParam, lParam); }
+
+protected:
+ bool CreateIcon(long lSpeed, long lAverage);
+ long GetAverage(long lSpeed);
+
+ HICON m_hIcon;
+ SIZE m_szIcon;
+ CImageList m_imgList;
+ CTrayIcon m_Icon; // Icon in Shell Tray
+ CRegSettings m_settings; // Our registry key
+
+ long m_aSpeeds[LAPSE_PER_MIN];
+ int m_nIndex;
+};
+
+#endif //__MONITORDLG_H_ \ No newline at end of file
diff --git a/program/Program.cpp b/program/Program.cpp
new file mode 100644
index 0000000..584e138
--- /dev/null
+++ b/program/Program.cpp
@@ -0,0 +1,57 @@
+//
+// 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 "resource.h"
+#include "MonitorDlg.h"
+
+CComModule _Module;
+
+/////////////////////////////////////////////////////////////////////////////
+//
+extern "C" int WINAPI _tWinMain(HINSTANCE hInstance,
+ HINSTANCE /*hPrevInstance*/, LPTSTR lpCmdLine, int /*nShowCmd*/)
+{
+ HRESULT hRes = CoInitialize(NULL);
+ _ASSERTE(SUCCEEDED(hRes));
+ _Module.Init(NULL, hInstance);
+
+ ::CreateMutex(NULL, TRUE, _T("WPM_START_MUTEX"));
+ if(::GetLastError() == ERROR_ALREADY_EXISTS)
+ return 0;
+
+ CMonitorDlg dlg;
+ dlg.Create(NULL);
+
+ MSG msg;
+ while (GetMessage(&msg, 0, 0, 0))
+ {
+ if(dlg.IsDialogMessage(&msg))
+ continue;
+
+ TranslateMessage(&msg);
+ DispatchMessage(&msg);
+ }
+
+ dlg.DestroyWindow();
+
+ _Module.Term();
+ CoUninitialize();
+ return 0;
+}
diff --git a/program/Program.dsp b/program/Program.dsp
new file mode 100644
index 0000000..9c9d79e
--- /dev/null
+++ b/program/Program.dsp
@@ -0,0 +1,143 @@
+# Microsoft Developer Studio Project File - Name="Program" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Application" 0x0101
+
+CFG=Program - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "Program.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "Program.mak" CFG="Program - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "Program - Win32 Debug" (based on "Win32 (x86) Application")
+!MESSAGE "Program - Win32 Release" (based on "Win32 (x86) Application")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+MTL=midl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "Program - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "debug"
+# PROP Intermediate_Dir "debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /Yu"stdafx.h" /FD /GZ /c
+# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /I "../common" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /Yu"stdafx.h" /FD /GZ /c
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 comctl32.lib kernel32.lib user32.lib gdi32.lib winspool.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib /nologo /subsystem:windows /debug /machine:I386 /out:"../debug/wpm.exe" /pdbtype:sept
+
+!ELSEIF "$(CFG)" == "Program - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "release"
+# PROP BASE Intermediate_Dir "release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "release"
+# PROP Intermediate_Dir "release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /O1 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_ATL_DLL" /D "_ATL_MIN_CRT" /Yu"stdafx.h" /FD /c
+# ADD CPP /nologo /W3 /GX /O1 /I "../common" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_ATL_DLL" /Yu"stdafx.h" /FD /c
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386
+# ADD LINK32 comdlg32.lib uuid.lib odbc32.lib odbccp32.lib comctl32.lib kernel32.lib user32.lib gdi32.lib winspool.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib /nologo /subsystem:windows /machine:I386 /out:"../release/wpm.exe"
+
+!ENDIF
+
+# Begin Target
+
+# Name "Program - Win32 Debug"
+# Name "Program - Win32 Release"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=.\MonitorDlg.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\Program.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\Program.rc
+# End Source File
+# Begin Source File
+
+SOURCE=.\StdAfx.cpp
+# ADD CPP /Yc"stdafx.h"
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# Begin Source File
+
+SOURCE=.\MonitorDlg.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\Resource.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\StdAfx.h
+# End Source File
+# End Group
+# Begin Group "Resource Files"
+
+# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
+# Begin Source File
+
+SOURCE=.\bitmap1.bmp
+# End Source File
+# Begin Source File
+
+SOURCE=.\ico00001.ico
+# End Source File
+# Begin Source File
+
+SOURCE=.\icon1.ico
+# End Source File
+# End Group
+# End Target
+# End Project
+# Section Program : {00404444-4404-4444-4444-444444444444}
+# 1:14:IDD_MONITORDLG:101
+# End Section
diff --git a/program/Program.rc b/program/Program.rc
new file mode 100644
index 0000000..555bdaa
--- /dev/null
+++ b/program/Program.rc
@@ -0,0 +1,190 @@
+//Microsoft Developer Studio generated resource script.
+//
+#include "resource.h"
+
+#define APSTUDIO_READONLY_SYMBOLS
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 2 resource.
+//
+#include "winres.h"
+
+/////////////////////////////////////////////////////////////////////////////
+#undef APSTUDIO_READONLY_SYMBOLS
+
+/////////////////////////////////////////////////////////////////////////////
+// English (U.S.) resources
+
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
+#ifdef _WIN32
+LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
+#pragma code_page(1252)
+#endif //_WIN32
+
+#ifdef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// TEXTINCLUDE
+//
+
+1 TEXTINCLUDE DISCARDABLE
+BEGIN
+ "resource.h\0"
+END
+
+2 TEXTINCLUDE DISCARDABLE
+BEGIN
+ "#include ""winres.h""\r\n"
+ "\0"
+END
+
+3 TEXTINCLUDE DISCARDABLE
+BEGIN
+ "1 TYPELIB ""Program.tlb""\r\n"
+ "\0"
+END
+
+#endif // APSTUDIO_INVOKED
+
+
+#ifndef _MAC
+/////////////////////////////////////////////////////////////////////////////
+//
+// Version
+//
+
+VS_VERSION_INFO VERSIONINFO
+ FILEVERSION 1,0,0,1
+ PRODUCTVERSION 1,0,0,1
+ FILEFLAGSMASK 0x3fL
+#ifdef _DEBUG
+ FILEFLAGS 0x1L
+#else
+ FILEFLAGS 0x0L
+#endif
+ FILEOS 0x4L
+ FILETYPE 0x1L
+ FILESUBTYPE 0x0L
+BEGIN
+ BLOCK "StringFileInfo"
+ BEGIN
+ BLOCK "040904B0"
+ BEGIN
+ VALUE "CompanyName", "\0"
+ VALUE "FileDescription", "Program Module\0"
+ VALUE "FileVersion", "1, 0, 0, 1\0"
+ VALUE "InternalName", "Program\0"
+ VALUE "LegalCopyright", "Copyright 2000\0"
+ VALUE "OriginalFilename", "Program.EXE\0"
+ VALUE "ProductName", "Program Module\0"
+ VALUE "ProductVersion", "1, 0, 0, 1\0"
+ VALUE "OLESelfRegister", "\0"
+ END
+ END
+ BLOCK "VarFileInfo"
+ BEGIN
+ VALUE "Translation", 0x409, 1200
+ END
+END
+
+#endif // !_MAC
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Dialog
+//
+
+IDD_MONITORDLG DIALOGEX 0, 0, 108, 57
+STYLE DS_MODALFRAME | WS_CAPTION | WS_SYSMENU
+EXSTYLE WS_EX_TOOLWINDOW
+FONT 8, "Tahoma", 0, 0, 0x1
+BEGIN
+ RTEXT "0",IDC_VALUE,0,10,20,8
+ LTEXT "current words/minute",IDC_STATIC,23,10,70,8
+ CONTROL "Always on top",IDC_ONTOP,"Button",BS_AUTOCHECKBOX |
+ WS_TABSTOP,19,41,60,10
+ RTEXT "0",IDC_AVERAGE,0,25,20,8
+ LTEXT "average words/minute",IDC_STATIC,23,25,73,8
+END
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Icon
+//
+
+// Icon with lowest ID value placed first to ensure application icon
+// remains consistent on all systems.
+IDI_KEYBOARD ICON DISCARDABLE "icon1.ico"
+ID_TRAY_WPM ICON DISCARDABLE "ico00001.ico"
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Bitmap
+//
+
+IDB_NUMBERS BITMAP DISCARDABLE "bitmap1.bmp"
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Menu
+//
+
+ID_TRAY_WPM MENU DISCARDABLE
+BEGIN
+ POPUP "Tray"
+ BEGIN
+ MENUITEM "Show", ID_TRAY_SHOW
+ MENUITEM SEPARATOR
+ MENUITEM "Exit", ID_TRAY_EXIT
+ END
+END
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// DESIGNINFO
+//
+
+#ifdef APSTUDIO_INVOKED
+GUIDELINES DESIGNINFO DISCARDABLE
+BEGIN
+ IDD_MONITORDLG, DIALOG
+ BEGIN
+ RIGHTMARGIN, 82
+ BOTTOMMARGIN, 41
+ END
+END
+#endif // APSTUDIO_INVOKED
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// String Table
+//
+
+STRINGTABLE DISCARDABLE
+BEGIN
+ IDS_PROJNAME "Program"
+END
+
+STRINGTABLE DISCARDABLE
+BEGIN
+ ID_TRAY_WPM "Words per minute"
+END
+
+#endif // English (U.S.) resources
+/////////////////////////////////////////////////////////////////////////////
+
+
+
+#ifndef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 3 resource.
+//
+
+/////////////////////////////////////////////////////////////////////////////
+#endif // not APSTUDIO_INVOKED
+
diff --git a/program/StdAfx.cpp b/program/StdAfx.cpp
new file mode 100644
index 0000000..dba6c2c
--- /dev/null
+++ b/program/StdAfx.cpp
@@ -0,0 +1,31 @@
+//
+// 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>
+//
+
+// stdafx.cpp : source file that includes just the standard includes
+// stdafx.pch will be the pre-compiled header
+// stdafx.obj will contain the pre-compiled type information
+
+#include "stdafx.h"
+
+#ifdef _ATL_STATIC_REGISTRY
+#include <statreg.h>
+#include <statreg.cpp>
+#endif
+
+#include <atlimpl.cpp>
diff --git a/program/StdAfx.h b/program/StdAfx.h
new file mode 100644
index 0000000..59d9c5f
--- /dev/null
+++ b/program/StdAfx.h
@@ -0,0 +1,46 @@
+//
+// 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>
+//
+
+// stdafx.h : include file for standard system include files,
+// or project specific include files that are used frequently,
+// but are changed infrequently
+
+#if !defined(AFX_STDAFX_H__55B93838_E818_11D3_8374_0020182B97FC__INCLUDED_)
+#define AFX_STDAFX_H__55B93838_E818_11D3_8374_0020182B97FC__INCLUDED_
+
+#if _MSC_VER > 1000
+#pragma once
+#endif // _MSC_VER > 1000
+
+#define STRICT
+#ifndef _WIN32_WINNT
+#define _WIN32_WINNT 0x0400
+#endif
+#define _ATL_APARTMENT_THREADED
+
+#include <atlbase.h>
+extern CComModule _Module;
+#include <atlcom.h>
+#include <atlwin.h>
+#include <atlctrls.h>
+
+//{{AFX_INSERT_LOCATION}}
+// Microsoft Visual C++ will insert additional declarations immediately before the previous line.
+
+#endif // !defined(AFX_STDAFX_H__55B93838_E818_11D3_8374_0020182B97FC__INCLUDED)
diff --git a/program/bitmap1.bmp b/program/bitmap1.bmp
new file mode 100644
index 0000000..25d5226
--- /dev/null
+++ b/program/bitmap1.bmp
Binary files differ
diff --git a/program/ico00001.ico b/program/ico00001.ico
new file mode 100644
index 0000000..dfb04b3
--- /dev/null
+++ b/program/ico00001.ico
Binary files differ
diff --git a/program/icon1.ico b/program/icon1.ico
new file mode 100644
index 0000000..0f82166
--- /dev/null
+++ b/program/icon1.ico
Binary files differ
diff --git a/program/resource.h b/program/resource.h
new file mode 100644
index 0000000..0d84a3e
--- /dev/null
+++ b/program/resource.h
@@ -0,0 +1,36 @@
+//{{NO_DEPENDENCIES}}
+// Microsoft Developer Studio generated include file.
+// Used by Program.rc
+//
+#define IDS_PROJNAME 100
+#define IDR_Program 100
+#define IDD_MONITORDLG 101
+#define IDC_VALUE 201
+#define IDI_KEYBOARD 202
+#define IDC_ONTOP 202
+#define IDB_NUMBERS 203
+#define IDC_AVERAGE 203
+#define IDB_0 204
+#define IDB_1 205
+#define ID_TRAY_WPM 205
+#define IDB_2 206
+#define IDB_3 207
+#define IDB_4 208
+#define IDB_5 209
+#define IDB_6 210
+#define IDB_7 211
+#define IDB_8 212
+#define IDB_9 213
+#define ID_TRAY_SHOW 32768
+#define ID_TRAY_EXIT 32769
+
+// Next default values for new objects
+//
+#ifdef APSTUDIO_INVOKED
+#ifndef APSTUDIO_READONLY_SYMBOLS
+#define _APS_NEXT_RESOURCE_VALUE 216
+#define _APS_NEXT_COMMAND_VALUE 32770
+#define _APS_NEXT_CONTROL_VALUE 203
+#define _APS_NEXT_SYMED_VALUE 102
+#endif
+#endif