tsTabs:(默認)選項卡樣式 tsButtons:按鈕樣式(經典樣式) tsFlatButtons:按鈕樣式2(經典樣式)TabHeight, TabWidth:選項卡位置設置(默認為0,單位:px)
TabPosition:選項卡的位置
tpBottom:下面(很奇怪) tpLeft:左面(經典樣式) tpRight:右面(經典樣式) tpTop:(默認)上面
然後是PageControl中的TabSheet:
Caption:在選項卡中顯示的內容 TabVisible:選項卡可見性 PageIndex:頁面的索引值
然後進入代碼編輯界面,在interface中的uses引用StdCtrls。
和以前不同的是,之前是把Memo也添加到窗體中,直接在屬性窗口設置好相應的屬性值。但是,用代碼創建的控件,就只能用代碼去設置其屬性了。
不難看出,這裡面的每一個控件(包括窗體)都是一個類。當然,不同於C++和java,類定義了之後要手動創建,一般情況下是Create()。
1 procedure TForm1.Button1Click(Sender: TObject); 2 var 3 btn: TButton; 4 begin 5 btn := TButton.Create(); 6 //下面是對Button的屬性修改 7 btn.Caption := '按鈕'; 8 end;然後,在ActionList中添加一些Action,接下來設置主菜單。如圖:
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 type 2 TRecEdit = class(TMemo) 3 protected 4 fPath: string; //用於存放通過打開的文件的完整路徑 5 end;這樣子類擁有父類能繼承的所有屬性,以及子類定義的屬性。 類的定義寫在interface中。 另外,主菜單的“關閉當前”和“關閉所有”使用的過程基本相同,這樣我們可以不用在另一個過程裡面寫xxx.Click();了。 選擇一個菜單,在屬性窗口中單擊Events,找到OnClick,選擇要使用的過程即可。
當用戶關閉窗口的時候,應該詢問用戶沒保存的文件是否保存,當然,這裡面會用到while循環,同時我定義了函數ClosePageQuery,通過其返回值來決定。
當ClosePageQuery返回False的時候使FormCloseQuery的CanClose為True。
則有如下代碼:
1 procedure TForm1.FormCloseQuery(Sender: TObject; var CanClose: Boolean); 2 begin 3 while PageControl1.PageCount > 0 do 4 if not ClosePageQuery() then begin 5 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 do 2 if not ClosePageQuery() then 3 break;也可以把while和if合並。 保存 保存和另存為是兩回事。首先,另存為是無論文件是否是新建的,都會彈出保存對話框。 而保存就是TRecEdit的fPath是空字符串的時候,也就是文件是新建的時候彈出保存對話框。所以有:
1 pIndex := PageControl1.ActivePageIndex; 2 s := TRecEdit(PageControl1.Pages[pIndex].Controls[0]).fPath; 3 if s = '' then begin 4 if SaveDialog1.Execute then 5 TRecEdit(PageControl1.Pages[pIndex].Controls[0]).Lines.SaveToFile(SaveDialog1.FileName); 6 end else 7 if TRecEdit(PageControl1.Pages[pIndex].Controls[0]).Modified then 8 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: begin
101 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 begin
112 Result := ClosePageQuery(PageControl1.ActivePageIndex);
113 end;
114
115 procedure TForm1.CloseAll1Click(Sender: TObject);
116 begin
117 while PageControl1.PageCount > 0 do
118 if not ClosePageQuery() then
119 break;
120 if PageControl1.PageCount = 0 then begin
121 C1.Enabled := False;
122 L1.Enabled := False;
123 end;
124 end;
125
126 procedure TForm1.ClosePage1Click(Sender: TObject);
127 begin
128 ClosePageQuery(PageControl1.ActivePageIndex);
129 if PageControl1.PageCount = 0 then begin
130 C1.Enabled := False;
131 L1.Enabled := False;
132 end;
133 end;
134
135 procedure TForm1.FileOpen1Accept(Sender: TObject);
136 var
137 pIndex: Integer;
138 fName: string;
139 begin
140 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 var
151 pIndex: Integer;
152 sPath: string;
153 begin
154 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 begin
162 while PageControl1.PageCount > 0 do
163 if not ClosePageQuery() then begin
164 CanClose := True;
165 Exit;
166 end;
167 end;
168
169 procedure TForm1.FormCreate(Sender: TObject);
170 begin
171 n := 1;
172 N1.Click;
173 end;
174
175 procedure TForm1.N1Click(Sender: TObject); //新建
176 begin
177 Add1.Click;
178 PageControl1.ActivePage.Caption := '無標題' + IntToStr(n);
179 Inc(n);
180 end;
181
182 procedure TForm1.S1Click(Sender: TObject); //保存
183 var
184 s: string;
185 pIndex: Integer;
186 begin
187 with PageControl1 do begin
188 pIndex := ActivePageIndex;
189 s := TRecEdit(Pages[pIndex].Controls[0]).fPath;
190 if s = '' then begin
191 if SaveDialog1.Execute then begin
192 TRecEdit(Pages[pIndex].Controls[0]).Lines.SaveToFile(SaveDialog1.FileName);
193 TRecEdit(Pages[pIndex].Controls[0]).fPath = SaveDialog1.FileName;
194 end;
195 end else
196 if TRecEdit(Pages[pIndex].Controls[0]).Modified then
197 TRecEdit(Pages[pIndex].Controls[0]).Lines.SaveToFile(s);
198 ActivePage.Caption := ExtractFileName(s);
199 end;
200 end;
201
202 end.