Programming and Application(编程与应用)


Content(目录)




Linux


MySQL
Office















 
PCNow 30-Day Free Trial, Remote PC Access
 
Logo_234x60

第二讲 一个多功能秒表的设计


DELPHI程序设计讲座(三)

一个实用的文件格式转换程序

董占山

(中国农科院棉花所,河南安阳,455112)

提要 本文从初学者的角度介绍了Object Pascal语言的基础知识,通过创建一个能完成Windows的位图文件(BMP)和SPDOS的(.SPT)文件相互转换的Windows程序,介绍了如何建立一个独立代码单元并将它和窗体界面相关联的方法步骤。

上一讲介绍了组件及其属性和定制组件的方法步骤。在DELPHI中,组件是设计应用程序界面的主要工具,并能有效地降低Windows编程的强度,使程序员不致于陷入界面编程的泥潭,能把主要精力集中于程序功能部分的设计。要实现程序的功能,主要使用DELPHI的基础语言Object Pascal进行编程,因此不了解和掌握Object Pascal语言是不行的。本讲着重介绍Object Pascal的数据、函数和过程、单元等概念,以后我们将会逐步讲到其他更高级的概念。

界面设计

第二讲着重讲解了界面设计,现在我们首先用上一讲所学的知识设计文件格式转换程序的界面。

主窗口的规划

该程序的主窗体被设计成一个简单的对话窗体,为了转换图片文件,需要一个输入文件名的编辑框、一个“转换”按钮和一个“关闭”窗口按钮,这就是最简单的配置了,如图1所示。主窗体和其包含的组件的主要属性见表1所示。

1 有关组件的主要属性

组件名

属性名

取值

Form

BorderIcons

[biSystemMenu,biMinimize]

 

BorderStyle

bsDialog

 

Caption

转换SPTBMP文件

 

Name

FrmSPTBMP

Label

Caption

源文件名

Edit

Text

 

Button1

Caption

转换

 

Name

btnTransfer

Button2

Caption

退出

为了单击“退出”按钮能够关闭窗口,为Button2创建OnClick事件处理程序如下:

procedure TFrmSPTBMP.Button2Click(Sender: TObject);

begin

close;

end;

添加获取文件名的组件

在编辑框中输入图片文件名,需要事先知道图片文件的名称和路径,并且正确地输入到编辑框中,在Windows系统下,常常不用这种方法,而是用对话窗口,从列表框中查找并选择,这样不仅能免去记忆文件名的过程,而且不容易出错。为了达到这个目的,再向窗体上添加一个按钮组件和一个打开文件对话组件OpenDialog(在Dialog组件页上)。这两个组件的主要属性表2

2 添加组件的属性

组件名

属性名

取值

Button

Caption

浏览

 

Name

btnBrowse

OpenDialog

Filter

Bitmap file |*.bmp|Super-DOS SPT file|*.spt

 

Title

选择文件

当用户单击按钮时,应该弹出打开文件对话窗口,要求用户从列表框中选择文件,因此为按钮创建了一个OnClick事件处理程序如下:

procedure TFrmSPTBMP.BtnBrowseClick(Sender: TObject);

begin

if OpenDialog1.Execute then

begin

Edit1.Text := OpenDialog1.FileName;

FileName := OpenDialog1.FileName;

BtnTransfer.Enabled := true;

if UpperCase(ExtractFileExt(FileName)) = '.SPT' then

OpenDialog1.FilterIndex := 2

else

if UpperCase(ExtractFileExt(FileName)) = '.BMP' then

begin

OpenDialog1.FilterIndex := 1;

BtnDisplay.Enabled := true;

end

else

begin

Edit1.Text := '';

FileName := '';

BtnTransfer.Enabled := false;

end;

end;

end;

在这个过程中,使用了一个FileName的字符串变量,它是在窗体对象的私有部分(Private declarations)声明的一个变量,需要您切换到代码编辑窗口,找到:

private

{ Private declarations }

部分,在其下添加如下变量声明语句:

FileName : String[79];

锦上天花

图形文件文件中的图形是什么样的?现在我们还不知道,那么向窗体再添加一个显示当前图形文件的图形组件,让我们在转换图片的同时能够欣赏到图片,这不是更好吗?为了显示图片,现向窗体添加一个Image组件和一个按钮。添加按钮的目的是允许用户单击按钮显示图片,它们的属性见表3

3 新添加组件的属性

组件名

属性名

取值

Button

Caption

显示图片

 

Name

btnDisplay

Image

Stretch

True

为了实现单击按钮可以弹出图片,为其创建了一个OnClick事件处理程序,清单如下:

procedure TFrmSPTBMP.BtnDisplayClick(Sender: TObject);

begin

image1.picture.loadfromfile(changefileext(filename,'.BMP'));

end;

为了美观,在图片组件和按钮组件之间加上一个Bevel组件,将它的Height属性设置为2,长度刚好达到窗体左右两边即可,完成的窗体如图2

Object Pascal的数据、函数和过程、单元

窗口界面设计好了,但是它还不能实际工作,原因是没有合适的转换文件的过程。要转换图片文件,需要分析图片文件的结构,编写具体的转换过程才行。这就要用到Object Pascal的编程知识了,为了帮助DELPHI初学者掌握Object Pascal,下面介绍Object Pascal的数据类型、常量、变量、函数、过程和单元等内容。

数据类型

在声明变量时,必须指明其类型,以确定其取值范围和可进行的操作。Object Pascal提供6种类型:简单类型、字符串类型、结构类型、指针类型、过程类型、可变类型。Object Pascal有许多预定义类型,同时也允许用户自己定义数据类型。下面我们介绍最常用的预定义类型和自定义类型的方法。

1 Pascal预定义类型

Object Pascal提供许多预定义数据类型,表1列出了在Object Pascal编程中最常用的一些类型。

1 Object Pascal提供常用预定义类型

类型名

意义或范围

长度

shortint

-128127

1字节

integer

-3276832767

2字节

longint

-21474836482147483647

4字节

byte

0255

1字节

word

065535

2字节

boolean

TRUEFALSE

1字节

char

所有字符

1字节

real

2.9×10391.7×1038

6字节

string

字符串

最大255个字节

variant

可变类型,用它声明的变量,可被赋予不同类型的值

根据赋值的类型而定

2 自定义类型的方法

要自定义类型,需要用保留字Type引导,然后跟类型说明,这部分被称为类型说明部分,可以在ProgramUnit的头部申明。下面是自定义数据类型的例子:

Type

String3 = String[3];

RealArr3 = array[1..3] of real;

在上面的类型声明中,等号前面的为类型标识符,等号后面为类型的说明。

常量和变量

常量就是在程序运行期间其值不变的量,分为无类型常量和类型常量两种。变量就是在程序运行期间其值不断变化的量。在程序中使用常量和变量之前,必须声明它们。

1 声明常量的方法

常量的声明包括在以保留字Const开始的常量声明部分,下面是常量声明的例子:

Const

max = 100;

MyName : String = 'Dong Zhanshan';

与类型声明一样,等号前面的部分为常量标识符,供在程序中引用常量时使用,后面是常量的值。第2个常量为类型常量,在常量标识符后面有一个用“:”符号引导的类型说明符。

2 声明变量的方法

变量的声明包括在以保留字Var开始的变量声明部分,下面是声明变量的例子:

Var

i,j,k : integer;

digit : 0..9;

matrix : array[1..5,1..5] of real; { 声明一个两维数组,或称为矩阵 }

在变量声明中,冒号前面的为变量标识符,后面的为类型标识符,指明变量的类型。

函数与过程

有了数据,还要有使用数据的函数或过程,在Object Pascal中,声明函数和过程的方法分别是:

函数 Function 函数名(参数表) : 函数返回类型;

过程 Procedure 过程名(参数表);

在函数头或过程头下是常量和变量的声明,之后是函数体或过程体,它们是用BeginEnd括起来的一条或多条Pascal语句,完成一定的功能。具体例子见后面SPTBMP单元中的SPT_to_BMPBMP_to_SPT过程。

单元

单元是Object Pascal模块化编程的基础,它用来创建能被许多程序引用而不需要源程序的库,把大程序分割成逻辑上相关的若干个模块。Object Pascal的预定义函数和过程都是用单元实现的。单元的一般结构见图3所示。在单元接口部分声明的类型、常量、变量、过程和函数等内容均可以被引用此单元的程序使用;而在实现部分声明的类型、常量、变量、过程和函数均是私有的,不能被引用单元的程序使用。在接口部分声明的过程和函数只有头部,而其程序体在实现部分。

文件与数据的存取

Pascal中,要存取数据,就要用到文件和处理文件的过程和函数,下面简要介绍Pascal的文件类型和系统提供处理文件的库函数和过程。

文件类型和文件变量

Pascal的文件类型分为3种,即类型文件(file of type)、文本文件(Text)和无类型文件(file)。可以用这些类型来声明文件变量。在使用一个文件变量之前,必须通过调用AsignFile过程将变量同一个外部文件相关联,一般为磁盘文件。

文件变量与外部文件建立了联系之后,必须打开文件,以便进行数据的输入和输出。用Reset打开已存在的文件,用Rewrite创建并打开新文件。用Reset打开的文本文件只能读,用RewriteAppend打开的文本文件只能写。对类型和无类型文件,无论是用Reset还是用Rewrite打开的文件均可读写。

文件操作函数与过程

2列出了Object Pascal的常用文件操作函数和过程。

2 Object Pascal提供的文件函数和过程

过程(函数)

功能

适用范围

AssignFile

将一个外部文件名赋予一个文件变量

全部

CloseFile

关闭一个打开的文件

全部

Reset

打开一个已存在的文件

全部

Rewrite

创建并打开一个文件

全部

Append

按添加方式打开一个文本文件

文本文件

Eof

返回文件的结束状态(函数)

全部

Read

从一个文件中读一个或多个值

文本文件、类型文件

Write

向一个文件中写一个或多个值

文本文件、类型文件

BlockRead

将一个或多个记录读入一个变量中

无类型文件

BlockWrite

将一个或多个记录从变量中写入文件中

无类型文件

FilePos

返回文件的当前读写位置(函数)

类型和无类型文件

FileSize

返回文件的大小(函数)

类型和无类型文件

IOResult

返回最后I/O函数的执行状态的整数值(函数)

全部

Seek

将文件指针移到指定位置,实现随机读写

类型和无类型文件

程序的进一步完善

学习了Object Pascal的有关内容后,现在继续设计我们的程序,首先需要创建一个单元,它包括处理图形文件的两个过程。

创建一个独立单元SPTBMP.PAS

单击“File”菜单中的“New”命令,弹出“New Item”对话窗口,单击“New”选项页上标题为“Unit”的图标,单击〖OK〗按钮,打开代码编辑窗口,一个单元的框架DELPHI已经帮您建立好了。单击加速条上的“Save file”按钮,打开保存文件对话窗口,在“文件名”编辑框中输入“SPTBMP.PAS”,单击〖保存〗按钮,保存新建单元。SPTBMP单元程序清单如下:

unit SPTBMP;

interface

uses SysUtils;

procedure SPT_to_BMP(SPT_file:string);

procedure BMP_to_SPT(BMP_file:string);

implementation

const

SPT_Head : array[1..64] of byte = (

$53,$75,$70,$65,$72,$2D,$53,$74,$61,$72,$20,$46,$69,$6C,$65,$1A,

$00,$01,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$61,$62,$63,$64,

$40,$00,$00,$00,$00,$00,$01,$00,$00,$00,$00,$00,$00,$00,$00,$00,

$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00);

BMP_Head : array[1..62] of byte = (

$42,$4D,$00,$00,$00,$00,$00,$00,$00,$00,$3E,$00,$00,$00,$28,$00,

$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$01,$00,$01,$00,$00,$00,

$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,

$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$FF,$FF,$FF,$00);

procedure SPT_to_BMP;

var

BMP_file : string;

ch : char;

BMP,SPT : file;

OneLine : array[1..1000] of char;

Width,Height,Bytes : word;

LineByte,Ofs,FileLength : longint;

Switch : string[3];

i : integer;

begin

BMP_File := ChangeFileExt(Spt_file,'.BMP');

assignfile(SPT,SPT_file);

{$I-} reset(SPT,1); {$I+}

assignfile(BMP,BMP_file);

rewrite(BMP,1);

seek(SPT,34);

blockread(SPT,Width,2);

blockread(SPT,Height,2);

bytes := Width div 8;

LineByte := ((Bytes + 3) div 4) * 4;

FileLength := FileSize(SPT);

move(FileLength,BMP_Head[3],4);

move(Width,BMP_Head[19],2);

move(Height,BMP_Head[23],2);

blockwrite(BMP,BMP_Head,62);

for i := bytes to LineByte do OneLine[i] := #0;

for i := Height downto 1 do

begin

Ofs := bytes * (i-1) + 64;

seek(SPT,ofs);

blockread(SPT,OneLine,Bytes);

blockWrite(BMP,OneLine,LineByte);

end;

closefile(SPT);

closefile(BMP);

end;

procedure BMP_to_SPT;

var

SPT_file : string;

ch : char;

BMP,SPT : file;

OneLine : array[1..1000] of char;

Width,Height,Bytes : word;

LineByte,Ofs,FileLength : longint;

Switch : string[3];

i : integer;

begin

SPT_File := ChangeFileExt(BMP_file,'.SPT');

assignfile(BMP,BMP_file);

{$I-} reset(BMP,1); {$I+}

assignfile(SPT,SPT_file);

rewrite(SPT,1);

seek(BMP,18);

blockread(BMP,Width,2);

seek(BMP,22);

blockread(BMP,Height,2);

bytes := (Width + 7) div 8;

LineByte := ((Width + 31) div 32) * 4;

Width := bytes * 8;

move(Width,SPT_Head[35],2);

move(Height,SPT_Head[37],2);

blockwrite(SPT,SPT_Head,64);

for i := Height downto 1 do

begin

Ofs := LineByte * (i-1) + 62;

seek(BMP,ofs);

blockread(BMP,OneLine,linebyte);

blockwrite(SPT,OneLine,bytes);

end;

closefile(BMP);

closefile(SPT);

end;

end.

关于SPTBMP文件的格式,这里不作解释,有兴趣的读者可以查找有关的文献资料,需要说明一点:SPT文件是单色的,所以在转换BMP文件时,要确保其是单色图形。

SPTBMP单元和主窗口连接起来

新创建的代码单元必须和主窗体以某种形式连接起来才能发挥它的作用。连接的方法比较简单,在主窗体单元的执行部分加上:

uses SPTBMP;

然后,创建“转换”按钮的OnClick事件处理程序,以完成文件格式的转换功能。事件处理程序如下:

procedure TFrmSPTBMP.BtnTransferClick(Sender: TObject);

begin

if UpperCase(ExtractFileExt(Filename)) = '.SPT' then

begin

SPT_to_BMP(FileName);

BtnDisplay.Enabled := true;

end

else

BMP_to_SPT(FileName);

end;

至此,该程序已经设计好了,单击保存按钮,保存项目,然后单击“Run”菜单中的“Run”命令或直接按<F9>键,编译并运行程序。

©董占山Zhanshan Dong

Post comments(留言)

Name(名字):

Comment(内容):


由Google提供

SunfineData Products|U's Bargain Network|Contact Me(与我联系)
© 1998-, 董占山, 版权所有, 欢迎转载文章链接。
转载文章和软件请注明出处(http://articles.sunfinedata.com/)。