#pragma hdrstop
#endif
-#include "wx/window.h"
#include "wx/msw/private.h"
// Mingw32 is a bit mental even though this is done in winundef
#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 <commctrl.h>
#endif
#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)
return TRUE;
}
+ size_t GetCount() const { return m_selections.GetCount(); }
+
private:
wxArrayTreeItemIds& m_selections;
};
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
m_imageListState = NULL;
m_textCtrl = NULL;
m_hasAnyAttr = FALSE;
+ m_dragImage = NULL;
}
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.
{
TraverseSelections selector(this, selections);
- return selections.GetCount();
+ return selector.GetCount();
}
// ----------------------------------------------------------------------------
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;
}
{
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
return NULL;
}
- DeleteTextCtrl();
-
m_textCtrl = (wxTextCtrl *)textControlClass->CreateObject();
m_textCtrl->SetHWND((WXHWND)hWnd);
m_textCtrl->SubclassWin((WXHWND)hWnd);
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)
{
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;
// 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