Using Hooks
The following code examples demonstrate how to perform the following tasks associated with hooks:
Installing and Releasing Hook Procedures
You can install a hook procedure by calling the SetWindowsHookEx function and specifying the type of hook calling the procedure, whether the procedure should be associated with all threads in the same desktop as the calling thread or with a particular thread, and a pointer to the procedure entry point.
You must place a global hook procedure in a DLL separate from the application installing the hook procedure. The installing application must have the handle to the DLL module before it can install the hook procedure. To retrieve a handle to the DLL module, call the LoadLibrary function with the name of the DLL. After you have obtained the handle, you can call the GetProcAddress function to retrieve a pointer to the hook procedure. Finally, use SetWindowsHookEx to install the hook procedure address in the appropriate hook chain. SetWindowsHookEx passes the module handle, a pointer to the hook-procedure entry point, and 0 for the thread identifier, indicating that the hook procedure should be associated with all threads in the same desktop as the calling thread. This sequence is shown in the following example.
HOOKPROC hkprcSysMsg;
static HINSTANCE hinstDLL;
static HHOOK hhookSysMsg; hinstDLL = LoadLibrary(TEXT("c:\\myapp\\sysmsg.dll"));
hkprcSysMsg = (HOOKPROC)GetProcAddress(hinstDLL, "SysMessageProc"); hhookSysMsg = SetWindowsHookEx(
WH_SYSMSGFILTER,
hkprcSysMsg,
hinstDLL,
0);
You can release a thread-specific hook procedure (remove its address from the hook chain) by calling the UnhookWindowsHookEx function, specifying the handle to the hook procedure to release. Release a hook procedure as soon as your application no longer needs it.
You can release a global hook procedure by using UnhookWindowsHookEx, but this function does not free the DLL containing the hook procedure. This is because global hook procedures are called in the process context of every application in the desktop, causing an implicit call to the LoadLibrary function for all of those processes. Because a call to the FreeLibrary function cannot be made for another process, there is then no way to free the DLL. The system eventually frees the DLL after all processes explicitly linked to the DLL have either terminated or called FreeLibrary and all processes that called the hook procedure have resumed processing outside the DLL.
An alternative method for installing a global hook procedure is to provide an installation function in the DLL, along with the hook procedure. With this method, the installing application does not need the handle to the DLL module. By linking with the DLL, the application gains access to the installation function. The installation function can supply the DLL module handle and other details in the call to SetWindowsHookEx. The DLL can also contain a function that releases the global hook procedure; the application can call this hook-releasing function when terminating.
Monitoring System Events
The following example uses a variety of thread-specific hook procedures to monitor the system for events affecting a thread. It demonstrates how to process events for the following types of hook procedures:
- WH_CALLWNDPROC
- WH_CBT
- WH_DEBUG
- WH_GETMESSAGE
- WH_KEYBOARD
- WH_MOUSE
- WH_MSGFILTER
The user can install and remove a hook procedure by using the menu. When a hook procedure is installed and an event that is monitored by the procedure occurs, the procedure writes information about the event to the client area of the application's main window.
#include <windows.h>
#include <strsafe.h>
#include "app.h" #pragma comment( lib, "user32.lib")
#pragma comment( lib, "gdi32.lib") #define NUMHOOKS 7 // Global variables typedef struct _MYHOOKDATA
{
int nType;
HOOKPROC hkprc;
HHOOK hhook;
} MYHOOKDATA; MYHOOKDATA myhookdata[NUMHOOKS]; HWND gh_hwndMain; // Hook procedures LRESULT WINAPI CallWndProc(int, WPARAM, LPARAM);
LRESULT WINAPI CBTProc(int, WPARAM, LPARAM);
LRESULT WINAPI DebugProc(int, WPARAM, LPARAM);
LRESULT WINAPI GetMsgProc(int, WPARAM, LPARAM);
LRESULT WINAPI KeyboardProc(int, WPARAM, LPARAM);
LRESULT WINAPI MouseProc(int, WPARAM, LPARAM);
LRESULT WINAPI MessageProc(int, WPARAM, LPARAM); void LookUpTheMessage(PMSG, LPTSTR); LRESULT WINAPI MainWndProc(HWND hwndMain, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
static BOOL afHooks[NUMHOOKS];
int index;
static HMENU hmenu; gh_hwndMain = hwndMain; switch (uMsg)
{
case WM_CREATE: // Save the menu handle hmenu = GetMenu(hwndMain); // Initialize structures with hook data. The menu-item identifiers are
// defined as 0 through 6 in the header file app.h. They can be used to
// identify array elements both here and during the WM_COMMAND message. myhookdata[IDM_CALLWNDPROC].nType = WH_CALLWNDPROC;
myhookdata[IDM_CALLWNDPROC].hkprc = CallWndProc;
myhookdata[IDM_CBT].nType = WH_CBT;
myhookdata[IDM_CBT].hkprc = CBTProc;
myhookdata[IDM_DEBUG].nType = WH_DEBUG;
myhookdata[IDM_DEBUG].hkprc = DebugProc;
myhookdata[IDM_GETMESSAGE].nType = WH_GETMESSAGE;
myhookdata[IDM_GETMESSAGE].hkprc = GetMsgProc;
myhookdata[IDM_KEYBOARD].nType = WH_KEYBOARD;
myhookdata[IDM_KEYBOARD].hkprc = KeyboardProc;
myhookdata[IDM_MOUSE].nType = WH_MOUSE;
myhookdata[IDM_MOUSE].hkprc = MouseProc;
myhookdata[IDM_MSGFILTER].nType = WH_MSGFILTER;
myhookdata[IDM_MSGFILTER].hkprc = MessageProc; // Initialize all flags in the array to FALSE. memset(afHooks, FALSE, sizeof(afHooks)); return 0; case WM_COMMAND:
switch (LOWORD(wParam))
{
// The user selected a hook command from the menu. case IDM_CALLWNDPROC:
case IDM_CBT:
case IDM_DEBUG:
case IDM_GETMESSAGE:
case IDM_KEYBOARD:
case IDM_MOUSE:
case IDM_MSGFILTER: // Use the menu-item identifier as an index
// into the array of structures with hook data. index = LOWORD(wParam); // If the selected type of hook procedure isn't
// installed yet, install it and check the
// associated menu item. if (!afHooks[index])
{
myhookdata[index].hhook = SetWindowsHookEx(
myhookdata[index].nType,
myhookdata[index].hkprc,
(HINSTANCE) NULL, GetCurrentThreadId());
CheckMenuItem(hmenu, index,
MF_BYCOMMAND | MF_CHECKED);
afHooks[index] = TRUE;
} // If the selected type of hook procedure is
// already installed, remove it and remove the
// check mark from the associated menu item. else
{
UnhookWindowsHookEx(myhookdata[index].hhook);
CheckMenuItem(hmenu, index,
MF_BYCOMMAND | MF_UNCHECKED);
afHooks[index] = FALSE;
} default:
return (DefWindowProc(hwndMain, uMsg, wParam,
lParam));
}
break; //
// Process other messages.
// default:
return DefWindowProc(hwndMain, uMsg, wParam, lParam);
}
return NULL;
} /****************************************************************
WH_CALLWNDPROC hook procedure
****************************************************************/ LRESULT WINAPI CallWndProc(int nCode, WPARAM wParam, LPARAM lParam)
{
CHAR szCWPBuf[256];
CHAR szMsg[16];
HDC hdc;
static int c = 0;
size_t cch;
HRESULT hResult; if (nCode < 0) // do not process message
return CallNextHookEx(myhookdata[IDM_CALLWNDPROC].hhook, nCode, wParam, lParam); // Call an application-defined function that converts a message
// constant to a string and copies it to a buffer. LookUpTheMessage((PMSG) lParam, szMsg); hdc = GetDC(gh_hwndMain); switch (nCode)
{
case HC_ACTION:
hResult = StringCchPrintf(szCWPBuf, 256/sizeof(TCHAR),
"CALLWNDPROC - tsk: %ld, msg: %s, %d times ",
wParam, szMsg, c++);
if (FAILED(hResult))
{
// TODO: writer error handler
}
hResult = StringCchLength(szCWPBuf, 256/sizeof(TCHAR), &cch);
if (FAILED(hResult))
{
// TODO: write error handler
}
TextOut(hdc, 2, 15, szCWPBuf, cch);
break; default:
break;
} ReleaseDC(gh_hwndMain, hdc); return CallNextHookEx(myhookdata[IDM_CALLWNDPROC].hhook, nCode, wParam, lParam);
} /****************************************************************
WH_GETMESSAGE hook procedure
****************************************************************/ LRESULT CALLBACK GetMsgProc(int nCode, WPARAM wParam, LPARAM lParam)
{
CHAR szMSGBuf[256];
CHAR szRem[16];
CHAR szMsg[16];
HDC hdc;
static int c = 0;
size_t cch;
HRESULT hResult; if (nCode < 0) // do not process message
return CallNextHookEx(myhookdata[IDM_GETMESSAGE].hhook, nCode,
wParam, lParam); switch (nCode)
{
case HC_ACTION:
switch (wParam)
{
case PM_REMOVE:
hResult = StringCchCopy(szRem, 16/sizeof(TCHAR), "PM_REMOVE");
if (FAILED(hResult))
{
// TODO: write error handler
}
break; case PM_NOREMOVE:
hResult = StringCchCopy(szRem, 16/sizeof(TCHAR), "PM_NOREMOVE");
if (FAILED(hResult))
{
// TODO: write error handler
}
break; default:
hResult = StringCchCopy(szRem, 16/sizeof(TCHAR), "Unknown");
if (FAILED(hResult))
{
// TODO: write error handler
}
break;
} // Call an application-defined function that converts a
// message constant to a string and copies it to a
// buffer. LookUpTheMessage((PMSG) lParam, szMsg); hdc = GetDC(gh_hwndMain);
hResult = StringCchPrintf(szMSGBuf, 256/sizeof(TCHAR),
"GETMESSAGE - wParam: %s, msg: %s, %d times ",
szRem, szMsg, c++);
if (FAILED(hResult))
{
// TODO: write error handler
}
hResult = StringCchLength(szMSGBuf, 256/sizeof(TCHAR), &cch);
if (FAILED(hResult))
{
// TODO: write error handler
}
TextOut(hdc, 2, 35, szMSGBuf, cch);
break; default:
break;
} ReleaseDC(gh_hwndMain, hdc); return CallNextHookEx(myhookdata[IDM_GETMESSAGE].hhook, nCode, wParam, lParam);
} /****************************************************************
WH_DEBUG hook procedure
****************************************************************/ LRESULT CALLBACK DebugProc(int nCode, WPARAM wParam, LPARAM lParam)
{
CHAR szBuf[128];
HDC hdc;
static int c = 0;
size_t cch;
HRESULT hResult; if (nCode < 0) // do not process message
return CallNextHookEx(myhookdata[IDM_DEBUG].hhook, nCode,
wParam, lParam); hdc = GetDC(gh_hwndMain); switch (nCode)
{
case HC_ACTION:
hResult = StringCchPrintf(szBuf, 128/sizeof(TCHAR),
"DEBUG - nCode: %d, tsk: %ld, %d times ",
nCode,wParam, c++);
if (FAILED(hResult))
{
// TODO: write error handler
}
hResult = StringCchLength(szBuf, 128/sizeof(TCHAR), &cch);
if (FAILED(hResult))
{
// TODO: write error handler
}
TextOut(hdc, 2, 55, szBuf, cch);
break; default:
break;
} ReleaseDC(gh_hwndMain, hdc); return CallNextHookEx(myhookdata[IDM_DEBUG].hhook, nCode, wParam, lParam);
} /****************************************************************
WH_CBT hook procedure
****************************************************************/ LRESULT CALLBACK CBTProc(int nCode, WPARAM wParam, LPARAM lParam)
{
CHAR szBuf[128];
CHAR szCode[128];
HDC hdc;
static int c = 0;
size_t cch;
HRESULT hResult; if (nCode < 0) // do not process message
return CallNextHookEx(myhookdata[IDM_CBT].hhook, nCode, wParam,
lParam); hdc = GetDC(gh_hwndMain); switch (nCode)
{
case HCBT_ACTIVATE:
hResult = StringCchCopy(szCode, 128/sizeof(TCHAR), "HCBT_ACTIVATE");
if (FAILED(hResult))
{
// TODO: write error handler
}
break; case HCBT_CLICKSKIPPED:
hResult = StringCchCopy(szCode, 128/sizeof(TCHAR), "HCBT_CLICKSKIPPED");
if (FAILED(hResult))
{
// TODO: write error handler
}
break; case HCBT_CREATEWND:
hResult = StringCchCopy(szCode, 128/sizeof(TCHAR), "HCBT_CREATEWND");
if (FAILED(hResult))
{
// TODO: write error handler
}
break; case HCBT_DESTROYWND:
hResult = StringCchCopy(szCode, 128/sizeof(TCHAR), "HCBT_DESTROYWND");
if (FAILED(hResult))
{
// TODO: write error handler
}
break; case HCBT_KEYSKIPPED:
hResult = StringCchCopy(szCode, 128/sizeof(TCHAR), "HCBT_KEYSKIPPED");
if (FAILED(hResult))
{
// TODO: write error handler
}
break; case HCBT_MINMAX:
hResult = StringCchCopy(szCode, 128/sizeof(TCHAR), "HCBT_MINMAX");
if (FAILED(hResult))
{
// TODO: write error handler
}
break; case HCBT_MOVESIZE:
hResult = StringCchCopy(szCode, 128/sizeof(TCHAR), "HCBT_MOVESIZE");
if (FAILED(hResult))
{
// TODO: write error handler
}
break; case HCBT_QS:
hResult = StringCchCopy(szCode, 128/sizeof(TCHAR), "HCBT_QS");
if (FAILED(hResult))
{
// TODO: write error handler
}
break; case HCBT_SETFOCUS:
hResult = StringCchCopy(szCode, 128/sizeof(TCHAR), "HCBT_SETFOCUS");
if (FAILED(hResult))
{
// TODO: write error handler
}
break; case HCBT_SYSCOMMAND:
hResult = StringCchCopy(szCode, 128/sizeof(TCHAR), "HCBT_SYSCOMMAND");
if (FAILED(hResult))
{
// TODO: write error handler
}
break; default:
hResult = StringCchCopy(szCode, 128/sizeof(TCHAR), "Unknown");
if (FAILED(hResult))
{
// TODO: write error handler
}
break;
}
hResult = StringCchPrintf(szBuf, 128/sizeof(TCHAR), "CBT - nCode: %s, tsk: %ld, %d times ",
szCode, wParam, c++);
if (FAILED(hResult))
{
// TODO: write error handler
}
hResult = StringCchLength(szBuf, 128/sizeof(TCHAR), &cch);
if (FAILED(hResult))
{
// TODO: write error handler
}
TextOut(hdc, 2, 75, szBuf, cch);
ReleaseDC(gh_hwndMain, hdc); return CallNextHookEx(myhookdata[IDM_CBT].hhook, nCode, wParam, lParam);
} /****************************************************************
WH_MOUSE hook procedure
****************************************************************/ LRESULT CALLBACK MouseProc(int nCode, WPARAM wParam, LPARAM lParam)
{
CHAR szBuf[128];
CHAR szMsg[16];
HDC hdc;
static int c = 0;
size_t cch;
HRESULT hResult; if (nCode < 0) // do not process the message
return CallNextHookEx(myhookdata[IDM_MOUSE].hhook, nCode,
wParam, lParam); // Call an application-defined function that converts a message
// constant to a string and copies it to a buffer. LookUpTheMessage((PMSG) lParam, szMsg); hdc = GetDC(gh_hwndMain);
hResult = StringCchPrintf(szBuf, 128/sizeof(TCHAR),
"MOUSE - nCode: %d, msg: %s, x: %d, y: %d, %d times ",
nCode, szMsg, LOWORD(lParam), HIWORD(lParam), c++);
if (FAILED(hResult))
{
// TODO: write error handler
}
hResult = StringCchLength(szBuf, 128/sizeof(TCHAR), &cch);
if (FAILED(hResult))
{
// TODO: write error handler
}
TextOut(hdc, 2, 95, szBuf, cch);
ReleaseDC(gh_hwndMain, hdc); return CallNextHookEx(myhookdata[IDM_MOUSE].hhook, nCode, wParam, lParam);
} /****************************************************************
WH_KEYBOARD hook procedure
****************************************************************/ LRESULT CALLBACK KeyboardProc(int nCode, WPARAM wParam, LPARAM lParam)
{
CHAR szBuf[128];
HDC hdc;
static int c = 0;
size_t cch;
HRESULT hResult; if (nCode < 0) // do not process message
return CallNextHookEx(myhookdata[IDM_KEYBOARD].hhook, nCode,
wParam, lParam); hdc = GetDC(gh_hwndMain);
hResult = StringCchPrintf(szBuf, 128/sizeof(TCHAR), "KEYBOARD - nCode: %d, vk: %d, %d times ", nCode, wParam, c++);
if (FAILED(hResult))
{
// TODO: write error handler
}
hResult = StringCchLength(szBuf, 128/sizeof(TCHAR), &cch);
if (FAILED(hResult))
{
// TODO: write error handler
}
TextOut(hdc, 2, 115, szBuf, cch);
ReleaseDC(gh_hwndMain, hdc); return CallNextHookEx(myhookdata[IDM_KEYBOARD].hhook, nCode, wParam, lParam);
} /****************************************************************
WH_MSGFILTER hook procedure
****************************************************************/ LRESULT CALLBACK MessageProc(int nCode, WPARAM wParam, LPARAM lParam)
{
CHAR szBuf[128];
CHAR szMsg[16];
CHAR szCode[32];
HDC hdc;
static int c = 0;
size_t cch;
HRESULT hResult; if (nCode < 0) // do not process message
return CallNextHookEx(myhookdata[IDM_MSGFILTER].hhook, nCode,
wParam, lParam); switch (nCode)
{
case MSGF_DIALOGBOX:
hResult = StringCchCopy(szCode, 32/sizeof(TCHAR), "MSGF_DIALOGBOX");
if (FAILED(hResult))
{
// TODO: write error handler
}
break; case MSGF_MENU:
hResult = StringCchCopy(szCode, 32/sizeof(TCHAR), "MSGF_MENU");
if (FAILED(hResult))
{
// TODO: write error handler
}
break; case MSGF_SCROLLBAR:
hResult = StringCchCopy(szCode, 32/sizeof(TCHAR), "MSGF_SCROLLBAR");
if (FAILED(hResult))
{
// TODO: write error handler
}
break; default:
hResult = StringCchPrintf(szCode, 128/sizeof(TCHAR), "Unknown: %d", nCode);
if (FAILED(hResult))
{
// TODO: write error handler
}
break;
} // Call an application-defined function that converts a message
// constant to a string and copies it to a buffer. LookUpTheMessage((PMSG) lParam, szMsg); hdc = GetDC(gh_hwndMain);
hResult = StringCchPrintf(szBuf, 128/sizeof(TCHAR),
"MSGFILTER nCode: %s, msg: %s, %d times ",
szCode, szMsg, c++);
if (FAILED(hResult))
{
// TODO: write error handler
}
hResult = StringCchLength(szBuf, 128/sizeof(TCHAR), &cch);
if (FAILED(hResult))
{
// TODO: write error handler
}
TextOut(hdc, 2, 135, szBuf, cch);
ReleaseDC(gh_hwndMain, hdc); return CallNextHookEx(myhookdata[IDM_MSGFILTER].hhook, nCode, wParam, lParam);
}
The original address:http://msdn.microsoft.com/en-us/library/ms644960%28v=VS.85%29.aspx#system_events
Using Hooks的更多相关文章
- 使用 Git Hooks 实现自动项目部署
最近在某服务器上面搭建 git 开发和部署环境,git 开发环境很简单,按照 ProGit 一书的相关知识就可以轻松搞定,实现了类似 Github 的使用 SSH + 私有 Clone 的方式. 关于 ...
- CI框架之HOOKS使用流程及原理
Ci框架中Hooks可以理解:在框架的执行流程过程中,允许开发者在固定的某些时间点上(如:调用控制器前,调用控制器后等时间点上),调用其他函数来扩充CI框架执行流程的一种方法.技术上来就是通过 ...
- 深入浏览器兼容 细数jQuery Hooks 属性篇
关于钩子:http://www.cnblogs.com/aaronjs/p/3387906.html 本章的目的很简单,通过钩子函数更细节的了解浏览器差异与处理方案, 版本是2.0.3所以不兼容ie6 ...
- jQuery-1.9.1源码分析系列(七) 钩子(hooks)机制及浏览器兼容
处理浏览器兼容问题实际上不是jQuery的精髓,毕竟让技术员想方设法取弥补浏览器的过错从而使得代码乱七八糟不是个好事.一些特殊情况的处理,完全实在浪费浏览器的性能:突兀的兼容解决使得的代码看起来既不美 ...
- 如何创建一个GitLab Web Hooks?
Git Hooks Git 能在特定的重要动作发生时触发自定义的脚本. 这些脚本都被存储在 Git 目录下的 hooks 子目录中(.git/hooks).当 git init 初始化一个仓库时,Gi ...
- (翻译)Emacs Hooks
Table of Contents 1. 51.2.2 Hooks 51.2.2 Hooks Hooks(钩子或挂钩,为了保持文章的纯正性,这种专有名词不做翻译,后续以hooks为主),是定制化Ema ...
- ubantu svn 安装、卸载、配置hooks
1.安装之前先看是否已经安装了 svn -version 若已经安装会有以下提示,若没有安装,进行下一步 若想卸载了执行命令 ( sudo apt-get remove --purge subvers ...
- linux svn hooks代码自动更新至项目
由于开发移动端web,ui需要及时看到样式变化,所以通过svn hooks(钩子)来提交文件,然后再把文件同步到测试服务器项目目录,步骤如下: 1.进入 /home/svn/cmall/hooks ( ...
- php利用svn hooks将程序自动发布到测试环境
利用svn hooks将php程序自动发布到测试环境 复制仓库hooks目录下的post-commit.tmpl为post-commit cp post-commit.tmpl post-commit ...
- 配置hooks使svn提交后自动同步客户端代码(客户端与服务端在同一台机器上)
1.配置svn的hooks 2.实例演示 1.配置svn的hooks 1.1)配置情况 承接上篇svn搭建的文章,今次继续使用上篇文章的配置 上篇文章的地址:linux下搭建svn代码库 svn仓库所 ...
随机推荐
- MySQL: InnoDB 还是 MyISAM?
MyISAM存储引擎 MyISAM是 默认存储引擎.它基于更老的ISAM代码,但有很多有用的扩展.MyISAM存储引擎的一些特征:· 所有数据值先存储低字节.这使得数据机和操作系统分离.二进 ...
- spark概论
一.概述 1.轻:(1)采用语言简洁的scala编写:(2)利用了hadoop和mesos的基础设施 2.快:spark的内存计算.数据本地性和传输优化.调度优化,使其在迭代机器学习,ad-hoc ...
- 可以获取get post url 传递参数的统一方法
public static string objRequest(string requestName) { object obj = HttpContext.Current.Request[reque ...
- flask学习
安装环境: centos 6.3 python2.6 使用easy_install安装方式: [root@localhost ~]# easy_install flask 简单的hello from ...
- IE8中JSON.stringify方法对自动转换unicode字符的解决方案
IE8内置了JSON对象,用以处理JSON数据.与标准方法的不同,IE8的JSON.stringify会把utf-8字符转码: var str = "我是程序员" var json ...
- HTML5的placeholder属性如何实现换行
在HTML5中,placeholder是一个非常有用的属性,当控件中无内容时可以代替UI控件的提示功能,而不需要写额外的代码.但如果有一个textarea控件,我们需要多行的文本提示信息时,使用”\n ...
- android 下滤镜效果的实现
android 下滤镜效果的实现 滤镜过滤颜色已实现,简单版本可通过下面代码的3个参数实现黑白.红.绿...等7种过滤(RGB的7种组合). 理论上讲可以过滤为任意颜色.调整混合结果的比值就行了. p ...
- vnextcn
Flag 标题 通过 提交 AC% 难度 E1 编写Hello World网站 9 17 52% 1 E2 编写Hello World控制台程序 11 13 84% 1 E3 控制器基础练 ...
- ExpressJS File Uploading – GridFS – MongoDB
n this blog post we will see how to handle multipart data/file uploading with expressjs. Save files ...
- StatusBar & StatusBarItem
StatusBar & StatusBarItem StatusBar StatusBar class StatusBarItem StatusBarItem class Example &l ...