#include "wx/treectrl.h"
#ifndef WX_PRECOMP
+ #include "wx/msw/wrapcctl.h" // include <commctrl.h> "properly"
+ #include "wx/msw/missing.h"
#include "wx/dynarray.h"
#include "wx/log.h"
#include "wx/app.h"
#include "wx/msw/private.h"
-// include <commctrl.h> "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
// 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
// ----------------------------------------------------------------------------
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)
{
}
}
-#endif // wxUSE_CHECKBOXES_IN_MULTI_SEL_TREE
-
// ----------------------------------------------------------------------------
// private classes
// ----------------------------------------------------------------------------
{
public:
wxTreeItemParam()
- : m_item((long int)0),
- m_data(NULL)
{
+ m_data = NULL;
+
for ( size_t n = 0; n < WXSIZEOF(m_images); n++ )
{
m_images[n] = -1;
virtual bool OnVisit(const wxTreeItemId& item)
{
+ const wxTreeCtrl * const tree = GetTree();
+
// can't visit a virtual node.
- if ( (GetTree()->GetRootItem() == item) && (GetTree()->GetWindowStyle() & wxTR_HIDE_ROOT))
+ if ( (tree->GetRootItem() == item) && tree->HasFlag(wxTR_HIDE_ROOT) )
{
return true;
}
-#if wxUSE_CHECKBOXES_IN_MULTI_SEL_TREE
- if ( GetTree()->IsItemChecked(item) )
-#else
- if ( ::IsItemSelected(GetHwndOf(GetTree()), HITEM(item)) )
-#endif
+ if ( ::IsItemSelected(GetHwndOf(tree), HITEM(item)) )
{
m_selections.Add(item);
}
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;
// Item access
// ----------------------------------------------------------------------------
+bool wxTreeCtrl::IsHiddenRoot(const wxTreeItemId& item) const
+{
+ return HITEM(item) == TVI_ROOT && HasFlag(wxTR_HIDE_ROOT);
+}
+
wxString wxTreeCtrl::GetItemText(const wxTreeItemId& item) const
{
wxCHECK_MSG( item.IsOk(), wxEmptyString, wxT("invalid tree item") );
{
wxCHECK_MSG( item.IsOk(), -1, wxT("invalid tree item") );
- if ( (HITEM(item) == TVI_ROOT) && (m_windowStyle & wxTR_HIDE_ROOT) )
+ if ( IsHiddenRoot(item) )
{
// no images for hidden root item
return -1;
wxT("invalid image index"));
- if ( (HITEM(item) == TVI_ROOT) && (m_windowStyle & wxTR_HIDE_ROOT) )
+ if ( IsHiddenRoot(item) )
{
// no images for hidden root item
return;
wxTreeItemData *data)
{
- if ( m_windowStyle & wxTR_HIDE_ROOT )
+ if ( HasFlag(wxTR_HIDE_ROOT) )
{
// create a virtual root item, the parent for all the others
wxTreeItemParam *param = new wxTreeItemParam;
wxT("Unknown flag in wxTreeCtrl::DoExpand") );
// A hidden root can be neither expanded nor collapsed.
- wxCHECK_RET( !(m_windowStyle & wxTR_HIDE_ROOT) || (HITEM(item) != TVI_ROOT),
+ wxCHECK_RET( !IsHiddenRoot(item),
wxT("Can't expand/collapse hidden root node!") );
// TreeView_Expand doesn't send TVN_ITEMEXPAND(ING) messages, so we must
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();
{
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
{
void wxTreeCtrl::EnsureVisible(const wxTreeItemId& item)
{
+ wxCHECK_RET( !IsHiddenRoot(item), _T("can't show hidden root item") );
+
// no error return
TreeView_EnsureVisible(GetHwnd(), HITEM(item));
}
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))
+ if (ItemRect.Contains(MenuPoint))
{
event.m_pointDrag = MenuPoint;
}
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 )
{
}
}
break;
-#endif // wxUSE_CHECKBOXES_IN_MULTI_SEL_TREE
case WM_MOUSEMOVE:
#ifndef __WXWINCE__
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
}
}
}
-#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
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
break;
}
-#endif
-#endif
+#endif // TVN_GETINFOTIP
+#endif // !__WXWINCE__
case TVN_GETDISPINFO:
eventType = wxEVT_COMMAND_TREE_GET_INFO;
*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 ( event.IsAllowed() )