Mesoscopic Programming

タコさんプログラミング専門

Programming Tips #9 ツリービューのスクロール位置の復帰

再起動時に、ツリービューのスクロール位置を終了時の位置に復帰する方法を調査しました。
終了時に保存してるのは選択アイテムとその座標だけで、各アイテムの展開状態までは保存していません。
どんだけ長くなるか分かりませんから。
そこで展開情報を再現しなくても選択アイテムを元の位置に表示させる方法を調査しました。
ポイントは、水平スクロールバーはドット単位、垂直スクロールバーはアイテム高さ単位ということです。

終了時処理

    HTREEITEM hItem;
    RECT      rc;
    TCHAR     path[ _MAX_PATH ];

    hItem = TreeView_GetSelection( hTreeView );

    TreeView_GetItemRect( hTreeView, hItem, & rc, TRUE );

    MakeItemPath( path, hItem );

    SetProfString( sectionName, keyTreePath, path );
    SetProfInt   ( sectionName, keyTreeLeft, rc.left );
    SetProfInt   ( sectionName, keyTreeTop,  rc.top );
解説

選択アイテムとその左上座標を保存します。
これはツリービューのクライアントエリア相対座標です。

再起動時処理

    TCHAR     path[ _MAX_PATH ];
    HTREEITEM hItem;
    LONG      left;
    LONG      top;
    RECT      rc;
    LONG      xpos;
    LONG      ypos;

    GetProfString( sectionName, keyTreePath, path, sizeof path );

    hItem = SearchPathItem( TreeView_GetRoot( hTreeView ), path );

    TreeView_Select( hTreeView, hItem, TVGN_CARET );

    left = GetProfInt( sectionName, keyTreeLeft, 0 );
    top  = GetProfInt( sectionName, keyTreeTop,  0 );

    TreeView_GetItemRect( hTreeView, tvItem.hItem, & rc, TRUE );

    xpos = GetScrollPos( hTreeView, SB_HORZ ) + ( rc.left - left );
    ypos = GetScrollPos( hTreeView, SB_VERT ) + ( rc.top  - top ) / TreeView_GetItemHeight( hTreeView );

    SetScrollPos( hTreeView, SB_HORZ, xpos, TRUE );
    SetScrollPos( hTreeView, SB_VERT, ypos, TRUE );
解説

保存した左上座標を取得し、選択アイテムが同じ座標になるようにスクロール位置を計算します。
垂直スクロールバーのみアイテム高さ単位なので、TreeView_GetItemHeight() で割って算出します。

以上。