3

I have a CTreeCtrl object (C++, MFC). This CTreeCtrl remembers the last selection and if the user opens the window again the last selection will be expand and select automatically. But when I call EnsureVisible to show the last selection, it appears at the bottom of the TreeCtrl. I tried a lot (for example this How to make a CTreeCtrl item centrally displayed?) but it has no effect to my TreeControl.

Does anyone know a good way to expand and show items in the middle of a TreeControl (programmatically)? A example would be great!

Community
  • 1
  • 1
Simon Hilner
  • 85
  • 2
  • 11

1 Answers1

4

After calling EnsureVisible, scroll down by one page (this will push the target item up and out of view), then call EnsureVisible again. This guarantees the target item is the first visible item on top (unless there are not enough items and it is impossible to scroll)

Then scroll up, to push the item down, until the item is in the middle.

tree.EnsureVisible(htreeitem_target);
tree.SendMessage(WM_VSCROLL, SB_PAGEDOWN, 0);
tree.EnsureVisible(htreeitem_target);//item is on top now

CRect rc;
tree.GetClientRect(&rc);
for (int i = 0; i < tree.GetVisibleCount(); i++)
{
    CRect r;
    tree.GetItemRect(htreeitem_target, &r, FALSE);
    if (r.bottom > rc.Height() / 2)
        break;
    tree.SendMessage(WM_VSCROLL, SB_LINEUP, 0);
}

You can also begin with tree.SetRedraw(FASLE); and end with tree.SetRedraw(TRUE); to avoid repaint.

Barmak Shemirani
  • 30,904
  • 6
  • 40
  • 77
  • 1
    Note that SetRedraw() will need to be true during the calls to EnsureVisible(). You can disable it after that to avoid redrawing during the for() loop. Thanks for a great post, Barmak! – Steve A May 11 '18 at 16:20