DELPHI语法基础学习笔记-Windows 句柄、回调函数、函数重载等(Delphi中很少需要直接使用句柄,因为句柄藏在窗体、 位图及其他Delphi 对象的内部)

时间:2022-09-25 09:23:12

函数重载
重载的思想很简单:编译器允许你用同一名字定义多个函数或过程,只要它们所带的参数不同。实际上,编译器是通过检测参数来确定需要调用的例程。
下面是从VCL 的数学单元(Math Unit)中摘录的一系列函数:

  1. function Min (A,B: Integer): Integer; overload;
  2. function Min (A,B: Int64): Int64; overload;
  3. function Min (A,B: Single): Single; overload;
  4. function Min (A,B: Double): Double; overload;
  5. function Min (A,B: Extended): Extended; overload;

当调用方式为Min (10, 20)时,编译器很容易就能判定你调用的是上列第一个函数,因此
返回值也是个整数。
声明重载函数有两条原则:
· 每个例程声明后面必须添加overload 关键字。
· 例程间的参数个数或(和)参数类型必须不同,返回值不能用于区分各例程。
41
下面是ShowMsg 过程的三个重载过程。我已把它们添加到例OverDef 中(一个说明重
载和确省参数的应用程序):

  1. procedure ShowMsg (str: string); overload;
  2. begin
  3. MessageDlg (str, mtInformation, [mbOK], 0);
  4. end;
  5. procedure ShowMsg (FormatStr: string;
  6. Params: array of const); overload;
  7. begin
  8. MessageDlg (Format (FormatStr, Params),
  9. mtInformation, [mbOK], 0);
  10. end;
  11. procedure ShowMsg (I: Integer; Str: string); overload;
  12. begin
  13. ShowMsg (IntToStr (I) + ' ' + Str);
  14. end;

三个过程分别用三种不同的方法格式化字符串,然后在信息框中显示字符串。下面是三个例程的调用:

  1. ShowMsg ('Hello');
  2. ShowMsg ('Total = %d.', [100]);
  3. ShowMsg (10, 'MBytes');

当你在例程名后面键入左圆括号时,窗口中会显示所有可用例程的参数列表,当你输入参数时,Delphi会根据所输入参数的类型过滤参数列表。从图6.4 你可看到,当开始输入一个常量字符串时,Delphi 只显示第一个参数为字符串的两个ShowMsg 例程参数列表,滤掉了第一个参数为整数的例程。

重载例程必须用overload 关键字明确标示,你不能在同一单元中重载没有overload 标示
的例程,否则会出现错误信息: "Previous declaration of '<name>' was not marked with
the 'overload' directive."。不过你可以重载在其他单元中声明的例程,这是为了与以前的
Delphi版本兼容,以前的Delphi版本允许不同的单元重用相同的例程名。无论如何,这是例程
重载的特殊情况不是其特殊功能,而且不小心会出现问题。
例如在一个单元中添加以下代码:

  1. procedure MessageDlg (str: string); overload;
  2. begin
  3. Dialogs.MessageDlg (str, mtInformation, [mbOK], 0);
  4. end;

这段代码并没有真正重载原始的MessageDlg 例程,实际上如果键入:

  1. MessageDlg ('Hello');

你将得到一个有意思的错误消息,告诉你缺少参数。调用本地例程而不是VCL的唯一途径是明确标示例程所在单元,这有悖于于例程重载的思想:

  1. OverDefF.MessageDlg ('Hello');

Windows 句柄
Delphi从Windows 引入了不少数据类型,其中句柄最重要。这种数据类型名为THandle,该类型在Windows 单元中定义:

  1. type
  2. THandle = LongWord;

句柄数据类型通过数字实现,但并不当数字用。在Windows 中,句柄是一个系统内部数据结构的引用。例如,当你操作一个窗口,或说是一个Delphi 窗体时,系统会给你一个该窗口的句柄,系统会通知你:你正在操作142号窗口,就此,你的应用程序就能要求系统对142 号窗口进行操作——移动窗口、改变窗口大小、把窗口极小化为图标,等等。实际上许多Windows API 函数把句柄作为它的第一个参数,如GDI (图形设备接口)句柄、菜单句柄、实例句柄、位图句柄等等,不仅仅局限于窗口函数,。换句话说,句柄是一种内部代码,通过它能引用受系统控制的特殊元素,如窗口、位图、图标、内存块、光标、字体、菜单等等。Delphi中很少需要直接使用句柄,因为句柄藏在窗体、
位图及其他Delphi 对象的内部。当你要调用Delphi不支持的Windows API 函数时,句柄才会有用。
现在举一个简单的Windows句柄例子,完善这节内容。例WHandle 程序的窗体很简单,
只有一个按钮。正如下面主窗体文本所定义的那样,在代码中添加了窗体的OnCreate 事件和
按钮的OnClick 事件:

  1. object FormWHandle: TFormWHandle
  2. 52
  3. Caption = 'Window Handle'
  4. OnCreate = FormCreate
  5. object BtnCallAPI: TButton
  6. Caption = 'Call API'
  7. OnClick = BtnCallAPIClick
  8. end
  9. end

窗体一创建,程序就会通过窗体本身的Handle 属性,获取窗体对应的窗口句柄。调用IntToStr ,把句柄数值转换为一个字符串,然后再把它添加到窗体标题中,如图9.1:

  1. procedure TFormWHandle.FormCreate(Sender: TObject);
  2. begin
  3. Caption := Caption + ' ' + IntToStr (Handle);
  4. end;

因为FormCreate 是窗体类的方法,它可直接访问同类的其他属性和方法。因此,在这个过程中我们能够直接访问窗体的Caption 属性和Handle 属性。

如果你多此次执行该程序,通常会获得不同的句柄值。这个值实际上是由Windows 操作系统确定并返回给应用程序的。(句柄从来不是由程序决定的,而且句柄没有预定义值,句柄是由系统决定的,每执行一次程序,产生一个新值。)当你单击按钮,程序将调用Windows API 函数SetWindowText,它会根据第一个传递参
数改变窗口的标题。更准确地说,所用的API 函数其第一个参数是需要修改窗体的句柄:

  1. procedure TFormWHandle.BtnCallAPIClick(Sender: TObject);
  2. begin
  3. SetWindowText (Handle, 'Hi');
  4. end;

这段代码与前面所讲的事件处理程序等效,它通过给窗体的Caption 属性赋一个新值,改变窗体的标题。对上面这种情况,调用一个API 函数没有什么意义,因为用Delphi 来做更简单。然而有些API 在Delphi中没有相应的函数,就需要直接调用API,这一点你会在后面的高级例子中看到。

回调函数
前面已经了解到Objet Pascal 支持过程类型。过程类型常用于给Windows API函数传递回调函数。
首先,什么是回调函数呢?回调函数就是能对一系列系统内部元素执行给定操作的API函数,例如能对所有同类窗口进行操作的函数。这种函数也叫枚举函数,它是作为参数传递的函数,代表对所有内部元素执行的操作,该函数或过程的类型必须与给定的过程类型兼容。Windows回调函数的应用不止上述一种,不过这里仅研究以上简单应用。
现在考虑 EnumWindows API 函数,它的原型如下(从Win32 帮助文件拷贝而来):

  1. BOOL EnumWindows(
  2. WNDENUMPROC lpEnumFunc, // address of callback function
  3. LPARAM lParam // application-defined value
  4. );

当然,这是个C 语言的定义。我们可以查看Windows 单元,从中找到相应的Pascal 语言定义:

  1. function EnumWindows (
  2. lpEnumFunc: TFNWndEnumProc;
  3. lParam: LPARAM): BOOL; stdcall;

查阅帮助文件,我们发现作为参数传递的函数应该属于下面的类型(也是在C中):

  1. BOOL CALLBACK EnumWindowsProc (
  2. HWND hwnd, // handle of parent window
  3. LPARAM lParam // application-defined value
  4. );

这与下面的Delphi 过程类型定义一致:

  1. type
  2. 54
  3. EnumWindowsProc = function (Hwnd: THandle;
  4. Param: Pointer): Boolean; stdcall;

其中第一个参数是各主窗体的句柄,第二个参数则是调用EnumWindows 函数时所传递的值。实际上,Pascal 中没有相应的TFNWndEnumProc 类型定义 ,它只是个指针。这意味着我们需要传递一个带有合适参数的函数,将它用作一个指针,也就是取函数的地址而不是调用它。不幸的是,这也意味着如果某个参数类型出现错误时,编译器不会给予提示。每当调用Windows API函数或传递一个回调函数给系统时,Windows 要求程序员遵循stdcall调用协定。缺省情况下,Delphi使用另一种更高效的调用协定,其关键字为register。下面是一个与定义兼容的回调函数,此函数把窗口的标题读到字符串中,然后添加到给定窗体的一个列表框中:

  1. function GetTitle (Hwnd: THandle; Param: Pointer): Boolean; stdcall;
  2. var
  3. Text: string;
  4. begin
  5. SetLength (Text, 100);
  6. GetWindowText (Hwnd, PChar (Text), 100);
  7. FormCallBack.ListBox1.Items.Add (
  8. IntToStr (Hwnd) + ': ' + Text);
  9. Result := True;
  10. end;

窗体有一个几乎覆盖整个窗体的列表框,窗体顶部有一个小面板,面板上有一个按钮。当按下按钮时,EnumWindows API函数被调用,并且GetTitle 函数作为参数传递给它:

  1. procedure TFormCallback.BtnTitlesClick(Sender: TObject);
  2. var
  3. EWProc: EnumWindowsProc;
  4. begin
  5. ListBox1.Items.Clear;
  6. EWProc := GetTitle;
  7. EnumWindows (@EWProc, 0);
  8. end;

你可以直接调用GetTitle函数,不必先把值保存到过程类型临时变量中,上例这么做是为了使回调过程更清楚。程序运行结果确实很有意思,正如你在图9.2 中看到的那样,结果显示了系统中正在运行的所有主窗口,其中大部分是隐藏的,你通常看不到,许多实际上没有标题。

http://blog.csdn.net/sushengmiyan/article/details/7453237

DELPHI语法基础学习笔记-Windows 句柄、回调函数、函数重载等(Delphi中很少需要直接使用句柄,因为句柄藏在窗体、 位图及其他Delphi 对象的内部)的更多相关文章

  1. C&plus;&plus;基础学习笔记----第十三课(操作符重载-下)

    本节主要讲使用成员函数重载操作符,包括[],=,(),->四种操作符的重载以及&&和||的问题. 类的成员函数进行操作符重载 基本概念 类的成员函数也可以进行操作符的重载.类的普 ...

  2. C&plus;&plus;基础学习笔记----第四课(函数的重载、C和C&plus;&plus;的相互调用)

    本节主要讲了函数重载的主要概念以及使用方法,还有C和C++的相互调用的准则和具体的工程中的使用技巧. 函数重载 1.基本概念 函数重载就是用同一个函数名来定义不同的函数.使用不同的函数参数来搭配同一个 ...

  3. delphi操作xml学习笔记 之一 入门必读

    Delphi 对XML的支持---TXMLDocument类       Delphi7 支持对XML文档的操作,可以通过TXMLDocument类来实现对XML文档的读写.可以利用TXMLDocum ...

  4. 尚学堂JAVA基础学习笔记

    目录 尚学堂JAVA基础学习笔记 写在前面 第1章 JAVA入门 第2章 数据类型和运算符 第3章 控制语句 第4章 Java面向对象基础 1. 面向对象基础 2. 面向对象的内存分析 3. 构造方法 ...

  5. Java基础学习笔记总结

    Java基础学习笔记一 Java介绍 Java基础学习笔记二 Java基础语法之变量.数据类型 Java基础学习笔记三 Java基础语法之流程控制语句.循环 Java基础学习笔记四 Java基础语法之 ...

  6. Mysql数据库基础学习笔记

    Mysql数据库基础学习笔记 1.mysql查看当前登录的账户名以及数据库 一.单表查询 1.创建数据库yuzly,创建表fruits 创建表 ) ) ,) NOT NULL,PRIMARY KEY( ...

  7. handlebars&period;js基础学习笔记

    最近在帮学校做个课程网站,就有人推荐用jquery+ajax+handlebars做网站前端,刚接触发现挺高大上的,于是就把一些基础学习笔记记录下来啦. 1.引用文件: jquery.js文件下载:h ...

  8. Oracle基础学习笔记

    Oracle基础学习笔记 最近找到一份实习工作,有点头疼的是,有阶段性考核,这...,实际想想看,大学期间只学过数据库原理,并没有针对某一数据库管理系统而系统的学习,这正好是一个机会,于是乎用了三天时 ...

  9. C&plus;&plus;基础 学习笔记之一:源代码的格式化

    C++基础 学习笔记之一:源代码的格式化 1. 源代码中的标记与空白 C++中的语句是以分号表示语句的结束.在C++中空格和回车以及制表符均为相同作用,即三者通常可以互相替代. 例如可以将一个简单的m ...

随机推荐

  1. delphi 中如何查看网页POSTDATA

    procedure TForm1.WebBrowser1NewWindow2(Sender: TObject;  var ppDisp: IDispatch; var Cancel: WordBool ...

  2. JavaWeb chapter 4 Servlet处理HTTP请求

    1.  GET/POST提交方法: 用户在网页上点击一个超链接:(get) 用户提交在网页上提交表单:(post或者get) 用户在浏览器地址栏输入URL地址并回车(get) 2.  默认情况下都是使 ...

  3. 一个RPC的demo

    从下面的例子中可以看到,Consumer(client)的代码中引用了Provider部分的class,本例中是 com.provider.EchoServiceImpl和com.provider.E ...

  4. linux挂载U盘,及乱码问题解决

    1. 首先使用切换到root用户. 2. 使用fdisk -l命令查看磁盘信息,找到u盘(能够依据显示的大小确定) 3. 在/mnt下创建挂载点,比如创建usb目录:mkdir /mnt/usb 4. ...

  5. Python学习笔记之基本语法学习1

    ★学习目标: 用Python做HTTP接口测试 ★学习的大纲: ●Python语言基础(安装,第一个案例,基本语法等) ●Request模块使用 ●编写一个简单功能的接口测试案例 ●HTTP协议基础 ...

  6. 尝试在条件&OpenCurlyDoubleQuote;&dollar;&lpar;&lowbar;DeviceSdkVersion&rpar; >&equals; 21”中对计算结果为&OpenCurlyDoubleQuote;”而不是数字的&OpenCurlyDoubleQuote;&dollar;&lpar;&lowbar;DeviceSdkVersion&rpar;

    晚上搞xamarin ,运行xamarin项目好好的,不知道怎么回事,一次运行xamarin android项目的时候,部署失败,以前也是遇到这样的错误. 尝试在条件"$(_DeviceSd ...

  7. Ajax 案例之三级联动

    每次在博客园网站写博客,格式真的好难搞,还望好心人告知更好的编辑工具.接下来进入正题:三级联动(其效果演示可看我的博文Ajax 学习总结 末尾). 数据表设计(Oracle) 新建数据表 Employ ...

  8. 更新mysql驱动5&period;1-47 Generated keys not requested&period; You need to specify Statement&period;RETURN&lowbar;GENERATED&lowbar;KEY

    今天在更新mysql驱动后运行程序突然报如下错误: java.sql.SQLException: Generated keys not requested. You need to specify S ...

  9. Win10 SQL Server 2017安装教程

    Win10 SQL Server 2017安装教程 1:下载地址 2:开始安装 1:安装环境预备说明 还要注意就是要先下载这个VC++的更新,可以解决服务器安装不上的问题,下载链接 :Microsof ...

  10. python模块的学习

    # time 模块 import time print(time.time()) #当前的时间挫 #time.sleep(3) #休息3秒钟,这3秒cpu不工作的 print(time.gmtime( ...