X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/f2fec40d2c3533e112e6d673fb113b77e65bfd66..27d7687903b04c56878597fefccf3daafd0a58fa:/src/msw/treectrl.cpp diff --git a/src/msw/treectrl.cpp b/src/msw/treectrl.cpp index f90ba117d3..6cb53d2876 100644 --- a/src/msw/treectrl.cpp +++ b/src/msw/treectrl.cpp @@ -750,6 +750,7 @@ void wxTreeCtrl::Init() m_focusLost = true; m_changingSelection = false; m_triggerStateImageClick = false; + m_mouseUpDeselect = false; // initialize the global array of events now as it can't be done statically // with the wxEVT_XXX values being allocated during run-time only @@ -1666,6 +1667,12 @@ void wxTreeCtrl::Delete(const wxTreeItemId& item) return; } + if ( item == m_htSelStart ) + m_htSelStart.Unset(); + + if ( item == m_htClickedItem ) + m_htClickedItem.Unset(); + if ( next.IsOk() ) { wxTreeEvent changingEvent(wxEVT_COMMAND_TREE_SEL_CHANGING, this, next); @@ -1720,6 +1727,10 @@ void wxTreeCtrl::DeleteAllItems() // unlock tree selections on vista for the duration of this call TreeItemUnlocker unlock_all; + // invalidate all the items we store as they're going to become invalid + m_htSelStart = + m_htClickedItem = wxTreeItemId(); + // delete the "virtual" root item. if ( GET_VIRTUAL_ROOT() ) { @@ -1872,6 +1883,39 @@ void wxTreeCtrl::UnselectAll() } } +void wxTreeCtrl::DoSelectChildren(const wxTreeItemId& parent) +{ + DoUnselectAll(); + + wxTreeItemIdValue cookie; + wxTreeItemId child = GetFirstChild(parent, cookie); + while ( child.IsOk() ) + { + DoSelectItem(child, true); + child = GetNextChild(child, cookie); + } +} + +void wxTreeCtrl::SelectChildren(const wxTreeItemId& parent) +{ + wxCHECK_RET( HasFlag(wxTR_MULTIPLE), + "this only works with multiple selection controls" ); + + HTREEITEM htFocus = (HTREEITEM)TreeView_GetSelection(GetHwnd()); + + wxTreeEvent changingEvent(wxEVT_COMMAND_TREE_SEL_CHANGING, this); + changingEvent.m_itemOld = htFocus; + + if ( IsTreeEventAllowed(changingEvent) ) + { + DoSelectChildren(parent); + + wxTreeEvent changedEvent(wxEVT_COMMAND_TREE_SEL_CHANGED, this); + changedEvent.m_itemOld = htFocus; + (void)HandleTreeEvent(changedEvent); + } +} + void wxTreeCtrl::DoSelectItem(const wxTreeItemId& item, bool select) { TempSetter set(m_changingSelection); @@ -1922,23 +1966,25 @@ void wxTreeCtrl::SelectItem(const wxTreeItemId& item, bool select) // leave itemNew invalid } - // in spite of the docs (MSDN Jan 99 edition), we don't seem to receive - // the notification from the control (i.e. TVN_SELCHANG{ED|ING}), so - // send them ourselves - + // Recent versions of comctl32.dll send TVN_SELCHANG{ED,ING} events + // when we call TreeView_SelectItem() but apparently some old ones did + // not so send the events ourselves and ignore those generated by + // TreeView_SelectItem() if m_changingSelection is set. wxTreeEvent changingEvent(wxEVT_COMMAND_TREE_SEL_CHANGING, this, itemNew); changingEvent.SetOldItem(itemOld); if ( IsTreeEventAllowed(changingEvent) ) { + TempSetter set(m_changingSelection); + if ( !TreeView_SelectItem(GetHwnd(), HITEM(itemNew)) ) { wxLogLastError(wxT("TreeView_SelectItem")); } else // ok { - SetFocusedItem(item); + ::SetFocus(GetHwnd(), HITEM(item)); wxTreeEvent changedEvent(wxEVT_COMMAND_TREE_SEL_CHANGED, this, itemNew); @@ -1985,8 +2031,7 @@ void wxTreeCtrl::DeleteTextCtrl() m_textCtrl->UnsubclassWin(); m_textCtrl->SetHWND(0); - delete m_textCtrl; - m_textCtrl = NULL; + wxDELETE(m_textCtrl); m_idEdited.Unset(); } @@ -2007,8 +2052,7 @@ wxTextCtrl *wxTreeCtrl::EditLabel(const wxTreeItemId& item, // returned false if ( !hWnd ) { - delete m_textCtrl; - m_textCtrl = NULL; + wxDELETE(m_textCtrl); return NULL; } @@ -2093,6 +2137,8 @@ void wxTreeCtrl::ClearFocusedItem() void wxTreeCtrl::SetFocusedItem(const wxTreeItemId& item) { + wxCHECK_RET( item.IsOk(), wxT("invalid tree item") ); + TempSetter set(m_changingSelection); ::SetFocus(GetHwnd(), HITEM(item)); @@ -2214,6 +2260,15 @@ bool wxTreeCtrl::MSWCommand(WXUINT cmd, WXWORD id_) return true; } +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(); @@ -2602,18 +2657,7 @@ bool wxTreeCtrl::MSWHandleSelectionKey(unsigned vkey) bool wxTreeCtrl::MSWHandleTreeKeyDownEvent(WXWPARAM wParam, WXLPARAM lParam) { wxTreeEvent keyEvent(wxEVT_COMMAND_TREE_KEY_DOWN, this); - - int keyCode = wxCharCodeMSWToWX(wParam); - - if ( !keyCode ) - { - // wxCharCodeMSWToWX() returns 0 to indicate that this is a - // simple ASCII key - keyCode = wParam; - } - - keyEvent.m_evtKey = CreateKeyEvent(wxEVT_KEY_DOWN, keyCode, - lParam, wParam); + keyEvent.m_evtKey = CreateKeyEvent(wxEVT_KEY_DOWN, wParam, lParam); bool processed = HandleTreeEvent(keyEvent); @@ -2685,13 +2729,16 @@ wxTreeCtrl::MSWWindowProc(WXUINT nMsg, WXWPARAM wParam, WXLPARAM lParam) } // create the event - wxTreeEvent event(wxEVT_COMMAND_TREE_ITEM_MENU, this, item); + if ( item.IsOk() ) + { + wxTreeEvent event(wxEVT_COMMAND_TREE_ITEM_MENU, this, item); - event.m_pointDrag = pt; + event.m_pointDrag = pt; - if ( HandleTreeEvent(event) ) - processed = true; - //else: continue with generating wxEVT_CONTEXT_MENU in base class code + if ( HandleTreeEvent(event) ) + processed = true; + //else: continue with generating wxEVT_CONTEXT_MENU in base class code + } } else if ( (nMsg >= WM_MOUSEFIRST) && (nMsg <= WM_MOUSELAST) ) { @@ -2715,7 +2762,7 @@ wxTreeCtrl::MSWWindowProc(WXUINT nMsg, WXWPARAM wParam, WXLPARAM lParam) m_htClickedItem.Unset(); - if ( !(tvht.flags & TVHT_ONITEM) ) + if ( !MSWIsOnItem(tvht.flags) ) { if ( tvht.flags & TVHT_ONITEMBUTTON ) { @@ -2876,6 +2923,7 @@ wxTreeCtrl::MSWWindowProc(WXUINT nMsg, WXWPARAM wParam, WXLPARAM lParam) else { SetFocusedItem(wxTreeItemId(htItem)); + m_mouseUpDeselect = true; } } else // click on a single selected item @@ -3025,16 +3073,13 @@ wxTreeCtrl::MSWWindowProc(WXUINT nMsg, WXWPARAM wParam, WXLPARAM lParam) case WM_LBUTTONUP: if ( isMultiple ) { - // deselect other items if multiple items selected + // deselect other items if needed if ( htItem ) { - wxArrayTreeItemIds selections; - size_t count = GetSelections(selections); - - if ( count > 1 && - !(wParam & MK_CONTROL) && - !(wParam & MK_SHIFT) ) + if ( m_mouseUpDeselect ) { + m_mouseUpDeselect = false; + wxTreeEvent changingEvent(wxEVT_COMMAND_TREE_SEL_CHANGING, this, htItem); changingEvent.m_itemOld = htOldItem; @@ -3068,10 +3113,7 @@ wxTreeCtrl::MSWWindowProc(WXUINT nMsg, WXWPARAM wParam, WXLPARAM lParam) } } - if ( !m_dragStarted && - (tvht.flags & TVHT_ONITEMSTATEICON || - tvht.flags & TVHT_ONITEMICON || - tvht.flags & TVHT_ONITEM) ) + if ( !m_dragStarted && MSWIsOnItem(tvht.flags) ) { processed = true; } @@ -3084,8 +3126,7 @@ wxTreeCtrl::MSWWindowProc(WXUINT nMsg, WXWPARAM wParam, WXLPARAM lParam) if ( m_dragImage ) { m_dragImage->EndDrag(); - delete m_dragImage; - m_dragImage = NULL; + wxDELETE(m_dragImage); // generate the drag end event wxTreeEvent event(wxEVT_COMMAND_TREE_END_DRAG, @@ -3162,7 +3203,8 @@ wxTreeCtrl::MSWWindowProc(WXUINT nMsg, WXWPARAM wParam, WXLPARAM lParam) case VK_END: case VK_PRIOR: case VK_NEXT: - if ( !MSWHandleTreeKeyDownEvent(wParam, lParam) ) + if ( !HandleKeyDown(wParam, lParam) && + !MSWHandleTreeKeyDownEvent(wParam, lParam) ) { // use the key to update the selection if it was left // unprocessed @@ -3224,8 +3266,7 @@ wxTreeCtrl::MSWDefWindowProc(WXUINT nMsg, WXWPARAM wParam, WXLPARAM lParam) if ( m_dragImage ) { m_dragImage->EndDrag(); - delete m_dragImage; - m_dragImage = NULL; + wxDELETE(m_dragImage); // if we don't do it, the tree seems to think that 2 items // are selected simultaneously which is quite weird @@ -3433,7 +3474,7 @@ bool wxTreeCtrl::MSWOnNotify(int idCtrl, WXLPARAM lParam, WXLPARAM *result) // we have to handle both messages: case TVN_SELCHANGEDA: case TVN_SELCHANGEDW: - if ( !HasFlag(wxTR_MULTIPLE) || !m_changingSelection ) + if ( !m_changingSelection ) { eventType = wxEVT_COMMAND_TREE_SEL_CHANGED; } @@ -3441,7 +3482,7 @@ bool wxTreeCtrl::MSWOnNotify(int idCtrl, WXLPARAM lParam, WXLPARAM *result) case TVN_SELCHANGINGA: case TVN_SELCHANGINGW: - if ( !HasFlag(wxTR_MULTIPLE) || !m_changingSelection ) + if ( !m_changingSelection ) { if ( eventType == wxEVT_NULL ) eventType = wxEVT_COMMAND_TREE_SEL_CHANGING; @@ -3473,7 +3514,8 @@ bool wxTreeCtrl::MSWOnNotify(int idCtrl, WXLPARAM lParam, WXLPARAM *result) // // to avoid such surprises, we force the generation of focus events // now, before we generate the selection change ones - SetFocus(); + if ( !m_changingSelection ) + SetFocus(); break; // instead of explicitly checking for _WIN32_IE, check if the @@ -3653,7 +3695,7 @@ bool wxTreeCtrl::MSWOnNotify(int idCtrl, WXLPARAM lParam, WXLPARAM *result) ::ScreenToClient(GetHwnd(), &tvhti.pt); if ( TreeView_HitTest(GetHwnd(), &tvhti) ) { - if ( tvhti.flags & TVHT_ONITEM ) + if ( MSWIsOnItem(tvhti.flags) ) { event.m_item = tvhti.hItem; eventType = (int)hdr->code == NM_DBLCLK