diff dwt/widgets/Tree.d @ 213:36f5cb12e1a2

Update to SWT 3.4M7
author Frank Benoit <benoit@tionex.de>
date Sat, 17 May 2008 17:34:28 +0200
parents ab60f3309436
children a8fed3e56433
line wrap: on
line diff
--- a/dwt/widgets/Tree.d	Mon May 05 00:12:38 2008 +0200
+++ b/dwt/widgets/Tree.d	Sat May 17 17:34:28 2008 +0200
@@ -37,6 +37,7 @@
 import dwt.widgets.Control;
 import dwt.widgets.Listener;
 import dwt.widgets.Widget;
+import dwt.widgets.Table;
 
 import dwt.dwthelper.utils;
 
@@ -77,12 +78,13 @@
  * </pre></code>
  * </p><p>
  * Note that although this class is a subclass of <code>Composite</code>,
- * it does not make sense to add <code>Control</code> children to it,
- * or set a layout on it.
+ * it does not normally make sense to add <code>Control</code> children to
+ * it, or set a layout on it, unless implementing something like a cell
+ * editor.
  * </p><p>
  * <dl>
  * <dt><b>Styles:</b></dt>
- * <dd>SINGLE, MULTI, CHECK, FULL_SELECTION, VIRTUAL</dd>
+ * <dd>SINGLE, MULTI, CHECK, FULL_SELECTION, VIRTUAL, NO_SCROLL</dd>
  * <dt><b>Events:</b></dt>
  * <dd>Selection, DefaultSelection, Collapse, Expand, SetData, MeasureItem, EraseItem, PaintItem</dd>
  * </dl>
@@ -102,9 +104,11 @@
 
     TreeItem [] items;
     TreeColumn [] columns;
+    int columnCount;
     ImageList imageList, headerImageList;
     TreeItem currentItem;
     TreeColumn sortColumn;
+    RECT* focusRect;
     HWND hwndParent, hwndHeader;
     HANDLE hAnchor, hInsert, hSelect;
     int lastID;
@@ -177,6 +181,9 @@
  * @see DWT#SINGLE
  * @see DWT#MULTI
  * @see DWT#CHECK
+ * @see DWT#FULL_SELECTION
+ * @see DWT#VIRTUAL
+ * @see DWT#NO_SCROLL
  * @see Widget#checkSubclass
  * @see Widget#getStyle
  */
@@ -187,15 +194,23 @@
 
 static int checkStyle (int style) {
     /*
-    * Feature in Windows.  It is not possible to create
-    * a tree that scrolls and does not have scroll bars.
-    * The TVS_NOSCROLL style will remove the scroll bars
-    * but the tree will never scroll.  Therefore, no matter
-    * what style bits are specified, set the H_SCROLL and
-    * V_SCROLL bits so that the DWT style will match the
-    * widget that Windows creates.
+    * Feature in Windows.  Even when WS_HSCROLL or
+    * WS_VSCROLL is not specified, Windows creates
+    * trees and tables with scroll bars.  The fix
+    * is to set H_SCROLL and V_SCROLL.
+    *
+    * NOTE: This code appears on all platforms so that
+    * applications have consistent scroll bar behavior.
     */
-    style |= DWT.H_SCROLL | DWT.V_SCROLL;
+    if ((style & DWT.NO_SCROLL) is 0) {
+        style |= DWT.H_SCROLL | DWT.V_SCROLL;
+    }
+    /*
+    * Note: Windows only supports TVS_NOSCROLL and TVS_NOHSCROLL.
+    */
+    if ((style & DWT.H_SCROLL) !is 0 && (style & DWT.V_SCROLL) is 0) {
+        style |= DWT.V_SCROLL;
+    }
     return checkBits (style, DWT.SINGLE, DWT.MULTI, 0, 0, 0, 0);
 }
 
@@ -215,10 +230,17 @@
         case DWT.PaintItem: {
             customDraw = true;
             style |= DWT.DOUBLE_BUFFERED;
+            if (isCustomToolTip ()) createItemToolTips ();
             OS.SendMessage (handle, OS.TVM_SETSCROLLTIME, 0, 0);
             int bits = OS.GetWindowLong (handle, OS.GWL_STYLE);
-            bits |= OS.TVS_NOTOOLTIPS;
-            if (eventType is DWT.MeasureItem) bits |= OS.TVS_NOHSCROLL;
+            if (eventType is DWT.MeasureItem) {
+                if (explorerTheme) {
+                    int bits1 = OS.SendMessage (handle, OS.TVM_GETEXTENDEDSTYLE, 0, 0);
+                    bits1 &= ~OS.TVS_EX_AUTOHSCROLL;
+                    OS.SendMessage (handle, OS.TVM_SETEXTENDEDSTYLE, 0, bits1);
+                }
+                bits |= OS.TVS_NOHSCROLL;
+            }
             /*
             * Feature in Windows.  When the tree has the style
             * TVS_FULLROWSELECT, the background color for the
@@ -419,16 +441,14 @@
             }
         }
     }
-    int count = 0;
     int [] order = null;
     RECT clientRect;
     OS.GetClientRect (scrolledHandle (), &clientRect);
     if (hwndHeader !is null) {
         OS.MapWindowPoints (hwndParent, handle, cast(POINT*) &clientRect, 2);
-        count = OS.SendMessage (hwndHeader, OS.HDM_GETITEMCOUNT, 0, 0);
-        if (count !is 0) {
-            order = new int [count];
-            OS.SendMessage (hwndHeader, OS.HDM_GETORDERARRAY, count, cast(int) order.ptr);
+        if (columnCount !is 0) {
+            order = new int [columnCount];
+            OS.SendMessage (hwndHeader, OS.HDM_GETORDERARRAY, columnCount, cast(int) order.ptr);
         }
     }
     int sortIndex = -1, clrSortBk = -1;
@@ -442,9 +462,9 @@
     }
     int x = 0;
     Point size = null;
-    for (int i=0; i<Math.max (1, count); i++) {
+    for (int i=0; i<Math.max (1, columnCount); i++) {
         int index = order is null ? i : order [i], width = nmcd.nmcd.rc.right - nmcd.nmcd.rc.left;
-        if (count > 0 && hwndHeader !is null) {
+        if (columnCount > 0 && hwndHeader !is null) {
             HDITEM hdItem;
             hdItem.mask = OS.HDI_WIDTH;
             OS.SendMessage (hwndHeader, OS.HDM_GETITEM, index, &hdItem);
@@ -464,7 +484,7 @@
                             itemRect.right += EXPLORER_EXTRA + 1;
                             pClipRect.left = itemRect.left;
                             pClipRect.right = itemRect.right;
-                            if (count > 0 && hwndHeader !is null) {
+                            if (columnCount > 0 && hwndHeader !is null) {
                                 HDITEM hdItem;
                                 hdItem.mask = OS.HDI_WIDTH;
                                 OS.SendMessage (hwndHeader, OS.HDM_GETITEM, index, &hdItem);
@@ -473,11 +493,11 @@
                         }
                         RECT pRect;
                         OS.SetRect (&pRect, nmcd.nmcd.rc.left, nmcd.nmcd.rc.top, nmcd.nmcd.rc.right, nmcd.nmcd.rc.bottom);
-                        if (count > 0 && hwndHeader !is null) {
+                        if (columnCount > 0 && hwndHeader !is null) {
                             int totalWidth = 0;
                             HDITEM hdItem;
                             hdItem.mask = OS.HDI_WIDTH;
-                            for (int j=0; j<count; j++) {
+                            for (int j=0; j<columnCount; j++) {
                                 OS.SendMessage (hwndHeader, OS.HDM_GETITEM, j, &hdItem);
                                 totalWidth += hdItem.cxy;
                             }
@@ -498,22 +518,6 @@
                     }
                     if (draw) fillBackground (hDC, OS.GetBkColor (hDC), &pClipRect);
                 }
-            } else {
-                if (explorerTheme && hooks (DWT.EraseItem)) {
-                    if ((selected && !ignoreDrawSelection) || (hot && !ignoreDrawHot)) {
-                        RECT pRect = item.getBounds (index, true, true, false, false, false, hDC);
-                        RECT pClipRect = item.getBounds (index, true, true, false, false, true, hDC);
-                        pRect.left -= EXPLORER_EXTRA;
-                        pRect.right += EXPLORER_EXTRA;
-                        pClipRect.left -= EXPLORER_EXTRA;
-                        pClipRect.right += EXPLORER_EXTRA;
-                        auto hTheme = OS.OpenThemeData (handle, cast(TCHAR*) Display.TREEVIEW);
-                        int iStateId = selected ? OS.TREIS_SELECTED : OS.TREIS_HOT;
-                        if (OS.GetFocus () !is handle && selected && !hot) iStateId = OS.TREIS_SELECTEDNOTFOCUS;
-                        OS.DrawThemeBackground (hTheme, hDC, OS.TVP_TREEITEM, iStateId, &pRect, &pClipRect);
-                        OS.CloseThemeData (hTheme);
-                    }
-                }
             }
         }
         if (x + width > clientRect.left) {
@@ -579,8 +583,7 @@
                 backgroundRect = &rect;
             }
             int clrText = -1, clrTextBk = -1;
-            HFONT hFont = item.cellFont !is null ? item.cellFont [index] : cast(HFONT)-1;
-            if (hFont is cast(HFONT)-1) hFont = item.font;
+            auto hFont = item.fontHandle (index);
             if (selectionForeground !is -1) clrText = selectionForeground;
             if (OS.IsWindowEnabled (handle)) {
                 bool drawForeground = false;
@@ -623,26 +626,8 @@
             if (drawItem) {
                 if (i !is 0) {
                     if (hooks (DWT.MeasureItem)) {
-                        RECT itemRect = item.getBounds (index, true, true, false, false, false, hDC);
-                        int nSavedDC = OS.SaveDC (hDC);
-                        GCData data = new GCData ();
-                        data.device = display;
-                        data.hFont = hFont;
-                        GC gc = GC.win32_new (hDC, data);
-                        Event event = new Event ();
-                        event.item = item;
-                        event.index = index;
-                        event.gc = gc;
-                        event.x = itemRect.left;
-                        event.y = itemRect.top;
-                        event.width = itemRect.right - itemRect.left;
-                        event.height = itemRect.bottom - itemRect.top;
-                        sendEvent (DWT.MeasureItem, event);
-                        event.gc = null;
-                        gc.dispose ();
-                        OS.RestoreDC (hDC, nSavedDC);
+                        sendMeasureItemEvent (item, index, hDC);
                         if (isDisposed () || item.isDisposed ()) break;
-                        if (event.height > getItemHeight ()) setItemHeight (event.height);
                     }
                     if (hooks (DWT.EraseItem)) {
                         RECT cellRect = item.getBounds (index, true, true, true, true, true, hDC);
@@ -655,7 +640,7 @@
                             if (clrText !is -1) data.foreground = clrText;
                             if (clrTextBk !is -1) data.background = clrTextBk;
                         }
-                        data.hFont = hFont;
+                        data.font = item.getFont (index);
                         data.uiState = OS.SendMessage (handle, OS.WM_QUERYUISTATE, 0, 0);
                         GC gc = GC.win32_new (hDC, data);
                         Event event = new Event ();
@@ -709,12 +694,12 @@
                                     if (!explorerTheme) {
                                         drawBackground = true;
                                         ignoreDrawBackground = false;
-                                        if (handle is OS.GetFocus () && OS.IsWindowEnabled (handle)) {
+                                        if ((handle is OS.GetFocus () || display.getHighContrast ()) && OS.IsWindowEnabled (handle)) {
                                             clrTextBk = OS.GetSysColor (OS.COLOR_HIGHLIGHT);
                                         } else {
                                             clrTextBk = OS.GetSysColor (OS.COLOR_3DFACE);
                                         }
-                                        if (!ignoreFullSelection && index is count - 1) {
+                                        if (!ignoreFullSelection && index is columnCount - 1) {
                                             RECT* selectionRect = new RECT ();
                                             OS.SetRect (selectionRect, backgroundRect.left, backgroundRect.top, nmcd.nmcd.rc.right, backgroundRect.bottom);
                                             backgroundRect = selectionRect;
@@ -722,11 +707,11 @@
                                     } else {
                                         RECT pRect;
                                         OS.SetRect (&pRect, nmcd.nmcd.rc.left, nmcd.nmcd.rc.top, nmcd.nmcd.rc.right, nmcd.nmcd.rc.bottom);
-                                        if (count > 0 && hwndHeader !is null) {
+                                        if (columnCount > 0 && hwndHeader !is null) {
                                             int totalWidth = 0;
                                             HDITEM hdItem;
                                             hdItem.mask = OS.HDI_WIDTH;
-                                            for (int j=0; j<count; j++) {
+                                            for (int j=0; j<columnCount; j++) {
                                                 OS.SendMessage (hwndHeader, OS.HDM_GETITEM, j, &hdItem);
                                                 totalWidth += hdItem.cxy;
                                             }
@@ -737,7 +722,7 @@
                                                 pRect.left = clientRect.left;
                                                 pRect.right = clientRect.right;
                                             }
-                                            if (index is count - 1) {
+                                            if (index is columnCount - 1) {
                                                 RECT* selectionRect = new RECT ();
                                                 OS.SetRect (selectionRect, backgroundRect.left, backgroundRect.top, pRect.right, backgroundRect.bottom);
                                                 backgroundRect = selectionRect;
@@ -796,17 +781,16 @@
                     if (image !is null) {
                         Rectangle bounds = image.getBounds ();
                         if (size is null) size = getImageSize ();
-                        //int y = rect.top + (index is 0 ? (getItemHeight () - size.y) / 2 : 0);
-                        int y = rect.top;
                         if (!ignoreDrawForeground) {
-                            //TODO - share GC, clip the drawing for index is 0
+                            //int y1 = rect.top + (index is 0 ? (getItemHeight () - size.y) / 2 : 0);
+                            int y1 = rect.top;
+                            int x1 = Math.max (rect.left, rect.left - inset + 1);
                             GCData data = new GCData();
                             data.device = display;
                             GC gc = GC.win32_new (hDC, data);
-                            //if (index is 0) { //must clear
-                                //gc.setClipping (rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top);
-                            //}
-                            gc.drawImage (image, 0, 0, bounds.width, bounds.height, rect.left - inset + 1, y, size.x, size.y);
+                            gc.setClipping (x1, rect.top, rect.right - x1, rect.bottom - rect.top);
+                            gc.drawImage (image, 0, 0, bounds.width, bounds.height, x1, y1, size.x, size.y);
+                            OS.SelectClipRgn (hDC, null);
                             gc.dispose ();
                         }
                         OS.SetRect (&rect, rect.left + size.x + offset, rect.top, rect.right - inset, rect.bottom);
@@ -837,7 +821,7 @@
                             if (strings !is null) string = strings [index];
                         }
                         if (string !is null) {
-                            if (hFont !is cast(HFONT)-1) hFont = OS.SelectObject (hDC, hFont);
+                            if (hFont !is cast(HFONT)-1) hFont = cast(HFONT)OS.SelectObject (hDC, hFont);
                             if (clrText !is -1) clrText = OS.SetTextColor (hDC, clrText);
                             if (clrTextBk !is -1) clrTextBk = OS.SetBkColor (hDC, clrTextBk);
                             int flags = OS.DT_NOPREFIX | OS.DT_SINGLELINE | OS.DT_VCENTER;
@@ -850,7 +834,7 @@
                             TCHAR[] buffer = StrToTCHARs (getCodePage (), string, false);
                             if (!ignoreDrawForeground) OS.DrawText (hDC, buffer.ptr, buffer.length, &rect, flags);
                             OS.DrawText (hDC, buffer.ptr, buffer.length, &rect, flags | OS.DT_CALCRECT);
-                            if (hFont !is cast(HFONT)-1) hFont = OS.SelectObject (hDC, hFont);
+                            if (hFont !is cast(HFONT)-1) hFont = cast(HFONT)OS.SelectObject (hDC, hFont);
                             if (clrText !is -1) clrText = OS.SetTextColor (hDC, clrText);
                             if (clrTextBk !is -1) clrTextBk = OS.SetBkColor (hDC, clrTextBk);
                         }
@@ -863,7 +847,7 @@
                 int nSavedDC = OS.SaveDC (hDC);
                 GCData data = new GCData ();
                 data.device = display;
-                data.hFont = hFont;
+                data.font = item.getFont (index);
                 data.foreground = OS.GetTextColor (hDC);
                 data.background = OS.GetBkColor (hDC);
                 if (selected && (style & DWT.FULL_SELECTION) !is 0) {
@@ -904,6 +888,7 @@
                 int cellHeight = cellRect.bottom - cellRect.top;
                 gc.setClipping (cellRect.left, cellRect.top, cellWidth, cellHeight);
                 sendEvent (DWT.PaintItem, event);
+                if (data.focusDrawn) focusRect = null;
                 event.gc = null;
                 gc.dispose ();
                 OS.RestoreDC (hDC, nSavedDC);
@@ -915,52 +900,42 @@
     }
     if (linesVisible) {
         if ((style & DWT.FULL_SELECTION) !is 0) {
-            if (hwndHeader !is null) {
-                if (OS.SendMessage (hwndHeader, OS.HDM_GETITEMCOUNT, 0, 0) !is 0) {
-                    HDITEM hdItem;
-                    hdItem.mask = OS.HDI_WIDTH;
-                    OS.SendMessage (hwndHeader, OS.HDM_GETITEM, 0, &hdItem);
-                    RECT rect;
-                    OS.SetRect (&rect, nmcd.nmcd.rc.left + hdItem.cxy, nmcd.nmcd.rc.top, nmcd.nmcd.rc.right, nmcd.nmcd.rc.bottom);
-                    OS.DrawEdge (hDC, &rect, OS.BDR_SUNKENINNER, OS.BF_BOTTOM);
-                }
+            if (columnCount !is 0) {
+                HDITEM hdItem;
+                hdItem.mask = OS.HDI_WIDTH;
+                OS.SendMessage (hwndHeader, OS.HDM_GETITEM, 0, &hdItem);
+                RECT rect;
+                OS.SetRect (&rect, nmcd.nmcd.rc.left + hdItem.cxy, nmcd.nmcd.rc.top, nmcd.nmcd.rc.right, nmcd.nmcd.rc.bottom);
+                OS.DrawEdge (hDC, &rect, OS.BDR_SUNKENINNER, OS.BF_BOTTOM);
             }
         }
         RECT rect;
         OS.SetRect (&rect, nmcd.nmcd.rc.left, nmcd.nmcd.rc.top, nmcd.nmcd.rc.right, nmcd.nmcd.rc.bottom);
         OS.DrawEdge (hDC, &rect, OS.BDR_SUNKENINNER, OS.BF_BOTTOM);
     }
-    if (!explorerTheme) {
-        if (handle is OS.GetFocus ()) {
-            int uiState = OS.SendMessage (handle, OS.WM_QUERYUISTATE, 0, 0);
-            if ((uiState & OS.UISF_HIDEFOCUS) is 0) {
-                auto hItem = cast(HANDLE) OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_CARET, 0);
-                if (hItem is item.handle) {
-                    if (!ignoreDrawFocus && findImageControl () !is null) {
-                        if ((style & DWT.FULL_SELECTION) !is 0) {
-                            RECT focusRect;
-                            OS.SetRect (&focusRect, nmcd.nmcd.rc.left, nmcd.nmcd.rc.top, nmcd.nmcd.rc.right, nmcd.nmcd.rc.bottom);
-                            if (count > 0 && hwndHeader !is null) {
-                                int width = 0;
-                                HDITEM hdItem;
-                                hdItem.mask = OS.HDI_WIDTH;
-                                for (int j=0; j<count; j++) {
-                                    OS.SendMessage (hwndHeader, OS.HDM_GETITEM, j, &hdItem);
-                                    width += hdItem.cxy;
-                                }
-                                focusRect.left = 0;
-                                RECT rect;
-                                OS.GetClientRect (handle, &rect);
-                                focusRect.right = Math.max (width, rect.right - OS.GetSystemMetrics (OS.SM_CXVSCROLL));
+    if (!ignoreDrawFocus && focusRect !is null) {
+        OS.DrawFocusRect (hDC, focusRect);
+        focusRect = null;
+    } else {
+        if (!explorerTheme) {
+            if (handle is OS.GetFocus ()) {
+                int uiState = OS.SendMessage (handle, OS.WM_QUERYUISTATE, 0, 0);
+                if ((uiState & OS.UISF_HIDEFOCUS) is 0) {
+                    auto hItem = cast(HANDLE) OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_CARET, 0);
+                    if (hItem is item.handle) {
+                        if (!ignoreDrawFocus && findImageControl () !is null) {
+                            if ((style & DWT.FULL_SELECTION) !is 0) {
+                                RECT focusRect;
+                                OS.SetRect (&focusRect, 0, nmcd.nmcd.rc.top, clientRect.right + 1, nmcd.nmcd.rc.bottom);
+                                OS.DrawFocusRect (hDC, &focusRect);
+                            } else {
+                                int index = OS.SendMessage (hwndHeader, OS.HDM_ORDERTOINDEX, 0, 0);
+                                RECT focusRect = item.getBounds (index, true, false, false, false, false, hDC);
+                                RECT clipRect = item.getBounds (index, true, false, false, false, true, hDC);
+                                OS.IntersectClipRect (hDC, clipRect.left, clipRect.top, clipRect.right, clipRect.bottom);
+                                OS.DrawFocusRect (hDC, &focusRect);
+                                OS.SelectClipRgn (hDC, null);
                             }
-                            OS.DrawFocusRect (hDC, &focusRect);
-                        } else {
-                            int index = OS.SendMessage (hwndHeader, OS.HDM_ORDERTOINDEX, 0, 0);
-                            RECT focusRect = item.getBounds (index, true, false, false, false, false, hDC);
-                            RECT clipRect = item.getBounds (index, true, false, false, false, true, hDC);
-                            OS.IntersectClipRect (hDC, clipRect.left, clipRect.top, clipRect.right, clipRect.bottom);
-                            OS.DrawFocusRect (hDC, &focusRect);
-                            OS.SelectClipRgn (hDC, null);
                         }
                     }
                 }
@@ -990,28 +965,23 @@
     if (item is null) return null;
     auto hDC = nmcd.nmcd.hdc;
     int index = hwndHeader !is null ? OS.SendMessage (hwndHeader, OS.HDM_ORDERTOINDEX, 0, 0) : 0;
-    HFONT hFont = item.cellFont !is null ? item.cellFont [index] : cast(HFONT)-1;
-    if (hFont is cast(HFONT)-1) hFont = item.font;
+    auto hFont = item.fontHandle (index);
     if (hFont !is cast(HFONT)-1) OS.SelectObject (hDC, hFont);
     if (ignoreCustomDraw || nmcd.nmcd.rc.left is nmcd.nmcd.rc.right) {
         return new LRESULT (hFont is cast(HFONT)-1 ? OS.CDRF_DODEFAULT : OS.CDRF_NEWFONT);
     }
-    int count = 0;
     RECT* clipRect = null;
-    if (hwndHeader !is null) {
-        count = OS.SendMessage (hwndHeader, OS.HDM_GETITEMCOUNT, 0, 0);
-        if (count !is 0) {
-            bool clip = !printClient;
-            if (!OS.IsWinCE && OS.WIN32_VERSION >= OS.VERSION (6, 0)) {
-                clip = true;
-            }
-            if (clip) {
-                clipRect = new RECT ();
-                HDITEM hdItem;
-                hdItem.mask = OS.HDI_WIDTH;
-                OS.SendMessage (hwndHeader, OS.HDM_GETITEM, index, &hdItem);
-                OS.SetRect (clipRect, nmcd.nmcd.rc.left, nmcd.nmcd.rc.top, nmcd.nmcd.rc.left + hdItem.cxy, nmcd.nmcd.rc.bottom);
-            }
+    if (columnCount !is 0) {
+        bool clip = !printClient;
+        if (!OS.IsWinCE && OS.WIN32_VERSION >= OS.VERSION (6, 0)) {
+            clip = true;
+        }
+        if (clip) {
+            clipRect = new RECT ();
+            HDITEM hdItem;
+            hdItem.mask = OS.HDI_WIDTH;
+            OS.SendMessage (hwndHeader, OS.HDM_GETITEM, index, &hdItem);
+            OS.SetRect (clipRect, nmcd.nmcd.rc.left, nmcd.nmcd.rc.top, nmcd.nmcd.rc.left + hdItem.cxy, nmcd.nmcd.rc.bottom);
         }
     }
     int clrText = -1, clrTextBk = -1;
@@ -1034,6 +1004,7 @@
     }
     bool selected = isItemSelected (nmcd);
     bool hot = explorerTheme && (nmcd.nmcd.uItemState & OS.CDIS_HOT) !is 0;
+    bool focused = explorerTheme && (nmcd.nmcd.uItemState & OS.CDIS_FOCUS) !is 0;
     if (OS.IsWindowVisible (handle) && nmcd.nmcd.rc.left < nmcd.nmcd.rc.right && nmcd.nmcd.rc.top < nmcd.nmcd.rc.bottom) {
         if (hFont !is cast(HFONT)-1) OS.SelectObject (hDC, hFont);
         if (linesVisible) {
@@ -1042,49 +1013,25 @@
             OS.DrawEdge (hDC, &rect, OS.BDR_SUNKENINNER, OS.BF_BOTTOM);
         }
         //TODO - BUG - measure and erase sent when first column is clipped
+        Event measureEvent = null;
         if (hooks (DWT.MeasureItem)) {
-            RECT itemRect = item.getBounds (index, true, true, false, false, false, hDC);
-            int nSavedDC = OS.SaveDC (hDC);
-            GCData data = new GCData ();
-            data.device = display;
-            data.hFont = hFont;
-            GC gc = GC.win32_new (hDC, data);
-            Event event = new Event ();
-            event.item = item;
-            event.gc = gc;
-            event.index = index;
-            event.x = itemRect.left;
-            event.y = itemRect.top;
-            event.width = itemRect.right - itemRect.left;
-            event.height = itemRect.bottom - itemRect.top;
-            sendEvent (DWT.MeasureItem, event);
-            event.gc = null;
-            gc.dispose ();
-            OS.RestoreDC (hDC, nSavedDC);
+            measureEvent = sendMeasureItemEvent (item, index, hDC);
             if (isDisposed () || item.isDisposed ()) return null;
-            if (hwndHeader !is null) {
-                if (count is 0) {
-                    if (event.x + event.width > scrollWidth) {
-                        setScrollWidth (scrollWidth = event.x + event.width);
-                    }
-                }
-            }
-            if (event.height > getItemHeight ()) setItemHeight (event.height);
         }
         selectionForeground = -1;
         ignoreDrawForeground = ignoreDrawBackground = ignoreDrawSelection = ignoreDrawFocus = ignoreDrawHot = ignoreFullSelection = false;
         if (hooks (DWT.EraseItem)) {
             RECT rect;
             OS.SetRect (&rect, nmcd.nmcd.rc.left, nmcd.nmcd.rc.top, nmcd.nmcd.rc.right, nmcd.nmcd.rc.bottom);
-            if (OS.IsWindowEnabled (handle) || findImageControl () !is null) {
-                drawBackground (hDC, &rect);
-            } else {
-                fillBackground (hDC, OS.GetBkColor (hDC), &rect);
-            }
             RECT cellRect = item.getBounds (index, true, true, true, true, true, hDC);
             if (clrSortBk !is -1) {
-                RECT fullRect = item.getBounds (index, true, true, true, true, true, hDC);
-                drawBackground (hDC, &fullRect, clrSortBk);
+                drawBackground (hDC, &cellRect, clrSortBk);
+            } else {
+                if (OS.IsWindowEnabled (handle) || findImageControl () !is null) {
+                    drawBackground (hDC, &rect);
+                } else {
+                    fillBackground (hDC, OS.GetBkColor (hDC), &rect);
+                }
             }
             int nSavedDC = OS.SaveDC (hDC);
             GCData data = new GCData ();
@@ -1100,7 +1047,7 @@
                 if (clrTextBk !is -1) data.background = clrTextBk;
             }
             data.uiState = OS.SendMessage (handle, OS.WM_QUERYUISTATE, 0, 0);
-            if (hFont !is cast(HFONT)-1) data.hFont = hFont;
+            data.font = item.getFont (index);
             GC gc = GC.win32_new (hDC, data);
             Event event = new Event ();
             event.index = index;
@@ -1115,7 +1062,10 @@
                 if (OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_CARET, 0) is nmcd.nmcd.dwItemSpec) {
                     if (handle is OS.GetFocus ()) {
                         int uiState = OS.SendMessage (handle, OS.WM_QUERYUISTATE, 0, 0);
-                        if ((uiState & OS.UISF_HIDEFOCUS) is 0) event.detail |= DWT.FOCUSED;
+                        if ((uiState & OS.UISF_HIDEFOCUS) is 0) {
+                            focused = true;
+                            event.detail |= DWT.FOCUSED;
+                        }
                     }
                 }
             }
@@ -1144,11 +1094,14 @@
                 bool draw = !selected && !hot;
                 if (!explorerTheme && selected) draw = !ignoreDrawSelection;
                 if (draw) {
-                    if (count is 0) {
+                    if (columnCount is 0) {
                         if ((style & DWT.FULL_SELECTION) !is 0) {
                             fillBackground (hDC, clrTextBk, &rect);
                         } else {
-                            RECT textRect = item.getBounds (index, true, false, true, false, true, hDC);
+                            RECT textRect = item.getBounds (index, true, false, false, false, true, hDC);
+                            if (measureEvent !is null) {
+                                textRect.right = Math.min (cellRect.right, measureEvent.x + measureEvent.width);
+                            }
                             fillBackground (hDC, clrTextBk, &textRect);
                         }
                     } else {
@@ -1161,7 +1114,25 @@
                 if (!selected && !hot) {
                     selectionForeground = clrText = OS.GetSysColor (OS.COLOR_HIGHLIGHTTEXT);
                 }
-                if (!explorerTheme) {
+                if (explorerTheme) {
+                    if ((style & DWT.FULL_SELECTION) is 0) {
+                        RECT pRect = item.getBounds (index, true, true, false, false, false, hDC);
+                        RECT pClipRect = item.getBounds (index, true, true, true, false, true, hDC);
+                        if (measureEvent !is null) {
+                            pRect.right = Math.min (pClipRect.right, measureEvent.x + measureEvent.width);
+                        } else {
+                            pRect.right += EXPLORER_EXTRA;
+                            pClipRect.right += EXPLORER_EXTRA;
+                        }
+                        pRect.left -= EXPLORER_EXTRA;
+                        pClipRect.left -= EXPLORER_EXTRA;
+                        auto hTheme = OS.OpenThemeData (handle, Display.TREEVIEW.ptr);
+                        int iStateId = selected ? OS.TREIS_SELECTED : OS.TREIS_HOT;
+                        if (OS.GetFocus () !is handle && selected && !hot) iStateId = OS.TREIS_SELECTEDNOTFOCUS;
+                        OS.DrawThemeBackground (hTheme, hDC, OS.TVP_TREEITEM, iStateId, &pRect, &pClipRect);
+                        OS.CloseThemeData (hTheme);
+                    }
+                } else {
                     /*
                     * Feature in Windows.  When the tree has the style
                     * TVS_FULLROWSELECT, the background color for the
@@ -1170,13 +1141,16 @@
                     * is to emulate TVS_FULLROWSELECT.
                     */
                     if ((style & DWT.FULL_SELECTION) !is 0) {
-                        if ((style & DWT.FULL_SELECTION) !is 0 && count is 0) {
+                        if ((style & DWT.FULL_SELECTION) !is 0 && columnCount is 0) {
                             fillBackground (hDC, OS.GetBkColor (hDC), &rect);
                         } else {
                             fillBackground (hDC, OS.GetBkColor (hDC), &cellRect);
                         }
                     } else {
                         RECT textRect = item.getBounds (index, true, false, false, false, true, hDC);
+                        if (measureEvent !is null) {
+                            textRect.right = Math.min (cellRect.right, measureEvent.x + measureEvent.width);
+                        }
                         fillBackground (hDC, OS.GetBkColor (hDC), &textRect);
                     }
                 }
@@ -1203,6 +1177,16 @@
                     OS.MoveMemory (lParam, nmcd, NMTVCUSTOMDRAW.sizeof);
                 }
             }
+            if (focused && !ignoreDrawFocus && (style & DWT.FULL_SELECTION) is 0) {
+                RECT textRect = item.getBounds (index, true, explorerTheme, false, false, true, hDC);
+                if (measureEvent !is null) {
+                    textRect.right = Math.min (cellRect.right, measureEvent.x + measureEvent.width);
+                }
+                nmcd.nmcd.uItemState &= ~OS.CDIS_FOCUS;
+                OS.MoveMemory (lParam, nmcd, NMTVCUSTOMDRAW.sizeof);
+                if( focusRect is null ) focusRect = new RECT;
+                *focusRect = textRect;
+            }
             if (explorerTheme) {
                 if (selected || (hot && ignoreDrawHot)) nmcd.nmcd.uItemState &= ~OS.CDIS_HOT;
                 OS.MoveMemory (cast(void*)lParam, nmcd, NMTVCUSTOMDRAW.sizeof);
@@ -1260,7 +1244,7 @@
             if (clrTextBk !is -1) {
                 int bits = OS.GetWindowLong (handle, OS.GWL_STYLE);
                 if ((bits & OS.TVS_FULLROWSELECT) is 0) {
-                    if (count !is 0 && hwndHeader !is null) {
+                    if (columnCount !is 0 && hwndHeader !is null) {
                         RECT rect;
                         HDITEM hdItem;
                         hdItem.mask = OS.HDI_WIDTH;
@@ -1268,8 +1252,7 @@
                         OS.SetRect (&rect, nmcd.nmcd.rc.left, nmcd.nmcd.rc.top, nmcd.nmcd.rc.left + hdItem.cxy, nmcd.nmcd.rc.bottom);
                         if (OS.COMCTL32_MAJOR < 6 || !OS.IsAppThemed ()) {
                             RECT itemRect;
-                            itemRect.left = cast(int) item.handle;
-                            if (OS.SendMessage (handle, OS.TVM_GETITEMRECT, 1, &itemRect) !is 0) {
+                            if (OS.TreeView_GetItemRect (handle, item.handle, &itemRect, true)) {
                                 rect.left = Math.min (itemRect.left, rect.right);
                             }
                         }
@@ -1329,7 +1312,7 @@
                     if (clrTextBk !is -1) {
                         if ((style & DWT.FULL_SELECTION) !is 0) {
                             RECT rect;
-                            if (count !is 0) {
+                            if (columnCount !is 0) {
                                 HDITEM hdItem;
                                 hdItem.mask = OS.HDI_WIDTH;
                                 OS.SendMessage (hwndHeader, OS.HDM_GETITEM, index, &hdItem);
@@ -1406,8 +1389,7 @@
                         }
                         if (hItem !is null) {
                             RECT rect;
-                            rect.left = cast(int) hItem;
-                            if (OS.SendMessage (handle, OS.TVM_GETITEMRECT, 0, &rect) !is 0) {
+                            if (OS.TreeView_GetItemRect (handle, hItem, &rect, false)) {
                                 top = rect.bottom;
                             }
                         }
@@ -1429,8 +1411,7 @@
                 RECT rect;
                 HDITEM hdItem;
                 hdItem.mask = OS.HDI_WIDTH;
-                int count = OS.SendMessage (hwndHeader, OS.HDM_GETITEMCOUNT, 0, 0);
-                for (int i=0; i<count; i++) {
+                for (int i=0; i<columnCount; i++) {
                     int index = OS.SendMessage (hwndHeader, OS.HDM_ORDERTOINDEX, i, 0);
                     OS.SendMessage (hwndHeader, OS.HDM_GETITEM, index, &hdItem);
                     OS.SetRect (&rect, x, nmcd.nmcd.rc.top, x + hdItem.cxy, nmcd.nmcd.rc.bottom);
@@ -1463,8 +1444,7 @@
                 hItem = cast(HANDLE) OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_LASTVISIBLE, 0);
             }
             if (hItem !is null) {
-                rect.left = cast(int) hItem;
-                if (OS.SendMessage (handle, OS.TVM_GETITEMRECT, 0, &rect) !is 0) {
+                if (OS.TreeView_GetItemRect (handle, hItem, &rect, false)) {
                     height = rect.bottom - rect.top;
                 }
             }
@@ -1591,7 +1571,7 @@
         }
         default:
     }
-    int code = OS.CallWindowProc (TreeProc, hwnd, msg, wParam, lParam);
+    int /*long*/ code = OS.CallWindowProc (TreeProc, hwnd, msg, wParam, lParam);
     switch (msg) {
         /* Keyboard messages */
         case OS.WM_KEYDOWN:
@@ -1665,7 +1645,7 @@
         OS.SendMessage (handle, OS.TVM_SETSCROLLTIME, 0, 0);
     }
     if (EXPLORER_THEME) {
-        if (!OS.IsWinCE && OS.WIN32_VERSION >= OS.VERSION (6, 0)) {
+        if (!OS.IsWinCE && OS.WIN32_VERSION >= OS.VERSION (6, 0) && OS.IsAppThemed ()) {
             int exStyle = OS.SendMessage (handle, OS.TVM_GETEXTENDEDSTYLE, 0, 0);
             if ((exStyle & OS.TVS_EX_DOUBLEBUFFER) !is 0) style |= DWT.DOUBLE_BUFFERED;
         }
@@ -1674,8 +1654,11 @@
 
 bool checkData (TreeItem item, bool redraw) {
     if ((style & DWT.VIRTUAL) is 0) return true;
-    TreeItem parentItem = item.getParentItem ();
-    return checkData (item, parentItem is null ? indexOf (item) : parentItem.indexOf (item), redraw);
+    if (!item.cached) {
+        TreeItem parentItem = item.getParentItem ();
+        return checkData (item, parentItem is null ? indexOf (item) : parentItem.indexOf (item), redraw);
+    }
+    return true;
 }
 
 bool checkData (TreeItem item, int index, bool redraw) {
@@ -1713,8 +1696,8 @@
     * callers of this method.
     */
     if (drawCount is 0) return false;
-    int hRoot = OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_ROOT, 0);
-    int hParent = OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_PARENT, hItem);
+    int /*long*/ hRoot = OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_ROOT, 0);
+    int /*long*/ hParent = OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_PARENT, hItem);
     while (hParent !is hRoot && hParent !is 0) {
         hParent = OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_PARENT, hParent);
     }
@@ -1770,6 +1753,7 @@
         item = tvItem.lParam !is -1 ? items [tvItem.lParam] : null;
     }
     if (item !is null) {
+        if ((style & DWT.VIRTUAL) !is 0 && !item.cached) return;
         item.clear ();
         item.redraw ();
     }
@@ -1798,16 +1782,30 @@
     checkWidget ();
     HANDLE hItem = cast(HANDLE) OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_ROOT, 0);
     if (hItem is null) return;
-    TVITEM tvItem;
-    tvItem.mask = OS.TVIF_HANDLE | OS.TVIF_PARAM;
-    clearAll (hItem, &tvItem, all);
+    if (all) {
+        bool redraw = false;
+        for (int i=0; i<items.length; i++) {
+            TreeItem item = items [i];
+            if (item !is null && item !is currentItem) {
+                item.clear ();
+                redraw = true;
+            }
+        }
+        if (redraw) OS.InvalidateRect (handle, null, true);
+    } else {
+        TVITEM tvItem;
+        tvItem.mask = OS.TVIF_HANDLE | OS.TVIF_PARAM;
+        clearAll (hItem, &tvItem, all);
+    }
 }
 
 void clearAll (HANDLE hItem, TVITEM* tvItem, bool all) {
     while (hItem !is null) {
         clear (hItem, tvItem);
-        auto hFirstItem = cast(HANDLE) OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_CHILD, hItem);
-        if (all) clearAll (hFirstItem, tvItem, all);
+        if (all) {
+            auto hFirstItem = cast(HANDLE)OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_CHILD, hItem);
+            clearAll (hFirstItem, tvItem, all);
+        }
         hItem = cast(HANDLE) OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_NEXT, hItem);
     }
 }
@@ -1827,8 +1825,7 @@
     if (hwndHeader !is null) {
         HDITEM hdItem;
         hdItem.mask = OS.HDI_WIDTH;
-        int count = OS.SendMessage (hwndHeader, OS.HDM_GETITEMCOUNT, 0, 0);
-        for (int i=0; i<count; i++) {
+        for (int i=0; i<columnCount; i++) {
             OS.SendMessage (hwndHeader, OS.HDM_GETITEM, i, &hdItem);
             width += hdItem.cxy;
         }
@@ -1848,12 +1845,11 @@
             OS.SendMessage (handle, OS.TVM_SETITEM, 0, &tvItem);
             ignoreCustomDraw = false;
         }
-        rect.left = cast(int) hItem;
-        if (OS.SendMessage (handle, OS.TVM_GETITEMRECT, 1, &rect) !is 0) {
+        if (OS.TreeView_GetItemRect (handle, hItem, &rect, true)) {
             width = Math.max (width, rect.right);
             height += rect.bottom - rect.top;
         }
-        hItem = cast(HANDLE) OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_NEXT, hItem);
+        hItem = cast(HANDLE) OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_NEXTVISIBLE, hItem);
     }
     if (width is 0) width = DEFAULT_WIDTH;
     if (height is 0) height = DEFAULT_HEIGHT;
@@ -1877,7 +1873,7 @@
 
     /* Use the Explorer theme */
     if (EXPLORER_THEME) {
-        if (!OS.IsWinCE && OS.WIN32_VERSION >= OS.VERSION (6, 0)) {
+        if (!OS.IsWinCE && OS.WIN32_VERSION >= OS.VERSION (6, 0) && OS.IsAppThemed ()) {
             explorerTheme = true;
             OS.SetWindowTheme (handle, cast(TCHAR*) Display.EXPLORER, null);
             int bits = OS.TVS_EX_DOUBLEBUFFER | OS.TVS_EX_FADEINOUTEXPANDOS | OS.TVS_EX_RICHTOOLTIP;
@@ -1931,11 +1927,15 @@
 void createHeaderToolTips () {
     static if (OS.IsWinCE) return;
     if (headerToolTipHandle !is null) return;
+    int bits = 0;
+    if (OS.WIN32_VERSION >= OS.VERSION (4, 10)) {
+        if ((style & DWT.RIGHT_TO_LEFT) !is 0) bits |= OS.WS_EX_LAYOUTRTL;
+    }
     headerToolTipHandle = OS.CreateWindowEx (
-        0,
+        bits,
         OS.TOOLTIPS_CLASS.ptr,
         null,
-        0,
+        OS.TTS_NOPREFIX,
         OS.CW_USEDEFAULT, 0, OS.CW_USEDEFAULT, 0,
         handle,
         null,
@@ -1954,7 +1954,6 @@
 
 void createItem (TreeColumn column, int index) {
     if (hwndHeader is null) createParent ();
-    int columnCount = OS.SendMessage (hwndHeader, OS.HDM_GETITEMCOUNT, 0, 0);
     if (!(0 <= index && index <= columnCount)) error (DWT.ERROR_INVALID_RANGE);
     if (columnCount is columns.length) {
         TreeColumn [] newColumns = new TreeColumn [columns.length + 4];
@@ -2009,16 +2008,15 @@
                 item.cellForeground = temp;
             }
             if (item.cellFont !is null) {
-                HFONT [] cellFont = item.cellFont;
-                HFONT [] temp = new HFONT [columnCount + 1];
+                Font [] cellFont = item.cellFont;
+                Font [] temp = new Font [columnCount + 1];
                 System.arraycopy (cellFont, 0, temp, 0, index);
                 System.arraycopy (cellFont, index, temp, index + 1, columnCount- index);
-                temp [index] = cast(HFONT)-1;
                 item.cellFont = temp;
             }
         }
     }
-    System.arraycopy (columns, index, columns, index + 1, columnCount - index);
+    System.arraycopy (columns, index, columns, index + 1, columnCount++ - index);
     columns [index] = column;
 
     /*
@@ -2039,11 +2037,13 @@
     if (pszText !is null) OS.HeapFree (hHeap, 0, pszText);
 
     /* When the first column is created, hide the horizontal scroll bar */
-    if (columnCount is 0) {
+    if (columnCount is 1) {
         scrollWidth = 0;
-        int bits = OS.GetWindowLong (handle, OS.GWL_STYLE);
-        bits |= OS.TVS_NOHSCROLL;
-        OS.SetWindowLong (handle, OS.GWL_STYLE, bits);
+        if ((style & DWT.H_SCROLL) !is 0) {
+            int bits = OS.GetWindowLong (handle, OS.GWL_STYLE);
+            bits |= OS.TVS_NOHSCROLL;
+            OS.SetWindowLong (handle, OS.GWL_STYLE, bits);
+        }
         /*
         * Bug in Windows.  When TVS_NOHSCROLL is set after items
         * have been inserted into the tree, Windows shows the
@@ -2054,13 +2054,17 @@
         if (count !is 0) {
             static if (!OS.IsWinCE) OS.ShowScrollBar (handle, OS.SB_HORZ, false);
         }
+        createItemToolTips ();
+        if (itemToolTipHandle !is null) {
+            OS.SendMessage (itemToolTipHandle, OS.TTM_SETDELAYTIME, OS.TTDT_AUTOMATIC, -1);
+        }
     }
     setScrollWidth ();
     updateImageList ();
     updateScrollBar ();
 
     /* Redraw to hide the items when the first column is created */
-    if (columnCount is 0 && OS.SendMessage (handle, OS.TVM_GETCOUNT, 0, 0) !is 0) {
+    if (columnCount is 1 && OS.SendMessage (handle, OS.TVM_GETCOUNT, 0, 0) !is 0) {
         OS.InvalidateRect (handle, null, true);
     }
 
@@ -2148,12 +2152,9 @@
         items [id] = item;
     }
     if (hFirstItem is null) {
-        switch ( cast(int) hInsertAfter) {
-            case OS.TVI_FIRST:
-            case OS.TVI_LAST:
-                hFirstIndexOf = hLastIndexOf = hFirstItem = hNewItem;
-                itemCount = lastIndexOf = 0;
-            default:
+        if (cast(int)hInsertAfter is OS.TVI_FIRST || cast(int)hInsertAfter is OS.TVI_LAST) {
+            hFirstIndexOf = hLastIndexOf = hFirstItem = hNewItem;
+            itemCount = lastIndexOf = 0;
         }
     }
     if (hFirstItem is hFirstIndexOf && itemCount !is -1) itemCount++;
@@ -2168,8 +2169,7 @@
         if (fixParent) {
             if (drawCount is 0 && OS.IsWindowVisible (handle)) {
                 RECT rect;
-                rect.left = cast(int) hParent;
-                if (OS.SendMessage (handle, OS.TVM_GETITEMRECT, 0, &rect) !is 0) {
+                if (OS.TreeView_GetItemRect (handle, hParent, &rect, false)) {
                     OS.InvalidateRect (handle, &rect, true);
                 }
             }
@@ -2184,8 +2184,7 @@
         if ((style & DWT.VIRTUAL) !is 0) {
             if (currentItem !is null) {
                 RECT rect;
-                rect.left = cast(int) hNewItem;
-                if (OS.SendMessage (handle, OS.TVM_GETITEMRECT, 0, &rect) !is 0) {
+                if (OS.TreeView_GetItemRect (handle, hNewItem, &rect, false)) {
                     RECT damageRect;
                     bool damaged = cast(bool) OS.GetUpdateRect (handle, &damageRect, true);
                     if (damaged && damageRect.top < rect.bottom) {
@@ -2212,28 +2211,36 @@
 void createItemToolTips () {
     static if (OS.IsWinCE) return;
     if (itemToolTipHandle !is null) return;
-    int bits = OS.GetWindowLong (handle, OS.GWL_STYLE);
-    bits |= OS.TVS_NOTOOLTIPS;
-    OS.SetWindowLong (handle, OS.GWL_STYLE, bits);
+    int bits1 = OS.GetWindowLong (handle, OS.GWL_STYLE);
+    bits1 |= OS.TVS_NOTOOLTIPS;
+    OS.SetWindowLong (handle, OS.GWL_STYLE, bits1);
+    int bits2 = 0;
+    if (OS.WIN32_VERSION >= OS.VERSION (4, 10)) {
+        if ((style & DWT.RIGHT_TO_LEFT) !is 0) bits2 |= OS.WS_EX_LAYOUTRTL;
+    }
+    /*
+    * Feature in Windows.  For some reason, when the user
+    * clicks on a tool tip, it temporarily takes focus, even
+    * when WS_EX_NOACTIVATE is specified.  The fix is to
+    * use WS_EX_TRANSPARENT, even though WS_EX_TRANSPARENT
+    * is documented to affect painting, not hit testing.
+    *
+    * NOTE: Windows 2000 doesn't have the problem and
+    * setting WS_EX_TRANSPARENT causes pixel corruption.
+    */
+    if (OS.COMCTL32_MAJOR >= 6) bits2 |= OS.WS_EX_TRANSPARENT;
     itemToolTipHandle = OS.CreateWindowEx (
-        0,
+        bits2,
         OS.TOOLTIPS_CLASS.ptr,
         null,
-        0,
+        OS.TTS_NOPREFIX | OS.TTS_NOANIMATE | OS.TTS_NOFADE,
         OS.CW_USEDEFAULT, 0, OS.CW_USEDEFAULT, 0,
         handle,
         null,
         OS.GetModuleHandle (null),
         null);
     if (itemToolTipHandle is null) error (DWT.ERROR_NO_HANDLES);
-    /*
-    * Feature in Windows.  Despite the fact that the
-    * tool tip text contains \r\n, the tooltip will
-    * not honour the new line unless TTM_SETMAXTIPWIDTH
-    * is set.  The fix is to set TTM_SETMAXTIPWIDTH to
-    * a large value.
-    */
-    OS.SendMessage (itemToolTipHandle, OS.TTM_SETMAXTIPWIDTH, 0, 0x7FFF);
+    OS.SendMessage (itemToolTipHandle, OS.TTM_SETDELAYTIME, OS.TTDT_INITIAL, 0);
     TOOLINFO lpti;
     lpti.cbSize = TOOLINFO.sizeof;
     lpti.hwnd = handle;
@@ -2266,7 +2273,7 @@
         OS.GetModuleHandle (null),
         null);
     if (hwndParent is null) error (DWT.ERROR_NO_HANDLES);
-    OS.SetWindowLong (hwndParent, OS.GWL_ID, cast(int) hwndParent);
+    OS.SetWindowLongPtr (hwndParent, OS.GWLP_ID, cast(LONG_PTR)hwndParent);
     int bits = 0;
     if (OS.WIN32_VERSION >= OS.VERSION (4, 10)) {
         bits |= OS.WS_EX_NOINHERITLAYOUT;
@@ -2283,7 +2290,7 @@
         OS.GetModuleHandle (null),
         null);
     if (hwndHeader is null) error (DWT.ERROR_NO_HANDLES);
-    OS.SetWindowLong (hwndHeader, OS.GWL_ID, cast(int) hwndHeader);
+    OS.SetWindowLongPtr (hwndHeader, OS.GWLP_ID, cast(LONG_PTR)hwndHeader);
     if (OS.IsDBLocale) {
         auto hIMC = OS.ImmGetContext (handle);
         OS.ImmAssociateContext (hwndParent, hIMC);
@@ -2323,7 +2330,6 @@
     if (hwndFocus is handle) OS.SetFocus (handle);
     register ();
     subclass ();
-    createItemToolTips ();
 }
 
 override void createWidget () {
@@ -2356,6 +2362,34 @@
 }
 
 /**
+ * Deselects an item in the receiver.  If the item was already
+ * deselected, it remains deselected.
+ *
+ * @param item the item to be deselected
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the item is null</li>
+ *    <li>ERROR_INVALID_ARGUMENT - if the item has been disposed</li>
+ * </ul>
+ * @exception DWTException <ul>
+ *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+ *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
+ * </ul>
+ *
+ * @since 3.4
+ */
+public void deselect (TreeItem item) {
+    checkWidget ();
+    if (item is null) error (DWT.ERROR_NULL_ARGUMENT);
+    if (item.isDisposed ()) error (DWT.ERROR_INVALID_ARGUMENT);
+    TVITEM tvItem;
+    tvItem.mask = OS.TVIF_HANDLE | OS.TVIF_STATE;
+    tvItem.stateMask = OS.TVIS_SELECTED;
+    tvItem.hItem = item.handle;
+    OS.SendMessage (handle, OS.TVM_SETITEM, 0, cast(int)&tvItem);
+}
+
+/**
  * Deselects all selected items in the receiver.
  *
  * @exception DWTException <ul>
@@ -2375,8 +2409,8 @@
             OS.SendMessage (handle, OS.TVM_SETITEM, 0, &tvItem);
         }
     } else {
-        int oldProc = OS.GetWindowLong (handle, OS.GWL_WNDPROC);
-        OS.SetWindowLong (handle, OS.GWL_WNDPROC, cast(int) TreeProc);
+        auto oldProc = OS.GetWindowLongPtr (handle, OS.GWLP_WNDPROC);
+        OS.SetWindowLongPtr (handle, OS.GWLP_WNDPROC, cast(LONG_PTR)TreeProc);
         if ((style & DWT.VIRTUAL) !is 0) {
             HANDLE hItem = cast(HANDLE) OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_ROOT, 0);
             deselect (hItem, &tvItem, null);
@@ -2389,13 +2423,12 @@
                 }
             }
         }
-        OS.SetWindowLong (handle, OS.GWL_WNDPROC, oldProc);
+        OS.SetWindowLongPtr (handle, OS.GWLP_WNDPROC, oldProc);
     }
 }
 
 void destroyItem (TreeColumn column) {
     if (hwndHeader is null) error (DWT.ERROR_ITEM_NOT_REMOVED);
-    int columnCount = OS.SendMessage (hwndHeader, OS.HDM_GETITEMCOUNT, 0, 0);
     int index = 0;
     while (index < columnCount) {
         if (columns [index] is column) break;
@@ -2462,8 +2495,8 @@
                     item.cellForeground = temp;
                 }
                 if (item.cellFont !is null) {
-                    HFONT [] cellFont = item.cellFont;
-                    HFONT [] temp = new HFONT [columnCount];
+                    Font [] cellFont = item.cellFont;
+                    Font [] temp = new Font [columnCount];
                     System.arraycopy (cellFont, 0, temp, 0, index);
                     System.arraycopy (cellFont, index + 1, temp, index, columnCount - index);
                     item.cellFont = temp;
@@ -2481,10 +2514,13 @@
         scrollWidth = 0;
         if (!hooks (DWT.MeasureItem)) {
             int bits = OS.GetWindowLong (handle, OS.GWL_STYLE);
-            bits &= ~OS.TVS_NOHSCROLL;
+            if ((style & DWT.H_SCROLL) !is 0) bits &= ~OS.TVS_NOHSCROLL;
             OS.SetWindowLong (handle, OS.GWL_STYLE, bits);
             OS.InvalidateRect (handle, null, true);
         }
+        if (itemToolTipHandle !is null) {
+            OS.SendMessage (itemToolTipHandle, OS.TTM_SETDELAYTIME, OS.TTDT_INITIAL, 0);
+        }
     } else {
         if (index is 0) {
             columns [0].style &= ~(DWT.LEFT | DWT.RIGHT | DWT.CENTER);
@@ -2552,8 +2588,7 @@
     if ((style & DWT.DOUBLE_BUFFERED) is 0) {
         if (drawCount is 0 && OS.IsWindowVisible (handle)) {
             RECT rect;
-            rect.left = cast(int) hItem;
-            fixRedraw = OS.SendMessage (handle, OS.TVM_GETITEMRECT, 0, &rect) is 0;
+            fixRedraw = !OS.TreeView_GetItemRect (handle, hItem, &rect, false);
         }
     }
     if (fixRedraw) {
@@ -2599,8 +2634,7 @@
         */
         if (OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_CHILD, hParent) is 0) {
             RECT rect;
-            rect.left = cast(int) hParent;
-            if (OS.SendMessage (handle, OS.TVM_GETITEMRECT, 0, &rect) !is 0) {
+            if (OS.TreeView_GetItemRect (handle, hParent, &rect, false)) {
                 OS.InvalidateRect (handle, &rect, true);
             }
         }
@@ -2624,6 +2658,21 @@
     updateScrollBar ();
 }
 
+void destroyScrollBar (int type) {
+    super.destroyScrollBar (type);
+    int bits = OS.GetWindowLong (handle, OS.GWL_STYLE);
+    if ((style & (DWT.H_SCROLL | DWT.V_SCROLL)) is 0) {
+        bits &= ~(OS.WS_HSCROLL | OS.WS_VSCROLL);
+        bits |= OS.TVS_NOSCROLL;
+    } else {
+        if ((style & DWT.H_SCROLL) is 0) {
+            bits &= ~OS.WS_HSCROLL;
+            bits |= OS.TVS_NOHSCROLL;
+        }
+    }
+    OS.SetWindowLong (handle, OS.GWL_STYLE, bits);
+}
+
 override void enableDrag (bool enabled) {
     int bits = OS.GetWindowLong (handle, OS.GWL_STYLE);
     if (enabled && hooks (DWT.DragDetect)) {
@@ -2672,6 +2721,66 @@
     updateFullSelection ();
 }
 
+bool findCell (int x, int y, inout TreeItem item, inout int index, inout RECT cellRect, inout RECT itemRect) {
+    bool found = false;
+    TVHITTESTINFO lpht;
+    lpht.pt.x = x;
+    lpht.pt.y = y;
+    OS.SendMessage (handle, OS.TVM_HITTEST, 0, &lpht);
+    if (lpht.hItem !is null) {
+        item = _getItem (lpht.hItem);
+        POINT pt;
+        pt.x = x;
+        pt.y = y;
+        auto hDC = OS.GetDC (handle);
+        HFONT oldFont;
+        auto newFont = cast(HFONT)OS.SendMessage (handle, OS.WM_GETFONT, 0, 0);
+        if (newFont !is null) oldFont = OS.SelectObject (hDC, newFont);
+        RECT rect;
+        if (hwndParent !is null) {
+            OS.GetClientRect (hwndParent, &rect);
+            OS.MapWindowPoints (hwndParent, handle, cast(POINT*)&rect, 2);
+        } else {
+            OS.GetClientRect (handle, &rect);
+        }
+        int count = Math.max (1, columnCount);
+        int [] order = new int [count];
+        if (hwndHeader !is null) OS.SendMessage (hwndHeader, OS.HDM_GETORDERARRAY, count, cast(int) order.ptr);
+        index = 0;
+        bool quit = false;
+        while (index < count && !quit) {
+            auto hFont = item.fontHandle (order [index]);
+            if (hFont !is cast(HFONT)-1) hFont = OS.SelectObject (hDC, hFont);
+            cellRect = item.getBounds (order [index], true, false, true, false, true, hDC);
+            if (cellRect.left > rect.right) {
+                quit = true;
+            } else {
+                cellRect.right = Math.min (cellRect.right, rect.right);
+                if (OS.PtInRect ( &cellRect, pt)) {
+                    if (isCustomToolTip ()) {
+                        Event event = sendMeasureItemEvent (item, order [index], hDC);
+                        if (isDisposed () || item.isDisposed ()) break;
+                        //itemRect [0] = new RECT ();
+                        itemRect.left = event.x;
+                        itemRect.right = event.x + event.width;
+                        itemRect.top = event.y;
+                        itemRect.bottom = event.y + event.height;
+                    } else {
+                        itemRect = item.getBounds (order [index], true, false, false, false, false, hDC);
+                    }
+                    if (itemRect.right > cellRect.right) found = true;
+                    quit = true;
+                }
+            }
+            if (hFont !is cast(HFONT)-1) OS.SelectObject (hDC, hFont);
+            if (!found) index++;
+        }
+        if (newFont !is null) OS.SelectObject (hDC, oldFont);
+        OS.ReleaseDC (handle, hDC);
+    }
+    return found;
+}
+
 int findIndex (HANDLE hFirstItem, HANDLE hItem) {
     if (hFirstItem is null) return -1;
     if (hFirstItem is hFirstIndexOf) {
@@ -2903,9 +3012,7 @@
  */
 public TreeColumn getColumn (int index) {
     checkWidget ();
-    if (hwndHeader is null) error (DWT.ERROR_INVALID_RANGE);
-    int count = OS.SendMessage (hwndHeader, OS.HDM_GETITEMCOUNT, 0, 0);
-    if (!(0 <= index && index < count)) error (DWT.ERROR_INVALID_RANGE);
+    if (!(0 <= index && index < columnCount)) error (DWT.ERROR_INVALID_RANGE);
     return columns [index];
 }
 
@@ -2927,8 +3034,7 @@
  */
 public int getColumnCount () {
     checkWidget ();
-    if (hwndHeader is null) return 0;
-    return OS.SendMessage (hwndHeader, OS.HDM_GETITEMCOUNT, 0, 0);
+    return columnCount;
 }
 
 /**
@@ -2961,10 +3067,9 @@
  */
 public int[] getColumnOrder () {
     checkWidget ();
-    if (hwndHeader is null) return new int [0];
-    int count = OS.SendMessage (hwndHeader, OS.HDM_GETITEMCOUNT, 0, 0);
-    int [] order = new int [count];
-    OS.SendMessage (hwndHeader, OS.HDM_GETORDERARRAY, count, order.ptr);
+    if (columnCount is 0) return null;
+    int [] order = new int [columnCount];
+    OS.SendMessage (hwndHeader, OS.HDM_GETORDERARRAY, columnCount, order.ptr);
     return order;
 }
 
@@ -2999,10 +3104,8 @@
  */
 public TreeColumn [] getColumns () {
     checkWidget ();
-    if (hwndHeader is null) return new TreeColumn [0];
-    int count = OS.SendMessage (hwndHeader, OS.HDM_GETITEMCOUNT, 0, 0);
-    TreeColumn [] result = new TreeColumn [count];
-    System.arraycopy (columns, 0, result, 0, count);
+    TreeColumn [] result = new TreeColumn [columnCount];
+    System.arraycopy (columns, 0, result, 0, columnCount);
     return result;
 }
 
@@ -3086,9 +3189,18 @@
     lpht.pt.y = point.y;
     OS.SendMessage (handle, OS.TVM_HITTEST, 0, &lpht);
     if (lpht.hItem !is null) {
-        if ((style & DWT.FULL_SELECTION) !is 0 || (lpht.flags & OS.TVHT_ONITEM) !is 0) {
-            return _getItem (lpht.hItem);
-        }
+        int flags = OS.TVHT_ONITEM;
+        if ((style & DWT.FULL_SELECTION) !is 0) {
+            flags |= OS.TVHT_ONITEMRIGHT | OS.TVHT_ONITEMINDENT;
+        } else {
+            if (hooks (DWT.MeasureItem)) {
+                lpht.flags &= ~(OS.TVHT_ONITEMICON | OS.TVHT_ONITEMLABEL);
+                if (hitTestSelection ( lpht.hItem, lpht.pt.x, lpht.pt.y)) {
+                    lpht.flags |= OS.TVHT_ONITEMICON | OS.TVHT_ONITEMLABEL;
+                }
+            }
+        }
+        if ((lpht.flags & flags) !is 0) return _getItem (lpht.hItem);
     }
     return null;
 }
@@ -3328,8 +3440,8 @@
     }
     int count = 0;
     TreeItem [] guess = new TreeItem [(style & DWT.VIRTUAL) !is 0 ? 8 : 1];
-    int oldProc = OS.GetWindowLong (handle, OS.GWL_WNDPROC);
-    OS.SetWindowLong (handle, OS.GWL_WNDPROC, cast(int) TreeProc);
+    int /*long*/ oldProc = OS.GetWindowLongPtr (handle, OS.GWLP_WNDPROC);
+    OS.SetWindowLongPtr (handle, OS.GWLP_WNDPROC, cast(LONG_PTR)TreeProc);
     if ((style & DWT.VIRTUAL) !is 0) {
         TVITEM tvItem;
         tvItem.mask = OS.TVIF_HANDLE | OS.TVIF_PARAM | OS.TVIF_STATE;
@@ -3360,7 +3472,7 @@
             }
         }
     }
-    OS.SetWindowLong (handle, OS.GWL_WNDPROC, oldProc);
+    OS.SetWindowLongPtr (handle, OS.GWLP_WNDPROC, oldProc);
     if (count is 0) return new TreeItem [0];
     if (count is guess.length) return guess;
     TreeItem [] result = new TreeItem [count];
@@ -3368,7 +3480,7 @@
         System.arraycopy (guess, 0, result, 0, count);
         return result;
     }
-    OS.SetWindowLong (handle, OS.GWL_WNDPROC, cast(int) TreeProc);
+    OS.SetWindowLongPtr (handle, OS.GWLP_WNDPROC, cast(LONG_PTR)TreeProc);
     TVITEM tvItem;
     tvItem.mask = OS.TVIF_HANDLE | OS.TVIF_PARAM | OS.TVIF_STATE;
     HANDLE hItem = cast(HANDLE) OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_ROOT, 0);
@@ -3377,7 +3489,7 @@
     if (count !is getSelection (hItem, &tvItem, result, 0, count, bigSelection, false)) {
         getSelection (hItem, &tvItem, result, 0, count, bigSelection, true);
     }
-    OS.SetWindowLong (handle, OS.GWL_WNDPROC, oldProc);
+    OS.SetWindowLongPtr (handle, OS.GWLP_WNDPROC, oldProc);
     return result;
 }
 
@@ -3409,14 +3521,14 @@
         return (state & OS.TVIS_SELECTED) is 0 ? 0 : 1;
     }
     int count = 0;
-    int oldProc = OS.GetWindowLong (handle, OS.GWL_WNDPROC);
+    int /*long*/ oldProc = OS.GetWindowLongPtr (handle, OS.GWLP_WNDPROC);
     TVITEM tvItem_;
     TVITEM* tvItem = null;
     static if (OS.IsWinCE) {
         tvItem = &tvitem_;
         tvItem.mask = OS.TVIF_STATE;
     }
-    OS.SetWindowLong (handle, OS.GWL_WNDPROC, cast(int) TreeProc);
+    OS.SetWindowLongPtr (handle, OS.GWLP_WNDPROC, cast(LONG_PTR)TreeProc);
     if ((style & DWT.VIRTUAL) !is 0) {
         HANDLE hItem = cast(HANDLE) OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_ROOT, 0);
         count = getSelection (hItem, tvItem, null, 0, -1, false, true);
@@ -3437,7 +3549,7 @@
             }
         }
     }
-    OS.SetWindowLong (handle, OS.GWL_WNDPROC, oldProc);
+    OS.SetWindowLongPtr (handle, OS.GWLP_WNDPROC, oldProc);
     return count;
 }
 
@@ -3520,6 +3632,30 @@
     return hItem !is null ? _getItem (hItem) : null;
 }
 
+bool hitTestSelection (HANDLE hItem, int x, int y) {
+    if (hItem is null) return false;
+    TreeItem item = _getItem (hItem);
+    if (item is null) return false;
+    if (!hooks (DWT.MeasureItem)) return false;
+    bool result = false;
+
+    //BUG? - moved columns, only hittest first column
+    //BUG? - check drag detect
+    int [] order = new int [1], index = new int [1];
+
+    auto hDC = OS.GetDC (handle);
+    HFONT oldFont, newFont = cast(HFONT)OS.SendMessage (handle, OS.WM_GETFONT, 0, 0);
+    if (newFont !is null) oldFont = OS.SelectObject (hDC, newFont);
+    auto hFont = item.fontHandle (order [index [0]]);
+    if (hFont !is cast(HFONT)-1) hFont = OS.SelectObject (hDC, hFont);
+    Event event = sendMeasureItemEvent (item, order [index [0]], hDC);
+    if (event.getBounds ().contains (x, y)) result = true;
+    if (newFont !is null) OS.SelectObject (hDC, oldFont);
+    OS.ReleaseDC (handle, hDC);
+//  if (isDisposed () || item.isDisposed ()) return false;
+    return result;
+}
+
 int imageIndex (Image image, int index) {
     if (image is null) return OS.I_IMAGENONE;
     if (imageList is null) {
@@ -3529,6 +3665,11 @@
     int imageIndex = imageList.indexOf (image);
     if (imageIndex is -1) imageIndex = imageList.add (image);
     if (hwndHeader is null || OS.SendMessage (hwndHeader, OS.HDM_ORDERTOINDEX, 0, 0) is index) {
+        /*
+        * Feature in Windows.  When setting the same image list multiple
+        * times, Windows does work making this operation slow.  The fix
+        * is to test for the same image list before setting the new one.
+        */
         auto hImageList = imageList.getHandle ();
         auto hOldImageList = cast(HANDLE) OS.SendMessage (handle, OS.TVM_GETIMAGELIST, OS.TVSIL_NORMAL, 0);
         if (hOldImageList !is hImageList) {
@@ -3581,9 +3722,7 @@
     checkWidget ();
     if (column is null) error (DWT.ERROR_NULL_ARGUMENT);
     if (column.isDisposed()) error(DWT.ERROR_INVALID_ARGUMENT);
-    if (hwndHeader is null) return -1;
-    int count = OS.SendMessage (hwndHeader, OS.HDM_GETITEMCOUNT, 0, 0);
-    for (int i=0; i<count; i++) {
+    for (int i=0; i<columnCount; i++) {
         if (columns [i] is column) return i;
     }
     return -1;
@@ -3617,6 +3756,10 @@
     return hItem is null ? -1 : findIndex (hItem, item.handle);
 }
 
+bool isCustomToolTip () {
+    return hooks (DWT.MeasureItem);
+}
+
 bool isItemSelected (NMTVCUSTOMDRAW* nmcd) {
     bool selected = false;
     if (OS.IsWindowEnabled (handle)) {
@@ -3686,9 +3829,9 @@
         HANDLE hItem = cast(HANDLE) OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_CARET, 0);
         if (hItem !is null) {
             RECT rect;
-            rect.left = cast(int) hItem;
-            OS.SendMessage (handle, OS.TVM_GETITEMRECT, 0, &rect);
-            OS.InvalidateRect (handle, &rect, true);
+            if (OS.TreeView_GetItemRect (handle, hItem, &rect, false)) {
+                OS.InvalidateRect (handle, &rect, true);
+            }
         }
     } else {
         HANDLE hItem = cast(HANDLE) OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_FIRSTVISIBLE, 0);
@@ -3710,9 +3853,9 @@
                     state = OS.SendMessage (handle, OS.TVM_GETITEMSTATE, hItem, OS.TVIS_SELECTED);
                 }
                 if ((state & OS.TVIS_SELECTED) !is 0) {
-                    rect.left = cast(int) hItem;
-                    OS.SendMessage (handle, OS.TVM_GETITEMRECT, 0, &rect);
-                    OS.InvalidateRect (handle, &rect, true);
+                    if (OS.TreeView_GetItemRect (handle, hItem, &rect, false)) {
+                        OS.InvalidateRect (handle, &rect, true);
+                    }
                 }
                 hItem = cast(HANDLE) OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_NEXTVISIBLE, hItem);
                 index++;
@@ -3808,12 +3951,6 @@
     if (itemToolTipHandle !is null) OS.DestroyWindow (itemToolTipHandle);
     if (headerToolTipHandle !is null) OS.DestroyWindow (headerToolTipHandle);
     itemToolTipHandle = headerToolTipHandle = null;
-    if (display.isXMouseActive ()) {
-        Shell shell = getShell ();
-        if (shell.lockToolTipControl is this) {
-            shell.lockToolTipControl = null;
-        }
-    }
 }
 
 /**
@@ -3838,7 +3975,7 @@
     bool redraw = drawCount is 0 && OS.IsWindowVisible (handle);
     if (redraw) OS.DefWindowProc (handle, OS.WM_SETREDRAW, 0, 0);
     shrink = ignoreShrink = true;
-    int result = OS.SendMessage (handle, OS.TVM_DELETEITEM, 0, OS.TVI_ROOT);
+    int /*long*/ result = OS.SendMessage (handle, OS.TVM_DELETEITEM, 0, OS.TVI_ROOT);
     ignoreShrink = false;
     if (redraw) {
         OS.DefWindowProc (handle, OS.WM_SETREDRAW, 1, 0);
@@ -3972,8 +4109,26 @@
         hItem = cast(HANDLE) OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_NEXT, hItem);
         itemCount++;
     }
+    bool expanded = false;
     TVITEM tvItem;
     tvItem.mask = OS.TVIF_HANDLE | OS.TVIF_PARAM;
+    if (!redraw && (style & DWT.VIRTUAL) !is 0) {
+        if (OS.IsWinCE) {
+            tvItem.hItem = hParent;
+            tvItem.mask = OS.TVIF_STATE;
+            OS.SendMessage (handle, OS.TVM_GETITEM, 0, cast(int)&tvItem);
+            expanded = (tvItem.state & OS.TVIS_EXPANDED) !is 0;
+        } else {
+            /*
+            * Bug in Windows.  Despite the fact that TVM_GETITEMSTATE claims
+            * to return only the bits specified by the stateMask, when called
+            * with TVIS_EXPANDED, the entire state is returned.  The fix is
+            * to explicitly check for the TVIS_EXPANDED bit.
+            */
+            int state = OS.SendMessage (handle, OS.TVM_GETITEMSTATE, hParent, OS.TVIS_EXPANDED);
+            expanded = (state & OS.TVIS_EXPANDED) !is 0;
+        }
+    }
     while (hItem !is null) {
         tvItem.hItem = hItem;
         OS.SendMessage (handle, OS.TVM_GETITEM, 0, &tvItem);
@@ -3988,7 +4143,9 @@
     }
     if ((style & DWT.VIRTUAL) !is 0) {
         for (int i=itemCount; i<count; i++) {
+            if (expanded) ignoreShrink = true;
             createItem (null, hParent, cast(HANDLE) OS.TVI_LAST, null);
+            if (expanded) ignoreShrink = false;
         }
     } else {
         shrink = true;
@@ -4053,8 +4210,7 @@
 
 override HWND scrolledHandle () {
     if (hwndHeader is null) return handle;
-    int count = OS.SendMessage (hwndHeader, OS.HDM_GETITEMCOUNT, 0, 0);
-    return count is 0 ? handle : hwndParent;
+    return columnCount is 0 && scrollWidth is 0 ? handle : hwndParent;
 }
 
 void select (HANDLE hItem, TVITEM* tvItem) {
@@ -4068,6 +4224,94 @@
 }
 
 /**
+ * Selects an item in the receiver.  If the item was already
+ * selected, it remains selected.
+ *
+ * @param item the item to be selected
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the item is null</li>
+ *    <li>ERROR_INVALID_ARGUMENT - if the item has been disposed</li>
+ * </ul>
+ * @exception DWTException <ul>
+ *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+ *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
+ * </ul>
+ *
+ * @since 3.4
+ */
+public void select (TreeItem item) {
+    checkWidget ();
+    if (item is null) error (DWT.ERROR_NULL_ARGUMENT);
+    if (item.isDisposed ()) error (DWT.ERROR_INVALID_ARGUMENT);
+    if ((style & DWT.SINGLE) !is 0) {
+        auto hItem = item.handle;
+        int state = 0;
+        static if (OS.IsWinCE) {
+            TVITEM tvItem;
+            tvItem.hItem = hItem;
+            tvItem.mask = OS.TVIF_STATE;
+            OS.SendMessage (handle, OS.TVM_GETITEM, 0, cast(int)&tvItem);
+            state = tvItem.state;
+        } else {
+            state = OS.SendMessage (handle, OS.TVM_GETITEMSTATE, cast(int)&hItem, OS.TVIS_SELECTED);
+        }
+        if ((state & OS.TVIS_SELECTED) !is 0) return;
+        /*
+        * Feature in Windows.  When an item is selected with
+        * TVM_SELECTITEM and TVGN_CARET, the tree expands and
+        * scrolls to show the new selected item.  Unfortunately,
+        * there is no other way in Windows to set the focus
+        * and select an item.  The fix is to save the current
+        * scroll bar positions, turn off redraw, select the item,
+        * then scroll back to the original position and redraw
+        * the entire tree.
+        */
+        SCROLLINFO* hInfo = null;
+        int bits = OS.GetWindowLong (handle, OS.GWL_STYLE);
+        if ((bits & (OS.TVS_NOHSCROLL | OS.TVS_NOSCROLL)) is 0) {
+            hInfo = new SCROLLINFO ();
+            hInfo.cbSize = SCROLLINFO.sizeof;
+            hInfo.fMask = OS.SIF_ALL;
+            OS.GetScrollInfo (handle, OS.SB_HORZ, hInfo);
+        }
+        SCROLLINFO vInfo;
+        vInfo.cbSize = SCROLLINFO.sizeof;
+        vInfo.fMask = OS.SIF_ALL;
+        OS.GetScrollInfo (handle, OS.SB_VERT, &vInfo);
+        bool redraw = drawCount is 0 && OS.IsWindowVisible (handle);
+        if (redraw) {
+            OS.UpdateWindow (handle);
+            OS.DefWindowProc (handle, OS.WM_SETREDRAW, 0, 0);
+        }
+        setSelection (item);
+        if (hInfo !is null) {
+            int /*long*/ hThumb = OS.MAKELPARAM (OS.SB_THUMBPOSITION, hInfo.nPos);
+            OS.SendMessage (handle, OS.WM_HSCROLL, hThumb, 0);
+        }
+        int /*long*/ vThumb = OS.MAKELPARAM (OS.SB_THUMBPOSITION, vInfo.nPos);
+        OS.SendMessage (handle, OS.WM_VSCROLL, vThumb, 0);
+        if (redraw) {
+            OS.DefWindowProc (handle, OS.WM_SETREDRAW, 1, 0);
+            OS.InvalidateRect (handle, null, true);
+            if ((style & DWT.DOUBLE_BUFFERED) is 0) {
+                int oldStyle = style;
+                style |= DWT.DOUBLE_BUFFERED;
+                OS.UpdateWindow (handle);
+                style = oldStyle;
+            }
+        }
+        return;
+    }
+    TVITEM tvItem;
+    tvItem.mask = OS.TVIF_HANDLE | OS.TVIF_STATE;
+    tvItem.stateMask = OS.TVIS_SELECTED;
+    tvItem.state = OS.TVIS_SELECTED;
+    tvItem.hItem = item.handle;
+    OS.SendMessage (handle, OS.TVM_SETITEM, 0, cast(int)&tvItem);
+}
+
+/**
  * Selects all of the items in the receiver.
  * <p>
  * If the receiver is single-select, do nothing.
@@ -4085,8 +4329,8 @@
     tvItem.mask = OS.TVIF_HANDLE | OS.TVIF_STATE;
     tvItem.state = OS.TVIS_SELECTED;
     tvItem.stateMask = OS.TVIS_SELECTED;
-    int oldProc = OS.GetWindowLong (handle, OS.GWL_WNDPROC);
-    OS.SetWindowLong (handle, OS.GWL_WNDPROC, cast(int) TreeProc);
+    int /*long*/ oldProc = OS.GetWindowLongPtr (handle, OS.GWLP_WNDPROC);
+    OS.SetWindowLongPtr (handle, OS.GWLP_WNDPROC, cast(LONG_PTR)TreeProc);
     if ((style & DWT.VIRTUAL) !is 0) {
         HANDLE hItem = cast(HANDLE) OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_ROOT, 0);
         select (hItem, &tvItem);
@@ -4099,7 +4343,95 @@
             }
         }
     }
-    OS.SetWindowLong (handle, OS.GWL_WNDPROC, oldProc);
+    OS.SetWindowLongPtr (handle, OS.GWLP_WNDPROC, oldProc);
+}
+
+Event sendEraseItemEvent (TreeItem item, NMTTCUSTOMDRAW* nmcd, int column, RECT* cellRect) {
+    int nSavedDC = OS.SaveDC (nmcd.nmcd.hdc);
+    RECT* insetRect = toolTipInset (cellRect);
+    OS.SetWindowOrgEx (nmcd.nmcd.hdc, insetRect.left, insetRect.top, null);
+    GCData data = new GCData ();
+    data.device = display;
+    data.foreground = OS.GetTextColor (nmcd.nmcd.hdc);
+    data.background = OS.GetBkColor (nmcd.nmcd.hdc);
+    data.font = item.getFont (column);
+    data.uiState = OS.SendMessage (handle, OS.WM_QUERYUISTATE, 0, 0);
+    GC gc = GC.win32_new (nmcd.nmcd.hdc, data);
+    Event event = new Event ();
+    event.item = item;
+    event.index = column;
+    event.gc = gc;
+    event.detail |= DWT.FOREGROUND;
+    event.x = cellRect.left;
+    event.y = cellRect.top;
+    event.width = cellRect.right - cellRect.left;
+    event.height = cellRect.bottom - cellRect.top;
+    //gc.setClipping (event.x, event.y, event.width, event.height);
+    sendEvent (DWT.EraseItem, event);
+    event.gc = null;
+    //int newTextClr = data.foreground;
+    gc.dispose ();
+    OS.RestoreDC (nmcd.nmcd.hdc, nSavedDC);
+    return event;
+}
+
+Event sendMeasureItemEvent (TreeItem item, int index, HDC hDC) {
+    RECT itemRect = item.getBounds (index, true, true, false, false, false, hDC);
+    int nSavedDC = OS.SaveDC (hDC);
+    GCData data = new GCData ();
+    data.device = display;
+    data.font = item.getFont (index);
+    GC gc = GC.win32_new (hDC, data);
+    Event event = new Event ();
+    event.item = item;
+    event.gc = gc;
+    event.index = index;
+    event.x = itemRect.left;
+    event.y = itemRect.top;
+    event.width = itemRect.right - itemRect.left;
+    event.height = itemRect.bottom - itemRect.top;
+    sendEvent (DWT.MeasureItem, event);
+    event.gc = null;
+    gc.dispose ();
+    OS.RestoreDC (hDC, nSavedDC);
+    if (isDisposed () || item.isDisposed ()) return null;
+    if (hwndHeader !is null) {
+        if (columnCount is 0) {
+            if (event.x + event.width > scrollWidth) {
+                setScrollWidth (scrollWidth = event.x + event.width);
+            }
+        }
+    }
+    if (event.height > getItemHeight ()) setItemHeight (event.height);
+    return event;
+}
+
+Event sendPaintItemEvent (TreeItem item, NMTTCUSTOMDRAW* nmcd, int column, RECT* itemRect) {
+    int nSavedDC = OS.SaveDC (nmcd.nmcd.hdc);
+    RECT* insetRect = toolTipInset (itemRect);
+    OS.SetWindowOrgEx (nmcd.nmcd.hdc, insetRect.left, insetRect.top, null);
+    GCData data = new GCData ();
+    data.device = display;
+    data.font = item.getFont (column);
+    data.foreground = OS.GetTextColor (nmcd.nmcd.hdc);
+    data.background = OS.GetBkColor (nmcd.nmcd.hdc);
+    data.uiState = OS.SendMessage (handle, OS.WM_QUERYUISTATE, 0, 0);
+    GC gc = GC.win32_new (nmcd.nmcd.hdc, data);
+    Event event = new Event ();
+    event.item = item;
+    event.index = column;
+    event.gc = gc;
+    event.detail |= DWT.FOREGROUND;
+    event.x = itemRect.left;
+    event.y = itemRect.top;
+    event.width = itemRect.right - itemRect.left;
+    event.height = itemRect.bottom - itemRect.top;
+    //gc.setClipping (cellRect.left, cellRect.top, cellWidth, cellHeight);
+    sendEvent (DWT.PaintItem, event);
+    event.gc = null;
+    gc.dispose ();
+    OS.RestoreDC (nmcd.nmcd.hdc, nSavedDC);
+    return event;
 }
 
 override void setBackgroundImage (HBITMAP hBitmap) {
@@ -4164,24 +4496,6 @@
     updateFullSelection ();
 }
 
-override void setBounds (int x, int y, int width, int height, int flags) {
-    /*
-    * Ensure that the selection is visible when the tree is resized
-    * from a zero size to a size that can show the selection.
-    */
-    bool fixSelection = false;
-    if ((flags & OS.SWP_NOSIZE) is 0 && (width !is 0 || height !is 0)) {
-        if (OS.SendMessage (handle, OS.TVM_GETVISIBLECOUNT, 0, 0) is 0) {
-            fixSelection = true;
-        }
-    }
-    super.setBounds (x, y, width, height, flags);
-    if (fixSelection) {
-        HANDLE hItem = cast(HANDLE) OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_CARET, 0);
-        if (hItem !is null) showItem (hItem);
-    }
-}
-
 override void setCursor () {
     /*
     * Bug in Windows.  Under certain circumstances, when WM_SETCURSOR
@@ -4224,39 +4538,35 @@
 public void setColumnOrder (int [] order) {
     checkWidget ();
     if (order is null) error (DWT.ERROR_NULL_ARGUMENT);
-    int count = 0;
-    if (hwndHeader !is null) {
-        count = OS.SendMessage (hwndHeader, OS.HDM_GETITEMCOUNT, 0, 0);
-    }
-    if (count is 0) {
+    if (columnCount is 0) {
         if (order.length !is 0) error (DWT.ERROR_INVALID_ARGUMENT);
         return;
     }
-    if (order.length !is count) error (DWT.ERROR_INVALID_ARGUMENT);
-    int [] oldOrder = new int [count];
-    OS.SendMessage (hwndHeader, OS.HDM_GETORDERARRAY, count, oldOrder.ptr);
+    if (order.length !is columnCount) error (DWT.ERROR_INVALID_ARGUMENT);
+    int [] oldOrder = new int [columnCount];
+    OS.SendMessage (hwndHeader, OS.HDM_GETORDERARRAY, columnCount, oldOrder.ptr);
     bool reorder = false;
-    bool [] seen = new bool [count];
+    bool [] seen = new bool [columnCount];
     for (int i=0; i<order.length; i++) {
         int index = order [i];
-        if (index < 0 || index >= count) error (DWT.ERROR_INVALID_RANGE);
+        if (index < 0 || index >= columnCount) error (DWT.ERROR_INVALID_RANGE);
         if (seen [index]) error (DWT.ERROR_INVALID_ARGUMENT);
         seen [index] = true;
         if (index !is oldOrder [i]) reorder = true;
     }
     if (reorder) {
-        RECT [] oldRects = new RECT [count];
-        for (int i=0; i<count; i++) {
+        RECT [] oldRects = new RECT [columnCount];
+        for (int i=0; i<columnCount; i++) {
             //oldRects [i] = new RECT ();
             OS.SendMessage (hwndHeader, OS.HDM_GETITEMRECT, i, & oldRects [i]);
         }
         OS.SendMessage (hwndHeader, OS.HDM_SETORDERARRAY, order.length, order.ptr);
         OS.InvalidateRect (handle, null, true);
         updateImageList ();
-        TreeColumn [] newColumns = new TreeColumn [count];
-        System.arraycopy (columns, 0, newColumns, 0, count);
+        TreeColumn [] newColumns = new TreeColumn [columnCount];
+        System.arraycopy (columns, 0, newColumns, 0, columnCount);
         RECT newRect;
-        for (int i=0; i<count; i++) {
+        for (int i=0; i<columnCount; i++) {
             TreeColumn column = newColumns [i];
             if (!column.isDisposed ()) {
                 OS.SendMessage (hwndHeader, OS.HDM_GETITEMRECT, i, &newRect);
@@ -4453,6 +4763,7 @@
                 hItem = cast(HANDLE) OS.SendMessage (handle, OS.TVM_INSERTITEM, 0, &tvInsert);
             }
             OS.DefWindowProc (handle, OS.WM_SETREDRAW, 1, 0);
+            updateScrollBar ();
         }
     }
     super.setRedraw (redraw);
@@ -4470,8 +4781,7 @@
     if (hwndHeader is null || hwndParent is null) return;
     int width = 0;
     HDITEM hdItem;
-    int count = OS.SendMessage (hwndHeader, OS.HDM_GETITEMCOUNT, 0, 0);
-    for (int i=0; i<count; i++) {
+    for (int i=0; i<columnCount; i++) {
         hdItem.mask = OS.HDI_WIDTH;
         OS.SendMessage (hwndHeader, OS.HDM_GETITEM, i, &hdItem);
         width += hdItem.cxy;
@@ -4488,8 +4798,7 @@
     SCROLLINFO info;
     info.cbSize = SCROLLINFO.sizeof;
     info.fMask = OS.SIF_RANGE | OS.SIF_PAGE;
-    int count = OS.SendMessage (hwndHeader, OS.HDM_GETITEMCOUNT, 0, 0);
-    if (count is 0 && width is 0) {
+    if (columnCount is 0 && width is 0) {
         OS.GetScrollInfo (hwndParent, OS.SB_HORZ, &info);
         info.nPage = info.nMax + 1;
         OS.SetScrollInfo (hwndParent, OS.SB_HORZ, &info, true);
@@ -4497,14 +4806,16 @@
         info.nPage = info.nMax + 1;
         OS.SetScrollInfo (hwndParent, OS.SB_VERT, &info, true);
     } else {
-        OS.GetClientRect (hwndParent, &rect);
-        OS.GetScrollInfo (hwndParent, OS.SB_HORZ, &info);
-        info.nMax = width;
-        info.nPage = rect.right - rect.left + 1;
-        OS.SetScrollInfo (hwndParent, OS.SB_HORZ, &info, true);
-        info.fMask = OS.SIF_POS;
-        OS.GetScrollInfo (hwndParent, OS.SB_HORZ, &info);
-        left = info.nPos;
+        if ((style & DWT.H_SCROLL) !is 0) {
+            OS.GetClientRect (hwndParent, &rect);
+            OS.GetScrollInfo (hwndParent, OS.SB_HORZ, &info);
+            info.nMax = width;
+            info.nPage = rect.right - rect.left + 1;
+            OS.SetScrollInfo (hwndParent, OS.SB_HORZ, &info, true);
+            info.fMask = OS.SIF_POS;
+            OS.GetScrollInfo (hwndParent, OS.SB_HORZ, &info);
+            left = info.nPos;
+        }
     }
     if (horizontalBar !is null) {
         horizontalBar.setIncrement (INCREMENT);
@@ -4520,7 +4831,7 @@
     SetWindowPos (hwndHeader, cast(HWND)OS.HWND_TOP, pos.x - left, pos.y, pos.cx + left, pos.cy, OS.SWP_NOACTIVATE);
     int bits = OS.GetWindowLong (handle, OS.GWL_EXSTYLE);
     int b = (bits & OS.WS_EX_CLIENTEDGE) !is 0 ? OS.GetSystemMetrics (OS.SM_CXEDGE) : 0;
-    int w = pos.cx + (count is 0 && width is 0 ? 0 : OS.GetSystemMetrics (OS.SM_CXVSCROLL));
+    int w = pos.cx + (columnCount is 0 && width is 0 ? 0 : OS.GetSystemMetrics (OS.SM_CXVSCROLL));
     int h = rect.bottom - rect.top - pos.cy;
     bool oldIgnore = ignoreResize;
     ignoreResize = true;
@@ -4641,7 +4952,7 @@
         ignoreSelect = false;
         if (OS.SendMessage (handle, OS.TVM_GETVISIBLECOUNT, 0, 0) is 0) {
             OS.SendMessage (handle, OS.TVM_SELECTITEM, OS.TVGN_FIRSTVISIBLE, hNewItem);
-            int hParent = OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_PARENT, hNewItem);
+            int /*long*/ hParent = OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_PARENT, hNewItem);
             if (hParent is 0) OS.SendMessage (handle, OS.WM_HSCROLL, OS.SB_TOP, 0);
         }
         if (fixScroll) {
@@ -4672,8 +4983,8 @@
     TVITEM tvItem;
     tvItem.mask = OS.TVIF_HANDLE | OS.TVIF_STATE;
     tvItem.stateMask = OS.TVIS_SELECTED;
-    int oldProc = OS.GetWindowLong (handle, OS.GWL_WNDPROC);
-    OS.SetWindowLong (handle, OS.GWL_WNDPROC, cast(int) TreeProc);
+    int /*long*/ oldProc = OS.GetWindowLongPtr (handle, OS.GWLP_WNDPROC);
+    OS.SetWindowLongPtr (handle, OS.GWLP_WNDPROC, cast(LONG_PTR)TreeProc);
     if ((style & DWT.VIRTUAL) !is 0) {
         HANDLE hItem = cast(HANDLE) OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_ROOT, 0);
         setSelection (hItem, &tvItem, items);
@@ -4702,7 +5013,7 @@
             }
         }
     }
-    OS.SetWindowLong (handle, OS.GWL_WNDPROC, oldProc);
+    OS.SetWindowLongPtr (handle, OS.GWLP_WNDPROC, oldProc);
 }
 
 /**
@@ -4834,8 +5145,7 @@
     } else {
         bool scroll = true;
         RECT itemRect;
-        itemRect.left = cast(int) hItem;
-        if (OS.SendMessage (handle, OS.TVM_GETITEMRECT, 1, &itemRect) !is 0) {
+        if (OS.TreeView_GetItemRect (handle, hItem, &itemRect, true)) {
             forceResize ();
             RECT rect;
             OS.GetClientRect (handle, &rect);
@@ -4862,8 +5172,7 @@
     }
     if (hwndParent !is null) {
         RECT itemRect;
-        itemRect.left = cast(int) hItem;
-        if (OS.SendMessage (handle, OS.TVM_GETITEMRECT, 1, &itemRect) !is 0) {
+        if (OS.TreeView_GetItemRect (handle, hItem, &itemRect, true)) {
             forceResize ();
             RECT rect;
             OS.GetClientRect (hwndParent, &rect);
@@ -4912,28 +5221,25 @@
     if (column.parent !is this) return;
     int index = indexOf (column);
     if (index is -1) return;
-    int count = OS.SendMessage (hwndHeader, OS.HDM_GETITEMCOUNT, 0, 0);
-    if (0 <= index && index < count) {
-        if (hwndParent !is null) {
-            forceResize ();
-            RECT rect;
-            OS.GetClientRect (hwndParent, &rect);
-            OS.MapWindowPoints (hwndParent, handle, cast(POINT*) &rect, 2);
-            RECT headerRect;
-            OS.SendMessage (hwndHeader, OS.HDM_GETITEMRECT, index, &headerRect);
-            bool scroll = headerRect.left < rect.left;
-            if (!scroll) {
-                int width = Math.min (rect.right - rect.left, headerRect.right - headerRect.left);
-                scroll = headerRect.left + width > rect.right;
-            }
-            if (scroll) {
-                SCROLLINFO info;
-                info.cbSize = SCROLLINFO.sizeof;
-                info.fMask = OS.SIF_POS;
-                info.nPos = Math.max (0, headerRect.left - Tree.INSET / 2);
-                OS.SetScrollInfo (hwndParent, OS.SB_HORZ, &info, true);
-                setScrollWidth ();
-            }
+    if (0 <= index && index < columnCount) {
+        forceResize ();
+        RECT rect;
+        OS.GetClientRect (hwndParent, &rect);
+        OS.MapWindowPoints (hwndParent, handle, cast(POINT*) &rect, 2);
+        RECT headerRect;
+        OS.SendMessage (hwndHeader, OS.HDM_GETITEMRECT, index, &headerRect);
+        bool scroll = headerRect.left < rect.left;
+        if (!scroll) {
+            int width = Math.min (rect.right - rect.left, headerRect.right - headerRect.left);
+            scroll = headerRect.left + width > rect.right;
+        }
+        if (scroll) {
+            SCROLLINFO info;
+            info.cbSize = SCROLLINFO.sizeof;
+            info.fMask = OS.SIF_POS;
+            info.nPos = Math.max (0, headerRect.left - Tree.INSET / 2);
+            OS.SetScrollInfo (hwndParent, OS.SB_HORZ, &info, true);
+            setScrollWidth ();
         }
     }
 }
@@ -4993,8 +5299,8 @@
         }
         if ((state & OS.TVIS_SELECTED) is 0) return;
     } else {
-        int oldProc = OS.GetWindowLong (handle, OS.GWL_WNDPROC);
-        OS.SetWindowLong (handle, OS.GWL_WNDPROC, cast(int) TreeProc);
+        int /*long*/ oldProc = OS.GetWindowLongPtr (handle, OS.GWLP_WNDPROC);
+        OS.SetWindowLongPtr (handle, OS.GWLP_WNDPROC, cast(LONG_PTR)TreeProc);
         TVITEM tvItem_;
         TVITEM* tvItem;
         static if (OS.IsWinCE) {
@@ -5026,7 +5332,7 @@
                 index++;
             }
         }
-        OS.SetWindowLong (handle, OS.GWL_WNDPROC, oldProc);
+        OS.SetWindowLongPtr (handle, OS.GWLP_WNDPROC, oldProc);
     }
     if (hItem !is null) showItem (hItem);
 }
@@ -5061,71 +5367,64 @@
 override void subclass () {
     super.subclass ();
     if (hwndHeader !is null) {
-        OS.SetWindowLong (hwndHeader, OS.GWL_WNDPROC, display.windowProc);
-    }
+        OS.SetWindowLongPtr (hwndHeader, OS.GWLP_WNDPROC, display.windowProc);
+    }
+}
+
+RECT* toolTipInset (RECT* rect) {
+    if (!OS.IsWinCE && OS.WIN32_VERSION >= OS.VERSION (6, 0)) {
+        RECT* insetRect = new RECT();
+        OS.SetRect (insetRect, rect.left - 1, rect.top - 1, rect.right + 1, rect.bottom + 1);
+        return insetRect;
+    }
+    return rect;
+}
+
+RECT* toolTipRect (RECT* rect) {
+    RECT* toolRect = new RECT ();
+    if (!OS.IsWinCE && OS.WIN32_VERSION >= OS.VERSION (6, 0)) {
+        OS.SetRect (toolRect, rect.left - 1, rect.top - 1, rect.right + 1, rect.bottom + 1);
+    } else {
+        OS.SetRect (toolRect, rect.left, rect.top, rect.right, rect.bottom);
+        int dwStyle = OS.GetWindowLong (itemToolTipHandle, OS.GWL_STYLE);
+        int dwExStyle = OS.GetWindowLong (itemToolTipHandle, OS.GWL_EXSTYLE);
+        OS.AdjustWindowRectEx (toolRect, dwStyle, false, dwExStyle);
+    }
+    return toolRect;
 }
 
 override String toolTipText (NMTTDISPINFO* hdr) {
     auto hwndToolTip = cast(HWND) OS.SendMessage (handle, OS.TVM_GETTOOLTIPS, 0, 0);
     if (hwndToolTip is hdr.hdr.hwndFrom && toolTipText_ !is null) return ""; //$NON-NLS-1$
     if (headerToolTipHandle is hdr.hdr.hwndFrom) {
-        int count = OS.SendMessage (hwndHeader, OS.HDM_GETITEMCOUNT, 0, 0);
-        for (int i=0; i<count; i++) {
+        for (int i=0; i<columnCount; i++) {
             TreeColumn column = columns [i];
             if (column.id is hdr.hdr.idFrom) return column.toolTipText;
         }
         return super.toolTipText (hdr);
     }
-    if (itemToolTipHandle is hdr.hdr.hwndFrom && hwndHeader !is null) {
+    if (itemToolTipHandle is hdr.hdr.hwndFrom) {
         if (toolTipText_ !is null) return "";
-        if (!hooks (DWT.EraseItem) && !hooks (DWT.PaintItem)) {
-            int pos = OS.GetMessagePos ();
-            POINT pt;
-            pt.x = cast(short) (pos & 0xFFFF);
-            pt.y = cast(short) (pos >> 16);
-            OS.ScreenToClient (handle, &pt);
-            TVHITTESTINFO lpht;
-            lpht.pt.x = pt.x;
-            lpht.pt.y = pt.y;
-            OS.SendMessage (handle, OS.TVM_HITTEST, 0, &lpht);
-            if (lpht.hItem !is null) {
-                auto hDC = OS.GetDC (handle);
-                HFONT oldFont, newFont = cast(HFONT) OS.SendMessage (handle, OS.WM_GETFONT, 0, 0);
-                if (newFont !is null) oldFont = OS.SelectObject (hDC, newFont);
-                RECT rect;
-                OS.GetClientRect (hwndParent, &rect);
-                OS.MapWindowPoints (hwndParent, handle, cast(POINT*) &rect, 2);
-                TreeItem item = _getItem (lpht.hItem);
-                String text = null;
-                int index = 0, count = Math.max (1, OS.SendMessage (hwndHeader, OS.HDM_GETITEMCOUNT, 0, 0));
-                int [] order = new int [count];
-                OS.SendMessage (hwndHeader, OS.HDM_GETORDERARRAY, count, order.ptr);
-                while (index < count) {
-                    HFONT hFont = item.cellFont !is null ? item.cellFont [order [index]] : cast(HFONT)-1;
-                    if (hFont is cast(HFONT)-1) hFont = item.font;
-                    if (hFont !is cast(HFONT)-1) hFont = OS.SelectObject (hDC, hFont);
-                    RECT cellRect = item.getBounds (order [index], true, false, true, false, true, hDC);
-                    if (hFont !is cast(HFONT)-1) OS.SelectObject (hDC, hFont);
-                    if (cellRect.left > rect.right) break;
-                    cellRect.right = Math.min (cellRect.right, rect.right);
-                    if (OS.PtInRect (&cellRect, pt)) {
-                        RECT textRect = item.getBounds (order [index], true, false, false, false, false, hDC);
-                        if (textRect.right > cellRect.right) {
-                            if (order [index] is 0) {
-                                text = item.text;
-                            } else {
-                                String[] strings = item.strings;
-                                if (strings !is null) text = strings [order [index]];
-                            }
-                        }
-                        break;
-                    }
-                    index++;
-                }
-                if (newFont !is null) OS.SelectObject (hDC, oldFont);
-                OS.ReleaseDC (handle, hDC);
-                if (text !is null) return text;
-            }
+        int pos = OS.GetMessagePos ();
+        POINT pt;
+        OS.POINTSTOPOINT (pt, pos);
+        OS.ScreenToClient (handle, &pt);
+        int index;
+        TreeItem item;
+        RECT cellRect, itemRect;
+        if (findCell (pt.x, pt.y, item, index, cellRect, itemRect)) {
+            String text = null;
+            if (index is 0) {
+                text = item.text;
+            } else {
+                String[] strings = item.strings;
+                if (strings !is null) text = strings [index];
+            }
+            //TEMPORARY CODE
+            if (!OS.IsWinCE && OS.WIN32_VERSION >= OS.VERSION (6, 0)) {
+                if (isCustomToolTip ()) text = " ";
+            }
+            if (text !is null) return text;
         }
     }
     return super.toolTipText (hdr);
@@ -5164,8 +5463,7 @@
     lpti.uFlags = OS.TTF_SUBCLASS;
     lpti.hwnd = hwndHeader;
     lpti.lpszText = OS.LPSTR_TEXTCALLBACK;
-    int count = OS.SendMessage (hwndHeader, OS.HDM_GETITEMCOUNT, 0, 0);
-    for (int i=0; i<count; i++) {
+    for (int i=0; i<columnCount; i++) {
         TreeColumn column = columns [i];
         if (OS.SendMessage (hwndHeader, OS.HDM_GETITEMRECT, i, &rect) !is 0) {
             lpti.uId = column.id = display.nextToolTipId++;
@@ -5224,7 +5522,6 @@
 
 void updateScrollBar () {
     if (hwndParent !is null) {
-        int columnCount = OS.SendMessage (hwndHeader, OS.HDM_GETITEMCOUNT, 0, 0);
         if (columnCount !is 0 || scrollWidth !is 0) {
             SCROLLINFO info;
             info.cbSize = SCROLLINFO.sizeof;
@@ -5236,7 +5533,16 @@
                 OS.SetScrollInfo (hwndParent, OS.SB_VERT, &info, true);
             } else {
                 OS.GetScrollInfo (handle, OS.SB_VERT, &info);
-                if (info.nPage is 0) info.nPage = info.nMax + 1;
+                if (!OS.IsWinCE && OS.WIN32_VERSION >= OS.VERSION(4, 10)) {
+                    if (info.nPage is 0) {
+                        SCROLLBARINFO psbi;
+                        psbi.cbSize = SCROLLBARINFO.sizeof;
+                        OS.GetScrollBarInfo (handle, OS.OBJID_VSCROLL, &psbi);
+                        if ((psbi.rgstate [0] & OS.STATE_SYSTEM_INVISIBLE) !is 0) {
+                            info.nPage = info.nMax + 1;
+                        }
+                    }
+                }
                 OS.SetScrollInfo (hwndParent, OS.SB_VERT, &info, true);
             }
         }
@@ -5246,13 +5552,13 @@
 override void unsubclass () {
     super.unsubclass ();
     if (hwndHeader !is null) {
-        OS.SetWindowLong (hwndHeader, OS.GWL_WNDPROC, cast(int) HeaderProc);
+        OS.SetWindowLongPtr (hwndHeader, OS.GWLP_WNDPROC, cast(LONG_PTR)HeaderProc);
     }
 }
 
 override int widgetStyle () {
     int bits = super.widgetStyle () | OS.TVS_SHOWSELALWAYS | OS.TVS_LINESATROOT | OS.TVS_HASBUTTONS | OS.TVS_NONEVENHEIGHT;
-    if (EXPLORER_THEME && !OS.IsWinCE && OS.WIN32_VERSION >= OS.VERSION (6, 0)) {
+    if (EXPLORER_THEME && !OS.IsWinCE && OS.WIN32_VERSION >= OS.VERSION (6, 0) && OS.IsAppThemed ()) {
         bits |= OS.TVS_TRACKSELECT;
         if ((style & DWT.FULL_SELECTION) !is 0) bits |= OS.TVS_FULLROWSELECT;
     } else {
@@ -5262,6 +5568,15 @@
             bits |= OS.TVS_HASLINES;
         }
     }
+    if ((style & (DWT.H_SCROLL | DWT.V_SCROLL)) is 0) {
+        bits &= ~(OS.WS_HSCROLL | OS.WS_VSCROLL);
+        bits |= OS.TVS_NOSCROLL;
+    } else {
+        if ((style & DWT.H_SCROLL) is 0) {
+            bits &= ~OS.WS_HSCROLL;
+            bits |= OS.TVS_NOHSCROLL;
+        }
+    }
 //  bits |= OS.TVS_NOTOOLTIPS | OS.TVS_DISABLEDRAGDROP;
     return bits | OS.TVS_DISABLEDRAGDROP;
 }
@@ -5331,17 +5646,15 @@
             }
             case OS.WM_SETCURSOR: {
                 if (cast(HWND)wParam is hwnd) {
-                    int hitTest = cast(short) (lParam & 0xFFFF);
+                    int hitTest = cast(short) OS.LOWORD (lParam);
                     if (hitTest is OS.HTCLIENT) {
                         HDHITTESTINFO pinfo;
                         int pos = OS.GetMessagePos ();
                         POINT pt;
-                        pt.x = cast(short) (pos & 0xFFFF);
-                        pt.y = cast(short) (pos >> 16);
+                        OS.POINTSTOPOINT (pt, pos);
                         OS.ScreenToClient (hwnd, &pt);
                         pinfo.pt.x = pt.x;
                         pinfo.pt.y = pt.y;
-                        int columnCount = OS.SendMessage (hwndHeader, OS.HDM_GETITEMCOUNT, 0, 0);
                         int index = OS.SendMessage (hwndHeader, OS.HDM_HITTEST, 0, &pinfo);
                         if (0 <= index && index < columnCount && !columns [index].resizable) {
                             if ((pinfo.flags & (OS.HHT_ONDIVIDER | OS.HHT_ONDIVOPEN)) !is 0) {
@@ -5367,7 +5680,7 @@
                 setScrollWidth ();
                 if (ignoreResize) return 0;
                 setResizeChildren (false);
-                int code = callWindowProc (hwnd, OS.WM_SIZE, wParam, lParam);
+                int /*long*/ code = callWindowProc (hwnd, OS.WM_SIZE, wParam, lParam);
                 sendEvent (DWT.Resize);
                 if (isDisposed ()) return 0;
                 if (layout_ !is null) {
@@ -5421,12 +5734,12 @@
                 * on Windows Vista.
                 */
                 if (!OS.IsWinCE && OS.WIN32_VERSION >= OS.VERSION (6, 0)) {
-                    if ((wParam & 0xFFFF) is OS.SB_THUMBTRACK) {
+                    if (OS.LOWORD (wParam) is OS.SB_THUMBTRACK) {
                         info.nPos = info.nTrackPos;
                     }
                 }
                 OS.SetScrollInfo (handle, OS.SB_VERT, &info, true);
-                int code = OS.SendMessage (handle, OS.WM_VSCROLL, wParam, lParam);
+                int /*long*/ code = OS.SendMessage (handle, OS.WM_VSCROLL, wParam, lParam);
                 OS.GetScrollInfo (handle, OS.SB_VERT, &info);
                 OS.SetScrollInfo (hwndParent, OS.SB_VERT, &info, true);
                 return code;
@@ -5435,6 +5748,20 @@
         }
         return callWindowProc (hwnd, msg, wParam, lParam);
     }
+    if (msg is Display.DI_GETDRAGIMAGE) {
+        //TEMPORARY CODE
+        if (hooks (DWT.EraseItem) || hooks (DWT.PaintItem)) return 0;
+        /*
+        * When there is more than one item selected, DI_GETDRAGIMAGE
+        * returns the item under the cursor.  This happens because
+        * the tree does not have implement multi-select.  The fix
+        * is to disable DI_GETDRAGIMAGE when more than one item is
+        * selected.
+        */
+        if ((style & DWT.MULTI) !is 0) {
+            if (getSelectionCount () !is 1) return 0;
+        }
+    }
     return super.windowProc (hwnd, msg, wParam, lParam);
 }
 
@@ -5545,7 +5872,29 @@
     return super.WM_GETOBJECT (wParam, lParam);
 }
 
-override LRESULT WM_KEYDOWN (int wParam, int lParam) {
+override LRESULT WM_HSCROLL (int wParam, int lParam) {
+    bool fixScroll = false;
+    if ((style & DWT.DOUBLE_BUFFERED) !is 0) {
+        fixScroll = (style & DWT.VIRTUAL) !is 0 || hooks (DWT.EraseItem) || hooks (DWT.PaintItem);
+    }
+    if (fixScroll) {
+        style &= ~DWT.DOUBLE_BUFFERED;
+        if (explorerTheme) {
+            OS.SendMessage (handle, OS.TVM_SETEXTENDEDSTYLE, OS.TVS_EX_DOUBLEBUFFER, 0);
+        }
+    }
+    LRESULT result = super.WM_HSCROLL (wParam, lParam);
+    if (fixScroll) {
+        style |= DWT.DOUBLE_BUFFERED;
+        if (explorerTheme) {
+            OS.SendMessage (handle, OS.TVM_SETEXTENDEDSTYLE, OS.TVS_EX_DOUBLEBUFFER, OS.TVS_EX_DOUBLEBUFFER);
+        }
+    }
+    if (result !is null) return result;
+    return result;
+}
+
+override LRESULT WM_KEYDOWN (int /*long*/ wParam, int /*long*/ lParam) {
     LRESULT result = super.WM_KEYDOWN (wParam, lParam);
     if (result !is null) return result;
     switch (wParam) {
@@ -5560,10 +5909,9 @@
         case OS.VK_ADD:
             if (OS.GetKeyState (OS.VK_CONTROL) < 0) {
                 if (hwndHeader !is null) {
-                    int count = OS.SendMessage (hwndHeader, OS.HDM_GETITEMCOUNT, 0, 0);
-                    TreeColumn [] newColumns = new TreeColumn [count];
-                    System.arraycopy (columns, 0, newColumns, 0, count);
-                    for (int i=0; i<count; i++) {
+                    TreeColumn [] newColumns = new TreeColumn [columnCount];
+                    System.arraycopy (columns, 0, newColumns, 0, columnCount);
+                    for (int i=0; i<columnCount; i++) {
                         TreeColumn column = newColumns [i];
                         if (!column.isDisposed () && column.getResizable ()) {
                             column.pack ();
@@ -5585,7 +5933,7 @@
                 if (hItem !is null) {
                     if (hAnchor is null) hAnchor = hItem;
                     ignoreSelect = ignoreDeselect = true;
-                    int code = callWindowProc (handle, OS.WM_KEYDOWN, wParam, lParam);
+                    int /*long*/ code = callWindowProc (handle, OS.WM_KEYDOWN, wParam, lParam);
                     ignoreSelect = ignoreDeselect = false;
                     auto hNewItem = cast(HANDLE) OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_CARET, 0);
                     TVITEM tvItem;
@@ -5593,11 +5941,12 @@
                     tvItem.stateMask = OS.TVIS_SELECTED;
                     auto hDeselectItem = hItem;
                     RECT rect1;
-                    rect1.left = cast(int)hAnchor;
-                    OS.SendMessage (handle, OS.TVM_GETITEMRECT, 0, &rect1);
+                    if (!OS.TreeView_GetItemRect (handle, hAnchor, &rect1, false)) {
+                        hAnchor = hItem;
+                        OS.TreeView_GetItemRect (handle, hAnchor, &rect1, false);
+                    }
                     RECT rect2;
-                    rect2.left = cast(int)hDeselectItem;
-                    OS.SendMessage (handle, OS.TVM_GETITEMRECT, 0, &rect2);
+                    OS.TreeView_GetItemRect (handle, hDeselectItem, &rect2, false);
                     int flags = rect1.top < rect2.top ? OS.TVGN_PREVIOUSVISIBLE : OS.TVGN_NEXTVISIBLE;
                     while (hDeselectItem !is hAnchor) {
                         tvItem.hItem = hDeselectItem;
@@ -5605,10 +5954,8 @@
                         hDeselectItem = cast(HANDLE) OS.SendMessage (handle, OS.TVM_GETNEXTITEM, flags, hDeselectItem);
                     }
                     auto hSelectItem = hAnchor;
-                    rect1.left = cast(int)hNewItem;
-                    OS.SendMessage (handle, OS.TVM_GETITEMRECT, 0, &rect1);
-                    rect2.left = cast(int)hSelectItem;
-                    OS.SendMessage (handle, OS.TVM_GETITEMRECT, 0, &rect2);
+                    OS.TreeView_GetItemRect (handle, hNewItem, &rect1, false);
+                    OS.TreeView_GetItemRect (handle, hSelectItem, &rect2, false);
                     tvItem.state = OS.TVIS_SELECTED;
                     flags = rect1.top < rect2.top ? OS.TVGN_PREVIOUSVISIBLE : OS.TVGN_NEXTVISIBLE;
                     while (hSelectItem !is hNewItem) {
@@ -5661,8 +6008,7 @@
                             do {
                                 auto hVisible = cast(HANDLE) OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_NEXTVISIBLE, hNewItem);
                                 if (hVisible is null) break;
-                                rect.left = cast(int)hVisible;
-                                OS.SendMessage (handle, OS.TVM_GETITEMRECT, 0, &rect);
+                                if (!OS.TreeView_GetItemRect (handle, hVisible, &rect, false)) break;
                                 if (rect.bottom > clientRect.bottom) break;
                                 if ((hNewItem = hVisible) is hItem) {
                                     OS.SendMessage (handle, OS.WM_VSCROLL, OS.SB_PAGEDOWN, 0);
@@ -5701,12 +6047,11 @@
                         }
                         if (redraw) {
                             RECT rect1, rect2;
-                            rect1.left = cast(int) hItem;  rect2.left = cast(int) hNewItem;
-                            int fItemRect = (style & DWT.FULL_SELECTION) !is 0 ? 0 : 1;
-                            if (hooks (DWT.EraseItem) || hooks (DWT.PaintItem)) fItemRect = 0;
-                            if (!OS.IsWinCE && OS.WIN32_VERSION >= OS.VERSION (6, 0)) fItemRect = 0;
-                            OS.SendMessage (handle, OS.TVM_GETITEMRECT, fItemRect, &rect1);
-                            OS.SendMessage (handle, OS.TVM_GETITEMRECT, fItemRect, &rect2);
+                            bool fItemRect = (style & DWT.FULL_SELECTION) is 0;
+                            if (hooks (DWT.EraseItem) || hooks (DWT.PaintItem)) fItemRect = false;
+                            if (!OS.IsWinCE && OS.WIN32_VERSION >= OS.VERSION (6, 0)) fItemRect = false;
+                            OS.TreeView_GetItemRect (handle, hItem, &rect1, fItemRect);
+                            OS.TreeView_GetItemRect (handle, hNewItem, &rect2, fItemRect);
                             OS.DefWindowProc (handle, OS.WM_SETREDRAW, 1, 0);
                             OS.InvalidateRect (handle, &rect1, true);
                             OS.InvalidateRect (handle, &rect2, true);
@@ -5716,7 +6061,7 @@
                     }
                 }
             }
-            int code = callWindowProc (handle, OS.WM_KEYDOWN, wParam, lParam);
+            int /*long*/ code = callWindowProc (handle, OS.WM_KEYDOWN, wParam, lParam);
             hAnchor = cast(HANDLE) OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_CARET, 0);
             return new LRESULT (code);
         }
@@ -5757,8 +6102,8 @@
 
 override LRESULT WM_LBUTTONDBLCLK (int wParam, int lParam) {
     TVHITTESTINFO lpht;
-    lpht.pt.x = cast(short) (lParam & 0xFFFF);
-    lpht.pt.y = cast(short) (lParam >> 16);
+    lpht.pt.x = OS.GET_X_LPARAM (lParam);
+    lpht.pt.y = OS.GET_Y_LPARAM (lParam);
     OS.SendMessage (handle, OS.TVM_HITTEST, 0, &lpht);
     if (lpht.hItem !is null) {
         if ((style & DWT.CHECK) !is 0) {
@@ -5807,7 +6152,18 @@
     LRESULT result = super.WM_LBUTTONDBLCLK (wParam, lParam);
     if (result is LRESULT.ZERO) return result;
     if (lpht.hItem !is null) {
-        if ((style & DWT.FULL_SELECTION) !is 0 || (lpht.flags & OS.TVHT_ONITEM) !is 0) {
+        int flags = OS.TVHT_ONITEM;
+        if ((style & DWT.FULL_SELECTION) !is 0) {
+            flags |= OS.TVHT_ONITEMRIGHT | OS.TVHT_ONITEMINDENT;
+        } else {
+            if (hooks (DWT.MeasureItem)) {
+                lpht.flags &= ~(OS.TVHT_ONITEMICON | OS.TVHT_ONITEMLABEL);
+                if (hitTestSelection (lpht.hItem, lpht.pt.x, lpht.pt.y)) {
+                    lpht.flags |= OS.TVHT_ONITEMICON | OS.TVHT_ONITEMLABEL;
+                }
+            }
+        }
+        if ((lpht.flags & flags) !is 0) {
             Event event = new Event ();
             event.item = _getItem (lpht.hItem);
             postEvent (DWT.DefaultSelection, event);
@@ -5825,8 +6181,8 @@
     * below the last item is selected.
     */
     TVHITTESTINFO lpht;
-    lpht.pt.x = cast(short) (lParam & 0xFFFF);
-    lpht.pt.y = cast(short) (lParam >> 16);
+    lpht.pt.x = OS.GET_X_LPARAM (lParam);
+    lpht.pt.y = OS.GET_Y_LPARAM (lParam);
     OS.SendMessage (handle, OS.TVM_HITTEST, 0, &lpht);
     if (lpht.hItem is null || (lpht.flags & OS.TVHT_ONITEMBUTTON) !is 0) {
         Display display = this.display;
@@ -5838,9 +6194,9 @@
             return LRESULT.ZERO;
         }
         bool fixSelection = false, deselected = false;
+        HANDLE hOldSelection = cast(HANDLE) OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_CARET, 0);
         if (lpht.hItem !is null && (style & DWT.MULTI) !is 0) {
-            int hSelection = OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_CARET, 0);
-            if (hSelection !is 0) {
+            if (hOldSelection !is null) {
                 TVITEM tvItem;
                 tvItem.mask = OS.TVIF_HANDLE | OS.TVIF_STATE;
                 tvItem.hItem = lpht.hItem;
@@ -5850,6 +6206,7 @@
                     tvItem.stateMask = OS.TVIS_SELECTED;
                     auto hNext = cast(HANDLE) OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_NEXTVISIBLE, lpht.hItem);
                     while (hNext !is null) {
+                        if (hNext is hAnchor) hAnchor = null;
                         tvItem.hItem = hNext;
                         OS.SendMessage (handle, OS.TVM_GETITEM, 0, &tvItem);
                         if ((tvItem.state & OS.TVIS_SELECTED) !is 0) deselected = true;
@@ -5866,13 +6223,39 @@
         }
         dragStarted = gestureCompleted = false;
         if (fixSelection) ignoreDeselect = ignoreSelect = lockSelection = true;
-        int code = callWindowProc (handle, OS.WM_LBUTTONDOWN, wParam, lParam);
+        int /*long*/ code = callWindowProc (handle, OS.WM_LBUTTONDOWN, wParam, lParam);
         if (fixSelection) ignoreDeselect = ignoreSelect = lockSelection = false;
+        HANDLE hNewSelection = cast(HANDLE) OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_CARET, 0);
+        if (hOldSelection !is hNewSelection) hAnchor = hNewSelection;
         if (dragStarted) {
             if (!display.captureChanged && !isDisposed ()) {
                 if (OS.GetCapture () !is handle) OS.SetCapture (handle);
             }
         }
+        /*
+        * Bug in Windows.  When a tree has no images and an item is
+        * expanded or collapsed, for some reason, Windows changes
+        * the size of the selection.  When the user expands a tree
+        * item, the selection rectangle is made a few pixels larger.
+        * When the user collapses an item, the selection rectangle
+        * is restored to the original size but the selection is not
+        * redrawn, causing pixel corruption.  The fix is to detect
+        * this case and redraw the item.
+        */
+        if ((lpht.flags & OS.TVHT_ONITEMBUTTON) !is 0) {
+            int bits = OS.GetWindowLong (handle, OS.GWL_STYLE);
+            if ((bits & OS.TVS_FULLROWSELECT) is 0) {
+                if (OS.SendMessage (handle, OS.TVM_GETIMAGELIST, OS.TVSIL_NORMAL, 0) is 0) {
+                    auto hItem = cast(HANDLE) OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_CARET, 0);
+                    if (hItem !is null) {
+                        RECT rect;
+                        if (OS.TreeView_GetItemRect (handle, hItem, &rect, false)) {
+                            OS.InvalidateRect (handle, &rect, true);
+                        }
+                    }
+                }
+            }
+        }
         if (deselected) {
             Event event = new Event ();
             event.item = _getItem (lpht.hItem);
@@ -5924,8 +6307,31 @@
         }
     }
 
+    /*
+    * Feature in Windows.  When the tree has the style
+    * TVS_FULLROWSELECT, the background color for the
+    * entire row is filled when an item is painted,
+    * drawing on top of any custom drawing.  The fix
+    * is to emulate TVS_FULLROWSELECT.
+    */
+    bool selected = false;
+    bool fakeSelection = false;
+    if (lpht.hItem !is null) {
+        if ((style & DWT.FULL_SELECTION) !is 0) {
+            int bits = OS.GetWindowLong (handle, OS.GWL_STYLE);
+            if ((bits & OS.TVS_FULLROWSELECT) is 0) fakeSelection = true;
+        } else {
+            if (hooks (DWT.MeasureItem)) {
+                selected = hitTestSelection (lpht.hItem, lpht.pt.x, lpht.pt.y) !is 0;
+                if (selected) {
+                    if ((lpht.flags & OS.TVHT_ONITEM) is 0) fakeSelection = true;
+                }
+            }
+        }
+    }
+
     /* Process the mouse when an item is not selected */
-    if ((style & DWT.FULL_SELECTION) is 0) {
+    if (!selected && (style & DWT.FULL_SELECTION) is 0) {
         if ((lpht.flags & OS.TVHT_ONITEM) is 0) {
             Display display = this.display;
             display.captureChanged = false;
@@ -5935,7 +6341,7 @@
                 }
                 return LRESULT.ZERO;
             }
-            int code = callWindowProc (handle, OS.WM_LBUTTONDOWN, wParam, lParam);
+            int /*long*/ code = callWindowProc (handle, OS.WM_LBUTTONDOWN, wParam, lParam);
             if (!display.captureChanged && !isDisposed ()) {
                 if (OS.GetCapture () !is handle) OS.SetCapture (handle);
             }
@@ -5947,16 +6353,14 @@
     TVITEM tvItem;
     tvItem.mask = OS.TVIF_HANDLE | OS.TVIF_STATE;
     tvItem.stateMask = OS.TVIS_SELECTED;
-    bool hittestSelected = false, focused = false;
+    bool hittestSelected = false;
     if ((style & DWT.MULTI) !is 0) {
         tvItem.hItem = lpht.hItem;
         OS.SendMessage (handle, OS.TVM_GETITEM, 0, &tvItem);
         hittestSelected = (tvItem.state & OS.TVIS_SELECTED) !is 0;
-        focused = OS.GetFocus () is handle;
     }
 
     /* Get the selected state of the last selected item */
-    bool redraw = false;
     auto hOldItem = cast(HANDLE) OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_CARET, 0);
     if ((style & DWT.MULTI) !is 0) {
         tvItem.hItem = hOldItem;
@@ -5966,8 +6370,8 @@
         if (hittestSelected || (wParam & OS.MK_CONTROL) !is 0) {
             /*
             * Feature in Windows.  When the tree is not drawing focus
-            * and the user selects a tree item using while the CONTROL
-            * key is down, the tree window proc sends WM_UPDATEUISTATE
+            * and the user selects a tree item while the CONTROL key
+            * is down, the tree window proc sends WM_UPDATEUISTATE
             * to the top level window, causing controls within the shell
             * to redraw.  When drag detect is enabled, the tree window
             * proc runs a modal loop that allows WM_PAINT messages to be
@@ -5978,23 +6382,21 @@
             * on without redrawing the entire tree, pixel corruption occurs.
             * This case only seems to happen when the tree has been given
             * focus from WM_MOUSEACTIVATE of the shell.  The fix is to
-            * detect that WM_UPDATEUISTATE will be sent and avoid using
-            * WM_SETREDRAW to disable drawing.
+            * force the WM_UPDATEUISTATE to be sent before disabling
+            * the drawing.
             *
             * NOTE:  Any redraw of a parent (or sibling) will be dispatched
             * during the modal drag detect loop.  This code only fixes the
             * case where the tree causes a redraw from WM_UPDATEUISTATE.
-            * In DWT, the InvalidateRect() that causes the pixel corruption
+            * In DWT, the InvalidateRect() that caused the pixel corruption
             * is found in Composite.WM_UPDATEUISTATE().
             */
             int uiState = OS.SendMessage (handle, OS.WM_QUERYUISTATE, 0, 0);
-            if ((uiState & OS.UISF_HIDEFOCUS) is 0) {
-                redraw = focused && drawCount is 0 && OS.IsWindowVisible (handle);
-            }
-            if (redraw) {
-                OS.UpdateWindow (handle);
-                OS.DefWindowProc (handle, OS.WM_SETREDRAW, 0, 0);
-            }
+            if ((uiState & OS.UISF_HIDEFOCUS) !is 0) {
+                OS.SendMessage (handle, OS.WM_CHANGEUISTATE, OS.UIS_INITIALIZE, 0);
+            }
+            OS.UpdateWindow (handle);
+            OS.DefWindowProc (handle, OS.WM_SETREDRAW, 0, 0);
         } else {
             deselectAll ();
         }
@@ -6012,25 +6414,15 @@
     hSelect = lpht.hItem;
     dragStarted = gestureCompleted = false;
     ignoreDeselect = ignoreSelect = true;
-    int code = callWindowProc (handle, OS.WM_LBUTTONDOWN, wParam, lParam);
+    int /*long*/ code = callWindowProc (handle, OS.WM_LBUTTONDOWN, wParam, lParam);
     auto hNewItem = cast(HANDLE) OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_CARET, 0);
-    /*
-    * Feature in Windows.  When the tree has the style
-    * TVS_FULLROWSELECT, the background color for the
-    * entire row is filled when an item is painted,
-    * drawing on top of any custom drawing.  The fix
-    * is to emulate TVS_FULLROWSELECT.
-    */
-    if ((style & DWT.FULL_SELECTION) !is 0) {
-        int bits = OS.GetWindowLong (handle, OS.GWL_STYLE);
-        if ((bits & OS.TVS_FULLROWSELECT) is 0) {
-            if (hNewItem is hOldItem && lpht.hItem !is hOldItem) {
-                OS.SendMessage (handle, OS.TVM_SELECTITEM, OS.TVGN_CARET, lpht.hItem);
-                hNewItem = cast(HANDLE) OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_CARET, 0);
-            }
-            if (!dragStarted && lpht.hItem !is null && (state & DRAG_DETECT) !is 0 && hooks (DWT.DragDetect)) {
-                dragStarted = dragDetect (handle, lpht.pt.x, lpht.pt.y, false, null, null);
-            }
+    if (fakeSelection) {
+        if (hOldItem is null || (hNewItem is hOldItem && lpht.hItem !is hOldItem)) {
+            OS.SendMessage (handle, OS.TVM_SELECTITEM, OS.TVGN_CARET, lpht.hItem);
+            hNewItem = cast(HANDLE) OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_CARET, 0);
+        }
+        if (!dragStarted && (state & DRAG_DETECT) !is 0 && hooks (DWT.DragDetect)) {
+            dragStarted = dragDetect (handle, lpht.pt.x, lpht.pt.y, false, null, null);
         }
     }
     ignoreDeselect = ignoreSelect = false;
@@ -6083,27 +6475,24 @@
                     }
                 }
             }
-            if (redraw) {
-                RECT rect1, rect2;
-                rect1.left = cast(int) hOldItem;  rect2.left = cast(int) hNewItem;
-                int fItemRect = (style & DWT.FULL_SELECTION) !is 0 ? 0 : 1;
-                if (hooks (DWT.EraseItem) || hooks (DWT.PaintItem)) fItemRect = 0;
-                if (!OS.IsWinCE && OS.WIN32_VERSION >= OS.VERSION (6, 0)) fItemRect = 0;
-                OS.SendMessage (handle, OS.TVM_GETITEMRECT, fItemRect, &rect1);
-                OS.SendMessage (handle, OS.TVM_GETITEMRECT, fItemRect, &rect2);
-                OS.DefWindowProc (handle, OS.WM_SETREDRAW, 1, 0);
-                OS.InvalidateRect (handle, &rect1, true);
-                OS.InvalidateRect (handle, &rect2, true);
-                OS.UpdateWindow (handle);
-            }
+            RECT rect1, rect2;
+            bool fItemRect = (style & DWT.FULL_SELECTION) is 0;
+            if (hooks (DWT.EraseItem) || hooks (DWT.PaintItem)) fItemRect = false;
+            if (!OS.IsWinCE && OS.WIN32_VERSION >= OS.VERSION (6, 0)) fItemRect = false;
+            OS.TreeView_GetItemRect (handle, hOldItem, &rect1, fItemRect);
+            OS.TreeView_GetItemRect (handle, hNewItem, &rect2, fItemRect);
+            OS.DefWindowProc (handle, OS.WM_SETREDRAW, 1, 0);
+            OS.InvalidateRect (handle, &rect1, true);
+            OS.InvalidateRect (handle, &rect2, true);
+            OS.UpdateWindow (handle);
         }
 
         /* Check for SHIFT or normal select and deselect/reselect items */
         if ((wParam & OS.MK_CONTROL) is 0) {
             if (!hittestSelected || !dragStarted) {
                 tvItem.state = 0;
-                int oldProc = OS.GetWindowLong (handle, OS.GWL_WNDPROC);
-                OS.SetWindowLong (handle, OS.GWL_WNDPROC, cast(int) TreeProc);
+                auto oldProc = OS.GetWindowLongPtr (handle, OS.GWLP_WNDPROC);
+                OS.SetWindowLongPtr (handle, OS.GWLP_WNDPROC, cast(LONG_PTR)TreeProc);
                 if ((style & DWT.VIRTUAL) !is 0) {
                     HANDLE hItem = cast(HANDLE) OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_ROOT, 0);
                     deselect (hItem, &tvItem, hNewItem);
@@ -6119,23 +6508,22 @@
                 tvItem.hItem = hNewItem;
                 tvItem.state = OS.TVIS_SELECTED;
                 OS.SendMessage (handle, OS.TVM_SETITEM, 0, &tvItem);
-                OS.SetWindowLong (handle, OS.GWL_WNDPROC, oldProc);
+                OS.SetWindowLongPtr (handle, OS.GWLP_WNDPROC, oldProc);
                 if ((wParam & OS.MK_SHIFT) !is 0) {
                     RECT rect1;
                     if (hAnchor is null) hAnchor = hNewItem;
-                    rect1.left = cast(int) hAnchor;
-                    if (OS.SendMessage (handle, OS.TVM_GETITEMRECT, 0, &rect1) !is 0) {
+                    if (OS.TreeView_GetItemRect (handle, hAnchor, &rect1, false)) {
                         RECT rect2;
-                        rect2.left = cast(int) hNewItem;
-                        OS.SendMessage (handle, OS.TVM_GETITEMRECT, 0, &rect2);
-                        int flags = rect1.top < rect2.top ? OS.TVGN_NEXTVISIBLE : OS.TVGN_PREVIOUSVISIBLE;
-                        tvItem.state = OS.TVIS_SELECTED;
-                        auto hItem = tvItem.hItem = hAnchor;
-                        OS.SendMessage (handle, OS.TVM_SETITEM, 0, &tvItem);
-                        while (hItem !is hNewItem) {
-                            tvItem.hItem = hItem;
+                        if (OS.TreeView_GetItemRect (handle, hNewItem, &rect2, false)) {
+                            int flags = rect1.top < rect2.top ? OS.TVGN_NEXTVISIBLE : OS.TVGN_PREVIOUSVISIBLE;
+                            tvItem.state = OS.TVIS_SELECTED;
+                            auto hItem = tvItem.hItem = hAnchor;
                             OS.SendMessage (handle, OS.TVM_SETITEM, 0, &tvItem);
-                            hItem = cast(HANDLE) OS.SendMessage (handle, OS.TVM_GETNEXTITEM, flags, hItem);
+                            while (hItem !is hNewItem) {
+                                tvItem.hItem = hItem;
+                                OS.SendMessage (handle, OS.TVM_SETITEM, 0, &tvItem);
+                                hItem = cast(HANDLE) OS.SendMessage (handle, OS.TVM_GETNEXTITEM, flags, hItem);
+                            }
                         }
                     }
                 }
@@ -6164,7 +6552,7 @@
     * issue a fake mouse up.
     */
     if (dragStarted) {
-        sendDragEvent (1, cast(short) (lParam & 0xFFFF), cast(short) (lParam >> 16));
+        sendDragEvent (1, OS.GET_X_LPARAM (lParam), OS.GET_Y_LPARAM (lParam));
     } else {
         int bits = OS.GetWindowLong (handle, OS.GWL_STYLE);
         if ((bits & OS.TVS_DISABLEDRAGDROP) is 0) {
@@ -6179,7 +6567,7 @@
     Display display = this.display;
     LRESULT result = super.WM_MOUSEMOVE (wParam, lParam);
     if (result !is null) return result;
-    if (itemToolTipHandle !is null && hwndHeader !is null) {
+    if (itemToolTipHandle !is null) {
         /*
         * Bug in Windows.  On some machines that do not have XBUTTONs,
         * the MK_XBUTTON1 and OS.MK_XBUTTON2 bits are sometimes set,
@@ -6188,53 +6576,36 @@
         */
         int mask = OS.MK_LBUTTON | OS.MK_MBUTTON | OS.MK_RBUTTON;
         if (display.xMouse) mask |= OS.MK_XBUTTON1 | OS.MK_XBUTTON2;
-        if (((wParam & 0xFFFF) & mask) is 0) {
-            TVHITTESTINFO lpht;
-            lpht.pt.x = cast(short) (lParam & 0xFFFF);
-            lpht.pt.y = cast(short) (lParam >> 16);
-            OS.SendMessage (handle, OS.TVM_HITTEST, 0, &lpht);
-            if (lpht.hItem !is null) {
-                auto hDC = OS.GetDC (handle);
-                HFONT oldFont, newFont = cast(HFONT) OS.SendMessage (handle, OS.WM_GETFONT, 0, 0);
-                if (newFont !is null) oldFont = OS.SelectObject (hDC, newFont);
-                POINT pt;
-                pt.x = lpht.pt.x;
-                pt.y = lpht.pt.y;
-                RECT rect;
-                OS.GetClientRect (hwndParent, &rect);
-                OS.MapWindowPoints (hwndParent, handle, cast(POINT*) &rect, 2);
-                TreeItem item = _getItem (lpht.hItem);
-                int index = 0, count = Math.max (1, OS.SendMessage (hwndHeader, OS.HDM_GETITEMCOUNT, 0, 0));
-                int [] order = new int [count];
-                OS.SendMessage (hwndHeader, OS.HDM_GETORDERARRAY, count, order.ptr);
-                while (index < count) {
-                    HFONT hFont = item.cellFont !is null ? item.cellFont [order [index]] : cast(HFONT)-1;
-                    if (hFont is cast(HFONT)-1) hFont = item.font;
-                    if (hFont !is cast(HFONT)-1) hFont = OS.SelectObject (hDC, hFont);
-                    RECT cellRect = item.getBounds (order [index], true, false, true, false, true, hDC);
-                    if (hFont !is cast(HFONT)-1) OS.SelectObject (hDC, hFont);
-                    if (cellRect.left > rect.right) break;
-                    cellRect.right = Math.min (cellRect.right, rect.right);
-                    if (OS.PtInRect (&cellRect, pt)) {
-                        RECT textRect = item.getBounds (order [index], true, false, false, false, false, hDC);
-                        if (textRect.right > cellRect.right) {
-                            TOOLINFO lpti;
-                            lpti.cbSize = TOOLINFO.sizeof;
-                            lpti.hwnd = handle;
-                            lpti.uId = cast(int) handle;
-                            lpti.uFlags = OS.TTF_SUBCLASS | OS.TTF_TRANSPARENT;
-                            lpti.rect.left = cellRect.left;
-                            lpti.rect.top = cellRect.top;
-                            lpti.rect.right = cellRect.right;
-                            lpti.rect.bottom = cellRect.bottom;
-                            OS.SendMessage (itemToolTipHandle, OS.TTM_NEWTOOLRECT, 0, &lpti);
-                        }
-                        break;
+        if ((wParam & mask) is 0) {
+            int x = OS.GET_X_LPARAM (lParam);
+            int y = OS.GET_Y_LPARAM (lParam);
+            int index;
+            TreeItem item;
+            RECT cellRect, itemRect;
+            if (findCell (x, y, item, index, cellRect, itemRect)) {
+                /*
+                * Feature in Windows.  When the new tool rectangle is
+                * set using TTM_NEWTOOLRECT and the tooltip is visible,
+                * Windows draws the tooltip right away and the sends
+                * WM_NOTIFY with TTN_SHOW.  This means that the tooltip
+                * shows first at the wrong location and then moves to
+                * the right one.  The fix is to hide the tooltip window.
+                */
+                if (OS.SendMessage (itemToolTipHandle, OS.TTM_GETCURRENTTOOL, 0, 0) is 0) {
+                    if (OS.IsWindowVisible (itemToolTipHandle)) {
+                        OS.ShowWindow (itemToolTipHandle, OS.SW_HIDE);
                     }
-                    index++;
                 }
-                if (newFont !is null) OS.SelectObject (hDC, oldFont);
-                OS.ReleaseDC (handle, hDC);
+                TOOLINFO lpti;
+                lpti.cbSize = TOOLINFO.sizeof;
+                lpti.hwnd = handle;
+                lpti.uId = cast(int) handle;
+                lpti.uFlags = OS.TTF_SUBCLASS | OS.TTF_TRANSPARENT;
+                lpti.rect.left = cellRect.left;
+                lpti.rect.top = cellRect.top;
+                lpti.rect.right = cellRect.right;
+                lpti.rect.bottom = cellRect.bottom;
+                OS.SendMessage (itemToolTipHandle, OS.TTM_NEWTOOLRECT, 0, &lpti);
             }
         }
     }
@@ -6283,12 +6654,20 @@
     * This behavior is consistent with the table.
     */
     TVHITTESTINFO lpht;
-    lpht.pt.x = cast(short) (lParam & 0xFFFF);
-    lpht.pt.y = cast(short) (lParam >> 16);
+    lpht.pt.x = OS.GET_X_LPARAM (lParam);
+    lpht.pt.y = OS.GET_Y_LPARAM (lParam);
     OS.SendMessage (handle, OS.TVM_HITTEST, 0, &lpht);
     if (lpht.hItem !is null) {
-        int flags = OS.TVHT_ONITEMICON | OS.TVHT_ONITEMLABEL;
-        if ((style & DWT.FULL_SELECTION) !is 0 || (lpht.flags & flags) !is 0) {
+        bool fakeSelection = (style & DWT.FULL_SELECTION) !is 0;
+        if (!fakeSelection) {
+            if (hooks (DWT.MeasureItem)) {
+                fakeSelection = hitTestSelection (lpht.hItem, lpht.pt.x, lpht.pt.y);
+            } else {
+                int flags = OS.TVHT_ONITEMICON | OS.TVHT_ONITEMLABEL;
+                fakeSelection = (lpht.flags & flags) !is 0;
+            }
+        }
+        if (fakeSelection) {
             if ((wParam & (OS.MK_CONTROL | OS.MK_SHIFT)) is 0) {
                 TVITEM tvItem;
                 tvItem.mask = OS.TVIF_HANDLE | OS.TVIF_STATE;
@@ -6326,11 +6705,9 @@
     }
     if ((style & DWT.DOUBLE_BUFFERED) !is 0 || findImageControl () !is null) {
         bool doubleBuffer = true;
-        if (EXPLORER_THEME) {
-            if (!OS.IsWinCE && OS.WIN32_VERSION >= OS.VERSION (6, 0)) {
-                int exStyle = OS.SendMessage (handle, OS.TVM_GETEXTENDEDSTYLE, 0, 0);
-                if ((exStyle & OS.TVS_EX_DOUBLEBUFFER) !is 0) doubleBuffer = false;
-            }
+        if (explorerTheme) {
+            int exStyle = OS.SendMessage (handle, OS.TVM_GETEXTENDEDSTYLE, 0, 0);
+            if ((exStyle & OS.TVS_EX_DOUBLEBUFFER) !is 0) doubleBuffer = false;
         }
         if (doubleBuffer) {
             GC gc = null;
@@ -6402,7 +6779,7 @@
     * is happening in WM_PRINTCLIENT, the redrawing is not visible.
     */
     printClient = true;
-    int code = callWindowProc (handle, OS.WM_PRINTCLIENT, wParam, lParam);
+    int /*long*/ code = callWindowProc (handle, OS.WM_PRINTCLIENT, wParam, lParam);
     printClient = false;
     return new LRESULT (code);
 }
@@ -6475,7 +6852,7 @@
     * Windows Vista running under the theme manager.
     */
     if (!OS.IsWinCE && OS.WIN32_VERSION >= OS.VERSION (6, 0)) {
-        int code = OS.DefWindowProc (handle, OS.WM_SETREDRAW, wParam, lParam);
+        int /*long*/ code = OS.DefWindowProc (handle, OS.WM_SETREDRAW, wParam, lParam);
         return code is 0 ? LRESULT.ZERO : new LRESULT (code);
     }
     return result;
@@ -6499,12 +6876,8 @@
     * of the selected items is not drawn.  The fix is the
     * redraw the entire tree.
     */
-    if (EXPLORER_THEME) {
-        if (!OS.IsWinCE && OS.WIN32_VERSION >= OS.VERSION (6, 0)) {
-            if ((style & DWT.FULL_SELECTION) !is 0) {
-                OS.InvalidateRect (handle, null, false);
-            }
-        }
+    if (explorerTheme && (style & DWT.FULL_SELECTION) !is 0) {
+        OS.InvalidateRect (handle, null, false);
     }
     if (ignoreResize) return null;
     return super.WM_SIZE (wParam, lParam);
@@ -6526,6 +6899,38 @@
     return result;
 }
 
+override LRESULT WM_VSCROLL (int /*long*/ wParam, int /*long*/ lParam) {
+    bool fixScroll = false;
+    if ((style & DWT.DOUBLE_BUFFERED) !is 0) {
+        int code = OS.LOWORD (wParam);
+        switch (code) {
+            case OS.SB_TOP:
+            case OS.SB_BOTTOM:
+            case OS.SB_LINEDOWN:
+            case OS.SB_LINEUP:
+            case OS.SB_PAGEDOWN:
+            case OS.SB_PAGEUP:
+                fixScroll = (style & DWT.VIRTUAL) !is 0 || hooks (DWT.EraseItem) || hooks (DWT.PaintItem);
+                break;
+        }
+    }
+    if (fixScroll) {
+        style &= ~DWT.DOUBLE_BUFFERED;
+        if (explorerTheme) {
+            OS.SendMessage (handle, OS.TVM_SETEXTENDEDSTYLE, OS.TVS_EX_DOUBLEBUFFER, 0);
+        }
+    }
+    LRESULT result = super.WM_VSCROLL (wParam, lParam);
+    if (fixScroll) {
+        style |= DWT.DOUBLE_BUFFERED;
+        if (explorerTheme) {
+            OS.SendMessage (handle, OS.TVM_SETEXTENDEDSTYLE, OS.TVS_EX_DOUBLEBUFFER, OS.TVS_EX_DOUBLEBUFFER);
+        }
+    }
+    if (result !is null) return result;
+    return result;
+}
+
 override LRESULT wmColorChild (int wParam, int lParam) {
     if (findImageControl () !is null) {
         if (OS.COMCTL32_MAJOR < 6) {
@@ -6544,274 +6949,13 @@
 }
 
 override LRESULT wmNotify (NMHDR* hdr, int wParam, int lParam) {
-    if (hdr.hwndFrom is itemToolTipHandle && hwndHeader !is null) {
-        static if (!OS.IsWinCE) {
-            switch (hdr.code) {
-                case OS.TTN_POP: {
-                    if (display.isXMouseActive ()) {
-                        Shell shell = getShell ();
-                        shell.lockToolTipControl = null;
-                    }
-                    break;
-                }
-                case OS.TTN_SHOW: {
-                    if (display.isXMouseActive ()) {
-                        Shell shell = getShell ();
-                        shell.lockToolTipControl = this;
-                    }
-                    int pos = OS.GetMessagePos ();
-                    POINT pt;
-                    pt.x = cast(short) (pos & 0xFFFF);
-                    pt.y = cast(short) (pos >> 16);
-                    OS.ScreenToClient (handle, &pt);
-                    TVHITTESTINFO lpht;
-                    lpht.pt.x = pt.x;
-                    lpht.pt.y = pt.y;
-                    OS.SendMessage (handle, OS.TVM_HITTEST, 0, &lpht);
-                    if (lpht.hItem !is null) {
-                        auto hDC = OS.GetDC (handle);
-                        HFONT oldFont, newFont = cast(HFONT) OS.SendMessage (handle, OS.WM_GETFONT, 0, 0);
-                        if (newFont !is null) oldFont = OS.SelectObject (hDC, newFont);
-                        LRESULT result = null;
-                        RECT rect;
-                        OS.GetClientRect (hwndParent, &rect);
-                        OS.MapWindowPoints (hwndParent, handle, cast(POINT*) &rect, 2);
-                        TreeItem item = _getItem (lpht.hItem);
-                        int index = 0, count = Math.max (1, OS.SendMessage (hwndHeader, OS.HDM_GETITEMCOUNT, 0, 0));
-                        int [] order = new int [count];
-                        OS.SendMessage (hwndHeader, OS.HDM_GETORDERARRAY, count, order.ptr);
-                        while (index < count) {
-                            HFONT hFont = item.cellFont !is null ? item.cellFont [order [index]] : cast(HFONT)-1;
-                            if (hFont is cast(HFONT)-1) hFont = item.font;
-                            if (hFont !is cast(HFONT)-1) hFont = OS.SelectObject (hDC, hFont);
-                            RECT cellRect = item.getBounds (order [index], true, false, true, false, true, hDC);
-                            if (hFont !is cast(HFONT)-1) OS.SelectObject (hDC, hFont);
-                            if (cellRect.left > rect.right) break;
-                            cellRect.right = Math.min (cellRect.right, rect.right);
-                            if (OS.PtInRect (&cellRect, pt)) {
-                                RECT textRect = item.getBounds (order [index], true, false, false, false, false, hDC);
-                                if (textRect.right > cellRect.right) {
-                                    OS.MapWindowPoints (handle, null, cast(POINT*) &textRect, 2);
-                                    int flags = OS.SWP_NOACTIVATE | OS.SWP_NOSIZE | OS.SWP_NOZORDER;
-                                    SetWindowPos (itemToolTipHandle, null, textRect.left, textRect.top, 0, 0, flags);
-                                    result = LRESULT.ONE;
-                                }
-                                break;
-                            }
-                            index++;
-                        }
-                        if (newFont !is null) OS.SelectObject (hDC, oldFont);
-                        OS.ReleaseDC (handle, hDC);
-                        if (result !is null) return result;
-                    }
-                }
-                default:
-            }
-        }
+    if (hdr.hwndFrom is itemToolTipHandle) {
+        LRESULT result = wmNotifyToolTip (hdr, wParam, lParam);
+        if (result !is null) return result;
     }
     if (hdr.hwndFrom is hwndHeader) {
-        /*
-        * Feature in Windows.  On NT, the automatically created
-        * header control is created as a UNICODE window, not an
-        * ANSI window despite the fact that the parent is created
-        * as an ANSI window.  This means that it sends UNICODE
-        * notification messages to the parent window on NT for
-        * no good reason.  The data and size in the NMHEADER and
-        * HDITEM structs is identical between the platforms so no
-        * different message is actually necessary.  Despite this,
-        * Windows sends different messages.  The fix is to look
-        * for both messages, despite the platform.  This works
-        * because only one will be sent on either platform, never
-        * both.
-        */
-        switch (hdr.code) {
-            case OS.HDN_BEGINTRACKW:
-            case OS.HDN_BEGINTRACKA:
-            case OS.HDN_DIVIDERDBLCLICKW:
-            case OS.HDN_DIVIDERDBLCLICKA: {
-                NMHEADER* phdn = cast(NMHEADER*)lParam;
-                //OS.MoveMemory (phdn, lParam, NMHEADER.sizeof);
-                TreeColumn column = columns [phdn.iItem];
-                if (column !is null && !column.getResizable ()) {
-                    return LRESULT.ONE;
-                }
-                ignoreColumnMove = true;
-                switch (hdr.code) {
-                    case OS.HDN_DIVIDERDBLCLICKW:
-                    case OS.HDN_DIVIDERDBLCLICKA:
-                        if (column !is null) column.pack ();
-                    default:
-                }
-                break;
-            }
-            case OS.NM_RELEASEDCAPTURE: {
-                if (!ignoreColumnMove) {
-                    int count = OS.SendMessage (hwndHeader, OS.HDM_GETITEMCOUNT, 0, 0);
-                    for (int i=0; i<count; i++) {
-                        TreeColumn column = columns [i];
-                        column.updateToolTip (i);
-                    }
-                    updateImageList ();
-                }
-                ignoreColumnMove = false;
-                break;
-            }
-            case OS.HDN_BEGINDRAG: {
-                if (ignoreColumnMove) return LRESULT.ONE;
-                NMHEADER* phdn = cast(NMHEADER*)lParam;
-                //OS.MoveMemory (phdn, lParam, NMHEADER.sizeof);
-                if (phdn.iItem !is -1) {
-                    TreeColumn column = columns [phdn.iItem];
-                    if (column !is null && !column.getMoveable ()) {
-                        ignoreColumnMove = true;
-                        return LRESULT.ONE;
-                    }
-                }
-                break;
-            }
-            case OS.HDN_ENDDRAG: {
-                NMHEADER* phdn = cast(NMHEADER*)lParam;
-                //OS.MoveMemory (phdn, lParam, NMHEADER.sizeof);
-                if (phdn.iItem !is -1 && phdn.pitem !is null) {
-                    HDITEM* pitem = phdn.pitem;
-                    //OS.MoveMemory (pitem, phdn.pitem, HDITEM.sizeof);
-                    if ((pitem.mask & OS.HDI_ORDER) !is 0 && pitem.iOrder !is -1) {
-                        int count = OS.SendMessage (hwndHeader, OS.HDM_GETITEMCOUNT, 0, 0);
-                        int [] order = new int [count];
-                        OS.SendMessage (hwndHeader, OS.HDM_GETORDERARRAY, count, order.ptr);
-                        int index = 0;
-                        while (index < order.length) {
-                            if (order [index] is phdn.iItem) break;
-                            index++;
-                        }
-                        if (index is order.length) index = 0;
-                        if (index is pitem.iOrder) break;
-                        int start = Math.min (index, pitem.iOrder);
-                        int end = Math.max (index, pitem.iOrder);
-                        RECT rect, headerRect;
-                        OS.GetClientRect (handle, &rect);
-                        OS.SendMessage (hwndHeader, OS.HDM_GETITEMRECT, order [start], &headerRect);
-                        rect.left = Math.max (rect.left, headerRect.left);
-                        OS.SendMessage (hwndHeader, OS.HDM_GETITEMRECT, order [end], &headerRect);
-                        rect.right = Math.min (rect.right, headerRect.right);
-                        OS.InvalidateRect (handle, &rect, true);
-                        ignoreColumnMove = false;
-                        for (int i=start; i<=end; i++) {
-                            TreeColumn column = columns [order [i]];
-                            if (!column.isDisposed ()) {
-                                column.postEvent (DWT.Move);
-                            }
-                        }
-                    }
-                }
-                break;
-            }
-            case OS.HDN_ITEMCHANGINGW:
-            case OS.HDN_ITEMCHANGINGA: {
-                NMHEADER* phdn = cast(NMHEADER*)lParam;
-                //OS.MoveMemory (phdn, lParam, NMHEADER.sizeof);
-                if (phdn.pitem !is null) {
-                    HDITEM* newItem = phdn.pitem;
-                    //OS.MoveMemory (newItem, phdn.pitem, HDITEM.sizeof);
-                    if ((newItem.mask & OS.HDI_WIDTH) !is 0) {
-                        RECT rect;
-                        OS.GetClientRect (handle, &rect);
-                        HDITEM oldItem;
-                        oldItem.mask = OS.HDI_WIDTH;
-                        OS.SendMessage (hwndHeader, OS.HDM_GETITEM, phdn.iItem, &oldItem);
-                        int deltaX = newItem.cxy - oldItem.cxy;
-                        RECT headerRect;
-                        OS.SendMessage (hwndHeader, OS.HDM_GETITEMRECT, phdn.iItem, &headerRect);
-                        int gridWidth = linesVisible ? GRID_WIDTH : 0;
-                        rect.left = headerRect.right - gridWidth;
-                        int newX = rect.left + deltaX;
-                        rect.right = Math.max (rect.right, rect.left + Math.abs (deltaX));
-                        if (explorerTheme || (findImageControl () !is null || hooks (DWT.EraseItem) || hooks (DWT.PaintItem))) {
-                            OS.InvalidateRect (handle, &rect, true);
-                            OS.OffsetRect (&rect, deltaX, 0);
-                            OS.InvalidateRect (handle, &rect, true);
-                        } else {
-                            int flags = OS.SW_INVALIDATE | OS.SW_ERASE;
-                            OS.ScrollWindowEx (handle, deltaX, 0, &rect, null, null, null, flags);
-                        }
-                        if (OS.SendMessage (hwndHeader, OS.HDM_ORDERTOINDEX, phdn.iItem, 0) !is 0) {
-                            rect.left = headerRect.left;
-                            rect.right = newX;
-                            OS.InvalidateRect (handle, &rect, true);
-                        }
-                        setScrollWidth ();
-                    }
-                }
-                break;
-            }
-            case OS.HDN_ITEMCHANGEDW:
-            case OS.HDN_ITEMCHANGEDA: {
-                NMHEADER* phdn = cast(NMHEADER*)lParam;
-                //OS.MoveMemory (phdn, lParam, NMHEADER.sizeof);
-                if (phdn.pitem !is null) {
-                    HDITEM* pitem = phdn.pitem;
-                    //OS.MoveMemory (pitem, phdn.pitem, HDITEM.sizeof);
-                    if ((pitem.mask & OS.HDI_WIDTH) !is 0) {
-                        if (ignoreColumnMove) {
-                            if (!OS.IsWinCE && OS.WIN32_VERSION >= OS.VERSION (6, 0)) {
-                                int flags = OS.RDW_UPDATENOW | OS.RDW_ALLCHILDREN;
-                                OS.RedrawWindow (handle, null, null, flags);
-                            } else {
-                                if ((style & DWT.DOUBLE_BUFFERED) is 0) {
-                                    int oldStyle = style;
-                                    style |= DWT.DOUBLE_BUFFERED;
-                                    OS.UpdateWindow (handle);
-                                    style = oldStyle;
-                                }
-                            }
-                        }
-                        TreeColumn column = columns [phdn.iItem];
-                        if (column !is null) {
-                            column.updateToolTip (phdn.iItem);
-                            column.sendEvent (DWT.Resize);
-                            if (isDisposed ()) return LRESULT.ZERO;
-                            int count = OS.SendMessage (hwndHeader, OS.HDM_GETITEMCOUNT, 0, 0);
-                            TreeColumn [] newColumns = new TreeColumn [count];
-                            System.arraycopy (columns, 0, newColumns, 0, count);
-                            int [] order = new int [count];
-                            OS.SendMessage (hwndHeader, OS.HDM_GETORDERARRAY, count, order.ptr);
-                            bool moved = false;
-                            for (int i=0; i<count; i++) {
-                                TreeColumn nextColumn = newColumns [order [i]];
-                                if (moved && !nextColumn.isDisposed ()) {
-                                    nextColumn.updateToolTip (order [i]);
-                                    nextColumn.sendEvent (DWT.Move);
-                                }
-                                if (nextColumn is column) moved = true;
-                            }
-                        }
-                    }
-                    setScrollWidth ();
-                }
-                break;
-            }
-            case OS.HDN_ITEMCLICKW:
-            case OS.HDN_ITEMCLICKA: {
-                NMHEADER* phdn = cast(NMHEADER*)lParam;
-                //OS.MoveMemory (phdn, lParam, NMHEADER.sizeof);
-                TreeColumn column = columns [phdn.iItem];
-                if (column !is null) {
-                    column.postEvent (DWT.Selection);
-                }
-                break;
-            }
-            case OS.HDN_ITEMDBLCLICKW:
-            case OS.HDN_ITEMDBLCLICKA: {
-                NMHEADER* phdn = cast(NMHEADER*)lParam;
-                //OS.MoveMemory (phdn, lParam, NMHEADER.sizeof);
-                TreeColumn column = columns [phdn.iItem];
-                if (column !is null) {
-                    column.postEvent (DWT.DefaultSelection);
-                }
-                break;
-            }
-            default:
-        }
+        LRESULT result = wmNotifyHeader (hdr, wParam, lParam);
+        if (result !is null) return result;
     }
     return super.wmNotify (hdr, wParam, lParam);
 }
@@ -6852,8 +6996,7 @@
                 if (checkVisible) {
                     if (drawCount !is 0 || !OS.IsWindowVisible (handle)) break;
                     RECT itemRect;
-                    itemRect.left = cast(int) lptvdi.item.hItem;
-                    if (OS.SendMessage (handle, OS.TVM_GETITEMRECT, 0, &itemRect) is 0) {
+                    if (!OS.TreeView_GetItemRect (handle, lptvdi.item.hItem, &itemRect, false)) {
                         break;
                     }
                     RECT rect;
@@ -6985,11 +7128,11 @@
             * avoid the operation by testing to see whether
             * the mouse was inside a tree item.
             */
+            if (hooks (DWT.MeasureItem)) return LRESULT.ONE;
             if (hooks (DWT.DefaultSelection)) {
                 POINT pt;
                 int pos = OS.GetMessagePos ();
-                pt.x = cast(short) (pos & 0xFFFF);
-                pt.y = cast(short) (pos >> 16);
+                OS.POINTSTOPOINT (pt, pos);
                 OS.ScreenToClient (handle, &pt);
                 TVHITTESTINFO lpht;
                 lpht.pt.x = pt.x;
@@ -7028,12 +7171,10 @@
             if ((style & DWT.MULTI) !is 0) {
                 if (lockSelection) {
                     /* Save the old selection state for both items */
-                    TVITEM tvItem;
-                    int offset1 = NMHDR.sizeof + 4;
-                    OS.MoveMemory (&tvItem, lParam + offset1, TVITEM.sizeof);
+                    auto treeView = cast(NMTREEVIEW*)lParam;
+                    TVITEM* tvItem = &treeView.itemOld;
                     oldSelected = (tvItem.state & OS.TVIS_SELECTED) !is 0;
-                    int offset2 = NMHDR.sizeof + 4 + TVITEM.sizeof;
-                    OS.MoveMemory (&tvItem, lParam + offset2, TVITEM.sizeof);
+                    tvItem = &treeView.itemNew;
                     newSelected = (tvItem.state & OS.TVIS_SELECTED) !is 0;
                 }
             }
@@ -7045,22 +7186,25 @@
         }
         case OS.TVN_SELCHANGEDA:
         case OS.TVN_SELCHANGEDW: {
+            NMTREEVIEW* treeView = null;
             if ((style & DWT.MULTI) !is 0) {
                 if (lockSelection) {
                     /* Restore the old selection state of both items */
                     if (oldSelected) {
-                        TVITEM tvItem;
-                        int offset = NMHDR.sizeof + 4;
-                        OS.MoveMemory (&tvItem, lParam + offset, TVITEM.sizeof);
+                        if (treeView is null) {
+                            treeView = cast(NMTREEVIEW*)lParam;
+                        }
+                        TVITEM tvItem = treeView.itemOld;
                         tvItem.mask = OS.TVIF_STATE;
                         tvItem.stateMask = OS.TVIS_SELECTED;
                         tvItem.state = OS.TVIS_SELECTED;
                         OS.SendMessage (handle, OS.TVM_SETITEM, 0, &tvItem);
                     }
                     if (!newSelected && ignoreSelect) {
-                        TVITEM tvItem;
-                        int offset = NMHDR.sizeof + 4 + TVITEM.sizeof;
-                        OS.MoveMemory (&tvItem, lParam + offset, TVITEM.sizeof);
+                        if (treeView is null) {
+                            treeView = cast(NMTREEVIEW*)lParam;
+                        }
+                        TVITEM tvItem = treeView.itemNew;
                         tvItem.mask = OS.TVIF_STATE;
                         tvItem.stateMask = OS.TVIS_SELECTED;
                         tvItem.state = 0;
@@ -7069,9 +7213,10 @@
                 }
             }
             if (!ignoreSelect) {
-                TVITEM tvItem;
-                int offset = NMHDR.sizeof + 4 + TVITEM.sizeof;
-                OS.MoveMemory (&tvItem, lParam + offset, TVITEM.sizeof);
+                if (treeView is null) {
+                    treeView = cast(NMTREEVIEW*)lParam;
+                }
+                TVITEM tvItem = treeView.itemNew;
                 hAnchor = tvItem.hItem;
                 Event event = new Event ();
                 event.item = _getItem (&tvItem.hItem, tvItem.lParam);
@@ -7099,9 +7244,9 @@
                 OS.SendMessage (handle, OS.TVM_SETINSERTMARK, 0, 0);
             }
             if (!ignoreExpand) {
-                TVITEM tvItem;
-                int offset = NMHDR.sizeof + 4 + TVITEM.sizeof;
-                OS.MoveMemory (&tvItem, lParam + offset, TVITEM.sizeof);
+                NMTREEVIEW* treeView = cast(NMTREEVIEW*)lParam;
+
+                TVITEM* tvItem = &treeView.itemNew;
                 /*
                 * Feature in Windows.  In some cases, TVM_ITEMEXPANDING
                 * is sent from within TVM_DELETEITEM for the tree item
@@ -7114,9 +7259,7 @@
                 if (item is null) break;
                 Event event = new Event ();
                 event.item = item;
-                int action = *cast(int*)(lParam + NMHDR.sizeof);
-                //OS.MoveMemory (action, lParam + NMHDR.sizeof, 4);
-                switch (action) {
+                switch (treeView.action) {
                     case OS.TVE_EXPAND:
                         /*
                         * Bug in Windows.  When the numeric keypad asterisk
@@ -7176,16 +7319,16 @@
             */
             if (!OS.IsWinCE && OS.COMCTL32_MAJOR >= 6) {
                 if (imageList !is null) {
-                    TVITEM tvItem;
-                    int offset = NMHDR.sizeof + 4 + TVITEM.sizeof;
-                    OS.MoveMemory (&tvItem, lParam + offset, TVITEM.sizeof);
+                    NMTREEVIEW* treeView = cast(NMTREEVIEW*)lParam;
+
+                    TVITEM* tvItem = &treeView.itemNew;
                     if (tvItem.hItem !is null) {
                         int bits = OS.GetWindowLong (handle, OS.GWL_STYLE);
                         if ((bits & OS.TVS_FULLROWSELECT) is 0) {
                             RECT rect;
-                            rect.left = cast(int)tvItem.hItem;
-                            OS.SendMessage (handle, OS.TVM_GETITEMRECT, 0, &rect);
-                            OS.InvalidateRect (handle, &rect, true);
+                            if (OS.TreeView_GetItemRect (handle, tvItem.hItem, &rect, false)) {
+                                OS.InvalidateRect (handle, &rect, true);
+                            }
                         }
                     }
                 }
@@ -7195,11 +7338,13 @@
         }
         case OS.TVN_BEGINDRAGA:
         case OS.TVN_BEGINDRAGW:
+            if (OS.GetKeyState (OS.VK_LBUTTON) >= 0) break;
+            //FALL THROUGH
         case OS.TVN_BEGINRDRAGA:
         case OS.TVN_BEGINRDRAGW: {
-            TVITEM tvItem;
-            int offset = NMHDR.sizeof + 4 + TVITEM.sizeof;
-            OS.MoveMemory (&tvItem, lParam + offset, TVITEM.sizeof);
+            dragStarted = true;
+            NMTREEVIEW* treeView = cast(NMTREEVIEW*)lParam;
+            TVITEM* tvItem = &treeView.itemNew;
             if (tvItem.hItem !is null && (tvItem.state & OS.TVIS_SELECTED) is 0) {
                 hSelect = tvItem.hItem;
                 ignoreSelect = ignoreDeselect = true;
@@ -7207,7 +7352,6 @@
                 ignoreSelect = ignoreDeselect = false;
                 hSelect = null;
             }
-            dragStarted = true;
             break;
         }
         case OS.NM_RECOGNIZEGESTURE: {
@@ -7244,4 +7388,336 @@
     return super.wmNotifyChild (hdr, wParam, lParam);
 }
 
-}
+LRESULT wmNotifyHeader (NMHDR* hdr, int /*long*/ wParam, int /*long*/ lParam) {
+    /*
+    * Feature in Windows.  On NT, the automatically created
+    * header control is created as a UNICODE window, not an
+    * ANSI window despite the fact that the parent is created
+    * as an ANSI window.  This means that it sends UNICODE
+    * notification messages to the parent window on NT for
+    * no good reason.  The data and size in the NMHEADER and
+    * HDITEM structs is identical between the platforms so no
+    * different message is actually necessary.  Despite this,
+    * Windows sends different messages.  The fix is to look
+    * for both messages, despite the platform.  This works
+    * because only one will be sent on either platform, never
+    * both.
+    */
+    switch (hdr.code) {
+        case OS.HDN_BEGINTRACKW:
+        case OS.HDN_BEGINTRACKA:
+        case OS.HDN_DIVIDERDBLCLICKW:
+        case OS.HDN_DIVIDERDBLCLICKA: {
+            NMHEADER* phdn = cast(NMHEADER*)lParam;
+            TreeColumn column = columns [phdn.iItem];
+            if (column !is null && !column.getResizable ()) {
+                return LRESULT.ONE;
+            }
+            ignoreColumnMove = true;
+            switch (hdr.code) {
+                case OS.HDN_DIVIDERDBLCLICKW:
+                case OS.HDN_DIVIDERDBLCLICKA:
+                    if (column !is null) column.pack ();
+            }
+            break;
+        }
+        case OS.NM_RELEASEDCAPTURE: {
+            if (!ignoreColumnMove) {
+                for (int i=0; i<columnCount; i++) {
+                    TreeColumn column = columns [i];
+                    column.updateToolTip (i);
+                }
+                updateImageList ();
+            }
+            ignoreColumnMove = false;
+            break;
+        }
+        case OS.HDN_BEGINDRAG: {
+            if (ignoreColumnMove) return LRESULT.ONE;
+            NMHEADER* phdn = cast(NMHEADER*)lParam;
+            if (phdn.iItem !is -1) {
+                TreeColumn column = columns [phdn.iItem];
+                if (column !is null && !column.getMoveable ()) {
+                    ignoreColumnMove = true;
+                    return LRESULT.ONE;
+                }
+            }
+            break;
+        }
+        case OS.HDN_ENDDRAG: {
+            NMHEADER* phdn = cast(NMHEADER*)lParam;
+            if (cast(int)phdn.iItem !is -1 && phdn.pitem !is null) {
+                HDITEM* pitem = cast(HDITEM*)phdn.pitem;
+                if ((pitem.mask & OS.HDI_ORDER) !is 0 && pitem.iOrder !is -1) {
+                    int [] order = new int [columnCount];
+                    OS.SendMessage (hwndHeader, OS.HDM_GETORDERARRAY, columnCount, order.ptr);
+                    int index = 0;
+                    while (index < order.length) {
+                        if (order [index] is phdn.iItem) break;
+                        index++;
+                    }
+                    if (index is order.length) index = 0;
+                    if (index is pitem.iOrder) break;
+                    int start = Math.min (index, pitem.iOrder);
+                    int end = Math.max (index, pitem.iOrder);
+                    RECT rect, headerRect;
+                    OS.GetClientRect (handle, &rect);
+                    OS.SendMessage (hwndHeader, OS.HDM_GETITEMRECT, order [start], &headerRect);
+                    rect.left = Math.max (rect.left, headerRect.left);
+                    OS.SendMessage (hwndHeader, OS.HDM_GETITEMRECT, order [end], &headerRect);
+                    rect.right = Math.min (rect.right, headerRect.right);
+                    OS.InvalidateRect (handle, &rect, true);
+                    ignoreColumnMove = false;
+                    for (int i=start; i<=end; i++) {
+                        TreeColumn column = columns [order [i]];
+                        if (!column.isDisposed ()) {
+                            column.postEvent (DWT.Move);
+                        }
+                    }
+                }
+            }
+            break;
+        }
+        case OS.HDN_ITEMCHANGINGW:
+        case OS.HDN_ITEMCHANGINGA: {
+            NMHEADER* phdn = cast(NMHEADER*)lParam;
+            if (phdn.pitem !is null) {
+                HDITEM* newItem = cast(HDITEM*)phdn.pitem;
+                if ((newItem.mask & OS.HDI_WIDTH) !is 0) {
+                    RECT rect;
+                    OS.GetClientRect (handle, &rect);
+                    HDITEM oldItem;
+                    oldItem.mask = OS.HDI_WIDTH;
+                    OS.SendMessage (hwndHeader, OS.HDM_GETITEM, phdn.iItem, &oldItem);
+                    int deltaX = newItem.cxy - oldItem.cxy;
+                    RECT headerRect;
+                    OS.SendMessage (hwndHeader, OS.HDM_GETITEMRECT, phdn.iItem, &headerRect);
+                    int gridWidth = linesVisible ? GRID_WIDTH : 0;
+                    rect.left = headerRect.right - gridWidth;
+                    int newX = rect.left + deltaX;
+                    rect.right = Math.max (rect.right, rect.left + Math.abs (deltaX));
+                    if (explorerTheme || (findImageControl () !is null || hooks (DWT.MeasureItem) || hooks (DWT.EraseItem) || hooks (DWT.PaintItem))) {
+                        rect.left -= OS.GetSystemMetrics (OS.SM_CXFOCUSBORDER);
+                        OS.InvalidateRect (handle, &rect, true);
+                        OS.OffsetRect (&rect, deltaX, 0);
+                        OS.InvalidateRect (handle, &rect, true);
+                    } else {
+                        int flags = OS.SW_INVALIDATE | OS.SW_ERASE;
+                        OS.ScrollWindowEx (handle, deltaX, 0, &rect, null, null, null, flags);
+                    }
+                    if (OS.SendMessage (hwndHeader, OS.HDM_ORDERTOINDEX, phdn.iItem, 0) !is 0) {
+                        rect.left = headerRect.left;
+                        rect.right = newX;
+                        OS.InvalidateRect (handle, &rect, true);
+                    }
+                    setScrollWidth ();
+                }
+            }
+            break;
+        }
+        case OS.HDN_ITEMCHANGEDW:
+        case OS.HDN_ITEMCHANGEDA: {
+            NMHEADER* phdn = cast(NMHEADER*)lParam;
+            if (phdn.pitem !is null) {
+                HDITEM* pitem = cast(HDITEM*)phdn.pitem;
+                if ((pitem.mask & OS.HDI_WIDTH) !is 0) {
+                    if (ignoreColumnMove) {
+                        if (!OS.IsWinCE && OS.WIN32_VERSION >= OS.VERSION (6, 0)) {
+                            int flags = OS.RDW_UPDATENOW | OS.RDW_ALLCHILDREN;
+                            OS.RedrawWindow (handle, null, null, flags);
+                        } else {
+                            if ((style & DWT.DOUBLE_BUFFERED) is 0) {
+                                int oldStyle = style;
+                                style |= DWT.DOUBLE_BUFFERED;
+                                OS.UpdateWindow (handle);
+                                style = oldStyle;
+                            }
+                        }
+                    }
+                    TreeColumn column = columns [phdn.iItem];
+                    if (column !is null) {
+                        column.updateToolTip (phdn.iItem);
+                        column.sendEvent (DWT.Resize);
+                        if (isDisposed ()) return LRESULT.ZERO;
+                        TreeColumn [] newColumns = new TreeColumn [columnCount];
+                        System.arraycopy (columns, 0, newColumns, 0, columnCount);
+                        int [] order = new int [columnCount];
+                        OS.SendMessage (hwndHeader, OS.HDM_GETORDERARRAY, columnCount, order.ptr);
+                        bool moved = false;
+                        for (int i=0; i<columnCount; i++) {
+                            TreeColumn nextColumn = newColumns [order [i]];
+                            if (moved && !nextColumn.isDisposed ()) {
+                                nextColumn.updateToolTip (order [i]);
+                                nextColumn.sendEvent (DWT.Move);
+                            }
+                            if (nextColumn is column) moved = true;
+                        }
+                    }
+                }
+                setScrollWidth ();
+            }
+            break;
+        }
+        case OS.HDN_ITEMCLICKW:
+        case OS.HDN_ITEMCLICKA: {
+            NMHEADER* phdn = cast(NMHEADER*)lParam;
+            TreeColumn column = columns [phdn.iItem];
+            if (column !is null) {
+                column.postEvent (DWT.Selection);
+            }
+            break;
+        }
+        case OS.HDN_ITEMDBLCLICKW:
+        case OS.HDN_ITEMDBLCLICKA: {
+            NMHEADER* phdn = cast(NMHEADER*)lParam;
+            TreeColumn column = columns [phdn.iItem];
+            if (column !is null) {
+                column.postEvent (DWT.DefaultSelection);
+            }
+            break;
+        }
+    }
+    return null;
+}
+
+LRESULT wmNotifyToolTip (NMHDR* hdr, int /*long*/ wParam, int /*long*/ lParam) {
+    if (OS.IsWinCE) return null;
+    switch (hdr.code) {
+        case OS.NM_CUSTOMDRAW: {
+            NMTTCUSTOMDRAW* nmcd = cast(NMTTCUSTOMDRAW*)lParam;
+            return wmNotifyToolTip (nmcd, lParam);
+        }
+        case OS.TTN_SHOW: {
+            LRESULT result = super.wmNotify (hdr, wParam, lParam);
+            if (result !is null) return result;
+            int pos = OS.GetMessagePos ();
+            POINT pt;
+            OS.POINTSTOPOINT (pt, pos);
+            OS.ScreenToClient (handle, &pt);
+            int index;
+            TreeItem item;
+            RECT cellRect, itemRect;
+            if (findCell (pt.x, pt.y, item, index, cellRect, itemRect)) {
+                RECT* toolRect = toolTipRect (&itemRect);
+                OS.MapWindowPoints (handle, null, cast(POINT*)toolRect, 2);
+                int width = toolRect.right - toolRect.left;
+                int height = toolRect.bottom - toolRect.top;
+                int flags = OS.SWP_NOACTIVATE | OS.SWP_NOZORDER | OS.SWP_NOSIZE;
+                if (isCustomToolTip ()) flags &= ~OS.SWP_NOSIZE;
+                SetWindowPos (itemToolTipHandle, null, toolRect.left, toolRect.top, width, height, flags);
+                return LRESULT.ONE;
+            }
+            return result;
+        }
+    }
+    return null;
+}
+
+LRESULT wmNotifyToolTip (NMTTCUSTOMDRAW* nmcd, int /*long*/ lParam) {
+    if (OS.IsWinCE) return null;
+    switch (nmcd.nmcd.dwDrawStage) {
+        case OS.CDDS_PREPAINT: {
+            if (isCustomToolTip ()) {
+                //TEMPORARY CODE
+                //nmcd.uDrawFlags |= OS.DT_CALCRECT;
+                //OS.MoveMemory (lParam, nmcd, NMTTCUSTOMDRAW.sizeof);
+                if (!OS.IsWinCE && OS.WIN32_VERSION < OS.VERSION (6, 0)) {
+                    OS.SetTextColor (nmcd.nmcd.hdc, OS.GetSysColor (OS.COLOR_INFOBK));
+                }
+                return new LRESULT (OS.CDRF_NOTIFYPOSTPAINT | OS.CDRF_NEWFONT);
+            }
+            break;
+        }
+        case OS.CDDS_POSTPAINT: {
+            if (!OS.IsWinCE && OS.WIN32_VERSION < OS.VERSION (6, 0)) {
+                OS.SetTextColor (nmcd.nmcd.hdc, OS.GetSysColor (OS.COLOR_INFOTEXT));
+            }
+            if (OS.SendMessage (itemToolTipHandle, OS.TTM_GETCURRENTTOOL, 0, 0) !is 0) {
+                TOOLINFO lpti;
+                lpti.cbSize = TOOLINFO.sizeof;
+                if (OS.SendMessage (itemToolTipHandle, OS.TTM_GETCURRENTTOOL, 0, cast(int)&lpti) !is 0) {
+                    int index;
+                    TreeItem item;
+                    RECT cellRect, itemRect;
+                    int pos = OS.GetMessagePos ();
+                    POINT pt;
+                    OS.POINTSTOPOINT (pt, pos);
+                    OS.ScreenToClient (handle, &pt);
+                    if (findCell (pt.x, pt.y, item, index, cellRect, itemRect)) {
+                        auto hDC = OS.GetDC (handle);
+                        auto hFont = item.fontHandle (index);
+                        if (hFont is cast(HFONT)-1) hFont = cast(HFONT) OS.SendMessage (handle, OS.WM_GETFONT, 0, 0);
+                        HFONT oldFont = OS.SelectObject (hDC, hFont);
+                        LRESULT result = null;
+                        bool drawForeground = true;
+                        cellRect = item.getBounds (index, true, true, false, false, false, hDC);
+                        if (hooks (DWT.EraseItem)) {
+                            Event event = sendEraseItemEvent (item, nmcd, index, &cellRect);
+                            if (isDisposed () || item.isDisposed ()) break;
+                            if (event.doit) {
+                                drawForeground = (event.detail & DWT.FOREGROUND) !is 0;
+                            } else {
+                                drawForeground = false;
+                            }
+                        }
+                        if (drawForeground) {
+                            int nSavedDC = OS.SaveDC (nmcd.nmcd.hdc);
+                            int gridWidth = getLinesVisible () ? Table.GRID_WIDTH : 0;
+                            RECT* insetRect = toolTipInset (&cellRect);
+                            OS.SetWindowOrgEx (nmcd.nmcd.hdc, insetRect.left, insetRect.top, null);
+                            GCData data = new GCData ();
+                            data.device = display;
+                            data.foreground = OS.GetTextColor (nmcd.nmcd.hdc);
+                            data.background = OS.GetBkColor (nmcd.nmcd.hdc);
+                            data.font = Font.win32_new (display, hFont);
+                            GC gc = GC.win32_new (nmcd.nmcd.hdc, data);
+                            int x = cellRect.left + INSET;
+                            if (index !is 0) x -= gridWidth;
+                            Image image = item.getImage (index);
+                            if (image !is null || index is 0) {
+                                Point size = getImageSize ();
+                                RECT imageRect = item.getBounds (index, false, true, false, false, false, hDC);
+                                if (imageList is null) size.x = imageRect.right - imageRect.left;
+                                if (image !is null) {
+                                    Rectangle rect = image.getBounds ();
+                                    gc.drawImage (image, rect.x, rect.y, rect.width, rect.height, x, imageRect.top, size.x, size.y);
+                                    x += INSET + (index is 0 ? 1 : 0);
+                                }
+                                x += size.x;
+                            } else {
+                                x += INSET;
+                            }
+                            String string = item.getText (index);
+                            if (string !is null) {
+                                int flags = OS.DT_NOPREFIX | OS.DT_SINGLELINE | OS.DT_VCENTER;
+                                TreeColumn column = columns !is null ? columns [index] : null;
+                                if (column !is null) {
+                                    if ((column.style & DWT.CENTER) !is 0) flags |= OS.DT_CENTER;
+                                    if ((column.style & DWT.RIGHT) !is 0) flags |= OS.DT_RIGHT;
+                                }
+                                TCHAR[] buffer = StrToTCHARs (getCodePage (), string, false);
+                                RECT textRect;
+                                OS.SetRect (&textRect, x, cellRect.top, cellRect.right, cellRect.bottom);
+                                OS.DrawText (nmcd.nmcd.hdc, buffer.ptr, buffer.length, &textRect, flags);
+                            }
+                            gc.dispose ();
+                            OS.RestoreDC (nmcd.nmcd.hdc, nSavedDC);
+                        }
+                        if (hooks (DWT.PaintItem)) {
+                            itemRect = item.getBounds (index, true, true, false, false, false, hDC);
+                            sendPaintItemEvent (item, nmcd, index, &itemRect);
+                        }
+                        OS.SelectObject (hDC, oldFont);
+                        OS.ReleaseDC (handle, hDC);
+                        if (result !is null) return result;
+                    }
+                    break;
+                }
+            }
+            break;
+        }
+    }
+    return null;
+}
+
+}