Migaro. 技術Tips

                       

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


【Delphi】リストボックスを2段表示する方法

得意先などを検索したいときに、その情報を特定するために
企業名・郵便番号・住所などをTListBoxに表示する場合があるかと思います。
その際に、住所など長くてリストボックスに表示しきれない項目もあるかと思います。

一般的には略称を使用したり、一部のみ表示したりなどの工夫をすることが多いですが、
リストの高さを大きくして対応する方法もあります。
その手順を以下に解説します。
 


 
まず以下のように画面にTListBoxを2つ配置します。
今回は右側のListBox2にのみ2段表示を実装し、結果表示を比較したいと思います。


 
2段表示に必要な設定として、
設計画面にてStyleプロパティをlbOwnerDrawVariableに変更しておきます。
(ロジックで記述しても可)

続いて、リストの中にデータを描く作業を2つのイベントを使って実装します。

 

①:OnMeasureItemイベントを使って、リスト項目の高さの変更を行います。
何もしないとリスト中の各項目の高さは1行分になっていますが、
ここで2行表示するのに必要な高さを計算しHeightに代入します。以下に例を示します。
(※3行以上の項目にも対応しています。)

procedure TForm1.ListBox2MeasureItem(Control: TWinControl; Index: Integer;
  var Height: Integer);
var
  R: TRect;
  LB: TListBox;
begin
  LB := TListBox(Control);

  // 幅いっぱいで高さ計算
  R := Rect(0, 0, LB.ClientWidth, 0);
  DrawText(LB.Canvas.Handle,
    PChar(LB.Items[Index]),
    -1,
    R,
    DT_LEFT or DT_TOP or DT_WORDBREAK or DT_CALCRECT);

  Height := R.Bottom - R.Top + 4; // 計算結果+少し余白をもたせる
end;

 

②:OnDrawItemイベントを使って、実際に描画を行います。
FillRect関数で描画領域を塗りつぶし、きれいになった領域にDrawText関数で描画します。
以下に例を示します。

procedure TForm1.ListBox2DrawItem(Control: TWinControl; Index: Integer;
  Rect: TRect; State: TOwnerDrawState);
var
  LB: TListBox;
begin
  LB := TListBox(Control);
  TListBox(Control).Canvas.FillRect(Rect);

  DrawText(LB.Canvas.Handle,
    PChar(LB.Items[Index]),
    -1,
    Rect,
    DT_LEFT or DT_TOP);
end;

 


 
プロジェクトをコンパイルして実行すると、
値を別途設定(※)しておいた各TListBoxの見た目は以下のようになります。

左が初期状態、右が今回のロジック適用で複数行対応した状態
 

※TListBoxのItemsには、
 以下のようにロジックで改行コード「#13#10」を含む値を1項目ずつ追加しておく必要があります。
 設計画面で元からセットされていたItemsには今回の描画変更は効きません。

  ListBox1.Items.Add('★株式会社サンプル' + #13#10 + '大阪市北区梅田1-1-1');
  ListBox1.Items.Add('★1行表示のテスト');
  ListBox1.Items.Add('★テスト商事' + #13#10 + '東京都千代田区1-2-3');
  ListBox1.Items.Add('★株式会社ミガロ.' + #13#10 + '浪速区湊町2-1-57' + #13#10 + '難波サンケイビル13F');

  ListBox2.Items.Add('★株式会社サンプル' + #13#10 + '大阪市北区梅田1-1-1');
  ListBox2.Items.Add('★1行表示のテスト');
  ListBox2.Items.Add('★テスト商事' + #13#10 + '東京都千代田区1-2-3');
  ListBox2.Items.Add('★株式会社ミガロ.' + #13#10 + '浪速区湊町2-1-57' + #13#10 + '難波サンケイビル13F');

  // ListBox2.Items.Text := ListBox1.Items.Text;
  // といった代入ロジックは、中の改行コードで別々の項目扱いされるため無効

 

 

(ミガロ.情報マガジン「MIGARO News!!」Vol.010 2001年11月号より、最新バージョン向けに修正)