Migaro. 技術Tips

                       

ミガロ. 製品の技術情報
IBMiの活用に役立つ情報を掲載!


【Delphi】画面をドッキングする制御方法について

Delphi/400にはドッキングと呼ばれる機能が用意されており、
画面の結合や分離をプロパティの設定やコーディングで制御することができます。

今回はこの手順を紹介します。

 


ドッキングの仕組み

画面の結合(ドッキング)を行うには
ドッキング元(子)とドッキング先(親)がそれぞれ必要となります。

ドッキング先(親)には、以下のようなコンテナコンポーネント(土台)を指定可能です。

  • TForm
  • TPanel
  • TPageControl(TTabSheet)
  • TScrollBox
  • TDockTabSet・・・など
     

ドッキング元(子)は、基本的には別のフォームとなります。

ドッキングを行うと、ドッキング元(子)をドッキング先(親)の中に
格納したような見た目になります。

 
 


画面をドッキング/ドッキング解除する手順

ドッキング先(親)には、以下のプロパティを設定しておきます。

DockSite = True

またドッキング元(子)には、以下のプロパティを設定しておきます。

DragKind = dkDock
DragMode = dmAutomatic

この状態でドッキング先(親)を含むフォームからドッキング元(子)のフォームを生成し、
Showで表示した状態からドラッグ&ドロップすると、画面がドッキングされます。

ドッキング元の種類にもよりますが、
ドラッグ&ドロップで引き剥がす(ドッキング解除)ことも可能です。

 
 


プログラムでドッキング/ドッキング解除する手順

ドラッグ&ドロップする以外にも、
以下のようなロジックでドッキングが可能です。
(先述のドラッグ&ドロップ時のようなプロパティ設定は不要です。)

ロジックでドッキングする場合は、以下のようにManualDockを使用します。

procedure TForm1.Button1Click(Sender: TObject);
begin
  Form2 := TForm2.Create(Application);  // 画面(子)を作成
  Form2.ManualDock(PageControl1);       // 画面(子)をPagecontrolにドッキングさせる
  Form2.Show; // 画面(子)を表示
end;

 

ロジックでドッキングを解除するには、以下のようにManualFloatを使用します。

以下の例では、ドッキング元フォーム(Form2)のカレンダー(Calendar1)を
ダブルクリックした時に切り替えができるようになっています。

※ドッキングの状態はFloatingという内部プロパティで判断できます。
※ドッキング元のフォームでuses節にドッキング先のフォームを追加する必要があります。

procedure TForm2.Calendar1DblClick(Sender: TObject);
begin
  if Floating then // フロート(ドッキング解除状態)であればドッキング
  begin
    ManualDock(Form1.PageControl1);
  end
  else             // ドッキング状態であればドッキング解除
  begin
    ManualFloat(Rect(0, 0, Width, Height));
  end;
end;

 
 


応用テクニック

以下のようなロジックで、ドッキング先を制御することが可能です。

ドッキング先(親)のOnGetSiteInfoイベントで条件を付けることで、
ドッキングを無効にできます。

procedure TForm1.PageControl1GetSiteInfo(Sender: TObject; DockClient: TControl;
  var InfluenceRect: TRect; MousePos: TPoint; var CanDock: Boolean);
begin
  if DockClient is TForm3 then //ドッキングする画面がXXXXであれば
  begin
    CanDock := False; //ドッキングを無効にする
  end;
end;

 

また、PageControlなどを使用していて合計の項目数が非常に多い画面がある場合、
単独画面にすべてのコンポーネントを配置していると
画面の起動だけでもかなりの時間を要したり、プログラムを修正する際に
どこを直せばいいのか煩雑になりすぎる場合があります。
(DelphiのIDEで設計画面を表示するだけでもかなりの時間を要するでしょう。)

このような場合に、個々のタブの情報を独立した画面として設計しておき、
ドッキング先(親)の画面の生成時に各画面(タブ)をドッキングさせることで
レスポンスや開発・修正工数の削減が期待できます。

以下のロジック例では、Form1のPageControl1に対して
項目がいっぱいのForm2・3・4を生成時にドッキングさせることで
あたかもForm1に項目が多い3タブが最初からあったかのような画面を表示できます。

procedure TForm1.FormCreate(Sender: TObject);
begin
  Form2 := TForm2.Create(Application); // 画面(子)を作成
  Form2.ManualDock(TabSheet1);         // 画面(子)をTabSheetにドッキングさせる
  Form2.Show;                          // 画面(子)を表示

  Form3 := TForm3.Create(Application);
  Form3.ManualDock(PageControl1);      // Pagecontrolにドッキングすると新規タブになる
  Form3.Show;                          // Showしないと非表示のまま

  Form4 := TForm4.Create(Application);
  Form4.ManualDock(PageControl1);
  Form4.Show;
end;

<上記のサンプルロジックを実行した際のイメージ>

 
 


注意ポイント

ここまで便利なドッキング機能をご紹介しましたが、以下のポイントにはご注意ください。

ドッキング先(親)を含む画面がドッキングしたまま閉じられた場合、
ドッキング元(子)の画面も閉じてしまいます。

ここまでは当たり前かと思われますが、
逆にドッキング元(子)の画面でTBitBtnのKind=bkcloseを使って
閉じるボタンを作成すると、このボタンがドッキング中に押されることで
ドッキング先(親)を含む画面ごと閉じてしまうのでご注意ください。
(ロジックで「Self.Close;」などを使って閉じた場合は、正しくドッキング元のみが閉じられます。)

 

 

(第10回 ミガロ. テクニカルセミナー
 知って得する!現役ヘルプデスクが答えるDelphiテクニカルエッセンス 10.0 より)