Delphi控件的“拿来主义”

  "一个优秀的Delphi程序员,不仅要会写控件,还要会使用控件。"

  我还是一个半瓢水的程序员,因此目前为止我所能努力达到的境界是:

  一个半瓢水的程序员,管他会不会写控件,只要能拿来改就可以了。

  使用过Delphi的朋友都知道,我们在设计Delphi应用程序的某一功能时总是希望能够有现成的第三方免费控件可以拿来使用。但实际情况往往是,网上的控件确实种类繁多,优秀作品也数不胜数,但真正完全能够符合设计者具体要求的控件却很少。究其原因,不外乎以下几条

  1、国人开发的应用程序大多具有中国特色,而优秀的第三方控件往往是国外程序开发人员开发的(大名鼎鼎的Rxlib,知道吧,俄罗斯人的作品)。功能定义上的差别导致了控件的不可用性,看看QuickReport就知道了(当然,QuickReport编的也很烂)。

  2、真正优秀的第三方控件总是从大局上把握控件所能达到的功能,细节问题考虑的不多。而我们设计的程序通常要考虑到很多操作细节上的问题(一般是客户的要求,有时会有些变态)

  3、对于许多很有特色的控件,我们所需要的只是其中一部分功能,但是它被整合到了某一个大的方法中,无法为我们所用。

  4、优秀和免费总是两个矛盾,天下没有免费的午餐。

  种种原因,限制了开发者对控件资源的充分利用。其实,很多控件的代码都提供了开放的接口。只要大家对控件的原理有一定的了解,然后对别人的控件代码作一捏捏的修改,就可以无缝的添加自己需要的功能,或剔除冗余的功能。既达到了开发的目的,又避免了重写代码的麻烦,一举两得(好像很不负责任啊,没办法了,半瓢水嘛)。关于控件的原理,应该有很多文章介绍过了,在这里我想通过一个具体的实例来介绍一下怎样将别人的控件"拿来"为我所用。

  这个例子是关于如何将一个文本数据导入导出控件作一些简单的修改之后拿来使用的。

  ◆程序功能

  将图书馆的ISO文件中的部分数据转到Oracle8数据库中。

  ◆设计要求

  1.显示导入进度条。

  2.在导入过程中,如果某条纪录导入失败,不显示异常,而将导入失败的纪录记入日志。

  ◆设计思路

  程序的关键在文本数据字段的分离。通常的做法,都是先将字符串进行处理(RegulateString),然后把串中每个字符同分割符(可以是空格,逗号等)比较,将不是分割符的字符追加到一个串中(GetRecordItem),得到一个字段的内容。通过一个循环(循环次数由GetItemNum来定),就可以将一个字符串分成几个字段。最后的工作就是将分离出来的数据对号入座加入数据库。

  按照上面的思路,利用Delphi提供的已有函数和过程,实现起来应该不难,但问题是,我可不想每次编文本导入程序的时候,都把什么这啊那的函数过程重新定义一遍,哎,最烦的就是重复性的工作了.那么有没有现成的控件将上述过程都封装起来呢?PS:又不用我编呢?

  答案是肯定的!前几天刚刚下了一个免费控件TPgCSV,据说可以实现文本的导入和导出.翻出来一看,正是我想要的。

  在深入到下面的内容之前,有必要对该控件的类声明部分作一定了解

  //中文部分为笔者所作的注释
//注意:
//在该控件中,Export代表将文本数据导入到数据库,Import代表从数据库导出到文本。??? 怎么和我理解的
//导入导出概念刚好是反的 :)
type
//在处理数据产生异常时,可选择继续还是中止
TPgCSVErrorResponse = (pgcsvAbort, pgcsvIgnore);
//进程监控事件声明,可以将导入/导出的进度作为参数传出
TPgCSVProgressEvent = procedure (Sender : TObject; AProgress: LongInt; var StopIt: Boolean) of object;
//发生异常时的事件处理声明,异常信息通过该接口传给程序员。
TPgCSVExportErrorEvent = procedure (Sender : TObject; Mess: string; RecNo: LongInt; var Response:TPgCSVErrorResponse) of object;
TPgCSV = class(TComponent)
private
FDataset : TDataset;
FCSVMap,
FCSVFile,
FDateFormat,
FIgnoreStr : string;
FSeprator,
FDelimiter,
FFieldIndicator : Char;
FAutoOpen,
FUseDelimiter,
FSilentExport,
FTrimData,
FStop,
FEmptyTable : Boolean;
FBeforeOpenTable,
FAfterOpenTable,
FBeforeCloseTable,
FAfterCloseTable,
FBeforeEmptyTable,
FAfterEmptyTable,
FBeforeExport,
FAfterExport,
FBeforeImport,
FAfterImport,
FOnAddRecord : TNotifyEvent;
FExportProgress,
FImportProgress : TPgCSVProgressEvent;
FExportError : TPgCSVExportErrorEvent;
FMapItems,
FDefaultInt : Integer;
FBufferSize : LongInt;
FFieldCache : TList;
protected
FFile : TextFile;
//以下就是我所说的希望封装的部分
function CountMapItems:Integer;//计算映射字符串的字段个数
function GetMapItem(ItemIndex:Integer;var AField:Boolean):string;//提取映射字符串的字段
function GetCSVRecordItem(ItemIndex:Integer;CSVRecord:string):string;//提取CSV文件字符串中的某一字段
function BuildMap:string;//自动创建映射,如果CSVMap一栏为空的话,会由它来产生映射字符串
function ExtractWord(Item: Integer;S, WordDelim: string): string;//提取文本数据字符串/映射字符串中的某一字段
function WordCount(const S ,WordDelim: string): Integer;//计算文本数据字符串/映射字符串中的字段数目
function WordPosition(Item: Integer; const S, SubStr: string): Integer;//计算子字符串在字符串中的位置
public
constructor Create(AOwner: TComponent); override;
published
//properties
property Dataset : TDataset read FDataset write FDataset;
//设置要导入或导出的目标数据集.
property CSVMap : string read FCSVMap write FCSVMap;
//CSV 文本数据文件到数据库字段值的映射字符串.控件通过该映射决定文本中的哪些数据要导入及要导入哪个字段.
property CSVFile : string read FCSVFile write FCSVFile;
//CSV 文件格式,其实就是文本数据文件。CSV代表什么意思?呵呵,我也不知道
property Seprator : Char read FSeprator write FSeprator;
//分隔符,可以是空格,也可以是,、;、#等符号
property FieldIndicator : Char read FFieldIndicator write FFieldIndicator;
//字段标识符.
property AutoOpen : Boolean read FAutoOpen write FAutoOpen;
//将AutoOpen设为True可以在处理数据前自动打开要导入的数据表并在操作完毕后自动关掉它。
property IgnoreString : string read FIgnoreStr write FIgnoreStr;
//忽略纪录的标识串.
//举例来说
//IgnoreString:='(ignore)';
//CSVMap:='$Name,(ignore),$Age';
//在这种情况下,CSVToDataSet方法,即导入数据方法将忽略文本文件中的第二列的字段。
property Delimiter : Char read FDelimiter write FDelimiter;
//在某些CSV文档中标识字符串纪录的标识符,比如,"john","boy",12中的",在这种情况下,TPgCSV
//会忽略这些标识符。
property EmptyTable : Boolean read FEmptyTable write FEmptyTable;
//只在从数据库导出(DataSetToCSV)方法中有效,作用是创建一个新的CSV文件。
property UseDelimiter : Boolean read FUseDelimiter write FUseDelimiter;
//是否有Delimiter。
property SilentExport : Boolean read FSilentExport write FSilentExport;
//若该属性为True,应用程序将不显示数据操作时的异常,而将异常信息通过一个接口传给程序员处理.
property DateFormat : string read FDateFormat write FDateFormat;
//设定CSV文件中日期数据的格式。
property TrimData : Boolean read FTrimData write FTrimData;
//是否去掉数据头尾的空格.
property DefaultInt : Integer read FDefaultInt write FDefaultInt;
//整/实形数据转换出错后的默认值
property BufferSize : LongInt read FBufferSize write FBufferSize;
//CSV 文件的缓冲值,以字节为单位,可以加快导入和导出数据的速度。
//events
property BeforeOpenTable : TNotifyEvent read FBeforeOpenTable write FBeforeOpenTable;
property AfterOpenTable : TNotifyEvent read FAfterOpenTable write FAfterOpenTable;
property BeforeCloseTable : TNotifyEvent read FBeforeCloseTable write FBeforeCloseTable;
property AfterCloseTable : TNotifyEvent read FAfterCloseTable write FAfterCloseTable;
property BeforeEmptyTable : TNotifyEvent read FBeforeEmptyTable write FBeforeEmptyTable;
property AfterEmptyTable : TNotifyEvent read FAfterEmptyTable write FAfterEmptyTable;
property BeforeImport : TNotifyEvent read FBeforeImport write FBeforeImport;
property AfterImport : TNotifyEvent read FAfterImport write FAfterImport;
property BeforeExport : TNotifyEvent read FBeforeExport write FBeforeExport;
property AfterExport : TNotifyEvent read FAfterExport write FAfterExport;
property ExportProgress : TPgCSVProgressEvent read FExportProgress write FExportProgress;
//进程监控事件。每完成一条文本数据的导入就触发该事件。
property ImportProgress : TPgCSVProgressEvent read FImportProgress write FImportProgress;
property OnAddRecord : TNotifyEvent read FOnAddRecord write FOnAddRecord;
property ExportError : TPgCSVExportErrorEvent read FExportError write FExportError;
//发生异常时交由该事件处理,异常信息通过该接口传给程序员。
//methodes
//整个控件的核心内容
procedure CSVToDataset;//将文本导入到数据集的方法
procedure DatasetToCSV;//将数据集的数据导入到文本的方法
end;
procedure Register;
{略}
implementation
{略}
end.

  从声明部分中我们可以看到,TPgCSV将文本数据的导入导出全部封装到了CSVToDataSet(文本数据导入)和DataSetToCSV(文本数据导出)两个方法中.开发者可以在设计阶段直接将文本文件同要导入/出的数据库相连,然后在程序运行当中调用这两个方法就可以了,根本不用理会那些函数什么的,相当的方便.

 

转载于:https://www.cnblogs.com/tecsoon/archive/2009/03/04/1403069.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/461824.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

WRF参数配置(PartV)

&bc_control spec_bdy_width 此参数指定用于边界过渡的格点总行数,默认值为5。此参数只用于真实大气方案。参数的大小至少为spec_zone 和 relax_zone的和。 spec_zone 指定区域(specified zone)的格点数,默认值为 1。指定边条件时起作用。 relax…

DHCP中继处理办法

这两天一直在客户这边测试DHCP,由于客户的网络是现成的server 2008 是后来加上去的,所以没有多的IP地址用于测试,只好拿客户的楼层网段来测试,由于需要跨VLAN实行DHCP地址分配,所有需要做DHCP中继。废话不多说&#xf…

富士 FinePix F401

功能特点 F401尽管外型娇小,但功能并不弱,机身内搭载Super CCD III,实际CCD画素210万,纪录画素可达400万(23041728像素),由于Super CCD III大幅改善噪声,有效ISO感光度提升到1600度&…

C++远航之封装篇——默认构造函数、初始化列表、拷贝构造函数

1、默认构造函数 没有参数;若有参数,则一定全部都有默认的参数值。 2、初始化列表 (1)概念 (2)特性 建议用初始化列表来初始化数据成员。初始化列表先于构造函数执行;初始化列表只能用于构造函…

性能测试流程-各阶段的工作

1 性能测试流程1.1 性能测试计划阶段测试计划阶段主要工作如下:1、明确测试对象2、定义测试目标3、定义测试通过的标准4、规划测试进度5、规划测试参与人员(需求、开发、测试、运维和配置)6、申请测试资源7、风险控制1.2 性…

恢复IE8自带的源代码查看器

各种知名不知名的文本编辑软件安完了之后,IE8的默认源代码编辑器也被改了很多次其实IE8默认已经不使用记事本了,带有语法高亮和行号功能的查看器很好用,堪比FF的查看器了。而且占用资源很少,跑起来很快,所以&#xff0…

C++远航之封装篇——析构函数

一、为什么需要析构函数? 见博客:http://blog.csdn.net/zhhymh/article/details/6239832 二、析构函数的理解 1、格式 2、必要性 释放资源。 3、什么时候调用? delet p时会调用析构函数;程序返回时,也会调用析构函数…

生成的数据库脚本没有注释?

1,选择Database->Generate Database 选中Generate name in empty comment就可以了转载于:https://www.cnblogs.com/hongjiumu/archive/2012/08/02/2620379.html

M.GetSum(); Myclass::GetSum(); // 调用类的静态成员函数。转载于:https://www.cnblogs.com/sunbines/p/11227051.html

HDU 1312

View Code 1 #include<stdio.h>2 #include<stdlib.h>3 #include<string.h>4 以前用BFS写过&#xff0c;这次改用DFS写发现DFS掌握的不好&#xff0c;挑了好久才过&#xff0c;今下午才AC了两道题&#xff0c;还要加紧练习DFS&#xff01;5 int row,col,coun…

C++远征之封装篇——对象数组,对象成员

一、对象数组 &#xff08;1&#xff09;如下&#xff0c;delet [ ]p时&#xff0c;会调用三次析构函数 &#xff08;2&#xff09;细节 实例化对象数组时&#xff0c;每一个对象的构造函数都会被执行。销毁对象数组时&#xff0c;每一个对象的析构函数都会被执行。 二、对象成…

linux sudo 免密码

修改/etc/sudoers文件为使用sudo命令的用户格式 username ALL(ALL) NOPASSWD: ALL转载于:https://www.cnblogs.com/xuedong09/p/3454794.html

shell 替换字符串的几种方法,变量替换${},sed,awk

变量a是一个带空格的字符串&#xff0c;现在用"hdpusr400"替换变量a中的"hduser302"&#xff1a; 1 [liusiyilocalhost ~]$ echo $a2 -rw-r----- 3 hduser302 hduser302 3336 2019-07-12 17:35 /apps/hduser302/student/properties/xxyy/IMP_00004_XXYY_US…

基于sqlite数据库的C语言编程

一 SQLITE 操作入门 sqlite 提供的是一些 C 函数接口&#xff0c;你可以用这些函数操作数据库。通过使用这些接口&#xff0c;传递一些标准 sql 语句&#xff08;以 char * 类型&#xff09;给 sqlite 函数&#xff0c; sqlite 就会为你操作数据库。 sqlite 跟 MS 的 access 一…

ehcache memcache redis 三大缓存男高音

2019独角兽企业重金招聘Python工程师标准>>> 最近项目组有用到这三个缓存&#xff0c;去各自的官方看了下,觉得还真的各有千秋&#xff01;今天特意归纳下各个缓存的优缺点&#xff0c;仅供参考&#xff01; Ehcache 在java项目广泛的使用。它是一个开源的、设计于…

Linux进程的诞生和消亡

1、进程的诞生 &#xff08;1&#xff09;、进程0和进程1 &#xff08;内核里边的固有的&#xff09; &#xff08;2&#xff09;、fork函数和vfork函数用于新进程的产生 2、进程的消亡 &#xff08;1&#xff09;、正常终止和异常终止 &#xff08;2&#xff09;、进程在运行时…

C++远航之封装篇——深拷贝、浅拷贝

1、浅拷贝 如下&#xff0c;此时如果同一块内存释放两次&#xff0c;会报错 2、深拷贝

TinyXML学习记录及整理

整理自 http://www.cnblogs.com/phinecos/archive/2008/03/11/1100912.html http://www.cppblog.com/age100/archive/2010/05/12/115203.html http://panpan.blog.51cto.com/489034/104961 及百度文库。 TinyXML是一个开源的解析XML的解析库&#xff0c;能够用于C&#xff0c;能…

indy10 UDP实例

UDP就比较简单了&#xff0c;放个按钮&#xff0c;一个TIdUDPServerTIdUDPServer绑定 0.0.0.0:3820&#xff0c;然后Active设置为True//发送按钮procedure TForm1.Button1Click(Sender: TObject);varIdUDPClient1: TIdUDPClient; //动态创建TIdUDPClientbeginIdUDPClient1:TIdU…

解决模拟MOSS用户调用WebService打开个人站点进行操作

From:http://www.cnblogs.com/BruceLee521/ 开始以为要构建 WindowsIdentity windowsIdentity WindowsIdentity.GetCurrent(); GenericPrincipal genericPrincipal new GenericPrincipal(genericIdentity, roles); 然后把HttpContext.Current.User 置成上面构造的。但发现在打…