* 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_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 *****************************************************/
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);
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 ********************************************************/
newItem->parent = parentItem;
newItem->iIntegral = 1;
+ newItem->visibleOrder = -1;
if (!TREEVIEW_DoSetItemT(infoPtr, newItem, tvItem, isW))
return 0;
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)
{
static LRESULT
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);
& (TVS_LINESATROOT|TVS_HASLINES|TVS_HASBUTTONS))
> TVS_LINESATROOT);
HBRUSH hbr, hbrOld;
- COLORREF clrBk = infoPtr->clrBk == -1 ? GetSysColor(COLOR_WINDOW):
- infoPtr->clrBk;
+ COLORREF clrBk = GETBKCOLOR(infoPtr->clrBk);
if (!lar && item->iLevel == 0)
return;
hbr = CreateSolidBrush(clrBk);
hbrOld = SelectObject(hdc, hbr);
-
+
centerx = (item->linesOffset + item->stateOffset) / 2;
centery = (item->rect.top + item->rect.bottom) / 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);
LONG rectsize = min(height, width) / 4;
/* 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);
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 == -1 ? GetSysColor(COLOR_WINDOW):
- 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));
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;
- COLORREF clrBk = infoPtr->clrBk == -1 ? GetSysColor(COLOR_WINDOW):
- infoPtr->clrBk;
RECT rect;
- hBrush = CreateSolidBrush(clrBk);
+ TRACE("%p\n", infoPtr);
+
GetClientRect(infoPtr->hwnd, &rect);
- FillRect(hDC, &rect, hBrush);
- DeleteObject(hBrush);
+ TREEVIEW_FillBkgnd(infoPtr, hdc, &rect);
return 1;
}
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;
- GetClientRect(infoPtr->hwnd, &rc);
- TREEVIEW_EraseBackground(infoPtr, hdc);
+ hdc = hdc_ref;
+ GetClientRect(infoPtr->hwnd, &rc);
}
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 **************************************************************/
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;
HFONT hFont, hOldFont = 0;
+ TRACE("edit=%p\n", infoPtr->hwndEdit);
+
+ if (!IsWindow(infoPtr->hwndEdit) || !hdc) return FALSE;
+
infoPtr->bLabelChanged = TRUE;
GetWindowTextW(infoPtr->hwndEdit, buffer, sizeof(buffer)/sizeof(buffer[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 */
- if (editItem->pszText)
- GetTextExtentPoint32W(hdc, editItem->pszText, strlenW(editItem->pszText),
+ if (hItem->pszText)
+ GetTextExtentPoint32W(hdc, hItem->pszText, strlenW(hItem->pszText),
&sz);
else
GetTextExtentPoint32A(hdc, "", 0, &sz);
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;
-
- if (editItem->pszText)
- SetWindowTextW(hwndEdit, editItem->pszText);
+ if (hItem->pszText)
+ SetWindowTextW(hwndEdit, hItem->pszText);
SetFocus(hwndEdit);
SendMessageW(hwndEdit, EM_SETSEL, 0, -1);
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);
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, &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;
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,
*
* 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) &&
}
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);
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 = -1; /* use system color */
- 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;
{
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 */
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;
}
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);
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_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, 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);
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");