#include "wx/dynlib.h"
#include "wx/msw/private.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/imaglist.h"
#include "wx/msw/dragimag.h"
+#include "wx/msw/uxtheme.h"
// macros to hide the cast ugliness
// --------------------------------
// The vista tree control includes some new code that originally broke the
// multi-selection tree, causing seemingly spurious item selection state changes
// during Shift or Ctrl-click item selection. (To witness the original broken
-// behavior, simply make IsLocked() below always return false). This problem was
+// behaviour, simply make IsLocked() below always return false). This problem was
// solved by using the following class to 'unlock' an item's selection state.
class TreeItemUnlocker
{
public:
// unlock a single item
- TreeItemUnlocker(HTREEITEM item) { ms_unlockedItem = item; }
+ TreeItemUnlocker(HTREEITEM item)
+ {
+ m_oldUnlockedItem = ms_unlockedItem;
+ ms_unlockedItem = item;
+ }
// unlock all items, don't use unless absolutely necessary
- TreeItemUnlocker() { ms_unlockedItem = (HTREEITEM)-1; }
+ TreeItemUnlocker()
+ {
+ m_oldUnlockedItem = ms_unlockedItem;
+ ms_unlockedItem = (HTREEITEM)-1;
+ }
// lock everything back
- ~TreeItemUnlocker() { ms_unlockedItem = NULL; }
+ ~TreeItemUnlocker() { ms_unlockedItem = m_oldUnlockedItem; }
// check if the item state is currently locked
private:
static HTREEITEM ms_unlockedItem;
+ HTREEITEM m_oldUnlockedItem;
+
+ wxDECLARE_NO_COPY_CLASS(TreeItemUnlocker);
};
HTREEITEM TreeItemUnlocker::ms_unlockedItem = NULL;
// private functions
// ----------------------------------------------------------------------------
+namespace
+{
+
+// Work around a problem with TreeView_GetItemRect() when using MinGW/Cygwin:
+// it results in warnings about breaking strict aliasing rules because HITEM is
+// passed via a RECT pointer, so use a union to avoid them and define our own
+// version of the standard macro using it.
+union TVGetItemRectParam
+{
+ RECT rect;
+ HTREEITEM hItem;
+};
+
+inline bool
+wxTreeView_GetItemRect(HWND hwnd,
+ HTREEITEM hItem,
+ TVGetItemRectParam& param,
+ BOOL fItemRect)
+{
+ param.hItem = hItem;
+ return ::SendMessage(hwnd, TVM_GETITEMRECT, fItemRect,
+ (LPARAM)¶m) == TRUE;
+}
+
+} // anonymous namespace
+
// wrappers for TreeView_GetItem/TreeView_SetItem
static bool IsItemSelected(HWND hwndTV, HTREEITEM hItem)
{
switch ( which )
{
case wxTreeItemIcon_SelectedExpanded:
- image = GetImage(wxTreeItemIcon_Expanded);
+ // We consider that expanded icon is more important than
+ // selected so test for it first.
+ image = m_images[wxTreeItemIcon_Expanded];
+ if ( image == -1 )
+ image = m_images[wxTreeItemIcon_Selected];
if ( image != -1 )
break;
//else: fall through
case wxTreeItemIcon_Selected:
case wxTreeItemIcon_Expanded:
- image = GetImage(wxTreeItemIcon_Normal);
+ image = m_images[wxTreeItemIcon_Normal];
break;
case wxTreeItemIcon_Normal:
// wxWin macros
// ----------------------------------------------------------------------------
-#if wxUSE_EXTENDED_RTTI
-WX_DEFINE_FLAGS( wxTreeCtrlStyle )
-
-wxBEGIN_FLAGS( wxTreeCtrlStyle )
- // new style border flags, we put them first to
- // use them for streaming out
- wxFLAGS_MEMBER(wxBORDER_SIMPLE)
- wxFLAGS_MEMBER(wxBORDER_SUNKEN)
- wxFLAGS_MEMBER(wxBORDER_DOUBLE)
- wxFLAGS_MEMBER(wxBORDER_RAISED)
- wxFLAGS_MEMBER(wxBORDER_STATIC)
- wxFLAGS_MEMBER(wxBORDER_NONE)
-
- // old style border flags
- wxFLAGS_MEMBER(wxSIMPLE_BORDER)
- wxFLAGS_MEMBER(wxSUNKEN_BORDER)
- wxFLAGS_MEMBER(wxDOUBLE_BORDER)
- wxFLAGS_MEMBER(wxRAISED_BORDER)
- wxFLAGS_MEMBER(wxSTATIC_BORDER)
- wxFLAGS_MEMBER(wxBORDER)
-
- // standard window styles
- wxFLAGS_MEMBER(wxTAB_TRAVERSAL)
- wxFLAGS_MEMBER(wxCLIP_CHILDREN)
- wxFLAGS_MEMBER(wxTRANSPARENT_WINDOW)
- wxFLAGS_MEMBER(wxWANTS_CHARS)
- wxFLAGS_MEMBER(wxFULL_REPAINT_ON_RESIZE)
- wxFLAGS_MEMBER(wxALWAYS_SHOW_SB )
- wxFLAGS_MEMBER(wxVSCROLL)
- wxFLAGS_MEMBER(wxHSCROLL)
-
- wxFLAGS_MEMBER(wxTR_EDIT_LABELS)
- wxFLAGS_MEMBER(wxTR_NO_BUTTONS)
- wxFLAGS_MEMBER(wxTR_HAS_BUTTONS)
- wxFLAGS_MEMBER(wxTR_TWIST_BUTTONS)
- wxFLAGS_MEMBER(wxTR_NO_LINES)
- wxFLAGS_MEMBER(wxTR_FULL_ROW_HIGHLIGHT)
- wxFLAGS_MEMBER(wxTR_LINES_AT_ROOT)
- wxFLAGS_MEMBER(wxTR_HIDE_ROOT)
- wxFLAGS_MEMBER(wxTR_ROW_LINES)
- wxFLAGS_MEMBER(wxTR_HAS_VARIABLE_ROW_HEIGHT)
- wxFLAGS_MEMBER(wxTR_SINGLE)
- wxFLAGS_MEMBER(wxTR_MULTIPLE)
-#if WXWIN_COMPATIBILITY_2_8
- wxFLAGS_MEMBER(wxTR_EXTENDED)
-#endif
- wxFLAGS_MEMBER(wxTR_DEFAULT_STYLE)
-
-wxEND_FLAGS( wxTreeCtrlStyle )
-
-IMPLEMENT_DYNAMIC_CLASS_XTI(wxTreeCtrl, wxControl,"wx/treectrl.h")
-
-wxBEGIN_PROPERTIES_TABLE(wxTreeCtrl)
- wxEVENT_PROPERTY( TextUpdated , wxEVT_COMMAND_TEXT_UPDATED , wxCommandEvent )
- wxEVENT_RANGE_PROPERTY( TreeEvent , wxEVT_COMMAND_TREE_BEGIN_DRAG , wxEVT_COMMAND_TREE_STATE_IMAGE_CLICK , wxTreeEvent )
- wxPROPERTY_FLAGS( WindowStyle , wxTreeCtrlStyle , long , SetWindowStyleFlag , GetWindowStyleFlag , EMPTY_MACROVALUE , 0 /*flags*/ , wxT("Helpstring") , wxT("group")) // style
-wxEND_PROPERTIES_TABLE()
-
-wxBEGIN_HANDLERS_TABLE(wxTreeCtrl)
-wxEND_HANDLERS_TABLE()
-
-wxCONSTRUCTOR_5( wxTreeCtrl , wxWindow* , Parent , wxWindowID , Id , wxPoint , Position , wxSize , Size , long , WindowStyle )
-#else
-IMPLEMENT_DYNAMIC_CLASS(wxTreeCtrl, wxControl)
-#endif
-
// ----------------------------------------------------------------------------
// constants
// ----------------------------------------------------------------------------
but logically it's a const table with the following entries:
=
{
- { wxEVT_COMMAND_TREE_ITEM_COLLAPSED, wxEVT_COMMAND_TREE_ITEM_COLLAPSING },
- { wxEVT_COMMAND_TREE_ITEM_EXPANDED, wxEVT_COMMAND_TREE_ITEM_EXPANDING }
+ { wxEVT_TREE_ITEM_COLLAPSED, wxEVT_TREE_ITEM_COLLAPSING },
+ { wxEVT_TREE_ITEM_EXPANDED, wxEVT_TREE_ITEM_EXPANDING }
};
*/
// initialize the global array of events now as it can't be done statically
// with the wxEVT_XXX values being allocated during run-time only
- gs_expandEvents[IDX_COLLAPSE][IDX_DONE] = wxEVT_COMMAND_TREE_ITEM_COLLAPSED;
- gs_expandEvents[IDX_COLLAPSE][IDX_DOING] = wxEVT_COMMAND_TREE_ITEM_COLLAPSING;
- gs_expandEvents[IDX_EXPAND][IDX_DONE] = wxEVT_COMMAND_TREE_ITEM_EXPANDED;
- gs_expandEvents[IDX_EXPAND][IDX_DOING] = wxEVT_COMMAND_TREE_ITEM_EXPANDING;
+ gs_expandEvents[IDX_COLLAPSE][IDX_DONE] = wxEVT_TREE_ITEM_COLLAPSED;
+ gs_expandEvents[IDX_COLLAPSE][IDX_DOING] = wxEVT_TREE_ITEM_COLLAPSING;
+ gs_expandEvents[IDX_EXPAND][IDX_DONE] = wxEVT_TREE_ITEM_EXPANDED;
+ gs_expandEvents[IDX_EXPAND][IDX_DOING] = wxEVT_TREE_ITEM_EXPANDING;
}
bool wxTreeCtrl::Create(wxWindow *parent,
if ( !MSWCreateControl(WC_TREEVIEW, wstyle, pos, size) )
return false;
-#if wxUSE_COMCTL32_SAFELY
- wxWindow::SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW));
- wxWindow::SetForegroundColour(wxWindow::GetParent()->GetForegroundColour());
-#elif 1
SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW));
SetForegroundColour(wxWindow::GetParent()->GetForegroundColour());
-#else
- // This works around a bug in the Windows tree control whereby for some versions
- // of comctrl32, setting any colour actually draws the background in black.
- // This will initialise the background to the system colour.
- // THIS FIX NOW REVERTED since it caused problems on _other_ systems.
- // Assume the user has an updated comctl32.dll.
- ::SendMessage(GetHwnd(), TVM_SETBKCOLOR, 0,-1);
- wxWindow::SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW));
- SetForegroundColour(wxWindow::GetParent()->GetForegroundColour());
-#endif
wxSetCCUnicodeFormat(GetHwnd());
+ if ( m_windowStyle & wxTR_TWIST_BUTTONS )
+ {
+ // Under Vista and later Explorer uses rotating ("twist") buttons
+ // instead of the default "+/-" ones so apply its theme to the tree
+ // control to implement this style.
+ if ( wxGetWinVersion() >= wxWinVersion_Vista )
+ {
+ if ( wxUxThemeEngine *theme = wxUxThemeEngine::GetIfActive() )
+ {
+ theme->SetWindowTheme(GetHwnd(), L"EXPLORER", NULL);
+ }
+ }
+ }
+
return true;
}
wxTreeCtrl::~wxTreeCtrl()
{
+ m_isBeingDeleted = true;
+
// delete any attributes
if ( m_hasAnyAttr )
{
bool wxTreeCtrl::SetBackgroundColour(const wxColour &colour)
{
-#if !wxUSE_COMCTL32_SAFELY
if ( !wxWindowBase::SetBackgroundColour(colour) )
return false;
::SendMessage(GetHwnd(), TVM_SETBKCOLOR, 0, colour.GetPixel());
-#endif
return true;
}
bool wxTreeCtrl::SetForegroundColour(const wxColour &colour)
{
-#if !wxUSE_COMCTL32_SAFELY
if ( !wxWindowBase::SetForegroundColour(colour) )
return false;
::SendMessage(GetHwnd(), TVM_SETTEXTCOLOR, 0, colour.GetPixel());
-#endif
return true;
}
return;
wxTreeViewItem tvItem(item, TVIF_TEXT);
- tvItem.pszText = (wxChar *)text.wx_str(); // conversion is ok
+ tvItem.pszText = wxMSW_CONV_LPTSTR(text);
DoSetItem(&tvItem);
// when setting the text of the item being edited, the text control should
{
if ( item == m_idEdited )
{
- ::SetWindowText(hwndEdit, text.wx_str());
+ ::SetWindowText(hwndEdit, text.t_str());
}
}
}
}
// Bug in Gnu-Win32 headers, so don't use the macro TreeView_GetItemRect
- RECT rect;
-
- // this ugliness comes directly from MSDN - it *is* the correct way to pass
- // the HTREEITEM with TVM_GETITEMRECT
- *(HTREEITEM *)&rect = HITEM(item);
+ TVGetItemRectParam param;
// true means to get rect for just the text, not the whole line
- if ( !::SendMessage(GetHwnd(), TVM_GETITEMRECT, true, (LPARAM)&rect) )
+ if ( !wxTreeView_GetItemRect(GetHwnd(), HITEM(item), param, TRUE) )
{
// if TVM_GETITEMRECT returned false, then the item is definitely not
// visible (because its parent is not expanded)
// however if it returned true, the item might still be outside the
// currently visible part of the tree, test for it (notice that partly
// visible means visible here)
- return rect.bottom > 0 && rect.top < GetClientSize().y;
+ return param.rect.bottom > 0 && param.rect.top < GetClientSize().y;
}
bool wxTreeCtrl::ItemHasChildren(const wxTreeItemId& item) const
if ( !text.empty() )
{
mask |= TVIF_TEXT;
- tvIns.item.pszText = (wxChar *)text.wx_str(); // cast is ok
+ tvIns.item.pszText = wxMSW_CONV_LPTSTR(text);
}
else
{
// need this to make the "[+]" appear
if ( firstChild )
{
- RECT rect;
- TreeView_GetItemRect(GetHwnd(), HITEM(parent), &rect, FALSE);
- ::InvalidateRect(GetHwnd(), &rect, FALSE);
+ TVGetItemRectParam param;
+
+ wxTreeView_GetItemRect(GetHwnd(), HITEM(parent), param, FALSE);
+ ::InvalidateRect(GetHwnd(), ¶m.rect, FALSE);
}
// associate the application tree item with Win32 tree item handle
if ( next.IsOk() )
{
- wxTreeEvent changingEvent(wxEVT_COMMAND_TREE_SEL_CHANGING, this, next);
+ wxTreeEvent changingEvent(wxEVT_TREE_SEL_CHANGING, this, next);
if ( IsTreeEventAllowed(changingEvent) )
{
- wxTreeEvent changedEvent(wxEVT_COMMAND_TREE_SEL_CHANGED, this, next);
+ wxTreeEvent changedEvent(wxEVT_TREE_SEL_CHANGED, this, next);
(void)HandleTreeEvent(changedEvent);
}
else
if ( IsExpanded(item) )
{
- wxTreeEvent event(wxEVT_COMMAND_TREE_ITEM_COLLAPSING,
+ wxTreeEvent event(wxEVT_TREE_ITEM_COLLAPSING,
this, wxTreeItemId(item));
if ( !IsTreeEventAllowed(event) )
if ( IsExpanded(item) )
return;
- wxTreeEvent event(wxEVT_COMMAND_TREE_ITEM_COLLAPSED, this, item);
+ wxTreeEvent event(wxEVT_TREE_ITEM_COLLAPSED, this, item);
(void)HandleTreeEvent(event);
}
//else: change didn't took place, so do nothing at all
if ( HasFlag(wxTR_MULTIPLE) )
{
- wxTreeEvent changingEvent(wxEVT_COMMAND_TREE_SEL_CHANGING,
+ wxTreeEvent changingEvent(wxEVT_TREE_SEL_CHANGING,
this, wxTreeItemId());
changingEvent.m_itemOld = htFocus;
{
ClearFocusedItem();
- wxTreeEvent changedEvent(wxEVT_COMMAND_TREE_SEL_CHANGED,
+ wxTreeEvent changedEvent(wxEVT_TREE_SEL_CHANGED,
this, wxTreeItemId());
changedEvent.m_itemOld = htFocus;
(void)HandleTreeEvent(changedEvent);
HTREEITEM htFocus = (HTREEITEM)TreeView_GetSelection(GetHwnd());
if ( !htFocus ) return;
- wxTreeEvent changingEvent(wxEVT_COMMAND_TREE_SEL_CHANGING, this);
+ wxTreeEvent changingEvent(wxEVT_TREE_SEL_CHANGING, this);
changingEvent.m_itemOld = htFocus;
if ( IsTreeEventAllowed(changingEvent) )
{
DoUnselectAll();
- wxTreeEvent changedEvent(wxEVT_COMMAND_TREE_SEL_CHANGED, this);
+ wxTreeEvent changedEvent(wxEVT_TREE_SEL_CHANGED, this);
changedEvent.m_itemOld = htFocus;
(void)HandleTreeEvent(changedEvent);
}
HTREEITEM htFocus = (HTREEITEM)TreeView_GetSelection(GetHwnd());
- wxTreeEvent changingEvent(wxEVT_COMMAND_TREE_SEL_CHANGING, this);
+ wxTreeEvent changingEvent(wxEVT_TREE_SEL_CHANGING, this);
changingEvent.m_itemOld = htFocus;
if ( IsTreeEventAllowed(changingEvent) )
{
DoSelectChildren(parent);
- wxTreeEvent changedEvent(wxEVT_COMMAND_TREE_SEL_CHANGED, this);
+ wxTreeEvent changedEvent(wxEVT_TREE_SEL_CHANGED, this);
changedEvent.m_itemOld = htFocus;
(void)HandleTreeEvent(changedEvent);
}
if ( HasFlag(wxTR_MULTIPLE) )
{
- wxTreeEvent changingEvent(wxEVT_COMMAND_TREE_SEL_CHANGING, this, item);
+ wxTreeEvent changingEvent(wxEVT_TREE_SEL_CHANGING, this, item);
if ( IsTreeEventAllowed(changingEvent) )
{
SetFocusedItem(item);
}
- wxTreeEvent changedEvent(wxEVT_COMMAND_TREE_SEL_CHANGED,
+ wxTreeEvent changedEvent(wxEVT_TREE_SEL_CHANGED,
this, item);
(void)HandleTreeEvent(changedEvent);
}
// leave itemNew invalid
}
- // in spite of the docs (MSDN Jan 99 edition), we don't seem to receive
- // the notification from the control (i.e. TVN_SELCHANG{ED|ING}), so
- // send them ourselves
-
+ // Recent versions of comctl32.dll send TVN_SELCHANG{ED,ING} events
+ // when we call TreeView_SelectItem() but apparently some old ones did
+ // not so send the events ourselves and ignore those generated by
+ // TreeView_SelectItem() if m_changingSelection is set.
wxTreeEvent
- changingEvent(wxEVT_COMMAND_TREE_SEL_CHANGING, this, itemNew);
+ changingEvent(wxEVT_TREE_SEL_CHANGING, this, itemNew);
changingEvent.SetOldItem(itemOld);
if ( IsTreeEventAllowed(changingEvent) )
{
+ TempSetter set(m_changingSelection);
+
if ( !TreeView_SelectItem(GetHwnd(), HITEM(itemNew)) )
{
wxLogLastError(wxT("TreeView_SelectItem"));
}
else // ok
{
- SetFocusedItem(item);
+ ::SetFocus(GetHwnd(), HITEM(item));
- wxTreeEvent changedEvent(wxEVT_COMMAND_TREE_SEL_CHANGED,
+ wxTreeEvent changedEvent(wxEVT_TREE_SEL_CHANGED,
this, itemNew);
changedEvent.SetOldItem(itemOld);
(void)HandleTreeEvent(changedEvent);
wxTextCtrl *wxTreeCtrl::EditLabel(const wxTreeItemId& item,
wxClassInfo *textControlClass)
{
- wxASSERT( textControlClass->IsKindOf(CLASSINFO(wxTextCtrl)) );
+ wxASSERT( textControlClass->IsKindOf(wxCLASSINFO(wxTextCtrl)) );
DeleteTextCtrl();
wxRect& rect,
bool textOnly) const
{
- RECT rc;
-
// Virtual root items have no bounding rectangle
if ( IS_VIRTUAL_ROOT(item) )
{
return false;
}
- if ( TreeView_GetItemRect(GetHwnd(), HITEM(item),
- &rc, textOnly) )
+ TVGetItemRectParam param;
+
+ if ( wxTreeView_GetItemRect(GetHwnd(), HITEM(item), param, textOnly) )
{
- rect = wxRect(wxPoint(rc.left, rc.top), wxPoint(rc.right, rc.bottom));
+ rect = wxRect(wxPoint(param.rect.left, param.rect.top),
+ wxPoint(param.rect.right, param.rect.bottom));
return true;
}
// may be why as if you don't use the DECLARE_CLASS/IMPLEMENT_CLASS
// combo for your derived wxTreeCtrl if will sort without
// OnCompareItems
- if ( GetClassInfo() == CLASSINFO(wxTreeCtrl) )
+ if ( GetClassInfo() == wxCLASSINFO(wxTreeCtrl) )
{
TreeView_SortChildren(GetHwnd(), HITEM(item), 0);
}
// conjunction with modifiers
if ( (msg->wParam == VK_RETURN) && !wxIsAnyModifierDown() )
{
- // we need VK_RETURN to generate wxEVT_COMMAND_TREE_ITEM_ACTIVATED
+ // we need VK_RETURN to generate wxEVT_TREE_ITEM_ACTIVATED
return false;
}
}
if ( cmd == EN_UPDATE )
{
- wxCommandEvent event(wxEVT_COMMAND_TEXT_UPDATED, id);
+ wxCommandEvent event(wxEVT_TEXT, id);
event.SetEventObject( this );
ProcessCommand(event);
}
if ( vkey != VK_RETURN && bCtrl )
{
- wxTreeEvent changingEvent(wxEVT_COMMAND_TREE_SEL_CHANGING,
+ wxTreeEvent changingEvent(wxEVT_TREE_SEL_CHANGING,
this, htSel);
changingEvent.m_itemOld = htSel;
{
DoToggleItemSelection(wxTreeItemId(htSel));
- wxTreeEvent changedEvent(wxEVT_COMMAND_TREE_SEL_CHANGED,
+ wxTreeEvent changedEvent(wxEVT_TREE_SEL_CHANGED,
this, htSel);
changedEvent.m_itemOld = htSel;
(void)HandleTreeEvent(changedEvent);
if ( count != 1 || HITEM(selections[0]) != htSel )
{
- wxTreeEvent changingEvent(wxEVT_COMMAND_TREE_SEL_CHANGING,
+ wxTreeEvent changingEvent(wxEVT_TREE_SEL_CHANGING,
this, htSel);
changingEvent.m_itemOld = htSel;
DoUnselectAll();
DoSelectItem(wxTreeItemId(htSel));
- wxTreeEvent changedEvent(wxEVT_COMMAND_TREE_SEL_CHANGED,
+ wxTreeEvent changedEvent(wxEVT_TREE_SEL_CHANGED,
this, htSel);
changedEvent.m_itemOld = htSel;
(void)HandleTreeEvent(changedEvent);
break;
}
- wxTreeEvent changingEvent(wxEVT_COMMAND_TREE_SEL_CHANGING,
+ wxTreeEvent changingEvent(wxEVT_TREE_SEL_CHANGING,
this, next);
changingEvent.m_itemOld = htSel;
DoSelectItem(next);
SetFocusedItem(next);
- wxTreeEvent changedEvent(wxEVT_COMMAND_TREE_SEL_CHANGED,
+ wxTreeEvent changedEvent(wxEVT_TREE_SEL_CHANGED,
this, next);
changedEvent.m_itemOld = htSel;
(void)HandleTreeEvent(changedEvent);
if ( bShift && SelectRange(GetHwnd(), HITEM(m_htSelStart), HITEM(next),
SR_UNSELECT_OTHERS | SR_SIMULATE) )
{
- wxTreeEvent changingEvent(wxEVT_COMMAND_TREE_SEL_CHANGING, this, next);
+ wxTreeEvent changingEvent(wxEVT_TREE_SEL_CHANGING, this, next);
changingEvent.m_itemOld = htSel;
if ( IsTreeEventAllowed(changingEvent) )
SelectRange(GetHwnd(), HITEM(m_htSelStart), HITEM(next),
SR_UNSELECT_OTHERS);
- wxTreeEvent changedEvent(wxEVT_COMMAND_TREE_SEL_CHANGED, this, next);
+ wxTreeEvent changedEvent(wxEVT_TREE_SEL_CHANGED, this, next);
changedEvent.m_itemOld = htSel;
(void)HandleTreeEvent(changedEvent);
}
if ( next.IsOk() && !IsHiddenRoot(next) )
{
- wxTreeEvent changingEvent(wxEVT_COMMAND_TREE_SEL_CHANGING,
+ wxTreeEvent changingEvent(wxEVT_TREE_SEL_CHANGING,
this, next);
changingEvent.m_itemOld = htSel;
DoSelectItem(next);
SetFocusedItem(next);
- wxTreeEvent changedEvent(wxEVT_COMMAND_TREE_SEL_CHANGED,
+ wxTreeEvent changedEvent(wxEVT_TREE_SEL_CHANGED,
this, next);
changedEvent.m_itemOld = htSel;
(void)HandleTreeEvent(changedEvent);
{
wxTreeItemId next = TreeView_GetChild(GetHwnd(), htSel);
- wxTreeEvent changingEvent(wxEVT_COMMAND_TREE_SEL_CHANGING, this, next);
+ wxTreeEvent changingEvent(wxEVT_TREE_SEL_CHANGING, this, next);
changingEvent.m_itemOld = htSel;
if ( IsTreeEventAllowed(changingEvent) )
DoSelectItem(next);
SetFocusedItem(next);
- wxTreeEvent changedEvent(wxEVT_COMMAND_TREE_SEL_CHANGED, this, next);
+ wxTreeEvent changedEvent(wxEVT_TREE_SEL_CHANGED, this, next);
changedEvent.m_itemOld = htSel;
(void)HandleTreeEvent(changedEvent);
}
HITEM(m_htSelStart), HITEM(next),
SR_UNSELECT_OTHERS | SR_SIMULATE) )
{
- wxTreeEvent changingEvent(wxEVT_COMMAND_TREE_SEL_CHANGING,
+ wxTreeEvent changingEvent(wxEVT_TREE_SEL_CHANGING,
this, next);
changingEvent.m_itemOld = htSel;
SR_UNSELECT_OTHERS);
SetFocusedItem(next);
- wxTreeEvent changedEvent(wxEVT_COMMAND_TREE_SEL_CHANGED,
+ wxTreeEvent changedEvent(wxEVT_TREE_SEL_CHANGED,
this, next);
changedEvent.m_itemOld = htSel;
(void)HandleTreeEvent(changedEvent);
}
else // no Shift
{
- wxTreeEvent changingEvent(wxEVT_COMMAND_TREE_SEL_CHANGING,
+ wxTreeEvent changingEvent(wxEVT_TREE_SEL_CHANGING,
this, next);
changingEvent.m_itemOld = htSel;
DoSelectItem(next);
SetFocusedItem(next);
- wxTreeEvent changedEvent(wxEVT_COMMAND_TREE_SEL_CHANGED,
+ wxTreeEvent changedEvent(wxEVT_TREE_SEL_CHANGED,
this, next);
changedEvent.m_itemOld = htSel;
(void)HandleTreeEvent(changedEvent);
next = nextTemp;
}
- wxTreeEvent changingEvent(wxEVT_COMMAND_TREE_SEL_CHANGING,
+ wxTreeEvent changingEvent(wxEVT_TREE_SEL_CHANGING,
this, next);
changingEvent.m_itemOld = htSel;
DoSelectItem(next);
SetFocusedItem(next);
- wxTreeEvent changedEvent(wxEVT_COMMAND_TREE_SEL_CHANGED,
+ wxTreeEvent changedEvent(wxEVT_TREE_SEL_CHANGED,
this, next);
changedEvent.m_itemOld = htSel;
(void)HandleTreeEvent(changedEvent);
bool wxTreeCtrl::MSWHandleTreeKeyDownEvent(WXWPARAM wParam, WXLPARAM lParam)
{
- wxTreeEvent keyEvent(wxEVT_COMMAND_TREE_KEY_DOWN, this);
-
- int keyCode = wxCharCodeMSWToWX(wParam);
-
- if ( !keyCode )
- {
- // wxCharCodeMSWToWX() returns 0 to indicate that this is a
- // simple ASCII key
- keyCode = wParam;
- }
-
- keyEvent.m_evtKey = CreateKeyEvent(wxEVT_KEY_DOWN, keyCode,
- lParam, wParam);
+ wxTreeEvent keyEvent(wxEVT_TREE_KEY_DOWN, this);
+ keyEvent.m_evtKey = CreateKeyEvent(wxEVT_KEY_DOWN, wParam, lParam);
bool processed = HandleTreeEvent(keyEvent);
const HTREEITEM htSel = (HTREEITEM)TreeView_GetSelection(GetHwnd());
if ( htSel )
{
- wxTreeEvent activatedEvent(wxEVT_COMMAND_TREE_ITEM_ACTIVATED,
+ wxTreeEvent activatedEvent(wxEVT_TREE_ITEM_ACTIVATED,
this, htSel);
(void)HandleTreeEvent(activatedEvent);
}
}
// create the event
- wxTreeEvent event(wxEVT_COMMAND_TREE_ITEM_MENU, this, item);
+ if ( item.IsOk() )
+ {
+ wxTreeEvent event(wxEVT_TREE_ITEM_MENU, this, item);
- event.m_pointDrag = pt;
+ event.m_pointDrag = pt;
- if ( HandleTreeEvent(event) )
- processed = true;
- //else: continue with generating wxEVT_CONTEXT_MENU in base class code
+ if ( HandleTreeEvent(event) )
+ processed = true;
+ //else: continue with generating wxEVT_CONTEXT_MENU in base class code
+ }
}
else if ( (nMsg >= WM_MOUSEFIRST) && (nMsg <= WM_MOUSELAST) )
{
break;
}
- wxTreeEvent changingEvent(wxEVT_COMMAND_TREE_SEL_CHANGING,
+ wxTreeEvent changingEvent(wxEVT_TREE_SEL_CHANGING,
this, htItem);
changingEvent.m_itemOld = htOldItem;
// reset on any click without Shift
m_htSelStart.Unset();
- wxTreeEvent changedEvent(wxEVT_COMMAND_TREE_SEL_CHANGED,
+ wxTreeEvent changedEvent(wxEVT_TREE_SEL_CHANGED,
this, htItem);
changedEvent.m_itemOld = htOldItem;
(void)HandleTreeEvent(changedEvent);
if ( willChange )
{
- wxTreeEvent changingEvent(wxEVT_COMMAND_TREE_SEL_CHANGING,
+ wxTreeEvent changingEvent(wxEVT_TREE_SEL_CHANGING,
this, htItem);
changingEvent.m_itemOld = htOldItem;
SetFocusedItem(wxTreeItemId(htItem));
- wxTreeEvent changedEvent(wxEVT_COMMAND_TREE_SEL_CHANGED,
+ wxTreeEvent changedEvent(wxEVT_TREE_SEL_CHANGED,
this, htItem);
changedEvent.m_itemOld = htOldItem;
(void)HandleTreeEvent(changedEvent);
// multiple drag and drop to work.
if ( !IsItemSelected(GetHwnd(), htItem))
{
- wxTreeEvent changingEvent(wxEVT_COMMAND_TREE_SEL_CHANGING,
+ wxTreeEvent changingEvent(wxEVT_TREE_SEL_CHANGING,
this, htItem);
changingEvent.m_itemOld = htOldItem;
DoSelectItem(wxTreeItemId(htItem));
SetFocusedItem(wxTreeItemId(htItem));
- wxTreeEvent changedEvent(wxEVT_COMMAND_TREE_SEL_CHANGED,
+ wxTreeEvent changedEvent(wxEVT_TREE_SEL_CHANGED,
this, htItem);
changedEvent.m_itemOld = htOldItem;
(void)HandleTreeEvent(changedEvent);
// click if needed
if ( processed )
{
- int htFlags = 0;
- wxTreeItemId item = HitTest(wxPoint(x, y), htFlags);
-
- if ( htFlags & wxTREE_HITTEST_ONITEMSTATEICON )
+ if ( tvht.flags & TVHT_ONITEMSTATEICON )
{
m_triggerStateImageClick = true;
}
// confusing, so override this default behaviour
if ( !IsItemSelected(GetHwnd(), htItem) )
{
- wxTreeEvent changingEvent(wxEVT_COMMAND_TREE_SEL_CHANGING,
+ wxTreeEvent changingEvent(wxEVT_TREE_SEL_CHANGING,
this, htItem);
changingEvent.m_itemOld = htOldItem;
DoSelectItem(wxTreeItemId(htItem));
SetFocusedItem(wxTreeItemId(htItem));
- wxTreeEvent changedEvent(wxEVT_COMMAND_TREE_SEL_CHANGED,
+ wxTreeEvent changedEvent(wxEVT_TREE_SEL_CHANGED,
this, htItem);
changedEvent.m_itemOld = htOldItem;
(void)HandleTreeEvent(changedEvent);
{
m_mouseUpDeselect = false;
- wxTreeEvent changingEvent(wxEVT_COMMAND_TREE_SEL_CHANGING,
+ wxTreeEvent changingEvent(wxEVT_TREE_SEL_CHANGING,
this, htItem);
changingEvent.m_itemOld = htOldItem;
DoSelectItem(wxTreeItemId(htItem));
SetFocusedItem(wxTreeItemId(htItem));
- wxTreeEvent changedEvent(wxEVT_COMMAND_TREE_SEL_CHANGED,
+ wxTreeEvent changedEvent(wxEVT_TREE_SEL_CHANGED,
this, htItem);
changedEvent.m_itemOld = htOldItem;
(void)HandleTreeEvent(changedEvent);
{
if ( tvht.flags & TVHT_ONITEMSTATEICON )
{
- wxTreeEvent event(wxEVT_COMMAND_TREE_STATE_IMAGE_CLICK,
+ wxTreeEvent event(wxEVT_TREE_STATE_IMAGE_CLICK,
this, htItem);
(void)HandleTreeEvent(event);
wxDELETE(m_dragImage);
// generate the drag end event
- wxTreeEvent event(wxEVT_COMMAND_TREE_END_DRAG,
+ wxTreeEvent event(wxEVT_TREE_END_DRAG,
this, htItem);
event.m_pointDrag = wxPoint(x, y);
(void)HandleTreeEvent(event);
// do it for the other items itself - help it
wxArrayTreeItemIds selections;
size_t count = GetSelections(selections);
- RECT rect;
+ TVGetItemRectParam param;
for ( size_t n = 0; n < count; n++ )
{
// TreeView_GetItemRect() will return false if item is not
// visible, which may happen perfectly well
- if ( TreeView_GetItemRect(GetHwnd(), HITEM(selections[n]),
- &rect, TRUE) )
+ if ( wxTreeView_GetItemRect(GetHwnd(), HITEM(selections[n]),
+ param, TRUE) )
{
- ::InvalidateRect(GetHwnd(), &rect, FALSE);
+ ::InvalidateRect(GetHwnd(), ¶m.rect, FALSE);
}
}
}
switch ( hdr->code )
{
case TVN_BEGINDRAG:
- eventType = wxEVT_COMMAND_TREE_BEGIN_DRAG;
+ eventType = wxEVT_TREE_BEGIN_DRAG;
// fall through
case TVN_BEGINRDRAG:
{
if ( eventType == wxEVT_NULL )
- eventType = wxEVT_COMMAND_TREE_BEGIN_RDRAG;
+ eventType = wxEVT_TREE_BEGIN_RDRAG;
//else: left drag, already set above
NM_TREEVIEW *tv = (NM_TREEVIEW *)lParam;
case TVN_BEGINLABELEDIT:
{
- eventType = wxEVT_COMMAND_TREE_BEGIN_LABEL_EDIT;
+ eventType = wxEVT_TREE_BEGIN_LABEL_EDIT;
TV_DISPINFO *info = (TV_DISPINFO *)lParam;
// although the user event handler may still veto it, it is
case TVN_DELETEITEM:
{
- eventType = wxEVT_COMMAND_TREE_DELETE_ITEM;
+ eventType = wxEVT_TREE_DELETE_ITEM;
NM_TREEVIEW *tv = (NM_TREEVIEW *)lParam;
event.m_item = tv->itemOld.hItem;
case TVN_ENDLABELEDIT:
{
- eventType = wxEVT_COMMAND_TREE_END_LABEL_EDIT;
+ eventType = wxEVT_TREE_END_LABEL_EDIT;
TV_DISPINFO *info = (TV_DISPINFO *)lParam;
event.m_item = info->item.hItem;
#ifdef TVN_GETINFOTIP
case TVN_GETINFOTIP:
{
- eventType = wxEVT_COMMAND_TREE_ITEM_GETTOOLTIP;
+ eventType = wxEVT_TREE_ITEM_GETTOOLTIP;
NMTVGETINFOTIP *info = (NMTVGETINFOTIP*)lParam;
// Which item are we trying to get a tooltip for?
#endif // !__WXWINCE__
case TVN_GETDISPINFO:
- eventType = wxEVT_COMMAND_TREE_GET_INFO;
+ eventType = wxEVT_TREE_GET_INFO;
// fall through
case TVN_SETDISPINFO:
{
if ( eventType == wxEVT_NULL )
- eventType = wxEVT_COMMAND_TREE_SET_INFO;
+ eventType = wxEVT_TREE_SET_INFO;
//else: get, already set above
TV_DISPINFO *info = (TV_DISPINFO *)lParam;
// the wrong items are deselected.
// Fortunately, Vista provides a new notification, TVN_ITEMCHANGING
- // that can be used to regulate this incorrect behavior. The
+ // that can be used to regulate this incorrect behaviour. The
// following messages will allow only the unlocked item's selection
// state to change
// we have to handle both messages:
case TVN_SELCHANGEDA:
case TVN_SELCHANGEDW:
- if ( !HasFlag(wxTR_MULTIPLE) || !m_changingSelection )
+ if ( !m_changingSelection )
{
- eventType = wxEVT_COMMAND_TREE_SEL_CHANGED;
+ eventType = wxEVT_TREE_SEL_CHANGED;
}
// fall through
case TVN_SELCHANGINGA:
case TVN_SELCHANGINGW:
- if ( !HasFlag(wxTR_MULTIPLE) || !m_changingSelection )
+ if ( !m_changingSelection )
{
if ( eventType == wxEVT_NULL )
- eventType = wxEVT_COMMAND_TREE_SEL_CHANGING;
+ eventType = wxEVT_TREE_SEL_CHANGING;
//else: already set above
if (hdr->code == TVN_SELCHANGINGW ||
//
// to avoid such surprises, we force the generation of focus events
// now, before we generate the selection change ones
- SetFocus();
+ if ( !m_changingSelection && !m_isBeingDeleted )
+ SetFocus();
break;
// instead of explicitly checking for _WIN32_IE, check if the
// required symbols are available in the headers
-#if defined(CDDS_PREPAINT) && !wxUSE_COMCTL32_SAFELY
+#if defined(CDDS_PREPAINT)
case NM_CUSTOMDRAW:
{
LPNMTVCUSTOMDRAW lptvcd = (LPNMTVCUSTOMDRAW)lParam;
{
wxLoadedDLL dllComCtl32(wxT("comctl32.dll"));
if ( dllComCtl32.IsLoaded() )
+ {
wxDL_INIT_FUNC(s_pfn, ImageList_Copy, dllComCtl32);
+ loaded = true;
+ }
}
if ( !s_pfnImageList_Copy )
if ( htFlags & wxTREE_HITTEST_ONITEMSTATEICON )
{
event.m_item = item;
- eventType = wxEVT_COMMAND_TREE_STATE_IMAGE_CLICK;
+ eventType = wxEVT_TREE_STATE_IMAGE_CLICK;
}
break;
case NM_RCLICK:
{
TV_HITTESTINFO tvhti;
- ::GetCursorPos(&tvhti.pt);
+ wxGetCursorPosMSW(&tvhti.pt);
::ScreenToClient(GetHwnd(), &tvhti.pt);
if ( TreeView_HitTest(GetHwnd(), &tvhti) )
{
{
event.m_item = tvhti.hItem;
eventType = (int)hdr->code == NM_DBLCLK
- ? wxEVT_COMMAND_TREE_ITEM_ACTIVATED
- : wxEVT_COMMAND_TREE_ITEM_RIGHT_CLICK;
+ ? wxEVT_TREE_ITEM_ACTIVATED
+ : wxEVT_TREE_ITEM_RIGHT_CLICK;
event.m_pointDrag.x = tvhti.pt.x;
event.m_pointDrag.y = tvhti.pt.y;
DoSetItem(&tvItem);
}
+// ----------------------------------------------------------------------------
+// Update locking.
+// ----------------------------------------------------------------------------
+
+// Using WM_SETREDRAW with the native control is a bad idea as it's broken in
+// some Windows versions (see http://support.microsoft.com/kb/130611) and
+// doesn't seem to do anything in other ones (e.g. under Windows 7 the tree
+// control keeps updating its scrollbars while the items are added to it,
+// resulting in horrible flicker when adding even a couple of dozen items).
+// So we resize it to the smallest possible size instead of freezing -- this
+// still flickers, but actually not as badly as it would if we didn't do it.
+
+void wxTreeCtrl::DoFreeze()
+{
+ if ( IsShown() )
+ {
+ RECT rc;
+ ::GetWindowRect(GetHwnd(), &rc);
+ m_thawnSize = wxRectFromRECT(rc).GetSize();
+
+ ::SetWindowPos(GetHwnd(), 0, 0, 0, 1, 1,
+ SWP_NOMOVE | SWP_NOZORDER | SWP_NOREDRAW | SWP_NOACTIVATE);
+ }
+}
+
+void wxTreeCtrl::DoThaw()
+{
+ if ( IsShown() )
+ {
+ if ( m_thawnSize != wxDefaultSize )
+ {
+ ::SetWindowPos(GetHwnd(), 0, 0, 0, m_thawnSize.x, m_thawnSize.y,
+ SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE);
+ }
+ }
+}
+
+// We also need to override DoSetSize() to ensure that m_thawnSize is reset if
+// the window is resized while being frozen -- in this case, we need to avoid
+// resizing it back to its original, pre-freeze, size when it's thawed.
+void wxTreeCtrl::DoSetSize(int x, int y, int width, int height, int sizeFlags)
+{
+ m_thawnSize = wxDefaultSize;
+
+ wxTreeCtrlBase::DoSetSize(x, y, width, height, sizeFlags);
+}
+
#endif // wxUSE_TREECTRL