Click here to Skip to main content
15,891,316 members
Articles / Desktop Programming / WTL

Screen Event Recorder DLL/Application

Rate me:
Please Sign up or sign in to vote.
4.91/5 (34 votes)
9 May 2003MIT3 min read 214.1K   4.4K   105  
Screen Event Recorder (DLL) shows how to create a DLL/Application (one that can be used with RunDll32.exe).
// PlayFileDlg.h: interface and implementation of the CPlayFileDlg class.
//
/////////////////////////////////////////////////////////////////////////////////


#include "stdafx.h"
#include <Shellapi.h> // Shell_NotifyIcon - note Shell32.dll is huge! > 8 Meg (XP)
#include "WndPlacement.h"
#include "EventManager.h"
#include "MacRcrdImport.h"

///////////////////////////////////////////////////////////////////////////////
#define WM_TRAYICONCLICK	WM_USER+0x0701
#define REG_KEY_WINDOW		_T("Software\\CodeAsm\\MacRcrd\\Window")
#define REG_KEY_LASTPOS		_T("Position")


class CPlayFileDlg : public CDialogImpl<CPlayFileDlg>,
					 public CEventManager
{
public:
	HICON m_hIcon;
	bool m_bAutoPlay;
	TCHAR m_szFileName[MAX_PATH];

public:
	enum { IDD = IDD_MACRCRD_DLG };

	CPlayFileDlg() : m_bAutoPlay(false), m_hIcon(0)
	{
		memset(m_szFileName,0,sizeof(m_szFileName));
	}

	virtual ~CPlayFileDlg()
	{
	}

	void SetAutoPlay(bool bAutoPlay) { m_bAutoPlay = bAutoPlay; }
	bool GetAutoPlay() { return m_bAutoPlay; }
	void SetFileName(LPCTSTR szFileName) { lstrcpyn(m_szFileName, szFileName, MAX_PATH); }

	BEGIN_MSG_MAP(CPlayFileDlg)
	MESSAGE_HANDLER(WM_INITDIALOG, OnInitDialog)
	COMMAND_HANDLER(IDC_BTN_RECORD, BN_CLICKED, OnRecordClicked)
	COMMAND_HANDLER(IDC_BTN_PLAY, BN_CLICKED, OnPlayClicked)
	COMMAND_HANDLER(IDC_BTN_BROWSE, BN_CLICKED, OnBrowseClicked)
	COMMAND_HANDLER(IDOK, BN_CLICKED, OnOK)
	MESSAGE_HANDLER(WM_SYSCOMMAND, OnSysCommand)
	MESSAGE_HANDLER(WM_TRAYICONCLICK, OnTrayIconClick)
	MESSAGE_HANDLER(WM_CANCELJOURNAL, OnCancelJournal)
	MESSAGE_HANDLER(WM_CLOSE, OnClose)
	MESSAGE_HANDLER(WM_DESTROY, OnDestroy)
	END_MSG_MAP()

	LRESULT OnInitDialog(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
	{
		// Show application on taskbar...
		ModifyStyleEx(0, WS_EX_APPWINDOW);

		// Set window icon
		m_hIcon = LoadIcon(_Module.GetResourceInstance(), MAKEINTRESOURCE(IDI_MACRCRD));
		SetIcon(m_hIcon, TRUE);
		SetIcon(m_hIcon, FALSE);

		// Initialize controls...
		SetDlgItemText(IDC_TXT_EVENTFILE, m_szFileName);
		SendDlgItemMessage(IDC_PLAY_LOOP_INC, UDM_SETRANGE32, (WPARAM)-1, (LPARAM)999);

		// Get windowplacement if exists
		CWindowPlacement wndPlacement;
		HKEY hKey;
		DWORD dwDisposition = 0;
		if (ERROR_SUCCESS == RegCreateKeyEx(HKEY_CURRENT_USER, REG_KEY_WINDOW, 0, NULL, 0,
							KEY_ALL_ACCESS, NULL, &hKey, &dwDisposition ))
		{
			if (wndPlacement.GetPosData(hKey, REG_KEY_LASTPOS))
				wndPlacement.SetPosData( m_hWnd );
			RegCloseKey( hKey );
		}
		
		// Auto play a file
		if ( GetAutoPlay() )
		{
			PostMessage(WM_COMMAND, MAKEWPARAM(IDC_BTN_PLAY, BN_CLICKED), NULL);
		}
		return 0;
	}
	LRESULT OnRecordClicked(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled)
	{
		if (!IsRecording())
		{
			// Get file name...
			GetDlgItemText(IDC_TXT_EVENTFILE, m_szFileName, MAX_PATH);
			bool bSkipMouse = SendDlgItemMessage(IDC_REC_MOUSE, BM_GETSTATE, 0, 0) == BST_CHECKED;
			bool bSkipKey = SendDlgItemMessage(IDC_REC_KEYBOARD, BM_GETSTATE, 0, 0) == BST_CHECKED;
			HRESULT hr = InstallRecorder((LONG_PTR)EventCallback, (LONG_PTR)this, EVTOBJECT_FUNCTION);
			if (SUCCEEDED(hr))
			{
				StartRecorder(bSkipMouse, bSkipKey);
				SetDlgItemText(IDC_BTN_RECORD, _T("Stop"));
				PostMessage(WM_SYSCOMMAND, SC_MINIMIZE, NULL);
				if (WaitForCancelJournal() < 0)
				{
					// Just Exit...
					UninstallRecorder();
					PostQuitMessage( 0 );
				}
			}
		}
		else {
			HRESULT hr = UninstallRecorder();
			StopRecorder( false );
			SetDlgItemText(IDC_BTN_RECORD, _T("Record"));
			if (m_szFileName[0] != 0)
				SaveEventFile( m_szFileName );
			OnRestore();
		}
		return 0;
	}
	LRESULT OnPlayClicked(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled)
	{
		if (!IsPlaying())
		{
			// Get file name...
			GetDlgItemText(IDC_TXT_EVENTFILE, m_szFileName, MAX_PATH);
			bool bSkipMouse = SendDlgItemMessage(IDC_PLAY_MOUSE, BM_GETSTATE, 0, 0) == BST_CHECKED;
			bool bSkipKey = SendDlgItemMessage(IDC_PLAY_KEYBOARD, BM_GETSTATE, 0, 0) == BST_CHECKED;
			BOOL bTranslated = FALSE;
			int nRepeat = (int) GetDlgItemInt(IDC_PLAY_LOOP, &bTranslated, TRUE);
			
			if (LoadEventFile( m_szFileName ))
			{
				HRESULT hr = InstallPlayer((LONG_PTR)EventCallback, (LONG_PTR)this, EVTOBJECT_FUNCTION);
				if (SUCCEEDED(hr))
				{
					StartPlayer( bSkipMouse, bSkipKey, nRepeat);
					SetDlgItemText(IDC_BTN_PLAY, _T("Stop"));
					PostMessage(WM_SYSCOMMAND, SC_MINIMIZE, NULL);
					if (WaitForCancelJournal() < 0)
					{
						// Just Exit...
						UninstallPlayer();
						PostQuitMessage( 0 );
					}
				}
			}
		}
		else {
			HRESULT hr = UninstallPlayer();
			StopPlayer();
			SetDlgItemText(IDC_BTN_PLAY, _T("Play"));
			OnRestore();
		}
		return 0;
	}
	LRESULT OnBrowseClicked(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled)
	{
		TCHAR szFile[MAX_PATH] = { 0 }; // buffer for file name

		// Initialize OPENFILENAME
		OPENFILENAME ofn = { 0 };		// common dialog box structure
		ofn.lStructSize = sizeof(OPENFILENAME);
		ofn.hwndOwner = m_hWnd;
		ofn.lpstrFile = szFile;
		ofn.nMaxFile = sizeof(szFile)/sizeof(TCHAR);
		ofn.lpstrFilter = _T("Event File\0*.evr\0All Files\0*.*\0");
		ofn.nFilterIndex = 1;
		ofn.lpstrFileTitle = NULL;
		ofn.nMaxFileTitle = 0;
		ofn.lpstrInitialDir = NULL;
		ofn.Flags  = OFN_CREATEPROMPT|OFN_PATHMUSTEXIST|OFN_FILEMUSTEXIST;
		ofn.Flags |= OFN_HIDEREADONLY |OFN_NONETWORKBUTTON;

		// Display the Open dialog box. 
		if (GetOpenFileName(&ofn) != FALSE)
		{
			SetDlgItemText(IDC_TXT_EVENTFILE, ofn.lpstrFile);
		}
		return 0;
	}
	LRESULT OnOK(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled)
	{
		EndDialog(IDOK);
		return 0;
	}
	LRESULT OnSysCommand(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
	{
		bHandled = FALSE;
		if (wParam == SC_MINIMIZE)
		{
			OnMinimize();
			bHandled = TRUE;
		}
		return 0;
	}
	LRESULT OnTrayIconClick(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
	{
		UINT uID = (UINT) wParam;
		UINT uMouseMsg = (UINT) lParam;

		if (uMouseMsg == WM_LBUTTONDOWN)
		{
			OnRestore();
		}
		return 0;
	}
	LRESULT OnCancelJournal(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
	{
		if (IsRecording())
			PostMessage(WM_COMMAND, MAKEWPARAM(IDC_BTN_RECORD, BN_CLICKED), NULL);
		if (IsPlaying())
			PostMessage(WM_COMMAND, MAKEWPARAM(IDC_BTN_PLAY, BN_CLICKED), NULL);
		return 0;
	}
	LRESULT OnClose(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
	{
		EndDialog(IDCANCEL);
		return 0;
	}
	LRESULT OnDestroy(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
	{
		CWindowPlacement wndPlacement( m_hWnd );
		HKEY hKey;
		if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_CURRENT_USER, REG_KEY_WINDOW, 0, KEY_WRITE, &hKey ))
		{
			wndPlacement.SetPosData(hKey, REG_KEY_LASTPOS);
			RegCloseKey( hKey );
		}
		TrayIconConfig(_T(""), NULL, FALSE);
		return 0;
	}
	///////////////////////////////////////////////////////////////////////////////
	// TrayIconConfig
	void TrayIconConfig(LPCTSTR szTip, HICON hIcon, BOOL bAddIcon)
	{
		NOTIFYICONDATA icondata;
		memset(&icondata, 0, sizeof(icondata));
		icondata.cbSize = sizeof(icondata);
		icondata.uID    = IDD_MACRCRD_DLG; // use the dialog id as the uID value
		icondata.hWnd   = m_hWnd;
		icondata.hIcon  = hIcon;
		_tcscpy(icondata.szTip, szTip);
		icondata.uCallbackMessage = WM_TRAYICONCLICK;
		icondata.uFlags = NIF_ICON|NIF_MESSAGE|NIF_TIP;
		::Shell_NotifyIcon((bAddIcon ? NIM_ADD : NIM_DELETE ), &icondata);
	}

	///////////////////////////////////////////////////////////////////////////////
	// OnMinimize
	void OnMinimize()
	{
		ShowWindow(SW_MINIMIZE);
		TrayIconConfig(_T("Event Recorder"), m_hIcon, TRUE);
		ShowWindow(SW_HIDE);
	}

	///////////////////////////////////////////////////////////////////////////////
	// OnRestore
	void OnRestore()
	{
		if (!IsWindowVisible())
		{
			ShowWindow(SW_SHOW);
		}

		ShowWindow(SW_RESTORE);
		TrayIconConfig(_T("Event Recorder"), NULL, FALSE);
	}
	///////////////////////////////////////////////////////////////////////////////
	// WaitForCancelJournal
	int WaitForCancelJournal()
	{
		MSG msg = { 0 };
		int nResult = 0;
		while( (nResult = GetMessage( &msg, NULL, 0, 0 )) > 0)
		{ 
			if (msg.message != WM_CANCELJOURNAL)
			{
				TranslateMessage(&msg);
				DispatchMessage(&msg);

				// break if not in recording or playback
				if (!IsRecording() && !IsPlaying())
					break;
			}
			else
			{
				PostMessage(WM_CANCELJOURNAL, NULL, NULL);
				MessageBeep(MB_ICONASTERISK);
				break; // just exit
			}
		}
		return nResult;
	}
	///////////////////////////////////////////////////////////////////////////////
	// EventCallback
	static LRESULT CALLBACK EventCallback(int nCode, WPARAM wParam, LPARAM lParam, LONG_PTR dwEventObjInstance)
	{
		LRESULT lRes = 0;
		CPlayFileDlg* pThis = reinterpret_cast<CPlayFileDlg*>( dwEventObjInstance );

		if (nCode != EVTMSG_STOPPED)
		{
			EventType event = static_cast<EventType>( (char)nCode );
			if (pThis->IsRecording())
				lRes = pThis->OnRecordEvent(event, lParam);
			else if (pThis->IsPlaying())
				lRes = pThis->OnPlayEvent(event, lParam);
		}

		if (lRes==-1 || nCode == EVTMSG_STOPPED) {
			if (pThis->IsRecording())
				::SendMessage(pThis->m_hWnd, WM_COMMAND, MAKEWPARAM(IDC_BTN_RECORD, BN_CLICKED), NULL);
			else if (pThis->IsPlaying())
				::SendMessage(pThis->m_hWnd, WM_COMMAND, MAKEWPARAM(IDC_BTN_PLAY, BN_CLICKED), NULL);
			lRes = 0;
		}

		return lRes;
	}
};

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The MIT License


Written By
Software Developer (Senior)
United States United States
Ernest is a multi-discipline software engineer.
Skilled at software design and development for all Windows platforms.
-
MCSD (C#, .NET)
Interests: User Interface, GDI/GDI+, Scripting, Android, iOS, Windows Mobile.
Programming Skills: C/C++, C#, Java (Android), VB and ASP.NET.

I hope you will enjoy my contributions.

Comments and Discussions