後一頁 前一頁 回目錄 回首頁 |
3. 建立新的訊息處理方法 因為Delphi只為大多數普通Windows訊息提供了處理方法,所以當你定義自己的訊息時,就要建立新的訊息處理方法。 用戶自定義訊息的過程包括兩個方面: ● 定義自己的訊息 ● 聲明新的訊息處理方法
⑴ 定義自己的訊息 許多標準部件為了內部使用定義了訊息。定義訊息的最一般的動因是廣播資訊和狀態改變的通知。 定義訊息過程分兩步: ● 聲明訊息標識符 ● 聲明訊息記錄型式
① 聲明訊息標識 訊息標識是整型大小的常數。Windows存檔了小於1024的訊息用於自己使用,因此當聲明自己的訊息時,你應當大於1024。 常數WM_USER代表用於自定義訊息的開始數字。當定義訊息標準時,你應當基於WM_USER。 某些標準Windows控制使用用戶自定義範圍的訊息,包括ListBox、ComboBox、EditBox和Button。如果從上述部件中繼承了一個部件,在定義新的訊息時,應當檢查一下Message單元是否有訊息用於該控制。 定義訊息的方法如下:
Const WM_MYFIRSTMESSAGE=WM_USER+0; WM_MYSECONDMESSAGE=WM_USER+1;
② 聲明訊息記錄型式 如果你想給予自定義訊息的參數有含義的名字,就要為該訊息聲明訊息記錄型式。訊息記錄是傳給訊息處理方法的參數的型式。如果不使用訊息參數或者想使用舊風格參數,可以使用缺省的訊息記錄。 聲明訊息記錄型式要遵循下列規則 ● 以訊息名命名訊息記錄型式,以T打頭 ● 將記錄中第一個欄位命名為Msg,型式為TMsgPraram ● 將接著的兩個位元群組定義為word 以響應word大小的參數 ● 將接著的四個位元群組與long參數匹配 ● 將最後的欄位命名為Result,型式為Longint
下面是TWMMouse的定義
type TWMMouse=record Msg: TMsgParam; { 第一個是訊息ID } Keys: Word; { wParam } case Integer of { 定義lParam的兩種方式 } o: ( Xpos: Integer; { 或者以x,y座標 } Ypos: Integer); 1: ( Pos : TPoint; { 或者作為單個點 } Result: Longint; ) { 最後是Result欄位 } end;
TWMMouse使用變長記錄定義了相同參數的不同名字集。 ⑵ 聲明新的訊息處理方法 有兩類環境需要你定義新的訊息處理方法: ● 自定義新部件需要處理沒有被標準部件處理的Windows訊息 ● 已定義了自定義部件使用的新訊息
聲明訊息處理方法的辦法如下: ● 在部件聲明中的protected部分聲明方法 ● 將方法做成過程 ● 以要處理的訊息名命名方法 但不帶底線 ● 傳遞一個命名為Message的var參數,型式為訊息記錄型式 ● 編寫用於該部件的特別處理代碼 ● 呼叫繼承的訊息方法
下面是用於用戶自定義訊息CM_CHANGECOLOR的訊息處理代碼:
type TMyComponent=class(TControl) … protected procedure CMChangeColor(var Message:TMessage); message CM_CHANGECOLOR; end:
procedure TMyComponent.CMChangeColor(var Message: TMessage); begin color := Message lParam; inherited; end;
19.2.2.4 註冊部件
編寫部件及其屬性、方法和事件只是部件建立過程的一部分。儘管部件具有這些特征就可用,但部件真正功能強大的是在設計時操作它們的能力。 使部件在設計時可用需要經過如下幾步: ● 用Delphi註冊部件 ● 增加選擇板點陣圖 ● 提供有關屬性和事件的輔助敘述 ● 存貯和讀取屬性
1. 用Delphi註冊部件 為了讓Delphi識別自定義部件,並將它們放置於Component Palette上,你必須註冊每一個部件。 註冊一個部件要在部件所在單元裏加入Register方法,這包括兩個方面的內容: ● 聲明註冊過程 ● 實現註冊過程
一旦裝設了註冊過程,就可以將部件裝設在選擇板上。 註冊過程要在部件所在單元中寫一個過程,該過程必須以Register命名。Register必須出現在庫單元的interface部分,這樣Delphi就能定位它。在Register過程中,可以為每個部件呼叫過程RegisterComponents。 下面的代碼演示了建立和註冊部件的概略方法:
unit MyBtns;
interface
type … { 聲明自定義部件 } procedure Register;
Implementation
procedure Register; begin … { 註冊部件 } end;
end.
在Register過程中,必須註冊每一個要加入Component Palette的部件,如果庫單元包含若干部件,就要將它們一次性註冊。 註冊一個部件時,為部件呼叫RegisterComponents過程。RegisterComponents告訴Delphi兩件有關所註冊的部件的事:: ● 要註冊部件所在的Component Palette的頁名 ● 要裝設的部件的名字
選擇板的頁名是個字元串。如果你所給名字的頁不存在,Delphi就用該名字建立新的頁。 下面的Register過程註冊了一個名為TMyComponent的部件,並將其放在名為“Miscellaneous”的Component Palette頁上。
procedure Register; begin RegisterComponents('Miscellaneous', [TFirst, TSecond]); end;
也可以在相同的頁上,或者在不同的頁上,一次註冊多個部件:
procedure Register; begin RegisterComponents('Miscellaneous', [TFirst, TSecond]); RegisterComponents('Assorted', [TThird]); end;
2. 增加Component Palette上的點陣圖 每個部件都需要一個點陣圖來在Component Palette上代表它。如果裝設時沒有描述自己的點陣圖,則Delphi會自動套用缺省點陣圖。 因為選擇板點陣圖只有在設計時需要,所以沒有必要將它們編譯進庫單元。而是將它們提供在與庫單名相同的Windows資源文件中,檔案附加名為.DCR。用Delphi的點陣圖編輯器來產生資源文件,每個點陣圖邊長24個像素。 為每個要裝設的庫單元提供一個選擇板點陣圖文件,在每個文件中為每個要註冊的部件提供一個點陣圖。點陣圖影像名與部件名相同,將文件放在與庫單元相同的目錄中,這樣在裝設部件時Dephi就能發現點陣圖。 例如,如果你在ToolBox單元中建立一個名為TMyControl的部件,就需要建立名為TOOLBOX.DCR的資源文件,文件中包含名為TMyControl的點陣圖。 3. 提供有關屬性和事件的輔助敘述 當在窗體中選擇一個部件或在Object Inspector中選擇事件或屬性時,能夠按F1得到有關這一項的輔助敘述。如果建立了相應的Help文件的話,自定義部件的用戶能得到有關你的部件的相應的文檔。 因為Delph使用了特殊的Help引擎支援跨多個Help文件處理主題搜索,所以你能提供關於自定義部件的小的Help文件,用戶不需要額外的步驟就能找到你的文檔。你的Help成了Delphi Help系統的一部分。 要給用戶提供輔助敘述,要理解下列兩方面: ● Delphi怎樣處理HELP請求 ● 將HELP插入Delphi
⑴ Delphi怎樣處理HELP請求 Delphi基於關鍵詞查詢HELP請求。就是說,當用戶在窗體設計視窗的已選部件上按F1鍵時,Delpdi將部件的名字轉換成一個關鍵詞,然後呼叫Windows Help引擎找到那個關鍵詞的輔助敘述主題。關鍵詞是Windows Help系統的標準部分。實際上 ,WinHelp使用Help中的關鍵詞產生Search對話方塊中的清單。因為用於上下文敏感搜索中的關鍵詞不是實際供用戶讀的,所以要輸入關鍵詞的替代詞。 例如,一個找到名為TSomething的部件的詳細資訊的用戶可能打開WinHelp的Search對話方塊並輸入TSomething。但不會使用用於窗體設計視窗的上下文找到的替代形式class-TSomething。因此,這個特殊的關鍵詞Class-TSomething對用戶是不可見的,以免弄亂了搜索清單。 ⑵ 將Help插入Delphi Delphi提供了建立和插入Windows Help文件的工具,包括Windows Help編譯器HC.EXE。為自定義部件建立Help文件的機制與建立任何Help文件沒什麼不同,但需要遵循一些約定以與庫中其它Help相容。 保持相容性的方法如下: ● 建立Help文件 ● 增加特殊的註腳 ● 建立關鍵詞文件 ● 插入Help索引
當你為自定義部件建立完Help,有下列幾個文件: ● 編譯過的Help(.HLP)文件 ● Help關鍵詞(.KWF)文件 ● 一個或多個Help源文件(.RTF) ● Help工程文件(.HLJ)
編譯過的Help文件和關鍵詞文件應當與庫單元在同一目錄。 ① 建立Help文件 你可以使用任何的工具建立Windows Help文件。Delphi的多文件搜索引擎,可以包含任何數目的Help文件的要素。在編譯的Help文件之外,你應當擁有RTF源文件,這樣才能產生關鍵詞文件。 為使自定義部件的Help同庫中其它部件一起工作,要遵循下列約定: ● 每個部件有佔一頁的輔助敘述 部件輔助敘述頁應當給出部件目的的簡單描述,然後列出最終用戶可用的屬性、事件和方法的描述。應用開發者通過在窗體上選擇部件並按F1存取這一頁。 部件輔助敘述頁應當有一個用於關鍵詞搜索的“K”注腳,注腳中包含部件名。例如,TMemo的關鍵詞注腳讀作"TMemo Component" ● 部件增加和修改的每一個屬性,事件和方法應當有一頁輔助敘述 屬性、事件或方法的輔助敘述頁應當指出該項用於哪個部件,顯示聲明語法和描述它的使用方法。 屬性、事件或方法的輔助敘述頁應當有一個用於關鍵詞搜索的“K”注腳,該注腳中包含該項的名字和種類。例如,屬性Top的關鍵詞注腳為“Top property”。 Help文件的每一頁也需要用於多文件索引搜索的特殊注腳。 ② 增加特殊注腳 Delphi需要特殊的搜索關鍵詞以區別用於部件的輔助敘述頁和其它項目。你應當為每一項提供標準的關鍵詞搜索項。但你也需要用於Delphi的特殊注腳。 要為來自Object Inspector視窗或代碼編輯器F1的搜索增加關鍵詞,就得為Help文件輔助敘述頁增加"B"注腳。 “B”注腳與用於標準WinHelp關鍵詞搜索的“K”注腳很相象,但它們只用於Delphi搜索引擎。下表列出怎樣為每種部件輔助敘述頁建立“B”注腳:
表19.7 部件輔助敘述頁搜索註腳 ────────────────────────────────── 輔助敘述頁型式 "B"注腳內容 示 例 —————————————————————————————————— 主部件頁 'class_'+部件型式名 class_TMemd 一般屬性或事件頁 'prop_'+屬性名 prop_WordWrap 'event_'+事件名 event_OnChange 部件特有的屬性 'prop_'+部件型式名 prop_TMemoWordWrap 或事件頁 +屬性名 'event_'+部件型式名 event_TMemoOnChange +事件名 ──────────────────────────────────
區別一般輔助敘述頁和部件特有的輔助敘述頁是很重要的。一般輔助敘述頁應用於所有部件上的特定屬性和事件。例如Left屬性是所有部件中的標識。因此,它用字元串Prop-Left進行搜索。而Borde-style依賴於所屬的部件,因此,BorderStyle屬性擁有自己的輔助敘述頁。例如,TEdit有BorderStyle屬性的輔助敘述頁,搜索字元串為Prop_TEditBorderStyle。 ③ 建立關鍵詞文件 建立和編譯了Help文件,並且增加了注腳之後,還要產生獨立的關鍵詞文件,這樣Delphi才能將它們插入主題搜索的索引。 從Help資源文件RTF建立關鍵詞文件的方法如下: ● 在DOS提示行下,進入包含RTF文件的目錄 ● 執行關鍵詞文件產生程式????KWGEN.EXE,後跟Help工程文件,如KWGEN SPECIAL.HPJ。當KWGEN執行完畢後,就有了與Help工程文件相同的關鍵詞文件,但以.KWF為檔案附加名 ● 將關鍵詞文件放在編譯完的庫單元和Help文件相同的目錄 當你在Component Palette上裝設部件時,希望關鍵詞插入Delphi Help系統的搜索索引。
④ 插入Help索引 以自定義部件建立關鍵詞文件後,要將關鍵詞插入Delphi的Help索引。 將關鍵詞文件插入Detphi Help索引的方法如下: ● 將關鍵詞文件放在與編譯完的庫單元和Heph文件相同的目錄中 ● 執行HELPINST程式
HELPINST執行完後,Delphi的Help索引文件(.HDX)包含自定義部件輔助敘述頁的關鍵詞。 ⑶ 存儲和載入屬性 Delphi將窗體及其擁有的部件存儲在窗體文件(.DFM)中,DFM文件用二進制表示窗體的屬性和它的部件。當Delphi用戶將自定義部件加入窗體中時,自定義部件應當具有存儲它們的屬性的能力。同樣,當被調入Delphi或應用程式時,部件必須能從DFM文件中恢復它們。 在大多數時候,不需要做任何使部件讀寫DFM文件的事。存儲和載入都是繼承的祖先部件的行為的一部分。然而在某些情況下,你可能想改變部件存儲和載入時初始化的方法。因此,應當理解下述的機制: ● 存儲和載入機制 ● 描述缺省值 ● 決定存儲什麼 ● 載入後的初始化
① 存儲和載入機制 當應用開發者設計窗體時,Delphi將窗體的描述存儲在DFM文件中。當用戶執行程式時,它讀取這些描述。 窗體的描述包含了一系列的窗體屬性和窗體中部件的相似描述。每一個部件,包括窗體本身,負責存儲和載入自身的描述。 在缺省情況下,當存儲時,部件將所有public和published屬性的不同於缺省值的值以聲明的順序寫入。當載入時,部件首先構造自己,並將所有屬性設為缺省值;然後,讀存儲的、非缺省的屬性值。 這種缺省機制,滿足了大多數部件的需要,而又不需部件編寫者的任何工作。然而自己定義存儲和載入過程以適合自定義部件需要的方法也有幾種。 ② 描述缺省值。 Delphi部件只存儲那些屬性值不同於缺省值的屬性。如果你不描述,Delphi假設屬性沒有缺省值,這意味著部件總是存儲屬性。 一個屬性的值沒被構造函數設定,則被假設為零值。為了描述一個缺省值,在屬性聲明後面加default指令和新的缺省值。 你也能在重聲明屬性時描述缺省值。實際上,重聲明屬性的一個原因是指定不同的缺省值。只描述缺省值,那麼在物件建立時並不會自動地給屬性賦值,還需要在部件的Create方法中賦所需的值。 下面的代碼用Align屬性演示了描述缺省值的過程.
type TStatusBar=class(TPanel) public constructor Create(Aowner: TComponent); override; { 覆蓋以設定新值 } published property Align default alBottom; { 重新聲明缺省值 } end;
constructor TStatusBar.Create(Aowner: TComponent); begin inherited Create(Aowner); { 執行繼承的初始化過程 } Align := alBottom; { 為Align賦新的缺省值 } end;
③ 決定存儲什麼 用戶也可以控制Delphi是否存儲部件的每一個屬性。缺省情況下,在物件的published部分聲明的所有屬性都被存儲。然而,可以選擇不存儲所給的屬性,或者設計一個函數在執行時決定是否存儲屬性。 控制Delphi是否存儲屬性的方法是在屬性聲明後面加stored指令,後跟True或False,或者是布爾方法名。你可以給任何屬性的聲明或重聲明加stored表達式。下面的代碼顯示了部件聲明三種新屬性。一個屬性是總是要存儲,一個是不存,第三個則決定於布爾方法的值:
type TSampleCompiment = class(TComponent) protected function storeIt: Boolean; public { 正常情況下在不存 } property Important: Integer stored True; { 總是存儲 } published { 正常情況下存檔 } property UnImportant: Integer stored False; { 不存 } property Sometimes: Integer stored StoreIt; { 存儲依賴於函數值 } end;
④ 載入後的初始化 在部件從存儲的描述中讀取所有的屬性後,它呼叫名為Loaded的虛方法,這提供了按需要執行任何初始化的機會。呼叫Loaded是在窗體和它的控制顯示之前,因此,不需要擔心初始化會帶來螢幕閃爍。 在部件載入屬性時初始化它,要覆蓋Loaded方法。 在Loaded方法中,要做的第一件事是呼叫繼承的Loaded方法。這使得在你的部件執行初始化之前,任何繼承的屬性都已初始化。 下面的代碼來自於TDatabase部件。在載入後,TDatabase試圖重建在它存儲時已打開的連接,並描述在連接發生異常時如何處理。
procedure TDatabase.Loaded begin inherited Loaded; { 總是先呼叫繼承的方法 } Modified; { 設定內部標誌 } try if FStreamedConnected then Open; { 重建聯接 } except if csDesigning in ComponentState then { 在設計時 } Application.HandleException(self) { 讓Delphi處理異常 } else raise; { 否 則 } end; end;
19.3 Delphi部件程式設計實例
19.3.1 建立資料庫相關的日曆控制-TDBCalendar
當處理資料庫聯接時,將控制和數據直接相聯是很重要的。就是說,應用程式可以建立控制與資料庫之間的鍊。Delphi包括了數據相關的標籤、編輯框、列示方塊和柵格。用戶可以使自己的控制與數據相關。 數據相關有若干等級。最簡單的是唯讀數據相關或數據瀏覽,以及反映資料庫目前狀態的能力。比較複雜的是數據相關的編輯,也即用戶可以在控制上操作資料庫中的數據。 在本部分中將示例最簡單的情況,即建立聯接資料庫的單個欄位的唯讀控制。本例中將使用Component Palette的Samples頁中的TCalendar部件。 建立數據相關的日曆控制包括下列幾步: ● 建立和註冊部件 ● 使控制唯讀 ● 增加數據聯接(Data Link) ● 響應數據改變
19.3.1. 1建立和註冊部件
每個部件的建立都從相同的方式開始,在本例中將遵循下列過程: ● 將部件庫單元命名為DBCal ● 從TCalendar繼承一個新部件,名為TDBCalendar ● 在Component Palette的Samples頁中註冊TDBCalendar
下面就是建立的代碼:
unit DBCal;
interface
uses SysUtils, WinTypes, WinProc, Messages, Classes, Graphics, Controls, Forms, Grids, Calendar; type TDBCalendar=class(TCalendar) end;
procedure Register;
implementation
procedure Register; begin RegisterComponents(Samples,[TDBabendar]); end;
end.
19.3.1.2 使控制唯讀
因為這個數據日曆以唯讀方式響應數據,所以用戶不能在控制中改變數據並指望它們反映到資料庫中。 使日曆唯讀包含下列兩步: ● 增加唯讀屬性 ● 允許所需的更新
1. 增加唯讀屬性 給日曆控制增加唯讀選項是直接過程。通過增加屬性,可以提供在設計時使控制唯讀的方法,當屬性值被設為True,將使控制中所有元素不可被選。 ⑴ 增加屬性聲明和存檔值的private欄位:
type TDBCalendar=class(TClendar) private FReadOnly: Boolean; public constructor Create (Aowner: TComponent); override; published property ReadOnly: Boolean read FReadOnly write FReadOnly default True; end;
constructor TDBCalendar.Create(Aowner: TComponent); begin inherited Create(AOwner); FReadOnly := True; end;
⑵ 覆蓋SelectCell方法,使得當控制是唯讀時,不允許選擇:
function TDBCalendar.SelectCell(ACol, Arow: Longint): Boolean; begin if FReadOnly then Result := False else Result := inherited SelectCell(Acol,ARow); end;
還要在TDBcalendar的聲明中聲明SelectCell。 如果現在將Calendar加入窗體,會發現部件完全忽略滑鼠和擊鍵事件,而且當改變日期時,也不能改變選擇的位置。下面將使控制響應更新。 2. 允許所需的更新 唯讀日曆使用SelectCell方法實現各種改變,包括設定Row和Col的值。當日期改變時,UpdateCalendar方法設定Row和Col的值,但因為SelectCell不允許你改變,即使日期改變了,選擇仍留在原處。 可以給日曆增加一個Boolean標誌,當標誌為True時允許改變:
type TDBCalendar=class(TCalendar) private Fupdating: Boolean; protected function SelectCell(Acol, Arow: Longint); Boolean; override; public procedure UpdateCalendar; override; end;
function TDBCalendar.SelectCell(ACol, ARow: Longint): Boolean; begin if (not FUpdating) and FReadOnly then Result := False { 如果更新則允許選擇 } else Result := inherited SelectCell(ACol, ARow); { 否則呼叫繼承的方法 } end;
procedure UpdateCalendar; begin FUpdating := True; { 將標誌設為允許更新 } try inherited UpdateCalendar; { 象通常一樣更新 } finally FUpdating := False; { 總是清除標誌 } end; end;
現在日曆仍舊不允許用戶修改,但當改變日期屬性時能正確反映改變;目前已有了一個真正唯讀控制,下一步是增加數據瀏覽能力。
3. 增加數據聯接 控制和資料庫的聯接是由一個名為DataLink的物件處理。Delphi提供了幾種型式的Datalink。將控制與資料庫單個欄位相聯的DataLink物件是TFieldDatalink。Delphi也提供了與整個表相聯的DataLink。 一個數據相關控制擁有DataLink物件,就是說,控制負責建立和析構DataLink。 要建立作為擁有物件的Datalink,要執行下列三步: ● 聲明物件欄位 ● 聲明存取屬性 ● 初始化DataLink
⑴ 聲明物件欄位 每個部件要為其擁有物件聲明一個物件欄位。因此,日曆物件DataLink 聲明TFieldDataLink型式的欄位。 日曆部件中DataLink的聲明如下:
type TDBCalendar = class(TSampleCalendar) private FDataLink: TFieldDataLink; … end;
⑵ 聲明存取屬性 每一個數據相關控制有一個DataSource屬性,該屬性描述應用程式給控制提供數據的數據源。而且,存取單個欄位的資料庫還需要一個DataField 屬性描述數據源中的欄位。 下面是DataSource和DataField的聲明和它們的實現方法:
type TDBCalendar = class(TSampleCalendar) private { 屬性的實現方法是 } function GetDataField: string; { 返回資料庫欄位的名字 } function GetDataSource: TDataSource; { 返回數據源(Data source)的引用 } procedure SetDataField(const Value: string); { 給資料庫欄位名賦值 } procedure SetDataSource(Value: TDataSource); { 給數據源賦值 } published { 使屬性在設計時可用 } property DataField: string read GetDataField write SetDataField; property DataSource: TDataSource read GetDataSource write SetDataSource; end;
……
function TDBCalendar.GetDataField: string; begin Result := FDataLink.FieldName; end;
function TDBCalendar.GetDataSource: TDataSource; begin Result := FDataLink.DataSource; end;
procedure TDBCalendar.SetDataField(const Value: string); begin FDataLink.FieldName := Value; end;
procedure TDBCalendar.SetDataSource(Value: TDataSource); begin FDataLink.DataSource := Value; end;
現在,就建立了日曆和DataLink的鍊,此外還有一個更重要的步驟。你必須在日曆構建時建立DataLink物件,在日曆析構時,復原DataLink物件。 ⑶ 初始化DataLink 在數據相關控制在其存在的期間要不停地存取DataLink物件,因此,必須在其構建函數中建立DataLink建立並且在析構時,復原DataLink物件,因此要覆蓋日曆的Create和Destroy方法。
type TDBCalendar=class(TCalendar) public constructor Create(Aowna: TComponent); override; destructor Destroy; override; end;
constructor TDBCalendar Create (Aowner: TComponent); begin inherited Create(AOwner); FReadOnly := True; FDataLink := TFieldDataLink.Create; end;
destructor TDBCalendar Destroy; begin FDataLink.Free; inherited Destroy; end;
現在,部件已擁有完整的DataLink,但部件還不知從相聯的欄位中讀取什麼數據。
19.3.1.4 響應數據變化
一旦控制擁有了數據聯接(DataLink)和描述數據源和數據欄位的屬性。就需在數據記錄改變時響應欄位中數據的變化。 DataLink物件都有個名為OnDataChange的事件。當數據源指示數據發生變化時,DataLink物件呼叫任何OnDataChange所聯接的事件處理過程。 要在數據改變時更新數據,就需要給DataLink物件的OnDataChange事件增加事件處理過程。 下面聲明了DataChange方法,並將其賦給DataLink物件的OnDataChange事件:
type TDBCalendar=class(TCalendar) private procedure Datachange(Sender: TObject); end;
constructor TDBCalendar Create(AOwner:TComponent); begin inherited Create(AOwner); FReadOnly := True; FDataLink := TFieldDataLink.Create; FDataLink.OnDataChange := DataChange; end;
destructor TDBcalendar.Destroy; begin FDataLink.OnDataChange := nil; FDataLink.Free; inherited Destroy end;
procedure TDBCalendar.DataChange(Sender: TObject); begin if FDataLink.Filed=nil then CalendarDate := 0; else CalendarDate := FDataLink.Field.AsDate; end; ; |
後一頁 前一頁 回目錄 回首頁 |