// 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)
{
}
}
-#endif // wxUSE_CHECKBOXES_IN_MULTI_SEL_TREE
-
// ----------------------------------------------------------------------------
// private classes
// ----------------------------------------------------------------------------
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);
}
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;
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;
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);
}
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
{
{
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
// 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 )
{
}
}
break;
-#endif // wxUSE_CHECKBOXES_IN_MULTI_SEL_TREE
case WM_MOUSEMOVE:
#ifndef __WXWINCE__
// 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
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() )