日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

用钩子函数实现鼠标动作录制

發(fā)布時間:2024/1/1 编程问答 31 豆豆
生活随笔 收集整理的這篇文章主要介紹了 用钩子函数实现鼠标动作录制 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

在日常的一些操作中,會遇到重復(fù)的鼠標(biāo)動作,類似按鍵精靈的軟件就會成為比較好的助手。這里借助網(wǎng)上查找的資料自己實(shí)現(xiàn)了一個簡單的鼠標(biāo)動作錄制軟件。
完成界面如圖:

錄制

錄制鼠標(biāo)動作首先需要截獲。鉤子函數(shù)是一種對Windows系統(tǒng)進(jìn)程進(jìn)行監(jiān)聽的函數(shù),可以用來截獲鼠標(biāo)、鍵盤的消息。鉤子函數(shù)的實(shí)現(xiàn)方法很多,這里借鑒的是一種比較簡單的方法,但是注意要在MFC中使用,我曾在控制臺程序下使用,會導(dǎo)致程序卡死,原因尚未知。
(參考:http://www.cnblogs.com/gongxijun/p/5043825.html
http://www.cnblogs.com/gongxijun/p/5043825.html)
關(guān)鍵回調(diào)函數(shù)如下:

LRESULT CALLBACK LowLevelMouseProc(INT nCode, WPARAM wParam, LPARAM lParam){CPoint _mousepoint;MSLLHOOKSTRUCT *pkbhs = (MSLLHOOKSTRUCT *)lParam;if(nCode == HC_ACTION && start_log){//鼠標(biāo)左擊 if (wParam == WM_LBUTTONDOWN){/* || wParam == WM_LBUTTONUP*/FILE*fp;if (!first_click){//第一次沒點(diǎn)過HWND h = ::GetForegroundWindow();hWnd = h;fopen_s(&fp, filename, "w");first_click = true;WCHAR name[100];::GetWindowText(h, name, 100);fprintf(fp, "%s\n", UnicodeToAnsi(name));fclose(fp);}fopen_s(&fp, filename, "a");if (is_time_count){int end = GetTickCount();fprintf(fp, "%d\n", end - time_count);time_count = end;}else{is_time_count = true;time_count = GetTickCount();}CPoint point;RECT rc;GetCursorPos(&point);GetWindowRect(hWnd, &rc);int x = point.x - rc.left;int y = point.y - rc.top;fprintf(fp, "%d %d\n", x, y);fclose(fp);}else if (first_click && (wParam == WM_RBUTTONDOWN || wParam == WM_RBUTTONUP)){//結(jié)束start_log = false;}}return CallNextHookEx(NULL, nCode, wParam, lParam); }

實(shí)現(xiàn)的功能是,從輸入框讀取要保存的文件名,然后在第一次點(diǎn)擊后開始錄制,把操作的窗口名保存到文件,然后保存坐標(biāo)。在之后每一次點(diǎn)擊,計算與之前的時間差(參考:http://blog.csdn.net/coder_xia/article/details/6566708)

運(yùn)行

運(yùn)行錄制文件中的數(shù)據(jù),只需要一些Windows的API即可實(shí)現(xiàn)鼠標(biāo)點(diǎn)擊:

char* A_p = UnicodeToAnsi(m_infile.GetBuffer());ifstream fin(A_p);if (fin.fail()){MessageBox(L"打開文件失敗!", NULL, MB_OK);return;}int x, y;char fname[100];fin >> fname;HWND hWnd;hWnd = FindWindowA(NULL, fname);if (!hWnd){MessageBox(L"窗口不存在!", NULL, MB_OK);return;}while (fin >> x >> y){LPARAM lParam = MAKELPARAM(x, y);::SendMessage(hWnd, WM_LBUTTONDOWN, MK_LBUTTON, lParam);Sleep(250);::SendMessage(hWnd, WM_LBUTTONUP, MK_LBUTTON, lParam);Sleep(250);int wait;if (fin >> wait){Sleep(wait);}else{break;}}fin.close();

但在對話框的函數(shù)中使用上述方法,會導(dǎo)致運(yùn)行后程序卡死,因此需要多線程編程,使二者運(yùn)行分離;同時,在將讀入的數(shù)據(jù)用一個數(shù)據(jù)結(jié)構(gòu)描述后再進(jìn)行運(yùn)行會使得運(yùn)行變得可控。

class mouse_act{HWND hWnd;std::vector<int>x;std::vector<int>y;std::vector<int>wait;int count = 0; public:mouse_act(HWND wd) :hWnd(wd){ ; }mouse_act(){ hWnd = NULL; }void add(int _x, int _y, int _wait = -1){x.push_back(_x);y.push_back(_y);wait.push_back(_wait);}void play(){if (!hWnd)return;LPARAM lParam = MAKELPARAM(x[count], y[count]);::SendMessage(this->hWnd, WM_LBUTTONDOWN, MK_LBUTTON, lParam);Sleep(250);::SendMessage(this->hWnd, WM_LBUTTONUP, MK_LBUTTON, lParam);Sleep(250);if (wait[count] > 0){Sleep(wait[count]);count++;}else{count = 0;}}void clear(){hWnd = NULL;}bool isNULL(){return hWnd == NULL;} };mouse_act act_player;

使用多線程的方法(參考:http://www.cnblogs.com/codingmengmeng/p/5913068.html),使其在全局變量控制下逐步運(yùn)行:

bool play_flag = false; DWORD WINAPI PlayMouseAction(LPVOID lpParamter){while(play_flag){act_player.play();}return 0; }

總結(jié)

以上是生活随笔為你收集整理的用钩子函数实现鼠标动作录制的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。