3 * Copyright 1998 Eric Kohl <ekohl@abo.rhein-zeitung.de>
4 * Copyright 1998,1999 Alex Priem <alexp@sci.kun.nl>
5 * Copyright 1999 Sylvain St-Germain
9 * Using DPA to store the item ptr would be good.
10 * Node label edition is implemented but something appened in wine in the
11 * two last weeks of march 99 that broke it.
13 -small array containing info about positions.
14 -better implementation of RefreshItem:
15 1) draw lines between parents
17 3) draw lines from parent<->items.
18 -implement partial drawing?
19 * -drag&drop: TVM_CREATEDRAGIMAGE should create drag bitmap.
20 * -scrollbars: horizontal scrollbar doesn't work.
24 * FIXME: check fontsize. (uRealItemHeight)
25 * test focusItem (redraw in different color)
28 better implementation.
29 * WM_HSCROLL is broken.
30 * use separate routine to get item text/image.
32 * Separate drawing/calculation.
34 * FIXMEs (for personal use)
35 Expand: -ctlmacro expands twice ->toggle.
36 -DblClick: ctlmacro.exe's NM_DBLCLK seems to go wrong (returns FALSE).
37 -treehelper: stack corruption makes big window.
47 #include "debugtools.h"
49 DEFAULT_DEBUG_CHANNEL(treeview
)
51 /* ffs should be in <string.h>. */
53 /* Defines, since they do not need to return previous state, and nr
54 * has no side effects in this file.
56 #define tv_test_bit(nr,bf) (((LPBYTE)bf)[nr>>3]&(1<<(nr&7)))
57 #define tv_set_bit(nr,bf) ((LPBYTE)bf)[nr>>3]|=(1<<(nr&7))
58 #define tv_clear_bit(nr,bf) ((LPBYTE)bf)[nr>>3]&=~(1<<(nr&7))
61 #define TREEVIEW_GetInfoPtr(hwnd) \
62 ((TREEVIEW_INFO *) GetWindowLongA( hwnd, 0))
65 TREEVIEW_SendSimpleNotify (HWND hwnd
, UINT code
);
67 TREEVIEW_SendTreeviewNotify (HWND hwnd
, UINT code
, UINT action
,
68 HTREEITEM oldItem
, HTREEITEM newItem
);
70 TREEVIEW_SendTreeviewDnDNotify (HWND hwnd
, UINT code
, HTREEITEM dragItem
,
73 TREEVIEW_SendDispInfoNotify (HWND hwnd
, TREEVIEW_ITEM
*wineItem
,
74 UINT code
, UINT what
);
76 TREEVIEW_SendCustomDrawNotify (HWND hwnd
, DWORD dwDrawStage
, HDC hdc
,
79 TREEVIEW_SendCustomDrawItemNotify (HWND hwnd
, HDC hdc
,
80 TREEVIEW_ITEM
*tvItem
, UINT uItemDrawState
);
82 TREEVIEW_DoSelectItem (HWND hwnd
, INT action
, HTREEITEM newSelect
, INT cause
);
84 TREEVIEW_Refresh (HWND hwnd
);
86 static LRESULT CALLBACK
87 TREEVIEW_Edit_SubclassProc (HWND hwnd
, UINT uMsg
, WPARAM wParam
,
91 TREEVIEW_EndEditLabelNow (HWND hwnd
, WPARAM wParam
, LPARAM lParam
);
96 /* helper functions. Work with the assumption that validity of operands
97 is checked beforehand, and that tree state is valid. */
99 /* FIXME: MS documentation says `GetNextVisibleItem' returns NULL
100 if not succesfull'. Probably only applies to derefencing infoPtr
101 (ie we are offered a valid treeview structure)
102 and not whether there is a next `visible' child.
103 FIXME: check other failures.
106 /***************************************************************************
107 * This method returns the TREEVIEW_ITEM object given the handle
109 static TREEVIEW_ITEM
* TREEVIEW_ValidItem(
110 TREEVIEW_INFO
*infoPtr
,
113 if ((!handle
) || (handle
>infoPtr
->uMaxHandle
))
116 if (tv_test_bit ((INT
)handle
, infoPtr
->freeList
))
119 return &infoPtr
->items
[(INT
)handle
];
122 /***************************************************************************
123 * This method returns the last expanded child item of a tree node
125 static TREEVIEW_ITEM
*TREEVIEW_GetLastListItem(
126 TREEVIEW_INFO
*infoPtr
,
127 TREEVIEW_ITEM
*tvItem
)
130 TREEVIEW_ITEM
*wineItem
= tvItem
;
133 * Get this item last sibling
135 while (wineItem
->sibling
)
136 wineItem
=& infoPtr
->items
[(INT
)wineItem
->sibling
];
139 * If the last sibling has expanded children, restart.
141 if ( ( wineItem
->cChildren
> 0 ) && ( wineItem
->state
& TVIS_EXPANDED
) )
142 return TREEVIEW_GetLastListItem(
144 &(infoPtr
->items
[(INT
)wineItem
->firstChild
]));
149 /***************************************************************************
150 * This method returns the previous physical item in the list not
151 * considering the tree hierarchy.
153 static TREEVIEW_ITEM
*TREEVIEW_GetPrevListItem(
154 TREEVIEW_INFO
*infoPtr
,
155 TREEVIEW_ITEM
*tvItem
)
157 if (tvItem
->upsibling
)
160 * This item has a upsibling, get the last item. Since, GetLastListItem
161 * first looks at siblings, we must feed it with the first child.
163 TREEVIEW_ITEM
*upItem
= &infoPtr
->items
[(INT
)tvItem
->upsibling
];
165 if ( ( upItem
->cChildren
> 0 ) && ( upItem
->state
& TVIS_EXPANDED
) )
166 return TREEVIEW_GetLastListItem(
168 &infoPtr
->items
[(INT
)upItem
->firstChild
]);
175 * this item does not have a upsibling, get the parent
178 return &infoPtr
->items
[(INT
)tvItem
->parent
];
185 /***************************************************************************
186 * This method returns the next physical item in the treeview not
187 * considering the tree hierarchy.
189 static TREEVIEW_ITEM
*TREEVIEW_GetNextListItem(
190 TREEVIEW_INFO
*infoPtr
,
191 TREEVIEW_ITEM
*tvItem
)
193 TREEVIEW_ITEM
*wineItem
= NULL
;
196 * If this item has children and is expanded, return the first child
198 if ((tvItem
->firstChild
) && (tvItem
->state
& TVIS_EXPANDED
))
199 return (& infoPtr
->items
[(INT
)tvItem
->firstChild
]);
203 * try to get the sibling
206 return (& infoPtr
->items
[(INT
)tvItem
->sibling
]);
209 * Otherwise, get the parent's sibling.
212 while (wineItem
->parent
) {
213 wineItem
=& infoPtr
->items
[(INT
)wineItem
->parent
];
214 if (wineItem
->sibling
)
215 return (& infoPtr
->items
[(INT
)wineItem
->sibling
]);
221 /***************************************************************************
222 * This method returns the nth item starting at the given item. It returns
223 * the last item (or first) we we run out of items.
225 * Will scroll backward if count is <0.
226 * forward if count is >0.
228 static TREEVIEW_ITEM
*TREEVIEW_GetListItem(
229 TREEVIEW_INFO
*infoPtr
,
230 TREEVIEW_ITEM
*tvItem
,
233 TREEVIEW_ITEM
*previousItem
= NULL
;
234 TREEVIEW_ITEM
*wineItem
= tvItem
;
239 /* Find count item downward */
240 while ((iter
++ < count
) && (wineItem
!= NULL
))
242 /* Keep a pointer to the previous in case we ask for more than we got */
243 previousItem
= wineItem
;
244 wineItem
= TREEVIEW_GetNextListItem(infoPtr
, wineItem
);
247 if (wineItem
== NULL
)
248 wineItem
= previousItem
;
252 /* Find count item upward */
253 while ((iter
-- > count
) && (wineItem
!= NULL
))
255 /* Keep a pointer to the previous in case we ask for more than we got */
256 previousItem
= wineItem
;
257 wineItem
= TREEVIEW_GetPrevListItem(infoPtr
, wineItem
);
260 if (wineItem
== NULL
)
261 wineItem
= previousItem
;
270 /***************************************************************************
273 static void TREEVIEW_RemoveAllChildren(
275 TREEVIEW_ITEM
*parentItem
)
277 TREEVIEW_INFO
*infoPtr
= TREEVIEW_GetInfoPtr(hwnd
);
278 TREEVIEW_ITEM
*killItem
;
281 kill
=(INT
)parentItem
->firstChild
;
283 tv_set_bit ( kill
, infoPtr
->freeList
);
284 killItem
=& infoPtr
->items
[kill
];
285 if (killItem
->pszText
!=LPSTR_TEXTCALLBACKA
)
286 COMCTL32_Free (killItem
->pszText
);
287 TREEVIEW_SendTreeviewNotify (hwnd
, TVN_DELETEITEM
, 0, (HTREEITEM
)kill
, 0);
288 if (killItem
->firstChild
)
289 TREEVIEW_RemoveAllChildren (hwnd
, killItem
);
290 kill
=(INT
)killItem
->sibling
;
293 if (parentItem
->cChildren
>0) {
294 infoPtr
->uNumItems
-= parentItem
->cChildren
;
295 parentItem
->firstChild
= 0;
296 parentItem
->cChildren
= 0;
303 TREEVIEW_RemoveItem (HWND hwnd
, TREEVIEW_ITEM
*wineItem
)
306 TREEVIEW_INFO
*infoPtr
= TREEVIEW_GetInfoPtr(hwnd
);
307 TREEVIEW_ITEM
*parentItem
, *upsiblingItem
, *siblingItem
;
310 iItem
=(INT
)wineItem
->hItem
;
311 tv_set_bit(iItem
,infoPtr
->freeList
);
312 infoPtr
->uNumItems
--;
314 if (wineItem
->pszText
!=LPSTR_TEXTCALLBACKA
)
315 COMCTL32_Free (wineItem
->pszText
);
317 TREEVIEW_SendTreeviewNotify (hwnd
, TVN_DELETEITEM
, 0, (HTREEITEM
)iItem
, 0);
319 if (wineItem
->firstChild
)
320 TREEVIEW_RemoveAllChildren (hwnd
,wineItem
);
322 if (wineItem
->parent
) {
323 parentItem
=& infoPtr
->items
[(INT
)wineItem
->parent
];
324 switch (parentItem
->cChildren
) {
325 case I_CHILDRENCALLBACK
:
326 FIXME("we don't handle I_CHILDRENCALLBACK yet\n");
329 parentItem
->cChildren
=0;
330 parentItem
->firstChild
=0;
333 parentItem
->cChildren
--;
334 if ((INT
)parentItem
->firstChild
==iItem
)
335 parentItem
->firstChild
=wineItem
->sibling
;
339 if (iItem
==(INT
)infoPtr
->TopRootItem
)
340 infoPtr
->TopRootItem
=(HTREEITEM
)wineItem
->sibling
;
341 if (wineItem
->upsibling
) {
342 upsiblingItem
=& infoPtr
->items
[(INT
)wineItem
->upsibling
];
343 upsiblingItem
->sibling
=wineItem
->sibling
;
345 if (wineItem
->sibling
) {
346 siblingItem
=& infoPtr
->items
[(INT
)wineItem
->sibling
];
347 siblingItem
->upsibling
=wineItem
->upsibling
;
355 /* Note:TREEVIEW_RemoveTree doesn't remove infoPtr itself */
357 static void TREEVIEW_RemoveTree (HWND hwnd
)
360 TREEVIEW_INFO
*infoPtr
= TREEVIEW_GetInfoPtr(hwnd
);
361 TREEVIEW_ITEM
*killItem
;
364 for (i
=1; i
<=(INT
)infoPtr
->uMaxHandle
; i
++)
365 if (!tv_test_bit (i
, infoPtr
->freeList
)) {
366 killItem
=& infoPtr
->items
[i
];
367 if (killItem
->pszText
!=LPSTR_TEXTCALLBACKA
)
368 COMCTL32_Free (killItem
->pszText
);
369 TREEVIEW_SendTreeviewNotify
370 (hwnd
, TVN_DELETEITEM
, 0, killItem
->hItem
, 0);
373 if (infoPtr
->uNumPtrsAlloced
) {
374 COMCTL32_Free (infoPtr
->items
);
375 COMCTL32_Free (infoPtr
->freeList
);
376 infoPtr
->uNumItems
=0;
377 infoPtr
->uNumPtrsAlloced
=0;
378 infoPtr
->uMaxHandle
=0;
389 TREEVIEW_GetImageList (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
391 TREEVIEW_INFO
*infoPtr
= TREEVIEW_GetInfoPtr(hwnd
);
394 if (infoPtr
==NULL
) return 0;
396 if ((INT
)wParam
== TVSIL_NORMAL
)
397 return (LRESULT
) infoPtr
->himlNormal
;
398 if ((INT
)wParam
== TVSIL_STATE
)
399 return (LRESULT
) infoPtr
->himlState
;
405 TREEVIEW_SetImageList (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
407 TREEVIEW_INFO
*infoPtr
= TREEVIEW_GetInfoPtr(hwnd
);
411 switch ((INT
)wParam
) {
413 himlTemp
= infoPtr
->himlNormal
;
414 infoPtr
->himlNormal
= (HIMAGELIST
)lParam
;
415 return (LRESULT
)himlTemp
;
418 himlTemp
= infoPtr
->himlState
;
419 infoPtr
->himlState
= (HIMAGELIST
)lParam
;
420 return (LRESULT
)himlTemp
;
423 return (LRESULT
)NULL
;
429 TREEVIEW_SetItemHeight (HWND hwnd
, WPARAM wParam
)
431 TREEVIEW_INFO
*infoPtr
= TREEVIEW_GetInfoPtr(hwnd
);
432 INT cx
,cy
,prevHeight
=infoPtr
->uItemHeight
;
438 infoPtr
->uItemHeight
=-1;
442 ImageList_GetIconSize (infoPtr
->himlNormal
, &cx
, &cy
);
444 if (wParam
>cy
) cy
=wParam
;
445 infoPtr
->uItemHeight
=cy
;
447 if (!( GetWindowLongA( hwnd
, GWL_STYLE
) & TVS_NONEVENHEIGHT
))
448 infoPtr
->uItemHeight
= (INT
) wParam
& 0xfffffffe;
453 TREEVIEW_GetItemHeight (HWND hwnd
)
455 TREEVIEW_INFO
*infoPtr
= TREEVIEW_GetInfoPtr(hwnd
);
458 return infoPtr
->uItemHeight
;
462 TREEVIEW_GetLineColor (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
464 TREEVIEW_INFO
*infoPtr
= TREEVIEW_GetInfoPtr(hwnd
);
467 return (LRESULT
) infoPtr
->clrLine
;
471 TREEVIEW_SetLineColor (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
473 TREEVIEW_INFO
*infoPtr
= TREEVIEW_GetInfoPtr(hwnd
);
474 COLORREF prevColor
=infoPtr
->clrLine
;
477 infoPtr
->clrLine
=(COLORREF
) lParam
;
478 return (LRESULT
) prevColor
;
482 TREEVIEW_SetTextColor (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
484 TREEVIEW_INFO
*infoPtr
= TREEVIEW_GetInfoPtr(hwnd
);
485 COLORREF prevColor
=infoPtr
->clrText
;
488 infoPtr
->clrText
=(COLORREF
) lParam
;
489 return (LRESULT
) prevColor
;
493 TREEVIEW_GetBkColor (HWND hwnd
)
495 TREEVIEW_INFO
*infoPtr
= TREEVIEW_GetInfoPtr(hwnd
);
498 return (LRESULT
) infoPtr
->clrBk
;
502 TREEVIEW_SetBkColor (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
504 TREEVIEW_INFO
*infoPtr
= TREEVIEW_GetInfoPtr(hwnd
);
505 COLORREF prevColor
=infoPtr
->clrBk
;
508 infoPtr
->clrBk
=(COLORREF
) lParam
;
509 return (LRESULT
) prevColor
;
513 TREEVIEW_GetTextColor (HWND hwnd
)
515 TREEVIEW_INFO
*infoPtr
= TREEVIEW_GetInfoPtr(hwnd
);
518 return (LRESULT
) infoPtr
->clrText
;
522 /* cdmode: custom draw mode as received from app. in first NMCUSTOMDRAW
525 #define TREEVIEW_LEFT_MARGIN 8
529 TREEVIEW_DrawItem (HWND hwnd
, HDC hdc
, TREEVIEW_ITEM
*wineItem
)
531 TREEVIEW_INFO
*infoPtr
= TREEVIEW_GetInfoPtr(hwnd
);
532 DWORD dwStyle
= GetWindowLongA (hwnd
, GWL_STYLE
);
533 INT center
,xpos
,cx
,cy
, cditem
, drawmode
;
535 UINT uTextJustify
= DT_LEFT
;
539 if (wineItem
->state
& TVIS_BOLD
)
540 hOldFont
= SelectObject (hdc
, infoPtr
->hBoldFont
);
542 hOldFont
= SelectObject (hdc
, infoPtr
->hFont
);
545 TRACE ("cdmode:%x\n",infoPtr
->cdmode
);
546 if (infoPtr
->cdmode
& CDRF_NOTIFYITEMDRAW
) {
547 drawmode
=CDDS_ITEMPREPAINT
;
549 if (infoPtr
->cdmode
& CDRF_NOTIFYSUBITEMDRAW
)
550 drawmode
|=CDDS_SUBITEM
;
552 cditem
=TREEVIEW_SendCustomDrawItemNotify (hwnd
, hdc
, wineItem
, drawmode
);
554 TRACE("cditem:%d\n",cditem
);
556 if (cditem
& CDRF_SKIPDEFAULT
)
561 * Set drawing starting points
563 r
= wineItem
->rect
; /* this item rectangle */
564 center
= (r
.top
+r
.bottom
)/2; /* this item vertical center */
565 xpos
= r
.left
+ TREEVIEW_LEFT_MARGIN
;/* horizontal starting point */
568 * Display the tree hierarchy
570 if ( dwStyle
& TVS_HASLINES
)
573 * Write links to parent node
574 * we draw the L starting from the child to the parent
576 * points[0] is attached to the current item
577 * points[1] is the L corner
578 * points[2] is attached to the parent or the up sibling
580 if ( dwStyle
& TVS_LINESATROOT
)
582 TREEVIEW_ITEM
*upNode
= NULL
;
583 BOOL hasParentOrSibling
= TRUE
;
584 RECT upRect
= {0,0,0,0};
585 HPEN hOldPen
, hnewPen
;
588 * determine the target location of the line at root, either be linked
589 * to the up sibling or to the parent node.
591 if (wineItem
->upsibling
)
592 upNode
= TREEVIEW_ValidItem (infoPtr
, wineItem
->upsibling
);
593 else if (wineItem
->parent
)
594 upNode
= TREEVIEW_ValidItem (infoPtr
, wineItem
->parent
);
596 hasParentOrSibling
= FALSE
;
599 upRect
= upNode
->rect
;
601 if ( wineItem
->iLevel
== 0 )
603 points
[2].x
= points
[1].x
= upRect
.left
+8;
604 points
[0].x
= points
[2].x
+ 10;
605 points
[2].y
= upRect
.bottom
-3;
606 points
[1].y
= points
[0].y
= center
;
610 points
[2].x
= points
[1].x
= 8 + (20*wineItem
->iLevel
);
611 points
[2].y
= ( upNode
->cChildren
== 0) ?
612 upRect
.top
: /* is linked to the "L" above */
613 ( wineItem
->upsibling
!= NULL
) ?
614 upRect
.bottom
-3: /* is linked to an icon */
615 upRect
.bottom
+1; /* is linked to a +/- box */
616 points
[1].y
= points
[0].y
= center
;
617 points
[0].x
= points
[1].x
+ 10;
623 hnewPen
= CreatePen(PS_DOT
, 0, infoPtr
->clrLine
);
624 hOldPen
= SelectObject( hdc
, hnewPen
);
626 if (hasParentOrSibling
)
627 Polyline (hdc
,points
,3);
629 Polyline (hdc
,points
,2);
631 DeleteObject(hnewPen
);
632 SelectObject(hdc
, hOldPen
);
637 * Display the (+/-) signs
639 if (wineItem
->iLevel
!= 0)/* update position only for non root node */
640 xpos
+=(5*wineItem
->iLevel
);
642 if (( dwStyle
& TVS_HASBUTTONS
) && ( dwStyle
& TVS_HASLINES
))
644 if ( (wineItem
->cChildren
) ||
645 (wineItem
->cChildren
== I_CHILDRENCALLBACK
))
647 /* Setup expand box coordinate to facilitate the LMBClick handling */
648 wineItem
->expandBox
.left
= xpos
-4;
649 wineItem
->expandBox
.top
= center
-4;
650 wineItem
->expandBox
.right
= xpos
+5;
651 wineItem
->expandBox
.bottom
= center
+5;
655 wineItem
->expandBox
.left
,
656 wineItem
->expandBox
.top
,
657 wineItem
->expandBox
.right
,
658 wineItem
->expandBox
.bottom
);
660 MoveToEx (hdc
, xpos
-2, center
, NULL
);
661 LineTo (hdc
, xpos
+3, center
);
663 if (!(wineItem
->state
& TVIS_EXPANDED
)) {
664 MoveToEx (hdc
, xpos
, center
-2, NULL
);
665 LineTo (hdc
, xpos
, center
+3);
671 * Display the image assiciated with this item
673 xpos
+= 13; /* update position */
674 if (wineItem
->mask
& (TVIF_IMAGE
|TVIF_SELECTEDIMAGE
)) {
676 HIMAGELIST
*himlp
= NULL
;
678 if (infoPtr
->himlNormal
)
679 himlp
=&infoPtr
->himlNormal
; /* get the image list */
681 if ( (wineItem
->state
& TVIS_SELECTED
) &&
682 (wineItem
->iSelectedImage
)) {
684 /* State images are displayed to the left of the Normal image*/
685 if (infoPtr
->himlState
)
686 himlp
=&infoPtr
->himlState
;
688 /* The item is curently selected */
689 if (wineItem
->iSelectedImage
== I_IMAGECALLBACK
)
690 TREEVIEW_SendDispInfoNotify (
696 imageIndex
= wineItem
->iSelectedImage
;
699 /* This item is not selected */
700 if (wineItem
->iImage
== I_IMAGECALLBACK
)
701 TREEVIEW_SendDispInfoNotify (
707 imageIndex
= wineItem
->iImage
;
712 /* We found an image to display? Draw it. */
721 ImageList_GetIconSize (*himlp
, &cx
, &cy
);
727 * Display the text assiciated with this item
730 if ((wineItem
->mask
& TVIF_TEXT
) && (wineItem
->pszText
))
732 COLORREF oldBkColor
= 0;
733 COLORREF oldTextColor
= 0;
739 wineItem
->text
.left
= r
.left
;
740 wineItem
->text
.right
= r
.right
;
741 wineItem
->text
.top
= r
.top
;
742 wineItem
->text
.bottom
= r
.bottom
;
744 if (wineItem
->state
& (TVIS_SELECTED
| TVIS_DROPHILITED
) ) {
745 oldBkMode
= SetBkMode (hdc
, OPAQUE
);
746 oldBkColor
= SetBkColor (hdc
, GetSysColor( COLOR_HIGHLIGHT
));
747 oldTextColor
= SetTextColor(hdc
, GetSysColor( COLOR_HIGHLIGHTTEXT
));
751 oldBkMode
= SetBkMode(hdc
, TRANSPARENT
);
752 oldTextColor
= SetTextColor(hdc
, GetSysColor( COLOR_WINDOWTEXT
));
755 if (wineItem
->pszText
== LPSTR_TEXTCALLBACKA
) {
756 TRACE("LPSTR_TEXTCALLBACK\n");
757 TREEVIEW_SendDispInfoNotify (hwnd
, wineItem
, TVN_GETDISPINFO
, TVIF_TEXT
);
764 lstrlenA(wineItem
->pszText
),
766 uTextJustify
| DT_VCENTER
| DT_SINGLELINE
);
768 /* Obtain the text coordinate */
772 lstrlenA(wineItem
->pszText
),
774 uTextJustify
| DT_VCENTER
| DT_SINGLELINE
| DT_CALCRECT
);
776 /* Restore the hdc state */
777 SetTextColor( hdc
, oldTextColor
);
779 if (oldBkMode
!= TRANSPARENT
)
780 SetBkMode(hdc
, oldBkMode
);
781 if (wineItem
->state
& (TVIS_SELECTED
| TVIS_DROPHILITED
))
782 SetBkColor (hdc
, oldBkColor
);
784 /* Draw the box arround the selected item */
785 if (wineItem
->state
& TVIS_SELECTED
)
787 HPEN hnewPen
= CreatePen(PS_DOT
, 0, GetSysColor(COLOR_WINDOWTEXT
) );
788 HPEN hOldPen
= SelectObject( hdc
, hnewPen
);
791 points
[0].x
= wineItem
->text
.left
-1;
792 points
[0].y
= wineItem
->text
.top
+1;
793 points
[1].x
= wineItem
->text
.right
;
794 points
[1].y
= wineItem
->text
.top
+1;
795 points
[2].x
= wineItem
->text
.right
;
796 points
[2].y
= wineItem
->text
.bottom
;
797 points
[3].x
= wineItem
->text
.left
-1;
798 points
[3].y
= wineItem
->text
.bottom
;
800 Polyline (hdc
,points
,4);
802 DeleteObject(hnewPen
);
803 SelectObject(hdc
, hOldPen
);
807 if (cditem
& CDRF_NOTIFYPOSTPAINT
)
808 TREEVIEW_SendCustomDrawItemNotify (hwnd
, hdc
, wineItem
, CDDS_ITEMPOSTPAINT
);
810 SelectObject (hdc
, hOldFont
);
814 TREEVIEW_GetItemRect (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
816 TREEVIEW_INFO
*infoPtr
= TREEVIEW_GetInfoPtr(hwnd
);
817 TREEVIEW_ITEM
*wineItem
;
819 LPRECT lpRect
= (LPRECT
)lParam
;
823 * validate parameters
825 if ( (infoPtr
==NULL
) || (lpRect
== NULL
) )
828 if (infoPtr
->Timer
& TV_REFRESH_TIMER_SET
)
829 TREEVIEW_Refresh (hwnd
); /* we want a rect for the current view */
832 * retrive the item ptr
834 iItem
= (HTREEITEM
*) lParam
;
835 wineItem
= TREEVIEW_ValidItem (infoPtr
, *iItem
);
836 if ((!wineItem
) || (!wineItem
->visible
))
840 * If wParam is TRUE return the text size otherwise return
841 * the whole item size
844 lpRect
->left
= wineItem
->text
.left
;
845 lpRect
->right
= wineItem
->text
.right
;
846 lpRect
->bottom
= wineItem
->text
.bottom
;
847 lpRect
->top
= wineItem
->text
.top
;
849 lpRect
->left
= wineItem
->rect
.left
;
850 lpRect
->right
= wineItem
->rect
.right
;
851 lpRect
->bottom
= wineItem
->rect
.bottom
;
852 lpRect
->top
= wineItem
->rect
.top
;
855 TRACE("[L:%d R:%d T:%d B:%d]\n",
856 lpRect
->left
,lpRect
->right
,
857 lpRect
->top
,lpRect
->bottom
);
863 TREEVIEW_GetVisibleCount (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
866 TREEVIEW_INFO
*infoPtr
= TREEVIEW_GetInfoPtr(hwnd
);
868 return (LRESULT
) infoPtr
->uVisibleHeight
/ infoPtr
->uRealItemHeight
;
874 TREEVIEW_SetItemA (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
876 TREEVIEW_INFO
*infoPtr
= TREEVIEW_GetInfoPtr(hwnd
);
877 TREEVIEW_ITEM
*wineItem
;
881 tvItem
=(LPTVITEMEXA
) lParam
;
882 iItem
=(INT
)tvItem
->hItem
;
883 TRACE("item %d,mask %x\n",iItem
,tvItem
->mask
);
885 wineItem
= TREEVIEW_ValidItem (infoPtr
, (HTREEITEM
)iItem
);
886 if (!wineItem
) return FALSE
;
888 if (tvItem
->mask
& TVIF_CHILDREN
) {
889 wineItem
->cChildren
=tvItem
->cChildren
;
892 if (tvItem
->mask
& TVIF_IMAGE
) {
893 wineItem
->iImage
=tvItem
->iImage
;
896 if (tvItem
->mask
& TVIF_INTEGRAL
) {
897 wineItem
->iIntegral
=tvItem
->iIntegral
;
900 if (tvItem
->mask
& TVIF_PARAM
) {
901 wineItem
->lParam
=tvItem
->lParam
;
904 if (tvItem
->mask
& TVIF_SELECTEDIMAGE
) {
905 wineItem
->iSelectedImage
=tvItem
->iSelectedImage
;
908 if (tvItem
->mask
& TVIF_STATE
) {
909 wineItem
->state
=tvItem
->state
& tvItem
->stateMask
;
912 if (tvItem
->mask
& TVIF_TEXT
) {
913 if (tvItem
->pszText
!=LPSTR_TEXTCALLBACKA
) {
914 len
=lstrlenA (tvItem
->pszText
);
915 if (len
>wineItem
->cchTextMax
)
916 wineItem
->pszText
= COMCTL32_ReAlloc (wineItem
->pszText
, len
+1);
917 lstrcpynA (wineItem
->pszText
, tvItem
->pszText
,len
);
919 if (wineItem
->cchTextMax
) {
920 COMCTL32_Free (wineItem
->pszText
);
921 wineItem
->cchTextMax
=0;
923 wineItem
->pszText
=LPSTR_TEXTCALLBACKA
;
927 wineItem
->mask
|= tvItem
->mask
;
933 TREEVIEW_GetItemState (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
936 TREEVIEW_INFO
*infoPtr
= TREEVIEW_GetInfoPtr(hwnd
);
937 TREEVIEW_ITEM
*wineItem
;
939 wineItem
= TREEVIEW_ValidItem (infoPtr
, (HTREEITEM
)wParam
);
940 if (!wineItem
) return 0;
942 return (wineItem
->state
& lParam
);
950 TREEVIEW_Refresh (HWND hwnd
)
953 TREEVIEW_INFO
*infoPtr
= TREEVIEW_GetInfoPtr(hwnd
);
958 INT iItem
, indent
, x
, y
, cx
, height
, itemHeight
;
959 INT viewtop
,viewbottom
,viewleft
,viewright
;
960 TREEVIEW_ITEM
*wineItem
, *prevItem
;
966 if (infoPtr
->Timer
& TV_REFRESH_TIMER_SET
) {
967 KillTimer (hwnd
, TV_REFRESH_TIMER
);
968 infoPtr
->Timer
&= ~TV_REFRESH_TIMER_SET
;
972 GetClientRect (hwnd
, &rect
);
973 if ((rect
.left
-rect
.right
==0) || (rect
.top
-rect
.bottom
==0)) return;
975 infoPtr
->cdmode
=TREEVIEW_SendCustomDrawNotify
976 (hwnd
, CDDS_PREPAINT
, hdc
, rect
);
978 if (infoPtr
->cdmode
==CDRF_SKIPDEFAULT
) {
979 ReleaseDC (hwnd
, hdc
);
983 infoPtr
->uVisibleHeight
= rect
.bottom
-rect
.top
;
984 infoPtr
->uVisibleWidth
= rect
.right
-rect
.left
;
987 viewbottom
=infoPtr
->cy
+ rect
.bottom
-rect
.top
;
988 viewleft
=infoPtr
->cx
;
989 viewright
=infoPtr
->cx
+ rect
.right
-rect
.left
;
991 /* draw background */
993 hbrBk
= CreateSolidBrush (infoPtr
->clrBk
);
994 FillRect(hdc
, &rect
, hbrBk
);
997 iItem
=(INT
)infoPtr
->TopRootItem
;
998 infoPtr
->firstVisible
=0;
1002 TRACE("[%d %d %d %d]\n",viewtop
,viewbottom
,viewleft
,viewright
);
1006 wineItem
= & infoPtr
->items
[iItem
];
1007 wineItem
->iLevel
=indent
;
1009 ImageList_GetIconSize (infoPtr
->himlNormal
, &cx
, &itemHeight
);
1010 if (infoPtr
->uItemHeight
>itemHeight
)
1011 itemHeight
=infoPtr
->uItemHeight
;
1013 GetTextMetricsA (hdc
, &tm
);
1014 if ((tm
.tmHeight
+ tm
.tmExternalLeading
) > itemHeight
)
1015 itemHeight
=tm
.tmHeight
+ tm
.tmExternalLeading
;
1017 infoPtr
->uRealItemHeight
=itemHeight
;
1020 /* FIXME: remove this in later stage */
1022 if (wineItem->pszText!=LPSTR_TEXTCALLBACK32A)
1023 TRACE (treeview, "%d %d [%d %d %d %d] (%s)\n",y,x,
1024 wineItem->rect.top, wineItem->rect.bottom,
1025 wineItem->rect.left, wineItem->rect.right,
1028 TRACE (treeview, "%d [%d %d %d %d] (CALLBACK)\n",
1030 wineItem->rect.top, wineItem->rect.bottom,
1031 wineItem->rect.left, wineItem->rect.right);
1034 height
=itemHeight
* wineItem
->iIntegral
+1;
1035 if ((y
>= viewtop
) && (y
<= viewbottom
) &&
1036 (x
>= viewleft
) && (x
<= viewright
)) {
1037 wineItem
->visible
= TRUE
;
1038 wineItem
->rect
.top
= y
- infoPtr
->cy
+ rect
.top
;
1039 wineItem
->rect
.bottom
= wineItem
->rect
.top
+ height
;
1040 wineItem
->rect
.left
= x
- infoPtr
->cx
+ rect
.left
;
1041 wineItem
->rect
.right
= rect
.right
;
1042 if (!infoPtr
->firstVisible
)
1043 infoPtr
->firstVisible
=wineItem
->hItem
;
1044 TREEVIEW_DrawItem (hwnd
, hdc
, wineItem
);
1047 wineItem
->visible
= FALSE
;
1048 wineItem
->rect
.left
= wineItem
->rect
.top
= 0;
1049 wineItem
->rect
.right
= wineItem
->rect
.bottom
= 0;
1050 wineItem
->text
.left
= wineItem
->text
.top
= 0;
1051 wineItem
->text
.right
= wineItem
->text
.bottom
= 0;
1054 /* look up next item */
1056 if ((wineItem
->firstChild
) && (wineItem
->state
& TVIS_EXPANDED
)) {
1057 iItem
=(INT
)wineItem
->firstChild
;
1059 x
+=infoPtr
->uIndent
;
1060 if (x
>infoPtr
->uTotalWidth
)
1061 infoPtr
->uTotalWidth
=x
;
1064 iItem
=(INT
)wineItem
->sibling
;
1065 while ((!iItem
) && (indent
>0)) {
1067 x
-=infoPtr
->uIndent
;
1069 wineItem
=&infoPtr
->items
[(INT
)wineItem
->parent
];
1070 iItem
=(INT
)wineItem
->sibling
;
1076 /* FIXME: infoPtr->uTotalWidth should also take item label into account */
1077 /* FIXME: or should query item sizes (ie check CDRF_NEWFONT) */
1079 infoPtr
->uTotalHeight
=y
;
1080 if (y
>= (viewbottom
-viewtop
)) {
1081 if (!(infoPtr
->uInternalStatus
& TV_VSCROLL
))
1082 ShowScrollBar (hwnd
, SB_VERT
, TRUE
);
1083 infoPtr
->uInternalStatus
|=TV_VSCROLL
;
1084 SetScrollRange (hwnd
, SB_VERT
, 0,
1085 y
- infoPtr
->uVisibleHeight
, FALSE
);
1086 SetScrollPos (hwnd
, SB_VERT
, infoPtr
->cy
, TRUE
);
1089 if (infoPtr
->uInternalStatus
& TV_VSCROLL
)
1090 ShowScrollBar (hwnd
, SB_VERT
, FALSE
);
1091 infoPtr
->uInternalStatus
&= ~TV_VSCROLL
;
1095 if (infoPtr
->cdmode
& CDRF_NOTIFYPOSTPAINT
)
1096 infoPtr
->cdmode
=TREEVIEW_SendCustomDrawNotify
1097 (hwnd
, CDDS_POSTPAINT
, hdc
, rect
);
1099 ReleaseDC (hwnd
, hdc
);
1105 TREEVIEW_HandleTimer (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1107 TREEVIEW_INFO
*infoPtr
= TREEVIEW_GetInfoPtr(hwnd
);
1109 TRACE(" %d\n",wParam
);
1110 if (!infoPtr
) return FALSE
;
1113 case TV_REFRESH_TIMER
:
1114 KillTimer (hwnd
, TV_REFRESH_TIMER
);
1115 infoPtr
->Timer
&= ~TV_REFRESH_TIMER_SET
;
1116 InvalidateRect(hwnd
, NULL
, FALSE
);
1119 KillTimer (hwnd
, TV_EDIT_TIMER
);
1120 infoPtr
->Timer
&= ~TV_EDIT_TIMER_SET
;
1123 ERR("got unknown timer\n");
1131 TREEVIEW_QueueRefresh (HWND hwnd
)
1134 TREEVIEW_INFO
*infoPtr
= TREEVIEW_GetInfoPtr(hwnd
);
1137 if (infoPtr
->Timer
& TV_REFRESH_TIMER_SET
) {
1138 KillTimer (hwnd
, TV_REFRESH_TIMER
);
1141 SetTimer (hwnd
, TV_REFRESH_TIMER
, TV_REFRESH_DELAY
, 0);
1142 infoPtr
->Timer
|=TV_REFRESH_TIMER_SET
;
1148 TREEVIEW_GetItemA (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1150 TREEVIEW_INFO
*infoPtr
= TREEVIEW_GetInfoPtr(hwnd
);
1152 TREEVIEW_ITEM
*wineItem
;
1155 tvItem
=(LPTVITEMEXA
) lParam
;
1156 iItem
=(INT
)tvItem
->hItem
;
1158 wineItem
= TREEVIEW_ValidItem (infoPtr
, (HTREEITEM
)iItem
);
1159 if (!wineItem
) return FALSE
;
1161 if (tvItem
->mask
& TVIF_CHILDREN
) {
1162 if (TVIF_CHILDREN
==I_CHILDRENCALLBACK
)
1163 FIXME("I_CHILDRENCALLBACK not supported\n");
1164 tvItem
->cChildren
=wineItem
->cChildren
;
1167 if (tvItem
->mask
& TVIF_HANDLE
) {
1168 tvItem
->hItem
=wineItem
->hItem
;
1171 if (tvItem
->mask
& TVIF_IMAGE
) {
1172 tvItem
->iImage
=wineItem
->iImage
;
1175 if (tvItem
->mask
& TVIF_INTEGRAL
) {
1176 tvItem
->iIntegral
=wineItem
->iIntegral
;
1179 /* undocumented: windows ignores TVIF_PARAM and
1180 * always sets lParam
1182 tvItem
->lParam
=wineItem
->lParam
;
1184 if (tvItem
->mask
& TVIF_SELECTEDIMAGE
) {
1185 tvItem
->iSelectedImage
=wineItem
->iSelectedImage
;
1188 if (tvItem
->mask
& TVIF_STATE
) {
1189 tvItem
->state
=wineItem
->state
& tvItem
->stateMask
;
1192 if (tvItem
->mask
& TVIF_TEXT
) {
1193 if (wineItem
->pszText
== LPSTR_TEXTCALLBACKA
) {
1194 tvItem
->pszText
= LPSTR_TEXTCALLBACKA
; /* FIXME:send notification? */
1195 ERR(" GetItem called with LPSTR_TEXTCALLBACK\n");
1197 else if (wineItem
->pszText
) {
1198 lstrcpynA (tvItem
->pszText
, wineItem
->pszText
, tvItem
->cchTextMax
);
1202 TRACE("item %d<%p>, txt %p, img %p, action %x\n",
1214 /* FIXME: check implementation of TVGN_NEXT/TVGN_NEXTVISIBLE */
1217 TREEVIEW_GetNextItem (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1220 TREEVIEW_INFO
*infoPtr
= TREEVIEW_GetInfoPtr(hwnd
);
1221 TREEVIEW_ITEM
*wineItem
, *returnItem
;
1222 INT iItem
, retval
, flag
;
1225 if (!infoPtr
) return FALSE
;
1226 flag
= (INT
) wParam
;
1227 iItem
= (INT
) lParam
;
1230 case TVGN_ROOT
: retval
=(INT
)infoPtr
->TopRootItem
;
1232 case TVGN_CARET
:retval
=(INT
)infoPtr
->selectedItem
;
1234 case TVGN_FIRSTVISIBLE
:
1235 TREEVIEW_Refresh (hwnd
);
1236 /* FIXME:we should only recalculate, not redraw */
1237 retval
=(INT
)infoPtr
->firstVisible
;
1239 case TVGN_DROPHILITE
:
1240 retval
=(INT
)infoPtr
->dropItem
;
1244 TRACE("flags:%x, returns %u\n", flag
, retval
);
1248 wineItem
= TREEVIEW_ValidItem (infoPtr
, (HTREEITEM
)iItem
);
1250 if (!wineItem
) return FALSE
;
1253 case TVGN_NEXT
: retval
=(INT
)wineItem
->sibling
;
1256 retval
=(INT
)wineItem
->upsibling
;
1259 retval
=(INT
)wineItem
->parent
;
1262 retval
=(INT
)wineItem
->firstChild
;
1264 case TVGN_LASTVISIBLE
:
1265 returnItem
=TREEVIEW_GetLastListItem (infoPtr
,wineItem
);
1267 case TVGN_NEXTVISIBLE
:
1268 returnItem
=TREEVIEW_GetNextListItem (infoPtr
,wineItem
);
1270 case TVGN_PREVIOUSVISIBLE
:
1271 returnItem
=TREEVIEW_GetPrevListItem (infoPtr
, wineItem
);
1273 default: FIXME("Unknown msg %x,item %x\n", flag
,iItem
);
1278 TRACE("flags:%x, item %d;returns %d\n", flag
, iItem
,
1279 (INT
)returnItem
->hItem
);
1280 return (INT
)returnItem
->hItem
;
1283 TRACE("flags:%x, item %d;returns %d\n", flag
, iItem
,retval
);
1289 TREEVIEW_GetCount (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1291 TREEVIEW_INFO
*infoPtr
= TREEVIEW_GetInfoPtr(hwnd
);
1293 TRACE(" %d\n",infoPtr
->uNumItems
);
1294 return (LRESULT
) infoPtr
->uNumItems
;
1297 /***************************************************************************
1298 * This method does the chaining of the insertion of a treeview item
1300 * If parent is NULL, we're inserting at the root of the list.
1302 static void TREEVIEW_InsertBefore(
1303 TREEVIEW_INFO
*infoPtr
,
1304 TREEVIEW_ITEM
*newItem
,
1305 TREEVIEW_ITEM
*sibling
,
1306 TREEVIEW_ITEM
*parent
)
1308 HTREEITEM siblingHandle
= 0;
1309 HTREEITEM upSiblingHandle
= 0;
1310 TREEVIEW_ITEM
*upSibling
= NULL
;
1312 if (newItem
== NULL
)
1313 ERR("NULL newItem, impossible condition\n");
1315 if (sibling
!= NULL
) /* Insert before this sibling for this parent */
1317 /* Store the new item sibling up sibling and sibling tem handle */
1318 siblingHandle
= sibling
->hItem
;
1319 upSiblingHandle
= sibling
->upsibling
;
1320 /* As well as a pointer to the upsibling sibling object */
1321 if ( (INT
)sibling
->upsibling
!= 0 )
1322 upSibling
= &infoPtr
->items
[(INT
)sibling
->upsibling
];
1324 /* Adjust the sibling pointer */
1325 sibling
->upsibling
= newItem
->hItem
;
1327 /* Adjust the new item pointers */
1328 newItem
->upsibling
= upSiblingHandle
;
1329 newItem
->sibling
= siblingHandle
;
1331 /* Adjust the up sibling pointer */
1332 if ( upSibling
!= NULL
)
1333 upSibling
->sibling
= newItem
->hItem
;
1335 /* this item is the first child of this parent, adjust parent pointers */
1337 parent
->firstChild
= newItem
->hItem
;
1339 infoPtr
->TopRootItem
= newItem
->hItem
;
1341 else /* Insert as first child of this parent */
1343 parent
->firstChild
= newItem
->hItem
;
1346 /***************************************************************************
1347 * This method does the chaining of the insertion of a treeview item
1349 * If parent is NULL, we're inserting at the root of the list.
1351 static void TREEVIEW_InsertAfter(
1352 TREEVIEW_INFO
*infoPtr
,
1353 TREEVIEW_ITEM
*newItem
,
1354 TREEVIEW_ITEM
*upSibling
,
1355 TREEVIEW_ITEM
*parent
)
1357 HTREEITEM upSiblingHandle
= 0;
1358 HTREEITEM siblingHandle
= 0;
1359 TREEVIEW_ITEM
*sibling
= NULL
;
1362 if (newItem
== NULL
)
1363 ERR("NULL newItem, impossible condition\n");
1365 if (upSibling
!= NULL
) /* Insert after this upsibling for this parent */
1367 /* Store the new item up sibling and sibling item handle */
1368 upSiblingHandle
= upSibling
->hItem
;
1369 siblingHandle
= upSibling
->sibling
;
1370 /* As well as a pointer to the upsibling sibling object */
1371 if ( (INT
)upSibling
->sibling
!= 0 )
1372 sibling
= &infoPtr
->items
[(INT
)upSibling
->sibling
];
1374 /* Adjust the up sibling pointer */
1375 upSibling
->sibling
= newItem
->hItem
;
1377 /* Adjust the new item pointers */
1378 newItem
->upsibling
= upSiblingHandle
;
1379 newItem
->sibling
= siblingHandle
;
1381 /* Adjust the sibling pointer */
1382 if ( sibling
!= NULL
)
1383 sibling
->upsibling
= newItem
->hItem
;
1386 newItem is the last of the level, nothing else to do
1389 else /* Insert as first child of this parent */
1391 parent
->firstChild
= newItem
->hItem
;
1394 /***************************************************************************
1395 * Forward the DPA local callback to the treeview owner callback
1397 static INT WINAPI
TREEVIEW_CallBackCompare(
1402 /* Forward the call to the client define callback */
1403 TREEVIEW_INFO
*infoPtr
= TREEVIEW_GetInfoPtr((HWND
)tvInfoPtr
);
1404 return (infoPtr
->pCallBackSort
->lpfnCompare
)(
1405 ((TREEVIEW_ITEM
*)first
)->lParam
,
1406 ((TREEVIEW_ITEM
*)second
)->lParam
,
1407 infoPtr
->pCallBackSort
->lParam
);
1410 /***************************************************************************
1411 * Treeview native sort routine: sort on item text.
1413 static INT WINAPI
TREEVIEW_SortOnName (
1418 HWND hwnd
=(HWND
) tvInfoPtr
;
1420 TREEVIEW_ITEM
*item
;
1423 item
=(TREEVIEW_ITEM
*) first
;
1424 if (item
->pszText
==LPSTR_TEXTCALLBACKA
) {
1425 TREEVIEW_SendDispInfoNotify (hwnd
, item
, TVN_GETDISPINFO
, TVIF_TEXT
);
1429 item
=(TREEVIEW_ITEM
*) second
;
1430 if (item
->pszText
==LPSTR_TEXTCALLBACKA
) {
1431 TREEVIEW_SendDispInfoNotify (hwnd
, item
, TVN_GETDISPINFO
, TVIF_TEXT
);
1435 return -strcmp (txt1
,txt2
);
1438 /***************************************************************************
1439 * Setup the treeview structure with regards of the sort method
1440 * and sort the children of the TV item specified in lParam
1441 * fRecurse: currently unused. Should be zero.
1442 * parent: if pSort!=NULL, should equal pSort->hParent.
1443 * otherwise, item which child items are to be sorted.
1444 * pSort: sort method info. if NULL, sort on item text.
1445 * if non-NULL, sort on item's lParam content, and let the
1446 * application decide what that means. See also TVM_SORTCHILDRENCB.
1449 static LRESULT WINAPI
TREEVIEW_Sort (
1456 TREEVIEW_INFO
*infoPtr
= TREEVIEW_GetInfoPtr(hwnd
);
1457 TREEVIEW_ITEM
*sortMe
= NULL
; /* Node for which we sort the children */
1459 /* Obtain the TVSORTBC struct */
1460 infoPtr
->pCallBackSort
= pSort
;
1462 /* undocumented feature: TVI_ROOT means `sort the whole tree' */
1464 if (parent
==TVI_ROOT
)
1465 parent
=infoPtr
->TopRootItem
;
1467 /* Check for a valid handle to the parent item */
1468 if (!TREEVIEW_ValidItem(infoPtr
, parent
))
1470 ERR ("invalid item hParent=%x\n", (INT
)parent
);
1474 /* Obtain the parent node to sort */
1475 sortMe
= &infoPtr
->items
[ (INT
)parent
];
1477 /* Make sure there is something to sort */
1478 if ( sortMe
->cChildren
> 1 )
1480 /* pointer organization */
1481 HDPA sortList
= DPA_Create(sortMe
->cChildren
);
1482 HTREEITEM itemHandle
= sortMe
->firstChild
;
1483 TREEVIEW_ITEM
*itemPtr
= & infoPtr
->items
[ (INT
)itemHandle
];
1485 /* TREEVIEW_ITEM rechaining */
1491 /* Build the list of item to sort */
1495 sortList
, /* the list */
1496 sortMe
->cChildren
+1, /* force the insertion to be an append */
1497 itemPtr
); /* the ptr to store */
1499 /* Get the next sibling */
1500 itemHandle
= itemPtr
->sibling
;
1501 itemPtr
= & infoPtr
->items
[ (INT
)itemHandle
];
1502 } while ( itemHandle
!= NULL
);
1504 /* let DPA perform the sort activity */
1507 sortList
, /* what */
1508 TREEVIEW_CallBackCompare
, /* how */
1512 sortList
, /* what */
1513 TREEVIEW_SortOnName
, /* how */
1517 * Reorganized TREEVIEW_ITEM structures.
1518 * Note that we know we have at least two elements.
1521 /* Get the first item and get ready to start... */
1522 item
= DPA_GetPtr(sortList
, count
++);
1523 while ( (nextItem
= DPA_GetPtr(sortList
, count
++)) != NULL
)
1525 /* link the two current item toghether */
1526 ((TREEVIEW_ITEM
*)item
)->sibling
= ((TREEVIEW_ITEM
*)nextItem
)->hItem
;
1527 ((TREEVIEW_ITEM
*)nextItem
)->upsibling
= ((TREEVIEW_ITEM
*)item
)->hItem
;
1529 if (prevItem
== NULL
) /* this is the first item, update the parent */
1531 sortMe
->firstChild
= ((TREEVIEW_ITEM
*)item
)->hItem
;
1532 ((TREEVIEW_ITEM
*)item
)->upsibling
= NULL
;
1534 else /* fix the back chaining */
1536 ((TREEVIEW_ITEM
*)item
)->upsibling
= ((TREEVIEW_ITEM
*)prevItem
)->hItem
;
1539 /* get ready for the next one */
1544 /* the last item is pointed to by item and never has a sibling */
1545 ((TREEVIEW_ITEM
*)item
)->sibling
= NULL
;
1547 DPA_Destroy(sortList
);
1555 /***************************************************************************
1556 * Setup the treeview structure with regards of the sort method
1557 * and sort the children of the TV item specified in lParam
1559 static LRESULT WINAPI
TREEVIEW_SortChildrenCB(
1565 LPTVSORTCB pSort
=(LPTVSORTCB
) lParam
;
1567 return TREEVIEW_Sort (hwnd
, wParam
, pSort
->hParent
, pSort
);
1571 /***************************************************************************
1572 * Sort the children of the TV item specified in lParam.
1574 static LRESULT WINAPI
TREEVIEW_SortChildren (
1579 return TREEVIEW_Sort (hwnd
, (BOOL
) wParam
, (HTREEITEM
) lParam
, NULL
);
1584 /* the method used below isn't the most memory-friendly, but it avoids
1585 a lot of memory reallocations */
1587 /* BTW: we waste handle 0; 0 is not an allowed handle. */
1590 TREEVIEW_InsertItemA (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1593 TREEVIEW_INFO
*infoPtr
= TREEVIEW_GetInfoPtr(hwnd
);
1594 TVINSERTSTRUCTA
*ptdi
;
1596 TREEVIEW_ITEM
*wineItem
, *parentItem
, *prevsib
, *sibItem
;
1597 INT iItem
,listItems
,i
,len
;
1599 /* Item to insert */
1600 ptdi
= (LPTVINSERTSTRUCTA
) lParam
;
1602 /* check if memory is available */
1604 if (infoPtr
->uNumPtrsAlloced
==0) {
1605 infoPtr
->items
= COMCTL32_Alloc (TVITEM_ALLOC
*sizeof (TREEVIEW_ITEM
));
1606 infoPtr
->freeList
= COMCTL32_Alloc ((1+(TVITEM_ALLOC
>>5)) * sizeof (INT
));
1607 infoPtr
->uNumPtrsAlloced
=TVITEM_ALLOC
;
1608 infoPtr
->TopRootItem
=(HTREEITEM
)1;
1612 * Reallocate contiguous space for items
1614 if (infoPtr
->uNumItems
== (infoPtr
->uNumPtrsAlloced
-1) ) {
1615 TREEVIEW_ITEM
*oldItems
= infoPtr
->items
;
1616 INT
*oldfreeList
= infoPtr
->freeList
;
1618 infoPtr
->uNumPtrsAlloced
*=2;
1619 infoPtr
->items
= COMCTL32_Alloc (infoPtr
->uNumPtrsAlloced
*sizeof (TREEVIEW_ITEM
));
1620 infoPtr
->freeList
= COMCTL32_Alloc ((1+(infoPtr
->uNumPtrsAlloced
>>5))*sizeof (INT
));
1622 memcpy (&infoPtr
->items
[0], &oldItems
[0],
1623 infoPtr
->uNumPtrsAlloced
/2 * sizeof(TREEVIEW_ITEM
));
1624 memcpy (&infoPtr
->freeList
[0], &oldfreeList
[0],
1625 (infoPtr
->uNumPtrsAlloced
>>6) * sizeof(INT
));
1627 COMCTL32_Free (oldItems
);
1628 COMCTL32_Free (oldfreeList
);
1632 * Reset infoPtr structure with new stat according to current TV picture
1635 infoPtr
->uNumItems
++;
1636 if ((INT
)infoPtr
->uMaxHandle
==(infoPtr
->uNumItems
-1)) {
1637 iItem
=infoPtr
->uNumItems
;
1638 infoPtr
->uMaxHandle
= (HTREEITEM
)((INT
)infoPtr
->uMaxHandle
+ 1);
1639 } else { /* check freelist */
1640 for (i
=0; i
<infoPtr
->uNumPtrsAlloced
>>5; i
++) {
1641 if (infoPtr
->freeList
[i
]) {
1642 iItem
=ffs (infoPtr
->freeList
[i
])-1;
1643 tv_clear_bit(iItem
,&infoPtr
->freeList
[i
]);
1650 if (TRACE_ON(treeview
)) {
1651 for (i
=0; i
<infoPtr
->uNumPtrsAlloced
>>5; i
++)
1652 TRACE("%8x\n",infoPtr
->freeList
[i
]);
1655 if (!iItem
) ERR("Argh -- can't find free item.\n");
1658 * Find the parent item of the new item
1660 tvItem
= & ptdi
->DUMMYUNIONNAME
.itemex
;
1661 wineItem
=& infoPtr
->items
[iItem
];
1663 if ((ptdi
->hParent
==TVI_ROOT
) || (ptdi
->hParent
==0)) {
1665 wineItem
->parent
= 0;
1666 sibItem
= &infoPtr
->items
[(INT
)infoPtr
->TopRootItem
];
1667 listItems
= infoPtr
->uNumItems
;
1670 parentItem
= &infoPtr
->items
[(INT
)ptdi
->hParent
];
1672 /* Do the insertion here it if it's the only item of this parent */
1673 if (!parentItem
->firstChild
)
1674 parentItem
->firstChild
=(HTREEITEM
)iItem
;
1676 wineItem
->parent
= ptdi
->hParent
;
1677 sibItem
= &infoPtr
->items
[(INT
)parentItem
->firstChild
];
1678 parentItem
->cChildren
++;
1679 listItems
= parentItem
->cChildren
;
1683 /* NOTE: I am moving some setup of the wineItem object that was initialy
1684 * done at the end of the function since some of the values are
1685 * required by the Callback sorting
1688 if (tvItem
->mask
& TVIF_TEXT
)
1691 * Setup the item text stuff here since it's required by the Sort method
1692 * when the insertion are ordered
1694 if (tvItem
->pszText
!=LPSTR_TEXTCALLBACKA
)
1696 TRACE("(%p,%s)\n", &tvItem
->pszText
, tvItem
->pszText
);
1697 len
= lstrlenA (tvItem
->pszText
)+1;
1698 wineItem
->pszText
= COMCTL32_Alloc (len
+1);
1699 lstrcpyA (wineItem
->pszText
, tvItem
->pszText
);
1700 wineItem
->cchTextMax
=len
;
1704 TRACE("LPSTR_TEXTCALLBACK\n");
1705 wineItem
->pszText
= LPSTR_TEXTCALLBACKA
;
1706 wineItem
->cchTextMax
= 0;
1710 if (tvItem
->mask
& TVIF_PARAM
)
1711 wineItem
->lParam
=tvItem
->lParam
;
1714 wineItem
->upsibling
=0; /* needed in case we're the first item in a list */
1715 wineItem
->sibling
=0;
1716 wineItem
->firstChild
=0;
1717 wineItem
->hItem
=(HTREEITEM
)iItem
;
1722 switch ((DWORD
) ptdi
->hInsertAfter
) {
1723 case (DWORD
) TVI_FIRST
:
1724 if (sibItem
==wineItem
) break;
1725 if (wineItem
->parent
) {
1726 wineItem
->sibling
=parentItem
->firstChild
;
1727 parentItem
->firstChild
=(HTREEITEM
)iItem
;
1729 wineItem
->sibling
=infoPtr
->TopRootItem
;
1730 infoPtr
->TopRootItem
=(HTREEITEM
)iItem
;
1732 sibItem
->upsibling
=(HTREEITEM
)iItem
;
1735 case (DWORD
) TVI_SORT
:
1736 if (sibItem
==wineItem
)
1738 * This item is the first child of the level and it
1739 * has already been inserted
1744 TREEVIEW_ITEM
*aChild
;
1747 TREEVIEW_ITEM
*previousChild
= NULL
;
1748 BOOL bItemInserted
= FALSE
;
1751 aChild
= &infoPtr
->items
[(INT
)parentItem
->firstChild
];
1753 aChild
= &infoPtr
->items
[(INT
)infoPtr
->TopRootItem
];
1755 /* Iterate the parent children to see where we fit in */
1756 while ( aChild
!= NULL
)
1758 INT comp
= strcmp(wineItem
->pszText
, aChild
->pszText
);
1759 if ( comp
< 0 ) /* we are smaller than the current one */
1761 TREEVIEW_InsertBefore(infoPtr
, wineItem
, aChild
, parentItem
);
1762 bItemInserted
= TRUE
;
1765 else if ( comp
> 0 ) /* we are bigger than the current one */
1767 previousChild
= aChild
;
1768 aChild
= (aChild
->sibling
== 0) /* This will help us to exit */
1769 ? NULL
/* if there is no more sibling */
1770 : &infoPtr
->items
[(INT
)aChild
->sibling
];
1772 /* Look at the next item */
1775 else if ( comp
== 0 )
1778 * An item with this name is already existing, therefore,
1779 * we add after the one we found
1781 TREEVIEW_InsertAfter(infoPtr
, wineItem
, aChild
, parentItem
);
1782 bItemInserted
= TRUE
;
1788 * we reach the end of the child list and the item as not
1789 * yet been inserted, therefore, insert it after the last child.
1791 if ( (! bItemInserted
) && (aChild
== NULL
) )
1792 TREEVIEW_InsertAfter(infoPtr
, wineItem
, previousChild
, parentItem
);
1798 case (DWORD
) TVI_LAST
:
1799 if (sibItem
==wineItem
) break;
1800 while (sibItem
->sibling
) {
1802 sibItem
=&infoPtr
->items
[(INT
)sibItem
->sibling
];
1804 sibItem
->sibling
=(HTREEITEM
)iItem
;
1805 wineItem
->upsibling
=sibItem
->hItem
;
1808 while ((sibItem
->sibling
) && (sibItem
->hItem
!=ptdi
->hInsertAfter
))
1811 sibItem
=&infoPtr
->items
[(INT
)sibItem
->sibling
];
1813 if (sibItem
->hItem
!=ptdi
->hInsertAfter
) {
1814 ERR("tried to insert item after nonexisting handle %d.\n",
1815 (INT
) ptdi
->hInsertAfter
);
1819 if (sibItem
->sibling
) {
1820 sibItem
=&infoPtr
->items
[(INT
)sibItem
->sibling
];
1821 sibItem
->upsibling
=(HTREEITEM
)iItem
;
1822 wineItem
->sibling
=sibItem
->hItem
;
1824 prevsib
->sibling
=(HTREEITEM
)iItem
;
1825 wineItem
->upsibling
=prevsib
->hItem
;
1831 /* Fill in info structure */
1833 TRACE("new item %d; parent %d, mask %x\n", iItem
,
1834 (INT
)wineItem
->parent
,tvItem
->mask
);
1836 wineItem
->mask
=tvItem
->mask
;
1837 wineItem
->iIntegral
=1;
1839 if (tvItem
->mask
& TVIF_CHILDREN
) {
1840 wineItem
->cChildren
=tvItem
->cChildren
;
1841 if (tvItem
->cChildren
==I_CHILDRENCALLBACK
)
1842 FIXME(" I_CHILDRENCALLBACK not supported\n");
1845 wineItem
->expandBox
.left
= 0; /* Initialize the expandBox */
1846 wineItem
->expandBox
.top
= 0;
1847 wineItem
->expandBox
.right
= 0;
1848 wineItem
->expandBox
.bottom
= 0;
1850 if (tvItem
->mask
& TVIF_IMAGE
)
1851 wineItem
->iImage
=tvItem
->iImage
;
1853 /* If the application sets TVIF_INTEGRAL without
1854 supplying a TVITEMEX structure, it's toast */
1856 if (tvItem
->mask
& TVIF_INTEGRAL
)
1857 wineItem
->iIntegral
=tvItem
->iIntegral
;
1859 if (tvItem
->mask
& TVIF_SELECTEDIMAGE
)
1860 wineItem
->iSelectedImage
=tvItem
->iSelectedImage
;
1862 if (tvItem
->mask
& TVIF_STATE
) {
1863 TRACE("Changing item state from %d to %d\n",
1866 wineItem
->state
=tvItem
->state
;
1867 wineItem
->stateMask
=tvItem
->stateMask
;
1871 TREEVIEW_QueueRefresh (hwnd
);
1873 return (LRESULT
) iItem
;
1878 TREEVIEW_InsertItemW(HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1880 TVINSERTSTRUCTW
*tvisW
;
1881 TVINSERTSTRUCTA tvisA
;
1884 tvisW
= (LPTVINSERTSTRUCTW
)lParam
;
1886 tvisA
.hParent
= tvisW
->hParent
;
1887 tvisA
.hInsertAfter
= tvisW
->hInsertAfter
;
1889 tvisA
.DUMMYUNIONNAME
.item
.mask
= tvisW
->DUMMYUNIONNAME
.item
.mask
;
1890 tvisA
.DUMMYUNIONNAME
.item
.hItem
= tvisW
->DUMMYUNIONNAME
.item
.hItem
;
1891 tvisA
.DUMMYUNIONNAME
.item
.state
= tvisW
->DUMMYUNIONNAME
.item
.state
;
1892 tvisA
.DUMMYUNIONNAME
.item
.stateMask
= tvisW
->DUMMYUNIONNAME
.item
.stateMask
;
1893 tvisA
.DUMMYUNIONNAME
.item
.cchTextMax
= tvisW
->DUMMYUNIONNAME
.item
.cchTextMax
;
1895 if(tvisW
->DUMMYUNIONNAME
.item
.pszText
)
1897 if (tvisW
->DUMMYUNIONNAME
.item
.pszText
!=LPSTR_TEXTCALLBACKW
)
1899 int len
= lstrlenW (tvisW
->DUMMYUNIONNAME
.item
.pszText
)+1;
1900 tvisA
.DUMMYUNIONNAME
.item
.pszText
= COMCTL32_Alloc (len
);
1901 lstrcpyWtoA (tvisA
.DUMMYUNIONNAME
.item
.pszText
,
1902 tvisW
->DUMMYUNIONNAME
.item
.pszText
);
1906 tvisA
.DUMMYUNIONNAME
.item
.pszText
= LPSTR_TEXTCALLBACKA
;
1907 tvisA
.DUMMYUNIONNAME
.item
.cchTextMax
= 0;
1911 tvisA
.DUMMYUNIONNAME
.item
.iImage
= tvisW
->DUMMYUNIONNAME
.item
.iImage
;
1912 tvisA
.DUMMYUNIONNAME
.item
.iSelectedImage
= tvisW
->DUMMYUNIONNAME
.item
.iSelectedImage
;
1913 tvisA
.DUMMYUNIONNAME
.item
.cChildren
= tvisW
->DUMMYUNIONNAME
.item
.cChildren
;
1914 tvisA
.DUMMYUNIONNAME
.item
.lParam
= tvisW
->DUMMYUNIONNAME
.item
.lParam
;
1916 lRes
= TREEVIEW_InsertItemA(hwnd
,wParam
,(LPARAM
)&tvisA
);
1918 if (tvisA
.DUMMYUNIONNAME
.item
.pszText
!=LPSTR_TEXTCALLBACKA
)
1920 COMCTL32_Free(tvisA
.DUMMYUNIONNAME
.item
.pszText
);
1929 TREEVIEW_DeleteItem (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1931 TREEVIEW_INFO
*infoPtr
= TREEVIEW_GetInfoPtr(hwnd
);
1933 TREEVIEW_ITEM
*wineItem
;
1936 if (!infoPtr
) return FALSE
;
1938 if (lParam
== (INT
)TVI_ROOT
) {
1939 TREEVIEW_RemoveTree (hwnd
);
1941 iItem
= (INT
) lParam
;
1942 wineItem
= TREEVIEW_ValidItem (infoPtr
, (HTREEITEM
)iItem
);
1943 if (!wineItem
) return FALSE
;
1944 TRACE("%s\n",wineItem
->pszText
);
1945 TREEVIEW_RemoveItem (hwnd
, wineItem
);
1948 TREEVIEW_QueueRefresh (hwnd
);
1956 TREEVIEW_GetIndent (HWND hwnd
)
1958 TREEVIEW_INFO
*infoPtr
= TREEVIEW_GetInfoPtr(hwnd
);
1961 return infoPtr
->uIndent
;
1965 TREEVIEW_SetIndent (HWND hwnd
, WPARAM wParam
)
1967 TREEVIEW_INFO
*infoPtr
= TREEVIEW_GetInfoPtr(hwnd
);
1971 newIndent
=(INT
) wParam
;
1972 if (newIndent
< MINIMUM_INDENT
) newIndent
=MINIMUM_INDENT
;
1973 infoPtr
->uIndent
=newIndent
;
1979 TREEVIEW_GetToolTips (HWND hwnd
)
1982 TREEVIEW_INFO
*infoPtr
= TREEVIEW_GetInfoPtr(hwnd
);
1985 return infoPtr
->hwndToolTip
;
1990 TREEVIEW_SetToolTips (HWND hwnd
, WPARAM wParam
)
1993 TREEVIEW_INFO
*infoPtr
= TREEVIEW_GetInfoPtr(hwnd
);
1997 prevToolTip
=infoPtr
->hwndToolTip
;
1998 infoPtr
->hwndToolTip
= (HWND
) wParam
;
2004 static LRESULT CALLBACK
2005 TREEVIEW_GetEditControl (HWND hwnd
)
2008 TREEVIEW_INFO
*infoPtr
= TREEVIEW_GetInfoPtr(hwnd
);
2010 return infoPtr
->hwndEdit
;
2014 TREEVIEW_Edit_SubclassProc (HWND hwnd
, UINT uMsg
, WPARAM wParam
,
2022 HDC hdc
= (HDC
) wParam
;
2023 GetClientRect (hwnd
, &rc
);
2024 Rectangle (hdc
, rc
.left
, rc
.top
, rc
.right
, rc
.bottom
);
2030 return DLGC_WANTARROWS
| DLGC_WANTALLKEYS
;
2035 TREEVIEW_INFO
*infoPtr
= TREEVIEW_GetInfoPtr(GetParent(hwnd
));
2036 return CallWindowProcA( infoPtr
->wpEditOrig
, hwnd
, uMsg
, wParam
, lParam
);
2044 /* should handle edit control messages here */
2047 TREEVIEW_Command (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
2050 TRACE("%x %ld\n",wParam
, lParam
);
2052 switch (HIWORD(wParam
))
2057 * Adjust the edit window size
2059 TREEVIEW_INFO
*infoPtr
= TREEVIEW_GetInfoPtr(hwnd
);
2060 TREEVIEW_ITEM
*editItem
= TREEVIEW_ValidItem(infoPtr
, infoPtr
->editItem
);
2061 INT iLength
= GetWindowTextLengthA(infoPtr
->hwndEdit
);
2062 HDC hdc
= GetDC(infoPtr
->hwndEdit
);
2065 if ( GetTextMetricsA(hdc
, &tm
) )
2067 LONG newWidth
= (iLength
* tm
.tmAveCharWidth
) + 15;
2072 editItem
->text
.left
- 2,
2073 editItem
->text
.top
- 1,
2075 editItem
->text
.bottom
- editItem
->text
.top
+ 3,
2078 ReleaseDC(hwnd
, hdc
);
2084 /* TREEVIEW_EndEditLabelNow(hwnd, (WPARAM)FALSE, 0);
2089 return SendMessageA (GetParent (hwnd
), WM_COMMAND
, wParam
, lParam
);
2096 TREEVIEW_Size (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
2099 TREEVIEW_INFO
*infoPtr
= TREEVIEW_GetInfoPtr(hwnd
);
2101 if (infoPtr
->bAutoSize
)
2103 infoPtr
->bAutoSize
= FALSE
;
2106 infoPtr
->bAutoSize
= TRUE
;
2108 if (wParam
== SIZE_RESTORED
)
2110 infoPtr
->uTotalWidth
= LOWORD (lParam
);
2111 infoPtr
->uTotalHeight
= HIWORD (lParam
);
2113 FIXME("WM_SIZE flag %x %lx not handled\n", wParam
, lParam
);
2116 TREEVIEW_QueueRefresh (hwnd
);
2123 TREEVIEW_StyleChanged (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
2125 TRACE("(%x %lx)\n",wParam
,lParam
);
2127 TREEVIEW_Refresh (hwnd
);
2133 TREEVIEW_Create (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
2135 TREEVIEW_INFO
*infoPtr
;
2140 TRACE("wnd %x\n",hwnd
);
2141 /* allocate memory for info structure */
2142 infoPtr
= (TREEVIEW_INFO
*) COMCTL32_Alloc (sizeof(TREEVIEW_INFO
));
2144 SetWindowLongA( hwnd
, 0, (DWORD
)infoPtr
);
2146 if (infoPtr
== NULL
) {
2147 ERR("could not allocate info memory!\n");
2151 if ((TREEVIEW_INFO
*) GetWindowLongA( hwnd
, 0) != infoPtr
) {
2152 ERR("pointer assignment error!\n");
2158 /* set default settings */
2159 infoPtr
->uInternalStatus
=0;
2160 infoPtr
->uNumItems
=0;
2161 infoPtr
->clrBk
= GetSysColor (COLOR_WINDOW
);
2162 infoPtr
->clrText
= GetSysColor (COLOR_BTNTEXT
);
2163 infoPtr
->clrLine
= GetSysColor (COLOR_WINDOWTEXT
);
2166 infoPtr
->uIndent
= 15;
2167 infoPtr
->himlNormal
= NULL
;
2168 infoPtr
->himlState
= NULL
;
2169 infoPtr
->uItemHeight
= -1;
2170 GetTextMetricsA (hdc
, &tm
);
2171 infoPtr
->hFont
= GetStockObject (DEFAULT_GUI_FONT
);
2172 GetObjectA (infoPtr
->hFont
, sizeof (LOGFONTA
), &logFont
);
2173 logFont
.lfWeight
=FW_BOLD
;
2174 infoPtr
->hBoldFont
= CreateFontIndirectA (&logFont
);
2176 infoPtr
->items
= NULL
;
2177 infoPtr
->selectedItem
=0;
2178 infoPtr
->clrText
=-1; /* use system color */
2179 infoPtr
->dropItem
=0;
2180 infoPtr
->pCallBackSort
=NULL
;
2181 infoPtr
->uScrollTime
= 300; /* milliseconds */
2184 infoPtr->hwndNotify = GetParent32 (hwnd);
2185 infoPtr->bTransparent = ( GetWindowLongA( hwnd, GWL_STYLE) & TBSTYLE_FLAT);
2188 infoPtr
->hwndToolTip
=0;
2189 if (!( GetWindowLongA( hwnd
, GWL_STYLE
) & TVS_NOTOOLTIPS
)) { /* Create tooltip control */
2192 infoPtr
->hwndToolTip
=
2193 CreateWindowExA (0, TOOLTIPS_CLASSA
, NULL
, 0,
2194 CW_USEDEFAULT
, CW_USEDEFAULT
,
2195 CW_USEDEFAULT
, CW_USEDEFAULT
,
2198 /* Send NM_TOOLTIPSCREATED notification */
2199 if (infoPtr
->hwndToolTip
) {
2200 NMTOOLTIPSCREATED nmttc
;
2202 nmttc
.hdr
.hwndFrom
= hwnd
;
2203 nmttc
.hdr
.idFrom
= GetWindowLongA( hwnd
, GWL_ID
);
2204 nmttc
.hdr
.code
= NM_TOOLTIPSCREATED
;
2205 nmttc
.hwndToolTips
= infoPtr
->hwndToolTip
;
2207 SendMessageA (GetParent (hwnd
), WM_NOTIFY
,
2208 (WPARAM
) GetWindowLongA( hwnd
, GWL_ID
), (LPARAM
)&nmttc
);
2211 ZeroMemory (&ti
, sizeof(TTTOOLINFOA
));
2212 ti
.cbSize
= sizeof(TTTOOLINFOA
);
2213 ti
.uFlags
= TTF_IDISHWND
| TTF_TRACK
| TTF_TRANSPARENT
;
2216 ti
.lpszText
= "Test"; /* LPSTR_TEXTCALLBACK; */
2217 SetRectEmpty (&ti
.rect
);
2219 SendMessageA (infoPtr
->hwndToolTip
, TTM_ADDTOOLA
, 0, (LPARAM
)&ti
);
2222 infoPtr
->hwndEdit
= CreateWindowExA (
2226 WS_CHILD
| WS_BORDER
| ES_AUTOHSCROLL
|
2227 ES_WANTRETURN
| ES_LEFT
,
2230 0,0,0); /* FIXME: (HMENU)IDTVEDIT,pcs->hInstance,0);*/
2232 SendMessageA ( infoPtr
->hwndEdit
, WM_SETFONT
, infoPtr
->hFont
, FALSE
);
2233 infoPtr
->wpEditOrig
= (WNDPROC
)SetWindowLongA (
2236 (LONG
) TREEVIEW_Edit_SubclassProc
);
2238 ReleaseDC (hwnd
, hdc
);
2245 TREEVIEW_Destroy (HWND hwnd
)
2247 TREEVIEW_INFO
*infoPtr
= TREEVIEW_GetInfoPtr(hwnd
);
2250 TREEVIEW_RemoveTree (hwnd
);
2251 if (infoPtr
->Timer
& TV_REFRESH_TIMER_SET
)
2252 KillTimer (hwnd
, TV_REFRESH_TIMER
);
2253 if (infoPtr
->hwndToolTip
)
2254 DestroyWindow (infoPtr
->hwndToolTip
);
2256 COMCTL32_Free (infoPtr
);
2262 TREEVIEW_Paint (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
2268 hdc
= wParam
==0 ? BeginPaint (hwnd
, &ps
) : (HDC
)wParam
;
2269 TREEVIEW_Refresh (hwnd
);
2271 EndPaint (hwnd
, &ps
);
2274 return DefWindowProcA (hwnd
, WM_PAINT
, wParam
, lParam
);
2278 TREEVIEW_SetFocus (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
2280 TREEVIEW_SendSimpleNotify (hwnd
, NM_SETFOCUS
);
2281 InvalidateRect(hwnd
, NULL
, FALSE
);
2286 TREEVIEW_KillFocus (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
2288 TREEVIEW_SendSimpleNotify (hwnd
, NM_KILLFOCUS
);
2289 InvalidateRect(hwnd
, NULL
, FALSE
);
2294 TREEVIEW_EraseBackground (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
2296 TREEVIEW_INFO
*infoPtr
= TREEVIEW_GetInfoPtr(hwnd
);
2297 HBRUSH hBrush
= CreateSolidBrush (infoPtr
->clrBk
);
2301 GetClientRect (hwnd
, &rect
);
2302 FillRect ((HDC
)wParam
, &rect
, hBrush
);
2303 DeleteObject (hBrush
);
2319 TREEVIEW_SendSimpleNotify (HWND hwnd
, UINT code
)
2324 nmhdr
.hwndFrom
= hwnd
;
2325 nmhdr
.idFrom
= GetWindowLongA( hwnd
, GWL_ID
);
2328 return (BOOL
) SendMessageA (GetParent (hwnd
), WM_NOTIFY
,
2329 (WPARAM
)nmhdr
.idFrom
, (LPARAM
)&nmhdr
);
2335 TREEVIEW_SendTreeviewNotify (HWND hwnd
, UINT code
, UINT action
,
2336 HTREEITEM oldItem
, HTREEITEM newItem
)
2339 TREEVIEW_INFO
*infoPtr
= TREEVIEW_GetInfoPtr(hwnd
);
2341 TREEVIEW_ITEM
*wineItem
;
2343 TRACE("code:%x action:%x olditem:%x newitem:%x\n",
2344 code
,action
,(INT
)oldItem
,(INT
)newItem
);
2345 nmhdr
.hdr
.hwndFrom
= hwnd
;
2346 nmhdr
.hdr
.idFrom
= GetWindowLongA( hwnd
, GWL_ID
);
2347 nmhdr
.hdr
.code
= code
;
2348 nmhdr
.action
= action
;
2350 wineItem
=& infoPtr
->items
[(INT
)oldItem
];
2351 nmhdr
.itemOld
.mask
= wineItem
->mask
;
2352 nmhdr
.itemOld
.hItem
= wineItem
->hItem
;
2353 nmhdr
.itemOld
.state
= wineItem
->state
;
2354 nmhdr
.itemOld
.stateMask
= wineItem
->stateMask
;
2355 nmhdr
.itemOld
.iImage
= wineItem
->iImage
;
2356 nmhdr
.itemOld
.pszText
= wineItem
->pszText
;
2357 nmhdr
.itemOld
.cchTextMax
= wineItem
->cchTextMax
;
2358 nmhdr
.itemOld
.iImage
= wineItem
->iImage
;
2359 nmhdr
.itemOld
.iSelectedImage
= wineItem
->iSelectedImage
;
2360 nmhdr
.itemOld
.cChildren
= wineItem
->cChildren
;
2361 nmhdr
.itemOld
.lParam
= wineItem
->lParam
;
2365 wineItem
=& infoPtr
->items
[(INT
)newItem
];
2366 nmhdr
.itemNew
.mask
= wineItem
->mask
;
2367 nmhdr
.itemNew
.hItem
= wineItem
->hItem
;
2368 nmhdr
.itemNew
.state
= wineItem
->state
;
2369 nmhdr
.itemNew
.stateMask
= wineItem
->stateMask
;
2370 nmhdr
.itemNew
.iImage
= wineItem
->iImage
;
2371 nmhdr
.itemNew
.pszText
= wineItem
->pszText
;
2372 nmhdr
.itemNew
.cchTextMax
= wineItem
->cchTextMax
;
2373 nmhdr
.itemNew
.iImage
= wineItem
->iImage
;
2374 nmhdr
.itemNew
.iSelectedImage
= wineItem
->iSelectedImage
;
2375 nmhdr
.itemNew
.cChildren
= wineItem
->cChildren
;
2376 nmhdr
.itemNew
.lParam
= wineItem
->lParam
;
2382 return (BOOL
)SendMessageA (GetParent (hwnd
), WM_NOTIFY
,
2383 (WPARAM
) GetWindowLongA( hwnd
, GWL_ID
), (LPARAM
)&nmhdr
);
2388 TREEVIEW_SendTreeviewDnDNotify (HWND hwnd
, UINT code
, HTREEITEM dragItem
,
2391 TREEVIEW_INFO
*infoPtr
= TREEVIEW_GetInfoPtr(hwnd
);
2393 TREEVIEW_ITEM
*wineItem
;
2395 TRACE("code:%x dragitem:%x\n", code
,(INT
)dragItem
);
2397 nmhdr
.hdr
.hwndFrom
= hwnd
;
2398 nmhdr
.hdr
.idFrom
= GetWindowLongA( hwnd
, GWL_ID
);
2399 nmhdr
.hdr
.code
= code
;
2401 wineItem
=& infoPtr
->items
[(INT
)dragItem
];
2402 nmhdr
.itemNew
.mask
= wineItem
->mask
;
2403 nmhdr
.itemNew
.hItem
= wineItem
->hItem
;
2404 nmhdr
.itemNew
.state
= wineItem
->state
;
2405 nmhdr
.itemNew
.lParam
= wineItem
->lParam
;
2407 nmhdr
.ptDrag
.x
= pt
.x
;
2408 nmhdr
.ptDrag
.y
= pt
.y
;
2410 return (BOOL
)SendMessageA (GetParent (hwnd
), WM_NOTIFY
,
2411 (WPARAM
) GetWindowLongA( hwnd
, GWL_ID
), (LPARAM
)&nmhdr
);
2418 TREEVIEW_SendDispInfoNotify (HWND hwnd
, TREEVIEW_ITEM
*wineItem
,
2419 UINT code
, UINT what
)
2425 TRACE("item %d, action %x, state %d\n",
2426 (INT
)wineItem
->hItem
,
2428 (INT
)wineItem
->state
);
2430 tvdi
.hdr
.hwndFrom
= hwnd
;
2431 tvdi
.hdr
.idFrom
= GetWindowLongA( hwnd
, GWL_ID
);
2432 tvdi
.hdr
.code
= code
;
2433 tvdi
.item
.mask
= what
;
2434 tvdi
.item
.hItem
= wineItem
->hItem
;
2435 tvdi
.item
.state
= wineItem
->state
;
2436 tvdi
.item
.lParam
= wineItem
->lParam
;
2437 tvdi
.item
.pszText
= COMCTL32_Alloc (128*sizeof(char));
2438 tvdi
.item
.cchTextMax
= 128;
2439 buf
= tvdi
.item
.pszText
;
2441 retval
=(BOOL
)SendMessageA (
2444 (WPARAM
)tvdi
.hdr
.idFrom
,
2447 if (what
& TVIF_TEXT
) {
2448 wineItem
->pszText
= tvdi
.item
.pszText
;
2449 if (buf
==tvdi
.item
.pszText
) {
2450 wineItem
->cchTextMax
= 128;
2452 TRACE("user-supplied buffer\n");
2453 COMCTL32_Free (buf
);
2454 wineItem
->cchTextMax
= 0;
2457 if (what
& TVIF_SELECTEDIMAGE
)
2458 wineItem
->iSelectedImage
= tvdi
.item
.iSelectedImage
;
2459 if (what
& TVIF_IMAGE
)
2460 wineItem
->iImage
= tvdi
.item
.iImage
;
2461 if (what
& TVIF_CHILDREN
)
2462 wineItem
->cChildren
= tvdi
.item
.cChildren
;
2470 TREEVIEW_SendCustomDrawNotify (HWND hwnd
, DWORD dwDrawStage
, HDC hdc
,
2473 TREEVIEW_INFO
*infoPtr
= TREEVIEW_GetInfoPtr(hwnd
);
2474 NMTVCUSTOMDRAW nmcdhdr
;
2475 LPNMCUSTOMDRAW nmcd
;
2477 TRACE("drawstage:%lx hdc:%x\n", dwDrawStage
, hdc
);
2479 nmcd
= & nmcdhdr
.nmcd
;
2480 nmcd
->hdr
.hwndFrom
= hwnd
;
2481 nmcd
->hdr
.idFrom
= GetWindowLongA( hwnd
, GWL_ID
);
2482 nmcd
->hdr
.code
= NM_CUSTOMDRAW
;
2483 nmcd
->dwDrawStage
= dwDrawStage
;
2485 nmcd
->rc
.left
= rc
.left
;
2486 nmcd
->rc
.right
= rc
.right
;
2487 nmcd
->rc
.bottom
= rc
.bottom
;
2488 nmcd
->rc
.top
= rc
.top
;
2489 nmcd
->dwItemSpec
= 0;
2490 nmcd
->uItemState
= 0;
2491 nmcd
->lItemlParam
= 0;
2492 nmcdhdr
.clrText
= infoPtr
->clrText
;
2493 nmcdhdr
.clrTextBk
= infoPtr
->clrBk
;
2496 return (BOOL
)SendMessageA (GetParent (hwnd
), WM_NOTIFY
,
2497 (WPARAM
) GetWindowLongA( hwnd
, GWL_ID
), (LPARAM
)&nmcdhdr
);
2503 /* FIXME: need to find out when the flags in uItemState need to be set */
2506 TREEVIEW_SendCustomDrawItemNotify (HWND hwnd
, HDC hdc
,
2507 TREEVIEW_ITEM
*wineItem
, UINT uItemDrawState
)
2509 TREEVIEW_INFO
*infoPtr
= TREEVIEW_GetInfoPtr(hwnd
);
2510 NMTVCUSTOMDRAW nmcdhdr
;
2511 LPNMCUSTOMDRAW nmcd
;
2512 DWORD dwDrawStage
,dwItemSpec
;
2515 dwDrawStage
=CDDS_ITEM
| uItemDrawState
;
2516 dwItemSpec
=(DWORD
)wineItem
->hItem
;
2518 if (wineItem
->hItem
==infoPtr
->selectedItem
) uItemState
|=CDIS_SELECTED
;
2519 if (wineItem
->hItem
==infoPtr
->focusItem
) uItemState
|=CDIS_FOCUS
;
2520 if (wineItem
->hItem
==infoPtr
->hotItem
) uItemState
|=CDIS_HOT
;
2522 nmcd
= & nmcdhdr
.nmcd
;
2523 nmcd
->hdr
.hwndFrom
= hwnd
;
2524 nmcd
->hdr
.idFrom
= GetWindowLongA( hwnd
, GWL_ID
);
2525 nmcd
->hdr
.code
= NM_CUSTOMDRAW
;
2526 nmcd
->dwDrawStage
= dwDrawStage
;
2528 nmcd
->rc
.left
= wineItem
->rect
.left
;
2529 nmcd
->rc
.right
= wineItem
->rect
.right
;
2530 nmcd
->rc
.bottom
= wineItem
->rect
.bottom
;
2531 nmcd
->rc
.top
= wineItem
->rect
.top
;
2532 nmcd
->dwItemSpec
= dwItemSpec
;
2533 nmcd
->uItemState
= uItemState
;
2534 nmcd
->lItemlParam
= wineItem
->lParam
;
2536 nmcdhdr
.clrText
= infoPtr
->clrText
;
2537 nmcdhdr
.clrTextBk
= infoPtr
->clrBk
;
2538 nmcdhdr
.iLevel
= wineItem
->iLevel
;
2540 TRACE("drawstage:%lx hdc:%x item:%lx, itemstate:%x\n",
2541 dwDrawStage
, hdc
, dwItemSpec
, uItemState
);
2543 return (BOOL
)SendMessageA (GetParent (hwnd
), WM_NOTIFY
,
2544 (WPARAM
) GetWindowLongA( hwnd
, GWL_ID
), (LPARAM
)&nmcdhdr
);
2549 /* Note:If the specified item is the child of a collapsed parent item,
2550 the parent's list of child items is (recursively) expanded to reveal the
2551 specified item. This is mentioned for TREEVIEW_SelectItem; don't
2552 know if it also applies here.
2556 TREEVIEW_Expand (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
2558 TREEVIEW_INFO
*infoPtr
= TREEVIEW_GetInfoPtr(hwnd
);
2559 TREEVIEW_ITEM
*wineItem
;
2563 flag
= (UINT
) wParam
;
2564 expand
= (INT
) lParam
;
2566 wineItem
= TREEVIEW_ValidItem (infoPtr
, (HTREEITEM
)expand
);
2570 if (!wineItem
->cChildren
)
2573 if (wineItem
->pszText
==LPSTR_TEXTCALLBACKA
)
2574 TRACE ("For item %d, flags %d, state %d\n",
2575 expand
, flag
, wineItem
->state
);
2577 TRACE("For (%s) item:%d, flags %x, state:%d\n",
2578 wineItem
->pszText
, flag
, expand
, wineItem
->state
);
2580 if (wineItem
->cChildren
==I_CHILDRENCALLBACK
) {
2581 FIXME("we don't handle I_CHILDRENCALLBACK yet\n");
2585 if (flag
== TVE_TOGGLE
) { /* FIXME: check exact behaviour here */
2586 flag
&= ~TVE_TOGGLE
; /* ie: bitwise ops or 'case' ops */
2587 if (wineItem
->state
& TVIS_EXPANDED
)
2588 flag
|= TVE_COLLAPSE
;
2595 case TVE_COLLAPSERESET
:
2596 TRACE(" case TVE_COLLAPSERESET\n");
2597 if (!wineItem
->state
& TVIS_EXPANDED
)
2600 wineItem
->state
&= ~(TVIS_EXPANDEDONCE
| TVIS_EXPANDED
);
2601 TREEVIEW_RemoveAllChildren (hwnd
, wineItem
);
2605 TRACE(" case TVE_COLLAPSE\n");
2606 if (!wineItem
->state
& TVIS_EXPANDED
)
2609 wineItem
->state
&= ~TVIS_EXPANDED
;
2613 TRACE(" case TVE_EXPAND\n");
2614 if (wineItem
->state
& TVIS_EXPANDED
)
2617 TRACE(" is not expanded...\n");
2619 if (!(wineItem
->state
& TVIS_EXPANDEDONCE
))
2621 TRACE(" and has never been expanded...\n");
2622 wineItem
->state
|= TVIS_EXPANDED
;
2624 /* this item has never been expanded */
2625 if (TREEVIEW_SendTreeviewNotify (
2632 TRACE(" TVN_ITEMEXPANDING returned TRUE, exiting...\n");
2637 * Since the TVN_ITEMEXPANDING message may has caused the parent to
2638 * insert new items which in turn may have cause items placeholder
2639 * reallocation, I reassign the current item pointer so we have
2640 * something valid to work with...
2641 * However, this should not be necessary,
2642 * investigation required in TREEVIEW_InsertItemA
2644 wineItem
= TREEVIEW_ValidItem (infoPtr
, (HTREEITEM
)expand
);
2648 "Catastropic situation, cannot retreive item #%d\n",
2653 wineItem
->state
|= TVIS_EXPANDEDONCE
;
2654 TRACE(" TVN_ITEMEXPANDING sent...\n");
2656 TREEVIEW_SendTreeviewNotify (
2663 TRACE(" TVN_ITEMEXPANDED sent...\n");
2668 /* this item has already been expanded */
2669 wineItem
->state
|= TVIS_EXPANDED
;
2673 case TVE_EXPANDPARTIAL
:
2674 TRACE(" case TVE_EXPANDPARTIAL\n");
2675 FIXME("TVE_EXPANDPARTIAL not implemented\n");
2676 wineItem
->state
^=TVIS_EXPANDED
;
2677 wineItem
->state
|=TVIS_EXPANDEDONCE
;
2681 TRACE("Exiting, Item %d state is now %d...\n",
2685 TREEVIEW_QueueRefresh (hwnd
);
2691 static TREEVIEW_ITEM
*
2692 TREEVIEW_HitTestPoint (HWND hwnd
, POINT pt
)
2694 TREEVIEW_INFO
*infoPtr
= TREEVIEW_GetInfoPtr(hwnd
);
2695 TREEVIEW_ITEM
*wineItem
;
2698 GetClientRect (hwnd
, &rect
);
2700 if (!infoPtr
->firstVisible
) return NULL
;
2702 wineItem
=&infoPtr
->items
[(INT
)infoPtr
->firstVisible
];
2704 while ((wineItem
!=NULL
) && (pt
.y
> wineItem
->rect
.bottom
))
2705 wineItem
=TREEVIEW_GetNextListItem (infoPtr
,wineItem
);
2717 TREEVIEW_HitTest (HWND hwnd
, LPARAM lParam
)
2719 LPTVHITTESTINFO lpht
=(LPTVHITTESTINFO
) lParam
;
2720 TREEVIEW_ITEM
*wineItem
;
2724 GetClientRect (hwnd
, &rect
);
2728 if (x
< rect
.left
) status
|=TVHT_TOLEFT
;
2729 if (x
> rect
.right
) status
|=TVHT_TORIGHT
;
2730 if (y
< rect
.top
) status
|=TVHT_ABOVE
;
2731 if (y
> rect
.bottom
) status
|=TVHT_BELOW
;
2738 wineItem
=TREEVIEW_HitTestPoint (hwnd
, lpht
->pt
);
2740 lpht
->flags
=TVHT_NOWHERE
;
2744 /* FIXME: implement other flags
2745 * Assign the appropriate flags depending on the click location
2746 * Intitialize flags before to "|=" it...
2750 if (x
< wineItem
->expandBox
.left
)
2752 lpht
->flags
|= TVHT_ONITEMINDENT
;
2754 else if ( ( x
>= wineItem
->expandBox
.left
) &&
2755 ( x
<= wineItem
->expandBox
.right
))
2757 lpht
->flags
|= TVHT_ONITEMBUTTON
;
2759 else if (x
< wineItem
->rect
.right
)
2761 lpht
->flags
|= TVHT_ONITEMLABEL
;
2765 lpht
->flags
|=TVHT_ONITEMRIGHT
;
2768 lpht
->hItem
=wineItem
->hItem
;
2770 return (LRESULT
) wineItem
->hItem
;
2774 TREEVIEW_EndEditLabelNow (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
2776 TREEVIEW_INFO
*infoPtr
= TREEVIEW_GetInfoPtr(hwnd
);
2777 TREEVIEW_ITEM
*editedItem
= TREEVIEW_ValidItem (infoPtr
, infoPtr
->editItem
);
2778 BOOL bRevert
= (BOOL
)wParam
;
2779 BOOL bReturn
= ! bRevert
;
2781 if ( ! (BOOL
)wParam
) /* wParam is set to true to cancel the edition */
2783 if ( TREEVIEW_SendDispInfoNotify( /* return true to cancel edition */
2794 if (bRevert
== FALSE
) /* Apply the changes */
2797 int iLength
= GetWindowTextA(infoPtr
->hwndEdit
, tmpText
, 1023);
2802 ERR("Problem retreiving new item label.");
2804 else if (iLength
>= 1023)
2807 "Insuficient space to retrieve new item label, new label ignored.");
2811 if (strcmp( tmpText
, editedItem
->pszText
) == 0)
2812 /* Do nothing if the label has not changed */
2816 LPSTR tmpLabel
= COMCTL32_Alloc( iLength
+1 );
2818 if ( tmpLabel
== NULL
)
2820 "OutOfMemory, cannot allocate space for label");
2823 COMCTL32_Free(editedItem
->pszText
);
2824 editedItem
->pszText
= tmpLabel
;
2825 lstrcpyA( editedItem
->pszText
, tmpText
);
2831 ShowWindow(infoPtr
->hwndEdit
, SW_HIDE
);
2832 EnableWindow(infoPtr
->hwndEdit
, FALSE
);
2833 infoPtr
->editItem
= 0;
2842 TREEVIEW_LButtonDoubleClick (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
2844 TREEVIEW_ITEM
*wineItem
;
2848 pt
.x
= (INT
)LOWORD(lParam
);
2849 pt
.y
= (INT
)HIWORD(lParam
);
2852 wineItem
=TREEVIEW_HitTestPoint (hwnd
, pt
);
2853 if (!wineItem
) return 0;
2854 TRACE("item %d \n",(INT
)wineItem
->hItem
);
2856 if (TREEVIEW_SendSimpleNotify (hwnd
, NM_DBLCLK
)!=TRUE
) { /* FIXME!*/
2857 TREEVIEW_Expand (hwnd
, (WPARAM
) TVE_TOGGLE
, (LPARAM
) wineItem
->hItem
);
2864 TREEVIEW_LButtonDown (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
2866 TREEVIEW_INFO
*infoPtr
= TREEVIEW_GetInfoPtr(hwnd
);
2870 ht
.pt
.x
= (INT
)LOWORD(lParam
);
2871 ht
.pt
.y
= (INT
)HIWORD(lParam
);
2874 iItem
=TREEVIEW_HitTest (hwnd
, (LPARAM
) &ht
);
2875 TRACE("item %d \n",iItem
);
2877 if (ht
.flags
& TVHT_ONITEMBUTTON
) {
2878 TREEVIEW_Expand (hwnd
, (WPARAM
) TVE_TOGGLE
, (LPARAM
) iItem
);
2882 infoPtr
->uInternalStatus
|=TV_LDRAG
;
2889 TREEVIEW_LButtonUp (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
2891 TREEVIEW_INFO
*infoPtr
= TREEVIEW_GetInfoPtr(hwnd
);
2893 TREEVIEW_ITEM
*editItem
;
2896 ht
.pt
.x
= (INT
)LOWORD(lParam
);
2897 ht
.pt
.y
= (INT
)HIWORD(lParam
);
2901 /* Return true to cancel default behaviour */
2902 if ( TREEVIEW_SendSimpleNotify (hwnd
, NM_CLICK
) )
2906 iItem
= TREEVIEW_HitTest (hwnd
, (LPARAM
) &ht
);
2910 editItem
= TREEVIEW_ValidItem(infoPtr
, (HTREEITEM
)iItem
);
2912 infoPtr
->uInternalStatus
&= ~(TV_LDRAG
| TV_LDRAGGING
);
2915 * If the style allow editing and the node is already selected
2916 * and the click occured on the item label...
2918 if ( ( GetWindowLongA( hwnd
, GWL_STYLE
) & TVS_EDITLABELS
) &&
2919 ( editItem
->state
& TVIS_SELECTED
) &&
2920 ( ht
.flags
& TVHT_ONITEMLABEL
))
2922 if ( infoPtr
->editItem
== 0 ) /* If we are not curently editing */
2924 if ( TREEVIEW_SendDispInfoNotify( /* Return true to cancel edition */
2933 TRACE("Edit started for %s.\n", editItem
->pszText
);
2934 infoPtr
->editItem
= editItem
->hItem
;
2939 editItem
->text
.left
- 2,
2940 editItem
->text
.top
- 1,
2941 editItem
->text
.right
- editItem
->text
.left
+ 20 ,
2942 editItem
->text
.bottom
- editItem
->text
.top
+ 3,
2945 SetWindowTextA( infoPtr
->hwndEdit
, editItem
->pszText
);
2946 SendMessageA ( infoPtr
->hwndEdit
, EM_SETSEL
, 0, -1 );
2947 SetFocus ( infoPtr
->hwndEdit
);
2948 ShowWindow ( infoPtr
->hwndEdit
, SW_SHOW
);
2951 else if ( infoPtr
->editItem
!= 0 ) /* If we are curently editing */
2953 TREEVIEW_EndEditLabelNow(hwnd
, (WPARAM
)FALSE
, 0);
2955 else if ( ht
.flags
& (TVHT_ONITEMLABEL
| TVHT_ONITEMICON
))
2957 TREEVIEW_DoSelectItem (
2969 TREEVIEW_RButtonDown (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
2971 TREEVIEW_INFO
*infoPtr
= TREEVIEW_GetInfoPtr(hwnd
);
2974 infoPtr
->uInternalStatus
|=TV_RDRAG
;
2979 TREEVIEW_RButtonUp (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
2981 TREEVIEW_INFO
*infoPtr
= TREEVIEW_GetInfoPtr(hwnd
);
2984 if (TREEVIEW_SendSimpleNotify (hwnd
, NM_RCLICK
)) return 0;
2985 infoPtr
->uInternalStatus
&= ~(TV_RDRAG
| TV_RDRAGGING
);
2991 TREEVIEW_MouseMove (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
2993 TREEVIEW_INFO
*infoPtr
= TREEVIEW_GetInfoPtr(hwnd
);
2994 TREEVIEW_ITEM
*hotItem
;
2997 pt
.x
=(INT
) LOWORD (lParam
);
2998 pt
.y
=(INT
) HIWORD (lParam
);
2999 hotItem
=TREEVIEW_HitTestPoint (hwnd
, pt
);
3000 if (!hotItem
) return 0;
3001 infoPtr
->focusItem
=hotItem
->hItem
;
3003 if ( GetWindowLongA( hwnd
, GWL_STYLE
) & TVS_DISABLEDRAGDROP
) return 0;
3005 if (infoPtr
->uInternalStatus
& TV_LDRAG
) {
3006 TREEVIEW_SendTreeviewDnDNotify (hwnd
, TVN_BEGINDRAG
, hotItem
->hItem
, pt
);
3007 infoPtr
->uInternalStatus
&= ~TV_LDRAG
;
3008 infoPtr
->uInternalStatus
|= TV_LDRAGGING
;
3009 infoPtr
->dropItem
=hotItem
->hItem
;
3013 if (infoPtr
->uInternalStatus
& TV_RDRAG
) {
3014 TREEVIEW_SendTreeviewDnDNotify (hwnd
, TVN_BEGINRDRAG
, hotItem
->hItem
, pt
);
3015 infoPtr
->uInternalStatus
&= ~TV_RDRAG
;
3016 infoPtr
->uInternalStatus
|= TV_RDRAGGING
;
3017 infoPtr
->dropItem
=hotItem
->hItem
;
3026 TREEVIEW_CreateDragImage (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
3028 TREEVIEW_INFO
*infoPtr
= TREEVIEW_GetInfoPtr(hwnd
);
3029 TREEVIEW_ITEM
*dragItem
;
3033 HBITMAP hbmp
,hOldbmp
;
3040 if (!(infoPtr
->himlNormal
)) return 0;
3041 dragItem
=TREEVIEW_ValidItem (infoPtr
, (HTREEITEM
) lParam
);
3043 if (!dragItem
) return 0;
3044 itemtxt
=dragItem
->pszText
;
3046 hwtop
=GetDesktopWindow ();
3047 htopdc
= GetDC (hwtop
);
3048 hdc
=CreateCompatibleDC (htopdc
);
3050 hOldFont
=SelectObject (hdc
, infoPtr
->hFont
);
3051 GetTextExtentPoint32A (hdc
, itemtxt
, lstrlenA (itemtxt
), &size
);
3052 TRACE("%d %d %s %d\n",size
.cx
,size
.cy
,itemtxt
,lstrlenA(itemtxt
));
3053 hbmp
=CreateCompatibleBitmap (htopdc
, size
.cx
, size
.cy
);
3054 hOldbmp
=SelectObject (hdc
, hbmp
);
3056 ImageList_GetIconSize (infoPtr
->himlNormal
, &cx
, &cy
);
3058 if (cy
>size
.cy
) size
.cy
=cy
;
3060 infoPtr
->dragList
=ImageList_Create (size
.cx
, size
.cy
, ILC_COLOR
, 10, 10);
3061 ImageList_Draw (infoPtr
->himlNormal
, dragItem
->iImage
, hdc
, 0, 0, ILD_NORMAL
);
3064 ImageList_GetImageInfo (infoPtr->himlNormal, dragItem->hItem, &iminfo);
3065 ImageList_AddMasked (infoPtr->dragList, iminfo.hbmImage, CLR_DEFAULT);
3068 /* draw item text */
3070 SetRect (&rc
, cx
, 0, size
.cx
,size
.cy
);
3071 DrawTextA (hdc
, itemtxt
, lstrlenA (itemtxt
), &rc
, DT_LEFT
);
3072 SelectObject (hdc
, hOldFont
);
3073 SelectObject (hdc
, hOldbmp
);
3075 ImageList_Add (infoPtr
->dragList
, hbmp
, 0);
3078 DeleteObject (hbmp
);
3079 ReleaseDC (hwtop
, htopdc
);
3081 return (LRESULT
)infoPtr
->dragList
;
3086 TREEVIEW_DoSelectItem (HWND hwnd
, INT action
, HTREEITEM newSelect
, INT cause
)
3089 TREEVIEW_INFO
*infoPtr
= TREEVIEW_GetInfoPtr(hwnd
);
3090 TREEVIEW_ITEM
*prevItem
,*wineItem
;
3093 wineItem
= TREEVIEW_ValidItem (infoPtr
, (HTREEITEM
)newSelect
);
3095 TRACE("Entering item %d, flag %x, cause %x, state %d\n",
3101 if ( (wineItem
) && (wineItem
->parent
))
3104 * If the item has a collapse parent expand the parent so he
3105 * can expose the item
3107 TREEVIEW_ITEM
*parentItem
= TREEVIEW_ValidItem (infoPtr
, wineItem
->parent
);
3108 if ( !(parentItem
->state
& TVIS_EXPANDED
))
3109 TREEVIEW_Expand (hwnd
, TVE_EXPAND
, (LPARAM
) wineItem
->parent
);
3115 prevSelect
=(INT
)infoPtr
->selectedItem
;
3117 if ((HTREEITEM
)prevSelect
==newSelect
)
3120 prevItem
= TREEVIEW_ValidItem (infoPtr
, (HTREEITEM
)prevSelect
);
3123 if (TREEVIEW_SendTreeviewNotify(
3127 (HTREEITEM
)prevSelect
,
3128 (HTREEITEM
)newSelect
))
3129 return FALSE
; /* FIXME: OK? */
3132 prevItem
->state
&= ~TVIS_SELECTED
;
3134 wineItem
->state
|= TVIS_SELECTED
;
3136 infoPtr
->selectedItem
=(HTREEITEM
)newSelect
;
3138 TREEVIEW_SendTreeviewNotify(
3142 (HTREEITEM
)prevSelect
,
3143 (HTREEITEM
)newSelect
);
3147 case TVGN_DROPHILITE
:
3148 prevItem
= TREEVIEW_ValidItem (infoPtr
, infoPtr
->dropItem
);
3151 prevItem
->state
&= ~TVIS_DROPHILITED
;
3153 infoPtr
->dropItem
=(HTREEITEM
)newSelect
;
3156 wineItem
->state
|=TVIS_DROPHILITED
;
3160 case TVGN_FIRSTVISIBLE
:
3161 FIXME("FIRSTVISIBLE not implemented\n");
3165 TREEVIEW_QueueRefresh (hwnd
);
3167 TRACE("Leaving state %d\n", wineItem
->state
);
3171 /* FIXME: handle NM_KILLFocus enzo */
3173 TREEVIEW_SelectItem (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
3176 return TREEVIEW_DoSelectItem (hwnd
, wParam
, (HTREEITEM
) lParam
, TVC_UNKNOWN
);
3183 TREEVIEW_GetFont (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
3186 TREEVIEW_INFO
*infoPtr
= TREEVIEW_GetInfoPtr(hwnd
);
3188 TRACE("%x\n",infoPtr
->hFont
);
3189 return infoPtr
->hFont
;
3193 TREEVIEW_SetFont (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
3196 TREEVIEW_INFO
*infoPtr
= TREEVIEW_GetInfoPtr(hwnd
);
3199 HFONT hFont
, hOldFont
;
3203 TRACE("%x %lx\n",wParam
, lParam
);
3205 infoPtr
->hFont
= (HFONT
)wParam
;
3207 hFont
= infoPtr
->hFont
? infoPtr
->hFont
: GetStockObject (SYSTEM_FONT
);
3209 GetObjectA (infoPtr
->hFont
, sizeof (LOGFONTA
), &logFont
);
3210 logFont
.lfWeight
=FW_BOLD
;
3211 infoPtr
->hBoldFont
= CreateFontIndirectA (&logFont
);
3214 hOldFont
= SelectObject (hdc
, hFont
);
3215 GetTextMetricsA (hdc
, &tm
);
3216 height
= tm
.tmHeight
+ tm
.tmExternalLeading
;
3217 if (height
>infoPtr
->uRealItemHeight
)
3218 infoPtr
->uRealItemHeight
=height
;
3219 SelectObject (hdc
, hOldFont
);
3223 TREEVIEW_QueueRefresh (hwnd
);
3231 TREEVIEW_VScroll (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
3234 TREEVIEW_INFO
*infoPtr
= TREEVIEW_GetInfoPtr(hwnd
);
3237 TRACE("wp %x, lp %lx\n", wParam
, lParam
);
3238 if (!infoPtr
->uInternalStatus
& TV_VSCROLL
) return FALSE
;
3240 switch (LOWORD (wParam
)) {
3242 if (!infoPtr
->cy
) return FALSE
;
3243 infoPtr
->cy
-= infoPtr
->uRealItemHeight
;
3244 if (infoPtr
->cy
< 0) infoPtr
->cy
=0;
3247 maxHeight
=infoPtr
->uTotalHeight
-infoPtr
->uVisibleHeight
;
3248 if (infoPtr
->cy
== maxHeight
) return FALSE
;
3249 infoPtr
->cy
+= infoPtr
->uRealItemHeight
;
3250 if (infoPtr
->cy
> maxHeight
)
3251 infoPtr
->cy
= maxHeight
;
3254 if (!infoPtr
->cy
) return FALSE
;
3255 infoPtr
->cy
-= infoPtr
->uVisibleHeight
;
3256 if (infoPtr
->cy
< 0) infoPtr
->cy
=0;
3259 maxHeight
=infoPtr
->uTotalHeight
-infoPtr
->uVisibleHeight
;
3260 if (infoPtr
->cy
== maxHeight
) return FALSE
;
3261 infoPtr
->cy
+= infoPtr
->uVisibleHeight
;
3262 if (infoPtr
->cy
> maxHeight
)
3263 infoPtr
->cy
= maxHeight
;
3266 infoPtr
->cy
= HIWORD (wParam
);
3271 TREEVIEW_QueueRefresh (hwnd
);
3276 TREEVIEW_HScroll (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
3278 TREEVIEW_INFO
*infoPtr
= TREEVIEW_GetInfoPtr(hwnd
);
3281 TRACE("wp %lx, lp %x\n", lParam
, wParam
);
3283 if (!infoPtr
->uInternalStatus
& TV_HSCROLL
) return FALSE
;
3285 switch (LOWORD (wParam
)) {
3287 if (!infoPtr
->cx
) return FALSE
;
3288 infoPtr
->cx
-= infoPtr
->uRealItemHeight
;
3289 if (infoPtr
->cx
< 0) infoPtr
->cx
=0;
3292 maxWidth
=infoPtr
->uTotalWidth
-infoPtr
->uVisibleWidth
;
3293 if (infoPtr
->cx
== maxWidth
) return FALSE
;
3294 infoPtr
->cx
+= infoPtr
->uRealItemHeight
; /*FIXME */
3295 if (infoPtr
->cx
> maxWidth
)
3296 infoPtr
->cx
= maxWidth
;
3299 if (!infoPtr
->cx
) return FALSE
;
3300 infoPtr
->cx
-= infoPtr
->uVisibleWidth
;
3301 if (infoPtr
->cx
< 0) infoPtr
->cx
=0;
3304 maxWidth
=infoPtr
->uTotalWidth
-infoPtr
->uVisibleWidth
;
3305 if (infoPtr
->cx
== maxWidth
) return FALSE
;
3306 infoPtr
->cx
+= infoPtr
->uVisibleWidth
;
3307 if (infoPtr
->cx
> maxWidth
)
3308 infoPtr
->cx
= maxWidth
;
3311 infoPtr
->cx
= HIWORD (wParam
);
3316 TREEVIEW_QueueRefresh (hwnd
);
3322 TREEVIEW_KeyDown (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
3324 TREEVIEW_INFO
*infoPtr
= TREEVIEW_GetInfoPtr(hwnd
);
3325 HTREEITEM hNewSelection
= 0;
3326 INT scrollNeeds
= -1;
3327 INT cyChangeNeeds
= -1;
3328 INT prevSelect
= (INT
)infoPtr
->selectedItem
;
3330 TREEVIEW_ITEM
*prevItem
=
3331 (prevSelect
!= 0 ) ?
3332 TREEVIEW_ValidItem (infoPtr
, (HTREEITEM
)prevSelect
) :
3335 TREEVIEW_ITEM
*newItem
= NULL
;
3337 TRACE("%x %lx\n",wParam
, lParam
);
3339 if (prevSelect
== 0)
3344 newItem
=TREEVIEW_GetPrevListItem (infoPtr
, prevItem
);
3347 newItem
=& infoPtr
->items
[(INT
)infoPtr
->TopRootItem
];
3349 hNewSelection
= newItem
->hItem
;
3351 if (! newItem
->visible
)
3352 scrollNeeds
= SB_LINEUP
;
3357 newItem
=TREEVIEW_GetNextListItem (infoPtr
, prevItem
);
3362 hNewSelection
= newItem
->hItem
;
3364 if (! newItem
->visible
)
3365 scrollNeeds
= SB_LINEDOWN
;
3370 newItem
= &infoPtr
->items
[(INT
)infoPtr
->TopRootItem
];
3371 hNewSelection
= newItem
->hItem
;
3376 newItem
= &infoPtr
->items
[(INT
)infoPtr
->TopRootItem
];
3377 newItem
= TREEVIEW_GetLastListItem (infoPtr
, newItem
);
3378 hNewSelection
= newItem
->hItem
;
3380 if (! newItem
->visible
)
3381 cyChangeNeeds
= infoPtr
->uTotalHeight
-infoPtr
->uVisibleHeight
;
3386 if ( (prevItem
->cChildren
> 0) && (prevItem
->state
& TVIS_EXPANDED
) )
3388 TREEVIEW_Expand(hwnd
, TVE_COLLAPSE
, prevSelect
);
3390 else if ((INT
)prevItem
->parent
)
3392 newItem
= (& infoPtr
->items
[(INT
)prevItem
->parent
]);
3393 if (! newItem
->visible
)
3394 /* FIXME find a way to make this item the first visible... */
3397 hNewSelection
= newItem
->hItem
;
3403 if ( ( prevItem
->cChildren
> 0) ||
3404 ( prevItem
->cChildren
== I_CHILDRENCALLBACK
))
3406 if (! (prevItem
->state
& TVIS_EXPANDED
))
3407 TREEVIEW_Expand(hwnd
, TVE_EXPAND
, prevSelect
);
3410 newItem
= (& infoPtr
->items
[(INT
)prevItem
->firstChild
]);
3411 hNewSelection
= newItem
->hItem
;
3418 if (! (prevItem
->state
& TVIS_EXPANDED
))
3419 TREEVIEW_Expand(hwnd
, TVE_EXPAND
, prevSelect
);
3423 if (prevItem
->state
& TVIS_EXPANDED
)
3424 TREEVIEW_Expand(hwnd
, TVE_COLLAPSE
, prevSelect
);
3429 newItem
=TREEVIEW_GetListItem(
3432 -1*(TREEVIEW_GetVisibleCount(hwnd
,0,0)-3));
3436 hNewSelection
= newItem
->hItem
;
3438 if (! newItem
->visible
)
3439 scrollNeeds
= SB_PAGEUP
;
3444 newItem
=TREEVIEW_GetListItem(
3447 TREEVIEW_GetVisibleCount(hwnd
,0,0)-3);
3452 hNewSelection
= newItem
->hItem
;
3454 if (! newItem
->visible
)
3455 scrollNeeds
= SB_PAGEDOWN
;
3464 FIXME("%x not implemented\n", wParam
);
3471 This works but does not send notification...
3473 prevItem->state &= ~TVIS_SELECTED;
3474 newItem->state |= TVIS_SELECTED;
3475 infoPtr->selectedItem = hNewSelection;
3476 TREEVIEW_QueueRefresh (hwnd);
3479 if ( TREEVIEW_DoSelectItem(
3482 (HTREEITEM
)hNewSelection
,
3485 /* If selection change is allowed for the new item, perform scrolling */
3486 if (scrollNeeds
!= -1)
3487 TREEVIEW_VScroll(hwnd
, scrollNeeds
, 0);
3489 if (cyChangeNeeds
!= -1)
3490 infoPtr
->cy
= cyChangeNeeds
;
3492 /* FIXME: Something happen in the load the in the two weeks before
3493 april 1st 1999 which makes this SetFocus mandatory otherwise, the focus
3494 is lost... However the SetFocus should not be required...*/
3505 TREEVIEW_GetScrollTime (HWND hwnd
)
3507 TREEVIEW_INFO
*infoPtr
= TREEVIEW_GetInfoPtr(hwnd
);
3509 return infoPtr
->uScrollTime
;
3514 TREEVIEW_SetScrollTime (HWND hwnd
, UINT uScrollTime
)
3516 TREEVIEW_INFO
*infoPtr
= TREEVIEW_GetInfoPtr(hwnd
);
3517 UINT uOldScrollTime
= infoPtr
->uScrollTime
;
3519 infoPtr
->uScrollTime
= min (uScrollTime
, 100);
3521 return uOldScrollTime
;
3525 static LRESULT WINAPI
3526 TREEVIEW_WindowProc (HWND hwnd
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
)
3529 case TVM_INSERTITEMA
:
3530 return TREEVIEW_InsertItemA (hwnd
, wParam
, lParam
);
3532 case TVM_INSERTITEMW
:
3533 return TREEVIEW_InsertItemW(hwnd
,wParam
,lParam
);;
3535 case TVM_DELETEITEM
:
3536 return TREEVIEW_DeleteItem (hwnd
, wParam
, lParam
);
3539 return TREEVIEW_Expand (hwnd
, wParam
, lParam
);
3541 case TVM_GETITEMRECT
:
3542 return TREEVIEW_GetItemRect (hwnd
, wParam
, lParam
);
3545 return TREEVIEW_GetCount (hwnd
, wParam
, lParam
);
3548 return TREEVIEW_GetIndent (hwnd
);
3551 return TREEVIEW_SetIndent (hwnd
, wParam
);
3553 case TVM_GETIMAGELIST
:
3554 return TREEVIEW_GetImageList (hwnd
, wParam
, lParam
);
3556 case TVM_SETIMAGELIST
:
3557 return TREEVIEW_SetImageList (hwnd
, wParam
, lParam
);
3559 case TVM_GETNEXTITEM
:
3560 return TREEVIEW_GetNextItem (hwnd
, wParam
, lParam
);
3562 case TVM_SELECTITEM
:
3563 return TREEVIEW_SelectItem (hwnd
, wParam
, lParam
);
3566 return TREEVIEW_GetItemA (hwnd
, wParam
, lParam
);
3569 FIXME("Unimplemented msg TVM_GETITEMW\n");
3573 return TREEVIEW_SetItemA (hwnd
, wParam
, lParam
);
3576 FIXME("Unimplemented msg TVM_SETITEMW\n");
3579 case TVM_EDITLABELA
:
3580 FIXME("Unimplemented msg TVM_EDITLABELA \n");
3583 case TVM_EDITLABELW
:
3584 FIXME("Unimplemented msg TVM_EDITLABELW \n");
3587 case TVM_GETEDITCONTROL
:
3588 return TREEVIEW_GetEditControl (hwnd
);
3590 case TVM_GETVISIBLECOUNT
:
3591 return TREEVIEW_GetVisibleCount (hwnd
, wParam
, lParam
);
3594 return TREEVIEW_HitTest (hwnd
, lParam
);
3596 case TVM_CREATEDRAGIMAGE
:
3597 return TREEVIEW_CreateDragImage (hwnd
, wParam
, lParam
);
3599 case TVM_SORTCHILDREN
:
3600 return TREEVIEW_SortChildren (hwnd
, wParam
, lParam
);
3602 case TVM_ENSUREVISIBLE
:
3603 FIXME("Unimplemented msg TVM_ENSUREVISIBLE\n");
3606 case TVM_SORTCHILDRENCB
:
3607 return TREEVIEW_SortChildrenCB(hwnd
, wParam
, lParam
);
3609 case TVM_ENDEDITLABELNOW
:
3610 return TREEVIEW_EndEditLabelNow (hwnd
, wParam
, lParam
);
3612 case TVM_GETISEARCHSTRINGA
:
3613 FIXME("Unimplemented msg TVM_GETISEARCHSTRINGA\n");
3616 case TVM_GETISEARCHSTRINGW
:
3617 FIXME("Unimplemented msg TVM_GETISEARCHSTRINGW\n");
3620 case TVM_GETTOOLTIPS
:
3621 return TREEVIEW_GetToolTips (hwnd
);
3623 case TVM_SETTOOLTIPS
:
3624 return TREEVIEW_SetToolTips (hwnd
, wParam
);
3626 case TVM_SETINSERTMARK
:
3627 FIXME("Unimplemented msg TVM_SETINSERTMARK\n");
3630 case TVM_SETITEMHEIGHT
:
3631 return TREEVIEW_SetItemHeight (hwnd
, wParam
);
3633 case TVM_GETITEMHEIGHT
:
3634 return TREEVIEW_GetItemHeight (hwnd
);
3636 case TVM_SETBKCOLOR
:
3637 return TREEVIEW_SetBkColor (hwnd
, wParam
, lParam
);
3639 case TVM_SETTEXTCOLOR
:
3640 return TREEVIEW_SetTextColor (hwnd
, wParam
, lParam
);
3642 case TVM_GETBKCOLOR
:
3643 return TREEVIEW_GetBkColor (hwnd
);
3645 case TVM_GETTEXTCOLOR
:
3646 return TREEVIEW_GetTextColor (hwnd
);
3648 case TVM_SETSCROLLTIME
:
3649 return TREEVIEW_SetScrollTime (hwnd
, (UINT
)wParam
);
3651 case TVM_GETSCROLLTIME
:
3652 return TREEVIEW_GetScrollTime (hwnd
);
3654 case TVM_GETITEMSTATE
:
3655 return TREEVIEW_GetItemState (hwnd
,wParam
, lParam
);
3657 case TVM_GETLINECOLOR
:
3658 return TREEVIEW_GetLineColor (hwnd
,wParam
, lParam
);
3660 case TVM_SETLINECOLOR
:
3661 return TREEVIEW_SetLineColor (hwnd
,wParam
, lParam
);
3663 case TVM_SETINSERTMARKCOLOR
:
3664 FIXME("Unimplemented msg TVM_SETINSERTMARKCOLOR\n");
3667 case TVM_SETUNICODEFORMAT
:
3668 FIXME("Unimplemented msg TVM_SETUNICODEFORMAT\n");
3671 case TVM_GETUNICODEFORMAT
:
3672 FIXME("Unimplemented msg TVM_GETUNICODEFORMAT\n");
3676 return TREEVIEW_Command (hwnd
, wParam
, lParam
);
3679 return TREEVIEW_Create (hwnd
, wParam
, lParam
);
3682 return TREEVIEW_Destroy (hwnd
);
3684 /* case WM_ENABLE: */
3687 return TREEVIEW_EraseBackground (hwnd
, wParam
, lParam
);
3690 return DLGC_WANTARROWS
| DLGC_WANTCHARS
;
3693 return TREEVIEW_Paint (hwnd
, wParam
, lParam
);
3696 return TREEVIEW_GetFont (hwnd
, wParam
, lParam
);
3699 return TREEVIEW_SetFont (hwnd
, wParam
, lParam
);
3702 return TREEVIEW_KeyDown (hwnd
, wParam
, lParam
);
3705 return TREEVIEW_SetFocus (hwnd
, wParam
, lParam
);
3708 return TREEVIEW_KillFocus (hwnd
, wParam
, lParam
);
3710 case WM_LBUTTONDOWN
:
3711 return TREEVIEW_LButtonDown (hwnd
, wParam
, lParam
);
3714 return TREEVIEW_LButtonUp (hwnd
, wParam
, lParam
);
3716 case WM_LBUTTONDBLCLK
:
3717 return TREEVIEW_LButtonDoubleClick (hwnd
, wParam
, lParam
);
3719 case WM_RBUTTONDOWN
:
3720 return TREEVIEW_RButtonDown (hwnd
, wParam
, lParam
);
3723 return TREEVIEW_RButtonUp (hwnd
, wParam
, lParam
);
3726 return TREEVIEW_MouseMove (hwnd
, wParam
, lParam
);
3728 case WM_STYLECHANGED
:
3729 return TREEVIEW_StyleChanged (hwnd
, wParam
, lParam
);
3731 /* case WM_SYSCOLORCHANGE: */
3732 /* case WM_SETREDRAW: */
3735 return TREEVIEW_HandleTimer (hwnd
, wParam
, lParam
);
3738 return TREEVIEW_Size (hwnd
, wParam
,lParam
);
3741 return TREEVIEW_HScroll (hwnd
, wParam
, lParam
);
3743 return TREEVIEW_VScroll (hwnd
, wParam
, lParam
);
3746 TRACE ("drawItem\n");
3747 return DefWindowProcA (hwnd
, uMsg
, wParam
, lParam
);
3750 if (uMsg
>= WM_USER
)
3751 FIXME("Unknown msg %04x wp=%08x lp=%08lx\n",
3752 uMsg
, wParam
, lParam
);
3753 return DefWindowProcA (hwnd
, uMsg
, wParam
, lParam
);
3760 TREEVIEW_Register (void)
3766 if (GlobalFindAtomA (WC_TREEVIEWA
)) return;
3768 ZeroMemory (&wndClass
, sizeof(WNDCLASSA
));
3769 wndClass
.style
= CS_GLOBALCLASS
| CS_DBLCLKS
;
3770 wndClass
.lpfnWndProc
= (WNDPROC
)TREEVIEW_WindowProc
;
3771 wndClass
.cbClsExtra
= 0;
3772 wndClass
.cbWndExtra
= sizeof(TREEVIEW_INFO
*);
3773 wndClass
.hCursor
= LoadCursorA (0, IDC_ARROWA
);
3774 wndClass
.hbrBackground
= 0;
3775 wndClass
.lpszClassName
= WC_TREEVIEWA
;
3777 RegisterClassA (&wndClass
);
3782 TREEVIEW_Unregister (void)
3784 if (GlobalFindAtomA (WC_TREEVIEWA
))
3785 UnregisterClassA (WC_TREEVIEWA
, (HINSTANCE
)NULL
);