delphi教程少(DELPHI基础教程:Delphi自定义部件开发(二)[4])

2025-09-02 02:00:01 :0

delphi教程少(DELPHI基础教程:Delphi自定义部件开发(二)[4])

今天给各位分享DELPHI基础教程:Delphi自定义部件开发(二)[4]的知识,其中也会对DELPHI基础教程:Delphi自定义部件开发(二)[4]进行解释,如果能碰巧解决你现在面临的问题,别忘了关注本站,现在开始吧!

本文目录

DELPHI基础教程:Delphi自定义部件开发(二)[4]

  ⑵ 定义处理过程类型

  一旦你决定产生事件 就要定义事件如何被处理 这就是要决定事件处理过程的类型 在大多数情况下 定义的事件处理过程的类型是简单的通知类型(TNotifyEvent)和已定义的事件类型

  通知事件只是告诉你特定的事件发生了 而没有描述什么时候和什么地方 通知事件使用时只带一个TObject类型的参数 该参数是Sender 然而所有通知事件的处理过程都知道是什么样的事件发生和发生在那个部件 例如 Click事件是通知类型 当编写Click事件的处理过程时 你知道的是Click事件发生和哪个部件被点按了 通知事件是单向过程 没有提供反馈机制

  在某些情况下 只知道什么事件发生和发生在那个部件是不够的 如果按键事件发生 事件处理过程往往要知道用户按了哪个键 在这种情况下 需要事件处理过程包含有关事件的必要信息的参数 如果事件产生是为了响应消息 那么传递给事件的参数最好是直接来自消息参数

  因为所有事件处理过程都是过程 所以从事件处理过程中返回信息的唯一方法是通过var参数 自定义部件可以用这些信息决定在用户事件处理过程执行后是否和怎样处理事件

  例如 所有的击键事件(OnKeyDown OnKeyUp和OnKeyPressed)通过名为key的var参数传递键值 为了使应用程序看见包含在事件中的不同的键 事件处理过程可以改变key变量值

  ⑶ 声明事件

  一旦你决定了事件处理过程的类型 你就要准备声明事件的方法指针和属性 为了让用户易于理解事件的功能 应当给事件一个有意义的名字 而且还要与部件中相似的属性的名称保持一致

  Delphi中所有标准事件的名称都以 On 开头 这只是出于方便 编译器并不强制它 Object Inspector是看属性类型来决定属性是否是事件 所有的方法指针属性都被看作事件 并出现在事件页中

  ⑷ 调用事件

  一般说来 最好将调用集中在事件上 就是说在部件中创建一个虚方法来调用用户的事件处理过程和提供任何缺省处理 当调用事件时 应考虑以下两点

  ● 必须允许空事件

  ● 用户能覆盖缺省处理

  不能允许使空事件处理过程产生错误的情况出现 就是说 自定义部件的正常功能不能依赖来自用户事件处理过程的响应 实际上 空事件处理过程应当产生与无事件处理过程一样的结果

  部件不应当要求用户以特殊方式使用它们 既然一个空事件处理过程应当与无事件处理过程一样动作 那么调用用户事件处理过程的代码应当象这样

  if Assigned(OnClick) then OnClick(Self)

  { 执行缺省处理 }

  而不应该有这样的代码

  if Assigned(OnClick) then

  OnClick(Self)

  else

  … { 执行缺省处理 }

  对于某些种类的事件 用户可能想取代缺省处理甚至删除所有的响应 为支持用户实现这种功能 你需要传递var参数给事件处理过程 并在事件处理过程返回时检测某个值 空事件处理过程与无事件处理过程有相同作用 因为空事件处理过程不会改变任何var参数值 所以缺省处理总是在调用空事件处理过程后发生

  例如在处理Key Press事件 用户可以通过将var参数key的值设置为空字符(# )来压制部件的缺省处理 代码如下

  if Assigned(OnkeyPress) then OnkeyPress(Self key)

  if key 《》 # then { 执行缺省处理 } ;

  实际的代码将与这稍有不同 因为它只处理窗口消息 但处理逻辑是相同的 在缺省情况下 部件先调用任何用户赋予的事件处理过程 然后执行标准处理 如果用户的事件处理过程将key设为空 则部件跳过缺省处理

   处理消息

  在传统Windows编程中 一个很关键的方面是处理Windows发送给应用程序的消息 Delphi已经帮你处理了大多数的普通消息 但是在创建部件的过程中有可能Delphi没有处理方法 得由自己处理消息 也可能创建了新的消息需要处理它们

  学习掌握Delphi的消息处理 要掌握以下三个方面

  ● 理解消息处理系统

  ● 修改(改变)消息处理方法

  ● 建立新的消息处理方法

   理解消息处理系统

  所有的Delphi对象内部具有处理消息的机制 如调用消息处理方法或消息处理过程 消息处理的基本思想是对象接收某种消息并派送它们 这是通过调用与接收的消息相应的方法来实现的 如果没有相应于消息的指定的方法 那就调用缺省处理 下面的图解表示消息派送系统

  Delphi部件库定义了将所有Windows消息(包括用户自定义消息)直接转换到对象方法调用的消息派送系统 一般没有必要改变这种消息派送系统 只要建立消息处理方法

  ⑴Windows消息中有什么?

  Windows消息是包含若干有用的域的数据记录 记录中最重要的是一个整型大小的值 该值标识消息 Windows定义了大量的消息 库单元Messages声明了所有消息的标识 消息中其它的有用信息包括两个域参数和结果域 两个参数分别是 位和 位的 Windows代码总是以wParam和lParam来引用它们

  最初 Windows程序员不得不记住包含的每一个参数 现在 微软公司已经命名了这参数 这样理解伴随这些消息的信息就更简单了 例如 WM_KEYDOWN消息的参数被称为vkey和keydata 这就比wParam和lParam给出了更多的描述信息

  Delphi为不同类型的消息定义了指定的记录类型 如鼠标消息在long参数中传递鼠标事件的x y座标 一个在高字 一个在低字 使用鼠标消息记录 你不需要自己关心哪个字是哪个座标 因为引用这些参数时通过名子Xpos和Ypos取代了lParamLo和lParamHi

  ⑵ 派送方法

  当应用程序创建窗口时 在Windows Kernel中注册了一个窗口过程 窗口过程是处理窗口消息的函数 传统上 窗口过程包括了Case表达式 表达式的每个入口是窗口要处理的每一条消息 当你每次创建窗口时 必须建立完整的窗口过程

  Delphi在下列三方面简化了消息派送

  ● 每个部件继承了完整的消息派送系统

  ● 派送系统具有缺省处理 用户只需定义想响应的消息的处理方法

  ● 可以修改消息处理的一部分 依靠继承的方法完成大多数处理

  这种消息派送系统的最大优点是用户能在任何时候安全地发送任何消息给任何部件 如果部件没有为该消息定义处理方法 那缺省处理方法会解决这个问题 通常是忽略它

  Delphi为应用程序每种类型的部件注册了名为MainWndProc的方法作为窗口过程 MainWndProc包含了异常处理块 它完成从Windows到名为WndProc的虚方法传送消息记录 并且通过调用应用程序对象的HandleException方法处理异常

  MainWndProc是静态方法 没有包含任何消息的指定处理方法 定制过程发生在WndProc中 因为每个部件类型都能覆盖该方法以适合特定的需要

  WndProc方法为每个影响它们处理的任何条件进行检查 以捕捉不要的消息 例如 当被拖动时 部件忽略键盘事件 因此 inControl的WndProc只在没有拖动时传送键盘事件 最后WndProc调用Dispatch方法 该方法是从TObject继承来的静态方法 决定什么方法来处理消息

  Dispatch使用消息记录的Msg域来决定怎样派送特定消息 如果部件已经给该消息定义了处理方法 则Dispatch调用该方法 反之 Dispatch调用缺省处理方法

   改变消息处理方法

  在改变自定义部件的消息处理方法之前 先要弄清楚你真正想要做什么 Delphi将大多数的Windows消息转换成部件编写者和部件用户都能处理的事件 一般来说 你应当改变事件处理行为而不是改变消息处理行为

  为了改变消息处理行为 要覆盖消息处理方法 也能提供捕获消息防止部件处理该消息

  ⑴ 覆盖处理方法

  为了改变部件处理特定消息的方法 要覆盖那个消息的处理方法 如果部件不处理该消息 你就需要声明新的消息处理方法

  为了覆盖消息处理方法 要在部件中以相同的消息索引声明新的方法 不要使用override指令 你必须使用Message指令和相应的消息索引

  例如 为了覆盖一个处理WM_PAINT消息的方法 你要重声明WMPaint方法

  type

  TMyComponent=class(…)

  procedure WMPaint(var Message: MPaint) message WM_PAINT;

  end;

  ⑵ 使用消息参数

  在消息处理方法内部 自定义部件访问消息记录的所有参数 因为消息总是var参数 如果需要的话 事件处理过程可以改变参数的值 Result域是经常改变的参数 Result是Windows文档中所指的消息的返回值 由SendMessage返回

  因为消息处理方法的消息参数的类型随着被处理的消息的变化而变化 所以应当参考Windows消息文档中的参数的名字和含义 如果出于某种原因要使用旧风格的消息参数(wParam lParam) 可以配合通用类型TMessage来决定Message

  ⑶ 捕获消息

  在某种情况下 你可能希望自定义部件能忽略某种消息 就是说 阻止部件将该消息派送给它的处理方法 为了那样来捕获消息 可以覆盖虚方法WndProc

  WndProc方法在将消息传给Dispatch方法前屏蔽该消息 它依次决定哪一个方法来处理消息 通过覆盖WndProc 部件得到了派送消息之前过滤它们的机会

  通常 象下面这样覆盖WndProc:

  procedure TMyControl WndProc(var Message: TMessage)

  begin

  { 决定是否继续处理过程 }

  inherited WndProc (Message)

  end;

  下面的代码是TControl的WndProc的一部分 TControl定义整个范围内的鼠标消息 当用户拖动和放置控制时 它们将被滤过

  procedure TControl WndProc(var Message:TMessage)

  begin

  if (Message Msg 》= WM_MOVSEFIRST) and

  (Message Msg 《= WM_MOUSELAST) then

  if Dragging then

  DragMouseMsg(MMOUSE(Message)) { 处理拖动 }

  else

  …   { 正常处理其它 }

  …   { 否则正常处理 }

  end;

   返回目录 DELPHI基础教程

       推荐

       Java程序设计培训视频教程

       J EE高级框架实战培训视频教程

  Visual C++音频/视频技术开发与实战

  Oracle索引技术

  ORACLE G数据库开发优化指南

  Java程序性能优化 让你的Java程序更快 更稳定

  C嵌入式编程设计模式

  Android游戏开发实践指南

lishixinzhi/Article/program/Delphi/201311/25120

DELPHI基础教程:SQL编程(一)[4]

   利用参数器(Parameter Editor)来为参数赋值

  具体方法是 选中TQuery部件 单击鼠标右键 然后从中选择Define Parameters 便可以打开参数器

  例如 在TQuery部件的SQL属性中我们设置如下的SQL语句

  Setect * From Customer Where CustNO=:Number;

  TQuery的DatabaseName属性为DBDEMOS 其中Number为参数变量 我们便可以为参数Number赋值 在Datetype组合框中选择该参数的数据类型为整数Integer 在Value框中可以为参数Number赋一个值 也可以单击Null Value检查框为参数Number赋一个空值Null 给参数赋值之后 单击OK按钮 这样TQuery部件中的SQL 查询便准备好了 而且参数值也被赋给了动态SQL语句中相应的参数 此时当把TQuery 部件的Active属性设置成True时 在与TQuery部件相连的数据浏览部件中会显示出查询结果 通过参数器为参数赋值 这种方式缺乏应有的灵活性 在实际应用中用得较少 在实际应用中程序设计人员希望用更灵活方便的方式为参数赋值 那就是我们接下来要介绍的另一种途径

   在运行过程中 通过程序为参数赋值

  用这种方式为参数赋值有三种方法

  ①根据参数在SQL语句中出现的顺序 设置TQuery部件的Params属性值为参数赋值

  ②直接根据SQL语句中各参数的名字 调用ParamByName方法来为各参数赋值

  ③将TQuery部件的DataSource属性设置为另一个数据源 这样将另一个数据源中与当前TQuery部件的SQL语句中的参数名相匹配的字段值赋给其对应的参数

  这三种方法我们将在下面的三小节中具体地介绍

   使用Params属性为参数赋值

  TQuery部件具有一个Params属性 它们在设计时不可用 在程序运行过程中可用 并且是动态建立的 当为TQuery部件编写动态SQL 语句时 Delphi 会自动地建立一个数组Params 数组Params是以 下标开始的 依次对应动态SQL 语句中的参数 也就是说动态SQL语句中第一个参数对应Params 依此类推

  例如 一个TQuery部件Query 我们为它编写的动态SQL语句是

  Insert Into Customer(CustNo Name Country)

  Values( CustNo :Name : Country)

  对于上述这条动态SQL语句中的参数 我们可以利用TQuery部件的params 属性为参数赋值

  Query params AsString := ;

  Query params AsString := Lichtenstein ;

  Query params AsString := USA ;

  上述语句将把 赋给参数 Cuse_No Lichtenstein 赋给参数 Name USA 赋给参数 Country

   使用ParamByName方法为参数赋值

  ParamByName是一个函数 用动态SQL语句中的参数作为调用ParamByName函数的参数 这样便可以为它们赋值 使用这种赋值方法 必须要知道动态SQL语句参数的名字

  例如在 节中的例子中 也可以用下述方法给参数赋值

  Query ParamByName( CustNo ) AsString := ;

  Query ParamByName( Name ) AsString := Lichtenstein ;

  Query ParamByName( Country ) AsString := USA ;

  使用这种方法同样可以为各参数赋值 而且更加直观一些

   使用Datasource属性为参数赋值

  上述两种方法的共同特点是 我们在为各参数赋值时 我们是知道各参数对应的具体参数值的 而在具体的应用程序中 有些参数值常常是无法确定的 例如参数值来自于另一个查询结果 对于这种情况 Delphi提供了使用Datasource属性为动态SQL 语句中尚存在没有赋值的参数时 Delphi 会自动检查 TQuery 部件的 Datasource 属性 如果为Datasource属性设置了属性值(该属性的值是另一个TDatasource部件的名字) Delphi 会把没有赋值的参数与TDatasource部件中的各字段比较 Delphi 会将相应的字段值赋给与其相匹配的参数 利用这种方法也能实现所谓的连接查询 我们在学习使用TTable部件时 便会创建主要 明细型数据库应用 用TQuery部件创建的连接查询与主要 明细型应用是相似的

  例如 在如图 所示的应用中 设置了下列部件

  ● 一个TTable部件

  名字为Cust 它的DatabaseName属性为DEMOS TableName属性为Customer

  ● 一个TDatasource部件

  名字为Custsource 其Dataset属性被设置为Cust

  ● 一个TQuery部件

  名字为ORDERS 其DatabaseName被设置为DEMOS SQL属性值为

  Select Orders CustNo Orders OrderNo Orders SaleDate FROM Orders

  WHERE Orders CustNo =: CustNo

  ORDERS的DataSouce属性被设置为CustSource

  ● 一个TDatasource部件

  名字为OrderSource 其DataSet属性被设置为Orders

  ● 两个TDBGrid部件

  它们分别连接CustSource和OrderSource

  TQuery部件Orders中的动态SQL语句中的参数 CustNo在程序设计过程中没有给它赋值 当该应用程序运行时Delphi会自动地到其Datasource属性中说明的数据源CustSource中查找与参数 CustNo匹配的字段 而CustSource中正好有一个名字为 CustNo 的字段与参数 CustNo匹配 这样Customer表中的CustNo字段值被赋给了参数 : CustNo 而当每移动Customer表中的记录指针 参数 CustNo的值会随之改变 而参数 CustNo的值发生改变时 Orders中的动态SQL语句会根据新的参数值重新查询 从数据库表中获取相应的订单数据 这样也变实现了类似于主要 明细型应用 即连接查询

   Prepare方法的使用

  在使用动态SQL语句编程时 常常用到一个很重要的方法prepare 调用prepare 方法之后 Delphi会将带参数的SQL语句传送给与其对应的数据库引擎 对动态SQL语句进行语法分析和优化 虽然在用动态SQL语句编程时 调用prepare方法并不是必须的 但是这里我们要极力推荐调用prepare方法 因为调用prepare方法后 会大大提高动态SQL 语句的执行性能 特别是当要反复多次执行同一条动态SQL语句时 其优越性会更加明显 如果在应用程序中执行一条SQL语句之前并没有显式地调用prepare方法 每次在执行SQL 语句时 Delphi会隐含地调用propare方法以准备这个查询

  TQuery部件还有一个prepare属性 这是一个布尔型属性 当其属性值为True时 表明该查询已被准备好了( SQL 语句已被传送到数据库引擎中 ) 当我们使用参数器Parameters Editor来为动态SQL语句中的参数赋值时 当设置完相应的参数值并退出参数器时 Delphi会隐含地调用prepare方法以准备好查询

  当SQL语句执行完之后 要想准备下一个查询 首先必须调用close方法 然后才能调用prepare方法准备下一个查询 一般来说 在一个应用程序中应该调用一次prepare方法 常常在窗体的OnCreate事件处理过程中调用prepare方法 然后用上述介绍的方法为参数赋值 最后调用Open方法或ExecSQL方法执行SQL语句 以完成查询

  当然在调用prepare方法准备好一个查询时 会消耗一些数据库资源 因而每当一个查询执行完毕之后 要养成调用Unprepare方法以撤消查询的好习惯 在运行程序过程中 通过程序改变TQuery部件的SQL属性值时 Delphi会自动地调用Close方法和Unprepare 方法 以撤消查询

   返回目录 DELPHI基础教程

       推荐

       Java程序设计培训视频教程

       J EE高级框架实战培训视频教程

  Visual C++音频/视频技术开发与实战

  Oracle索引技术

  ORACLE G数据库开发优化指南

  Java程序性能优化 让你的Java程序更快 更稳定

  C嵌入式编程设计模式

  Android游戏开发实践指南

lishixinzhi/Article/program/Delphi/201311/25147

DELPHI基础教程:SQL编程(一)[2]

  静态方式是把SQL命令文作为TQuery部件的SQL属性值进行设置 这样 当执行应用程序时 Delphi便执行TQuery部件SQL属性中设置的SQL命令 如果是SQL中的查询命令 把TQuery部件通过TDataSource部件与数据控制部件相连 查询的结果将会显示在与 TQuery部件相连接的数据浏览部件中 动态SQL语句是指SQL语句中包含一些参数变量 在程序中可以为这些参数赋值 在程序运行过程中 各个参数值是变化的 TQuery部件的SQL 属性中的SQL语句的编写也有两种方法 一种方法是在程序设置阶段便将相应的SQL语句写入到TQuery的SQL属性中 另一种方法是在Delphi开发的应用程序将SQL语句 包含在Pascal代码单元中

  在SQL编程中使用TQuery部件的具体方法步骤如下

  ①为TQuery部件设置DatabaseName属性 它可以是用BDE建立的数据库的别名 或桌面数据库系统中的目录名或数据库服务器中的文件名 如果在应用中使用了TDatabase 部件 那么TQuery部件的DatabaseName属性可以是TDatabase部件中定义的一个数据库别名 详细情况请参看 TDatabase部件的使用 ;

  ②为TQuery部件设置SQL属性 TQuery部件的SQL属性值就是应用程序要执行的SQL 命令文本 设置SQL属性有两种方法

  ● 在程序设计过程中 我们可以通过对象浏览器(Object Inspector)SQL属性在Object Inspector中选择SQL属性 这样会打开String List Editor窗口 在其中我们便可以编写SQL命令 我还可以打开Visual Query Builder来编写SQL命令 (只有Delphi的客户/服务器版本才具有这一工具)

  ● 将SQL命令包含在Pascal代码单元中

  在程序运行过程中 首先调用TQuery部件的Close方法关闭当前的TQuery部件 然后调用Clear方法清除SQL属性 并说明新的SQL命令文本 然后调用Add方法 将新的SQL命令文本加入到SQL属性中

  ③通过调用TQuery部件的Open方法或ExecSQl方法执行 SQL 命令 Open 方法只执行Select命令 ExecSQL方法还可以执行其它的SQL命令 Open方法和ExecSQL 方法的区别我们在后面的章节里会进一步地加以讨论的

  如果使用动态SQL语句 首先调用prepare方法 给动态SQL语句中的参数赋值 然后再调用Open方法或ExecSQL方法 调用propare 方法并不是必须的 但是对于要多次执行TQuery部件中SQL属性中的动态SQL语句 调用Prepare可以大大提高TQuery部件执行SQL语句的性能

   在TQuery部件中编写简单的SQL查询命令

  在这一节里我们将学习如何使用TQuery部件编写简单的SQL查询命令 并在Delphi 应用程序中实现SQL查询

  例如 如果我们想查询出表Customer DB中客户的编号和公司名称 我们按下列步骤来实现

  ①在应用窗体中放置一个TQuery部件 一个TDataSource部件一个TDataGrid部件 并将它们连接起来

  ②设置窗体TQuery 部件Query 的DatabaseName属性值为DBDEMOS

  ③双击Object Inspector窗口中Query 的SQL 属性 Delphi 将显示 String List Editor窗口

  ④在图 中的窗口中输入SQL语句

  Select CustNo Company From Custormer;

  ⑤单击OK按钮 关闭String List Editor窗口

  ⑥设置Query的Open属性为True

   SQL语言编程概述

  在Delphi应用程序中的SQL命令语句是包含在TQuery部件的SQL属性中 TQuery部件的SQL属性是TString类型的 也就是说SQL属性值是一个字符串列表 这个字符串列表非常类似于一个字符串类型的数组 有关TString类型的信息请参看联机帮助 在前一节里我们介绍了TQuery部件可以执行两种SQL语句

  ● 静态SQL语句

  ● 动态SQL语句

  静态SQL语句在程序设计时便已固定下来 它不包含任何参数和变量 例如下面的语句便是一条静态SQL语句

  Select * From Cusromer Where CustNo = ;

  而动态SQL语句 也被称作参数化的语句 在其中间包含着表示字段名或表名的参数 例如下面的语句是一条动态SQL语句

  Select * From Customer Where CustNo =: Number;

  其中的变量Number便是一个参数变量 它由一个冒号引导 在程序运行过程中 必须要为该参数赋值 该条SQL语句才能正确执行 每次运行应用程序时可以为该参数变量赋予不同的值

    SQL命令文本的编写

   使用String List Editor编写

  我们要为TQuery部件的SQL属性设置SQL命令文本时 可以在应用窗体中选择TQuery部件且双击Object Inspector窗口中的SQL属性 这样便打开了String List Editor 窗口 在该窗口中我们便可以编写各种SQL命令 如图 所示

  在编写完适当的SQL语句之后 选择 OK 按钮便可以将器中的 SQL 命令文装入到TQuery部件的SQL属性中 选择SAVE按钮可以将编写好的SQL命令保存到一个文件中供以后编程时使用 我们在编写SQL命令文本时还可以选择Load按钮从一个 SQL 命令文件中调入SQL命令 在程序运行过程中 要想设置TQuery部件的SQL属性 必须首先调用Close方法 关闭TQuery部件 然后再调用Clear方法清除SQL属性中现存的SQL命令语句 最后再调用Add方法为SQL属性设置新的SQL命令语句 例如

  Query Close {关闭Query )

  Query SQL Clear {清除SQL属性中的SQL命令语句}

  Query SQL Add( Select * From Country )

  Query SQL Add( Where Name = ARGENTINA )

  在为TQuery部件设置SQL属性时调用Close方法总是很安全的 如果TQuery部件已经被关闭了 调用Close方法时不会产生任何影响 在应用程序中为SQL属性设置新的SQL 命令语句时 必须要调用Clear方法以清除SQL属性中现存的SQL命令语句 如果不调用Clear方法 便调用Add方法向SQL属性中设置SQL命令语句 那么新设置的SQL命令语句会追加在现存SQL命令语句后面 在程序运行时常常会出现出乎意料的查询结果甚至程序无法运行下去

  在这里要特别注意的 一般情况下TQuery部件的SQL属性只能包含一条完整的SQL语句 它不允许被设置成多条SQL语句 当然有些数据库服务器也支持在TQuery部件的SQL属性中设置多条SQL语句 只要数据库服务器允许这样 我们在编程时可以为 SQL 属性设置多条SQL语句

lishixinzhi/Article/program/Delphi/201311/25145

DELPHI基础教程:Delphi开发数据库应用程序概述(一)[3]

  Visual Query Builder 以可视化的方式建立SQL语句对数据库表和表中的记录进行操作

  ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

  SQL links使得Delphi数据库应用程序利用SQL语言访问驻留在远程服务器上的数据 这些服务器包括ORACLE Sybase Microsoft SQL Server Informix InterBase 当安装SQL Link驱动程序之后 SQL语句便可以直接操作服务器上的数据

   Delphi可以访问的数据源(DataSource)

  Delphi数据库应用程序是通过BDE获取它们所需的数据的 BDE与不同类型的数据源打交道 BDE可以使用的数据源有如表 所示

  表 Delphi可访问的数据源

  ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

  数据源(DataSource)   特 性 描 述  文件扩展名

  ─────────────────────────────────────

  dBASE数据库  数据库表是通过dBASE数据库管理系统或DBD建立的 每个表是一个独立的文件  DBF

  ─────────────────────────────────────

  Paradox数据库  数据库表是通过Paradox数据库管理系统  DB或DBD建立的 每个表是一个独立的文件

  ─────────────────────────────────────

  ASCII文件  表是通过Database Desktop建立的 每个  TXT表是一个独立的文件

  ─────────────────────────────────────

  本地InterBase服务器  数据库是通过InterBase数据库管理系统  GDB建立的 多个表包含在一个数据库文件中

  ─────────────────────────────────────

  SQL数据库服务器   数据库是通过相应的数据库服务器提供的 依赖不同的ORACLE Sybase Informix 专用或通用工具建立的 也可以通过DBD来 数据库管理Microsoft SQL Server  创建数据库 并通过SQL Link访问数据库  系统InterBase

  ─────────────────────────────────────

  ODBC数据源  主要是指那些具有ODBC接口的数据库系统 依赖于相应如MS Access Btrieve等的数据库

  ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

   Delphi数据库的体系结构

  Delphi使用可视化的部件创建数据库应用 跟创建其它的非数据库应用程序一样 数据库部件都具备一定的属性 程序设计人员可以在设计过程中设置部件的多种属性 也可以在程序运行过程中通过程序来设置部件的各种属性

  在Delphi部件板上有两页数据库部件用于开发数据库应用程序

  数据访问部件页 该页上的部件主要用于说明有关的数据库的信息 如应用程序要访问(连接)的数据库 要访问数据库中的具体的数据库表 以及要访问表中哪些字段等 在实际的开发应用中常用的部件有TDataSource TTable TQuery等

  数据控制部件页 该页上的部件主要用于显示浏览数据库中的数据信息 为用户提供了一个可视化的界面 常用的部件有 TDBGrid TDBEdit TDBCheck等 可以让用户对数据库中的信息进行有效的浏览 插入 删除等操作

  TTable TQuery TStoredproc部件负责与实际的数据库表联系 并从中获取数据信息 因而它们又常常被称为数据集部件 它们在程序设计过程中是可见的 但在程序运行时是不可见的 它们通过 BDE 为应用程序提供与数据库的连接 数据控制部件通过TDataSource部件与数据集部件相连 为用户提供一个可视化的界面 并在其中显示数据库中的数据信息

   数据访问部件

  数据访问部件页上提供了一组数据访问部件用来访问数据库中的数据

  当要创建一个数据库应用时 首先在窗体中选择一个数据访问部件 然后为数据访问部件设置有关的属性 说明要访问的数据库 数据表以及表中的记录等 数据访问部件为数据控制部件与数据源建立一条通道 数据访问部件在程序运行时是不可见的 下表列出了数据访问页上的数据访问部件以及它们的主要用途

  表 数据访问部件

  ━━━━━━━━━━━━━━━━━━━━━━━━━━━━

  部件名称   主 要 用 途

  ────────────────────────────

  作为数据集部件TTable TQuery StoredProc组TDataSource 件与数据浏览件TDBGrid TDBEdit之间传送数据的通道

  ────────────────────────────

  TTable  它是存取磁盘上数据库表的媒介 它通过BDE存取数据库表中的数据 TTable再与TDataSource进行 对话 使得数据浏览部件能够有效地从TTable中访问数据并能显示和其中的数据

  ────────────────────────────

  TQuery  它利用SQL语言访问磁盘上数据库表中的数据 并与TDataSource 对话 实现数据浏览部件对数据库的访问

  ────────────────────────────

  TStoredProc 在应用程序中 它主要用来访问远程服务器中的存贮过程

  ────────────────────────────

  TDatabase  当应用程序要登录到一个远程服务器上的数据库时 可以用该部件来建立应用程序与数据库永久

  性的连接

  ────────────────────────────

  TBatchMove 用于复制数据库表的结构或表中的记录

  ────────────────────────────

  TReport  用于创建数据库的输出报表

  ━━━━━━━━━━━━━━━━━━━━━━━━━━━━

lishixinzhi/Article/program/Delphi/201311/25180

DELPHI基础教程:Delphi拖放编程[1]

  拖放(DragDrop)是Windows提供的一种快捷的操作方式 作为基于Windows的开发工具 Delphi同样支持拖放操作 而且开发应用系统的拖放功能十分方便 真正体现了Delphi的强大功能和方便性

  Delphi提供的所有控件(Control 即能获得输入焦点的部件)都支持拖放操作 并有相应的拖放属性 拖放事件和拖放方法 下面我们先介绍控件的拖放支持 而后再给出开发拖放操作的一般步骤和应用实例

   控件的拖放支持

  拖放操作中控件可以分为源控件和目标控件两类 绝大部分控件既可以作为源控件也可以作为目标控件 但也有一部分控件只能支持其中的一种

   拖放属性

  拖放属性主要有两个

  ● DragMode : 拖动模式

  ● DragCursor : 拖动光标

  它们都是在拖放的源控件中设置 DragMode控制用户在运行时间内当在控件上按下鼠标时控件如何反应 如果DragMode置为dmAutomatic 那么当用户在控件上按下鼠标时拖动自动开始 如果DragMode置为dmManual(这是缺省值) 则将通过处理鼠标事件来判断一个拖动是否可以开始

  DragCursor用于选择拖动时显示的光标 缺省值是CrDrag 一般不要去修改它 在程序设计过程中通用的界面规范应该得到开发者的尊重 但有时候为了特定的目的 开发者也可以把自己设计的光标赋给DragCursor

   拖放事件

  拖放事件主要有三个

  ●OnDragOver:拖动经过时激发

  ●OnDragDrop:拖动放下时激发

  ●OnEndDrop :拖动结束时激发

  前两个事件由目标控件响应 后一个事件由源控件响应

  OnDragOver事件最主要的功能是确定当用户就地放下拖动时控件是否可以接受 它的参数包括

  Source : TObject;  {源控件}

  X Y : Integer; {光标位置}

  State : TDragState; {拖动状态}

  var Accept : Boolean {能否接受}

  TDragState是一个枚举类型 表示拖放项目与目标控件的关系

  type

  TDragState = (dsDragEnter dsDragLeave dsDragMove)

  不同取值的意义如下表

  表 DragState 的取值与意义

  ━━━━━━━━━━━━━━━━━━━━━━━━━━━

      取 值                             意 义

  ───────────────────────────

  dsDragEnter 拖动对象进入一个允许拖动对象放下的控件中 为缺省状态

  dsDragLeave 拖动对象离开一个允许拖动对象放下的控件

  dsDragMove 拖动对象在一个允许拖动对象放下的控件内移动

  ━━━━━━━━━━━━━━━━━━━━━━━━━━━

  用户可以利用提供的参数来确定放下的拖动是否可被接受 如

  ● 判断源控件类型

  Accept := Source is TLabel;

  ● 判断源控件对象

  Accept := (Source = TabSet )

  ● 判断光标位置

  见( ) ( )中的例程

  ● 判断拖动状态

  If (Source is TLabel) and (State = dsDragMove) then

  begin

  source DragIcon := New Ico ;

  Accept := True;

  end

  else

  Accept := False;

  当Accept=True时 目标控件可以响应OnDragDrop事件 用于确定拖动被放下后程序如何进行处理

  OnDragDrop事件处理过程的参数包括源控件和光标位置 这些信息可用于处理方式的确定

  OnEndDrag事件是在拖动操作结束后由源控件来进行响应的 用于源控件进行相应的处理 拖动操作结束既包括拖动放下被接受 也包括用户在一个不能接受放下的控件上释放了鼠标 该事件处理过程的参数包括目标控件(Target)和放下位置的坐标 如果Target=nil 表示拖动项目没有被任何控件接受

  在第 节将介绍的文件拖放移动 拖放拷贝操作中 如果操作成功 则文件列表框应更新显示内容 下面这段程序用于实现这一功能

  procedure TFMForm FileListEndDrag(Sender Target: TObject; X Y: Integer)

  begin

  if Target 《》 nil then FileList Update;

  end;

  除以上介绍的三个事件外 还有一个事件OnMouseDown 也常用于拖放操作的响应 OnMouseDown虽然不是一个专门的拖放事件 但在人工模式下拖动的开始是在这一事件的处理过程中实现的

lishixinzhi/Article/program/Delphi/201311/25213

为什么Delphi的教程那么少

以下一系列原因至使Delphi的用户群越来越少,所以资料也就越来越少,原意为Delphi写书的人就越来越少。
1、Delphi的实际使用人群越来越少,Delphi工程师的就业前景越来越小。
2、Delphi的后期版本除一些特别点上有不同外,主要操作、界面是很类似的,掌握了Delphi7,其后续版本对脑子不太笨的技术人员来说,其本上就都掌握了。一些不同的地方,上网查查多数就懂了。
3、Delphi主要用于数据库的二层架构的客户端开发,当前,基于这种二层架构的数据库系统的安全性越来越被人认识到,所以只要安全要求不高的环境下才有用,所以,市场越来越小,所以用它的人越来越少。
4、当前的电脑应用越来越网络化,基于.net、基于网站开发、基于3层架构的开发越来越被人看重,所以,Delphi的使用人群越来越少,随之而来的结果,自然是资料也越来越少。
5、也可以使用Delphi的最新版本进行.net的网站开发,但,很明显,不如使用微软的VS系列,因为微软自身掌握了核心技术,稳性性、易用性、通用性、使用人群都要比Delphi广。
6、与Delphi的出品公司的运作理念也有很大的关系,Delphi与BCB原来是宝兰公司的,后来被Embarcadero(易愽龙)收购,两个公司对市场的运作都很菜,宣传不利,产品又以天价卖,其结果是正规公司用不起,非正规公司及个人用户用盗版。

DELPHI基础教程:开发Delphi对象式数据管理功能(五)[1]

   第二十章 开发Delphi对象式数据管理功能(五)

    写DFM文件的过程 WriteComponentResFie

  该过程带有两个参数FileName和Instance FileName参数指定要写入的DFM文件名 Instance参数是TComponent类型的 它指定要写入的部件名 一般是TForm对象的子类 该过程将Instance部件和其拥有的所有部件写入DFM文件

  这个过程的意义在于 可以在程序运行过程中产生Delphi的窗体部件和在窗体中插入部件 并由该函数将窗体写入DFM文件 支持了动态DFM文件的重用性

  该过程的程序是这样的

  procedure WriteComponentResFile(const FileName: string; Instance: TComponent)

  var

  Stream: TStream;

  begin

  Stream := TFileStream Create(FileName fmCreate)

  try

  Stream WriteComponentRes(Instance ClassName Instance)

  finally

  Stream Free;

  end;

  end;

  函数中 用FileStream创建文件 用Stream对象的WriteComponetRes方法将Instance写入流中

   读DFM文件的函数 ReadComponentResFile

  ReadComponentResFile函数带有两个参数FileName和Instance FileName参数指定要读DFM文件名 Instance参数指定从DFM文件中要读的部件 该函数从DFM文件中将Instance和它拥有的所有部件 并返回该部件

  这个函数的意义在于 配合WriteComponentResFile过程的使用支持DFM文件的重用性

  该函数的程序是这样的

  function ReadComponentResFile(const FileName: string; Instance: TComponent)

  TComponent;

  var

  Stream: TStream;

  begin

  Stream := TFileStream Create(FileName fmOpenRead)

  try

  Result := Stream ReadComponentRes(Instance)

  finally

  Stream Free;

  end;

  end;

  程序中使用FileStream对象打开由FileName指定的DFM文件 然后用Stream对象的ReadComponentRes方法读出Instance 并将读的结果作为函数的返回值

   读取Delphi应用程序资源中的部件

  函数InternalReadComponentRes可以读取Delphi应用程序资源中的部件 Delphi 的DFM文件在程序经过编译链接后被嵌入应用程序的资源中 而且格式发生了改变 即少了资源文件头

  在第一节中曾经介绍过TResourceStream对象 该对象是操作资源媒介上的数据的 函数InternalReadComponentRes用了TResourceStream 程序是这样的

  function InternalReadComponentRes(const ResName: string;

  var Instance: TComponent) Boolean;

  var

  HRsrc: THandle;

  begin { 避免 EResNotFound 异常事件的出现 }

  HRsrc := FindResource(HInstance PChar(ResName) RT_RCDATA)

  Result := HRsrc 《》 ;

  if not Result then Exit;

  FreeResource(HRsrc)

  with TResourceStream Create(HInstance ResName RT_RCDATA) do

  try

  Instance := ReadComponent(Instance)

  finally

  Free;

  end;

  Result := True;

  end;

  HInstance是一个Delphi VCL定义的全局变量 代表当前应用程序的句柄 函数用了资源访问API函数FindResource来测定是否存在ResName所描述资源 因为在TResourceStream的创建过程还有FindResource等操作 所以函数中调用了FreeResource 最后函数调用了Stream对象的ReadComponent方法读出部件 因为函数的Instance是var类型的参数 所以可以访问Instance 得到读出的部件

   DFM文件与标准文本文件(TXT文件)的相互转换

  在Delphi可视化设计环境中 允许程序员在代码器中以文本的方式浏览和修改DFM文件内容 当用File/Open命令直接打开DFM文件或者选择窗体设计窗口的弹出式菜单上的View as Text命令时 就会在器中出现文本形式的信息 我们姑且将这种文本形式称之为窗体设计脚本 Delphi提供的这种脚本功能是对Delphi可视化设计的一大补充 当然这个脚本能力是有限制的 比方说不能在脚本任意地添加和删除部件 因为代码和DFM脚本是紧密相连的 任意添加和修改会导致不一致性 然而在动态生成的DFM文件中 就不存在这一限制 后面会介绍DFM动态生成技术的应用

  实际上 DFM文件内容是二进制数据 它的脚本是经过Delphi开发环境自动转化的 而且Delphi VCL中的Classes库单元中提供了在二进制流中的文件DFM和它的脚本之相互转化的过程 它们是ObjectBinaryToText和ObjectTextBinary ObjectResourceToText和ObjectTextToResource

  ObjectBinaryToText过程将二进制流中存储的部件转化为基于文本的表现形式 这样就可以用文本处理函数进行处理 还可以用文本器进行查找和替代操作 最后可以将文本再转化成二进制流中的部件

  ObjectBinaryToText过程的主程序是这样的

  procedure ObjectBinaryToText(Input Output: TStream)

  var

  NestingLevel: Integer;

  SaveSeparator: Char;

  Reader: TReader;

  Writer: riter;

  procedure WriteIndent;

  const

  Blanks: array of Char = ;

  var

  I: Integer;

  begin

  for I := to NestingLevel do Writer Write(Blanks SizeOf(Blanks))

  end;

  procedure WriteStr(const S: string)

  begin

  Writer Write(S Length(S))

  end;

  procedure NewLine;

  begin

  WriteStr(# # )

  WriteIndent;

  end;

  procedure ConvertHeader;

  begin

  …

  end;

  procedure ConvertBinary;

  begin

  …

  end;

  procedure ConvertValue;

  begin

  …

  end;

  procedure ConvertProperty;

  begin

  …

  end;

  procedure ConvertObject;

  begin

  …

  end;

  begin

  NestingLevel := ;

  Reader := TReader Create(Input )

  SaveSeparator := DecimalSeparator;

  DecimalSeparator := ;

  try

  Writer := riter Create(Output )

  try

  Reader ReadSignature;

  ConvertObject;

  finally

  Writer Free;

  end;

  finally

  DecimalSeparator := SaveSeparator;

  Reader Free;

  end;

  end;

  过程中调用的ConvertObject过程是个递归过程 用于将DFM文件中的每一个部件转化为文本形式 因为由于部件的拥有关系 所以部件成嵌套结构 采用递归是最好的方式

  procedure ConvertObject;

  begin

  ConvertHeader;

  Inc(NestingLevel)

  while not Reader EndOfList do ConvertProperty;

  Reader ReadListEnd;

  while not Reader EndOfList do ConvertObject;

  Reader ReadListEnd;

  Dec(NestingLevel)

  WriteIndent;

  WriteStr( end # # )

  end;

  NestStingLevel变量表示部件的嵌套层次 WriteIndent是写入每一行起始字符前的空格 ConvertHeader过程是处理部件的继承标志信息 转换成的头信息文本有两种形式

  Inherited TestForm : TTestForm

  或者

  Object TestForm : TTestForm

  前者是ffInherited和ffChildPos置位 后面是都没置位

  ConvertProperty过程用于转化属性

  procedure ConvertProperty;

  begin

  WriteIndent;

  WriteStr(Reader ReadStr)

  WriteStr( = )

  ConvertValue;

  WriteStr(# # )

  end;

  WriteIndent语句写入属性名前的空格 WriteStr(Reader ReadStr)语句写入属性名ConvertValue过程根据属性的类型将属性值转化为字符串 然后写入流中

lishixinzhi/Article/program/Delphi/201311/25088

DELPHI基础教程:Delphi自定义部件开发(二)[1]

   Delphi部件编程

   创建属性

  属性(Property)是部件中最特殊的部分 主要因为部件用户在设计时可以看见和操作它们 并且在交互过程中能立即得到返回结果 属性也很重要 因为如果将它们设计好后 将使用户更容易地使用 自己维护起来也很容易

  为了使你在部件中更好地使用属性 本部分将介绍下列内容

  ● 为什么要创建属性

  ● 属性的种类

  ● 公布(publishing)继承的属性

  ● 定义部件属性

  ● 编写属性器

   为什么要创建属性

  属性提供非常重要的好处 最明显的好处是属性在设计时能出现在Object Inspector窗口中 这将简化编程工作 因为你只需读用户所赋的值 而不要处理构造对象的参数

  从部件使用者的观点看 属性象变量 用户可以给属性赋值或读值 就好象属性是对象的域

  从部件编写者的观点看属性比对象的域有更强的功能

  ⑴ 用户可以在设计时设置属性

  这是非常重要的 因为不象方法 只能在运行时访问 属性使用户在运行程序之前就能定制部件 通常你的部件不应包含很多的方法 它们的功能可以通过属性来实现

  ⑵ 属性能隐藏详细的实现细节

  ⑶ 属性能引起简单地赋值之外的响应 如触发事件

  ⑷ 用于属性的实现方法可以是虚拟方法 这样看似简单的属性在不同的部件中 将实现不同的功能

   属性的类型

  属性可以是函数能返回的任何类型 因为属性的实现可以使用函数 所有的Pascal类型 兼容性规则都适用属性 为属性选择类型的最重要的方面是不同的类型出现在Object Inspector窗口中的方式不同 Object Inspector将按不同的类型决定其出现的方式

  你也能在注册部件时描述不同的属性器

  下表列出属性出现在Object Inspector窗口中的方式

  表 属性出现在Object Inspector窗口中的方式

  ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

  属性类型       处 理 方 式

  ───────────────────────────────────────

  简单类型   Numeric Character和 String属性出现在Object Inspector中 用户可以直接

  枚举类型 枚举类型的属性显示值的方式定义在代码中 选择时将出现下拉式列表框 显示所有的可能取值

  集合类型 集合类型出现在Object Inspector窗口中时正如一个集合 展开后 用户通过将集合元素设为True或False来选择

  对象类型 作为对象的属性本身有属性器 如果对象有自己的published属性 用户在Object Inspector中通过展开对象属性列 可以独立它们 对象类型的属性必须从TPersistent继承

  数组类型 数组属性必须有它们自己的属性器 Object Inspector没有内嵌对数组属性的支持

  ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

   公布继承的属性

  所有部件都从祖先类型继承属性 当你从已有部件继承时 新部件将继承祖先类型的所有属性 如果你继承的是抽象类 则继承的属性是protected或public 但不是published 如想使用户访问protected或public属性 可以将该属性重定义为published 如果你使用inControl继承 它继承了Ctl D属性 但是protected的 因此用户在设计和运行时不能访问Ctl D 通过在新部件中将Ctl D重声明为published 就改变了Ctl D的访问级别 下面的代码演示如何将Ctl D声明为published 使之在设计时可被访问

  type

  TSampleComponent=class(inControl)

  published

  property Ctl D;

  end;

   定义部件属性

  ⑴ 属性的声明

  声明部件的属性 你要描述

  ● 属性名

  ● 属性的类型

  ● 读和设置属性值的方法

  至少 部件属性应当定义在部件对象声明的public部分 这样可以在运行时很方便地从外部访问 为了能在设计时属性 应当将属性在published部分声明 这样属性能自动显示在Object Inspector窗口中 下面是典型的属性声明

  type

  TYourComponent=class(TComponent)

  …

  private

  FCount: Integer { 内部存储域 }

  function GetCount: Integer; { 读方法 }

  procedure SetCount(ACount: Integer) { 写方法 }

  pubilic

  property Count: Integer read GetCount write SetCount;

  end;

  ⑵ 内部数据存储

  关于如何存储属性的数据值 Delphi没有特别的规定 通常Delphi部件遵循下列规定

  ● 属性数据存储在对象的数据域处

  ● 属性对象域的标识符以F开头 例如定义在TControl中的属性FWidth

  ● 属性数据的对象域应声明在private部分

  后代部件只应使用继承的属性自身 而不能直接访问内部的数据存储

  ⑶ 直接访问

  使属性数据可用的最简单的办法是直接访问 属性声明的read 和write部分描述了怎样不通过调用访问方法来给内部数据域赋值 但一般都用read进行直接访问 而用write进行方法访问 以改变部件的状态

  下面的部件声明演示了怎样在属性定义的read 和write部分都采用直接访问

  type

  TYourComponent=class(TComponent)

  …

  private { 内部存储是私有 }

  FReadOnly: Boolean; { 声明保存属性值的域 }

  published { 使属性在设计时可用 }

  property ReadOnly: Boolean read FReadOnly write FReadOnly;

  end;

  ⑷ 访问方法

  属性的声明语法允许属性声明的read和write部分用访问方法取代对象私有数据域 不管属性是如何实现它的read 和write部分 方法实现应当是private 后代部件只能使用继承的属性访问

  ① 读方法

  属性的读方法是不带参数的函数 并且返回同属性相同类型的值 通常读函数的名字是 Get 后加属性名 例如 属性Count的读方法是GetCount 不带参数的唯一例外是数组属性 如果你不定义read方法 则属性是只写的

  ② 写方法

  属性的写方法总是只带一个参数的过程 参数可以是引用或值 通常过程名是 Set 加属性名 例如 属性Count的写方法名是SetCount 参数的值采用设置属性的新值 因此 写方法需要执行在内部存储数据中写的操作

  如果没有声明写方法 那么属性是只读的

  通常在设置新值前要检测新值是否与当前值不同

  下面是一个简单的整数属性Count的写方法

  procedure TMyComponent SetCount( value: Integer)

  begin

  if value 《》FCount then

  begin

  FCount := Value;

  update;

  end;

  end;

  ⑸ 缺省属性值

  当声明一个属性 能有选择地声明属性的缺省值 部件属性的缺省值是部件构造方法中的属性值集 例如 当从Component Palette选择某部件置于窗体中时 Delphi通过调用部件构造方法创建部件 并决定部件属性初始值

  Delphi使用声明缺省值决定是否将属性值存在DFM文件中 如果不描述缺省值 Delphi将总是保存该属性值 声明缺省值的方法是在属性声明后加default指令 再跟缺省值

  当重声明一个属性时 能够描述没有缺省值的属性 如果继承的属性已有一个 则设立没有缺省值的属性的方法是在属性声明后加nodefault指令 如果是第一次声明属性 则没有必要加nodefault指令 因为没有default指令即表示如此

lishixinzhi/Article/program/Delphi/201311/25117

DELPHI基础教程:Delphi自定义部件开发(一)[2]

   建立图形控制

  图形控制非常类似定制的控制 但它们没有窗口句柄 因此不占有系统资源 对图形控制最大的限制是它们不能接收输入焦点 你需要从TGraphicControl继承 它提供了作图的Canvas和能处理WM_PAINT消息 你需要覆盖Paint方法

   继承窗口控制

  Windows中有一种称之为窗口类的概念 类似于面向对象的对象和类的概念 窗口类是Windows中相同窗口或控制的不同实例之间共享的信息集合 当你用传统的Windows编程方法创建一种新的控制 你要定义一个新的窗口类 并在Windows中注册 你也能基于已有的窗口类创建新的窗口类 这就称为从窗口类继承 在传统的Windows编程中 如果你想建立客户化的控制 你就必须将其做在动态链接库里 就象标准Windows控制 并且提供一个访问界面 使用Delphi 你能创建一个部件包装在已有窗口类之上 如果你已有客户化控制的库 并想使其运行在你的Delphi应用中 那你就能创建一个使你能使用已有控制和获得新的控制的部件 在库单元StdCtrls中有许多这样的例子

   建立非可视化的部件

  抽象对象类型TComponent是所有部件的基础类型 从TComponent直接继承所创建的部件就是非可视化部件 你编写的大多数部件都是可视控制 TComponent定义了部件在FormDesigner中所需的基本的属性和方法 因此 从TComponent继承来的任何部件都具备设计能力

  非可视部件相当少 主要用它们作为非可视程序单元(如数据库单元)和对话框的界面

   建立新部件的方法

  建立新部件的方法有两种

  ● 手工建立部件

  ● 使用Component Expert

  一旦完成建立后 就得到所需的最小功能单位的部件 并可以安装在Component Palette上 安装完后 你就能将新部件放置在窗体窗口 并可在设计阶段和运行阶段进行测试 你还能为部件增加新的特征 更新选择板 重新测试

   手工创建部件

  显然创建部件最容易的方法是使用Component Expert 然而 你也能通过手工来完成相同步骤

  手工创建部件需要下列三步

  ● 创建新的库单元

  ● 继承一个部件对象

  ● 注册部件

  ⑴ 创建新的库单元

  库单元是Object Pascal代码的独立编译单位 每一个窗体有自己的库单元 大多数部件(在逻辑上是一组)也有自己的库单元

  当你建立部件时 你可以为部件创建一个库单元 也可将新的部件加在已有的库单元中

  ① 为部件创建库单元 可选择File/New… 在New Items对话框中选择Unit Delphi将创建一个新文件 并在代码器中打开它

  ② 在已有库单元中增加部件 只须选择File/OPen为已有库单元选择源代码 在该库单元中只能包含部件代码 如果该库单元中有一个窗体 将产生错误

  ⑵ 继承一个部件对象

  每个部件都是TComponent的后代对象 也可从TControl TGraphicControl等继承

  为继承一个部件对象 要将对象类型声明加在库单元的interface部分

  例如 建立一个最简单的从TComponent直接继承非可视的部件 将下列的类型定义加在部件单元的interface部分

  type

  TNewComponent=class(TComponent)

  ……

  end;

  现在你能注册TNewComponent 但是新部件与TComponent没什么不同 你只创建了自己部件的框架

  ⑶ 注册部件

  注册部件是为了告诉Delphi什么部件被加入部件库和加入Component Palette的哪一页

  为了注册一个部件

  ① 在部件单元的interface部分增加一个Register过程 Register不带任何参数 因此声明很简单

  procedure Register;

  如果你在已有部件的库单元中增加部件 因为已有Register 过程 因此不须要修改声明

  ② 在库单位的implementation部件编写Register过程为每一个你想注册的部件调用过程RegisterComponents 过程RegisterComponents带两个参数 Component Palette的页名和部件类型集 例如 注册名为TNewComponent的部件 并将其置于Component Palette的Samples页 在程序中使用下列过程

  procedure Register;

  begin

  RegisterComponents( Samples )

  end;

  一旦注册完毕 Delphi自动将部件图标显示在Component Palette上

    使用Component Expert(部件专家)

  你能使用Component Expert创建新部件 使用Component Expert简化了创建新部件最初阶段的工作 因为你只需描述三件事

  ● 新部件的名字

  ● 祖先类型

  ● 新部件要加入的Component Palette页名

  Component Expert执行了手工方式的相同工作

  ● 建立新的库单元

  ● 继承得到新部件对象

  ● 注册部件

  但Component Expert不能在已有单元中增加部件

  可选择File/New… 在New Items对话框中选择Component 就打开Component Expert对话框

  填完Component Expert对话框的每一个域后 选择OK Delphi建立包括新部件和Register过程的库单元 并自动增加uses语句

  你应该立刻保存库单元 并给予其有意义的名字

   测试未安装的部件

  在将新部件安装在Component Palette之前就能测试部件运行时的动作 这对于调试新部件特别有用 而且还能用同样的技术测试任意部件 无论该部件是否出现在Component Palette上

  从本质上说 你通过模仿用户将部件放置在窗体中的Delphi的动作来测试一个未安装的部件

  可按下列步骤来测试未安装的部件

   在窗体单元的uses语句中加入部件所在单元的名字

   在窗体中增加一个对象域来表示部件

  这是自己增加部件和Delphi增加部件的方法的主要不同点

  你将对象域加在窗体类型声明底部的public部分 Delphi则会将对象域加在底部声明的上面

  你不能将域加在Delphi管理的窗体类型的声明的上部 在这一部分声明的对象域将相应在存储在DFM文件中 增加不在窗体中存在的部件名将产生DFM文件无效的错误

   附上窗体的OnCreate事件处理过程

   在窗体的OnCreate处理过程中构造该部件

  当调用部件的构造过程时 必须传递Owner参数(由Owner负责析构该部件)一般说来总是将Self作为Owner的传入参数 在OnCreate中 Self是指窗体

   给Component的Parent属性赋值

  设置Parent属性往往是构造部件后要做的第一件事时 Parent在形式上包含部件 一般来说Parent是窗体或者GoupBox Panel 通常给Parent赋与Self 即窗体 在设置部件的其它属性之前最好先给Parent赋值

lishixinzhi/Article/program/Delphi/201311/25122

以上就是我们为大家找到的有关“delphi教程少(DELPHI基础教程:Delphi自定义部件开发(二)[4])”的所有内容了,希望可以帮助到你。如果对我们网站的其他内容感兴趣请持续关注本站。

delphi教程少(DELPHI基础教程:Delphi自定义部件开发(二)[4])

本文编辑:admin

更多文章:


native在java中的用法(native的Java关键字)

native在java中的用法(native的Java关键字)

本篇文章给大家谈谈native在java中的用法,以及native的Java关键字对应的知识点,文章可能有点长,但是希望大家可以阅读完,增长自己的知识,最重要的是希望对各位有所帮助,可以解决了您的问题,不要忘了收藏本站喔。本文目录nativ

2026年8月22日 20:30

正则匹配数字字符串开头(js 正则表达式获取字符串开头结尾的数字)

正则匹配数字字符串开头(js 正则表达式获取字符串开头结尾的数字)

大家好,关于正则匹配数字字符串开头很多朋友都还不太明白,不过没关系,因为今天小编就来为大家分享关于js 正则表达式获取字符串开头结尾的数字的知识点,相信应该可以解决大家的一些困惑和问题,如果碰巧可以解决您的问题,还望关注下本站哦,希望对各位

2025年7月24日 05:00

businessman怎么念(businessman怎么读什么意思)

businessman怎么念(businessman怎么读什么意思)

大家好,businessman怎么念相信很多的网友都不是很明白,包括businessman怎么读什么意思也是一样,不过没有关系,接下来就来为大家分享关于businessman怎么念和businessman怎么读什么意思的一些知识点,大家可以

2026年8月29日 10:15

js在哪下载(我的世界js怎么下载)

js在哪下载(我的世界js怎么下载)

这篇文章给大家聊聊关于js在哪下载,以及我的世界js怎么下载对应的知识点,希望对各位有所帮助,不要忘了收藏本站哦。本文目录我的世界js怎么下载我的世界js怎么下载怎么把一个网页的js代码下载 下来啊jquery-1.2.6.pack.js是

2025年9月18日 22:30

什么叫做超链接?具备单击后直接返回网页顶部功能的超链接是

什么叫做超链接?具备单击后直接返回网页顶部功能的超链接是

本篇文章给大家谈谈超链接,以及什么叫做超链接对应的知识点,希望对各位有所帮助,不要忘了收藏本站喔。本文目录什么叫做超链接具备单击后直接返回网页顶部功能的超链接是什么是超链接,超链接的意思是什么超链接什么意思什么叫做超链接超链接是指从一个网页

2026年7月8日 17:15

candidate的由来(什么是bug啊还有什么是beta)

candidate的由来(什么是bug啊还有什么是beta)

大家好,如果您还对candidate的由来不太了解,没有关系,今天就由本站为大家分享candidate的由来的知识,包括什么是bug啊还有什么是beta的问题都会给大家分析到,还望可以解决大家的问题,下面我们就开始吧!本文目录什么是bug啊

2026年5月29日 05:45

swift是什么电脑(笔记本电脑质量十大排名)

swift是什么电脑(笔记本电脑质量十大排名)

各位老铁们好,相信很多人对swift是什么电脑都不是特别的了解,因此呢,今天就来为大家分享下关于swift是什么电脑以及笔记本电脑质量十大排名的问题知识,还望可以帮助大家,解决大家的一些困惑,下面一起来看看吧!本文目录笔记本电脑质量十大排名

2026年3月21日 12:15

不会java可以学javaweb吗(web 开发者需要会java吗)

不会java可以学javaweb吗(web 开发者需要会java吗)

“不会java可以学javaweb吗”相关信息最新大全有哪些,这是大家都非常关心的,接下来就一起看看不会java可以学javaweb吗(web 开发者需要会java吗)!本文目录web 开发者需要会java吗请问学习Java web前,必须

2025年11月25日 10:00

mutex取值范围(“原语“定义)

mutex取值范围(“原语“定义)

今天给各位分享“原语“定义的知识,其中也会对“原语“定义进行解释,如果能碰巧解决你现在面临的问题,别忘了关注本站,现在开始吧!本文目录“原语“定义有N个进程共享同一临界资源,如用信号量机制,实现对一临界资源的互斥访问,则信号量的变化范围是互

2025年7月5日 10:00

competition怎么说(competition翻译一下)

competition怎么说(competition翻译一下)

这篇文章给大家聊聊关于competition怎么说,以及competition翻译一下对应的知识点,希望对各位有所帮助,不要忘了收藏本站哦。本文目录competition翻译一下“竞赛”用英语怎么说competition翻译一下compet

2026年3月31日 22:15

winxp如何用汇编(如果在windows下没有任何现成编译器,怎样用机器语言(或汇编语言) 编写程序)

winxp如何用汇编(如果在windows下没有任何现成编译器,怎样用机器语言(或汇编语言) 编写程序)

大家好,今天小编来为大家解答以下的问题,关于winxp如何用汇编,如果在windows下没有任何现成编译器,怎样用机器语言(或汇编语言) 编写程序这个很多人还不知道,现在让我们一起来看看吧!本文目录如果在windows下没有任何现成编译器,

2025年9月14日 09:00

spring认证含金量(中级软件工程师资格证有用吗)

spring认证含金量(中级软件工程师资格证有用吗)

大家好,今天小编来为大家解答以下的问题,关于spring认证含金量,中级软件工程师资格证有用吗这个很多人还不知道,现在让我们一起来看看吧!本文目录中级软件工程师资格证有用吗达内推荐的spring证书有用么华为spring认证有用吗sprin

2025年7月8日 03:15

字体识别免费版(迅捷ocr文字识别软件免费版怎么样)

字体识别免费版(迅捷ocr文字识别软件免费版怎么样)

大家好,字体识别免费版相信很多的网友都不是很明白,包括迅捷ocr文字识别软件免费版怎么样也是一样,不过没有关系,接下来就来为大家分享关于字体识别免费版和迅捷ocr文字识别软件免费版怎么样的一些知识点,大家可以关注收藏,免得下次来找不到哦,下

2026年3月11日 07:00

java编程规范单行(JAVA中单行注释和多行注释是什么意思我没弄明白,能解释一下么举个例子也好,谢谢~!)

java编程规范单行(JAVA中单行注释和多行注释是什么意思我没弄明白,能解释一下么举个例子也好,谢谢~!)

各位老铁们好,相信很多人对java编程规范单行都不是特别的了解,因此呢,今天就来为大家分享下关于java编程规范单行以及JAVA中单行注释和多行注释是什么意思我没弄明白,能解释一下么举个例子也好,谢谢~!的问题知识,还望可以帮助大家,解决大

2026年3月11日 01:15

eclipse连接sql server(eclipse连接sql server2008r2jar包导进去了还是显示驱动有问题怎么办)

eclipse连接sql server(eclipse连接sql server2008r2jar包导进去了还是显示驱动有问题怎么办)

这篇文章给大家聊聊关于eclipse连接sql server,以及eclipse连接sql server2008r2jar包导进去了还是显示驱动有问题怎么办对应的知识点,希望对各位有所帮助,不要忘了收藏本站哦。本文目录eclipse连接sq

2026年1月22日 20:30

android源码调试(如何调试Android Framework)

android源码调试(如何调试Android Framework)

其实android源码调试的问题并不复杂,但是又很多的朋友都不太了解如何调试Android Framework,因此呢,今天小编就来为大家分享android源码调试的一些知识,希望可以帮助到大家,下面我们一起来看看这个问题的分析吧!本文目录

2025年11月18日 07:45

cancel反义词(打消的反义词是什么)

cancel反义词(打消的反义词是什么)

大家好,关于cancel反义词很多朋友都还不太明白,不过没关系,因为今天小编就来为大家分享关于打消的反义词是什么的知识点,相信应该可以解决大家的一些困惑和问题,如果碰巧可以解决您的问题,还望关注下本站哦,希望对各位有所帮助!本文目录打消的反

2025年10月22日 13:00

center形容词(center是中心的意思吗)

center形容词(center是中心的意思吗)

大家好,center形容词相信很多的网友都不是很明白,包括center是中心的意思吗也是一样,不过没有关系,接下来就来为大家分享关于center形容词和center是中心的意思吗的一些知识点,大家可以关注收藏,免得下次来找不到哦,下面我们开

2026年9月25日 09:45

java经典100例算法题(利用Java编写应用程序求100以内的全部素数)

java经典100例算法题(利用Java编写应用程序求100以内的全部素数)

大家好,关于java经典100例算法题很多朋友都还不太明白,不过没关系,因为今天小编就来为大家分享关于利用Java编写应用程序求100以内的全部素数的知识点,相信应该可以解决大家的一些困惑和问题,如果碰巧可以解决您的问题,还望关注下本站哦,

2025年10月23日 20:00

全国疫情的最新数据(最新中国疫情死亡人数一共有多少)

全国疫情的最新数据(最新中国疫情死亡人数一共有多少)

“全国疫情的最新数据”相关信息最新大全有哪些,这是大家都非常关心的,接下来就一起看看全国疫情的最新数据(最新中国疫情死亡人数一共有多少)!本文目录最新中国疫情死亡人数一共有多少最新疫情:全国新冠累计确诊371918例,累计死亡5235例最新

2026年8月26日 01:00

近期文章

本站热文

electronics软件(labcenter electronics是什么软件)
2025-05-22 23:45:02 浏览:134
博客是微博吗(博客是微博吗)
2025-05-22 22:45:01 浏览:111
diversity and distribution(悬赏英语短文)
2025-05-23 16:15:02 浏览:107
ios软件开发前景(iOS就业前景怎么样)
2025-05-22 23:00:01 浏览:102
next month(有The next month这个单词吗,和 next month有什么区别)
2025-05-23 02:30:01 浏览:102
patron(patron是什么意思)
2025-05-23 10:30:02 浏览:95
标签列表

热门搜索