+ if ( !MSWCreateControl(WC_TREEVIEW, wstyle) )
+ 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
+
+
+ // VZ: this is some experimental code which may be used to get the
+ // TVS_CHECKBOXES style functionality for comctl32.dll < 4.71.
+ // AFAIK, the standard DLL does about the same thing anyhow.
+#if 0
+ if ( m_windowStyle & wxTR_MULTIPLE )
+ {
+ wxBitmap bmp;
+
+ // create the DC compatible with the current screen
+ HDC hdcMem = CreateCompatibleDC(NULL);
+
+ // create a mono bitmap of the standard size
+ int x = GetSystemMetrics(SM_CXMENUCHECK);
+ int y = GetSystemMetrics(SM_CYMENUCHECK);
+ wxImageList imagelistCheckboxes(x, y, false, 2);
+ HBITMAP hbmpCheck = CreateBitmap(x, y, // bitmap size
+ 1, // # of color planes
+ 1, // # bits needed for one pixel
+ 0); // array containing colour data
+ SelectObject(hdcMem, hbmpCheck);
+
+ // then draw a check mark into it
+ RECT rect = { 0, 0, x, y };
+ if ( !::DrawFrameControl(hdcMem, &rect,
+ DFC_BUTTON,
+ DFCS_BUTTONCHECK | DFCS_CHECKED) )
+ {
+ wxLogLastError(wxT("DrawFrameControl(check)"));
+ }
+
+ bmp.SetHBITMAP((WXHBITMAP)hbmpCheck);
+ imagelistCheckboxes.Add(bmp);
+
+ if ( !::DrawFrameControl(hdcMem, &rect,
+ DFC_BUTTON,
+ DFCS_BUTTONCHECK) )
+ {
+ wxLogLastError(wxT("DrawFrameControl(uncheck)"));
+ }
+
+ bmp.SetHBITMAP((WXHBITMAP)hbmpCheck);
+ imagelistCheckboxes.Add(bmp);
+
+ // clean up
+ ::DeleteDC(hdcMem);
+
+ // set the imagelist
+ SetStateImageList(&imagelistCheckboxes);
+ }
+#endif // 0
+
+ SetSize(pos.x, pos.y, size.x, size.y);
+
+ return true;
+}
+
+wxTreeCtrl::~wxTreeCtrl()
+{
+ // delete any attributes
+ if ( m_hasAnyAttr )
+ {
+ WX_CLEAR_HASH_MAP(wxMapTreeAttr, m_attrs);
+
+ // prevent TVN_DELETEITEM handler from deleting the attributes again!
+ m_hasAnyAttr = false;
+ }
+
+ DeleteTextCtrl();
+
+ // delete user data to prevent memory leaks
+ // also deletes hidden root node storage.
+ DeleteAllItems();
+
+ if (m_ownsImageListNormal) delete m_imageListNormal;
+ if (m_ownsImageListState) delete m_imageListState;
+}
+
+// ----------------------------------------------------------------------------
+// accessors
+// ----------------------------------------------------------------------------
+
+// simple wrappers which add error checking in debug mode
+
+bool wxTreeCtrl::DoGetItem(wxTreeViewItem* tvItem) const
+{
+ wxCHECK_MSG( tvItem->hItem != TVI_ROOT, false,
+ _T("can't retrieve virtual root item") );
+
+ if ( !TreeView_GetItem(GetHwnd(), tvItem) )
+ {
+ wxLogLastError(wxT("TreeView_GetItem"));
+
+ return false;
+ }
+
+ return true;
+}
+
+void wxTreeCtrl::DoSetItem(wxTreeViewItem* tvItem)
+{
+ if ( TreeView_SetItem(GetHwnd(), tvItem) == -1 )
+ {
+ wxLogLastError(wxT("TreeView_SetItem"));
+ }
+}
+
+size_t wxTreeCtrl::GetCount() const
+{
+ return (size_t)TreeView_GetCount(GetHwnd());
+}
+
+unsigned int wxTreeCtrl::GetIndent() const
+{
+ return TreeView_GetIndent(GetHwnd());
+}
+
+void wxTreeCtrl::SetIndent(unsigned int indent)
+{
+ TreeView_SetIndent(GetHwnd(), indent);
+}
+
+wxImageList *wxTreeCtrl::GetImageList() const
+{
+ return m_imageListNormal;
+}
+
+wxImageList *wxTreeCtrl::GetStateImageList() const
+{
+ return m_imageListState;
+}
+
+void wxTreeCtrl::SetAnyImageList(wxImageList *imageList, int which)
+{
+ // no error return
+ TreeView_SetImageList(GetHwnd(),
+ imageList ? imageList->GetHIMAGELIST() : 0,
+ which);
+}
+
+void wxTreeCtrl::SetImageList(wxImageList *imageList)
+{
+ if (m_ownsImageListNormal)
+ delete m_imageListNormal;
+
+ SetAnyImageList(m_imageListNormal = imageList, TVSIL_NORMAL);
+ m_ownsImageListNormal = false;
+}
+
+void wxTreeCtrl::SetStateImageList(wxImageList *imageList)
+{
+ if (m_ownsImageListState) delete m_imageListState;
+ SetAnyImageList(m_imageListState = imageList, TVSIL_STATE);
+ m_ownsImageListState = false;
+}
+
+void wxTreeCtrl::AssignImageList(wxImageList *imageList)
+{
+ SetImageList(imageList);
+ m_ownsImageListNormal = true;
+}
+
+void wxTreeCtrl::AssignStateImageList(wxImageList *imageList)
+{
+ SetStateImageList(imageList);
+ m_ownsImageListState = true;
+}
+
+size_t wxTreeCtrl::GetChildrenCount(const wxTreeItemId& item,
+ bool recursively) const
+{
+ TraverseCounter counter(this, item, recursively);
+
+ return counter.GetCount() - 1;
+}
+
+// ----------------------------------------------------------------------------
+// control colours
+// ----------------------------------------------------------------------------
+
+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;
+}
+
+// ----------------------------------------------------------------------------
+// Item access
+// ----------------------------------------------------------------------------
+
+wxString wxTreeCtrl::GetItemText(const wxTreeItemId& item) const
+{
+ wxChar buf[512]; // the size is arbitrary...
+
+ wxTreeViewItem tvItem(item, TVIF_TEXT);
+ tvItem.pszText = buf;
+ tvItem.cchTextMax = WXSIZEOF(buf);
+ if ( !DoGetItem(&tvItem) )
+ {
+ // don't return some garbage which was on stack, but an empty string
+ buf[0] = wxT('\0');
+ }
+
+ return wxString(buf);
+}
+
+void wxTreeCtrl::SetItemText(const wxTreeItemId& item, const wxString& text)
+{
+ if ( IS_VIRTUAL_ROOT(item) )
+ return;
+
+ wxTreeViewItem tvItem(item, TVIF_TEXT);
+ tvItem.pszText = (wxChar *)text.c_str(); // conversion is ok
+ DoSetItem(&tvItem);
+
+ // when setting the text of the item being edited, the text control should
+ // be updated to reflect the new text as well, otherwise calling
+ // SetItemText() in the OnBeginLabelEdit() handler doesn't have any effect
+ //
+ // don't use GetEditControl() here because m_textCtrl is not set yet
+ HWND hwndEdit = TreeView_GetEditControl(GetHwnd());
+ if ( hwndEdit )
+ {
+ if ( item == GetSelection() )
+ {
+ ::SetWindowText(hwndEdit, text);
+ }
+ }
+}
+
+int wxTreeCtrl::DoGetItemImageFromData(const wxTreeItemId& item,
+ wxTreeItemIcon which) const
+{
+ wxTreeViewItem tvItem(item, TVIF_PARAM);
+ if ( !DoGetItem(&tvItem) )
+ {
+ return -1;
+ }
+
+ return ((wxTreeItemIndirectData *)tvItem.lParam)->GetImage(which);
+}
+
+void wxTreeCtrl::DoSetItemImageFromData(const wxTreeItemId& item,
+ int image,
+ wxTreeItemIcon which) const
+{
+ wxTreeViewItem tvItem(item, TVIF_PARAM);
+ if ( !DoGetItem(&tvItem) )
+ {
+ return;
+ }
+
+ wxTreeItemIndirectData *data = ((wxTreeItemIndirectData *)tvItem.lParam);
+
+ data->SetImage(image, which);
+
+ // make sure that we have selected images as well
+ if ( which == wxTreeItemIcon_Normal &&
+ !data->HasImage(wxTreeItemIcon_Selected) )
+ {
+ data->SetImage(image, wxTreeItemIcon_Selected);
+ }
+
+ if ( which == wxTreeItemIcon_Expanded &&
+ !data->HasImage(wxTreeItemIcon_SelectedExpanded) )
+ {
+ data->SetImage(image, wxTreeItemIcon_SelectedExpanded);
+ }
+}
+
+void wxTreeCtrl::DoSetItemImages(const wxTreeItemId& item,
+ int image,
+ int imageSel)
+{
+ wxTreeViewItem tvItem(item, TVIF_IMAGE | TVIF_SELECTEDIMAGE);
+ tvItem.iSelectedImage = imageSel;
+ tvItem.iImage = image;
+ DoSetItem(&tvItem);
+}
+
+int wxTreeCtrl::GetItemImage(const wxTreeItemId& item,
+ wxTreeItemIcon which) const
+{
+ if ( (HITEM(item) == TVI_ROOT) && (m_windowStyle & wxTR_HIDE_ROOT) )
+ {
+ // TODO: Maybe a hidden root can still provide images?
+ return -1;
+ }
+
+ if ( HasIndirectData(item) )
+ {
+ return DoGetItemImageFromData(item, which);
+ }
+
+ UINT mask;
+ switch ( which )
+ {
+ default:
+ wxFAIL_MSG( wxT("unknown tree item image type") );
+
+ case wxTreeItemIcon_Normal:
+ mask = TVIF_IMAGE;
+ break;
+
+ case wxTreeItemIcon_Selected:
+ mask = TVIF_SELECTEDIMAGE;
+ break;
+
+ case wxTreeItemIcon_Expanded:
+ case wxTreeItemIcon_SelectedExpanded:
+ return -1;
+ }
+
+ wxTreeViewItem tvItem(item, mask);
+ DoGetItem(&tvItem);
+
+ return mask == TVIF_IMAGE ? tvItem.iImage : tvItem.iSelectedImage;
+}
+
+void wxTreeCtrl::SetItemImage(const wxTreeItemId& item, int image,
+ wxTreeItemIcon which)
+{
+ if ( IS_VIRTUAL_ROOT(item) )
+ {
+ // TODO: Maybe a hidden root can still store images?
+ return;
+ }
+
+ int imageNormal,
+ imageSel;
+
+ switch ( which )
+ {
+ default:
+ wxFAIL_MSG( wxT("unknown tree item image type") );
+ // fall through
+
+ case wxTreeItemIcon_Normal:
+ {
+ const int imageNormalOld = GetItemImage(item);
+ const int imageSelOld =
+ GetItemImage(item, wxTreeItemIcon_Selected);
+
+ // always set the normal image
+ imageNormal = image;
+
+ // if the selected and normal images were the same, they should
+ // be the same after the update, otherwise leave the selected
+ // image as it was
+ imageSel = imageNormalOld == imageSelOld ? image : imageSelOld;
+ }
+ break;
+
+ case wxTreeItemIcon_Selected:
+ imageNormal = GetItemImage(item);
+ imageSel = image;
+ break;