2009-08-27 67 views
2

這應該是非常簡單的,但我找不到我想要的確切答案。我有一個基於TSpeedButton的自定義delphi控件。我希望SpeedButton的Caption屬性始終爲'Comments',但我不想在運行時設置它,我想將它設置在組件本身中,以便當我將它放在我的表單上時它已經填充了這個文本。我也想設置按鈕的高度和寬度,但我想象這樣做的方法將與設置標題相同。德爾福2009年 - 在自定義德爾福組件中設置默認屬性值

爲了完整起見,這裏是組件代碼:

unit CustomSpeedButton; 

interface 

uses 
    SysUtils, Classes, Controls, Buttons; 

type 
    TCustomSpeedButton = class(TSpeedButton) 
    private 
    FCommentText: string; 
    FCommentTitle: string; 

    procedure SetCommentText(const Value: string); 
    procedure SetCommentTitle(const Value: string); 

    { Private declarations } 
    protected 
    { Protected declarations } 
    public 
    { Public declarations } 

    published 
    { Published declarations } 
    property CommentTitle: string read FCommentTitle write SetCommentTitle; 
    property CommentText: string read FCommentText write SetCommentText; 
    end; 

procedure Register; 

implementation 

procedure Register; 
begin 
    RegisterComponents('Standard', [TCustomSpeedButton]); 
end; 

{ TCustomSpeedButton } 

procedure TCustomSpeedButton.SetCommentText(const Value: string); 
begin 
    FCommentText := Value; 
end; 

procedure TCustomSpeedButton.SetCommentTitle(const Value: string); 
begin 
    FCommentTitle := Value; 
end; 

end. 
+0

你的意思是你想要的*默認*標題爲「評論」,或者你的意思是你想要的標題爲*總*是「評論,」不管是什麼開發人員將其更改爲以後? – 2009-08-27 20:35:38

+0

默認標題爲'評論' – Rafe 2009-08-27 20:40:09

回答

3

既然你想正確完成標題屬性,梅森的答案不會工作,因爲他錯過了'csSetCaption'的事情,他的'默認'的建議不會工作,因爲標題和你的屬性都是字符串類型。

下面是你想要的單位。

的行爲如下:

  1. intially Caption屬性的值將是「評論」
  2. 用戶可以覆蓋在設計時通過設置新的值

(如果你不想要2.,那麼你需要像Ken提到的那樣用一個被覆蓋的Loaded方法來指定Caption屬性;但是,從你的問題中不清楚你是否需要這個方法,如果你願意的話,請重新說明你的問題。

這是代碼的工作原理。

對於字符串屬性,您不能提示任何默認的流式系統。 但是,您可以在構造函數中爲設計時間設置初始值:Caption:= DefaultCustomSpeedButtonCaption;

對於Caption屬性,您還必須禁用Caption屬性的默認分配(否則您的組件將自動獲得像'CustomSpeedButton1'這樣的標題)。 這一行代碼適用於您:ControlStyle:= ControlStyle - [csSetCaption];

最後,將組件註冊拆分爲單獨的單元是一種很好的做法。 這使您可以擁有一個設計時包,它可以在IDE中註冊組件,並提供運行時包(或根本沒有包),以便在應用程序中使用組件。

如果您有一個組件圖標,那麼您也將其加載到註冊單元中(因爲它只在設計時需要)。

雷Konopka的寫了書面成分一個很好的書,仍然是非常有效的:Developing Custom Delphi 3 Components 和很多優秀的德爾福書,它是絕版的,但你可以order a PDF copy on his site

我不確定CommentTitle和CommentText屬性是什麼,所以我將它們放在下面的代碼中。

清單1:實際的組件

unit CustomSpeedButtonUnit; 

interface 

uses 
    SysUtils, Classes, Controls, Buttons; 

const 
    DefaultCustomSpeedButtonCaption = 'Comments'; 

type 
    TCustomCustomSpeedButton = class(TSpeedButton) 
    strict private 
    FCommentText: string; 
    FCommentTitle: string; 
    strict protected 
    procedure SetCommentText(const Value: string); virtual; 
    procedure SetCommentTitle(const Value: string); virtual; 
    public 
    constructor Create(AOwner: TComponent); override; 
    destructor Destroy; override; 
    property CommentTitle: string read FCommentTitle write SetCommentTitle; 
    property CommentText: string read FCommentText write SetCommentText; 
    end; 

    TCustomSpeedButton = class(TCustomCustomSpeedButton) 
    published 
// note you cannot use 'default' for string types; 'default' is only valid for ordinal ordinal, pointer or small set type 
// [DCC Error] CustomSpeedButtonUnit.pas(29): E2146 Default values must be of ordinal, pointer or small set type 
// property Caption default DefaultCustomSpeedButtonCaption; 
    property CommentTitle; 
    property CommentText; 
    end; 

implementation 

constructor TCustomCustomSpeedButton.Create(AOwner: TComponent); 
begin 
    inherited Create(AOwner); 
    Caption := DefaultCustomSpeedButtonCaption; 
    ControlStyle := ControlStyle - [csSetCaption]; 
end; 

destructor TCustomCustomSpeedButton.Destroy; 
begin 
    inherited Destroy; 
end; 

procedure TCustomCustomSpeedButton.SetCommentText(const Value: string); 
begin 
    FCommentText := Value; 
end; 

procedure TCustomCustomSpeedButton.SetCommentTitle(const Value: string); 
begin 
    FCommentTitle := Value; 
end; 

end. 

清單2:組件註冊

unit CustomSpeedButtonRegistrationUnit; 

interface 

procedure Register; 

implementation 

uses 
    CustomSpeedButtonUnit; 

procedure Register; 
begin 
    RegisterComponents('Standard', [TCustomSpeedButton]); 
end; 

end. 
+0

謝謝Jeroen。在幾次錯誤的開始之後,我得出了結論,我只是要求太多,最終只是在將所有按鈕粘貼到頁面並改變它們的特性作爲「批次」之後選擇了所有按鈕。上面給出的完整列表顯示所有內容都不會丟失,因此我非常感謝您的意見。另外,我實際上擁有一本關於Delphi 3組件的書(D3早在1998年我第一次接觸Delphi)。我從來沒有閱讀過它,但現在會這樣做! – Rafe 2009-08-28 18:04:47

+0

嗯,有趣。我創建了一個新的組件,以創建組件註冊單元,然後保存並嘗試切換到另一個項目,IDE將我踢出去,現在不會重新啓動。唯一不同的是,我將其修改爲只是註冊過程說'開始登記;結束;'因爲registercomponents不斷拋出一個關於它無法識別的錯誤。必須以某種方式清除IDE緩存。 – Rafe 2009-08-28 19:05:44

+0

Ooops - 如果您執行了「過程註冊;開始註冊;結束;」那麼你會得到一個無限循環。當你將這樣一個循環放在IDE中加載的設計時包中時,IDE就會掛起。 最好的解決方案是關閉Delphi IDE,找到你得到無限循環的組件包.bpl,然後刪除該.bpl文件,然後啓動Delphi IDE。 希望有所幫助。如果沒有,給我發一封電子郵件(幾乎任何在pluimers網絡公司將得到我,但最簡單的是使用我的名字)。我可以與您一起完成TeamViewer會話來解決它。 好luch! - jeroen – 2009-08-28 19:29:24

2

你需要在組件的構造函數來設置初始值。

編輯:你也想把ControlStyle := ControlStyle - [csSetCaption];加到構造函數中。

+0

@Mason:這並不總是奏效。調用構造函數,然後在DFM流入時設置屬性。您在構造函數中執行的操作可以由DFM中的內容替換。 – 2009-08-27 20:02:41

+1

是的,那是預期的和期望的行爲。如果用戶在屬性中輸入了某些內容,保存,重新加載以及保存的內容都被更改了,他們會感到惱火。 – 2009-08-27 20:04:47

+0

我讀過它應該在構造函數中完成之前,我發誓我曾經知道那是,但現在我拉我的頭髮試圖找到它! – Rafe 2009-08-27 20:42:21

1

@Etherman:如果你想有默認值的字符串屬性,你想將它保存到DFM - 即使它是空白的 - 你必須自己做。幸運的是,Delphi爲您提供了方法。看看下面的代碼:

type 
    TMyComp = class(TControl) 
    private 
    FMyStringProperty: string; 
    procedure WriteMyStringProperty(Writer: TWriter); 
    procedure DefineProperties(Filer: TFiler); override; 
    public 
    constructor Create(AOwner: TComponent); override; 
    published 
    property MyStringProperty: string read FMyStringProperty write FMyStringProperty stored False; 
    end; 


implementation 


constructor TMyComp.Create(AOwner: TComponent); 
begin 
    inherited Create(AOwner); 
    FMyStringProperty := 'my default value'; 
end; 

procedure TMyComp.WriteMyStringProperty(Writer: TWriter); 
begin 
    Writer.WriteString(FMyStringProperty); 
end; 

procedure TMyComp.DefineProperties(Filer: TFiler); 
begin 
    inherited DefineProperties(Filer); 
    Filer.DefineProperty('MyStringProperty', nil, WriteMyStringProperty, True); 
end;