熱點推薦:
您现在的位置: 電腦知識網 >> 編程 >> Delphi編程 >> 正文

DELPHI基礎教程:Delphi自定義部件開發(二)[3]

2013-11-23 17:48:15  來源: Delphi編程 

  Color屬性是靈活的它允許在Object Inspector窗口中以多種方式選擇他們或者鍵入或者從列表中選擇定編輯器因此TColorProperty的GetAttributes方法在返回值中包含多種屬性

  function TColorPropertyGetAttributes: TProrertyAttributes;

  begin

  Result := [PaMultiselect paDialog paValuelist];

  end;

  ⑸ 注冊屬性編輯器

  一旦創建屬性編輯器必須在Delphi中注冊注冊屬性編輯器時要與某種屬性相聯

  調用RegisterPropertyEditor過程來注冊屬性編輯器該過程接受四個參數

  ● 要編輯的屬性的類型信息的指針這總是通過調用調用TypeInfo函數得到如TypeInfo ( TMyComponent )

  ● 編輯器應用的部件類型如果該參數為nil則編輯器應用於所給的類型的所有屬性

  ● 屬性名該參數只有在前一參數描述了部件的情況下才可用

  ● 使用該屬性編輯器的屬性的類型

  下面引用了注冊標准部件的過程

  procedure Register;

  begin

  RegisterPropertyEditor (TypeInfo(TComponent) nil TComponentProperty

  RegisterPropertyEditor(TypeInfo(TComponentName) TComponent

  Name (ComponentNamePropety)

  RegisterPropertyEditor (TypeInfo(TMenuItem) TMenu TMenuItemProperty)

  end;

  這三句表達式使用RegisterPropertyEditor三種不同的用法

  ● 第一種最典型

  它注冊了用於所有TComponent類型屬性的屬性編輯器TComponentProperty通常當為某種類型屬性注冊屬性編輯器時它就能應用於所有這種類型的屬性因此第二和第三個參數為nil

  ● 第二個表達式注冊特定類型的屬性編輯器

  它為特定部件的特定屬性注冊屬性編輯器在這種情況下編輯器用於所有部件的Name屬性

  ● 第三個表達式介於第一個和第二個表達式之間

  它為部件TMenu的TMenuItem類型的所有屬性注冊了屬性編輯器

   創建事件

  事件是部件的很重要的部分事件是部件必須響應的系統事件與響應事件的一段代碼的聯接響應代碼被稱為事件處理過程它總是由部件用戶來編寫通過使用事件應用開發者不需要改變部件本身就能定制部件的行為作為部件編寫者運用事件能使應用發者定制所有的標准Delphi部件要創建事件應當理解

  ● 什麼是事件

  ● 怎樣實現標准事件

  ● 怎樣定義自己的事件

   什麼是事件

  事件是聯接發生的事情與某些代碼的機制或者說是方法指針一個指向特定對象實例的特定方法的指針從部件用戶的角度事件是與系統事件(如OnClick)有關的名稱用戶能給該事件賦特定的方法供調用例如按鈕Buttonl有OnClick方法缺省情況下Delphi在包含該按鈕的窗體中產生一個為ButtonlClick的方法並將其賦給OnClick當一個Click事件發生在按鈕上時按鈕調用賦給OnClick的方法ButtonlClick:

  部件用戶將事件看作是由用戶編寫的代碼而事件發生時由系統調用的處理辦法

  從部件編寫者角度事件有更多的含義最重要的是提供了一個讓用戶編寫代碼響應特定事情的場所

  要編寫一個事件應當理解

  ● 事件和方法指針

  ● 事件是屬性

  ● 事件處理過程類型

  ● 事件處理過程是可選的

  ⑴ 事件是方法指針

  Delphi使用方法指針實現事件一個方法指針是指向特定對象實例的特定方法的特定指針作為部件編寫者能將方法指針作為一種容器你的代碼一發現事情發生就調用由用戶定義的方法

  方法指針的工作方式就象其它的過程類型但它們保持一個隱含的指向對象實例的指針所有的控制都繼承了一個名為Click的方法以處理Click事件Click方法調用用戶的Click事件處理過程

  procedure TControlClick;

  begin

  if Assigned(OnClick ) then OnClick( Self )

  end;

  如果用戶給Control的OnClick事件賦了處理過程(Handle)那鼠標點按Control時將導致方法被調用

  ⑵ 事件是屬性

  部件采用屬性的形式實現事件不象大多數其它屬性事件不使用方法來使實現read和write部分事件屬性使用了相同類型的私有對象域作為屬性按約定域名在屬性名前加F例如OnClick方法的指針存在TNotifyEvent類型FOnClick域中OnClick事件屬性的聲明如下

  type

  TControl=class ( TComponent )

  private

  FOnClick: TNofiFyEvent; { 聲明保存方法指針的域 }

  protected

  property OnClick: TNotifyEvent read FOnClick write FOnClick;

  end;

  象其它類型的屬性一樣你能在運行時設置和改變事件的值將事件做成屬性的主要好處是部件用戶能在設計時使用Object Inspector設置事件處理過程

  ⑶ 事件處理過程類型

  因為一個事件是指向事件處理過程的指針因此事件屬性必須是方法指針類型被用作事件處理過程的代碼必須是相應的對象的方法

  所有的事件方法都是過程為了與所給類型的事件兼容一個事件處理過程必須有相同數目和相同類型的相同順序的參數Delphi定義了所有標准事件處理過程的方法類型當你創建自己的事件時你能使用已有的事件類型或創建新的雖然不能用函數做事件處理過程但可以用var參數得到返回信息

  在事件處理過程中傳遞var參數的典型例子是TKeyPressEvent類型的KeyPressed事件TKeyPressEvent定義中含有兩個參數一個指示哪個對象產生該事件另一個指示那個鍵按下

  type

  TKeyPressEvent=procedure( Sender: TObject; var key: char) of Object;

  通常key參數包含用戶按下鍵的字符在某些情況下部件的用戶可能想改變字符值例如在編輯器中強制所有字符為大寫在這種情況下用戶能定義下列的事件處理過程

  procedure TFormlEditlKeyPressed( Sender: TObject; var key: char)

  begin

  key := Upcase( key )

  end;

  也可使用var參數讓用戶覆蓋缺省的處理

  ⑷ 事件處理過程是可選的

  在為部件創建事件時要記住部件用戶可能並不編寫該事件的處理過程這意味著你的部件不能因為部件用戶沒有編寫處理代碼而出錯這種事件處理過程的可選性有兩個方面

  ① 部件用戶並非不得不處理事件

  事件總是不斷地發生在Windows應用程序中例如在部件上方移動鼠標就引起Windows發送大量的MouseMove消息給部件部件將鼠標消息傳給OnMouseMove事件在大多數情況下部件用戶不需要關心MouseMove事件這不會產生問題因為部件不依賴鼠標事件的處理過程同樣自定義部件也不能依賴用戶的事件處理過程

  ② 部件用戶能在事件處理過程寫任意的代碼

  一般說來對用戶在事件處理過程中的代碼沒有限制Delphi部件庫的部件都支持這種方式以使所寫代碼產生錯誤的可能性最小顯然不能防止用戶代碼出現邏輯錯誤

   怎樣實現標准事件

  Delphi帶的所有控制繼承了大多數Windows事件這些就是標准事件盡管所有這些事件都嵌在標准控制中但它們缺省是protected這意味著用戶無法訪問它們當創建控制時則可選擇這些事件使用戶可用將這些標准事件嵌入自定義控制需要考慮如下

  ● 什麼是標准事件

  ● 怎樣使事件可見

  ● 怎樣修改標准事件處理過程

  ⑴ 什麼是標准事件

  有兩種標准事件用於所有控制和只用於標准Windows控制

  最基本的事件都定義在對象TControl中窗口控制圖形控制和自定義控制都繼承了這些事件下面列出用於所有控制的事件

  OnClick OnDragDrop OnEndDrag OnMouseMove

  OnDblClick OnDragOver OnMouseDown OnMouseUp

  所有標准事件在TControl中都定義了相應的protected動態方法只是沒有加On例如OnClick事件調用名為Click的方法

  標准控制(從TWinControl繼承)具有下列事件

  OnEnter OnKeyDown OnkeyPress OnKeyUp OnExit

  正如TControl中的標准事件窗口控制也有相應protected動態方法

  ⑵ 怎樣使事件可見

  標准事件的聲明是protected如果想使用戶在運行時或設計時能訪問它們就需要將它們重聲明為public和 published重聲明屬性而不描述它的實現將繼承相同的實現方法只是改變了訪問級別例如創建一個部件並使它的OnClick事件出現在運行時你可增加下面的部件聲明

  type

  TMyControl=class(TCustomControl)

  published

  property OnClick; { 使OnClick在objectinspector中可見 }

  end;

  ⑶ 怎樣修改標准事件處理過程

  如果想修改自定義部件響應某種事件的方法可以重寫代碼並將其賦給事件將聯接每個標准事件的方法聲明的protected是出於慎密的考慮通過覆蓋實現方法能修改內部事件處理過程通過調用繼承的方法能保持標准事件處理過程

  調用繼承的方法的順序是很重要的一般首先調用繼承的方法允許用戶的事件處理過程代碼在你的定制代碼前執行然而也有在調用繼承的方法之前執行自己的代碼情況出現

  下面是一個覆蓋Click事件的例子

  procedure TMyControlClick;

  begin

  inherited Click; { 執行標准處理包括調用事件處理過程你自己的定制代碼 }

  end;

   定義自己的事件

  定義全新的事件的情況是很少見的只有當部件的行為完全不同於任何其它事件才需要定義新事件定義新事件一般包含三個步驟

  ● 觸發事件

  ● 定義處理過程類型

  ● 聲明事件

  ● 調用事件

  ⑴ 觸發事件

  定義自己的事件要遇到的第一個關鍵是當使用標准事件時你不需要考慮由什麼觸發事件對某些事件問題是顯然的例如一個MouseDown事件是在用戶按下鼠標的左鍵時發生Windows給應用發送WM_LBUTTONDOWN消息接到消息後一個部件調用它的MouseDown方法它依次調用用戶的OnMouseDown事件處理過程代碼但是有些事件卻不是那麼可以描述清楚的例如滾行槓有一個OnChange事件可被各種情況觸發包括按鍵鼠標點按或其它按制中的改變當定義事件時你必須使各種情況的發生調用正確的事件

  這裡有TControl處理WM_LBUTTONDOWN消息的方法DoMouseDown是私有的實現方法它提供了一般的處理左右和中按鈕的方法並將Windows消息的參數轉換為MouseDown方法的值

  type

  TControl = class(TComponent)

  private

  FOnMouseDown: TMouseEvent;

  procedure DoMouseDown(var Message: TWMMouse; Button: TMouseButton;

  Shift: TShiftState)

  procedure WMLButtonDown(var Message: TWMLButtonDown)

  message M_LBUTTONDOWN;

  protected

  procedure MouseDown(Button: TMouseButton; Shift: TShiftState;

  X Y: Integer) dynamic;

  end;

  procedure TControlMouseDown(Button: TMouseButton; Shift: TShiftState; X Y: Integer)

  begin

  if Assigned(FOnMouseDown) then

  FOnMouseDown(Self Button Shift X Y) { 調用事件處理過程 }

  end;

  procedure TControlDoMouseDown(var Message: TWMMouse; Button: TMouseButton;

  Shift: ShiftState)

  begin

  with Message do

  MouseDown(Button KeysToShiftState(Keys) + Shift XPos YPos) { 調用動態方法 }

  end;

  procedure TControlWMLButtonDown(var Message: TWMLButtonDown)

  begin

  inherited; { perform default handling }

  if csCaptureMouse in ControlStyle then

  MouseCapture := True;

  if csClickEvents in ControlStyle then

  Include(FControlState csClicked)

  DoMouseDown(Message mbLeft []) { 調用常規的mousedown 方法 }

  end;

  當兩種事情狀態變化和用戶交互發生時處理機制是相同的但過程稍微不同用戶交互事件將總是由Windows消息觸發狀態改變事件也與Windows消息有關但它們也可由屬性變化或其它代碼產生你擁有對自定義事件觸發的完全控制

[]  []  []  []  


From:http://tw.wingwit.com/Article/program/Delphi/201311/25119.html
    推薦文章
    Copyright © 2005-2013 電腦知識網 Computer Knowledge   All rights reserved.