Mercurial > projects > dwt-win
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 = ▭ } 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; +} + +}