11.04.2014 Views

Advanced MFC Programming

Advanced MFC Programming

Advanced MFC Programming

SHOW MORE
SHOW LESS

Create successful ePaper yourself

Turn your PDF publications into a flip-book with our unique Google optimized e-Paper software.

Chapter 13. Adding Special Features to Application<br />

implementing the playback, parameter code indicates what we need to do: if it is HC_SKIP, we need to get<br />

the next event for playback; if it is HC_GETNEXT, we need to copy the event to an EVENTMSG type object<br />

whose address can be obtained from parameter lParam. Here is how we get the next event when parameter<br />

code is HC_SKIP:<br />

……<br />

……<br />

if(code == HC_SKIP)<br />

{<br />

if(lpEventPlay->lpNextEvent == NULL)<br />

{<br />

free(lpEventHead);<br />

lpEventHead=lpEventPlay=NULL;<br />

UnsetJournalPlaybackHook();<br />

PostMessage(g_hWnd, uMsgFinishJournal, (WPARAM)TRUE, (LPARAM)NULL);<br />

}<br />

Here, if there is no more event, we need to reset everything and send a message (the message is a user<br />

defined message WM_FINISHJOURNAL, see below) to the mainframe window of the application indicating that<br />

the playback is over. If there are still events left, we get the next recorded event and free the buffers holding<br />

the event that is being played back. If parameter code is HC_GETNEXT, we need to obtain an EVENTMSG type<br />

pointer from parameter lParam, and copy the event pointed by lpEventPlay to the object pointed by this<br />

pointer. When doing this copy, we need to add an offset to the time stamp because originally it indicates the<br />

time when the events were recorded:<br />

……<br />

else<br />

{<br />

lpEventPlay=lpEventPlay->lpNextEvent;<br />

free(lpEventHead);<br />

lpEventHead=lpEventPlay;<br />

}<br />

}<br />

else if(code == HC_GETNEXT)<br />

{<br />

lpEvent=(LPEVENTMSG)lParam;<br />

lpEvent->message=lpEventPlay->Event.message;<br />

lpEvent->paramL=lpEventPlay->Event.paramL;<br />

lpEvent->paramH=lpEventPlay->Event.paramH;<br />

lpEvent->time=lpEventPlay->Event.time+dwTimeAdjust;<br />

lReturnValue=lpEvent->time-GetTickCount();<br />

if(lReturnValue < 0L)<br />

{<br />

lReturnValue=0L;<br />

lpEvent->time=GetTickCount();<br />

}<br />

return lReturnValue;<br />

}<br />

Using Functions Contained in DLL<br />

To notify the mainframe window about journal finishing event, a user registered message is used to<br />

communicate between the application and DLL. In the DLL, function ::RegisterMessage() is called after<br />

it is loaded, which will register WM_FINISHJOURNAL message in DLL. This message is also registered in the<br />

application’s CMainFrame::OnCreate(…) function. In the sample, two menu commands Macro | Record<br />

and Macro | Playback are added to the application. To avoid journal playback, journal record and<br />

keyboard hook from getting entangled, only one of the three hook related commands are enabled at any<br />

time. Besides this, playback hook could not be installed if journal record hook has not been installed. This<br />

is controlled by the following two variables declared in the application: CMainFrame::m_bEnableMenu,<br />

CMainFrame::m_bPlayAvailable.<br />

Installing and removing the hooks is simple. The following three functions show how the journal<br />

record hook and journal playback hook are implemented in the application. Here,<br />

CMainFrame::OnMacroRecord() implements command Macro | Record,<br />

422

Hooray! Your file is uploaded and ready to be published.

Saved successfully!

Ooh no, something went wrong!