#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
#include "wx/msw/treectrl.h"
#include "wx/msw/dragimag.h"
-// include <commctrl.h> "properly"
-#include "wx/msw/wrapcctl.h"
-
// macros to hide the cast ugliness
// --------------------------------
{
m_selections.Empty();
- DoTraverse(tree->GetRootItem());
+ if (tree->GetCount() > 0)
+ DoTraverse(tree->GetRootItem());
}
virtual bool OnVisit(const wxTreeItemId& item)
wstyle |= TVS_CHECKBOXES;
#endif // wxUSE_CHECKBOXES_IN_MULTI_SEL_TREE
-#ifndef __WXWINCE__
+#if !defined(__WXWINCE__) && defined(TVS_INFOTIP)
// Need so that TVN_GETINFOTIP messages will be sent
wstyle |= TVS_INFOTIP;
#endif
WXLRESULT rc = 0;
bool isMultiple = HasFlag(wxTR_MULTIPLE);
-#ifdef WM_CONTEXTMENU
+ // This message is sent after a right-click, or when the "menu" key is pressed
if ( nMsg == WM_CONTEXTMENU )
{
+ 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));
+
wxTreeEvent event( wxEVT_COMMAND_TREE_ITEM_MENU, GetId() );
// can't use GetSelection() here as it would assert in multiselect mode
event.m_item = wxTreeItemId(TreeView_GetSelection(GetHwnd()));
event.SetEventObject( this );
+ // 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))
+ {
+ event.m_pointDrag = MenuPoint;
+ }
+ // 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
+ {
+ // 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);
+ }
+
if ( GetEventHandler()->ProcessEvent(event) )
processed = true;
//else: continue with generating wxEVT_CONTEXT_MENU in base class code
}
-#endif // WM_CONTEXTMENU
else if ( (nMsg >= WM_MOUSEFIRST) && (nMsg <= WM_MOUSELAST) )
{
// we only process mouse messages here and these parameters have the
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
break;
}
+#ifdef TVN_GETINFOTIP
case TVN_GETINFOTIP:
{
eventType = wxEVT_COMMAND_TREE_ITEM_GETTOOLTIP;
break;
}
+#endif
#endif
case TVN_GETDISPINFO:
break;
#ifndef __WXWINCE__
+#ifdef TVN_GETINFOTIP
case TVN_GETINFOTIP:
{
// If the user permitted a tooltip change, change it
}
}
break;
+#endif
#endif
case TVN_SELCHANGING: