#include "wx/settings.h"
#endif
+#include "wx/dynlib.h"
#include "wx/msw/private.h"
// Set this to 1 to be _absolutely_ sure that repainting will work for all
// the real client data
wxTreeItemData *m_data;
- DECLARE_NO_COPY_CLASS(wxTreeItemParam)
+ wxDECLARE_NO_COPY_CLASS(wxTreeItemParam);
};
// wxVirutalNode is used in place of a single root when 'hidden' root is
private:
wxTreeItemParam *m_param;
- DECLARE_NO_COPY_CLASS(wxVirtualNode)
+ wxDECLARE_NO_COPY_CLASS(wxVirtualNode);
};
#ifdef __VISUALC__
const wxTreeCtrl *m_tree;
- DECLARE_NO_COPY_CLASS(wxTreeTraversal)
+ wxDECLARE_NO_COPY_CLASS(wxTreeTraversal);
};
// internal class for getting the selected items
private:
wxArrayTreeItemIds& m_selections;
- DECLARE_NO_COPY_CLASS(TraverseSelections)
+ wxDECLARE_NO_COPY_CLASS(TraverseSelections);
};
// internal class for counting tree items
private:
size_t m_count;
- DECLARE_NO_COPY_CLASS(TraverseCounter)
+ wxDECLARE_NO_COPY_CLASS(TraverseCounter);
};
// ----------------------------------------------------------------------------
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
-
wxSetCCUnicodeFormat(GetHwnd());
return true;
{
wxCHECK_MSG( item.IsOk(), false, wxT("invalid tree item") );
+ if ( IS_VIRTUAL_ROOT(item) )
+ {
+ wxTreeItemIdValue cookie;
+ return GetFirstChild(item, cookie).IsOk();
+ }
+
wxTreeViewItem tvItem(item, TVIF_CHILDREN);
DoGetItem(&tvItem);
// multiple selections emulation
// ----------------------------------------------------------------------------
-bool wxTreeCtrl::IsItemChecked(const wxTreeItemId& item) const
-{
- wxCHECK_MSG( item.IsOk(), false, wxT("invalid tree item") );
-
- // receive the desired information.
- wxTreeViewItem tvItem(item, TVIF_STATE, TVIS_STATEIMAGEMASK);
- DoGetItem(&tvItem);
-
- // state image indices are 1 based
- return ((tvItem.state >> 12) - 1) == 1;
-}
-
-void wxTreeCtrl::SetItemCheck(const wxTreeItemId& item, bool check)
-{
- wxCHECK_RET( item.IsOk(), wxT("invalid tree item") );
-
- // receive the desired information.
- wxTreeViewItem tvItem(item, TVIF_STATE, TVIS_STATEIMAGEMASK);
-
- DoGetItem(&tvItem);
-
- // state images are one-based
- tvItem.state = (check ? 2 : 1) << 12;
-
- DoSetItem(&tvItem);
-}
-
size_t wxTreeCtrl::GetSelections(wxArrayTreeItemIds& selections) const
{
TraverseSelections selector(this, selections);
tvIns.item.lParam = (LPARAM)param;
tvIns.item.mask = mask;
+ // don't use the hack below for the children of hidden root: this results
+ // in a crash inside comctl32.dll when we call TreeView_GetItemRect()
+ const bool firstChild = !IsHiddenRoot(parent) &&
+ !TreeView_GetChild(GetHwnd(), HITEM(parent));
+
HTREEITEM id = TreeView_InsertItem(GetHwnd(), &tvIns);
if ( id == 0 )
{
wxLogLastError(wxT("TreeView_InsertItem"));
}
+ // apparently some Windows versions (2000 and XP are reported to do this)
+ // sometimes don't refresh the tree after adding the first child and so we
+ // need this to make the "[+]" appear
+ if ( firstChild )
+ {
+ RECT rect;
+ TreeView_GetItemRect(GetHwnd(), HITEM(parent), &rect, FALSE);
+ ::InvalidateRect(GetHwnd(), &rect, FALSE);
+ }
+
// associate the application tree item with Win32 tree item handle
param->SetItem(id);
// notify us before painting each item
*result = m_hasAnyAttr ? CDRF_NOTIFYITEMDRAW
: CDRF_DODEFAULT;
+
+ // windows in TreeCtrl use one-based index for item state images,
+ // 0 indexed image is not being used, we're using zero-based index,
+ // so we have to add temp image (of zero index) to state image list
+ // before we draw any item, then after items are drawn we have to
+ // delete it (in POSTPAINT notify)
+ if (m_imageListState && m_imageListState->GetImageCount() > 0)
+ {
+ typedef BOOL (wxSTDCALL *ImageList_Copy_t)
+ (HIMAGELIST, int, HIMAGELIST, int, UINT);
+ static ImageList_Copy_t s_pfnImageList_Copy = NULL;
+ static bool loaded = false;
+
+ if ( !loaded )
+ {
+ wxLoadedDLL dllComCtl32(_T("comctl32.dll"));
+ if ( dllComCtl32.IsLoaded() )
+ wxDL_INIT_FUNC(s_pfn, ImageList_Copy, dllComCtl32);
+ }
+
+ if ( !s_pfnImageList_Copy )
+ {
+ // this code is broken with ImageList_Copy()
+ // but I don't care enough about Win95 support
+ // to write it now -- if anybody does, please
+ // do it
+ wxFAIL_MSG("TODO: implement this for Win95");
+ break;
+ }
+
+ const HIMAGELIST
+ hImageList = GetHimagelistOf(m_imageListState);
+
+ // add temporary image
+ int width, height;
+ m_imageListState->GetSize(0, width, height);
+
+ HBITMAP hbmpTemp = ::CreateBitmap(width, height, 1, 1, NULL);
+ int index = ::ImageList_Add(hImageList, hbmpTemp, hbmpTemp);
+ ::DeleteObject(hbmpTemp);
+
+ if ( index != -1 )
+ {
+ // move images to right
+ for ( int i = index; i > 0; i-- )
+ {
+ (*s_pfnImageList_Copy)(hImageList, i,
+ hImageList, i-1,
+ ILCF_MOVE);
+ }
+
+ // we must remove the image in POSTPAINT notify
+ *result |= CDRF_NOTIFYPOSTPAINT;
+ }
+ }
+ break;
+
+ case CDDS_POSTPAINT:
+ // we are deleting temp image of 0 index, which was
+ // added before items were drawn (in PREPAINT notify)
+ if (m_imageListState && m_imageListState->GetImageCount() > 0)
+ m_imageListState->Remove(0);
break;
case CDDS_ITEMPREPAINT:
switch ( hdr->code )
{
case NM_DBLCLK:
- // we translate NM_DBLCLK into ACTIVATED event, so don't interpret
- // the return code of this event handler as the return value for
- // NM_DBLCLK - otherwise, double clicking the item to toggle its
- // expanded status would never work
- *result = false;
+ // we translate NM_DBLCLK into ACTIVATED event and if the user
+ // handled the activation of the item we shouldn't proceed with
+ // also using the same double click for toggling the item expanded
+ // state -- but OTOH do let the user to expand/collapse the item by
+ // double clicking on it if the activation is not handled specially
+ *result = processed;
break;
case NM_RCLICK:
// why do they define INDEXTOSTATEIMAGEMASK but not the inverse?
#define STATEIMAGEMASKTOINDEX(state) (((state) & TVIS_STATEIMAGEMASK) >> 12)
-void wxTreeCtrl::SetState(const wxTreeItemId& node, int state)
+int wxTreeCtrl::DoGetItemState(const wxTreeItemId& item) const
{
- TV_ITEM tvi;
- tvi.hItem = (HTREEITEM)node.m_pItem;
- tvi.mask = TVIF_STATE;
- tvi.stateMask = TVIS_STATEIMAGEMASK;
-
- // Select the specified state, or -1 == cycle to the next one.
- if ( state == -1 )
- {
- TreeView_GetItem(GetHwnd(), &tvi);
-
- state = STATEIMAGEMASKTOINDEX(tvi.state) + 1;
- if ( state == m_imageListState->GetImageCount() )
- state = 1;
- }
-
- wxCHECK_RET( state < m_imageListState->GetImageCount(),
- _T("wxTreeCtrl::SetState(): item index out of bounds") );
+ wxCHECK_MSG( item.IsOk(), wxTREE_ITEMSTATE_NONE, wxT("invalid tree item") );
- tvi.state = INDEXTOSTATEIMAGEMASK(state);
+ // receive the desired information
+ wxTreeViewItem tvItem(item, TVIF_STATE, TVIS_STATEIMAGEMASK);
+ DoGetItem(&tvItem);
- TreeView_SetItem(GetHwnd(), &tvi);
+ // state images are one-based
+ return STATEIMAGEMASKTOINDEX(tvItem.state) - 1;
}
-int wxTreeCtrl::GetState(const wxTreeItemId& node)
+void wxTreeCtrl::DoSetItemState(const wxTreeItemId& item, int state)
{
- TV_ITEM tvi;
- tvi.hItem = (HTREEITEM)node.m_pItem;
- tvi.mask = TVIF_STATE;
- tvi.stateMask = TVIS_STATEIMAGEMASK;
- TreeView_GetItem(GetHwnd(), &tvi);
+ wxCHECK_RET( item.IsOk(), wxT("invalid tree item") );
- return STATEIMAGEMASKTOINDEX(tvi.state);
+ wxTreeViewItem tvItem(item, TVIF_STATE, TVIS_STATEIMAGEMASK);
+
+ // state images are one-based
+ // 0 if no state image display (wxTREE_ITEMSTATE_NONE = -1)
+ tvItem.state = INDEXTOSTATEIMAGEMASK(state + 1);
+
+ DoSetItem(&tvItem);
}
#endif // wxUSE_TREECTRL