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)