函数重载
重载的思想很简单:编译器允许你用同一名字定义多个函数或过程,只要它们所带的参数不同。实际上,编译器是通过检测参数来确定需要调用的例程。
下面是从VCL 的数学单元(Math Unit)中摘录的一系列函数:
- function Min (A,B: Integer): Integer; overload;
- function Min (A,B: Int64): Int64; overload;
- function Min (A,B: Single): Single; overload;
- function Min (A,B: Double): Double; overload;
- function Min (A,B: Extended): Extended; overload;
当调用方式为Min (10, 20)时,编译器很容易就能判定你调用的是上列第一个函数,因此
返回值也是个整数。
声明重载函数有两条原则:
· 每个例程声明后面必须添加overload 关键字。
· 例程间的参数个数或(和)参数类型必须不同,返回值不能用于区分各例程。
41
下面是ShowMsg 过程的三个重载过程。我已把它们添加到例OverDef 中(一个说明重
载和确省参数的应用程序):
- procedure ShowMsg (str: string); overload;
- begin
- MessageDlg (str, mtInformation, [mbOK], 0);
- end;
- procedure ShowMsg (FormatStr: string;
- Params: array of const); overload;
- begin
- MessageDlg (Format (FormatStr, Params),
- mtInformation, [mbOK], 0);
- end;
- procedure ShowMsg (I: Integer; Str: string); overload;
- begin
- ShowMsg (IntToStr (I) + ' ' + Str);
- end;
三个过程分别用三种不同的方法格式化字符串,然后在信息框中显示字符串。下面是三个例程的调用:
- ShowMsg ('Hello');
- ShowMsg ('Total = %d.', [100]);
- ShowMsg (10, 'MBytes');
当你在例程名后面键入左圆括号时,窗口中会显示所有可用例程的参数列表,当你输入参数时,Delphi会根据所输入参数的类型过滤参数列表。从图6.4 你可看到,当开始输入一个常量字符串时,Delphi 只显示第一个参数为字符串的两个ShowMsg 例程参数列表,滤掉了第一个参数为整数的例程。
重载例程必须用overload 关键字明确标示,你不能在同一单元中重载没有overload 标示
的例程,否则会出现错误信息: "Previous declaration of '<name>' was not marked with
the 'overload' directive."。不过你可以重载在其他单元中声明的例程,这是为了与以前的
Delphi版本兼容,以前的Delphi版本允许不同的单元重用相同的例程名。无论如何,这是例程
重载的特殊情况不是其特殊功能,而且不小心会出现问题。
例如在一个单元中添加以下代码:
- procedure MessageDlg (str: string); overload;
- begin
- Dialogs.MessageDlg (str, mtInformation, [mbOK], 0);
- end;
这段代码并没有真正重载原始的MessageDlg 例程,实际上如果键入:
- MessageDlg ('Hello');
你将得到一个有意思的错误消息,告诉你缺少参数。调用本地例程而不是VCL的唯一途径是明确标示例程所在单元,这有悖于于例程重载的思想:
- OverDefF.MessageDlg ('Hello');
Windows 句柄
Delphi从Windows 引入了不少数据类型,其中句柄最重要。这种数据类型名为THandle,该类型在Windows 单元中定义:
- type
- THandle = LongWord;
句柄数据类型通过数字实现,但并不当数字用。在Windows 中,句柄是一个系统内部数据结构的引用。例如,当你操作一个窗口,或说是一个Delphi 窗体时,系统会给你一个该窗口的句柄,系统会通知你:你正在操作142号窗口,就此,你的应用程序就能要求系统对142 号窗口进行操作——移动窗口、改变窗口大小、把窗口极小化为图标,等等。实际上许多Windows API 函数把句柄作为它的第一个参数,如GDI (图形设备接口)句柄、菜单句柄、实例句柄、位图句柄等等,不仅仅局限于窗口函数,。换句话说,句柄是一种内部代码,通过它能引用受系统控制的特殊元素,如窗口、位图、图标、内存块、光标、字体、菜单等等。Delphi中很少需要直接使用句柄,因为句柄藏在窗体、
位图及其他Delphi 对象的内部。当你要调用Delphi不支持的Windows API 函数时,句柄才会有用。
现在举一个简单的Windows句柄例子,完善这节内容。例WHandle 程序的窗体很简单,
只有一个按钮。正如下面主窗体文本所定义的那样,在代码中添加了窗体的OnCreate 事件和
按钮的OnClick 事件:
- object FormWHandle: TFormWHandle
- 52
- Caption = 'Window Handle'
- OnCreate = FormCreate
- object BtnCallAPI: TButton
- Caption = 'Call API'
- OnClick = BtnCallAPIClick
- end
- end
窗体一创建,程序就会通过窗体本身的Handle 属性,获取窗体对应的窗口句柄。调用IntToStr ,把句柄数值转换为一个字符串,然后再把它添加到窗体标题中,如图9.1:
- procedure TFormWHandle.FormCreate(Sender: TObject);
- begin
- Caption := Caption + ' ' + IntToStr (Handle);
- end;
因为FormCreate 是窗体类的方法,它可直接访问同类的其他属性和方法。因此,在这个过程中我们能够直接访问窗体的Caption 属性和Handle 属性。
如果你多此次执行该程序,通常会获得不同的句柄值。这个值实际上是由Windows 操作系统确定并返回给应用程序的。(句柄从来不是由程序决定的,而且句柄没有预定义值,句柄是由系统决定的,每执行一次程序,产生一个新值。)当你单击按钮,程序将调用Windows API 函数SetWindowText,它会根据第一个传递参
数改变窗口的标题。更准确地说,所用的API 函数其第一个参数是需要修改窗体的句柄:
- procedure TFormWHandle.BtnCallAPIClick(Sender: TObject);
- begin
- SetWindowText (Handle, 'Hi');
- end;
这段代码与前面所讲的事件处理程序等效,它通过给窗体的Caption 属性赋一个新值,改变窗体的标题。对上面这种情况,调用一个API 函数没有什么意义,因为用Delphi 来做更简单。然而有些API 在Delphi中没有相应的函数,就需要直接调用API,这一点你会在后面的高级例子中看到。
回调函数
前面已经了解到Objet Pascal 支持过程类型。过程类型常用于给Windows API函数传递回调函数。
首先,什么是回调函数呢?回调函数就是能对一系列系统内部元素执行给定操作的API函数,例如能对所有同类窗口进行操作的函数。这种函数也叫枚举函数,它是作为参数传递的函数,代表对所有内部元素执行的操作,该函数或过程的类型必须与给定的过程类型兼容。Windows回调函数的应用不止上述一种,不过这里仅研究以上简单应用。
现在考虑 EnumWindows API 函数,它的原型如下(从Win32 帮助文件拷贝而来):
- BOOL EnumWindows(
- WNDENUMPROC lpEnumFunc, // address of callback function
- LPARAM lParam // application-defined value
- );
当然,这是个C 语言的定义。我们可以查看Windows 单元,从中找到相应的Pascal 语言定义:
- function EnumWindows (
- lpEnumFunc: TFNWndEnumProc;
- lParam: LPARAM): BOOL; stdcall;
查阅帮助文件,我们发现作为参数传递的函数应该属于下面的类型(也是在C中):
- BOOL CALLBACK EnumWindowsProc (
- HWND hwnd, // handle of parent window
- LPARAM lParam // application-defined value
- );
这与下面的Delphi 过程类型定义一致:
- type
- 54
- EnumWindowsProc = function (Hwnd: THandle;
- Param: Pointer): Boolean; stdcall;
其中第一个参数是各主窗体的句柄,第二个参数则是调用EnumWindows 函数时所传递的值。实际上,Pascal 中没有相应的TFNWndEnumProc 类型定义 ,它只是个指针。这意味着我们需要传递一个带有合适参数的函数,将它用作一个指针,也就是取函数的地址而不是调用它。不幸的是,这也意味着如果某个参数类型出现错误时,编译器不会给予提示。每当调用Windows API函数或传递一个回调函数给系统时,Windows 要求程序员遵循stdcall调用协定。缺省情况下,Delphi使用另一种更高效的调用协定,其关键字为register。下面是一个与定义兼容的回调函数,此函数把窗口的标题读到字符串中,然后添加到给定窗体的一个列表框中:
- function GetTitle (Hwnd: THandle; Param: Pointer): Boolean; stdcall;
- var
- Text: string;
- begin
- SetLength (Text, 100);
- GetWindowText (Hwnd, PChar (Text), 100);
- FormCallBack.ListBox1.Items.Add (
- IntToStr (Hwnd) + ': ' + Text);
- Result := True;
- end;
窗体有一个几乎覆盖整个窗体的列表框,窗体顶部有一个小面板,面板上有一个按钮。当按下按钮时,EnumWindows API函数被调用,并且GetTitle 函数作为参数传递给它:
- procedure TFormCallback.BtnTitlesClick(Sender: TObject);
- var
- EWProc: EnumWindowsProc;
- begin
- ListBox1.Items.Clear;
- EWProc := GetTitle;
- EnumWindows (@EWProc, 0);
- end;
你可以直接调用GetTitle函数,不必先把值保存到过程类型临时变量中,上例这么做是为了使回调过程更清楚。程序运行结果确实很有意思,正如你在图9.2 中看到的那样,结果显示了系统中正在运行的所有主窗口,其中大部分是隐藏的,你通常看不到,许多实际上没有标题。
http://blog.csdn.net/sushengmiyan/article/details/7453237
DELPHI语法基础学习笔记-Windows 句柄、回调函数、函数重载等(Delphi中很少需要直接使用句柄,因为句柄藏在窗体、 位图及其他Delphi 对象的内部)的更多相关文章
-
C++基础学习笔记----第十三课(操作符重载-下)
本节主要讲使用成员函数重载操作符,包括[],=,(),->四种操作符的重载以及&&和||的问题. 类的成员函数进行操作符重载 基本概念 类的成员函数也可以进行操作符的重载.类的普 ...
-
C++基础学习笔记----第四课(函数的重载、C和C++的相互调用)
本节主要讲了函数重载的主要概念以及使用方法,还有C和C++的相互调用的准则和具体的工程中的使用技巧. 函数重载 1.基本概念 函数重载就是用同一个函数名来定义不同的函数.使用不同的函数参数来搭配同一个 ...
-
delphi操作xml学习笔记 之一 入门必读
Delphi 对XML的支持---TXMLDocument类 Delphi7 支持对XML文档的操作,可以通过TXMLDocument类来实现对XML文档的读写.可以利用TXMLDocum ...
-
尚学堂JAVA基础学习笔记
目录 尚学堂JAVA基础学习笔记 写在前面 第1章 JAVA入门 第2章 数据类型和运算符 第3章 控制语句 第4章 Java面向对象基础 1. 面向对象基础 2. 面向对象的内存分析 3. 构造方法 ...
-
Java基础学习笔记总结
Java基础学习笔记一 Java介绍 Java基础学习笔记二 Java基础语法之变量.数据类型 Java基础学习笔记三 Java基础语法之流程控制语句.循环 Java基础学习笔记四 Java基础语法之 ...
-
Mysql数据库基础学习笔记
Mysql数据库基础学习笔记 1.mysql查看当前登录的账户名以及数据库 一.单表查询 1.创建数据库yuzly,创建表fruits 创建表 ) ) ,) NOT NULL,PRIMARY KEY( ...
-
handlebars.js基础学习笔记
最近在帮学校做个课程网站,就有人推荐用jquery+ajax+handlebars做网站前端,刚接触发现挺高大上的,于是就把一些基础学习笔记记录下来啦. 1.引用文件: jquery.js文件下载:h ...
-
Oracle基础学习笔记
Oracle基础学习笔记 最近找到一份实习工作,有点头疼的是,有阶段性考核,这...,实际想想看,大学期间只学过数据库原理,并没有针对某一数据库管理系统而系统的学习,这正好是一个机会,于是乎用了三天时 ...
-
C++基础 学习笔记之一:源代码的格式化
C++基础 学习笔记之一:源代码的格式化 1. 源代码中的标记与空白 C++中的语句是以分号表示语句的结束.在C++中空格和回车以及制表符均为相同作用,即三者通常可以互相替代. 例如可以将一个简单的m ...
随机推荐
-
delphi 中如何查看网页POSTDATA
procedure TForm1.WebBrowser1NewWindow2(Sender: TObject; var ppDisp: IDispatch; var Cancel: WordBool ...
-
JavaWeb chapter 4 Servlet处理HTTP请求
1. GET/POST提交方法: 用户在网页上点击一个超链接:(get) 用户提交在网页上提交表单:(post或者get) 用户在浏览器地址栏输入URL地址并回车(get) 2. 默认情况下都是使 ...
-
一个RPC的demo
从下面的例子中可以看到,Consumer(client)的代码中引用了Provider部分的class,本例中是 com.provider.EchoServiceImpl和com.provider.E ...
-
linux挂载U盘,及乱码问题解决
1. 首先使用切换到root用户. 2. 使用fdisk -l命令查看磁盘信息,找到u盘(能够依据显示的大小确定) 3. 在/mnt下创建挂载点,比如创建usb目录:mkdir /mnt/usb 4. ...
-
Python学习笔记之基本语法学习1
★学习目标: 用Python做HTTP接口测试 ★学习的大纲: ●Python语言基础(安装,第一个案例,基本语法等) ●Request模块使用 ●编写一个简单功能的接口测试案例 ●HTTP协议基础 ...
-
尝试在条件“$(_DeviceSdkVersion) >= 21”中对计算结果为“”而不是数字的“$(_DeviceSdkVersion)
晚上搞xamarin ,运行xamarin项目好好的,不知道怎么回事,一次运行xamarin android项目的时候,部署失败,以前也是遇到这样的错误. 尝试在条件"$(_DeviceSd ...
-
Ajax 案例之三级联动
每次在博客园网站写博客,格式真的好难搞,还望好心人告知更好的编辑工具.接下来进入正题:三级联动(其效果演示可看我的博文Ajax 学习总结 末尾). 数据表设计(Oracle) 新建数据表 Employ ...
-
更新mysql驱动5.1-47 Generated keys not requested. You need to specify Statement.RETURN_GENERATED_KEY
今天在更新mysql驱动后运行程序突然报如下错误: java.sql.SQLException: Generated keys not requested. You need to specify S ...
-
Win10 SQL Server 2017安装教程
Win10 SQL Server 2017安装教程 1:下载地址 2:开始安装 1:安装环境预备说明 还要注意就是要先下载这个VC++的更新,可以解决服务器安装不上的问题,下载链接 :Microsof ...
-
python模块的学习
# time 模块 import time print(time.time()) #当前的时间挫 #time.sleep(3) #休息3秒钟,这3秒cpu不工作的 print(time.gmtime( ...