+bool wxTreeCtrl::MSWIsOnItem(unsigned flags) const
+{
+ unsigned mask = TVHT_ONITEM;
+ if ( HasFlag(wxTR_FULL_ROW_HIGHLIGHT) )
+ mask |= TVHT_ONITEMINDENT | TVHT_ONITEMRIGHT;
+
+ return (flags & mask) != 0;
+}
+
+bool wxTreeCtrl::MSWHandleSelectionKey(unsigned vkey)
+{
+ const bool bCtrl = wxIsCtrlDown();
+ const bool bShift = wxIsShiftDown();
+ const HTREEITEM htSel = (HTREEITEM)TreeView_GetSelection(GetHwnd());
+
+ switch ( vkey )
+ {
+ case VK_RETURN:
+ case VK_SPACE:
+ if ( !htSel )
+ break;
+
+ if ( vkey != VK_RETURN && bCtrl )
+ {
+ wxTreeEvent changingEvent(wxEVT_TREE_SEL_CHANGING,
+ this, htSel);
+ changingEvent.m_itemOld = htSel;
+
+ if ( IsTreeEventAllowed(changingEvent) )
+ {
+ DoToggleItemSelection(wxTreeItemId(htSel));
+
+ wxTreeEvent changedEvent(wxEVT_TREE_SEL_CHANGED,
+ this, htSel);
+ changedEvent.m_itemOld = htSel;
+ (void)HandleTreeEvent(changedEvent);
+ }
+ }
+ else
+ {
+ wxArrayTreeItemIds selections;
+ size_t count = GetSelections(selections);
+
+ if ( count != 1 || HITEM(selections[0]) != htSel )
+ {
+ wxTreeEvent changingEvent(wxEVT_TREE_SEL_CHANGING,
+ this, htSel);
+ changingEvent.m_itemOld = htSel;
+
+ if ( IsTreeEventAllowed(changingEvent) )
+ {
+ DoUnselectAll();
+ DoSelectItem(wxTreeItemId(htSel));
+
+ wxTreeEvent changedEvent(wxEVT_TREE_SEL_CHANGED,
+ this, htSel);
+ changedEvent.m_itemOld = htSel;
+ (void)HandleTreeEvent(changedEvent);
+ }
+ }
+ }
+ break;
+
+ case VK_UP:
+ case VK_DOWN:
+ if ( !bCtrl && !bShift )
+ {
+ wxArrayTreeItemIds selections;
+ wxTreeItemId next;
+
+ if ( htSel )
+ {
+ next = vkey == VK_UP
+ ? TreeView_GetPrevVisible(GetHwnd(), htSel)
+ : TreeView_GetNextVisible(GetHwnd(), htSel);
+ }
+ else
+ {
+ next = GetRootItem();
+
+ if ( IsHiddenRoot(next) )
+ next = TreeView_GetChild(GetHwnd(), HITEM(next));
+ }
+
+ if ( !next.IsOk() )
+ {
+ break;
+ }
+
+ wxTreeEvent changingEvent(wxEVT_TREE_SEL_CHANGING,
+ this, next);
+ changingEvent.m_itemOld = htSel;
+
+ if ( IsTreeEventAllowed(changingEvent) )
+ {
+ DoUnselectAll();
+ DoSelectItem(next);
+ SetFocusedItem(next);
+
+ wxTreeEvent changedEvent(wxEVT_TREE_SEL_CHANGED,
+ this, next);
+ changedEvent.m_itemOld = htSel;
+ (void)HandleTreeEvent(changedEvent);
+ }
+ }
+ else if ( htSel )
+ {
+ wxTreeItemId next = vkey == VK_UP
+ ? TreeView_GetPrevVisible(GetHwnd(), htSel)
+ : TreeView_GetNextVisible(GetHwnd(), htSel);
+
+ if ( !next.IsOk() )
+ {
+ break;
+ }
+
+ if ( !m_htSelStart )
+ {
+ m_htSelStart = htSel;
+ }
+
+ if ( bShift && SelectRange(GetHwnd(), HITEM(m_htSelStart), HITEM(next),
+ SR_UNSELECT_OTHERS | SR_SIMULATE) )
+ {
+ wxTreeEvent changingEvent(wxEVT_TREE_SEL_CHANGING, this, next);
+ changingEvent.m_itemOld = htSel;
+
+ if ( IsTreeEventAllowed(changingEvent) )
+ {
+ SelectRange(GetHwnd(), HITEM(m_htSelStart), HITEM(next),
+ SR_UNSELECT_OTHERS);
+
+ wxTreeEvent changedEvent(wxEVT_TREE_SEL_CHANGED, this, next);
+ changedEvent.m_itemOld = htSel;
+ (void)HandleTreeEvent(changedEvent);
+ }
+ }
+
+ SetFocusedItem(next);
+ }
+ break;
+
+ case VK_LEFT:
+ if ( HasChildren(htSel) && IsExpanded(htSel) )
+ {
+ Collapse(htSel);
+ }
+ else
+ {
+ wxTreeItemId next = GetItemParent(htSel);
+
+ if ( next.IsOk() && !IsHiddenRoot(next) )
+ {
+ wxTreeEvent changingEvent(wxEVT_TREE_SEL_CHANGING,
+ this, next);
+ changingEvent.m_itemOld = htSel;
+
+ if ( IsTreeEventAllowed(changingEvent) )
+ {
+ DoUnselectAll();
+ DoSelectItem(next);
+ SetFocusedItem(next);
+
+ wxTreeEvent changedEvent(wxEVT_TREE_SEL_CHANGED,
+ this, next);
+ changedEvent.m_itemOld = htSel;
+ (void)HandleTreeEvent(changedEvent);
+ }
+ }
+ }
+ break;
+
+ case VK_RIGHT:
+ if ( !IsVisible(htSel) )
+ {
+ EnsureVisible(htSel);
+ }
+
+ if ( !HasChildren(htSel) )
+ break;
+
+ if ( !IsExpanded(htSel) )
+ {
+ Expand(htSel);
+ }
+ else
+ {
+ wxTreeItemId next = TreeView_GetChild(GetHwnd(), htSel);
+
+ wxTreeEvent changingEvent(wxEVT_TREE_SEL_CHANGING, this, next);
+ changingEvent.m_itemOld = htSel;
+
+ if ( IsTreeEventAllowed(changingEvent) )
+ {
+ DoUnselectAll();
+ DoSelectItem(next);
+ SetFocusedItem(next);
+
+ wxTreeEvent changedEvent(wxEVT_TREE_SEL_CHANGED, this, next);
+ changedEvent.m_itemOld = htSel;
+ (void)HandleTreeEvent(changedEvent);
+ }
+ }
+ break;
+
+ case VK_HOME:
+ case VK_END:
+ {
+ wxTreeItemId next = GetRootItem();
+
+ if ( IsHiddenRoot(next) )
+ {
+ next = TreeView_GetChild(GetHwnd(), HITEM(next));
+ }
+
+ if ( !next.IsOk() )
+ break;
+
+ if ( vkey == VK_END )
+ {
+ for ( ;; )
+ {
+ wxTreeItemId nextTemp = TreeView_GetNextVisible(
+ GetHwnd(), HITEM(next));
+
+ if ( !nextTemp.IsOk() )
+ break;
+
+ next = nextTemp;
+ }
+ }
+
+ if ( htSel == HITEM(next) )
+ break;
+
+ if ( bShift )
+ {
+ if ( !m_htSelStart )
+ {
+ m_htSelStart = htSel;
+ }
+
+ if ( SelectRange(GetHwnd(),
+ HITEM(m_htSelStart), HITEM(next),
+ SR_UNSELECT_OTHERS | SR_SIMULATE) )
+ {
+ wxTreeEvent changingEvent(wxEVT_TREE_SEL_CHANGING,
+ this, next);
+ changingEvent.m_itemOld = htSel;
+
+ if ( IsTreeEventAllowed(changingEvent) )
+ {
+ SelectRange(GetHwnd(),
+ HITEM(m_htSelStart), HITEM(next),
+ SR_UNSELECT_OTHERS);
+ SetFocusedItem(next);
+
+ wxTreeEvent changedEvent(wxEVT_TREE_SEL_CHANGED,
+ this, next);
+ changedEvent.m_itemOld = htSel;
+ (void)HandleTreeEvent(changedEvent);
+ }
+ }
+ }
+ else // no Shift
+ {
+ wxTreeEvent changingEvent(wxEVT_TREE_SEL_CHANGING,
+ this, next);
+ changingEvent.m_itemOld = htSel;
+
+ if ( IsTreeEventAllowed(changingEvent) )
+ {
+ DoUnselectAll();
+ DoSelectItem(next);
+ SetFocusedItem(next);
+
+ wxTreeEvent changedEvent(wxEVT_TREE_SEL_CHANGED,
+ this, next);
+ changedEvent.m_itemOld = htSel;
+ (void)HandleTreeEvent(changedEvent);
+ }
+ }
+ }
+ break;
+
+ case VK_PRIOR:
+ case VK_NEXT:
+ if ( bCtrl )
+ {
+ wxTreeItemId firstVisible = GetFirstVisibleItem();
+ size_t visibleCount = TreeView_GetVisibleCount(GetHwnd());
+ wxTreeItemId nextAdjacent = (vkey == VK_PRIOR) ?
+ TreeView_GetPrevVisible(GetHwnd(), HITEM(firstVisible)) :
+ TreeView_GetNextVisible(GetHwnd(), HITEM(firstVisible));
+
+ if ( !nextAdjacent )
+ {
+ break;
+ }
+
+ wxTreeItemId nextStart = firstVisible;
+
+ for ( size_t n = 1; n < visibleCount; n++ )
+ {
+ wxTreeItemId nextTemp = (vkey == VK_PRIOR) ?
+ TreeView_GetPrevVisible(GetHwnd(), HITEM(nextStart)) :
+ TreeView_GetNextVisible(GetHwnd(), HITEM(nextStart));
+
+ if ( nextTemp.IsOk() )
+ {
+ nextStart = nextTemp;
+ }
+ else
+ {
+ break;
+ }
+ }
+
+ EnsureVisible(nextStart);
+
+ if ( vkey == VK_NEXT )
+ {
+ wxTreeItemId nextEnd = nextStart;
+
+ for ( size_t n = 1; n < visibleCount; n++ )
+ {
+ wxTreeItemId nextTemp =
+ TreeView_GetNextVisible(GetHwnd(), HITEM(nextEnd));
+
+ if ( nextTemp.IsOk() )
+ {
+ nextEnd = nextTemp;
+ }
+ else
+ {
+ break;
+ }
+ }
+
+ EnsureVisible(nextEnd);
+ }
+ }
+ else // no Ctrl
+ {
+ size_t visibleCount = TreeView_GetVisibleCount(GetHwnd());
+ wxTreeItemId nextAdjacent = (vkey == VK_PRIOR) ?
+ TreeView_GetPrevVisible(GetHwnd(), htSel) :
+ TreeView_GetNextVisible(GetHwnd(), htSel);
+
+ if ( !nextAdjacent )
+ {
+ break;
+ }
+
+ wxTreeItemId next(htSel);
+
+ for ( size_t n = 1; n < visibleCount; n++ )
+ {
+ wxTreeItemId nextTemp = vkey == VK_PRIOR ?
+ TreeView_GetPrevVisible(GetHwnd(), HITEM(next)) :
+ TreeView_GetNextVisible(GetHwnd(), HITEM(next));
+
+ if ( !nextTemp.IsOk() )
+ break;
+
+ next = nextTemp;
+ }
+
+ wxTreeEvent changingEvent(wxEVT_TREE_SEL_CHANGING,
+ this, next);
+ changingEvent.m_itemOld = htSel;
+
+ if ( IsTreeEventAllowed(changingEvent) )
+ {
+ DoUnselectAll();
+ m_htSelStart.Unset();
+ DoSelectItem(next);
+ SetFocusedItem(next);
+
+ wxTreeEvent changedEvent(wxEVT_TREE_SEL_CHANGED,
+ this, next);
+ changedEvent.m_itemOld = htSel;
+ (void)HandleTreeEvent(changedEvent);
+ }
+ }
+ break;
+
+ default:
+ return false;
+ }
+
+ return true;
+}
+
+bool wxTreeCtrl::MSWHandleTreeKeyDownEvent(WXWPARAM wParam, WXLPARAM lParam)
+{
+ wxTreeEvent keyEvent(wxEVT_TREE_KEY_DOWN, this);
+ keyEvent.m_evtKey = CreateKeyEvent(wxEVT_KEY_DOWN, wParam, lParam);
+
+ bool processed = HandleTreeEvent(keyEvent);
+
+ // generate a separate event for Space/Return
+ if ( !wxIsCtrlDown() && !wxIsShiftDown() && !wxIsAltDown() &&
+ ((wParam == VK_SPACE) || (wParam == VK_RETURN)) )
+ {
+ const HTREEITEM htSel = (HTREEITEM)TreeView_GetSelection(GetHwnd());
+ if ( htSel )
+ {
+ wxTreeEvent activatedEvent(wxEVT_TREE_ITEM_ACTIVATED,
+ this, htSel);
+ (void)HandleTreeEvent(activatedEvent);
+ }
+ }
+
+ return processed;
+}
+
+// we hook into WndProc to process WM_MOUSEMOVE/WM_BUTTONUP messages - as we
+// only do it during dragging, minimize wxWin overhead (this is important for