公用对话框是一类非可视的组件,它们都由TDialog类继承而来,存在Dialogs组件面板上。包括:
- TOpenDialog——打开文件对话框组件,用它选择文件和浏览目录
- TSaveDialog——保存文件对话框组件,用它类输入或选择文件名以及浏览目录
- TFontDialog——字体设置对话框组件,用它可以允许用户选择字体进行设置
- TColorDialog——颜色设置对话框组件,是一个通用的颜色选择工具
- TOpenPictureDialog——打开图像对话框组件,比普通打开对话框多一个图像预览区域
- TSavePictureDialog——保存图像对话框组件,可以对图像进行预览
- TFindDialog——查找对话框组件,用于完成数据查找工作
- TReplaceDialog——替换对话框组件,用它完成查找并替换这一操作
- TPrintDialog——打印对话框组件,用来给打印进分配一个打印作业
- TPrinterSetupDialog——打印机设置对话框组件,用来对打印机进行设置
Dialogs类引入了抽象的Execute函数。在程序运行期间调用各种公用对话框很简单,只需使用Execute方法即可。一般来说,当用户选择了文件并单击“OK”按钮之后,Execute方法就返回True;而如果没有选择文件就关闭了对话框的话,就返回一个False。
除了Find和Replace对话框无模式地显示对话框外,其它的对话框都是模式显示。公用对话框经常如此实现:
1
2
3
4
5
6
|
if
OpenDialog1
.
Execute
then
begin
{ 用户点击了OK,选择了文件}
Memo1
.
Lines
.
LoadFromFile(OpenDialog1
.
FileName);
{ 做一些其它的操作}
end
;
|
这个代码显示了TOpenDialog对话框并从用户那儿得到了文件名,如果点击OK按钮,在If块中的代码得到执行,文件被装载到了Memo组件中,如果OK没有点击,if块中的代码就被忽略了。
文件选择型对话框组件
文件选择型对话框组件也是我们最常用的对话框组件了,它包括了OpenDialog、SaveDialog、OpenPictureDialog和SavePictureDialog四种对话框组件,主要被应用程序“文件”菜单下的“打开”、“保存”、命令所调用。该对话框允许你浏览、切换目录,并使用通配符选择一组文件。OpenPictureDialog和SavePictureDialog除了比OpenDialog和SaveDialog多了一个图像预览的区域外,几乎毫无差别。
文件选择型对话框组件的一些主要属性如下:
- Default——默认扩展名。当所选文件扩展名没有注册时,默认扩展名就会加在文件名末尾,不能超过三个字符,不要在前面加上“.”。
- FileName——记录最后一次选取的文件完整路径(只用于OpenDialog)
- Filter——对文件类型的过滤规则
- FilterIndex——默认过滤规则序号。第一条序号为1,第二条为2,以此类推。
- HelpContext——如果程序有联机帮助,该属性用来指定本对话框帮助位于帮助文件的位置。
- InitialDir——对话框打开时会将初始路径作为当前目录。
- Options——对话框的外观等一些选项
- OptionsEx——更进一步定制对话框的选项
- Title——对话框的标题
- HistoryList——记录了打开文件的历史列表,是为兼容以前版本而保留的,不推荐使用。
- Files——运行期才可见,以TStrings的形式记录了所有选定文件的文件名和完整路径。选定多个文件时,需要将Options属性中的ofAllowMultiSelect设置为True,并用“Files[i]”的形式得到每个文件名。
我们经常要用到定义文件类型的过滤规则。在Object Inspector中单击Filter属性右侧的“…”符号,弹出“FilterEditor”对话框,如下图所示。
其中,Filter Name是对这种文件类型的描述,Filter定义过滤规则,上图中的*.txt代表只有txt扩展名的文件才会出现在文件列表中。
也可以运行期给Filter属性赋值,用管道号(|)把描述和过滤器分开,例如:
1
|
OpenDialog1
.
Filter :=
'文本文件(*.txt)|*.txt|超文本文件(*.htm)|*.htm|脚本文件(*.asp)|*.asp|所有文件(*.*)|*.*'
;
|
这行代码和上面的Filter Editor中输入的是一样的。
Tip
Save As对话框就是Title属性设置为“Save As”的SaveDialog组件。
Tip
可以不把OpenDialog组件放到窗体上,而通过在运行期间通过建立TOpenDialog类的实例,调用其Execute方法,代码如下:
1234567891011procedure
TForm1
.
Button1Click(Sender: TObject);
var
OpenDlg: TOpenDialog;
begin
OpenDlg := TOpenDialog
.
Create(Self);
if
OpenDlg
.
Execute
then
begin
{ do something here}
end
;
OpenDlg
.
Free;
end
;
若有必要,在调用Execute前设置OpenDialog组件的属性。
下面我们通过一个简单的字处理程序的设计来介绍如何使用各种公用对话框组件。我们先来做第一步
1)、新建一个工程,放置的组件及其属性如下表
2)、双击MainMenu,设计主菜单菜单内容如下:
具体菜单项属性如下:
3)、现在窗口看起来如下:
4)、为窗体Form1添加OnCreate事件,代码如下:
1
2
3
4
5
6
|
procedure
TForm1
.
FormCreate(Sender: TObject);
begin
{ 为打开和保存对话框建立过滤器}
OpenDialog1
.
Filter :=
'Text file(*.txt)|*.txt|Rich Type Files(*.rtf)|*.rtf'
;
SaveDialog1
.
Filter := OpenDialog1
.
Filter;
end
;
|
5)、为窗体创建CheckSave函数,用于检查文件是否需要保存。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
|
private
function
CheckSave:
Boolean
;
public
{ Public declarations }
end
;
{ ...省略一些不必要在此显示的代码,节省空间}
function
TForm1
.
CheckSave:
Boolean
;
var
Confirm:
Word
;
begin
Result :=
True
;
if
RichEdit1
.
Modified
then
{ 弹出对话框询问用户是否要保存文件}
Confirm := MessageDlg(
'文件还没有保存,是否保存?'
, mtWarning, [mbYes, mbNo, mbCancel],
0
);
{ 如果用户选择了取消按钮,则返回False}
if
Confirm = mrCancel
then
Result :=
False
;
if
Confirm = mrYes
then
{ 如果用户选择了是按钮,则弹出保存对话框进行保存}
if
SaveDialog1
.
Execute
then
Result :=
True
else
Result :=
False
;
end
;
|
6)、为窗体的OnCloseQuery事件建立响应代码,用于在关闭窗体前检查文件是否保存。
1
2
3
4
5
6
|
procedure
TForm1
.
FormCloseQuery(Sender: TObject;
var
CanClose:
Boolean
);
begin
{ 调用CheckSave函数检查文件是否经过保存,如果不需要保存或者已经保存,
则允许窗体关闭}
CanClose := CheckSave;
end
;
|
7)、为“新建”菜单项建立事件,代码如下:
1
2
3
4
5
|
procedure
TForm1
.
FileNewClick(Sender: TObject);
begin
if
CheckSave
then
RichEdit1
.
Lines
.
Clear;
end
;
|
8)、为“打开”菜单项建立时间,代码如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
procedure
TForm1
.
FileOpenClick(Sender: TObject);
begin
if
CheckSave
then
{ 检查文件是否保存}
with
OpenDialog1
do
begin
{ 对话框中不显示只读文件,没有快速位置栏}
Options := [ofHideReadOnly, ofFileMustExist];
OptionsEx := [ofExNoPlacesBar];
if
Execute
then
{ 如果文件扩展名不符合,则显示出错信息}
if
ofExtensionDifferent
in
Options
then
ShowMessage(
'打开文件类型错误'
)
else
{ 利用TStrings类的LoadFromFile方法,将文本文件读取到RichEdit1中}
RichEdit1
.
Lines
.
LoadFromFile(FileName);
end
;
end
;
|
9)、双击“保存”菜单项,编写如下代码:
1
2
3
4
5
6
7
8
9
10
11
|
procedure
TForm1
.
FileSaveClick(Sender: TObject);
begin
with
SaveDialog1
do
begin
{ 当用户试图覆盖已有文件时,弹出警告窗口}
Options := [ofOverwritePrompt];
OptionsEx := [ofExNoPlacesBar];
if
Execute
then
RichEdit1
.
Lines
.
SaveToFile(FileName);
end
;
end
;
|
10)、保存该程序,现在程序已经实现了打开文件,保存文件,新建文件的功能。接下讲解中里还将用到这个程序。
颜色对话框
ColorDialog对话框使用户能选择颜色。当点击OK按钮时,Color属性包含颜色信息。Color对话框没有响应事件。颜色对话框如下:
颜色对话框的主要属性
- Color——可在设计期时设置打开对话框时的默认颜色,也可在运行期传递用户选择的颜色
- CustomColors——决定了可用的自定义颜色
- Options——一些选项的集合
我们仍然通过上面您的程序例子,来说明颜色对话框的使用。
1)、在主窗体上放置一个ColorDialog组件,设置其cdFullOpen选项为True
2)、双击“背景色”菜单项,编写代码如下:
1
2
3
4
5
|
procedure
TForm1
.
EditColorClick(Sender: TObject);
begin
if
ColorDialog1
.
Execute
then
RichEdit1
.
Color := ColorDialog1
.
Color;
end
;
|
3)、运行程序后可以通过“背景色”菜单,改变文本的颜色。如下:
字体对话框
FontDialog对话框提供了对应用程序中文字的字体、字形、大小和颜色进行设置的方法。一个完整的字体对话框如下:
字体对话框组件的主要属性
Device——指定得到可用字体列表的设备。Device属性属于FontDialogDevice类,有三种取值:fdScreen代表从屏幕设备得到可用字体列表;fdPrinter代表从打印设备得到;fdBoth表示从两者共同得到。
Font——可在设计期指定默认字体,也可在运行期用来传递用户选择的字体
MaxFontSize、MinFontSize——决定了最大和最小可用的字号,只有当Options属性中fdLimitSize选项设置为True时才起作用
Options——一些选项的集合
Font对话框有一个OnApply事件,当用户点击Font对话框上的Apply按钮时,会出现OnApply事件。Apply按钮不会出现在Font对话框上,除非事先为OnApply事件建立了有效(非空)事件处理程序。
我们在上面的例子的基础上进一步加工,来熟悉字体对话框的用法。
1)、在窗体上放置一个FontDialog组件,并为其添加OnApply事件,代码如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
|
procedure
TForm1
.
FontDialog1Apply(Sender: TObject; Wnd: HWND);
begin
{ 如果存在选区,则仅仅改变选区的文本字体}
if
RichEdit1
.
SelLength >
0
then
begin
RichEdit1
.
SelAttributes
.
Color := FontDialog1
.
Font
.
Color;
RichEdit1
.
SelAttributes
.
Name := FontDialog1
.
Font
.
Name;
RichEdit1
.
SelAttributes
.
Size := FontDialog1
.
Font
.
Size;
RichEdit1
.
SelAttributes
.
Style := FontDialog1
.
Font
.
Style;
end
else
{ 不存在选区则所有文本字体都要改变}
RichEdit1
.
Font := FontDialog1
.
Font;
end
;
|
当用户双击对话框中的“应用”按钮时,将字体设置应用到选区文字或全部文字。
2)、为“字体”菜单项添加代码:
1
2
3
4
5
6
|
procedure
TForm1
.
EditFontClick(Sender: TObject);
begin
if
FontDialog1
.
Execute
then
{ 重用字体对话中的“应用”按钮的代码}
FontDialog1Apply(Form1, Handle);
end
;
|
3)、保存程序,运行后测试字体功能,如下:
查找对话框
查找对话框FindDialog组件主要用来在字处理一类的软件中,查找指定字符串,是非模式对话框,如下:
查找对话框和替换对话框的Execute方法与其他公用对话框组件不太一样,首先Find和Replace对话框是非模式的,对话框显示出来后,Execute方法就返回。由于对话框是非模式的,返回值没有意义总是True。而且查找与替换对话框使用OnFind与OnReplace事件,与Options属性一起确定对话框发生了什么。点击“查找下一个”按钮时出现OnFind事件,ReplaceDialog对话框有OnFind事件,也有OnReplace事件,在点击“替换”和“全部替换”按钮时就被触发。
FindDialog与ReplaceDialog对话框主要属性包括FindText(要找的文本)、ReplaceText(用来替换找到文本的文本)及Options选项。显然FindDialog没有ReplaceText属性。Options属性包含了用户点击“查找下一个”与“全部替换”按钮时设置的各种选项的各种信息。
让我们继续来完善上面的例子。
1)、在窗体上放置一个FindDialog组件,编写它的OnFind事件:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
procedure
TForm1
.
FindDialog1Find(Sender: TObject);
var
FoundAt:
Integer
;
StartPos, ToEnd:
Integer
;
begin
with
RichEdit1
do
begin
if
SelLength <>
0
then
StartPos := SelStart + SelLength
else
StartPos :=
0
;
{ toEnd是RichEdit1中从开始查找位置到结束位置的距离}
ToEnd := Length(Text) - StartPos;
FoundAt := FindText(FindDialog1
.
FindText, StartPos, ToEnd, []);
if
FoundAt <> -
1
then
begin
SetFocus;
SelStart := FoundAt;
SelLength := Length(FindDialog1
.
FindText);
end
;
end
;
end
;
|
如果RichEdit1中存在一个选择区域,那么就从选区结束处开始查找,否则就从头开始查找(如果从选区开始处查找的话,第一次查找到的字符串会自动选中,造成无法进行第二次查找)
2)、为“编辑”菜单下的“查找”命令建立OnClick事件:
1
2
3
4
5
6
7
8
9
|
procedure
TForm1
.
EditFindClick(Sender: TObject);
begin
with
FindDialog1
do
begin
{隐藏“区分大小写”和“全字匹配”复选框}
Options := [frDown, frHideMatchCase, frHideWholeWord];
Execute;
end
;
end
;
|
3)、运行程序,打开一个文件,单击“查找”菜单项弹出“查找”对话框,输入要查找的字符串后,单击“查找下一个”按钮,就会立刻找到符合要求的第一个字符串并选定。如下图:
替换对话框
替换对话框TReplaceDialog组件也是非模式对话框,用于将查找到的匹配字符串用指定的字符串来替换,如下图:
替换对话框的主要属性就是ReplaceText属性,用来替换的文本。
下面我们给前面的例子加上替换对话框:
1)、在主窗体上放置一个ReplaceDialog组件,在该组件的OnReplace事件中完成替换功能的代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
procedure
TForm1
.
ReplaceDialog1Replace(Sender: TObject);
var
SelPos:
Integer
;
begin
with
TReplaceDialog(Sender)
do
begin
{ 在RichEdit1中进行区分大小写的完全查找}
SelPos := Pos(FindText, RichEdit1
.
Lines
.
Text);
if
SelPos >
0
then
begin
RichEdit1
.
SelStart := SelPos -
1
;
RichEdit1
.
SelLength := Length(FindText);
{ 替换字符串}
RichEdit1
.
SelText := ReplaceText;
end
else
MessageDlg(concat(
'找不到 “'
, FindText,
'”!'
), mtError, [mbOK],
0
);
end
;
end
;
|
2)、单击“替换”菜单项,为此菜单项添加事件响应:
1
2
3
4
5
6
7
8
|
procedure
TForm1
.
EditReplaceClick(Sender: TObject);
begin
with
ReplaceDialog1
do
begin
Options := [frDown, frHideMatchCase, frHideWholeWord];
Execute;
end
;
end
;
|
因为上面的查找算法区分大小写并且不能修改,所有这里我们隐藏了“区分大小写”和“全字匹配”复选框。
3)、运行程序,测试下替换功能,如下:
打印对话框
打印对话框TPrintDialog组件通常用来给打印机分配一项打印显示内容的作业。在字处理类软件和图像处理类软件中使用非常普遍。打印对话框也属于模式对话框,如下图:
打印对话框常用属性见下表,默认情况下,所有选项都设为False。
打印对话框常用属性
- Collate——指定了“自动分页”复选框有没有被选择
- Copies——指定打印的份数
- FromPage——开始的页数
- MaxPage和MinPage——当用户指定页号打印时,可以输入的最大和最小页号(只有当poPageNums选项为True时才起作用,且MaxPage值必须大于MinPage值,否则打印对话框不会显示)
- Options——一些更进一步定制对话框的选项
- PrintRange——指定了打印范围列表中选择的类型:prAllPages选择所有页;prSelection选择“选定范围”;prPageNums选择“指定页号”。
- PrintToFile——指定“打印到文件”复选框有没有被选择
- ToPage——结束的页数
下面我们给对话框演示程序添加打印功能:
1)、在窗体上添加一个PrintDialog组件,设置其poPageNums、poPrintToFile、poSelection均为False,即不允许用户选择打印范围和使用打印到文件功能。
2)、为“文件”菜单下的“打印”命令添加事件响应:
1
2
3
4
5
6
7
8
9
|
procedure
TForm1
.
FilePrintClick(Sender: TObject);
var
i:
Integer
;
begin
if
PrintDialog1
.
Execute
then
{ 利用RichEdit对象的Print方法打印指定份数的文档}
for
i :=
1
to
PrintDialog1
.
Copies
do
RichEdit1
.
Print(
'默认打印文档'
);
end
;
|
3)、执行该程序。至此,我们就利用各种公共对话框完成了一个简单的字处理程序。