TLabbeledEdit
みたいな複合コントロールにも使われるサブコンポーネント機能について。
TEdit
とTUpDown
の連動もよく使う組み合わせです。
というかサンプルにすらTSpinEdit
があります。
しかし、TSpinEdit
はWindowsとは別に独自に実装を持っているので何となく外観が異なります。
やはりここはTEdit
とTUpDown
を組み合わせたい!
今まで、TWinControl
から継承しふたつのコントロールを子に持ったもの、TFrame
を用いたもの、と、作った経験があります。
しかし、PositionなどのプロパティをTUpDown
と同じように作らねばならず、面倒でした。
Delphi 6の新機能サブコンポーネントはこういう時のためのものです。
コンポーネント型の読み取り専用プロパティを、TFont
のように展開して使えるので、無駄がありません。
…というわけで作り直したのですな。僕もご苦労なことです。
ここまで書いて解説が面倒になったのでソースを全掲します。
多分問題なく動くと思いますけど、何か(バグ、問題、変な動作、改造してより高機能にしたのでオリジナル作者に還元してあげたい!など)あったら教えて下さい。
unit VNumEdit; interface uses Windows, Messages, Classes, Controls, StdCtrls, ComCtrls; const NEM_REASSIGN = WM_USER + 300; type TBoundUpDown = class(TCustomUpDown) private function GetTop: Integer; function GetLeft: Integer; function GetWidth: Integer; function GetHeight: Integer; public constructor Create(AOwner: TComponent); override; published property Height: Integer read GetHeight stored False; property Left: Integer read GetLeft stored False; property Top: Integer read GetTop stored False; property Width: Integer read GetWidth stored False; property AlignButton; property Anchors; {property Associate;} property ArrowKeys; property Enabled; property Hint; property Min; property Max; property Increment; property Constraints; property Orientation; property ParentShowHint; property PopupMenu; property Position; property ShowHint; property TabOrder; property TabStop; property Thousands; property Visible; property Wrap; property OnChanging; property OnChangingEx; property OnContextPopup; property OnClick; property OnEnter; property OnExit; property OnMouseDown; property OnMouseMove; property OnMouseUp; end; TCustomNumEdit = class(TCustomEdit) private FUpDown: TBoundUpDown; procedure CMVisiblechanged(var Message: TMessage); message CM_VISIBLECHANGED; procedure CMEnabledchanged(var Message: TMessage); message CM_ENABLEDCHANGED; procedure CMBidimodechanged(var Message: TMessage); message CM_BIDIMODECHANGED; procedure NEMReassign(var Message); message NEM_REASSIGN; protected procedure SetParent(AParent: TWinControl); override; procedure Notification(AComponent: TComponent; Operation: TOperation); override; procedure CreateWnd; override; procedure CreateParams(var Params: TCreateParams); override; public constructor Create(AOwner: TComponent); override; procedure SetBounds(ALeft: Integer; ATop: Integer; AWidth: Integer; AHeight: Integer); override; property UpDown: TBoundUpDown read FUpDown; end; TNumEdit = class(TCustomNumEdit) published property Anchors; property AutoSelect; property AutoSize; property BevelEdges; property BevelInner; property BevelKind; property BevelOuter; property BiDiMode; property BorderStyle; property CharCase; property Color; property Constraints; property Ctl3D; property DragCursor; property DragKind; property DragMode; property UpDown; property Enabled; property Font; property HideSelection; {property ImeMode;} {property ImeName;} {property MaxLength;} {property OEMConvert;} property ParentBiDiMode; property ParentColor; property ParentCtl3D; property ParentFont; property ParentShowHint; property PasswordChar; property PopupMenu; property ReadOnly; property ShowHint; property TabOrder; property TabStop; {property Text;} property Visible; property OnChange; property OnClick; property OnContextPopup; property OnDblClick; property OnDragDrop; property OnDragOver; property OnEndDock; property OnEndDrag; property OnEnter; property OnExit; property OnKeyDown; property OnKeyPress; property OnKeyUp; property OnMouseDown; property OnMouseMove; property OnMouseUp; property OnStartDock; property OnStartDrag; end; implementation { TBoundUpDown } constructor TBoundUpDown.Create(AOwner: TComponent); begin inherited Create(AOwner); Name := 'SubUpDown'; SetSubComponent(True); if Assigned(AOwner) then Caption := AOwner.Name; end; function TBoundUpDown.GetHeight: Integer; begin Result := inherited Height; end; function TBoundUpDown.GetLeft: Integer; begin Result := inherited Left; end; function TBoundUpDown.GetTop: Integer; begin Result := inherited Top; end; function TBoundUpDown.GetWidth: Integer; begin Result := inherited Width; end; { TCustomNumEdit } constructor TCustomNumEdit.Create(AOwner: TComponent); begin inherited Create(AOwner); FUpDown := TBoundUpDown.Create(Self); FUpDown.FreeNotification(Self); end; procedure TCustomNumEdit.CMBidimodechanged(var Message: TMessage); begin inherited; FUpDown.BiDiMode := BiDiMode; end; procedure TCustomNumEdit.CMEnabledchanged(var Message: TMessage); begin inherited; FUpDown.Enabled := Enabled; end; procedure TCustomNumEdit.CMVisiblechanged(var Message: TMessage); begin inherited; FUpDown.Visible := Visible; end; procedure TCustomNumEdit. Notification(AComponent: TComponent; Operation: TOperation); begin inherited Notification(AComponent, Operation); if (AComponent = FUpDown) and (Operation = opRemove) then FUpDown := nil; end; procedure TCustomNumEdit. SetBounds(ALeft, ATop, AWidth, AHeight: Integer); begin inherited SetBounds(ALeft, ATop, AWidth, AHeight); if HandleAllocated then PostMessage(Handle, NEM_REASSIGN, 0, 0); end; procedure TCustomNumEdit.SetParent(AParent: TWinControl); begin inherited SetParent(AParent); if FUpDown <> nil then begin FUpDown.Parent := AParent; FUpDown.Visible := True; end; end; procedure TCustomNumEdit.CreateWnd; begin inherited; PostMessage(Handle, NEM_REASSIGN, 0, 0); end; procedure TCustomNumEdit.NEMReassign(var Message); begin if FUpDown <> nil then if HandleAllocated and FUpDown.HandleAllocated then if Left + Width <> FUpDown.Left then FUpDown.Associate := Self; end; procedure TCustomNumEdit.CreateParams(var Params: TCreateParams); begin inherited; Params.Style := Params.Style or ES_NUMBER end; end.
2003-02-28 | 最終更新日時らしい |