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.
48 #include "debugtools.h"
50 DEFAULT_DEBUG_CHANNEL(treeview)
52 /* ffs should be in <string.h>. */
54 /* Defines, since they do not need to return previous state, and nr
55 * has no side effects in this file.
57 #define tv_test_bit(nr,bf) (((LPBYTE)bf)[nr>>3]&(1<<(nr&7)))
58 #define tv_set_bit(nr,bf) ((LPBYTE)bf)[nr>>3]|=(1<<(nr&7))
59 #define tv_clear_bit(nr,bf) ((LPBYTE)bf)[nr>>3]&=~(1<<(nr&7))
62 #define TREEVIEW_GetInfoPtr(hwnd) \
63 ((TREEVIEW_INFO *) GetWindowLongA( hwnd, 0))
66 TREEVIEW_SendSimpleNotify (HWND hwnd, UINT code);
68 TREEVIEW_SendTreeviewNotify (HWND hwnd, UINT code, UINT action,
69 HTREEITEM oldItem, HTREEITEM newItem);
71 TREEVIEW_SendTreeviewDnDNotify (HWND hwnd, UINT code, HTREEITEM dragItem,
74 TREEVIEW_SendDispInfoNotify (HWND hwnd, TREEVIEW_ITEM *wineItem,
75 UINT code, UINT what);
77 TREEVIEW_SendCustomDrawNotify (HWND hwnd, DWORD dwDrawStage, HDC hdc,
80 TREEVIEW_SendCustomDrawItemNotify (HWND hwnd, HDC hdc,
81 TREEVIEW_ITEM *tvItem, UINT uItemDrawState);
83 TREEVIEW_DoSelectItem (HWND hwnd, INT action, HTREEITEM newSelect, INT cause);
85 TREEVIEW_Refresh (HWND hwnd, HDC hdc);
87 static LRESULT CALLBACK
88 TREEVIEW_Edit_SubclassProc (HWND hwnd, UINT uMsg, WPARAM wParam,
92 TREEVIEW_EndEditLabelNow (HWND hwnd, WPARAM wParam, LPARAM lParam);
97 /* helper functions. Work with the assumption that validity of operands
98 is checked beforehand, and that tree state is valid. */
100 /* FIXME: MS documentation says `GetNextVisibleItem' returns NULL
101 if not succesfull'. Probably only applies to derefencing infoPtr
102 (ie we are offered a valid treeview structure)
103 and not whether there is a next `visible' child.
104 FIXME: check other failures.
107 /***************************************************************************
108 * This method returns the TREEVIEW_ITEM object given the handle
110 static TREEVIEW_ITEM* TREEVIEW_ValidItem(
111 TREEVIEW_INFO *infoPtr,
114 if ((!handle) || (handle>infoPtr->uMaxHandle))
117 if (tv_test_bit ((INT)handle, infoPtr->freeList))
120 return &infoPtr->items[(INT)handle];
123 /***************************************************************************
124 * This method returns the last expanded child item of a tree node
126 static TREEVIEW_ITEM *TREEVIEW_GetLastListItem(
127 TREEVIEW_INFO *infoPtr,
128 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);
395 if ((INT)wParam == TVSIL_NORMAL)
396 return (LRESULT) infoPtr->himlNormal;
397 if ((INT)wParam == TVSIL_STATE)
398 return (LRESULT) infoPtr->himlState;
404 TREEVIEW_SetImageList (HWND hwnd, WPARAM wParam, LPARAM lParam)
406 TREEVIEW_INFO *infoPtr = TREEVIEW_GetInfoPtr(hwnd);
409 TRACE("%x,%lx\n", wParam, lParam);
410 switch ((INT)wParam) {
412 himlTemp = infoPtr->himlNormal;
413 infoPtr->himlNormal = (HIMAGELIST)lParam;
414 return (LRESULT)himlTemp;
417 himlTemp = infoPtr->himlState;
418 infoPtr->himlState = (HIMAGELIST)lParam;
419 return (LRESULT)himlTemp;
422 return (LRESULT)NULL;
428 TREEVIEW_SetItemHeight (HWND hwnd, WPARAM wParam)
430 TREEVIEW_INFO *infoPtr = TREEVIEW_GetInfoPtr(hwnd);
431 INT cx,cy,prevHeight=infoPtr->uItemHeight;
435 infoPtr->uItemHeight=-1;
439 ImageList_GetIconSize (infoPtr->himlNormal, &cx, &cy);
441 if (wParam>cy) cy=wParam;
442 infoPtr->uItemHeight=cy;
444 if (!( GetWindowLongA( hwnd, GWL_STYLE) & TVS_NONEVENHEIGHT))
445 infoPtr->uItemHeight = (INT) wParam & 0xfffffffe;
450 TREEVIEW_GetItemHeight (HWND hwnd)
452 TREEVIEW_INFO *infoPtr = TREEVIEW_GetInfoPtr(hwnd);
455 return infoPtr->uItemHeight;
459 TREEVIEW_GetLineColor (HWND hwnd, WPARAM wParam, LPARAM lParam)
461 TREEVIEW_INFO *infoPtr = TREEVIEW_GetInfoPtr(hwnd);
464 return (LRESULT) infoPtr->clrLine;
468 TREEVIEW_SetLineColor (HWND hwnd, WPARAM wParam, LPARAM lParam)
470 TREEVIEW_INFO *infoPtr = TREEVIEW_GetInfoPtr(hwnd);
471 COLORREF prevColor=infoPtr->clrLine;
474 infoPtr->clrLine=(COLORREF) lParam;
475 return (LRESULT) prevColor;
479 TREEVIEW_GetInsertMarkColor (HWND hwnd, WPARAM wParam, LPARAM lParam)
481 TREEVIEW_INFO *infoPtr = TREEVIEW_GetInfoPtr(hwnd);
484 return (LRESULT) infoPtr->clrInsertMark;
488 TREEVIEW_SetInsertMarkColor (HWND hwnd, WPARAM wParam, LPARAM lParam)
490 TREEVIEW_INFO *infoPtr = TREEVIEW_GetInfoPtr(hwnd);
491 COLORREF prevColor=infoPtr->clrInsertMark;
493 TRACE("%d %ld\n",wParam,lParam);
494 infoPtr->clrInsertMark=(COLORREF) lParam;
495 return (LRESULT) prevColor;
499 TREEVIEW_SetInsertMark (HWND hwnd, WPARAM wParam, LPARAM lParam)
501 TREEVIEW_INFO *infoPtr = TREEVIEW_GetInfoPtr(hwnd);
504 FIXME("%d %ld\n",wParam,lParam);
505 if (!TREEVIEW_ValidItem (infoPtr, (HTREEITEM)lParam)) return 0;
506 FIXME("%d %ld\n",wParam,lParam);
508 infoPtr->insertBeforeorAfter=(BOOL) wParam;
509 infoPtr->insertMarkItem=(HTREEITEM) lParam;
512 TREEVIEW_Refresh (hwnd, hdc);
519 TREEVIEW_SetTextColor (HWND hwnd, WPARAM wParam, LPARAM lParam)
521 TREEVIEW_INFO *infoPtr = TREEVIEW_GetInfoPtr(hwnd);
522 COLORREF prevColor=infoPtr->clrText;
525 infoPtr->clrText=(COLORREF) lParam;
526 return (LRESULT) prevColor;
530 TREEVIEW_GetBkColor (HWND hwnd)
532 TREEVIEW_INFO *infoPtr = TREEVIEW_GetInfoPtr(hwnd);
535 return (LRESULT) infoPtr->clrBk;
539 TREEVIEW_SetBkColor (HWND hwnd, WPARAM wParam, LPARAM lParam)
541 TREEVIEW_INFO *infoPtr = TREEVIEW_GetInfoPtr(hwnd);
542 COLORREF prevColor=infoPtr->clrBk;
545 infoPtr->clrBk=(COLORREF) lParam;
546 return (LRESULT) prevColor;
550 TREEVIEW_GetTextColor (HWND hwnd)
552 TREEVIEW_INFO *infoPtr = TREEVIEW_GetInfoPtr(hwnd);
555 return (LRESULT) infoPtr->clrText;
559 /* cdmode: custom draw mode as received from app. in first NMCUSTOMDRAW
562 #define TREEVIEW_LEFT_MARGIN 8
566 TREEVIEW_DrawItem (HWND hwnd, HDC hdc, TREEVIEW_ITEM *wineItem)
568 TREEVIEW_INFO *infoPtr = TREEVIEW_GetInfoPtr(hwnd);
569 DWORD dwStyle = GetWindowLongA (hwnd, GWL_STYLE);
570 INT center,xpos,cx,cy, cditem;
572 UINT uTextJustify = DT_LEFT;
576 if (wineItem->state & TVIS_BOLD)
577 hOldFont = SelectObject (hdc, infoPtr->hBoldFont);
579 hOldFont = SelectObject (hdc, infoPtr->hFont);
582 TRACE ("cdmode:%x\n",infoPtr->cdmode);
583 if (infoPtr->cdmode & CDRF_NOTIFYITEMDRAW) {
584 cditem=TREEVIEW_SendCustomDrawItemNotify
585 (hwnd, hdc, wineItem, CDDS_ITEMPREPAINT);
586 TRACE("prepaint:cditem-app returns 0x%x\n",cditem);
588 if (cditem & CDRF_SKIPDEFAULT)
593 * Set drawing starting points
595 r = wineItem->rect; /* this item rectangle */
596 center = (r.top+r.bottom)/2; /* this item vertical center */
597 xpos = r.left + TREEVIEW_LEFT_MARGIN;/* horizontal starting point */
600 * Display the tree hierarchy
602 if ( dwStyle & TVS_HASLINES)
605 * Write links to parent node
606 * we draw the L starting from the child to the parent
608 * points[0] is attached to the current item
609 * points[1] is the L corner
610 * points[2] is attached to the parent or the up sibling
612 if ( dwStyle & TVS_LINESATROOT)
614 TREEVIEW_ITEM *upNode = NULL;
615 BOOL hasParentOrSibling = TRUE;
616 RECT upRect = {0,0,0,0};
617 HPEN hOldPen, hNewPen;
620 * determine the target location of the line at root, either be linked
621 * to the up sibling or to the parent node.
623 if (wineItem->upsibling)
624 upNode = TREEVIEW_ValidItem (infoPtr, wineItem->upsibling);
625 else if (wineItem->parent)
626 upNode = TREEVIEW_ValidItem (infoPtr, wineItem->parent);
628 hasParentOrSibling = FALSE;
631 upRect = upNode->rect;
633 if ( wineItem->iLevel == 0 )
635 points[2].x = points[1].x = upRect.left+8;
636 points[0].x = points[2].x + 10;
637 points[2].y = upRect.bottom-3;
638 points[1].y = points[0].y = center;
642 points[2].x = points[1].x = 8 + (20*wineItem->iLevel);
643 points[2].y = ( upNode->cChildren == 0) ?
644 upRect.top : /* is linked to the "L" above */
645 ( wineItem->upsibling != NULL) ?
646 upRect.bottom-3: /* is linked to an icon */
647 upRect.bottom+1; /* is linked to a +/- box */
648 points[1].y = points[0].y = center;
649 points[0].x = points[1].x + 10;
655 hNewPen = CreatePen(PS_DOT, 0, infoPtr->clrLine);
656 hOldPen = SelectObject( hdc, hNewPen );
658 if (hasParentOrSibling)
659 Polyline (hdc,points,3);
661 Polyline (hdc,points,2);
663 DeleteObject(hNewPen);
664 SelectObject(hdc, hOldPen);
669 * Display the (+/-) signs
671 if (wineItem->iLevel != 0)/* update position only for non root node */
672 xpos+=(5*wineItem->iLevel);
674 if (( dwStyle & TVS_HASBUTTONS) && ( dwStyle & TVS_HASLINES))
676 if ( (wineItem->cChildren) ||
677 (wineItem->cChildren == I_CHILDRENCALLBACK))
679 /* Setup expand box coordinate to facilitate the LMBClick handling */
680 wineItem->expandBox.left = xpos-4;
681 wineItem->expandBox.top = center-4;
682 wineItem->expandBox.right = xpos+5;
683 wineItem->expandBox.bottom = center+5;
687 wineItem->expandBox.left,
688 wineItem->expandBox.top ,
689 wineItem->expandBox.right,
690 wineItem->expandBox.bottom);
692 MoveToEx (hdc, xpos-2, center, NULL);
693 LineTo (hdc, xpos+3, center);
695 if (!(wineItem->state & TVIS_EXPANDED)) {
696 MoveToEx (hdc, xpos, center-2, NULL);
697 LineTo (hdc, xpos, center+3);
703 * Display the image associated with this item
705 xpos += 13; /* update position */
706 if (wineItem->mask & (TVIF_IMAGE|TVIF_SELECTEDIMAGE)) {
708 HIMAGELIST *himlp = NULL;
710 /* State images are displayed to the left of the Normal image
711 * image number is in state; zero should be `display no image'.
712 * FIXME: that last sentence looks like it needs some checking.
714 if (infoPtr->himlState)
715 himlp=&infoPtr->himlState;
716 imageIndex=wineItem->state>>12;
717 imageIndex++; /* yeah, right */
718 TRACE ("imindex:%d\n",imageIndex);
719 if ((himlp) && (imageIndex))
721 imageIndex--; /* see FIXME */
722 ImageList_Draw ( *himlp, imageIndex, hdc, xpos-2, r.top+1, ILD_NORMAL);
723 ImageList_GetIconSize (*himlp, &cx, &cy);
724 wineItem->statebitmap.left=xpos-2;
725 wineItem->statebitmap.right=xpos-2+cx;
726 wineItem->statebitmap.top=r.top+1;
727 wineItem->statebitmap.bottom=r.top+1+cy;
731 /* Now, draw the normal image; can be either selected or
732 * non-selected image.
736 if (infoPtr->himlNormal)
737 himlp=&infoPtr->himlNormal; /* get the image list */
739 imageIndex = wineItem->iImage;
740 if ( (wineItem->state & TVIS_SELECTED) &&
741 (wineItem->iSelectedImage)) {
743 /* The item is curently selected */
744 if (wineItem->iSelectedImage == I_IMAGECALLBACK)
745 TREEVIEW_SendDispInfoNotify
746 (hwnd, wineItem, TVN_GETDISPINFO, TVIF_SELECTEDIMAGE);
748 imageIndex = wineItem->iSelectedImage;
750 /* The item is not selected */
751 if (wineItem->iImage == I_IMAGECALLBACK)
752 TREEVIEW_SendDispInfoNotify
753 (hwnd, wineItem, TVN_GETDISPINFO, TVIF_IMAGE);
755 imageIndex = wineItem->iImage;
760 ImageList_Draw ( *himlp, imageIndex, hdc, xpos-2, r.top+1, ILD_NORMAL);
761 ImageList_GetIconSize (*himlp, &cx, &cy);
762 wineItem->bitmap.left=xpos-2;
763 wineItem->bitmap.right=xpos-2+cx;
764 wineItem->bitmap.top=r.top+1;
765 wineItem->bitmap.bottom=r.top+1+cy;
772 * Display the text associated with this item
775 if ((wineItem->mask & TVIF_TEXT) && (wineItem->pszText))
777 COLORREF oldBkColor = 0;
778 COLORREF oldTextColor = 0;
784 wineItem->text.left = r.left;
785 wineItem->text.right = r.right;
786 wineItem->text.top = r.top;
787 wineItem->text.bottom= r.bottom;
789 if (wineItem->pszText== LPSTR_TEXTCALLBACKA) {
790 TRACE("LPSTR_TEXTCALLBACK\n");
791 TREEVIEW_SendDispInfoNotify (hwnd, wineItem, TVN_GETDISPINFO, TVIF_TEXT);
794 /* Yep, there are some things that need to be straightened out here.
795 Removing the comments around the setTextColor does not give the right
796 results. Dito FillRect.
800 /* GetTextExtentPoint32A (hdc, wineItem->pszText,
801 strlen (wineItem->pszText), &size); */
803 /* FillRect ( hdc, &wineItem->text, GetSysColorBrush (infoPtr->clrBk));
807 if (!(cditem & CDRF_NOTIFYPOSTPAINT) &&
808 (wineItem->state & (TVIS_SELECTED | TVIS_DROPHILITED)) ) {
809 oldBkMode = SetBkMode (hdc, OPAQUE);
810 oldBkColor = SetBkColor (hdc, GetSysColor( COLOR_HIGHLIGHT));
811 oldTextColor = SetTextColor(hdc, GetSysColor( COLOR_HIGHLIGHTTEXT));
813 oldBkMode = SetBkMode (hdc, TRANSPARENT);
814 oldBkColor = SetBkColor (hdc, infoPtr->clrBk);
815 /* oldTextColor = SetTextColor(hdc, infoPtr->clrText); */
823 lstrlenA(wineItem->pszText),
825 uTextJustify | DT_VCENTER | DT_SINGLELINE );
827 /* Obtain the text coordinate */
831 lstrlenA(wineItem->pszText),
833 uTextJustify | DT_VCENTER | DT_SINGLELINE | DT_CALCRECT);
835 /* Restore the hdc state */
836 SetTextColor( hdc, oldTextColor);
838 if (oldBkMode != TRANSPARENT)
839 SetBkMode(hdc, oldBkMode);
840 if (wineItem->state & (TVIS_SELECTED | TVIS_DROPHILITED))
841 SetBkColor (hdc, oldBkColor);
843 /* Draw the box arround the selected item */
844 if (wineItem->state & TVIS_SELECTED )
846 HPEN hNewPen = CreatePen(PS_DOT, 0, GetSysColor(COLOR_WINDOWTEXT) );
847 HPEN hOldPen = SelectObject( hdc, hNewPen );
850 points[0].x = wineItem->text.left-1;
851 points[0].y = wineItem->text.top+1;
852 points[1].x = wineItem->text.right;
853 points[1].y = wineItem->text.top+1;
854 points[2].x = wineItem->text.right;
855 points[2].y = wineItem->text.bottom;
856 points[3].x = wineItem->text.left-1;
857 points[3].y = wineItem->text.bottom;
859 Polyline (hdc,points,4);
861 DeleteObject(hNewPen);
862 SelectObject(hdc, hOldPen);
866 /* Draw insertion mark if necessary */
868 if (infoPtr->insertMarkItem)
869 TRACE ("item:%d,mark:%d\n", (int)wineItem->hItem,
870 (int) infoPtr->insertMarkItem);
871 if (wineItem->hItem==infoPtr->insertMarkItem) {
872 HPEN hNewPen, hOldPen;
875 hNewPen = CreatePen(PS_SOLID, 2, infoPtr->clrInsertMark);
876 hOldPen = SelectObject( hdc, hNewPen );
878 if (infoPtr->insertBeforeorAfter)
879 offset=wineItem->text.top+1;
881 offset=wineItem->text.bottom-1;
883 MoveToEx (hdc, wineItem->text.left, offset-3, NULL);
884 LineTo (hdc, wineItem->text.left, offset+3);
886 MoveToEx (hdc, wineItem->text.left, offset, NULL);
887 LineTo (hdc, r.right-2, offset);
889 MoveToEx (hdc, r.right-2, offset+3, NULL);
890 LineTo (hdc, r.right-2, offset-3);
892 DeleteObject(hNewPen);
894 SelectObject(hdc, hOldPen);
897 if (cditem & CDRF_NOTIFYPOSTPAINT) {
898 cditem=TREEVIEW_SendCustomDrawItemNotify
899 (hwnd, hdc, wineItem, CDDS_ITEMPOSTPAINT);
900 TRACE("postpaint:cditem-app returns 0x%x\n",cditem);
903 SelectObject (hdc, hOldFont);
907 TREEVIEW_GetItemRect (HWND hwnd, WPARAM wParam, LPARAM lParam)
909 TREEVIEW_INFO *infoPtr = TREEVIEW_GetInfoPtr(hwnd);
910 TREEVIEW_ITEM *wineItem;
912 LPRECT lpRect = (LPRECT)lParam;
917 * validate parameters
922 if (infoPtr->Timer & TV_REFRESH_TIMER_SET) {
924 TREEVIEW_Refresh (hwnd, hdc); /* we want a rect for the current view */
930 * retrieve the item ptr
932 iItem = (HTREEITEM *) lParam;
933 wineItem = TREEVIEW_ValidItem (infoPtr, *iItem);
934 if ((!wineItem) || (!wineItem->visible))
938 * If wParam is TRUE return the text size otherwise return
939 * the whole item size
942 lpRect->left = wineItem->text.left;
943 lpRect->right = wineItem->text.right;
944 lpRect->bottom = wineItem->text.bottom;
945 lpRect->top = wineItem->text.top;
947 lpRect->left = wineItem->rect.left;
948 lpRect->right = wineItem->rect.right;
949 lpRect->bottom = wineItem->rect.bottom;
950 lpRect->top = wineItem->rect.top;
953 TRACE("[L:%d R:%d T:%d B:%d]\n",
954 lpRect->left,lpRect->right,
955 lpRect->top,lpRect->bottom);
961 TREEVIEW_GetVisibleCount (HWND hwnd, WPARAM wParam, LPARAM lParam)
964 TREEVIEW_INFO *infoPtr = TREEVIEW_GetInfoPtr(hwnd);
966 return (LRESULT) infoPtr->uVisibleHeight / infoPtr->uRealItemHeight;
972 TREEVIEW_SetItemA (HWND hwnd, WPARAM wParam, LPARAM lParam)
974 TREEVIEW_INFO *infoPtr = TREEVIEW_GetInfoPtr(hwnd);
975 TREEVIEW_ITEM *wineItem;
979 tvItem=(LPTVITEMEXA) lParam;
980 iItem=(INT)tvItem->hItem;
981 TRACE("item %d,mask %x\n",iItem,tvItem->mask);
983 wineItem = TREEVIEW_ValidItem (infoPtr, (HTREEITEM)iItem);
984 if (!wineItem) return FALSE;
986 if (tvItem->mask & TVIF_CHILDREN) {
987 wineItem->cChildren=tvItem->cChildren;
990 if (tvItem->mask & TVIF_IMAGE) {
991 wineItem->iImage=tvItem->iImage;
994 if (tvItem->mask & TVIF_INTEGRAL) {
995 wineItem->iIntegral=tvItem->iIntegral;
998 if (tvItem->mask & TVIF_PARAM) {
999 wineItem->lParam=tvItem->lParam;
1002 if (tvItem->mask & TVIF_SELECTEDIMAGE) {
1003 wineItem->iSelectedImage=tvItem->iSelectedImage;
1006 if (tvItem->mask & TVIF_STATE) {
1007 TRACE ("prevstate,state,mask:%x,%x,%x\n",wineItem->state,tvItem->state,
1009 wineItem->state&= ~tvItem->stateMask;
1010 wineItem->state|= (tvItem->state & tvItem->stateMask);
1011 wineItem->stateMask|= tvItem->stateMask;
1014 if (tvItem->mask & TVIF_TEXT) {
1015 if (tvItem->pszText!=LPSTR_TEXTCALLBACKA) {
1016 len=lstrlenA (tvItem->pszText);
1017 if (len>wineItem->cchTextMax)
1018 wineItem->pszText= COMCTL32_ReAlloc (wineItem->pszText, len+1);
1019 lstrcpynA (wineItem->pszText, tvItem->pszText,len);
1021 if (wineItem->cchTextMax) {
1022 COMCTL32_Free (wineItem->pszText);
1023 wineItem->cchTextMax=0;
1025 wineItem->pszText=LPSTR_TEXTCALLBACKA;
1029 wineItem->mask |= tvItem->mask;
1035 TREEVIEW_GetItemState (HWND hwnd, WPARAM wParam, LPARAM lParam)
1038 TREEVIEW_INFO *infoPtr = TREEVIEW_GetInfoPtr(hwnd);
1039 TREEVIEW_ITEM *wineItem;
1042 wineItem = TREEVIEW_ValidItem (infoPtr, (HTREEITEM)wParam);
1043 if (!wineItem) return 0;
1045 return (wineItem->state & lParam);
1052 TREEVIEW_Refresh (HWND hwnd, HDC hdc)
1054 TREEVIEW_INFO *infoPtr = TREEVIEW_GetInfoPtr(hwnd);
1058 INT iItem, indent, x, y, cx, height, itemHeight;
1059 INT viewtop,viewbottom,viewleft,viewright;
1060 TREEVIEW_ITEM *wineItem, *prevItem;
1065 if (infoPtr->Timer & TV_REFRESH_TIMER_SET) {
1066 KillTimer (hwnd, TV_REFRESH_TIMER);
1067 infoPtr->Timer &= ~TV_REFRESH_TIMER_SET;
1071 GetClientRect (hwnd, &rect);
1072 if ((rect.left-rect.right ==0) || (rect.top-rect.bottom==0)) return;
1074 infoPtr->cdmode=TREEVIEW_SendCustomDrawNotify
1075 (hwnd, CDDS_PREPAINT, hdc, rect);
1077 if (infoPtr->cdmode==CDRF_SKIPDEFAULT) return;
1079 infoPtr->uVisibleHeight= rect.bottom-rect.top;
1080 infoPtr->uVisibleWidth= rect.right-rect.left;
1082 viewtop=infoPtr->cy;
1083 viewbottom=infoPtr->cy + rect.bottom-rect.top;
1084 viewleft=infoPtr->cx;
1085 viewright=infoPtr->cx + rect.right-rect.left;
1087 /* draw background */
1089 hbrBk = CreateSolidBrush (infoPtr->clrBk);
1090 FillRect(hdc, &rect, hbrBk);
1091 DeleteObject(hbrBk);
1093 iItem=(INT)infoPtr->TopRootItem;
1094 infoPtr->firstVisible=0;
1098 TRACE("[%d %d %d %d]\n",viewtop,viewbottom,viewleft,viewright);
1102 wineItem= & infoPtr->items[iItem];
1103 wineItem->iLevel=indent;
1105 ImageList_GetIconSize (infoPtr->himlNormal, &cx, &itemHeight);
1106 if (infoPtr->uItemHeight>itemHeight)
1107 itemHeight=infoPtr->uItemHeight;
1109 GetTextMetricsA (hdc, &tm);
1110 if ((tm.tmHeight + tm.tmExternalLeading) > itemHeight)
1111 itemHeight=tm.tmHeight + tm.tmExternalLeading;
1113 infoPtr->uRealItemHeight=itemHeight;
1116 /* FIXME: remove this in later stage */
1118 if (wineItem->pszText!=LPSTR_TEXTCALLBACK32A)
1119 TRACE (treeview, "%d %d [%d %d %d %d] (%s)\n",y,x,
1120 wineItem->rect.top, wineItem->rect.bottom,
1121 wineItem->rect.left, wineItem->rect.right,
1124 TRACE (treeview, "%d [%d %d %d %d] (CALLBACK)\n",
1126 wineItem->rect.top, wineItem->rect.bottom,
1127 wineItem->rect.left, wineItem->rect.right);
1130 height=itemHeight * wineItem->iIntegral +1;
1131 if ((y >= viewtop) && (y <= viewbottom) &&
1132 (x >= viewleft ) && (x <= viewright)) {
1133 wineItem->visible = TRUE;
1134 wineItem->rect.top = y - infoPtr->cy + rect.top;
1135 wineItem->rect.bottom = wineItem->rect.top + height ;
1136 wineItem->rect.left = x - infoPtr->cx + rect.left;
1137 wineItem->rect.right = rect.right;
1138 if (!infoPtr->firstVisible)
1139 infoPtr->firstVisible=wineItem->hItem;
1140 TREEVIEW_DrawItem (hwnd, hdc, wineItem);
1143 wineItem->visible = FALSE;
1144 wineItem->rect.left = wineItem->rect.top = 0;
1145 wineItem->rect.right= wineItem->rect.bottom = 0;
1146 wineItem->text.left = wineItem->text.top = 0;
1147 wineItem->text.right= wineItem->text.bottom = 0;
1150 /* look up next item */
1152 if ((wineItem->firstChild) && (wineItem->state & TVIS_EXPANDED)) {
1153 iItem=(INT)wineItem->firstChild;
1155 x+=infoPtr->uIndent;
1156 if (x>infoPtr->uTotalWidth)
1157 infoPtr->uTotalWidth=x;
1160 iItem=(INT)wineItem->sibling;
1161 while ((!iItem) && (indent>0)) {
1163 x-=infoPtr->uIndent;
1165 wineItem=&infoPtr->items[(INT)wineItem->parent];
1166 iItem=(INT)wineItem->sibling;
1172 /* FIXME: infoPtr->uTotalWidth should also take item label into account */
1173 /* FIXME: or should query item sizes (ie check CDRF_NEWFONT) */
1175 infoPtr->uTotalHeight=y;
1176 if (y >= (viewbottom-viewtop)) {
1177 if (!(infoPtr->uInternalStatus & TV_VSCROLL))
1178 ShowScrollBar (hwnd, SB_VERT, TRUE);
1179 infoPtr->uInternalStatus |=TV_VSCROLL;
1180 SetScrollRange (hwnd, SB_VERT, 0,
1181 y - infoPtr->uVisibleHeight, FALSE);
1182 SetScrollPos (hwnd, SB_VERT, infoPtr->cy, TRUE);
1185 if (infoPtr->uInternalStatus & TV_VSCROLL)
1186 ShowScrollBar (hwnd, SB_VERT, FALSE);
1187 infoPtr->uInternalStatus &= ~TV_VSCROLL;
1191 if (infoPtr->cdmode & CDRF_NOTIFYPOSTPAINT)
1192 infoPtr->cdmode=TREEVIEW_SendCustomDrawNotify
1193 (hwnd, CDDS_POSTPAINT, hdc, rect);
1200 TREEVIEW_HandleTimer (HWND hwnd, WPARAM wParam, LPARAM lParam)
1202 TREEVIEW_INFO *infoPtr = TREEVIEW_GetInfoPtr(hwnd);
1204 TRACE(" %d\n",wParam);
1207 case TV_REFRESH_TIMER:
1208 KillTimer (hwnd, TV_REFRESH_TIMER);
1209 infoPtr->Timer &= ~TV_REFRESH_TIMER_SET;
1210 InvalidateRect(hwnd, NULL, FALSE);
1213 KillTimer (hwnd, TV_EDIT_TIMER);
1214 infoPtr->Timer &= ~TV_EDIT_TIMER_SET;
1217 ERR("got unknown timer\n");
1225 TREEVIEW_QueueRefresh (HWND hwnd)
1228 TREEVIEW_INFO *infoPtr = TREEVIEW_GetInfoPtr(hwnd);
1231 if (infoPtr->Timer & TV_REFRESH_TIMER_SET) {
1232 KillTimer (hwnd, TV_REFRESH_TIMER);
1235 SetTimer (hwnd, TV_REFRESH_TIMER, TV_REFRESH_DELAY, 0);
1236 infoPtr->Timer|=TV_REFRESH_TIMER_SET;
1242 TREEVIEW_GetItemA (HWND hwnd, WPARAM wParam, LPARAM lParam)
1244 TREEVIEW_INFO *infoPtr = TREEVIEW_GetInfoPtr(hwnd);
1246 TREEVIEW_ITEM *wineItem;
1249 tvItem=(LPTVITEMEXA) lParam;
1250 iItem=(INT)tvItem->hItem;
1252 wineItem = TREEVIEW_ValidItem (infoPtr, (HTREEITEM)iItem);
1253 if (!wineItem) return FALSE;
1255 if (tvItem->mask & TVIF_CHILDREN) {
1256 if (TVIF_CHILDREN==I_CHILDRENCALLBACK)
1257 FIXME("I_CHILDRENCALLBACK not supported\n");
1258 tvItem->cChildren=wineItem->cChildren;
1261 if (tvItem->mask & TVIF_HANDLE) {
1262 tvItem->hItem=wineItem->hItem;
1265 if (tvItem->mask & TVIF_IMAGE) {
1266 tvItem->iImage=wineItem->iImage;
1269 if (tvItem->mask & TVIF_INTEGRAL) {
1270 tvItem->iIntegral=wineItem->iIntegral;
1273 /* undocumented: windows ignores TVIF_PARAM and
1274 * always sets lParam
1276 tvItem->lParam=wineItem->lParam;
1278 if (tvItem->mask & TVIF_SELECTEDIMAGE) {
1279 tvItem->iSelectedImage=wineItem->iSelectedImage;
1282 if (tvItem->mask & TVIF_STATE) {
1283 tvItem->state=wineItem->state & tvItem->stateMask;
1286 if (tvItem->mask & TVIF_TEXT) {
1287 if (wineItem->pszText == LPSTR_TEXTCALLBACKA) {
1288 tvItem->pszText = LPSTR_TEXTCALLBACKA; /* FIXME:send notification? */
1289 ERR(" GetItem called with LPSTR_TEXTCALLBACK\n");
1291 else if (wineItem->pszText) {
1292 lstrcpynA (tvItem->pszText, wineItem->pszText, tvItem->cchTextMax);
1296 TRACE("item %d<%p>, txt %p, img %p, action %x\n",
1297 iItem, tvItem, tvItem->pszText, &tvItem->iImage, tvItem->mask);
1304 /* FIXME: check implementation of TVGN_NEXT/TVGN_NEXTVISIBLE */
1307 TREEVIEW_GetNextItem (HWND hwnd, WPARAM wParam, LPARAM lParam)
1310 TREEVIEW_INFO *infoPtr = TREEVIEW_GetInfoPtr(hwnd);
1311 TREEVIEW_ITEM *wineItem, *returnItem;
1312 INT iItem, retval, flag;
1315 flag = (INT) wParam;
1316 iItem = (INT) lParam;
1319 case TVGN_ROOT: retval=(INT)infoPtr->TopRootItem;
1321 case TVGN_CARET:retval=(INT)infoPtr->selectedItem;
1323 case TVGN_FIRSTVISIBLE: /* FIXME:we should only recalculate, not redraw */
1325 TREEVIEW_Refresh (hwnd, hdc);
1326 ReleaseDC(hwnd,hdc);
1327 retval=(INT)infoPtr->firstVisible;
1329 case TVGN_DROPHILITE:
1330 retval=(INT)infoPtr->dropItem;
1334 TRACE("flags:%x, returns %u\n", flag, retval);
1338 wineItem = TREEVIEW_ValidItem (infoPtr, (HTREEITEM)iItem);
1340 if (!wineItem) return FALSE;
1343 case TVGN_NEXT: retval=(INT)wineItem->sibling;
1346 retval=(INT)wineItem->upsibling;
1349 retval=(INT)wineItem->parent;
1352 retval=(INT)wineItem->firstChild;
1354 case TVGN_LASTVISIBLE:
1355 returnItem=TREEVIEW_GetLastListItem (infoPtr,wineItem);
1357 case TVGN_NEXTVISIBLE:
1358 returnItem=TREEVIEW_GetNextListItem (infoPtr,wineItem);
1360 case TVGN_PREVIOUSVISIBLE:
1361 returnItem=TREEVIEW_GetPrevListItem (infoPtr, wineItem);
1363 default: FIXME("Unknown msg %x,item %x\n", flag,iItem);
1368 TRACE("flags:%x, item %d;returns %d\n", flag, iItem,
1369 (INT)returnItem->hItem);
1370 return (INT)returnItem->hItem;
1373 TRACE("flags:%x, item %d;returns %d\n", flag, iItem,retval);
1379 TREEVIEW_GetCount (HWND hwnd, WPARAM wParam, LPARAM lParam)
1381 TREEVIEW_INFO *infoPtr = TREEVIEW_GetInfoPtr(hwnd);
1383 TRACE(" %d\n",infoPtr->uNumItems);
1384 return (LRESULT) infoPtr->uNumItems;
1387 /***************************************************************************
1388 * This method does the chaining of the insertion of a treeview item
1390 * If parent is NULL, we're inserting at the root of the list.
1392 static void TREEVIEW_InsertBefore(
1393 TREEVIEW_INFO *infoPtr,
1394 TREEVIEW_ITEM *newItem,
1395 TREEVIEW_ITEM *sibling,
1396 TREEVIEW_ITEM *parent)
1398 HTREEITEM siblingHandle = 0;
1399 HTREEITEM upSiblingHandle = 0;
1400 TREEVIEW_ITEM *upSibling = NULL;
1402 if (newItem == NULL)
1403 ERR("NULL newItem, impossible condition\n");
1405 if (sibling != NULL) /* Insert before this sibling for this parent */
1407 /* Store the new item sibling up sibling and sibling tem handle */
1408 siblingHandle = sibling->hItem;
1409 upSiblingHandle = sibling->upsibling;
1410 /* As well as a pointer to the upsibling sibling object */
1411 if ( (INT)sibling->upsibling != 0 )
1412 upSibling = &infoPtr->items[(INT)sibling->upsibling];
1414 /* Adjust the sibling pointer */
1415 sibling->upsibling = newItem->hItem;
1417 /* Adjust the new item pointers */
1418 newItem->upsibling = upSiblingHandle;
1419 newItem->sibling = siblingHandle;
1421 /* Adjust the up sibling pointer */
1422 if ( upSibling != NULL )
1423 upSibling->sibling = newItem->hItem;
1425 /* this item is the first child of this parent, adjust parent pointers */
1427 parent->firstChild = newItem->hItem;
1429 infoPtr->TopRootItem= newItem->hItem;
1431 else /* Insert as first child of this parent */
1433 parent->firstChild = newItem->hItem;
1436 /***************************************************************************
1437 * This method does the chaining of the insertion of a treeview item
1439 * If parent is NULL, we're inserting at the root of the list.
1441 static void TREEVIEW_InsertAfter(
1442 TREEVIEW_INFO *infoPtr,
1443 TREEVIEW_ITEM *newItem,
1444 TREEVIEW_ITEM *upSibling,
1445 TREEVIEW_ITEM *parent)
1447 HTREEITEM upSiblingHandle = 0;
1448 HTREEITEM siblingHandle = 0;
1449 TREEVIEW_ITEM *sibling = NULL;
1452 if (newItem == NULL)
1453 ERR("NULL newItem, impossible condition\n");
1455 if (upSibling != NULL) /* Insert after this upsibling for this parent */
1457 /* Store the new item up sibling and sibling item handle */
1458 upSiblingHandle = upSibling->hItem;
1459 siblingHandle = upSibling->sibling;
1460 /* As well as a pointer to the upsibling sibling object */
1461 if ( (INT)upSibling->sibling != 0 )
1462 sibling = &infoPtr->items[(INT)upSibling->sibling];
1464 /* Adjust the up sibling pointer */
1465 upSibling->sibling = newItem->hItem;
1467 /* Adjust the new item pointers */
1468 newItem->upsibling = upSiblingHandle;
1469 newItem->sibling = siblingHandle;
1471 /* Adjust the sibling pointer */
1472 if ( sibling != NULL )
1473 sibling->upsibling = newItem->hItem;
1476 newItem is the last of the level, nothing else to do
1479 else /* Insert as first child of this parent */
1481 parent->firstChild = newItem->hItem;
1484 /***************************************************************************
1485 * Forward the DPA local callback to the treeview owner callback
1487 static INT WINAPI TREEVIEW_CallBackCompare(
1492 /* Forward the call to the client define callback */
1493 TREEVIEW_INFO *infoPtr = TREEVIEW_GetInfoPtr((HWND)tvInfoPtr);
1494 return (infoPtr->pCallBackSort->lpfnCompare)(
1495 ((TREEVIEW_ITEM*)first)->lParam,
1496 ((TREEVIEW_ITEM*)second)->lParam,
1497 infoPtr->pCallBackSort->lParam);
1500 /***************************************************************************
1501 * Treeview native sort routine: sort on item text.
1503 static INT WINAPI TREEVIEW_SortOnName (
1508 HWND hwnd=(HWND) tvInfoPtr;
1510 TREEVIEW_ITEM *item;
1513 item=(TREEVIEW_ITEM *) first;
1514 if (item->pszText==LPSTR_TEXTCALLBACKA) {
1515 TREEVIEW_SendDispInfoNotify (hwnd, item, TVN_GETDISPINFO, TVIF_TEXT);
1519 item=(TREEVIEW_ITEM *) second;
1520 if (item->pszText==LPSTR_TEXTCALLBACKA) {
1521 TREEVIEW_SendDispInfoNotify (hwnd, item, TVN_GETDISPINFO, TVIF_TEXT);
1525 return -strcmp (txt1,txt2);
1528 /***************************************************************************
1529 * Setup the treeview structure with regards of the sort method
1530 * and sort the children of the TV item specified in lParam
1531 * fRecurse: currently unused. Should be zero.
1532 * parent: if pSort!=NULL, should equal pSort->hParent.
1533 * otherwise, item which child items are to be sorted.
1534 * pSort: sort method info. if NULL, sort on item text.
1535 * if non-NULL, sort on item's lParam content, and let the
1536 * application decide what that means. See also TVM_SORTCHILDRENCB.
1539 static LRESULT WINAPI TREEVIEW_Sort (
1546 TREEVIEW_INFO *infoPtr = TREEVIEW_GetInfoPtr(hwnd);
1547 TREEVIEW_ITEM *sortMe = NULL; /* Node for which we sort the children */
1549 /* Obtain the TVSORTBC struct */
1550 infoPtr->pCallBackSort = pSort;
1552 /* undocumented feature: TVI_ROOT means `sort the whole tree' */
1554 if (parent==TVI_ROOT)
1555 parent=infoPtr->TopRootItem;
1557 /* Check for a valid handle to the parent item */
1558 if (!TREEVIEW_ValidItem(infoPtr, parent))
1560 ERR ("invalid item hParent=%x\n", (INT)parent);
1564 /* Obtain the parent node to sort */
1565 sortMe = &infoPtr->items[ (INT)parent ];
1567 /* Make sure there is something to sort */
1568 if ( sortMe->cChildren > 1 )
1570 /* pointer organization */
1571 HDPA sortList = DPA_Create(sortMe->cChildren);
1572 HTREEITEM itemHandle = sortMe->firstChild;
1573 TREEVIEW_ITEM *itemPtr = & infoPtr->items[ (INT)itemHandle ];
1575 /* TREEVIEW_ITEM rechaining */
1581 /* Build the list of item to sort */
1585 sortList, /* the list */
1586 sortMe->cChildren+1, /* force the insertion to be an append */
1587 itemPtr); /* the ptr to store */
1589 /* Get the next sibling */
1590 itemHandle = itemPtr->sibling;
1591 itemPtr = & infoPtr->items[ (INT)itemHandle ];
1592 } while ( itemHandle != NULL );
1594 /* let DPA perform the sort activity */
1597 sortList, /* what */
1598 TREEVIEW_CallBackCompare, /* how */
1602 sortList, /* what */
1603 TREEVIEW_SortOnName, /* how */
1607 * Reorganized TREEVIEW_ITEM structures.
1608 * Note that we know we have at least two elements.
1611 /* Get the first item and get ready to start... */
1612 item = DPA_GetPtr(sortList, count++);
1613 while ( (nextItem = DPA_GetPtr(sortList, count++)) != NULL )
1615 /* link the two current item toghether */
1616 ((TREEVIEW_ITEM*)item)->sibling = ((TREEVIEW_ITEM*)nextItem)->hItem;
1617 ((TREEVIEW_ITEM*)nextItem)->upsibling = ((TREEVIEW_ITEM*)item)->hItem;
1619 if (prevItem == NULL) /* this is the first item, update the parent */
1621 sortMe->firstChild = ((TREEVIEW_ITEM*)item)->hItem;
1622 ((TREEVIEW_ITEM*)item)->upsibling = NULL;
1624 else /* fix the back chaining */
1626 ((TREEVIEW_ITEM*)item)->upsibling = ((TREEVIEW_ITEM*)prevItem)->hItem;
1629 /* get ready for the next one */
1634 /* the last item is pointed to by item and never has a sibling */
1635 ((TREEVIEW_ITEM*)item)->sibling = NULL;
1637 DPA_Destroy(sortList);
1645 /***************************************************************************
1646 * Setup the treeview structure with regards of the sort method
1647 * and sort the children of the TV item specified in lParam
1649 static LRESULT WINAPI TREEVIEW_SortChildrenCB(
1655 LPTVSORTCB pSort=(LPTVSORTCB) lParam;
1657 return TREEVIEW_Sort (hwnd, wParam, pSort->hParent, pSort);
1661 /***************************************************************************
1662 * Sort the children of the TV item specified in lParam.
1664 static LRESULT WINAPI TREEVIEW_SortChildren (
1669 return TREEVIEW_Sort (hwnd, (BOOL) wParam, (HTREEITEM) lParam, NULL);
1674 /* the method used below isn't the most memory-friendly, but it avoids
1675 a lot of memory reallocations */
1677 /* BTW: we waste handle 0; 0 is not an allowed handle. */
1680 TREEVIEW_InsertItemA (HWND hwnd, WPARAM wParam, LPARAM lParam)
1683 TREEVIEW_INFO *infoPtr = TREEVIEW_GetInfoPtr(hwnd);
1684 TVINSERTSTRUCTA *ptdi;
1686 TREEVIEW_ITEM *wineItem, *parentItem, *prevsib, *sibItem;
1687 INT iItem,listItems,i,len;
1689 /* Item to insert */
1690 ptdi = (LPTVINSERTSTRUCTA) lParam;
1692 /* check if memory is available */
1694 if (infoPtr->uNumPtrsAlloced==0) {
1695 infoPtr->items = COMCTL32_Alloc (TVITEM_ALLOC*sizeof (TREEVIEW_ITEM));
1696 infoPtr->freeList= COMCTL32_Alloc ((1+(TVITEM_ALLOC>>5)) * sizeof (INT));
1697 infoPtr->uNumPtrsAlloced=TVITEM_ALLOC;
1698 infoPtr->TopRootItem=(HTREEITEM)1;
1702 * Reallocate contiguous space for items
1704 if (infoPtr->uNumItems == (infoPtr->uNumPtrsAlloced-1) ) {
1705 TREEVIEW_ITEM *oldItems = infoPtr->items;
1706 INT *oldfreeList = infoPtr->freeList;
1708 infoPtr->uNumPtrsAlloced*=2;
1709 infoPtr->items = COMCTL32_Alloc (infoPtr->uNumPtrsAlloced*sizeof (TREEVIEW_ITEM));
1710 infoPtr->freeList= COMCTL32_Alloc ((1+(infoPtr->uNumPtrsAlloced>>5))*sizeof (INT));
1712 memcpy (&infoPtr->items[0], &oldItems[0],
1713 infoPtr->uNumPtrsAlloced/2 * sizeof(TREEVIEW_ITEM));
1714 memcpy (&infoPtr->freeList[0], &oldfreeList[0],
1715 (infoPtr->uNumPtrsAlloced>>6) * sizeof(INT));
1717 COMCTL32_Free (oldItems);
1718 COMCTL32_Free (oldfreeList);
1722 * Reset infoPtr structure with new stat according to current TV picture
1725 infoPtr->uNumItems++;
1726 if ((INT)infoPtr->uMaxHandle==(infoPtr->uNumItems-1)) {
1727 iItem=infoPtr->uNumItems;
1728 infoPtr->uMaxHandle = (HTREEITEM)((INT)infoPtr->uMaxHandle + 1);
1729 } else { /* check freelist */
1730 for (i=0; i<infoPtr->uNumPtrsAlloced>>5; i++) {
1731 if (infoPtr->freeList[i]) {
1732 iItem=ffs (infoPtr->freeList[i])-1;
1733 tv_clear_bit(iItem,&infoPtr->freeList[i]);
1740 if (TRACE_ON(treeview)) {
1741 for (i=0; i<infoPtr->uNumPtrsAlloced>>5; i++)
1742 TRACE("%8x\n",infoPtr->freeList[i]);
1745 if (!iItem) ERR("Argh -- can't find free item.\n");
1748 * Find the parent item of the new item
1750 tvItem= & ptdi->DUMMYUNIONNAME.itemex;
1751 wineItem=& infoPtr->items[iItem];
1753 if ((ptdi->hParent==TVI_ROOT) || (ptdi->hParent==0)) {
1755 wineItem->parent = 0;
1756 sibItem = &infoPtr->items [(INT)infoPtr->TopRootItem];
1757 listItems = infoPtr->uNumItems;
1760 parentItem = &infoPtr->items[(INT)ptdi->hParent];
1762 /* Do the insertion here it if it's the only item of this parent */
1763 if (!parentItem->firstChild)
1764 parentItem->firstChild=(HTREEITEM)iItem;
1766 wineItem->parent = ptdi->hParent;
1767 sibItem = &infoPtr->items [(INT)parentItem->firstChild];
1768 parentItem->cChildren++;
1769 listItems = parentItem->cChildren;
1773 /* NOTE: I am moving some setup of the wineItem object that was initialy
1774 * done at the end of the function since some of the values are
1775 * required by the Callback sorting
1778 if (tvItem->mask & TVIF_TEXT)
1781 * Setup the item text stuff here since it's required by the Sort method
1782 * when the insertion are ordered
1784 if (tvItem->pszText!=LPSTR_TEXTCALLBACKA)
1786 TRACE("(%p,%s)\n", &tvItem->pszText, tvItem->pszText);
1787 len = lstrlenA (tvItem->pszText)+1;
1788 wineItem->pszText= COMCTL32_Alloc (len+1);
1789 lstrcpyA (wineItem->pszText, tvItem->pszText);
1790 wineItem->cchTextMax=len;
1794 TRACE("LPSTR_TEXTCALLBACK\n");
1795 wineItem->pszText = LPSTR_TEXTCALLBACKA;
1796 wineItem->cchTextMax = 0;
1800 if (tvItem->mask & TVIF_PARAM)
1801 wineItem->lParam=tvItem->lParam;
1804 wineItem->upsibling=0; /* needed in case we're the first item in a list */
1805 wineItem->sibling=0;
1806 wineItem->firstChild=0;
1807 wineItem->hItem=(HTREEITEM)iItem;
1812 switch ((DWORD) ptdi->hInsertAfter) {
1813 case (DWORD) TVI_FIRST:
1814 if (sibItem==wineItem) break;
1815 if (wineItem->parent) {
1816 wineItem->sibling=parentItem->firstChild;
1817 parentItem->firstChild=(HTREEITEM)iItem;
1819 wineItem->sibling=infoPtr->TopRootItem;
1820 infoPtr->TopRootItem=(HTREEITEM)iItem;
1822 sibItem->upsibling=(HTREEITEM)iItem;
1825 case (DWORD) TVI_SORT:
1826 if (sibItem==wineItem)
1828 * This item is the first child of the level and it
1829 * has already been inserted
1834 TREEVIEW_ITEM *aChild;
1837 TREEVIEW_ITEM *previousChild = NULL;
1838 BOOL bItemInserted = FALSE;
1841 aChild = &infoPtr->items[(INT)parentItem->firstChild];
1843 aChild = &infoPtr->items[(INT)infoPtr->TopRootItem];
1845 /* lookup the text if using LPSTR_TEXTCALLBACKs */
1846 if (wineItem->pszText==LPSTR_TEXTCALLBACKA) {
1847 TREEVIEW_SendDispInfoNotify (hwnd, wineItem, TVN_GETDISPINFO, TVIF_TEXT);
1850 /* Iterate the parent children to see where we fit in */
1851 while ( aChild != NULL )
1855 /* lookup the text if using LPSTR_TEXTCALLBACKs */
1856 if (aChild->pszText==LPSTR_TEXTCALLBACKA) {
1857 TREEVIEW_SendDispInfoNotify (hwnd, aChild, TVN_GETDISPINFO, TVIF_TEXT);
1860 comp = strcmp(wineItem->pszText, aChild->pszText);
1861 if ( comp < 0 ) /* we are smaller than the current one */
1863 TREEVIEW_InsertBefore(infoPtr, wineItem, aChild, parentItem);
1864 bItemInserted = TRUE;
1867 else if ( comp > 0 ) /* we are bigger than the current one */
1869 previousChild = aChild;
1870 aChild = (aChild->sibling == 0) /* This will help us to exit */
1871 ? NULL /* if there is no more sibling */
1872 : &infoPtr->items[(INT)aChild->sibling];
1874 /* Look at the next item */
1877 else if ( comp == 0 )
1880 * An item with this name is already existing, therefore,
1881 * we add after the one we found
1883 TREEVIEW_InsertAfter(infoPtr, wineItem, aChild, parentItem);
1884 bItemInserted = TRUE;
1890 * we reach the end of the child list and the item as not
1891 * yet been inserted, therefore, insert it after the last child.
1893 if ( (! bItemInserted ) && (aChild == NULL) )
1894 TREEVIEW_InsertAfter(infoPtr, wineItem, previousChild, parentItem);
1900 case (DWORD) TVI_LAST:
1901 if (sibItem==wineItem) break;
1902 while (sibItem->sibling) {
1904 sibItem=&infoPtr->items [(INT)sibItem->sibling];
1906 sibItem->sibling=(HTREEITEM)iItem;
1907 wineItem->upsibling=sibItem->hItem;
1910 while ((sibItem->sibling) && (sibItem->hItem!=ptdi->hInsertAfter))
1913 sibItem=&infoPtr->items [(INT)sibItem->sibling];
1915 if (sibItem->hItem!=ptdi->hInsertAfter) {
1916 ERR("tried to insert item after nonexisting handle %d.\n",
1917 (INT) ptdi->hInsertAfter);
1921 if (sibItem->sibling) {
1922 sibItem=&infoPtr->items [(INT)sibItem->sibling];
1923 sibItem->upsibling=(HTREEITEM)iItem;
1924 wineItem->sibling=sibItem->hItem;
1926 prevsib->sibling=(HTREEITEM)iItem;
1927 wineItem->upsibling=prevsib->hItem;
1933 /* Fill in info structure */
1935 TRACE("new item %d; parent %d, mask %x\n", iItem,
1936 (INT)wineItem->parent,tvItem->mask);
1938 wineItem->mask=tvItem->mask;
1939 wineItem->iIntegral=1;
1941 if (tvItem->mask & TVIF_CHILDREN) {
1942 wineItem->cChildren=tvItem->cChildren;
1943 if (tvItem->cChildren==I_CHILDRENCALLBACK)
1944 FIXME(" I_CHILDRENCALLBACK not supported\n");
1947 wineItem->expandBox.left = 0; /* Initialize the expandBox */
1948 wineItem->expandBox.top = 0;
1949 wineItem->expandBox.right = 0;
1950 wineItem->expandBox.bottom = 0;
1952 if (tvItem->mask & TVIF_IMAGE)
1953 wineItem->iImage=tvItem->iImage;
1955 /* If the application sets TVIF_INTEGRAL without
1956 supplying a TVITEMEX structure, it's toast */
1958 if (tvItem->mask & TVIF_INTEGRAL)
1959 wineItem->iIntegral=tvItem->iIntegral;
1961 if (tvItem->mask & TVIF_SELECTEDIMAGE)
1962 wineItem->iSelectedImage=tvItem->iSelectedImage;
1964 if (tvItem->mask & TVIF_STATE) {
1965 TRACE("item state: %x ->%x\n", wineItem->state, tvItem->state);
1966 TRACE("statemask: %x ->%x\n", wineItem->stateMask, tvItem->stateMask);
1967 wineItem->state=tvItem->state;
1968 wineItem->stateMask=tvItem->stateMask;
1971 TREEVIEW_QueueRefresh (hwnd);
1973 return (LRESULT) iItem;
1978 TREEVIEW_InsertItemW(HWND hwnd, WPARAM wParam, LPARAM lParam)
1980 TVINSERTSTRUCTW *tvisW;
1981 TVINSERTSTRUCTA tvisA;
1984 tvisW = (LPTVINSERTSTRUCTW)lParam;
1986 tvisA.hParent = tvisW->hParent;
1987 tvisA.hInsertAfter = tvisW->hInsertAfter;
1989 tvisA.DUMMYUNIONNAME.item.mask = tvisW->DUMMYUNIONNAME.item.mask;
1990 tvisA.DUMMYUNIONNAME.item.hItem = tvisW->DUMMYUNIONNAME.item.hItem;
1991 tvisA.DUMMYUNIONNAME.item.state = tvisW->DUMMYUNIONNAME.item.state;
1992 tvisA.DUMMYUNIONNAME.item.stateMask = tvisW->DUMMYUNIONNAME.item.stateMask;
1993 tvisA.DUMMYUNIONNAME.item.cchTextMax = tvisW->DUMMYUNIONNAME.item.cchTextMax;
1995 if(tvisW->DUMMYUNIONNAME.item.pszText)
1997 if (tvisW->DUMMYUNIONNAME.item.pszText!=LPSTR_TEXTCALLBACKW)
1999 int len = lstrlenW (tvisW->DUMMYUNIONNAME.item.pszText)+1;
2000 tvisA.DUMMYUNIONNAME.item.pszText = COMCTL32_Alloc (len);
2001 lstrcpyWtoA (tvisA.DUMMYUNIONNAME.item.pszText,
2002 tvisW->DUMMYUNIONNAME.item.pszText );
2006 tvisA.DUMMYUNIONNAME.item.pszText = LPSTR_TEXTCALLBACKA;
2007 tvisA.DUMMYUNIONNAME.item.cchTextMax = 0;
2011 tvisA.DUMMYUNIONNAME.item.iImage = tvisW->DUMMYUNIONNAME.item.iImage;
2012 tvisA.DUMMYUNIONNAME.item.iSelectedImage = tvisW->DUMMYUNIONNAME.item.iSelectedImage;
2013 tvisA.DUMMYUNIONNAME.item.cChildren = tvisW->DUMMYUNIONNAME.item.cChildren;
2014 tvisA.DUMMYUNIONNAME.item.lParam = tvisW->DUMMYUNIONNAME.item.lParam;
2016 lRes = TREEVIEW_InsertItemA(hwnd,wParam,(LPARAM)&tvisA);
2018 if (tvisA.DUMMYUNIONNAME.item.pszText!=LPSTR_TEXTCALLBACKA)
2020 COMCTL32_Free(tvisA.DUMMYUNIONNAME.item.pszText);
2029 TREEVIEW_DeleteItem (HWND hwnd, WPARAM wParam, LPARAM lParam)
2031 TREEVIEW_INFO *infoPtr = TREEVIEW_GetInfoPtr(hwnd);
2033 TREEVIEW_ITEM *wineItem;
2037 if (lParam == (INT)TVI_ROOT) {
2038 TREEVIEW_RemoveTree (hwnd);
2040 iItem= (INT) lParam;
2041 wineItem = TREEVIEW_ValidItem (infoPtr, (HTREEITEM)iItem);
2042 if (!wineItem) return FALSE;
2044 if (wineItem->pszText==LPSTR_TEXTCALLBACKA)
2045 TRACE("LPSTR_TEXTCALLBACK\n");
2047 TRACE("%s\n",wineItem->pszText);
2048 TREEVIEW_RemoveItem (hwnd, wineItem);
2051 TREEVIEW_QueueRefresh (hwnd);
2059 TREEVIEW_GetIndent (HWND hwnd)
2061 TREEVIEW_INFO *infoPtr = TREEVIEW_GetInfoPtr(hwnd);
2064 return infoPtr->uIndent;
2068 TREEVIEW_SetIndent (HWND hwnd, WPARAM wParam)
2070 TREEVIEW_INFO *infoPtr = TREEVIEW_GetInfoPtr(hwnd);
2074 newIndent=(INT) wParam;
2075 if (newIndent < MINIMUM_INDENT) newIndent=MINIMUM_INDENT;
2076 infoPtr->uIndent=newIndent;
2082 TREEVIEW_GetToolTips (HWND hwnd)
2085 TREEVIEW_INFO *infoPtr = TREEVIEW_GetInfoPtr(hwnd);
2088 return infoPtr->hwndToolTip;
2093 TREEVIEW_SetToolTips (HWND hwnd, WPARAM wParam)
2096 TREEVIEW_INFO *infoPtr = TREEVIEW_GetInfoPtr(hwnd);
2100 prevToolTip=infoPtr->hwndToolTip;
2101 infoPtr->hwndToolTip= (HWND) wParam;
2107 static LRESULT CALLBACK
2108 TREEVIEW_GetEditControl (HWND hwnd)
2111 TREEVIEW_INFO *infoPtr = TREEVIEW_GetInfoPtr(hwnd);
2113 return infoPtr->hwndEdit;
2117 TREEVIEW_Edit_SubclassProc (HWND hwnd, UINT uMsg, WPARAM wParam,
2125 HDC hdc = (HDC) wParam;
2126 GetClientRect (hwnd, &rc);
2127 Rectangle (hdc, rc.left, rc.top, rc.right, rc.bottom);
2133 return DLGC_WANTARROWS | DLGC_WANTALLKEYS;
2138 TREEVIEW_INFO *infoPtr = TREEVIEW_GetInfoPtr(GetParent(hwnd));
2140 return CallWindowProcA (infoPtr->wpEditOrig, hwnd, uMsg, wParam, lParam);
2151 /* should handle edit control messages here */
2154 TREEVIEW_Command (HWND hwnd, WPARAM wParam, LPARAM lParam)
2157 TRACE("%x %ld\n",wParam, lParam);
2159 switch (HIWORD(wParam))
2164 * Adjust the edit window size
2166 TREEVIEW_INFO *infoPtr = TREEVIEW_GetInfoPtr(hwnd);
2167 TREEVIEW_ITEM *editItem = TREEVIEW_ValidItem(infoPtr, infoPtr->editItem);
2168 INT iLength = GetWindowTextLengthA(infoPtr->hwndEdit);
2169 HDC hdc = GetDC(infoPtr->hwndEdit);
2172 if ( GetTextMetricsA(hdc, &tm) )
2174 LONG newWidth = (iLength * tm.tmAveCharWidth) + 15;
2179 editItem->text.left - 2,
2180 editItem->text.top - 1,
2182 editItem->text.bottom - editItem->text.top + 3,
2185 ReleaseDC(hwnd, hdc);
2191 /* TREEVIEW_EndEditLabelNow(hwnd, (WPARAM)FALSE, 0);
2196 return SendMessageA (GetParent (hwnd), WM_COMMAND, wParam, lParam);
2203 TREEVIEW_Size (HWND hwnd, WPARAM wParam, LPARAM lParam)
2206 TREEVIEW_INFO *infoPtr = TREEVIEW_GetInfoPtr(hwnd);
2208 if (infoPtr->bAutoSize)
2210 infoPtr->bAutoSize = FALSE;
2213 infoPtr->bAutoSize = TRUE;
2215 if (wParam == SIZE_RESTORED)
2217 infoPtr->uTotalWidth = LOWORD (lParam);
2218 infoPtr->uTotalHeight = HIWORD (lParam);
2220 FIXME("WM_SIZE flag %x %lx not handled\n", wParam, lParam);
2223 TREEVIEW_QueueRefresh (hwnd);
2230 TREEVIEW_StyleChanged (HWND hwnd, WPARAM wParam, LPARAM lParam)
2234 TRACE("(%x %lx)\n",wParam,lParam);
2236 TREEVIEW_Refresh (hwnd, hdc);
2237 ReleaseDC(hwnd,hdc);
2243 TREEVIEW_Create (HWND hwnd, WPARAM wParam, LPARAM lParam)
2245 TREEVIEW_INFO *infoPtr;
2246 DWORD dwStyle = GetWindowLongA (hwnd, GWL_STYLE);
2251 TRACE("wnd %x, style %lx\n",hwnd,dwStyle);
2252 /* allocate memory for info structure */
2253 infoPtr = (TREEVIEW_INFO *) COMCTL32_Alloc (sizeof(TREEVIEW_INFO));
2255 SetWindowLongA( hwnd, 0, (DWORD)infoPtr);
2257 if (infoPtr == NULL) {
2258 ERR("could not allocate info memory!\n");
2262 if ((TREEVIEW_INFO*) GetWindowLongA( hwnd, 0) != infoPtr) {
2263 ERR("pointer assignment error!\n");
2269 /* set default settings */
2270 infoPtr->uInternalStatus=0;
2271 infoPtr->uNumItems=0;
2272 infoPtr->clrBk = GetSysColor (COLOR_WINDOW);
2273 infoPtr->clrText = GetSysColor (COLOR_WINDOWTEXT);
2274 infoPtr->clrLine = GetSysColor (COLOR_WINDOWTEXT);
2275 infoPtr->clrInsertMark = GetSysColor (COLOR_BTNTEXT);
2278 infoPtr->uIndent = 15;
2279 infoPtr->himlNormal = NULL;
2280 infoPtr->himlState = NULL;
2281 infoPtr->uItemHeight = -1;
2282 GetTextMetricsA (hdc, &tm);
2283 infoPtr->hFont = GetStockObject (DEFAULT_GUI_FONT);
2284 GetObjectA (infoPtr->hFont, sizeof (LOGFONTA), &logFont);
2285 logFont.lfWeight=FW_BOLD;
2286 infoPtr->hBoldFont = CreateFontIndirectA (&logFont);
2288 infoPtr->items = NULL;
2289 infoPtr->selectedItem=0;
2290 infoPtr->clrText=-1; /* use system color */
2291 infoPtr->dropItem=0;
2292 infoPtr->insertMarkItem=0;
2293 infoPtr->insertBeforeorAfter=0;
2294 infoPtr->pCallBackSort=NULL;
2295 infoPtr->uScrollTime = 300; /* milliseconds */
2296 infoPtr->wpEditOrig = NULL; /* we haven't subclassed anything yet */
2298 infoPtr->hwndToolTip=0;
2299 if (!(dwStyle & TVS_NOTOOLTIPS)) { /* Create tooltip control */
2302 infoPtr->hwndToolTip =
2303 CreateWindowExA (0, TOOLTIPS_CLASSA, NULL, 0,
2304 CW_USEDEFAULT, CW_USEDEFAULT,
2305 CW_USEDEFAULT, CW_USEDEFAULT,
2308 /* Send NM_TOOLTIPSCREATED notification */
2309 if (infoPtr->hwndToolTip) {
2310 NMTOOLTIPSCREATED nmttc;
2312 nmttc.hdr.hwndFrom = hwnd;
2313 nmttc.hdr.idFrom = GetWindowLongA( hwnd, GWL_ID);
2314 nmttc.hdr.code = NM_TOOLTIPSCREATED;
2315 nmttc.hwndToolTips = infoPtr->hwndToolTip;
2317 SendMessageA (GetParent (hwnd), WM_NOTIFY,
2318 (WPARAM) GetWindowLongA( hwnd, GWL_ID), (LPARAM)&nmttc);
2321 ZeroMemory (&ti, sizeof(TTTOOLINFOA));
2322 ti.cbSize = sizeof(TTTOOLINFOA);
2323 ti.uFlags = TTF_IDISHWND | TTF_TRACK | TTF_TRANSPARENT ;
2326 ti.lpszText = "Test"; /* LPSTR_TEXTCALLBACK; */
2327 SetRectEmpty (&ti.rect);
2329 SendMessageA (infoPtr->hwndToolTip, TTM_ADDTOOLA, 0, (LPARAM)&ti);
2332 infoPtr->hwndEdit = CreateWindowExA (
2336 WS_CHILD | WS_BORDER | ES_AUTOHSCROLL |
2337 ES_WANTRETURN | ES_LEFT,
2340 0,0,0); /* FIXME: (HMENU)IDTVEDIT,pcs->hInstance,0);*/
2342 SendMessageA ( infoPtr->hwndEdit, WM_SETFONT, infoPtr->hFont, FALSE);
2343 infoPtr->wpEditOrig = (WNDPROC)SetWindowLongA (
2346 (LONG) TREEVIEW_Edit_SubclassProc);
2348 if (dwStyle & TVS_CHECKBOXES) {
2352 infoPtr->himlState =
2353 ImageList_Create (16, 16,ILC_COLOR|ILC_MASK, 15, 1);
2355 hbmLoad = LoadBitmapA (COMCTL32_hModule, MAKEINTRESOURCEA(IDT_CHECK));
2356 TRACE ("%x\n",hbmLoad);
2357 nIndex = ImageList_AddMasked (infoPtr->himlState, hbmLoad, CLR_DEFAULT);
2358 TRACE ("%d\n",nIndex);
2359 DeleteObject (hbmLoad);
2361 ReleaseDC (hwnd, hdc);
2368 TREEVIEW_Destroy (HWND hwnd)
2370 TREEVIEW_INFO *infoPtr = TREEVIEW_GetInfoPtr(hwnd);
2373 TREEVIEW_RemoveTree (hwnd);
2374 SetWindowLongA (hwnd, 0, (DWORD)NULL);
2376 if (infoPtr->Timer & TV_REFRESH_TIMER_SET)
2377 KillTimer (hwnd, TV_REFRESH_TIMER);
2378 if (infoPtr->hwndToolTip)
2379 DestroyWindow (infoPtr->hwndToolTip);
2381 COMCTL32_Free (infoPtr);
2387 TREEVIEW_Paint (HWND hwnd, WPARAM wParam, LPARAM lParam)
2393 hdc = wParam==0 ? BeginPaint (hwnd, &ps) : (HDC)wParam;
2394 TREEVIEW_Refresh (hwnd, hdc);
2395 ReleaseDC(hwnd,hdc);
2396 if(!wParam) EndPaint (hwnd, &ps);
2399 return DefWindowProcA (hwnd, WM_PAINT, wParam, lParam);
2403 TREEVIEW_SetFocus (HWND hwnd, WPARAM wParam, LPARAM lParam)
2405 TREEVIEW_SendSimpleNotify (hwnd, NM_SETFOCUS);
2406 InvalidateRect(hwnd, NULL, FALSE);
2411 TREEVIEW_KillFocus (HWND hwnd, WPARAM wParam, LPARAM lParam)
2413 TREEVIEW_SendSimpleNotify (hwnd, NM_KILLFOCUS);
2414 InvalidateRect(hwnd, NULL, FALSE);
2419 TREEVIEW_EraseBackground (HWND hwnd, WPARAM wParam, LPARAM lParam)
2421 TREEVIEW_INFO *infoPtr = TREEVIEW_GetInfoPtr(hwnd);
2422 HBRUSH hBrush = CreateSolidBrush (infoPtr->clrBk);
2426 GetClientRect (hwnd, &rect);
2427 FillRect ((HDC)wParam, &rect, hBrush);
2428 DeleteObject (hBrush);
2444 TREEVIEW_SendSimpleNotify (HWND hwnd, UINT code)
2449 nmhdr.hwndFrom = hwnd;
2450 nmhdr.idFrom = GetWindowLongA( hwnd, GWL_ID);
2453 return (BOOL) SendMessageA (GetParent (hwnd), WM_NOTIFY,
2454 (WPARAM)nmhdr.idFrom, (LPARAM)&nmhdr);
2460 TREEVIEW_SendTreeviewNotify (HWND hwnd, UINT code, UINT action,
2461 HTREEITEM oldItem, HTREEITEM newItem)
2464 TREEVIEW_INFO *infoPtr = TREEVIEW_GetInfoPtr(hwnd);
2466 TREEVIEW_ITEM *wineItem;
2468 TRACE("code:%x action:%x olditem:%x newitem:%x\n",
2469 code,action,(INT)oldItem,(INT)newItem);
2470 nmhdr.hdr.hwndFrom = hwnd;
2471 nmhdr.hdr.idFrom = GetWindowLongA( hwnd, GWL_ID);
2472 nmhdr.hdr.code = code;
2473 nmhdr.action = action;
2475 wineItem=& infoPtr->items[(INT)oldItem];
2476 nmhdr.itemOld.mask = wineItem->mask;
2477 nmhdr.itemOld.hItem = wineItem->hItem;
2478 nmhdr.itemOld.state = wineItem->state;
2479 nmhdr.itemOld.stateMask = wineItem->stateMask;
2480 nmhdr.itemOld.iImage = wineItem->iImage;
2481 nmhdr.itemOld.pszText = wineItem->pszText;
2482 nmhdr.itemOld.cchTextMax= wineItem->cchTextMax;
2483 nmhdr.itemOld.iImage = wineItem->iImage;
2484 nmhdr.itemOld.iSelectedImage = wineItem->iSelectedImage;
2485 nmhdr.itemOld.cChildren = wineItem->cChildren;
2486 nmhdr.itemOld.lParam = wineItem->lParam;
2490 wineItem=& infoPtr->items[(INT)newItem];
2491 nmhdr.itemNew.mask = wineItem->mask;
2492 nmhdr.itemNew.hItem = wineItem->hItem;
2493 nmhdr.itemNew.state = wineItem->state;
2494 nmhdr.itemNew.stateMask = wineItem->stateMask;
2495 nmhdr.itemNew.iImage = wineItem->iImage;
2496 nmhdr.itemNew.pszText = wineItem->pszText;
2497 nmhdr.itemNew.cchTextMax= wineItem->cchTextMax;
2498 nmhdr.itemNew.iImage = wineItem->iImage;
2499 nmhdr.itemNew.iSelectedImage = wineItem->iSelectedImage;
2500 nmhdr.itemNew.cChildren = wineItem->cChildren;
2501 nmhdr.itemNew.lParam = wineItem->lParam;
2507 return (BOOL)SendMessageA (GetParent (hwnd), WM_NOTIFY,
2508 (WPARAM) GetWindowLongA( hwnd, GWL_ID), (LPARAM)&nmhdr);
2513 TREEVIEW_SendTreeviewDnDNotify (HWND hwnd, UINT code, HTREEITEM dragItem,
2516 TREEVIEW_INFO *infoPtr = TREEVIEW_GetInfoPtr(hwnd);
2518 TREEVIEW_ITEM *wineItem;
2520 TRACE("code:%x dragitem:%x\n", code,(INT)dragItem);
2522 nmhdr.hdr.hwndFrom = hwnd;
2523 nmhdr.hdr.idFrom = GetWindowLongA( hwnd, GWL_ID);
2524 nmhdr.hdr.code = code;
2526 wineItem=& infoPtr->items[(INT)dragItem];
2527 nmhdr.itemNew.mask = wineItem->mask;
2528 nmhdr.itemNew.hItem = wineItem->hItem;
2529 nmhdr.itemNew.state = wineItem->state;
2530 nmhdr.itemNew.lParam = wineItem->lParam;
2532 nmhdr.ptDrag.x = pt.x;
2533 nmhdr.ptDrag.y = pt.y;
2535 return (BOOL)SendMessageA (GetParent (hwnd), WM_NOTIFY,
2536 (WPARAM) GetWindowLongA( hwnd, GWL_ID), (LPARAM)&nmhdr);
2543 TREEVIEW_SendDispInfoNotify (HWND hwnd, TREEVIEW_ITEM *wineItem,
2544 UINT code, UINT what)
2550 TRACE("item %d, action %x, state %d\n",
2551 (INT)wineItem->hItem,
2553 (INT)wineItem->state);
2555 tvdi.hdr.hwndFrom = hwnd;
2556 tvdi.hdr.idFrom = GetWindowLongA( hwnd, GWL_ID);
2557 tvdi.hdr.code = code;
2558 tvdi.item.mask = what;
2559 tvdi.item.hItem = wineItem->hItem;
2560 tvdi.item.state = wineItem->state;
2561 tvdi.item.lParam = wineItem->lParam;
2562 tvdi.item.pszText = COMCTL32_Alloc (128*sizeof(char));
2563 tvdi.item.cchTextMax = 128;
2564 buf = tvdi.item.pszText;
2566 retval=(BOOL)SendMessageA (
2569 (WPARAM)tvdi.hdr.idFrom,
2572 if (what & TVIF_TEXT) {
2573 wineItem->pszText = tvdi.item.pszText;
2574 if (buf==tvdi.item.pszText) {
2575 wineItem->cchTextMax = 128;
2577 TRACE("user-supplied buffer\n");
2578 COMCTL32_Free (buf);
2579 wineItem->cchTextMax = 0;
2582 if (what & TVIF_SELECTEDIMAGE)
2583 wineItem->iSelectedImage = tvdi.item.iSelectedImage;
2584 if (what & TVIF_IMAGE)
2585 wineItem->iImage = tvdi.item.iImage;
2586 if (what & TVIF_CHILDREN)
2587 wineItem->cChildren = tvdi.item.cChildren;
2595 TREEVIEW_SendCustomDrawNotify (HWND hwnd, DWORD dwDrawStage, HDC hdc,
2598 TREEVIEW_INFO *infoPtr = TREEVIEW_GetInfoPtr(hwnd);
2599 NMTVCUSTOMDRAW nmcdhdr;
2600 LPNMCUSTOMDRAW nmcd;
2602 TRACE("drawstage:%lx hdc:%x\n", dwDrawStage, hdc);
2604 nmcd= & nmcdhdr.nmcd;
2605 nmcd->hdr.hwndFrom = hwnd;
2606 nmcd->hdr.idFrom = GetWindowLongA( hwnd, GWL_ID);
2607 nmcd->hdr.code = NM_CUSTOMDRAW;
2608 nmcd->dwDrawStage= dwDrawStage;
2610 nmcd->rc.left = rc.left;
2611 nmcd->rc.right = rc.right;
2612 nmcd->rc.bottom = rc.bottom;
2613 nmcd->rc.top = rc.top;
2614 nmcd->dwItemSpec = 0;
2615 nmcd->uItemState = 0;
2616 nmcd->lItemlParam= 0;
2617 nmcdhdr.clrText = infoPtr->clrText;
2618 nmcdhdr.clrTextBk= infoPtr->clrBk;
2621 return (BOOL)SendMessageA (GetParent (hwnd), WM_NOTIFY,
2622 (WPARAM) GetWindowLongA( hwnd, GWL_ID), (LPARAM)&nmcdhdr);
2628 /* FIXME: need to find out when the flags in uItemState need to be set */
2631 TREEVIEW_SendCustomDrawItemNotify (HWND hwnd, HDC hdc,
2632 TREEVIEW_ITEM *wineItem, UINT uItemDrawState)
2634 TREEVIEW_INFO *infoPtr = TREEVIEW_GetInfoPtr(hwnd);
2635 NMTVCUSTOMDRAW nmcdhdr;
2636 LPNMCUSTOMDRAW nmcd;
2637 DWORD dwDrawStage,dwItemSpec;
2641 dwDrawStage=CDDS_ITEM | uItemDrawState;
2642 dwItemSpec=(DWORD)wineItem->hItem;
2644 if (wineItem->hItem==infoPtr->selectedItem) uItemState|=CDIS_SELECTED;
2645 if (wineItem->hItem==infoPtr->focusItem) uItemState|=CDIS_FOCUS;
2646 if (wineItem->hItem==infoPtr->hotItem) uItemState|=CDIS_HOT;
2648 nmcd= & nmcdhdr.nmcd;
2649 nmcd->hdr.hwndFrom = hwnd;
2650 nmcd->hdr.idFrom = GetWindowLongA( hwnd, GWL_ID);
2651 nmcd->hdr.code = NM_CUSTOMDRAW;
2652 nmcd->dwDrawStage= dwDrawStage;
2654 nmcd->rc.left = wineItem->rect.left;
2655 nmcd->rc.right = wineItem->rect.right;
2656 nmcd->rc.bottom = wineItem->rect.bottom;
2657 nmcd->rc.top = wineItem->rect.top;
2658 nmcd->dwItemSpec = dwItemSpec;
2659 nmcd->uItemState = uItemState;
2660 nmcd->lItemlParam= wineItem->lParam;
2661 nmcdhdr.clrText = infoPtr->clrText;
2662 nmcdhdr.clrTextBk= infoPtr->clrBk;
2663 nmcdhdr.iLevel = wineItem->iLevel;
2665 TRACE("drawstage:%lx hdc:%x item:%lx, itemstate:%x, lItemlParam:%lx\n",
2666 nmcd->dwDrawStage, nmcd->hdc, nmcd->dwItemSpec,
2667 nmcd->uItemState, nmcd->lItemlParam);
2669 retval=SendMessageA (GetParent (hwnd), WM_NOTIFY,
2670 (WPARAM) GetWindowLongA( hwnd, GWL_ID), (LPARAM)&nmcdhdr);
2672 infoPtr->clrText=nmcdhdr.clrText;
2673 infoPtr->clrBk =nmcdhdr.clrTextBk;
2674 return (BOOL) retval;
2679 /* Note:If the specified item is the child of a collapsed parent item,
2680 the parent's list of child items is (recursively) expanded to reveal the
2681 specified item. This is mentioned for TREEVIEW_SelectItem; don't
2682 know if it also applies here.
2686 TREEVIEW_Expand (HWND hwnd, WPARAM wParam, LPARAM lParam)
2688 TREEVIEW_INFO *infoPtr = TREEVIEW_GetInfoPtr(hwnd);
2689 TREEVIEW_ITEM *wineItem;
2693 flag = (UINT) wParam;
2694 expand = (INT) lParam;
2696 wineItem = TREEVIEW_ValidItem (infoPtr, (HTREEITEM)expand);
2700 if (!wineItem->cChildren)
2703 if (wineItem->pszText==LPSTR_TEXTCALLBACKA)
2704 TRACE ("For item %d, flags %d, state %d\n",
2705 expand, flag, wineItem->state);
2707 TRACE("For (%s) item:%d, flags %x, state:%d\n",
2708 wineItem->pszText, flag, expand, wineItem->state);
2710 if (wineItem->cChildren==I_CHILDRENCALLBACK) {
2711 FIXME("we don't handle I_CHILDRENCALLBACK yet\n");
2715 if (flag == TVE_TOGGLE) { /* FIXME: check exact behaviour here */
2716 flag &= ~TVE_TOGGLE; /* ie: bitwise ops or 'case' ops */
2717 if (wineItem->state & TVIS_EXPANDED)
2718 flag |= TVE_COLLAPSE;
2725 case TVE_COLLAPSERESET:
2726 TRACE(" case TVE_COLLAPSERESET\n");
2727 if (!wineItem->state & TVIS_EXPANDED)
2730 wineItem->state &= ~(TVIS_EXPANDEDONCE | TVIS_EXPANDED);
2731 TREEVIEW_RemoveAllChildren (hwnd, wineItem);
2735 TRACE(" case TVE_COLLAPSE\n");
2736 if (!wineItem->state & TVIS_EXPANDED)
2739 wineItem->state &= ~TVIS_EXPANDED;
2743 TRACE(" case TVE_EXPAND\n");
2744 if (wineItem->state & TVIS_EXPANDED)
2747 TRACE(" is not expanded...\n");
2749 if (!(wineItem->state & TVIS_EXPANDEDONCE))
2751 TRACE(" and has never been expanded...\n");
2752 wineItem->state |= TVIS_EXPANDED;
2754 /* this item has never been expanded */
2755 if (TREEVIEW_SendTreeviewNotify (
2762 TRACE(" TVN_ITEMEXPANDING returned TRUE, exiting...\n");
2767 * Since the TVN_ITEMEXPANDING message may has caused the parent to
2768 * insert new items which in turn may have cause items placeholder
2769 * reallocation, I reassign the current item pointer so we have
2770 * something valid to work with...
2771 * However, this should not be necessary,
2772 * investigation required in TREEVIEW_InsertItemA
2774 wineItem = TREEVIEW_ValidItem (infoPtr, (HTREEITEM)expand);
2778 "Catastropic situation, cannot retreive item #%d\n",
2783 wineItem->state |= TVIS_EXPANDEDONCE;
2784 TRACE(" TVN_ITEMEXPANDING sent...\n");
2786 TREEVIEW_SendTreeviewNotify (
2793 TRACE(" TVN_ITEMEXPANDED sent...\n");
2798 /* this item has already been expanded */
2799 wineItem->state |= TVIS_EXPANDED;
2803 case TVE_EXPANDPARTIAL:
2804 TRACE(" case TVE_EXPANDPARTIAL\n");
2805 FIXME("TVE_EXPANDPARTIAL not implemented\n");
2806 wineItem->state ^=TVIS_EXPANDED;
2807 wineItem->state |=TVIS_EXPANDEDONCE;
2811 TRACE("Exiting, Item %d state is now %d...\n",
2815 TREEVIEW_QueueRefresh (hwnd);
2821 static TREEVIEW_ITEM *
2822 TREEVIEW_HitTestPoint (HWND hwnd, POINT pt)
2824 TREEVIEW_INFO *infoPtr = TREEVIEW_GetInfoPtr(hwnd);
2825 TREEVIEW_ITEM *wineItem;
2828 GetClientRect (hwnd, &rect);
2830 if (!infoPtr->firstVisible) return NULL;
2832 wineItem=&infoPtr->items [(INT)infoPtr->firstVisible];
2834 while ((wineItem!=NULL) && (pt.y > wineItem->rect.bottom))
2835 wineItem=TREEVIEW_GetNextListItem (infoPtr,wineItem);
2847 TREEVIEW_HitTest (HWND hwnd, LPARAM lParam)
2849 LPTVHITTESTINFO lpht=(LPTVHITTESTINFO) lParam;
2850 TREEVIEW_ITEM *wineItem;
2854 GetClientRect (hwnd, &rect);
2858 if (x < rect.left) status|=TVHT_TOLEFT;
2859 if (x > rect.right) status|=TVHT_TORIGHT;
2860 if (y < rect.top ) status|=TVHT_ABOVE;
2861 if (y > rect.bottom) status|=TVHT_BELOW;
2868 wineItem=TREEVIEW_HitTestPoint (hwnd, lpht->pt);
2870 lpht->flags=TVHT_NOWHERE;
2876 if (x < wineItem->expandBox.left) {
2877 lpht->flags |= TVHT_ONITEMINDENT;
2880 if ( PtInRect ( &wineItem->expandBox, lpht->pt)) {
2881 lpht->flags |= TVHT_ONITEMBUTTON;
2884 if ( PtInRect ( &wineItem->bitmap, lpht->pt)) {
2885 lpht->flags |= TVHT_ONITEMICON;
2888 if ( PtInRect ( &wineItem->statebitmap, lpht->pt)) {
2889 lpht->flags |= TVHT_ONITEMSTATEICON;
2892 if ( PtInRect ( &wineItem->text, lpht->pt)) {
2893 lpht->flags |= TVHT_ONITEMLABEL;
2897 lpht->flags|=TVHT_ONITEMRIGHT;
2901 lpht->hItem=wineItem->hItem;
2902 TRACE ("(%ld,%ld):result %x\n",lpht->pt.x,lpht->pt.y,lpht->flags);
2904 return (LRESULT) wineItem->hItem;
2908 TREEVIEW_EndEditLabelNow (HWND hwnd, WPARAM wParam, LPARAM lParam)
2910 TREEVIEW_INFO *infoPtr = TREEVIEW_GetInfoPtr(hwnd);
2911 TREEVIEW_ITEM *editedItem = TREEVIEW_ValidItem (infoPtr, infoPtr->editItem);
2912 BOOL bRevert = (BOOL)wParam;
2913 BOOL bReturn = ! bRevert;
2915 if ( ! (BOOL)wParam ) /* wParam is set to true to cancel the edition */
2917 if ( TREEVIEW_SendDispInfoNotify( /* return true to cancel edition */
2928 if (bRevert == FALSE) /* Apply the changes */
2931 int iLength = GetWindowTextA(infoPtr->hwndEdit, tmpText, 1023);
2936 ERR("Problem retreiving new item label.");
2938 else if (iLength >= 1023)
2941 "Insuficient space to retrieve new item label, new label ignored.");
2945 if (strcmp( tmpText, editedItem->pszText ) == 0)
2946 /* Do nothing if the label has not changed */
2950 LPSTR tmpLabel = COMCTL32_Alloc( iLength+1 );
2952 if ( tmpLabel == NULL )
2954 "OutOfMemory, cannot allocate space for label");
2957 COMCTL32_Free(editedItem->pszText);
2958 editedItem->pszText = tmpLabel;
2959 lstrcpyA( editedItem->pszText, tmpText);
2965 ShowWindow(infoPtr->hwndEdit, SW_HIDE);
2966 EnableWindow(infoPtr->hwndEdit, FALSE);
2967 infoPtr->editItem = 0;
2976 TREEVIEW_LButtonDoubleClick (HWND hwnd, WPARAM wParam, LPARAM lParam)
2978 TREEVIEW_ITEM *wineItem;
2982 pt.x = (INT)LOWORD(lParam);
2983 pt.y = (INT)HIWORD(lParam);
2986 wineItem=TREEVIEW_HitTestPoint (hwnd, pt);
2987 if (!wineItem) return 0;
2988 TRACE("item %d \n",(INT)wineItem->hItem);
2990 if (TREEVIEW_SendSimpleNotify (hwnd, NM_DBLCLK)!=TRUE) { /* FIXME!*/
2991 TREEVIEW_Expand (hwnd, (WPARAM) TVE_TOGGLE, (LPARAM) wineItem->hItem);
2998 TREEVIEW_LButtonDown (HWND hwnd, WPARAM wParam, LPARAM lParam)
3000 TREEVIEW_INFO *infoPtr = TREEVIEW_GetInfoPtr(hwnd);
3004 ht.pt.x = (INT)LOWORD(lParam);
3005 ht.pt.y = (INT)HIWORD(lParam);
3008 iItem=TREEVIEW_HitTest (hwnd, (LPARAM) &ht);
3009 TRACE("item %d \n",iItem);
3011 if (ht.flags & TVHT_ONITEMBUTTON) {
3012 TREEVIEW_Expand (hwnd, (WPARAM) TVE_TOGGLE, (LPARAM) iItem);
3016 infoPtr->uInternalStatus|=TV_LDRAG;
3023 TREEVIEW_LButtonUp (HWND hwnd, WPARAM wParam, LPARAM lParam)
3025 TREEVIEW_INFO *infoPtr = TREEVIEW_GetInfoPtr(hwnd);
3027 TREEVIEW_ITEM *wineItem;
3030 ht.pt.x = (INT)LOWORD(lParam);
3031 ht.pt.y = (INT)HIWORD(lParam);
3035 /* Return true to cancel default behaviour */
3036 if ( TREEVIEW_SendSimpleNotify (hwnd, NM_CLICK) )
3040 iItem = TREEVIEW_HitTest (hwnd, (LPARAM) &ht);
3041 TRACE ("%d\n",iItem);
3045 wineItem = TREEVIEW_ValidItem(infoPtr, (HTREEITEM)iItem);
3047 infoPtr->uInternalStatus &= ~(TV_LDRAG | TV_LDRAGGING);
3050 * If the style allow editing and the node is already selected
3051 * and the click occured on the item label...
3053 if ( ( GetWindowLongA( hwnd, GWL_STYLE) & TVS_EDITLABELS ) &&
3054 ( wineItem->state & TVIS_SELECTED ) &&
3055 ( ht.flags & TVHT_ONITEMLABEL ))
3057 if ( infoPtr->editItem == 0 ) /* If we are not curently editing */
3059 if ( TREEVIEW_SendDispInfoNotify( /* Return true to cancel edition */
3068 TRACE("Edit started for %s.\n", wineItem->pszText);
3069 infoPtr->editItem = wineItem->hItem;
3074 wineItem->text.left - 2,
3075 wineItem->text.top - 1,
3076 wineItem->text.right - wineItem->text.left + 20 ,
3077 wineItem->text.bottom - wineItem->text.top + 3,
3080 SetWindowTextA( infoPtr->hwndEdit, wineItem->pszText );
3081 SendMessageA ( infoPtr->hwndEdit, EM_SETSEL, 0, -1 );
3082 SetFocus ( infoPtr->hwndEdit);
3083 ShowWindow ( infoPtr->hwndEdit, SW_SHOW);
3086 else if ( infoPtr->editItem != 0 ) /* If we are curently editing */
3088 TREEVIEW_EndEditLabelNow(hwnd, (WPARAM)FALSE, 0);
3090 else if ( ht.flags & (TVHT_ONITEMLABEL | TVHT_ONITEMICON))
3092 TREEVIEW_DoSelectItem ( hwnd, TVGN_CARET, (HTREEITEM)iItem, TVC_BYMOUSE);
3095 if (ht.flags & TVHT_ONITEMSTATEICON) {
3096 DWORD dwStyle = GetWindowLongA (hwnd, GWL_STYLE);
3099 if (dwStyle & TVS_CHECKBOXES) { /* TVS_CHECKBOXES requires _us_ */
3100 int state; /* to toggle the current state */
3101 state=1-(wineItem->state>>12);
3102 TRACE ("state:%x\n", state);
3103 wineItem->state&= ~TVIS_STATEIMAGEMASK;
3104 wineItem->state|=state<<12;
3105 TRACE ("state:%x\n", wineItem->state);
3106 TREEVIEW_QueueRefresh (hwnd);
3114 TREEVIEW_RButtonDown (HWND hwnd, WPARAM wParam, LPARAM lParam)
3116 TREEVIEW_INFO *infoPtr = TREEVIEW_GetInfoPtr(hwnd);
3119 infoPtr->uInternalStatus|=TV_RDRAG;
3124 TREEVIEW_RButtonUp (HWND hwnd, WPARAM wParam, LPARAM lParam)
3126 TREEVIEW_INFO *infoPtr = TREEVIEW_GetInfoPtr(hwnd);
3129 if (TREEVIEW_SendSimpleNotify (hwnd, NM_RCLICK)) return 0;
3130 infoPtr->uInternalStatus&= ~(TV_RDRAG | TV_RDRAGGING);
3136 TREEVIEW_MouseMove (HWND hwnd, WPARAM wParam, LPARAM lParam)
3138 TREEVIEW_INFO *infoPtr = TREEVIEW_GetInfoPtr(hwnd);
3139 TREEVIEW_ITEM *hotItem;
3142 pt.x=(INT) LOWORD (lParam);
3143 pt.y=(INT) HIWORD (lParam);
3144 hotItem=TREEVIEW_HitTestPoint (hwnd, pt);
3145 if (!hotItem) return 0;
3146 infoPtr->focusItem=hotItem->hItem;
3148 if ( GetWindowLongA( hwnd, GWL_STYLE) & TVS_DISABLEDRAGDROP) return 0;
3150 if (infoPtr->uInternalStatus & TV_LDRAG) {
3151 TREEVIEW_SendTreeviewDnDNotify (hwnd, TVN_BEGINDRAG, hotItem->hItem, pt);
3152 infoPtr->uInternalStatus &= ~TV_LDRAG;
3153 infoPtr->uInternalStatus |= TV_LDRAGGING;
3154 infoPtr->dropItem=hotItem->hItem;
3158 if (infoPtr->uInternalStatus & TV_RDRAG) {
3159 TREEVIEW_SendTreeviewDnDNotify (hwnd, TVN_BEGINRDRAG, hotItem->hItem, pt);
3160 infoPtr->uInternalStatus &= ~TV_RDRAG;
3161 infoPtr->uInternalStatus |= TV_RDRAGGING;
3162 infoPtr->dropItem=hotItem->hItem;
3171 TREEVIEW_CreateDragImage (HWND hwnd, WPARAM wParam, LPARAM lParam)
3173 TREEVIEW_INFO *infoPtr = TREEVIEW_GetInfoPtr(hwnd);
3174 TREEVIEW_ITEM *dragItem;
3178 HBITMAP hbmp,hOldbmp;
3185 if (!(infoPtr->himlNormal)) return 0;
3186 dragItem=TREEVIEW_ValidItem (infoPtr, (HTREEITEM) lParam);
3188 if (!dragItem) return 0;
3190 if (dragItem->pszText==LPSTR_TEXTCALLBACKA) {
3191 TREEVIEW_SendDispInfoNotify (hwnd, dragItem, TVN_GETDISPINFO, TVIF_TEXT);
3193 itemtxt=dragItem->pszText;
3195 hwtop=GetDesktopWindow ();
3196 htopdc= GetDC (hwtop);
3197 hdc=CreateCompatibleDC (htopdc);
3199 hOldFont=SelectObject (hdc, infoPtr->hFont);
3200 GetTextExtentPoint32A (hdc, itemtxt, lstrlenA (itemtxt), &size);
3201 TRACE("%d %d %s %d\n",size.cx,size.cy,itemtxt,lstrlenA(itemtxt));
3202 hbmp=CreateCompatibleBitmap (htopdc, size.cx, size.cy);
3203 hOldbmp=SelectObject (hdc, hbmp);
3205 ImageList_GetIconSize (infoPtr->himlNormal, &cx, &cy);
3207 if (cy>size.cy) size.cy=cy;
3209 infoPtr->dragList=ImageList_Create (size.cx, size.cy, ILC_COLOR, 10, 10);
3210 ImageList_Draw (infoPtr->himlNormal, dragItem->iImage, hdc, 0, 0, ILD_NORMAL);
3213 ImageList_GetImageInfo (infoPtr->himlNormal, dragItem->hItem, &iminfo);
3214 ImageList_AddMasked (infoPtr->dragList, iminfo.hbmImage, CLR_DEFAULT);
3217 /* draw item text */
3219 SetRect (&rc, cx, 0, size.cx,size.cy);
3220 DrawTextA (hdc, itemtxt, lstrlenA (itemtxt), &rc, DT_LEFT);
3221 SelectObject (hdc, hOldFont);
3222 SelectObject (hdc, hOldbmp);
3224 ImageList_Add (infoPtr->dragList, hbmp, 0);
3227 DeleteObject (hbmp);
3228 ReleaseDC (hwtop, htopdc);
3230 return (LRESULT)infoPtr->dragList;
3235 TREEVIEW_DoSelectItem (HWND hwnd, INT action, HTREEITEM newSelect, INT cause)
3238 TREEVIEW_INFO *infoPtr = TREEVIEW_GetInfoPtr(hwnd);
3239 TREEVIEW_ITEM *prevItem,*wineItem;
3242 wineItem = TREEVIEW_ValidItem (infoPtr, (HTREEITEM)newSelect);
3244 TRACE("Entering item %d, flag %x, cause %x, state %d\n",
3250 if ( (wineItem) && (wineItem->parent))
3253 * If the item has a collapse parent expand the parent so he
3254 * can expose the item
3256 TREEVIEW_ITEM *parentItem = TREEVIEW_ValidItem (infoPtr, wineItem->parent);
3257 if ( !(parentItem->state & TVIS_EXPANDED))
3258 TREEVIEW_Expand (hwnd, TVE_EXPAND, (LPARAM) wineItem->parent);
3264 prevSelect=(INT)infoPtr->selectedItem;
3266 if ((HTREEITEM)prevSelect==newSelect)
3269 prevItem= TREEVIEW_ValidItem (infoPtr, (HTREEITEM)prevSelect);
3272 if (TREEVIEW_SendTreeviewNotify(
3276 (HTREEITEM)prevSelect,
3277 (HTREEITEM)newSelect))
3278 return FALSE; /* FIXME: OK? */
3281 prevItem->state &= ~TVIS_SELECTED;
3283 wineItem->state |= TVIS_SELECTED;
3285 infoPtr->selectedItem=(HTREEITEM)newSelect;
3287 TREEVIEW_SendTreeviewNotify(
3291 (HTREEITEM)prevSelect,
3292 (HTREEITEM)newSelect);
3296 case TVGN_DROPHILITE:
3297 prevItem= TREEVIEW_ValidItem (infoPtr, infoPtr->dropItem);
3300 prevItem->state &= ~TVIS_DROPHILITED;
3302 infoPtr->dropItem=(HTREEITEM)newSelect;
3305 wineItem->state |=TVIS_DROPHILITED;
3309 case TVGN_FIRSTVISIBLE:
3310 FIXME("FIRSTVISIBLE not implemented\n");
3314 TREEVIEW_QueueRefresh (hwnd);
3316 TRACE("Leaving state %d\n", wineItem->state);
3320 /* FIXME: handle NM_KILLFocus etc */
3322 TREEVIEW_SelectItem (HWND hwnd, WPARAM wParam, LPARAM lParam)
3325 return TREEVIEW_DoSelectItem (hwnd, wParam, (HTREEITEM) lParam, TVC_UNKNOWN);
3332 TREEVIEW_GetFont (HWND hwnd, WPARAM wParam, LPARAM lParam)
3335 TREEVIEW_INFO *infoPtr = TREEVIEW_GetInfoPtr(hwnd);
3337 TRACE("%x\n",infoPtr->hFont);
3338 return infoPtr->hFont;
3342 TREEVIEW_SetFont (HWND hwnd, WPARAM wParam, LPARAM lParam)
3345 TREEVIEW_INFO *infoPtr = TREEVIEW_GetInfoPtr(hwnd);
3348 HFONT hFont, hOldFont;
3352 TRACE("%x %lx\n",wParam, lParam);
3354 infoPtr->hFont = (HFONT)wParam;
3356 hFont = infoPtr->hFont ? infoPtr->hFont : GetStockObject (SYSTEM_FONT);
3358 GetObjectA (infoPtr->hFont, sizeof (LOGFONTA), &logFont);
3359 logFont.lfWeight=FW_BOLD;
3360 infoPtr->hBoldFont = CreateFontIndirectA (&logFont);
3363 hOldFont = SelectObject (hdc, hFont);
3364 GetTextMetricsA (hdc, &tm);
3365 height= tm.tmHeight + tm.tmExternalLeading;
3366 if (height>infoPtr->uRealItemHeight)
3367 infoPtr->uRealItemHeight=height;
3368 SelectObject (hdc, hOldFont);
3372 TREEVIEW_QueueRefresh (hwnd);
3380 TREEVIEW_VScroll (HWND hwnd, WPARAM wParam, LPARAM lParam)
3383 TREEVIEW_INFO *infoPtr = TREEVIEW_GetInfoPtr(hwnd);
3386 TRACE("wp %x, lp %lx\n", wParam, lParam);
3387 if (!infoPtr->uInternalStatus & TV_VSCROLL) return FALSE;
3389 switch (LOWORD (wParam)) {
3391 if (!infoPtr->cy) return FALSE;
3392 infoPtr->cy -= infoPtr->uRealItemHeight;
3393 if (infoPtr->cy < 0) infoPtr->cy=0;
3396 maxHeight=infoPtr->uTotalHeight-infoPtr->uVisibleHeight;
3397 if (infoPtr->cy == maxHeight) return FALSE;
3398 infoPtr->cy += infoPtr->uRealItemHeight;
3399 if (infoPtr->cy > maxHeight)
3400 infoPtr->cy = maxHeight;
3403 if (!infoPtr->cy) return FALSE;
3404 infoPtr->cy -= infoPtr->uVisibleHeight;
3405 if (infoPtr->cy < 0) infoPtr->cy=0;
3408 maxHeight=infoPtr->uTotalHeight-infoPtr->uVisibleHeight;
3409 if (infoPtr->cy == maxHeight) return FALSE;
3410 infoPtr->cy += infoPtr->uVisibleHeight;
3411 if (infoPtr->cy > maxHeight)
3412 infoPtr->cy = maxHeight;
3415 infoPtr->cy = HIWORD (wParam);
3420 TREEVIEW_QueueRefresh (hwnd);
3425 TREEVIEW_HScroll (HWND hwnd, WPARAM wParam, LPARAM lParam)
3427 TREEVIEW_INFO *infoPtr = TREEVIEW_GetInfoPtr(hwnd);
3430 TRACE("wp %lx, lp %x\n", lParam, wParam);
3432 if (!infoPtr->uInternalStatus & TV_HSCROLL) return FALSE;
3434 switch (LOWORD (wParam)) {
3436 if (!infoPtr->cx) return FALSE;
3437 infoPtr->cx -= infoPtr->uRealItemHeight;
3438 if (infoPtr->cx < 0) infoPtr->cx=0;
3441 maxWidth=infoPtr->uTotalWidth-infoPtr->uVisibleWidth;
3442 if (infoPtr->cx == maxWidth) return FALSE;
3443 infoPtr->cx += infoPtr->uRealItemHeight; /*FIXME */
3444 if (infoPtr->cx > maxWidth)
3445 infoPtr->cx = maxWidth;
3448 if (!infoPtr->cx) return FALSE;
3449 infoPtr->cx -= infoPtr->uVisibleWidth;
3450 if (infoPtr->cx < 0) infoPtr->cx=0;
3453 maxWidth=infoPtr->uTotalWidth-infoPtr->uVisibleWidth;
3454 if (infoPtr->cx == maxWidth) return FALSE;
3455 infoPtr->cx += infoPtr->uVisibleWidth;
3456 if (infoPtr->cx > maxWidth)
3457 infoPtr->cx = maxWidth;
3460 infoPtr->cx = HIWORD (wParam);
3465 TREEVIEW_QueueRefresh (hwnd);
3471 TREEVIEW_KeyDown (HWND hwnd, WPARAM wParam, LPARAM lParam)
3473 TREEVIEW_INFO *infoPtr = TREEVIEW_GetInfoPtr(hwnd);
3474 HTREEITEM hNewSelection = 0;
3475 INT scrollNeeds = -1;
3476 INT cyChangeNeeds = -1;
3477 INT prevSelect = (INT)infoPtr->selectedItem;
3479 TREEVIEW_ITEM *prevItem =
3480 (prevSelect != 0 ) ?
3481 TREEVIEW_ValidItem (infoPtr, (HTREEITEM)prevSelect) :
3484 TREEVIEW_ITEM *newItem = NULL;
3486 TRACE("%x %lx\n",wParam, lParam);
3488 if (prevSelect == 0)
3493 newItem=TREEVIEW_GetPrevListItem (infoPtr, prevItem);
3496 newItem=& infoPtr->items[(INT)infoPtr->TopRootItem];
3498 hNewSelection = newItem->hItem;
3500 if (! newItem->visible)
3501 scrollNeeds = SB_LINEUP;
3505 newItem=TREEVIEW_GetNextListItem (infoPtr, prevItem);
3510 hNewSelection = newItem->hItem;
3512 if (! newItem->visible)
3513 scrollNeeds = SB_LINEDOWN;
3518 newItem = &infoPtr->items[(INT)infoPtr->TopRootItem];
3519 hNewSelection = newItem->hItem;
3524 newItem = &infoPtr->items[(INT)infoPtr->TopRootItem];
3525 newItem = TREEVIEW_GetLastListItem (infoPtr, newItem);
3526 hNewSelection = newItem->hItem;
3528 if (! newItem->visible)
3529 cyChangeNeeds = infoPtr->uTotalHeight-infoPtr->uVisibleHeight;
3534 if ( (prevItem->cChildren > 0) && (prevItem->state & TVIS_EXPANDED) )
3536 TREEVIEW_Expand(hwnd, TVE_COLLAPSE, prevSelect );
3538 else if ((INT)prevItem->parent)
3540 newItem = (& infoPtr->items[(INT)prevItem->parent]);
3541 if (! newItem->visible)
3542 /* FIXME find a way to make this item the first visible... */
3545 hNewSelection = newItem->hItem;
3551 if ( ( prevItem->cChildren > 0) ||
3552 ( prevItem->cChildren == I_CHILDRENCALLBACK))
3554 if (! (prevItem->state & TVIS_EXPANDED))
3555 TREEVIEW_Expand(hwnd, TVE_EXPAND, prevSelect );
3558 newItem = (& infoPtr->items[(INT)prevItem->firstChild]);
3559 hNewSelection = newItem->hItem;
3566 if (! (prevItem->state & TVIS_EXPANDED))
3567 TREEVIEW_Expand(hwnd, TVE_EXPAND, prevSelect );
3571 if (prevItem->state & TVIS_EXPANDED)
3572 TREEVIEW_Expand(hwnd, TVE_COLLAPSE, prevSelect );
3577 newItem=TREEVIEW_GetListItem(
3580 -1*(TREEVIEW_GetVisibleCount(hwnd,0,0)-3));
3584 hNewSelection = newItem->hItem;
3586 if (! newItem->visible)
3587 scrollNeeds = SB_PAGEUP;
3592 newItem=TREEVIEW_GetListItem(
3595 TREEVIEW_GetVisibleCount(hwnd,0,0)-3);
3600 hNewSelection = newItem->hItem;
3602 if (! newItem->visible)
3603 scrollNeeds = SB_PAGEDOWN;
3612 FIXME("%x not implemented\n", wParam);
3619 This works but does not send notification...
3621 prevItem->state &= ~TVIS_SELECTED;
3622 newItem->state |= TVIS_SELECTED;
3623 infoPtr->selectedItem = hNewSelection;
3624 TREEVIEW_QueueRefresh (hwnd);
3627 if ( TREEVIEW_DoSelectItem(
3630 (HTREEITEM)hNewSelection,
3633 /* If selection change is allowed for the new item, perform scrolling */
3634 if (scrollNeeds != -1)
3635 TREEVIEW_VScroll(hwnd, scrollNeeds, 0);
3637 if (cyChangeNeeds != -1)
3638 infoPtr->cy = cyChangeNeeds;
3640 /* FIXME: Something happen in the load the in the two weeks before
3641 april 1st 1999 which makes this SetFocus mandatory otherwise, the focus
3642 is lost... However the SetFocus should not be required...*/
3653 TREEVIEW_GetScrollTime (HWND hwnd)
3655 TREEVIEW_INFO *infoPtr = TREEVIEW_GetInfoPtr(hwnd);
3657 return infoPtr->uScrollTime;
3662 TREEVIEW_SetScrollTime (HWND hwnd, UINT uScrollTime)
3664 TREEVIEW_INFO *infoPtr = TREEVIEW_GetInfoPtr(hwnd);
3665 UINT uOldScrollTime = infoPtr->uScrollTime;
3667 infoPtr->uScrollTime = min (uScrollTime, 100);
3669 return uOldScrollTime;
3673 static LRESULT WINAPI
3674 TREEVIEW_WindowProc (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
3676 if (uMsg==WM_CREATE)
3677 return TREEVIEW_Create (hwnd, wParam, lParam);
3679 if (!TREEVIEW_GetInfoPtr(hwnd))
3680 return DefWindowProcA (hwnd, uMsg, wParam, lParam);
3684 case TVM_INSERTITEMA:
3685 return TREEVIEW_InsertItemA (hwnd, wParam, lParam);
3687 case TVM_INSERTITEMW:
3688 return TREEVIEW_InsertItemW(hwnd,wParam,lParam);;
3690 case TVM_DELETEITEM:
3691 return TREEVIEW_DeleteItem (hwnd, wParam, lParam);
3694 return TREEVIEW_Expand (hwnd, wParam, lParam);
3696 case TVM_GETITEMRECT:
3697 return TREEVIEW_GetItemRect (hwnd, wParam, lParam);
3700 return TREEVIEW_GetCount (hwnd, wParam, lParam);
3703 return TREEVIEW_GetIndent (hwnd);
3706 return TREEVIEW_SetIndent (hwnd, wParam);
3708 case TVM_GETIMAGELIST:
3709 return TREEVIEW_GetImageList (hwnd, wParam, lParam);
3711 case TVM_SETIMAGELIST:
3712 return TREEVIEW_SetImageList (hwnd, wParam, lParam);
3714 case TVM_GETNEXTITEM:
3715 return TREEVIEW_GetNextItem (hwnd, wParam, lParam);
3717 case TVM_SELECTITEM:
3718 return TREEVIEW_SelectItem (hwnd, wParam, lParam);
3721 return TREEVIEW_GetItemA (hwnd, wParam, lParam);
3724 FIXME("Unimplemented msg TVM_GETITEMW\n");
3728 return TREEVIEW_SetItemA (hwnd, wParam, lParam);
3731 FIXME("Unimplemented msg TVM_SETITEMW\n");
3734 case TVM_EDITLABELA:
3735 FIXME("Unimplemented msg TVM_EDITLABELA \n");
3738 case TVM_EDITLABELW:
3739 FIXME("Unimplemented msg TVM_EDITLABELW \n");
3742 case TVM_GETEDITCONTROL:
3743 return TREEVIEW_GetEditControl (hwnd);
3745 case TVM_GETVISIBLECOUNT:
3746 return TREEVIEW_GetVisibleCount (hwnd, wParam, lParam);
3749 return TREEVIEW_HitTest (hwnd, lParam);
3751 case TVM_CREATEDRAGIMAGE:
3752 return TREEVIEW_CreateDragImage (hwnd, wParam, lParam);
3754 case TVM_SORTCHILDREN:
3755 return TREEVIEW_SortChildren (hwnd, wParam, lParam);
3757 case TVM_ENSUREVISIBLE:
3758 FIXME("Unimplemented msg TVM_ENSUREVISIBLE\n");
3761 case TVM_SORTCHILDRENCB:
3762 return TREEVIEW_SortChildrenCB(hwnd, wParam, lParam);
3764 case TVM_ENDEDITLABELNOW:
3765 return TREEVIEW_EndEditLabelNow (hwnd, wParam, lParam);
3767 case TVM_GETISEARCHSTRINGA:
3768 FIXME("Unimplemented msg TVM_GETISEARCHSTRINGA\n");
3771 case TVM_GETISEARCHSTRINGW:
3772 FIXME("Unimplemented msg TVM_GETISEARCHSTRINGW\n");
3775 case TVM_GETTOOLTIPS:
3776 return TREEVIEW_GetToolTips (hwnd);
3778 case TVM_SETTOOLTIPS:
3779 return TREEVIEW_SetToolTips (hwnd, wParam);
3781 case TVM_SETINSERTMARK:
3782 return TREEVIEW_SetInsertMark (hwnd,wParam, lParam);
3784 case TVM_SETITEMHEIGHT:
3785 return TREEVIEW_SetItemHeight (hwnd, wParam);
3787 case TVM_GETITEMHEIGHT:
3788 return TREEVIEW_GetItemHeight (hwnd);
3790 case TVM_SETBKCOLOR:
3791 return TREEVIEW_SetBkColor (hwnd, wParam, lParam);
3793 case TVM_SETTEXTCOLOR:
3794 return TREEVIEW_SetTextColor (hwnd, wParam, lParam);
3796 case TVM_GETBKCOLOR:
3797 return TREEVIEW_GetBkColor (hwnd);
3799 case TVM_GETTEXTCOLOR:
3800 return TREEVIEW_GetTextColor (hwnd);
3802 case TVM_SETSCROLLTIME:
3803 return TREEVIEW_SetScrollTime (hwnd, (UINT)wParam);
3805 case TVM_GETSCROLLTIME:
3806 return TREEVIEW_GetScrollTime (hwnd);
3808 case TVM_GETITEMSTATE:
3809 return TREEVIEW_GetItemState (hwnd,wParam, lParam);
3811 case TVM_GETLINECOLOR:
3812 return TREEVIEW_GetLineColor (hwnd,wParam, lParam);
3814 case TVM_SETLINECOLOR:
3815 return TREEVIEW_SetLineColor (hwnd,wParam, lParam);
3817 case TVM_SETINSERTMARKCOLOR:
3818 return TREEVIEW_SetInsertMarkColor (hwnd,wParam, lParam);
3820 case TVM_GETINSERTMARKCOLOR:
3821 return TREEVIEW_GetInsertMarkColor (hwnd,wParam, lParam);
3823 case TVM_SETUNICODEFORMAT:
3824 FIXME("Unimplemented msg TVM_SETUNICODEFORMAT\n");
3827 case TVM_GETUNICODEFORMAT:
3828 FIXME("Unimplemented msg TVM_GETUNICODEFORMAT\n");
3832 return TREEVIEW_Command (hwnd, wParam, lParam);
3835 return TREEVIEW_Destroy (hwnd);
3837 /* case WM_ENABLE: */
3840 return TREEVIEW_EraseBackground (hwnd, wParam, lParam);
3843 return DLGC_WANTARROWS | DLGC_WANTCHARS;
3846 return TREEVIEW_Paint (hwnd, wParam, lParam);
3849 return TREEVIEW_GetFont (hwnd, wParam, lParam);
3852 return TREEVIEW_SetFont (hwnd, wParam, lParam);
3855 return TREEVIEW_KeyDown (hwnd, wParam, lParam);
3858 return TREEVIEW_SetFocus (hwnd, wParam, lParam);
3861 return TREEVIEW_KillFocus (hwnd, wParam, lParam);
3863 case WM_LBUTTONDOWN:
3864 return TREEVIEW_LButtonDown (hwnd, wParam, lParam);
3867 return TREEVIEW_LButtonUp (hwnd, wParam, lParam);
3869 case WM_LBUTTONDBLCLK:
3870 return TREEVIEW_LButtonDoubleClick (hwnd, wParam, lParam);
3872 case WM_RBUTTONDOWN:
3873 return TREEVIEW_RButtonDown (hwnd, wParam, lParam);
3876 return TREEVIEW_RButtonUp (hwnd, wParam, lParam);
3879 return TREEVIEW_MouseMove (hwnd, wParam, lParam);
3881 case WM_STYLECHANGED:
3882 return TREEVIEW_StyleChanged (hwnd, wParam, lParam);
3884 /* case WM_SYSCOLORCHANGE: */
3885 /* case WM_SETREDRAW: */
3888 return TREEVIEW_HandleTimer (hwnd, wParam, lParam);
3891 return TREEVIEW_Size (hwnd, wParam,lParam);
3894 return TREEVIEW_HScroll (hwnd, wParam, lParam);
3896 return TREEVIEW_VScroll (hwnd, wParam, lParam);
3899 TRACE ("drawItem\n");
3900 return DefWindowProcA (hwnd, uMsg, wParam, lParam);
3903 if (uMsg >= WM_USER)
3904 FIXME("Unknown msg %04x wp=%08x lp=%08lx\n",
3905 uMsg, wParam, lParam);
3906 return DefWindowProcA (hwnd, uMsg, wParam, lParam);
3913 TREEVIEW_Register (void)
3919 if (GlobalFindAtomA (WC_TREEVIEWA)) return;
3921 ZeroMemory (&wndClass, sizeof(WNDCLASSA));
3922 wndClass.style = CS_GLOBALCLASS | CS_DBLCLKS;
3923 wndClass.lpfnWndProc = (WNDPROC)TREEVIEW_WindowProc;
3924 wndClass.cbClsExtra = 0;
3925 wndClass.cbWndExtra = sizeof(TREEVIEW_INFO *);
3926 wndClass.hCursor = LoadCursorA (0, IDC_ARROWA);
3927 wndClass.hbrBackground = 0;
3928 wndClass.lpszClassName = WC_TREEVIEWA;
3930 RegisterClassA (&wndClass);
3935 TREEVIEW_Unregister (void)
3937 if (GlobalFindAtomA (WC_TREEVIEWA))
3938 UnregisterClassA (WC_TREEVIEWA, (HINSTANCE)NULL);