Delphi句柄类型计时器及回调函数

windodws.pas中 HWND = type LongWord;windows.pas中THandle定义:THandle = System.THandle; 而在system单元中,定义THandle = LongWord; windows.pas中 HDC = type LongWord;也就是说delphi中这三个实际上都是longword,定义出这么三个东西来, 是为了与 windows api配合,因为程序是在windows的平台上开发的,要调用windows 的API,而在windowsAPI中定义了这么个类型。 在windows系统中,HDC Handle to a device context (DC). 即指向一个设备上下文(device context 设备描述表:要在窗口中输出文字或者显示图形,就需要用到设备描述表,即DC。DC是一个包含设备(物理输出设备,如显示器,以及设备驱动程序)信息的结构体,在Windows平台下,所有的图形操作都是利用DC来完成的。设备描述表是一个Windows数据结构,它包含了一个设备(比如显示器打印机)绘图属性的相关信息。所有的绘图操作的调用都是通过一个设备描述表类型的对象来实现,这个类对象封装了Windows API(Application Programming Interface,应用程序编程接口)函数中关于划线、作图输入输出文本的的相关操作。设备描述表允许在窗口上进行与设备无关的绘图操作,设备描述表可以用在往屏幕、打印机或者图元文件的绘图操作。设备描述表旗下有4个常用DC类,他们分别是CPaintDC,CClientDC,CWindowDCCMetaFileDC)。HWND Handle to a window. 是一个窗口句柄。 THandle是delphi的东西,windows自己没有定义。handle属性是Delphi封装的上述各种句柄,对不同对象是不同类型,如:Form1.handle,Application.handle是窗口句柄;Canvas1.handle是设备环境句柄。Brush1.handle是画刷句柄等。

HWND就是句柄的类型(其实就是个cardinal),Windows利用它来标识资源(画笔,窗体,控件==);Handle则是一个句柄, Self.Handle 就是当前窗口的句柄,一般来说 句柄为0是无效的。HWND,THANDLE在数据类型上没有区别可以混用.但Windwos约定是返回THANDLE的一般需要CloseHandle来关闭句柄.也就是说THANDLE就是内核对象的句柄.而HWND一般就是窗口等普通句柄。

WinAPI函数都是靠句柄来访问各种可视化 非可视化对象不同对象的句柄都是不同的

if Handle <> 0 then //判断句柄有效

begin

TopWindow := GetLastActivePopup(Handle); //获得当前窗口的最上层窗口

if (TopWindow <> 0) and IsWindowVisible(TopWindow){如果可见} and IsWindowEnabled(TopWindow){如果没有被禁用} then

SetForegroundWindow(TopWindow); {把TopWindow推至前台}

定时器API SetTimer

delphi实现延时的方法,很多人首先就想到用timer控件,其实使用API来做定时器也很简单,主要就是一个SetTimer函数和KillTimer函数,

例如:settimer(self.handle,0,1000,@timerfun);

参数依次为:

1.调用函数的handle,windows会定时发送WM_TIMER消息给此handle

2.timer的标识,可设置为0

3.定时器的值,单位是毫秒

4.回调函数

其中SetTimer的第二个参数是这个定时器的ID,以便和其他的定时器区别开,第三个参数是时间间隔,以毫秒为单位。第四个参数是一个回调函数,每次定时的时间一到,这个定时器便会通过第四个参数所传过来的地址去找到这个函数并执行。

例子1:

var

i :Integer = 0;

procedure TimerProc(hwnd:HWND;uMsg,idEvent:UINT;dwTime:DWORD); stdcall;

begin

inc(i);

Form1.Caption := IntToStr(i);

end;

procedure TForm1.FormCreate(Sender:TObject);

begin

SetTimer(Handle,10,500,@TimerProc);

end;

procedure TForm1.FormDestroy(Sender:TObject);

begin

KillTimer(Handle,10);

end;

例子2:

//回调函数:当定时器到点后,就会调用该函数,该函数的格式有一定的讲究,可以参照以下写:

procedure TimerProc(hwnd:HWND;uMsg,idEvent:UINT;dwTime:DWORD); stdcall;

begin

showmessage('到点了');

killtimer(handle, idEvent);//关闭定时器

end;

//主函数:在主函数里定义定时器并开始运作:比如在一个按纽事件里写:

procedure TForm1.Button1Click(Sender: TObject);

var

identer:integer;

begin

identer:=settimer(0,0,2000,@timerfun);//两秒

if identer=0 then //定时器没有创建成功。

exit;

end;

Delphi 回调函数及例子

甲要托乙办件事,乙说:"行,把你的电话号码告诉我,我办好了通知你"(乙的函数申明)。于是甲告诉了乙他的电话号码(回调函数),乙在事情办好之后播打该电话(进行回调)通知甲。其实就是和C#里面的委托一个事件是一回事情。举个简单的例子:比如说,你要调用一个dll。按照一般的方法,只有主程序调用dll里面的过程。但是,如果你在dll里面要调用主程序的过程怎么办?这就是回调,主程序把某个过程的地址告诉dll。dll需要调用时,就通过这个地址来调用。

回调函数是应用程序提供给Windows系统DLL或其它DLL调用的函数,一般用于截获消息、获取系统信息或处理异步事件。应用程序把回调函数的地址指针告诉DLL,而DLL在适当的时候会调用该函数。回调函数必须遵守事先规定好的参数格式和传递方式,否则DLL一调用它就会引起程序或系统的崩溃。通常情况下,回调函数采用标准WindowsAPI的调用方式,即__stdcall,当然,DLL编制者可以自己定义调用方式,但客户程序也必须遵守相同的规定。在__stdcall方式下,函数的参数按从右到左的顺序压入堆栈,除了明确指明是指针或引用外,参数都按值传递,函数返回之前自己负责把参数从堆栈中弹出。

理解回调函数!

程序在调用一个函数(function)时(通常指api).相当于程序(program)呼叫(Call)了一个函数(function)关系表示如下:

call(调用)

program --------------------→ dll

程序在调用一个函数时,将自己的函数的地址作为参数传递给程序调用的函数时(那么这个自己的函数称回调函数).需要回调函数的 DLL 函数往往是一些必须重复执行某些操作的函数.关系表示如下:

call(调用)

program --------------------→ dll

↑ ¦

¦_______________________________¦

callback(回调)

当你调用的函数在传递返回值给回调函数时,你就可以利用回调函数来处理或完成一定的操作。至于如何定义自己的回调函数,跟具体使用的API函数有关,很多不同类别的回调函数有各种各样的参数,有关这些参数的描述一般在帮助中有说明回调函数的参数和返回值等.其实简单说回调函数就是你所写的函数满足一定条件后,被DLL调用!

也有这样的说法(比较容易理解):

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

1. 声明;

2. 定义;

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

回调函数就是通过函数的指针来调用的函数。对于一个传递给其他函数的参数,如果你传递的是一个函数的指针(也就是地址),当这个指针被用来调用这个函数时,就可以说是构造了一个回调函数。就是你把自定义函数地址给别人,别人调用你的函数。回调函数是由你自己写的。你需要调用另外一个函数,而这个函数的其中一个参数,就是你的这个回调函数名。这样,系统在必要的时候,就会调用你写的回调函数,这样你就可以在回调函数里完成你要做的事。

1. 回调函数是由开发者按照一定的原型进行定义的函

2. 回调函数并不由开发者直接调用执行

3 .回调函数通常作为参数传递给系统API,由该API来调用。

4. 回调函数可能被系统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;

完整例子:

type

TCallbackFunc = procedure ();stdcall;

procedure AFunc(Callback: TCallbackFunc);

begin

ShowMessage('AFunc 1');

Callback;

ShowMessage('AFunc 2');

Callback;

end;

procedure MyCallback();stdcall;//回调函数

begin

ShowMessage('Callback function');

end;

procedure TForm1.FormCreate(Sender: TObject);

begin

AFunc(MyCallback);

end;