




版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
第十二章Win32环境程序设计这一章节可以说是本书精华之一,Win32程序设计算是比较复杂的部分,但是我们以最简单的叙述带领着大家进入Win32程序设计的殿堂,让你写出来的程序具有一定的水平以上。若能将本章与下一章的技巧灵活运用,更能让大家写出高阶的窗口程序。1第十二章Win32环境程序设计这一章节可以说是本书精华大纲12-1.档案总管的接口12-2.标头控制组件12-3.进度状态显示组件12-4.轨迹追踪列12-5.上下控制组件12-6.日期时间12-7.热键组件的使用(HotKey)12-8.常驻在SystemTray的程序本章习题2大纲12-1.档案总管的接口212-1.档案总管的接口提到Win32的程序设计,最重要的范例就是档案总管。整个档案总管都是使用Win32的接口来完成。而我们在这一章以及下一章,也都会围绕着档案总管来介绍大部分内容。下图中就是档案总管的接口,在这个接口里,主要组件有ListView、TreeView、Splitter、以及StatusBar这四种VCL组件,SplitterTreeViewListViewStatusBar312-1.档案总管的接口提到Win32的程序设计,最重要的12-1.档案总管的接口窗体检视组件(ListView)范例12-1在范例12-1,我们的接口相当简单,除了一个输入数据的接口外,就是一个ListView。除了提到这些可看见的VCL组件外,我们还有放入一个Popupmenu以及一个ImageList在这个范例中。Popupmenu主要是提供鼠标右键的功能选单,,而ImageList则是要提供一些Image给ListView使用。412-1.档案总管的接口窗体检视组件(ListView)412-1.档案总管的接口窗体检视组件(ListView)新增Column个数512-1.档案总管的接口窗体检视组件(ListView)512-1.档案总管的接口窗体检视组件(ListView)ViewStyle的不同大图示(vsIcon)小图示(vsSmallIcon)清单(List)详细列表(Report)612-1.档案总管的接口窗体检视组件(ListView)612-1.档案总管的接口窗体检视组件(ListView)范例12-1执行结果712-1.档案总管的接口窗体检视组件(ListView)712-1.档案总管的接口树状检视组件(TreeView)TreeView是目前档案总管中的重要组件之一,在档案总管中TreeView负责显示从桌面开始的所有树状结构。在这一小节里,我们将会利用三个范例让各位练习TreeView的各项使用实例。谈到Tree的使用,就必须谈到什么是『根节点』、『父节点』、『子节点』、以及『叶节点』。根节点就是我们所谓的『root』,他是在整个Tree的最上方,以档案总管来说,根节点就是『桌面』父节点就是这个节点的底下还有一个以上的节点子节点就是这个节点的上一层还有节点叶节点就代表这个节点已经是这支树的最后一个节点812-1.档案总管的接口树状检视组件(TreeView)812-1.档案总管的接口树状检视组件(TreeView)范例12-2:利用简单的程序来控制TreeView的各项动作。我们主要是使用静态的方式将一棵树建立起来。这棵树是利用BCB提供的接口去产生。912-1.档案总管的接口树状检视组件(TreeView)912-1.档案总管的接口树状检视组件(TreeView)范例12-2执行结果1012-1.档案总管的接口树状检视组件(TreeView)112-1.档案总管的接口树状检视组件(TreeView)范例12-3:在程序中建构一个静态的TreeView在范例12-3,我们也是静态产生Tree,但是这次我们不是从BCB的接口中产生,我们是从程序代码中产生。在范例12-3的接口中,全部都跟范例12-2一模一样。程序中,我们宣告了三个TreeNode(两个也可以),经由这三个TreeNode之间的相互关系,我们完成了整颗树的建立。在建树的程序代码方面并不难,比较特别的就是要回到上一层我们使用的是『parent=parentParent』这样的方法来取得上一层Node的内存地址。至于一开始我们有保留Root的地址这只是一个习惯,因为从BCB中也是可以判断哪个Node是Root,在范例12-3中这样做只是为了方便以及写程序者的习惯。1112-1.档案总管的接口树状检视组件(TreeView)112-1.档案总管的接口树状检视组件(TreeView)范例12-3:程序代码void__fastcallTForm1::FormCreate(TObject*Sender){TTreeNode*root,*parent,*son;root=TreeView1->Items->Add(NULL,"Root");root->ImageIndex=0;root->SelectedIndex=1;root->StateIndex=-1;parent=root;son=TreeView1->Items->AddChild(parent,"Parent1");son->ImageIndex=2;son->SelectedIndex=3;son->StateIndex=-1;parent=son;son=TreeView1->Items->AddChild(parent,"Son_1_1");son->ImageIndex=2;son->SelectedIndex=3;son->StateIndex=0;son=TreeView1->Items->AddChild(parent,"Son_1_2");son->ImageIndex=2;son->SelectedIndex=3;son->StateIndex=-1;parent=parent->Parent;son=TreeView1->Items->AddChild(parent,"Parent2");son->ImageIndex=2;son->SelectedIndex=3;son->StateIndex=-1;parent=son;son=TreeView1->Items->AddChild(parent,"Son_2_1");son->ImageIndex=2;son->SelectedIndex=3;son->StateIndex=-1;parent=son;son=TreeView1->Items->AddChild(parent,"Son_2_1_1");son->ImageIndex=2;son->SelectedIndex=3;son->StateIndex=1;parent=parent->Parent->Parent;son=TreeView1->Items->AddChild(parent,"Parent3");son->ImageIndex=2;son->SelectedIndex=3;son->StateIndex=-1;}1212-1.档案总管的接口树状检视组件(TreeView)v12-1.档案总管的接口树状检视组件(TreeView)范例12-4:在程序中建构一个TreeView,主要程序代码我们分成三个部分第一部份是动态新增所需要的变量宣告,这部分是宣告在main.cpp的上方,归类于全域变数第二部份就是有关新增/删除TreeNode部分的程序代码最后一部分就是一些琐碎的功能,这些程序代码包括了展开以及收合的功能,也有在StatusBar上面显示目前的状况,还有一个就是选择要不要显示Root。1312-1.档案总管的接口树状检视组件(TreeView)112-1.档案总管的接口树状检视组件(TreeView)范例12-4:程序代码宣告//宣告两个变量..用来存放RootAddress和Node的AddressTTreeNode*root=NULL;TTreeNode*node=NULL;1412-1.档案总管的接口树状检视组件(TreeView)/12-1.档案总管的接口树状检视组件(TreeView)范例12-4:程序代码动态新增Nodevoid__fastcallTForm1::N1Click(TObject*Sender){//新增一个Node,在新增的时候会自动判断是不是新增Root,在新增的时候利用InputQuery来当作输入接口AnsiStringBuf;if(root==NULL){//如果现在root还是NULL的话..表示要新增一个rootif(InputQuery("输入","请输入TreeNode的名称",Buf)){//使用InputQuery当作输入接口root=TreeView1->Items->AddChild(NULL,Buf);//将新增的Node加入到TreeView中root->ImageIndex=0;root->SelectedIndex=1;root->StateIndex=-1;//设定该Node的一些基本属性StatusBar1->SimpleText="新增Root节点";//在StatusBar显示目前的运作情况TreeView1->AlphaSort();//新增之后利用AlphaSort对整个Tree排序}}else{//新增一般的Node//必须得先选一个node才能继续产生Child,不然如果没有Parent那来的Childif(TreeView1->Selected!=NULL){//使用InputQuery当作输入接口if(InputQuery("输入","请输入TreeNode的名称",Buf)){//将新增的Node加入到TreeView中node=TreeView1->Items->AddChildFirst(TreeView1->Selected,Buf);node->ImageIndex=2;node->SelectedIndex=3;node->StateIndex=-1;//设定该Node的一些基本属性StatusBar1->SimpleText="新增一个Node";//在StatusBar显示目前的运作情况TreeView1->AlphaSort();//新增之后利用AlphaSort对整个Tree排序}}}}1512-1.档案总管的接口树状检视组件(TreeView)v12-1.档案总管的接口树状检视组件(TreeView)范例12-4:程序代码动态删除Nodevoid__fastcallTForm1::N2Click(TObject*Sender){if(TreeView1->Selected!=NULL){//如果有Node被选取..也选择要删除才执行if(TreeView1->Selected==root){//判断是不是RootTreeView1->Selected->Delete();root=NULL;//如果是root被删除..要将root的point设成nullStatusBar1->SimpleText="删除Root节点";}else{TreeView1->Selected->Delete();StatusBar1->SimpleText="删除一个Node";}}}1612-1.档案总管的接口树状检视组件(TreeView)v12-1.档案总管的接口树状检视组件(TreeView)SortAlphaSort:根据我们每个Node的Caption中的值去做排序CustomSort:让我们自己写函式去做排列SortTypestBoth:当Date或是Text有任何一种改变时就重新SortstDate:当Node的数据改变时就重新Sort一次stNone:永远不排序stText:当Node的Text改变时重新Sort1712-1.档案总管的接口树状检视组件(TreeView)112-1.档案总管的接口分隔组件(Splitter)分隔组件最主要的功能就是让两个组件在你拉动的时候自动分配组件的大小。例如在档案总管中,我们可以将光标停放在TreeView和ListView的中间,接着游标就会变成一个双箭头的光标,然后我们就可以按着鼠标的左键左右移动鼠标,这时候TreeView和ListView的窗口会随着鼠标的移动自动改变大小。拉动之后可以自动调整大小1812-1.档案总管的接口分隔组件(Splitter)拉动之12-1.档案总管的接口状态列组件(StatusBar)顾名思义就是将一些讯息显示在这个Bar上面,在档案总管中就是在档案总管画面的最下方。范例12-6StatusBar基本应用void__fastcallTForm1::Button1Click(TObject*Sender){StatusBar1->SimpleText="你刚刚按下了Button1";}//void__fastcallTForm1::Button2Click(TObject*Sender){StatusBar1->SimpleText="你刚刚按下了Button2";}//void__fastcallTForm1::Button3Click(TObject*Sender){StatusBar1->SimpleText="你刚刚按下了Button3";}//void__fastcallTForm1::Edit1Change(TObject*Sender){StatusBar1->SimpleText="你刚刚修改了Edit1";}//void__fastcallTForm1::Edit2Change(TObject*Sender){StatusBar1->SimpleText="你刚刚修改了Edit2";}1912-1.档案总管的接口状态列组件(StatusBar)v12-1.档案总管的接口状态列组件(StatusBar)范例12-7:StatusBar进阶应用使用一个按钮、一个Edit、一个Image、以及一个StatusBar。在StatusBar上总共有四个字段,跟上一个范例不一样。在StatusBar上面按下鼠标右键,选择『PanelsEditor』会出现StatusBar的Panel编辑画面。2012-1.档案总管的接口状态列组件(StatusBar)212-1.档案总管的接口状态列组件(StatusBar)范例12-7:程序代码(PartI)void__fastcallTForm1::Button1MouseDown(TObject*Sender,
TMouseButtonButton,TShiftStateShift,intX,intY)
{StatusBar1->Panels->Items[0]->Text="你按下了Button1";}//void__fastcallTForm1::Button1MouseUp(TObject*Sender,TMouseButtonButton,TShiftStateShift,intX,intY)
{StatusBar1->Panels->Items[0]->Text="你没按下Button1";}//void__fastcallTForm1::Edit1Change(TObject*Sender)
{StatusBar1->Panels->Items[1]->Text="Edit1的文字是:"+Edit1->Text;}//void__fastcallTForm1::FormDragDrop(TObject*Sender,TObject*Source,intX,intY)
{//设定Form上的DragDrop的Function,主要是用来让Image在Form上可以做Drag的动作TImage*buf=(TImage*)Source;buf->Left=X;buf->Top=Y;}2112-1.档案总管的接口状态列组件(StatusBar)v12-1.档案总管的接口状态列组件(StatusBar)范例12-7:程序代码(PartII)void__fastcallTForm1::FormDragOver(TObject*Sender,TObject*Source,
intX,intY,TDragStateState,bool&Accept)
{Accept=true;//让Form可以被允许DragOver}//void__fastcallTForm1::Image1StartDrag(TObject*Sender,TDragObject*&DragObject)
{StatusBar1->Panels->Items[2]->Text="正在拉图片";//当启动Drag的时候显示"正在拉图片"}//void__fastcallTForm1::Image1EndDrag(TObject*Sender,TObject*Target,
intX,intY)
{StatusBar1->Panels->Items[2]->Text="没在拉图片";//结束Drag的时候显示"没在拉图片"}//void__fastcallTForm1::FormMouseMove(TObject*Sender,TShiftStateShift,
intX,intY)
{//利用Form上面的MouseMove事件抓取鼠标光标,并且在StatusBar上将光标显示出来AnsiStringBuf;Buf="("+IntToStr(X)+","+IntToStr(Y)+")";StatusBar1->Panels->Items[3]->Text="鼠标光标(X,Y):"+Buf;}2212-1.档案总管的接口状态列组件(StatusBar)v12-1.档案总管的接口状态列组件(StatusBar)范例12-7执行结果2312-1.档案总管的接口状态列组件(StatusBar)212-2.标头控制组件标头控制组件所提供的功能,一般来说我们都会直接利用ListView来完成,而不是单纯的去拉一个标头控制组件下来用。因为HeaderControl一般都是用来区分是不是同类型的资料,例如在ListView中我们显示档案的话,文件名就会集体放在档名那一个Column,档案大小也都会放在同一个Column……等,所以才会说大部分的使用都是利用ListView来完成。但是如果想要在Header部分加上一些图片等花俏的功能,还是得使用HeaderControl2412-2.标头控制组件标头控制组件所提供的功能,一般来说我12-3.进度状态显示组件我们在安装应用程序(或是使用一些应用程序)的过程中,常常会有一条光棒跑出来告诉我们目前工作正进行了多少百分比,这个组件我们称做进度状态列组件。进度状态列组件可以给使用程序的使用者非常高层次的讯息(可以马上了解现在的情况),也可以让使用者预估时间,也可以增加整个程序UserFriendly的程度。在BorlandC++Builder6中,有『ProgressBar』、『Cgauge』这两个组件可以用来表示目前的完成度为何,其中ProgressBar位在Win32的页面中,而Cgauge在Sample这一页里。2512-3.进度状态显示组件我们在安装应用程序(或是使用一些12-3.进度状态显示组件范例12-9:ProgressBar&CGauge操作实例ProgressBar重要属性说明属性说明MaxProgressBar跑到100%时的那个值。MinProgressBar在0%时的那个值。Orientation有Horizontal和Vertical两种不同的属性值,主要是用来决定ProgressBar是要往右增加或是往上增加。Position决定目前ProgressBar的光棒的所在位置。Smooth决定移动的光棒要用平滑的模式或是一格一格的模式呈现出来。2612-3.进度状态显示组件范例12-9:ProgressB12-3.进度状态显示组件范例12-9:ProgressBar&CGauge操作实例CGauge重要属性说明属性说明BackColorCGauge在显示ProgressBar的地方的颜色Color除了ProgressBar的地方的颜色。如果ProgressBar不是标准的长条状,就有可能会需要用到Color这个属性。ForeColorProgressBar本身的颜色。KindCGauge的表示种类,有『HorizontalBar』、『Needle』、『Pie』、『Text』、以及『VerticalBar』这五种不同的表示方法。MaxValueProgressBar跑到100%时的那个值。MinValueProgressBar在0%时的那个值。Progress决定目前ProgressBar的光棒的所在位置。跟ProgressBar这个组件的Position属性功能一样。ShowText决定是否要在ProgressBar上面显示出目前完成的百分比数字。2712-3.进度状态显示组件范例12-9:ProgressB12-3.进度状态显示组件范例12-9:ProgressBar&CGauge操作实例执行结果2812-3.进度状态显示组件范例12-9:ProgressB12-3.进度状态显示组件不管在执行ProgressBar或是CGauge的时候,整个程序几乎都陷入了停顿状态,也就是停止响应﹔反过来说,当我们需要使用到ProgressBar或是CGauge的功能时,通常也是因为正在跑一个非常大的循环。现在有一个问题产生了,不管是在跑一个非常大的循环(CPU使用率100%)或是跑Progress的组件,都会让程序停止响应,这时候该怎么办?我们在这边将提出一个简单的解决方案『ApplicationProcessMessages()』这个函式,这个函式可以让我们的接口程序在执行中取得一些CPUTime,也因为这样,我们的接口就不会再发生『没有响应』的情况了。2912-3.进度状态显示组件不管在执行ProgressBar12-3.进度状态显示组件大家在写过几个程序之后,一定也会发现ProcessMessages()这个函式会有无效的时候,其实不是无效,而是刚刚好ProcessMessages()运作原理刚好跟你程序的做法无法match,这时候又该怎么办呢?在这边非常建议各位采用Thread的做法,虽然有些情况下不加入ProcessMessages()也可以正常运作,虽然有时候加入了ProcessMessages()就可以正常运作,但是最终的解决方法仍然是使用Thread的做法,因为Thread才是真正将所有的工作分成『执行绪』后才交给CPU去执行,所以不管现在程序在跑什么东西,只要有开Thread,不管同时间有多少程序在跑一定都可以使用到CPUTime。关于Thread的介绍与使用,我们将在后面章节提到。3012-3.进度状态显示组件大家在写过几个程序之后,一定也会12-3.进度状态显示组件其实除了上面介绍的这两个组件以外,还有其它很多组件都可以用来表示类似这方面的功能,例如曲线图、圆饼图、Shape,或是任何一个可以显示图形或是文字的都可以,只是需要程序设计师自己设计表现的模式。3112-3.进度状态显示组件其实除了上面介绍的这两个组件以外12-4.轨迹追踪列轨迹追踪列通常都是为了让使用者可以有比较方便的方法设定数值。例如在写一个骰子的程序时(一次丢多个骰子),我们一定要输入各点数会出现的机率,这时候我们就可以利用TrackBar这个组件,采用『拉』的方式来设定好各点数出现的机率。概观的说,凡是需要设定『数值』时,都可以利用TrackBar来完成,这样可以增加不少UserFriendly的效果喔!3212-4.轨迹追踪列轨迹追踪列通常都是为了让使用者可以有比12-4.轨迹追踪列范例12-10:TrackBar操作实例TrackBar重要属性说明属性说明Frequency在TrackBar上的标记多少单位划一格LineSize当你使用方向键控制TrackBar上面的指标时,按一下会移动多少格MaxTrackBar的最大值MinTrackBar的最小值Orientation有Horizontal和Vertical两种不同的属性值,主要是用来决定TrackBar是要往右移动或是往上移动PageSize跟LineSize很像,不过LineSize是控制方向键对于TrackBar的移动数量,而PageSize是控制PageDown、PageUp对于TrackBar的移动数量Position目前TrackBar指针的位置SelEnd会显示出一个Range的光棒在TrackBar上,这个光棒的结束位置就是在SelEnd这个位置。SelStart会显示出一个Range的光棒在TrackBar上,这个光棒的结束位置就是在SelStart这个位置。一般来说SelStart的位置都设定在『0』,而SelEnd的位置跟Position的值是同步的。因为这样就会将TrackBar已经被指针拉过的位置用其它颜色来表示SliderVisible决定指标要不要出现在TrackBar上ThumbLengthTrackBar的长度TickMarks决定标记点要在哪个方向TickStyle决定标记点产生的方式,Auto、Manual、或是None3312-4.轨迹追踪列范例12-10:TrackBar操作实12-4.轨迹追踪列范例12-10程序代码void__fastcallTForm1::TrackBar1Change(TObject*Sender){Label1->Caption="目前位置:"+IntToStr(TrackBar1->Position);Label2->Caption="百分比率:"+\FloatToStr((float)100*(float)TrackBar1->Position/(float)TrackBar1->Max)+"%";}3412-4.轨迹追踪列范例12-10void__fastc12-5.上下控制组件上下控制组件跟TrackBar非常的类似,都是用来设定(表现)数值,只是TrackBar一定是一个调整棒在那边让使用者拉,但是上下控制组件就不一样了,你可以结合各种不同的VCL组件,例如可以跟Label或是Edit结合等等。在范例12-11中,我们将列出一些比较常跟上下控制组件结合的使用范例,也会提到『CspinEdit』这个类似上下控制组件。3512-5.上下控制组件上下控制组件跟TrackBar非常的12-5.上下控制组件范例12-11:UpDown&CSpinEdit操作范例UpDown常用的属性说明属性说明AlignButton设定UpDown按钮的方向要在那个方向ArrowKeys决定我们是不是可以使用方向键来控制UpDown组件Associate想要跟UpDown组件结合的VCL组件Increment每次按一次按钮所增加或是减少的值MaxUpDown中会出现的最大的值,也就是Position这个属性的值不可以超过这个值MinUpDown中会出现的最小的值,也就是Position这个属性的值不可以小于这个值Orientation有Horizontal和Vertical两种不同的属性值,主要是用来决定UpDown的按钮是要上下方向或是左右方向Position目前UpDown所在的位置(显示出来的值)Thousands如果数值超过1000的时候,需要需要每三个数字打一个逗点3612-5.上下控制组件范例12-11:UpDown&C12-5.上下控制组件范例12-11:UpDown&CSpinEdit操作范例CspinEdit常用的属性说明属性说明AutoSelect当CspinEdit刚好在focus的时候,Text中的值会自动被选取EditorEnabled设定我们可不可以直接EditorCspinEdit的TextIncrement每次按一次按钮所增加或是减少的值MaxValueCSpinEdit中会出现的最大的值,也就是Value这个属性的值不可以超过这个值MinValueCSpinEdit中会出现的最大的值,也就是Value这个属性的值不可以低于这个值Value目前CSpinEdit所在的位置(显示出来的值)3712-5.上下控制组件范例12-11:UpDown&C12-5.上下控制组件范例12-11:UpDown&CSpinEdit操作范例程序代码执行结果void__fastcallTForm1::UpDown3Click(TObject*Sender,TUDBtnTypeButton){if(Button==btPrev)ProgressBar1->Position--;elseProgressBar1->Position++;}3812-5.上下控制组件范例12-11:UpDown&C12-6.日期时间在BCB内有不少跟『日期/时间』相关的组件可以用,例如Win32页次中的『DateTimePicker』及『MonthCalendar』,System页次中的『Timer』,以及Sample页次中的『Ccalendar』这几个组件。范例12-12我们将实做这几个组件让大家看看。3912-6.日期时间在BCB内有不少跟『日期/时间』相关的组12-6.日期时间范例12-12TimerTimer用白话一点的话来说就是『定时器』。也就是说我们可以利用Timer来做固定时间的定时器。除了可以利用Timer做时间的定时器外,在BCB中也有提供一些函式可以做时间的计算,例如时间间距的计算或是目前时间的回报等等。在范例程序12-12中,我们将上面我们所说的三个功能写出来当作范例,让大家可以对Timer这个组件以及有关DateTime方面的函式更熟悉。4012-6.日期时间范例12-124012-6.日期时间范例12-12月历MonthCalendar&DateTimePicker&CCalendarMonthCalendar重要属性说明属性说明CalColor设定月历中的各种颜色Date月历中被选取的日期FirstDayOfWeek设定每个星期的第一天是星期几MultiSelect可以选多个日期ShowToday在月历上显示出今天的日期ShowTodayCircle在今天的日期上会出现一个圈圈包住WeekNumbers出现这一周是今年的第几周的数字4112-6.日期时间范例12-12属性说明CalColor设12-6.日期时间范例12-12月历CCalendar重要属性说明属性说明Day目前选定的日子GridLineWidth表格网格线的宽度Month目前选定的月份StartOfWeek设定每个星期的第一天是星期几UseCurrentDate预设为目前的日期Year目前表格显示出来的日期的年份4212-6.日期时间范例12-12属性说明Day目前选定的日12-6.日期时间范例12-12Timer执行画面&DateTime执行画面4312-6.日期时间范例12-124312-7.热键组件的使(HotKey)热键的使用在Windows系统中也是蛮重要的功能。虽然说目前大家都习惯使用鼠标,但是如果想让自己在使用软件上能加快速度或是提升效率,热键的使用及建立就相当的重要了。例如在Word中,你要打个『顿号』可能得从〔插入〕〔符号〕这个选单中慢慢找,但是如果你将他设定成快速键,节省下来的时间可能高达30秒钟。4412-7.热键组件的使(HotKey)热键的使用在Wind12-7.热键组件的使(HotKey)范例12-13:HotKey实作技巧在BCB中有提供热键的组件。在范例12-13中我们将会设计一个范例程序来展现热键的实作技巧,以及使用热键的好处。在范例12-13中我们利用MainMenu这个组件当作我们要指定快速键的组件。设定好了之后按下快速键就会启动相关的函式。4512-7.热键组件的使(HotKey)范例12-13:Ho12-7.热键组件的使(HotKey)范例12-13:HotKey实作技巧相关程序代码void__fastcallTForm1::BitBtn1Click(TObject*Sender){AnsiStringStrBuf,HotKeyBuf;TMenuItem*ItemBuf;if(RadioGroup1->ItemIndex!=-1){StrBuf=RadioGroup1->Items->Strings[RadioGroup1->ItemIndex];for(inti=0;i<MainMenu1->Items->Count;i++)if((ItemBuf=MainMenu1->Items->Items[i]->Find(StrBuf))!=NULL)break;if(ItemBuf)ItemBuf->ShortCut=HotKey1->HotKey;}}//void__fastcallTForm1::ShowHotKeySet(TObject*Sender){ShowMessage("SetHotKeySuccess!\n");}4612-7.热键组件的使(HotKey)范例12-13:Ho12-7.热键组件的使(HotKey)范例12-13:HotKey实作技巧执行画面4712-7.热键组件的使(HotKey)范例12-13:Ho12-8.常驻在SystemTray的程序有很多软件常常会将自己的软件最小化在右下角的系统列,例如防毒软件或是一些常驻程序都会在系统列。在BCB中也有这样的组件提供给programmer使用,这个组件就是『TrayIcon』。范例12-14:系统列程序实作技巧TrayIcon的使用方法非常的简单,在范例12-14中,我们除了放入一个TrayIcon外,我们也加入一个PopupMenu当做快速选单,也加入一个ImageList,并且放入多个Image在ImageList中,让TrayIcon最小化的时候可以在系统列出现我们所设定的图示。4812-8.常驻在SystemTray的程序有很多软件常常12-8.常驻在SystemTray的程序范例12-14:系统列程序实作技巧主要程序代码void__fastcallTForm1::N1Click(TObject*Sender){//放置于系统列if(TrayIcon1->Visible==false){N1->Enabled=false;N2->Enabled=true;TrayIcon1->Visible=true;TrayIcon1->Minimize();}}void__fastcallTForm1::N2Click(TObject*Sender){//放置于桌面if(TrayIcon1->Visible==true){N1->Enabled=true;N2->Enabled=false;TrayIcon1->Visible=false;TrayIcon1->Restore();}}4912-8.常驻在SystemTray的程序范例12-1412-8.常驻在SystemTray的程序范例12-14:系统列程序实作技巧主要程序代码void__fastcallTForm1::CheckBox1Click(TObject*Sender){//设定要不要在系统列开启动态的效果if(CheckBox1->Checked){TrayIcon1->AnimateInterval=Edit1->Text.ToInt()*1000;TrayIcon1->Animate=true;}else{TrayIcon1->Animate=false;TrayIcon1->IconIndex=0;}}5012-8.常驻在SystemTray的程序范例12-1412-8.常驻在SystemTray的程序范例12-14:系统列程序实作技巧主要程序代码void__fastcallTForm1::Edit1Change(TObject*Sender){//设定动态效果的时间长短if(CheckBox1->Checked){TrayIcon1->AnimateInterval=Edit1->Text.ToInt()*1000;TrayIcon1->Animate=true;}else{TrayIcon1->Animate=false;TrayIcon1->IconIndex=0;}}5112-8.常驻在SystemTray的程序范例12-1412-8.常驻在SystemTray的程序范例12-14:系统列程序实作技巧主要执行画面5212-8.常驻在SystemTray的程序范例12-1412-8.常驻在SystemTray的程序其实要实做系统列的程序也不一定需要使用BCB提供的TrayIcon这个VCL组件,我们也可以直接利用Win32API所提供的函式来完成这个功能,而且透过Win32API的方式更能提供多样化的功能。5312-8.常驻在SystemTray的程序其实要实做系统本章习题利用Win32API实做出可以将程序最小化至系统列的应用程序。除了MainMenu可以结合HotKey外,找出其它的组件搭配HotKey实做出应用程序。试着拉出类似档案总管的接口(不需要实做程序代码)。54本章习题利用Win32API实做出可以将程序最小化至系统列第十二章Win32环境程序设计这一章节可以说是本书精华之一,Win32程序设计算是比较复杂的部分,但是我们以最简单的叙述带领着大家进入Win32程序设计的殿堂,让你写出来的程序具有一定的水平以上。若能将本章与下一章的技巧灵活运用,更能让大家写出高阶的窗口程序。55第十二章Win32环境程序设计这一章节可以说是本书精华大纲12-1.档案总管的接口12-2.标头控制组件12-3.进度状态显示组件12-4.轨迹追踪列12-5.上下控制组件12-6.日期时间12-7.热键组件的使用(HotKey)12-8.常驻在SystemTray的程序本章习题56大纲12-1.档案总管的接口212-1.档案总管的接口提到Win32的程序设计,最重要的范例就是档案总管。整个档案总管都是使用Win32的接口来完成。而我们在这一章以及下一章,也都会围绕着档案总管来介绍大部分内容。下图中就是档案总管的接口,在这个接口里,主要组件有ListView、TreeView、Splitter、以及StatusBar这四种VCL组件,SplitterTreeViewListViewStatusBar5712-1.档案总管的接口提到Win32的程序设计,最重要的12-1.档案总管的接口窗体检视组件(ListView)范例12-1在范例12-1,我们的接口相当简单,除了一个输入数据的接口外,就是一个ListView。除了提到这些可看见的VCL组件外,我们还有放入一个Popupmenu以及一个ImageList在这个范例中。Popupmenu主要是提供鼠标右键的功能选单,,而ImageList则是要提供一些Image给ListView使用。5812-1.档案总管的接口窗体检视组件(ListView)412-1.档案总管的接口窗体检视组件(ListView)新增Column个数5912-1.档案总管的接口窗体检视组件(ListView)512-1.档案总管的接口窗体检视组件(ListView)ViewStyle的不同大图示(vsIcon)小图示(vsSmallIcon)清单(List)详细列表(Report)6012-1.档案总管的接口窗体检视组件(ListView)612-1.档案总管的接口窗体检视组件(ListView)范例12-1执行结果6112-1.档案总管的接口窗体检视组件(ListView)712-1.档案总管的接口树状检视组件(TreeView)TreeView是目前档案总管中的重要组件之一,在档案总管中TreeView负责显示从桌面开始的所有树状结构。在这一小节里,我们将会利用三个范例让各位练习TreeView的各项使用实例。谈到Tree的使用,就必须谈到什么是『根节点』、『父节点』、『子节点』、以及『叶节点』。根节点就是我们所谓的『root』,他是在整个Tree的最上方,以档案总管来说,根节点就是『桌面』父节点就是这个节点的底下还有一个以上的节点子节点就是这个节点的上一层还有节点叶节点就代表这个节点已经是这支树的最后一个节点6212-1.档案总管的接口树状检视组件(TreeView)812-1.档案总管的接口树状检视组件(TreeView)范例12-2:利用简单的程序来控制TreeView的各项动作。我们主要是使用静态的方式将一棵树建立起来。这棵树是利用BCB提供的接口去产生。6312-1.档案总管的接口树状检视组件(TreeView)912-1.档案总管的接口树状检视组件(TreeView)范例12-2执行结果6412-1.档案总管的接口树状检视组件(TreeView)112-1.档案总管的接口树状检视组件(TreeView)范例12-3:在程序中建构一个静态的TreeView在范例12-3,我们也是静态产生Tree,但是这次我们不是从BCB的接口中产生,我们是从程序代码中产生。在范例12-3的接口中,全部都跟范例12-2一模一样。程序中,我们宣告了三个TreeNode(两个也可以),经由这三个TreeNode之间的相互关系,我们完成了整颗树的建立。在建树的程序代码方面并不难,比较特别的就是要回到上一层我们使用的是『parent=parentParent』这样的方法来取得上一层Node的内存地址。至于一开始我们有保留Root的地址这只是一个习惯,因为从BCB中也是可以判断哪个Node是Root,在范例12-3中这样做只是为了方便以及写程序者的习惯。6512-1.档案总管的接口树状检视组件(TreeView)112-1.档案总管的接口树状检视组件(TreeView)范例12-3:程序代码void__fastcallTForm1::FormCreate(TObject*Sender){TTreeNode*root,*parent,*son;root=TreeView1->Items->Add(NULL,"Root");root->ImageIndex=0;root->SelectedIndex=1;root->StateIndex=-1;parent=root;son=TreeView1->Items->AddChild(parent,"Parent1");son->ImageIndex=2;son->SelectedIndex=3;son->StateIndex=-1;parent=son;son=TreeView1->Items->AddChild(parent,"Son_1_1");son->ImageIndex=2;son->SelectedIndex=3;son->StateIndex=0;son=TreeView1->Items->AddChild(parent,"Son_1_2");son->ImageIndex=2;son->SelectedIndex=3;son->StateIndex=-1;parent=parent->Parent;son=TreeView1->Items->AddChild(parent,"Parent2");son->ImageIndex=2;son->SelectedIndex=3;son->StateIndex=-1;parent=son;son=TreeView1->Items->AddChild(parent,"Son_2_1");son->ImageIndex=2;son->SelectedIndex=3;son->StateIndex=-1;parent=son;son=TreeView1->Items->AddChild(parent,"Son_2_1_1");son->ImageIndex=2;son->SelectedIndex=3;son->StateIndex=1;parent=parent->Parent->Parent;son=TreeView1->Items->AddChild(parent,"Parent3");son->ImageIndex=2;son->SelectedIndex=3;son->StateIndex=-1;}6612-1.档案总管的接口树状检视组件(TreeView)v12-1.档案总管的接口树状检视组件(TreeView)范例12-4:在程序中建构一个TreeView,主要程序代码我们分成三个部分第一部份是动态新增所需要的变量宣告,这部分是宣告在main.cpp的上方,归类于全域变数第二部份就是有关新增/删除TreeNode部分的程序代码最后一部分就是一些琐碎的功能,这些程序代码包括了展开以及收合的功能,也有在StatusBar上面显示目前的状况,还有一个就是选择要不要显示Root。6712-1.档案总管的接口树状检视组件(TreeView)112-1.档案总管的接口树状检视组件(TreeView)范例12-4:程序代码宣告//宣告两个变量..用来存放RootAddress和Node的AddressTTreeNode*root=NULL;TTreeNode*node=NULL;6812-1.档案总管的接口树状检视组件(TreeView)/12-1.档案总管的接口树状检视组件(TreeView)范例12-4:程序代码动态新增Nodevoid__fastcallTForm1::N1Click(TObject*Sender){//新增一个Node,在新增的时候会自动判断是不是新增Root,在新增的时候利用InputQuery来当作输入接口AnsiStringBuf;if(root==NULL){//如果现在root还是NULL的话..表示要新增一个rootif(InputQuery("输入","请输入TreeNode的名称",Buf)){//使用InputQuery当作输入接口root=TreeView1->Items->AddChild(NULL,Buf);//将新增的Node加入到TreeView中root->ImageIndex=0;root->SelectedIndex=1;root->StateIndex=-1;//设定该Node的一些基本属性StatusBar1->SimpleText="新增Root节点";//在StatusBar显示目前的运作情况TreeView1->AlphaSort();//新增之后利用AlphaSort对整个Tree排序}}else{//新增一般的Node//必须得先选一个node才能继续产生Child,不然如果没有Parent那来的Childif(TreeView1->Selected!=NULL){//使用InputQuery当作输入接口if(InputQuery("输入","请输入TreeNode的名称",Buf)){//将新增的Node加入到TreeView中node=TreeView1->Items->AddChildFirst(TreeView1->Selected,Buf);node->ImageIndex=2;node->SelectedIndex=3;node->StateIndex=-1;//设定该Node的一些基本属性StatusBar1->SimpleText="新增一个Node";//在StatusBar显示目前的运作情况TreeView1->AlphaSort();//新增之后利用AlphaSort对整个Tree排序}}}}6912-1.档案总管的接口树状检视组件(TreeView)v12-1.档案总管的接口树状检视组件(TreeView)范例12-4:程序代码动态删除Nodevoid__fastcallTForm1::N2Click(TObject*Sender){if(TreeView1->Selected!=NULL){//如果有Node被选取..也选择要删除才执行if(TreeView1->Selected==root){//判断是不是RootTreeView1->Selected->Delete();root=NULL;//如果是root被删除..要将root的point设成nullStatusBar1->SimpleText="删除Root节点";}else{TreeView1->Selected->Delete();StatusBar1->SimpleText="删除一个Node";}}}7012-1.档案总管的接口树状检视组件(TreeView)v12-1.档案总管的接口树状检视组件(TreeView)SortAlphaSort:根据我们每个Node的Caption中的值去做排序CustomSort:让我们自己写函式去做排列SortTypestBoth:当Date或是Text有任何一种改变时就重新SortstDate:当Node的数据改变时就重新Sort一次stNone:永远不排序stText:当Node的Text改变时重新Sort7112-1.档案总管的接口树状检视组件(TreeView)112-1.档案总管的接口分隔组件(Splitter)分隔组件最主要的功能就是让两个组件在你拉动的时候自动分配组件的大小。例如在档案总管中,我们可以将光标停放在TreeView和ListView的中间,接着游标就会变成一个双箭头的光标,然后我们就可以按着鼠标的左键左右移动鼠标,这时候TreeView和ListView的窗口会随着鼠标的移动自动改变大小。拉动之后可以自动调整大小7212-1.档案总管的接口分隔组件(Splitter)拉动之12-1.档案总管的接口状态列组件(StatusBar)顾名思义就是将一些讯息显示在这个Bar上面,在档案总管中就是在档案总管画面的最下方。范例12-6StatusBar基本应用void__fastcallTForm1::Button1Click(TObject*Sender){StatusBar1->SimpleText="你刚刚按下了Button1";}//void__fastcallTForm1::Button2Click(TObject*Sender){StatusBar1->SimpleText="你刚刚按下了Button2";}//void__fastcallTForm1::Button3Click(TObject*Sender){StatusBar1->SimpleText="你刚刚按下了Button3";}//void__fastcallTForm1::Edit1Change(TObject*Sender){StatusBar1->SimpleText="你刚刚修改了Edit1";}//void__fastcallTForm1::Edit2Change(TObject*Sender){StatusBar1->SimpleText="你刚刚修改了Edit2";}7312-1.档案总管的接口状态列组件(StatusBar)v12-1.档案总管的接口状态列组件(StatusBar)范例12-7:StatusBar进阶应用使用一个按钮、一个Edit、一个Image、以及一个StatusBar。在StatusBar上总共有四个字段,跟上一个范例不一样。在StatusBar上面按下鼠标右键,选择『PanelsEditor』会出现StatusBar的Panel编辑画面。7412-1.档案总管的接口状态列组件(StatusBar)212-1.档案总管的接口状态列组件(StatusBar)范例12-7:程序代码(PartI)void__fastcallTForm1::Button1MouseDown(TObject*Sender,
TMouseButtonButton,TShiftStateShift,intX,intY)
{StatusBar1->Panels->Items[0]->Text="你按下了Button1";}//void__fastcallTForm1::Button1MouseUp(TObject*Sender,TMouseButtonButton,TShiftStateShift,intX,intY)
{StatusBar1->Panels->Items[0]->Text="你没按下Button1";}//void__fastcallTForm1::Edit1Change(TObject*Sender)
{StatusBar1->Panels->Items[1]->Text="Edit1的文字是:"+Edit1->Text;}//void__fastcallTForm1::FormDragDrop(TObject*Sender,TObject*Source,intX,intY)
{//设定Form上的DragDrop的Function,主要是用来让Image在Form上可以做Drag的动作TImage*buf=(TImage*)Source;buf->Left=X;buf->Top=Y;}7512-1.档案总管的接口状态列组件(StatusBar)v12-1.档案总管的接口状态列组件(StatusBar)范例12-7:程序代码(PartII)void__fastcallTForm1::FormDragOver(TObject*Sender,TObject*Source,
intX,intY,TDragStateState,bool&Accept)
{Accept=true;//让Form可以被允许DragOver}//void__fastcallTForm1::Image1StartDrag(TObject*Sender,TDragObject*&DragObject)
{StatusBar1->Panels->Items[2]->Text="正在拉图片";//当启动Drag的时候显示"正在拉图片"}//void__fastcallTForm1::Image1EndDrag(TObject*Sender,TObject*Target,
intX,intY)
{StatusBar1->Panels->Items[2]->Text="没在拉图片";//结束Drag的时候显示"没在拉图片"}//void__fastcallTForm1::FormMouseMove(TObject*Sender,TShiftStateShift,
intX,intY)
{//利用Form上面的MouseMove事件抓取鼠标光标,并且在StatusBar上将光标显示出来AnsiStringBuf;Buf="("+IntToStr(X)+","+IntToStr(Y)+")";StatusBar1->Panels->Items[3]->Text="鼠标光标(X,Y):"+Buf;}7612-1.档案总管的接口状态列组件(StatusBar)v12-1.档案总管的接口状态列组件(StatusBar)范例12-7执行结果7712-1.档案总管的接口状态列组件(StatusBar)212-2.标头控制组件标头控制组件所提供的功能,一般来说我们都会直接利用ListView来完成,而不是单纯的去拉一个标头控制组件下来用。因为HeaderControl一般都是用来区分是不是同类型的资料,例如在ListView中我们显示档案的话,文件名就会集体放在档名那一个Column,档案大小也都会放在同一个Column……等,所以才会说大部分的使用都是利用ListView来完成。但是如果想要在Header部分加上一些图片等花俏的功能,还是得使用HeaderControl7812-2.标头控制组件标头控制组件所提供的功能,一般来说我12-3.进度状态显示组件我们在安装应用程序(或是使用一些应用程序)的过程中,常常会有一条光棒跑出来告诉我们目前工作正进行了多少百分比,这个组件我们称做进度状态列组件。进度状态列组件可以给使用程序的使用者非常高层次的讯息(可以马上了解现在的情况),也可以让使用者预估时间,也可以增加整个程序UserFriendly的程度。在BorlandC++Builder6中,有『ProgressBar』、『Cgauge』这两个组件可以用来表示目前的完成度为何,其中ProgressBar位在Win32的页面中,而Cgauge在
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 2025年湖南九嶷职业技术学院单招职业倾向性测试题库及答案一套
- 2025年河北机电职业技术学院单招职业倾向性测试题库及答案一套
- 2025年广州工程技术职业学院单招职业技能测试题库必考题
- 2025年怀化师范高等专科学校单招职业适应性测试题库及答案1套
- 2025贵州省安全员A证考试题库附答案
- 2025年甘肃省兰州市单招职业适应性测试题库完整
- 2025年湖南理工职业技术学院单招职业技能测试题库必考题
- 标点符号修改题强化训练(引号)
- 2025年贵州应用技术职业学院单招职业技能测试题库1套
- 科技发展与职业教育培训课程的互动关系
- 中职普通话教师教案模板
- 施工后期的场地恢复措施
- 七年级历史下册 第一单元 隋唐时期繁荣与开放的时代 第1课 隋朝的统一与灭亡说课稿1 新人教版
- 智能教育机器人AI项目策划创业计划书
- 《MATLAB编程及应用》全套教学课件
- T-CCSAS 001-2018 危险与可操作性分析(HAZOP分析)质量控制与审查导则
- 2025年春人教版九年级英语下册 2025年中考模拟测试卷
- 果园轨道运输施工方案
- 《医疗事故处理条例》解读
- 《学位论文选题与写作》教学大纲
- 广西版五年级下册美术全册教案【完整版】
评论
0/150
提交评论