3个回答
展开全部
Delphi回调函数及其使用
1 回调函数的概述
回调函数是这样一种机制:调用者在初始化一个对象(这里的对象是泛指,包括OOP中的对象、全局函数等)时,将一些参数传递给对象,同时将一个调用者可以访问的函数地址传递给该对象。这个函数就是调用者和被调用者之间的一种通知约定,当约定的事件发生时,被调用者(一般会包含一个工作线程)就会按照回调函数地址调用该函数。
这种方式,调用者在一个线程,被调用者在另一个线程。
消息:
消息也可以看作是某种形式的回调,因为消息也是在初始化时由调用者向被调用者传递一个句柄和一个消息编号,在约定的事件发生时被调用者向调用者发送消息。
这种方式,调用者在主线程中,被调用者在主线程或者工作线程中。
Delphi事件模型:
在Delphi的VCL中有很多可视化组件都是使用事件模型,例如TForm的OnCreate事件,其原理是:在设计时指定事件函数,在运行时事件触发,则会调用在设计时指定的事件函数。
在机制上,Delphi事件模型与回调是一样的。但具体形式有些区别,纯的回调函数是全局函数的形式,而Delphi事件是对象方法的形式,即可以定义如下回调函数类型
type
TCallBackFunc = procedure (pData: Pointer) of object;
2 回调函数的使用说明
回调函数主要在两个场合使用,第一个是某些Windows的API要求用回调函数作为其参数地址,另一种是用户在某种特定的场合定义的某个函数需要使用回调函数作为其参数地址,对于用户的定义的函数来说,一般是当调用动态连接库中的函数时使用。
对于使用一个回调函数主要有以下几个步骤:
1、定义一个回调函数类型,跟一般的函数过程的定义并没有什么区别,但其定义必须根据需要满足回调函数的函数要求,唯一的区别在于在函数或过程的定义后面必须声明其为windows标准调用;
例:
type
THDFunction= function(I:integer;s:string):integer; stdcall;
对于过程的声明:
type
THDProcedure=procedure(s:string); stdcall;
2、 然后根据此原形定义一个相应的函数或过程,对于这个函数或过程来说名字没有什么要求,对函数其参数的类型和返回值的类型必须和定义的回调函数类型完全一致,对于过程来说,只需要其参数类型一样就可以了。
例:根据上面的函数和过程的原形定义一个相应的函数和一个相应的过程。
函数原形定义:
Function HdFunExample(k:integer,sExam:string):integer; stdcall;
过程定义:
procedure HdProExample(sExam:string);stdcall;
3、 在程序中实现此回调函数或着过程;
Function HdFunExample(k:integer,sExam:string):integer; stdcall;
Begin
End;
procedure HdProExample(sExam:string);stdcall;
begin
end;
4、 调用过程;
回调函数一般作为系统的某个函数的入口地址;
根据调用函数的原形:
假设有如下调用函数:
function DyHdFunExample(HdFun:THDFunction;I:integer):boolean;
注:
在调用函数中通过对函数指针的处理可以直接调用回调函数(即调用函数中的那个是回调函数类型的参数,直接操作它),使回调函数履行一定的操作。即在调用函数中实现回调函数的功能。
调用:
var
I:integer;
begin
I:=DyHdFunExample(@HdFunExample,i);
//…….
End;
3 举例说明
示例程序在H:\ 回调函数示例\ 目录下面。
回调函数的使用主要在于Windows原有的API函数,但对于用户的自定义的调用函数一般在于动态连接库中。常规的同一个工程下面一般不需要使用回调函数。(个人认为).。
1 回调函数的概述
回调函数是这样一种机制:调用者在初始化一个对象(这里的对象是泛指,包括OOP中的对象、全局函数等)时,将一些参数传递给对象,同时将一个调用者可以访问的函数地址传递给该对象。这个函数就是调用者和被调用者之间的一种通知约定,当约定的事件发生时,被调用者(一般会包含一个工作线程)就会按照回调函数地址调用该函数。
这种方式,调用者在一个线程,被调用者在另一个线程。
消息:
消息也可以看作是某种形式的回调,因为消息也是在初始化时由调用者向被调用者传递一个句柄和一个消息编号,在约定的事件发生时被调用者向调用者发送消息。
这种方式,调用者在主线程中,被调用者在主线程或者工作线程中。
Delphi事件模型:
在Delphi的VCL中有很多可视化组件都是使用事件模型,例如TForm的OnCreate事件,其原理是:在设计时指定事件函数,在运行时事件触发,则会调用在设计时指定的事件函数。
在机制上,Delphi事件模型与回调是一样的。但具体形式有些区别,纯的回调函数是全局函数的形式,而Delphi事件是对象方法的形式,即可以定义如下回调函数类型
type
TCallBackFunc = procedure (pData: Pointer) of object;
2 回调函数的使用说明
回调函数主要在两个场合使用,第一个是某些Windows的API要求用回调函数作为其参数地址,另一种是用户在某种特定的场合定义的某个函数需要使用回调函数作为其参数地址,对于用户的定义的函数来说,一般是当调用动态连接库中的函数时使用。
对于使用一个回调函数主要有以下几个步骤:
1、定义一个回调函数类型,跟一般的函数过程的定义并没有什么区别,但其定义必须根据需要满足回调函数的函数要求,唯一的区别在于在函数或过程的定义后面必须声明其为windows标准调用;
例:
type
THDFunction= function(I:integer;s:string):integer; stdcall;
对于过程的声明:
type
THDProcedure=procedure(s:string); stdcall;
2、 然后根据此原形定义一个相应的函数或过程,对于这个函数或过程来说名字没有什么要求,对函数其参数的类型和返回值的类型必须和定义的回调函数类型完全一致,对于过程来说,只需要其参数类型一样就可以了。
例:根据上面的函数和过程的原形定义一个相应的函数和一个相应的过程。
函数原形定义:
Function HdFunExample(k:integer,sExam:string):integer; stdcall;
过程定义:
procedure HdProExample(sExam:string);stdcall;
3、 在程序中实现此回调函数或着过程;
Function HdFunExample(k:integer,sExam:string):integer; stdcall;
Begin
End;
procedure HdProExample(sExam:string);stdcall;
begin
end;
4、 调用过程;
回调函数一般作为系统的某个函数的入口地址;
根据调用函数的原形:
假设有如下调用函数:
function DyHdFunExample(HdFun:THDFunction;I:integer):boolean;
注:
在调用函数中通过对函数指针的处理可以直接调用回调函数(即调用函数中的那个是回调函数类型的参数,直接操作它),使回调函数履行一定的操作。即在调用函数中实现回调函数的功能。
调用:
var
I:integer;
begin
I:=DyHdFunExample(@HdFunExample,i);
//…….
End;
3 举例说明
示例程序在H:\ 回调函数示例\ 目录下面。
回调函数的使用主要在于Windows原有的API函数,但对于用户的自定义的调用函数一般在于动态连接库中。常规的同一个工程下面一般不需要使用回调函数。(个人认为).。
已赞过
已踩过<
评论
收起
你对这个回答的评价是?
展开全部
推荐答案已经很好的,只对最后一句说说咱的认识——“常规的同一个工程下面一般不需要使用回调函数。(个人认为)”
回调函数的作用是接口,为什么用接口呢?原因就是具体想做的事儿或者做事儿的方法太多了,没办法穷举,所以留个口子让编程者自己去发挥。举例说明:
1、EnumWindow要求一个回调函数,是什么目的呢?枚举窗口是个挺复杂的活儿,要是自己动手实现,不但要了解操作系统底层知识,还需要精湛的编程技巧和大量编码,于是操作系统帮你做了这部分最有难度、最繁琐的活儿,它帮你把一个个窗口找到,然后问你,找到了,你想干什么,表达想干什么的程序代码才是你亲自编写的,编写在那个回调函数中。常见的企图是把找到的一个个窗口暂存起来,以备后用,后有何用?向窗口发各种各样的消息均是用法,比如说发关闭消息。哪怕是没有实际的动机,就是想溜溜操作系统,让它跑一圈,把结果告诉咱,咱啥也不干。
2、快速排序要求的回调函数:排序的一个基本操作是判断两个元素谁先谁后,这个逻辑可就多了,对于整数,有从大到小、从小到大,对于字符串,有按照串大小、串长度大小等,不可穷举,完全是用户的自由,提供快排算法的先贤不知道,只能留个口子,让你来实现。先贤的功绩在于把快排这个很复杂的算法框架给你包装好了,让你不需要了解算法细节就能高效地达到意图。举个罕见的例子:有时候我们需要的不是精致的排序结果,而是想要尽可能乱的顺序,对于一个文本文件,手工操作就是反复随便剪切一些行,再粘贴到随便的位置,编程实现怎么做呢?可以用快速排序,比较大小的回调函数返回随机正负数即可,结果就是一个字:乱;两个字就是:胡乱;四个字就是:乱七八糟。
以上两个例子,尤其是排序的例子,都有可能是同一个工程下需要的,所以说,回调函数的本质是接口,而不是用在哪里。
回调函数的作用是接口,为什么用接口呢?原因就是具体想做的事儿或者做事儿的方法太多了,没办法穷举,所以留个口子让编程者自己去发挥。举例说明:
1、EnumWindow要求一个回调函数,是什么目的呢?枚举窗口是个挺复杂的活儿,要是自己动手实现,不但要了解操作系统底层知识,还需要精湛的编程技巧和大量编码,于是操作系统帮你做了这部分最有难度、最繁琐的活儿,它帮你把一个个窗口找到,然后问你,找到了,你想干什么,表达想干什么的程序代码才是你亲自编写的,编写在那个回调函数中。常见的企图是把找到的一个个窗口暂存起来,以备后用,后有何用?向窗口发各种各样的消息均是用法,比如说发关闭消息。哪怕是没有实际的动机,就是想溜溜操作系统,让它跑一圈,把结果告诉咱,咱啥也不干。
2、快速排序要求的回调函数:排序的一个基本操作是判断两个元素谁先谁后,这个逻辑可就多了,对于整数,有从大到小、从小到大,对于字符串,有按照串大小、串长度大小等,不可穷举,完全是用户的自由,提供快排算法的先贤不知道,只能留个口子,让你来实现。先贤的功绩在于把快排这个很复杂的算法框架给你包装好了,让你不需要了解算法细节就能高效地达到意图。举个罕见的例子:有时候我们需要的不是精致的排序结果,而是想要尽可能乱的顺序,对于一个文本文件,手工操作就是反复随便剪切一些行,再粘贴到随便的位置,编程实现怎么做呢?可以用快速排序,比较大小的回调函数返回随机正负数即可,结果就是一个字:乱;两个字就是:胡乱;四个字就是:乱七八糟。
以上两个例子,尤其是排序的例子,都有可能是同一个工程下需要的,所以说,回调函数的本质是接口,而不是用在哪里。
已赞过
已踩过<
评论
收起
你对这个回答的评价是?
推荐律师服务:
若未解决您的问题,请您详细描述您的问题,通过百度律临进行免费专业咨询