




版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
1、控件 2010-11,Delphi 培训(二),通过本课程,你将掌握,Windows是如何通过消息机制来运作的,Delphi是如何完成消息分发,程序运作机制是怎样的,知道如何利用消息编写控件 了解Delphi VCL的框架,知道该用什么控件来完成什么样的功能,如果自己要编写控件,该从哪里去继承 能够通过Delphi编写一个简单的控件,能够使用属性编辑器,知道怎么样去封装控件,以便达到重用目的 了解一些简单的OTA机制,能够简单地控制Delphi开发环境,主要内容,Windows消息和事件机制 Delphi封装机制 VCL控件框架 编写VCL控件 属性编辑器 Open Tools API,Win
2、dows 消息机制,Windows的消息循环机制三个部分组成: 消息队列 消息循环 窗口过程,Windows消息机制,消息队列 消息队列是有限制的,由操作系统限定,在Windows 200/XP中我们可以修改这个限制的极限: HKEY_LOCAL_MACHINESOFTWAREMicrosoftWindows NTCurrentVersionWindows,USERPostMessageLimit或者USERProcessHandleQuota,默认是10000 自主创建消息:PostMessage /窗口句柄 message:UINT;/消息常量标识符 wParam:WPARAM; /消息的
3、特定附加信息 lParam:LPARAM; /消息的特定附加信息 time:DWORD;/消息创建时的时间 pt:TPoint;/消息创建时的鼠标位置 end;,需要处理消息的窗口句柄,最终将会调用该窗口的WndProc过程,消息类型,如WM_PAINT,wParam和lParam消息对应的参数,每个消息不一样,Windows标准的消息附带的参数参考MSDN,用户自定义的消息,则可以自定义这两个参数的含义,请问:如果需要处理的某个消息的参数,不只两个,怎么办?,Delphi是如何封装消息的?,Delphi把收到的消息,封装成TMessage,以便在各个窗口及其窗口消息处理过程之间传递消息队列被
4、封装; TApplication窗口接管所有的消息队列,其中Run负责消息的处理和分发对应消息的循环; Delphi封装了所有的Windows标准控件,每个控件可以绑定一个WindowProc过程,Delphi指定控件的消息处理过程为其自身的WndProc过程,完成映射和关联,同时在WndProc中,可以封装出事件以供外部可视化编程(Object Inspector)调用对应消息的窗口过程 TApplication可以分发所有的TMessage到对应窗口的WndProc过程,然后Delphi自身的WndProc就可以完成消息处理了,同时Delphi VCL调用Windows控件本身的默认消息处
5、理过程DefWindowProc来完成一些基本的消息处理,Delphi中消息处理顺序,搜索类本身有没有处理该消息值的函数,如果有,则终止循环 搜索父类有没有处理该消息值的函数,如果有,则终止循环 向父类继续搜索,直到object 搜索类本身在没有默认处理函数,如果有,则终止循环 搜索父类有没有默认处理函数 向父类继续搜索.直到object.(默认处理函数,object一定有),VCL中DMT和VMT的使用,Delphi通过DMT(dynamic)和VMT(virtual)实现多态 VMT在类及其父类中保存了每个虚函数的入口地址,因此速度快,但消耗内存,一般应用于每个子类都要覆盖的函数方法,将它
6、声明为 virtual即可 DMT通过搜索类及其父类的虚函数地址表来实现多态和重载,不需要保存每个类的虚函数入口地址,因此内存占用小,但一旦方法没有被覆盖,那么将需要通过搜索来定位入口地址,效率较差,一般应用于类层次很深或者子类非常多且某个方法又很少被重载的情况 自己开发控件,需要考虑到virtual和dynamic的情况,如果无法决定,可以使用virtual,以TEdit为例子说明消息是如何被封装的?,外部消息发送,TApplication.Run,TEdit.WndProc,Delphi分装Windows的EDIT控件为TEdit控件,指定控件的窗口消息处理过程为TEdit.WndProc
7、,1,2,3,4,本示例为方便大家理解已经大大简化,不代表实际在VCL中的情况,主要内容,Windows消息和事件机制 Delphi封装机制 VCL控件框架 编写VCL控件 属性编辑器 Open Tools API,VCL主要框架,TObject提供基础对象支持,以及动态消息方法支持 VCL封装消息的三个关键类TOjbect、TComponent、TControl、TWinControl Exception为异常基类,所有异常从此继承下去 TComponent提供组件管理 TControl封装没有句柄的组件,消息有赖于TWinControl分发 TWinControl封装Windows有句柄的
8、组件 以WM开头是Windows标准消息,CM开头是Delphi自定义消息,VCL框架说明,TObject万类之源 TPersistent完成控件的持续化处理,即能够重新加载和保存控件、控件之间相互赋值的能力 TComponent,VCL所有组件的父类,只要从此继承,就可以被“摆放”到窗口上,可以通过它封装一些数据操作的对象给用户“可视化”编程使用 TControl,可视控件的基类,这类控件都是可以在窗口上被用户看到 TGraphControl,图形控件,无用户输入,不占用Windows句柄资源,如Label控件、SpeedButton等控件 TWinControl,可视化句柄控件,有焦点,用
9、户可输入,占用Windows句柄资源,封装的Windows标准控件都继承自该类,如Button、Edit、ListView等,VCL框架要点,VCL自动创建TApplication窗口和主线程,Application.Run为程序的消息循环处理过程 VCL会负责自己的线程同步,但用户创建的线程需要自主同步 窗口消息处理过程必须与某个线程关联,且线程销毁必须晚于窗口销毁 VCL封装的控件,会自动加载相关属性 VCL控件,有两种状态:设计期和运行期 RTTI使得VCL可以轻松操作属性,并进行可视化的编程,VCL及控件的生命周期过程,Dpr中的begin程序入口注册控件类(RegisterClass
10、) Application对象创建创建主窗体加载主窗体的属性创建子控件子控件Loaded,从exe中读取窗体资源子控件属性被设定事件方法绑定到控件窗口消息过程回到主窗体创建Application.Run消息被分发到各个窗体及其控件各窗体及控件响应消息子控件被销毁Owner控件被销毁窗体被销毁程序终止,主要内容,Windows消息和事件机制 Delphi封装机制 VCL控件框架 编写VCL控件 属性编辑器 Open Tools API,控件开发的一些约定,请遵循一般的命名准则!基本准则: 类名以T开头 类内部变量用F开头,如FColor 公开事件以On开头,如OnClick; 内部动作方法如果需
11、要被继承一般以Do开头,例如DoClick; 公开的方法,属性等,以驼峰命名法命名,例如CheckFileExist; 读取属性的方法一般以Get开头,设置属性一般以Set开头,例如SetColor,GetColor 函数参数命名,以A开头,例如function SetColor(AColor: TColor) 具体可以参考VCL的源代码本身,组件的结构,可见性:Private、Protected、Published(属性窗口可见)、Public 属性(Property),属性类型包括 简单类型(字符串、浮点数、整数、字符等)、枚举、集合 对象,必须有自己的属性编辑器 数组,必须有自己的属性编
12、辑器 方法(Method) 事件(Event):OnXXXX 流属性:持续化 拥有关系(Owner):Owner释放时,被Owner者会被同时Free 父子关系(Parent),VCL控件相关知识,控件的创建 控件的安装和使用 控件的调试 控件的设计期和运行期 自定义控件的属性编辑器 控件属性的存储 控件资源的使用 控件的版本兼容性控制 RTTI,控件创建123 启动Delphi 点击菜单【Component】,New Component 按下图输入,点击【OK】即可,创建控件,设计之前 拿来主义检查是否有同类控件?!同时自己编写的控件也要考虑到给别人使用,要做到低耦合性和独立性 没有同类控件
13、,则需要考虑借鉴类似控件或考虑设计新控件 理清楚需求和架构 是否可以组合或者集成、继承现有控件? 控件属性,方法等其保护、集成、公开特性都需要考虑清楚 选择合适的父类 注意选择合适的父类控件,可以大大重用已有代码 选择父类标准:一般优先考虑TCustomXXX类,例如TCustomLabel,而不是直接使用TLabel等;请问为什么? 选择要恰当,不要过高或过低,例如继承自TCustomLabel,而不是TComponent!为什么?,创建控件,利用Delphi生成框架代码 Component New VCL Component 提高生产力,提高正确性,规范化 增加方法或编写需要重载的方法 O
14、verride Wndproc Message 添加事件 更改已有事件的处理过程:点击事件! 添加自己的特有的事件 添加属性 添加自定义的属性 属性的默认值,存储值等 如有必要,编写自己的属性编辑器,控件和包,Package(*.dpk) 控件必须包含于一个Package才能安装 一个Package可以包含多个控件 Design Package 来注册控件; 用RegisterPropertyEditor(TypeInfo(TCaption), TObject, Text, TCaptionEditor);注册属性编辑器 Register可以独立的单元,也可以在每个控件单元中,控件集一般用一个
15、独立的单元来Register所有控件 Delphi会自动搜索单元文件中是否有Register过程,有的话自动调用,注意Register必须区分大消息,第一个字母大写!这是Delphi中关键字唯一区分大小写的地方!,安装控件,控件组的安装 一些大的控件包一般有DPK文件和Pas文件源代码,用Delphi打开即可安装;(最常见的方式!),只有PAS的控件包,请注意查找文件名中带有register或者类似含义的文件,打开安装到某个Package即可,单个文件的控件,直接加入Package安装即可 安装包的,只要执行安装文件即可!(优秀的控件包都会提供安装程序) 一些控件只提供BPL包,这种,可以在P
16、roject OptionsPackage里面加载即可安装; ActiveX控件的安装,可以用Import ActiveX Control和Import Type Library方式安装即可 只有DCU的控件:Install Component,添加DCU到Package,并安装Package即可 控件组安装后一般要注意设置Delphi的Library Path或者Search Path,卸载控件,如果要卸载自己的控件,可以打开你的Package,把你的控件的单元文件从中移除并重新Build和安装Package一次即可 如果要卸载整个Package,可以在Project OptionPacka
17、ge中,把Package Remove即可 控件包的卸载类似上面,有卸载程序的,利用卸载程序即可,没有的就按照卸载Package的方式取消即可 最坏的打算就是把Package的BPL文件直接删除,Delphi会在下次启动时提示找不到BPL文件,并询问以后是否继续加载,选择【否】即可。,控件调试,创建一个Demo程序,使用控件即可调试 控件可以和Demo程序在同一个Project Group即可进入代码级的调试 所有的程序调试技巧可以同样使用在控件调试上面;,Default和Stored,Default 属性关键字 格式:property Color: TColor read GetColor
18、write SetColor Default clRed; 控件自己必须在构造函数中设定属性的默认值 Default可以为控件设定一个默认值,在保存窗体的时候,Delphi会检查属性值与Default值是否一致,如果一致,则不会保存到窗体当中,可以减少窗体文件体积 Default可以大大减少窗体文件的体积,提高性能 Stored属性关键字 格式property Color: TColor read GetColor write SetColor stored true | false | 布尔变量; 可以根据某个属性是不是被设定来决定另外一个属性是否需要保存,从而减少dfm资源的体积,加快速度
19、,控件的设计期和运行期,控件的生命状态有两个:设计和运行 设计指的是控件在Delphi IDE中的状态 运行是指控件被编译后,脱离Delphi独立运行的状态 可以在控件代码任何地方使用下面代码判断是否在设计期 if csDesigning in ComponentState then 在设计期,可以使用OTA(Open Tools API)(uses ToolsAPI) 控件的设计期状态,主要是为了便于开发者能否对一些属性、状态等进行可视化编辑使用,控件属性的存储,对于Publish的简单类型数据,如String,Integer,枚举等等,Delphi可以自动存储其属性数据 自定义的复杂的高级
20、属性有两种方式可以变通 把复杂数据编码变成字符串,缺点是用户无法直接编辑,但可以利用自定义属性编辑器来转换 实现控件属性存储接口,道地的解决方法,缺点是复杂度高 可以参考TPicture的属性编辑器是如何实现的 参考Delphi的资料:Creating properties - Storing and loading unpublished properties,控件属性的存储,利用TReaderProc和TWriterProc完成属性的存取 编写控件的LoadCompProperty(Reader: TReader) 编写控件的StoreCompProperty(Writer: TWrite
21、r),procedure TSampleComponent.LoadCompProperty(Reader: TReader); begin if Reader.ReadBoolean then / 可以调用Reader.ReaderInteger, ReadBoolean, ReadBinary end; procedure TSampleComponent.StoreCompProperty(Writer: TWriter); begin Writer.WriteBoolean(MyCompProperty nil); if MyCompProperty nil then begin /
22、可以调用Writer.WriteInteger, WriteBoolean, WriteBinary end; end;,控件属性的存储,重载控件的DefineProperties 方法,利用该方法完成关联属性的存取方法的关联,让VCL知道碰到某个属性的时候找“谁”,procedure TSampleComponent.DefineProperties(Filer: TFiler); functionDoWrite: Boolean; begin if Filer.Ancestor nil then check Ancestor for an inherited value begin / 检
23、查是否需要写入属性数据,例如和默认值相同就可以忽略 end else no inherited value - check for default (nil) value Result := MyCompProperty nil; end; begin inherited; allow base classes to define properties Filer.DefineProperty(MyCompProperty, LoadCompProperty, StoreCompProperty, DoWrite); end;,控件资源的使用,控件资源使用有两种方式 内嵌式:资源数据直接作为属
24、性数据存储,例如图片,图标等 资源文件方式:Windows标准的资源使用方式,需要编写代码和资源文件脚本,并且需要手动编译资源 控件图标 DCR文件:与控件同名(THyperLabel)的图标即在Delphi控件面板中的图标! 可以包含多个图标资源 利用Delphi的Image Editor可以创建DCR文件 资源文件脚本(.rc文件) 标准资源:字符串表、菜单表、位图、图标等 数据文件等等,控件的版本兼容性控制,版本控制是Delphi非常头疼的一个问题 很多控件无法在高版本Delphi下使用和编译 Borland对兼容性控制不够好,随心所欲变动太多 控件作者编译指令使用考虑不周到 条件编译指
25、令是保证兼容控制的重要手段 $IFDEF xxxx$ELSE|$ELSEIF$ENDIF $IF xxx$ELSE | $ELSEIF$IFEND $DEFINE xxxx 最常用的版本判断预定义条件: VERnnn,其中nnn即Delphi的版本号,Delphi7即VER150,Delphi1即VER80 WIN32、MSWINDOWS、LINUX 版本控制请注意未来高版本的问题!大部分人只考虑低版本兼容和当前最新版本的兼容,不考虑未来版本的兼容性问题,可能出现问题 参考文件:DPS.inc 的编译指令定义文件,RTTI,TypInfo.pas单元中包含了和RTTI相关的定义 IS和AS的应
26、用就是RTTI的功劳 RTTI使得VCL可以轻松操作属性,并进行可视化的编程 TTypeData为基础,包含了大部分RTTI需要的数据 TObject的RTTI相关信息(IS,AS) ClassName ClassType InheritsFrom ClassParent InstanseSize ClassInfo:指向RTTI的指针,自定义控件的属性编辑器,可以挂接一个特别的属性处理方式到某个属性,也可以自定义Delphi本身属性编辑器中的动作行为表现 挂接特定属性的编辑器,在控件的Register过程中:RegisterPropertyEditor(TypeInfo(TCaption),
27、 TObject, Caption, TCaptionEditor); 多个属性编辑器注册同一个属性,以先注册的为准 自己编写属性编辑器的操作类,例如TCaptionEditor Uses DsgnIntf(从VER140开始为DesignIntf, VCLEditors) 属性编辑器类,继承自特定属性的编辑类或者属性编辑器基类,必须重载至少两个方法:GetAttributes和Edit方法; 如果自定义Delphi Object Inspector的属性表现,则需要重载对应属性的PropDrawValue方法 procedure PropDrawValue(Canvas: TCanvas; const Rect: TRect; Selected: Boolean); override; 具体可以参考VCL本身的代码或者其他的例子资料等,O
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 二零二五版茶叶品牌推广代理服务合同规范
- 辽宁省葫芦岛市第一中学2025届物理高二第二学期期末学业质量监测模拟试题含解析
- 2025年度贵金属库房托管与安全保障合同
- 二零二五年度地下管网安装劳务分包合同城市基础设施
- 2025版办公室装修合同(含智能家居系统)升级版
- 二零二五年POS机租赁与移动支付业务合作合同
- 2025年航空机场保洁托管服务合同标准
- 2025版新能源发电设备采购预付款合同示范
- 2025版建筑原材料集中采购合同范本
- 二零二五年度残疾人康复辅助器具生产与销售合同
- ICD-9-CM3编码与手术分级目录
- 淹溺诊疗规范内科学诊疗规范诊疗指南2023版
- PremiereProCC视频剪辑基础教程PPT完整版全套教学课件
- 八上数学冀教课后习题答案
- 新教材北师大版高中英语选择性必修第一册全册各单元学案(单词短语句型写作等知识点汇总)
- 2022年石嘴山市矿业(集团)有限责任公司招聘考试真题
- 哪些农产品免税(免税农产品包括哪些)
- 镀锌板国家新标准规定
- 《电工学》“课程思政”教学设计案例
- 融资合作协议模板(2篇)
- 数字时代的商务英语写作知到章节答案智慧树2023年对外经济贸易大学
评论
0/150
提交评论