代碼編輯器(三)-PageControl和類

来源:http://www.cnblogs.com/Zory/archive/2016/02/11/5186456.html
-Advertisement-
Play Games

PageControl位於Win32選項卡中,可以在控制項上右鍵點擊“New Page”,來實現靜態的頁面添加。 先說說幾個重要的屬性: ActivePage:當前活動的頁面(在設計模式中切換頁面會更改ActivePage屬性) MultiLine:選項卡以多行形式顯示。 Style:頁面樣式。 ts


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 var
3   btn: TButton;
4 begin
5   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 type
2   TRecEdit = class(TMemo)
3   protected
4     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 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.

您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 原文地址 本文只是帶你進入 Scala 的世界,包括安裝、不可變變數 val、可變變數 var、定義類、集合(包括列表(list)、集(set)、映射(map))以及集合遍歷和集合庫(能達到並行/併發效果)。 題外話,如果 Java 爭氣的話,還就真不會出現像 Scala 這些語言。對於函數編程風格...
  • 作為一個開發者,我發現在我的日常工作中越來越多地查看PHP的源碼。在為了弄清楚奇怪的邊界問題和為什麼某些問題應該發生的卻沒有發生而去理解背後究竟發生了什麼事情的時候非常有用。在文檔缺失、不完整或者錯誤的情況下也很有用。因此,我已經決定通過一系列的文章來分享我學到的知識,給予PHP開發者們足夠的知識去...
  • C++Primer第5版學習筆記(三) 第四/五章的重難點內容 你可以點擊這裡回顧第三章內容 因為第五章的內容比較少,因此和第四章的筆記內容合併。 第四章是和表達式有關的知識,表達式是C++的基礎設施,本章由三部分組成: 1.表達式概念基礎,包括表達式的基本概念,左值和右值的概念,優先順序結合律,求值
  • 其實不是真的創建了批量任務,而是用python創建一個文本文件,每行一個要下載的鏈接,然後打開迅雷,複製文本文件的內容,迅雷監測到剪切板變化,彈出下載全部鏈接的對話框~~ 實際情況是這樣的,因為用python分析網頁非常,比如下載某頁中的全部pdf鏈接 1 from __future__ impor
  • C-Free和VC++ 6.0是根據源文件擴展名來編譯的。在學習C語言時,應將IDE的預設擴展名設置為.c,或者先保存為.c文件再進行編譯,以避免造成不必要的困惑。
  • 官網地址 本文內容 簡介 Futures 阻塞 異常 Promises 工具 最近看了《七周七語言:理解多種編程泛型》,介紹了七種語言(四種編程泛型)的主要特性:基本語法,集合,並行/併發,其中就有 Scala。你不能指望這種書全面介紹,因為其中任何一門語言都夠寫一本書了~ 我比較關註並行/併發,但
  • 1 /* 2 類是屬於用戶自定義的數據類型, 3 並且該類型的數據具有一定的行為能力, 4 也就是類中說描述的方法。 5 通常來說, 6 一個類的定義包含兩部分的內容, 7 一是該類的屬性, 8 另一部分是它所擁有的方法。 9 以 "人類" 這個類來說, 10 每個人都有自己的姓名、年齡、出生日期、
  • 本文實例講述了PHP實現上傳文件並存進資料庫的方法。分享給大家供大家參考。具體如下: show_add.php文件如下: <?php if(!isset($_REQUEST[''id'']) or $_REQUEST[''id'']=="") die("error: id none"); $id =
一周排行
    -Advertisement-
    Play Games
  • 基於.NET Framework 4.8 開發的深度學習模型部署測試平臺,提供了YOLO框架的主流系列模型,包括YOLOv8~v9,以及其系列下的Det、Seg、Pose、Obb、Cls等應用場景,同時支持圖像與視頻檢測。模型部署引擎使用的是OpenVINO™、TensorRT、ONNX runti... ...
  • 十年沉澱,重啟開發之路 十年前,我沉浸在開發的海洋中,每日與代碼為伍,與演算法共舞。那時的我,滿懷激情,對技術的追求近乎狂熱。然而,隨著歲月的流逝,生活的忙碌逐漸占據了我的大部分時間,讓我無暇顧及技術的沉澱與積累。 十年間,我經歷了職業生涯的起伏和變遷。從初出茅廬的菜鳥到逐漸嶄露頭角的開發者,我見證了 ...
  • C# 是一種簡單、現代、面向對象和類型安全的編程語言。.NET 是由 Microsoft 創建的開發平臺,平臺包含了語言規範、工具、運行,支持開發各種應用,如Web、移動、桌面等。.NET框架有多個實現,如.NET Framework、.NET Core(及後續的.NET 5+版本),以及社區版本M... ...
  • 前言 本文介紹瞭如何使用三菱提供的MX Component插件實現對三菱PLC軟元件數據的讀寫,記錄了使用電腦模擬,模擬PLC,直至完成測試的詳細流程,並重點介紹了在這個過程中的易錯點,供參考。 用到的軟體: 1. PLC開發編程環境GX Works2,GX Works2下載鏈接 https:// ...
  • 前言 整理這個官方翻譯的系列,原因是網上大部分的 tomcat 版本比較舊,此版本為 v11 最新的版本。 開源項目 從零手寫實現 tomcat minicat 別稱【嗅虎】心有猛虎,輕嗅薔薇。 系列文章 web server apache tomcat11-01-官方文檔入門介紹 web serv ...
  • 1、jQuery介紹 jQuery是什麼 jQuery是一個快速、簡潔的JavaScript框架,是繼Prototype之後又一個優秀的JavaScript代碼庫(或JavaScript框架)。jQuery設計的宗旨是“write Less,Do More”,即倡導寫更少的代碼,做更多的事情。它封裝 ...
  • 前言 之前的文章把js引擎(aardio封裝庫) 微軟開源的js引擎(ChakraCore))寫好了,這篇文章整點js代碼來測一下bug。測試網站:https://fanyi.youdao.com/index.html#/ 逆向思路 逆向思路可以看有道翻譯js逆向(MD5加密,AES加密)附完整源碼 ...
  • 引言 現代的操作系統(Windows,Linux,Mac OS)等都可以同時打開多個軟體(任務),這些軟體在我們的感知上是同時運行的,例如我們可以一邊瀏覽網頁,一邊聽音樂。而CPU執行代碼同一時間只能執行一條,但即使我們的電腦是單核CPU也可以同時運行多個任務,如下圖所示,這是因為我們的 CPU 的 ...
  • 掌握使用Python進行文本英文統計的基本方法,並瞭解如何進一步優化和擴展這些方法,以應對更複雜的文本分析任務。 ...
  • 背景 Redis多數據源常見的場景: 分區數據處理:當數據量增長時,單個Redis實例可能無法處理所有的數據。通過使用多個Redis數據源,可以將數據分區存儲在不同的實例中,使得數據處理更加高效。 多租戶應用程式:對於多租戶應用程式,每個租戶可以擁有自己的Redis數據源,以確保數據隔離和安全性。 ...