X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/0228081ff2d7642df743e812aa3d46cf61efa1d2..25c702609db6a749ffd5f3e659ec348e4aa3a3c8:/src/msw/treectrl.cpp?ds=sidebyside diff --git a/src/msw/treectrl.cpp b/src/msw/treectrl.cpp index cafa185031..96bf25a0b5 100644 --- a/src/msw/treectrl.cpp +++ b/src/msw/treectrl.cpp @@ -29,6 +29,8 @@ #include "wx/treectrl.h" #ifndef WX_PRECOMP + #include "wx/msw/wrapcctl.h" // include "properly" + #include "wx/msw/missing.h" #include "wx/dynarray.h" #include "wx/log.h" #include "wx/app.h" @@ -37,11 +39,6 @@ #include "wx/msw/private.h" -// include "properly" -#include "wx/msw/wrapcctl.h" - -#include "wx/msw/missing.h" - // Set this to 1 to be _absolutely_ sure that repainting will work for all // comctl32.dll versions #define wxUSE_COMCTL32_SAFELY 0 @@ -55,30 +52,10 @@ // get HTREEITEM from wxTreeItemId #define HITEM(item) ((HTREEITEM)(((item).m_pItem))) -// the native control doesn't support multiple selections under MSW and we -// have 2 ways to emulate them: either using TVS_CHECKBOXES style and let -// checkboxes be the selection status (checked == selected) or by really -// emulating everything, i.e. intercepting mouse and key events &c. The first -// approach is much easier but doesn't work with comctl32.dll < 4.71 and also -// looks quite ugly. -#define wxUSE_CHECKBOXES_IN_MULTI_SEL_TREE 0 - // ---------------------------------------------------------------------------- // private functions // ---------------------------------------------------------------------------- -// wrapper for TreeView_HitTest -static HTREEITEM GetItemFromPoint(HWND hwndTV, int x, int y) -{ - TV_HITTESTINFO tvht; - tvht.pt.x = x; - tvht.pt.y = y; - - return (HTREEITEM)TreeView_HitTest(hwndTV, &tvht); -} - -#if !wxUSE_CHECKBOXES_IN_MULTI_SEL_TREE - // wrappers for TreeView_GetItem/TreeView_SetItem static bool IsItemSelected(HWND hwndTV, HTREEITEM hItem) { @@ -118,11 +95,6 @@ static inline void UnselectItem(HWND hwndTV, HTREEITEM htItem) SelectItem(hwndTV, htItem, false); } -static inline void ToggleItemSelection(HWND hwndTV, HTREEITEM htItem) -{ - SelectItem(hwndTV, htItem, !IsItemSelected(hwndTV, htItem)); -} - // helper function which selects all items in a range and, optionally, // unselects all others static void SelectRange(HWND hwndTV, @@ -191,60 +163,57 @@ static void SelectRange(HWND hwndTV, // helper function which tricks the standard control into changing the focused // item without changing anything else (if someone knows why Microsoft doesn't // allow to do it by just setting TVIS_FOCUSED flag, please tell me!) -static void SetFocus(HWND hwndTV, HTREEITEM htItem) +// +// returns true if the focus was changed, false if the given item was already +// the focused one +static bool SetFocus(HWND hwndTV, HTREEITEM htItem) { // the current focus HTREEITEM htFocus = (HTREEITEM)TreeView_GetSelection(hwndTV); + if ( htItem == htFocus ) + return false; + if ( htItem ) { - // set the focus - if ( htItem != htFocus ) - { - // remember the selection state of the item - bool wasSelected = IsItemSelected(hwndTV, htItem); + // remember the selection state of the item + bool wasSelected = IsItemSelected(hwndTV, htItem); - if ( htFocus && IsItemSelected(hwndTV, htFocus) ) - { - // prevent the tree from unselecting the old focus which it - // would do by default (TreeView_SelectItem unselects the - // focused item) - TreeView_SelectItem(hwndTV, 0); - SelectItem(hwndTV, htFocus); - } + if ( htFocus && IsItemSelected(hwndTV, htFocus) ) + { + // prevent the tree from unselecting the old focus which it + // would do by default (TreeView_SelectItem unselects the + // focused item) + TreeView_SelectItem(hwndTV, 0); + SelectItem(hwndTV, htFocus); + } - TreeView_SelectItem(hwndTV, htItem); + TreeView_SelectItem(hwndTV, htItem); - if ( !wasSelected ) - { - // need to clear the selection which TreeView_SelectItem() gave - // us - UnselectItem(hwndTV, htItem); - } - //else: was selected, still selected - ok + if ( !wasSelected ) + { + // need to clear the selection which TreeView_SelectItem() gave + // us + UnselectItem(hwndTV, htItem); } - //else: nothing to do, focus already there + //else: was selected, still selected - ok } - else + else // reset focus { - if ( htFocus ) - { - bool wasFocusSelected = IsItemSelected(hwndTV, htFocus); + bool wasFocusSelected = IsItemSelected(hwndTV, htFocus); - // just clear the focus - TreeView_SelectItem(hwndTV, 0); + // just clear the focus + TreeView_SelectItem(hwndTV, 0); - if ( wasFocusSelected ) - { - // restore the selection state - SelectItem(hwndTV, htFocus); - } + if ( wasFocusSelected ) + { + // restore the selection state + SelectItem(hwndTV, htFocus); } - //else: nothing to do, no focus already } -} -#endif // wxUSE_CHECKBOXES_IN_MULTI_SEL_TREE + return true; +} // ---------------------------------------------------------------------------- // private classes @@ -459,11 +428,7 @@ public: return true; } -#if wxUSE_CHECKBOXES_IN_MULTI_SEL_TREE - if ( tree->IsItemChecked(item) ) -#else if ( ::IsItemSelected(GetHwndOf(tree), HITEM(item)) ) -#endif { m_selections.Add(item); } @@ -555,7 +520,9 @@ wxBEGIN_FLAGS( wxTreeCtrlStyle ) wxFLAGS_MEMBER(wxTR_HAS_VARIABLE_ROW_HEIGHT) wxFLAGS_MEMBER(wxTR_SINGLE) wxFLAGS_MEMBER(wxTR_MULTIPLE) +#if WXWIN_COMPATIBILITY_2_8 wxFLAGS_MEMBER(wxTR_EXTENDED) +#endif wxFLAGS_MEMBER(wxTR_DEFAULT_STYLE) wxEND_FLAGS( wxTreeCtrlStyle ) @@ -651,7 +618,9 @@ void wxTreeCtrl::Init() { m_textCtrl = NULL; m_hasAnyAttr = false; +#if wxUSE_DRAGIMAGE m_dragImage = NULL; +#endif m_pVirtualRoot = NULL; // initialize the global array of events now as it can't be done statically @@ -678,7 +647,7 @@ bool wxTreeCtrl::Create(wxWindow *parent, if ( !CreateControl(parent, id, pos, size, style, validator, name) ) return false; - DWORD exStyle = 0; + WXDWORD exStyle = 0; DWORD wstyle = MSWGetStyle(m_windowStyle, & exStyle); wstyle |= WS_TABSTOP | TVS_SHOWSELALWAYS; @@ -699,20 +668,6 @@ bool wxTreeCtrl::Create(wxWindow *parent, wstyle |= TVS_FULLROWSELECT; } - // using TVS_CHECKBOXES for emulation of a multiselection tree control - // doesn't work without the new enough headers -#if wxUSE_CHECKBOXES_IN_MULTI_SEL_TREE && \ - !defined( __GNUWIN32_OLD__ ) && \ - !defined( __BORLANDC__ ) && \ - !defined( __WATCOMC__ ) && \ - (!defined(__VISUALC__) || (__VISUALC__ > 1010)) - - // we emulate the multiple selection tree controls by using checkboxes: set - // up the image list we need for this if we do have multiple selections - if ( m_windowStyle & wxTR_MULTIPLE ) - wstyle |= TVS_CHECKBOXES; -#endif // wxUSE_CHECKBOXES_IN_MULTI_SEL_TREE - #if !defined(__WXWINCE__) && defined(TVS_INFOTIP) // Need so that TVN_GETINFOTIP messages will be sent wstyle |= TVS_INFOTIP; @@ -966,7 +921,7 @@ void wxTreeCtrl::SetItemText(const wxTreeItemId& item, const wxString& text) return; wxTreeViewItem tvItem(item, TVIF_TEXT); - tvItem.pszText = (wxChar *)text.c_str(); // conversion is ok + tvItem.pszText = (wxChar *)text.wx_str(); // conversion is ok DoSetItem(&tvItem); // when setting the text of the item being edited, the text control should @@ -979,7 +934,7 @@ void wxTreeCtrl::SetItemText(const wxTreeItemId& item, const wxString& text) { if ( item == m_idEdited ) { - ::SetWindowText(hwndEdit, text); + ::SetWindowText(hwndEdit, text.wx_str()); } } } @@ -1205,6 +1160,10 @@ void wxTreeCtrl::SetItemFont(const wxTreeItemId& item, const wxFont& font) attr->SetFont(font); + // Reset the item's text to ensure that the bounding rect will be adjusted + // for the new font. + SetItemText(item, GetItemText(item)); + RefreshItem(item); } @@ -1355,36 +1314,6 @@ wxTreeItemId wxTreeCtrl::GetNextChild(const wxTreeItemId& WXUNUSED(item), return item; } -#if WXWIN_COMPATIBILITY_2_4 - -wxTreeItemId wxTreeCtrl::GetFirstChild(const wxTreeItemId& item, - long& cookie) const -{ - wxCHECK_MSG( item.IsOk(), wxTreeItemId(), wxT("invalid tree item") ); - - cookie = (long)TreeView_GetChild(GetHwnd(), HITEM(item)); - - return wxTreeItemId((void *)cookie); -} - -wxTreeItemId wxTreeCtrl::GetNextChild(const wxTreeItemId& WXUNUSED(item), - long& cookie) const -{ - wxTreeItemId fromCookie((void *)cookie); - - HTREEITEM hitem = HITEM(fromCookie); - - hitem = TreeView_GetNextSibling(GetHwnd(), hitem); - - wxTreeItemId item(hitem); - - cookie = (long)item.m_pItem; - - return item; -} - -#endif // WXWIN_COMPATIBILITY_2_4 - wxTreeItemId wxTreeCtrl::GetLastChild(const wxTreeItemId& item) const { wxCHECK_MSG( item.IsOk(), wxTreeItemId(), wxT("invalid tree item") ); @@ -1503,7 +1432,7 @@ wxTreeItemId wxTreeCtrl::DoInsertAfter(const wxTreeItemId& parent, if ( !text.empty() ) { mask |= TVIF_TEXT; - tvIns.item.pszText = (wxChar *)text.c_str(); // cast is ok + tvIns.item.pszText = (wxChar *)text.wx_str(); // cast is ok } else { @@ -1546,33 +1475,14 @@ wxTreeItemId wxTreeCtrl::DoInsertAfter(const wxTreeItemId& parent, return wxTreeItemId(id); } -// for compatibility only -#if WXWIN_COMPATIBILITY_2_4 - -void wxTreeCtrl::SetImageList(wxImageList *imageList, int) -{ - SetImageList(imageList); -} - -int wxTreeCtrl::GetItemSelectedImage(const wxTreeItemId& item) const -{ - return GetItemImage(item, wxTreeItemIcon_Selected); -} - -void wxTreeCtrl::SetItemSelectedImage(const wxTreeItemId& item, int image) -{ - SetItemImage(item, image, wxTreeItemIcon_Selected); -} - -#endif // WXWIN_COMPATIBILITY_2_4 - wxTreeItemId wxTreeCtrl::AddRoot(const wxString& text, int image, int selectedImage, wxTreeItemData *data) { - if ( HasFlag(wxTR_HIDE_ROOT) ) { + wxASSERT_MSG( !m_pVirtualRoot, _T("tree can have only a single root") ); + // create a virtual root item, the parent for all the others wxTreeItemParam *param = new wxTreeItemParam; param->SetData(data); @@ -1724,15 +1634,6 @@ void wxTreeCtrl::Toggle(const wxTreeItemId& item) DoExpand(item, TVE_TOGGLE); } -#if WXWIN_COMPATIBILITY_2_4 - -void wxTreeCtrl::ExpandItem(const wxTreeItemId& item, int action) -{ - DoExpand(item, action); -} - -#endif - void wxTreeCtrl::Unselect() { wxASSERT_MSG( !(m_windowStyle & wxTR_MULTIPLE), @@ -1750,11 +1651,7 @@ void wxTreeCtrl::UnselectAll() size_t count = GetSelections(selections); for ( size_t n = 0; n < count; n++ ) { -#if wxUSE_CHECKBOXES_IN_MULTI_SEL_TREE - SetItemCheck(HITEM(selections[n]), false); -#else // !wxUSE_CHECKBOXES_IN_MULTI_SEL_TREE ::UnselectItem(GetHwnd(), HITEM(selections[n])); -#endif // wxUSE_CHECKBOXES_IN_MULTI_SEL_TREE/!wxUSE_CHECKBOXES_IN_MULTI_SEL_TREE } m_htSelStart.Unset(); @@ -1768,39 +1665,36 @@ void wxTreeCtrl::UnselectAll() void wxTreeCtrl::SelectItem(const wxTreeItemId& item, bool select) { - if ( m_windowStyle & wxTR_MULTIPLE ) - { -#if wxUSE_CHECKBOXES_IN_MULTI_SEL_TREE - // selecting the item means checking it - SetItemCheck(item, select); -#else // !wxUSE_CHECKBOXES_IN_MULTI_SEL_TREE - ::SelectItem(GetHwnd(), HITEM(item), select); -#endif // wxUSE_CHECKBOXES_IN_MULTI_SEL_TREE/!wxUSE_CHECKBOXES_IN_MULTI_SEL_TREE - } - else - { - wxASSERT_MSG( select, - _T("SelectItem(false) works only for multiselect") ); + wxCHECK_RET( !IsHiddenRoot(item), _T("can't select hidden root item") ); - // inspite 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 + wxASSERT_MSG( select || HasFlag(wxTR_MULTIPLE), + _T("SelectItem(false) works only for multiselect") ); - wxTreeEvent event(wxEVT_COMMAND_TREE_SEL_CHANGING, this, item); - if ( !GetEventHandler()->ProcessEvent(event) || event.IsAllowed() ) + wxTreeEvent event(wxEVT_COMMAND_TREE_SEL_CHANGING, this, item); + if ( !GetEventHandler()->ProcessEvent(event) || event.IsAllowed() ) + { + if ( HasFlag(wxTR_MULTIPLE) ) { - if ( !TreeView_SelectItem(GetHwnd(), HITEM(item)) ) + if ( !::SelectItem(GetHwnd(), HITEM(item), select) ) { wxLogLastError(wxT("TreeView_SelectItem")); + return; } - else // ok + } + else // single selection + { + // use TreeView_SelectItem() to deselect the previous selection + if ( !TreeView_SelectItem(GetHwnd(), HITEM(item)) ) { - event.SetEventType(wxEVT_COMMAND_TREE_SEL_CHANGED); - (void)GetEventHandler()->ProcessEvent(event); + wxLogLastError(wxT("TreeView_SelectItem")); + return; } } - //else: program vetoed the change + + event.SetEventType(wxEVT_COMMAND_TREE_SEL_CHANGED); + (void)GetEventHandler()->ProcessEvent(event); } + //else: program vetoed the change } void wxTreeCtrl::EnsureVisible(const wxTreeItemId& item) @@ -2008,8 +1902,10 @@ bool wxTreeCtrl::MSWShouldPreProcessMessage(WXMSG* msg) return wxTreeCtrlBase::MSWShouldPreProcessMessage(msg); } -bool wxTreeCtrl::MSWCommand(WXUINT cmd, WXWORD id) +bool wxTreeCtrl::MSWCommand(WXUINT cmd, WXWORD id_) { + const int id = (signed short)id_; + if ( cmd == EN_UPDATE ) { wxCommandEvent event(wxEVT_COMMAND_TEXT_UPDATED, id); @@ -2047,31 +1943,46 @@ WXLRESULT wxTreeCtrl::MSWWindowProc(WXUINT nMsg, WXWPARAM wParam, WXLPARAM lPara { int x = GET_X_LPARAM(lParam), y = GET_Y_LPARAM(lParam); - // Convert the screen point to a client point - wxPoint MenuPoint = ScreenToClient(wxPoint(x, y)); - - // can't use GetSelection() here as it would assert in multiselect mode - wxTreeEvent event(wxEVT_COMMAND_TREE_ITEM_MENU, this, - wxTreeItemId(TreeView_GetSelection(GetHwnd()))); - - // Get the bounding rectangle for the item, including the non-text areas - wxRect ItemRect; - GetBoundingRect(event.m_item, ItemRect, false); - // If the point is inside the bounding rectangle, use it as the click position. - // This should be the case for WM_CONTEXTMENU as the result of a right-click - if (ItemRect.Inside(MenuPoint)) + + // the item for which the menu should be shown + wxTreeItemId item; + + // the position where the menu should be shown in client coordinates + // (so that it can be passed directly to PopupMenu()) + wxPoint pt; + + if ( x == -1 || y == -1 ) { - event.m_pointDrag = MenuPoint; + // this means that the event was generated from keyboard (e.g. with + // Shift-F10 or special Windows menu key) + // + // use the Explorer standard of putting the menu at the left edge + // of the text, in the vertical middle of the text + item = wxTreeItemId(TreeView_GetSelection(GetHwnd())); + if ( item.IsOk() ) + { + // Use the bounding rectangle of only the text part + wxRect rect; + GetBoundingRect(item, rect, true); + pt = wxPoint(rect.GetX(), rect.GetY() + rect.GetHeight() / 2); + } } - // Use the Explorer standard of putting the menu at the left edge of the text, - // in the vertical middle of the text. Should be the case for the "menu" key - else + else // event from mouse, use mouse position { - // Use the bounding rectangle of only the text part - GetBoundingRect(event.m_item, ItemRect, true); - event.m_pointDrag = wxPoint(ItemRect.GetX(), ItemRect.GetY() + ItemRect.GetHeight() / 2); + pt = ScreenToClient(wxPoint(x, y)); + + TV_HITTESTINFO tvhti; + tvhti.pt.x = pt.x; + tvhti.pt.y = pt.y; + if ( TreeView_HitTest(GetHwnd(), &tvhti) ) + item = wxTreeItemId(tvhti.hItem); } + // create the event + wxTreeEvent event(wxEVT_COMMAND_TREE_ITEM_MENU, this, item); + + event.m_pointDrag = pt; + if ( GetEventHandler()->ProcessEvent(event) ) processed = true; //else: continue with generating wxEVT_CONTEXT_MENU in base class code @@ -2082,32 +1993,15 @@ WXLRESULT wxTreeCtrl::MSWWindowProc(WXUINT nMsg, WXWPARAM wParam, WXLPARAM lPara // same meaning for all of them int x = GET_X_LPARAM(lParam), y = GET_Y_LPARAM(lParam); - HTREEITEM htItem = GetItemFromPoint(GetHwnd(), x, y); TV_HITTESTINFO tvht; tvht.pt.x = x; tvht.pt.y = y; - (void) TreeView_HitTest(GetHwnd(), &tvht); + HTREEITEM htItem = TreeView_HitTest(GetHwnd(), &tvht); switch ( nMsg ) { - case WM_RBUTTONDOWN: - // if the item we are about to right click on is not already - // selected or if we click outside of any item, remove the - // entire previous selection - if ( !htItem || !::IsItemSelected(GetHwnd(), htItem) ) - { - UnselectAll(); - } - - // select item and set the focus to the - // newly selected item - ::SelectItem(GetHwnd(), htItem); - ::SetFocus(GetHwnd(), htItem); - break; - -#if !wxUSE_CHECKBOXES_IN_MULTI_SEL_TREE case WM_LBUTTONDOWN: if ( htItem && isMultiple && (tvht.flags & TVHT_ONITEM) != 0 ) { @@ -2119,7 +2013,7 @@ WXLRESULT wxTreeCtrl::MSWWindowProc(WXUINT nMsg, WXWPARAM wParam, WXLPARAM lPara SetFocus(); // toggle selected state - ::ToggleItemSelection(GetHwnd(), htItem); + ToggleItemSelection(htItem); ::SetFocus(GetHwnd(), htItem); @@ -2182,13 +2076,20 @@ WXLRESULT wxTreeCtrl::MSWWindowProc(WXUINT nMsg, WXWPARAM wParam, WXLPARAM lPara ::SetFocus(GetHwnd(), htItem); processed = true; } + else // click on a single selected item + { + // don't interfere with the default processing in + // WM_MOUSEMOVE handler below as the default window + // proc will start the drag itself if we let have + // WM_LBUTTONDOWN + m_htClickedItem.Unset(); + } // reset on any click without Shift m_htSelStart.Unset(); } } break; -#endif // wxUSE_CHECKBOXES_IN_MULTI_SEL_TREE case WM_MOUSEMOVE: #ifndef __WXWINCE__ @@ -2197,39 +2098,49 @@ WXLRESULT wxTreeCtrl::MSWWindowProc(WXUINT nMsg, WXWPARAM wParam, WXLPARAM lPara int cx = abs(m_ptClick.x - x); int cy = abs(m_ptClick.y - y); - if ( cx > GetSystemMetrics( SM_CXDRAG ) || cy > GetSystemMetrics( SM_CYDRAG ) ) + if ( cx > ::GetSystemMetrics(SM_CXDRAG) || + cy > ::GetSystemMetrics(SM_CYDRAG) ) { - HWND pWnd = ::GetParent( GetHwnd() ); - if ( pWnd ) - { - NM_TREEVIEW tv; + NM_TREEVIEW tv; + wxZeroMemory(tv); - tv.hdr.hwndFrom = GetHwnd(); - tv.hdr.idFrom = ::GetWindowLong( GetHwnd(), GWL_ID ); - tv.hdr.code = TVN_BEGINDRAG; + tv.hdr.hwndFrom = GetHwnd(); + tv.hdr.idFrom = ::GetWindowLong(GetHwnd(), GWL_ID); + tv.hdr.code = TVN_BEGINDRAG; - tv.itemNew.hItem = HITEM(m_htClickedItem); + tv.itemNew.hItem = HITEM(m_htClickedItem); - TVITEM tviAux; - ZeroMemory(&tviAux, sizeof(tviAux)); - tviAux.hItem = HITEM(m_htClickedItem); - tviAux.mask = TVIF_STATE | TVIF_PARAM; - tviAux.stateMask = 0xffffffff; - TreeView_GetItem( GetHwnd(), &tviAux ); - tv.itemNew.state = tviAux.state; - tv.itemNew.lParam = tviAux.lParam; + TVITEM tviAux; + wxZeroMemory(tviAux); - tv.ptDrag.x = x; - tv.ptDrag.y = y; + tviAux.hItem = HITEM(m_htClickedItem); + tviAux.mask = TVIF_STATE | TVIF_PARAM; + tviAux.stateMask = 0xffffffff; + TreeView_GetItem(GetHwnd(), &tviAux); - ::SendMessage( pWnd, WM_NOTIFY, tv.hdr.idFrom, (LPARAM)&tv ); - } + tv.itemNew.state = tviAux.state; + tv.itemNew.lParam = tviAux.lParam; + + tv.ptDrag.x = x; + tv.ptDrag.y = y; + + // do it before SendMessage() call below to avoid + // reentrancies here if there is another WM_MOUSEMOVE + // in the queue already m_htClickedItem.Unset(); + + ::SendMessage(GetHwndOf(GetParent()), WM_NOTIFY, + tv.hdr.idFrom, (LPARAM)&tv ); + + // don't pass it to the default window proc, it would + // start dragging again + processed = true; } } #endif // __WXWINCE__ +#if wxUSE_DRAGIMAGE if ( m_dragImage ) { m_dragImage->Move(wxPoint(x, y)); @@ -2242,6 +2153,7 @@ WXLRESULT wxTreeCtrl::MSWWindowProc(WXUINT nMsg, WXWPARAM wParam, WXLPARAM lPara m_dragImage->Show(); } } +#endif // wxUSE_DRAGIMAGE break; case WM_LBUTTONUP: @@ -2267,6 +2179,7 @@ WXLRESULT wxTreeCtrl::MSWWindowProc(WXUINT nMsg, WXWPARAM wParam, WXLPARAM lPara // fall through case WM_RBUTTONUP: +#if wxUSE_DRAGIMAGE if ( m_dragImage ) { m_dragImage->EndDrag(); @@ -2275,16 +2188,18 @@ WXLRESULT wxTreeCtrl::MSWWindowProc(WXUINT nMsg, WXWPARAM wParam, WXLPARAM lPara // generate the drag end event wxTreeEvent event(wxEVT_COMMAND_TREE_END_DRAG, this, htItem); + event.m_pointDrag = wxPoint(x, y); + (void)GetEventHandler()->ProcessEvent(event); // if we don't do it, the tree seems to think that 2 items // are selected simultaneously which is quite weird TreeView_SelectDropTarget(GetHwnd(), 0); } +#endif // wxUSE_DRAGIMAGE break; } } -#if !wxUSE_CHECKBOXES_IN_MULTI_SEL_TREE else if ( (nMsg == WM_SETFOCUS || nMsg == WM_KILLFOCUS) && isMultiple ) { // the tree control greys out the selected item when it loses focus and @@ -2315,7 +2230,7 @@ WXLRESULT wxTreeCtrl::MSWWindowProc(WXUINT nMsg, WXWPARAM wParam, WXLPARAM lPara case VK_SPACE: if ( bCtrl ) { - ::ToggleItemSelection(GetHwnd(), htSel); + ToggleItemSelection(htSel); } else { @@ -2384,7 +2299,6 @@ WXLRESULT wxTreeCtrl::MSWWindowProc(WXUINT nMsg, WXWPARAM wParam, WXLPARAM lPara } } } -#endif // !wxUSE_CHECKBOXES_IN_MULTI_SEL_TREE else if ( nMsg == WM_COMMAND ) { // if we receive a EN_KILLFOCUS command from the in-place edit control @@ -2413,32 +2327,9 @@ WXLRESULT wxTreeCtrl::MSWWindowProc(WXUINT nMsg, WXWPARAM wParam, WXLPARAM lPara WXLRESULT wxTreeCtrl::MSWDefWindowProc(WXUINT nMsg, WXWPARAM wParam, WXLPARAM lParam) { - // default WM_RBUTTONDOWN handler enters modal loop inside DefWindowProc() - // waiting for WM_RBUTTONUP and then sends the resulting WM_CONTEXTMENU to - // the parent window, not us, which completely breaks everything so simply - // don't let it see this message at all - if ( nMsg == WM_RBUTTONDOWN ) - return 0; - - // but because of the above we don't get NM_RCLICK which is normally - // generated by tree window proc when the modal loop mentioned above ends - // because the mouse is released -- synthesize it ourselves instead - if ( nMsg == WM_RBUTTONUP ) - { - NMHDR hdr; - hdr.hwndFrom = GetHwnd(); - hdr.idFrom = GetId(); - hdr.code = NM_RCLICK; - - WXLPARAM rc; - MSWOnNotify(GetId(), (LPARAM)&hdr, &rc); - - // continue as usual - } - if ( nMsg == WM_CHAR ) { - // also don't let the control process Space and Return keys because it + // don't let the control process Space and Return keys because it // doesn't do anything useful with them anyhow but always beeps // annoyingly when it receives them and there is no way to turn it off // simply if you just process TREEITEM_ACTIVATED event to which Space @@ -2446,6 +2337,24 @@ wxTreeCtrl::MSWDefWindowProc(WXUINT nMsg, WXWPARAM wParam, WXLPARAM lParam) if ( wParam == VK_SPACE || wParam == VK_RETURN ) return 0; } +#if wxUSE_DRAGIMAGE + else if ( nMsg == WM_KEYDOWN ) + { + if ( wParam == VK_ESCAPE ) + { + if ( m_dragImage ) + { + m_dragImage->EndDrag(); + delete m_dragImage; + m_dragImage = NULL; + + // if we don't do it, the tree seems to think that 2 items + // are selected simultaneously which is quite weird + TreeView_SelectDropTarget(GetHwnd(), 0); + } + } + } +#endif // wxUSE_DRAGIMAGE return wxControl::MSWDefWindowProc(nMsg, wParam, lParam); } @@ -2549,8 +2458,8 @@ bool wxTreeCtrl::MSWOnNotify(int idCtrl, WXLPARAM lParam, WXLPARAM *result) break; } -#endif -#endif +#endif // TVN_GETINFOTIP +#endif // !__WXWINCE__ case TVN_GETDISPINFO: eventType = wxEVT_COMMAND_TREE_GET_INFO; @@ -2821,8 +2730,20 @@ bool wxTreeCtrl::MSWOnNotify(int idCtrl, WXLPARAM lParam, WXLPARAM *result) *result = false; break; + case NM_RCLICK: + // prevent tree control from sending WM_CONTEXTMENU to our parent + // (which it does if NM_RCLICK is not handled) because we want to + // send it to the control itself + *result = + processed = true; + + ::SendMessage(GetHwnd(), WM_CONTEXTMENU, + (WPARAM)GetHwnd(), ::GetMessagePos()); + break; + case TVN_BEGINDRAG: case TVN_BEGINRDRAG: +#if wxUSE_DRAGIMAGE if ( event.IsAllowed() ) { // normally this is impossible because the m_dragImage is @@ -2833,6 +2754,7 @@ bool wxTreeCtrl::MSWOnNotify(int idCtrl, WXLPARAM lParam, WXLPARAM *result) m_dragImage->BeginDrag(wxPoint(0,0), this); m_dragImage->Show(); } +#endif // wxUSE_DRAGIMAGE break; case TVN_DELETEITEM: