X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/bb448552973769217dbbdfd25806a462351d4ba5..18d2e17080a0bea4b85e0ad7223cfc6bcdab0e1e:/src/msw/treectrl.cpp diff --git a/src/msw/treectrl.cpp b/src/msw/treectrl.cpp index b309b70702..a613f5e12e 100644 --- a/src/msw/treectrl.cpp +++ b/src/msw/treectrl.cpp @@ -27,7 +27,6 @@ #pragma hdrstop #endif -#include "wx/window.h" #include "wx/msw/private.h" // Mingw32 is a bit mental even though this is done in winundef @@ -47,13 +46,13 @@ #include "wx/treectrl.h" #include "wx/settings.h" -#ifdef __GNUWIN32__ -#ifndef wxUSE_NORLANDER_HEADERS -#include "wx/msw/gnuwin32/extra.h" -#endif +#include "wx/msw/dragimag.h" + +#ifdef __GNUWIN32_OLD__ + #include "wx/msw/gnuwin32/extra.h" #endif -#if (defined(__WIN95__) && !defined(__GNUWIN32__)) || defined(__TWIN32__) || defined(wxUSE_NORLANDER_HEADERS) +#if defined(__WIN95__) && !(defined(__GNUWIN32_OLD__) || defined(__TWIN32__)) #include #endif @@ -66,6 +65,10 @@ #define TV_FIRST 0x1100 #endif +#ifndef TVS_CHECKBOXES + #define TVS_CHECKBOXES 0x0100 +#endif + // old headers might miss these messages (comctl32.dll 4.71+ only) #ifndef TVM_SETBKCOLOR #define TVM_SETBKCOLOR (TV_FIRST + 29) @@ -149,6 +152,8 @@ public: return TRUE; } + size_t GetCount() const { return m_selections.GetCount(); } + private: wxArrayTreeItemIds& m_selections; }; @@ -236,11 +241,25 @@ private: wxTreeItemData *m_data; }; +// ---------------------------------------------------------------------------- +// private functions +// ---------------------------------------------------------------------------- + +static HTREEITEM GetItemFromPoint(HWND hwndTV, int x, int y) +{ + TV_HITTESTINFO tvht; + tvht.pt.x = x; + tvht.pt.y = y; + + // TreeView_HitTest() doesn't do the right cast in mingw32 headers + return (HTREEITEM)TreeView_HitTest(hwndTV, &tvht); +} + // ---------------------------------------------------------------------------- // macros // ---------------------------------------------------------------------------- - IMPLEMENT_DYNAMIC_CLASS(wxTreeCtrl, wxControl) +IMPLEMENT_DYNAMIC_CLASS(wxTreeCtrl, wxControl) // ---------------------------------------------------------------------------- // variables @@ -298,6 +317,7 @@ void wxTreeCtrl::Init() m_imageListState = NULL; m_textCtrl = NULL; m_hasAnyAttr = FALSE; + m_dragImage = NULL; } bool wxTreeCtrl::Create(wxWindow *parent, @@ -325,13 +345,15 @@ bool wxTreeCtrl::Create(wxWindow *parent, if ( m_windowStyle & wxTR_LINES_AT_ROOT ) wstyle |= TVS_LINESATROOT; -#if !defined( __GNUWIN32__ ) && !defined( __BORLANDC__ ) && !defined( __WATCOMC__ ) && !defined(wxUSE_NORLANDER_HEADERS) +#if !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 !defined(__VISUALC__) || (__VISUALC__ > 1010) if ( m_windowStyle & wxTR_MULTIPLE ) wstyle |= TVS_CHECKBOXES; -#endif #endif // Create the tree control. @@ -978,7 +1000,7 @@ size_t wxTreeCtrl::GetSelections(wxArrayTreeItemIds& selections) const { TraverseSelections selector(this, selections); - return selections.GetCount(); + return selector.GetCount(); } // ---------------------------------------------------------------------------- @@ -1299,6 +1321,24 @@ void wxTreeCtrl::ScrollTo(const wxTreeItemId& item) wxTextCtrl* wxTreeCtrl::GetEditControl() const { + // normally, we could try to do something like this to return something + // even when the editing was started by the user and not by calling + // EditLabel() - but as nobody has asked for this so far and there might be + // problems in the code below, I leave it disabled for now (VZ) +#if 0 + if ( !m_textCtrl ) + { + HWND hwndText = TreeView_GetEditControl(GetHwnd()); + if ( hwndText ) + { + m_textCtrl = new wxTextCtrl(this, -1); + m_textCtrl->Hide(); + m_textCtrl->SetHWND((WXHWND)hwndText); + } + //else: not editing label right now + } +#endif // 0 + return m_textCtrl; } @@ -1318,6 +1358,8 @@ wxTextCtrl* wxTreeCtrl::EditLabel(const wxTreeItemId& item, { wxASSERT( textControlClass->IsKindOf(CLASSINFO(wxTextCtrl)) ); + DeleteTextCtrl(); + HWND hWnd = (HWND) TreeView_EditLabel(GetHwnd(), (HTREEITEM) (WXHTREEITEM) item); // this is not an error - the TVN_BEGINLABELEDIT handler might have @@ -1327,8 +1369,6 @@ wxTextCtrl* wxTreeCtrl::EditLabel(const wxTreeItemId& item, return NULL; } - DeleteTextCtrl(); - m_textCtrl = (wxTextCtrl *)textControlClass->CreateObject(); m_textCtrl->SetHWND((WXHWND)hWnd); m_textCtrl->SubclassWin((WXHWND)hWnd); @@ -1461,6 +1501,62 @@ bool wxTreeCtrl::MSWCommand(WXUINT cmd, WXWORD id) return TRUE; } +// 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 +// WM_MOUSEMOVE as they're a lot of them) by catching Windows messages directly +// instead of passing by wxWin events +long wxTreeCtrl::MSWWindowProc(WXUINT nMsg, WXWPARAM wParam, WXLPARAM lParam) +{ + if ( m_dragImage ) + { + switch ( nMsg ) + { + case WM_MOUSEMOVE: + { + int x = GET_X_LPARAM(lParam), + y = GET_Y_LPARAM(lParam); + + m_dragImage->Move(wxPoint(x, y), this); + + HTREEITEM htiTarget = GetItemFromPoint(GetHwnd(), x, y); + if ( htiTarget ) + { + // highlight the item as target (hiding drag image is + // necessary - otherwise the display will be corrupted) + m_dragImage->Hide(this); + TreeView_SelectDropTarget(GetHwnd(), htiTarget); + m_dragImage->Show(this); + } + } + break; + + case WM_LBUTTONUP: + case WM_RBUTTONUP: + { + m_dragImage->EndDrag(this); + delete m_dragImage; + m_dragImage = NULL; + + // generate the drag end event + wxTreeEvent event(wxEVT_COMMAND_TREE_END_DRAG, m_windowId); + + int x = GET_X_LPARAM(lParam), + y = GET_Y_LPARAM(lParam); + + event.m_item + = (WXHTREEITEM)GetItemFromPoint(GetHwnd(), x, y); + event.m_pointDrag = wxPoint(x, y); + event.SetEventObject(this); + + (void)GetEventHandler()->ProcessEvent(event); + } + break; + } + } + + return wxControl::MSWWindowProc(nMsg, wParam, lParam); +} + // process WM_NOTIFY Windows message bool wxTreeCtrl::MSWOnNotify(int idCtrl, WXLPARAM lParam, WXLPARAM *result) { @@ -1503,6 +1599,11 @@ bool wxTreeCtrl::MSWOnNotify(int idCtrl, WXLPARAM lParam, WXLPARAM *result) event.m_item = (WXHTREEITEM) tv->itemNew.hItem; event.m_pointDrag = wxPoint(tv->ptDrag.x, tv->ptDrag.y); + + // don't allow dragging by default: the user code must + // explicitly say that it wants to allow it to avoid breaking + // the old apps + event.Veto(); } break; @@ -1735,6 +1836,20 @@ bool wxTreeCtrl::MSWOnNotify(int idCtrl, WXLPARAM lParam, WXLPARAM *result) // post processing switch ( hdr->code ) { + case TVN_BEGINDRAG: + case TVN_BEGINRDRAG: + if ( event.IsAllowed() ) + { + // normally this is impossible because the m_dragImage is + // deleted once the drag operation is over + wxASSERT_MSG( !m_dragImage, _T("starting to drag once again?") ); + + m_dragImage = new wxDragImage(*this, event.m_item); + m_dragImage->BeginDrag(wxPoint(0, 0), this); + m_dragImage->Show(this); + } + break; + case TVN_DELETEITEM: { // NB: we might process this message using wxWindows event