Programming Tips #10 ツリービューの謎が解けた
スクロールバーの位置を変更したら WM_SIZE を送れ!
ツリービューの選択アイテムを上下キーで変更すると、垂直スクロールバーは選択アイテムが表示されるように自動で調整されるけど、水平スクロールバーはそうならないよね。
なんでやねん、と怒りつつも自分で何とかするしかないので死ぬほど調査した。
そして解決方法をやっと見つけました。
スクロールバーの設定は前回の復元方法と同じなんだけど、実は前回のはたまたまうまく行ってただけなんだよね。
初期化の直後はちゃんとスクロールバーの設定どおりに表示されるのに、それ以外ではスクロールバーのつまみだけ更新されて中身は変化なし。
何でだろ、何でだろ、って試行錯誤してたら犯人は WM_SIZE メッセージだったのだ。
初期化の直後は表示の開始なので自動的に WM_SIZE が送られていたのだ。
選択アイテム変更通知イベント
LRESULT App :: OnTvnSelChanged() { RECT rcItem; RECT rcClient; LONG xpos; TreeView_GetItemRect( hTreeView, lpnmtv->itemNew.hItem, & rcItem, TRUE ); rcItem.left -= GetSystemMetrics( SM_CXSMICON ); GetClientRect( hTreeView, & rcClient ); if ( ( rcItem.left < rcClient.left && rcItem.right < rcClient.right ) || ( rcItem.left > rcClient.left && rcItem.right > rcClient.right ) ) { xpos = GetScrollPos( hTreeView, SB_HORZ ) + rcItem.left; SetScrollPos( hTreeView, SB_HORZ, xpos, TRUE ); SendMessage( hTreeView, WM_SIZE, 0, 0 ); } }
解説
選択されたアイテムの表示矩形を取得し、ツリービューのクライアント領域と比較し、はみ出てるようなら中に入れてあげる。
最後に WM_SIZE メッセージを忘れずに送る。これで万事OK。
以上。