コンポーネントをインストールせずに使う方法
|
24 |
ChangeComponent |
動作確認 |
Delphi2007 |
更新日 |
2008/01/21(月) 2008/03/26(木) |
Delphiでは開発環境(IDE)に
コンポーネントをインストールできます。
BDS2006付属のDelphi2006互換である
TurboDelphi Explorer 無料版では
この機能は制限されています。
複数のプロジェクトで使うような
汎用コンポーネントならインストールの手間は気になりませんが
一度のプロジェクトだけしか使わない改造コンポーネントを
IDEにインストールする気は失せてしまいます。
その場合、そのプロジェクトにコンポーネントを含んで
ソースコード内で動的生成してしまいましょう。
非常に簡単ですし、このコードを利用すれば
わずか1行を新たに記述することでコンポーネントを使えます。
もちろん、TurboDelphi Explorer 無料版でも使えて
無料版の制限を全く気にならなくさせるテクニックです。
まず、その改造コンポーネントが標準VCLの何のクラスから
派生しているかをしっておいてください。
例えばButtonEx.pasにTButtonExという
TButton派生のクラスを作っているとします。
ButtonEx.pasをプロジェクトと同じフォルダに配置して
Form上にTButtonのButton1を配置します。
次のようにコードを書いてください。
────────────────────
uses
ButtonEx,
TypInfo;
//コンポーネントを交換する関数
//usesにTypInfoを追加必要
function ChangeComponent(Original: TComponent; NewClass: TComponentClass): TComponent;
var
New: TComponent;
Stream: TStream;
Methods: array of TMethod;
aPPropInfo: array of PPropInfo;
MethodCount, i: Integer;
begin
SetLength(aPPropInfo, 16379);
MethodCount := GetPropList(Original.ClassInfo, [tkMethod], @aPPropInfo[0]);
SetLength(Methods, MethodCount);
for i := 0 to MethodCount - 1 do
Methods[i] := GetMethodProp(Original, aPPropInfo[i]);
Stream := TMemoryStream.Create; try
Stream.WriteComponent(Original);
New := NewClass.Create(Original.Owner);
if New is TControl then
TControl(New).Parent := TControl(Original).Parent;
Original.Free;
Stream.Position := 0;
Stream.ReadComponent(New);
finally Stream.free end;
for i := 0 to MethodCount - 1 do
SetMethodProp(New, aPPropInfo[i], Methods[i]);
Result := New;
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
Button1 := TButton(ChangeComponent(Button1, TButtonEx));
end;
────────────────────
これで、ButtonはTButtonExのクラスとして動作します。
TButtonEx独自の機能、例えばプロパティなどに値を代入する場合は
TButtonEx(Button1).MyProperty := 値
と型キャストを行って実行することができます。
このChangeComponentは
Publishedプロパティ、
つまりオブジェクトインスペクタで設定できるプロパティを
他のコンポーネントに引き継ぐ事ができる
仕組みになっています。
イベントも引き継げます。
例えば、拡張ボタンとして有名なものを試しに実行してみましょう。
パンタグラフ(fumika)さんの
COSMIC TOWER TCuteButton
http://homepage1.nifty.com/cosmic/delphi/vcl.html
Mr.XRAYさんの
均等割付グラデーションボタン
http://homepage2.nifty.com/Mr_XRAY/Delphi/plButton/index.htm
これらのコンポーネントはButtonなのに
TCustomPanelから派生しています。
そこで、TCustomPanelからの直接の派生ではないですが
ほぼ同一であるTPanelをFormに貼り付けて、
次のコードを書いておきます。
────────────────────
uses
plButton,
CuteBtn,
TypInfo;
procedure TForm1.FormCreate(Sender: TObject);
begin
Panel1 := TPanel(ChangeComponent(Panel1, TCuteButton));
TCuteButton(Panel1).Color := clLime;
Panel2.Caption := '';
Panel2 := TPanel(ChangeComponent(Panel2, TplButton));
TplButton(Panel2).Gradation := True;
TplButton(Panel2).CaptionA.Caption := 'テスト';
TplButton(Panel2).CaptionB.Caption := 'テスト';
end;
────────────────────
ChangeComponentを記述して
各ボタンの独自プロパティをコード上で設定しています。
実行した結果です。
Captionに空文字を代入しているのは
TCustomPanelにはCaptionプロパティがpublishedで公開されていない為
ChangeComponentの仕組みで引き継ぐ時に
TplButtonにはCaptionが無い!というエラーが出るため、
空文字を代入してプロパティを引き継がないようにしています。
追記:
毎回、TCuteButton(Panel1)やTplButton(Panel2)と
キャスト指定するのはかっこよくありませんね。
Panel1とPanel2はデザイン時にだけ使って
後はCuteButtonとplButtonは
自分で変数宣言して代入して使いましょう。
────────────────────
uses
plButton,
CuteBtn,
TypInfo;
type
TForm11 = class(TForm)
Panel1: TPanel;
Panel2: TPanel;
procedure Button1Click(Sender: TObject);
procedure FormCreate(Sender: TObject);
procedure Panel1Click(Sender: TObject);
procedure Panel2Click(Sender: TObject);
private
public
plButton1: TplButton;
CuteButton1: TCuteButton;
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
CuteButton1 := TCuteButton(ChangeComponent(Panel1, TCuteButton));
CuteButton1.Color := clLime;
Panel2.Caption := '';
plButton1 := TplButton(ChangeComponent(Panel2, TplButton));
plButton1.Gradation := True;
plButton1.CaptionA.Caption := 'テスト';
plButton1.CaptionB.Caption := 'テスト';
end;
procedure TForm11.Panel1Click(Sender: TObject);
begin
ShowMessage('CuteButtonテスト');
end;
procedure TForm11.Panel2Click(Sender: TObject);
begin
ShowMessage('plButtonテスト');
end;
────────────────────
これでより便利です。
参考────────────────────
DelFusaBlog コンポーネントをインストールせずに使う方法
http://delfusa.blog65.fc2.com/blog-entry-40.html
DelWiki - コード倉庫/コンポの付け替え
http://delwiki.info/?コード倉庫/コンポの付け替え
|