标题:[灌水]EssentialPascal(这个不错的,对于刚刚学习delphi的新手很有帮助)
只看楼主
shuyue1981
Rank: 1
等 级:新手上路
帖 子:89
专家分:0
注 册:2005-1-20
得分:0 
PASCAL 精要 第九章 Windows 编程

Delphi 利用Object Pascal 和可视控件库(VCL)对底层的Windows API 进行了完美的封装,所以很少需要使用基础Pascal 语言来建立Windows应用程序,也无需直接调用Windows API 函数。尽管如此,如果遇到特殊情况,VCL 又不支持,Delphi程序员还得直接面对Windows编程。不过只有在极其特殊的情况下,例如:基于不寻常API 调用的Delphi新控件开发, 你才需要这样做,这里我不想讨论这方面内容,我只想让大家看一下与操作系统交互的几个Delphi元素以及Delphi程序员能从中获益的Windows编程技术。

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  Caption = 'Window Handle'  OnCreate = FormCreate  object BtnCallAPI: TButton    Caption = 'Call API'    OnClick = BtnCallAPIClick  endend

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

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

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

图 9.1: 例 WHandle 显示窗体句柄,每次运行程序得到的句柄值不同

如果你多此次执行该程序,通常会获得不同的句柄值。这个值实际上是由Windows 操作系统确定并返回给应用程序的。(句柄从来不是由程序决定的,而且句柄没有预定义值,句柄是由系统决定的,每执行一次程序,产生一个新值。)

当你单击按钮,程序将调用Windows API 函数SetWindowText,它会根据第一个传递参数改变窗口的标题。更准确地说,所用的API 函数其第一个参数是需要修改窗体的句柄:

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

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

外部声明

Windows 编程中涉及的另一个重要元素是外部声明。外部声明原先用于在Pascal代码中连接汇编语言写的外部函数,现在外部声明用于Windows编程,用来调用动态连接库DLL函数。在Delphi的Windows 单元中有许多这种声明:

// forward declarationfunction LineTo (DC: HDC; X, Y: Integer): BOOL; stdcall;// external declaration (instead of actual code)function LineTo; external 'gdi32.dll' name 'LineTo';

这段声明表示函数LineTo 的代码同名保存在GDI32.DLL 动态链接库中(最重要的Windows 系统库之一)。实际应用时,外部声明中的函数名与DLL中的函数名可以不同。

一般你不需要象刚才所例举的那样写声明,因为Windows 单元和一些Delphi 系统单元中已包含了这些声明。只有在调用自定义DLL,或调用Delphi 中未定义的Windows 函数时,你才能需要写外部声明。

注意:在16位Delphi中,外部声明使用不带扩展名的库名,后面跟name指令(如上所示)或是一个index指令,后面跟DLL中函数的序号。尽管Win32 仍然允许通过序号访问DLL函数,但是微软公司已经声明未来将不支持这种访问方式,这一改变反映了系统库访问方式的改变。还要注意的是:目前Delphi的Windows 单元已取代了16位Delphi的WinProcs 和WinTypes 单元。

回调函数

从第六章已经了解到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  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中看到的那样,结果显示了系统中正在运行的所有主窗口,其中大部分是隐藏的,你通常看不到,许多实际上没有标题。

图 9.2: 例CallBack输出结果--当前所有主窗体,其中包括可见及隐藏的窗体

最小的Windows 程序

为了完整介绍Windows 编程及Pascal 语言,现在我展示一个简单但完整的应用程序,建立该程序没有使用VCL库。这个程序只是简单地采用命令行参数(保存在系统全程变量cmdLine中),并利用ParamCount 和 ParamStr 这两个Pascal 函数从参数中提取信息。其中第一个函数返回参数的个数,第二个返回给定位置的参数。

尽管在图形用户界面环境下用户很少操纵命令行参数,但是Windows 命令行参数对系统本身却很重要。例如,一旦你定义了文件扩展名和应用程序的关联,只要双击所关联的文件就能执行这个程序。实际上,当你双击一个文件,Windows 即启动关联程序并把选定的文件作为命令行参数传递给它。

下面是工程文件的完整源代码(一个DPR 文件,不是PAS 文件):

program Strparam;uses  Windows;begin  // show the full string  MessageBox (0, cmdLine,     'StrParam Command Line', MB_OK);  // show the first parameter  if ParamCount > 0 then    MessageBox (0, PChar (ParamStr (1)),       '1st StrParam Parameter', MB_OK)  else    MessageBox (0, PChar ('No parameters'),       '1st StrParam Parameter', MB_OK);end.

输出代码使用MessageBox API 函数,很容易就避开了VCL库。实际上,象上面那样纯粹的Windows 程序,其优点就是占的内存少,程序执行文件大约才16k字节。

为了给程序提供命令行参数,你可以用Delphi的 Run > Parameters 菜单命令。另一个方法是:打开Windows 资源管理器,查找包含程序执行文件的目录,然后把你要执行的文件拖到可执行文件上,Windows 资源管理器会把拖放的文件名用作命令行参数,开始执行程序。图9.3显示了资源管理器及相应的输出。

图9.3: 把一个文件拖放到执行文件上,给例StrParam提供命令行参数

结束语

在这一章中,我们对Windows 编程的底层内容进行了介绍,讨论了句柄和简单的Windows 程序。对于常规的Windows 编程任务,通常只需使用Delphi 提供的可视开发工具及VCL可视控件库。但是这超出了本书讨论的范围,因为本书讨论的是Pascal 语言。

下一章介绍variant类型。对Pascal 数据类型系统来说,它是一个非常特殊的外来物,引入它是为了提供完全的OLE 支持。


一个爱学习的人!
2005-01-27 15:44
shuyue1981
Rank: 1
等 级:新手上路
帖 子:89
专家分:0
注 册:2005-1-20
得分:0 
PASCAL 精要 第十章 Variant类型

为了完全支持OLE,32位Delphi 增加了Variant 数据类型,本节将从宏观角度来分析这种数据类型。实际上,Variant类型对Pascal语言有普遍而深入的影响,Delphi 控件库中与OLE 无关的地方也使用到这种类型。

Variant变量没有类型

一般说来,你可以用Variant 变量存储任何数据类型,对它执行各种操作和类型转换。需要注意的是:这违反了Pascal 语言的一贯原则,有悖于良好的编程习惯。variant 变量的类型检查和计算在运行期间才进行,编译器不会提示代码中的潜在错误,这些错误在进一步测试中才能发现。总之,你可以认为包含variant变量的代码是解释性代码,正如解释性代码一样,许多操作直到执行时才能知道,这对代码运行速度会有很大的影响。

上面对Variant 类型的使用提出了警告,现在来看看Variant 类型究竟能干什么。基本上说,如果声明了一个variant 变量:

var  V: Variant;

你就可以把各种不同类型的值赋给它:

V := 10;V := 'Hello, World';V := 45.55;

一旦得到一个variant 值,你可以把它拷贝给任何兼容或不兼容的数据类型。如果你把值赋给不兼容的数据类型,Delphi 会力尽所能进行转换,无法转换则颁布一个运行时间错误。实际上,variant变量中不仅包含了数据还包含有类型信息,并允许一系列运行时间操作,这些操作很方便,但运行速度慢且安全性差。

见例VariTest,它是上面代码的扩展。窗体上有三个编辑框,一对按钮,第一个按钮的OnClick 事件代码如下:

procedure TForm1.Button1Click(Sender: TObject);var  V: Variant;begin  V := 10;  Edit1.Text := V;  V := 'Hello, World';  Edit2.Text := V;  V := 45.55;  Edit3.Text := V;end;

很有趣是不是?你可以把一个值为字符串的variant 变量赋给编辑框Text 属性,还可以把值为整数或浮点数的variant 变量赋给Text属性。正如你在图10.1中所看到的,一切正常。

(图10.1)按Assign按钮后,例VariTest的输出结果

图 10.1: 例 VariTest 的 Assign 按钮 Click 事件输出结果

更糟糕的是:你还可以用variant变量计算数值,从第二个按钮的Click事件代码就可看到这一点:

procedure TForm1.Button2Click(Sender: TObject);var  V: Variant;  N: Integer;begin  V := Edit1.Text;  N := Integer(V) * 2;  V := N;  Edit1.Text := V;end;

至少这种代码带有一定危险性,如果第一个编辑框包含了一个数字,那么一切运行正常;如果不是,将会引发异常。这里再重申一遍,如果不到万不得以,不要随便使用Variant 类型,还是应坚持使用传统的Pascal 数据类型和类型检查方法。在Delphi 和 VCL中,variant变量主要是用于 OLE 支持和数据库域的访问。

Variant类型内部结构

Delphi中定义了一个 variant 记录类型,TVarData,它与Variant 类型有相同的内存布局。你可以通过TVarData访问variant变量的实际类型。TVarData 结构中包含了Variant类型信息(由Vtype域表示)、一些保留域及当前值。

VType域的取值包括OLE 自动化中的所有数据类型,这些类型通常叫OLE 类型或variant 类型。以下是variant 类型的完整列表,按字母顺序排列:

  • varArray
  • varBoolean
  • varByRef
  • varCurrency
  • varDate
  • varDispatch
  • varDouble
  • varEmpty
  • varError
  • varInteger
  • varNull
  • varOleStr
  • varSingle
  • varSmallint
  • varString
  • varTypeMask
  • varUnknown
  • varVariant

你可以在Delphi 帮助系统的variants 主题下找到这些类型的说明。

还有许多操作variant 变量的函数,你可以用它们进行特定的类型转换,或通过它们获取variant变量的类型信息(例如VarType 函数),当你用variant变量写表达式时,Delphi会自动调用这些类型转换和赋值函数。另外还有操作variant 数组的例程,你可以通过帮助文件的Variant support routines 主题了解相关内容。

Variant类型运行很慢!

Variant 类型代码运行很慢,不仅数据类型转换如此,两个值为整数的Variant 变量相加也是如此。它们几乎跟Visual Basic这种解释性代码一样慢!为了比较Variant变量和整型变量的运行速度,请看例VSpeed 。

程序中设置了一个循环,记录运行时间并在进程条中显示运行状态。下面是基于variant类型的一段代码,基于整型的代码与此相似:

procedure TForm1.Button1Click(Sender: TObject);var  time1, time2: TDateTime;  n1, n2: Variant;begin  time1 := Now;  n1 := 0;  n2 := 0;  ProgressBar1.Position := 0;  while n1 < 5000000 do  begin    n2 := n2 + n1;    Inc (n1);    if (n1 mod 50000) = 0 then    begin      ProgressBar1.Position := n1 div 50000;      Application.ProcessMessages;    end;  end;  // we must use the result  Total := n2;  time2 := Now;  Label1.Caption := FormatDateTime (    'n:ss', Time2-Time1) + ' seconds';end;

记时这段代码值得一看,因为你可以把它用到任何类型的性能测试中。正如你所看到的,程序用Now 函数获取当前的时间,用FormatDateTime 函数格式化时间差,输出结果以分("n")和秒("ss")表示。除此之外,你可以用Windows API的GetTickCount 函数,该函数能精确显示操作系统启动后至当前的毫秒数。

从上例可见两者的速度差异非常之大,以至于不用精确记时也能看到这种差异。图10.2是在本人计算机上运行程序看到的结果。当然运行结果取决于运行程序的计算机,但是两者的数值比不会有太大变化。

图 10.2: 例Vspeed中整型与Variant类型的计算速度差异

结束语

Variant类型与传统Pascal 数据类型差别很大,所以本章以短小篇幅单独阐述了Variant类型的有关内容。尽管Variant类型主要用于OLE 编程,但用来写一些潦潦草草的程序倒也便利,因为不用考虑数据类型,不过正如以上所述,这样做会影响程序执行速度。

通过前面各章我们已经介绍了绝大部分的语言特征,下一章将讨论程序的总体框架和单元模块。


一个爱学习的人!
2005-01-27 15:45
shuyue1981
Rank: 1
等 级:新手上路
帖 子:89
专家分:0
注 册:2005-1-20
得分:0 
PASCAL 精要 第十一章 程序和单元

Delphi 应用程序中的单元,或说程序模块可谓老道精深。实际上,单元是程序模块化的基础,类是继它之后才有的。在Delphi 应用程序中,每个窗体都有一个相对应的单元。用相应的工具按钮, 或File > New Form 菜单命令,在工程中添加一个新窗体,实际上是增加了一个新单元,也就是建立了该新窗体的类。

单元

虽然所有窗体都在单元中定义,但反之则不然。除窗体外,单元中还可以定义一系列能访问的例程。选择File > New菜单命令,然后在Object Repository的New 页中选择Unit 图标,随即当前工程中就会加入一个空白单元。单元代码分区存放,空白单元的代码如下:

unit Unit1;interfaceimplementationend.

单元的概念比较简单,单元名与文件名相同,而且必须唯一。单元包括界面区(interface)及实现区(implementation),界面区用于声明其它单元能看到的部分;实现区存放界面的实现代码及外部不可见的声明。此外还有两个可选的区,即初始化区及结束区,其中初始化区存放初始化代码,当程序加载到内存时执行;结束区存放程序终止时执行的代码。

单元总体结构如下:

unit unitName;interface// other units we need to refer touses  A, B, C;// exported type definitiontype  newType = TypeDefinition;// exported constantsconst  Zero = 0;// global variablesvar  Total: Integer;// list of exported functions and proceduresprocedure MyProc;implementationuses  D, E;// hidden global variablevar  PartialTotal: Integer;// all the exported functions must be codedprocedure MyProc;begin  // ... code of procedure MyProcend;initialization  // optional initialization partfinalization  // optional clean-up codeend.

界面区头部的uses子句表示需要访问的外部单元,这些外部单元中定义了你需要引用的数据类型,如自定义窗体内所用的控件。

实现区头部的uses子句用于表示只在实现部分访问的单元。如果例程或方法的代码需要引用其他单元,你应该把这些单元加到实现区子句中,而不是界面区。你所引用的单元必须在工程文件目录中能找到,或在工程选项对话框的 Directories/Conditionals 页设定这些单元的搜索路径。

C++程序员应该知道uses语句和include 指令是不同的。uses语句只是用于输入引用单元的预编译界面部分,引用单元的实现部分在单元编译时才考虑。你引用的单元可以是源代码格式(PAS),也可以是编译格式(DCU),但是必须用同一版本的Delphi进行编译。

在单元的界面区中可以声明许多不同的元素,包括过程、函数、全程变量及数据类型。在Delphi 应用程序中,数据类型可能用得最频繁。每创建一个窗体,Delphi 会在单元中自动建立一个新的数据类型--类(class)。在Delphi 单元中不仅能定义窗体;还能象传统单元一样,只包含过程及函数;还可以定义与窗体和任何可视控件无关的类。

单元的工作空间

Pascal单元是封装性和可视性的关键,它很可能比类中的 private 和 public 关键字还要重要。(实际上,private关键字与类单元的工作空间有关)。一个标识符(如一个变量、过程、函数或数据类型)的工作空间是指能访问标识符的代码段。基本原则是:标识符在它工作空间内才有意义,也就是说,只在其声明的代码块中才有意义,在工作空间外你不能访问这些标识符。例如:

  • 局部变量:如果你在例程或方法代码块内声明一个变量,那么单元外部不能访问这个变量。该标识符的工作空间就是定义标识符的整个例程,其中包括嵌套例程(除非嵌套例程内有一个同名标识符覆盖了外部定义)。当调用到例程时,其变量压入栈内存中,例程一结束,栈中的内存就自动释放。
  • 全程隐藏变量:如果你在单元的实现部分声明一个标识符,那么在单元外你不能使用它,但是能在单元内任一代码块及过程中使用它。程序一启动就会为全程隐藏变量分配内存,程序终止内存释放,你可以在单元初始化区给它赋初值。

  • 全程变量:如果你在单元的界面部分声明标识符,那么该标识符的工作空间就扩大了,任何Use它的单元都能访问它。这类变量的内存分配及生命周期与上类变量相同,唯一不同的是其可见性。

只要程序单元的uses子句中列出某一单元名,那么所列单元界面区中声明的任何标识符该程序都能访问。窗体类的变量就是这样声明的,所以你可以在其他窗体代码中访问这个窗体以及它的公共域、方法、属性和组件。当然把什么都声明为全局标识这种编程习惯并不好。除了明显的内存消耗问题外,使用全程变量使代码维护和更新变得困难。一句话,你应该尽量少用全程变量。

单元用作命名空间

uses 语句是访问其他单元工作空间的标准技术,通过该语句你能访问其它单元的定义内容。如果恰巧两个单元声明的标识符同名,也就是说你可能有两个同名的类或例程,遇到这种情况,你可以用单元名作前缀定义类型或过程名,由此进行区分。例如用Totals.ComputeTotal访问Totals 单元中的ComputeTotal 过程。不过这种情况最好不要经常遇到,因此强烈建议不要在同一程序中用同一名字表示两个不同的东西。

然而,如果查阅VCL库和Windows 文件,你会发现一些Delphi 函数和Delphi 可用的Windows API 函数同名,不过参数往往不同,下面以Beep 过程为例说明这个问题。

新建一个Delphi 程序,添加一个按钮,然后写入以下代码:

procedure TForm1.Button1Click(Sender: TObject);begin  Beep;end;

执行程序,单击按钮,你会听到一个短促的声音。现在移到单元的uses语句,把原先的代码:

uses  Windows, Messages, SysUtils, Classes, ...

改为下面的样式,只要把SysUtils单元移到Windows之前:

uses  SysUtils, Windows, Messages, Classes, ...

现在如果重新编译这段代码,你会得到一个编译错误:”Not enough actual parameters”(实际参数不够)。问题在于Windows 单元定义了另一个带两个参数的Beep 函数。应该说uses子句中第一个单元的定义被后面单元的定义覆盖,解决方法很简单:

procedure TForm1.Button1Click(Sender: TObject);begin  SysUtils.Beep;end;

不管uses子句中单元顺序如何排列,以上代码都能编译通过。在Delphi中很少有其他命名冲突的情况,因为Delphi 代码通常放在类的方法中,如果不同类中有两个同名的方法不会产生任何冲突,只是使用全程例程会产生冲突问题。

单元和程序

Delphi 应用程序源代码文件可分成两类,它们是一个或多个单元文件及一个程序文件,单元文件可以看成是次一级的文件,它被应用程序的主体——程序文件——引用。理论上如此,实际上程序文件通常是自动产生的,作用有限,程序启动并运行主窗体时才会用到它。程序文件的代码,或说Delphi 工程文件(DPR),可用手工进行编辑,也可通过工程管理器及其与应用程序、窗体相关的选项进行编辑。

程序文件的结构通常比单元文件的结构简单得多。下面是一个程序文件的源代码:

program Project1;uses  Forms,  Unit1 in Unit1.PAS?{Form1DateForm};begin  Application.Initialize;  Application.CreateForm (TForm1, Form1);  Application.Run;end.

从上可见,文件中只有一个uses区和应用程序的主体代码,主体代码包含在begin 和 end 关键字之间。程序的uses子句特别重要,因为需要通过它来管理应用程序的编译和连接。

结束语

讨论完Delphi中Pascal 应用程序的结构,本书就翻过了最后一章,至少目前是这样,欢迎来email发表你的意见和要求。

如果想进一步学习Delphi Object Pascal中面向对象的内容,你可以参考我已出版的书《精通Delphi 5》(Mastering Delphi 5 ,Sybex,1999),详细情况可访问网址www.marcocanto.com,你也可以从该网址上下载本书的最新版本。


一个爱学习的人!
2005-01-27 15:45
shuyue1981
Rank: 1
等 级:新手上路
帖 子:89
专家分:0
注 册:2005-1-20
得分:0 
PASCAL 精要 附录A 术语表

这里列出了本书中用到的一些技术术语,在别的地方你也能找到它们,不过我想还是把它们集中一处,以便查找。

堆(内存)

堆表示程序可用的内存区,也叫动态内存区。堆内存的分配与释放次序是随机的,这就是说,如果你按次序分配三块内存,那么到时并不按分配时的次序释放内存。 堆管理器会负责所有操作,你只需简单地使用GetMem 函数请求新内存或调用constructor 建立对象, Delphi 会返回一个新的内存块(随意重用已经丢弃的内存块)。

堆是应用程序可用的三种内存区之一, 其它两种分别是全局内存区(存放全程变量) 和栈。与堆相反,全程变量内存在程序启动时就分配,然后一直保留到程序终止才释放;栈的内容请详见术语表。

Delphi 使用堆为对象、字符串、动态数组及特殊的动态内存请求(GetMem)内存分配。

Windows 应用程序的地址空间最大允许有 2 GigaByte, 其中大部分能被堆使用。

栈(内存)

栈表示程序可用的内存区,栈内存动态分配,并按特定次序分配、释放。栈内存按后进先出次序(LIFO)分配,这表示最后分配的内存区先被释放。栈内存一般在例程中使用(过程、函数及方法调用)。 当你调用例程时,例程参数及返回值是放在栈中的(除非使用Delphi缺省调用方式,对调用过程进行优化)。此外,例程中声明的变量(在begin语句前的 var 块中)也存放在栈中,所以当例程终止时,这些变量会被自动清除(在返回调用点之前以LIFO次序释放)。

栈是应用程序可用的三种内存区之一,其它两种分别是全局内存区和堆。堆的内容请详见术语表。

Delphi 使用栈存放例程参数及其返回值(除非你使用Delphi缺省的 register 调用协定)、局部例程变量、Windows API 函数调用等等。

Windows 应用程序可以预留大量的栈内存,在 Delphi 中你可以通过工程选项的 linker 页设置, 不过一般采用缺省设置就可以了。 如果你收到一个栈溢出错误信息,这可能是因为你的函数进入了死循环自调用,而不是栈空间太小。

其它

  • Dynamic
  • Static
  • Virtual
  • memory leak
  • painting
  • literal
  • array
  • API
  • class reference
  • class method
  • parent
  • owner
  • self

一个爱学习的人!
2005-01-27 15:45
shuyue1981
Rank: 1
等 级:新手上路
帖 子:89
专家分:0
注 册:2005-1-20
得分:0 
PASCAL 精要 附录B 例名表

以下列出了《Pascal精要》中用到的所有例子,需要可以从网上免费下载:

第三章

ResStr: 资源串 Range: 有序类型取值范围 TimeNow: 时间类型数据操作

第四章

GPF: 空指针的一般保护错

第五章

IfTest: if 语句 Loops: for 和 while 语句

第六章

OpenArr: 开放数组参数 DoubleH: 几个简单的过程 ProcType: 过程类型 OverDef: 重载及缺省参数

第七章

StrRef: 字符串引用计数 LongStr: 使用长字符串 FmtTest: 格式化举例

第八章

DynArr: 动态数组 WHandle: Windows 句柄 Callback: Windows 回调函数 StrParam: 命令行参数

第十章

VariTest: 简单的variant变量操作 VariSpeed: variant变量运算速度


一个爱学习的人!
2005-01-27 15:46
shuyue1981
Rank: 1
等 级:新手上路
帖 子:89
专家分:0
注 册:2005-1-20
得分:0 
不能上传文件,这样灌水很累!

一个爱学习的人!
2005-01-27 15:46
siri
Rank: 1
等 级:新手上路
帖 子:12
专家分:0
注 册:2005-2-19
得分:0 
这样的文章太简短了,根本不能学到什么,倒像是一个介绍!

2005-04-22 18:21



参与讨论请移步原网站贴子:https://bbs.bccn.net/thread-11777-1-1.html




关于我们 | 广告合作 | 编程中国 | 清除Cookies | TOP | 手机版

编程中国 版权所有,并保留所有权利。
Powered by Discuz, Processed in 0.161162 second(s), 7 queries.
Copyright©2004-2024, BCCN.NET, All Rights Reserved