我想完全覆盖TDateTime类型并将我的自定义编辑器放在其位置,所以无论TDateTime在对象检查器中发布和可见,我可以使用此编辑器在同一个窗口中一起修改日期和时间.
问题是关于创建自定义属性编辑器的文档很差,虽然一些资源非常详尽,但是它们在功能上有太多的细节,并且在最常见的情况下还没有得到解决.
解决方法
自定义属性编辑器,对话框和组件编辑器有许多不同的可能性.这特别要求一个TDateTimeProperty后代.这将允许您在保持DateTime格式的同时,直接在Object Inspector中以纯文本(String)的形式编辑属性的值.
我假设你已经有一个关于创建自定义组件和一个包,您可以在其中发布此属性编辑器的一般知识,因为这是一个教训,我将不会介绍.这就需要在注册过程中放置一行代码,但稍后我们再来看看.
首先,您需要在您的组件注册的设计时包中创建一个新表单.将单位命名为DateTimeProperty.pas,并将表单DateTimeDialog命名(从而使表单的类TDateTimeDialog).放置任何您需要的控件,在这种情况下,TMonthCalendar,TDateTimePicker(Kind设置为dtkTime)和2个TBitBtn控件,一个标记为“OK”,其中mrOK为ModalResult,另一个标记为“取消与malCancel的ModalResult”.
你的单位应该是这样的:
unit DateTimeProperty; interface uses Winapi.Windows,Winapi.Messages,System.SysUtils,System.Variants,System.Classes,Vcl.Graphics,Vcl.Controls,Vcl.Forms,Vcl.Dialogs,Vcl.ComCtrls,Vcl.StdCtrls,Vcl.Buttons; type TDateTimeDialog = class(TForm) dtDate: TMonthCalendar; dtTime: TDateTimePicker; BitBtn1: TBitBtn; BitBtn2: TBitBtn; private public end; var DateTimeDialog: TDateTimeDialog; implementation {$R *.dfm} end.
这里是DFM代码:
object DateTimeDialog: TDateTimeDialog Left = 591 Top = 158 BorderIcons = [biSystemMenu] BorderStyle = bsToolWindow Caption = 'Pick Date/Time' ClientHeight = 231 ClientWidth = 241 Color = clBtnFace Font.Charset = DEFAULT_CHARSET Font.Color = clWindowText Font.Height = -11 Font.Name = 'Tahoma' Font.Style = [] OldCreateOrder = False Position = poScreenCenter DesignSize = ( 241 231) PixelsPerInch = 96 TextHeight = 13 object dtDate: TMonthCalendar Left = 8 Top = 31 Width = 225 Height = 166 Anchors = [akLeft,akRight,akBottom] Date = 41261.901190613430000000 TabOrder = 1 end object dtTime: TDateTimePicker Left = 8 Top = 8 Width = 113 Height = 21 Date = 41261.000000000000000000 Time = 41261.000000000000000000 Kind = dtkTime TabOrder = 2 end object BitBtn1: TBitBtn Left = 158 Top = 200 Width = 75 Height = 25 Caption = 'OK' Default = True ModalResult = 1 TabOrder = 0 end object BitBtn2: TBitBtn Left = 77 Top = 200 Width = 75 Height = 25 Caption = 'Cancel' ModalResult = 2 TabOrder = 3 end end
现在,将DesignEditors和DesignIntf添加到uses子句中.确保您在此设计时间包的要求中声明了DesignIDE.这是发布任何属性编辑器所必需的.
在表单中,使用属性getter和setter创建一个名为DateTime的类型为TDateTime的新的公共属性.此属性将允许您轻松读/写完整选择实际表示的TDateTime值.所以你应该用你的形式:
private function GetDateTime: TDateTime; procedure SetDateTime(const Value: TDateTime); public property DateTime: TDateTime read GetDateTime write SetDateTime; .... function TDateTimeDialog.GetDateTime: TDateTime; begin Result:= Int(dtDate.Date) + Frac(dtTime.Time); end; procedure TDateTimeDialog.SetDateTime(const Value: TDateTime); begin dtDate.Date:= Value; dtTime.DateTime:= Value; end;
接下来我们需要添加实际的属性编辑器类.在刚刚实施的{$R * .dfm}下面创建这个类:
type TDateTimeEditor = class(TDateTimeProperty) public procedure Edit; override; function GetAttributes: TPropertyAttributes; override; function GetValue: String; override; procedure SetValue(const Value: String); override; end; procedure TDateTimeEditor.Edit; var F: TDateTimeDialog; begin //Initialize the property editor window F:= TDateTimeDialog.Create(Application); try F.DateTime:= GetFloatValue; if F.ShowModal = mrOK then begin SetFloatValue(F.DateTime); end; finally F.Free; end; end; function TDateTimeEditor.GetAttributes: TPropertyAttributes; begin //Makes the small button show to the right of the property Result := inherited GetAttributes + [paDialog]; end; function TDateTimeEditor.GetValue: String; begin //Returns the string which should show in Object Inspector Result:= FormatDateTime('m/d/yy h:nn:ss ampm',GetFloatValue); end; procedure TDateTimeEditor.SetValue(const Value: String); begin //Assigns the string typed in Object Inspector to the property inherited; end;
最后,我们需要添加一个注册过程来执行这个新的属性编辑器的实际注册:
procedure Register; begin RegisterPropertyEditor(TypeInfo(TDateTime),nil,'',TDateTimeEditor); end;
现在在对RegisterPropertyEditor的这个调用中有一个重要的理解.由于第2和第3个参数为零和空字符串,这意味着编辑器将应用于TDateTime的所有实例.查看此过程以获取有关使特定于某些组件和属性实例的更多信息.
这是安装后的最终结果…
贡献的定制财产编辑的一些好的资源如下:
> how to make custom component property?
> http://delphi.about.com/library/bluc/text/uc092501d.htm
> http://www.sandownet.com/propedit.html