《第3章金融风险管理原理》由会员分享,可在线阅读,更多相关《第3章金融风险管理原理(182页珍藏版)》请在金锄头文库上搜索。
1、第第3 3章章 应用程序界面设计应用程序界面设计 第第3章章 应用程序界面设计应用程序界面设计 3.1 菜单菜单 3.2 工具栏与状态行工具栏与状态行 3.3 对话框对话框 3.4 多窗体程序多窗体程序 3.5 拖放技术拖放技术 3.6 窗体的分割窗体的分割 习题习题 第第3 3章章 应用程序界面设计应用程序界面设计 3.1 菜菜 单单 3.1.1菜单设计器和菜单组件MainMenu组件位于组件面板的Standard页上,将它放入一个应用程序的窗体,然后我们就可以利用菜单设计器(MenuDesigner)设计菜单了。第第3 3章章 应用程序界面设计应用程序界面设计 菜单设计器是BCB提供的一个
2、可视化工具,使用起来直观简便。右击窗体中的MainMenu组件,出现该组件的快捷菜单,其中第一项就是“MenuDesigner”。选择该项就打开了菜单设计器,如图3-1所示。BCB提供的另一种菜单组件是下拉菜单(PopupMenu),它也可以用MenuDesigner来设计。两种菜单中的各个菜单项都是TMenuItem类的对象,它们是由MenuDesigner在设计过程中添入到菜单组件中去的,如图3-2所示。第第3 3章章 应用程序界面设计应用程序界面设计 图3-1MainMenu的快捷菜单第第3 3章章 应用程序界面设计应用程序界面设计 图3-2在MenuDesigner中设计第第3 3章章
3、 应用程序界面设计应用程序界面设计 在MenuDesigner中的操作主要用鼠标。当选中某个菜单项时,ObjectInspector会切换到对应该项的MenuItem对象,此时可输入它的Caption属性,也就是菜单项的名称。若要删除某菜单项,可在MenuDesigner内选中该项后按Delete键,也可右击该菜单项打开它的MenuItem快捷菜单,再选该菜单上的Delete项。若要插入菜单项,可在选中插入位置后按Insert键,也可右击该菜单项打开它的MenuItem快捷菜单,再选该菜单上的Insert项。若要移动菜单项的位置可以用鼠标进行拖曳完成。第第3 3章章 应用程序界面设计应用程序界
4、面设计 此外,还可用MenuItem的快捷菜单上的CreateSubMenu选项为菜单项增加一个子菜单,这样就可构建任意层数的菜单系统。如果要在程序运行中动态地增减菜单项,则可在程序中调用TMenuItem对象的Add和Delete方法。根据菜单在应用程序中的作用,它的选项常被指派执行某项功能或操作。BCB中的MenuItem对象都有OnClick事件,为该事件编写的代码即被指派到菜单项对应的操作中。在MenuDesigner中双击菜单项即可打开对应的OnClick事件代码段;在窗体设计区中单击菜单项也能打开OnClick事件代码段。当然,还可以在ObjectInspector中打开MenuI
5、tem的OnClick事件。第第3 3章章 应用程序界面设计应用程序界面设计 下面是菜单组件的常用属性。1AutoMerge属性AutoMerge属性用于菜单的合并,当子窗体上菜单的该属性为true时,则在执行程序中会将子窗体上的菜单自动合并到它的父窗体的菜单上。本章3.4.2节将给出有关菜单合并的详细讲解和范例。在该属性不为true时,用户仍可执行Merge方法将两个菜单合并。UnMerge方法则将已合并的菜单拆分。第第3 3章章 应用程序界面设计应用程序界面设计 2Caption属性菜单项上的文字就是该菜单项的Caption属性值。缺省的BCB会将该Caption作为菜单项的Name,但如
6、果Caption中有汉字,则菜单项的Name被缺省设置为N1、N2等。如果在Caption的某个字母前加上一个&符号,则该字符在显示时就会有一个下划线,这一字符就被称为加速键,也就是说,当用户按下Alt键,再加上该字符时,即可选择该菜单。如果对Caption属性输入一个“-”符号(减号),则在菜单上显示为一条横线,我们可用此线对菜单项进行分组。第第3 3章章 应用程序界面设计应用程序界面设计 3Checked属性Cheched属性若为true,则会在菜单项左方显示一个钩,使该菜单项具有和一个复选按钮类似的作用。但注意,与复选按钮不同的是,BCB不会自动对Checked置值,用户必须在该菜单项的
7、OnClick中写入改变Checked值的代码。4Enabled属性与其它控件的Enabled的用法属性类似,该属性为false时,对应的菜单项颜色变灰且不能被选择。该属性不仅可用于控制主菜单上的项,也可控制下拉菜单上的项。若要相应菜单项变为不可见,则可设置Visible为false。第第3 3章章 应用程序界面设计应用程序界面设计 5GroupIndex属性GroupIndex属性是整型值,它可控制下拉菜单在主菜单中的位置(即顺序)。一般用于在菜单合并时,确定合并后菜单项的位置。6ShortCut属性ShortCut属性定义了一个可快速访问某个菜单项的快捷键。一般地,该快捷键显示在菜单项的右
8、边。在菜单中可以作为快捷键的一般都是功能键(如F1,F2,)或组合键(如Ctrl+A,Ctrl+F2,Alt+F3,)。菜单项被选中时,在ObjectInspector中打开ShortCut的组合框选取或输入。第第3 3章章 应用程序界面设计应用程序界面设计 7Visible属性Visible属性为false时,对应的菜单项不可见(不可见的项当然也是不能被选取的)。当某一项不可见时,排列在该项之后的各项位置会自动上移。第第3 3章章 应用程序界面设计应用程序界面设计 3.1.2菜单设计范例【例3-1】在应用程序中建立如下菜单系统:主菜单含六个项,分别为“File”、“Edit”、“View”、
9、“Windows”、“Tools”和“Help”。“File”下拉菜单有“New”、“Open”、“Save”、“Print”、“PrintSetup”和“Exit”等六项。它们被分成三个组,并对“New”和“Exit”分别定义了快捷键F10和Ctrl+E。“View”下拉菜单中有 “File Enabled”、“FileDisabled”、“HideHelp”和“ShowHelp”等四项。第第3 3章章 应用程序界面设计应用程序界面设计 “Tools”下拉菜单中有一项“ToolBar”。“Edit”、“Windows”和“Help”的下拉菜单为空。图3-3为在MenuDesigner中设计该
10、菜单。我们看到菜单中有两条将菜单项分组的横线,它们是通过在Caption中输入“-”号得到的。第第3 3章章 应用程序界面设计应用程序界面设计 图3-3在MenuDesigner中设计菜单第第3 3章章 应用程序界面设计应用程序界面设计 我们希望该菜单系统能实现以下的功能:当选择“Exit”时能退出程序。当选择“ToolBar”时能切换该项的Checked属性。当选择“FileEnabled”时使“File”下拉菜单有效 , 并 使 “File Enabled”菜 单 项 失 效 以 及 “FileDisabled”菜单项有效。当选择“FileDisabled”时使“File”下拉菜单失效,并
11、使“File Disabled”菜单项失效以及“FileEnabled”菜单项有效。第第3 3章章 应用程序界面设计应用程序界面设计 当选择“HideHelp”时使“Help”项不可见。当选择“ShowHelp”时使“Help”恢复为可见。当选择“New”、“Open”或“Save”时分别出现一个对话框提示相应的功能“NotCompleted”。选择其它项时程序不进行处理。为此,设计时应使“ShowHelp”和“FileEnabled”菜单项的Enabled为false。然后为各菜单项的OnClick事件编写以下代码:第第3 3章章 应用程序界面设计应用程序界面设计 void_fastcall
12、TForm1:Exit1Click(TObject*Sender)Form1-Close();/-void_fastcallTForm1:ToolBar1Click(TObject*Sender)ToolBar1-Checked = ! (ToolBar1-Checked); /使 该 菜 单 项 的Checked属性值取反/-第第3 3章章 应用程序界面设计应用程序界面设计 void_fastcallTForm1:FileEnabled1Click(TObject*Sender)File1-Enabled=true;FileEnabled1-Enabled=false;FileDisable
13、d1-Enabled=true;/-void_fastcallTForm1:FileDisabled1Click(TObject*Sender)File1-Enabled=false;FileEnabled1-Enabled=true;FileDisabled1-Enabled=false;第第3 3章章 应用程序界面设计应用程序界面设计 /-void_fastcallTForm1:HideHelp1Click(TObject*Sender)Help1-Visible=false;ShowHelp1-Enabled=true;HideHelp1-Enabled=false;/-第第3 3章章
14、应用程序界面设计应用程序界面设计 void_fastcallTForm1:ShowHelp1Click(TObject*Sender)Help1-Visible=true;ShowHelp1-Enabled=false;HideHelp1-Enabled=true;/-void_fastcallTForm1:New1Click(TObject*Sender)ShowMessage(NewHasNotCompleted);/调用通用函数ShowMessage输出信息第第3 3章章 应用程序界面设计应用程序界面设计 /-void_fastcallTForm1:Open1Click(TObject*
15、Sender)ShowMessage(OpenHasNotCompleted);/调用通用函数ShowMessage输出信息第第3 3章章 应用程序界面设计应用程序界面设计 /-void_fastcallTForm1:Save1Click(TObject*Sender)ShowMessage(SaveHasNotCompleted);/调用通用函数ShowMessage输出信息/-ToolBar1-Checked=!(ToolBar1-Checked);第第3 3章章 应用程序界面设计应用程序界面设计 运行该程序,选择FileDisabled后的画面如图3-4所示,选择HideHelp后的画面
16、如图3-5所示,选择ToolBar后的画面如图3-6所示,再次选择ToolBar后的画面如图3-7所示。在选择了FileNew后弹出的消息框如图3-8所示。第第3 3章章 应用程序界面设计应用程序界面设计 图3-4选择FileDisabled第第3 3章章 应用程序界面设计应用程序界面设计 图3-5选择HideHelp第第3 3章章 应用程序界面设计应用程序界面设计 图3-6选择ToolBars使Checked被勾选第第3 3章章 应用程序界面设计应用程序界面设计 图3-7再次选择ToolBars取消Checked勾选第第3 3章章 应用程序界面设计应用程序界面设计 图3-8选择FileNew
17、弹出消息框第第3 3章章 应用程序界面设计应用程序界面设计 3.2 工具栏与状态行工具栏与状态行大部分Windows应用程序都有一个工具栏,利用工具栏上的图形按钮可加快操作速度,一般工具栏位于窗体的顶部。在BCB中有许多方法可设计出不同风格的工具栏,其中较简单直接的方法是使用Panel和SpeedButton控件进行的。第第3 3章章 应用程序界面设计应用程序界面设计 3.2.1面板和加速按钮1面板面板(Panel)控件位于组件面板的Standard页上的倒数第二个位置,它是一个容器组件,即可以将其它组件放入面板。它的主要功能就是制作工具栏和状态栏。以下是面板的常用属性。1)Align属性为设
18、置面板在窗体上的位置,可以使用它的Align属性。该属性取值范围为alTop、alRight、alBottom、alLeft、alClient和alNone。第第3 3章章 应用程序界面设计应用程序界面设计 缺省值为alNone,此时可用鼠标操作确定其位置和尺寸。当作为工具栏使用时,面板常被放置在窗体顶部位于菜单条之下,我们可以用alTop指定该位置。这样,即使窗体尺寸改变,面板也能准确定位,而且能自动改变宽度以保持横贯整个窗体。alRight、alLeft、alBottom和alTop类似,分别适合将面板定位到窗体的右、左和底部。alClient则定位在整个窗体的客户区。第第3 3章章 应用
19、程序界面设计应用程序界面设计 2)BevelInner和BevelOuter属性BevelInner和BevelOuter这两个属性决定了面板的外观,适当搭配二者的值可以产生不同的三维效果。它们的取值范围为bvLowered、bvNone、bvRaised和bvSpace。缺省值BevelInner=None,BevelOuter=Raised。3)Caption属性面板也有Caption属性,因此可在面板上显示文字。此时,它的功能类似于Label组件,但可以制作出三维效果,简单的状态栏就是利用面板的Caption制作的。在用作工具栏时,一般应将Caption置为空白。第第3 3章章 应用程序
20、界面设计应用程序界面设计 4)Visible属性Visible属性为false时,可隐藏面板及面板上的组件。我们可用来隐藏工具栏。第第3 3章章 应用程序界面设计应用程序界面设计 2加速按钮加速按钮(SpeedButton)是位于Additional页上第二个位置的组件。它与按钮类似,但可以在表面上放置图形。与按钮或位图按钮(BitButton)相比,它没有窗口句柄,不消耗Windows资源,绘制速度也更快一点。所以,非常适合用作工具栏上的工具按钮。加速按钮有以下主要属性。第第3 3章章 应用程序界面设计应用程序界面设计 1)Glyph属性Glyph属性指定一个图像文件放到加速按钮的表面。点击
21、ObjectInspector中该属性右侧的“.”按钮就打开PictureEditor对话框,可选“Load.”按钮指定一个图片文件,按“OK”完成装入,如图3-9所示。一般应装入小型位图或图标(2020像素左右),位图文件既可通过各种途径收集得到,也可利用BCB的ImageEditor工具自行绘制。参见本书基础篇1.3.6节。在BCB的 目 录 C:ProgramFilesCommonFilesBorlandSharedImagesButtons下就有许多按钮图标。第第3 3章章 应用程序界面设计应用程序界面设计 图3-9输入Glyph属性时选择位图第第3 3章章 应用程序界面设计应用程序界
22、面设计 2)NumGlyphs属性NumGlyphs属性可输入数字14,缺省值为1,它表示加速按钮中包含的位图的数目。当该数目为2时,第一个位图为按钮的标准状态,第二个位图用于按钮失效时。当该数目为4时,第一、二个位图作用同前,第三个位图用于单击按钮时,第四个位图用于按钮持续保持按下状态时。前面提到Buttons目录下有许多按钮的位图,如果打开这些位图观察可以发现它们都是“两位一体”的,即图片中横向并排着两个同样尺寸的类似图形。第第3 3章章 应用程序界面设计应用程序界面设计 其实这些图形就是专门被定制成可以用作NumGlyphs等于2时的按钮表面贴图。类似地,如果用于NumGlyphs等于4
23、时的贴图,图片中必须包含从左到右排列的四个同样尺寸的小图形。第第3 3章章 应用程序界面设计应用程序界面设计 3)Hint和ShowHint属性Hint和ShowHint属性用于产生提示,该两个属性并非加速按钮专有。但由于仅靠一幅简单的位图难以表达复杂的意义,加速按钮更加需要有自我提示的功能。Hint是字符串类型的属性,应输入提示的内容;ShowHint则是bool型,当它为true时组件具有提示功能。第第3 3章章 应用程序界面设计应用程序界面设计 3.2.2工具栏设计范例下面给出一个工具栏程序范例。【例3-2】我们在前面例3-1的基础上,保留主菜单上的“File”、“Edit”和“Tool
24、s”三个下拉菜单,删去其余菜单项。往该程序窗体内放入一个由面板Panel1和三个加速按钮组成的工具栏。Panel1的Align设置为alTop;三个加速按钮的Glyph中分别装入三个位图,它们的ShowHint都设置为true, Hint属性分别输入“New”、“Open”和“Save”。第第3 3章章 应用程序界面设计应用程序界面设计 再将菜单项“ToolBar”的Checked属性设置为true,表示程序在初始状态下显示工具栏。各菜单项的OnClick基本上与例3-1中相同,但“ToolBar”的OnClick事件中应增加改变Panel1的Visible属性的语句。第第3 3章章 应用程序
25、界面设计应用程序界面设计 程序中,工具栏上三个加速按钮的功能应分别等同于菜单上的“New”、“Open”和“Save”,即它们可以分别与三个菜单项的OnClick事件分享代码。因此,可按如下方式定义三个按钮的OnClick事件:选中第一个按钮,在ObjectInspector中选Events页,在OnClick事件右面组合框中选择New1Click(即菜单项“New”的OnClick事件的名称),然后对第二、三个按钮进行类似操作,如图3-10所示。第第3 3章章 应用程序界面设计应用程序界面设计 图3-10为加速按钮选择OnClick第第3 3章章 应用程序界面设计应用程序界面设计 下面是该范
26、例中惟一需要修改的代码段:void_fastcallTForm1:ToolBar1Click(TObject*Sender)ToolBar1-Checked=!ToolBar1-Checked;if(ToolBar1-Checked)Panel1-Visible=true;elsePanel1-Visible=false;第第3 3章章 应用程序界面设计应用程序界面设计 程序运行开始时的画面如图3-11所示。若把鼠标靠近加速按钮并停留,就会看到提示信息。选择ToolBar菜单项,能打开或关闭工具栏,图3-12为工具栏已被关闭。当点击三个加速按钮时,与点击菜单项“New”、“Open”和“Sav
27、e”时一样,会出现一个显示“XXXHasNotCompleted”的信息框。我们也可以把组合框、微调按钮(UpDown)等控件放到面板组件上,做出一个像Word中那样有更加复杂功能的工具栏,如图3-13所示。第第3 3章章 应用程序界面设计应用程序界面设计 图3-11程序初始画面图3-12工具栏已关闭第第3 3章章 应用程序界面设计应用程序界面设计 图3-13一个复杂的工具栏第第3 3章章 应用程序界面设计应用程序界面设计 3.2.3StatusBar组件通常在Windows应用程序的底部有一个状态行,用以提供一些系统信息和提示。C+Builder中我们可以利用面板组件制作状态行,但效果较差。
28、本节中将介绍StatusBar组件,它位于Win32页上,是非常适合用作状态行的。StatusBar可以看作是面板的容器,它可包含有若干面板,从左向右排列。其中每个面板都能被独立控制,用于显示一项信息。图3-14为含有五个面板的StatusBar组件。第第3 3章章 应用程序界面设计应用程序界面设计 图3-14StatusBar组件第第3 3章章 应用程序界面设计应用程序界面设计 下面简单介绍一下StatusBar的主要属性。1Align属性用法与面板的Align一样,但作为状态行组件,其缺省值被设置为alBottom。2Font属性Font属性可设置状态行中使用的字体,但必须同时设置UseS
29、ystemFont为false,否则状态行使用系统定义的字体。第第3 3章章 应用程序界面设计应用程序界面设计 3SimplePanel属性SimplePanel属性为true时,StatusBar具有一个简单面板(Panel)的一切特征,而不能作为面板容器使用。一般,应设置SimplePanel为false。第第3 3章章 应用程序界面设计应用程序界面设计 4Panels属性Panels属性是StatusBar最主要的属性,它是一个数组,其中的每个元素代表一个面板。当SimplePanel为false时,可点击Panels属性值右侧的“.”按钮打开一个面板设置对话框,如图3-15所示。打开该
30、对话框的另一个办法是右击StatusBar,当出现快捷菜单后,再选择“PanelsEditor”。第第3 3章章 应用程序界面设计应用程序界面设计 图3-15使用PanelsEditor第第3 3章章 应用程序界面设计应用程序界面设计 PanelsEditor是一个小窗口,开始时为空,每次点击工具栏上的“New”(左面第一个)按钮就在窗口中增加一个项,相应地StatusBar中也增加了一个面板。当在PanelEditor中选中某项时,ObjectInspector中会切换到与其对应的面板,我们就能设置该面板的Width、Bevel和Alignment等属性。Bevel属性与面板的外观有关,一个
31、状态行组件的各个面板可分别有不同的Bevel值 。 Alignment的 可 选 值 为 taCenter、 taLeftJustify和taRightJustify,分别表示显示文字的位置为居中、靠左和靠右。第第3 3章章 应用程序界面设计应用程序界面设计 3.2.4状态行设计范例下面给出一个状态行设计的范例。【例3-3】程序的主菜单上有“File”和“Edit”两项,窗体中间放了一个TMemo控件,可输入文本,窗口底部有一个被分隔为五个部分的状态行,如图3-16所示。这五部分显示的信息分别为:(1)时间,显示为XX:XX:XX;(2)Memo控件中当前插入点的位置,它用Y行、X列形式表示,
32、Y、X起始值都是0;第第3 3章章 应用程序界面设计应用程序界面设计 (3)Memo中文本的字数;(4)键盘上Insert键的状态,显示为INS或空白;(5)键盘上NumLock键的状态,显示为NUM或空白。我们让前三项居中显示,后两项靠左显示,如图3-16所示。第第3 3章章 应用程序界面设计应用程序界面设计 图3-16程序运行时状态行中显示有关信息第第3 3章章 应用程序界面设计应用程序界面设计 (操作要点将StatusBar控件放入窗体,设置其Align为alBottom,SimplePanel和UseSystemFont为false,并选择适当的字体和颜色。右击StatusBar打开P
33、anelEditor,五次点击New工具按钮添加面板,将五个面板的Width分别设置为100、100、100、50和50,并将前三 项 Alignment设 置 为 taCenter, 后 两 项 设 置 为taLeftJustify。第第3 3章章 应用程序界面设计应用程序界面设计 为了能实时显示动态信息,我们需要每隔一小段时间将状态行刷新一遍,因此要在Form1中加入一个定时器组件Timer1(位于组件面板上System页)。我们将该Timer的Interval设为100,Enabled设为true,并为Timer1编写OnTimer事件的代码如下:void_fastcallTForm1:
34、Timer1Timer(TObject*Sender)第第3 3章章 应用程序界面设计应用程序界面设计 AnsiStringstr1;/显示时间TDateTimeDateTime=Time();StatusBar1-Panels-Items0-Text=时 间 :+TimeToStr(DateTime);/显示插入点位置str1=位置:;str1=str1+IntToStr(Memo1-CaretPos.y)+行;str1=str1+IntToStr(Memo1-CaretPos.x)+列;StatusBar1-Panels-Items1-Text=str1;/显示字数第第3 3章章 应用程序
35、界面设计应用程序界面设计 str1=Memo1-Lines-Text;StatusBar1-Panels-Items2-Text=字数:+IntToStr(str1.Length();/显示NUM状态if(GetKeyState(VK_NUMLOCK)StatusBar1-Panels-Items3-Text=NUM;elseStatusBar1-Panels-Items3-Text=;/显示INS状态第第3 3章章 应用程序界面设计应用程序界面设计 if(GetKeyState(VK_INSERT)StatusBar1-Panels-Items4-Text=INS;elseStatusBar
36、1-Panels-Items4-Text=;第第3 3章章 应用程序界面设计应用程序界面设计 【评析】(1)StatusBar1-Panels-Itemsi-Text属性代表状态行中第i个面板上的文本,(i=0,1,2,3,4),我们只要将有关信息放入相应的Text属性即可。(2)可用Time函数取得TDateTime类型的时间信息,再用函数TimeToStr把它转换为AnsiString字符串类型。(3)Memo1-CaretPos.y和Memo1-CaretPos.x为当前插入位置。str1=Memo1-Lines-Text取得Memo1中的文本,再用AnsiString的Length方法
37、求出它的长度,即文本中的字数。第第3 3章章 应用程序界面设计应用程序界面设计 注意:计算字数时每次回车会增加两个字(回车符和换行符)。(4)GetKeyState是一个API函数,可取到键盘上各个键的状态。(5)本例中使用了Timer组件,该组件起到定时控制的作用。它的Interval属性指定时间间隔,本例中设置为100,表示每间隔100毫秒(0.1秒)调用一次时控过程(由OnTimer事件确定)。注意:设置Timer的Enabled为true,以启动Timer的时控功能。第第3 3章章 应用程序界面设计应用程序界面设计 (6)本例中为了能显示一些有意义的信息,使用了若干WindowsAPI
38、函数(在本书提高篇中将较系统地介绍WindowsAPI)。对初学者来说,如何在各种场合取得所需的状态信息,可以是一个逐渐积累的过程。第第3 3章章 应用程序界面设计应用程序界面设计 3.3 对对 话话 框框3.3.1对话框与模态窗口设计对话框与设计普通的窗体没什么本质区别,但对话框一般具有如下特征:(1)在程序中不作为主窗体,通常被缺省命名为Form2或Form3等。在BCB中为了给应用程序加入第二个窗体(或第三个窗体等),可选FileNewForm菜单项或点击相应的工具按钮。第第3 3章章 应用程序界面设计应用程序界面设计 对于有两个以上(含两个)窗体的程序,在与主窗体Form1对应的Uni
39、t1.h(或Unit1.cpp)中一般要加入#includeUnit2.h语句(或执行FileIncludeUnitHdr.命令),否则,在Form1中就不能识别Form2中定义的对象。至于是否要在uint2.h中加入#includeUnit1.h,则应看具体情况。(2)窗口标题一般应为对话框名称,窗口内没有主菜单。边框上无控制按钮,也不能改变窗口尺寸。要做到这一点,较简单的方法是设置BorderStyle属性为bsDialog。第第3 3章章 应用程序界面设计应用程序界面设计 (3)窗口往往以模态方式打开,Windows的窗口可定义为模态窗口或非模态窗口。当应用程序打开一个模态窗口后,只要该
40、窗口未关闭,就不能对程序中的其它窗口进行任何操作,以此方式强制用户对该模态窗口作出响应。所谓以模态方式打开即指使打开的窗口成为模态窗口。在BCB中一个窗口是否为模态一般并非取决于其设计阶段,而是由打开该窗口时使用的方法所确定。如果一个窗口是被Show方法打开的,那么它就是非模态方式的;如果用ShowModal方法打开窗口,那么该窗口就是模态的。第第3 3章章 应用程序界面设计应用程序界面设计 3.3.2信息框C+Builder中使用ShowMessage和MessageDlg函数产生标准的Windows信息框,这种信息框是一个模态窗口。ShowMessage使用方便但功能较弱,只能显示一个带有
41、OK按钮的信息框。在例3-1中我们已经用过该函数。MessageDlg函数适用范围更广。它有四个参数,BCB对该函数声明如下:int_fastcallMessageDlg(constAnsiStringMsg,TMsgDlgTypeDlgType,TMsgDlgButtonsButtons,intHelpCtx);第第3 3章章 应用程序界面设计应用程序界面设计 Msg参数指定了显示的信息。DlgType参数可指定信息框的类型,该参数为TmsgDlgType类型,它的取值范围及含义如表3-1所示。Buttons参数指定了信息框所包含的按钮,类型为TmsgDlgButtons,它的取值范围及含义
42、如表3-2所示。HelpCtx参数可指定当用户单击Help按钮或按F1键时所弹出的帮助主题的帮助上下文ID。MessageDlg函数返回一个整数,代表用户在对话框中所选的按钮,该值必定为以下预定义常数之一:mrNone、mrAbort、mrYes、mrOk、mrRetry、mrNo、mrCancel、mrIgnore、mrAll。第第3 3章章 应用程序界面设计应用程序界面设计 表3-1DlgType参数的取值取值说明mtWarning显示一个带有蓝色惊叹号的信息框mtError显示一个带有红色停止符号的信息框mtInformation显示一个带有蓝色“i”标志的信息框mtConfirmati
43、on显示一个带有绿色问号的信息框mtCustom框中没有位图,对话框标题为应用程序文件名第第3 3章章 应用程序界面设计应用程序界面设计 表3-2Buttons参数的取值取值说明mbYes“Yes”按钮mbNo“No”按钮mbOK“OK”按钮mbCancel“Cancel”按钮mbHelp“Help”按钮mbAbort“Abort”按钮mbRetry“Retry”按钮mbIgnore“Ignore”按钮mbAll“All”按钮第第3 3章章 应用程序界面设计应用程序界面设计 下面一段代码出现一个信息框询问用户是否退出程序,若选择Yes,则关闭Form1,使程序结束。代码运行时的画面如图3-17
44、所示。if(MessageDlg(是否退出程序?,mtConfirmation,TMsgDlgButtons ( ) mbYes Close();第第3 3章章 应用程序界面设计应用程序界面设计 图3-17使用MessageDlg函数第第3 3章章 应用程序界面设计应用程序界面设计 3.3.3通用对话框组件在组件面板的Dialog页上有一组共10个通用对话框组件可供使用。这些对话框实际上是由Windows提供的,BCB把它们包装了一下,使用更加方便了。其中,最常用的是OpenDialog(打开文件)、SaveDialog(保存文件)、FontDialog(字体)和ColorDialog(颜色)
45、对话框,图3-18图3-21为这四个对话框的画面。另外几个是OpenPictureDialog(打开图形)、SavePictureDialog(保存图形)、PrintDialog(打印)、PrinterSetupDialog(打印机设置)、FindDialog(查找)和ReplaceDialog(替换)对话框。第第3 3章章 应用程序界面设计应用程序界面设计 图3-18OpenDialog第第3 3章章 应用程序界面设计应用程序界面设计 图3-19SaveDialog第第3 3章章 应用程序界面设计应用程序界面设计 图3-20FontDialog第第3 3章章 应用程序界面设计应用程序界面设计
46、 图3-21ColorDialog第第3 3章章 应用程序界面设计应用程序界面设计 这些对话框的用法是类似的:先调用组件的Execute方法打开对话框供用户操作,当操作完成对话框被关闭后,用户选定的对象被存放在该组件的相应属性内。如操作OpenDialog和SaveDialog对话框所选定的文件名被存放在FileName属性内,FontDialog中选定的字体被存放在Font属性内,ColorDialog中选定的颜色则被存放在Color属性内。第第3 3章章 应用程序界面设计应用程序界面设计 【例3-4】在窗体Form1中放入一个TColorDialog组件ColorDialog1,再放入一个
47、按钮组件Button1。为Button1的OnClick事件编写如下代码:void_fastcallTForm1:Button1Click(TObject*Sender)if(ColorDialog1-Execute()Form1-Color=ColorDialog1-Color;第第3 3章章 应用程序界面设计应用程序界面设计 程序运行时,点击Button1弹出颜色对话框,在对话框中选定颜色并点击“确定”后,程序使Form1的颜色改变为所选颜色。注意:ColorDialog1-Execute()函数返回一个整型值,若用户在对话框中选定后按“确定”退出则该值为1,若按“取消”退出则为0。因此,
48、根据用户是否选中了某种颜色,程序中用if语句来判定是否需要设置窗体的颜色。具体设置窗体颜色则是通过“Form1-Color=ColorDialog1-Color;”语句完成的。第第3 3章章 应用程序界面设计应用程序界面设计 3.4 多多 窗窗 体体 程程 序序 3.4.1项目与窗体BCB应用程序通常是一个项目,项目文件的扩展名为.bpr,这是一个C+的源文件,我们可以执行ProjectViewSource菜单命令打开该文件。通常BCB6.0缺省定义下项目文件包含如下代码:第第3 3章章 应用程序界面设计应用程序界面设计 #include#pragmahdrstop/-USEFORM(Unit
49、1.cpp,Form1);/-WINAPIWinMain(HINSTANCE,HINSTANCE,LPSTR,int)tryApplication-Initialize();第第3 3章章 应用程序界面设计应用程序界面设计 Application-CreateForm(_classid(TForm1),&Form1);Application-Run();catch(Exception&exception)Application-ShowException(&exception);catch(.)trythrowException();第第3 3章章 应用程序界面设计应用程序界面设计 catch
50、(Exception&exception)Application-ShowException(&exception);return0;/-第第3 3章章 应用程序界面设计应用程序界面设计 一般情况下初学者不需要修改该文件的代码。应用程序项目通常还含有若干窗体,每个窗体由三个文件组成,它们分别是扩展名为.cpp的源文件、扩展名为.h的头文件和扩展名为.dfm的窗体定义文件。在BCB5.0以前版本中,通常要按Ctrl+F6键才能将对应某个.cpp文件的头文件在代码编辑器中打开。而BCB6.0只要在代码编辑器中选择某个.cpp文件,此时编辑器窗口的底部就会出现相应头文件的标签,点击该标签就能打开它。
51、第第3 3章章 应用程序界面设计应用程序界面设计 一个项目可以有多个窗体,但其中只有一个是主窗体(通常是Form1)。主窗体构成程序的主控界面。每次启动时,BCB自动生成含有一个空的主窗体的项目框架。用户在设计中将各种组件放入该窗体,并编写若干事件代码。如果要编写多窗体应用程序,那么从第二个窗体开始,必须由用户在项目中进行添加。可以 执 行 FileNewForm菜 单 命 令 或 者 使 用 “NewForm”工具按钮为当前项目添加一个新窗体。注意:当我们需要建立一个新项目时,应首先执行FileCloseAll关闭当前项目,然后再执行FileNewApplication菜单命令。第第3 3章
52、章 应用程序界面设计应用程序界面设计 有些类型的项目如DLL是不包含任何窗体的,它们一般要由专门的向导生成,读者可参考本书提高篇9.5节。也可以将几个项目结合起来建立更复杂的应用。BCB支持项目组(Project Group)的概念,可以执行ViewProjectManager菜单命令进入项目管理器窗口对项目组进行管理。第第3 3章章 应用程序界面设计应用程序界面设计 3.4.2窗体之间的关系在多窗体应用程序中窗体之间可以有两种常见的关系:主从关系和父子关系。C+Builder创建的窗体中,Form1一般是主窗体,它在程序中具有较重要的地位,如Form1被关闭时,程序通常也就结束了。其它窗体与
53、Form1的关系往往就是主从关系,如Form2可能是Form1在某项操作时需要的一个对话框等。一般,可在主窗体中调用从属窗体的Show、Hide和Close等方法控制它们的显示、隐藏和关闭等。第第3 3章章 应用程序界面设计应用程序界面设计 窗口的父子关系则是Windows中的概念:子窗口可以从父窗口那里继承到一些特性,但只能在父窗口客户区范围内显示或移动。此外,当父窗口关闭时,所有子窗口会自动被关闭。子窗口必定是从属于父窗口的,但一般在窗口的主从关系中,从属的一方不一定是子窗口。如BCBIDE的ObjectInspector和代码编辑器都是从属于主窗口的,但不是子窗口(它们可以在主窗口之外移
54、动)。在BCB程序中,当需要指定一个子窗口时,可以在相关的代码中将子窗口的Parent属性设置成它的父窗口(例如Form2-Parent=Form1)。第第3 3章章 应用程序界面设计应用程序界面设计 3.4.3菜单的合并在多窗体应用程序中,从属于主窗体的窗口(不管它是否为子窗口)上如果有菜单,通常会将其与主窗体上的菜单合并。在BCB中要做到这一点很容易,只要适当设置菜单的AutoMerge和GroupIndex属性即可。下面给出一个例子。第第3 3章章 应用程序界面设计应用程序界面设计 【例3-5】应用程序主窗体Form1有如下菜单系统:主菜单上有三项,分别为“File”、“Windows”
55、和“Help”。“File”下 拉 菜 单 中 有 “New”、 “Open”、“Save”和“Exit”四项;“Windows”下拉菜单中有“ShowForm2”和“HideForm2”两项;“Help”没有下拉菜单。选“Exit”可退出程序,选“ShowForm2”或“HideForm2”则分别显示或隐藏Form2。Form2上也有一个主菜单,它只有一个下拉菜单“Edit”。该下拉菜单上有“Copy”和“Paste”两项。第第3 3章章 应用程序界面设计应用程序界面设计 要 求 程 序 开 始 时 , Form2不 显 示 。 选 “ShowForm2”时,Form2显示并将“Edit”菜
56、单合并到Form1的菜单上。制作步骤(1)在窗体Form1上放一个主菜单MainMenu1,在MenuDesigner中设计主菜单。注意,MainMenu1的AutoMerge应设为false,“File”、“Windows”、“Help”三项的GroupIndex可分别设置为1、3、5。第第3 3章章 应用程序界面设计应用程序界面设计 (2)选取FileNewForm菜单命令,在项目中加入Form2。在Form2中加入主菜单,将AutoMerge设置为true,“Edit”下拉菜单的GroupIndex可设为4。(3)在Unit1.cpp中加入#includeUnit2.h语句。(4)对Fo
57、rm1的“Exit”、“ShowForm2”和“HideForm2”的OnClick事件编写如下的代码:void_fastcallTForm1:Exit1Click(TObject*Sender)Form1-Close();/-第第3 3章章 应用程序界面设计应用程序界面设计 void_fastcallTForm1:ShowForm21Click(TObject*Sender)Form2-Show();/-void_fastcallTForm1:HideForm21Click(TObject*Sender)Form2-Hide();/-第第3 3章章 应用程序界面设计应用程序界面设计 该程序运
58、行时初始画面如图3-22所示,点击“ShowForm2”菜单后的画面如图3-23所示。注意,其中的菜单已被合并,合并后各下拉菜单的顺序是按照GroupIndex从小到大排列的。第第3 3章章 应用程序界面设计应用程序界面设计 图3-22Form2未显示时第第3 3章章 应用程序界面设计应用程序界面设计 图3-23Form2显示时菜单被合并第第3 3章章 应用程序界面设计应用程序界面设计 我们可以进一步对AutoMerge及GroupIndex做一点试验:将Form2的AutoMerge改为false后运行的画面如图3-24所示,我们看到Form2的菜单未合并。将Form2中“Edit1”的Gr
59、oupIndex改为6后运行的画面如图3-25所示,我们看到,合并后“Edit”下拉菜单的位置在“Help”之后(“Help”的GroupIndex为5)。有趣的是,若“Edit”的GroupIndex设置为1,则在合并时会用“Edit”覆盖具有同一GroupIndex的“File”项。第第3 3章章 应用程序界面设计应用程序界面设计 图3-24菜单未合并第第3 3章章 应用程序界面设计应用程序界面设计 图3-25合并后Edit项位于末尾第第3 3章章 应用程序界面设计应用程序界面设计 3.4.4设计多页窗体多页窗体,也可称作属性对话框,是一种较新颖的图形界面。它使用某些控件,将窗体分成若干个
60、页面,用户可单击页标签在不同的页面间切换。这种界面的一个明显好处是扩大了窗体的客户区,使其能排列大量的控件,也便于区分对话框的不同功能区域。BCB提供了几种用于建立多页窗体的控件,它们是TTabControl、TPageControl和TNotebook等,它们都位于Win32组件页上,并且在用法上大同小异。下面我们简单介绍一下PageControl的用法。第第3 3章章 应用程序界面设计应用程序界面设计 TPageControl也被称作页框,它是一种容器类型,它包含的控件为页面(TabSheet)。TPageControl的常用属性有ActivePage、PageCount、Pages、Al
61、ign、TabPosition等。前两个属性分别代表当前页和页面总数。Pages是以TabSheet为元素的数组。Align用法与在其它控件中类似。TabPosition可取之值为tpTop、tpBottom、tpLeft和tpRight,分别表示页标签显示在页面的顶部、底部、左方和右方。第第3 3章章 应用程序界面设计应用程序界面设计 当一个PageControl刚放入窗体中时,框内是空的。右击该PageControl控件,在弹出的快捷菜单上点击“NewPage”项,页框内即增加了一页。点击快捷菜单上“DeletePage”或按Delete键可删除一个页。新建页的 Caption属 性 缺
62、省 名 称 为 “TabSheet1”、“TabSheet2”等,用户可以对其修改。当完成了PageControl及其页面设置后,就能往各个页面上放置控件。这与往窗体上放置控件是一样的。第第3 3章章 应用程序界面设计应用程序界面设计 3.4.5MDI程序MDI(MultipleDocumentInterface,多文档接口)是Windows应用程序的一种规范。就如同Windows在桌面窗口中维护多个应用程序窗口一样,MDI应用程序在它的客户区中维护多个文档窗口。MicroSoft的Word97是标准的MDI应用程序,但Word2000在默认设置下不是一个MDI应用程序。通常情况下,MDI可分
63、为父窗口和子窗口。父窗口也是程序的主窗口,它可以包含若干个子窗口。MDI还必须符合以下若干规范:第第3 3章章 应用程序界面设计应用程序界面设计 (1)MDI的父窗口通常包含主菜单和缩放边框。通常情况下,它的客户区不显示任何输出,而是用于在其中放置若干个处理文档的子窗口。这些子窗口看上去与普通的应用程序窗口非常相似,但是,子窗口没有菜单,必须使用父窗口上的菜单操作子窗口内的文档。或者说,MDI子窗口的菜单总是合并到父窗口的菜单上。(2)MDI程序运行时,主程序客户区内可打开多个子窗口,但只能有一个子窗口是活动的。子窗口被最小化时,会以图标形式显示在主窗口的底部。第第3 3章章 应用程序界面设计
64、应用程序界面设计 (3)主菜单通常包含“File”下拉菜单,该下拉菜单中有“New”、“Open”、“Save”和“Close”等基本的文档操作功能。(4)主菜单中通常还有一个“Windows”下拉菜单,该下拉菜单一般能对子窗口进行“平铺”和“层叠”等操作。BCB对MDI程序提供了很好的支持,我们可以直接编程或使用向导来建立MDI程序。第第3 3章章 应用程序界面设计应用程序界面设计 以下是TForm类所拥有的若干与MDI有关的属性和方法:(1)ActiveMDIChild属性代表当前处于活动状态的子窗口,它是TForm类型的。(2)MDIChildCount属性表示父窗口当前所拥有的MDI子
65、窗口数量。(3)MDIChildren属性是TForm的一个数组,它的每一个元素是一个MDI子窗口。(4)Tile和Cascade这两个方法分别用于在主窗体的客户区内“平铺”和“层叠”MDI子窗口。(5)Previous和Next这两个方法分别用于按顺序激活当前MDI子窗口的前一或后一个窗口。第第3 3章章 应用程序界面设计应用程序界面设计 下面是在BCB中创建MDI程序的要点。1创建主窗口主窗体Form1作为MDI的主窗口必须设置FormStyle属性为fsMDIForm。为了进行文件操作,一般还要在Form1中放入TOpenDialog和TSaveDialog等组件。2创建子窗口选择Fil
66、eNewForm创建一个子窗口Form2。严格地说,这只是为子窗口建立一个窗口类TForm2,子窗口对象的实例要在程序运行时动态地创建。Form2的FormStyle属性应设置为fsMDIChild,根据文档处理的需要可在Form2中加入其它的组件。第第3 3章章 应用程序界面设计应用程序界面设计 根据MDI程序的特点,我们还要在BCB的“Project”菜单中选择“Options”对话窗口进行相关的设置,使BCB不会自动创建Form2。第第3 3章章 应用程序界面设计应用程序界面设计 3编写事件处理代码MDI程 序 中 通 常 要 为 “New”、 “Open”、“Save”、“Copy”和
67、“Paste”等菜单项编写事件代码,具体与MDI处理子窗口中文档的方式有关,读者可参考本节中的范例。一般地,由于无法事先预料需建立的MDI子窗口的个数,MDI采用动态方式在“New”操作时创建子窗口,因此当关闭子窗口时必须释放内存。所以,通常要在Form2的OnClose事件中加入“Action=caFree;”语句。第第3 3章章 应用程序界面设计应用程序界面设计 下面,我们给出一个MDI应用程序范例。【例3-6】Form1为主窗体,主菜单上有“File”、“Edit”和“Windows”三个下拉菜单,其中“File”下 拉 菜 单 中 有 “New”、 “Open”、 “Save”、“Cl
68、ose”和“Exit”五项;“Edit”下拉菜单中有“Copy”和“Paste”两项;“Windows”下拉菜单中有“Tile”和“Cascade”两项。Form2为MDI子窗口的类型。上面放入一个Memo控件,使子窗口能处理文本文件。第第3 3章章 应用程序界面设计应用程序界面设计 要求:程序开始时,主窗体客户区内没有子窗口。选择“New”时打开一个空的子窗口,它的文件名为“UnTitled”(未命名)。选择“Open”时,弹出打开文件对话框,在选中一个文本文件后,打开一个子窗口处理该文件。选择“Save”时将当前文件存盘。若当前文件未命名,则先弹出保存文件对话框供用户输入文件名后再存盘。选
69、择“Close”时关闭当前子窗口。选择“Exit”结束程序。“Copy”和“Paste”提供剪贴板操作。“Tile”和“Cascade”将MDI子窗口在主窗体客户区内“平铺”和“层叠”。第第3 3章章 应用程序界面设计应用程序界面设计 所有的子窗口按其打开的顺序编号,并在子窗口标题上显示。制作步骤(1)对主窗体Form1设置FormStyle属性为fsMDIForm,并放入TOpenDialog和TSave-Dialog对话框组件各一个。(2)在项目中加入Form2。它的FormStyle属性设置为fsMDIChild。在Form2中加入一个TMemo控件,并使它的Align属性为alClie
70、nt,Lines属性为空。第第3 3章章 应用程序界面设计应用程序界面设计 (3)在Unit1.cpp中加入#includeUnit2.h语句。(4) 在代码编辑器内切换到Unit2.h头文件。在TForm2类 声 明 的 public段 内 加 入 “AnsiStringFileName;”语句。(5)选择“Project”菜单上的Options项,打开项目设置对话框,如图3-26所示,选择“Forms”页。在“Autocreateforms”框内选中Form2,点击“”按钮,将Form2从“Autocreateforms”框移到“Availableforms”框内,使程序开始时不创建For
71、m2。第第3 3章章 应用程序界面设计应用程序界面设计 图3-26项目设置对话框第第3 3章章 应用程序界面设计应用程序界面设计 (6) 为Form1菜单上各个项的OnClick事件以及Form2的OnClose事件编写代码。/文件Unit1.cpp-#includeUnit1.h#includeUnit2.h/-void_fastcallTForm1:Tile1Click(TObject*Sender)Form1-Tile();/调用主窗体Tile方法平铺窗口第第3 3章章 应用程序界面设计应用程序界面设计 /-void_fastcallTForm1:Cascade1Click(TObjec
72、t*Sender)Form1-Cascade();/调用主窗体Cascade方法层叠窗口/-void_fastcallTForm1:New1Click(TObject*Sender)第第3 3章章 应用程序界面设计应用程序界面设计 TForm2*ChildForm;ChildForm=newTForm2(this);/创建新窗体ChildForm-Caption=子窗体+IntToStr(MDIChildCount);/窗体标题给以编号ChildForm-FileName=UnTitled;/相应文件未命名ChildForm-Show();/-void_fastcallTForm1:Open1
73、Click(TObject*Sender)第第3 3章章 应用程序界面设计应用程序界面设计 if(OpenDialog1-Execute()TForm2*ChildForm;ChildForm=newTForm2(this);ChildForm-Caption=子窗体+IntToStr(MDIChildCount);ChildForm-FileName=OpenDialog1-FileName;ChildForm-Memo1-Lines-LoadFromFile(OpenDialog1-FileName);ChildForm-Show();/将打开的文件放入新建窗体内并显示第第3 3章章 应用
74、程序界面设计应用程序界面设计 /-void_fastcallTForm1:Close1Click(TObject*Sender)if(MDIChildCount0)ActiveMDIChild-Close();/关闭当前子窗体/-void_fastcallTForm1:Save1Click(TObject*Sender)TForm2*ChildForm;ChildForm=(TForm2*)ActiveMDIChild;/强制类型转换第第3 3章章 应用程序界面设计应用程序界面设计 if(ChildForm-FileName=UnTitled)/文档尚未命名则打开保存文件对话框if(SaveD
75、ialog1-Execute()ChildForm-Memo1-Lines-SaveToFile(SaveDialog1-FileName);elseChildForm-Memo1-Lines-SaveToFile(ChildForm-FileName);/保存文件/-void_fastcallTForm1:Exit1Click(TObject*Sender)第第3 3章章 应用程序界面设计应用程序界面设计 Form1-Close();/-void_fastcallTForm1:Copy1Click(TObject*Sender)TForm2*ChildForm;ChildForm=(TFor
76、m2*)ActiveMDIChild;ChildForm-Memo1-CopyToClipboard();/将被选文本放入剪贴板/-第第3 3章章 应用程序界面设计应用程序界面设计 void_fastcallTForm1:Paste1Click(TObject*Sender)TForm2*ChildForm;ChildForm=(TForm2*)ActiveMDIChild;ChildForm-Memo1-PasteFromClipboard();/从剪贴板粘贴内容/文件Unit2.cpp-/-void_fastcall TForm2:FormClose (TObject *Sender, T
77、CloseAction&Action)第第3 3章章 应用程序界面设计应用程序界面设计 Action=caFree;/使关闭窗体时释放内存/文件Unit2.h-classTForm2:publicTFormpublic:/Userdeclarations_fastcallTForm2(TComponent*Owner);/添加数据成员,用于记录子窗口内的文件名AnsiStringFileName;图3-27图3-30给出本例运行时的若干画面。第第3 3章章 应用程序界面设计应用程序界面设计 图3-27初始时客户区没有子窗体第第3 3章章 应用程序界面设计应用程序界面设计 图3-28打开了两个子
78、窗体第第3 3章章 应用程序界面设计应用程序界面设计 图3-29平铺六个子窗体第第3 3章章 应用程序界面设计应用程序界面设计 图3-30层叠四个子窗体第第3 3章章 应用程序界面设计应用程序界面设计 3.5 拖拖 放放 技技 术术拖放是鼠标操作的基本动作之一,在Windows应用程序的界面设计中起着重要的作用。在BCB中,可以使用组件的有关属性和事件对拖放操作进行控制。在Windows下,窗口可以在桌面上拖放,控件则可以在窗口内或窗口间拖放,它们的基本原理是一致的。BCB可视组件通常有一个DragMode属性用于控制其是否能被拖动,该属性为dmManual时组件不能直接拖动,为dmAutom
79、atic时则可以拖动,缺省值为dmManual。第第3 3章章 应用程序界面设计应用程序界面设计 拖放操作可以被分解为“拖动”和“释放”两个基本动作。与拖放有关的事件有OnDrag-Drop、OnDragOver、OnStartDrag、ONEndDrag、OnStartDock、ONEndDock等,但也有些控件只有其中的前两个事件。注意:OnDragDrop和OnDragOver事件不属于被“拖”的组件,而是属于接受其“放”的那个组件或容器。例如,Edit1编辑框在Form1窗体内被拖放,则应处理Form1的OnDragDrop和OnDragOver事件。第第3 3章章 应用程序界面设计应
80、用程序界面设计 OnDragOver用于控制外来组件是否允许被拖入,一般只要写上“Accept=true;”表示允许被拖入(这里Accept是方法参数)。在较复杂的情况下,则应根据被拖动对象的类型或某些条件确定是否允许其被拖入。当Accept为false时不接受(不会发生)OnDragDrop事件。OnDragDrop事件中的代码确定当某组件被拖入并释放时应如何响应,通常这是需要我们处理的主要事件。在处理该事件时,往往需要对被拖入的对象进行识别。第第3 3章章 应用程序界面设计应用程序界面设计 OnStartDrag用于组件开始被拖动时的处理,ONEndDrag则用于组件拖动结束时(即释放之前
81、的瞬间)的处理。在特殊情况下,如果使用这几个事件还不能对拖放操作进行有效的控制,那么可直接处理鼠标的OnMouseDown、OnMouseMove和OnMouseUp事件,读者可参考本书应用篇4.3.2节。在拖放时我们还可以通过设置Cursor属性改变鼠标的光标形状。第第3 3章章 应用程序界面设计应用程序界面设计 3.5.1简单拖放我们从实现最简单的拖放开始,首先介绍一个拖放标签组件的范例。【例3-7】建立一个应用程序项目,在Form1中放入四个标签:Label1、Label2、Label3和Label4。Label1、Label2和Label3在程序中可以被拖放,因此它们的DragMode
82、属性都应设置为dmAutomatic。此外,要将它们的Color属性分别设置为clRed、clBlue和clYellow,并且相应地,将Caption属性分别设置为“Red”、“Blue”和“Yellow”。第第3 3章章 应用程序界面设计应用程序界面设计 Label4在程序中的作用是接受拖放,我们将它的Caption清空,AutoSize设置为false,Color设置为clWhite。各组件在窗体中的布局如图3-31所示。第第3 3章章 应用程序界面设计应用程序界面设计 图3-31范例3-7在设计时的界面第第3 3章章 应用程序界面设计应用程序界面设计 程序中需要处理Label4的OnDr
83、agOver、OnDragDrop和OnClick事件,下面是有关的事件代码:void_fastcallTForm1:Label4DragOver(TObject*Sender,TObject*Source,intX,intY,TDragStateState,bool&Accept)Accept=true;/-第第3 3章章 应用程序界面设计应用程序界面设计 void_fastcallTForm1:Label4DragDrop(TObject*Sender,TObject*Source,intX,intY)Label4-Color=(TLabel*)Source)-Color;(TLabel*
84、)Source)-Visible=false;/-void_fastcallTForm1:Label4Click(TObject*Sender)第第3 3章章 应用程序界面设计应用程序界面设计 Label1-Visible=true;Label2-Visible=true;Label3-Visible=true;Label4-Color=clWhite;程序运行时,Label1、Label2和Label3可被拖入Label4,当Label1拖入到Label4时,Label4的颜色会变成红色,相应地,拖入Label2或Label3会使Label4变成蓝或黄色。若点击Label4,则使程序还原。第
85、第3 3章章 应用程序界面设计应用程序界面设计 【评析】(1)Label4的OnDragOver事件执行“Accept=true;”语句,使任何组件都能拖入Label4。从函数声明部分可看出Accept是可以返回给系统的bool型变量。(2)Label4的OnDragDrop事件执行了两个语句。语 句 “Label4-Color=(TLabel*) Source)-Color;”使Label4的颜色与被拖入的Label对象的颜色相同。其中的Source参数代表“源”,即被拖入的对象。第第3 3章章 应用程序界面设计应用程序界面设计 但从函数声明中看到Source是TObject*类型的(由于系
86、统不能预先知道哪些对象可能被拖入,所以只能用最宽泛的VCL类型TObject),因此要用(TLabel*)实行强制类型转换后才能访问其Color属性。语句“(TLabel*)Source)-Visible=false;”使被拖入的Label对象不可见,给人的感觉是它们被拖入到Label4中去了。第第3 3章章 应用程序界面设计应用程序界面设计 (3)有时候,拖放的目的只是为了在窗体上移动组件的位置,在这种情况下,我们只需要处理窗体的OnDragOver和OnDragDrop事件。在OnDragOver中写入“Accept=true;”语句,并在OnDragDrop中将被拖放对象的Top和Lef
87、t属性设置为X和Y。例如:(TLabel*)Source)-Left=X;(TLabel*)Source)-Top=Y;从函数的声明部分可以看到X和Y是由系统传入的整型变量,代表对象被放下时的鼠标位置。我们要介绍的下一个范例要稍微复杂一点,它可以把一个列表框中的项目拖进另一个列表框。第第3 3章章 应用程序界面设计应用程序界面设计 【例3-8】建立一个应用程序项目,在Form1中放入两个列表框组件。将它们的DragMode属性都设置为dmAutomatic,它们的Items属性可分别初始化为若干行简单文本,并分别编写两个列表框的OnDragOver和OnDragDrop事件的代码。其事件的代码
88、如下:void_fastcallTForm1:ListBox1DragOver(TObject*Sender,TObject*Source,intX,intY,TDragStateState,bool&Accept)第第3 3章章 应用程序界面设计应用程序界面设计 Accept=true;/-void_fastcallTForm1:ListBox2DragOver(TObject*Sender,TObject*Source,intX,intY,TDragStateState,bool&Accept)Accept=true;/-第第3 3章章 应用程序界面设计应用程序界面设计 void_fast
89、callTForm1:ListBox1DragDrop(TObject*Sender,TObject*Source,intX,intY)AnsiStrings1;s1=ListBox2-Items-StringsListBox2-ItemIndex;ListBox2-Items-Delete(ListBox2-ItemIndex);ListBox1-Items-Add(s1);/-第第3 3章章 应用程序界面设计应用程序界面设计 void_fastcallTForm1:ListBox2DragDrop(TObject*Sender,TObject*Source,intX,intY)AnsiSt
90、rings1;s1=ListBox1-Items-StringsListBox1-ItemIndex;ListBox1-Items-Delete(ListBox1-ItemIndex);ListBox2-Items-Add(s1);第第3 3章章 应用程序界面设计应用程序界面设计 程序运行时,我们可以在两个列表框之间将选中的内容从一个框拖放到另一个框中,如图3-32所示。第第3 3章章 应用程序界面设计应用程序界面设计 图3-32在两个列表框间拖放内容第第3 3章章 应用程序界面设计应用程序界面设计 在ListBox1的OnDragDrop事件的处理中,下面两句ListBox2-Items-D
91、elete(ListBox2-ItemIndex);ListBox1-Items-Add(s1);分别在ListBox2中删去一行并在ListBox1中添加一个同样内容的新行,而看上去则好像是将ListBox2的一个行拖入到ListBox1中。第第3 3章章 应用程序界面设计应用程序界面设计 3.5.2窗体间拖放在前面的例子中,拖放是在同一个窗体中进行的,下面的一个例子展示如何将组件从一个窗体拖进另一个窗体。【例3-9】类似范例3-7,在主窗体Form1中放入红、蓝、黄三个标签,将它们的DragMode属性都设置为dmAutomatic。在项目中增加一个窗体Form2,并在Unit1.h中加入
92、语句“#includeUnit2.h;”。下面是本例中需要编写的事件代码,这些代码分别位于Unit1.cpp和Unit2.cpp两个文件内。第第3 3章章 应用程序界面设计应用程序界面设计 /文件Unit1.cpp/-void_fastcallTForm1:FormDragOver(TObject*Sender,TObject*Source,intX,intY,TDragStateState,bool&Accept)Accept=true;/-第第3 3章章 应用程序界面设计应用程序界面设计 void _fastcall TForm1:FormDragDrop (TObject *Sender
93、, TObject*Source,intX,intY)TLabel*L1;L1=(TLabel*)Source;L1-Parent=Form1;L1-Left=X;L1-Top=Y;/-第第3 3章章 应用程序界面设计应用程序界面设计 /文件Unit2.cpp/-void_fastcallTForm2:FormCreate(TObject*Sender)Show();/-第第3 3章章 应用程序界面设计应用程序界面设计 void _fastcall TForm2:FormDragOver (TObject *Sender, TObject*Source,intX,intY,TDragState
94、State,bool&Accept)Accept=true;/-void _fastcall TForm2:FormDragDrop (TObject *Sender, TObject*Source,intX,intY)第第3 3章章 应用程序界面设计应用程序界面设计 TLabel*L1;L1=(TLabel*)Source;L1-Parent=Form2;L1-Left=X;L1-Top=Y;图3-33为执行本范例程序时,“Red”组件被拖入到Form2中。第第3 3章章 应用程序界面设计应用程序界面设计 图3-33在窗体间拖放组件第第3 3章章 应用程序界面设计应用程序界面设计 【评析】(
95、1)本例中三个TLabel组件要在两个窗体之间拖来拖去,所以要分别对Form1和Form2编写OnDragOver和OnDragDrop事件。(2)为了使TLabel组件从一个窗体进入另一个窗体,我们改变了它们的Parent属性。我们知道窗体可以看作是一个容器,组件的Parent属性表明它是属于哪一个容器的。另一种方法是类似范例3-8的做法,在一个窗体中删除对象并在另一个窗体中新建一个同样的对象。第第3 3章章 应用程序界面设计应用程序界面设计 3.6 窗窗 体体 的的 分分 割割窗体分割是非常实用的技术,它使用可以移动的分割条将一个窗体分割成几个区域,用户可以随意地调整这几个区域的大小。例如
96、,Windows的“资源管理器”窗体就是被分割成左右两个区域的,左面区域用于显示目录树,右面区域则显示文件或子目录。第第3 3章章 应用程序界面设计应用程序界面设计 在BCB中可以使用位于Additional页上的Splitter组件作为分割条。该组件的常用属性有AutoSnap、Beveled、MinSize、ResizeStyle、Align等,常用的事件有OnCanResize、OnMoved等。其中,Align用于定位;Beveled和ResizeStyle与外观有关;MinSize指定一个最小值(必须大于“0”,单位是像素)以避免某一区域在分割后宽度或高度小于该值。Splitter通
97、常与Panel等控件配合使用,每个Panel或控件可形成一个区域,Panel之间用Splitter进行分割。适当设置Align等属性可使窗体实现水平分割或垂直分割,还可以将这两种分割组合。第第3 3章章 应用程序界面设计应用程序界面设计 图3-34垂直分割窗体第第3 3章章 应用程序界面设计应用程序界面设计 【例3-10】建立一个应用程序项目,在Form1窗体内放入三个TListBox组件和两个TSplitter组件。请按下述次序依此排列组件:首先放入ListBox1,将其Align设为alLeft;接下来放入Splitter1,设置其Align为alLeft,AutoSnap为false;再
98、放入ListBox2,设置其Align为alLeft;然后放入Splitter2,设置其Align为alLeft,AutoSnap为false;最后放入ListBox3,设置其Align为alClient。该简单分割窗体程序不需要编写代码即可运行,图3-34为该程序运行时的画面。第第3 3章章 应用程序界面设计应用程序界面设计 【例3-11】建立一个应用程序项目,在Form1窗体内放入一个Memo、两个ListBox、三个Splitter和一个Panel组件,还要在Panel1上放两个按钮。请按以下次序操作:首先放入Memo1,它的Align属性设为alTop;接下来放入Splitter1,设
99、置其Align为alTop;再放入ListBox1,设置其Align为alLeft;然后放入Splitter2,设置其Align为alLeft;再放入ListBox2,设置其Align为alLeft;然后放入Splitter3,设置其Align为alLeft;最后放入Panel1,设置其Align为alClient,清空其Caption,并在上面放两个按钮。第第3 3章章 应用程序界面设计应用程序界面设计 图3-35复杂分割窗体分割方式一第第3 3章章 应用程序界面设计应用程序界面设计 图3-36复杂分割窗体分割方式二第第3 3章章 应用程序界面设计应用程序界面设计 习习 题题1.试按如下要求
100、设计BCB程序。程序使用两个窗体,主窗体Form1上有如图3-37所示菜单。Form2有如图3-38所示菜单。第第3 3章章 应用程序界面设计应用程序界面设计 图3-37习题1-1图第第3 3章章 应用程序界面设计应用程序界面设计 图3-38习题1-2图第第3 3章章 应用程序界面设计应用程序界面设计 图3-39习题2图第第3 3章章 应用程序界面设计应用程序界面设计 要求:程序开始时Form2 不显示,执行“ShowForm2”菜单命令使Form2显示。此时Form2的菜单Windows合并到Form1菜单的Edit和Help两项之间。执行“Close”时关闭Form2。执行“Exit”则关
101、闭Form1并退出程序。此外,要为“ShowForm2”定义快捷键为Alt+F。第第3 3章章 应用程序界面设计应用程序界面设计 2.试按如下要求设计具有两个窗体的Windows应用程序,它们具有父子窗体的关系。父窗体Form1上有如图3-39所示菜单。初始时Form2应处于关闭状态。执行“OpenForm2”菜单命令时打开(显示)子窗体Form2;执行“CloseForm2”时关闭Form2;执行“Minimized”则使Form2窗口最小化。当Form2处于关闭状态时,应使“OpenForm2”项可用,而“CloseForm2”和“Minimized”项为不可用(灰显)。当Form2处于打
102、开状态时,则应使“OpenForm2”项不可用,而“CloseForm2”和“Minimized”项可用。第第3 3章章 应用程序界面设计应用程序界面设计 执行“Color”菜单命令时会打开一个设置颜色的对话框,在该对话框内选中的颜色被作为子窗体Form2的背景色。执行“Exit”菜单命令则结束程序。提示:为了使某个窗体最小化,可设置该窗体的WindowState属性为wsMinimized。第第3 3章章 应用程序界面设计应用程序界面设计 3.应用程序主窗体中放入一个备注框Memo1用于文本输入,程序的主菜单上有“File”和“Options”两个下拉菜单项。“File”下拉菜单项内有“Op
103、en”、“SaveAs”和“Exit”三项。“Options”下拉菜单项内有“Font”和“Color”两项。为菜单项“Open”、“SaveAs”、“Exit”、“Font”、“Color”分别设置快捷键“Ctrl+O”、“Ctrl+S”、“Ctrl+E”、“Ctrl+F”、“Ctrl+C”。第第3 3章章 应用程序界面设计应用程序界面设计 执行“Open”菜单命令时弹出打开文件对话框,在该对话框内选中一个文本文件后,在Memo1中将其打开。执行“SaveAs”菜单命令时弹出保存文件对话框,在该对话框中输入文件名或选中一个文件后,将Memo1中编辑的文本保存到该文件。执行“Font”或“Co
104、lor”菜单命令时可分别弹出字体设置或颜色设置对话框,在该对话框中选择的字体或颜色被用于Memo1文本框的字体及背景颜色。执行“Exit”菜单命令退出程序。再为该程序加一个有五个SpeedButton的工具栏,这 些 按 钮 的 功 能 分 别 对 应 “Open”、 “Save As”、“Exit”、“Font”、“Color”菜单项。第第3 3章章 应用程序界面设计应用程序界面设计 4.在应用程序主窗体上放一个面板Panel1,将其定位在窗体顶部当作工具栏,再在该窗体底部加上一个StatusBar控件作为状态栏。往Panel1面板上加入三个SpeedButton,给它们分别设置提示信息(H
105、int)为:“Clear”、“Color”、“Quit”,并配上合适的按钮图标。在程序中设置一个整型的全局变量作为计数器,初始值为0。每次用鼠标点击程序窗体时,计数器加1。将窗口底部的状态栏分隔为左右两部分。左边用于显示上述计数器的当前值,右边用于显示最近一次点击时鼠标指针位置的坐标。例如,X=100,Y=80可显示为(100,80)。第第3 3章章 应用程序界面设计应用程序界面设计 点击“Clear”按钮时计数器被清“0”。点击“Color”按钮时打开一个设置颜色对话框,在该对话框内选择窗体的背景色。点击“Quit”按钮退出程序。第第3 3章章 应用程序界面设计应用程序界面设计 7.类似例3
106、-9,在窗体中放入两个可以多选的列表框并且支持拖放,即一次可以将多个被选中的项目从一个列表框拖到另一个列表框。8.窗体中放三个备注框以及两个分割条,试适当设置这些控件以实现对窗体的水平分割。第第3 3章章 应用程序界面设计应用程序界面设计 5.设计一个检查密码的程序,它有两个窗体。Form1用于检查密码,Form2窗体上只有一个“欢迎”标签和一个“退出”按钮。假定密码是固定的,用户若连续三次输入错误则程序被中止。以下是一些具体要求:第第3 3章章 应用程序界面设计应用程序界面设计 Form1上有两个编辑框用于输入用户的姓名和密码,再用两个标签分别说明这两个编辑框。输入密码时,编辑框应显示“*”
107、以隐藏输入的内容。窗体上还有一个“确认”按钮。程序内置密码为“abcd”,不区分大小写。当用户输入了姓名和密码并按下“确认”按钮后,若密码输入正确,则显示Form2并隐藏Form1;若输入密码错误,则弹出一个信息框显示“密码输入错误,请再试”,并对输入次数进行计数;当连续三次输入错误时关闭Form1,并退出程序。第第3 3章章 应用程序界面设计应用程序界面设计 Form1窗体底部还有一个分成左右两格的状态栏,左面一个显示输错的次数(可显示为“您已经X次输入密码错误”),右边一个显示系统时间。Form2的“退出”按钮被点击时,不仅关闭Form2,而且要使整个程序结束运行。第第3 3章章 应用程序界面设计应用程序界面设计 6.在窗体上放四个标签,将Label1、Label2和Label3三个标签分别标上“100元”、“10元”和“1元”。Label4放在窗口底部并有固定的尺寸,但初始时标签被清空。程序运行时,Label1、Label2和Label3都能被拖放到Label4。每次拖放后,Label4标签显示为“收到捐款XXXX元,谢谢!”,其中具体数字XXXX应根据被拖放的标签所对应的金额数进行累加而得。要求Label1、Label2和Label3标签都可以反复多次被拖放,即每次拖放动作完成后该标签并不消失。