comparison 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
comparison
equal deleted inserted replaced
212:ab60f3309436 213:36f5cb12e1a2
35 import dwt.widgets.Display; 35 import dwt.widgets.Display;
36 import dwt.widgets.Shell; 36 import dwt.widgets.Shell;
37 import dwt.widgets.Control; 37 import dwt.widgets.Control;
38 import dwt.widgets.Listener; 38 import dwt.widgets.Listener;
39 import dwt.widgets.Widget; 39 import dwt.widgets.Widget;
40 import dwt.widgets.Table;
40 41
41 import dwt.dwthelper.utils; 42 import dwt.dwthelper.utils;
42 43
43 44
44 /** 45 /**
75 * } 76 * }
76 * }); 77 * });
77 * </pre></code> 78 * </pre></code>
78 * </p><p> 79 * </p><p>
79 * Note that although this class is a subclass of <code>Composite</code>, 80 * Note that although this class is a subclass of <code>Composite</code>,
80 * it does not make sense to add <code>Control</code> children to it, 81 * it does not normally make sense to add <code>Control</code> children to
81 * or set a layout on it. 82 * it, or set a layout on it, unless implementing something like a cell
83 * editor.
82 * </p><p> 84 * </p><p>
83 * <dl> 85 * <dl>
84 * <dt><b>Styles:</b></dt> 86 * <dt><b>Styles:</b></dt>
85 * <dd>SINGLE, MULTI, CHECK, FULL_SELECTION, VIRTUAL</dd> 87 * <dd>SINGLE, MULTI, CHECK, FULL_SELECTION, VIRTUAL, NO_SCROLL</dd>
86 * <dt><b>Events:</b></dt> 88 * <dt><b>Events:</b></dt>
87 * <dd>Selection, DefaultSelection, Collapse, Expand, SetData, MeasureItem, EraseItem, PaintItem</dd> 89 * <dd>Selection, DefaultSelection, Collapse, Expand, SetData, MeasureItem, EraseItem, PaintItem</dd>
88 * </dl> 90 * </dl>
89 * </p><p> 91 * </p><p>
90 * Note: Only one of the styles SINGLE and MULTI may be specified. 92 * Note: Only one of the styles SINGLE and MULTI may be specified.
100 alias Composite.setCursor setCursor; 102 alias Composite.setCursor setCursor;
101 alias Composite.sort sort; 103 alias Composite.sort sort;
102 104
103 TreeItem [] items; 105 TreeItem [] items;
104 TreeColumn [] columns; 106 TreeColumn [] columns;
107 int columnCount;
105 ImageList imageList, headerImageList; 108 ImageList imageList, headerImageList;
106 TreeItem currentItem; 109 TreeItem currentItem;
107 TreeColumn sortColumn; 110 TreeColumn sortColumn;
111 RECT* focusRect;
108 HWND hwndParent, hwndHeader; 112 HWND hwndParent, hwndHeader;
109 HANDLE hAnchor, hInsert, hSelect; 113 HANDLE hAnchor, hInsert, hSelect;
110 int lastID; 114 int lastID;
111 HANDLE hFirstIndexOf, hLastIndexOf; 115 HANDLE hFirstIndexOf, hLastIndexOf;
112 int lastIndexOf, itemCount, sortDirection; 116 int lastIndexOf, itemCount, sortDirection;
175 * </ul> 179 * </ul>
176 * 180 *
177 * @see DWT#SINGLE 181 * @see DWT#SINGLE
178 * @see DWT#MULTI 182 * @see DWT#MULTI
179 * @see DWT#CHECK 183 * @see DWT#CHECK
184 * @see DWT#FULL_SELECTION
185 * @see DWT#VIRTUAL
186 * @see DWT#NO_SCROLL
180 * @see Widget#checkSubclass 187 * @see Widget#checkSubclass
181 * @see Widget#getStyle 188 * @see Widget#getStyle
182 */ 189 */
183 public this (Composite parent, int style) { 190 public this (Composite parent, int style) {
184 static_this(); 191 static_this();
185 super (parent, checkStyle (style)); 192 super (parent, checkStyle (style));
186 } 193 }
187 194
188 static int checkStyle (int style) { 195 static int checkStyle (int style) {
189 /* 196 /*
190 * Feature in Windows. It is not possible to create 197 * Feature in Windows. Even when WS_HSCROLL or
191 * a tree that scrolls and does not have scroll bars. 198 * WS_VSCROLL is not specified, Windows creates
192 * The TVS_NOSCROLL style will remove the scroll bars 199 * trees and tables with scroll bars. The fix
193 * but the tree will never scroll. Therefore, no matter 200 * is to set H_SCROLL and V_SCROLL.
194 * what style bits are specified, set the H_SCROLL and 201 *
195 * V_SCROLL bits so that the DWT style will match the 202 * NOTE: This code appears on all platforms so that
196 * widget that Windows creates. 203 * applications have consistent scroll bar behavior.
197 */ 204 */
198 style |= DWT.H_SCROLL | DWT.V_SCROLL; 205 if ((style & DWT.NO_SCROLL) is 0) {
206 style |= DWT.H_SCROLL | DWT.V_SCROLL;
207 }
208 /*
209 * Note: Windows only supports TVS_NOSCROLL and TVS_NOHSCROLL.
210 */
211 if ((style & DWT.H_SCROLL) !is 0 && (style & DWT.V_SCROLL) is 0) {
212 style |= DWT.V_SCROLL;
213 }
199 return checkBits (style, DWT.SINGLE, DWT.MULTI, 0, 0, 0, 0); 214 return checkBits (style, DWT.SINGLE, DWT.MULTI, 0, 0, 0, 0);
200 } 215 }
201 216
202 override void _addListener (int eventType, Listener listener) { 217 override void _addListener (int eventType, Listener listener) {
203 super._addListener (eventType, listener); 218 super._addListener (eventType, listener);
213 case DWT.MeasureItem: 228 case DWT.MeasureItem:
214 case DWT.EraseItem: 229 case DWT.EraseItem:
215 case DWT.PaintItem: { 230 case DWT.PaintItem: {
216 customDraw = true; 231 customDraw = true;
217 style |= DWT.DOUBLE_BUFFERED; 232 style |= DWT.DOUBLE_BUFFERED;
233 if (isCustomToolTip ()) createItemToolTips ();
218 OS.SendMessage (handle, OS.TVM_SETSCROLLTIME, 0, 0); 234 OS.SendMessage (handle, OS.TVM_SETSCROLLTIME, 0, 0);
219 int bits = OS.GetWindowLong (handle, OS.GWL_STYLE); 235 int bits = OS.GetWindowLong (handle, OS.GWL_STYLE);
220 bits |= OS.TVS_NOTOOLTIPS; 236 if (eventType is DWT.MeasureItem) {
221 if (eventType is DWT.MeasureItem) bits |= OS.TVS_NOHSCROLL; 237 if (explorerTheme) {
238 int bits1 = OS.SendMessage (handle, OS.TVM_GETEXTENDEDSTYLE, 0, 0);
239 bits1 &= ~OS.TVS_EX_AUTOHSCROLL;
240 OS.SendMessage (handle, OS.TVM_SETEXTENDEDSTYLE, 0, bits1);
241 }
242 bits |= OS.TVS_NOHSCROLL;
243 }
222 /* 244 /*
223 * Feature in Windows. When the tree has the style 245 * Feature in Windows. When the tree has the style
224 * TVS_FULLROWSELECT, the background color for the 246 * TVS_FULLROWSELECT, the background color for the
225 * entire row is filled when an item is painted, 247 * entire row is filled when an item is painted,
226 * drawing on top of any custom drawing. The fix 248 * drawing on top of any custom drawing. The fix
417 OS.SetTextColor (hDC, getForegroundPixel ()); 439 OS.SetTextColor (hDC, getForegroundPixel ());
418 } 440 }
419 } 441 }
420 } 442 }
421 } 443 }
422 int count = 0;
423 int [] order = null; 444 int [] order = null;
424 RECT clientRect; 445 RECT clientRect;
425 OS.GetClientRect (scrolledHandle (), &clientRect); 446 OS.GetClientRect (scrolledHandle (), &clientRect);
426 if (hwndHeader !is null) { 447 if (hwndHeader !is null) {
427 OS.MapWindowPoints (hwndParent, handle, cast(POINT*) &clientRect, 2); 448 OS.MapWindowPoints (hwndParent, handle, cast(POINT*) &clientRect, 2);
428 count = OS.SendMessage (hwndHeader, OS.HDM_GETITEMCOUNT, 0, 0); 449 if (columnCount !is 0) {
429 if (count !is 0) { 450 order = new int [columnCount];
430 order = new int [count]; 451 OS.SendMessage (hwndHeader, OS.HDM_GETORDERARRAY, columnCount, cast(int) order.ptr);
431 OS.SendMessage (hwndHeader, OS.HDM_GETORDERARRAY, count, cast(int) order.ptr);
432 } 452 }
433 } 453 }
434 int sortIndex = -1, clrSortBk = -1; 454 int sortIndex = -1, clrSortBk = -1;
435 if (OS.COMCTL32_MAJOR >= 6 && OS.IsAppThemed ()) { 455 if (OS.COMCTL32_MAJOR >= 6 && OS.IsAppThemed ()) {
436 if (sortColumn !is null && sortDirection !is DWT.NONE) { 456 if (sortColumn !is null && sortDirection !is DWT.NONE) {
440 } 460 }
441 } 461 }
442 } 462 }
443 int x = 0; 463 int x = 0;
444 Point size = null; 464 Point size = null;
445 for (int i=0; i<Math.max (1, count); i++) { 465 for (int i=0; i<Math.max (1, columnCount); i++) {
446 int index = order is null ? i : order [i], width = nmcd.nmcd.rc.right - nmcd.nmcd.rc.left; 466 int index = order is null ? i : order [i], width = nmcd.nmcd.rc.right - nmcd.nmcd.rc.left;
447 if (count > 0 && hwndHeader !is null) { 467 if (columnCount > 0 && hwndHeader !is null) {
448 HDITEM hdItem; 468 HDITEM hdItem;
449 hdItem.mask = OS.HDI_WIDTH; 469 hdItem.mask = OS.HDI_WIDTH;
450 OS.SendMessage (hwndHeader, OS.HDM_GETITEM, index, &hdItem); 470 OS.SendMessage (hwndHeader, OS.HDM_GETITEM, index, &hdItem);
451 width = hdItem.cxy; 471 width = hdItem.cxy;
452 } 472 }
462 RECT itemRect = item.getBounds (index, true, true, false, false, true, hDC); 482 RECT itemRect = item.getBounds (index, true, true, false, false, true, hDC);
463 itemRect.left -= EXPLORER_EXTRA; 483 itemRect.left -= EXPLORER_EXTRA;
464 itemRect.right += EXPLORER_EXTRA + 1; 484 itemRect.right += EXPLORER_EXTRA + 1;
465 pClipRect.left = itemRect.left; 485 pClipRect.left = itemRect.left;
466 pClipRect.right = itemRect.right; 486 pClipRect.right = itemRect.right;
467 if (count > 0 && hwndHeader !is null) { 487 if (columnCount > 0 && hwndHeader !is null) {
468 HDITEM hdItem; 488 HDITEM hdItem;
469 hdItem.mask = OS.HDI_WIDTH; 489 hdItem.mask = OS.HDI_WIDTH;
470 OS.SendMessage (hwndHeader, OS.HDM_GETITEM, index, &hdItem); 490 OS.SendMessage (hwndHeader, OS.HDM_GETITEM, index, &hdItem);
471 pClipRect.right = Math.min (pClipRect.right, nmcd.nmcd.rc.left + hdItem.cxy); 491 pClipRect.right = Math.min (pClipRect.right, nmcd.nmcd.rc.left + hdItem.cxy);
472 } 492 }
473 } 493 }
474 RECT pRect; 494 RECT pRect;
475 OS.SetRect (&pRect, nmcd.nmcd.rc.left, nmcd.nmcd.rc.top, nmcd.nmcd.rc.right, nmcd.nmcd.rc.bottom); 495 OS.SetRect (&pRect, nmcd.nmcd.rc.left, nmcd.nmcd.rc.top, nmcd.nmcd.rc.right, nmcd.nmcd.rc.bottom);
476 if (count > 0 && hwndHeader !is null) { 496 if (columnCount > 0 && hwndHeader !is null) {
477 int totalWidth = 0; 497 int totalWidth = 0;
478 HDITEM hdItem; 498 HDITEM hdItem;
479 hdItem.mask = OS.HDI_WIDTH; 499 hdItem.mask = OS.HDI_WIDTH;
480 for (int j=0; j<count; j++) { 500 for (int j=0; j<columnCount; j++) {
481 OS.SendMessage (hwndHeader, OS.HDM_GETITEM, j, &hdItem); 501 OS.SendMessage (hwndHeader, OS.HDM_GETITEM, j, &hdItem);
482 totalWidth += hdItem.cxy; 502 totalWidth += hdItem.cxy;
483 } 503 }
484 if (totalWidth > clientRect.right - clientRect.left) { 504 if (totalWidth > clientRect.right - clientRect.left) {
485 pRect.left = 0; 505 pRect.left = 0;
495 if (OS.GetFocus () !is handle && selected && !hot) iStateId = OS.TREIS_SELECTEDNOTFOCUS; 515 if (OS.GetFocus () !is handle && selected && !hot) iStateId = OS.TREIS_SELECTEDNOTFOCUS;
496 OS.DrawThemeBackground (hTheme, hDC, OS.TVP_TREEITEM, iStateId, &pRect, &pClipRect); 516 OS.DrawThemeBackground (hTheme, hDC, OS.TVP_TREEITEM, iStateId, &pRect, &pClipRect);
497 OS.CloseThemeData (hTheme); 517 OS.CloseThemeData (hTheme);
498 } 518 }
499 if (draw) fillBackground (hDC, OS.GetBkColor (hDC), &pClipRect); 519 if (draw) fillBackground (hDC, OS.GetBkColor (hDC), &pClipRect);
500 }
501 } else {
502 if (explorerTheme && hooks (DWT.EraseItem)) {
503 if ((selected && !ignoreDrawSelection) || (hot && !ignoreDrawHot)) {
504 RECT pRect = item.getBounds (index, true, true, false, false, false, hDC);
505 RECT pClipRect = item.getBounds (index, true, true, false, false, true, hDC);
506 pRect.left -= EXPLORER_EXTRA;
507 pRect.right += EXPLORER_EXTRA;
508 pClipRect.left -= EXPLORER_EXTRA;
509 pClipRect.right += EXPLORER_EXTRA;
510 auto hTheme = OS.OpenThemeData (handle, cast(TCHAR*) Display.TREEVIEW);
511 int iStateId = selected ? OS.TREIS_SELECTED : OS.TREIS_HOT;
512 if (OS.GetFocus () !is handle && selected && !hot) iStateId = OS.TREIS_SELECTEDNOTFOCUS;
513 OS.DrawThemeBackground (hTheme, hDC, OS.TVP_TREEITEM, iStateId, &pRect, &pClipRect);
514 OS.CloseThemeData (hTheme);
515 }
516 } 520 }
517 } 521 }
518 } 522 }
519 if (x + width > clientRect.left) { 523 if (x + width > clientRect.left) {
520 RECT rect; 524 RECT rect;
577 ignoreDrawForeground = ignoreDrawBackground = ignoreDrawSelection = ignoreDrawFocus = ignoreDrawHot = false; 581 ignoreDrawForeground = ignoreDrawBackground = ignoreDrawSelection = ignoreDrawFocus = ignoreDrawHot = false;
578 OS.SetRect (&rect, x, nmcd.nmcd.rc.top, x + width, nmcd.nmcd.rc.bottom); 582 OS.SetRect (&rect, x, nmcd.nmcd.rc.top, x + width, nmcd.nmcd.rc.bottom);
579 backgroundRect = &rect; 583 backgroundRect = &rect;
580 } 584 }
581 int clrText = -1, clrTextBk = -1; 585 int clrText = -1, clrTextBk = -1;
582 HFONT hFont = item.cellFont !is null ? item.cellFont [index] : cast(HFONT)-1; 586 auto hFont = item.fontHandle (index);
583 if (hFont is cast(HFONT)-1) hFont = item.font;
584 if (selectionForeground !is -1) clrText = selectionForeground; 587 if (selectionForeground !is -1) clrText = selectionForeground;
585 if (OS.IsWindowEnabled (handle)) { 588 if (OS.IsWindowEnabled (handle)) {
586 bool drawForeground = false; 589 bool drawForeground = false;
587 if (selected) { 590 if (selected) {
588 if (i !is 0 && (style & DWT.FULL_SELECTION) is 0) { 591 if (i !is 0 && (style & DWT.FULL_SELECTION) is 0) {
621 } 624 }
622 } 625 }
623 if (drawItem) { 626 if (drawItem) {
624 if (i !is 0) { 627 if (i !is 0) {
625 if (hooks (DWT.MeasureItem)) { 628 if (hooks (DWT.MeasureItem)) {
626 RECT itemRect = item.getBounds (index, true, true, false, false, false, hDC); 629 sendMeasureItemEvent (item, index, hDC);
627 int nSavedDC = OS.SaveDC (hDC);
628 GCData data = new GCData ();
629 data.device = display;
630 data.hFont = hFont;
631 GC gc = GC.win32_new (hDC, data);
632 Event event = new Event ();
633 event.item = item;
634 event.index = index;
635 event.gc = gc;
636 event.x = itemRect.left;
637 event.y = itemRect.top;
638 event.width = itemRect.right - itemRect.left;
639 event.height = itemRect.bottom - itemRect.top;
640 sendEvent (DWT.MeasureItem, event);
641 event.gc = null;
642 gc.dispose ();
643 OS.RestoreDC (hDC, nSavedDC);
644 if (isDisposed () || item.isDisposed ()) break; 630 if (isDisposed () || item.isDisposed ()) break;
645 if (event.height > getItemHeight ()) setItemHeight (event.height);
646 } 631 }
647 if (hooks (DWT.EraseItem)) { 632 if (hooks (DWT.EraseItem)) {
648 RECT cellRect = item.getBounds (index, true, true, true, true, true, hDC); 633 RECT cellRect = item.getBounds (index, true, true, true, true, true, hDC);
649 int nSavedDC = OS.SaveDC (hDC); 634 int nSavedDC = OS.SaveDC (hDC);
650 GCData data = new GCData (); 635 GCData data = new GCData ();
653 data.background = OS.GetBkColor (hDC); 638 data.background = OS.GetBkColor (hDC);
654 if (!selected || (style & DWT.FULL_SELECTION) is 0) { 639 if (!selected || (style & DWT.FULL_SELECTION) is 0) {
655 if (clrText !is -1) data.foreground = clrText; 640 if (clrText !is -1) data.foreground = clrText;
656 if (clrTextBk !is -1) data.background = clrTextBk; 641 if (clrTextBk !is -1) data.background = clrTextBk;
657 } 642 }
658 data.hFont = hFont; 643 data.font = item.getFont (index);
659 data.uiState = OS.SendMessage (handle, OS.WM_QUERYUISTATE, 0, 0); 644 data.uiState = OS.SendMessage (handle, OS.WM_QUERYUISTATE, 0, 0);
660 GC gc = GC.win32_new (hDC, data); 645 GC gc = GC.win32_new (hDC, data);
661 Event event = new Event (); 646 Event event = new Event ();
662 event.item = item; 647 event.item = item;
663 event.index = index; 648 event.index = index;
707 selectionForeground = OS.GetSysColor (OS.COLOR_HIGHLIGHTTEXT); 692 selectionForeground = OS.GetSysColor (OS.COLOR_HIGHLIGHTTEXT);
708 } else { 693 } else {
709 if (!explorerTheme) { 694 if (!explorerTheme) {
710 drawBackground = true; 695 drawBackground = true;
711 ignoreDrawBackground = false; 696 ignoreDrawBackground = false;
712 if (handle is OS.GetFocus () && OS.IsWindowEnabled (handle)) { 697 if ((handle is OS.GetFocus () || display.getHighContrast ()) && OS.IsWindowEnabled (handle)) {
713 clrTextBk = OS.GetSysColor (OS.COLOR_HIGHLIGHT); 698 clrTextBk = OS.GetSysColor (OS.COLOR_HIGHLIGHT);
714 } else { 699 } else {
715 clrTextBk = OS.GetSysColor (OS.COLOR_3DFACE); 700 clrTextBk = OS.GetSysColor (OS.COLOR_3DFACE);
716 } 701 }
717 if (!ignoreFullSelection && index is count - 1) { 702 if (!ignoreFullSelection && index is columnCount - 1) {
718 RECT* selectionRect = new RECT (); 703 RECT* selectionRect = new RECT ();
719 OS.SetRect (selectionRect, backgroundRect.left, backgroundRect.top, nmcd.nmcd.rc.right, backgroundRect.bottom); 704 OS.SetRect (selectionRect, backgroundRect.left, backgroundRect.top, nmcd.nmcd.rc.right, backgroundRect.bottom);
720 backgroundRect = selectionRect; 705 backgroundRect = selectionRect;
721 } 706 }
722 } else { 707 } else {
723 RECT pRect; 708 RECT pRect;
724 OS.SetRect (&pRect, nmcd.nmcd.rc.left, nmcd.nmcd.rc.top, nmcd.nmcd.rc.right, nmcd.nmcd.rc.bottom); 709 OS.SetRect (&pRect, nmcd.nmcd.rc.left, nmcd.nmcd.rc.top, nmcd.nmcd.rc.right, nmcd.nmcd.rc.bottom);
725 if (count > 0 && hwndHeader !is null) { 710 if (columnCount > 0 && hwndHeader !is null) {
726 int totalWidth = 0; 711 int totalWidth = 0;
727 HDITEM hdItem; 712 HDITEM hdItem;
728 hdItem.mask = OS.HDI_WIDTH; 713 hdItem.mask = OS.HDI_WIDTH;
729 for (int j=0; j<count; j++) { 714 for (int j=0; j<columnCount; j++) {
730 OS.SendMessage (hwndHeader, OS.HDM_GETITEM, j, &hdItem); 715 OS.SendMessage (hwndHeader, OS.HDM_GETITEM, j, &hdItem);
731 totalWidth += hdItem.cxy; 716 totalWidth += hdItem.cxy;
732 } 717 }
733 if (totalWidth > clientRect.right - clientRect.left) { 718 if (totalWidth > clientRect.right - clientRect.left) {
734 pRect.left = 0; 719 pRect.left = 0;
735 pRect.right = totalWidth; 720 pRect.right = totalWidth;
736 } else { 721 } else {
737 pRect.left = clientRect.left; 722 pRect.left = clientRect.left;
738 pRect.right = clientRect.right; 723 pRect.right = clientRect.right;
739 } 724 }
740 if (index is count - 1) { 725 if (index is columnCount - 1) {
741 RECT* selectionRect = new RECT (); 726 RECT* selectionRect = new RECT ();
742 OS.SetRect (selectionRect, backgroundRect.left, backgroundRect.top, pRect.right, backgroundRect.bottom); 727 OS.SetRect (selectionRect, backgroundRect.left, backgroundRect.top, pRect.right, backgroundRect.bottom);
743 backgroundRect = selectionRect; 728 backgroundRect = selectionRect;
744 } 729 }
745 } 730 }
794 int inset = i !is 0 ? INSET : 0; 779 int inset = i !is 0 ? INSET : 0;
795 int offset = i !is 0 ? INSET : INSET + 2; 780 int offset = i !is 0 ? INSET : INSET + 2;
796 if (image !is null) { 781 if (image !is null) {
797 Rectangle bounds = image.getBounds (); 782 Rectangle bounds = image.getBounds ();
798 if (size is null) size = getImageSize (); 783 if (size is null) size = getImageSize ();
799 //int y = rect.top + (index is 0 ? (getItemHeight () - size.y) / 2 : 0);
800 int y = rect.top;
801 if (!ignoreDrawForeground) { 784 if (!ignoreDrawForeground) {
802 //TODO - share GC, clip the drawing for index is 0 785 //int y1 = rect.top + (index is 0 ? (getItemHeight () - size.y) / 2 : 0);
786 int y1 = rect.top;
787 int x1 = Math.max (rect.left, rect.left - inset + 1);
803 GCData data = new GCData(); 788 GCData data = new GCData();
804 data.device = display; 789 data.device = display;
805 GC gc = GC.win32_new (hDC, data); 790 GC gc = GC.win32_new (hDC, data);
806 //if (index is 0) { //must clear 791 gc.setClipping (x1, rect.top, rect.right - x1, rect.bottom - rect.top);
807 //gc.setClipping (rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top); 792 gc.drawImage (image, 0, 0, bounds.width, bounds.height, x1, y1, size.x, size.y);
808 //} 793 OS.SelectClipRgn (hDC, null);
809 gc.drawImage (image, 0, 0, bounds.width, bounds.height, rect.left - inset + 1, y, size.x, size.y);
810 gc.dispose (); 794 gc.dispose ();
811 } 795 }
812 OS.SetRect (&rect, rect.left + size.x + offset, rect.top, rect.right - inset, rect.bottom); 796 OS.SetRect (&rect, rect.left + size.x + offset, rect.top, rect.right - inset, rect.bottom);
813 } else { 797 } else {
814 if (i is 0) { 798 if (i is 0) {
835 } else { 819 } else {
836 String [] strings = item.strings; 820 String [] strings = item.strings;
837 if (strings !is null) string = strings [index]; 821 if (strings !is null) string = strings [index];
838 } 822 }
839 if (string !is null) { 823 if (string !is null) {
840 if (hFont !is cast(HFONT)-1) hFont = OS.SelectObject (hDC, hFont); 824 if (hFont !is cast(HFONT)-1) hFont = cast(HFONT)OS.SelectObject (hDC, hFont);
841 if (clrText !is -1) clrText = OS.SetTextColor (hDC, clrText); 825 if (clrText !is -1) clrText = OS.SetTextColor (hDC, clrText);
842 if (clrTextBk !is -1) clrTextBk = OS.SetBkColor (hDC, clrTextBk); 826 if (clrTextBk !is -1) clrTextBk = OS.SetBkColor (hDC, clrTextBk);
843 int flags = OS.DT_NOPREFIX | OS.DT_SINGLELINE | OS.DT_VCENTER; 827 int flags = OS.DT_NOPREFIX | OS.DT_SINGLELINE | OS.DT_VCENTER;
844 if (i !is 0) flags |= OS.DT_ENDELLIPSIS; 828 if (i !is 0) flags |= OS.DT_ENDELLIPSIS;
845 TreeColumn column = columns !is null ? columns [index] : null; 829 TreeColumn column = columns !is null ? columns [index] : null;
848 if ((column.style & DWT.RIGHT) !is 0) flags |= OS.DT_RIGHT; 832 if ((column.style & DWT.RIGHT) !is 0) flags |= OS.DT_RIGHT;
849 } 833 }
850 TCHAR[] buffer = StrToTCHARs (getCodePage (), string, false); 834 TCHAR[] buffer = StrToTCHARs (getCodePage (), string, false);
851 if (!ignoreDrawForeground) OS.DrawText (hDC, buffer.ptr, buffer.length, &rect, flags); 835 if (!ignoreDrawForeground) OS.DrawText (hDC, buffer.ptr, buffer.length, &rect, flags);
852 OS.DrawText (hDC, buffer.ptr, buffer.length, &rect, flags | OS.DT_CALCRECT); 836 OS.DrawText (hDC, buffer.ptr, buffer.length, &rect, flags | OS.DT_CALCRECT);
853 if (hFont !is cast(HFONT)-1) hFont = OS.SelectObject (hDC, hFont); 837 if (hFont !is cast(HFONT)-1) hFont = cast(HFONT)OS.SelectObject (hDC, hFont);
854 if (clrText !is -1) clrText = OS.SetTextColor (hDC, clrText); 838 if (clrText !is -1) clrText = OS.SetTextColor (hDC, clrText);
855 if (clrTextBk !is -1) clrTextBk = OS.SetBkColor (hDC, clrTextBk); 839 if (clrTextBk !is -1) clrTextBk = OS.SetBkColor (hDC, clrTextBk);
856 } 840 }
857 } 841 }
858 } 842 }
861 if (hooks (DWT.PaintItem)) { 845 if (hooks (DWT.PaintItem)) {
862 RECT itemRect = item.getBounds (index, true, true, false, false, false, hDC); 846 RECT itemRect = item.getBounds (index, true, true, false, false, false, hDC);
863 int nSavedDC = OS.SaveDC (hDC); 847 int nSavedDC = OS.SaveDC (hDC);
864 GCData data = new GCData (); 848 GCData data = new GCData ();
865 data.device = display; 849 data.device = display;
866 data.hFont = hFont; 850 data.font = item.getFont (index);
867 data.foreground = OS.GetTextColor (hDC); 851 data.foreground = OS.GetTextColor (hDC);
868 data.background = OS.GetBkColor (hDC); 852 data.background = OS.GetBkColor (hDC);
869 if (selected && (style & DWT.FULL_SELECTION) !is 0) { 853 if (selected && (style & DWT.FULL_SELECTION) !is 0) {
870 if (selectionForeground !is -1) data.foreground = selectionForeground; 854 if (selectionForeground !is -1) data.foreground = selectionForeground;
871 } else { 855 } else {
902 RECT cellRect = item.getBounds (index, true, true, true, true, true, hDC); 886 RECT cellRect = item.getBounds (index, true, true, true, true, true, hDC);
903 int cellWidth = cellRect.right - cellRect.left; 887 int cellWidth = cellRect.right - cellRect.left;
904 int cellHeight = cellRect.bottom - cellRect.top; 888 int cellHeight = cellRect.bottom - cellRect.top;
905 gc.setClipping (cellRect.left, cellRect.top, cellWidth, cellHeight); 889 gc.setClipping (cellRect.left, cellRect.top, cellWidth, cellHeight);
906 sendEvent (DWT.PaintItem, event); 890 sendEvent (DWT.PaintItem, event);
891 if (data.focusDrawn) focusRect = null;
907 event.gc = null; 892 event.gc = null;
908 gc.dispose (); 893 gc.dispose ();
909 OS.RestoreDC (hDC, nSavedDC); 894 OS.RestoreDC (hDC, nSavedDC);
910 if (isDisposed () || item.isDisposed ()) break; 895 if (isDisposed () || item.isDisposed ()) break;
911 } 896 }
913 x += width; 898 x += width;
914 if (x > clientRect.right) break; 899 if (x > clientRect.right) break;
915 } 900 }
916 if (linesVisible) { 901 if (linesVisible) {
917 if ((style & DWT.FULL_SELECTION) !is 0) { 902 if ((style & DWT.FULL_SELECTION) !is 0) {
918 if (hwndHeader !is null) { 903 if (columnCount !is 0) {
919 if (OS.SendMessage (hwndHeader, OS.HDM_GETITEMCOUNT, 0, 0) !is 0) { 904 HDITEM hdItem;
920 HDITEM hdItem; 905 hdItem.mask = OS.HDI_WIDTH;
921 hdItem.mask = OS.HDI_WIDTH; 906 OS.SendMessage (hwndHeader, OS.HDM_GETITEM, 0, &hdItem);
922 OS.SendMessage (hwndHeader, OS.HDM_GETITEM, 0, &hdItem); 907 RECT rect;
923 RECT rect; 908 OS.SetRect (&rect, nmcd.nmcd.rc.left + hdItem.cxy, nmcd.nmcd.rc.top, nmcd.nmcd.rc.right, nmcd.nmcd.rc.bottom);
924 OS.SetRect (&rect, nmcd.nmcd.rc.left + hdItem.cxy, nmcd.nmcd.rc.top, nmcd.nmcd.rc.right, nmcd.nmcd.rc.bottom); 909 OS.DrawEdge (hDC, &rect, OS.BDR_SUNKENINNER, OS.BF_BOTTOM);
925 OS.DrawEdge (hDC, &rect, OS.BDR_SUNKENINNER, OS.BF_BOTTOM);
926 }
927 } 910 }
928 } 911 }
929 RECT rect; 912 RECT rect;
930 OS.SetRect (&rect, nmcd.nmcd.rc.left, nmcd.nmcd.rc.top, nmcd.nmcd.rc.right, nmcd.nmcd.rc.bottom); 913 OS.SetRect (&rect, nmcd.nmcd.rc.left, nmcd.nmcd.rc.top, nmcd.nmcd.rc.right, nmcd.nmcd.rc.bottom);
931 OS.DrawEdge (hDC, &rect, OS.BDR_SUNKENINNER, OS.BF_BOTTOM); 914 OS.DrawEdge (hDC, &rect, OS.BDR_SUNKENINNER, OS.BF_BOTTOM);
932 } 915 }
933 if (!explorerTheme) { 916 if (!ignoreDrawFocus && focusRect !is null) {
934 if (handle is OS.GetFocus ()) { 917 OS.DrawFocusRect (hDC, focusRect);
935 int uiState = OS.SendMessage (handle, OS.WM_QUERYUISTATE, 0, 0); 918 focusRect = null;
936 if ((uiState & OS.UISF_HIDEFOCUS) is 0) { 919 } else {
937 auto hItem = cast(HANDLE) OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_CARET, 0); 920 if (!explorerTheme) {
938 if (hItem is item.handle) { 921 if (handle is OS.GetFocus ()) {
939 if (!ignoreDrawFocus && findImageControl () !is null) { 922 int uiState = OS.SendMessage (handle, OS.WM_QUERYUISTATE, 0, 0);
940 if ((style & DWT.FULL_SELECTION) !is 0) { 923 if ((uiState & OS.UISF_HIDEFOCUS) is 0) {
941 RECT focusRect; 924 auto hItem = cast(HANDLE) OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_CARET, 0);
942 OS.SetRect (&focusRect, nmcd.nmcd.rc.left, nmcd.nmcd.rc.top, nmcd.nmcd.rc.right, nmcd.nmcd.rc.bottom); 925 if (hItem is item.handle) {
943 if (count > 0 && hwndHeader !is null) { 926 if (!ignoreDrawFocus && findImageControl () !is null) {
944 int width = 0; 927 if ((style & DWT.FULL_SELECTION) !is 0) {
945 HDITEM hdItem; 928 RECT focusRect;
946 hdItem.mask = OS.HDI_WIDTH; 929 OS.SetRect (&focusRect, 0, nmcd.nmcd.rc.top, clientRect.right + 1, nmcd.nmcd.rc.bottom);
947 for (int j=0; j<count; j++) { 930 OS.DrawFocusRect (hDC, &focusRect);
948 OS.SendMessage (hwndHeader, OS.HDM_GETITEM, j, &hdItem); 931 } else {
949 width += hdItem.cxy; 932 int index = OS.SendMessage (hwndHeader, OS.HDM_ORDERTOINDEX, 0, 0);
950 } 933 RECT focusRect = item.getBounds (index, true, false, false, false, false, hDC);
951 focusRect.left = 0; 934 RECT clipRect = item.getBounds (index, true, false, false, false, true, hDC);
952 RECT rect; 935 OS.IntersectClipRect (hDC, clipRect.left, clipRect.top, clipRect.right, clipRect.bottom);
953 OS.GetClientRect (handle, &rect); 936 OS.DrawFocusRect (hDC, &focusRect);
954 focusRect.right = Math.max (width, rect.right - OS.GetSystemMetrics (OS.SM_CXVSCROLL)); 937 OS.SelectClipRgn (hDC, null);
955 } 938 }
956 OS.DrawFocusRect (hDC, &focusRect);
957 } else {
958 int index = OS.SendMessage (hwndHeader, OS.HDM_ORDERTOINDEX, 0, 0);
959 RECT focusRect = item.getBounds (index, true, false, false, false, false, hDC);
960 RECT clipRect = item.getBounds (index, true, false, false, false, true, hDC);
961 OS.IntersectClipRect (hDC, clipRect.left, clipRect.top, clipRect.right, clipRect.bottom);
962 OS.DrawFocusRect (hDC, &focusRect);
963 OS.SelectClipRgn (hDC, null);
964 } 939 }
965 } 940 }
966 } 941 }
967 } 942 }
968 } 943 }
988 * COMCTL32.DLL, 963 * COMCTL32.DLL,
989 */ 964 */
990 if (item is null) return null; 965 if (item is null) return null;
991 auto hDC = nmcd.nmcd.hdc; 966 auto hDC = nmcd.nmcd.hdc;
992 int index = hwndHeader !is null ? OS.SendMessage (hwndHeader, OS.HDM_ORDERTOINDEX, 0, 0) : 0; 967 int index = hwndHeader !is null ? OS.SendMessage (hwndHeader, OS.HDM_ORDERTOINDEX, 0, 0) : 0;
993 HFONT hFont = item.cellFont !is null ? item.cellFont [index] : cast(HFONT)-1; 968 auto hFont = item.fontHandle (index);
994 if (hFont is cast(HFONT)-1) hFont = item.font;
995 if (hFont !is cast(HFONT)-1) OS.SelectObject (hDC, hFont); 969 if (hFont !is cast(HFONT)-1) OS.SelectObject (hDC, hFont);
996 if (ignoreCustomDraw || nmcd.nmcd.rc.left is nmcd.nmcd.rc.right) { 970 if (ignoreCustomDraw || nmcd.nmcd.rc.left is nmcd.nmcd.rc.right) {
997 return new LRESULT (hFont is cast(HFONT)-1 ? OS.CDRF_DODEFAULT : OS.CDRF_NEWFONT); 971 return new LRESULT (hFont is cast(HFONT)-1 ? OS.CDRF_DODEFAULT : OS.CDRF_NEWFONT);
998 } 972 }
999 int count = 0;
1000 RECT* clipRect = null; 973 RECT* clipRect = null;
1001 if (hwndHeader !is null) { 974 if (columnCount !is 0) {
1002 count = OS.SendMessage (hwndHeader, OS.HDM_GETITEMCOUNT, 0, 0); 975 bool clip = !printClient;
1003 if (count !is 0) { 976 if (!OS.IsWinCE && OS.WIN32_VERSION >= OS.VERSION (6, 0)) {
1004 bool clip = !printClient; 977 clip = true;
1005 if (!OS.IsWinCE && OS.WIN32_VERSION >= OS.VERSION (6, 0)) { 978 }
1006 clip = true; 979 if (clip) {
1007 } 980 clipRect = new RECT ();
1008 if (clip) { 981 HDITEM hdItem;
1009 clipRect = new RECT (); 982 hdItem.mask = OS.HDI_WIDTH;
1010 HDITEM hdItem; 983 OS.SendMessage (hwndHeader, OS.HDM_GETITEM, index, &hdItem);
1011 hdItem.mask = OS.HDI_WIDTH; 984 OS.SetRect (clipRect, nmcd.nmcd.rc.left, nmcd.nmcd.rc.top, nmcd.nmcd.rc.left + hdItem.cxy, nmcd.nmcd.rc.bottom);
1012 OS.SendMessage (hwndHeader, OS.HDM_GETITEM, index, &hdItem);
1013 OS.SetRect (clipRect, nmcd.nmcd.rc.left, nmcd.nmcd.rc.top, nmcd.nmcd.rc.left + hdItem.cxy, nmcd.nmcd.rc.bottom);
1014 }
1015 } 985 }
1016 } 986 }
1017 int clrText = -1, clrTextBk = -1; 987 int clrText = -1, clrTextBk = -1;
1018 if (OS.IsWindowEnabled (handle)) { 988 if (OS.IsWindowEnabled (handle)) {
1019 clrText = item.cellForeground !is null ? item.cellForeground [index] : -1; 989 clrText = item.cellForeground !is null ? item.cellForeground [index] : -1;
1032 } 1002 }
1033 } 1003 }
1034 } 1004 }
1035 bool selected = isItemSelected (nmcd); 1005 bool selected = isItemSelected (nmcd);
1036 bool hot = explorerTheme && (nmcd.nmcd.uItemState & OS.CDIS_HOT) !is 0; 1006 bool hot = explorerTheme && (nmcd.nmcd.uItemState & OS.CDIS_HOT) !is 0;
1007 bool focused = explorerTheme && (nmcd.nmcd.uItemState & OS.CDIS_FOCUS) !is 0;
1037 if (OS.IsWindowVisible (handle) && nmcd.nmcd.rc.left < nmcd.nmcd.rc.right && nmcd.nmcd.rc.top < nmcd.nmcd.rc.bottom) { 1008 if (OS.IsWindowVisible (handle) && nmcd.nmcd.rc.left < nmcd.nmcd.rc.right && nmcd.nmcd.rc.top < nmcd.nmcd.rc.bottom) {
1038 if (hFont !is cast(HFONT)-1) OS.SelectObject (hDC, hFont); 1009 if (hFont !is cast(HFONT)-1) OS.SelectObject (hDC, hFont);
1039 if (linesVisible) { 1010 if (linesVisible) {
1040 RECT rect; 1011 RECT rect;
1041 OS.SetRect (&rect, nmcd.nmcd.rc.left, nmcd.nmcd.rc.top, nmcd.nmcd.rc.right, nmcd.nmcd.rc.bottom); 1012 OS.SetRect (&rect, nmcd.nmcd.rc.left, nmcd.nmcd.rc.top, nmcd.nmcd.rc.right, nmcd.nmcd.rc.bottom);
1042 OS.DrawEdge (hDC, &rect, OS.BDR_SUNKENINNER, OS.BF_BOTTOM); 1013 OS.DrawEdge (hDC, &rect, OS.BDR_SUNKENINNER, OS.BF_BOTTOM);
1043 } 1014 }
1044 //TODO - BUG - measure and erase sent when first column is clipped 1015 //TODO - BUG - measure and erase sent when first column is clipped
1016 Event measureEvent = null;
1045 if (hooks (DWT.MeasureItem)) { 1017 if (hooks (DWT.MeasureItem)) {
1046 RECT itemRect = item.getBounds (index, true, true, false, false, false, hDC); 1018 measureEvent = sendMeasureItemEvent (item, index, hDC);
1047 int nSavedDC = OS.SaveDC (hDC);
1048 GCData data = new GCData ();
1049 data.device = display;
1050 data.hFont = hFont;
1051 GC gc = GC.win32_new (hDC, data);
1052 Event event = new Event ();
1053 event.item = item;
1054 event.gc = gc;
1055 event.index = index;
1056 event.x = itemRect.left;
1057 event.y = itemRect.top;
1058 event.width = itemRect.right - itemRect.left;
1059 event.height = itemRect.bottom - itemRect.top;
1060 sendEvent (DWT.MeasureItem, event);
1061 event.gc = null;
1062 gc.dispose ();
1063 OS.RestoreDC (hDC, nSavedDC);
1064 if (isDisposed () || item.isDisposed ()) return null; 1019 if (isDisposed () || item.isDisposed ()) return null;
1065 if (hwndHeader !is null) {
1066 if (count is 0) {
1067 if (event.x + event.width > scrollWidth) {
1068 setScrollWidth (scrollWidth = event.x + event.width);
1069 }
1070 }
1071 }
1072 if (event.height > getItemHeight ()) setItemHeight (event.height);
1073 } 1020 }
1074 selectionForeground = -1; 1021 selectionForeground = -1;
1075 ignoreDrawForeground = ignoreDrawBackground = ignoreDrawSelection = ignoreDrawFocus = ignoreDrawHot = ignoreFullSelection = false; 1022 ignoreDrawForeground = ignoreDrawBackground = ignoreDrawSelection = ignoreDrawFocus = ignoreDrawHot = ignoreFullSelection = false;
1076 if (hooks (DWT.EraseItem)) { 1023 if (hooks (DWT.EraseItem)) {
1077 RECT rect; 1024 RECT rect;
1078 OS.SetRect (&rect, nmcd.nmcd.rc.left, nmcd.nmcd.rc.top, nmcd.nmcd.rc.right, nmcd.nmcd.rc.bottom); 1025 OS.SetRect (&rect, nmcd.nmcd.rc.left, nmcd.nmcd.rc.top, nmcd.nmcd.rc.right, nmcd.nmcd.rc.bottom);
1079 if (OS.IsWindowEnabled (handle) || findImageControl () !is null) {
1080 drawBackground (hDC, &rect);
1081 } else {
1082 fillBackground (hDC, OS.GetBkColor (hDC), &rect);
1083 }
1084 RECT cellRect = item.getBounds (index, true, true, true, true, true, hDC); 1026 RECT cellRect = item.getBounds (index, true, true, true, true, true, hDC);
1085 if (clrSortBk !is -1) { 1027 if (clrSortBk !is -1) {
1086 RECT fullRect = item.getBounds (index, true, true, true, true, true, hDC); 1028 drawBackground (hDC, &cellRect, clrSortBk);
1087 drawBackground (hDC, &fullRect, clrSortBk); 1029 } else {
1030 if (OS.IsWindowEnabled (handle) || findImageControl () !is null) {
1031 drawBackground (hDC, &rect);
1032 } else {
1033 fillBackground (hDC, OS.GetBkColor (hDC), &rect);
1034 }
1088 } 1035 }
1089 int nSavedDC = OS.SaveDC (hDC); 1036 int nSavedDC = OS.SaveDC (hDC);
1090 GCData data = new GCData (); 1037 GCData data = new GCData ();
1091 data.device = display; 1038 data.device = display;
1092 if (selected && explorerTheme) { 1039 if (selected && explorerTheme) {
1098 if (!selected) { 1045 if (!selected) {
1099 if (clrText !is -1) data.foreground = clrText; 1046 if (clrText !is -1) data.foreground = clrText;
1100 if (clrTextBk !is -1) data.background = clrTextBk; 1047 if (clrTextBk !is -1) data.background = clrTextBk;
1101 } 1048 }
1102 data.uiState = OS.SendMessage (handle, OS.WM_QUERYUISTATE, 0, 0); 1049 data.uiState = OS.SendMessage (handle, OS.WM_QUERYUISTATE, 0, 0);
1103 if (hFont !is cast(HFONT)-1) data.hFont = hFont; 1050 data.font = item.getFont (index);
1104 GC gc = GC.win32_new (hDC, data); 1051 GC gc = GC.win32_new (hDC, data);
1105 Event event = new Event (); 1052 Event event = new Event ();
1106 event.index = index; 1053 event.index = index;
1107 event.item = item; 1054 event.item = item;
1108 event.gc = gc; 1055 event.gc = gc;
1113 if (!explorerTheme) { 1060 if (!explorerTheme) {
1114 //if ((nmcd.uItemState & OS.CDIS_FOCUS) !is 0) { 1061 //if ((nmcd.uItemState & OS.CDIS_FOCUS) !is 0) {
1115 if (OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_CARET, 0) is nmcd.nmcd.dwItemSpec) { 1062 if (OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_CARET, 0) is nmcd.nmcd.dwItemSpec) {
1116 if (handle is OS.GetFocus ()) { 1063 if (handle is OS.GetFocus ()) {
1117 int uiState = OS.SendMessage (handle, OS.WM_QUERYUISTATE, 0, 0); 1064 int uiState = OS.SendMessage (handle, OS.WM_QUERYUISTATE, 0, 0);
1118 if ((uiState & OS.UISF_HIDEFOCUS) is 0) event.detail |= DWT.FOCUSED; 1065 if ((uiState & OS.UISF_HIDEFOCUS) is 0) {
1066 focused = true;
1067 event.detail |= DWT.FOCUSED;
1068 }
1119 } 1069 }
1120 } 1070 }
1121 } 1071 }
1122 event.x = cellRect.left; 1072 event.x = cellRect.left;
1123 event.y = cellRect.top; 1073 event.y = cellRect.top;
1142 if (selected && ignoreDrawSelection) ignoreDrawHot = true; 1092 if (selected && ignoreDrawSelection) ignoreDrawHot = true;
1143 if (!ignoreDrawBackground && clrTextBk !is -1) { 1093 if (!ignoreDrawBackground && clrTextBk !is -1) {
1144 bool draw = !selected && !hot; 1094 bool draw = !selected && !hot;
1145 if (!explorerTheme && selected) draw = !ignoreDrawSelection; 1095 if (!explorerTheme && selected) draw = !ignoreDrawSelection;
1146 if (draw) { 1096 if (draw) {
1147 if (count is 0) { 1097 if (columnCount is 0) {
1148 if ((style & DWT.FULL_SELECTION) !is 0) { 1098 if ((style & DWT.FULL_SELECTION) !is 0) {
1149 fillBackground (hDC, clrTextBk, &rect); 1099 fillBackground (hDC, clrTextBk, &rect);
1150 } else { 1100 } else {
1151 RECT textRect = item.getBounds (index, true, false, true, false, true, hDC); 1101 RECT textRect = item.getBounds (index, true, false, false, false, true, hDC);
1102 if (measureEvent !is null) {
1103 textRect.right = Math.min (cellRect.right, measureEvent.x + measureEvent.width);
1104 }
1152 fillBackground (hDC, clrTextBk, &textRect); 1105 fillBackground (hDC, clrTextBk, &textRect);
1153 } 1106 }
1154 } else { 1107 } else {
1155 fillBackground (hDC, clrTextBk, &cellRect); 1108 fillBackground (hDC, clrTextBk, &cellRect);
1156 } 1109 }
1159 if (ignoreDrawSelection) ignoreFullSelection = true; 1112 if (ignoreDrawSelection) ignoreFullSelection = true;
1160 if (!ignoreDrawSelection || !ignoreDrawHot) { 1113 if (!ignoreDrawSelection || !ignoreDrawHot) {
1161 if (!selected && !hot) { 1114 if (!selected && !hot) {
1162 selectionForeground = clrText = OS.GetSysColor (OS.COLOR_HIGHLIGHTTEXT); 1115 selectionForeground = clrText = OS.GetSysColor (OS.COLOR_HIGHLIGHTTEXT);
1163 } 1116 }
1164 if (!explorerTheme) { 1117 if (explorerTheme) {
1118 if ((style & DWT.FULL_SELECTION) is 0) {
1119 RECT pRect = item.getBounds (index, true, true, false, false, false, hDC);
1120 RECT pClipRect = item.getBounds (index, true, true, true, false, true, hDC);
1121 if (measureEvent !is null) {
1122 pRect.right = Math.min (pClipRect.right, measureEvent.x + measureEvent.width);
1123 } else {
1124 pRect.right += EXPLORER_EXTRA;
1125 pClipRect.right += EXPLORER_EXTRA;
1126 }
1127 pRect.left -= EXPLORER_EXTRA;
1128 pClipRect.left -= EXPLORER_EXTRA;
1129 auto hTheme = OS.OpenThemeData (handle, Display.TREEVIEW.ptr);
1130 int iStateId = selected ? OS.TREIS_SELECTED : OS.TREIS_HOT;
1131 if (OS.GetFocus () !is handle && selected && !hot) iStateId = OS.TREIS_SELECTEDNOTFOCUS;
1132 OS.DrawThemeBackground (hTheme, hDC, OS.TVP_TREEITEM, iStateId, &pRect, &pClipRect);
1133 OS.CloseThemeData (hTheme);
1134 }
1135 } else {
1165 /* 1136 /*
1166 * Feature in Windows. When the tree has the style 1137 * Feature in Windows. When the tree has the style
1167 * TVS_FULLROWSELECT, the background color for the 1138 * TVS_FULLROWSELECT, the background color for the
1168 * entire row is filled when an item is painted, 1139 * entire row is filled when an item is painted,
1169 * drawing on top of any custom drawing. The fix 1140 * drawing on top of any custom drawing. The fix
1170 * is to emulate TVS_FULLROWSELECT. 1141 * is to emulate TVS_FULLROWSELECT.
1171 */ 1142 */
1172 if ((style & DWT.FULL_SELECTION) !is 0) { 1143 if ((style & DWT.FULL_SELECTION) !is 0) {
1173 if ((style & DWT.FULL_SELECTION) !is 0 && count is 0) { 1144 if ((style & DWT.FULL_SELECTION) !is 0 && columnCount is 0) {
1174 fillBackground (hDC, OS.GetBkColor (hDC), &rect); 1145 fillBackground (hDC, OS.GetBkColor (hDC), &rect);
1175 } else { 1146 } else {
1176 fillBackground (hDC, OS.GetBkColor (hDC), &cellRect); 1147 fillBackground (hDC, OS.GetBkColor (hDC), &cellRect);
1177 } 1148 }
1178 } else { 1149 } else {
1179 RECT textRect = item.getBounds (index, true, false, false, false, true, hDC); 1150 RECT textRect = item.getBounds (index, true, false, false, false, true, hDC);
1151 if (measureEvent !is null) {
1152 textRect.right = Math.min (cellRect.right, measureEvent.x + measureEvent.width);
1153 }
1180 fillBackground (hDC, OS.GetBkColor (hDC), &textRect); 1154 fillBackground (hDC, OS.GetBkColor (hDC), &textRect);
1181 } 1155 }
1182 } 1156 }
1183 } else { 1157 } else {
1184 if (selected || hot) { 1158 if (selected || hot) {
1201 nmcd.clrText = newColor; 1175 nmcd.clrText = newColor;
1202 } 1176 }
1203 OS.MoveMemory (lParam, nmcd, NMTVCUSTOMDRAW.sizeof); 1177 OS.MoveMemory (lParam, nmcd, NMTVCUSTOMDRAW.sizeof);
1204 } 1178 }
1205 } 1179 }
1180 if (focused && !ignoreDrawFocus && (style & DWT.FULL_SELECTION) is 0) {
1181 RECT textRect = item.getBounds (index, true, explorerTheme, false, false, true, hDC);
1182 if (measureEvent !is null) {
1183 textRect.right = Math.min (cellRect.right, measureEvent.x + measureEvent.width);
1184 }
1185 nmcd.nmcd.uItemState &= ~OS.CDIS_FOCUS;
1186 OS.MoveMemory (lParam, nmcd, NMTVCUSTOMDRAW.sizeof);
1187 if( focusRect is null ) focusRect = new RECT;
1188 *focusRect = textRect;
1189 }
1206 if (explorerTheme) { 1190 if (explorerTheme) {
1207 if (selected || (hot && ignoreDrawHot)) nmcd.nmcd.uItemState &= ~OS.CDIS_HOT; 1191 if (selected || (hot && ignoreDrawHot)) nmcd.nmcd.uItemState &= ~OS.CDIS_HOT;
1208 OS.MoveMemory (cast(void*)lParam, nmcd, NMTVCUSTOMDRAW.sizeof); 1192 OS.MoveMemory (cast(void*)lParam, nmcd, NMTVCUSTOMDRAW.sizeof);
1209 } 1193 }
1210 RECT itemRect = item.getBounds (index, true, true, false, false, false, hDC); 1194 RECT itemRect = item.getBounds (index, true, true, false, false, false, hDC);
1258 * The fix is to fill the cell with the background color. 1242 * The fix is to fill the cell with the background color.
1259 */ 1243 */
1260 if (clrTextBk !is -1) { 1244 if (clrTextBk !is -1) {
1261 int bits = OS.GetWindowLong (handle, OS.GWL_STYLE); 1245 int bits = OS.GetWindowLong (handle, OS.GWL_STYLE);
1262 if ((bits & OS.TVS_FULLROWSELECT) is 0) { 1246 if ((bits & OS.TVS_FULLROWSELECT) is 0) {
1263 if (count !is 0 && hwndHeader !is null) { 1247 if (columnCount !is 0 && hwndHeader !is null) {
1264 RECT rect; 1248 RECT rect;
1265 HDITEM hdItem; 1249 HDITEM hdItem;
1266 hdItem.mask = OS.HDI_WIDTH; 1250 hdItem.mask = OS.HDI_WIDTH;
1267 OS.SendMessage (hwndHeader, OS.HDM_GETITEM, index, &hdItem); 1251 OS.SendMessage (hwndHeader, OS.HDM_GETITEM, index, &hdItem);
1268 OS.SetRect (&rect, nmcd.nmcd.rc.left, nmcd.nmcd.rc.top, nmcd.nmcd.rc.left + hdItem.cxy, nmcd.nmcd.rc.bottom); 1252 OS.SetRect (&rect, nmcd.nmcd.rc.left, nmcd.nmcd.rc.top, nmcd.nmcd.rc.left + hdItem.cxy, nmcd.nmcd.rc.bottom);
1269 if (OS.COMCTL32_MAJOR < 6 || !OS.IsAppThemed ()) { 1253 if (OS.COMCTL32_MAJOR < 6 || !OS.IsAppThemed ()) {
1270 RECT itemRect; 1254 RECT itemRect;
1271 itemRect.left = cast(int) item.handle; 1255 if (OS.TreeView_GetItemRect (handle, item.handle, &itemRect, true)) {
1272 if (OS.SendMessage (handle, OS.TVM_GETITEMRECT, 1, &itemRect) !is 0) {
1273 rect.left = Math.min (itemRect.left, rect.right); 1256 rect.left = Math.min (itemRect.left, rect.right);
1274 } 1257 }
1275 } 1258 }
1276 if ((style & DWT.FULL_SELECTION) !is 0) { 1259 if ((style & DWT.FULL_SELECTION) !is 0) {
1277 if (!selected) fillBackground (hDC, clrTextBk, &rect); 1260 if (!selected) fillBackground (hDC, clrTextBk, &rect);
1327 } 1310 }
1328 OS.MoveMemory (lParam, nmcd, NMTVCUSTOMDRAW.sizeof); 1311 OS.MoveMemory (lParam, nmcd, NMTVCUSTOMDRAW.sizeof);
1329 if (clrTextBk !is -1) { 1312 if (clrTextBk !is -1) {
1330 if ((style & DWT.FULL_SELECTION) !is 0) { 1313 if ((style & DWT.FULL_SELECTION) !is 0) {
1331 RECT rect; 1314 RECT rect;
1332 if (count !is 0) { 1315 if (columnCount !is 0) {
1333 HDITEM hdItem; 1316 HDITEM hdItem;
1334 hdItem.mask = OS.HDI_WIDTH; 1317 hdItem.mask = OS.HDI_WIDTH;
1335 OS.SendMessage (hwndHeader, OS.HDM_GETITEM, index, &hdItem); 1318 OS.SendMessage (hwndHeader, OS.HDM_GETITEM, index, &hdItem);
1336 OS.SetRect (&rect, nmcd.nmcd.rc.left, nmcd.nmcd.rc.top, nmcd.nmcd.rc.left + hdItem.cxy, nmcd.nmcd.rc.bottom); 1319 OS.SetRect (&rect, nmcd.nmcd.rc.left, nmcd.nmcd.rc.top, nmcd.nmcd.rc.left + hdItem.cxy, nmcd.nmcd.rc.bottom);
1337 } else { 1320 } else {
1404 } else { 1387 } else {
1405 hItem = cast(HANDLE) OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_LASTVISIBLE, 0); 1388 hItem = cast(HANDLE) OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_LASTVISIBLE, 0);
1406 } 1389 }
1407 if (hItem !is null) { 1390 if (hItem !is null) {
1408 RECT rect; 1391 RECT rect;
1409 rect.left = cast(int) hItem; 1392 if (OS.TreeView_GetItemRect (handle, hItem, &rect, false)) {
1410 if (OS.SendMessage (handle, OS.TVM_GETITEMRECT, 0, &rect) !is 0) {
1411 top = rect.bottom; 1393 top = rect.bottom;
1412 } 1394 }
1413 } 1395 }
1414 RECT rect; 1396 RECT rect;
1415 OS.SetRect (&rect, nmcd.nmcd.rc.left, top, nmcd.nmcd.rc.right, nmcd.nmcd.rc.bottom); 1397 OS.SetRect (&rect, nmcd.nmcd.rc.left, top, nmcd.nmcd.rc.right, nmcd.nmcd.rc.bottom);
1427 if (hwndHeader !is null) { 1409 if (hwndHeader !is null) {
1428 int x = 0; 1410 int x = 0;
1429 RECT rect; 1411 RECT rect;
1430 HDITEM hdItem; 1412 HDITEM hdItem;
1431 hdItem.mask = OS.HDI_WIDTH; 1413 hdItem.mask = OS.HDI_WIDTH;
1432 int count = OS.SendMessage (hwndHeader, OS.HDM_GETITEMCOUNT, 0, 0); 1414 for (int i=0; i<columnCount; i++) {
1433 for (int i=0; i<count; i++) {
1434 int index = OS.SendMessage (hwndHeader, OS.HDM_ORDERTOINDEX, i, 0); 1415 int index = OS.SendMessage (hwndHeader, OS.HDM_ORDERTOINDEX, i, 0);
1435 OS.SendMessage (hwndHeader, OS.HDM_GETITEM, index, &hdItem); 1416 OS.SendMessage (hwndHeader, OS.HDM_GETITEM, index, &hdItem);
1436 OS.SetRect (&rect, x, nmcd.nmcd.rc.top, x + hdItem.cxy, nmcd.nmcd.rc.bottom); 1417 OS.SetRect (&rect, x, nmcd.nmcd.rc.top, x + hdItem.cxy, nmcd.nmcd.rc.bottom);
1437 OS.DrawEdge (hDC, &rect, OS.BDR_SUNKENINNER, OS.BF_RIGHT); 1418 OS.DrawEdge (hDC, &rect, OS.BDR_SUNKENINNER, OS.BF_RIGHT);
1438 x += hdItem.cxy; 1419 x += hdItem.cxy;
1461 hItem = getBottomItem (); 1442 hItem = getBottomItem ();
1462 } else { 1443 } else {
1463 hItem = cast(HANDLE) OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_LASTVISIBLE, 0); 1444 hItem = cast(HANDLE) OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_LASTVISIBLE, 0);
1464 } 1445 }
1465 if (hItem !is null) { 1446 if (hItem !is null) {
1466 rect.left = cast(int) hItem; 1447 if (OS.TreeView_GetItemRect (handle, hItem, &rect, false)) {
1467 if (OS.SendMessage (handle, OS.TVM_GETITEMRECT, 0, &rect) !is 0) {
1468 height = rect.bottom - rect.top; 1448 height = rect.bottom - rect.top;
1469 } 1449 }
1470 } 1450 }
1471 if (height is 0) { 1451 if (height is 0) {
1472 height = OS.SendMessage (handle, OS.TVM_GETITEMHEIGHT, 0, 0); 1452 height = OS.SendMessage (handle, OS.TVM_GETITEMHEIGHT, 0, 0);
1589 } 1569 }
1590 break; 1570 break;
1591 } 1571 }
1592 default: 1572 default:
1593 } 1573 }
1594 int code = OS.CallWindowProc (TreeProc, hwnd, msg, wParam, lParam); 1574 int /*long*/ code = OS.CallWindowProc (TreeProc, hwnd, msg, wParam, lParam);
1595 switch (msg) { 1575 switch (msg) {
1596 /* Keyboard messages */ 1576 /* Keyboard messages */
1597 case OS.WM_KEYDOWN: 1577 case OS.WM_KEYDOWN:
1598 if (wParam is OS.VK_CONTROL || wParam is OS.VK_SHIFT) break; 1578 if (wParam is OS.VK_CONTROL || wParam is OS.VK_SHIFT) break;
1599 //FALL THROUGH 1579 //FALL THROUGH
1663 if ((style & DWT.VIRTUAL) !is 0) { 1643 if ((style & DWT.VIRTUAL) !is 0) {
1664 style |= DWT.DOUBLE_BUFFERED; 1644 style |= DWT.DOUBLE_BUFFERED;
1665 OS.SendMessage (handle, OS.TVM_SETSCROLLTIME, 0, 0); 1645 OS.SendMessage (handle, OS.TVM_SETSCROLLTIME, 0, 0);
1666 } 1646 }
1667 if (EXPLORER_THEME) { 1647 if (EXPLORER_THEME) {
1668 if (!OS.IsWinCE && OS.WIN32_VERSION >= OS.VERSION (6, 0)) { 1648 if (!OS.IsWinCE && OS.WIN32_VERSION >= OS.VERSION (6, 0) && OS.IsAppThemed ()) {
1669 int exStyle = OS.SendMessage (handle, OS.TVM_GETEXTENDEDSTYLE, 0, 0); 1649 int exStyle = OS.SendMessage (handle, OS.TVM_GETEXTENDEDSTYLE, 0, 0);
1670 if ((exStyle & OS.TVS_EX_DOUBLEBUFFER) !is 0) style |= DWT.DOUBLE_BUFFERED; 1650 if ((exStyle & OS.TVS_EX_DOUBLEBUFFER) !is 0) style |= DWT.DOUBLE_BUFFERED;
1671 } 1651 }
1672 } 1652 }
1673 } 1653 }
1674 1654
1675 bool checkData (TreeItem item, bool redraw) { 1655 bool checkData (TreeItem item, bool redraw) {
1676 if ((style & DWT.VIRTUAL) is 0) return true; 1656 if ((style & DWT.VIRTUAL) is 0) return true;
1677 TreeItem parentItem = item.getParentItem (); 1657 if (!item.cached) {
1678 return checkData (item, parentItem is null ? indexOf (item) : parentItem.indexOf (item), redraw); 1658 TreeItem parentItem = item.getParentItem ();
1659 return checkData (item, parentItem is null ? indexOf (item) : parentItem.indexOf (item), redraw);
1660 }
1661 return true;
1679 } 1662 }
1680 1663
1681 bool checkData (TreeItem item, int index, bool redraw) { 1664 bool checkData (TreeItem item, int index, bool redraw) {
1682 if ((style & DWT.VIRTUAL) is 0) return true; 1665 if ((style & DWT.VIRTUAL) is 0) return true;
1683 if (!item.cached) { 1666 if (!item.cached) {
1711 * 1694 *
1712 * NOTE: The code that actually works around the problem is in the 1695 * NOTE: The code that actually works around the problem is in the
1713 * callers of this method. 1696 * callers of this method.
1714 */ 1697 */
1715 if (drawCount is 0) return false; 1698 if (drawCount is 0) return false;
1716 int hRoot = OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_ROOT, 0); 1699 int /*long*/ hRoot = OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_ROOT, 0);
1717 int hParent = OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_PARENT, hItem); 1700 int /*long*/ hParent = OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_PARENT, hItem);
1718 while (hParent !is hRoot && hParent !is 0) { 1701 while (hParent !is hRoot && hParent !is 0) {
1719 hParent = OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_PARENT, hParent); 1702 hParent = OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_PARENT, hParent);
1720 } 1703 }
1721 return hParent is 0; 1704 return hParent is 0;
1722 } 1705 }
1768 TreeItem item = null; 1751 TreeItem item = null;
1769 if (OS.SendMessage (handle, OS.TVM_GETITEM, 0, tvItem) !is 0) { 1752 if (OS.SendMessage (handle, OS.TVM_GETITEM, 0, tvItem) !is 0) {
1770 item = tvItem.lParam !is -1 ? items [tvItem.lParam] : null; 1753 item = tvItem.lParam !is -1 ? items [tvItem.lParam] : null;
1771 } 1754 }
1772 if (item !is null) { 1755 if (item !is null) {
1756 if ((style & DWT.VIRTUAL) !is 0 && !item.cached) return;
1773 item.clear (); 1757 item.clear ();
1774 item.redraw (); 1758 item.redraw ();
1775 } 1759 }
1776 } 1760 }
1777 1761
1796 */ 1780 */
1797 public void clearAll (bool all) { 1781 public void clearAll (bool all) {
1798 checkWidget (); 1782 checkWidget ();
1799 HANDLE hItem = cast(HANDLE) OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_ROOT, 0); 1783 HANDLE hItem = cast(HANDLE) OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_ROOT, 0);
1800 if (hItem is null) return; 1784 if (hItem is null) return;
1801 TVITEM tvItem; 1785 if (all) {
1802 tvItem.mask = OS.TVIF_HANDLE | OS.TVIF_PARAM; 1786 bool redraw = false;
1803 clearAll (hItem, &tvItem, all); 1787 for (int i=0; i<items.length; i++) {
1788 TreeItem item = items [i];
1789 if (item !is null && item !is currentItem) {
1790 item.clear ();
1791 redraw = true;
1792 }
1793 }
1794 if (redraw) OS.InvalidateRect (handle, null, true);
1795 } else {
1796 TVITEM tvItem;
1797 tvItem.mask = OS.TVIF_HANDLE | OS.TVIF_PARAM;
1798 clearAll (hItem, &tvItem, all);
1799 }
1804 } 1800 }
1805 1801
1806 void clearAll (HANDLE hItem, TVITEM* tvItem, bool all) { 1802 void clearAll (HANDLE hItem, TVITEM* tvItem, bool all) {
1807 while (hItem !is null) { 1803 while (hItem !is null) {
1808 clear (hItem, tvItem); 1804 clear (hItem, tvItem);
1809 auto hFirstItem = cast(HANDLE) OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_CHILD, hItem); 1805 if (all) {
1810 if (all) clearAll (hFirstItem, tvItem, all); 1806 auto hFirstItem = cast(HANDLE)OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_CHILD, hItem);
1807 clearAll (hFirstItem, tvItem, all);
1808 }
1811 hItem = cast(HANDLE) OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_NEXT, hItem); 1809 hItem = cast(HANDLE) OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_NEXT, hItem);
1812 } 1810 }
1813 } 1811 }
1814 1812
1815 private static extern(Windows) int CompareFunc (int lParam1, int lParam2, int lParamSort) { 1813 private static extern(Windows) int CompareFunc (int lParam1, int lParam2, int lParamSort) {
1825 checkWidget (); 1823 checkWidget ();
1826 int width = 0, height = 0; 1824 int width = 0, height = 0;
1827 if (hwndHeader !is null) { 1825 if (hwndHeader !is null) {
1828 HDITEM hdItem; 1826 HDITEM hdItem;
1829 hdItem.mask = OS.HDI_WIDTH; 1827 hdItem.mask = OS.HDI_WIDTH;
1830 int count = OS.SendMessage (hwndHeader, OS.HDM_GETITEMCOUNT, 0, 0); 1828 for (int i=0; i<columnCount; i++) {
1831 for (int i=0; i<count; i++) {
1832 OS.SendMessage (hwndHeader, OS.HDM_GETITEM, i, &hdItem); 1829 OS.SendMessage (hwndHeader, OS.HDM_GETITEM, i, &hdItem);
1833 width += hdItem.cxy; 1830 width += hdItem.cxy;
1834 } 1831 }
1835 RECT rect; 1832 RECT rect;
1836 OS.GetWindowRect (hwndHeader, &rect); 1833 OS.GetWindowRect (hwndHeader, &rect);
1846 tvItem.pszText = OS.LPSTR_TEXTCALLBACK; 1843 tvItem.pszText = OS.LPSTR_TEXTCALLBACK;
1847 ignoreCustomDraw = true; 1844 ignoreCustomDraw = true;
1848 OS.SendMessage (handle, OS.TVM_SETITEM, 0, &tvItem); 1845 OS.SendMessage (handle, OS.TVM_SETITEM, 0, &tvItem);
1849 ignoreCustomDraw = false; 1846 ignoreCustomDraw = false;
1850 } 1847 }
1851 rect.left = cast(int) hItem; 1848 if (OS.TreeView_GetItemRect (handle, hItem, &rect, true)) {
1852 if (OS.SendMessage (handle, OS.TVM_GETITEMRECT, 1, &rect) !is 0) {
1853 width = Math.max (width, rect.right); 1849 width = Math.max (width, rect.right);
1854 height += rect.bottom - rect.top; 1850 height += rect.bottom - rect.top;
1855 } 1851 }
1856 hItem = cast(HANDLE) OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_NEXT, hItem); 1852 hItem = cast(HANDLE) OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_NEXTVISIBLE, hItem);
1857 } 1853 }
1858 if (width is 0) width = DEFAULT_WIDTH; 1854 if (width is 0) width = DEFAULT_WIDTH;
1859 if (height is 0) height = DEFAULT_HEIGHT; 1855 if (height is 0) height = DEFAULT_HEIGHT;
1860 if (wHint !is DWT.DEFAULT) width = wHint; 1856 if (wHint !is DWT.DEFAULT) width = wHint;
1861 if (hHint !is DWT.DEFAULT) height = hHint; 1857 if (hHint !is DWT.DEFAULT) height = hHint;
1875 super.createHandle (); 1871 super.createHandle ();
1876 state &= ~(CANVAS | THEME_BACKGROUND); 1872 state &= ~(CANVAS | THEME_BACKGROUND);
1877 1873
1878 /* Use the Explorer theme */ 1874 /* Use the Explorer theme */
1879 if (EXPLORER_THEME) { 1875 if (EXPLORER_THEME) {
1880 if (!OS.IsWinCE && OS.WIN32_VERSION >= OS.VERSION (6, 0)) { 1876 if (!OS.IsWinCE && OS.WIN32_VERSION >= OS.VERSION (6, 0) && OS.IsAppThemed ()) {
1881 explorerTheme = true; 1877 explorerTheme = true;
1882 OS.SetWindowTheme (handle, cast(TCHAR*) Display.EXPLORER, null); 1878 OS.SetWindowTheme (handle, cast(TCHAR*) Display.EXPLORER, null);
1883 int bits = OS.TVS_EX_DOUBLEBUFFER | OS.TVS_EX_FADEINOUTEXPANDOS | OS.TVS_EX_RICHTOOLTIP; 1879 int bits = OS.TVS_EX_DOUBLEBUFFER | OS.TVS_EX_FADEINOUTEXPANDOS | OS.TVS_EX_RICHTOOLTIP;
1884 if ((style & DWT.FULL_SELECTION) is 0) bits |= OS.TVS_EX_AUTOHSCROLL; 1880 if ((style & DWT.FULL_SELECTION) is 0) bits |= OS.TVS_EX_AUTOHSCROLL;
1885 OS.SendMessage (handle, OS.TVM_SETEXTENDEDSTYLE, 0, bits); 1881 OS.SendMessage (handle, OS.TVM_SETEXTENDEDSTYLE, 0, bits);
1929 } 1925 }
1930 1926
1931 void createHeaderToolTips () { 1927 void createHeaderToolTips () {
1932 static if (OS.IsWinCE) return; 1928 static if (OS.IsWinCE) return;
1933 if (headerToolTipHandle !is null) return; 1929 if (headerToolTipHandle !is null) return;
1930 int bits = 0;
1931 if (OS.WIN32_VERSION >= OS.VERSION (4, 10)) {
1932 if ((style & DWT.RIGHT_TO_LEFT) !is 0) bits |= OS.WS_EX_LAYOUTRTL;
1933 }
1934 headerToolTipHandle = OS.CreateWindowEx ( 1934 headerToolTipHandle = OS.CreateWindowEx (
1935 0, 1935 bits,
1936 OS.TOOLTIPS_CLASS.ptr, 1936 OS.TOOLTIPS_CLASS.ptr,
1937 null, 1937 null,
1938 0, 1938 OS.TTS_NOPREFIX,
1939 OS.CW_USEDEFAULT, 0, OS.CW_USEDEFAULT, 0, 1939 OS.CW_USEDEFAULT, 0, OS.CW_USEDEFAULT, 0,
1940 handle, 1940 handle,
1941 null, 1941 null,
1942 OS.GetModuleHandle (null), 1942 OS.GetModuleHandle (null),
1943 null); 1943 null);
1952 OS.SendMessage (headerToolTipHandle, OS.TTM_SETMAXTIPWIDTH, 0, 0x7FFF); 1952 OS.SendMessage (headerToolTipHandle, OS.TTM_SETMAXTIPWIDTH, 0, 0x7FFF);
1953 } 1953 }
1954 1954
1955 void createItem (TreeColumn column, int index) { 1955 void createItem (TreeColumn column, int index) {
1956 if (hwndHeader is null) createParent (); 1956 if (hwndHeader is null) createParent ();
1957 int columnCount = OS.SendMessage (hwndHeader, OS.HDM_GETITEMCOUNT, 0, 0);
1958 if (!(0 <= index && index <= columnCount)) error (DWT.ERROR_INVALID_RANGE); 1957 if (!(0 <= index && index <= columnCount)) error (DWT.ERROR_INVALID_RANGE);
1959 if (columnCount is columns.length) { 1958 if (columnCount is columns.length) {
1960 TreeColumn [] newColumns = new TreeColumn [columns.length + 4]; 1959 TreeColumn [] newColumns = new TreeColumn [columns.length + 4];
1961 System.arraycopy (columns, 0, newColumns, 0, columns.length); 1960 System.arraycopy (columns, 0, newColumns, 0, columns.length);
1962 columns = newColumns; 1961 columns = newColumns;
2007 System.arraycopy (cellForeground, index, temp, index + 1, columnCount - index); 2006 System.arraycopy (cellForeground, index, temp, index + 1, columnCount - index);
2008 temp [index] = -1; 2007 temp [index] = -1;
2009 item.cellForeground = temp; 2008 item.cellForeground = temp;
2010 } 2009 }
2011 if (item.cellFont !is null) { 2010 if (item.cellFont !is null) {
2012 HFONT [] cellFont = item.cellFont; 2011 Font [] cellFont = item.cellFont;
2013 HFONT [] temp = new HFONT [columnCount + 1]; 2012 Font [] temp = new Font [columnCount + 1];
2014 System.arraycopy (cellFont, 0, temp, 0, index); 2013 System.arraycopy (cellFont, 0, temp, 0, index);
2015 System.arraycopy (cellFont, index, temp, index + 1, columnCount- index); 2014 System.arraycopy (cellFont, index, temp, index + 1, columnCount- index);
2016 temp [index] = cast(HFONT)-1;
2017 item.cellFont = temp; 2015 item.cellFont = temp;
2018 } 2016 }
2019 } 2017 }
2020 } 2018 }
2021 System.arraycopy (columns, index, columns, index + 1, columnCount - index); 2019 System.arraycopy (columns, index, columns, index + 1, columnCount++ - index);
2022 columns [index] = column; 2020 columns [index] = column;
2023 2021
2024 /* 2022 /*
2025 * Bug in Windows. For some reason, when HDM_INSERTITEM 2023 * Bug in Windows. For some reason, when HDM_INSERTITEM
2026 * is used to insert an item into a header without text, 2024 * is used to insert an item into a header without text,
2037 if ((column.style & DWT.RIGHT) is DWT.RIGHT) hdItem.fmt = OS.HDF_RIGHT; 2035 if ((column.style & DWT.RIGHT) is DWT.RIGHT) hdItem.fmt = OS.HDF_RIGHT;
2038 OS.SendMessage (hwndHeader, OS.HDM_INSERTITEM, index, &hdItem); 2036 OS.SendMessage (hwndHeader, OS.HDM_INSERTITEM, index, &hdItem);
2039 if (pszText !is null) OS.HeapFree (hHeap, 0, pszText); 2037 if (pszText !is null) OS.HeapFree (hHeap, 0, pszText);
2040 2038
2041 /* When the first column is created, hide the horizontal scroll bar */ 2039 /* When the first column is created, hide the horizontal scroll bar */
2042 if (columnCount is 0) { 2040 if (columnCount is 1) {
2043 scrollWidth = 0; 2041 scrollWidth = 0;
2044 int bits = OS.GetWindowLong (handle, OS.GWL_STYLE); 2042 if ((style & DWT.H_SCROLL) !is 0) {
2045 bits |= OS.TVS_NOHSCROLL; 2043 int bits = OS.GetWindowLong (handle, OS.GWL_STYLE);
2046 OS.SetWindowLong (handle, OS.GWL_STYLE, bits); 2044 bits |= OS.TVS_NOHSCROLL;
2045 OS.SetWindowLong (handle, OS.GWL_STYLE, bits);
2046 }
2047 /* 2047 /*
2048 * Bug in Windows. When TVS_NOHSCROLL is set after items 2048 * Bug in Windows. When TVS_NOHSCROLL is set after items
2049 * have been inserted into the tree, Windows shows the 2049 * have been inserted into the tree, Windows shows the
2050 * scroll bar. The fix is to check for this case and 2050 * scroll bar. The fix is to check for this case and
2051 * explicitly hide the scroll bar explicitly. 2051 * explicitly hide the scroll bar explicitly.
2052 */ 2052 */
2053 int count = OS.SendMessage (handle, OS.TVM_GETCOUNT, 0, 0); 2053 int count = OS.SendMessage (handle, OS.TVM_GETCOUNT, 0, 0);
2054 if (count !is 0) { 2054 if (count !is 0) {
2055 static if (!OS.IsWinCE) OS.ShowScrollBar (handle, OS.SB_HORZ, false); 2055 static if (!OS.IsWinCE) OS.ShowScrollBar (handle, OS.SB_HORZ, false);
2056 } 2056 }
2057 createItemToolTips ();
2058 if (itemToolTipHandle !is null) {
2059 OS.SendMessage (itemToolTipHandle, OS.TTM_SETDELAYTIME, OS.TTDT_AUTOMATIC, -1);
2060 }
2057 } 2061 }
2058 setScrollWidth (); 2062 setScrollWidth ();
2059 updateImageList (); 2063 updateImageList ();
2060 updateScrollBar (); 2064 updateScrollBar ();
2061 2065
2062 /* Redraw to hide the items when the first column is created */ 2066 /* Redraw to hide the items when the first column is created */
2063 if (columnCount is 0 && OS.SendMessage (handle, OS.TVM_GETCOUNT, 0, 0) !is 0) { 2067 if (columnCount is 1 && OS.SendMessage (handle, OS.TVM_GETCOUNT, 0, 0) !is 0) {
2064 OS.InvalidateRect (handle, null, true); 2068 OS.InvalidateRect (handle, null, true);
2065 } 2069 }
2066 2070
2067 /* Add the tool tip item for the header */ 2071 /* Add the tool tip item for the header */
2068 if (headerToolTipHandle !is null) { 2072 if (headerToolTipHandle !is null) {
2146 if (item !is null) { 2150 if (item !is null) {
2147 item.handle = hNewItem; 2151 item.handle = hNewItem;
2148 items [id] = item; 2152 items [id] = item;
2149 } 2153 }
2150 if (hFirstItem is null) { 2154 if (hFirstItem is null) {
2151 switch ( cast(int) hInsertAfter) { 2155 if (cast(int)hInsertAfter is OS.TVI_FIRST || cast(int)hInsertAfter is OS.TVI_LAST) {
2152 case OS.TVI_FIRST: 2156 hFirstIndexOf = hLastIndexOf = hFirstItem = hNewItem;
2153 case OS.TVI_LAST: 2157 itemCount = lastIndexOf = 0;
2154 hFirstIndexOf = hLastIndexOf = hFirstItem = hNewItem;
2155 itemCount = lastIndexOf = 0;
2156 default:
2157 } 2158 }
2158 } 2159 }
2159 if (hFirstItem is hFirstIndexOf && itemCount !is -1) itemCount++; 2160 if (hFirstItem is hFirstIndexOf && itemCount !is -1) itemCount++;
2160 if (hItem is null) { 2161 if (hItem is null) {
2161 /* 2162 /*
2166 * child is added to a visible parent item and redraw the parent. 2167 * child is added to a visible parent item and redraw the parent.
2167 */ 2168 */
2168 if (fixParent) { 2169 if (fixParent) {
2169 if (drawCount is 0 && OS.IsWindowVisible (handle)) { 2170 if (drawCount is 0 && OS.IsWindowVisible (handle)) {
2170 RECT rect; 2171 RECT rect;
2171 rect.left = cast(int) hParent; 2172 if (OS.TreeView_GetItemRect (handle, hParent, &rect, false)) {
2172 if (OS.SendMessage (handle, OS.TVM_GETITEMRECT, 0, &rect) !is 0) {
2173 OS.InvalidateRect (handle, &rect, true); 2173 OS.InvalidateRect (handle, &rect, true);
2174 } 2174 }
2175 } 2175 }
2176 } 2176 }
2177 /* 2177 /*
2182 * new area. 2182 * new area.
2183 */ 2183 */
2184 if ((style & DWT.VIRTUAL) !is 0) { 2184 if ((style & DWT.VIRTUAL) !is 0) {
2185 if (currentItem !is null) { 2185 if (currentItem !is null) {
2186 RECT rect; 2186 RECT rect;
2187 rect.left = cast(int) hNewItem; 2187 if (OS.TreeView_GetItemRect (handle, hNewItem, &rect, false)) {
2188 if (OS.SendMessage (handle, OS.TVM_GETITEMRECT, 0, &rect) !is 0) {
2189 RECT damageRect; 2188 RECT damageRect;
2190 bool damaged = cast(bool) OS.GetUpdateRect (handle, &damageRect, true); 2189 bool damaged = cast(bool) OS.GetUpdateRect (handle, &damageRect, true);
2191 if (damaged && damageRect.top < rect.bottom) { 2190 if (damaged && damageRect.top < rect.bottom) {
2192 static if (OS.IsWinCE) { 2191 static if (OS.IsWinCE) {
2193 OS.OffsetRect (&damageRect, 0, rect.bottom - rect.top); 2192 OS.OffsetRect (&damageRect, 0, rect.bottom - rect.top);
2210 } 2209 }
2211 2210
2212 void createItemToolTips () { 2211 void createItemToolTips () {
2213 static if (OS.IsWinCE) return; 2212 static if (OS.IsWinCE) return;
2214 if (itemToolTipHandle !is null) return; 2213 if (itemToolTipHandle !is null) return;
2215 int bits = OS.GetWindowLong (handle, OS.GWL_STYLE); 2214 int bits1 = OS.GetWindowLong (handle, OS.GWL_STYLE);
2216 bits |= OS.TVS_NOTOOLTIPS; 2215 bits1 |= OS.TVS_NOTOOLTIPS;
2217 OS.SetWindowLong (handle, OS.GWL_STYLE, bits); 2216 OS.SetWindowLong (handle, OS.GWL_STYLE, bits1);
2217 int bits2 = 0;
2218 if (OS.WIN32_VERSION >= OS.VERSION (4, 10)) {
2219 if ((style & DWT.RIGHT_TO_LEFT) !is 0) bits2 |= OS.WS_EX_LAYOUTRTL;
2220 }
2221 /*
2222 * Feature in Windows. For some reason, when the user
2223 * clicks on a tool tip, it temporarily takes focus, even
2224 * when WS_EX_NOACTIVATE is specified. The fix is to
2225 * use WS_EX_TRANSPARENT, even though WS_EX_TRANSPARENT
2226 * is documented to affect painting, not hit testing.
2227 *
2228 * NOTE: Windows 2000 doesn't have the problem and
2229 * setting WS_EX_TRANSPARENT causes pixel corruption.
2230 */
2231 if (OS.COMCTL32_MAJOR >= 6) bits2 |= OS.WS_EX_TRANSPARENT;
2218 itemToolTipHandle = OS.CreateWindowEx ( 2232 itemToolTipHandle = OS.CreateWindowEx (
2219 0, 2233 bits2,
2220 OS.TOOLTIPS_CLASS.ptr, 2234 OS.TOOLTIPS_CLASS.ptr,
2221 null, 2235 null,
2222 0, 2236 OS.TTS_NOPREFIX | OS.TTS_NOANIMATE | OS.TTS_NOFADE,
2223 OS.CW_USEDEFAULT, 0, OS.CW_USEDEFAULT, 0, 2237 OS.CW_USEDEFAULT, 0, OS.CW_USEDEFAULT, 0,
2224 handle, 2238 handle,
2225 null, 2239 null,
2226 OS.GetModuleHandle (null), 2240 OS.GetModuleHandle (null),
2227 null); 2241 null);
2228 if (itemToolTipHandle is null) error (DWT.ERROR_NO_HANDLES); 2242 if (itemToolTipHandle is null) error (DWT.ERROR_NO_HANDLES);
2229 /* 2243 OS.SendMessage (itemToolTipHandle, OS.TTM_SETDELAYTIME, OS.TTDT_INITIAL, 0);
2230 * Feature in Windows. Despite the fact that the
2231 * tool tip text contains \r\n, the tooltip will
2232 * not honour the new line unless TTM_SETMAXTIPWIDTH
2233 * is set. The fix is to set TTM_SETMAXTIPWIDTH to
2234 * a large value.
2235 */
2236 OS.SendMessage (itemToolTipHandle, OS.TTM_SETMAXTIPWIDTH, 0, 0x7FFF);
2237 TOOLINFO lpti; 2244 TOOLINFO lpti;
2238 lpti.cbSize = TOOLINFO.sizeof; 2245 lpti.cbSize = TOOLINFO.sizeof;
2239 lpti.hwnd = handle; 2246 lpti.hwnd = handle;
2240 lpti.uId = cast(int)handle; 2247 lpti.uId = cast(int)handle;
2241 lpti.uFlags = OS.TTF_SUBCLASS | OS.TTF_TRANSPARENT; 2248 lpti.uFlags = OS.TTF_SUBCLASS | OS.TTF_TRANSPARENT;
2264 parent.handle, 2271 parent.handle,
2265 null, 2272 null,
2266 OS.GetModuleHandle (null), 2273 OS.GetModuleHandle (null),
2267 null); 2274 null);
2268 if (hwndParent is null) error (DWT.ERROR_NO_HANDLES); 2275 if (hwndParent is null) error (DWT.ERROR_NO_HANDLES);
2269 OS.SetWindowLong (hwndParent, OS.GWL_ID, cast(int) hwndParent); 2276 OS.SetWindowLongPtr (hwndParent, OS.GWLP_ID, cast(LONG_PTR)hwndParent);
2270 int bits = 0; 2277 int bits = 0;
2271 if (OS.WIN32_VERSION >= OS.VERSION (4, 10)) { 2278 if (OS.WIN32_VERSION >= OS.VERSION (4, 10)) {
2272 bits |= OS.WS_EX_NOINHERITLAYOUT; 2279 bits |= OS.WS_EX_NOINHERITLAYOUT;
2273 if ((style & DWT.RIGHT_TO_LEFT) !is 0) bits |= OS.WS_EX_LAYOUTRTL; 2280 if ((style & DWT.RIGHT_TO_LEFT) !is 0) bits |= OS.WS_EX_LAYOUTRTL;
2274 } 2281 }
2281 hwndParent, 2288 hwndParent,
2282 null, 2289 null,
2283 OS.GetModuleHandle (null), 2290 OS.GetModuleHandle (null),
2284 null); 2291 null);
2285 if (hwndHeader is null) error (DWT.ERROR_NO_HANDLES); 2292 if (hwndHeader is null) error (DWT.ERROR_NO_HANDLES);
2286 OS.SetWindowLong (hwndHeader, OS.GWL_ID, cast(int) hwndHeader); 2293 OS.SetWindowLongPtr (hwndHeader, OS.GWLP_ID, cast(LONG_PTR)hwndHeader);
2287 if (OS.IsDBLocale) { 2294 if (OS.IsDBLocale) {
2288 auto hIMC = OS.ImmGetContext (handle); 2295 auto hIMC = OS.ImmGetContext (handle);
2289 OS.ImmAssociateContext (hwndParent, hIMC); 2296 OS.ImmAssociateContext (hwndParent, hIMC);
2290 OS.ImmAssociateContext (hwndHeader, hIMC); 2297 OS.ImmAssociateContext (hwndHeader, hIMC);
2291 OS.ImmReleaseContext (handle, hIMC); 2298 OS.ImmReleaseContext (handle, hIMC);
2321 if (hwndFocus is handle) OS.SetFocus (hwndParent); 2328 if (hwndFocus is handle) OS.SetFocus (hwndParent);
2322 OS.SetParent (handle, hwndParent); 2329 OS.SetParent (handle, hwndParent);
2323 if (hwndFocus is handle) OS.SetFocus (handle); 2330 if (hwndFocus is handle) OS.SetFocus (handle);
2324 register (); 2331 register ();
2325 subclass (); 2332 subclass ();
2326 createItemToolTips ();
2327 } 2333 }
2328 2334
2329 override void createWidget () { 2335 override void createWidget () {
2330 super.createWidget (); 2336 super.createWidget ();
2331 items = new TreeItem [4]; 2337 items = new TreeItem [4];
2351 } 2357 }
2352 auto hFirstItem = cast(HANDLE) OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_CHILD, hItem); 2358 auto hFirstItem = cast(HANDLE) OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_CHILD, hItem);
2353 deselect (hFirstItem, tvItem, hIgnoreItem); 2359 deselect (hFirstItem, tvItem, hIgnoreItem);
2354 hItem = cast(HANDLE) OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_NEXT, hItem); 2360 hItem = cast(HANDLE) OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_NEXT, hItem);
2355 } 2361 }
2362 }
2363
2364 /**
2365 * Deselects an item in the receiver. If the item was already
2366 * deselected, it remains deselected.
2367 *
2368 * @param item the item to be deselected
2369 *
2370 * @exception IllegalArgumentException <ul>
2371 * <li>ERROR_NULL_ARGUMENT - if the item is null</li>
2372 * <li>ERROR_INVALID_ARGUMENT - if the item has been disposed</li>
2373 * </ul>
2374 * @exception DWTException <ul>
2375 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
2376 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
2377 * </ul>
2378 *
2379 * @since 3.4
2380 */
2381 public void deselect (TreeItem item) {
2382 checkWidget ();
2383 if (item is null) error (DWT.ERROR_NULL_ARGUMENT);
2384 if (item.isDisposed ()) error (DWT.ERROR_INVALID_ARGUMENT);
2385 TVITEM tvItem;
2386 tvItem.mask = OS.TVIF_HANDLE | OS.TVIF_STATE;
2387 tvItem.stateMask = OS.TVIS_SELECTED;
2388 tvItem.hItem = item.handle;
2389 OS.SendMessage (handle, OS.TVM_SETITEM, 0, cast(int)&tvItem);
2356 } 2390 }
2357 2391
2358 /** 2392 /**
2359 * Deselects all selected items in the receiver. 2393 * Deselects all selected items in the receiver.
2360 * 2394 *
2373 if (hItem !is null) { 2407 if (hItem !is null) {
2374 tvItem.hItem = hItem; 2408 tvItem.hItem = hItem;
2375 OS.SendMessage (handle, OS.TVM_SETITEM, 0, &tvItem); 2409 OS.SendMessage (handle, OS.TVM_SETITEM, 0, &tvItem);
2376 } 2410 }
2377 } else { 2411 } else {
2378 int oldProc = OS.GetWindowLong (handle, OS.GWL_WNDPROC); 2412 auto oldProc = OS.GetWindowLongPtr (handle, OS.GWLP_WNDPROC);
2379 OS.SetWindowLong (handle, OS.GWL_WNDPROC, cast(int) TreeProc); 2413 OS.SetWindowLongPtr (handle, OS.GWLP_WNDPROC, cast(LONG_PTR)TreeProc);
2380 if ((style & DWT.VIRTUAL) !is 0) { 2414 if ((style & DWT.VIRTUAL) !is 0) {
2381 HANDLE hItem = cast(HANDLE) OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_ROOT, 0); 2415 HANDLE hItem = cast(HANDLE) OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_ROOT, 0);
2382 deselect (hItem, &tvItem, null); 2416 deselect (hItem, &tvItem, null);
2383 } else { 2417 } else {
2384 for (int i=0; i<items.length; i++) { 2418 for (int i=0; i<items.length; i++) {
2387 tvItem.hItem = item.handle; 2421 tvItem.hItem = item.handle;
2388 OS.SendMessage (handle, OS.TVM_SETITEM, 0, &tvItem); 2422 OS.SendMessage (handle, OS.TVM_SETITEM, 0, &tvItem);
2389 } 2423 }
2390 } 2424 }
2391 } 2425 }
2392 OS.SetWindowLong (handle, OS.GWL_WNDPROC, oldProc); 2426 OS.SetWindowLongPtr (handle, OS.GWLP_WNDPROC, oldProc);
2393 } 2427 }
2394 } 2428 }
2395 2429
2396 void destroyItem (TreeColumn column) { 2430 void destroyItem (TreeColumn column) {
2397 if (hwndHeader is null) error (DWT.ERROR_ITEM_NOT_REMOVED); 2431 if (hwndHeader is null) error (DWT.ERROR_ITEM_NOT_REMOVED);
2398 int columnCount = OS.SendMessage (hwndHeader, OS.HDM_GETITEMCOUNT, 0, 0);
2399 int index = 0; 2432 int index = 0;
2400 while (index < columnCount) { 2433 while (index < columnCount) {
2401 if (columns [index] is column) break; 2434 if (columns [index] is column) break;
2402 index++; 2435 index++;
2403 } 2436 }
2460 System.arraycopy (cellForeground, 0, temp, 0, index); 2493 System.arraycopy (cellForeground, 0, temp, 0, index);
2461 System.arraycopy (cellForeground, index + 1, temp, index, columnCount - index); 2494 System.arraycopy (cellForeground, index + 1, temp, index, columnCount - index);
2462 item.cellForeground = temp; 2495 item.cellForeground = temp;
2463 } 2496 }
2464 if (item.cellFont !is null) { 2497 if (item.cellFont !is null) {
2465 HFONT [] cellFont = item.cellFont; 2498 Font [] cellFont = item.cellFont;
2466 HFONT [] temp = new HFONT [columnCount]; 2499 Font [] temp = new Font [columnCount];
2467 System.arraycopy (cellFont, 0, temp, 0, index); 2500 System.arraycopy (cellFont, 0, temp, 0, index);
2468 System.arraycopy (cellFont, index + 1, temp, index, columnCount - index); 2501 System.arraycopy (cellFont, index + 1, temp, index, columnCount - index);
2469 item.cellFont = temp; 2502 item.cellFont = temp;
2470 } 2503 }
2471 } 2504 }
2479 */ 2512 */
2480 if (columnCount is 0) { 2513 if (columnCount is 0) {
2481 scrollWidth = 0; 2514 scrollWidth = 0;
2482 if (!hooks (DWT.MeasureItem)) { 2515 if (!hooks (DWT.MeasureItem)) {
2483 int bits = OS.GetWindowLong (handle, OS.GWL_STYLE); 2516 int bits = OS.GetWindowLong (handle, OS.GWL_STYLE);
2484 bits &= ~OS.TVS_NOHSCROLL; 2517 if ((style & DWT.H_SCROLL) !is 0) bits &= ~OS.TVS_NOHSCROLL;
2485 OS.SetWindowLong (handle, OS.GWL_STYLE, bits); 2518 OS.SetWindowLong (handle, OS.GWL_STYLE, bits);
2486 OS.InvalidateRect (handle, null, true); 2519 OS.InvalidateRect (handle, null, true);
2520 }
2521 if (itemToolTipHandle !is null) {
2522 OS.SendMessage (itemToolTipHandle, OS.TTM_SETDELAYTIME, OS.TTDT_INITIAL, 0);
2487 } 2523 }
2488 } else { 2524 } else {
2489 if (index is 0) { 2525 if (index is 0) {
2490 columns [0].style &= ~(DWT.LEFT | DWT.RIGHT | DWT.CENTER); 2526 columns [0].style &= ~(DWT.LEFT | DWT.RIGHT | DWT.CENTER);
2491 columns [0].style |= DWT.LEFT; 2527 columns [0].style |= DWT.LEFT;
2550 HANDLE hParent; 2586 HANDLE hParent;
2551 bool fixRedraw = false; 2587 bool fixRedraw = false;
2552 if ((style & DWT.DOUBLE_BUFFERED) is 0) { 2588 if ((style & DWT.DOUBLE_BUFFERED) is 0) {
2553 if (drawCount is 0 && OS.IsWindowVisible (handle)) { 2589 if (drawCount is 0 && OS.IsWindowVisible (handle)) {
2554 RECT rect; 2590 RECT rect;
2555 rect.left = cast(int) hItem; 2591 fixRedraw = !OS.TreeView_GetItemRect (handle, hItem, &rect, false);
2556 fixRedraw = OS.SendMessage (handle, OS.TVM_GETITEMRECT, 0, &rect) is 0;
2557 } 2592 }
2558 } 2593 }
2559 if (fixRedraw) { 2594 if (fixRedraw) {
2560 hParent = cast(HANDLE) OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_PARENT, hItem); 2595 hParent = cast(HANDLE) OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_PARENT, hItem);
2561 OS.UpdateWindow (handle); 2596 OS.UpdateWindow (handle);
2597 * If the item that was deleted was the last child of a tree item that 2632 * If the item that was deleted was the last child of a tree item that
2598 * is visible, redraw the parent item to force the + / - to be updated. 2633 * is visible, redraw the parent item to force the + / - to be updated.
2599 */ 2634 */
2600 if (OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_CHILD, hParent) is 0) { 2635 if (OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_CHILD, hParent) is 0) {
2601 RECT rect; 2636 RECT rect;
2602 rect.left = cast(int) hParent; 2637 if (OS.TreeView_GetItemRect (handle, hParent, &rect, false)) {
2603 if (OS.SendMessage (handle, OS.TVM_GETITEMRECT, 0, &rect) !is 0) {
2604 OS.InvalidateRect (handle, &rect, true); 2638 OS.InvalidateRect (handle, &rect, true);
2605 } 2639 }
2606 } 2640 }
2607 } 2641 }
2608 int count = OS.SendMessage (handle, OS.TVM_GETCOUNT, 0, 0); 2642 int count = OS.SendMessage (handle, OS.TVM_GETCOUNT, 0, 0);
2620 items = new TreeItem [4]; 2654 items = new TreeItem [4];
2621 scrollWidth = 0; 2655 scrollWidth = 0;
2622 setScrollWidth (); 2656 setScrollWidth ();
2623 } 2657 }
2624 updateScrollBar (); 2658 updateScrollBar ();
2659 }
2660
2661 void destroyScrollBar (int type) {
2662 super.destroyScrollBar (type);
2663 int bits = OS.GetWindowLong (handle, OS.GWL_STYLE);
2664 if ((style & (DWT.H_SCROLL | DWT.V_SCROLL)) is 0) {
2665 bits &= ~(OS.WS_HSCROLL | OS.WS_VSCROLL);
2666 bits |= OS.TVS_NOSCROLL;
2667 } else {
2668 if ((style & DWT.H_SCROLL) is 0) {
2669 bits &= ~OS.WS_HSCROLL;
2670 bits |= OS.TVS_NOHSCROLL;
2671 }
2672 }
2673 OS.SetWindowLong (handle, OS.GWL_STYLE, bits);
2625 } 2674 }
2626 2675
2627 override void enableDrag (bool enabled) { 2676 override void enableDrag (bool enabled) {
2628 int bits = OS.GetWindowLong (handle, OS.GWL_STYLE); 2677 int bits = OS.GetWindowLong (handle, OS.GWL_STYLE);
2629 if (enabled && hooks (DWT.DragDetect)) { 2678 if (enabled && hooks (DWT.DragDetect)) {
2670 * as sort column. 2719 * as sort column.
2671 */ 2720 */
2672 updateFullSelection (); 2721 updateFullSelection ();
2673 } 2722 }
2674 2723
2724 bool findCell (int x, int y, inout TreeItem item, inout int index, inout RECT cellRect, inout RECT itemRect) {
2725 bool found = false;
2726 TVHITTESTINFO lpht;
2727 lpht.pt.x = x;
2728 lpht.pt.y = y;
2729 OS.SendMessage (handle, OS.TVM_HITTEST, 0, &lpht);
2730 if (lpht.hItem !is null) {
2731 item = _getItem (lpht.hItem);
2732 POINT pt;
2733 pt.x = x;
2734 pt.y = y;
2735 auto hDC = OS.GetDC (handle);
2736 HFONT oldFont;
2737 auto newFont = cast(HFONT)OS.SendMessage (handle, OS.WM_GETFONT, 0, 0);
2738 if (newFont !is null) oldFont = OS.SelectObject (hDC, newFont);
2739 RECT rect;
2740 if (hwndParent !is null) {
2741 OS.GetClientRect (hwndParent, &rect);
2742 OS.MapWindowPoints (hwndParent, handle, cast(POINT*)&rect, 2);
2743 } else {
2744 OS.GetClientRect (handle, &rect);
2745 }
2746 int count = Math.max (1, columnCount);
2747 int [] order = new int [count];
2748 if (hwndHeader !is null) OS.SendMessage (hwndHeader, OS.HDM_GETORDERARRAY, count, cast(int) order.ptr);
2749 index = 0;
2750 bool quit = false;
2751 while (index < count && !quit) {
2752 auto hFont = item.fontHandle (order [index]);
2753 if (hFont !is cast(HFONT)-1) hFont = OS.SelectObject (hDC, hFont);
2754 cellRect = item.getBounds (order [index], true, false, true, false, true, hDC);
2755 if (cellRect.left > rect.right) {
2756 quit = true;
2757 } else {
2758 cellRect.right = Math.min (cellRect.right, rect.right);
2759 if (OS.PtInRect ( &cellRect, pt)) {
2760 if (isCustomToolTip ()) {
2761 Event event = sendMeasureItemEvent (item, order [index], hDC);
2762 if (isDisposed () || item.isDisposed ()) break;
2763 //itemRect [0] = new RECT ();
2764 itemRect.left = event.x;
2765 itemRect.right = event.x + event.width;
2766 itemRect.top = event.y;
2767 itemRect.bottom = event.y + event.height;
2768 } else {
2769 itemRect = item.getBounds (order [index], true, false, false, false, false, hDC);
2770 }
2771 if (itemRect.right > cellRect.right) found = true;
2772 quit = true;
2773 }
2774 }
2775 if (hFont !is cast(HFONT)-1) OS.SelectObject (hDC, hFont);
2776 if (!found) index++;
2777 }
2778 if (newFont !is null) OS.SelectObject (hDC, oldFont);
2779 OS.ReleaseDC (handle, hDC);
2780 }
2781 return found;
2782 }
2783
2675 int findIndex (HANDLE hFirstItem, HANDLE hItem) { 2784 int findIndex (HANDLE hFirstItem, HANDLE hItem) {
2676 if (hFirstItem is null) return -1; 2785 if (hFirstItem is null) return -1;
2677 if (hFirstItem is hFirstIndexOf) { 2786 if (hFirstItem is hFirstIndexOf) {
2678 if (hFirstIndexOf is hItem) { 2787 if (hFirstIndexOf is hItem) {
2679 hLastIndexOf = hFirstIndexOf; 2788 hLastIndexOf = hFirstIndexOf;
2901 * 3010 *
2902 * @since 3.1 3011 * @since 3.1
2903 */ 3012 */
2904 public TreeColumn getColumn (int index) { 3013 public TreeColumn getColumn (int index) {
2905 checkWidget (); 3014 checkWidget ();
2906 if (hwndHeader is null) error (DWT.ERROR_INVALID_RANGE); 3015 if (!(0 <= index && index < columnCount)) error (DWT.ERROR_INVALID_RANGE);
2907 int count = OS.SendMessage (hwndHeader, OS.HDM_GETITEMCOUNT, 0, 0);
2908 if (!(0 <= index && index < count)) error (DWT.ERROR_INVALID_RANGE);
2909 return columns [index]; 3016 return columns [index];
2910 } 3017 }
2911 3018
2912 /** 3019 /**
2913 * Returns the number of columns contained in the receiver. 3020 * Returns the number of columns contained in the receiver.
2925 * 3032 *
2926 * @since 3.1 3033 * @since 3.1
2927 */ 3034 */
2928 public int getColumnCount () { 3035 public int getColumnCount () {
2929 checkWidget (); 3036 checkWidget ();
2930 if (hwndHeader is null) return 0; 3037 return columnCount;
2931 return OS.SendMessage (hwndHeader, OS.HDM_GETITEMCOUNT, 0, 0);
2932 } 3038 }
2933 3039
2934 /** 3040 /**
2935 * Returns an array of zero-relative integers that map 3041 * Returns an array of zero-relative integers that map
2936 * the creation order of the receiver's items to the 3042 * the creation order of the receiver's items to the
2959 * 3065 *
2960 * @since 3.2 3066 * @since 3.2
2961 */ 3067 */
2962 public int[] getColumnOrder () { 3068 public int[] getColumnOrder () {
2963 checkWidget (); 3069 checkWidget ();
2964 if (hwndHeader is null) return new int [0]; 3070 if (columnCount is 0) return null;
2965 int count = OS.SendMessage (hwndHeader, OS.HDM_GETITEMCOUNT, 0, 0); 3071 int [] order = new int [columnCount];
2966 int [] order = new int [count]; 3072 OS.SendMessage (hwndHeader, OS.HDM_GETORDERARRAY, columnCount, order.ptr);
2967 OS.SendMessage (hwndHeader, OS.HDM_GETORDERARRAY, count, order.ptr);
2968 return order; 3073 return order;
2969 } 3074 }
2970 3075
2971 /** 3076 /**
2972 * Returns an array of <code>TreeColumn</code>s which are the 3077 * Returns an array of <code>TreeColumn</code>s which are the
2997 * 3102 *
2998 * @since 3.1 3103 * @since 3.1
2999 */ 3104 */
3000 public TreeColumn [] getColumns () { 3105 public TreeColumn [] getColumns () {
3001 checkWidget (); 3106 checkWidget ();
3002 if (hwndHeader is null) return new TreeColumn [0]; 3107 TreeColumn [] result = new TreeColumn [columnCount];
3003 int count = OS.SendMessage (hwndHeader, OS.HDM_GETITEMCOUNT, 0, 0); 3108 System.arraycopy (columns, 0, result, 0, columnCount);
3004 TreeColumn [] result = new TreeColumn [count];
3005 System.arraycopy (columns, 0, result, 0, count);
3006 return result; 3109 return result;
3007 } 3110 }
3008 3111
3009 /** 3112 /**
3010 * Returns the item at the given, zero-relative index in the 3113 * Returns the item at the given, zero-relative index in the
3084 TVHITTESTINFO lpht; 3187 TVHITTESTINFO lpht;
3085 lpht.pt.x = point.x; 3188 lpht.pt.x = point.x;
3086 lpht.pt.y = point.y; 3189 lpht.pt.y = point.y;
3087 OS.SendMessage (handle, OS.TVM_HITTEST, 0, &lpht); 3190 OS.SendMessage (handle, OS.TVM_HITTEST, 0, &lpht);
3088 if (lpht.hItem !is null) { 3191 if (lpht.hItem !is null) {
3089 if ((style & DWT.FULL_SELECTION) !is 0 || (lpht.flags & OS.TVHT_ONITEM) !is 0) { 3192 int flags = OS.TVHT_ONITEM;
3090 return _getItem (lpht.hItem); 3193 if ((style & DWT.FULL_SELECTION) !is 0) {
3091 } 3194 flags |= OS.TVHT_ONITEMRIGHT | OS.TVHT_ONITEMINDENT;
3195 } else {
3196 if (hooks (DWT.MeasureItem)) {
3197 lpht.flags &= ~(OS.TVHT_ONITEMICON | OS.TVHT_ONITEMLABEL);
3198 if (hitTestSelection ( lpht.hItem, lpht.pt.x, lpht.pt.y)) {
3199 lpht.flags |= OS.TVHT_ONITEMICON | OS.TVHT_ONITEMLABEL;
3200 }
3201 }
3202 }
3203 if ((lpht.flags & flags) !is 0) return _getItem (lpht.hItem);
3092 } 3204 }
3093 return null; 3205 return null;
3094 } 3206 }
3095 3207
3096 /** 3208 /**
3326 if ((tvItem.state & OS.TVIS_SELECTED) is 0) return new TreeItem [0]; 3438 if ((tvItem.state & OS.TVIS_SELECTED) is 0) return new TreeItem [0];
3327 return [_getItem (tvItem.hItem, tvItem.lParam)]; 3439 return [_getItem (tvItem.hItem, tvItem.lParam)];
3328 } 3440 }
3329 int count = 0; 3441 int count = 0;
3330 TreeItem [] guess = new TreeItem [(style & DWT.VIRTUAL) !is 0 ? 8 : 1]; 3442 TreeItem [] guess = new TreeItem [(style & DWT.VIRTUAL) !is 0 ? 8 : 1];
3331 int oldProc = OS.GetWindowLong (handle, OS.GWL_WNDPROC); 3443 int /*long*/ oldProc = OS.GetWindowLongPtr (handle, OS.GWLP_WNDPROC);
3332 OS.SetWindowLong (handle, OS.GWL_WNDPROC, cast(int) TreeProc); 3444 OS.SetWindowLongPtr (handle, OS.GWLP_WNDPROC, cast(LONG_PTR)TreeProc);
3333 if ((style & DWT.VIRTUAL) !is 0) { 3445 if ((style & DWT.VIRTUAL) !is 0) {
3334 TVITEM tvItem; 3446 TVITEM tvItem;
3335 tvItem.mask = OS.TVIF_HANDLE | OS.TVIF_PARAM | OS.TVIF_STATE; 3447 tvItem.mask = OS.TVIF_HANDLE | OS.TVIF_PARAM | OS.TVIF_STATE;
3336 HANDLE hItem = cast(HANDLE) OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_ROOT, 0); 3448 HANDLE hItem = cast(HANDLE) OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_ROOT, 0);
3337 count = getSelection (hItem, &tvItem, guess, 0, -1, false, true); 3449 count = getSelection (hItem, &tvItem, guess, 0, -1, false, true);
3358 count++; 3470 count++;
3359 } 3471 }
3360 } 3472 }
3361 } 3473 }
3362 } 3474 }
3363 OS.SetWindowLong (handle, OS.GWL_WNDPROC, oldProc); 3475 OS.SetWindowLongPtr (handle, OS.GWLP_WNDPROC, oldProc);
3364 if (count is 0) return new TreeItem [0]; 3476 if (count is 0) return new TreeItem [0];
3365 if (count is guess.length) return guess; 3477 if (count is guess.length) return guess;
3366 TreeItem [] result = new TreeItem [count]; 3478 TreeItem [] result = new TreeItem [count];
3367 if (count < guess.length) { 3479 if (count < guess.length) {
3368 System.arraycopy (guess, 0, result, 0, count); 3480 System.arraycopy (guess, 0, result, 0, count);
3369 return result; 3481 return result;
3370 } 3482 }
3371 OS.SetWindowLong (handle, OS.GWL_WNDPROC, cast(int) TreeProc); 3483 OS.SetWindowLongPtr (handle, OS.GWLP_WNDPROC, cast(LONG_PTR)TreeProc);
3372 TVITEM tvItem; 3484 TVITEM tvItem;
3373 tvItem.mask = OS.TVIF_HANDLE | OS.TVIF_PARAM | OS.TVIF_STATE; 3485 tvItem.mask = OS.TVIF_HANDLE | OS.TVIF_PARAM | OS.TVIF_STATE;
3374 HANDLE hItem = cast(HANDLE) OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_ROOT, 0); 3486 HANDLE hItem = cast(HANDLE) OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_ROOT, 0);
3375 int itemCount = OS.SendMessage (handle, OS.TVM_GETCOUNT, 0, 0); 3487 int itemCount = OS.SendMessage (handle, OS.TVM_GETCOUNT, 0, 0);
3376 bool bigSelection = result.length > itemCount / 2; 3488 bool bigSelection = result.length > itemCount / 2;
3377 if (count !is getSelection (hItem, &tvItem, result, 0, count, bigSelection, false)) { 3489 if (count !is getSelection (hItem, &tvItem, result, 0, count, bigSelection, false)) {
3378 getSelection (hItem, &tvItem, result, 0, count, bigSelection, true); 3490 getSelection (hItem, &tvItem, result, 0, count, bigSelection, true);
3379 } 3491 }
3380 OS.SetWindowLong (handle, OS.GWL_WNDPROC, oldProc); 3492 OS.SetWindowLongPtr (handle, OS.GWLP_WNDPROC, oldProc);
3381 return result; 3493 return result;
3382 } 3494 }
3383 3495
3384 /** 3496 /**
3385 * Returns the number of selected items contained in the receiver. 3497 * Returns the number of selected items contained in the receiver.
3407 state = OS.SendMessage (handle, OS.TVM_GETITEMSTATE, hItem, OS.TVIS_SELECTED); 3519 state = OS.SendMessage (handle, OS.TVM_GETITEMSTATE, hItem, OS.TVIS_SELECTED);
3408 } 3520 }
3409 return (state & OS.TVIS_SELECTED) is 0 ? 0 : 1; 3521 return (state & OS.TVIS_SELECTED) is 0 ? 0 : 1;
3410 } 3522 }
3411 int count = 0; 3523 int count = 0;
3412 int oldProc = OS.GetWindowLong (handle, OS.GWL_WNDPROC); 3524 int /*long*/ oldProc = OS.GetWindowLongPtr (handle, OS.GWLP_WNDPROC);
3413 TVITEM tvItem_; 3525 TVITEM tvItem_;
3414 TVITEM* tvItem = null; 3526 TVITEM* tvItem = null;
3415 static if (OS.IsWinCE) { 3527 static if (OS.IsWinCE) {
3416 tvItem = &tvitem_; 3528 tvItem = &tvitem_;
3417 tvItem.mask = OS.TVIF_STATE; 3529 tvItem.mask = OS.TVIF_STATE;
3418 } 3530 }
3419 OS.SetWindowLong (handle, OS.GWL_WNDPROC, cast(int) TreeProc); 3531 OS.SetWindowLongPtr (handle, OS.GWLP_WNDPROC, cast(LONG_PTR)TreeProc);
3420 if ((style & DWT.VIRTUAL) !is 0) { 3532 if ((style & DWT.VIRTUAL) !is 0) {
3421 HANDLE hItem = cast(HANDLE) OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_ROOT, 0); 3533 HANDLE hItem = cast(HANDLE) OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_ROOT, 0);
3422 count = getSelection (hItem, tvItem, null, 0, -1, false, true); 3534 count = getSelection (hItem, tvItem, null, 0, -1, false, true);
3423 } else { 3535 } else {
3424 for (int i=0; i<items.length; i++) { 3536 for (int i=0; i<items.length; i++) {
3435 } 3547 }
3436 if ((state & OS.TVIS_SELECTED) !is 0) count++; 3548 if ((state & OS.TVIS_SELECTED) !is 0) count++;
3437 } 3549 }
3438 } 3550 }
3439 } 3551 }
3440 OS.SetWindowLong (handle, OS.GWL_WNDPROC, oldProc); 3552 OS.SetWindowLongPtr (handle, OS.GWLP_WNDPROC, oldProc);
3441 return count; 3553 return count;
3442 } 3554 }
3443 3555
3444 /** 3556 /**
3445 * Returns the column which shows the sort indicator for 3557 * Returns the column which shows the sort indicator for
3518 checkWidget (); 3630 checkWidget ();
3519 HANDLE hItem = cast(HANDLE) OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_FIRSTVISIBLE, 0); 3631 HANDLE hItem = cast(HANDLE) OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_FIRSTVISIBLE, 0);
3520 return hItem !is null ? _getItem (hItem) : null; 3632 return hItem !is null ? _getItem (hItem) : null;
3521 } 3633 }
3522 3634
3635 bool hitTestSelection (HANDLE hItem, int x, int y) {
3636 if (hItem is null) return false;
3637 TreeItem item = _getItem (hItem);
3638 if (item is null) return false;
3639 if (!hooks (DWT.MeasureItem)) return false;
3640 bool result = false;
3641
3642 //BUG? - moved columns, only hittest first column
3643 //BUG? - check drag detect
3644 int [] order = new int [1], index = new int [1];
3645
3646 auto hDC = OS.GetDC (handle);
3647 HFONT oldFont, newFont = cast(HFONT)OS.SendMessage (handle, OS.WM_GETFONT, 0, 0);
3648 if (newFont !is null) oldFont = OS.SelectObject (hDC, newFont);
3649 auto hFont = item.fontHandle (order [index [0]]);
3650 if (hFont !is cast(HFONT)-1) hFont = OS.SelectObject (hDC, hFont);
3651 Event event = sendMeasureItemEvent (item, order [index [0]], hDC);
3652 if (event.getBounds ().contains (x, y)) result = true;
3653 if (newFont !is null) OS.SelectObject (hDC, oldFont);
3654 OS.ReleaseDC (handle, hDC);
3655 // if (isDisposed () || item.isDisposed ()) return false;
3656 return result;
3657 }
3658
3523 int imageIndex (Image image, int index) { 3659 int imageIndex (Image image, int index) {
3524 if (image is null) return OS.I_IMAGENONE; 3660 if (image is null) return OS.I_IMAGENONE;
3525 if (imageList is null) { 3661 if (imageList is null) {
3526 Rectangle bounds = image.getBounds (); 3662 Rectangle bounds = image.getBounds ();
3527 imageList = display.getImageList (style & DWT.RIGHT_TO_LEFT, bounds.width, bounds.height); 3663 imageList = display.getImageList (style & DWT.RIGHT_TO_LEFT, bounds.width, bounds.height);
3528 } 3664 }
3529 int imageIndex = imageList.indexOf (image); 3665 int imageIndex = imageList.indexOf (image);
3530 if (imageIndex is -1) imageIndex = imageList.add (image); 3666 if (imageIndex is -1) imageIndex = imageList.add (image);
3531 if (hwndHeader is null || OS.SendMessage (hwndHeader, OS.HDM_ORDERTOINDEX, 0, 0) is index) { 3667 if (hwndHeader is null || OS.SendMessage (hwndHeader, OS.HDM_ORDERTOINDEX, 0, 0) is index) {
3668 /*
3669 * Feature in Windows. When setting the same image list multiple
3670 * times, Windows does work making this operation slow. The fix
3671 * is to test for the same image list before setting the new one.
3672 */
3532 auto hImageList = imageList.getHandle (); 3673 auto hImageList = imageList.getHandle ();
3533 auto hOldImageList = cast(HANDLE) OS.SendMessage (handle, OS.TVM_GETIMAGELIST, OS.TVSIL_NORMAL, 0); 3674 auto hOldImageList = cast(HANDLE) OS.SendMessage (handle, OS.TVM_GETIMAGELIST, OS.TVSIL_NORMAL, 0);
3534 if (hOldImageList !is hImageList) { 3675 if (hOldImageList !is hImageList) {
3535 OS.SendMessage (handle, OS.TVM_SETIMAGELIST, OS.TVSIL_NORMAL, hImageList); 3676 OS.SendMessage (handle, OS.TVM_SETIMAGELIST, OS.TVSIL_NORMAL, hImageList);
3536 updateScrollBar (); 3677 updateScrollBar ();
3579 */ 3720 */
3580 public int indexOf (TreeColumn column) { 3721 public int indexOf (TreeColumn column) {
3581 checkWidget (); 3722 checkWidget ();
3582 if (column is null) error (DWT.ERROR_NULL_ARGUMENT); 3723 if (column is null) error (DWT.ERROR_NULL_ARGUMENT);
3583 if (column.isDisposed()) error(DWT.ERROR_INVALID_ARGUMENT); 3724 if (column.isDisposed()) error(DWT.ERROR_INVALID_ARGUMENT);
3584 if (hwndHeader is null) return -1; 3725 for (int i=0; i<columnCount; i++) {
3585 int count = OS.SendMessage (hwndHeader, OS.HDM_GETITEMCOUNT, 0, 0);
3586 for (int i=0; i<count; i++) {
3587 if (columns [i] is column) return i; 3726 if (columns [i] is column) return i;
3588 } 3727 }
3589 return -1; 3728 return -1;
3590 } 3729 }
3591 3730
3613 checkWidget (); 3752 checkWidget ();
3614 if (item is null) error (DWT.ERROR_NULL_ARGUMENT); 3753 if (item is null) error (DWT.ERROR_NULL_ARGUMENT);
3615 if (item.isDisposed()) error(DWT.ERROR_INVALID_ARGUMENT); 3754 if (item.isDisposed()) error(DWT.ERROR_INVALID_ARGUMENT);
3616 HANDLE hItem = cast(HANDLE) OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_ROOT, 0); 3755 HANDLE hItem = cast(HANDLE) OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_ROOT, 0);
3617 return hItem is null ? -1 : findIndex (hItem, item.handle); 3756 return hItem is null ? -1 : findIndex (hItem, item.handle);
3757 }
3758
3759 bool isCustomToolTip () {
3760 return hooks (DWT.MeasureItem);
3618 } 3761 }
3619 3762
3620 bool isItemSelected (NMTVCUSTOMDRAW* nmcd) { 3763 bool isItemSelected (NMTVCUSTOMDRAW* nmcd) {
3621 bool selected = false; 3764 bool selected = false;
3622 if (OS.IsWindowEnabled (handle)) { 3765 if (OS.IsWindowEnabled (handle)) {
3684 void redrawSelection () { 3827 void redrawSelection () {
3685 if ((style & DWT.SINGLE) !is 0) { 3828 if ((style & DWT.SINGLE) !is 0) {
3686 HANDLE hItem = cast(HANDLE) OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_CARET, 0); 3829 HANDLE hItem = cast(HANDLE) OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_CARET, 0);
3687 if (hItem !is null) { 3830 if (hItem !is null) {
3688 RECT rect; 3831 RECT rect;
3689 rect.left = cast(int) hItem; 3832 if (OS.TreeView_GetItemRect (handle, hItem, &rect, false)) {
3690 OS.SendMessage (handle, OS.TVM_GETITEMRECT, 0, &rect); 3833 OS.InvalidateRect (handle, &rect, true);
3691 OS.InvalidateRect (handle, &rect, true); 3834 }
3692 } 3835 }
3693 } else { 3836 } else {
3694 HANDLE hItem = cast(HANDLE) OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_FIRSTVISIBLE, 0); 3837 HANDLE hItem = cast(HANDLE) OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_FIRSTVISIBLE, 0);
3695 if (hItem !is null) { 3838 if (hItem !is null) {
3696 TVITEM tvItem; 3839 TVITEM tvItem;
3708 state = tvItem.state; 3851 state = tvItem.state;
3709 } else { 3852 } else {
3710 state = OS.SendMessage (handle, OS.TVM_GETITEMSTATE, hItem, OS.TVIS_SELECTED); 3853 state = OS.SendMessage (handle, OS.TVM_GETITEMSTATE, hItem, OS.TVIS_SELECTED);
3711 } 3854 }
3712 if ((state & OS.TVIS_SELECTED) !is 0) { 3855 if ((state & OS.TVIS_SELECTED) !is 0) {
3713 rect.left = cast(int) hItem; 3856 if (OS.TreeView_GetItemRect (handle, hItem, &rect, false)) {
3714 OS.SendMessage (handle, OS.TVM_GETITEMRECT, 0, &rect); 3857 OS.InvalidateRect (handle, &rect, true);
3715 OS.InvalidateRect (handle, &rect, true); 3858 }
3716 } 3859 }
3717 hItem = cast(HANDLE) OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_NEXTVISIBLE, hItem); 3860 hItem = cast(HANDLE) OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_NEXTVISIBLE, hItem);
3718 index++; 3861 index++;
3719 } 3862 }
3720 } 3863 }
3806 OS.SendMessage (handle, OS.TVM_SETIMAGELIST, OS.TVSIL_STATE, 0); 3949 OS.SendMessage (handle, OS.TVM_SETIMAGELIST, OS.TVSIL_STATE, 0);
3807 if (hStateList !is null) OS.ImageList_Destroy (hStateList); 3950 if (hStateList !is null) OS.ImageList_Destroy (hStateList);
3808 if (itemToolTipHandle !is null) OS.DestroyWindow (itemToolTipHandle); 3951 if (itemToolTipHandle !is null) OS.DestroyWindow (itemToolTipHandle);
3809 if (headerToolTipHandle !is null) OS.DestroyWindow (headerToolTipHandle); 3952 if (headerToolTipHandle !is null) OS.DestroyWindow (headerToolTipHandle);
3810 itemToolTipHandle = headerToolTipHandle = null; 3953 itemToolTipHandle = headerToolTipHandle = null;
3811 if (display.isXMouseActive ()) {
3812 Shell shell = getShell ();
3813 if (shell.lockToolTipControl is this) {
3814 shell.lockToolTipControl = null;
3815 }
3816 }
3817 } 3954 }
3818 3955
3819 /** 3956 /**
3820 * Removes all of the items from the receiver. 3957 * Removes all of the items from the receiver.
3821 * 3958 *
3836 } 3973 }
3837 ignoreDeselect = ignoreSelect = true; 3974 ignoreDeselect = ignoreSelect = true;
3838 bool redraw = drawCount is 0 && OS.IsWindowVisible (handle); 3975 bool redraw = drawCount is 0 && OS.IsWindowVisible (handle);
3839 if (redraw) OS.DefWindowProc (handle, OS.WM_SETREDRAW, 0, 0); 3976 if (redraw) OS.DefWindowProc (handle, OS.WM_SETREDRAW, 0, 0);
3840 shrink = ignoreShrink = true; 3977 shrink = ignoreShrink = true;
3841 int result = OS.SendMessage (handle, OS.TVM_DELETEITEM, 0, OS.TVI_ROOT); 3978 int /*long*/ result = OS.SendMessage (handle, OS.TVM_DELETEITEM, 0, OS.TVI_ROOT);
3842 ignoreShrink = false; 3979 ignoreShrink = false;
3843 if (redraw) { 3980 if (redraw) {
3844 OS.DefWindowProc (handle, OS.WM_SETREDRAW, 1, 0); 3981 OS.DefWindowProc (handle, OS.WM_SETREDRAW, 1, 0);
3845 OS.InvalidateRect (handle, null, true); 3982 OS.InvalidateRect (handle, null, true);
3846 } 3983 }
3970 int itemCount = 0; 4107 int itemCount = 0;
3971 while (hItem !is null && itemCount < count) { 4108 while (hItem !is null && itemCount < count) {
3972 hItem = cast(HANDLE) OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_NEXT, hItem); 4109 hItem = cast(HANDLE) OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_NEXT, hItem);
3973 itemCount++; 4110 itemCount++;
3974 } 4111 }
4112 bool expanded = false;
3975 TVITEM tvItem; 4113 TVITEM tvItem;
3976 tvItem.mask = OS.TVIF_HANDLE | OS.TVIF_PARAM; 4114 tvItem.mask = OS.TVIF_HANDLE | OS.TVIF_PARAM;
4115 if (!redraw && (style & DWT.VIRTUAL) !is 0) {
4116 if (OS.IsWinCE) {
4117 tvItem.hItem = hParent;
4118 tvItem.mask = OS.TVIF_STATE;
4119 OS.SendMessage (handle, OS.TVM_GETITEM, 0, cast(int)&tvItem);
4120 expanded = (tvItem.state & OS.TVIS_EXPANDED) !is 0;
4121 } else {
4122 /*
4123 * Bug in Windows. Despite the fact that TVM_GETITEMSTATE claims
4124 * to return only the bits specified by the stateMask, when called
4125 * with TVIS_EXPANDED, the entire state is returned. The fix is
4126 * to explicitly check for the TVIS_EXPANDED bit.
4127 */
4128 int state = OS.SendMessage (handle, OS.TVM_GETITEMSTATE, hParent, OS.TVIS_EXPANDED);
4129 expanded = (state & OS.TVIS_EXPANDED) !is 0;
4130 }
4131 }
3977 while (hItem !is null) { 4132 while (hItem !is null) {
3978 tvItem.hItem = hItem; 4133 tvItem.hItem = hItem;
3979 OS.SendMessage (handle, OS.TVM_GETITEM, 0, &tvItem); 4134 OS.SendMessage (handle, OS.TVM_GETITEM, 0, &tvItem);
3980 hItem = cast(HANDLE) OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_NEXT, hItem); 4135 hItem = cast(HANDLE) OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_NEXT, hItem);
3981 TreeItem item = tvItem.lParam !is -1 ? items [tvItem.lParam] : null; 4136 TreeItem item = tvItem.lParam !is -1 ? items [tvItem.lParam] : null;
3986 destroyItem (null, tvItem.hItem); 4141 destroyItem (null, tvItem.hItem);
3987 } 4142 }
3988 } 4143 }
3989 if ((style & DWT.VIRTUAL) !is 0) { 4144 if ((style & DWT.VIRTUAL) !is 0) {
3990 for (int i=itemCount; i<count; i++) { 4145 for (int i=itemCount; i<count; i++) {
4146 if (expanded) ignoreShrink = true;
3991 createItem (null, hParent, cast(HANDLE) OS.TVI_LAST, null); 4147 createItem (null, hParent, cast(HANDLE) OS.TVI_LAST, null);
4148 if (expanded) ignoreShrink = false;
3992 } 4149 }
3993 } else { 4150 } else {
3994 shrink = true; 4151 shrink = true;
3995 int extra = Math.max (4, (count + 3) / 4 * 4); 4152 int extra = Math.max (4, (count + 3) / 4 * 4);
3996 TreeItem [] newItems = new TreeItem [items.length + extra]; 4153 TreeItem [] newItems = new TreeItem [items.length + extra];
4051 OS.InvalidateRect (handle, null, true); 4208 OS.InvalidateRect (handle, null, true);
4052 } 4209 }
4053 4210
4054 override HWND scrolledHandle () { 4211 override HWND scrolledHandle () {
4055 if (hwndHeader is null) return handle; 4212 if (hwndHeader is null) return handle;
4056 int count = OS.SendMessage (hwndHeader, OS.HDM_GETITEMCOUNT, 0, 0); 4213 return columnCount is 0 && scrollWidth is 0 ? handle : hwndParent;
4057 return count is 0 ? handle : hwndParent;
4058 } 4214 }
4059 4215
4060 void select (HANDLE hItem, TVITEM* tvItem) { 4216 void select (HANDLE hItem, TVITEM* tvItem) {
4061 while (hItem !is null) { 4217 while (hItem !is null) {
4062 tvItem.hItem = hItem; 4218 tvItem.hItem = hItem;
4063 OS.SendMessage (handle, OS.TVM_SETITEM, 0, tvItem); 4219 OS.SendMessage (handle, OS.TVM_SETITEM, 0, tvItem);
4064 auto hFirstItem = cast(HANDLE) OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_CHILD, hItem); 4220 auto hFirstItem = cast(HANDLE) OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_CHILD, hItem);
4065 select (hFirstItem, tvItem); 4221 select (hFirstItem, tvItem);
4066 hItem = cast(HANDLE) OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_NEXT, hItem); 4222 hItem = cast(HANDLE) OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_NEXT, hItem);
4067 } 4223 }
4224 }
4225
4226 /**
4227 * Selects an item in the receiver. If the item was already
4228 * selected, it remains selected.
4229 *
4230 * @param item the item to be selected
4231 *
4232 * @exception IllegalArgumentException <ul>
4233 * <li>ERROR_NULL_ARGUMENT - if the item is null</li>
4234 * <li>ERROR_INVALID_ARGUMENT - if the item has been disposed</li>
4235 * </ul>
4236 * @exception DWTException <ul>
4237 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
4238 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
4239 * </ul>
4240 *
4241 * @since 3.4
4242 */
4243 public void select (TreeItem item) {
4244 checkWidget ();
4245 if (item is null) error (DWT.ERROR_NULL_ARGUMENT);
4246 if (item.isDisposed ()) error (DWT.ERROR_INVALID_ARGUMENT);
4247 if ((style & DWT.SINGLE) !is 0) {
4248 auto hItem = item.handle;
4249 int state = 0;
4250 static if (OS.IsWinCE) {
4251 TVITEM tvItem;
4252 tvItem.hItem = hItem;
4253 tvItem.mask = OS.TVIF_STATE;
4254 OS.SendMessage (handle, OS.TVM_GETITEM, 0, cast(int)&tvItem);
4255 state = tvItem.state;
4256 } else {
4257 state = OS.SendMessage (handle, OS.TVM_GETITEMSTATE, cast(int)&hItem, OS.TVIS_SELECTED);
4258 }
4259 if ((state & OS.TVIS_SELECTED) !is 0) return;
4260 /*
4261 * Feature in Windows. When an item is selected with
4262 * TVM_SELECTITEM and TVGN_CARET, the tree expands and
4263 * scrolls to show the new selected item. Unfortunately,
4264 * there is no other way in Windows to set the focus
4265 * and select an item. The fix is to save the current
4266 * scroll bar positions, turn off redraw, select the item,
4267 * then scroll back to the original position and redraw
4268 * the entire tree.
4269 */
4270 SCROLLINFO* hInfo = null;
4271 int bits = OS.GetWindowLong (handle, OS.GWL_STYLE);
4272 if ((bits & (OS.TVS_NOHSCROLL | OS.TVS_NOSCROLL)) is 0) {
4273 hInfo = new SCROLLINFO ();
4274 hInfo.cbSize = SCROLLINFO.sizeof;
4275 hInfo.fMask = OS.SIF_ALL;
4276 OS.GetScrollInfo (handle, OS.SB_HORZ, hInfo);
4277 }
4278 SCROLLINFO vInfo;
4279 vInfo.cbSize = SCROLLINFO.sizeof;
4280 vInfo.fMask = OS.SIF_ALL;
4281 OS.GetScrollInfo (handle, OS.SB_VERT, &vInfo);
4282 bool redraw = drawCount is 0 && OS.IsWindowVisible (handle);
4283 if (redraw) {
4284 OS.UpdateWindow (handle);
4285 OS.DefWindowProc (handle, OS.WM_SETREDRAW, 0, 0);
4286 }
4287 setSelection (item);
4288 if (hInfo !is null) {
4289 int /*long*/ hThumb = OS.MAKELPARAM (OS.SB_THUMBPOSITION, hInfo.nPos);
4290 OS.SendMessage (handle, OS.WM_HSCROLL, hThumb, 0);
4291 }
4292 int /*long*/ vThumb = OS.MAKELPARAM (OS.SB_THUMBPOSITION, vInfo.nPos);
4293 OS.SendMessage (handle, OS.WM_VSCROLL, vThumb, 0);
4294 if (redraw) {
4295 OS.DefWindowProc (handle, OS.WM_SETREDRAW, 1, 0);
4296 OS.InvalidateRect (handle, null, true);
4297 if ((style & DWT.DOUBLE_BUFFERED) is 0) {
4298 int oldStyle = style;
4299 style |= DWT.DOUBLE_BUFFERED;
4300 OS.UpdateWindow (handle);
4301 style = oldStyle;
4302 }
4303 }
4304 return;
4305 }
4306 TVITEM tvItem;
4307 tvItem.mask = OS.TVIF_HANDLE | OS.TVIF_STATE;
4308 tvItem.stateMask = OS.TVIS_SELECTED;
4309 tvItem.state = OS.TVIS_SELECTED;
4310 tvItem.hItem = item.handle;
4311 OS.SendMessage (handle, OS.TVM_SETITEM, 0, cast(int)&tvItem);
4068 } 4312 }
4069 4313
4070 /** 4314 /**
4071 * Selects all of the items in the receiver. 4315 * Selects all of the items in the receiver.
4072 * <p> 4316 * <p>
4083 if ((style & DWT.SINGLE) !is 0) return; 4327 if ((style & DWT.SINGLE) !is 0) return;
4084 TVITEM tvItem; 4328 TVITEM tvItem;
4085 tvItem.mask = OS.TVIF_HANDLE | OS.TVIF_STATE; 4329 tvItem.mask = OS.TVIF_HANDLE | OS.TVIF_STATE;
4086 tvItem.state = OS.TVIS_SELECTED; 4330 tvItem.state = OS.TVIS_SELECTED;
4087 tvItem.stateMask = OS.TVIS_SELECTED; 4331 tvItem.stateMask = OS.TVIS_SELECTED;
4088 int oldProc = OS.GetWindowLong (handle, OS.GWL_WNDPROC); 4332 int /*long*/ oldProc = OS.GetWindowLongPtr (handle, OS.GWLP_WNDPROC);
4089 OS.SetWindowLong (handle, OS.GWL_WNDPROC, cast(int) TreeProc); 4333 OS.SetWindowLongPtr (handle, OS.GWLP_WNDPROC, cast(LONG_PTR)TreeProc);
4090 if ((style & DWT.VIRTUAL) !is 0) { 4334 if ((style & DWT.VIRTUAL) !is 0) {
4091 HANDLE hItem = cast(HANDLE) OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_ROOT, 0); 4335 HANDLE hItem = cast(HANDLE) OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_ROOT, 0);
4092 select (hItem, &tvItem); 4336 select (hItem, &tvItem);
4093 } else { 4337 } else {
4094 for (int i=0; i<items.length; i++) { 4338 for (int i=0; i<items.length; i++) {
4097 tvItem.hItem = item.handle; 4341 tvItem.hItem = item.handle;
4098 OS.SendMessage (handle, OS.TVM_SETITEM, 0, &tvItem); 4342 OS.SendMessage (handle, OS.TVM_SETITEM, 0, &tvItem);
4099 } 4343 }
4100 } 4344 }
4101 } 4345 }
4102 OS.SetWindowLong (handle, OS.GWL_WNDPROC, oldProc); 4346 OS.SetWindowLongPtr (handle, OS.GWLP_WNDPROC, oldProc);
4347 }
4348
4349 Event sendEraseItemEvent (TreeItem item, NMTTCUSTOMDRAW* nmcd, int column, RECT* cellRect) {
4350 int nSavedDC = OS.SaveDC (nmcd.nmcd.hdc);
4351 RECT* insetRect = toolTipInset (cellRect);
4352 OS.SetWindowOrgEx (nmcd.nmcd.hdc, insetRect.left, insetRect.top, null);
4353 GCData data = new GCData ();
4354 data.device = display;
4355 data.foreground = OS.GetTextColor (nmcd.nmcd.hdc);
4356 data.background = OS.GetBkColor (nmcd.nmcd.hdc);
4357 data.font = item.getFont (column);
4358 data.uiState = OS.SendMessage (handle, OS.WM_QUERYUISTATE, 0, 0);
4359 GC gc = GC.win32_new (nmcd.nmcd.hdc, data);
4360 Event event = new Event ();
4361 event.item = item;
4362 event.index = column;
4363 event.gc = gc;
4364 event.detail |= DWT.FOREGROUND;
4365 event.x = cellRect.left;
4366 event.y = cellRect.top;
4367 event.width = cellRect.right - cellRect.left;
4368 event.height = cellRect.bottom - cellRect.top;
4369 //gc.setClipping (event.x, event.y, event.width, event.height);
4370 sendEvent (DWT.EraseItem, event);
4371 event.gc = null;
4372 //int newTextClr = data.foreground;
4373 gc.dispose ();
4374 OS.RestoreDC (nmcd.nmcd.hdc, nSavedDC);
4375 return event;
4376 }
4377
4378 Event sendMeasureItemEvent (TreeItem item, int index, HDC hDC) {
4379 RECT itemRect = item.getBounds (index, true, true, false, false, false, hDC);
4380 int nSavedDC = OS.SaveDC (hDC);
4381 GCData data = new GCData ();
4382 data.device = display;
4383 data.font = item.getFont (index);
4384 GC gc = GC.win32_new (hDC, data);
4385 Event event = new Event ();
4386 event.item = item;
4387 event.gc = gc;
4388 event.index = index;
4389 event.x = itemRect.left;
4390 event.y = itemRect.top;
4391 event.width = itemRect.right - itemRect.left;
4392 event.height = itemRect.bottom - itemRect.top;
4393 sendEvent (DWT.MeasureItem, event);
4394 event.gc = null;
4395 gc.dispose ();
4396 OS.RestoreDC (hDC, nSavedDC);
4397 if (isDisposed () || item.isDisposed ()) return null;
4398 if (hwndHeader !is null) {
4399 if (columnCount is 0) {
4400 if (event.x + event.width > scrollWidth) {
4401 setScrollWidth (scrollWidth = event.x + event.width);
4402 }
4403 }
4404 }
4405 if (event.height > getItemHeight ()) setItemHeight (event.height);
4406 return event;
4407 }
4408
4409 Event sendPaintItemEvent (TreeItem item, NMTTCUSTOMDRAW* nmcd, int column, RECT* itemRect) {
4410 int nSavedDC = OS.SaveDC (nmcd.nmcd.hdc);
4411 RECT* insetRect = toolTipInset (itemRect);
4412 OS.SetWindowOrgEx (nmcd.nmcd.hdc, insetRect.left, insetRect.top, null);
4413 GCData data = new GCData ();
4414 data.device = display;
4415 data.font = item.getFont (column);
4416 data.foreground = OS.GetTextColor (nmcd.nmcd.hdc);
4417 data.background = OS.GetBkColor (nmcd.nmcd.hdc);
4418 data.uiState = OS.SendMessage (handle, OS.WM_QUERYUISTATE, 0, 0);
4419 GC gc = GC.win32_new (nmcd.nmcd.hdc, data);
4420 Event event = new Event ();
4421 event.item = item;
4422 event.index = column;
4423 event.gc = gc;
4424 event.detail |= DWT.FOREGROUND;
4425 event.x = itemRect.left;
4426 event.y = itemRect.top;
4427 event.width = itemRect.right - itemRect.left;
4428 event.height = itemRect.bottom - itemRect.top;
4429 //gc.setClipping (cellRect.left, cellRect.top, cellWidth, cellHeight);
4430 sendEvent (DWT.PaintItem, event);
4431 event.gc = null;
4432 gc.dispose ();
4433 OS.RestoreDC (nmcd.nmcd.hdc, nSavedDC);
4434 return event;
4103 } 4435 }
4104 4436
4105 override void setBackgroundImage (HBITMAP hBitmap) { 4437 override void setBackgroundImage (HBITMAP hBitmap) {
4106 super.setBackgroundImage (hBitmap); 4438 super.setBackgroundImage (hBitmap);
4107 if (hBitmap !is null) { 4439 if (hBitmap !is null) {
4162 * color is set. 4494 * color is set.
4163 */ 4495 */
4164 updateFullSelection (); 4496 updateFullSelection ();
4165 } 4497 }
4166 4498
4167 override void setBounds (int x, int y, int width, int height, int flags) {
4168 /*
4169 * Ensure that the selection is visible when the tree is resized
4170 * from a zero size to a size that can show the selection.
4171 */
4172 bool fixSelection = false;
4173 if ((flags & OS.SWP_NOSIZE) is 0 && (width !is 0 || height !is 0)) {
4174 if (OS.SendMessage (handle, OS.TVM_GETVISIBLECOUNT, 0, 0) is 0) {
4175 fixSelection = true;
4176 }
4177 }
4178 super.setBounds (x, y, width, height, flags);
4179 if (fixSelection) {
4180 HANDLE hItem = cast(HANDLE) OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_CARET, 0);
4181 if (hItem !is null) showItem (hItem);
4182 }
4183 }
4184
4185 override void setCursor () { 4499 override void setCursor () {
4186 /* 4500 /*
4187 * Bug in Windows. Under certain circumstances, when WM_SETCURSOR 4501 * Bug in Windows. Under certain circumstances, when WM_SETCURSOR
4188 * is sent from SendMessage(), Windows GP's in the window proc for 4502 * is sent from SendMessage(), Windows GP's in the window proc for
4189 * the tree. The fix is to avoid calling the tree window proc and 4503 * the tree. The fix is to avoid calling the tree window proc and
4222 * @since 3.2 4536 * @since 3.2
4223 */ 4537 */
4224 public void setColumnOrder (int [] order) { 4538 public void setColumnOrder (int [] order) {
4225 checkWidget (); 4539 checkWidget ();
4226 if (order is null) error (DWT.ERROR_NULL_ARGUMENT); 4540 if (order is null) error (DWT.ERROR_NULL_ARGUMENT);
4227 int count = 0; 4541 if (columnCount is 0) {
4228 if (hwndHeader !is null) {
4229 count = OS.SendMessage (hwndHeader, OS.HDM_GETITEMCOUNT, 0, 0);
4230 }
4231 if (count is 0) {
4232 if (order.length !is 0) error (DWT.ERROR_INVALID_ARGUMENT); 4542 if (order.length !is 0) error (DWT.ERROR_INVALID_ARGUMENT);
4233 return; 4543 return;
4234 } 4544 }
4235 if (order.length !is count) error (DWT.ERROR_INVALID_ARGUMENT); 4545 if (order.length !is columnCount) error (DWT.ERROR_INVALID_ARGUMENT);
4236 int [] oldOrder = new int [count]; 4546 int [] oldOrder = new int [columnCount];
4237 OS.SendMessage (hwndHeader, OS.HDM_GETORDERARRAY, count, oldOrder.ptr); 4547 OS.SendMessage (hwndHeader, OS.HDM_GETORDERARRAY, columnCount, oldOrder.ptr);
4238 bool reorder = false; 4548 bool reorder = false;
4239 bool [] seen = new bool [count]; 4549 bool [] seen = new bool [columnCount];
4240 for (int i=0; i<order.length; i++) { 4550 for (int i=0; i<order.length; i++) {
4241 int index = order [i]; 4551 int index = order [i];
4242 if (index < 0 || index >= count) error (DWT.ERROR_INVALID_RANGE); 4552 if (index < 0 || index >= columnCount) error (DWT.ERROR_INVALID_RANGE);
4243 if (seen [index]) error (DWT.ERROR_INVALID_ARGUMENT); 4553 if (seen [index]) error (DWT.ERROR_INVALID_ARGUMENT);
4244 seen [index] = true; 4554 seen [index] = true;
4245 if (index !is oldOrder [i]) reorder = true; 4555 if (index !is oldOrder [i]) reorder = true;
4246 } 4556 }
4247 if (reorder) { 4557 if (reorder) {
4248 RECT [] oldRects = new RECT [count]; 4558 RECT [] oldRects = new RECT [columnCount];
4249 for (int i=0; i<count; i++) { 4559 for (int i=0; i<columnCount; i++) {
4250 //oldRects [i] = new RECT (); 4560 //oldRects [i] = new RECT ();
4251 OS.SendMessage (hwndHeader, OS.HDM_GETITEMRECT, i, & oldRects [i]); 4561 OS.SendMessage (hwndHeader, OS.HDM_GETITEMRECT, i, & oldRects [i]);
4252 } 4562 }
4253 OS.SendMessage (hwndHeader, OS.HDM_SETORDERARRAY, order.length, order.ptr); 4563 OS.SendMessage (hwndHeader, OS.HDM_SETORDERARRAY, order.length, order.ptr);
4254 OS.InvalidateRect (handle, null, true); 4564 OS.InvalidateRect (handle, null, true);
4255 updateImageList (); 4565 updateImageList ();
4256 TreeColumn [] newColumns = new TreeColumn [count]; 4566 TreeColumn [] newColumns = new TreeColumn [columnCount];
4257 System.arraycopy (columns, 0, newColumns, 0, count); 4567 System.arraycopy (columns, 0, newColumns, 0, columnCount);
4258 RECT newRect; 4568 RECT newRect;
4259 for (int i=0; i<count; i++) { 4569 for (int i=0; i<columnCount; i++) {
4260 TreeColumn column = newColumns [i]; 4570 TreeColumn column = newColumns [i];
4261 if (!column.isDisposed ()) { 4571 if (!column.isDisposed ()) {
4262 OS.SendMessage (hwndHeader, OS.HDM_GETITEMRECT, i, &newRect); 4572 OS.SendMessage (hwndHeader, OS.HDM_GETITEMRECT, i, &newRect);
4263 if (newRect.left !is oldRects [i].left) { 4573 if (newRect.left !is oldRects [i].left) {
4264 column.updateToolTip (i); 4574 column.updateToolTip (i);
4451 TVINSERTSTRUCT tvInsert; 4761 TVINSERTSTRUCT tvInsert;
4452 tvInsert.hInsertAfter = cast(HANDLE) OS.TVI_FIRST; 4762 tvInsert.hInsertAfter = cast(HANDLE) OS.TVI_FIRST;
4453 hItem = cast(HANDLE) OS.SendMessage (handle, OS.TVM_INSERTITEM, 0, &tvInsert); 4763 hItem = cast(HANDLE) OS.SendMessage (handle, OS.TVM_INSERTITEM, 0, &tvInsert);
4454 } 4764 }
4455 OS.DefWindowProc (handle, OS.WM_SETREDRAW, 1, 0); 4765 OS.DefWindowProc (handle, OS.WM_SETREDRAW, 1, 0);
4766 updateScrollBar ();
4456 } 4767 }
4457 } 4768 }
4458 super.setRedraw (redraw); 4769 super.setRedraw (redraw);
4459 if (!redraw) { 4770 if (!redraw) {
4460 if (drawCount is 1) OS.DefWindowProc (handle, OS.WM_SETREDRAW, 0, 0); 4771 if (drawCount is 1) OS.DefWindowProc (handle, OS.WM_SETREDRAW, 0, 0);
4468 4779
4469 void setScrollWidth () { 4780 void setScrollWidth () {
4470 if (hwndHeader is null || hwndParent is null) return; 4781 if (hwndHeader is null || hwndParent is null) return;
4471 int width = 0; 4782 int width = 0;
4472 HDITEM hdItem; 4783 HDITEM hdItem;
4473 int count = OS.SendMessage (hwndHeader, OS.HDM_GETITEMCOUNT, 0, 0); 4784 for (int i=0; i<columnCount; i++) {
4474 for (int i=0; i<count; i++) {
4475 hdItem.mask = OS.HDI_WIDTH; 4785 hdItem.mask = OS.HDI_WIDTH;
4476 OS.SendMessage (hwndHeader, OS.HDM_GETITEM, i, &hdItem); 4786 OS.SendMessage (hwndHeader, OS.HDM_GETITEM, i, &hdItem);
4477 width += hdItem.cxy; 4787 width += hdItem.cxy;
4478 } 4788 }
4479 setScrollWidth (Math.max (scrollWidth, width)); 4789 setScrollWidth (Math.max (scrollWidth, width));
4486 int left = 0; 4796 int left = 0;
4487 RECT rect; 4797 RECT rect;
4488 SCROLLINFO info; 4798 SCROLLINFO info;
4489 info.cbSize = SCROLLINFO.sizeof; 4799 info.cbSize = SCROLLINFO.sizeof;
4490 info.fMask = OS.SIF_RANGE | OS.SIF_PAGE; 4800 info.fMask = OS.SIF_RANGE | OS.SIF_PAGE;
4491 int count = OS.SendMessage (hwndHeader, OS.HDM_GETITEMCOUNT, 0, 0); 4801 if (columnCount is 0 && width is 0) {
4492 if (count is 0 && width is 0) {
4493 OS.GetScrollInfo (hwndParent, OS.SB_HORZ, &info); 4802 OS.GetScrollInfo (hwndParent, OS.SB_HORZ, &info);
4494 info.nPage = info.nMax + 1; 4803 info.nPage = info.nMax + 1;
4495 OS.SetScrollInfo (hwndParent, OS.SB_HORZ, &info, true); 4804 OS.SetScrollInfo (hwndParent, OS.SB_HORZ, &info, true);
4496 OS.GetScrollInfo (hwndParent, OS.SB_VERT, &info); 4805 OS.GetScrollInfo (hwndParent, OS.SB_VERT, &info);
4497 info.nPage = info.nMax + 1; 4806 info.nPage = info.nMax + 1;
4498 OS.SetScrollInfo (hwndParent, OS.SB_VERT, &info, true); 4807 OS.SetScrollInfo (hwndParent, OS.SB_VERT, &info, true);
4499 } else { 4808 } else {
4500 OS.GetClientRect (hwndParent, &rect); 4809 if ((style & DWT.H_SCROLL) !is 0) {
4501 OS.GetScrollInfo (hwndParent, OS.SB_HORZ, &info); 4810 OS.GetClientRect (hwndParent, &rect);
4502 info.nMax = width; 4811 OS.GetScrollInfo (hwndParent, OS.SB_HORZ, &info);
4503 info.nPage = rect.right - rect.left + 1; 4812 info.nMax = width;
4504 OS.SetScrollInfo (hwndParent, OS.SB_HORZ, &info, true); 4813 info.nPage = rect.right - rect.left + 1;
4505 info.fMask = OS.SIF_POS; 4814 OS.SetScrollInfo (hwndParent, OS.SB_HORZ, &info, true);
4506 OS.GetScrollInfo (hwndParent, OS.SB_HORZ, &info); 4815 info.fMask = OS.SIF_POS;
4507 left = info.nPos; 4816 OS.GetScrollInfo (hwndParent, OS.SB_HORZ, &info);
4817 left = info.nPos;
4818 }
4508 } 4819 }
4509 if (horizontalBar !is null) { 4820 if (horizontalBar !is null) {
4510 horizontalBar.setIncrement (INCREMENT); 4821 horizontalBar.setIncrement (INCREMENT);
4511 horizontalBar.setPageIncrement (info.nPage); 4822 horizontalBar.setPageIncrement (info.nPage);
4512 } 4823 }
4518 playout.pwpos = &pos; 4829 playout.pwpos = &pos;
4519 OS.SendMessage (hwndHeader, OS.HDM_LAYOUT, 0, &playout); 4830 OS.SendMessage (hwndHeader, OS.HDM_LAYOUT, 0, &playout);
4520 SetWindowPos (hwndHeader, cast(HWND)OS.HWND_TOP, pos.x - left, pos.y, pos.cx + left, pos.cy, OS.SWP_NOACTIVATE); 4831 SetWindowPos (hwndHeader, cast(HWND)OS.HWND_TOP, pos.x - left, pos.y, pos.cx + left, pos.cy, OS.SWP_NOACTIVATE);
4521 int bits = OS.GetWindowLong (handle, OS.GWL_EXSTYLE); 4832 int bits = OS.GetWindowLong (handle, OS.GWL_EXSTYLE);
4522 int b = (bits & OS.WS_EX_CLIENTEDGE) !is 0 ? OS.GetSystemMetrics (OS.SM_CXEDGE) : 0; 4833 int b = (bits & OS.WS_EX_CLIENTEDGE) !is 0 ? OS.GetSystemMetrics (OS.SM_CXEDGE) : 0;
4523 int w = pos.cx + (count is 0 && width is 0 ? 0 : OS.GetSystemMetrics (OS.SM_CXVSCROLL)); 4834 int w = pos.cx + (columnCount is 0 && width is 0 ? 0 : OS.GetSystemMetrics (OS.SM_CXVSCROLL));
4524 int h = rect.bottom - rect.top - pos.cy; 4835 int h = rect.bottom - rect.top - pos.cy;
4525 bool oldIgnore = ignoreResize; 4836 bool oldIgnore = ignoreResize;
4526 ignoreResize = true; 4837 ignoreResize = true;
4527 SetWindowPos (handle, null, pos.x - left - b, pos.y + pos.cy - b, w + left + b * 2, h + b * 2, OS.SWP_NOACTIVATE | OS.SWP_NOZORDER); 4838 SetWindowPos (handle, null, pos.x - left - b, pos.y + pos.cy - b, w + left + b * 2, h + b * 2, OS.SWP_NOACTIVATE | OS.SWP_NOZORDER);
4528 ignoreResize = oldIgnore; 4839 ignoreResize = oldIgnore;
4639 ignoreSelect = true; 4950 ignoreSelect = true;
4640 OS.SendMessage (handle, OS.TVM_SELECTITEM, OS.TVGN_CARET, hNewItem); 4951 OS.SendMessage (handle, OS.TVM_SELECTITEM, OS.TVGN_CARET, hNewItem);
4641 ignoreSelect = false; 4952 ignoreSelect = false;
4642 if (OS.SendMessage (handle, OS.TVM_GETVISIBLECOUNT, 0, 0) is 0) { 4953 if (OS.SendMessage (handle, OS.TVM_GETVISIBLECOUNT, 0, 0) is 0) {
4643 OS.SendMessage (handle, OS.TVM_SELECTITEM, OS.TVGN_FIRSTVISIBLE, hNewItem); 4954 OS.SendMessage (handle, OS.TVM_SELECTITEM, OS.TVGN_FIRSTVISIBLE, hNewItem);
4644 int hParent = OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_PARENT, hNewItem); 4955 int /*long*/ hParent = OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_PARENT, hNewItem);
4645 if (hParent is 0) OS.SendMessage (handle, OS.WM_HSCROLL, OS.SB_TOP, 0); 4956 if (hParent is 0) OS.SendMessage (handle, OS.WM_HSCROLL, OS.SB_TOP, 0);
4646 } 4957 }
4647 if (fixScroll) { 4958 if (fixScroll) {
4648 OS.DefWindowProc (handle, OS.WM_SETREDRAW, 1, 0); 4959 OS.DefWindowProc (handle, OS.WM_SETREDRAW, 1, 0);
4649 OS.SendMessage (handle, OS.WM_SETREDRAW, 0, 0); 4960 OS.SendMessage (handle, OS.WM_SETREDRAW, 0, 0);
4670 4981
4671 /* Select/deselect the rest of the items */ 4982 /* Select/deselect the rest of the items */
4672 TVITEM tvItem; 4983 TVITEM tvItem;
4673 tvItem.mask = OS.TVIF_HANDLE | OS.TVIF_STATE; 4984 tvItem.mask = OS.TVIF_HANDLE | OS.TVIF_STATE;
4674 tvItem.stateMask = OS.TVIS_SELECTED; 4985 tvItem.stateMask = OS.TVIS_SELECTED;
4675 int oldProc = OS.GetWindowLong (handle, OS.GWL_WNDPROC); 4986 int /*long*/ oldProc = OS.GetWindowLongPtr (handle, OS.GWLP_WNDPROC);
4676 OS.SetWindowLong (handle, OS.GWL_WNDPROC, cast(int) TreeProc); 4987 OS.SetWindowLongPtr (handle, OS.GWLP_WNDPROC, cast(LONG_PTR)TreeProc);
4677 if ((style & DWT.VIRTUAL) !is 0) { 4988 if ((style & DWT.VIRTUAL) !is 0) {
4678 HANDLE hItem = cast(HANDLE) OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_ROOT, 0); 4989 HANDLE hItem = cast(HANDLE) OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_ROOT, 0);
4679 setSelection (hItem, &tvItem, items); 4990 setSelection (hItem, &tvItem, items);
4680 } else { 4991 } else {
4681 for (int i=0; i<this.items.length; i++) { 4992 for (int i=0; i<this.items.length; i++) {
4700 } 5011 }
4701 } 5012 }
4702 } 5013 }
4703 } 5014 }
4704 } 5015 }
4705 OS.SetWindowLong (handle, OS.GWL_WNDPROC, oldProc); 5016 OS.SetWindowLongPtr (handle, OS.GWLP_WNDPROC, oldProc);
4706 } 5017 }
4707 5018
4708 /** 5019 /**
4709 * Sets the column used by the sort indicator for the receiver. A null 5020 * Sets the column used by the sort indicator for the receiver. A null
4710 * value will clear the sort indicator. The current sort column is cleared 5021 * value will clear the sort indicator. The current sort column is cleared
4832 OS.SendMessage (handle, OS.WM_SETREDRAW, 0, 0); 5143 OS.SendMessage (handle, OS.WM_SETREDRAW, 0, 0);
4833 } 5144 }
4834 } else { 5145 } else {
4835 bool scroll = true; 5146 bool scroll = true;
4836 RECT itemRect; 5147 RECT itemRect;
4837 itemRect.left = cast(int) hItem; 5148 if (OS.TreeView_GetItemRect (handle, hItem, &itemRect, true)) {
4838 if (OS.SendMessage (handle, OS.TVM_GETITEMRECT, 1, &itemRect) !is 0) {
4839 forceResize (); 5149 forceResize ();
4840 RECT rect; 5150 RECT rect;
4841 OS.GetClientRect (handle, &rect); 5151 OS.GetClientRect (handle, &rect);
4842 POINT pt; 5152 POINT pt;
4843 pt.x = itemRect.left; 5153 pt.x = itemRect.left;
4860 } 5170 }
4861 } 5171 }
4862 } 5172 }
4863 if (hwndParent !is null) { 5173 if (hwndParent !is null) {
4864 RECT itemRect; 5174 RECT itemRect;
4865 itemRect.left = cast(int) hItem; 5175 if (OS.TreeView_GetItemRect (handle, hItem, &itemRect, true)) {
4866 if (OS.SendMessage (handle, OS.TVM_GETITEMRECT, 1, &itemRect) !is 0) {
4867 forceResize (); 5176 forceResize ();
4868 RECT rect; 5177 RECT rect;
4869 OS.GetClientRect (hwndParent, &rect); 5178 OS.GetClientRect (hwndParent, &rect);
4870 OS.MapWindowPoints (hwndParent, handle, cast(POINT*) &rect, 2); 5179 OS.MapWindowPoints (hwndParent, handle, cast(POINT*) &rect, 2);
4871 POINT pt; 5180 POINT pt;
4910 if (column is null) error (DWT.ERROR_NULL_ARGUMENT); 5219 if (column is null) error (DWT.ERROR_NULL_ARGUMENT);
4911 if (column.isDisposed ()) error(DWT.ERROR_INVALID_ARGUMENT); 5220 if (column.isDisposed ()) error(DWT.ERROR_INVALID_ARGUMENT);
4912 if (column.parent !is this) return; 5221 if (column.parent !is this) return;
4913 int index = indexOf (column); 5222 int index = indexOf (column);
4914 if (index is -1) return; 5223 if (index is -1) return;
4915 int count = OS.SendMessage (hwndHeader, OS.HDM_GETITEMCOUNT, 0, 0); 5224 if (0 <= index && index < columnCount) {
4916 if (0 <= index && index < count) { 5225 forceResize ();
4917 if (hwndParent !is null) { 5226 RECT rect;
4918 forceResize (); 5227 OS.GetClientRect (hwndParent, &rect);
4919 RECT rect; 5228 OS.MapWindowPoints (hwndParent, handle, cast(POINT*) &rect, 2);
4920 OS.GetClientRect (hwndParent, &rect); 5229 RECT headerRect;
4921 OS.MapWindowPoints (hwndParent, handle, cast(POINT*) &rect, 2); 5230 OS.SendMessage (hwndHeader, OS.HDM_GETITEMRECT, index, &headerRect);
4922 RECT headerRect; 5231 bool scroll = headerRect.left < rect.left;
4923 OS.SendMessage (hwndHeader, OS.HDM_GETITEMRECT, index, &headerRect); 5232 if (!scroll) {
4924 bool scroll = headerRect.left < rect.left; 5233 int width = Math.min (rect.right - rect.left, headerRect.right - headerRect.left);
4925 if (!scroll) { 5234 scroll = headerRect.left + width > rect.right;
4926 int width = Math.min (rect.right - rect.left, headerRect.right - headerRect.left); 5235 }
4927 scroll = headerRect.left + width > rect.right; 5236 if (scroll) {
4928 } 5237 SCROLLINFO info;
4929 if (scroll) { 5238 info.cbSize = SCROLLINFO.sizeof;
4930 SCROLLINFO info; 5239 info.fMask = OS.SIF_POS;
4931 info.cbSize = SCROLLINFO.sizeof; 5240 info.nPos = Math.max (0, headerRect.left - Tree.INSET / 2);
4932 info.fMask = OS.SIF_POS; 5241 OS.SetScrollInfo (hwndParent, OS.SB_HORZ, &info, true);
4933 info.nPos = Math.max (0, headerRect.left - Tree.INSET / 2); 5242 setScrollWidth ();
4934 OS.SetScrollInfo (hwndParent, OS.SB_HORZ, &info, true);
4935 setScrollWidth ();
4936 }
4937 } 5243 }
4938 } 5244 }
4939 } 5245 }
4940 5246
4941 /** 5247 /**
4991 } else { 5297 } else {
4992 state = OS.SendMessage (handle, OS.TVM_GETITEMSTATE, hItem, OS.TVIS_SELECTED); 5298 state = OS.SendMessage (handle, OS.TVM_GETITEMSTATE, hItem, OS.TVIS_SELECTED);
4993 } 5299 }
4994 if ((state & OS.TVIS_SELECTED) is 0) return; 5300 if ((state & OS.TVIS_SELECTED) is 0) return;
4995 } else { 5301 } else {
4996 int oldProc = OS.GetWindowLong (handle, OS.GWL_WNDPROC); 5302 int /*long*/ oldProc = OS.GetWindowLongPtr (handle, OS.GWLP_WNDPROC);
4997 OS.SetWindowLong (handle, OS.GWL_WNDPROC, cast(int) TreeProc); 5303 OS.SetWindowLongPtr (handle, OS.GWLP_WNDPROC, cast(LONG_PTR)TreeProc);
4998 TVITEM tvItem_; 5304 TVITEM tvItem_;
4999 TVITEM* tvItem; 5305 TVITEM* tvItem;
5000 static if (OS.IsWinCE) { 5306 static if (OS.IsWinCE) {
5001 tvItem = &tvItem_; 5307 tvItem = &tvItem_;
5002 tvItem.mask = OS.TVIF_STATE; 5308 tvItem.mask = OS.TVIF_STATE;
5024 } 5330 }
5025 } 5331 }
5026 index++; 5332 index++;
5027 } 5333 }
5028 } 5334 }
5029 OS.SetWindowLong (handle, OS.GWL_WNDPROC, oldProc); 5335 OS.SetWindowLongPtr (handle, OS.GWLP_WNDPROC, oldProc);
5030 } 5336 }
5031 if (hItem !is null) showItem (hItem); 5337 if (hItem !is null) showItem (hItem);
5032 } 5338 }
5033 5339
5034 /*public*/ void sort () { 5340 /*public*/ void sort () {
5059 } 5365 }
5060 5366
5061 override void subclass () { 5367 override void subclass () {
5062 super.subclass (); 5368 super.subclass ();
5063 if (hwndHeader !is null) { 5369 if (hwndHeader !is null) {
5064 OS.SetWindowLong (hwndHeader, OS.GWL_WNDPROC, display.windowProc); 5370 OS.SetWindowLongPtr (hwndHeader, OS.GWLP_WNDPROC, display.windowProc);
5065 } 5371 }
5372 }
5373
5374 RECT* toolTipInset (RECT* rect) {
5375 if (!OS.IsWinCE && OS.WIN32_VERSION >= OS.VERSION (6, 0)) {
5376 RECT* insetRect = new RECT();
5377 OS.SetRect (insetRect, rect.left - 1, rect.top - 1, rect.right + 1, rect.bottom + 1);
5378 return insetRect;
5379 }
5380 return rect;
5381 }
5382
5383 RECT* toolTipRect (RECT* rect) {
5384 RECT* toolRect = new RECT ();
5385 if (!OS.IsWinCE && OS.WIN32_VERSION >= OS.VERSION (6, 0)) {
5386 OS.SetRect (toolRect, rect.left - 1, rect.top - 1, rect.right + 1, rect.bottom + 1);
5387 } else {
5388 OS.SetRect (toolRect, rect.left, rect.top, rect.right, rect.bottom);
5389 int dwStyle = OS.GetWindowLong (itemToolTipHandle, OS.GWL_STYLE);
5390 int dwExStyle = OS.GetWindowLong (itemToolTipHandle, OS.GWL_EXSTYLE);
5391 OS.AdjustWindowRectEx (toolRect, dwStyle, false, dwExStyle);
5392 }
5393 return toolRect;
5066 } 5394 }
5067 5395
5068 override String toolTipText (NMTTDISPINFO* hdr) { 5396 override String toolTipText (NMTTDISPINFO* hdr) {
5069 auto hwndToolTip = cast(HWND) OS.SendMessage (handle, OS.TVM_GETTOOLTIPS, 0, 0); 5397 auto hwndToolTip = cast(HWND) OS.SendMessage (handle, OS.TVM_GETTOOLTIPS, 0, 0);
5070 if (hwndToolTip is hdr.hdr.hwndFrom && toolTipText_ !is null) return ""; //$NON-NLS-1$ 5398 if (hwndToolTip is hdr.hdr.hwndFrom && toolTipText_ !is null) return ""; //$NON-NLS-1$
5071 if (headerToolTipHandle is hdr.hdr.hwndFrom) { 5399 if (headerToolTipHandle is hdr.hdr.hwndFrom) {
5072 int count = OS.SendMessage (hwndHeader, OS.HDM_GETITEMCOUNT, 0, 0); 5400 for (int i=0; i<columnCount; i++) {
5073 for (int i=0; i<count; i++) {
5074 TreeColumn column = columns [i]; 5401 TreeColumn column = columns [i];
5075 if (column.id is hdr.hdr.idFrom) return column.toolTipText; 5402 if (column.id is hdr.hdr.idFrom) return column.toolTipText;
5076 } 5403 }
5077 return super.toolTipText (hdr); 5404 return super.toolTipText (hdr);
5078 } 5405 }
5079 if (itemToolTipHandle is hdr.hdr.hwndFrom && hwndHeader !is null) { 5406 if (itemToolTipHandle is hdr.hdr.hwndFrom) {
5080 if (toolTipText_ !is null) return ""; 5407 if (toolTipText_ !is null) return "";
5081 if (!hooks (DWT.EraseItem) && !hooks (DWT.PaintItem)) { 5408 int pos = OS.GetMessagePos ();
5082 int pos = OS.GetMessagePos (); 5409 POINT pt;
5083 POINT pt; 5410 OS.POINTSTOPOINT (pt, pos);
5084 pt.x = cast(short) (pos & 0xFFFF); 5411 OS.ScreenToClient (handle, &pt);
5085 pt.y = cast(short) (pos >> 16); 5412 int index;
5086 OS.ScreenToClient (handle, &pt); 5413 TreeItem item;
5087 TVHITTESTINFO lpht; 5414 RECT cellRect, itemRect;
5088 lpht.pt.x = pt.x; 5415 if (findCell (pt.x, pt.y, item, index, cellRect, itemRect)) {
5089 lpht.pt.y = pt.y; 5416 String text = null;
5090 OS.SendMessage (handle, OS.TVM_HITTEST, 0, &lpht); 5417 if (index is 0) {
5091 if (lpht.hItem !is null) { 5418 text = item.text;
5092 auto hDC = OS.GetDC (handle); 5419 } else {
5093 HFONT oldFont, newFont = cast(HFONT) OS.SendMessage (handle, OS.WM_GETFONT, 0, 0); 5420 String[] strings = item.strings;
5094 if (newFont !is null) oldFont = OS.SelectObject (hDC, newFont); 5421 if (strings !is null) text = strings [index];
5095 RECT rect; 5422 }
5096 OS.GetClientRect (hwndParent, &rect); 5423 //TEMPORARY CODE
5097 OS.MapWindowPoints (hwndParent, handle, cast(POINT*) &rect, 2); 5424 if (!OS.IsWinCE && OS.WIN32_VERSION >= OS.VERSION (6, 0)) {
5098 TreeItem item = _getItem (lpht.hItem); 5425 if (isCustomToolTip ()) text = " ";
5099 String text = null; 5426 }
5100 int index = 0, count = Math.max (1, OS.SendMessage (hwndHeader, OS.HDM_GETITEMCOUNT, 0, 0)); 5427 if (text !is null) return text;
5101 int [] order = new int [count];
5102 OS.SendMessage (hwndHeader, OS.HDM_GETORDERARRAY, count, order.ptr);
5103 while (index < count) {
5104 HFONT hFont = item.cellFont !is null ? item.cellFont [order [index]] : cast(HFONT)-1;
5105 if (hFont is cast(HFONT)-1) hFont = item.font;
5106 if (hFont !is cast(HFONT)-1) hFont = OS.SelectObject (hDC, hFont);
5107 RECT cellRect = item.getBounds (order [index], true, false, true, false, true, hDC);
5108 if (hFont !is cast(HFONT)-1) OS.SelectObject (hDC, hFont);
5109 if (cellRect.left > rect.right) break;
5110 cellRect.right = Math.min (cellRect.right, rect.right);
5111 if (OS.PtInRect (&cellRect, pt)) {
5112 RECT textRect = item.getBounds (order [index], true, false, false, false, false, hDC);
5113 if (textRect.right > cellRect.right) {
5114 if (order [index] is 0) {
5115 text = item.text;
5116 } else {
5117 String[] strings = item.strings;
5118 if (strings !is null) text = strings [order [index]];
5119 }
5120 }
5121 break;
5122 }
5123 index++;
5124 }
5125 if (newFont !is null) OS.SelectObject (hDC, oldFont);
5126 OS.ReleaseDC (handle, hDC);
5127 if (text !is null) return text;
5128 }
5129 } 5428 }
5130 } 5429 }
5131 return super.toolTipText (hdr); 5430 return super.toolTipText (hdr);
5132 } 5431 }
5133 5432
5162 TOOLINFO lpti; 5461 TOOLINFO lpti;
5163 lpti.cbSize = TOOLINFO.sizeof; 5462 lpti.cbSize = TOOLINFO.sizeof;
5164 lpti.uFlags = OS.TTF_SUBCLASS; 5463 lpti.uFlags = OS.TTF_SUBCLASS;
5165 lpti.hwnd = hwndHeader; 5464 lpti.hwnd = hwndHeader;
5166 lpti.lpszText = OS.LPSTR_TEXTCALLBACK; 5465 lpti.lpszText = OS.LPSTR_TEXTCALLBACK;
5167 int count = OS.SendMessage (hwndHeader, OS.HDM_GETITEMCOUNT, 0, 0); 5466 for (int i=0; i<columnCount; i++) {
5168 for (int i=0; i<count; i++) {
5169 TreeColumn column = columns [i]; 5467 TreeColumn column = columns [i];
5170 if (OS.SendMessage (hwndHeader, OS.HDM_GETITEMRECT, i, &rect) !is 0) { 5468 if (OS.SendMessage (hwndHeader, OS.HDM_GETITEMRECT, i, &rect) !is 0) {
5171 lpti.uId = column.id = display.nextToolTipId++; 5469 lpti.uId = column.id = display.nextToolTipId++;
5172 lpti.rect.left = rect.left; 5470 lpti.rect.left = rect.left;
5173 lpti.rect.top = rect.top; 5471 lpti.rect.top = rect.top;
5222 } 5520 }
5223 } 5521 }
5224 5522
5225 void updateScrollBar () { 5523 void updateScrollBar () {
5226 if (hwndParent !is null) { 5524 if (hwndParent !is null) {
5227 int columnCount = OS.SendMessage (hwndHeader, OS.HDM_GETITEMCOUNT, 0, 0);
5228 if (columnCount !is 0 || scrollWidth !is 0) { 5525 if (columnCount !is 0 || scrollWidth !is 0) {
5229 SCROLLINFO info; 5526 SCROLLINFO info;
5230 info.cbSize = SCROLLINFO.sizeof; 5527 info.cbSize = SCROLLINFO.sizeof;
5231 info.fMask = OS.SIF_ALL; 5528 info.fMask = OS.SIF_ALL;
5232 int itemCount = OS.SendMessage (handle, OS.TVM_GETCOUNT, 0, 0); 5529 int itemCount = OS.SendMessage (handle, OS.TVM_GETCOUNT, 0, 0);
5234 OS.GetScrollInfo (hwndParent, OS.SB_VERT, &info); 5531 OS.GetScrollInfo (hwndParent, OS.SB_VERT, &info);
5235 info.nPage = info.nMax + 1; 5532 info.nPage = info.nMax + 1;
5236 OS.SetScrollInfo (hwndParent, OS.SB_VERT, &info, true); 5533 OS.SetScrollInfo (hwndParent, OS.SB_VERT, &info, true);
5237 } else { 5534 } else {
5238 OS.GetScrollInfo (handle, OS.SB_VERT, &info); 5535 OS.GetScrollInfo (handle, OS.SB_VERT, &info);
5239 if (info.nPage is 0) info.nPage = info.nMax + 1; 5536 if (!OS.IsWinCE && OS.WIN32_VERSION >= OS.VERSION(4, 10)) {
5537 if (info.nPage is 0) {
5538 SCROLLBARINFO psbi;
5539 psbi.cbSize = SCROLLBARINFO.sizeof;
5540 OS.GetScrollBarInfo (handle, OS.OBJID_VSCROLL, &psbi);
5541 if ((psbi.rgstate [0] & OS.STATE_SYSTEM_INVISIBLE) !is 0) {
5542 info.nPage = info.nMax + 1;
5543 }
5544 }
5545 }
5240 OS.SetScrollInfo (hwndParent, OS.SB_VERT, &info, true); 5546 OS.SetScrollInfo (hwndParent, OS.SB_VERT, &info, true);
5241 } 5547 }
5242 } 5548 }
5243 } 5549 }
5244 } 5550 }
5245 5551
5246 override void unsubclass () { 5552 override void unsubclass () {
5247 super.unsubclass (); 5553 super.unsubclass ();
5248 if (hwndHeader !is null) { 5554 if (hwndHeader !is null) {
5249 OS.SetWindowLong (hwndHeader, OS.GWL_WNDPROC, cast(int) HeaderProc); 5555 OS.SetWindowLongPtr (hwndHeader, OS.GWLP_WNDPROC, cast(LONG_PTR)HeaderProc);
5250 } 5556 }
5251 } 5557 }
5252 5558
5253 override int widgetStyle () { 5559 override int widgetStyle () {
5254 int bits = super.widgetStyle () | OS.TVS_SHOWSELALWAYS | OS.TVS_LINESATROOT | OS.TVS_HASBUTTONS | OS.TVS_NONEVENHEIGHT; 5560 int bits = super.widgetStyle () | OS.TVS_SHOWSELALWAYS | OS.TVS_LINESATROOT | OS.TVS_HASBUTTONS | OS.TVS_NONEVENHEIGHT;
5255 if (EXPLORER_THEME && !OS.IsWinCE && OS.WIN32_VERSION >= OS.VERSION (6, 0)) { 5561 if (EXPLORER_THEME && !OS.IsWinCE && OS.WIN32_VERSION >= OS.VERSION (6, 0) && OS.IsAppThemed ()) {
5256 bits |= OS.TVS_TRACKSELECT; 5562 bits |= OS.TVS_TRACKSELECT;
5257 if ((style & DWT.FULL_SELECTION) !is 0) bits |= OS.TVS_FULLROWSELECT; 5563 if ((style & DWT.FULL_SELECTION) !is 0) bits |= OS.TVS_FULLROWSELECT;
5258 } else { 5564 } else {
5259 if ((style & DWT.FULL_SELECTION) !is 0) { 5565 if ((style & DWT.FULL_SELECTION) !is 0) {
5260 bits |= OS.TVS_FULLROWSELECT; 5566 bits |= OS.TVS_FULLROWSELECT;
5261 } else { 5567 } else {
5262 bits |= OS.TVS_HASLINES; 5568 bits |= OS.TVS_HASLINES;
5569 }
5570 }
5571 if ((style & (DWT.H_SCROLL | DWT.V_SCROLL)) is 0) {
5572 bits &= ~(OS.WS_HSCROLL | OS.WS_VSCROLL);
5573 bits |= OS.TVS_NOSCROLL;
5574 } else {
5575 if ((style & DWT.H_SCROLL) is 0) {
5576 bits &= ~OS.WS_HSCROLL;
5577 bits |= OS.TVS_NOHSCROLL;
5263 } 5578 }
5264 } 5579 }
5265 // bits |= OS.TVS_NOTOOLTIPS | OS.TVS_DISABLEDRAGDROP; 5580 // bits |= OS.TVS_NOTOOLTIPS | OS.TVS_DISABLEDRAGDROP;
5266 return bits | OS.TVS_DISABLEDRAGDROP; 5581 return bits | OS.TVS_DISABLEDRAGDROP;
5267 } 5582 }
5329 } 5644 }
5330 break; 5645 break;
5331 } 5646 }
5332 case OS.WM_SETCURSOR: { 5647 case OS.WM_SETCURSOR: {
5333 if (cast(HWND)wParam is hwnd) { 5648 if (cast(HWND)wParam is hwnd) {
5334 int hitTest = cast(short) (lParam & 0xFFFF); 5649 int hitTest = cast(short) OS.LOWORD (lParam);
5335 if (hitTest is OS.HTCLIENT) { 5650 if (hitTest is OS.HTCLIENT) {
5336 HDHITTESTINFO pinfo; 5651 HDHITTESTINFO pinfo;
5337 int pos = OS.GetMessagePos (); 5652 int pos = OS.GetMessagePos ();
5338 POINT pt; 5653 POINT pt;
5339 pt.x = cast(short) (pos & 0xFFFF); 5654 OS.POINTSTOPOINT (pt, pos);
5340 pt.y = cast(short) (pos >> 16);
5341 OS.ScreenToClient (hwnd, &pt); 5655 OS.ScreenToClient (hwnd, &pt);
5342 pinfo.pt.x = pt.x; 5656 pinfo.pt.x = pt.x;
5343 pinfo.pt.y = pt.y; 5657 pinfo.pt.y = pt.y;
5344 int columnCount = OS.SendMessage (hwndHeader, OS.HDM_GETITEMCOUNT, 0, 0);
5345 int index = OS.SendMessage (hwndHeader, OS.HDM_HITTEST, 0, &pinfo); 5658 int index = OS.SendMessage (hwndHeader, OS.HDM_HITTEST, 0, &pinfo);
5346 if (0 <= index && index < columnCount && !columns [index].resizable) { 5659 if (0 <= index && index < columnCount && !columns [index].resizable) {
5347 if ((pinfo.flags & (OS.HHT_ONDIVIDER | OS.HHT_ONDIVOPEN)) !is 0) { 5660 if ((pinfo.flags & (OS.HHT_ONDIVIDER | OS.HHT_ONDIVOPEN)) !is 0) {
5348 OS.SetCursor (OS.LoadCursor (null, cast(TCHAR*) OS.IDC_ARROW)); 5661 OS.SetCursor (OS.LoadCursor (null, cast(TCHAR*) OS.IDC_ARROW));
5349 return 1; 5662 return 1;
5365 } 5678 }
5366 case OS.WM_SIZE: { 5679 case OS.WM_SIZE: {
5367 setScrollWidth (); 5680 setScrollWidth ();
5368 if (ignoreResize) return 0; 5681 if (ignoreResize) return 0;
5369 setResizeChildren (false); 5682 setResizeChildren (false);
5370 int code = callWindowProc (hwnd, OS.WM_SIZE, wParam, lParam); 5683 int /*long*/ code = callWindowProc (hwnd, OS.WM_SIZE, wParam, lParam);
5371 sendEvent (DWT.Resize); 5684 sendEvent (DWT.Resize);
5372 if (isDisposed ()) return 0; 5685 if (isDisposed ()) return 0;
5373 if (layout_ !is null) { 5686 if (layout_ !is null) {
5374 markLayout (false, false); 5687 markLayout (false, false);
5375 updateLayout (false, false); 5688 updateLayout (false, false);
5419 * 5732 *
5420 * NOTE: For some reason, this code is only necessary 5733 * NOTE: For some reason, this code is only necessary
5421 * on Windows Vista. 5734 * on Windows Vista.
5422 */ 5735 */
5423 if (!OS.IsWinCE && OS.WIN32_VERSION >= OS.VERSION (6, 0)) { 5736 if (!OS.IsWinCE && OS.WIN32_VERSION >= OS.VERSION (6, 0)) {
5424 if ((wParam & 0xFFFF) is OS.SB_THUMBTRACK) { 5737 if (OS.LOWORD (wParam) is OS.SB_THUMBTRACK) {
5425 info.nPos = info.nTrackPos; 5738 info.nPos = info.nTrackPos;
5426 } 5739 }
5427 } 5740 }
5428 OS.SetScrollInfo (handle, OS.SB_VERT, &info, true); 5741 OS.SetScrollInfo (handle, OS.SB_VERT, &info, true);
5429 int code = OS.SendMessage (handle, OS.WM_VSCROLL, wParam, lParam); 5742 int /*long*/ code = OS.SendMessage (handle, OS.WM_VSCROLL, wParam, lParam);
5430 OS.GetScrollInfo (handle, OS.SB_VERT, &info); 5743 OS.GetScrollInfo (handle, OS.SB_VERT, &info);
5431 OS.SetScrollInfo (hwndParent, OS.SB_VERT, &info, true); 5744 OS.SetScrollInfo (hwndParent, OS.SB_VERT, &info, true);
5432 return code; 5745 return code;
5433 } 5746 }
5434 default: 5747 default:
5435 } 5748 }
5436 return callWindowProc (hwnd, msg, wParam, lParam); 5749 return callWindowProc (hwnd, msg, wParam, lParam);
5750 }
5751 if (msg is Display.DI_GETDRAGIMAGE) {
5752 //TEMPORARY CODE
5753 if (hooks (DWT.EraseItem) || hooks (DWT.PaintItem)) return 0;
5754 /*
5755 * When there is more than one item selected, DI_GETDRAGIMAGE
5756 * returns the item under the cursor. This happens because
5757 * the tree does not have implement multi-select. The fix
5758 * is to disable DI_GETDRAGIMAGE when more than one item is
5759 * selected.
5760 */
5761 if ((style & DWT.MULTI) !is 0) {
5762 if (getSelectionCount () !is 1) return 0;
5763 }
5437 } 5764 }
5438 return super.windowProc (hwnd, msg, wParam, lParam); 5765 return super.windowProc (hwnd, msg, wParam, lParam);
5439 } 5766 }
5440 5767
5441 override LRESULT WM_CHAR (int wParam, int lParam) { 5768 override LRESULT WM_CHAR (int wParam, int lParam) {
5543 if (accessible is null) accessible = new_Accessible (this); 5870 if (accessible is null) accessible = new_Accessible (this);
5544 } 5871 }
5545 return super.WM_GETOBJECT (wParam, lParam); 5872 return super.WM_GETOBJECT (wParam, lParam);
5546 } 5873 }
5547 5874
5548 override LRESULT WM_KEYDOWN (int wParam, int lParam) { 5875 override LRESULT WM_HSCROLL (int wParam, int lParam) {
5876 bool fixScroll = false;
5877 if ((style & DWT.DOUBLE_BUFFERED) !is 0) {
5878 fixScroll = (style & DWT.VIRTUAL) !is 0 || hooks (DWT.EraseItem) || hooks (DWT.PaintItem);
5879 }
5880 if (fixScroll) {
5881 style &= ~DWT.DOUBLE_BUFFERED;
5882 if (explorerTheme) {
5883 OS.SendMessage (handle, OS.TVM_SETEXTENDEDSTYLE, OS.TVS_EX_DOUBLEBUFFER, 0);
5884 }
5885 }
5886 LRESULT result = super.WM_HSCROLL (wParam, lParam);
5887 if (fixScroll) {
5888 style |= DWT.DOUBLE_BUFFERED;
5889 if (explorerTheme) {
5890 OS.SendMessage (handle, OS.TVM_SETEXTENDEDSTYLE, OS.TVS_EX_DOUBLEBUFFER, OS.TVS_EX_DOUBLEBUFFER);
5891 }
5892 }
5893 if (result !is null) return result;
5894 return result;
5895 }
5896
5897 override LRESULT WM_KEYDOWN (int /*long*/ wParam, int /*long*/ lParam) {
5549 LRESULT result = super.WM_KEYDOWN (wParam, lParam); 5898 LRESULT result = super.WM_KEYDOWN (wParam, lParam);
5550 if (result !is null) return result; 5899 if (result !is null) return result;
5551 switch (wParam) { 5900 switch (wParam) {
5552 case OS.VK_SPACE: 5901 case OS.VK_SPACE:
5553 /* 5902 /*
5558 */ 5907 */
5559 return LRESULT.ZERO; 5908 return LRESULT.ZERO;
5560 case OS.VK_ADD: 5909 case OS.VK_ADD:
5561 if (OS.GetKeyState (OS.VK_CONTROL) < 0) { 5910 if (OS.GetKeyState (OS.VK_CONTROL) < 0) {
5562 if (hwndHeader !is null) { 5911 if (hwndHeader !is null) {
5563 int count = OS.SendMessage (hwndHeader, OS.HDM_GETITEMCOUNT, 0, 0); 5912 TreeColumn [] newColumns = new TreeColumn [columnCount];
5564 TreeColumn [] newColumns = new TreeColumn [count]; 5913 System.arraycopy (columns, 0, newColumns, 0, columnCount);
5565 System.arraycopy (columns, 0, newColumns, 0, count); 5914 for (int i=0; i<columnCount; i++) {
5566 for (int i=0; i<count; i++) {
5567 TreeColumn column = newColumns [i]; 5915 TreeColumn column = newColumns [i];
5568 if (!column.isDisposed () && column.getResizable ()) { 5916 if (!column.isDisposed () && column.getResizable ()) {
5569 column.pack (); 5917 column.pack ();
5570 } 5918 }
5571 } 5919 }
5583 if (OS.GetKeyState (OS.VK_SHIFT) < 0) { 5931 if (OS.GetKeyState (OS.VK_SHIFT) < 0) {
5584 HANDLE hItem = cast(HANDLE) OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_CARET, 0); 5932 HANDLE hItem = cast(HANDLE) OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_CARET, 0);
5585 if (hItem !is null) { 5933 if (hItem !is null) {
5586 if (hAnchor is null) hAnchor = hItem; 5934 if (hAnchor is null) hAnchor = hItem;
5587 ignoreSelect = ignoreDeselect = true; 5935 ignoreSelect = ignoreDeselect = true;
5588 int code = callWindowProc (handle, OS.WM_KEYDOWN, wParam, lParam); 5936 int /*long*/ code = callWindowProc (handle, OS.WM_KEYDOWN, wParam, lParam);
5589 ignoreSelect = ignoreDeselect = false; 5937 ignoreSelect = ignoreDeselect = false;
5590 auto hNewItem = cast(HANDLE) OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_CARET, 0); 5938 auto hNewItem = cast(HANDLE) OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_CARET, 0);
5591 TVITEM tvItem; 5939 TVITEM tvItem;
5592 tvItem.mask = OS.TVIF_HANDLE | OS.TVIF_STATE; 5940 tvItem.mask = OS.TVIF_HANDLE | OS.TVIF_STATE;
5593 tvItem.stateMask = OS.TVIS_SELECTED; 5941 tvItem.stateMask = OS.TVIS_SELECTED;
5594 auto hDeselectItem = hItem; 5942 auto hDeselectItem = hItem;
5595 RECT rect1; 5943 RECT rect1;
5596 rect1.left = cast(int)hAnchor; 5944 if (!OS.TreeView_GetItemRect (handle, hAnchor, &rect1, false)) {
5597 OS.SendMessage (handle, OS.TVM_GETITEMRECT, 0, &rect1); 5945 hAnchor = hItem;
5946 OS.TreeView_GetItemRect (handle, hAnchor, &rect1, false);
5947 }
5598 RECT rect2; 5948 RECT rect2;
5599 rect2.left = cast(int)hDeselectItem; 5949 OS.TreeView_GetItemRect (handle, hDeselectItem, &rect2, false);
5600 OS.SendMessage (handle, OS.TVM_GETITEMRECT, 0, &rect2);
5601 int flags = rect1.top < rect2.top ? OS.TVGN_PREVIOUSVISIBLE : OS.TVGN_NEXTVISIBLE; 5950 int flags = rect1.top < rect2.top ? OS.TVGN_PREVIOUSVISIBLE : OS.TVGN_NEXTVISIBLE;
5602 while (hDeselectItem !is hAnchor) { 5951 while (hDeselectItem !is hAnchor) {
5603 tvItem.hItem = hDeselectItem; 5952 tvItem.hItem = hDeselectItem;
5604 OS.SendMessage (handle, OS.TVM_SETITEM, 0, &tvItem); 5953 OS.SendMessage (handle, OS.TVM_SETITEM, 0, &tvItem);
5605 hDeselectItem = cast(HANDLE) OS.SendMessage (handle, OS.TVM_GETNEXTITEM, flags, hDeselectItem); 5954 hDeselectItem = cast(HANDLE) OS.SendMessage (handle, OS.TVM_GETNEXTITEM, flags, hDeselectItem);
5606 } 5955 }
5607 auto hSelectItem = hAnchor; 5956 auto hSelectItem = hAnchor;
5608 rect1.left = cast(int)hNewItem; 5957 OS.TreeView_GetItemRect (handle, hNewItem, &rect1, false);
5609 OS.SendMessage (handle, OS.TVM_GETITEMRECT, 0, &rect1); 5958 OS.TreeView_GetItemRect (handle, hSelectItem, &rect2, false);
5610 rect2.left = cast(int)hSelectItem;
5611 OS.SendMessage (handle, OS.TVM_GETITEMRECT, 0, &rect2);
5612 tvItem.state = OS.TVIS_SELECTED; 5959 tvItem.state = OS.TVIS_SELECTED;
5613 flags = rect1.top < rect2.top ? OS.TVGN_PREVIOUSVISIBLE : OS.TVGN_NEXTVISIBLE; 5960 flags = rect1.top < rect2.top ? OS.TVGN_PREVIOUSVISIBLE : OS.TVGN_NEXTVISIBLE;
5614 while (hSelectItem !is hNewItem) { 5961 while (hSelectItem !is hNewItem) {
5615 tvItem.hItem = hSelectItem; 5962 tvItem.hItem = hSelectItem;
5616 OS.SendMessage (handle, OS.TVM_SETITEM, 0, &tvItem); 5963 OS.SendMessage (handle, OS.TVM_SETITEM, 0, &tvItem);
5659 OS.GetClientRect (handle, &clientRect); 6006 OS.GetClientRect (handle, &clientRect);
5660 hNewItem = cast(HANDLE) OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_FIRSTVISIBLE, 0); 6007 hNewItem = cast(HANDLE) OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_FIRSTVISIBLE, 0);
5661 do { 6008 do {
5662 auto hVisible = cast(HANDLE) OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_NEXTVISIBLE, hNewItem); 6009 auto hVisible = cast(HANDLE) OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_NEXTVISIBLE, hNewItem);
5663 if (hVisible is null) break; 6010 if (hVisible is null) break;
5664 rect.left = cast(int)hVisible; 6011 if (!OS.TreeView_GetItemRect (handle, hVisible, &rect, false)) break;
5665 OS.SendMessage (handle, OS.TVM_GETITEMRECT, 0, &rect);
5666 if (rect.bottom > clientRect.bottom) break; 6012 if (rect.bottom > clientRect.bottom) break;
5667 if ((hNewItem = hVisible) is hItem) { 6013 if ((hNewItem = hVisible) is hItem) {
5668 OS.SendMessage (handle, OS.WM_VSCROLL, OS.SB_PAGEDOWN, 0); 6014 OS.SendMessage (handle, OS.WM_VSCROLL, OS.SB_PAGEDOWN, 0);
5669 } 6015 }
5670 } while (hNewItem !is null); 6016 } while (hNewItem !is null);
5699 tvItem.hItem = hNewItem; 6045 tvItem.hItem = hNewItem;
5700 OS.SendMessage (handle, OS.TVM_SETITEM, 0, &tvItem); 6046 OS.SendMessage (handle, OS.TVM_SETITEM, 0, &tvItem);
5701 } 6047 }
5702 if (redraw) { 6048 if (redraw) {
5703 RECT rect1, rect2; 6049 RECT rect1, rect2;
5704 rect1.left = cast(int) hItem; rect2.left = cast(int) hNewItem; 6050 bool fItemRect = (style & DWT.FULL_SELECTION) is 0;
5705 int fItemRect = (style & DWT.FULL_SELECTION) !is 0 ? 0 : 1; 6051 if (hooks (DWT.EraseItem) || hooks (DWT.PaintItem)) fItemRect = false;
5706 if (hooks (DWT.EraseItem) || hooks (DWT.PaintItem)) fItemRect = 0; 6052 if (!OS.IsWinCE && OS.WIN32_VERSION >= OS.VERSION (6, 0)) fItemRect = false;
5707 if (!OS.IsWinCE && OS.WIN32_VERSION >= OS.VERSION (6, 0)) fItemRect = 0; 6053 OS.TreeView_GetItemRect (handle, hItem, &rect1, fItemRect);
5708 OS.SendMessage (handle, OS.TVM_GETITEMRECT, fItemRect, &rect1); 6054 OS.TreeView_GetItemRect (handle, hNewItem, &rect2, fItemRect);
5709 OS.SendMessage (handle, OS.TVM_GETITEMRECT, fItemRect, &rect2);
5710 OS.DefWindowProc (handle, OS.WM_SETREDRAW, 1, 0); 6055 OS.DefWindowProc (handle, OS.WM_SETREDRAW, 1, 0);
5711 OS.InvalidateRect (handle, &rect1, true); 6056 OS.InvalidateRect (handle, &rect1, true);
5712 OS.InvalidateRect (handle, &rect2, true); 6057 OS.InvalidateRect (handle, &rect2, true);
5713 OS.UpdateWindow (handle); 6058 OS.UpdateWindow (handle);
5714 } 6059 }
5715 return LRESULT.ZERO; 6060 return LRESULT.ZERO;
5716 } 6061 }
5717 } 6062 }
5718 } 6063 }
5719 int code = callWindowProc (handle, OS.WM_KEYDOWN, wParam, lParam); 6064 int /*long*/ code = callWindowProc (handle, OS.WM_KEYDOWN, wParam, lParam);
5720 hAnchor = cast(HANDLE) OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_CARET, 0); 6065 hAnchor = cast(HANDLE) OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_CARET, 0);
5721 return new LRESULT (code); 6066 return new LRESULT (code);
5722 } 6067 }
5723 default: 6068 default:
5724 } 6069 }
5755 return super.WM_KILLFOCUS (wParam, lParam); 6100 return super.WM_KILLFOCUS (wParam, lParam);
5756 } 6101 }
5757 6102
5758 override LRESULT WM_LBUTTONDBLCLK (int wParam, int lParam) { 6103 override LRESULT WM_LBUTTONDBLCLK (int wParam, int lParam) {
5759 TVHITTESTINFO lpht; 6104 TVHITTESTINFO lpht;
5760 lpht.pt.x = cast(short) (lParam & 0xFFFF); 6105 lpht.pt.x = OS.GET_X_LPARAM (lParam);
5761 lpht.pt.y = cast(short) (lParam >> 16); 6106 lpht.pt.y = OS.GET_Y_LPARAM (lParam);
5762 OS.SendMessage (handle, OS.TVM_HITTEST, 0, &lpht); 6107 OS.SendMessage (handle, OS.TVM_HITTEST, 0, &lpht);
5763 if (lpht.hItem !is null) { 6108 if (lpht.hItem !is null) {
5764 if ((style & DWT.CHECK) !is 0) { 6109 if ((style & DWT.CHECK) !is 0) {
5765 if ((lpht.flags & OS.TVHT_ONITEMSTATEICON) !is 0) { 6110 if ((lpht.flags & OS.TVHT_ONITEMSTATEICON) !is 0) {
5766 Display display = this.display; 6111 Display display = this.display;
5805 } 6150 }
5806 } 6151 }
5807 LRESULT result = super.WM_LBUTTONDBLCLK (wParam, lParam); 6152 LRESULT result = super.WM_LBUTTONDBLCLK (wParam, lParam);
5808 if (result is LRESULT.ZERO) return result; 6153 if (result is LRESULT.ZERO) return result;
5809 if (lpht.hItem !is null) { 6154 if (lpht.hItem !is null) {
5810 if ((style & DWT.FULL_SELECTION) !is 0 || (lpht.flags & OS.TVHT_ONITEM) !is 0) { 6155 int flags = OS.TVHT_ONITEM;
6156 if ((style & DWT.FULL_SELECTION) !is 0) {
6157 flags |= OS.TVHT_ONITEMRIGHT | OS.TVHT_ONITEMINDENT;
6158 } else {
6159 if (hooks (DWT.MeasureItem)) {
6160 lpht.flags &= ~(OS.TVHT_ONITEMICON | OS.TVHT_ONITEMLABEL);
6161 if (hitTestSelection (lpht.hItem, lpht.pt.x, lpht.pt.y)) {
6162 lpht.flags |= OS.TVHT_ONITEMICON | OS.TVHT_ONITEMLABEL;
6163 }
6164 }
6165 }
6166 if ((lpht.flags & flags) !is 0) {
5811 Event event = new Event (); 6167 Event event = new Event ();
5812 event.item = _getItem (lpht.hItem); 6168 event.item = _getItem (lpht.hItem);
5813 postEvent (DWT.DefaultSelection, event); 6169 postEvent (DWT.DefaultSelection, event);
5814 } 6170 }
5815 } 6171 }
5823 * issue a selection event. Only items that are selected and visible 6179 * issue a selection event. Only items that are selected and visible
5824 * are cleared. This code also runs in the case when the white space 6180 * are cleared. This code also runs in the case when the white space
5825 * below the last item is selected. 6181 * below the last item is selected.
5826 */ 6182 */
5827 TVHITTESTINFO lpht; 6183 TVHITTESTINFO lpht;
5828 lpht.pt.x = cast(short) (lParam & 0xFFFF); 6184 lpht.pt.x = OS.GET_X_LPARAM (lParam);
5829 lpht.pt.y = cast(short) (lParam >> 16); 6185 lpht.pt.y = OS.GET_Y_LPARAM (lParam);
5830 OS.SendMessage (handle, OS.TVM_HITTEST, 0, &lpht); 6186 OS.SendMessage (handle, OS.TVM_HITTEST, 0, &lpht);
5831 if (lpht.hItem is null || (lpht.flags & OS.TVHT_ONITEMBUTTON) !is 0) { 6187 if (lpht.hItem is null || (lpht.flags & OS.TVHT_ONITEMBUTTON) !is 0) {
5832 Display display = this.display; 6188 Display display = this.display;
5833 display.captureChanged = false; 6189 display.captureChanged = false;
5834 if (!sendMouseEvent (DWT.MouseDown, 1, handle, OS.WM_LBUTTONDOWN, wParam, lParam)) { 6190 if (!sendMouseEvent (DWT.MouseDown, 1, handle, OS.WM_LBUTTONDOWN, wParam, lParam)) {
5836 if (OS.GetCapture () !is handle) OS.SetCapture (handle); 6192 if (OS.GetCapture () !is handle) OS.SetCapture (handle);
5837 } 6193 }
5838 return LRESULT.ZERO; 6194 return LRESULT.ZERO;
5839 } 6195 }
5840 bool fixSelection = false, deselected = false; 6196 bool fixSelection = false, deselected = false;
6197 HANDLE hOldSelection = cast(HANDLE) OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_CARET, 0);
5841 if (lpht.hItem !is null && (style & DWT.MULTI) !is 0) { 6198 if (lpht.hItem !is null && (style & DWT.MULTI) !is 0) {
5842 int hSelection = OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_CARET, 0); 6199 if (hOldSelection !is null) {
5843 if (hSelection !is 0) {
5844 TVITEM tvItem; 6200 TVITEM tvItem;
5845 tvItem.mask = OS.TVIF_HANDLE | OS.TVIF_STATE; 6201 tvItem.mask = OS.TVIF_HANDLE | OS.TVIF_STATE;
5846 tvItem.hItem = lpht.hItem; 6202 tvItem.hItem = lpht.hItem;
5847 OS.SendMessage (handle, OS.TVM_GETITEM, 0, &tvItem); 6203 OS.SendMessage (handle, OS.TVM_GETITEM, 0, &tvItem);
5848 if ((tvItem.state & OS.TVIS_EXPANDED) !is 0) { 6204 if ((tvItem.state & OS.TVIS_EXPANDED) !is 0) {
5849 fixSelection = true; 6205 fixSelection = true;
5850 tvItem.stateMask = OS.TVIS_SELECTED; 6206 tvItem.stateMask = OS.TVIS_SELECTED;
5851 auto hNext = cast(HANDLE) OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_NEXTVISIBLE, lpht.hItem); 6207 auto hNext = cast(HANDLE) OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_NEXTVISIBLE, lpht.hItem);
5852 while (hNext !is null) { 6208 while (hNext !is null) {
6209 if (hNext is hAnchor) hAnchor = null;
5853 tvItem.hItem = hNext; 6210 tvItem.hItem = hNext;
5854 OS.SendMessage (handle, OS.TVM_GETITEM, 0, &tvItem); 6211 OS.SendMessage (handle, OS.TVM_GETITEM, 0, &tvItem);
5855 if ((tvItem.state & OS.TVIS_SELECTED) !is 0) deselected = true; 6212 if ((tvItem.state & OS.TVIS_SELECTED) !is 0) deselected = true;
5856 tvItem.state = 0; 6213 tvItem.state = 0;
5857 OS.SendMessage (handle, OS.TVM_SETITEM, 0, &tvItem); 6214 OS.SendMessage (handle, OS.TVM_SETITEM, 0, &tvItem);
5864 } 6221 }
5865 } 6222 }
5866 } 6223 }
5867 dragStarted = gestureCompleted = false; 6224 dragStarted = gestureCompleted = false;
5868 if (fixSelection) ignoreDeselect = ignoreSelect = lockSelection = true; 6225 if (fixSelection) ignoreDeselect = ignoreSelect = lockSelection = true;
5869 int code = callWindowProc (handle, OS.WM_LBUTTONDOWN, wParam, lParam); 6226 int /*long*/ code = callWindowProc (handle, OS.WM_LBUTTONDOWN, wParam, lParam);
5870 if (fixSelection) ignoreDeselect = ignoreSelect = lockSelection = false; 6227 if (fixSelection) ignoreDeselect = ignoreSelect = lockSelection = false;
6228 HANDLE hNewSelection = cast(HANDLE) OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_CARET, 0);
6229 if (hOldSelection !is hNewSelection) hAnchor = hNewSelection;
5871 if (dragStarted) { 6230 if (dragStarted) {
5872 if (!display.captureChanged && !isDisposed ()) { 6231 if (!display.captureChanged && !isDisposed ()) {
5873 if (OS.GetCapture () !is handle) OS.SetCapture (handle); 6232 if (OS.GetCapture () !is handle) OS.SetCapture (handle);
6233 }
6234 }
6235 /*
6236 * Bug in Windows. When a tree has no images and an item is
6237 * expanded or collapsed, for some reason, Windows changes
6238 * the size of the selection. When the user expands a tree
6239 * item, the selection rectangle is made a few pixels larger.
6240 * When the user collapses an item, the selection rectangle
6241 * is restored to the original size but the selection is not
6242 * redrawn, causing pixel corruption. The fix is to detect
6243 * this case and redraw the item.
6244 */
6245 if ((lpht.flags & OS.TVHT_ONITEMBUTTON) !is 0) {
6246 int bits = OS.GetWindowLong (handle, OS.GWL_STYLE);
6247 if ((bits & OS.TVS_FULLROWSELECT) is 0) {
6248 if (OS.SendMessage (handle, OS.TVM_GETIMAGELIST, OS.TVSIL_NORMAL, 0) is 0) {
6249 auto hItem = cast(HANDLE) OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_CARET, 0);
6250 if (hItem !is null) {
6251 RECT rect;
6252 if (OS.TreeView_GetItemRect (handle, hItem, &rect, false)) {
6253 OS.InvalidateRect (handle, &rect, true);
6254 }
6255 }
6256 }
5874 } 6257 }
5875 } 6258 }
5876 if (deselected) { 6259 if (deselected) {
5877 Event event = new Event (); 6260 Event event = new Event ();
5878 event.item = _getItem (lpht.hItem); 6261 event.item = _getItem (lpht.hItem);
5922 postEvent (DWT.Selection, event); 6305 postEvent (DWT.Selection, event);
5923 return LRESULT.ZERO; 6306 return LRESULT.ZERO;
5924 } 6307 }
5925 } 6308 }
5926 6309
6310 /*
6311 * Feature in Windows. When the tree has the style
6312 * TVS_FULLROWSELECT, the background color for the
6313 * entire row is filled when an item is painted,
6314 * drawing on top of any custom drawing. The fix
6315 * is to emulate TVS_FULLROWSELECT.
6316 */
6317 bool selected = false;
6318 bool fakeSelection = false;
6319 if (lpht.hItem !is null) {
6320 if ((style & DWT.FULL_SELECTION) !is 0) {
6321 int bits = OS.GetWindowLong (handle, OS.GWL_STYLE);
6322 if ((bits & OS.TVS_FULLROWSELECT) is 0) fakeSelection = true;
6323 } else {
6324 if (hooks (DWT.MeasureItem)) {
6325 selected = hitTestSelection (lpht.hItem, lpht.pt.x, lpht.pt.y) !is 0;
6326 if (selected) {
6327 if ((lpht.flags & OS.TVHT_ONITEM) is 0) fakeSelection = true;
6328 }
6329 }
6330 }
6331 }
6332
5927 /* Process the mouse when an item is not selected */ 6333 /* Process the mouse when an item is not selected */
5928 if ((style & DWT.FULL_SELECTION) is 0) { 6334 if (!selected && (style & DWT.FULL_SELECTION) is 0) {
5929 if ((lpht.flags & OS.TVHT_ONITEM) is 0) { 6335 if ((lpht.flags & OS.TVHT_ONITEM) is 0) {
5930 Display display = this.display; 6336 Display display = this.display;
5931 display.captureChanged = false; 6337 display.captureChanged = false;
5932 if (!sendMouseEvent (DWT.MouseDown, 1, handle, OS.WM_LBUTTONDOWN, wParam, lParam)) { 6338 if (!sendMouseEvent (DWT.MouseDown, 1, handle, OS.WM_LBUTTONDOWN, wParam, lParam)) {
5933 if (!display.captureChanged && !isDisposed ()) { 6339 if (!display.captureChanged && !isDisposed ()) {
5934 if (OS.GetCapture () !is handle) OS.SetCapture (handle); 6340 if (OS.GetCapture () !is handle) OS.SetCapture (handle);
5935 } 6341 }
5936 return LRESULT.ZERO; 6342 return LRESULT.ZERO;
5937 } 6343 }
5938 int code = callWindowProc (handle, OS.WM_LBUTTONDOWN, wParam, lParam); 6344 int /*long*/ code = callWindowProc (handle, OS.WM_LBUTTONDOWN, wParam, lParam);
5939 if (!display.captureChanged && !isDisposed ()) { 6345 if (!display.captureChanged && !isDisposed ()) {
5940 if (OS.GetCapture () !is handle) OS.SetCapture (handle); 6346 if (OS.GetCapture () !is handle) OS.SetCapture (handle);
5941 } 6347 }
5942 return new LRESULT (code); 6348 return new LRESULT (code);
5943 } 6349 }
5945 6351
5946 /* Get the selected state of the item under the mouse */ 6352 /* Get the selected state of the item under the mouse */
5947 TVITEM tvItem; 6353 TVITEM tvItem;
5948 tvItem.mask = OS.TVIF_HANDLE | OS.TVIF_STATE; 6354 tvItem.mask = OS.TVIF_HANDLE | OS.TVIF_STATE;
5949 tvItem.stateMask = OS.TVIS_SELECTED; 6355 tvItem.stateMask = OS.TVIS_SELECTED;
5950 bool hittestSelected = false, focused = false; 6356 bool hittestSelected = false;
5951 if ((style & DWT.MULTI) !is 0) { 6357 if ((style & DWT.MULTI) !is 0) {
5952 tvItem.hItem = lpht.hItem; 6358 tvItem.hItem = lpht.hItem;
5953 OS.SendMessage (handle, OS.TVM_GETITEM, 0, &tvItem); 6359 OS.SendMessage (handle, OS.TVM_GETITEM, 0, &tvItem);
5954 hittestSelected = (tvItem.state & OS.TVIS_SELECTED) !is 0; 6360 hittestSelected = (tvItem.state & OS.TVIS_SELECTED) !is 0;
5955 focused = OS.GetFocus () is handle;
5956 } 6361 }
5957 6362
5958 /* Get the selected state of the last selected item */ 6363 /* Get the selected state of the last selected item */
5959 bool redraw = false;
5960 auto hOldItem = cast(HANDLE) OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_CARET, 0); 6364 auto hOldItem = cast(HANDLE) OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_CARET, 0);
5961 if ((style & DWT.MULTI) !is 0) { 6365 if ((style & DWT.MULTI) !is 0) {
5962 tvItem.hItem = hOldItem; 6366 tvItem.hItem = hOldItem;
5963 OS.SendMessage (handle, OS.TVM_GETITEM, 0, &tvItem); 6367 OS.SendMessage (handle, OS.TVM_GETITEM, 0, &tvItem);
5964 6368
5965 /* Check for CONTROL or drag selection */ 6369 /* Check for CONTROL or drag selection */
5966 if (hittestSelected || (wParam & OS.MK_CONTROL) !is 0) { 6370 if (hittestSelected || (wParam & OS.MK_CONTROL) !is 0) {
5967 /* 6371 /*
5968 * Feature in Windows. When the tree is not drawing focus 6372 * Feature in Windows. When the tree is not drawing focus
5969 * and the user selects a tree item using while the CONTROL 6373 * and the user selects a tree item while the CONTROL key
5970 * key is down, the tree window proc sends WM_UPDATEUISTATE 6374 * is down, the tree window proc sends WM_UPDATEUISTATE
5971 * to the top level window, causing controls within the shell 6375 * to the top level window, causing controls within the shell
5972 * to redraw. When drag detect is enabled, the tree window 6376 * to redraw. When drag detect is enabled, the tree window
5973 * proc runs a modal loop that allows WM_PAINT messages to be 6377 * proc runs a modal loop that allows WM_PAINT messages to be
5974 * delivered during WM_LBUTTONDOWN. When WM_SETREDRAW is used 6378 * delivered during WM_LBUTTONDOWN. When WM_SETREDRAW is used
5975 * to disable drawing for the tree and a WM_PAINT happens for 6379 * to disable drawing for the tree and a WM_PAINT happens for
5976 * a parent of the tree (or a sibling that overlaps), the parent 6380 * a parent of the tree (or a sibling that overlaps), the parent
5977 * will draw on top of the tree. If WM_SETREDRAW is turned back 6381 * will draw on top of the tree. If WM_SETREDRAW is turned back
5978 * on without redrawing the entire tree, pixel corruption occurs. 6382 * on without redrawing the entire tree, pixel corruption occurs.
5979 * This case only seems to happen when the tree has been given 6383 * This case only seems to happen when the tree has been given
5980 * focus from WM_MOUSEACTIVATE of the shell. The fix is to 6384 * focus from WM_MOUSEACTIVATE of the shell. The fix is to
5981 * detect that WM_UPDATEUISTATE will be sent and avoid using 6385 * force the WM_UPDATEUISTATE to be sent before disabling
5982 * WM_SETREDRAW to disable drawing. 6386 * the drawing.
5983 * 6387 *
5984 * NOTE: Any redraw of a parent (or sibling) will be dispatched 6388 * NOTE: Any redraw of a parent (or sibling) will be dispatched
5985 * during the modal drag detect loop. This code only fixes the 6389 * during the modal drag detect loop. This code only fixes the
5986 * case where the tree causes a redraw from WM_UPDATEUISTATE. 6390 * case where the tree causes a redraw from WM_UPDATEUISTATE.
5987 * In DWT, the InvalidateRect() that causes the pixel corruption 6391 * In DWT, the InvalidateRect() that caused the pixel corruption
5988 * is found in Composite.WM_UPDATEUISTATE(). 6392 * is found in Composite.WM_UPDATEUISTATE().
5989 */ 6393 */
5990 int uiState = OS.SendMessage (handle, OS.WM_QUERYUISTATE, 0, 0); 6394 int uiState = OS.SendMessage (handle, OS.WM_QUERYUISTATE, 0, 0);
5991 if ((uiState & OS.UISF_HIDEFOCUS) is 0) { 6395 if ((uiState & OS.UISF_HIDEFOCUS) !is 0) {
5992 redraw = focused && drawCount is 0 && OS.IsWindowVisible (handle); 6396 OS.SendMessage (handle, OS.WM_CHANGEUISTATE, OS.UIS_INITIALIZE, 0);
5993 } 6397 }
5994 if (redraw) { 6398 OS.UpdateWindow (handle);
5995 OS.UpdateWindow (handle); 6399 OS.DefWindowProc (handle, OS.WM_SETREDRAW, 0, 0);
5996 OS.DefWindowProc (handle, OS.WM_SETREDRAW, 0, 0);
5997 }
5998 } else { 6400 } else {
5999 deselectAll (); 6401 deselectAll ();
6000 } 6402 }
6001 } 6403 }
6002 6404
6010 return LRESULT.ZERO; 6412 return LRESULT.ZERO;
6011 } 6413 }
6012 hSelect = lpht.hItem; 6414 hSelect = lpht.hItem;
6013 dragStarted = gestureCompleted = false; 6415 dragStarted = gestureCompleted = false;
6014 ignoreDeselect = ignoreSelect = true; 6416 ignoreDeselect = ignoreSelect = true;
6015 int code = callWindowProc (handle, OS.WM_LBUTTONDOWN, wParam, lParam); 6417 int /*long*/ code = callWindowProc (handle, OS.WM_LBUTTONDOWN, wParam, lParam);
6016 auto hNewItem = cast(HANDLE) OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_CARET, 0); 6418 auto hNewItem = cast(HANDLE) OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_CARET, 0);
6017 /* 6419 if (fakeSelection) {
6018 * Feature in Windows. When the tree has the style 6420 if (hOldItem is null || (hNewItem is hOldItem && lpht.hItem !is hOldItem)) {
6019 * TVS_FULLROWSELECT, the background color for the 6421 OS.SendMessage (handle, OS.TVM_SELECTITEM, OS.TVGN_CARET, lpht.hItem);
6020 * entire row is filled when an item is painted, 6422 hNewItem = cast(HANDLE) OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_CARET, 0);
6021 * drawing on top of any custom drawing. The fix 6423 }
6022 * is to emulate TVS_FULLROWSELECT. 6424 if (!dragStarted && (state & DRAG_DETECT) !is 0 && hooks (DWT.DragDetect)) {
6023 */ 6425 dragStarted = dragDetect (handle, lpht.pt.x, lpht.pt.y, false, null, null);
6024 if ((style & DWT.FULL_SELECTION) !is 0) {
6025 int bits = OS.GetWindowLong (handle, OS.GWL_STYLE);
6026 if ((bits & OS.TVS_FULLROWSELECT) is 0) {
6027 if (hNewItem is hOldItem && lpht.hItem !is hOldItem) {
6028 OS.SendMessage (handle, OS.TVM_SELECTITEM, OS.TVGN_CARET, lpht.hItem);
6029 hNewItem = cast(HANDLE) OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_CARET, 0);
6030 }
6031 if (!dragStarted && lpht.hItem !is null && (state & DRAG_DETECT) !is 0 && hooks (DWT.DragDetect)) {
6032 dragStarted = dragDetect (handle, lpht.pt.x, lpht.pt.y, false, null, null);
6033 }
6034 } 6426 }
6035 } 6427 }
6036 ignoreDeselect = ignoreSelect = false; 6428 ignoreDeselect = ignoreSelect = false;
6037 hSelect = null; 6429 hSelect = null;
6038 if (dragStarted) { 6430 if (dragStarted) {
6081 tvItem.hItem = lpht.hItem; 6473 tvItem.hItem = lpht.hItem;
6082 OS.SendMessage (handle, OS.TVM_SETITEM, 0, &tvItem); 6474 OS.SendMessage (handle, OS.TVM_SETITEM, 0, &tvItem);
6083 } 6475 }
6084 } 6476 }
6085 } 6477 }
6086 if (redraw) { 6478 RECT rect1, rect2;
6087 RECT rect1, rect2; 6479 bool fItemRect = (style & DWT.FULL_SELECTION) is 0;
6088 rect1.left = cast(int) hOldItem; rect2.left = cast(int) hNewItem; 6480 if (hooks (DWT.EraseItem) || hooks (DWT.PaintItem)) fItemRect = false;
6089 int fItemRect = (style & DWT.FULL_SELECTION) !is 0 ? 0 : 1; 6481 if (!OS.IsWinCE && OS.WIN32_VERSION >= OS.VERSION (6, 0)) fItemRect = false;
6090 if (hooks (DWT.EraseItem) || hooks (DWT.PaintItem)) fItemRect = 0; 6482 OS.TreeView_GetItemRect (handle, hOldItem, &rect1, fItemRect);
6091 if (!OS.IsWinCE && OS.WIN32_VERSION >= OS.VERSION (6, 0)) fItemRect = 0; 6483 OS.TreeView_GetItemRect (handle, hNewItem, &rect2, fItemRect);
6092 OS.SendMessage (handle, OS.TVM_GETITEMRECT, fItemRect, &rect1); 6484 OS.DefWindowProc (handle, OS.WM_SETREDRAW, 1, 0);
6093 OS.SendMessage (handle, OS.TVM_GETITEMRECT, fItemRect, &rect2); 6485 OS.InvalidateRect (handle, &rect1, true);
6094 OS.DefWindowProc (handle, OS.WM_SETREDRAW, 1, 0); 6486 OS.InvalidateRect (handle, &rect2, true);
6095 OS.InvalidateRect (handle, &rect1, true); 6487 OS.UpdateWindow (handle);
6096 OS.InvalidateRect (handle, &rect2, true);
6097 OS.UpdateWindow (handle);
6098 }
6099 } 6488 }
6100 6489
6101 /* Check for SHIFT or normal select and deselect/reselect items */ 6490 /* Check for SHIFT or normal select and deselect/reselect items */
6102 if ((wParam & OS.MK_CONTROL) is 0) { 6491 if ((wParam & OS.MK_CONTROL) is 0) {
6103 if (!hittestSelected || !dragStarted) { 6492 if (!hittestSelected || !dragStarted) {
6104 tvItem.state = 0; 6493 tvItem.state = 0;
6105 int oldProc = OS.GetWindowLong (handle, OS.GWL_WNDPROC); 6494 auto oldProc = OS.GetWindowLongPtr (handle, OS.GWLP_WNDPROC);
6106 OS.SetWindowLong (handle, OS.GWL_WNDPROC, cast(int) TreeProc); 6495 OS.SetWindowLongPtr (handle, OS.GWLP_WNDPROC, cast(LONG_PTR)TreeProc);
6107 if ((style & DWT.VIRTUAL) !is 0) { 6496 if ((style & DWT.VIRTUAL) !is 0) {
6108 HANDLE hItem = cast(HANDLE) OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_ROOT, 0); 6497 HANDLE hItem = cast(HANDLE) OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_ROOT, 0);
6109 deselect (hItem, &tvItem, hNewItem); 6498 deselect (hItem, &tvItem, hNewItem);
6110 } else { 6499 } else {
6111 for (int i=0; i<items.length; i++) { 6500 for (int i=0; i<items.length; i++) {
6117 } 6506 }
6118 } 6507 }
6119 tvItem.hItem = hNewItem; 6508 tvItem.hItem = hNewItem;
6120 tvItem.state = OS.TVIS_SELECTED; 6509 tvItem.state = OS.TVIS_SELECTED;
6121 OS.SendMessage (handle, OS.TVM_SETITEM, 0, &tvItem); 6510 OS.SendMessage (handle, OS.TVM_SETITEM, 0, &tvItem);
6122 OS.SetWindowLong (handle, OS.GWL_WNDPROC, oldProc); 6511 OS.SetWindowLongPtr (handle, OS.GWLP_WNDPROC, oldProc);
6123 if ((wParam & OS.MK_SHIFT) !is 0) { 6512 if ((wParam & OS.MK_SHIFT) !is 0) {
6124 RECT rect1; 6513 RECT rect1;
6125 if (hAnchor is null) hAnchor = hNewItem; 6514 if (hAnchor is null) hAnchor = hNewItem;
6126 rect1.left = cast(int) hAnchor; 6515 if (OS.TreeView_GetItemRect (handle, hAnchor, &rect1, false)) {
6127 if (OS.SendMessage (handle, OS.TVM_GETITEMRECT, 0, &rect1) !is 0) {
6128 RECT rect2; 6516 RECT rect2;
6129 rect2.left = cast(int) hNewItem; 6517 if (OS.TreeView_GetItemRect (handle, hNewItem, &rect2, false)) {
6130 OS.SendMessage (handle, OS.TVM_GETITEMRECT, 0, &rect2); 6518 int flags = rect1.top < rect2.top ? OS.TVGN_NEXTVISIBLE : OS.TVGN_PREVIOUSVISIBLE;
6131 int flags = rect1.top < rect2.top ? OS.TVGN_NEXTVISIBLE : OS.TVGN_PREVIOUSVISIBLE; 6519 tvItem.state = OS.TVIS_SELECTED;
6132 tvItem.state = OS.TVIS_SELECTED; 6520 auto hItem = tvItem.hItem = hAnchor;
6133 auto hItem = tvItem.hItem = hAnchor;
6134 OS.SendMessage (handle, OS.TVM_SETITEM, 0, &tvItem);
6135 while (hItem !is hNewItem) {
6136 tvItem.hItem = hItem;
6137 OS.SendMessage (handle, OS.TVM_SETITEM, 0, &tvItem); 6521 OS.SendMessage (handle, OS.TVM_SETITEM, 0, &tvItem);
6138 hItem = cast(HANDLE) OS.SendMessage (handle, OS.TVM_GETNEXTITEM, flags, hItem); 6522 while (hItem !is hNewItem) {
6523 tvItem.hItem = hItem;
6524 OS.SendMessage (handle, OS.TVM_SETITEM, 0, &tvItem);
6525 hItem = cast(HANDLE) OS.SendMessage (handle, OS.TVM_GETNEXTITEM, flags, hItem);
6526 }
6139 } 6527 }
6140 } 6528 }
6141 } 6529 }
6142 } 6530 }
6143 } 6531 }
6162 * this modal loop eats the corresponding mouse up. The fix is to 6550 * this modal loop eats the corresponding mouse up. The fix is to
6163 * detect the cases when the modal loop has eaten the mouse up and 6551 * detect the cases when the modal loop has eaten the mouse up and
6164 * issue a fake mouse up. 6552 * issue a fake mouse up.
6165 */ 6553 */
6166 if (dragStarted) { 6554 if (dragStarted) {
6167 sendDragEvent (1, cast(short) (lParam & 0xFFFF), cast(short) (lParam >> 16)); 6555 sendDragEvent (1, OS.GET_X_LPARAM (lParam), OS.GET_Y_LPARAM (lParam));
6168 } else { 6556 } else {
6169 int bits = OS.GetWindowLong (handle, OS.GWL_STYLE); 6557 int bits = OS.GetWindowLong (handle, OS.GWL_STYLE);
6170 if ((bits & OS.TVS_DISABLEDRAGDROP) is 0) { 6558 if ((bits & OS.TVS_DISABLEDRAGDROP) is 0) {
6171 sendMouseEvent (DWT.MouseUp, 1, handle, OS.WM_LBUTTONUP, wParam, lParam); 6559 sendMouseEvent (DWT.MouseUp, 1, handle, OS.WM_LBUTTONUP, wParam, lParam);
6172 } 6560 }
6177 6565
6178 override LRESULT WM_MOUSEMOVE (int wParam, int lParam) { 6566 override LRESULT WM_MOUSEMOVE (int wParam, int lParam) {
6179 Display display = this.display; 6567 Display display = this.display;
6180 LRESULT result = super.WM_MOUSEMOVE (wParam, lParam); 6568 LRESULT result = super.WM_MOUSEMOVE (wParam, lParam);
6181 if (result !is null) return result; 6569 if (result !is null) return result;
6182 if (itemToolTipHandle !is null && hwndHeader !is null) { 6570 if (itemToolTipHandle !is null) {
6183 /* 6571 /*
6184 * Bug in Windows. On some machines that do not have XBUTTONs, 6572 * Bug in Windows. On some machines that do not have XBUTTONs,
6185 * the MK_XBUTTON1 and OS.MK_XBUTTON2 bits are sometimes set, 6573 * the MK_XBUTTON1 and OS.MK_XBUTTON2 bits are sometimes set,
6186 * causing mouse capture to become stuck. The fix is to test 6574 * causing mouse capture to become stuck. The fix is to test
6187 * for the extra buttons only when they exist. 6575 * for the extra buttons only when they exist.
6188 */ 6576 */
6189 int mask = OS.MK_LBUTTON | OS.MK_MBUTTON | OS.MK_RBUTTON; 6577 int mask = OS.MK_LBUTTON | OS.MK_MBUTTON | OS.MK_RBUTTON;
6190 if (display.xMouse) mask |= OS.MK_XBUTTON1 | OS.MK_XBUTTON2; 6578 if (display.xMouse) mask |= OS.MK_XBUTTON1 | OS.MK_XBUTTON2;
6191 if (((wParam & 0xFFFF) & mask) is 0) { 6579 if ((wParam & mask) is 0) {
6192 TVHITTESTINFO lpht; 6580 int x = OS.GET_X_LPARAM (lParam);
6193 lpht.pt.x = cast(short) (lParam & 0xFFFF); 6581 int y = OS.GET_Y_LPARAM (lParam);
6194 lpht.pt.y = cast(short) (lParam >> 16); 6582 int index;
6195 OS.SendMessage (handle, OS.TVM_HITTEST, 0, &lpht); 6583 TreeItem item;
6196 if (lpht.hItem !is null) { 6584 RECT cellRect, itemRect;
6197 auto hDC = OS.GetDC (handle); 6585 if (findCell (x, y, item, index, cellRect, itemRect)) {
6198 HFONT oldFont, newFont = cast(HFONT) OS.SendMessage (handle, OS.WM_GETFONT, 0, 0); 6586 /*
6199 if (newFont !is null) oldFont = OS.SelectObject (hDC, newFont); 6587 * Feature in Windows. When the new tool rectangle is
6200 POINT pt; 6588 * set using TTM_NEWTOOLRECT and the tooltip is visible,
6201 pt.x = lpht.pt.x; 6589 * Windows draws the tooltip right away and the sends
6202 pt.y = lpht.pt.y; 6590 * WM_NOTIFY with TTN_SHOW. This means that the tooltip
6203 RECT rect; 6591 * shows first at the wrong location and then moves to
6204 OS.GetClientRect (hwndParent, &rect); 6592 * the right one. The fix is to hide the tooltip window.
6205 OS.MapWindowPoints (hwndParent, handle, cast(POINT*) &rect, 2); 6593 */
6206 TreeItem item = _getItem (lpht.hItem); 6594 if (OS.SendMessage (itemToolTipHandle, OS.TTM_GETCURRENTTOOL, 0, 0) is 0) {
6207 int index = 0, count = Math.max (1, OS.SendMessage (hwndHeader, OS.HDM_GETITEMCOUNT, 0, 0)); 6595 if (OS.IsWindowVisible (itemToolTipHandle)) {
6208 int [] order = new int [count]; 6596 OS.ShowWindow (itemToolTipHandle, OS.SW_HIDE);
6209 OS.SendMessage (hwndHeader, OS.HDM_GETORDERARRAY, count, order.ptr);
6210 while (index < count) {
6211 HFONT hFont = item.cellFont !is null ? item.cellFont [order [index]] : cast(HFONT)-1;
6212 if (hFont is cast(HFONT)-1) hFont = item.font;
6213 if (hFont !is cast(HFONT)-1) hFont = OS.SelectObject (hDC, hFont);
6214 RECT cellRect = item.getBounds (order [index], true, false, true, false, true, hDC);
6215 if (hFont !is cast(HFONT)-1) OS.SelectObject (hDC, hFont);
6216 if (cellRect.left > rect.right) break;
6217 cellRect.right = Math.min (cellRect.right, rect.right);
6218 if (OS.PtInRect (&cellRect, pt)) {
6219 RECT textRect = item.getBounds (order [index], true, false, false, false, false, hDC);
6220 if (textRect.right > cellRect.right) {
6221 TOOLINFO lpti;
6222 lpti.cbSize = TOOLINFO.sizeof;
6223 lpti.hwnd = handle;
6224 lpti.uId = cast(int) handle;
6225 lpti.uFlags = OS.TTF_SUBCLASS | OS.TTF_TRANSPARENT;
6226 lpti.rect.left = cellRect.left;
6227 lpti.rect.top = cellRect.top;
6228 lpti.rect.right = cellRect.right;
6229 lpti.rect.bottom = cellRect.bottom;
6230 OS.SendMessage (itemToolTipHandle, OS.TTM_NEWTOOLRECT, 0, &lpti);
6231 }
6232 break;
6233 } 6597 }
6234 index++; 6598 }
6235 } 6599 TOOLINFO lpti;
6236 if (newFont !is null) OS.SelectObject (hDC, oldFont); 6600 lpti.cbSize = TOOLINFO.sizeof;
6237 OS.ReleaseDC (handle, hDC); 6601 lpti.hwnd = handle;
6602 lpti.uId = cast(int) handle;
6603 lpti.uFlags = OS.TTF_SUBCLASS | OS.TTF_TRANSPARENT;
6604 lpti.rect.left = cellRect.left;
6605 lpti.rect.top = cellRect.top;
6606 lpti.rect.right = cellRect.right;
6607 lpti.rect.bottom = cellRect.bottom;
6608 OS.SendMessage (itemToolTipHandle, OS.TTM_NEWTOOLRECT, 0, &lpti);
6238 } 6609 }
6239 } 6610 }
6240 } 6611 }
6241 return result; 6612 return result;
6242 } 6613 }
6281 * menu, the selection snaps back. The fix is to avoid 6652 * menu, the selection snaps back. The fix is to avoid
6282 * calling the window proc and do the selection ourselves. 6653 * calling the window proc and do the selection ourselves.
6283 * This behavior is consistent with the table. 6654 * This behavior is consistent with the table.
6284 */ 6655 */
6285 TVHITTESTINFO lpht; 6656 TVHITTESTINFO lpht;
6286 lpht.pt.x = cast(short) (lParam & 0xFFFF); 6657 lpht.pt.x = OS.GET_X_LPARAM (lParam);
6287 lpht.pt.y = cast(short) (lParam >> 16); 6658 lpht.pt.y = OS.GET_Y_LPARAM (lParam);
6288 OS.SendMessage (handle, OS.TVM_HITTEST, 0, &lpht); 6659 OS.SendMessage (handle, OS.TVM_HITTEST, 0, &lpht);
6289 if (lpht.hItem !is null) { 6660 if (lpht.hItem !is null) {
6290 int flags = OS.TVHT_ONITEMICON | OS.TVHT_ONITEMLABEL; 6661 bool fakeSelection = (style & DWT.FULL_SELECTION) !is 0;
6291 if ((style & DWT.FULL_SELECTION) !is 0 || (lpht.flags & flags) !is 0) { 6662 if (!fakeSelection) {
6663 if (hooks (DWT.MeasureItem)) {
6664 fakeSelection = hitTestSelection (lpht.hItem, lpht.pt.x, lpht.pt.y);
6665 } else {
6666 int flags = OS.TVHT_ONITEMICON | OS.TVHT_ONITEMLABEL;
6667 fakeSelection = (lpht.flags & flags) !is 0;
6668 }
6669 }
6670 if (fakeSelection) {
6292 if ((wParam & (OS.MK_CONTROL | OS.MK_SHIFT)) is 0) { 6671 if ((wParam & (OS.MK_CONTROL | OS.MK_SHIFT)) is 0) {
6293 TVITEM tvItem; 6672 TVITEM tvItem;
6294 tvItem.mask = OS.TVIF_HANDLE | OS.TVIF_STATE; 6673 tvItem.mask = OS.TVIF_HANDLE | OS.TVIF_STATE;
6295 tvItem.stateMask = OS.TVIS_SELECTED; 6674 tvItem.stateMask = OS.TVIS_SELECTED;
6296 tvItem.hItem = lpht.hItem; 6675 tvItem.hItem = lpht.hItem;
6324 } 6703 }
6325 shrink = false; 6704 shrink = false;
6326 } 6705 }
6327 if ((style & DWT.DOUBLE_BUFFERED) !is 0 || findImageControl () !is null) { 6706 if ((style & DWT.DOUBLE_BUFFERED) !is 0 || findImageControl () !is null) {
6328 bool doubleBuffer = true; 6707 bool doubleBuffer = true;
6329 if (EXPLORER_THEME) { 6708 if (explorerTheme) {
6330 if (!OS.IsWinCE && OS.WIN32_VERSION >= OS.VERSION (6, 0)) { 6709 int exStyle = OS.SendMessage (handle, OS.TVM_GETEXTENDEDSTYLE, 0, 0);
6331 int exStyle = OS.SendMessage (handle, OS.TVM_GETEXTENDEDSTYLE, 0, 0); 6710 if ((exStyle & OS.TVS_EX_DOUBLEBUFFER) !is 0) doubleBuffer = false;
6332 if ((exStyle & OS.TVS_EX_DOUBLEBUFFER) !is 0) doubleBuffer = false;
6333 }
6334 } 6711 }
6335 if (doubleBuffer) { 6712 if (doubleBuffer) {
6336 GC gc = null; 6713 GC gc = null;
6337 HDC paintDC; 6714 HDC paintDC;
6338 PAINTSTRUCT ps; 6715 PAINTSTRUCT ps;
6400 * during WM_PAINT. The fix is to draw without clipping and 6777 * during WM_PAINT. The fix is to draw without clipping and
6401 * then draw the rest of the columns on top. Since the drawing 6778 * then draw the rest of the columns on top. Since the drawing
6402 * is happening in WM_PRINTCLIENT, the redrawing is not visible. 6779 * is happening in WM_PRINTCLIENT, the redrawing is not visible.
6403 */ 6780 */
6404 printClient = true; 6781 printClient = true;
6405 int code = callWindowProc (handle, OS.WM_PRINTCLIENT, wParam, lParam); 6782 int /*long*/ code = callWindowProc (handle, OS.WM_PRINTCLIENT, wParam, lParam);
6406 printClient = false; 6783 printClient = false;
6407 return new LRESULT (code); 6784 return new LRESULT (code);
6408 } 6785 }
6409 6786
6410 override LRESULT WM_SETFOCUS (int wParam, int lParam) { 6787 override LRESULT WM_SETFOCUS (int wParam, int lParam) {
6473 * 6850 *
6474 * NOTE: This problem is intermittent and happens on 6851 * NOTE: This problem is intermittent and happens on
6475 * Windows Vista running under the theme manager. 6852 * Windows Vista running under the theme manager.
6476 */ 6853 */
6477 if (!OS.IsWinCE && OS.WIN32_VERSION >= OS.VERSION (6, 0)) { 6854 if (!OS.IsWinCE && OS.WIN32_VERSION >= OS.VERSION (6, 0)) {
6478 int code = OS.DefWindowProc (handle, OS.WM_SETREDRAW, wParam, lParam); 6855 int /*long*/ code = OS.DefWindowProc (handle, OS.WM_SETREDRAW, wParam, lParam);
6479 return code is 0 ? LRESULT.ZERO : new LRESULT (code); 6856 return code is 0 ? LRESULT.ZERO : new LRESULT (code);
6480 } 6857 }
6481 return result; 6858 return result;
6482 } 6859 }
6483 6860
6497 * is used with a full selection tree, when the tree 6874 * is used with a full selection tree, when the tree
6498 * is resized to be smaller, the rounded right edge 6875 * is resized to be smaller, the rounded right edge
6499 * of the selected items is not drawn. The fix is the 6876 * of the selected items is not drawn. The fix is the
6500 * redraw the entire tree. 6877 * redraw the entire tree.
6501 */ 6878 */
6502 if (EXPLORER_THEME) { 6879 if (explorerTheme && (style & DWT.FULL_SELECTION) !is 0) {
6503 if (!OS.IsWinCE && OS.WIN32_VERSION >= OS.VERSION (6, 0)) { 6880 OS.InvalidateRect (handle, null, false);
6504 if ((style & DWT.FULL_SELECTION) !is 0) {
6505 OS.InvalidateRect (handle, null, false);
6506 }
6507 }
6508 } 6881 }
6509 if (ignoreResize) return null; 6882 if (ignoreResize) return null;
6510 return super.WM_SIZE (wParam, lParam); 6883 return super.WM_SIZE (wParam, lParam);
6511 } 6884 }
6512 6885
6524 } 6897 }
6525 if ((style & DWT.CHECK) !is 0) setCheckboxImageList (); 6898 if ((style & DWT.CHECK) !is 0) setCheckboxImageList ();
6526 return result; 6899 return result;
6527 } 6900 }
6528 6901
6902 override LRESULT WM_VSCROLL (int /*long*/ wParam, int /*long*/ lParam) {
6903 bool fixScroll = false;
6904 if ((style & DWT.DOUBLE_BUFFERED) !is 0) {
6905 int code = OS.LOWORD (wParam);
6906 switch (code) {
6907 case OS.SB_TOP:
6908 case OS.SB_BOTTOM:
6909 case OS.SB_LINEDOWN:
6910 case OS.SB_LINEUP:
6911 case OS.SB_PAGEDOWN:
6912 case OS.SB_PAGEUP:
6913 fixScroll = (style & DWT.VIRTUAL) !is 0 || hooks (DWT.EraseItem) || hooks (DWT.PaintItem);
6914 break;
6915 }
6916 }
6917 if (fixScroll) {
6918 style &= ~DWT.DOUBLE_BUFFERED;
6919 if (explorerTheme) {
6920 OS.SendMessage (handle, OS.TVM_SETEXTENDEDSTYLE, OS.TVS_EX_DOUBLEBUFFER, 0);
6921 }
6922 }
6923 LRESULT result = super.WM_VSCROLL (wParam, lParam);
6924 if (fixScroll) {
6925 style |= DWT.DOUBLE_BUFFERED;
6926 if (explorerTheme) {
6927 OS.SendMessage (handle, OS.TVM_SETEXTENDEDSTYLE, OS.TVS_EX_DOUBLEBUFFER, OS.TVS_EX_DOUBLEBUFFER);
6928 }
6929 }
6930 if (result !is null) return result;
6931 return result;
6932 }
6933
6529 override LRESULT wmColorChild (int wParam, int lParam) { 6934 override LRESULT wmColorChild (int wParam, int lParam) {
6530 if (findImageControl () !is null) { 6935 if (findImageControl () !is null) {
6531 if (OS.COMCTL32_MAJOR < 6) { 6936 if (OS.COMCTL32_MAJOR < 6) {
6532 return super.wmColorChild (wParam, lParam); 6937 return super.wmColorChild (wParam, lParam);
6533 } 6938 }
6542 */ 6947 */
6543 return null; 6948 return null;
6544 } 6949 }
6545 6950
6546 override LRESULT wmNotify (NMHDR* hdr, int wParam, int lParam) { 6951 override LRESULT wmNotify (NMHDR* hdr, int wParam, int lParam) {
6547 if (hdr.hwndFrom is itemToolTipHandle && hwndHeader !is null) { 6952 if (hdr.hwndFrom is itemToolTipHandle) {
6548 static if (!OS.IsWinCE) { 6953 LRESULT result = wmNotifyToolTip (hdr, wParam, lParam);
6549 switch (hdr.code) { 6954 if (result !is null) return result;
6550 case OS.TTN_POP: {
6551 if (display.isXMouseActive ()) {
6552 Shell shell = getShell ();
6553 shell.lockToolTipControl = null;
6554 }
6555 break;
6556 }
6557 case OS.TTN_SHOW: {
6558 if (display.isXMouseActive ()) {
6559 Shell shell = getShell ();
6560 shell.lockToolTipControl = this;
6561 }
6562 int pos = OS.GetMessagePos ();
6563 POINT pt;
6564 pt.x = cast(short) (pos & 0xFFFF);
6565 pt.y = cast(short) (pos >> 16);
6566 OS.ScreenToClient (handle, &pt);
6567 TVHITTESTINFO lpht;
6568 lpht.pt.x = pt.x;
6569 lpht.pt.y = pt.y;
6570 OS.SendMessage (handle, OS.TVM_HITTEST, 0, &lpht);
6571 if (lpht.hItem !is null) {
6572 auto hDC = OS.GetDC (handle);
6573 HFONT oldFont, newFont = cast(HFONT) OS.SendMessage (handle, OS.WM_GETFONT, 0, 0);
6574 if (newFont !is null) oldFont = OS.SelectObject (hDC, newFont);
6575 LRESULT result = null;
6576 RECT rect;
6577 OS.GetClientRect (hwndParent, &rect);
6578 OS.MapWindowPoints (hwndParent, handle, cast(POINT*) &rect, 2);
6579 TreeItem item = _getItem (lpht.hItem);
6580 int index = 0, count = Math.max (1, OS.SendMessage (hwndHeader, OS.HDM_GETITEMCOUNT, 0, 0));
6581 int [] order = new int [count];
6582 OS.SendMessage (hwndHeader, OS.HDM_GETORDERARRAY, count, order.ptr);
6583 while (index < count) {
6584 HFONT hFont = item.cellFont !is null ? item.cellFont [order [index]] : cast(HFONT)-1;
6585 if (hFont is cast(HFONT)-1) hFont = item.font;
6586 if (hFont !is cast(HFONT)-1) hFont = OS.SelectObject (hDC, hFont);
6587 RECT cellRect = item.getBounds (order [index], true, false, true, false, true, hDC);
6588 if (hFont !is cast(HFONT)-1) OS.SelectObject (hDC, hFont);
6589 if (cellRect.left > rect.right) break;
6590 cellRect.right = Math.min (cellRect.right, rect.right);
6591 if (OS.PtInRect (&cellRect, pt)) {
6592 RECT textRect = item.getBounds (order [index], true, false, false, false, false, hDC);
6593 if (textRect.right > cellRect.right) {
6594 OS.MapWindowPoints (handle, null, cast(POINT*) &textRect, 2);
6595 int flags = OS.SWP_NOACTIVATE | OS.SWP_NOSIZE | OS.SWP_NOZORDER;
6596 SetWindowPos (itemToolTipHandle, null, textRect.left, textRect.top, 0, 0, flags);
6597 result = LRESULT.ONE;
6598 }
6599 break;
6600 }
6601 index++;
6602 }
6603 if (newFont !is null) OS.SelectObject (hDC, oldFont);
6604 OS.ReleaseDC (handle, hDC);
6605 if (result !is null) return result;
6606 }
6607 }
6608 default:
6609 }
6610 }
6611 } 6955 }
6612 if (hdr.hwndFrom is hwndHeader) { 6956 if (hdr.hwndFrom is hwndHeader) {
6613 /* 6957 LRESULT result = wmNotifyHeader (hdr, wParam, lParam);
6614 * Feature in Windows. On NT, the automatically created 6958 if (result !is null) return result;
6615 * header control is created as a UNICODE window, not an
6616 * ANSI window despite the fact that the parent is created
6617 * as an ANSI window. This means that it sends UNICODE
6618 * notification messages to the parent window on NT for
6619 * no good reason. The data and size in the NMHEADER and
6620 * HDITEM structs is identical between the platforms so no
6621 * different message is actually necessary. Despite this,
6622 * Windows sends different messages. The fix is to look
6623 * for both messages, despite the platform. This works
6624 * because only one will be sent on either platform, never
6625 * both.
6626 */
6627 switch (hdr.code) {
6628 case OS.HDN_BEGINTRACKW:
6629 case OS.HDN_BEGINTRACKA:
6630 case OS.HDN_DIVIDERDBLCLICKW:
6631 case OS.HDN_DIVIDERDBLCLICKA: {
6632 NMHEADER* phdn = cast(NMHEADER*)lParam;
6633 //OS.MoveMemory (phdn, lParam, NMHEADER.sizeof);
6634 TreeColumn column = columns [phdn.iItem];
6635 if (column !is null && !column.getResizable ()) {
6636 return LRESULT.ONE;
6637 }
6638 ignoreColumnMove = true;
6639 switch (hdr.code) {
6640 case OS.HDN_DIVIDERDBLCLICKW:
6641 case OS.HDN_DIVIDERDBLCLICKA:
6642 if (column !is null) column.pack ();
6643 default:
6644 }
6645 break;
6646 }
6647 case OS.NM_RELEASEDCAPTURE: {
6648 if (!ignoreColumnMove) {
6649 int count = OS.SendMessage (hwndHeader, OS.HDM_GETITEMCOUNT, 0, 0);
6650 for (int i=0; i<count; i++) {
6651 TreeColumn column = columns [i];
6652 column.updateToolTip (i);
6653 }
6654 updateImageList ();
6655 }
6656 ignoreColumnMove = false;
6657 break;
6658 }
6659 case OS.HDN_BEGINDRAG: {
6660 if (ignoreColumnMove) return LRESULT.ONE;
6661 NMHEADER* phdn = cast(NMHEADER*)lParam;
6662 //OS.MoveMemory (phdn, lParam, NMHEADER.sizeof);
6663 if (phdn.iItem !is -1) {
6664 TreeColumn column = columns [phdn.iItem];
6665 if (column !is null && !column.getMoveable ()) {
6666 ignoreColumnMove = true;
6667 return LRESULT.ONE;
6668 }
6669 }
6670 break;
6671 }
6672 case OS.HDN_ENDDRAG: {
6673 NMHEADER* phdn = cast(NMHEADER*)lParam;
6674 //OS.MoveMemory (phdn, lParam, NMHEADER.sizeof);
6675 if (phdn.iItem !is -1 && phdn.pitem !is null) {
6676 HDITEM* pitem = phdn.pitem;
6677 //OS.MoveMemory (pitem, phdn.pitem, HDITEM.sizeof);
6678 if ((pitem.mask & OS.HDI_ORDER) !is 0 && pitem.iOrder !is -1) {
6679 int count = OS.SendMessage (hwndHeader, OS.HDM_GETITEMCOUNT, 0, 0);
6680 int [] order = new int [count];
6681 OS.SendMessage (hwndHeader, OS.HDM_GETORDERARRAY, count, order.ptr);
6682 int index = 0;
6683 while (index < order.length) {
6684 if (order [index] is phdn.iItem) break;
6685 index++;
6686 }
6687 if (index is order.length) index = 0;
6688 if (index is pitem.iOrder) break;
6689 int start = Math.min (index, pitem.iOrder);
6690 int end = Math.max (index, pitem.iOrder);
6691 RECT rect, headerRect;
6692 OS.GetClientRect (handle, &rect);
6693 OS.SendMessage (hwndHeader, OS.HDM_GETITEMRECT, order [start], &headerRect);
6694 rect.left = Math.max (rect.left, headerRect.left);
6695 OS.SendMessage (hwndHeader, OS.HDM_GETITEMRECT, order [end], &headerRect);
6696 rect.right = Math.min (rect.right, headerRect.right);
6697 OS.InvalidateRect (handle, &rect, true);
6698 ignoreColumnMove = false;
6699 for (int i=start; i<=end; i++) {
6700 TreeColumn column = columns [order [i]];
6701 if (!column.isDisposed ()) {
6702 column.postEvent (DWT.Move);
6703 }
6704 }
6705 }
6706 }
6707 break;
6708 }
6709 case OS.HDN_ITEMCHANGINGW:
6710 case OS.HDN_ITEMCHANGINGA: {
6711 NMHEADER* phdn = cast(NMHEADER*)lParam;
6712 //OS.MoveMemory (phdn, lParam, NMHEADER.sizeof);
6713 if (phdn.pitem !is null) {
6714 HDITEM* newItem = phdn.pitem;
6715 //OS.MoveMemory (newItem, phdn.pitem, HDITEM.sizeof);
6716 if ((newItem.mask & OS.HDI_WIDTH) !is 0) {
6717 RECT rect;
6718 OS.GetClientRect (handle, &rect);
6719 HDITEM oldItem;
6720 oldItem.mask = OS.HDI_WIDTH;
6721 OS.SendMessage (hwndHeader, OS.HDM_GETITEM, phdn.iItem, &oldItem);
6722 int deltaX = newItem.cxy - oldItem.cxy;
6723 RECT headerRect;
6724 OS.SendMessage (hwndHeader, OS.HDM_GETITEMRECT, phdn.iItem, &headerRect);
6725 int gridWidth = linesVisible ? GRID_WIDTH : 0;
6726 rect.left = headerRect.right - gridWidth;
6727 int newX = rect.left + deltaX;
6728 rect.right = Math.max (rect.right, rect.left + Math.abs (deltaX));
6729 if (explorerTheme || (findImageControl () !is null || hooks (DWT.EraseItem) || hooks (DWT.PaintItem))) {
6730 OS.InvalidateRect (handle, &rect, true);
6731 OS.OffsetRect (&rect, deltaX, 0);
6732 OS.InvalidateRect (handle, &rect, true);
6733 } else {
6734 int flags = OS.SW_INVALIDATE | OS.SW_ERASE;
6735 OS.ScrollWindowEx (handle, deltaX, 0, &rect, null, null, null, flags);
6736 }
6737 if (OS.SendMessage (hwndHeader, OS.HDM_ORDERTOINDEX, phdn.iItem, 0) !is 0) {
6738 rect.left = headerRect.left;
6739 rect.right = newX;
6740 OS.InvalidateRect (handle, &rect, true);
6741 }
6742 setScrollWidth ();
6743 }
6744 }
6745 break;
6746 }
6747 case OS.HDN_ITEMCHANGEDW:
6748 case OS.HDN_ITEMCHANGEDA: {
6749 NMHEADER* phdn = cast(NMHEADER*)lParam;
6750 //OS.MoveMemory (phdn, lParam, NMHEADER.sizeof);
6751 if (phdn.pitem !is null) {
6752 HDITEM* pitem = phdn.pitem;
6753 //OS.MoveMemory (pitem, phdn.pitem, HDITEM.sizeof);
6754 if ((pitem.mask & OS.HDI_WIDTH) !is 0) {
6755 if (ignoreColumnMove) {
6756 if (!OS.IsWinCE && OS.WIN32_VERSION >= OS.VERSION (6, 0)) {
6757 int flags = OS.RDW_UPDATENOW | OS.RDW_ALLCHILDREN;
6758 OS.RedrawWindow (handle, null, null, flags);
6759 } else {
6760 if ((style & DWT.DOUBLE_BUFFERED) is 0) {
6761 int oldStyle = style;
6762 style |= DWT.DOUBLE_BUFFERED;
6763 OS.UpdateWindow (handle);
6764 style = oldStyle;
6765 }
6766 }
6767 }
6768 TreeColumn column = columns [phdn.iItem];
6769 if (column !is null) {
6770 column.updateToolTip (phdn.iItem);
6771 column.sendEvent (DWT.Resize);
6772 if (isDisposed ()) return LRESULT.ZERO;
6773 int count = OS.SendMessage (hwndHeader, OS.HDM_GETITEMCOUNT, 0, 0);
6774 TreeColumn [] newColumns = new TreeColumn [count];
6775 System.arraycopy (columns, 0, newColumns, 0, count);
6776 int [] order = new int [count];
6777 OS.SendMessage (hwndHeader, OS.HDM_GETORDERARRAY, count, order.ptr);
6778 bool moved = false;
6779 for (int i=0; i<count; i++) {
6780 TreeColumn nextColumn = newColumns [order [i]];
6781 if (moved && !nextColumn.isDisposed ()) {
6782 nextColumn.updateToolTip (order [i]);
6783 nextColumn.sendEvent (DWT.Move);
6784 }
6785 if (nextColumn is column) moved = true;
6786 }
6787 }
6788 }
6789 setScrollWidth ();
6790 }
6791 break;
6792 }
6793 case OS.HDN_ITEMCLICKW:
6794 case OS.HDN_ITEMCLICKA: {
6795 NMHEADER* phdn = cast(NMHEADER*)lParam;
6796 //OS.MoveMemory (phdn, lParam, NMHEADER.sizeof);
6797 TreeColumn column = columns [phdn.iItem];
6798 if (column !is null) {
6799 column.postEvent (DWT.Selection);
6800 }
6801 break;
6802 }
6803 case OS.HDN_ITEMDBLCLICKW:
6804 case OS.HDN_ITEMDBLCLICKA: {
6805 NMHEADER* phdn = cast(NMHEADER*)lParam;
6806 //OS.MoveMemory (phdn, lParam, NMHEADER.sizeof);
6807 TreeColumn column = columns [phdn.iItem];
6808 if (column !is null) {
6809 column.postEvent (DWT.DefaultSelection);
6810 }
6811 break;
6812 }
6813 default:
6814 }
6815 } 6959 }
6816 return super.wmNotify (hdr, wParam, lParam); 6960 return super.wmNotify (hdr, wParam, lParam);
6817 } 6961 }
6818 6962
6819 override LRESULT wmNotifyChild (NMHDR* hdr, int wParam, int lParam) { 6963 override LRESULT wmNotifyChild (NMHDR* hdr, int wParam, int lParam) {
6850 } 6994 }
6851 } 6995 }
6852 if (checkVisible) { 6996 if (checkVisible) {
6853 if (drawCount !is 0 || !OS.IsWindowVisible (handle)) break; 6997 if (drawCount !is 0 || !OS.IsWindowVisible (handle)) break;
6854 RECT itemRect; 6998 RECT itemRect;
6855 itemRect.left = cast(int) lptvdi.item.hItem; 6999 if (!OS.TreeView_GetItemRect (handle, lptvdi.item.hItem, &itemRect, false)) {
6856 if (OS.SendMessage (handle, OS.TVM_GETITEMRECT, 0, &itemRect) is 0) {
6857 break; 7000 break;
6858 } 7001 }
6859 RECT rect; 7002 RECT rect;
6860 OS.GetClientRect (handle, &rect); 7003 OS.GetClientRect (handle, &rect);
6861 if (!OS.IntersectRect (&rect, &rect, &itemRect)) break; 7004 if (!OS.IntersectRect (&rect, &rect, &itemRect)) break;
6983 * with double clicking, then the tree expand 7126 * with double clicking, then the tree expand
6984 * is unexpected and unwanted. The fix is to 7127 * is unexpected and unwanted. The fix is to
6985 * avoid the operation by testing to see whether 7128 * avoid the operation by testing to see whether
6986 * the mouse was inside a tree item. 7129 * the mouse was inside a tree item.
6987 */ 7130 */
7131 if (hooks (DWT.MeasureItem)) return LRESULT.ONE;
6988 if (hooks (DWT.DefaultSelection)) { 7132 if (hooks (DWT.DefaultSelection)) {
6989 POINT pt; 7133 POINT pt;
6990 int pos = OS.GetMessagePos (); 7134 int pos = OS.GetMessagePos ();
6991 pt.x = cast(short) (pos & 0xFFFF); 7135 OS.POINTSTOPOINT (pt, pos);
6992 pt.y = cast(short) (pos >> 16);
6993 OS.ScreenToClient (handle, &pt); 7136 OS.ScreenToClient (handle, &pt);
6994 TVHITTESTINFO lpht; 7137 TVHITTESTINFO lpht;
6995 lpht.pt.x = pt.x; 7138 lpht.pt.x = pt.x;
6996 lpht.pt.y = pt.y; 7139 lpht.pt.y = pt.y;
6997 OS.SendMessage (handle, OS.TVM_HITTEST, 0, &lpht); 7140 OS.SendMessage (handle, OS.TVM_HITTEST, 0, &lpht);
7026 case OS.TVN_SELCHANGINGA: 7169 case OS.TVN_SELCHANGINGA:
7027 case OS.TVN_SELCHANGINGW: { 7170 case OS.TVN_SELCHANGINGW: {
7028 if ((style & DWT.MULTI) !is 0) { 7171 if ((style & DWT.MULTI) !is 0) {
7029 if (lockSelection) { 7172 if (lockSelection) {
7030 /* Save the old selection state for both items */ 7173 /* Save the old selection state for both items */
7031 TVITEM tvItem; 7174 auto treeView = cast(NMTREEVIEW*)lParam;
7032 int offset1 = NMHDR.sizeof + 4; 7175 TVITEM* tvItem = &treeView.itemOld;
7033 OS.MoveMemory (&tvItem, lParam + offset1, TVITEM.sizeof);
7034 oldSelected = (tvItem.state & OS.TVIS_SELECTED) !is 0; 7176 oldSelected = (tvItem.state & OS.TVIS_SELECTED) !is 0;
7035 int offset2 = NMHDR.sizeof + 4 + TVITEM.sizeof; 7177 tvItem = &treeView.itemNew;
7036 OS.MoveMemory (&tvItem, lParam + offset2, TVITEM.sizeof);
7037 newSelected = (tvItem.state & OS.TVIS_SELECTED) !is 0; 7178 newSelected = (tvItem.state & OS.TVIS_SELECTED) !is 0;
7038 } 7179 }
7039 } 7180 }
7040 if (!ignoreSelect && !ignoreDeselect) { 7181 if (!ignoreSelect && !ignoreDeselect) {
7041 hAnchor = null; 7182 hAnchor = null;
7043 } 7184 }
7044 break; 7185 break;
7045 } 7186 }
7046 case OS.TVN_SELCHANGEDA: 7187 case OS.TVN_SELCHANGEDA:
7047 case OS.TVN_SELCHANGEDW: { 7188 case OS.TVN_SELCHANGEDW: {
7189 NMTREEVIEW* treeView = null;
7048 if ((style & DWT.MULTI) !is 0) { 7190 if ((style & DWT.MULTI) !is 0) {
7049 if (lockSelection) { 7191 if (lockSelection) {
7050 /* Restore the old selection state of both items */ 7192 /* Restore the old selection state of both items */
7051 if (oldSelected) { 7193 if (oldSelected) {
7052 TVITEM tvItem; 7194 if (treeView is null) {
7053 int offset = NMHDR.sizeof + 4; 7195 treeView = cast(NMTREEVIEW*)lParam;
7054 OS.MoveMemory (&tvItem, lParam + offset, TVITEM.sizeof); 7196 }
7197 TVITEM tvItem = treeView.itemOld;
7055 tvItem.mask = OS.TVIF_STATE; 7198 tvItem.mask = OS.TVIF_STATE;
7056 tvItem.stateMask = OS.TVIS_SELECTED; 7199 tvItem.stateMask = OS.TVIS_SELECTED;
7057 tvItem.state = OS.TVIS_SELECTED; 7200 tvItem.state = OS.TVIS_SELECTED;
7058 OS.SendMessage (handle, OS.TVM_SETITEM, 0, &tvItem); 7201 OS.SendMessage (handle, OS.TVM_SETITEM, 0, &tvItem);
7059 } 7202 }
7060 if (!newSelected && ignoreSelect) { 7203 if (!newSelected && ignoreSelect) {
7061 TVITEM tvItem; 7204 if (treeView is null) {
7062 int offset = NMHDR.sizeof + 4 + TVITEM.sizeof; 7205 treeView = cast(NMTREEVIEW*)lParam;
7063 OS.MoveMemory (&tvItem, lParam + offset, TVITEM.sizeof); 7206 }
7207 TVITEM tvItem = treeView.itemNew;
7064 tvItem.mask = OS.TVIF_STATE; 7208 tvItem.mask = OS.TVIF_STATE;
7065 tvItem.stateMask = OS.TVIS_SELECTED; 7209 tvItem.stateMask = OS.TVIS_SELECTED;
7066 tvItem.state = 0; 7210 tvItem.state = 0;
7067 OS.SendMessage (handle, OS.TVM_SETITEM, 0, &tvItem); 7211 OS.SendMessage (handle, OS.TVM_SETITEM, 0, &tvItem);
7068 } 7212 }
7069 } 7213 }
7070 } 7214 }
7071 if (!ignoreSelect) { 7215 if (!ignoreSelect) {
7072 TVITEM tvItem; 7216 if (treeView is null) {
7073 int offset = NMHDR.sizeof + 4 + TVITEM.sizeof; 7217 treeView = cast(NMTREEVIEW*)lParam;
7074 OS.MoveMemory (&tvItem, lParam + offset, TVITEM.sizeof); 7218 }
7219 TVITEM tvItem = treeView.itemNew;
7075 hAnchor = tvItem.hItem; 7220 hAnchor = tvItem.hItem;
7076 Event event = new Event (); 7221 Event event = new Event ();
7077 event.item = _getItem (&tvItem.hItem, tvItem.lParam); 7222 event.item = _getItem (&tvItem.hItem, tvItem.lParam);
7078 postEvent (DWT.Selection, event); 7223 postEvent (DWT.Selection, event);
7079 } 7224 }
7097 */ 7242 */
7098 if (hInsert !is null) { 7243 if (hInsert !is null) {
7099 OS.SendMessage (handle, OS.TVM_SETINSERTMARK, 0, 0); 7244 OS.SendMessage (handle, OS.TVM_SETINSERTMARK, 0, 0);
7100 } 7245 }
7101 if (!ignoreExpand) { 7246 if (!ignoreExpand) {
7102 TVITEM tvItem; 7247 NMTREEVIEW* treeView = cast(NMTREEVIEW*)lParam;
7103 int offset = NMHDR.sizeof + 4 + TVITEM.sizeof; 7248
7104 OS.MoveMemory (&tvItem, lParam + offset, TVITEM.sizeof); 7249 TVITEM* tvItem = &treeView.itemNew;
7105 /* 7250 /*
7106 * Feature in Windows. In some cases, TVM_ITEMEXPANDING 7251 * Feature in Windows. In some cases, TVM_ITEMEXPANDING
7107 * is sent from within TVM_DELETEITEM for the tree item 7252 * is sent from within TVM_DELETEITEM for the tree item
7108 * being destroyed. By the time the message is sent, 7253 * being destroyed. By the time the message is sent,
7109 * the item has already been removed from the list of 7254 * the item has already been removed from the list of
7112 if (items is null) break; 7257 if (items is null) break;
7113 TreeItem item = _getItem (tvItem.hItem, tvItem.lParam); 7258 TreeItem item = _getItem (tvItem.hItem, tvItem.lParam);
7114 if (item is null) break; 7259 if (item is null) break;
7115 Event event = new Event (); 7260 Event event = new Event ();
7116 event.item = item; 7261 event.item = item;
7117 int action = *cast(int*)(lParam + NMHDR.sizeof); 7262 switch (treeView.action) {
7118 //OS.MoveMemory (action, lParam + NMHDR.sizeof, 4);
7119 switch (action) {
7120 case OS.TVE_EXPAND: 7263 case OS.TVE_EXPAND:
7121 /* 7264 /*
7122 * Bug in Windows. When the numeric keypad asterisk 7265 * Bug in Windows. When the numeric keypad asterisk
7123 * key is used to expand every item in the tree, Windows 7266 * key is used to expand every item in the tree, Windows
7124 * sends TVN_ITEMEXPANDING to items in the tree that 7267 * sends TVN_ITEMEXPANDING to items in the tree that
7174 * This means that the image gets darker each time. 7317 * This means that the image gets darker each time.
7175 * The fix is to redraw the item. 7318 * The fix is to redraw the item.
7176 */ 7319 */
7177 if (!OS.IsWinCE && OS.COMCTL32_MAJOR >= 6) { 7320 if (!OS.IsWinCE && OS.COMCTL32_MAJOR >= 6) {
7178 if (imageList !is null) { 7321 if (imageList !is null) {
7179 TVITEM tvItem; 7322 NMTREEVIEW* treeView = cast(NMTREEVIEW*)lParam;
7180 int offset = NMHDR.sizeof + 4 + TVITEM.sizeof; 7323
7181 OS.MoveMemory (&tvItem, lParam + offset, TVITEM.sizeof); 7324 TVITEM* tvItem = &treeView.itemNew;
7182 if (tvItem.hItem !is null) { 7325 if (tvItem.hItem !is null) {
7183 int bits = OS.GetWindowLong (handle, OS.GWL_STYLE); 7326 int bits = OS.GetWindowLong (handle, OS.GWL_STYLE);
7184 if ((bits & OS.TVS_FULLROWSELECT) is 0) { 7327 if ((bits & OS.TVS_FULLROWSELECT) is 0) {
7185 RECT rect; 7328 RECT rect;
7186 rect.left = cast(int)tvItem.hItem; 7329 if (OS.TreeView_GetItemRect (handle, tvItem.hItem, &rect, false)) {
7187 OS.SendMessage (handle, OS.TVM_GETITEMRECT, 0, &rect); 7330 OS.InvalidateRect (handle, &rect, true);
7188 OS.InvalidateRect (handle, &rect, true); 7331 }
7189 } 7332 }
7190 } 7333 }
7191 } 7334 }
7192 } 7335 }
7193 updateScrollBar (); 7336 updateScrollBar ();
7194 break; 7337 break;
7195 } 7338 }
7196 case OS.TVN_BEGINDRAGA: 7339 case OS.TVN_BEGINDRAGA:
7197 case OS.TVN_BEGINDRAGW: 7340 case OS.TVN_BEGINDRAGW:
7341 if (OS.GetKeyState (OS.VK_LBUTTON) >= 0) break;
7342 //FALL THROUGH
7198 case OS.TVN_BEGINRDRAGA: 7343 case OS.TVN_BEGINRDRAGA:
7199 case OS.TVN_BEGINRDRAGW: { 7344 case OS.TVN_BEGINRDRAGW: {
7200 TVITEM tvItem; 7345 dragStarted = true;
7201 int offset = NMHDR.sizeof + 4 + TVITEM.sizeof; 7346 NMTREEVIEW* treeView = cast(NMTREEVIEW*)lParam;
7202 OS.MoveMemory (&tvItem, lParam + offset, TVITEM.sizeof); 7347 TVITEM* tvItem = &treeView.itemNew;
7203 if (tvItem.hItem !is null && (tvItem.state & OS.TVIS_SELECTED) is 0) { 7348 if (tvItem.hItem !is null && (tvItem.state & OS.TVIS_SELECTED) is 0) {
7204 hSelect = tvItem.hItem; 7349 hSelect = tvItem.hItem;
7205 ignoreSelect = ignoreDeselect = true; 7350 ignoreSelect = ignoreDeselect = true;
7206 OS.SendMessage (handle, OS.TVM_SELECTITEM, OS.TVGN_CARET, tvItem.hItem); 7351 OS.SendMessage (handle, OS.TVM_SELECTITEM, OS.TVGN_CARET, tvItem.hItem);
7207 ignoreSelect = ignoreDeselect = false; 7352 ignoreSelect = ignoreDeselect = false;
7208 hSelect = null; 7353 hSelect = null;
7209 } 7354 }
7210 dragStarted = true;
7211 break; 7355 break;
7212 } 7356 }
7213 case OS.NM_RECOGNIZEGESTURE: { 7357 case OS.NM_RECOGNIZEGESTURE: {
7214 /* 7358 /*
7215 * Feature in Pocket PC. The tree and table controls detect the tap 7359 * Feature in Pocket PC. The tree and table controls detect the tap
7242 default: 7386 default:
7243 } 7387 }
7244 return super.wmNotifyChild (hdr, wParam, lParam); 7388 return super.wmNotifyChild (hdr, wParam, lParam);
7245 } 7389 }
7246 7390
7247 } 7391 LRESULT wmNotifyHeader (NMHDR* hdr, int /*long*/ wParam, int /*long*/ lParam) {
7392 /*
7393 * Feature in Windows. On NT, the automatically created
7394 * header control is created as a UNICODE window, not an
7395 * ANSI window despite the fact that the parent is created
7396 * as an ANSI window. This means that it sends UNICODE
7397 * notification messages to the parent window on NT for
7398 * no good reason. The data and size in the NMHEADER and
7399 * HDITEM structs is identical between the platforms so no
7400 * different message is actually necessary. Despite this,
7401 * Windows sends different messages. The fix is to look
7402 * for both messages, despite the platform. This works
7403 * because only one will be sent on either platform, never
7404 * both.
7405 */
7406 switch (hdr.code) {
7407 case OS.HDN_BEGINTRACKW:
7408 case OS.HDN_BEGINTRACKA:
7409 case OS.HDN_DIVIDERDBLCLICKW:
7410 case OS.HDN_DIVIDERDBLCLICKA: {
7411 NMHEADER* phdn = cast(NMHEADER*)lParam;
7412 TreeColumn column = columns [phdn.iItem];
7413 if (column !is null && !column.getResizable ()) {
7414 return LRESULT.ONE;
7415 }
7416 ignoreColumnMove = true;
7417 switch (hdr.code) {
7418 case OS.HDN_DIVIDERDBLCLICKW:
7419 case OS.HDN_DIVIDERDBLCLICKA:
7420 if (column !is null) column.pack ();
7421 }
7422 break;
7423 }
7424 case OS.NM_RELEASEDCAPTURE: {
7425 if (!ignoreColumnMove) {
7426 for (int i=0; i<columnCount; i++) {
7427 TreeColumn column = columns [i];
7428 column.updateToolTip (i);
7429 }
7430 updateImageList ();
7431 }
7432 ignoreColumnMove = false;
7433 break;
7434 }
7435 case OS.HDN_BEGINDRAG: {
7436 if (ignoreColumnMove) return LRESULT.ONE;
7437 NMHEADER* phdn = cast(NMHEADER*)lParam;
7438 if (phdn.iItem !is -1) {
7439 TreeColumn column = columns [phdn.iItem];
7440 if (column !is null && !column.getMoveable ()) {
7441 ignoreColumnMove = true;
7442 return LRESULT.ONE;
7443 }
7444 }
7445 break;
7446 }
7447 case OS.HDN_ENDDRAG: {
7448 NMHEADER* phdn = cast(NMHEADER*)lParam;
7449 if (cast(int)phdn.iItem !is -1 && phdn.pitem !is null) {
7450 HDITEM* pitem = cast(HDITEM*)phdn.pitem;
7451 if ((pitem.mask & OS.HDI_ORDER) !is 0 && pitem.iOrder !is -1) {
7452 int [] order = new int [columnCount];
7453 OS.SendMessage (hwndHeader, OS.HDM_GETORDERARRAY, columnCount, order.ptr);
7454 int index = 0;
7455 while (index < order.length) {
7456 if (order [index] is phdn.iItem) break;
7457 index++;
7458 }
7459 if (index is order.length) index = 0;
7460 if (index is pitem.iOrder) break;
7461 int start = Math.min (index, pitem.iOrder);
7462 int end = Math.max (index, pitem.iOrder);
7463 RECT rect, headerRect;
7464 OS.GetClientRect (handle, &rect);
7465 OS.SendMessage (hwndHeader, OS.HDM_GETITEMRECT, order [start], &headerRect);
7466 rect.left = Math.max (rect.left, headerRect.left);
7467 OS.SendMessage (hwndHeader, OS.HDM_GETITEMRECT, order [end], &headerRect);
7468 rect.right = Math.min (rect.right, headerRect.right);
7469 OS.InvalidateRect (handle, &rect, true);
7470 ignoreColumnMove = false;
7471 for (int i=start; i<=end; i++) {
7472 TreeColumn column = columns [order [i]];
7473 if (!column.isDisposed ()) {
7474 column.postEvent (DWT.Move);
7475 }
7476 }
7477 }
7478 }
7479 break;
7480 }
7481 case OS.HDN_ITEMCHANGINGW:
7482 case OS.HDN_ITEMCHANGINGA: {
7483 NMHEADER* phdn = cast(NMHEADER*)lParam;
7484 if (phdn.pitem !is null) {
7485 HDITEM* newItem = cast(HDITEM*)phdn.pitem;
7486 if ((newItem.mask & OS.HDI_WIDTH) !is 0) {
7487 RECT rect;
7488 OS.GetClientRect (handle, &rect);
7489 HDITEM oldItem;
7490 oldItem.mask = OS.HDI_WIDTH;
7491 OS.SendMessage (hwndHeader, OS.HDM_GETITEM, phdn.iItem, &oldItem);
7492 int deltaX = newItem.cxy - oldItem.cxy;
7493 RECT headerRect;
7494 OS.SendMessage (hwndHeader, OS.HDM_GETITEMRECT, phdn.iItem, &headerRect);
7495 int gridWidth = linesVisible ? GRID_WIDTH : 0;
7496 rect.left = headerRect.right - gridWidth;
7497 int newX = rect.left + deltaX;
7498 rect.right = Math.max (rect.right, rect.left + Math.abs (deltaX));
7499 if (explorerTheme || (findImageControl () !is null || hooks (DWT.MeasureItem) || hooks (DWT.EraseItem) || hooks (DWT.PaintItem))) {
7500 rect.left -= OS.GetSystemMetrics (OS.SM_CXFOCUSBORDER);
7501 OS.InvalidateRect (handle, &rect, true);
7502 OS.OffsetRect (&rect, deltaX, 0);
7503 OS.InvalidateRect (handle, &rect, true);
7504 } else {
7505 int flags = OS.SW_INVALIDATE | OS.SW_ERASE;
7506 OS.ScrollWindowEx (handle, deltaX, 0, &rect, null, null, null, flags);
7507 }
7508 if (OS.SendMessage (hwndHeader, OS.HDM_ORDERTOINDEX, phdn.iItem, 0) !is 0) {
7509 rect.left = headerRect.left;
7510 rect.right = newX;
7511 OS.InvalidateRect (handle, &rect, true);
7512 }
7513 setScrollWidth ();
7514 }
7515 }
7516 break;
7517 }
7518 case OS.HDN_ITEMCHANGEDW:
7519 case OS.HDN_ITEMCHANGEDA: {
7520 NMHEADER* phdn = cast(NMHEADER*)lParam;
7521 if (phdn.pitem !is null) {
7522 HDITEM* pitem = cast(HDITEM*)phdn.pitem;
7523 if ((pitem.mask & OS.HDI_WIDTH) !is 0) {
7524 if (ignoreColumnMove) {
7525 if (!OS.IsWinCE && OS.WIN32_VERSION >= OS.VERSION (6, 0)) {
7526 int flags = OS.RDW_UPDATENOW | OS.RDW_ALLCHILDREN;
7527 OS.RedrawWindow (handle, null, null, flags);
7528 } else {
7529 if ((style & DWT.DOUBLE_BUFFERED) is 0) {
7530 int oldStyle = style;
7531 style |= DWT.DOUBLE_BUFFERED;
7532 OS.UpdateWindow (handle);
7533 style = oldStyle;
7534 }
7535 }
7536 }
7537 TreeColumn column = columns [phdn.iItem];
7538 if (column !is null) {
7539 column.updateToolTip (phdn.iItem);
7540 column.sendEvent (DWT.Resize);
7541 if (isDisposed ()) return LRESULT.ZERO;
7542 TreeColumn [] newColumns = new TreeColumn [columnCount];
7543 System.arraycopy (columns, 0, newColumns, 0, columnCount);
7544 int [] order = new int [columnCount];
7545 OS.SendMessage (hwndHeader, OS.HDM_GETORDERARRAY, columnCount, order.ptr);
7546 bool moved = false;
7547 for (int i=0; i<columnCount; i++) {
7548 TreeColumn nextColumn = newColumns [order [i]];
7549 if (moved && !nextColumn.isDisposed ()) {
7550 nextColumn.updateToolTip (order [i]);
7551 nextColumn.sendEvent (DWT.Move);
7552 }
7553 if (nextColumn is column) moved = true;
7554 }
7555 }
7556 }
7557 setScrollWidth ();
7558 }
7559 break;
7560 }
7561 case OS.HDN_ITEMCLICKW:
7562 case OS.HDN_ITEMCLICKA: {
7563 NMHEADER* phdn = cast(NMHEADER*)lParam;
7564 TreeColumn column = columns [phdn.iItem];
7565 if (column !is null) {
7566 column.postEvent (DWT.Selection);
7567 }
7568 break;
7569 }
7570 case OS.HDN_ITEMDBLCLICKW:
7571 case OS.HDN_ITEMDBLCLICKA: {
7572 NMHEADER* phdn = cast(NMHEADER*)lParam;
7573 TreeColumn column = columns [phdn.iItem];
7574 if (column !is null) {
7575 column.postEvent (DWT.DefaultSelection);
7576 }
7577 break;
7578 }
7579 }
7580 return null;
7581 }
7582
7583 LRESULT wmNotifyToolTip (NMHDR* hdr, int /*long*/ wParam, int /*long*/ lParam) {
7584 if (OS.IsWinCE) return null;
7585 switch (hdr.code) {
7586 case OS.NM_CUSTOMDRAW: {
7587 NMTTCUSTOMDRAW* nmcd = cast(NMTTCUSTOMDRAW*)lParam;
7588 return wmNotifyToolTip (nmcd, lParam);
7589 }
7590 case OS.TTN_SHOW: {
7591 LRESULT result = super.wmNotify (hdr, wParam, lParam);
7592 if (result !is null) return result;
7593 int pos = OS.GetMessagePos ();
7594 POINT pt;
7595 OS.POINTSTOPOINT (pt, pos);
7596 OS.ScreenToClient (handle, &pt);
7597 int index;
7598 TreeItem item;
7599 RECT cellRect, itemRect;
7600 if (findCell (pt.x, pt.y, item, index, cellRect, itemRect)) {
7601 RECT* toolRect = toolTipRect (&itemRect);
7602 OS.MapWindowPoints (handle, null, cast(POINT*)toolRect, 2);
7603 int width = toolRect.right - toolRect.left;
7604 int height = toolRect.bottom - toolRect.top;
7605 int flags = OS.SWP_NOACTIVATE | OS.SWP_NOZORDER | OS.SWP_NOSIZE;
7606 if (isCustomToolTip ()) flags &= ~OS.SWP_NOSIZE;
7607 SetWindowPos (itemToolTipHandle, null, toolRect.left, toolRect.top, width, height, flags);
7608 return LRESULT.ONE;
7609 }
7610 return result;
7611 }
7612 }
7613 return null;
7614 }
7615
7616 LRESULT wmNotifyToolTip (NMTTCUSTOMDRAW* nmcd, int /*long*/ lParam) {
7617 if (OS.IsWinCE) return null;
7618 switch (nmcd.nmcd.dwDrawStage) {
7619 case OS.CDDS_PREPAINT: {
7620 if (isCustomToolTip ()) {
7621 //TEMPORARY CODE
7622 //nmcd.uDrawFlags |= OS.DT_CALCRECT;
7623 //OS.MoveMemory (lParam, nmcd, NMTTCUSTOMDRAW.sizeof);
7624 if (!OS.IsWinCE && OS.WIN32_VERSION < OS.VERSION (6, 0)) {
7625 OS.SetTextColor (nmcd.nmcd.hdc, OS.GetSysColor (OS.COLOR_INFOBK));
7626 }
7627 return new LRESULT (OS.CDRF_NOTIFYPOSTPAINT | OS.CDRF_NEWFONT);
7628 }
7629 break;
7630 }
7631 case OS.CDDS_POSTPAINT: {
7632 if (!OS.IsWinCE && OS.WIN32_VERSION < OS.VERSION (6, 0)) {
7633 OS.SetTextColor (nmcd.nmcd.hdc, OS.GetSysColor (OS.COLOR_INFOTEXT));
7634 }
7635 if (OS.SendMessage (itemToolTipHandle, OS.TTM_GETCURRENTTOOL, 0, 0) !is 0) {
7636 TOOLINFO lpti;
7637 lpti.cbSize = TOOLINFO.sizeof;
7638 if (OS.SendMessage (itemToolTipHandle, OS.TTM_GETCURRENTTOOL, 0, cast(int)&lpti) !is 0) {
7639 int index;
7640 TreeItem item;
7641 RECT cellRect, itemRect;
7642 int pos = OS.GetMessagePos ();
7643 POINT pt;
7644 OS.POINTSTOPOINT (pt, pos);
7645 OS.ScreenToClient (handle, &pt);
7646 if (findCell (pt.x, pt.y, item, index, cellRect, itemRect)) {
7647 auto hDC = OS.GetDC (handle);
7648 auto hFont = item.fontHandle (index);
7649 if (hFont is cast(HFONT)-1) hFont = cast(HFONT) OS.SendMessage (handle, OS.WM_GETFONT, 0, 0);
7650 HFONT oldFont = OS.SelectObject (hDC, hFont);
7651 LRESULT result = null;
7652 bool drawForeground = true;
7653 cellRect = item.getBounds (index, true, true, false, false, false, hDC);
7654 if (hooks (DWT.EraseItem)) {
7655 Event event = sendEraseItemEvent (item, nmcd, index, &cellRect);
7656 if (isDisposed () || item.isDisposed ()) break;
7657 if (event.doit) {
7658 drawForeground = (event.detail & DWT.FOREGROUND) !is 0;
7659 } else {
7660 drawForeground = false;
7661 }
7662 }
7663 if (drawForeground) {
7664 int nSavedDC = OS.SaveDC (nmcd.nmcd.hdc);
7665 int gridWidth = getLinesVisible () ? Table.GRID_WIDTH : 0;
7666 RECT* insetRect = toolTipInset (&cellRect);
7667 OS.SetWindowOrgEx (nmcd.nmcd.hdc, insetRect.left, insetRect.top, null);
7668 GCData data = new GCData ();
7669 data.device = display;
7670 data.foreground = OS.GetTextColor (nmcd.nmcd.hdc);
7671 data.background = OS.GetBkColor (nmcd.nmcd.hdc);
7672 data.font = Font.win32_new (display, hFont);
7673 GC gc = GC.win32_new (nmcd.nmcd.hdc, data);
7674 int x = cellRect.left + INSET;
7675 if (index !is 0) x -= gridWidth;
7676 Image image = item.getImage (index);
7677 if (image !is null || index is 0) {
7678 Point size = getImageSize ();
7679 RECT imageRect = item.getBounds (index, false, true, false, false, false, hDC);
7680 if (imageList is null) size.x = imageRect.right - imageRect.left;
7681 if (image !is null) {
7682 Rectangle rect = image.getBounds ();
7683 gc.drawImage (image, rect.x, rect.y, rect.width, rect.height, x, imageRect.top, size.x, size.y);
7684 x += INSET + (index is 0 ? 1 : 0);
7685 }
7686 x += size.x;
7687 } else {
7688 x += INSET;
7689 }
7690 String string = item.getText (index);
7691 if (string !is null) {
7692 int flags = OS.DT_NOPREFIX | OS.DT_SINGLELINE | OS.DT_VCENTER;
7693 TreeColumn column = columns !is null ? columns [index] : null;
7694 if (column !is null) {
7695 if ((column.style & DWT.CENTER) !is 0) flags |= OS.DT_CENTER;
7696 if ((column.style & DWT.RIGHT) !is 0) flags |= OS.DT_RIGHT;
7697 }
7698 TCHAR[] buffer = StrToTCHARs (getCodePage (), string, false);
7699 RECT textRect;
7700 OS.SetRect (&textRect, x, cellRect.top, cellRect.right, cellRect.bottom);
7701 OS.DrawText (nmcd.nmcd.hdc, buffer.ptr, buffer.length, &textRect, flags);
7702 }
7703 gc.dispose ();
7704 OS.RestoreDC (nmcd.nmcd.hdc, nSavedDC);
7705 }
7706 if (hooks (DWT.PaintItem)) {
7707 itemRect = item.getBounds (index, true, true, false, false, false, hDC);
7708 sendPaintItemEvent (item, nmcd, index, &itemRect);
7709 }
7710 OS.SelectObject (hDC, oldFont);
7711 OS.ReleaseDC (handle, hDC);
7712 if (result !is null) return result;
7713 }
7714 break;
7715 }
7716 }
7717 break;
7718 }
7719 }
7720 return null;
7721 }
7722
7723 }