はじめに
会社で Delphi 使用しているのですが、コンポーネントを作成するという文化が無かった為、この度勉強してみました。シチュエーションとして、外部への配布は考えず、社内で共用利用する事を想定しています。あ、VCLです。Delphi XE3 での例となります。
手順(長いです)
作成例:「一定時間アニメーションすると、自動でアニメーションが停止するトレイアイコンを作りたい」 (常駐アプリで使用する事を想定)1.パッケージを新規作成する
Delphiを起動し、ファイル → 新規作成 → パッケージ を選択します。 ![ss1.png](https://qiita-image-store.s3.amazonaws.com/0/33684/c4bf508d-a580-8aa9-dbba-54a934064514.png)プロジェクトが作られたので、最初に「プロジェクトに名前を付けて保存」を実行します。
ここでは、D:\MyComponent\MyPackage.dproj としました。
2.コンポーネントを新規作成する
プロジェクトマネージャ画面にて、「Contains」を右クリック、新規追加→その他 ![ss3.png](https://qiita-image-store.s3.amazonaws.com/0/33684/3880cfd9-a193-0ac8-ce7e-746d65386825.png)継承元コンポーネントで、TCustomTrayIconを選択。
(TTrayIconとどちらを継承元にすべきかは、追加したい機能にて判断する、と自分は解釈しました)
クラス名、パレットページ名、ユニット名をそれぞれ変更しました。
完了すると、まずユニットの保存を要求されますので、「D:\MyComponent\」を選択(直前の設定がデフォルトになる筈?)。
最後に、以下のような確認ダイアログが表示されます。
「はい」で問題無いかと思います。
3.実装する
(何故クラスを2個作っているかと聞かれると、答えられません。VCLの他のコンポーネントの作りに従いました。)unit AutoStopTrayIcon;
interface
uses
System.SysUtils, System.Classes, Vcl.ExtCtrls, Winapi.MMSystem;
type
TAutoStopCustomTrayIcon = class(TCustomTrayIcon)
private
FAnimationStartTime:Integer;
FAnimationLifetime:Integer;
procedure SetAnimationLifetime(Value:Integer);
function GetAnimate: Boolean;
protected
constructor Create(Owner: TComponent); override;
procedure DoOnAnimate(Sender: TObject); override;
public
procedure DoAnimate;
property AnimationLifetime:Integer read FAnimationLifetime write SetAnimationLifetime default 1000;
property Animate:Boolean read GetAnimate;
end;
TAutoStopTrayIcon = class(TAutoStopCustomTrayIcon)
published
property AnimationLifetime;
property AnimateInterval;
property Hint;
property BalloonHint;
property BalloonTitle;
property BalloonTimeout;
property BalloonFlags;
property Icon;
property Icons;
property IconIndex;
property PopupMenu;
property Visible;
property OnBalloonClick;
property OnClick;
property OnDblClick;
property OnMouseMove;
property OnMouseUp;
property OnMouseDown;
property OnAnimate;
end;
procedure Register;
implementation
procedure Register;
begin
RegisterComponents('MyComponent', [TAutoStopTrayIcon]);
end;
{ TAutoStopCustomTrayIcon }
constructor TAutoStopCustomTrayIcon.Create(Owner: TComponent);
begin
inherited;
FAnimationLifetime:= 1000;
end;
procedure TAutoStopCustomTrayIcon.DoAnimate;
begin
FAnimationStartTime := TimeGetTime;
SetAnimate(True);
end;
procedure TAutoStopCustomTrayIcon.DoOnAnimate(Sender: TObject);
begin
inherited;
if (TimeGetTime > FAnimationStartTime+FAnimationLifetime ) then
SetAnimate(False);
end;
function TAutoStopCustomTrayIcon.GetAnimate: Boolean;
begin
Result := inherited Animate;
end;
procedure TAutoStopCustomTrayIcon.SetAnimationLifetime(Value: Integer);
begin
if (Value < 0) then
FAnimationLifetime := 0
else
FAnimationLifetime := Value;
end;
end.
プロパティのデフォルト値
マジックナンバー「1000」が2回も出てきて気持ち悪いですが、それぞれ役割が違いました。 (interfaceの方)property AnimationLifetime:Integer read FAnimationLifetime write SetAnimationLifetime default 1000;
これは、(恐らく)DelphiのIDE上で、「プロパティに設定されている値がデフォルト値かどうか」を判定する為に使用されています。
上の例だと、プロパティに1000が設定されていると細字、それ以外の値だと太字強調されるようになります。
(constructorの方)
constructor TAutoStopCustomTrayIcon.Create(Owner: TComponent);
begin
inherited;
FAnimationLifetime:= 1000;
end;
こちらは、コンポーネントをフォームに配置した際の「IDEのプロパティにデフォルトで入力されている値」を決めています。
基本、宣言部と同値で良いような気がしました。(別にしておくとこういう使い方が!など有りましたら是非・・)
継承元プロパティの書き込みを防ぐ
今回はアニメーションの停止を自動で行うので、通常のアニメーション状態を制御するAnimateプロパティを読み取り専用とし、アニメ開始時はDoAnimateメソッドを呼び出すように設計してみました。 プロパティを再宣言してあげれば良い様子。デス。このあたり。
property Animate:Boolean read GetAnimate;
function TAutoStopCustomTrayIcon.GetAnimate: Boolean;
begin
Result := inherited Animate;
end;
4.使ってみる
コンポーネントのインストール
最初にメニューのプロジェクト → MyPackageのコンパイル を選択します。特にエラーがなければ、コンポーネントのインストールが可能です。
プロジェクトマネージャ上で、MyPackage.bplを右クリックし、インストールを選択します。
ライブラリパスの設定
コンポーネントを使用してみる前に、ライブライパスを設定しておきましょう。 メニューの「ツール」→「オプション」を選択し、 ![ss12.png](https://qiita-image-store.s3.amazonaws.com/0/33684/64d750b2-4ba3-4d46-af89-0deaddab204e.png)テストアプリケーションの作成
疲れてきました。いよいよ大詰めです。 MyPackegeは一旦閉じて、新規にプロジェクトを作ってみましょう。配置すると、無事プロパティにもデフォルト値が設定されていました。
あとはImageListコンポーネントを配置し、画像を読み込みます。
(←ペイントで64px*16pxの画像を作った)
AutoStopTrayIcon1のIconsプロパティにImageList1を設定したり、ボタンを配置します。
procedure TForm1.Button1Click(Sender: TObject);
begin
AutoStopTrayIcon1.Visible := True;
AutoStopTrayIcon1.DoAnimate;
end;
上手く行けば、10秒間、1秒ごとに画像が切り替わります。
終わりに
作ったコンポーネント/パッケージを社内で共有する場合は、 D:\MyConponent 内のファイルをバージョン管理下に置けばよいのかな?と思います。 各自ローカルにチェックアウトして、パッケージのインストール・ライブラリパスの設定が必要になると思います。こうした方が楽!とか、間違っている点がありましたら、ご指摘いただければと思います。