![]() |
![]() |
![]() |
![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() |
![]() |
![]() |
To access the contents, click the chapter and section titles.
Fast Track Visual C++ 6.0 Programming
Storing KeyDown and KeyUp MessagesWe handle WM_KEYDOWN messages first. LRESULT CALLBACK RecordProcedure(int nCode, WPARAM wParam, LPARAM lParam){ LRESULT Result = CallNextHookEx(Hook, nCode, wParam, lParam); if (nCode != HC_ACTION) return(Result); if(((PEVENTMSG) lParam)->message == WM_KEYDOWN){ ⇐ . . . } ⇐ If this is indeed a WM_KEYDOWN event, we store it in an array of events named EventArray[]. // JournalView.cpp : implementation of the CJournalView class // #include stdafx.h #include Journal.h #include JournalDoc.h
#include JournalView.h #ifdef _DEBUG #define new DEBUG_NEW #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif HHOOK Hook; EVENTMSG EventArray[2048]; ⇐ . . . We store the EVENTMSG structure pointed to by lParam in this array, increment the number of recorded events, and set the value passed back to Windows to 0, indicating that weve handled the event. LRESULT CALLBACK RecordProcedure(int nCode, WPARAM wParam, LPARAM lParam){ LRESULT Result = CallNextHookEx(Hook, nCode, wParam, lParam); if (nCode != HC_ACTION) return(Result); if(((PEVENTMSG) lParam)->message == WM_KEYDOWN){ ⇐ EventArray[RecordedEvents++] = *((PEVENTMSG) lParam); ⇐ Result = 0; ⇐ } ⇐ We record WM_KEYUP messages in the same way. LRESULT CALLBACK RecordProcedure(int nCode, WPARAM wParam, LPARAM lParam){ LRESULT Result = CallNextHookEx(Hook, nCode, wParam, lParam); if (nCode != HC_ACTION) return(Result); if(((PEVENTMSG) lParam)->message == WM_KEYDOWN){ EventArray[RecordedEvents++] = *((PEVENTMSG) lParam); Result = 0; } if(((PEVENTMSG) lParam)->message == WM_KEYUP){ ⇐ EventArray[RecordedEvents++] = *((PEVENTMSG) lParam); ⇐ Result = 0; ⇐ } ⇐ Finally, we check to see if weve recorded as many events as weve put aside space for in the EventArray[] array. If so, unhook the hook with UnhookWindowsHookEx() to make sure we dont go past our allocated memory. We also return the result weve set to Windows. LRESULT CALLBACK RecordProcedure(int nCode, WPARAM wParam, LPARAM lParam){ LRESULT Result = CallNextHookEx(Hook, nCode, wParam, lParam); if (nCode != HC_ACTION) return(Result); if(((PEVENTMSG) lParam)->message == WM_KEYDOWN){ EventArray[RecordedEvents++] = *((PEVENTMSG) lParam); Result = 0; } if(((PEVENTMSG) lParam)->message == WM_KEYUP){ EventArray[RecordedEvents++] = *((PEVENTMSG) lParam); Result = 0; } if (RecordedEvents >= 2048) ⇐ UnhookWindowsHookEx(Hook); ⇐ return(Result); ⇐ } That completes the recording process. Next, we play the keystrokes back in PlayProcedure(). Playing Events BackWhen the user plays keystrokes back, we execute the code in the PlayProcedure() function that were about to write. Add its prototype to our project now. // JournalView.h : interface of the CJournalView class // ///////////////////////////////////////////////////////////////////////////// #if !defined(AFX_JOURNALVIEW_H__6433B67B_A86C_11D1_887F_D42B07C10710__INCLUDED_) #define AFX_JOURNALVIEW_H__6433B67B_A86C_11D1_887F_D42B07C10710__INCLUDED_ #if _MSC_VER > 1000 #pragma once #endif // _MSC_VER > 1000 LRESULT CALLBACK RecordProcedure(int nCode, WPARAM wParam, LPARAM lParam); LRESULT CALLBACK PlayProcedure(int nCode, WPARAM wParam, LPARAM lParam); ⇐ . . . As we did in RecordProcedure(), we start PlayProcedure() by calling the next hook in the chain, if there is one, using CallNextHookEx(). LRESULT CALLBACK PlayProcedure(int nCode, WPARAM wParam, LPARAM lParam){ LRESULT Result = CallNextHookEx(Hook, nCode, wParam, lParam); ⇐ . . . We have to watch out for two event codes when playing back events: HC_GETNEXT and HC_SKIP. When PlayProcedure() is called with HC_GETNEXT, we should pass the next event were playing back to Windows by placing a pointer to that events EVENTMSG structure in lParam. When we get an HC_SKIP code, Windows is notifying us to skip to the next event and to get ready to play that one back. We start by handling the HC_GETNEXT code. Playing Back an EventTo play back an event, we first make sure the event code passed to us is HC_GETNEXT. LRESULT CALLBACK PlayProcedure(int nCode, WPARAM wParam, LPARAM lParam){ LRESULT Result = CallNextHookEx(Hook, nCode, wParam, lParam); switch(nCode){ ⇐ case HC_GETNEXT: ⇐ . . . If so, we should play back an event. You may recall that one of the members of the EVENTMSG structure holds the time the event occurred. The time weve recorded is the time the key was originally struck, which might have been some time ago, so we reset that time member to the current time with the GetTick-Count() function (Windows event times are stored in timer ticks) in case the program were playing keystrokes into relies on the time in some way. LRESULT CALLBACK PlayProcedure(int nCode, WPARAM wParam, LPARAM lParam){ LRESULT Result = CallNextHookEx(Hook, nCode, wParam, lParam); switch(nCode){ case HC_GETNEXT: EventArray[PlayedEvents].time = GetTickCount(); ⇐ . . . Next, we play back the event by copying it to the location the point in lParam points to, then set the result of PlayProcedure() to 0, indicating weve handled the call. LRESULT CALLBACK PlayProcedure(int nCode, WPARAM wParam, LPARAM lParam){ LRESULT Result = CallNextHookEx(Hook, nCode, wParam, lParam); switch(nCode){ case HC_GETNEXT: EventArray[PlayedEvents].time = GetTickCount(); *((PEVENTMSG) lParam) = EventArray[PlayedEvents]; ⇐ Result = 0; ⇐ break; ⇐ . . . Weve played back the event. The next step is to handle the HC_SKIP event code, which means we should skip to the next event. Skipping to the Next EventIf we get an HC_SKIP event code, we should skip on to the next event to play back. We do that simply by incrementing our PlayedEvents index. LRESULT CALLBACK PlayProcedure(int nCode, WPARAM wParam, LPARAM lParam){ LRESULT Result = CallNextHookEx(Hook, nCode, wParam, lParam); switch(nCode){ case HC_GETNEXT: EventArray[PlayedEvents].time = GetTickCount(); *((PEVENTMSG) lParam) = EventArray[PlayedEvents]; Result = 0; break; case HC_SKIP: ⇐ PlayedEvents++; ⇐ Result = 0; ⇐ break; ⇐ } . . .
|
![]() |
Products | Contact Us | About Us | Privacy | Ad Info | Home
Use of this site is subject to certain Terms & Conditions, Copyright © 1996-2000 EarthWeb Inc. All rights reserved. Reproduction whole or in part in any form or medium without express written permission of EarthWeb is prohibited. Read EarthWeb's privacy statement. |