リストボックスに水平スクロールバーを表示する

リストボックスに長い文字列を登録するとリストボックスから文字がはみ出ますが
通常ではスクロールバーは表示されず全体を見ることが出来ません。

スクロールバーを表示するにはまずリストボックスのスタイルでWS_HSCROLLを追加し
(DDXでリストボックスのプロパティーのスタイルで水平スクロールバーをチェック)
CListBoxクラスメンバのSetHorizontalExtent()で最大スクロール幅を設定すると
水平スクロールバーが表示されるようになります。

しかし、最大スクロール幅を設定するといってもその大きさは分かりません。
必要以上に大きく取っておけば問題はありませんがみっともないです。
そこでリストに表示されている文字列の中で最大の幅を表示している文字列の幅を
ピクセル単位で取得してSetHorizontalExtent()で設定してやるといいです。

表示されてる文字列の幅をピクセル単位で取得するにはCDCクラスメンバの
GetTextExtent()で取得することが可能です。
しかし、これまたただリストボックスのデバイスコンテキストを取得し
GetTextExtent()を使用しても上手い具合に幅を取得することが出来ません。
これはデバイスコンテキストにフォントが設定されていない為、
システムのデフォルトのフォントで大きさを計算してしまうからです。
これを回避する為、デバイスコンテキストのフォントをリストボックスで使用している
フォントに設定してやる必要があります。
フォントの設定の仕方はCDCクラスのSelectObject()を使用し、
リストボックスに使われているフォントの取得はCWndクラスのGetFont()で取得します。
フォントを設定した時の戻り値は後でフォントを戻す為、取っておいてください。
(必要無い気もしますがフォントを解放する為に必要みたいです)

それからGetTextExtent()で取得できる文字列の幅を
そのままリストボックスに設定してやるとピチピチになってしまうので
+5 ぐらいしてやって少し余裕を持たせるといいです。

2001/3/5 追記
最後に
GetDC()で取得したデバイスコンテキストは開放する必要があるので
ReleaseDC()で開放してやります。

これらをまとめると次のようになります。


// m_listboxはリストボックスのCListBox型コントロールメンバ
int nMax = 0;
int nSize;
CString strText;

// リストボックスのデバイスコンテキストを取得
CDC *pDC = m_listbox.GetDC();

// デバイスコンテキストにリストボックスのフォントを設定
CFont* pOldFont = pDC->SelectObject(m_listbox.GetFont());

// リストボックス内の最大文字列幅取得
for(int i = 0;i < m_listbox.GetCount(); ++i)
{
    m_listbox.GetText(i, strText);
    nSize = pDC->GetTextExtent(strText).cx;
    if(nMax < nSize)
        nMax = nSize;
}

// 水平スクロールバーを設定
m_listbox.SetHorizontalExtent(nMax + 5);

// デバイスコンテキストのフォントを元に戻す
pDC->SelectObject(pOldFont);
ReleaseDC(pDC);    // 2001/3/5 デバイスコンテキストの開放を忘れていたのを修正

これを関数にしてリストボックスに項目を追加したり削除した後に
呼び出してやればいいのですが、リストの項目が多くなってくると
設定に時間がかかってしまうのであまりお勧めは出来ません。

最大幅を保存するメンバ変数を定義しておいて
項目追加時は追加する項目の文字幅が最大幅より大きいか調べ、
大きければその文字幅をリストボックスに設定してやり最大幅を更新する。
項目削除時は削除する項目の文字幅が最大幅かどうか調べて
同じ大きさの時だけ上記の処理をしてリストボックスと最大幅を再設定する。
といったようにすれば項目数が多くなっても重くならないので良いでしょう。

< 戻る << HOME ©1999-2001 by Akky, All right reserved.