1.定义一个回调函数;
2.提供函数实现的一方在初始化的时候,将回调函数的函数指针注册给调用者;
3.当特定的事件或条件发生的时候,调用者使用函数指针调用回调函数对事件进行处理。
回调函数允许用户把需要调用的方法的指针作为参数传递给一个函数,以便该函数在处理相似事件的时候可以灵活的使用不同的方法。
SetTimer()、EnumWindow()等API
回调函数是继承自C语言的,在C++中,应只在与C代码建立接口或与已有的回调接口打交道时,才使用回调函数。除了上述情况,在C++中应使用虚拟方法或仿函数(functor),而不是回调函数。
http://baike.baidu.com/link?url=AWKsLnS0qdbKupmgSaO6kh_uBNTmcqrj_VffHMYX_VlkQHBT7zeRrVkcE7b6LqBydhAke_b1E0V49MVAnXf0Sq
钩子函数是Windows消息处理机制的一部分,通过设置“钩子”,应用程序可以在系统级对所有消息、事件进行过滤,访问在正常情况下无法访问的消息。钩子的本质是一段用以处理系统消息的程序,通过系统调用,把它挂入系统。
1.局部钩子:仅钩挂您自己进程的事件。
2.远程钩子:可以钩挂自己进程或其他进程的事件,远程钩子又分为两种:一种是系统级的全局钩子,一种是线程级的钩子。全局钩子函数需要定义在 DLL 中,线程级的钩子中经常用到 GetCurrentThreadID 函数来获取当前线程的ID。
当创建一个钩子时,WINDOWS会先在内存中创建一个数据结构,该数据结构包含了钩子的相关信息,然后把该结构体加到已经存在的钩子链表中去。新的钩子将加到老的前面。当一个事件发生时,如果安装的是一个局部钩子,自己进程中的钩子函数将被调用。如果是一个远程钩子,系统就必须把钩子函数插入到其他进程的地址空间,要做到这一点要求钩子函数必须在一个动态链接库中,所以如果想要使用远程钩子,就必须把该钩子函数放到动态链接库中去。
两个例外:工作日志钩子和工作日志回放钩子。这两个钩子的钩子函数必须在安装钩子的线程中。原因是:这两个钩子是用来监控比较底层的硬件事件的,既然是记录和回放,所有的事件就当然都是有先后次序的。所以如果把回调函数放在DLL中,输入的事件被放在几个线程中记录,所以我们无法保证得到正确的次序。
解决办法:把钩子函数放到单个的线程中,譬如安装钩子的线程。
http://baike.baidu.com/link?url=Q_baWz43zpCpxkqgTJhPgiwDD9LZ6XA-OIGw96hVJhXL7WnUWomdJBF92QgJTsFfqMfy9UIwmTrcgwyiI6xOU_
C语言中通过函数指针实现回调函数(Callback Function)
====== 首先使用typedef定义回调函数类型 ======
typedef void (*event_cb_t)(const struct event *evt, void *userdata);
上面的语句表示event_cb_t类型函数返回值类型为void类型。
====== 定义并实现一个函数用于注册回调函数 ======
int event_cb_register(event_cb_t cb, void *userdata);
static void my_event_cb(const struct event *evt, void *data)
{
/* do stuff and things with the event */
}
...
event_cb_register(my_event_cb, &my_custom_data);
...
由于非静态成员函数有一个额外的参数this指针,因此成员函数前面需要加上static。
struct event_cb
{
event_cb_t cb;
void *data;
};
struct event_cb *callback;
...
/* Get the event_cb that you want to execute */
callback->cb(event, callback->data);
http://blog.csdn.net/xiahouzuoxin/article/details/10163109