我想完全覆盖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