第二十八章 開發新的VCL元件 雖然BCB內提供了很多VCL元件,但是一定還有一些我們常常需要用的介面並沒有製作成VCL元件,或是一些個人化的介面,我們也有需要做成VCL元件。在第十三章,我們將介紹如何自行開發新的VCL元件。
大綱 28-1. 製作VCL元件 28-2. 安裝VCL元件 28-3. 移除VCL元件 本章習題
前言 一般來說,當一個使用者使用BCB到一個程度以上,一定會覺得有些VCL元件是BCB本身所沒有的,就舉前幾章所提『檔案總管』這個介面來說好了。很多人都希望可以在網路上抓到檔案總管的VCL元件,假設你找到了,但是你知道該如何安裝使用嗎?如果你不想用了,是否又該將之移除呢?這種新增、刪除的方法,我們會在下面為各位介紹。 接下來就是自己製作VCL元件了,因為我們一定有很多元件是自己開發出來而且使用率非常的高,這時候我們就可以考慮將這個功能做成一個VCL元件來使用,如此可以增加往後我們開發程式的速度,更可以將我們的成果跟全世界所有的人一起分享使用。
28-1. 製作VCL元件 範例28-1:製作VCL元件 範例說明 製作VCL元件其實非常的容易,在範例程式28-1中,我們將實做一個可以顯示今天的日期以及今天是星期幾的元件,我們將這個新的元件稱做『TWeekDate』,如果要安裝新的VCL元件時,我們會將這個新的VCL元件放在Sample這個頁次中。
28-1. 製作VCL元件 範例28-1:製作VCL元件 Step 1: 選擇『New』來新增一個專案,在選擇專案類型的時候我們選擇『Component』這個項目 開啟Component這個項目後,會出現一個設定畫面,這個畫面主要是要讓我們設定一些有關這個Component的基本資料,如Class名稱、檔案位置等等
28-1. 製作VCL元件 範例28-1:製作VCL元件 基本設定說明 Ancestor type: 設定這個新Component的Parent是什麼Component。在這邊的設定就是表示我們新產生的這個VCL元件要繼承哪一個Class的屬性及事件等等。 Class Name: 我們這個VCL元件的Class要稱做什麼。例如Edit的就是TEdit這個Class,在程式範例28-1中我們將這個Class Name設定成TWeekDate。 Palette Page: 決定我們這個VCL元件要放在哪個頁次裡。 Unit file name: 這個VCL元件所用到的cpp file和header file在那個目錄內,以及指定cpp file的檔名。 Search Path: 搜尋VCL元件的路徑。
28-1. 製作VCL元件 範例28-1:製作VCL元件 該範例的設定值 Ancestor type: TStaticText Class Name: TWeekDate Palette Page: Samples Unit file name: <Directory>\WeekDate.cpp Search Path: <Default Directory>;<Directory> 注意事項 <Directory> 儲存WeekDate.cpp的檔案目錄 <Default Directory> 是系統預設值,原本就會在設定值內 當我們設定好Unit file name的時候,BCB很貼心的會幫我們將路徑一併加入到Search Path中,所以一般來說我們並不需要設定Search Path。
28-1. 製作VCL元件 範例28-1:製作VCL元件 Step 2: 設定完成,撰寫程式碼 在設定好所有的設定值後,我們按下『OK』的按鈕 在這邊不按下『Install』的原因是因為我們只有一個VCL元件的雛形,我們並沒有真正將VCL元件的內容或是程式碼寫好,所以就算安裝了,也只是安裝一個和Ancestor type中一模一樣的VCL元件在Palette Page頁單上面。 出現程式編輯器的畫面,而且此時BCB已經幫我們將一些程式碼Generate出來了!
28-1. 製作VCL元件 範例28-1:元件之主要程式碼(WeekDate.h) 在Header中加入適當的宣告 class PACKAGE TWeekDate : public TStaticText { private: protected: public: //如果有要加入一些VCL元件 //或是一些function的宣告都加在這邊 void __fastcall TWeekDate::Show(); __fastcall TWeekDate(TComponent* Owner); __published: };
28-1. 製作VCL元件 範例28-1:元件之主要程式碼(WeekDate.cpp) Create WeekDate元件 __fastcall TWeekDate::TWeekDate(TComponent* Owner) : TStaticText(Owner) { Caption = "今天是 " + DateToStr(Date()); }
28-1. 製作VCL元件 範例28-1:製作VCL元件 當我們將這些必要的程式碼都具備之後,接下來就是建立一個Project來使用我們的這個元件 Step 1: 將WeekDate.h和WeekDate.cpp都存檔並且關閉 Step 2: 建立新專案,並且修改設定 將『 WeekDate.cpp』加入Project中: Project選單內的『Add to Project』 將『WeekDate.h』include進入Project中 在Project中new一個TWeekDate物件 直接在該Project的Form的constructor中直接寫入需要的Code,而不是再去Create另外一個Event。 Step 3: 編譯並且執行該程式
28-1. 製作VCL元件 範例28-1:專案之主要程式碼(main.cpp) //--------------------------------------------------------------------------- #include <vcl.h> #pragma hdrstop #include "main.h" #include "WeekDate.h" //將WeekDate.h include進來 #pragma package(smart_init) #pragma resource "*.dfm" TForm1 *Form1; TWeekDate *WeekDate; //new一個TWeekDate的物件 __fastcall TForm1::TForm1(TComponent* Owner) : TForm(Owner) { //直接將code寫在constructor中 WeekDate = new TWeekDate(this); WeekDate->Parent = this; WeekDate->Top = 10; WeekDate->Left = 10; }
28-1. 製作VCL元件 範例28-1:製作VCL元件 執行結果
28-1. 製作VCL元件 範例28-1:製作VCL元件 除了基本的設計外,我們也可以增加一些屬性(Property)或是方法(Method)在這個元件中。 現在我們要新增的屬性是『Type』這個屬性,這個屬性用在設定顯示Week、Date、或是Week和Date一起顯示。 我們將在範例28-2告訴各位讀者該如何在我們自己的VCL元件中新增屬性。 在範例28-3中介紹該如何加入Method在該VCL元件中。 接下來我們在範例程式28-2和28-3的開發過程都跟上面的開發程序一樣,不一樣的地方只有在程式碼中,所以在底下我們將不詳述開發過程,而把重點放在說明程式碼上面。
28-1. 製作VCL元件 範例28-2:改善Code的撰寫方式 範例說明 在範例28-2的WeekDate.h中,我們獨立了一個Show的函式出來,這函式呈現的效果其實就是範例28-1直接寫在Constructor中那行程式的效果(CH28_001\WeekDate.cpp中關於TWeekDate的Constructor中的那行程式)。 在這個範例會獨立出來最主要是因為在這個範例(範例28-3也是)中關於顯示部分的程式碼比較多,所以我們將之拿出來成為一個獨立的函式,程式碼比較容易閱讀,在以後的維護上也會比較方便。 『__property int Type = {read = SType, write = SetType, default = 0};』這一行最主要是要告訴程式,我們的Type是由SType指定,而且由SetType這個函式處理,預設值是0,這個宣告很重要,關係到整個屬性是否能正常運作。
28-1. 製作VCL元件 範例28-2:主要程式碼(WeekDate.h) class PACKAGE TWeekDate : public TStaticText { private: int SType; //屬性在程式中的變數 void __fastcall SetType(int type); //設定屬性的函式 protected: public: void __fastcall TWeekDate::Show(); //顯示時間的函式 //底下這個宣告是設定整個屬性的動作 //例如讀取SType這個變數 //它是利用SetType去設定屬性,預設值是0 __property int Type = {read = SType, write = SetType, default = 0}; __fastcall TWeekDate(TComponent* Owner); __published: };
28-1. 製作VCL元件 範例28-2:主要程式碼(WeekDate.cpp) __fastcall TWeekDate::TWeekDate(TComponent* Owner) : TStaticText(Owner) { Show(); //執行顯示結果的函式 } //--------------------------------------------------------------------------- void __fastcall TWeekDate::Show() { AnsiString days[7] = {"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday" }; switch (SType) { //利用SType告訴程式要顯示什麼樣的畫面 case 0 : Caption = "今天是 " + DateToStr(Date()); break; case 1 : Caption = "今天是 " + days[Date().DayOfWeek() - 1]; break; case 2 : Caption = "今天是 " + DateToStr(Date()) + " " + days[Date().DayOfWeek() - 1]; break; default : Caption = "今天是 " + DateToStr(Date()); void __fastcall TWeekDate::SetType(int type) { SType = type; //設定SType的值 Show(); //設定SType後就直接顯示時間
28-1. 製作VCL元件 範例28-2:改善Code的撰寫方式 當我們設計好WeekDate.cpp和WeekDate.h之後,跟範例28-1一樣,接下來的動作就是產生一個Project來負責處理開VCL元件的顯示。在範例28-2裡,我們主要放置一個下拉式選單和一個Button來決定要以什麼樣的方式來顯示日期和時間。
28-1. 製作VCL元件 範例28-2:主要程式碼(main.cpp) #include "WeekDate.h" //將所需要的header file include進來 TWeekDate *WeekDate; //宣告一個TWeekDate物件 //--------------------------------------------------------------------------- __fastcall TForm1::TForm1(TComponent* Owner) : TForm(Owner) { WeekDate = new TWeekDate(this); //將WeekDate new出來 WeekDate->Parent = this; WeekDate->Top = 10; WeekDate->Left = 10; } void __fastcall TForm1::Button1Click(TObject *Sender) { //根據ComboBox選的項目的不同而有不同的Type switch (ComboBox1->ItemIndex) { case 0 : WeekDate->Type = 0; break; case 1 : WeekDate->Type = 1; break; case 2 : WeekDate->Type = 2; break;
28-1. 製作VCL元件 範例28-2:改善Code的撰寫方式 執行結果
28-1. 製作VCL元件 範例28-3:實作一個VCL元件中的Method 範例說明 在範例程式28-3中我們要做的就是在VCL元件上實做一個Method出來,這個新增的Method是『SetColor』。利用這個方法我們可以很輕易的設定所顯示出來的文字的顏色。 在WeekDate.h中,大部分都跟範例28-2一樣,只是在public那邊加了一個function進去,這個function的名稱就是『SetColor』。
28-1. 製作VCL元件 範例28-3:主要程式碼(WeekDate.h) class PACKAGE TWeekDate : public TStaticText { private: int SType; void __fastcall SetType(int type); protected: public: void __fastcall TWeekDate::Show(); __property int Type = {read = SType, write = SetType, default = 0}; //底下的宣告就是該VCL元件中設定顏色的Method void __fastcall TWeekDate::SetColor(int index, int type); __fastcall TWeekDate(TComponent* Owner); __published: };
28-1. 製作VCL元件 範例28-3:主要程式碼(WeekDate.cpp) __fastcall TWeekDate::TWeekDate(TComponent* Owner) : TStaticText(Owner) { Show(); //執行顯示結果的函式 } //--------------------------------------------------------------------------- void __fastcall TWeekDate::Show() { AnsiString days[7] = {"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday" }; switch (SType) { //利用SType告訴程式要顯示什麼樣的畫面 case 0 : Caption = "今天是 " + DateToStr(Date()); break; case 1 : Caption = "今天是 " + days[Date().DayOfWeek() - 1]; break; case 2 : Caption = "今天是 " + DateToStr(Date()) + " " + days[Date().DayOfWeek() - 1]; break; default : Caption = "今天是 " + DateToStr(Date()); void __fastcall TWeekDate::SetType(int type) { SType = type; //設定SType的值 Show(); //設定SType後就直接顯示時間
28-1. 製作VCL元件 範例28-3:主要程式碼(WeekDate.cpp) void __fastcall TWeekDate::SetColor(int index, int Type) { switch (index) { //根據不同的顏色和項目做不同的設定 case 0 : if (Type) Font->Color = clAqua; else Color = clAqua; break; case 1 : if (Type) Font->Color = clBlack; else Color = clBlack; break; case 2 : if (Type) Font->Color = clBlue; else Color = clBlue; break; case 3 : if (Type) Font->Color = clDkGray; else Color = clDkGray; break; case 4 : if (Type) Font->Color = clFuchsia; else Color = clFuchsia; break; case 5 : if (Type) Font->Color = clGray; else Color = clGray; break; case 6 : if (Type) Font->Color = clGreen; else Color = clGreen; break; case 7 : if (Type) Font->Color = clLime; else Color = clLime; break; case 8 : if (Type) Font->Color = clLtGray; else Color = clLtGray; break; case 9 : if (Type) Font->Color = clMaroon; else Color = clMaroon; break; case 10 : if (Type) Font->Color = clNavy; else Color = clNavy; break; case 11 : if (Type) Font->Color = clOlive; else Color = clOlive; break; case 12 : if (Type) Font->Color = clPurple; else Color = clPurple; break; case 13 : if (Type) Font->Color = clRed; else Color = clRed; break; case 14 : if (Type) Font->Color = clSilver; else Color = clSilver; break; case 15 : if (Type) Font->Color = clTeal; else Color = clTeal; break; case 16 : if (Type) Font->Color = clWhite; else Color = clWhite; break; case 17 : if (Type) Font->Color = clYellow; else Color = clYellow; break; } }
28-1. 製作VCL元件 範例28-3:主要程式碼(main.cpp) #include "WeekDate.h" //將所需要的header file include進來 TWeekDate *WeekDate; //宣告一個TWeekDate物件 //--------------------------------------------------------------------------- __fastcall TForm1::TForm1(TComponent* Owner) : TForm(Owner) { WeekDate = new TWeekDate(this); //將WeekDate new出來 WeekDate->Parent = this; WeekDate->Top = 10; WeekDate->Left = 10; } void __fastcall TForm1::Button1Click(TObject *Sender) { switch (ComboBox1->ItemIndex) { //根據ComboBox選的項目的不同而有不同的Type case 0 : WeekDate->Type = 0; break; case 1 : WeekDate->Type = 1; break; case 2 : WeekDate->Type = 2; break; void __fastcall TForm1::Button2Click(TObject *Sender) { WeekDate->SetColor(ComboBox2->ItemIndex, 1); //設定前景色 void __fastcall TForm1::Button3Click(TObject *Sender) { WeekDate->SetColor(ComboBox3->ItemIndex, 0); //設定背景色
28-1. 製作VCL元件 範例28-3:實作一個VCL元件中的Method 執行結果
28-1. 製作VCL元件 在這三個範例我們都是採用StaticText作為輸出的格式,所以選擇的Ancestor type這個屬性就是用TstaticText,如果各位讀者有其他的需求,可以自行改變喔! 如果是要顯示出VCL元件,則記得要在元件的header file中先宣告好,然後在元件的cpp file中都要採用動態產生的方式來產生(使用new這個語法)。
28-2. 安裝VCL元件 上一小節我們教會大家如何發展一個VCL元件,發展後一定要安裝起來才能使用,不然跟一般的Application根本沒有什麼差別。 但是在安裝之前還有一件重要的事情,那就是每個VCL元件都有一個屬於自己的logo,像StaticText有他自己的圖示,Edit也有自己的圖示,當然我們自己寫的WeekDate也要有自己的圖示才可以囉!在這邊若是沒有提供logo,BCB會主動以Ancestor type所設定的Component的logo作為預設值。
28-2. 安裝VCL元件 在BCB中有提供製作Logo的工具供我們使用,這套工具就是『Image Editor』。Image Editor的位置在程式集中BCB的選單內可以找到。
28-2. 安裝VCL元件 在使用Image Editor的第一步,我們必須先開一個VCL的專案,也就是在New中的『Component Resource File』,選擇好之後會出現一個畫面讓我們可以開始設定圖片的一些參數。 接著在Contents上按滑鼠右鍵,並且選擇New底下的Bitmap這個選項,然後會出現一個設定對話窗,這個對話窗主要是設定我們需要多大的圖案,在這邊因為VCL Logo的大小是24x24,所以我們在這邊就將大小設定成24x24,另外,為了顯示的顏色數目夠多,我們也將Color設定成SuperVGA的模式。
28-2. 安裝VCL元件 接著我們將所有的樹狀圖都展開,在最下層的那個Node上輕輕的用滑鼠點一下,將名稱改成『TWEEKDATE』。 在這個Node上連續點兩下,就會出現編輯畫面,這時候大家就可以利用Image Editor所提供的一些工具和顏色來設計我們所要的Logo。 最後,我們要將這個設計圖存檔,記住,存檔的地方要和我們要加入的原始檔案在同一個目錄,而且名稱也要一樣。例如我們在範例28-3中,因為我們VCL的原始檔案叫做『WeekDate.cpp』,所以在這邊我們的這個資源檔應該要叫做『WeekDate.dcr』。 如果不叫這個檔名,我們必須在設計VCL的原始檔案時,在程式的前面加入『#pragma resource "dcr file name"』。
28-2. 安裝VCL元件 VCL元件的圖示做完了,我們就必須把這個VCL元件安裝起來,這樣才能顯示出VCL元件的功能。 在這一部份,我們將告訴大家,該如何將我們發展出來的VCL元件加入到BCB上面的VCL面板中。 首先,選取主選單下的Component下的Install Component,然後會出現對話視窗,主要是要我們選擇一個已經存在的VCL元件。在這邊我們選擇範例28-3裡面的『WeekDate.cpp』,也就是說,在這個畫面我們必須在Unit file name選擇該VCL元件的程式碼。另外也要再次注意一下Search path有沒有正確指到我們要加入的這個VCL元件的目錄。 以上這兩個都設定結束後,我們就可以按下OK來開始進行安裝的動作。在這邊如果你想要安裝在其他的Package File中也可以,這個設定對話窗中有兩個頁面,另一個頁面就是可以新增一個我們所想要的新的Package檔案。
28-2. 安裝VCL元件 當我們在設定對話窗中按下OK之後,BCB會跳出程式編輯器,並且開啟有關這個Package的檔案。 接著就會跳出一個對話窗出來問你,是不是要繼續Package Build的動作,這個動作最主要就是要將我們所選的VCL元件加入目前BCB的Package當中,所以在這邊我們當然是選擇『Yes』繼續我們的安裝動作。 等到BCB將Package Build完成後,會再出現一個對話窗和使用者確定已經新增一個名叫TWeekDate的VCL元件。最後很重要的一點要注意,就是這時候要記得儲存檔案一次,不然Package的專案內容可能會出現問題。
28-2. 安裝VCL元件 範例28-4:使用我們自己創造的VCL元件 範例說明 我們在範例28-4中用很簡單的方式開一個專案出來,並且馬上使用TWeekDate這個元件。 很簡單吧。還可以進入程式編輯器中查查看,是不是這個VCL元件內也有我們自己所新增的『Type』屬性以及『SetColor』這個Method!
28-3. 移除VCL元件 學會如何安裝也該學會如何移除,所以在這一小節內我們將教大家如何移除已經安裝的VCL元件。 首先我們先到BCB目錄下Lib的目錄內選擇『dclusr.bpk』這個檔案,並且將他開啟,開啟之後除了會出現一個程式編輯器外,比較重要的是Package的視窗,這個視窗可以告訴我們目前我們自己安裝了哪些VCL元件。
28-3. 移除VCL元件 當我們想要移除這些自己安裝的VCL元件時,也是從這個Package視窗下手。我們利用滑鼠在我們想要移除的元件上按一下右鍵,這時候會出現一個popup menu出來,上面有許多選項可以讓我們選,我們在這邊選擇『Remove From Project』將我們選取的檔案從Package中移除,這樣移除就等於將這個VCL元件從我們的VCL面板中移除掉了。
28-3. 移除VCL元件 當你選擇Remove之候,系統會跳出一個確認畫面再次向使用者確定是不是真的要移除這個檔案。在這個範例中,我們需要移除兩個檔案,分別是『WeekDate.cpp』和『WeekDate.dcr』這兩個檔案。 當我們將不需要的檔案移除後,千萬不要忘了要按一下圖13-24上方的Compile的按鈕,Compile好的時候會出現一個對話窗告知我們已經編譯完成。如果在這邊沒有按下Compile這個按鈕,那就等於做白工了。當然也不可以忘了要按一下Save鈕,作用跟上面新增的時候一樣,都是為了避免Package的專案內容出問題。
本章習題 請到網路上找三個以上提供Free的VCL元件的網站。 請從那些網站上抓下幾個VCL元件,並且安裝到自己的BCB內。