支持自绘画的属性编辑器
热 ★★★★
支持自绘画的属性编辑器
作者:闵涛 文章来源:闵涛的学习笔记 点击数:1799 更新时间:2009/4/23 18:26:28
;type TBoldComponentNameProperty =class (TComponentNameProperty)public procedure PropDrawName(Canvas: TCanvas; const Rect: TRect; Selected: Boolean); override ;end ;procedure TBoldComponentNameProperty.PropDrawName( Canvas: TCanvas; const Rect: TRect; Selected: Boolean);var Style: TFontStyles;begin Style := Canvas.Font.Style; Canvas.Font.Style := Canvas.Font.Style + [fsBold]; try inherited ; finally //恢复字体的样式以便Delphi正确的画属性值 Canvas.Font.Style := Style; end ;end ;
下拉列表 一个属性编辑器可能会拥有一个下拉列表框,用户可以通过选择列表项来改变属性值。Delphi 5使用了自绘画的特性来改进Tcolor和Tcursor属性的界面友好性,我们也可以作同样的事情,通过重载ListDrawValue,ListMeasureHeight和ListMeasureWidth方法可以很容易的做到。下面是这几个方法的声明:procedure ListDrawValue(const Value: string ; Canvas: TCanvas; const Rect: TRect; Selected: Boolean);procedure ListMeasureHeight(const Value: string ; Canvas: TCanvas; var Height: Integer);procedure ListMeasureWidth(const Value: string ; Canvas: TCanvas; var Width: Integer);
ListDrawValue方法类似于PropDrawValue方法,但它的Selected是有意义的,表示用户已经选择了这个列表项。Delphi会根据Selected参数自动设定画布的颜色为合适的值,所以通常情况下我们可以忽略这个参数。Value参数是要显示的字符串,Delphi调用GetValue方法来获得这些字符串, 在对象编辑器显示列表框之前,它会调用ListMeasureHeight和ListMeasureWidth方法来获得每个列表项的尺寸,我们可以设定Height和Width参数来获得想要得到的高度和宽度。下拉列表框使用全部列表项中最大的尺寸,然后显示相同区域大小的列表项。 当用户滚动列表框时,Delphi调用ListDrawValue方法来画心新的可见的列表项。用户可能会前后滚动多次,如果列表项很多,每次重绘需要很多时间的话,我们应该建立一个临时的位图,把列表项先画到位图上,然后在ListDrawValue方法中快速显示位图。这实际上就是双缓冲技术。 下面的例子是一个扩展的集合类型属性,下拉列表显示全部的集合元素,并在每个集合元素旁边添加一个复选框。复选框是通过位图来模仿的,属性编辑器先取得复选框位图,并在不同情况下显示打叉和未打叉的位图。全局变量Checked和Unchecked保存这两个位图 为Tbitmap类型。下面的代码显示了TSetPropertyEx.类是如何实现自绘画集合类型的:// 在下拉列表框的每一个列表项旁边画一个复选框 procedure TSetPropertyEx.ListDrawValue(const Value: string ; Canvas: TCanvas; const Rect: TRect; Selected: Boolean);var IsChecked: Boolean; OrdValue: Integer;begin OrdValue := GetOrdValue; IsChecked := GetEnumValue(EnumInfo, Value) in TIntegerSet(OrdValue); Canvas.FillRect(Rect); Canvas.TextRect(Rect, Rect.Left + Checked.Width + 2, Rect.Top + 1, Value); if IsChecked then Canvas.Draw(Rect.Left + 1, Rect.Top + 1, Checked) else Canvas.Draw(Rect.Left + 1, Rect.Top + 1, Unchecked);end ;procedure TSetPropertyEx.ListMeasureHeight(const Value: string ; Canvas: TCanvas; var Height: Integer);begin if Height < Checked.Height then Height := Checked.Height;end ;procedure TSetPropertyEx.ListMeasureWidth(const Value: string ; Canvas: TCanvas;var Width: Integer);begin Width := Width + Checked.Width + 2;end ;
类似于显示集合元素,对于布耳类型的属性我们也可以加一个复选框。下面我们要实现TBooleanPropertyEx 属性编辑器对布耳类型进行了扩展,对于不同的布耳类型,比如ByteBool, WordBool和LongBool属性的实现方式是类似的,当时需要不同的属性编辑器。下面就是TbooleanPropertyEx的实现代码,对于复选框如何相应消息,有点小问题,因为通常我们是希望单击实现复选框切换状态,Delphi不支持单击,我们只好使用双击了(估计在Delphi 6中属性编辑器可能会支持单击),注意双击会调用属性编辑器的Edit方法。对于集合元素或布耳属性,双击可以切换属性值。估计在Delphi 6中属性编辑器可能会支持单击。 //根据True或者False来画一个复选框及布耳值的文本标签 procedure DrawBoolCheckBox(Canvas: TCanvas;const Rect: TRect; const Value: string );begin Canvas.FillRect(Rect); Canvas.TextRect(Rect, Rect.Left + Checked.Width + 2, Rect.Top + 1, Value); if Value = BooleanIdents[False ] then Canvas.Draw(Rect.Left + 1, Rect.Top + 1, UnChecked) else Canvas.Draw(Rect.Left + 1, Rect.Top + 1, Checked);end ;{ TSetElementPropertyEx } // 每个列表项旁边显示一个复选框,用户必须双击 //而不是单击才能切换复选框状态 procedure TSetElementPropertyEx.PropDrawValue( Canvas: TCanvas; const Rect: TRect; Selected: Boolean);begin DrawBoolCheckBox(Canvas, Rect, Value);end ;{ TBoolPropertyEx } // 为ByteBool, WordBool和LongBool类型显示复选框 procedure TBoolPropertyEx.PropDrawValue(Canvas: TCanvas;const Rect: TRect; Selected: Boolean);begin DrawBoolCheckBox(Canvas, Rect, Value);end ;
使用属性编辑器 最后我们需要作的就是注册这些新的属性编辑器,大多数的编辑器比较容易注册,但是新的集合类属性编辑器存在一个问题,每一个集合都是一个独立的类型,我们必须分别为每个集合类型注册一遍属性编辑器。幸运的是,Delphi有一个不为人知的特性就是允许为所有的集合类型注册同一个属性编辑器。同通常的为单独一个类型注册属性编辑器不同的是,我们可以通过提供一个属性映射函数来实现注册,这个函数把对象和属性信息作为参数,然后返回属性编辑器类或是nil。这种情况下,映射函数校验属性类型,并为所有属性类型是tkSet的属性返回新的集合属性编辑器。下面是注册过程的代码: //为全部的集合属性注册一个统一的属性编辑器 function SetMapper(Obj: TPersistent; PropInfo: PPropInfo): TPropertyEditorClass;begin if PropInfo.PropType^.Kind = tkSet then Result := TSetPropertyEx else Result := nil ;end ;procedure Register;begin RegisterPropertyEditor(TypeInfo(TFont), nil , '''''''', TVisualFontProperty); RegisterPropertyEditor(TypeInfo(TGraphic), nil , '''''''', TVisualGraphicProperty); RegisterPropertyEditor(TypeInfo(TComponentName), TComponent, ''''Name'''', TBoldComponentNameProperty); RegisterPropertyEditor(TypeInfo(Boolean), nil , '''''''', TBooleanPropertyEx); RegisterPropertyEditor(Type
上一页 [1] [2] [3] 下一页
没有相关教程
教程录入:mintao 责任编辑:mintao
上一篇教程: TValueListEditor 控件使用方法 下一篇教程: [Delphi]一个解析FTP地址的小函数
【字体:小 大 】【发表评论 】【加入收藏 】【告诉好友 】【打印此文 】【关闭窗口 】
注:本站部分文章源于互联网,版权归原作者所有!如有侵权,请原作者与本站联系,本站将立即删除! 本站文章除特别注明外均可转载,但需注明出处! [MinTao学以致用网]
网友评论: (只显示最新10条。评论内容只代表网友观点,与本站立场无关!)
同类栏目
赞助链接
500 - 内部服务器错误。
500 - 内部服务器错误。
您查找的资源存在问题,因而无法显示。