treectrl.cpp
来自「A*算法 A*算法 A*算法 A*算法A*算法A*算法」· C++ 代码 · 共 2,196 行 · 第 1/5 页
CPP
2,196 行
text, image, selectedImage, data);
}
wxTreeItemId wxTreeCtrl::PrependItem(const wxTreeItemId& parent,
const wxString& text,
int image, int selectedImage,
wxTreeItemData *data)
{
return DoInsertItem(parent, TVI_FIRST,
text, image, selectedImage, data);
}
wxTreeItemId wxTreeCtrl::InsertItem(const wxTreeItemId& parent,
const wxTreeItemId& idPrevious,
const wxString& text,
int image, int selectedImage,
wxTreeItemData *data)
{
return DoInsertItem(parent, idPrevious, text, image, selectedImage, data);
}
wxTreeItemId wxTreeCtrl::InsertItem(const wxTreeItemId& parent,
size_t index,
const wxString& text,
int image, int selectedImage,
wxTreeItemData *data)
{
// find the item from index
wxTreeItemIdValue cookie;
wxTreeItemId idPrev, idCur = GetFirstChild(parent, cookie);
while ( index != 0 && idCur.IsOk() )
{
index--;
idPrev = idCur;
idCur = GetNextChild(parent, cookie);
}
// assert, not check: if the index is invalid, we will append the item
// to the end
wxASSERT_MSG( index == 0, _T("bad index in wxTreeCtrl::InsertItem") );
return DoInsertItem(parent, idPrev, text, image, selectedImage, data);
}
wxTreeItemId wxTreeCtrl::AppendItem(const wxTreeItemId& parent,
const wxString& text,
int image, int selectedImage,
wxTreeItemData *data)
{
return DoInsertItem(parent, TVI_LAST,
text, image, selectedImage, data);
}
void wxTreeCtrl::Delete(const wxTreeItemId& item)
{
if ( !TreeView_DeleteItem(GetHwnd(), HITEM(item)) )
{
wxLogLastError(wxT("TreeView_DeleteItem"));
}
}
// delete all children (but don't delete the item itself)
void wxTreeCtrl::DeleteChildren(const wxTreeItemId& item)
{
wxTreeItemIdValue cookie;
wxArrayTreeItemIds children;
wxTreeItemId child = GetFirstChild(item, cookie);
while ( child.IsOk() )
{
children.Add(child);
child = GetNextChild(item, cookie);
}
size_t nCount = children.Count();
for ( size_t n = 0; n < nCount; n++ )
{
if ( !TreeView_DeleteItem(GetHwnd(), HITEM_PTR(children[n])) )
{
wxLogLastError(wxT("TreeView_DeleteItem"));
}
}
}
void wxTreeCtrl::DeleteAllItems()
{
// delete the "virtual" root item.
if ( GET_VIRTUAL_ROOT() )
{
delete GET_VIRTUAL_ROOT();
m_pVirtualRoot = NULL;
}
// and all the real items
if ( !TreeView_DeleteAllItems(GetHwnd()) )
{
wxLogLastError(wxT("TreeView_DeleteAllItems"));
}
}
void wxTreeCtrl::DoExpand(const wxTreeItemId& item, int flag)
{
wxASSERT_MSG( flag == TVE_COLLAPSE ||
flag == (TVE_COLLAPSE | TVE_COLLAPSERESET) ||
flag == TVE_EXPAND ||
flag == TVE_TOGGLE,
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),
wxT("Can't expand/collapse hidden root node!") )
// TreeView_Expand doesn't send TVN_ITEMEXPAND(ING) messages, so we must
// emulate them. This behaviour has changed slightly with comctl32.dll
// v 4.70 - now it does send them but only the first time. To maintain
// compatible behaviour and also in order to not have surprises with the
// future versions, don't rely on this and still do everything ourselves.
// To avoid that the messages be sent twice when the item is expanded for
// the first time we must clear TVIS_EXPANDEDONCE style manually.
wxTreeViewItem tvItem(item, TVIF_STATE, TVIS_EXPANDEDONCE);
tvItem.state = 0;
DoSetItem(&tvItem);
if ( TreeView_Expand(GetHwnd(), HITEM(item), flag) != 0 )
{
wxTreeEvent event(wxEVT_NULL, m_windowId);
event.m_item = item;
event.SetEventObject(this);
// note that the {EXPAND|COLLAPS}ING event is sent by TreeView_Expand()
// itself
event.SetEventType(gs_expandEvents[IsExpanded(item) ? IDX_EXPAND
: IDX_COLLAPSE]
[IDX_DONE]);
(void)GetEventHandler()->ProcessEvent(event);
}
//else: change didn't took place, so do nothing at all
}
void wxTreeCtrl::Expand(const wxTreeItemId& item)
{
DoExpand(item, TVE_EXPAND);
}
void wxTreeCtrl::Collapse(const wxTreeItemId& item)
{
DoExpand(item, TVE_COLLAPSE);
}
void wxTreeCtrl::CollapseAndReset(const wxTreeItemId& item)
{
DoExpand(item, TVE_COLLAPSE | TVE_COLLAPSERESET);
}
void wxTreeCtrl::Toggle(const wxTreeItemId& item)
{
DoExpand(item, TVE_TOGGLE);
}
#if WXWIN_COMPATIBILITY_2_4
void wxTreeCtrl::ExpandItem(const wxTreeItemId& item, int action)
{
DoExpand(item, action);
}
#endif
void wxTreeCtrl::Unselect()
{
wxASSERT_MSG( !(m_windowStyle & wxTR_MULTIPLE),
wxT("doesn't make sense, may be you want UnselectAll()?") );
// just remove the selection
SelectItem(wxTreeItemId());
}
void wxTreeCtrl::UnselectAll()
{
if ( m_windowStyle & wxTR_MULTIPLE )
{
wxArrayTreeItemIds selections;
size_t count = GetSelections(selections);
for ( size_t n = 0; n < count; n++ )
{
#if wxUSE_CHECKBOXES_IN_MULTI_SEL_TREE
SetItemCheck(HITEM_PTR(selections[n]), false);
#else // !wxUSE_CHECKBOXES_IN_MULTI_SEL_TREE
::UnselectItem(GetHwnd(), HITEM_PTR(selections[n]));
#endif // wxUSE_CHECKBOXES_IN_MULTI_SEL_TREE/!wxUSE_CHECKBOXES_IN_MULTI_SEL_TREE
}
m_htSelStart.Unset();
}
else
{
// just remove the selection
Unselect();
}
}
void wxTreeCtrl::SelectItem(const wxTreeItemId& item, bool select)
{
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
{
wxASSERT_MSG( select,
_T("SelectItem(false) works only for multiselect") );
// inspite 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
wxTreeEvent event(wxEVT_NULL, m_windowId);
event.m_item = item;
event.SetEventObject(this);
event.SetEventType(wxEVT_COMMAND_TREE_SEL_CHANGING);
if ( !GetEventHandler()->ProcessEvent(event) || event.IsAllowed() )
{
if ( !TreeView_SelectItem(GetHwnd(), HITEM(item)) )
{
wxLogLastError(wxT("TreeView_SelectItem"));
}
else // ok
{
event.SetEventType(wxEVT_COMMAND_TREE_SEL_CHANGED);
(void)GetEventHandler()->ProcessEvent(event);
}
}
//else: program vetoed the change
}
}
void wxTreeCtrl::UnselectItem(const wxTreeItemId& item)
{
SelectItem(item, false);
}
void wxTreeCtrl::ToggleItemSelection(const wxTreeItemId& item)
{
SelectItem(item, !IsSelected(item));
}
void wxTreeCtrl::EnsureVisible(const wxTreeItemId& item)
{
// no error return
TreeView_EnsureVisible(GetHwnd(), HITEM(item));
}
void wxTreeCtrl::ScrollTo(const wxTreeItemId& item)
{
if ( !TreeView_SelectSetFirstVisible(GetHwnd(), HITEM(item)) )
{
wxLogLastError(wxT("TreeView_SelectSetFirstVisible"));
}
}
wxTextCtrl *wxTreeCtrl::GetEditControl() const
{
return m_textCtrl;
}
void wxTreeCtrl::DeleteTextCtrl()
{
if ( m_textCtrl )
{
// the HWND corresponding to this control is deleted by the tree
// control itself and we don't know when exactly this happens, so check
// if the window still exists before calling UnsubclassWin()
if ( !::IsWindow(GetHwndOf(m_textCtrl)) )
{
m_textCtrl->SetHWND(0);
}
m_textCtrl->UnsubclassWin();
m_textCtrl->SetHWND(0);
delete m_textCtrl;
m_textCtrl = NULL;
m_idEdited.Unset();
}
}
wxTextCtrl* wxTreeCtrl::EditLabel(const wxTreeItemId& item,
wxClassInfo* textControlClass)
{
wxASSERT( textControlClass->IsKindOf(CLASSINFO(wxTextCtrl)) );
DeleteTextCtrl();
m_idEdited = item;
m_textCtrl = (wxTextCtrl *)textControlClass->CreateObject();
HWND hWnd = (HWND) TreeView_EditLabel(GetHwnd(), HITEM(item));
// this is not an error - the TVN_BEGINLABELEDIT handler might have
// returned false
if ( !hWnd )
{
delete m_textCtrl;
m_textCtrl = NULL;
return NULL;
}
// textctrl is subclassed in MSWOnNotify
return m_textCtrl;
}
// End label editing, optionally cancelling the edit
void wxTreeCtrl::DoEndEditLabel(bool discardChanges)
{
TreeView_EndEditLabelNow(GetHwnd(), discardChanges);
DeleteTextCtrl();
}
wxTreeItemId wxTreeCtrl::HitTest(const wxPoint& point, int& flags)
{
TV_HITTESTINFO hitTestInfo;
hitTestInfo.pt.x = (int)point.x;
hitTestInfo.pt.y = (int)point.y;
(void) TreeView_HitTest(GetHwnd(), &hitTestInfo);
flags = 0;
// avoid repetition
#define TRANSLATE_FLAG(flag) if ( hitTestInfo.flags & TVHT_##flag ) \
flags |= wxTREE_HITTEST_##flag
TRANSLATE_FLAG(ABOVE);
TRANSLATE_FLAG(BELOW);
TRANSLATE_FLAG(NOWHERE);
TRANSLATE_FLAG(ONITEMBUTTON);
TRANSLATE_FLAG(ONITEMICON);
TRANSLATE_FLAG(ONITEMINDENT);
TRANSLATE_FLAG(ONITEMLABEL);
TRANSLATE_FLAG(ONITEMRIGHT);
TRANSLATE_FLAG(ONITEMSTATEICON);
TRANSLATE_FLAG(TOLEFT);
TRANSLATE_FLAG(TORIGHT);
#undef TRANSLATE_FLAG
return wxTreeItemId(hitTestInfo.hItem);
}
bool wxTreeCtrl::GetBoundingRect(const wxTreeItemId& item,
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) )
{
rect = wxRect(wxPoint(rc.left, rc.top), wxPoint(rc.right, rc.bottom));
return true;
}
else
{
// couldn't retrieve rect: for example, item isn't visible
return false;
}
}
// ----------------------------------------------------------------------------
// sorting stuff
// ----------------------------------------------------------------------------
// this is just a tiny namespace which is friend to wxTreeCtrl and so can use
// functions such as IsDataIndirect()
class wxTreeSortHelper
{
public:
static int CALLBACK Compare(LPARAM data1, LPARAM data2, LPARAM tree);
private:
static wxTreeItemId GetIdFromData(wxTreeCtrl *tree, LPARAM item)
{
wxTreeItemData *data = (wxTreeItemData *)item;
if ( tree->IsDataIndirect(data) )
{
data = ((wxTreeItemIndirectData *)data)->GetData();
}
return data->GetId();
}
};
int CALLBACK wxTreeSortHelper::Compare(LPARAM pItem1,
LPARAM pItem2,
LPARAM htree)
{
wxCHECK_MSG( pItem1 && pItem2, 0,
wxT("sorting tree without data doesn't make sense") );
wxTreeCtrl *tree = (wxTreeCtrl *)htree;
return tree->OnCompareItems(GetIdFromData(tree, pItem1),
GetIdFromData(tree, pItem2));
}
int wxTreeCtrl::OnCompareItems(const wxTreeItemId& item1,
const wxTreeItemId& item2)
{
return wxStrcmp(GetItemText(item1), GetItemText(item2));
}
void wxTreeCtrl::SortChildren(const wxTreeItemId& item)
{
wxCHECK_RET( item.IsOk(), wxT("invalid tree item") );
// rely on the fact that TreeView_SortChildren does the same thing as our
// default behaviour, i.e. sorts items alphabetically and so call it
// directly if we're n
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?