公用对话框是一类非可视的组件,它们都由TDialog类继承而来,存在Dialogs组件面板上。包括:
Dialogs类引入了抽象的Execute函数。在程序运行期间调用各种公用对话框很简单,只需使用Execute方法即可。一般来说,当用户选择了文件并单击“OK”按钮之后,Execute方法就返回True;而如果没有选择文件就关闭了对话框的话,就返回一个False。
除了Find和Replace对话框无模式地显示对话框外,其它的对话框都是模式显示。公用对话框经常如此实现:
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多了一个图像预览的区域外,几乎毫无差别。
我们经常要用到定义文件类型的过滤规则。在Object Inspector中单击Filter属性右侧的“…”符号,弹出“FilterEditor”对话框,如下图所示。
其中,Filter Name是对这种文件类型的描述,Filter定义过滤规则,上图中的*.txt代表只有txt扩展名的文件才会出现在文件列表中。
也可以运行期给Filter属性赋值,用管道号(|)把描述和过滤器分开,例如:
OpenDialog1.Filter := '文本文件(*.txt)|*.txt|超文本文件(*.htm)|*.htm|脚本文件(*.asp)|*.asp|所有文件(*.*)|*.*';
这行代码和上面的Filter Editor中输入的是一样的。
Tip
Save As对话框就是Title属性设置为“Save As”的SaveDialog组件。
Tip
可以不把OpenDialog组件放到窗体上,而通过在运行期间通过建立TOpenDialog类的实例,调用其Execute方法,代码如下:
procedure 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事件,代码如下:
procedure TForm1.FormCreate(Sender: TObject); begin { 为打开和保存对话框建立过滤器} OpenDialog1.Filter := 'Text file(*.txt)|*.txt|Rich Type Files(*.rtf)|*.rtf'; SaveDialog1.Filter := OpenDialog1.Filter; end;
5)、为窗体创建CheckSave函数,用于检查文件是否需要保存。
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事件建立响应代码,用于在关闭窗体前检查文件是否保存。
procedure TForm1.FormCloseQuery(Sender: TObject; var CanClose: Boolean); begin { 调用CheckSave函数检查文件是否经过保存,如果不需要保存或者已经保存, 则允许窗体关闭} CanClose := CheckSave; end;
7)、为“新建”菜单项建立事件,代码如下:
procedure TForm1.FileNewClick(Sender: TObject); begin if CheckSave then RichEdit1.Lines.Clear; end;
8)、为“打开”菜单项建立时间,代码如下:
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)、双击“保存”菜单项,编写如下代码:
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对话框没有响应事件。颜色对话框如下:
我们仍然通过上面您的程序例子,来说明颜色对话框的使用。
1)、在主窗体上放置一个ColorDialog组件,设置其cdFullOpen选项为True
2)、双击“背景色”菜单项,编写代码如下:
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事件,代码如下:
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)、为“字体”菜单项添加代码:
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事件:
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事件:
procedure TForm1.EditFindClick(Sender: TObject); begin with FindDialog1 do begin {隐藏“区分大小写”和“全字匹配”复选框} Options := [frDown, frHideMatchCase, frHideWholeWord]; Execute; end; end;
3)、运行程序,打开一个文件,单击“查找”菜单项弹出“查找”对话框,输入要查找的字符串后,单击“查找下一个”按钮,就会立刻找到符合要求的第一个字符串并选定。如下图:
替换对话框TReplaceDialog组件也是非模式对话框,用于将查找到的匹配字符串用指定的字符串来替换,如下图:
替换对话框的主要属性就是ReplaceText属性,用来替换的文本。
下面我们给前面的例子加上替换对话框:
1)、在主窗体上放置一个ReplaceDialog组件,在该组件的OnReplace事件中完成替换功能的代码:
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)、单击“替换”菜单项,为此菜单项添加事件响应:
procedure TForm1.EditReplaceClick(Sender: TObject); begin with ReplaceDialog1 do begin Options := [frDown, frHideMatchCase, frHideWholeWord]; Execute; end; end;
因为上面的查找算法区分大小写并且不能修改,所有这里我们隐藏了“区分大小写”和“全字匹配”复选框。
3)、运行程序,测试下替换功能,如下:
打印对话框TPrintDialog组件通常用来给打印机分配一项打印显示内容的作业。在字处理类软件和图像处理类软件中使用非常普遍。打印对话框也属于模式对话框,如下图:
打印对话框常用属性见下表,默认情况下,所有选项都设为False。
下面我们给对话框演示程序添加打印功能:
1)、在窗体上添加一个PrintDialog组件,设置其poPageNums、poPrintToFile、poSelection均为False,即不允许用户选择打印范围和使用打印到文件功能。
2)、为“文件”菜单下的“打印”命令添加事件响应:
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)、执行该程序。至此,我们就利用各种公共对话框完成了一个简单的字处理程序。
以上代码均在delphi7中测试通过,示例代码下载:公用对话框演示程序.rar