Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1944884
  • 博文数量: 383
  • 博客积分: 10011
  • 博客等级: 上将
  • 技术积分: 4061
  • 用 户 组: 普通用户
  • 注册时间: 2008-04-24 18:53
文章分类

全部博文(383)

文章存档

2011年(1)

2010年(9)

2009年(276)

2008年(97)

我的朋友

分类:

2009-04-05 17:16:28

    使用回调函数实际上就是在调用某个函数(通常是API函数)时,将自己的一个函数(这个函数为回调函数)的地址作为参数传递给那个函数。而那个函数在需要的时候,利用传递的地址调用回调函数,这时你可以利用这个机会在回调函数中处理消息或完成一定的操作。至于如何定义回调函数,跟具体使用的API函数有关,一般在帮助中有说明回调函数的参数和返回值等。C++中一般要求在回调函数前加CALLBACK(相当于FAR PASCAL),这主要是说明该函数的调用方式。

    至于钩子函数,只是回调函数的一个特例。习惯上把与SetWindowsHookEx函数一起使用的回调函数称为钩子函数。也有人把利用VirtualQueryEx安装的函数称为钩子函数,不过这种叫法不太流行。

    也可以这样,更容易理解:回调函数就好像是一个中断处理函数,系统在符合你设定的条件时自动调用。为此,你需要做三件事:

1. 声明;

2. 定义;
3. 设置触发条件,就是在你的函数中把你的回调函数名称转化为地址作为一个参数,以便于系统调用。

   声明和定义时应注意:回调函数由系统调用,所以可以认为它属于WINDOWS系统,不要把它当作你的某个类的成员函数。
 
VC 回调函数及使用方法

    回调函数说白了就是事件响应程序,Windows的每个消息可以理解为一个事件,事件的响应代码要由用户自己来定义。用户定义了事件响应的代码,但还要Windows知道这段代码的位置(要不然Windows就不知道如何去调用,这也没有用),于是用户需要将回调函数的指针告诉Windows,最典型的例子是在窗口类的结构(WNDCLASS)中给lpfnWndProc分量赋回调函数指针值。
    回调函数的参数格式是由回调函数的调用者(一般是Windows)来定义的,而回调函数的实现者必须遵循这种格式。Windows程序是以事件驱动模型为基础的,这就必然要用到回调函数这种机制。
    要透彻了解回调函数,多看看SDK Samples。而MFC中的消息映射机制已经将窗口消息响应的回调函数隐藏起来了,这也符合C++的编程思想,回调函数终究是一种全局函数,它不能在类中实现,而消息映射机制的目的是使消息响应的代码最终封装在窗口类(CWnd类的子类)中。

    如果有时间,不妨看看MESSAGE_MAP宏,消息映射是回调函数,只是这种回调函数的用法不同而已。普通的回调函数是要你提供地址,传进某个函数,由它去调用;而消息映射函数,却是由你定义函数,由MESSAGE_MAP宏去取得地址,并实现它的调用。

    回调函数是一个程序员不能显式调用的函数;通过将回调函数的地址传给调用者从而实现调用。要实现回调,必须首先定义函数指针。尽管定义的语法有点不可思议,但如果你熟悉函数声明的一般方法,便会发现函数指针的声明与函数声明非常类似。
CODE:
#include
void (*p) (); //p是指向某函数的指针
void func1()
{
        /* do something */
        printf("From func1(), Hello World!\n");
}
void caller(void(*ptrfunc1)())
{
        ptrfunc1(); /* 调用ptr指向的函数 */
}
int (*q) (int *); //q是指向某函数的指针
int func2(int* t_i)
{
        /* do something */
        printf("From func2() = %d, Hello World!\n", (*t_i)++);
        return 1;
}
void caller2(int (*ptrfunc2)(int *), int * i)
{
        ptrfunc2(i); /* 调用ptr指向的函数 */
}
int main(int argc, char* argv[])
{
        printf("From main(), Hello World!\n");
        printf("\n");
        //无参数调用
        p = func1; /* 传递函数地址 */
        caller(p); /* 传递函数地址到调用者 */
        //有参数调用
        int i = 0;
        int j;
        for (j = 0; j < 10; j++)
        {
              caller2(func2, &i); //* 传递函数地址到调用者 */
        }
        

        //有参数调用第二次
        i = 0;
        q = func2; /* 传递函数地址 */
        for(j=0;j<10;j++)
        {
                caller2(q, &i); /* 传递函数地址到调用者 */
        }
        printf("\n");
        printf("From main(), Hello World!\n");
        getchar();
        return 0;
}

运行结果:

From main(), Hello World!

From func1(), Hello World!
From func2() = 0, Hello World!
From func2() = 1, Hello World!
From func2() = 2, Hello World!
From func2() = 3, Hello World!
From func2() = 4, Hello World!
From func2() = 5, Hello World!
From func2() = 6, Hello World!
From func2() = 7, Hello World!
From func2() = 8, Hello World!
From func2() = 9, Hello World!
From func2() = 0, Hello World!
From func2() = 1, Hello World!
From func2() = 2, Hello World!
From func2() = 3, Hello World!
From func2() = 4, Hello World!
From func2() = 5, Hello World!
From func2() = 6, Hello World!
From func2() = 7, Hello World!
From func2() = 8, Hello World!
From func2() = 9, Hello World!
From main(), Hello World!

                                                                                                                                                                                                        
阅读(1240) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~