Delphi Programming / Object Pascal
サイトのトップページへ リンクのページへ ロゴマーク
[掲載 2005年04月10日] [更新 2013年10月31日] Delphi サンプルプログラム集
162_サブコンポーネントの作成方法
動作確認等 Windows 7 U64(SP1) + Delphi XE Pro
162_SubComponent.zip [543 KB] 2013年10月31日版 (EXE 同梱)







サブコンポーネントとは


ここでは,TPanel の上に TTrackBar と TEdit を配置したコンポーネントを作成します.
TTrackBar と TEdit は,作成したコンポーネントの内部コンポーネントになります.このような内部コンポーネントは,設計時にオブジェクトインスペクタでプロパティを設定しても,実行時には初期化され,無視されてしまいます.
オブジェクトインスペクタで設定できるにも関わらず,実行時に反映されないというのは,オブジェクトインスペクタにプロパティを表示している意味がありません.
サブコンポーネントは,主に,そのような内部コンポーネントの設計時の設定を,実行時に有効にするための実装です.


[備考]
設計時に,オブジェクトインスペクタで,内部コンポーネントの設定をさせたくない場合は,内部コンポーネントを public のメンバにします.public なメンバのプロパティは,オブジェクトインスペクタには表示されません.






01_サブコンポーネントの作成方法


サブコンポーネントの作成方法は,内部コンポーネント (子コンポーネント) の作成方法とほとんど同じです.あるコンポーネントの内部コンポーネントをサブコンポーネントにするには,
  • (1) プロパティとしての内部コンポーネントはリードオンリーにする
  • (2) 内部コンポーネント自身の コンストラクタ (Create) で,SetSubComponent を実行する
  • (3) Assign メソッドの実装は不要なので,実装していたら該当コードを削除する
とします.これで,内部コンポーネントがサブコンポーネントになります.





02_サブコンポーネントの例


下の plPanelTrackBarEditEx.pas がテストに使用したコンポーネントのコードです.
このテストプログラムを使用するには,添付の plPanelTrackBarEditEx.pas をコンポーネントとして登録 (インストール) しておく必要があります.


図1
設計時画面
  • コンポーネントを配置
図2
オブジェクト・インスペクタ
  • TEdit の Text の値を 30 にしてコンパイル
  • サブコンポーネントは,イベントも設定可能
図3
実行開始画面
  • トラックバーの位置が 30 になっている

リスト1
メインプログラムのコード
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, plPanelTrackBarEditEx, ExtCtrls;

type
  TForm1 = class(TForm)
    plPanelTrackBarEditEx1: TplPanelTrackBarEditEx;
    procedure FormShow(Sender: TObject);
  private
    { Private 宣言 }
  public
    { Public 宣言 }
  end;

var
  Form1: TForm1;

implementation

{$R *.DFM}

{ TForm1 }

//=============================================================================
//  フォーカスをコンホーネントの内部コンポーネントのトラックバーに移動
//=============================================================================
procedure TForm1.FormShow(Sender: TObject);
begin
  plPanelTrackBarEditEx1.TrackBar.SetFocus;
end;

end.


リスト2
サブコンポーネントを持つコンポーネントの例
unit plPanelTrackBarEditEx;

interface

uses
  SysUtils, Classes, Controls, ExtCtrls, StdCtrls, ComCtrls, Graphics;

type
  //前方参照
  TplTrackBar = class;
  TplEditSP   = class;

  TplPanelTrackBarEditEx = class(TPanel)
  private
    { Private 宣言 }
    FTrackBar : TplTrackBar;
    FEdit     : TplEditSP;
  protected
    { Protected 宣言 }
    procedure SetParent(AParent: TWinControl); override;
    procedure Resize; override;
  public
    { Public 宣言 }
    constructor Create( AOwner: TComponent); override;
    destructor  Destroy; override;
  published
    { Published 宣言 }
    //サブコンポーネントはリードオンリーとする
    property TrackBar : TplTrackBar read FTrackBar;
    property Edit     : TplEditSP   read FEdit;
  end;

  //内部コントロールでサブコンポーネントのTTrackBar
  TplTrackBar = class(TTrackBar)
  private
    FPanelTrackBarEditEx : TplPanelTrackBarEditEx;
  protected
    procedure Changed; override;
  public
    constructor Create( AOwner: TComponent); override;
    property PanelTrackBarEditEx : TplPanelTrackBarEditEx read FPanelTrackBarEditEx;
  end;

  //内部コントロールでサブコンポーネントのTEdit
  TplEditSP = class(TCustomEdit)
  private
    FPanelTrackBarEditEx : TplPanelTrackBarEditEx;
  protected
    procedure Change; override;
    procedure DoEnter; override;
    procedure KeyPress(var Key: Char); override;
  public
    constructor Create( AOwner: TComponent); override;
    property PanelTrackBarEditEx : TplPanelTrackBarEditEx read FPanelTrackBarEditEx;
  published
    property Text;
  end;

procedure Register;

implementation

{ TplTrackBarEditEx }

//-----------------------------------------------------------------------------
//  コンポーネントのCreate処理
//  ビジュアルな内部コンポーネントはSetParentで生成する
//  非ビジュアルな内部コンポーネントはCreateで生成してよい
//-----------------------------------------------------------------------------
constructor TplPanelTrackBarEditEx.Create(AOwner: TComponent);
begin
  inherited;

  Caption := '';
  Width   := 250;
  Height  := 85;
  Color   := $00AFBBA6;

  //これがないとTPanelのColorプロパティの設定が反映されない場合がある
  Self.ParentBackground := False;
end;

//-----------------------------------------------------------------------------
//  コンポのDestroy処理
//  内部コンポーネントを解放する
//-----------------------------------------------------------------------------
destructor TplPanelTrackBarEditEx.Destroy;
begin
  if Assigned(FTrackBar) then FreeAndNil(FTrackBar);
  if Assigned(FEdit)     then FreeAndNil(FEdit);

  inherited;
end;

//-----------------------------------------------------------------------------
//  コンポのSetParent処理
//  ビジュアルな内部コンポーネントはSetParentで生成する
//  SetParentメソッドは何回も呼出されるので注意
//-----------------------------------------------------------------------------
procedure TplPanelTrackBarEditEx.SetParent(AParent: TWinControl);
begin
  inherited;

  if AParent = nil then exit;

  Caption := '';

   if not Assigned(FTrackBar) then begin
    FTrackBar := TplTrackBar.Create(Self);

    FTrackBar.Parent    := Self;
    FTrackBar.Left      := 10;
    FTrackBar.Top       := 10;
    FTrackBar.Height    := 35;
    FTrackBar.Width     := Self.Width - 20;
    FTrackBar.Min       := 0;
    FTrackBar.Max       := 100;
    FTrackBar.Frequency := 10;
    FTrackBar.TickStyle := tsNone;
    FTrackBar.FPanelTrackBarEditEx := Self;
  end;

  if not Assigned(FEdit) then begin
    FEdit := TplEditSP.Create(Self);

    FEdit.Parent := Self;
    FEdit.Left   := FTrackBar.Left + 5;
    FEdit.Top    := FTrackBar.Top + FTrackBar.Height + 3;
    FEdit.Width  := 45;
    FEdit.FPanelTrackBarEditEx := Self;
  end;
end;

//-----------------------------------------------------------------------------
//  コンポのResizeメソッド
//  内部コンポーネントのTTrackBarのサイズを変更する
//-----------------------------------------------------------------------------
procedure TplPanelTrackBarEditEx.Resize;
begin
  inherited;
  if not Assigned(FTrackBar) then exit;

  FTrackBar.Width := Self.Width - 20;
end;

{ TplTrackBar }

//-----------------------------------------------------------------------------
//  内部コンポーネントTplTrackBarのCreateメソッド
//-----------------------------------------------------------------------------
constructor TplTrackBar.Create(AOwner: TComponent);
begin
  inherited;
  //サブコンポーネントにする
  SetSubComponent(True);
end;

//-----------------------------------------------------------------------------
//  内部コンポーネントTplTrackBarのChangeメソッド
//-----------------------------------------------------------------------------
procedure TplTrackBar.Changed;
begin
  inherited;
  FPanelTrackBarEditEx.FEdit.Text := IntTostr(Self.Position);
end;

{ TplEditSP }

//-----------------------------------------------------------------------------
//  内部コンポーネントTplEditSPのCreateメソッド
//-----------------------------------------------------------------------------
constructor TplEditSP.Create(AOwner: TComponent);
begin
  inherited;
  //サブコンポーネントにする
  SetSubComponent(True);
end;

//-----------------------------------------------------------------------------
//  内部コンポーネントTplEditSPのChangeメソッド
//-----------------------------------------------------------------------------
procedure TplEditSP.Change;
begin
  inherited;
  FPanelTrackBarEditEx.FTrackBar.Position :=
            StrToIntDef(FPanelTrackBarEditEx.FEdit.Text, 0);
end;

//-----------------------------------------------------------------------------
//  内部コンポーネントTplEditSPのDoEnterメソッド
//-----------------------------------------------------------------------------
procedure TplEditSP.DoEnter;
begin
  inherited;

  //かな漢字入力を不可にしてしまう
  SetImeMode(Handle, imDisable);
end;

//-----------------------------------------------------------------------------
//  内部コンポーネントTplEditSPのKeyPressメソッド
//-----------------------------------------------------------------------------
procedure TplEditSP.KeyPress(var Key: Char);
begin
  //数値以外は入力させない
  //英字は入力できない. #8は[BackSpace]. #27は[Escape]
  if ((Key >= '0') and (Key <= '9')) or (Key = #8) or (Key = #27) then begin
    inherited KeyPress(Key);
  end else begin
    Key := #0;
  end;
end;

//-----------------------------------------------------------------------------
//  コンポーネント登録情報
//-----------------------------------------------------------------------------
procedure Register;
begin
  RegisterComponents('plXRAY', [TplPanelTrackBarEditEx]);
end;

end.