【IPC-钩子】WM_COPYDATA和鼠标钩子小程序
【IPC-鉤子】WM_COPYDATA和鼠標鉤子小程序
作者:? 來自:? 閱讀次數(shù): 218 [大 中 小]
--------------------------------------------------------------------------------
?
? WM_COPYDATA和鼠標鉤子的簡單例子
作者:enoloo
這個小程序創(chuàng)建了一個全局鼠標鉤子,獲取目標窗口的一些屬性,然后通過WM_COPYDATA將結果傳遞給主程序。程序效果和部分代碼如下:
===========================================================
/*
*文件名:mouse_hook.h
*使用:鉤子dll和程序共同使用
*用途:申明鉤子類,消息結構
*/
class AFX_EXT_CLASS Cmousehook:public CObject //AFX_EXT_CLASS輸出類
{
public:
?Cmousehook();
?~Cmousehook();
?//設置鉤子
?BOOL starthook(HWND hWnd);
?//取消鉤子
?BOOL stophook();
};
#define SIZETEXT 100
struct Msg
{
?HWND hwnd;??? //窗口句柄
?LONG style;????? //窗口樣式
?LONG exstyle;??? //擴展樣式
?char caption[SIZETEXT];? //窗口名
?char parentcaption[SIZETEXT]; //父窗口名
?char classname[SIZETEXT];? //類名
?DWORD threadid;?? //線程id
?DWORD processid;?? //進程id
};
?
1,dll程序部分:
===========================================================
//mouse_hook.cpp[部分]
#pragma data_seg("shared")
HWND? g_hwnd = NULL;? //主程序的窗口句柄,用于給主程序發(fā)送消息
//臨時窗口句柄,避免在同一個窗口中多次激發(fā)鼠標消息發(fā)送到程序
HWND? g_prehwnd = NULL;
??
HHOOK g_hook = NULL;? //鉤子句柄
Msg msg = {0};? //上面頭文件定義的消息,傳遞給主程序
#pragma data_seg()
#pragma comment(linker,"/SECTION:shared,rws")
//實例句柄
HINSTANCE g_hInstance = NULL;
?
//給主程序用SendMessage發(fā)送WM_COPYDATA消息
BOOL SendMsg(HWND hwnd,LONG style,LONG exstyle,DWORD tid,DWORD pid,char* buf1,char* buf2,char* buf3)
{
?Msg msg;
?msg.hwnd = hwnd;
?msg.style = style;
?msg.exstyle = exstyle;
?msg.threadid = tid;
?msg.processid = pid;
?strcpy(msg.caption,buf1);? //窗口文本
?strcpy(msg.parentcaption,buf2); //父窗口文本
?strcpy(msg.classname,buf3);? //窗口類名
?if(IsWindow(g_hwnd))
?{
?
? COPYDATASTRUCT cs;
? cs.cbData = sizeof(Msg); //發(fā)送數(shù)據(jù)cs.lpData的大小
? cs.dwData = 0;? //現(xiàn)在沒有使用
? cs.lpData = &msg;? //要發(fā)送的數(shù)據(jù)指針
? //發(fā)送消息給主程序
? return SendMessage(g_hwnd,WM_COPYDATA,(WPARAM)hwnd,(LPARAM)&cs);
?
?}
?return false;
}
Cmousehook::Cmousehook()
{
}
Cmousehook::~Cmousehook()
{
?stophook();
}
//開啟鼠標鉤子
BOOL Cmousehook::starthook(HWND hwnd)
{
?ASSERT(hwnd);
?//全局鉤子
?g_hook = SetWindowsHookEx(WH_MOUSE,HOOKPROC(hookproc),g_hInstance,0);
?if(!g_hook)
?{
? return false;
?}
?g_hwnd = hwnd;
?return true;
}
LRESULT WINAPI hookproc(int code,WPARAM wParam,LPARAM lParam)
{
?ASSERT(g_hook);
?char buf1[SIZETEXT]; //存儲窗口文字
?char buf2[SIZETEXT]; //存儲父窗口文字
?char buf3[SIZETEXT]; //存儲類名
?DWORD tid;? //線程id
?DWORD pid;? //進程id
?LONG style;? //窗口樣式
?LONG exstyle;? //窗口擴充樣式
?
?
?HWND htarget;
?HWND htarget2;
?//遠指針
?LPMOUSEHOOKSTRUCT pMouseHook = (MOUSEHOOKSTRUCT FAR *) lParam;
?if (code >= 0)
?{
? htarget = pMouseHook->hwnd;
? if(htarget != g_prehwnd)
? {
?? GetWindowText(htarget,buf1,SIZETEXT);
?? style = GetWindowLong(htarget,GWL_STYLE);
?? exstyle = GetWindowLong(htarget,GWL_EXSTYLE);
?? tid = GetWindowThreadProcessId(htarget,&pid);
?? pid = pid;???? //獲得進程id
?? GetClassName(htarget,buf3,SIZETEXT); //獲得類名
?? htarget2 = htarget;??? //暫時保存句柄
?? HWND hparent = htarget;
?? while (hparent !=NULL)?? //獲得父窗口句柄
?? {
??? htarget = hparent;
??? hparent = GetParent(htarget);
?? }
?? GetWindowText(htarget,buf2,100);
?? //給主程序發(fā)送消息
?? SendMsg(htarget2,style,exstyle,tid,pid,buf1,buf2,buf3);
?? g_prehwnd = htarget2;
? }
?}
?return CallNextHookEx(g_hook,code,wParam,lParam);
}
2,測試程序部分:
===========================================================
//mousehook_testDlg.cpp[部分]
#pragma comment(lib,"mouse_hook.lib") //dll庫
Cmousehook g_hook;??? //定義鉤子對象
//在程序初始化的時候,設置鉤子
g_hook.starthook(GetSafeHwnd());
//程序退出的時候,卸載鉤子
g_hook.stophook();
//接收從鉤子dll傳過來的數(shù)據(jù)
BOOL CMousehook_testDlg::OnCopyData(CWnd* pWnd, COPYDATASTRUCT* pCopyDataStruct)
{
?// TODO: Add your message handler code here and/or call default
?Msg* pmsg =(Msg*)(pCopyDataStruct->lpData);
?CString str;
?str.Format("%d",pmsg->hwnd);
?m_list.SetItemText(0,1,str);
?str.Format("%d",pmsg->style);
?m_list.SetItemText(1,1,str);
?str.Format("%d",pmsg->exstyle);
?m_list.SetItemText(2,1,str);
?str.Format("%d",pmsg->threadid);
?m_list.SetItemText(3,1,str);
?str.Format("%d",pmsg->processid);
?m_list.SetItemText(4,1,str);
?m_list.SetItemText(5,1,pmsg->classname);
?m_list.SetItemText(6,1,pmsg->caption);
?m_list.SetItemText(7,1,pmsg->parentcaption);
?return CDialog::OnCopyData(pWnd, pCopyDataStruct);
}
===========================================================
3,說明:
WM_COPYDATA消息能夠在進程間通信。可以通過一個這樣的結構給目標進程通信:
typedef struct tagCOPYDATASTRUCT {
??? ULONG_PTR dwData;?? //發(fā)送的附帶信息
??? DWORD???? cbData;?? //發(fā)送數(shù)據(jù)的大小
??? PVOID???? lpData;?? //要發(fā)送的數(shù)據(jù)指針
} COPYDATASTRUCT, *PCOPYDATASTRUCT;
目標進程要接受處理數(shù)據(jù),添加WM_COPYDATA消息的處理,
afx_msg BOOL OnCopyData(CWnd* pWnd, COPYDATASTRUCT* pCopyDataStruct);
其中,pCopyDataStruct包含剛才介紹的那個結構,lpData中是你發(fā)送的數(shù)據(jù)。
需要注意的是,WM_COPYDATA消息保證發(fā)送的數(shù)據(jù)從原進程拷貝到目標進程。但是,WM_COPYDATA消息不能發(fā)送HDC,HBITMAP之類的東西,他們對于目標進程來說是無效的。目標進程拿到這些數(shù)據(jù)不能在原進程作任何事情,因為他們屬于不同的進程。
關于全局鉤子。如果系統(tǒng)中的一個線程創(chuàng)建了一個全局鼠標鉤子,當鼠標移動到系統(tǒng)中某個進程擁有的窗口下的時候,系統(tǒng)首先要判斷鉤子處理程序hookproc所在的dll有沒有映射到這個進程,如果沒有,則強制映射這個dll到進程地址空間。
所以,給主程序發(fā)送消息的dll可能各不相同。那么這些dll之間怎么溝通?這需要dll共享數(shù)據(jù)段。
===========================================================
#pragma data_seg("shared")
HWND? g_hwnd = NULL;? //主程序的窗口句柄,用于給主程序發(fā)送消息
//臨時窗口句柄,避免在同一個窗口中多次激發(fā)鼠標消息發(fā)送到程序
HWND? g_prehwnd = NULL;
??
HHOOK g_hook = NULL;? //鉤子句柄
Msg msg = {0};? //上面頭文件定義的消息,傳遞給主程序
#pragma data_seg()
#pragma comment(linker,"/SECTION:shared,rws")
===========================================================
比如上面的,g_hook是創(chuàng)建的鉤子句柄。因為整個系統(tǒng)并不是每個dll都有一個,所以應該是共享的,他在CallNextHookEx中用到,如果不共享,就會出錯;再比如g_hwnd,主程序傳遞給dll的句柄,放在共享區(qū)中,所有的dll用一個就行了;g_prehwnd是用來避免在一個窗口中重復向輸出窗口發(fā)送消息的(見代碼),如果把它移出來,你看看效果...
?
總結
以上是生活随笔為你收集整理的【IPC-钩子】WM_COPYDATA和鼠标钩子小程序的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Python4:DataStructur
- 下一篇: Python5:Script