代碼編輯器(三)-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 MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...