Swanman's Horizon

性欲をもてあましつつなんらかの話をするよ。

Component Initializerのちょっと便利な使い方。

Component Initializerとは?

Component Initializerは、去年のAdvent Calendar用記事で紹介した、IDE上でコンポーネントを配置する際にちょっとしたコードを走らせることのできるプラグインです。
その「ちょっとしたコード」のサンプルとして、プラグインにはTEditやTMemo、TPanelといったコンポーネントを配置した際にそれぞれのText、Lines、Captionプロパティを空にする…というものが入っていますが、他にも便利かもしれないサンプルを紹介してみます。

TFormのフォントを設定する

日本語版のDelphi 7までは、新規にフォームを作成するとフォントとして「MS Pゴシック」がデフォルト指定されていましたが、それ以降は「Tahoma」になってしまいました。そのため、新規にフォームを作った際はまずフォントを変更するという方は多いと思います。
Component Initializerで初期化コードを書くイベント関数には、配置されたコンポーネントを指す「Self」引数だけでなく、「Parent」も引数として渡されます。フォームに直接何かを置いた場合、Parentの中身はフォームなので、これに対してフォントを設定すればいいわけです。

procedure OnCreateComponent(Self: TObject; Parent: TComponent; const Rect: TRect);
begin
  if (Parent is Vcl.Forms.TForm) and (Parent.ComponentCount <= 1) then
  begin
    with Vcl.Forms.TForm(Parent) do
    begin
      Font.Name := 'MS UI Gothic';
      Font.Size := 9;
      Scaled := False; // ついでにw
    end;
  end;
end;

TUpDownをTEditに関連付ける

TUpDownというのは上下ボタンのコンポーネントで、単体で使うこともあるかもしれませんが、多くはTEditなどのエディットコントロールと組み合わせて使います。TUpDown側にもAssociateというプロパティがあるので、ここにTEditなどのコンポーネントをセットしておくと、値がお互いに連動するようになります。
僕なんかはほぼ100%TEditと組み合わせて使うんですが、実際にAssociateを指定する時、画面上にすでにたくさんのコンポーネントが配置されているとリスト上にも大量のコンポーネントが表示されてしまうため、結構面倒だったりします。というわけでこれを自動化してみたのが以下のコードです。

procedure OnCreateComponent(Self: TObject; Parent: TComponent; const Rect: TRect);
var
  distCurr, distMin: Double;
  edit: Vcl.StdCtrls.TCustomEdit;
  i: Integer;
  r: TRect;
begin
  if Self is Vcl.ComCtrls.TUpDown then
  begin
    if not (Parent is Vcl.Controls.TWinControl) then Exit;
    distMin := MaxDouble;
    edit := nil;
    for i := 0 to Vcl.Controls.TWinControl(Parent).ControlCount-1 do
    begin
      if not (Vcl.Controls.TWinControl(Parent).Controls[i] is TCustomEdit) then Continue;
      r := Vcl.Controls.TWinControl(Parent).Controls[i].BoundsRect;
      distCurr := Sqrt(Sqr(r.Right - Vcl.ComCtrls.TUpDown(Self).Left) + Sqr(r.Top - Vcl.ComCtrls.TUpDown(Self).Top));
      if distCurr < distMin then
      begin
        distMin := distCurr;
        edit := TCustomEdit(Vcl.Controls.TWinControl(Parent).Controls[i]);
      end;
    end;
    if edit = nil then Exit;
    try // ←同じTEditに複数のTUpDownを関連付けるとエラーになるので、その簡易対策
      Vcl.ComCtrls.TUpDown(Self).Associate := edit;
    except
    end;
  end;
end;

これでコンポーネントパレットからTUpDownを選んだ後、TEditの右肩付近をクリックすれば、そこに関連付けた状態でTUpDownが配置されます。

終わりに

今回はVCLのサンプルでしたが、もちろんFireMonkeyのコンポーネントでも同じようにコードを走らせることが可能ですし、TTimerといった非ビジュアルコンポーネントにも適用可能です。なので、例えば非ビジュアルコンポを置く度にそれらを綺麗に整列する、といった処理も書くことができます。
他にも何か面白い活用方法を思いついた方は教えてもらえると嬉しいです。