首页 > 学院 > 开发设计 > 正文

PageControl和类-代码编辑器

2019-11-14 13:15:04
字体:
来源:转载
供稿:网友
PageControl位于Win32选项卡中,可以在控件上右键点击“New Page”,来实现静态的页面添加。
先说说几个重要的属性:
ActivePage:当前活动的页面(在设计模式中切换页面会更改ActivePage属性)
MultiLine:选项卡以多行形式显示。
Style:页面样式。
tsTabs:(默认)选项卡样式
tsButtons:按钮样式(经典样式)
tsFlatButtons:按钮样式2(经典样式)
TabHeight, TabWidth:选项卡位置设置(默认为0,单位:px)

TabPosition:选项卡的位置

tpBottom:下面(很奇怪)
tpLeft:左面(经典样式)
tPRight:右面(经典样式)
tpTop:(默认)上面

然后是PageControl中的TabSheet:

Caption:在选项卡中显示的内容
TabVisible:选项卡可见性
PageIndex:页面的索引值
首先添加一个PopupMenu,PageControl1。PageControl不要添加TabSheet。
PageControl的Align设置为alClient,PupopMenu设置为PopupMenu1。
PopupMenu1添加如下菜单(Add的Visible是False):
简单文本编辑器——PageControl和类(Delphi 2009) - ZomGraves - 编程为主
然后进入代码编辑界面,在interface中的uses引用StdCtrls。
和以前不同的是,之前是把Memo也添加到窗体中,直接在属性窗口设置好相应的属性值。但是,用代码创建的控件,就只能用代码去设置其属性了。
 
不难看出,这里面的每一个控件(包括窗体)都是一个类。当然,不同于C++和java,类定义了之后要手动创建,一般情况下是Create()。
1 procedure TForm1.Button1Click(Sender: TObject);2 var3   btn: TButton;4 begin5   btn := TButton.Create();6   //下面是对Button的属性修改7   btn.Caption := '按钮';8 end;
然后,在ActionList中添加一些Action,接下来设置主菜单。如图:
简单文本编辑器——PageControl(Delphi 2009) - ZomGraves - 编程为主
Action里面的StandardAction可以直接使用。
只不过,有的还需要自己手动添加代码,比如:打开等等。
像撤销,剪切,粘贴等不需要自己添加代码,也不需要自己弄Enabled属性。
之前说过,只有窗体,菜单(主菜单和弹出式菜单),按钮等一些控件能使用Action。
想想如果不使用ActionList里面的StandardAction,自己去写代码的话,除了引用Clipbrd.pas之外就是使用Windows.pas里面的SendMessage了。
不过,还是得提醒一下:在菜单上添加Action会更改菜单的Caption, Checked和ShortCut属性。
所以在设置完Action之后再改Caption(StandardAction的默认的Caption是英文...)。
--如何判断当前活动的Memo
在这里,一个Page里面只有一个Memo,这样,就可以通过PageControl的ActivePageIndex来决定了。
在静态使用Memo的时候我们可以直接Memo1.Text什么的,但是现在不可以。那么,可以用下面的替代:
类名(PageControl1.Pages[PageControl1.ActivePageIndex].Controls[0]).属性
比如:
TMemo(PageControl1.Pages[PageControl1.ActivePageIndex].Controls[0])
--关闭页面与打开、保存
关闭的时候,直接调用TabSheet的Destroy()就可以了,对于容器型的控件来说,对容器进行Destroy的同时,内部的控件也同样会被Destroy。
注意,静态添加的控件也可以用代码Destroy。但是...不推荐这么做。
在关闭之前最好询问用户没保存的文件是否保存。
那么,Memo的Modified属性就非常重要了,初始情况是False,当文本框的内容出现变化的时候Modified为True(但也有特例)。
在不考虑UTF-8编码的情况下直接使用Lines.LoadFromFile()和Lines.SaveToFile()就可以了。
 1 procedure TForm1.FileOpenAccept(Sender: TObject); 2 var 3   fName: string; 4   cIndex: Integer; 5 begin 6   Add1.Click(); 7   cIndex := PageControl1.ActivePageIndex; 8   fName := FileOpen1.Dialog.FileName; 9   TMemo(PageControl1.Pages[cIndex].Controls[0]).LoadFromFile(fName);10 end;
在不考虑类的继承的情况下,保存这部分实现比较难而且很麻烦。
首先,需要一个字符串类型的动态数组,按照PageControl1的标签的顺序记录其完整的文件名(新建的文件,值为空),而且数组的索引值要和PageControl的TabSheet的索引值对应。
然后还需要考虑什么时候需要修改这个动态数组等等。显然很麻烦。
所以,这里通过类的继承实现。则有:
1 type2   TRecEdit = class(TMemo)3   protected4     fPath: string;        //用于存放通过打开的文件的完整路径5   end;
这样子类拥有父类能继承的所有属性,以及子类定义的属性。
类的定义写在interface中。
另外,主菜单的“关闭当前”和“关闭所有”使用的过程基本相同,这样我们可以不用在另一个过程里面写xxx.Click();了。
选择一个菜单,在属性窗口中单击Events,找到OnClick,选择要使用的过程即可。
简单文本编辑器——PageControl和类(Delphi 2009) - ZomGraves - 编程为主
当用户关闭窗口的时候,应该询问用户没保存的文件是否保存,当然,这里面会用到while循环,同时我定义了函数ClosePageQuery,通过其返回值来决定。
当ClosePageQuery返回False的时候使FormCloseQuery的CanClose为True。
则有如下代码:
1 procedure TForm1.FormCloseQuery(Sender: TObject; var CanClose: Boolean);2 begin3   while PageControl1.PageCount > 0 do4     if not ClosePageQuery() then begin5       CanClose := True;6       Exit;7     end;8 end;
--扩展
字体设置:
在窗体上添加一个FontDialog。然后可以使用如下代码:
那么,在这里就可以这么用:
if FontDialog1.Execute then
  TRecEdit(PageControl1.Pages[PageControl1.ActivePageIndex].Controls[0]).Font := FontDialog1.Font
上面的几个可以根据自己的情况添加。
--调试
调试还是比较简单的。这里先说一下容易出问题的地方。
关闭所有
最开始的时候使用for循环,然后就有如下代码:
for i := 0 to PageControl1.PageCount - 1 do  PageControl1.Pages[i].Destroy;
但是——这么做会出错。
因为i的值会变,而且PageControl1.PageCount也会变,但只能变小,而i只能变大。
所以,会出现下标越界的错误。
PageControl1.Pages[i].Destroy;
换成
PageControl1.ActivePage.Destroy;
就不会出错。
后期把保存部分添加之后,就不能直接使用Destroy了。
显然,for循环不合适。
然后是while循环,之前说ClosePageQuery为False的时候退出循环。
1 while PageControl1.PageCount > 0 do2   if not ClosePageQuery() then3     break;
也可以把while和if合并。
保存
保存和另存为是两回事。首先,另存为是无论文件是否是新建的,都会弹出保存对话框。
而保存就是TRecEdit的fPath是空字符串的时候,也就是文件是新建的时候弹出保存对话框。所以有:
1 pIndex := PageControl1.ActivePageIndex;2 s := TRecEdit(PageControl1.Pages[pIndex].Controls[0]).fPath;3 if s = '' then begin4   if SaveDialog1.Execute then5     TRecEdit(PageControl1.Pages[pIndex].Controls[0]).Lines.SaveToFile(SaveDialog1.FileName);6 end else7   if TRecEdit(PageControl1.Pages[pIndex].Controls[0]).Modified then8       TRecEdit(PageControl1.Pages[pIndex].Controls[0]).Lines.SaveToFile(s);
实际上是if语句的嵌套。
这里很可能弄成先if xxx.Modified then然后再if s = '' then。
但这样会忽略一种情况——新建的文件没有输入任何文字,理论上会弹出保存对话框的但实际上没有,而且没有进行保存。
 
根据前面部分(不包括扩展),整理代码:
  1 unit Unit1;  2   3 interface  4   5 uses  6   Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,  7   Dialogs, Menus, StdCtrls, ComCtrls, StdActns, ActnList;  8   9 type 10   TRecEdit = class(TMemo) 11   protected 12     fPath: string; 13   end; 14  15   TForm1 = class(TForm) 16     PageControl1: TPageControl; 17     PopupMenu1: TPopupMenu; 18     Add1: TMenuItem; 19     ClosePage1: TMenuItem; 20     CloseAll1: TMenuItem; 21     ActionList1: TActionList; 22     FileOpen1: TFileOpen; 23     FileSaveAs1: TFileSaveAs; 24     EditCut1: TEditCut; 25     EditCopy1: TEditCopy; 26     EditPaste1: TEditPaste; 27     EditSelectAll1: TEditSelectAll; 28     EditUndo1: TEditUndo; 29     EditDelete1: TEditDelete; 30     MainMenu1: TMainMenu; 31     F1: TMenuItem; 32     E1: TMenuItem; 33     N1: TMenuItem; 34     O1: TMenuItem; 35     S1: TMenuItem; 36     SaveAs1: TMenuItem; 37     Undo1: TMenuItem; 38     N2: TMenuItem; 39     Cut1: TMenuItem; 40     Copy1: TMenuItem; 41     Paste1: TMenuItem; 42     Delete1: TMenuItem; 43     N3: TMenuItem; 44     SelectAll1: TMenuItem; 45     N4: TMenuItem; 46     C1: TMenuItem; 47     L1: TMenuItem; 48     N5: TMenuItem; 49     X1: TMenuItem; 50     SaveDialog1: TSaveDialog; 51     procedure Add1Click(Sender: TObject); 52     procedure FormCreate(Sender: TObject); 53     procedure ClosePage1Click(Sender: TObject); 54     procedure CloseAll1Click(Sender: TObject); 55     procedure FileOpen1Accept(Sender: TObject); 56     procedure N1Click(Sender: TObject); 57     procedure S1Click(Sender: TObject); 58     procedure FileSaveAs1Accept(Sender: TObject); 59     procedure FormCloseQuery(Sender: TObject; var CanClose: Boolean); 60   private 61     { Private declarations } 62     function ClosePageQuery(pIndex: Integer): Boolean; overload; 63     function ClosePageQuery(): Boolean; overload; 64   public 65     { Public declarations } 66   end; 67  68 var 69   Form1: TForm1; 70   n: Integer; 71  72 implementation 73  74 {$R *.dfm} 75  76 procedure TForm1.Add1Click(Sender: TObject); 77 var 78   tab: TTabSheet; 79   TeMemo: TRecEdit; 80 begin 81   tab := TTabSheet.Create(PageControl1); 82   tab.PageControl := PageControl1; 83   TeMemo := TRecEdit.Create(tab); 84   TeMemo.Parent := tab; 85   TeMemo.fPath := ''; 86   TeMemo.Align := alClient; 87   TeMemo.ScrollBars := ssVertical; 88   C1.Enabled := True; 89   L1.Enabled := True; 90 end; 91  92 function TForm1.ClosePageQuery(pIndex: Integer): Boolean; 93 var 94   ret: Integer; 95 begin 96   if TRecEdit(PageControl1.Pages[pIndex].Controls[0]).Modified then begin 97     ret := application.MessageBox('当前文件内容已经修改,想保存文件吗?', '保存', 51);    //51=48+3 98     case ret of 99     IDYES:      FileSave1.Click();100     IDCANCEL:   begin101                   Result := False;102                   Exit;103                 end;104     end;105   end;106   PageControl1.Pages[pIndex].Destroy;107   Result := True;108 end;109 110 function TForm1.ClosePageQuery: Boolean;111 begin112   Result := ClosePageQuery(PageControl1.ActivePageIndex);113 end;114 115 procedure TForm1.CloseAll1Click(Sender: TObject);116 begin117   while PageControl1.PageCount > 0 do118     if not ClosePageQuery() then119       break;120   if PageControl1.PageCount = 0 then begin121     C1.Enabled := False;122     L1.Enabled := False;123   end;124 end;125 126 procedure TForm1.ClosePage1Click(Sender: TObject);127 begin128   ClosePageQuery(PageControl1.ActivePageIndex);129   if PageControl1.PageCount = 0 then begin130     C1.Enabled := False;131     L1.Enabled := False;132   end;133 end;134 135 procedure TForm1.FileOpen1Accept(Sender: TObject);136 var137   pIndex: Integer;138   fName: string;139 begin140   Add1.Click;141   pIndex := PageControl1.ActivePageIndex;142   fName := FileOpen1.Dialog.FileName;143   TRecEdit(PageControl1.Pages[pIndex].Controls[0]).Lines.LoadFromFile(fName);144   TRecEdit(PageControl1.Pages[pIndex].Controls[0]).fPath := fName;145   PageControl1.ActivePage.Caption := ExtractFileName(fName);146   //Form1.Caption := fName;147 end;148 149 procedure TForm1.FileSaveAs1Accept(Sender: TObject);150 var151   pIndex: Integer;152   sPath: string;153 begin154   pIndex := PageControl1.ActivePageIndex;155   sPath := FileSaveAs1.Dialog.FileName;156   TRecEdit(PageControl1.Pages[pIndex].Controls[0]).Lines.SaveToFile(sPath);157   TRecEdit(PageControl1.Pages[pIndex].Controls[0]).fPath := sPath;158 end;159 160 procedure TForm1.FormCloseQuery(Sender: TObject; var CanClose: Boolean);161 begin162   while PageControl1.PageCount > 0 do163     if not ClosePageQuery() then begin164       CanClose := True;165       Exit;166     end;167 end;168 169 procedure TForm1.FormCreate(Sender: TObject);170 begin171   n := 1;172   N1.Click;173 end;174 175 procedure TForm1.N1Click(Sender: TObject);        //新建176 begin177   Add1.Click;178   PageControl1.ActivePage.Caption := '无标题' + IntToStr(n);179   Inc(n);180 end;181 182 procedure TForm1.S1Click(Sender: TObject);        //保存183 var184   s: string;185   pIndex: Integer;186 begin187   with PageControl1 do begin188     pIndex := ActivePageIndex;189     s := TRecEdit(Pages[pIndex].Controls[0]).fPath;190     if s = '' then begin191       if SaveDialog1.Execute then begin192         TRecEdit(Pages[pIndex].Controls[0]).Lines.SaveToFile(SaveDialog1.FileName);193         TRecEdit(Pages[pIndex].Controls[0]).fPath = SaveDialog1.FileName;194       end;195     end else196       if TRecEdit(Pages[pIndex].Controls[0]).Modified then197         TRecEdit(Pages[pIndex].Controls[0]).Lines.SaveToFile(s);198     ActivePage.Caption := ExtractFileName(s);199   end;200 end;201 202 end.

发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表