+ if (hdr->code == TVN_SELCHANGINGW ||
+ hdr->code == TVN_SELCHANGEDW)
+ {
+ NM_TREEVIEWW *tv = (NM_TREEVIEWW *)lParam;
+ event.m_item = tv->itemNew.hItem;
+ event.m_itemOld = tv->itemOld.hItem;
+ }
+ else
+ {
+ NM_TREEVIEWA *tv = (NM_TREEVIEWA *)lParam;
+ event.m_item = tv->itemNew.hItem;
+ event.m_itemOld = tv->itemOld.hItem;
+ }
+ }
+
+ // we receive this message from WM_LBUTTONDOWN handler inside
+ // comctl32.dll and so before the click is passed to
+ // DefWindowProc() which sets the focus to the window which was
+ // clicked and this can lead to unexpected event sequences: for
+ // example, we may get a "selection change" event from the tree
+ // before getting a "kill focus" event for the text control which
+ // had the focus previously, thus breaking user code doing input
+ // validation
+ //
+ // to avoid such surprises, we force the generation of focus events
+ // now, before we generate the selection change ones
+ 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
+ case NM_CUSTOMDRAW:
+ {
+ LPNMTVCUSTOMDRAW lptvcd = (LPNMTVCUSTOMDRAW)lParam;
+ NMCUSTOMDRAW& nmcd = lptvcd->nmcd;
+ switch ( nmcd.dwDrawStage )
+ {
+ case CDDS_PREPAINT:
+ // if we've got any items with non standard attributes,
+ // 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 (*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:
+ {
+ wxMapTreeAttr::iterator
+ it = m_attrs.find((void *)nmcd.dwItemSpec);
+
+ if ( it == m_attrs.end() )
+ {
+ // nothing to do for this item
+ *result = CDRF_DODEFAULT;
+ break;
+ }
+
+ wxTreeItemAttr * const attr = it->second;
+
+ wxTreeViewItem tvItem((void *)nmcd.dwItemSpec,
+ TVIF_STATE, TVIS_DROPHILITED);
+ DoGetItem(&tvItem);
+ const UINT tvItemState = tvItem.state;
+
+ // selection colours should override ours,
+ // otherwise it is too confusing to the user
+ if ( !(nmcd.uItemState & CDIS_SELECTED) &&
+ !(tvItemState & TVIS_DROPHILITED) )
+ {
+ wxColour colBack;
+ if ( attr->HasBackgroundColour() )
+ {
+ colBack = attr->GetBackgroundColour();
+ lptvcd->clrTextBk = wxColourToRGB(colBack);
+ }
+ }
+
+ // but we still want to keep the special foreground
+ // colour when we don't have focus (we can't keep
+ // it when we do, it would usually be unreadable on
+ // the almost inverted bg colour...)
+ if ( ( !(nmcd.uItemState & CDIS_SELECTED) ||
+ FindFocus() != this ) &&
+ !(tvItemState & TVIS_DROPHILITED) )
+ {
+ wxColour colText;
+ if ( attr->HasTextColour() )
+ {
+ colText = attr->GetTextColour();
+ lptvcd->clrText = wxColourToRGB(colText);
+ }
+ }
+
+ if ( attr->HasFont() )
+ {
+ HFONT hFont = GetHfontOf(attr->GetFont());
+
+ ::SelectObject(nmcd.hdc, hFont);
+
+ *result = CDRF_NEWFONT;
+ }
+ else // no specific font
+ {
+ *result = CDRF_DODEFAULT;
+ }
+ }
+ break;
+
+ default:
+ *result = CDRF_DODEFAULT;
+ }
+ }
+
+ // we always process it
+ return true;
+#endif // have owner drawn support in headers