リストのカラム幅を最適化するには?

解決


いかた  2007-02-28 09:42:38  No: 64550  IP: 192.*.*.*

VC++6.0での開発です。
CListCtrlの拡張クラスを作成しているのですが、全カラム幅を最適化(ヘッダ及びアイテムが、…など省略なしに全て可視となる状態に)する手法について教えて頂きたく。
対象の全カラムに、CListCtrl::SetColumnWidth を LVSCW_AUTOSIZE_USEHEADER 指定で実行すれば良いものと考えておりましたが、初期状態で不可視となるアイテム(初期状態からスクロールバーで移動しなければ見えないアイテム)が、"xxxx..."となり最適化することが出来ません。以下のソースです。
void CListCtrlExt::SetAutoSizeColumnWidth()
{
  // カラム(ヘッダ)の最大数を取得
  int nColCount = GetColumnCount();  // 内部関数を使用

  for (int nCol=0; nCol<nColCount; nCol++)
  {
    // ヘッダ幅による最適化
    CListCtrl::SetColumnWidth(nCol, LVSCW_AUTOSIZE_USEHEADER);
  }
}

ですので、以下のように変更しました。

void CListCtrlExt::SetAutoSizeColumnWidth()
{
  // カラム(ヘッダ)の最大数を取得
  int nColCount = GetColumnCount();  // 内部関数を使用
  // アイテム最大数を取得
  int nItemCount = CListCtrl::GetItemCount();//■追加■

  for (int nCol=0; nCol<nColCount; nCol++)
  {
    // ヘッダ幅による最適化
    CListCtrl::SetColumnWidth(nCol, LVSCW_AUTOSIZE_USEHEADER);

    //■追加■ ここから ----------------------------------------

    // ヘッダ幅による最適化により設定された幅をデフォルト値とする
    int nMaxWidth = CListCtrl::GetColumnWidth(nCol);

    for (int nItem=0; nItem<nItemCount; nItem++)
    {
      // アイテムテキストの幅を取得
      CString strItemText = m_pList->GetItemText(nItem, nCol);
      int nTmpWidth = m_pList->GetStringWidth(strItemText);

      // アイテムテキストを表示するためにマージンを設定
      nTmpWidth += 16;

      // 最大の幅となる場合は情報を更新
      if (nTmpWidth > nMaxWidth)
      {
        nMaxWidth = nTmpWidth;
      }
    }

    // 最大幅をヘッダ幅に設定
    m_pList->SetColumnWidth(nCol, nMaxWidth);

    //■追加■ ここまで ----------------------------------------
  }

}
## アイコン描画時に対応するための処理も追加予定です。

期待する動きは実現出来たのですが、作り的にどうも好ましく感じず、悩んでおります。回避方法をご存知の方いらっしゃいましたら、教えて頂きたく。
ちなみに、オーナー描画はしておりませんが、仮想リスト(LVS_OWNERDATA)で作成しております。

よろしくお願い致します。

編集 削除
いかた  2007-02-28 10:03:38  No: 64551  IP: 192.*.*.*

非仮想リスト(LVS_OWNERDATA設定なし)で試したところ、
最初の手法で期待する動作が確認できました。
仮想リストの場合は、なにか特別なやり方が必要なのかもしれません。
ご存知の方いらっしゃいませんでしょうか?

編集 削除
PATIO  2007-03-01 17:08:22  No: 64552  IP: 192.*.*.*

仮想リストの場合は表示対象外の場合は、LVSCW_AUTOSIZE_USEHEADERを使っても
データ取得に来ていないのでは?
仮想リストは表示対象で無い部分の処理をスキップする事で無駄な処理を
省く目的で使いますからそれはそれでリーズナブルな動きなのではと思います。

ただ、それだったらどうすれば良いのと言う話に関しては分からないですねぇ。
常に全ての項目が表示できる状態になっていれば良いと言う話なら、
LVSCW_AUTOSIZE_USEHEADERを使わずに各カラム毎の最長文字列をきちんと
管理しておいてデータ取得処理が来たタイミングでカラム幅が想定サイズで
無かったら強制的にサイズ変更を行うような処理をするしかないかもしれません。

編集 削除
いかた  2007-03-02 11:54:54  No: 64553  IP: 192.*.*.*

PATIOさん、ありがとうございます。
仮想リストの動作的に表示対象部位のみ対象となっているだろうとは疑っていましたが…
視覚性の向上のため、サイズ変更処理を自分で持つようにしようと思います。
ご意見ありがとうございました。

編集 削除