1

タブ コントロールのコンテンツ領域に配置されたツリー ビューがあります (ツリー ビューはタブ コントロールの兄弟です)。ツリー ビュー アイテムを削除し、新しいツリー ビュー アイテムを追加して、そのうちの 1 つを選択すると、ツリー ビューが正しく描画されません。新しく作成された+選択されたアイテムの上にあるものはすべて灰色です。アイテムを削除して挿入した後、ツリー ビューにすべてを適切に描画させる方法はありますか?

アイテムを交換する前に アイテム交換後

所見:

  • スクロール バーが表示されないほどツリー ビューの項目が少ない場合、ツリー ビューは問題ないように見えます。
  • ツリー ビューにタブ コントロールが隣接していない場合、ツリー ビューは問題ないように見えます。
  • ツリー ビューがタブ コントロールの子である場合、ツリー ビューは問題ないように見えます (ただし、Tabキーは GetNextDlgTabItem/IsDialogMessage を使用してタブ コントロールとツリー ビューの間を移動できません)。
  • 新しいノードを挿入した後、ツリー ビューでアイテムを選択しなければ、ツリー ビューは問題ないように見えます。

ツリーにアイテムを挿入するときは、TreeView_InsertItem に続いて TreeView_SelectItem を呼び出します。完全なサンプルの要点。サンプル プログラムでは、Ctrl+Rアクセラレータがすべてのツリー ノードを置き換え、アーティファクトを引き起こします。

4

1 に答える 1

1

ここにエラーがあります:

ACCEL accel[1]***; //change to accel[2]
accel[0].fVirt = FCONTROL | FVIRTKEY;
accel[0].key = 'R';
accel[0].cmd = IDM_REGENERATETREE;
accel[1].fVirt = FCONTROL | FVIRTKEY;
accel[1].key = 'S';
accel[1].cmd = IDM_SELECTRANDOM;
HACCEL haccel = CreateAcceleratorTable(accel, 2);

以前のアイテムの状態を保存しようとすると、表示の問題が発生します。previousStatesから外せば表示に問題はありませんaddTreeItem。状態を適切に保存するには、std::map と各ツリー項目のユーザー ID が必要になる場合があります。少なくとも、追跡しやすくするために std::vector を使用する必要があります。

視覚効果を向上させるTVS_LINESATROOTために、TreeView とWS_CLIPCHILDRENメイン ウィンドウに追加できます。

編集:

で以前のアイテムの状態を保存しないでくださいaddTreeItem。たとえば、挿入されたばかりの新しいアイテムにはまだ子がないため、展開できません。次のように簡略化addTreeItemします。

HTREEITEM addTreeItem(HWND htree, HTREEITEM par, HTREEITEM after, LPCTSTR str, LPARAM lp) 
{
    TVINSERTSTRUCT tvins;
    tvins.hParent = par;
    tvins.hInsertAfter = after;
    tvins.itemex.mask = TVIF_TEXT | TVIF_PARAM;
    tvins.itemex.pszText = const_cast<LPTSTR>(str);
    tvins.itemex.lParam = lp;
    HTREEITEM node = TreeView_InsertItem(htree, &tvins);
    return node; 
}

以前のアイテムの状態を保存するには、各アイテムに異なる ID が必要です。この例ではアイテムの名前がノードごとに異なるため、それをマップに使用できます。ただし、これがディレクトリ構造の場合は機能しないため、ノード名の代わりにフルパスを使用する必要があります。

void RootWindow::RegenerateTree()
{
    if (!m_hwndTreeView) return;
    if (!IsWindow(m_hwndTreeView)) return;
    HWND hwnd = m_hwndTreeView;

    //this will stop treeview from updating after every insert
    SetWindowRedraw(hwnd, 0);

    std::map<std::wstring, UINT> state;
    const int maxtext = 260;
    wchar_t buf[maxtext];
    std::wstring selection;

    UINT count = TreeView_GetCount(hwnd);
    if (count)
    {
        for (HTREEITEM item = TreeView_GetRoot(hwnd); item; item = nextItem(hwnd, item))
        {
            TVITEM tv{ 0 };
            tv.mask = TVIF_TEXT | TVIF_STATE;
            tv.stateMask = TVIF_TEXT | TVIF_STATE;
            tv.cchTextMax = maxtext;
            tv.pszText = buf;
            tv.hItem = item;
            if (TreeView_GetItem(hwnd, &tv))
                state[buf] = TreeView_GetItemState(hwnd, item, 
                TVIS_SELECTED | TVIS_EXPANDED);
        }
    }
    TreeView_DeleteAllItems(hwnd);

    addTreeItem...
    addTreeItem...
    addTreeItem...

    //restore previous item state here:
    if (count)
    {
        for (HTREEITEM item = TreeView_GetRoot(hwnd); item; item = nextItem(hwnd, item))
        {
            TVITEM tvitem{ 0 };
            tvitem.hItem = item;
            tvitem.mask = TVIF_TEXT;
            tvitem.cchTextMax = maxtext;
            tvitem.pszText = buf;
            if (TreeView_GetItem(hwnd, &tvitem))
                TreeView_SetItemState(hwnd, item, state[buf], 
                TVIS_SELECTED | TVIS_EXPANDED);
        }
    }

    SetWindowRedraw(hwnd, 1);
}
于 2015-05-13T02:38:40.653 に答える