./index.html ../index.html

サブコンポーネント

TLabbeledEditみたいな複合コントロールにも使われるサブコンポーネント機能について。

TEditTUpDownの連動もよく使う組み合わせです。 というかサンプルにすらTSpinEditがあります。 しかし、TSpinEditはWindowsとは別に独自に実装を持っているので何となく外観が異なります。 やはりここはTEditTUpDownを組み合わせたい!

今まで、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最終更新日時らしい