4.举重若轻
4.1.源于一个简单的框架TFrame
在04年的时候,为了方便书写游戏修改器,曾经做过一个框架,由三个组件组成,两个T[x]Edit和一个T[x]SpeedButton,前两个T[x]Edit分别显示编号与信息,后面的T[x]SpeedButton用于调用修改功能,界面如下:
实际上,就算不是书写游戏修改器,很多地方都可能用得上它,比如数据库系统……
它的定义很简单:
TfPubSimple = class(TfFrameGameEditor)
edtNo: TTntEdit;
edtName: TTntEdit;
sbChange: TTntSpeedButton;
private
function GetNo: Integer;
procedure SetNo(const Value: Integer);
function GetSimpleName: WideString;
procedure SetSimpleName(const Value: WideString);
public
property No: Integer read GetNo write SetNo;
property SimpleName: WideString read GetSimpleName write SetSimpleName;
end;
先不要考虑它的基础类TfFrameGameEditor做了些什么,那不是我们现在关心的重点,先看它的代码吧,其实超级简单。
function TfPubSimple.GetNo: Integer;
begin
Result := StrToIntDef(edtNo.Text, 0);
end;
procedure TfPubSimple.SetNo(const Value: Integer);
begin
edtNo.Text := IntToStr(Value);
end;
function TfPubSimple.GetSimpleName: WideString;
begin
Result := edtName.Text;
end;
procedure TfPubSimple.SetSimpleName(const Value: WideString);
begin
edtName.Text := Value;
end;
为什么没有使用TTntLabeledEdit呢?在没有仔细阅读TTntLabeledEdit代码之前,我实在不知道怎么控制好那个Label,就算是现在,它也是一个让人费神经的话题。
那么,如何把它变成一个组件呢?
4.2.定义我们的TGcxCustomValueInfoEdit
首先是需求分析,它有一个数值输入输出,一个文本输入输出,还有一个控制按钮。为了使用更加方便,我们再增加一个标签。
好了,我们开始从TWinControl继承,并增加三个必要对象,定义如下:
TGcxCustomValueInfoEdit = class(TWinControl)
private
FValueEdit: TGcxCustomIntLabeledEditX;
FInfoEdit: TGcxCustomEditX;
FSubBtn: TTntSpeedButton;
public
constructor Create(AOwner: TComponent); override;
property ValueEdit: TGcxCustomIntLabeledEditX read FValueEdit;
property InfoEdit: TGcxCustomEditX read FInfoEdit;
property SubBtn: TTntSpeedButton read FSubBtn;
这里出现了两个新的类:TGcxCustomIntLabeledEditX和TGcxCustomEditX,他们从哪里来的呢?
实际上它们是TGcxCustomIntLabeledEdit和TGcxCustomEdit的另外一个面孔。
为什么没有用TGcxIntLabeledEdit和TGcxEdit呢?因为他们公开的属性、事件太多了,如果把它们放入TGcxCustomValueInfoEdit中,估计我们很快就会被眼花缭乱的属性弄晕的。
4.2.1.TGcxCustomIntLabeledEditX的定义
TGcxCustomIntLabeledEditX = class(TGcxCustomIntLabeledEdit)
published
property Alignment;
property CharCase;
property Constraints;
property EditLabel;
property FormatStyle;
property HideSelection;
property LabelPosition;
property LabelSpacing;
property LeadingZeros;
property Margin;
property MaxLength;
property ParentShowHint;
property PopupMenu;
property ShowHint;
property Value;
property ValueMax;
property ValueMin;
published
property OnChange;
property OnClick;
property OnDblClick;
property OnEnter;
property OnExit;
property OnKeyDown;
property OnKeyPress;
property OnKeyUp;
property OnMouseDown;
property OnMouseMove;
property OnMouseUp;
end;
4.2.2.TGcxCustomEditX的定义
TGcxCustomEditX = class(TGcxCustomEdit)
published
property Alignment;
property Constraints;
property HideSelection;
property ImeMode;
property ImeName;
property Margin;
property MaxLength;
property ParentShowHint;
property PopupMenu;
property ShowHint;
property Text;
published
property OnChange;
property OnClick;
property OnDblClick;
property OnEnter;
property OnExit;
property OnKeyDown;
property OnKeyPress;
property OnKeyUp;
{$IFDEF COMPILER_9_UP}
property OnMouseActivate;
{$ENDIF}
property OnMouseDown;
{$IFDEF COMPILER_10_UP}
property OnMouseEnter;
property OnMouseLeave;
{$ENDIF}
property OnMouseMove;
property OnMouseUp;
end;
4.3.简化常用属性
4.3.1.引出CommonColor、ReadOnlyColor与ReadOnly
这三个属性是TGcxCustomIntLabeledEdit和TGcxCustomEdit共有的属性,我们在TGcxCustomIntLabeledEditX和TGcxCustomEditX中并没有公布出来,在这里一并引出。
private
function GetCommonColor: TColor;
procedure SetCommonColor(const Value: TColor);
function GetReadOnly: Boolean;
procedure SetReadOnly(const Value: Boolean);
function GetReadOnlyColor: TColor;
procedure SetReadOnlyColor(const Value: TColor);
protected
property CommonColor: TColor
read GetCommonColor write SetCommonColor default clInfoBk;
property ReadOnly: Boolean read GetReadOnly write SetReadOnly default False;
property ReadOnlyColor: TColor
read GetReadOnlyColor write SetReadOnlyColor default clSkyBlue;
function TGcxCustomValueInfoEdit.GetCommonColor: TColor;
begin
Result := FValueEdit.CommonColor;
end;
procedure TGcxCustomValueInfoEdit.SetCommonColor(const Value: TColor);
begin
FValueEdit.CommonColor := Value;
FInfoEdit.CommonColor := Value;
end;
function TGcxCustomValueInfoEdit.GetReadOnly: Boolean;
begin
Result := FValueEdit.ReadOnly;
end;
procedure TGcxCustomValueInfoEdit.SetReadOnly(const Value: Boolean);
begin
FValueEdit.ReadOnly := Value;
FInfoEdit.ReadOnly := Value;
end;
function TGcxCustomValueInfoEdit.GetReadOnlyColor: TColor;
begin
Result := FValueEdit.ReadOnlyColor;
end;
procedure TGcxCustomValueInfoEdit.SetReadOnlyColor(const Value: TColor);
begin
FValueEdit.ReadOnlyColor := Value;
FInfoEdit.ReadOnlyColor := Value;
end;
4.3.2.引出FSubBtn的Caption属性——ButtonCaption
实际上这个引出不是必须的,但是为了设计时修改方便,添加代码如下:
private
function GetButtonCaption: WideString;
procedure SetButtonCaption(const Value: WideString);
protected
property ButtonCaption: WideString read GetButtonCaption write SetButtonCaption;
function TGcxCustomValueInfoEdit.GetButtonCaption: WideString;
begin
Result := Self.FSubBtn.Caption;
end;
procedure TGcxCustomValueInfoEdit.SetButtonCaption(const Value: WideString);
begin
Self.FSubBtn.Caption := Value;
end;
4.3.3.引出EditLabel的Caption
TGcxCustomIntLabeledEdit的EditLabel对象在TGcxCustomIntLabeledEditX中虽然公布,但在设计期间,甚至在书写代码访问TGcxCustomIntLabeledEdit.EditLabel.Caption也是让人头痛的事情,它的层次太深了。
private
function GetCaption: WideString;
procedure SetCaption(const Value: WideString);
protected
property Caption: WideString read GetCaption write SetCaption;
function TGcxCustomValueInfoEdit.GetCaption: WideString;
begin
Result := Self.FValueEdit.FEditLabel.Caption;
end;
procedure TGcxCustomValueInfoEdit.SetCaption(const Value: WideString);
begin
Self.FValueEdit.FEditLabel.Caption := Value;
end;
4.3.4.引出FormatStyle、LabelPosition、Text、Value
同样为了方便访问TGcxCustomIntLabeledEdit的FormatStyle、LabelPosition、Value属性,以及TGcxCustomEdit的Text属性,我们将他们引出:
private
function GetFormatStyle: TIntegerFormatStyle;
procedure SetFormatStyle(const Value: TIntegerFormatStyle);
function GetLabelPosition: TLabelPosition;
procedure SetLabelPosition(const Value: TLabelPosition);
function GetText: WideString;
procedure SetText(const Value: WideString);
function GetValue: Integer;
procedure SetValue(const Value: Integer);
protected
property FormatStyle: TIntegerFormatStyle
read GetFormatStyle write SetFormatStyle default ifsInteger;
property LabelPosition: TLabelPosition
read GetLabelPosition write SetLabelPosition default lpLeft;
property Text: WideString read GetText write SetText;
property Value: Integer read GetValue write SetValue default 0;
function TGcxCustomValueInfoEdit.GetFormatStyle: TIntegerFormatStyle;
begin
Result := FValueEdit.FormatStyle;
end;
procedure TGcxCustomValueInfoEdit.SetFormatStyle(
const Value: TIntegerFormatStyle);
begin
FValueEdit.FormatStyle := Value;
end;
function TGcxCustomValueInfoEdit.GetLabelPosition: TLabelPosition;
begin
Result := FValueEdit.LabelPosition;
end;
procedure TGcxCustomValueInfoEdit.SetLabelPosition(
const Value: TLabelPosition);
begin
FValueEdit.LabelPosition := Value;
end;
function TGcxCustomValueInfoEdit.GetText: WideString;
begin
Result := Self.FInfoEdit.Text;
end;
procedure TGcxCustomValueInfoEdit.SetText(const Value: WideString);
begin
Self.FInfoEdit.Text := Value;
end;
function TGcxCustomValueInfoEdit.GetValue: Integer;
begin
Result := Self.FValueEdit.Value;
end;
procedure TGcxCustomValueInfoEdit.SetValue(const Value: Integer);
begin
Self.FValueEdit.Value := Value;
end;