Stworzyłem aplikacje która (teoretycznie) ma nagrywać a później odtwarzać konkretną akcje. skorzystałem z haków WH_JOURNALRECORD i WH_JOURNALPLAYBACK. Program się kompiluje i faktycznie nagrywa i odtwarza. Ale jak próbuje odtworzyć nagrany ruch myszką to wyskakuje mi po chwili bluescreen. Wie ktoś może jak zaradzić takiemu problemowi? Pracuje na Windowsie 7. Program korzysta z dll stworzonych przeze mnie. O to sam kod:
dll (.cpp)
BOOL APIENTRY DllMain (HMODULE hModule /* Library instance handle. */ ,
DWORD reason /* Reason this function is being called. */ ,
LPVOID reserved /* Not used. */ )
{
g_hInst = hModule;
switch (reason)
{
case DLL_PROCESS_ATTACH:
break;
case DLL_PROCESS_DETACH:
break;
case DLL_THREAD_ATTACH:
break;
case DLL_THREAD_DETACH:
break;
}
/* Returns TRUE on success, FALSE on failure */
return TRUE;
}
DLLIMPORT LRESULT CALLBACK RecordProc (int code, WPARAM wParam, LPARAM lParam)
{
if( code < 0 ) return CallNextHookEx( 0, code, wParam, lParam );
if( code == HC_ACTION )
{
EVENTMSG * msg =( EVENTMSG * ) lParam;
msg->time -= g_StartTime;
g_Events.push_back(* msg);
return 0;
}
return CallNextHookEx (0, code, wParam, lParam);
}
DLLIMPORT LRESULT CALLBACK PlaybackProc(int code, WPARAM wParam, LPARAM lParam)
{
if(code < 0) return CallNextHookEx(0, code, wParam, lParam);
if(code == HC_GETNEXT)
{
EVENTMSG * msg = (EVENTMSG *) lParam;
msg->hwnd = g_Events[g_CurrentEvent].hwnd;
msg->message = g_Events[g_CurrentEvent].message;
msg->paramH = g_Events[g_CurrentEvent].paramH;
msg->paramL = g_Events[g_CurrentEvent].paramL;
msg->time = g_StartTime + g_Events[g_CurrentEvent].time;
DWORD delta = msg->time - GetTickCount();
if(delta > 0) return delta;
else return 0;
}
else if(code == HC_SKIP)
{
if(!g_PlaybackStopped)
g_CurrentEvent++;
if(g_CurrentEvent >= g_Events.size() )
{
g_CurrentEvent = 0;
g_StartTime = GetTickCount();
g_PlaybackStopped = false;
return 0;
}
}
return 0;
}
DLLIMPORT void StartRecording()
{
g_StartTime=GetTickCount();
g_RecordHook = SetWindowsHookEx(WH_JOURNALRECORD, RecordProc, g_hInst, 0);
}
DLLIMPORT void StartPlayback()
{
g_CurrentEvent = 0;
g_StartTime = GetTickCount();
g_PlaybackStopped = false;
UnhookWindowsHookEx(g_RecordHook);
g_PlaybackHook= SetWindowsHookEx(WH_JOURNALPLAYBACK, PlaybackProc, g_hInst, 0);
}
dll (.h)
#ifndef _DLL_H_
#define _DLL_H_
#if BUILDING_DLL
# define DLLIMPORT __declspec (dllexport)
#else /* Not BUILDING_DLL */
# define DLLIMPORT __declspec (dllimport)
#endif /* Not BUILDING_DLL */
#include <windows.h>
#include <iostream>
#include <vector>
using namespace std;
class DLLIMPORT DllClass
{
public:
DllClass();
virtual ~DllClass(void);
private:
};
DLLIMPORT vector <EVENTMSG> g_Events;
DLLIMPORT int g_CurrentEvent;
DLLIMPORT bool g_PlaybackStopped;
DLLIMPORT HHOOK g_RecordHook = NULL;
DLLIMPORT HHOOK g_PlaybackHook = NULL;
DLLIMPORT DWORD g_StartTime = 0;
HINSTANCE g_hInst = NULL;
extern "C"
{
DLLIMPORT void StartRecording();
DLLIMPORT void StartPlayback();
}
#endif /* _DLL_H_ */
program (.cpp)
typedef void(* Voidfn)();
Voidfn g_Play = NULL;
Voidfn g_Record = NULL;
HINSTANCE g_hInstdll = NULL;
LRESULT CALLBACK WindowProcedure (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message) /* handle the messages */
{
case WM_KEYDOWN:
{//case
if(wParam == VK_F2)
{//if 3
g_Record();
}//if 3 end
else if(wParam == VK_F3)
{//if 3
g_Play();
}//if 3 end
}//case end
break;
case WM_DESTROY:
PostQuitMessage (0); /* send a WM_QUIT to the message queue */
break;
default: /* for messages that we don't deal with */
return DefWindowProc (hwnd, message, wParam, lParam);
}
return 0;
}
char szClassName[ ] = "WindowsApp";
int WINAPI WinMain (HINSTANCE hThisInstance,
HINSTANCE hPrevInstance,
LPSTR lpszArgument,
int nFunsterStil)
{
HWND hwnd; /* This is the handle for our window */
MSG messages; /* Here messages to the application are saved */
WNDCLASSEX wincl; /* Data structure for the windowclass */
/* The Window structure */
wincl.hInstance = hThisInstance;
wincl.lpszClassName = szClassName;
wincl.lpfnWndProc = WindowProcedure; /* This function is called by windows */
wincl.style = CS_DBLCLKS; /* Catch double-clicks */
wincl.cbSize = sizeof (WNDCLASSEX);
/* Use default icon and mouse-pointer */
wincl.hIcon = LoadIcon (NULL, IDI_APPLICATION);
wincl.hIconSm = LoadIcon (NULL, IDI_APPLICATION);
wincl.hCursor = LoadCursor (NULL, IDC_ARROW);
wincl.lpszMenuName = NULL; /* No menu */
wincl.cbClsExtra = 0; /* No extra bytes after the window class */
wincl.cbWndExtra = 0; /* structure or the window instance */
/* Use Windows's default color as the background of the window */
wincl.hbrBackground = (HBRUSH) COLOR_BACKGROUND;
/* Register the window class, and if it fails quit the program */
if (!RegisterClassEx (&wincl))
return 0;
/* The class is registered, let's create the program*/
hwnd = CreateWindowEx (
0, /* Extended possibilites for variation */
szClassName, /* Classname */
"Windows App", /* Title Text */
WS_OVERLAPPEDWINDOW, /* default window */
CW_USEDEFAULT, /* Windows decides the position */
CW_USEDEFAULT, /* where the window ends up on the screen */
544, /* The programs width */
375, /* and height in pixels */
HWND_DESKTOP, /* The window is a child-window to desktop */
NULL, /* No menu */
hThisInstance, /* Program Instance handler */
NULL /* No Window Creation data */
);
g_hInstdll = LoadLibrary("Lib/RecPlayLib");
if(g_hInstdll!=NULL)
{//if 1
MessageBox(0,"Udalo sie zaladowac biblioteki!", NULL, MB_OK);
g_Play = (Voidfn)GetProcAddress(g_hInstdll, "StartPlayback");
g_Record = (Voidfn)GetProcAddress(g_hInstdll, "StartRecording");
if(g_Play!=NULL && g_Record!=NULL)
{//if 2
MessageBox(0,"Udalo sie zaladowac Metody!", NULL, MB_OK);
} else MessageBox(0,"Nie udalo sie zaladowac Metody!", NULL, MB_OK); //if 2 end
}//if 1 end
else MessageBox(0,"nie udalo sie zaladowac biblioteki!", NULL, MB_OK);
/* Make the window visible on the screen */
ShowWindow (hwnd, nFunsterStil);
/* Run the message loop. It will run until GetMessage() returns 0 */
while (GetMessage (&messages, NULL, 0, 0))
{
/* Translate virtual-key messages into character messages */
TranslateMessage(&messages);
/* Send message to WindowProcedure */
DispatchMessage(&messages);
}
/* The program return-value is 0 - The value that PostQuitMessage() gave */
return messages.wParam;
}
Przy okazji może ktoś poleciłby książkę taką troche bardziej zaawansowaną do nauki i najlepiej książkę z ćwiczeniami z programowania (najlepiej zawierającą głównie programowanie obiektowe + struktury danych)