*
* Note that TREEVIEW_INFO * and HTREEITEM are the same thing.
*
- * Note2: All items always! have valid (allocated) pszText field.
- * If item's text == LPSTR_TEXTCALLBACKA we allocate buffer
+ * Note2: If item's text == LPSTR_TEXTCALLBACKA we allocate buffer
* of size TEXT_CALLBACK_SIZE in DoSetItem.
* We use callbackMask to keep track of fields to be updated.
*
* TODO:
- * missing notifications: NM_SETCURSOR, TVN_GETINFOTIP, TVN_KEYDOWN,
+ * missing notifications: TVN_GETINFOTIP, TVN_KEYDOWN,
* TVN_SETDISPINFO, TVN_SINGLEEXPAND
*
* missing styles: TVS_FULLROWSELECT, TVS_INFOTIP, TVS_RTLREADING,
#include "wine/unicode.h"
#include "wine/debug.h"
+WINE_DEFAULT_DEBUG_CHANNEL(treeview);
+
/* internal structures */
typedef struct _TREEITEM /* HTREEITEM is a _TREEINFO *. */
HTREEITEM selectedItem; /* handle to selected item or 0 if none */
HTREEITEM hotItem; /* handle currently under cursor, 0 if none */
HTREEITEM focusedItem; /* item that was under the cursor when WM_LBUTTONDOWN was received */
+ HTREEITEM editItem; /* item being edited with builtin edit box */
HTREEITEM firstVisible; /* handle to first visible item */
LONG maxVisibleOrder;
int stateImageWidth;
HDPA items;
- DWORD lastKeyPressTimestamp; /* Added */
- WPARAM charCode; /* Added */
- INT nSearchParamLength; /* Added */
- WCHAR szSearchParam[ MAX_PATH ]; /* Added */
+ DWORD lastKeyPressTimestamp;
+ WPARAM charCode;
+ INT nSearchParamLength;
+ WCHAR szSearchParam[ MAX_PATH ];
} TREEVIEW_INFO;
#define TV_VSCROLL 0x02 /* (horizontal/vertical) */
#define TV_LDRAG 0x04 /* Lbutton pushed to start drag */
#define TV_LDRAGGING 0x08 /* Lbutton pushed, mouse moved. */
-#define TV_RDRAG 0x10 /* dito Rbutton */
+#define TV_RDRAG 0x10 /* ditto Rbutton */
#define TV_RDRAGGING 0x20
/* bitflags for infoPtr->timer */
#define TV_EDIT_TIMER 2
#define TV_EDIT_TIMER_SET 2
-
-VOID TREEVIEW_Register (VOID);
-VOID TREEVIEW_Unregister (VOID);
-
-
-WINE_DEFAULT_DEBUG_CHANNEL(treeview);
-
-
#define TEXT_CALLBACK_SIZE 260
#define TREEVIEW_LEFT_MARGIN 8
#define OVERLAYIMAGEINDEX(x) (((x) >> 8) & 0x0f)
#define ISVISIBLE(x) ((x)->visibleOrder >= 0)
+#define GETLINECOLOR(x) ((x) == CLR_DEFAULT ? comctl32_color.clrGrayText : (x))
+#define GETBKCOLOR(x) ((x) == CLR_NONE ? comctl32_color.clrWindow : (x))
+#define GETTXTCOLOR(x) ((x) == CLR_NONE ? comctl32_color.clrWindowText : (x))
+#define GETINSCOLOR(x) ((x) == CLR_DEFAULT ? comctl32_color.clrBtnText : (x))
static const WCHAR themeClass[] = { 'T','r','e','e','v','i','e','w',0 };
static LRESULT TREEVIEW_EndEditLabelNow(TREEVIEW_INFO *infoPtr, BOOL bCancel);
static VOID TREEVIEW_UpdateScrollBars(TREEVIEW_INFO *infoPtr);
static LRESULT TREEVIEW_HScroll(TREEVIEW_INFO *, WPARAM);
-static INT TREEVIEW_NotifyFormat (TREEVIEW_INFO *infoPtr, HWND wParam, UINT lParam);
-
/* Random Utilities *****************************************************/
static inline int
TREEVIEW_GetItemIndex(const TREEVIEW_INFO *infoPtr, HTREEITEM handle)
{
- assert(infoPtr != NULL);
-
return DPA_GetPtrIndex(infoPtr->items, handle);
}
static TREEVIEW_ITEM *
TREEVIEW_GetNextListItem(const TREEVIEW_INFO *infoPtr, const TREEVIEW_ITEM *tvItem)
{
- assert(tvItem != NULL);
-
/*
* If this item has children and is expanded, return the first child
*/
nmhdr.idFrom = GetWindowLongPtrW(hwnd, GWLP_ID);
nmhdr.code = get_notifycode(infoPtr, code);
- return (BOOL)TREEVIEW_SendRealNotify(infoPtr,
- (WPARAM)nmhdr.idFrom, (LPARAM)&nmhdr);
+ return (BOOL)TREEVIEW_SendRealNotify(infoPtr, nmhdr.idFrom, (LPARAM)&nmhdr);
}
static VOID
nmhdr.ptDrag.x = 0;
nmhdr.ptDrag.y = 0;
- ret = (BOOL)TREEVIEW_SendRealNotify(infoPtr,
- (WPARAM)nmhdr.hdr.idFrom,
- (LPARAM)&nmhdr);
+ ret = (BOOL)TREEVIEW_SendRealNotify(infoPtr, nmhdr.hdr.idFrom, (LPARAM)&nmhdr);
if (!infoPtr->bNtfUnicode)
{
Free(nmhdr.itemOld.pszText);
nmhdr.ptDrag.x = pt.x;
nmhdr.ptDrag.y = pt.y;
- return (BOOL)TREEVIEW_SendRealNotify(infoPtr,
- (WPARAM)nmhdr.hdr.idFrom,
- (LPARAM)&nmhdr);
+ return (BOOL)TREEVIEW_SendRealNotify(infoPtr, nmhdr.hdr.idFrom, (LPARAM)&nmhdr);
}
nmcdhdr.clrTextBk = infoPtr->clrBk;
nmcdhdr.iLevel = 0;
- return (BOOL)TREEVIEW_SendRealNotify(infoPtr,
- (WPARAM)nmcd->hdr.idFrom,
- (LPARAM)&nmcdhdr);
+ return (BOOL)TREEVIEW_SendRealNotify(infoPtr, nmcd->hdr.idFrom, (LPARAM)&nmcdhdr);
}
nmcd->dwDrawStage, nmcd->hdc, nmcd->dwItemSpec,
nmcd->uItemState, nmcd->lItemlParam);
- retval = TREEVIEW_SendRealNotify(infoPtr,
- (WPARAM)nmcd->hdr.idFrom,
- (LPARAM)nmcdhdr);
+ retval = TREEVIEW_SendRealNotify(infoPtr, nmcd->hdr.idFrom, (LPARAM)nmcdhdr);
- return (BOOL)retval;
+ return retval;
}
static BOOL
TREEVIEW_UpdateDispInfo(const TREEVIEW_INFO *infoPtr, TREEVIEW_ITEM *wineItem,
UINT mask)
{
- NMTVDISPINFOW callback;
+ NMTVDISPINFOEXW callback;
HWND hwnd = infoPtr->hwnd;
TRACE("mask %x callbackMask %x\n", mask, wineItem->callbackMask);
if (mask & TVIF_TEXT)
wineItem->textWidth = 0;
- TREEVIEW_SendRealNotify(infoPtr,
- (WPARAM)callback.hdr.idFrom, (LPARAM)&callback);
+ TREEVIEW_SendRealNotify(infoPtr, callback.hdr.idFrom, (LPARAM)&callback);
/* It may have changed due to a call to SetItem. */
mask &= wineItem->callbackMask;
(LPSTR)callback.item.pszText, -1,
NULL, 0);
buflen = max((len)*sizeof(WCHAR), TEXT_CALLBACK_SIZE);
- newText = (LPWSTR)ReAlloc(wineItem->pszText, buflen);
+ newText = ReAlloc(wineItem->pszText, buflen);
TRACE("returned str %s, len=%d, buflen=%d\n",
debugstr_a((LPSTR)callback.item.pszText), len, buflen);
(LPSTR)callback.item.pszText, -1,
NULL, 0);
buflen = max((len)*sizeof(WCHAR), TEXT_CALLBACK_SIZE);
- newText = (LPWSTR)Alloc(buflen);
+ newText = Alloc(buflen);
TRACE("same buffer str %s, len=%d, buflen=%d\n",
debugstr_a((LPSTR)callback.item.pszText), len, buflen);
return wineItem->cChildren > 0;
}
+static INT TREEVIEW_NotifyFormat (TREEVIEW_INFO *infoPtr, HWND hwndFrom, UINT nCommand)
+{
+ INT format;
+
+ TRACE("(hwndFrom=%p, nCommand=%d)\n", hwndFrom, nCommand);
+
+ if (nCommand != NF_REQUERY) return 0;
+
+ format = SendMessageW(hwndFrom, WM_NOTIFYFORMAT, (WPARAM)infoPtr->hwnd, NF_QUERY);
+ TRACE("format=%d\n", format);
+
+ if (format != NFR_ANSI && format != NFR_UNICODE) return 0;
+
+ infoPtr->bNtfUnicode = (format == NFR_UNICODE);
+
+ return format;
+}
/* Item Position ********************************************************/
> TVS_LINESATROOT);
#endif
- item->linesOffset = infoPtr->uIndent * (item->iLevel + lar - 1)
+ item->linesOffset = infoPtr->uIndent * (lar ? item->iLevel : item->iLevel - 1)
- infoPtr->scrollX;
item->stateOffset = item->linesOffset + infoPtr->uIndent;
item->imageOffset = item->stateOffset
TREEVIEW_FreeItem(TREEVIEW_INFO *infoPtr, TREEVIEW_ITEM *item)
{
DPA_DeletePtr(infoPtr->items, DPA_GetPtrIndex(infoPtr->items, item));
- Free(item);
if (infoPtr->selectedItem == item)
infoPtr->selectedItem = NULL;
if (infoPtr->hotItem == item)
infoPtr->dropItem = NULL;
if (infoPtr->insertMarkItem == item)
infoPtr->insertMarkItem = NULL;
+ Free(item);
}
TREEVIEW_InsertBefore(TREEVIEW_ITEM *newItem, TREEVIEW_ITEM *sibling,
TREEVIEW_ITEM *parent)
{
- assert(newItem != NULL);
assert(parent != NULL);
if (sibling != NULL)
TREEVIEW_InsertAfter(TREEVIEW_ITEM *newItem, TREEVIEW_ITEM *sibling,
TREEVIEW_ITEM *parent)
{
- assert(newItem != NULL);
assert(parent != NULL);
if (sibling != NULL)
if (tvItem->mask & TVIF_TEXT)
{
wineItem->textWidth = 0; /* force width recalculation */
- if (tvItem->pszText != LPSTR_TEXTCALLBACKW) /* covers != TEXTCALLBACKA too */
+ if (tvItem->pszText != LPSTR_TEXTCALLBACKW && tvItem->pszText != NULL) /* covers != TEXTCALLBACKA too, and undocumented: pszText of NULL also means TEXTCALLBACK */
{
int len;
LPWSTR newText;
if (!TREEVIEW_ValidItem(infoPtr, parentItem))
{
WARN("invalid parent %p\n", parentItem);
- return (LRESULT)(HTREEITEM)NULL;
+ return 0;
}
}
newItem = TREEVIEW_AllocateItem(infoPtr);
if (newItem == NULL)
- return (LRESULT)(HTREEITEM)NULL;
+ return 0;
newItem->parent = parentItem;
newItem->iIntegral = 1;
+ newItem->visibleOrder = -1;
if (!TREEVIEW_DoSetItemT(infoPtr, newItem, tvItem, isW))
- return (LRESULT)(HTREEITEM)NULL;
+ return 0;
/* After this point, nothing can fail. (Except for TVI_SORT.) */
TREEVIEW_VerifyTree(infoPtr);
+ if (!infoPtr->bRedraw) return (LRESULT)newItem;
+
if (parentItem == infoPtr->root ||
(ISVISIBLE(parentItem) && parentItem->state & TVIS_EXPANDED))
{
}
else
{
- newItem->visibleOrder = -1;
-
/* refresh treeview if newItem is the first item inserted under parentItem */
if (ISVISIBLE(parentItem) && newItem->prevSibling == newItem->nextSibling)
{
TREEVIEW_VerifyTree(infoPtr);
+ if (!infoPtr->bRedraw) return TRUE;
if (visible)
{
/* Get/Set Messages *********************************************************/
static LRESULT
-TREEVIEW_SetRedraw(TREEVIEW_INFO* infoPtr, WPARAM wParam, LPARAM lParam)
+TREEVIEW_SetRedraw(TREEVIEW_INFO* infoPtr, WPARAM wParam)
{
- if(wParam)
- infoPtr->bRedraw = TRUE;
- else
- infoPtr->bRedraw = FALSE;
+ infoPtr->bRedraw = wParam ? TRUE : FALSE;
- return 0;
+ if (infoPtr->bRedraw)
+ {
+ TREEVIEW_UpdateSubTree(infoPtr, infoPtr->root);
+ TREEVIEW_RecalculateVisibleOrder(infoPtr, NULL);
+ TREEVIEW_UpdateScrollBars(infoPtr);
+ TREEVIEW_Invalidate(infoPtr, NULL);
+ }
+ return 0;
}
static LRESULT
switch (wParam)
{
- case (WPARAM)TVSIL_NORMAL:
+ case TVSIL_NORMAL:
return (LRESULT)infoPtr->himlNormal;
- case (WPARAM)TVSIL_STATE:
+ case TVSIL_STATE:
return (LRESULT)infoPtr->himlState;
default:
switch (wParam)
{
- case (WPARAM)TVSIL_NORMAL:
+ case TVSIL_NORMAL:
himlOld = infoPtr->himlNormal;
infoPtr->himlNormal = himlNew;
break;
- case (WPARAM)TVSIL_STATE:
+ case TVSIL_STATE:
himlOld = infoPtr->himlState;
infoPtr->himlState = himlNew;
infoPtr->hFont = hFont ? hFont : infoPtr->hDefaultFont;
DeleteObject(infoPtr->hBoldFont);
+ DeleteObject(infoPtr->hUnderlineFont);
infoPtr->hBoldFont = TREEVIEW_CreateBoldFont(infoPtr->hFont);
infoPtr->hUnderlineFont = TREEVIEW_CreateUnderlineFont(infoPtr->hFont);
*lpRect = wineItem->rect;
}
- TRACE("%s [L:%d R:%d T:%d B:%d]\n", fTextRect ? "text" : "item",
- lpRect->left, lpRect->right, lpRect->top, lpRect->bottom);
+ TRACE("%s [%s]\n", fTextRect ? "text" : "item", wine_dbgstr_rect(lpRect));
return TRUE;
}
static inline LRESULT
TREEVIEW_GetVisibleCount(const TREEVIEW_INFO *infoPtr)
{
- /* Suprise! This does not take integral height into account. */
+ /* Surprise! This does not take integral height into account. */
return infoPtr->clientHeight / infoPtr->uItemHeight;
}
if (tvItem->mask & TVIF_TEXT)
{
- if (isW)
+ if (wineItem->pszText == NULL)
+ {
+ if (tvItem->cchTextMax > 0)
+ tvItem->pszText[0] = '\0';
+ }
+ else if (isW)
{
if (wineItem->pszText == LPSTR_TEXTCALLBACKW)
{
if (!TREEVIEW_ValidItem(infoPtr, wineItem))
return FALSE;
- /* store the orignal item values */
+ /* store the original item values */
originalItem = *wineItem;
if (!TREEVIEW_DoSetItemT(infoPtr, wineItem, tvItem, isW))
& (TVS_LINESATROOT|TVS_HASLINES|TVS_HASBUTTONS))
> TVS_LINESATROOT);
HBRUSH hbr, hbrOld;
+ COLORREF clrBk = GETBKCOLOR(infoPtr->clrBk);
if (!lar && item->iLevel == 0)
return;
- hbr = CreateSolidBrush(infoPtr->clrBk);
+ hbr = CreateSolidBrush(clrBk);
hbrOld = SelectObject(hdc, hbr);
centerx = (item->linesOffset + item->stateOffset) / 2;
/* Get a dotted grey pen */
lb.lbStyle = BS_SOLID;
- lb.lbColor = infoPtr->clrLine;
+ lb.lbColor = GETLINECOLOR(infoPtr->clrLine);
hNewPen = ExtCreatePen(PS_COSMETIC|PS_ALTERNATE, 1, &lb, 0, NULL);
hOldPen = SelectObject(hdc, hNewPen);
/* plussize = ceil(rectsize * 3/4) */
LONG plussize = (rectsize + 1) * 3 / 4;
- HPEN hNewPen = CreatePen(PS_SOLID, 0, infoPtr->clrLine);
- HPEN hOldPen = SelectObject(hdc, hNewPen);
+ HPEN new_pen = CreatePen(PS_SOLID, 0, GETLINECOLOR(infoPtr->clrLine));
+ HPEN old_pen = SelectObject(hdc, new_pen);
Rectangle(hdc, centerx - rectsize - 1, centery - rectsize - 1,
centerx + rectsize + 2, centery + rectsize + 2);
- SelectObject(hdc, hOldPen);
- DeleteObject(hNewPen);
+ SelectObject(hdc, old_pen);
+ DeleteObject(new_pen);
+
+ /* draw +/- signs with current text color */
+ new_pen = CreatePen(PS_SOLID, 0, GETTXTCOLOR(infoPtr->clrText));
+ old_pen = SelectObject(hdc, new_pen);
if (height < 18 || width < 18)
{
MoveToEx(hdc, centerx - plussize + 1, centery, NULL);
LineTo(hdc, centerx + plussize, centery);
-
+
if (!(item->state & TVIS_EXPANDED))
{
MoveToEx(hdc, centerx, centery - plussize + 1, NULL);
{
Rectangle(hdc, centerx - plussize + 1, centery - 1,
centerx + plussize, centery + 2);
-
+
if (!(item->state & TVIS_EXPANDED))
{
Rectangle(hdc, centerx - 1, centery - plussize + 1,
centerx + 2, centery + plussize);
- SetPixel(hdc, centerx - 1, centery, infoPtr->clrBk);
- SetPixel(hdc, centerx + 1, centery, infoPtr->clrBk);
+ SetPixel(hdc, centerx - 1, centery, clrBk);
+ SetPixel(hdc, centerx + 1, centery, clrBk);
}
}
+
+ SelectObject(hdc, old_pen);
+ DeleteObject(new_pen);
}
}
}
{
if ((wineItem->state & TVIS_DROPHILITED) || inFocus)
{
- nmcdhdr.clrTextBk = GetSysColor(COLOR_HIGHLIGHT);
- nmcdhdr.clrText = GetSysColor(COLOR_HIGHLIGHTTEXT);
+ nmcdhdr.clrTextBk = comctl32_color.clrHighlight;
+ nmcdhdr.clrText = comctl32_color.clrHighlightText;
}
else
{
- nmcdhdr.clrTextBk = GetSysColor(COLOR_BTNFACE);
- if (infoPtr->clrText == -1)
- nmcdhdr.clrText = GetSysColor(COLOR_WINDOWTEXT);
- else
- nmcdhdr.clrText = infoPtr->clrText;
+ nmcdhdr.clrTextBk = comctl32_color.clrBtnFace;
+ nmcdhdr.clrText = GETTXTCOLOR(infoPtr->clrText);
}
}
else
{
- nmcdhdr.clrTextBk = infoPtr->clrBk;
+ nmcdhdr.clrTextBk = GETBKCOLOR(infoPtr->clrBk);
if ((infoPtr->dwStyle & TVS_TRACKSELECT) && (wineItem == infoPtr->hotItem))
nmcdhdr.clrText = comctl32_color.clrHighlight;
- else if (infoPtr->clrText == -1)
- nmcdhdr.clrText = GetSysColor(COLOR_WINDOWTEXT);
else
- nmcdhdr.clrText = infoPtr->clrText;
+ nmcdhdr.clrText = GETTXTCOLOR(infoPtr->clrText);
}
hOldFont = SelectObject(hdc, TREEVIEW_FontForItem(infoPtr, wineItem));
rcText.left = wineItem->textOffset;
rcText.right = rcText.left + wineItem->textWidth + 4;
- TRACE("drawing text %s at (%d,%d)-(%d,%d)\n",
- debugstr_w(wineItem->pszText),
- rcText.left, rcText.top, rcText.right, rcText.bottom);
+ TRACE("drawing text %s at (%s)\n",
+ debugstr_w(wineItem->pszText), wine_dbgstr_rect(&rcText));
/* Draw it */
ExtTextOutW(hdc, rcText.left + 2, rcText.top + 1,
wineItem->pszText,
lstrlenW(wineItem->pszText),
NULL);
-
+
/* Draw the box around the selected item */
if ((wineItem == infoPtr->selectedItem) && inFocus)
{
int offset;
int left, right;
- hNewPen = CreatePen(PS_SOLID, 2, infoPtr->clrInsertMark);
+ hNewPen = CreatePen(PS_SOLID, 2, GETINSCOLOR(infoPtr->clrInsertMark));
hOldPen = SelectObject(hdc, hNewPen);
if (infoPtr->insertBeforeorAfter)
infoPtr->uInternalStatus &= ~TV_HSCROLL;
}
+static void
+TREEVIEW_FillBkgnd(const TREEVIEW_INFO *infoPtr, HDC hdc, const RECT *rc)
+{
+ HBRUSH hBrush;
+ COLORREF clrBk = GETBKCOLOR(infoPtr->clrBk);
+
+ hBrush = CreateSolidBrush(clrBk);
+ FillRect(hdc, rc, hBrush);
+ DeleteObject(hBrush);
+}
+
/* CtrlSpy doesn't mention this, but CorelDRAW's object manager needs it. */
static LRESULT
-TREEVIEW_EraseBackground(const TREEVIEW_INFO *infoPtr, HDC hDC)
+TREEVIEW_EraseBackground(const TREEVIEW_INFO *infoPtr, HDC hdc)
{
- HBRUSH hBrush = CreateSolidBrush(infoPtr->clrBk);
RECT rect;
+ TRACE("%p\n", infoPtr);
+
GetClientRect(infoPtr->hwnd, &rect);
- FillRect(hDC, &rect, hBrush);
- DeleteObject(hBrush);
+ TREEVIEW_FillBkgnd(infoPtr, hdc, &rect);
return 1;
}
}
}
+ //
+ // This is correct, but is causes and infinite loop of WM_PAINT messages, resulting
+ // in continuous painting of the scroll bar in reactos. Comment out until the real
+ // bug is found
+ //
+ //TREEVIEW_UpdateScrollBars(infoPtr);
+
if (infoPtr->cdmode & CDRF_NOTIFYPOSTPAINT)
infoPtr->cdmode =
TREEVIEW_SendCustomDrawNotify(infoPtr, CDDS_POSTPAINT, hdc, rect);
}
+static inline void
+TREEVIEW_InvalidateItem(const TREEVIEW_INFO *infoPtr, const TREEVIEW_ITEM *item)
+{
+ if (item) InvalidateRect(infoPtr->hwnd, &item->rect, TRUE);
+}
+
static void
TREEVIEW_Invalidate(const TREEVIEW_INFO *infoPtr, const TREEVIEW_ITEM *item)
{
- if (item != NULL)
+ if (item)
InvalidateRect(infoPtr->hwnd, &item->rect, TRUE);
else
InvalidateRect(infoPtr->hwnd, NULL, TRUE);
}
static LRESULT
-TREEVIEW_Paint(TREEVIEW_INFO *infoPtr, WPARAM wParam)
+TREEVIEW_Paint(TREEVIEW_INFO *infoPtr, HDC hdc_ref)
{
HDC hdc;
PAINTSTRUCT ps;
TRACE("\n");
- if (wParam)
+ if (hdc_ref)
{
- hdc = (HDC)wParam;
+ hdc = hdc_ref;
GetClientRect(infoPtr->hwnd, &rc);
- TREEVIEW_EraseBackground(infoPtr, hdc);
}
else
{
hdc = BeginPaint(infoPtr->hwnd, &ps);
- rc = ps.rcPaint;
+ rc = ps.rcPaint;
+ if(ps.fErase)
+ TREEVIEW_FillBkgnd(infoPtr, hdc, &rc);
}
if(infoPtr->bRedraw) /* WM_SETREDRAW sets bRedraw */
TREEVIEW_Refresh(infoPtr, hdc, &rc);
- if (!wParam)
+ if (!hdc_ref)
EndPaint(infoPtr->hwnd, &ps);
return 0;
}
+static LRESULT
+TREEVIEW_PrintClient(TREEVIEW_INFO *infoPtr, HDC hdc, DWORD options)
+{
+ FIXME("Partial Stub: (hdc=%p options=0x%08x)\n", hdc, options);
+
+ if ((options & PRF_CHECKVISIBLE) && !IsWindowVisible(infoPtr->hwnd))
+ return 0;
+
+ if (options & PRF_ERASEBKGND)
+ TREEVIEW_EraseBackground(infoPtr, hdc);
+
+ if (options & PRF_CLIENT)
+ {
+ RECT rc;
+ GetClientRect(infoPtr->hwnd, &rc);
+ TREEVIEW_Refresh(infoPtr, hdc, &rc);
+ }
+
+ return 0;
+}
/* Sorting **************************************************************/
/* Returns the number of physical children belonging to item. */
static INT
-TREEVIEW_CountChildren(const TREEVIEW_INFO *infoPtr, const TREEVIEW_ITEM *item)
+TREEVIEW_CountChildren(const TREEVIEW_ITEM *item)
{
INT cChildren = 0;
HTREEITEM hti;
/* Returns a DPA containing a pointer to each physical child of item in
* sibling order. If item has no children, an empty DPA is returned. */
static HDPA
-TREEVIEW_BuildChildDPA(const TREEVIEW_INFO *infoPtr, const TREEVIEW_ITEM *item)
+TREEVIEW_BuildChildDPA(const TREEVIEW_ITEM *item)
{
HTREEITEM child = item->firstChild;
*/
static LRESULT
-TREEVIEW_Sort(TREEVIEW_INFO *infoPtr, BOOL fRecurse, HTREEITEM parent,
+TREEVIEW_Sort(TREEVIEW_INFO *infoPtr, HTREEITEM parent,
LPTVSORTCB pSort)
{
INT cChildren;
lpCompare = (LPARAM)infoPtr;
}
- cChildren = TREEVIEW_CountChildren(infoPtr, parent);
+ cChildren = TREEVIEW_CountChildren(parent);
/* Make sure there is something to sort */
if (cChildren > 1)
HTREEITEM nextItem = 0;
HTREEITEM prevItem = 0;
- HDPA sortList = TREEVIEW_BuildChildDPA(infoPtr, parent);
+ HDPA sortList = TREEVIEW_BuildChildDPA(parent);
if (sortList == NULL)
return FALSE;
/* The order of DPA entries has been changed, so fixup the
* nextSibling and prevSibling pointers. */
- item = (HTREEITEM)DPA_GetPtr(sortList, count++);
- while ((nextItem = (HTREEITEM)DPA_GetPtr(sortList, count++)) != NULL)
+ item = DPA_GetPtr(sortList, count++);
+ while ((nextItem = DPA_GetPtr(sortList, count++)) != NULL)
{
- /* link the two current item toghether */
+ /* link the two current item together */
item->nextSibling = nextItem;
nextItem->prevSibling = item;
* and sort the children of the TV item specified in lParam
*/
static LRESULT
-TREEVIEW_SortChildrenCB(TREEVIEW_INFO *infoPtr, WPARAM wParam, LPTVSORTCB pSort)
+TREEVIEW_SortChildrenCB(TREEVIEW_INFO *infoPtr, LPTVSORTCB pSort)
{
- return TREEVIEW_Sort(infoPtr, wParam, pSort->hParent, pSort);
+ return TREEVIEW_Sort(infoPtr, pSort->hParent, pSort);
}
* Sort the children of the TV item specified in lParam.
*/
static LRESULT
-TREEVIEW_SortChildren(TREEVIEW_INFO *infoPtr, WPARAM wParam, LPARAM lParam)
+TREEVIEW_SortChildren(TREEVIEW_INFO *infoPtr, LPARAM lParam)
{
- return TREEVIEW_Sort(infoPtr, (BOOL)wParam, (HTREEITEM)lParam, NULL);
+ return TREEVIEW_Sort(infoPtr, (HTREEITEM)lParam, NULL);
}
{
scrollRect.top = nextItem->rect.top;
- ScrollWindowEx (infoPtr->hwnd, 0, scrollDist, &scrollRect, NULL,
+ ScrollWindowEx (infoPtr->hwnd, 0, scrollDist, &scrollRect, &scrollRect,
NULL, NULL, SW_ERASE | SW_INVALIDATE);
TREEVIEW_Invalidate(infoPtr, wineItem);
} else {
if (bExpandPartial)
FIXME("TVE_EXPANDPARTIAL not implemented\n");
- TREEVIEW_RecalculateVisibleOrder(infoPtr, wineItem);
- TREEVIEW_UpdateSubTree(infoPtr, wineItem);
- TREEVIEW_UpdateScrollBars(infoPtr);
-
- scrollRect.left = 0;
- scrollRect.bottom = infoPtr->treeHeight;
- scrollRect.right = infoPtr->clientWidth;
- if (nextItem)
+ if (ISVISIBLE(wineItem))
{
- scrollDist = nextItem->rect.top - orgNextTop;
- scrollRect.top = orgNextTop;
+ TREEVIEW_RecalculateVisibleOrder(infoPtr, wineItem);
+ TREEVIEW_UpdateSubTree(infoPtr, wineItem);
+ TREEVIEW_UpdateScrollBars(infoPtr);
- ScrollWindowEx (infoPtr->hwnd, 0, scrollDist, &scrollRect, NULL,
- NULL, NULL, SW_ERASE | SW_INVALIDATE);
- TREEVIEW_Invalidate (infoPtr, wineItem);
- } else {
- scrollRect.top = wineItem->rect.top;
- InvalidateRect(infoPtr->hwnd, &scrollRect, FALSE);
- }
+ scrollRect.left = 0;
+ scrollRect.bottom = infoPtr->treeHeight;
+ scrollRect.right = infoPtr->clientWidth;
+ if (nextItem)
+ {
+ scrollDist = nextItem->rect.top - orgNextTop;
+ scrollRect.top = orgNextTop;
+
+ ScrollWindowEx (infoPtr->hwnd, 0, scrollDist, &scrollRect, NULL,
+ NULL, NULL, SW_ERASE | SW_INVALIDATE);
+ TREEVIEW_Invalidate (infoPtr, wineItem);
+ } else {
+ scrollRect.top = wineItem->rect.top;
+ InvalidateRect(infoPtr->hwnd, &scrollRect, FALSE);
+ }
- /* Scroll up so that as many children as possible are visible.
- * This fails when expanding causes an HScroll bar to appear, but we
- * don't know that yet, so the last item is obscured. */
- if (wineItem->firstChild != NULL)
- {
- int nChildren = wineItem->lastChild->visibleOrder
- - wineItem->firstChild->visibleOrder + 1;
+ /* Scroll up so that as many children as possible are visible.
+ * This fails when expanding causes an HScroll bar to appear, but we
+ * don't know that yet, so the last item is obscured. */
+ if (wineItem->firstChild != NULL)
+ {
+ int nChildren = wineItem->lastChild->visibleOrder
+ - wineItem->firstChild->visibleOrder + 1;
- int visible_pos = wineItem->visibleOrder
- - infoPtr->firstVisible->visibleOrder;
+ int visible_pos = wineItem->visibleOrder
+ - infoPtr->firstVisible->visibleOrder;
- int rows_below = TREEVIEW_GetVisibleCount(infoPtr) - visible_pos - 1;
+ int rows_below = TREEVIEW_GetVisibleCount(infoPtr) - visible_pos - 1;
- if (visible_pos > 0 && nChildren > rows_below)
- {
- int scroll = nChildren - rows_below;
+ if (visible_pos > 0 && nChildren > rows_below)
+ {
+ int scroll = nChildren - rows_below;
- if (scroll > visible_pos)
- scroll = visible_pos;
+ if (scroll > visible_pos)
+ scroll = visible_pos;
- if (scroll > 0)
- {
- TREEVIEW_ITEM *newFirstVisible
- = TREEVIEW_GetListItem(infoPtr, infoPtr->firstVisible,
- scroll);
+ if (scroll > 0)
+ {
+ TREEVIEW_ITEM *newFirstVisible
+ = TREEVIEW_GetListItem(infoPtr, infoPtr->firstVisible,
+ scroll);
- TREEVIEW_SetFirstVisible(infoPtr, newFirstVisible, TRUE);
- }
- }
+ TREEVIEW_SetFirstVisible(infoPtr, newFirstVisible, TRUE);
+ }
+ }
+ }
}
return TRUE;
if (status)
{
lpht->flags = status;
- return (LRESULT)(HTREEITEM)NULL;
+ return 0;
}
wineItem = TREEVIEW_HitTestPoint(infoPtr, lpht->pt);
if (!wineItem)
{
lpht->flags = TVHT_NOWHERE;
- return (LRESULT)(HTREEITEM)NULL;
+ return 0;
}
if (x >= wineItem->textOffset + wineItem->textWidth)
return TRUE;
break;
+ case WM_DESTROY:
+ {
+ WNDPROC editProc = infoPtr->wpEditOrig;
+ infoPtr->wpEditOrig = 0;
+ SetWindowLongPtrW(hwnd, GWLP_WNDPROC, (DWORD_PTR)editProc);
+ return CallWindowProcW(editProc, hwnd, uMsg, wParam, lParam);
+ }
+
case WM_GETDLGCODE:
return DLGC_WANTARROWS | DLGC_WANTALLKEYS;
case WM_KEYDOWN:
- if (wParam == (WPARAM)VK_ESCAPE)
+ if (wParam == VK_ESCAPE)
{
bCancel = TRUE;
break;
}
- else if (wParam == (WPARAM)VK_RETURN)
+ else if (wParam == VK_RETURN)
{
break;
}
static LRESULT
TREEVIEW_Command(TREEVIEW_INFO *infoPtr, WPARAM wParam, LPARAM lParam)
{
- TRACE("%lx %ld\n", wParam, lParam);
+ TRACE("code=%x, id=%x, handle=%lx\n", HIWORD(wParam), LOWORD(wParam), lParam);
switch (HIWORD(wParam))
{
* Adjust the edit window size
*/
WCHAR buffer[1024];
- TREEVIEW_ITEM *editItem = infoPtr->selectedItem;
+ TREEVIEW_ITEM *editItem = infoPtr->editItem;
HDC hdc = GetDC(infoPtr->hwndEdit);
SIZE sz;
- int len;
HFONT hFont, hOldFont = 0;
+ TRACE("edit=%p\n", infoPtr->hwndEdit);
+
+ if (!IsWindow(infoPtr->hwndEdit) || !hdc) return FALSE;
+
infoPtr->bLabelChanged = TRUE;
- len = GetWindowTextW(infoPtr->hwndEdit, buffer, sizeof(buffer));
+ GetWindowTextW(infoPtr->hwndEdit, buffer, sizeof(buffer)/sizeof(buffer[0]));
/* Select font to get the right dimension of the string */
hFont = (HFONT)SendMessageW(infoPtr->hwndEdit, WM_GETFONT, 0, 0);
ReleaseDC(infoPtr->hwnd, hdc);
break;
}
+ case EN_KILLFOCUS:
+ /* apparently we should respect passed handle value */
+ if (infoPtr->hwndEdit != (HWND)lParam) return FALSE;
+
+ TREEVIEW_EndEditLabelNow(infoPtr, FALSE);
+ break;
default:
return SendMessageW(infoPtr->hwndNotify, WM_COMMAND, wParam, lParam);
HWND hwnd = infoPtr->hwnd;
HWND hwndEdit;
SIZE sz;
- TREEVIEW_ITEM *editItem = hItem;
HINSTANCE hinst = (HINSTANCE)GetWindowLongPtrW(hwnd, GWLP_HINSTANCE);
HDC hdc;
HFONT hOldFont=0;
TEXTMETRICW textMetric;
- static const WCHAR EditW[] = {'E','d','i','t',0};
TRACE("%p %p\n", hwnd, hItem);
- if (!TREEVIEW_ValidItem(infoPtr, editItem))
+ if (!TREEVIEW_ValidItem(infoPtr, hItem))
return NULL;
if (infoPtr->hwndEdit)
infoPtr->bLabelChanged = FALSE;
- /* Make sure that edit item is selected */
- TREEVIEW_DoSelectItem(infoPtr, TVGN_CARET, hItem, TVC_UNKNOWN);
+ /* make edit item visible */
TREEVIEW_EnsureVisible(infoPtr, hItem, TRUE);
- TREEVIEW_UpdateDispInfo(infoPtr, editItem, TVIF_TEXT);
+ TREEVIEW_UpdateDispInfo(infoPtr, hItem, TVIF_TEXT);
hdc = GetDC(hwnd);
/* Select the font to get appropriate metric dimensions */
}
/* Get string length in pixels */
- GetTextExtentPoint32W(hdc, editItem->pszText, strlenW(editItem->pszText),
- &sz);
+ if (hItem->pszText)
+ GetTextExtentPoint32W(hdc, hItem->pszText, strlenW(hItem->pszText),
+ &sz);
+ else
+ GetTextExtentPoint32A(hdc, "", 0, &sz);
/* Add Extra spacing for the next character */
GetTextMetricsW(hdc, &textMetric);
sz.cx += (textMetric.tmMaxCharWidth * 2);
sz.cx = max(sz.cx, textMetric.tmMaxCharWidth * 3);
- sz.cx = min(sz.cx, infoPtr->clientWidth - editItem->textOffset + 2);
+ sz.cx = min(sz.cx, infoPtr->clientWidth - hItem->textOffset + 2);
if (infoPtr->hFont != 0)
{
}
ReleaseDC(hwnd, hdc);
+
+ infoPtr->editItem = hItem;
+
hwndEdit = CreateWindowExW(WS_EX_LEFT,
- EditW,
+ WC_EDITW,
0,
WS_CHILD | WS_BORDER | ES_AUTOHSCROLL |
WS_CLIPSIBLINGS | ES_WANTRETURN |
- ES_LEFT, editItem->textOffset - 2,
- editItem->rect.top - 1, sz.cx + 3,
- editItem->rect.bottom -
- editItem->rect.top + 3, hwnd, 0, hinst, 0);
+ ES_LEFT, hItem->textOffset - 2,
+ hItem->rect.top - 1, sz.cx + 3,
+ hItem->rect.bottom -
+ hItem->rect.top + 3, hwnd, 0, hinst, 0);
/* FIXME: (HMENU)IDTVEDIT,pcs->hInstance,0); */
infoPtr->hwndEdit = hwndEdit;
GetWindowLongW(hwndEdit, GWL_STYLE) | WS_BORDER);
SendMessageW(hwndEdit, WM_SETFONT,
- (WPARAM)TREEVIEW_FontForItem(infoPtr, editItem), FALSE);
+ (WPARAM)TREEVIEW_FontForItem(infoPtr, hItem), FALSE);
infoPtr->wpEditOrig = (WNDPROC)SetWindowLongPtrW(hwndEdit, GWLP_WNDPROC,
(DWORD_PTR)
TREEVIEW_Edit_SubclassProc);
- if (TREEVIEW_BeginLabelEditNotify(infoPtr, editItem))
+ if (TREEVIEW_BeginLabelEditNotify(infoPtr, hItem))
{
DestroyWindow(hwndEdit);
infoPtr->hwndEdit = 0;
+ infoPtr->editItem = NULL;
return NULL;
}
- infoPtr->selectedItem = hItem;
- SetWindowTextW(hwndEdit, editItem->pszText);
+ if (hItem->pszText)
+ SetWindowTextW(hwndEdit, hItem->pszText);
+
SetFocus(hwndEdit);
SendMessageW(hwndEdit, EM_SETSEL, 0, -1);
ShowWindow(hwndEdit, SW_SHOW);
TREEVIEW_EndEditLabelNow(TREEVIEW_INFO *infoPtr, BOOL bCancel)
{
HWND hwnd = infoPtr->hwnd;
- TREEVIEW_ITEM *editedItem = infoPtr->selectedItem;
+ TREEVIEW_ITEM *editedItem = infoPtr->editItem;
NMTVDISPINFOW tvdi;
BOOL bCommit;
WCHAR tmpText[1024] = { '\0' };
WCHAR *newText = tmpText;
int iLength = 0;
- if (!infoPtr->hwndEdit)
- return FALSE;
+ if (!IsWindow(infoPtr->hwndEdit)) return FALSE;
tvdi.hdr.hwndFrom = hwnd;
tvdi.hdr.idFrom = GetWindowLongPtrW(hwnd, GWLP_ID);
tvdi.item.cchTextMax = 0;
}
- bCommit = (BOOL)TREEVIEW_SendRealNotify(infoPtr,
- (WPARAM)tvdi.hdr.idFrom, (LPARAM)&tvdi);
+ bCommit = (BOOL)TREEVIEW_SendRealNotify(infoPtr, tvdi.hdr.idFrom, (LPARAM)&tvdi);
if (!bCancel && bCommit) /* Apply the changes */
{
if(newText != tmpText) Free(newText);
DestroyWindow(infoPtr->hwndEdit);
infoPtr->hwndEdit = 0;
+ infoPtr->editItem = NULL;
return FALSE;
}
else
ShowWindow(infoPtr->hwndEdit, SW_HIDE);
DestroyWindow(infoPtr->hwndEdit);
infoPtr->hwndEdit = 0;
+ infoPtr->editItem = NULL;
return TRUE;
}
HWND hwnd = infoPtr->hwnd;
TVHITTESTINFO ht;
BOOL bTrack, bDoLabelEdit;
- HTREEITEM tempItem;
/* If Edit control is active - kill it and return.
* The best way to do it is to set focus to itself.
if(ht.hItem && (ht.flags & TVHT_ONITEM))
{
infoPtr->focusedItem = ht.hItem;
- InvalidateRect(hwnd, &(((HTREEITEM)(ht.hItem))->rect), TRUE);
-
- if(infoPtr->selectedItem)
- InvalidateRect(hwnd, &(infoPtr->selectedItem->rect), TRUE);
+ TREEVIEW_InvalidateItem(infoPtr, infoPtr->focusedItem);
+ TREEVIEW_InvalidateItem(infoPtr, infoPtr->selectedItem);
}
bTrack = (ht.flags & TVHT_ONITEM)
if(infoPtr->focusedItem)
{
/* refresh the item that was focused */
- tempItem = infoPtr->focusedItem;
- infoPtr->focusedItem = 0;
- InvalidateRect(infoPtr->hwnd, &tempItem->rect, TRUE);
+ TREEVIEW_InvalidateItem(infoPtr, infoPtr->focusedItem);
+ infoPtr->focusedItem = NULL;
/* refresh the selected item to return the filled background */
- InvalidateRect(infoPtr->hwnd, &(infoPtr->selectedItem->rect), TRUE);
+ TREEVIEW_InvalidateItem(infoPtr, infoPtr->selectedItem);
}
return 0;
SendMessageW(infoPtr->hwnd, WM_CONTEXTMENU,
(WPARAM)infoPtr->hwnd, MAKELPARAM(ht.pt.x, ht.pt.y));
}
-
return 0;
}
static LRESULT
-TREEVIEW_CreateDragImage(TREEVIEW_INFO *infoPtr, WPARAM wParam, LPARAM lParam)
+TREEVIEW_CreateDragImage(TREEVIEW_INFO *infoPtr, LPARAM lParam)
{
TREEVIEW_ITEM *dragItem = (HTREEITEM)lParam;
INT cx, cy;
hdc = CreateCompatibleDC(htopdc);
hOldFont = SelectObject(hdc, infoPtr->hFont);
- GetTextExtentPoint32W(hdc, dragItem->pszText, strlenW(dragItem->pszText),
+
+ if (dragItem->pszText)
+ GetTextExtentPoint32W(hdc, dragItem->pszText, strlenW(dragItem->pszText),
&size);
- TRACE("%d %d %s %d\n", size.cx, size.cy, debugstr_w(dragItem->pszText),
- strlenW(dragItem->pszText));
+ else
+ GetTextExtentPoint32A(hdc, "", 0, &size);
+
+ TRACE("%d %d %s\n", size.cx, size.cy, debugstr_w(dragItem->pszText));
hbmp = CreateCompatibleBitmap(htopdc, size.cx, size.cy);
hOldbmp = SelectObject(hdc, hbmp);
/* draw item text */
SetRect(&rc, cx, 0, size.cx, size.cy);
- DrawTextW(hdc, dragItem->pszText, strlenW(dragItem->pszText), &rc,
- DT_LEFT);
+
+ if (dragItem->pszText)
+ DrawTextW(hdc, dragItem->pszText, strlenW(dragItem->pszText), &rc,
+ DT_LEFT);
+
SelectObject(hdc, hOldFont);
SelectObject(hdc, hOldbmp);
INT cause)
{
TREEVIEW_ITEM *prevSelect;
- RECT rcFocused;
assert(newSelect == NULL || TREEVIEW_ValidItem(infoPtr, newSelect));
/* reset and redraw focusedItem if focusedItem was set so we don't */
/* have to worry about the previously focused item when we set a new one */
- if(infoPtr->focusedItem)
- {
- rcFocused = (infoPtr->focusedItem)->rect;
- infoPtr->focusedItem = 0;
- InvalidateRect(infoPtr->hwnd, &rcFocused, TRUE);
- }
+ TREEVIEW_InvalidateItem(infoPtr, infoPtr->focusedItem);
+ infoPtr->focusedItem = NULL;
switch (action)
{
TREEVIEW_EnsureVisible(infoPtr, infoPtr->selectedItem, FALSE);
- if (prevSelect)
- TREEVIEW_Invalidate(infoPtr, prevSelect);
- if (newSelect)
- TREEVIEW_Invalidate(infoPtr, newSelect);
+ TREEVIEW_InvalidateItem(infoPtr, prevSelect);
+ TREEVIEW_InvalidateItem(infoPtr, newSelect);
TREEVIEW_SendTreeviewNotify(infoPtr,
TVN_SELCHANGEDW,
* BUGS
*
* - The current implementation has a list of characters it will
- * accept and it ignores averything else. In particular it will
+ * accept and it ignores everything else. In particular it will
* ignore accentuated characters which seems to match what
* Windows does. But I'm not sure it makes sense to follow
* Windows there.
*
* TREEVIEW_ProcessLetterKeys
*/
-static INT TREEVIEW_ProcessLetterKeys(
- HWND hwnd, /* handle to the window */
- WPARAM charCode, /* the character code, the actual character */
- LPARAM keyData /* key data */
- )
+static INT TREEVIEW_ProcessLetterKeys(TREEVIEW_INFO *infoPtr, WPARAM charCode, LPARAM keyData)
{
- TREEVIEW_INFO *infoPtr;
HTREEITEM nItem;
HTREEITEM endidx,idx;
TVITEMEXW item;
DWORD timestamp,elapsed;
/* simple parameter checking */
- if (!hwnd || !charCode || !keyData)
- return 0;
-
- infoPtr=(TREEVIEW_INFO*)GetWindowLongPtrW(hwnd, 0);
- if (!infoPtr)
- return 0;
+ if (!charCode || !keyData) return 0;
/* only allow the valid WM_CHARs through */
if (!isalnum(charCode) &&
/* Expand parents as necessary. */
HTREEITEM parent;
- /* see if we are trying to ensure that root is vislble */
+ /* see if we are trying to ensure that root is visible */
if((item != infoPtr->root) && TREEVIEW_ValidItem(infoPtr, item))
parent = item->parent;
else
}
static LRESULT
-TREEVIEW_MouseWheel(TREEVIEW_INFO *infoPtr, WPARAM wParam)
+TREEVIEW_MouseWheel(TREEVIEW_INFO *infoPtr, WPARAM wParam, LPARAM lParam)
{
short gcWheelDelta;
UINT pulScrollLines = 3;
+ if (wParam & (MK_SHIFT | MK_CONTROL))
+ return DefWindowProcW(infoPtr->hwnd, WM_MOUSEWHEEL, wParam, lParam);
+
if (infoPtr->firstVisible == NULL)
return TRUE;
SelectObject(hdc, hbmOld);
nIndex = ImageList_AddMasked(infoPtr->himlState, hbm,
- GetSysColor(COLOR_WINDOW));
+ comctl32_color.clrWindow);
TRACE("checkbox index %d\n", nIndex);
DeleteObject(hbm);
TRACE("wnd %p, style %x\n", hwnd, GetWindowLongW(hwnd, GWL_STYLE));
- infoPtr = (TREEVIEW_INFO *)Alloc(sizeof(TREEVIEW_INFO));
+ infoPtr = Alloc(sizeof(TREEVIEW_INFO));
if (infoPtr == NULL)
{
infoPtr->treeHeight = 0;
infoPtr->uIndent = MINIMUM_INDENT;
- infoPtr->selectedItem = 0;
- infoPtr->focusedItem = 0;
- infoPtr->hotItem = 0;
- infoPtr->firstVisible = 0;
+ infoPtr->selectedItem = NULL;
+ infoPtr->focusedItem = NULL;
+ infoPtr->hotItem = NULL;
+ infoPtr->editItem = NULL;
+ infoPtr->firstVisible = NULL;
infoPtr->maxVisibleOrder = 0;
- infoPtr->dropItem = 0;
- infoPtr->insertMarkItem = 0;
+ infoPtr->dropItem = NULL;
+ infoPtr->insertMarkItem = NULL;
infoPtr->insertBeforeorAfter = 0;
/* dragList */
infoPtr->scrollX = 0;
- infoPtr->clrBk = GetSysColor(COLOR_WINDOW);
- infoPtr->clrText = -1; /* use system color */
- infoPtr->clrLine = RGB(128, 128, 128);
- infoPtr->clrInsertMark = GetSysColor(COLOR_BTNTEXT);
+ infoPtr->clrBk = CLR_NONE; /* use system color */
+ infoPtr->clrText = CLR_NONE; /* use system color */
+ infoPtr->clrLine = CLR_DEFAULT;
+ infoPtr->clrInsertMark = CLR_DEFAULT;
/* hwndToolTip */
- infoPtr->hwndEdit = 0;
+ infoPtr->hwndEdit = NULL;
infoPtr->wpEditOrig = NULL;
infoPtr->bIgnoreEditKillFocus = FALSE;
infoPtr->bLabelChanged = FALSE;
/* Make sure actual scrollbar state is consistent with uInternalStatus */
ShowScrollBar(hwnd, SB_VERT, FALSE);
ShowScrollBar(hwnd, SB_HORZ, FALSE);
-
+
OpenThemeData (hwnd, themeClass);
return 0;
{
TRACE("\n");
+ /* free item data */
TREEVIEW_RemoveTree(infoPtr);
+ /* root isn't freed with other items */
+ TREEVIEW_FreeItem(infoPtr, infoPtr->root);
+ DPA_Destroy(infoPtr->items);
/* tool tip is automatically destroyed: we are its owner */
CloseThemeData (GetWindowTheme (infoPtr->hwnd));
/* Deassociate treeview from the window before doing anything drastic. */
- SetWindowLongPtrW(infoPtr->hwnd, 0, (DWORD_PTR)NULL);
+ SetWindowLongPtrW(infoPtr->hwnd, 0, 0);
DeleteObject(infoPtr->hDefaultFont);
static LRESULT
TREEVIEW_MouseLeave (TREEVIEW_INFO * infoPtr)
{
- if (infoPtr->hotItem)
- {
- /* remove hot effect from item */
- InvalidateRect(infoPtr->hwnd, &infoPtr->hotItem->rect, TRUE);
- infoPtr->hotItem = NULL;
- }
+ /* remove hot effect from item */
+ TREEVIEW_InvalidateItem(infoPtr, infoPtr->hotItem);
+ infoPtr->hotItem = NULL;
+
return 0;
}
static LRESULT
-TREEVIEW_MouseMove (TREEVIEW_INFO * infoPtr, WPARAM wParam, LPARAM lParam)
+TREEVIEW_MouseMove (TREEVIEW_INFO * infoPtr, LPARAM lParam)
{
POINT pt;
TRACKMOUSEEVENT trackinfo;
TREEVIEW_ITEM * item;
+ if (!(infoPtr->dwStyle & TVS_TRACKSELECT)) return 0;
+
/* fill in the TRACKMOUSEEVENT struct */
trackinfo.cbSize = sizeof(TRACKMOUSEEVENT);
trackinfo.dwFlags = TME_QUERY;
trackinfo.hwndTrack = infoPtr->hwnd;
- trackinfo.dwHoverTime = HOVER_DEFAULT;
/* call _TrackMouseEvent to see if we are currently tracking for this hwnd */
_TrackMouseEvent(&trackinfo);
if(!(trackinfo.dwFlags & TME_LEAVE))
{
trackinfo.dwFlags = TME_LEAVE; /* notify upon leaving */
+ trackinfo.hwndTrack = infoPtr->hwnd;
+ /* do it as fast as possible, minimal systimer latency will be used */
+ trackinfo.dwHoverTime = 1;
/* call TRACKMOUSEEVENT so we receive a WM_MOUSELEAVE message */
/* and can properly deactivate the hot item */
if (item != infoPtr->hotItem)
{
/* redraw old hot item */
- if (infoPtr->hotItem)
- InvalidateRect(infoPtr->hwnd, &infoPtr->hotItem->rect, TRUE);
+ TREEVIEW_InvalidateItem(infoPtr, infoPtr->hotItem);
infoPtr->hotItem = item;
/* redraw new hot item */
- if (infoPtr->hotItem)
- InvalidateRect(infoPtr->hwnd, &infoPtr->hotItem->rect, TRUE);
+ TREEVIEW_InvalidateItem(infoPtr, infoPtr->hotItem);
}
return 0;
}
/* Draw themed border */
-static BOOL nc_paint (const TREEVIEW_INFO *infoPtr, HRGN region)
+static BOOL TREEVIEW_NCPaint (const TREEVIEW_INFO *infoPtr, HRGN region, LPARAM lParam)
{
HTHEME theme = GetWindowTheme (infoPtr->hwnd);
HDC dc;
int cxEdge = GetSystemMetrics (SM_CXEDGE),
cyEdge = GetSystemMetrics (SM_CYEDGE);
- if (!theme) return FALSE;
+ if (!theme)
+ return DefWindowProcW (infoPtr->hwnd, WM_NCPAINT, (WPARAM)region, lParam);
GetWindowRect(infoPtr->hwnd, &r);
return DefWindowProcW(infoPtr->hwnd, WM_NOTIFY, wParam, lParam);
}
-static INT TREEVIEW_NotifyFormat (TREEVIEW_INFO *infoPtr, HWND hwndFrom, UINT nCommand)
-{
- INT format;
-
- TRACE("(hwndFrom=%p, nCommand=%d)\n", hwndFrom, nCommand);
-
- if (nCommand != NF_REQUERY) return 0;
-
- format = SendMessageW(hwndFrom, WM_NOTIFYFORMAT, (WPARAM)infoPtr->hwnd, NF_QUERY);
- TRACE("format=%d\n", format);
-
- if (format != NFR_ANSI && format != NFR_UNICODE) return 0;
-
- infoPtr->bNtfUnicode = (format == NFR_UNICODE);
-
- return format;
-}
-
static LRESULT
TREEVIEW_Size(TREEVIEW_INFO *infoPtr, WPARAM wParam, LPARAM lParam)
{
{
POINT pt;
TREEVIEW_ITEM * item;
+ NMMOUSE nmmouse;
GetCursorPos(&pt);
ScreenToClient(infoPtr->hwnd, &pt);
item = TREEVIEW_HitTestPoint(infoPtr, pt);
- /* FIXME: send NM_SETCURSOR */
+ memset(&nmmouse, 0, sizeof(nmmouse));
+ nmmouse.hdr.hwndFrom = infoPtr->hwnd;
+ nmmouse.hdr.idFrom = GetWindowLongPtrW(infoPtr->hwnd, GWLP_ID);
+ nmmouse.hdr.code = NM_SETCURSOR;
+ if (item)
+ {
+ nmmouse.dwItemSpec = (DWORD_PTR)item;
+ nmmouse.dwItemData = item->lParam;
+ }
+ nmmouse.pt.x = 0;
+ nmmouse.pt.y = 0;
+ nmmouse.dwHitInfo = lParam;
+ if (TREEVIEW_SendRealNotify(infoPtr, nmmouse.hdr.idFrom, (LPARAM)&nmmouse))
+ return 0;
if (item && (infoPtr->dwStyle & TVS_TRACKSELECT))
{
}
/* update theme after a WM_THEMECHANGED message */
-static LRESULT theme_changed(const TREEVIEW_INFO *infoPtr)
+static LRESULT TREEVIEW_ThemeChanged(const TREEVIEW_INFO *infoPtr)
{
HTHEME theme = GetWindowTheme (infoPtr->hwnd);
CloseThemeData (theme);
switch (uMsg)
{
case TVM_CREATEDRAGIMAGE:
- return TREEVIEW_CreateDragImage(infoPtr, wParam, lParam);
+ return TREEVIEW_CreateDragImage(infoPtr, lParam);
case TVM_DELETEITEM:
return TREEVIEW_DeleteItem(infoPtr, (HTREEITEM)lParam);
case TVM_EDITLABELA:
- return (LRESULT)TREEVIEW_EditLabel(infoPtr, (HTREEITEM)lParam);
-
case TVM_EDITLABELW:
return (LRESULT)TREEVIEW_EditLabel(infoPtr, (HTREEITEM)lParam);
return 0;
case TVM_GETITEMA:
- return TREEVIEW_GetItemT(infoPtr, (LPTVITEMEXW)lParam, FALSE);
-
case TVM_GETITEMW:
- return TREEVIEW_GetItemT(infoPtr, (LPTVITEMEXW)lParam, TRUE);
-
+ return TREEVIEW_GetItemT(infoPtr, (LPTVITEMEXW)lParam,
+ uMsg == TVM_GETITEMW);
case TVM_GETITEMHEIGHT:
return TREEVIEW_GetItemHeight(infoPtr);
return TREEVIEW_HitTest(infoPtr, (LPTVHITTESTINFO)lParam);
case TVM_INSERTITEMA:
- return TREEVIEW_InsertItemT(infoPtr, (LPTVINSERTSTRUCTW)lParam, FALSE);
-
case TVM_INSERTITEMW:
- return TREEVIEW_InsertItemT(infoPtr, (LPTVINSERTSTRUCTW)lParam, TRUE);
-
+ return TREEVIEW_InsertItemT(infoPtr, (LPTVINSERTSTRUCTW)lParam,
+ uMsg == TVM_INSERTITEMW);
case TVM_SELECTITEM:
return TREEVIEW_SelectItem(infoPtr, (INT)wParam, (HTREEITEM)lParam);
return TREEVIEW_SetInsertMarkColor(infoPtr, (COLORREF)lParam);
case TVM_SETITEMA:
- return TREEVIEW_SetItemT(infoPtr, (LPTVITEMEXW)lParam, FALSE);
-
case TVM_SETITEMW:
- return TREEVIEW_SetItemT(infoPtr, (LPTVITEMEXW)lParam, TRUE);
-
+ return TREEVIEW_SetItemT(infoPtr, (LPTVITEMEXW)lParam,
+ uMsg == TVM_SETITEMW);
case TVM_SETLINECOLOR:
return TREEVIEW_SetLineColor(infoPtr, (COLORREF)lParam);
return TREEVIEW_SetUnicodeFormat(infoPtr, (BOOL)wParam);
case TVM_SORTCHILDREN:
- return TREEVIEW_SortChildren(infoPtr, wParam, lParam);
+ return TREEVIEW_SortChildren(infoPtr, lParam);
case TVM_SORTCHILDRENCB:
- return TREEVIEW_SortChildrenCB(infoPtr, wParam, (LPTVSORTCB)lParam);
+ return TREEVIEW_SortChildrenCB(infoPtr, (LPTVSORTCB)lParam);
case WM_CHAR:
- return TREEVIEW_ProcessLetterKeys( hwnd, wParam, lParam );
+ return TREEVIEW_ProcessLetterKeys(infoPtr, wParam, lParam);
case WM_COMMAND:
return TREEVIEW_Command(infoPtr, wParam, lParam);
return TREEVIEW_MouseLeave(infoPtr);
case WM_MOUSEMOVE:
- if (infoPtr->dwStyle & TVS_TRACKSELECT)
- return TREEVIEW_MouseMove(infoPtr, wParam, lParam);
- else
- return 0;
+ return TREEVIEW_MouseMove(infoPtr, lParam);
case WM_NCLBUTTONDOWN:
if (infoPtr->hwndEdit)
goto def;
case WM_NCPAINT:
- if (nc_paint (infoPtr, (HRGN)wParam))
- return 0;
- goto def;
+ return TREEVIEW_NCPaint (infoPtr, (HRGN)wParam, lParam);
case WM_NOTIFY:
return TREEVIEW_Notify(infoPtr, wParam, lParam);
return TREEVIEW_NotifyFormat(infoPtr, (HWND)wParam, (UINT)lParam);
case WM_PRINTCLIENT:
+ return TREEVIEW_PrintClient(infoPtr, (HDC)wParam, lParam);
+
case WM_PAINT:
- return TREEVIEW_Paint(infoPtr, wParam);
+ return TREEVIEW_Paint(infoPtr, (HDC)wParam);
case WM_RBUTTONDOWN:
return TREEVIEW_RButtonDown(infoPtr, lParam);
return TREEVIEW_SetFont(infoPtr, (HFONT)wParam, (BOOL)lParam);
case WM_SETREDRAW:
- return TREEVIEW_SetRedraw(infoPtr, wParam, lParam);
+ return TREEVIEW_SetRedraw(infoPtr, wParam);
case WM_SIZE:
return TREEVIEW_Size(infoPtr, wParam, lParam);
case WM_STYLECHANGED:
return TREEVIEW_StyleChanged(infoPtr, wParam, lParam);
- /* WM_SYSCOLORCHANGE */
+ case WM_SYSCOLORCHANGE:
+ COMCTL32_RefreshSysColors();
+ return 0;
/* WM_SYSKEYDOWN */
return TREEVIEW_HandleTimer(infoPtr, wParam);
case WM_THEMECHANGED:
- return theme_changed (infoPtr);
+ return TREEVIEW_ThemeChanged (infoPtr);
case WM_VSCROLL:
return TREEVIEW_VScroll(infoPtr, wParam);
/* WM_WININICHANGE */
case WM_MOUSEWHEEL:
- if (wParam & (MK_SHIFT | MK_CONTROL))
- goto def;
- return TREEVIEW_MouseWheel(infoPtr, wParam);
+ return TREEVIEW_MouseWheel(infoPtr, wParam, lParam);
case WM_DRAWITEM:
TRACE("drawItem\n");
default:
/* This mostly catches MFC and Delphi messages. :( */
- if ((uMsg >= WM_USER) && (uMsg < WM_APP))
+ if ((uMsg >= WM_USER) && (uMsg < WM_APP) && !COMCTL32_IsReflectedMessage(uMsg))
TRACE("Unknown msg %04x wp=%08lx lp=%08lx\n", uMsg, wParam, lParam);
def:
return DefWindowProcW(hwnd, uMsg, wParam, lParam);