* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
-#include "precomp.h"
-
+#include <stdarg.h>
+#include <stdio.h>
+
+#include "windef.h"
+#include "winbase.h"
+#include "wingdi.h"
+#include "winuser.h"
+#include "winnls.h"
+#include "winreg.h"
+#include "wine/commctrl.h"
+
+#include "wine/test.h"
+#include "v6util.h"
+#include "msg.h"
+
+static BOOL (WINAPI *pInitCommonControlsEx)(const INITCOMMONCONTROLSEX*);
static const char *TEST_CALLBACK_TEXT = "callback_text";
static TVITEMA g_item_expanding, g_item_expanded;
{ WM_RBUTTONDOWN, sent|wparam, MK_RBUTTON },
{ WM_CAPTURECHANGED, sent|defwinproc },
{ TVM_GETNEXTITEM, sent|wparam|lparam|defwinproc, TVGN_CARET, 0 },
+ { WM_NCHITTEST, sent|optional },
+ { WM_SETCURSOR, sent|optional },
+ { WM_MOUSEMOVE, sent|optional },
{ 0 }
};
static const struct message parent_right_click_seq[] = {
{ WM_NOTIFY, sent|id, 0, 0, NM_RCLICK },
{ WM_CONTEXTMENU, sent },
+ { WM_NOTIFY, sent|optional },
+ { WM_SETCURSOR, sent|optional },
{ 0 }
};
tvi.hItem = hRoot;
tvi.mask = TVIF_TEXT;
tvi.pszText = buf;
- tvi.cchTextMax = sizeof(buf)/sizeof(buf[0]);
+ tvi.cchTextMax = ARRAY_SIZE(buf);
ret = TreeView_GetItemA(hTree, &tvi);
expect(TRUE, ret);
ok(strcmp(tvi.pszText, TEST_CALLBACK_TEXT) == 0, "Callback item text mismatch %s vs %s\n",
HWND hTree;
CHAR szBuffer[80] = "Blah";
- int nBufferSize = sizeof(szBuffer)/sizeof(CHAR);
+ int nBufferSize = ARRAY_SIZE(szBuffer);
hTree = create_treeview_control(0);
fill_tree(hTree);
static void test_get_set_tooltips(void)
{
- HWND hwndLastToolTip = NULL;
- HWND hPopupTreeView;
- HWND hTree;
+ HWND hTree, tooltips, hwnd;
+ DWORD style;
+ int i;
+
+ /* TVS_NOTOOLTIPS */
+ hTree = create_treeview_control(TVS_NOTOOLTIPS);
+
+ tooltips = (HWND)SendMessageA(hTree, TVM_GETTOOLTIPS, 0, 0);
+ ok(tooltips == NULL, "Unexpected tooltip window %p.\n", tooltips);
+
+ tooltips = (HWND)SendMessageA(hTree, TVM_SETTOOLTIPS, 0, 0);
+ ok(tooltips == NULL, "Unexpected ret value %p.\n", tooltips);
+
+ /* Toggle style */
+ style = GetWindowLongA(hTree, GWL_STYLE);
+ SetWindowLongA(hTree, GWL_STYLE, style & ~TVS_NOTOOLTIPS);
+
+ tooltips = (HWND)SendMessageA(hTree, TVM_GETTOOLTIPS, 0, 0);
+ ok(IsWindow(tooltips), "Unexpected tooltip window %p.\n", tooltips);
+
+ style = GetWindowLongA(hTree, GWL_STYLE);
+ SetWindowLongA(hTree, GWL_STYLE, style | TVS_NOTOOLTIPS);
+
+ tooltips = (HWND)SendMessageA(hTree, TVM_GETTOOLTIPS, 0, 0);
+ ok(tooltips == NULL, "Unexpected tooltip window %p.\n", tooltips);
+
+ DestroyWindow(hTree);
+
+ /* Set some valid window, does not have to be tooltips class. */
+ hTree = create_treeview_control(TVS_NOTOOLTIPS);
+
+ hwnd = CreateWindowA(WC_STATICA, "Test", WS_VISIBLE|WS_CHILD, 5, 5, 100, 100, hMainWnd, NULL, NULL, 0);
+ ok(hwnd != NULL, "Failed to create child window.\n");
+
+ tooltips = (HWND)SendMessageA(hTree, TVM_SETTOOLTIPS, (WPARAM)hwnd, 0);
+ ok(tooltips == NULL, "Unexpected ret value %p.\n", tooltips);
+
+ tooltips = (HWND)SendMessageA(hTree, TVM_GETTOOLTIPS, 0, 0);
+ ok(tooltips == hwnd, "Unexpected tooltip window %p.\n", tooltips);
+
+ /* Externally set tooltips window, disable style. */
+ style = GetWindowLongA(hTree, GWL_STYLE);
+ SetWindowLongA(hTree, GWL_STYLE, style & ~TVS_NOTOOLTIPS);
+
+ tooltips = (HWND)SendMessageA(hTree, TVM_GETTOOLTIPS, 0, 0);
+ ok(IsWindow(tooltips) && tooltips != hwnd, "Unexpected tooltip window %p.\n", tooltips);
+ ok(IsWindow(hwnd), "Expected valid window.\n");
+
+ style = GetWindowLongA(hTree, GWL_STYLE);
+ SetWindowLongA(hTree, GWL_STYLE, style | TVS_NOTOOLTIPS);
+ ok(!IsWindow(tooltips), "Unexpected tooltip window %p.\n", tooltips);
+
+ tooltips = (HWND)SendMessageA(hTree, TVM_GETTOOLTIPS, 0, 0);
+ ok(tooltips == NULL, "Unexpected tooltip window %p.\n", tooltips);
+ ok(IsWindow(hwnd), "Expected valid window.\n");
+
+ DestroyWindow(hTree);
+ ok(IsWindow(hwnd), "Expected valid window.\n");
+
+ /* Set window, disable tooltips. */
+ hTree = create_treeview_control(0);
+
+ tooltips = (HWND)SendMessageA(hTree, TVM_SETTOOLTIPS, (WPARAM)hwnd, 0);
+ ok(IsWindow(tooltips), "Unexpected ret value %p.\n", tooltips);
+
+ style = GetWindowLongA(hTree, GWL_STYLE);
+ SetWindowLongA(hTree, GWL_STYLE, style | TVS_NOTOOLTIPS);
+ ok(!IsWindow(hwnd), "Unexpected tooltip window %p.\n", tooltips);
+ ok(IsWindow(tooltips), "Expected valid window %p.\n", tooltips);
+
+ DestroyWindow(hTree);
+ ok(IsWindow(tooltips), "Expected valid window %p.\n", tooltips);
+ DestroyWindow(tooltips);
+ DestroyWindow(hwnd);
+
+ for (i = 0; i < 2; i++)
+ {
+ DWORD style = i == 0 ? 0 : TVS_NOTOOLTIPS;
+
+ hwnd = CreateWindowA(WC_STATICA, "Test", WS_VISIBLE|WS_CHILD, 5, 5, 100, 100, hMainWnd, NULL, NULL, 0);
+ ok(hwnd != NULL, "Failed to create child window.\n");
+
+ hTree = create_treeview_control(style);
+
+ tooltips = (HWND)SendMessageA(hTree, TVM_SETTOOLTIPS, (WPARAM)hwnd, 0);
+ ok(style & TVS_NOTOOLTIPS ? tooltips == NULL : IsWindow(tooltips), "Unexpected ret value %p.\n", tooltips);
+ DestroyWindow(tooltips);
+
+ tooltips = (HWND)SendMessageA(hTree, TVM_GETTOOLTIPS, 0, 0);
+ ok(tooltips == hwnd, "Unexpected tooltip window %p.\n", tooltips);
+
+ /* TreeView is destroyed, check if set window is still around. */
+ DestroyWindow(hTree);
+ ok(!IsWindow(hwnd), "Unexpected window.\n");
+ }
hTree = create_treeview_control(0);
fill_tree(hTree);
flush_sequences(sequences, NUM_MSG_SEQUENCES);
/* show even WS_POPUP treeview don't send NM_TOOLTIPSCREATED */
- hPopupTreeView = CreateWindowA(WC_TREEVIEWA, NULL, WS_POPUP|WS_VISIBLE, 0, 0, 100, 100,
+ hwnd = CreateWindowA(WC_TREEVIEWA, NULL, WS_POPUP|WS_VISIBLE, 0, 0, 100, 100,
hMainWnd, NULL, NULL, NULL);
- DestroyWindow(hPopupTreeView);
+ DestroyWindow(hwnd);
/* Testing setting a NULL ToolTip */
- SendMessageA(hTree, TVM_SETTOOLTIPS, 0, 0);
- hwndLastToolTip = (HWND)SendMessageA(hTree, TVM_GETTOOLTIPS, 0, 0);
- ok(hwndLastToolTip == NULL, "NULL tool tip, reported as 0x%p, expected 0.\n", hwndLastToolTip);
+ tooltips = (HWND)SendMessageA(hTree, TVM_SETTOOLTIPS, 0, 0);
+ ok(IsWindow(tooltips), "Unexpected ret value %p.\n", tooltips);
+
+ hwnd = (HWND)SendMessageA(hTree, TVM_GETTOOLTIPS, 0, 0);
+ ok(hwnd == NULL, "Unexpected tooltip window %p.\n", hwnd);
ok_sequence(sequences, TREEVIEW_SEQ_INDEX, test_get_set_tooltips_seq,
"test get set tooltips", TRUE);
- /* TODO: Add a test of an actual tooltip */
DestroyWindow(hTree);
+ ok(IsWindow(tooltips), "Expected valid window.\n");
+ DestroyWindow(tooltips);
}
static void test_get_set_unicodeformat(void)
visibleItem = (HTREEITEM)SendMessageA(pHdr->hwndFrom, TVM_GETNEXTITEM,
TVGN_NEXTVISIBLE, (LPARAM)visibleItem);
*(HTREEITEM*)&rect = visibleItem;
- ok(visibleItem != NULL, "There must be a visible item after the first visisble item.\n");
+ ok(visibleItem != NULL, "There must be a visible item after the first one.\n");
ok(SendMessageA(pHdr->hwndFrom, TVM_GETITEMRECT, TRUE, (LPARAM)&rect),
"Failed to get rect for second visible item.\n");
}
break;
}
- case WM_DESTROY:
- PostQuitMessage(0);
- break;
}
defwndproc_counter++;
DestroyWindow(hTree);
}
+static void test_expand(void)
+{
+ HTREEITEM first, second, last, child;
+ TVINSERTSTRUCTA ins;
+ BOOL visible;
+ RECT rect;
+ HWND tv;
+ int i;
+
+ tv = create_treeview_control(0);
+
+ ins.hParent = TVI_ROOT;
+ ins.hInsertAfter = TVI_LAST;
+ U(ins).item.mask = 0;
+ first = TreeView_InsertItemA(tv, &ins);
+ ok(first != NULL, "failed to insert first node\n");
+ second = TreeView_InsertItemA(tv, &ins);
+ ok(second != NULL, "failed to insert second node\n");
+ for (i=0; i<100; i++)
+ {
+ last = TreeView_InsertItemA(tv, &ins);
+ ok(last != NULL, "failed to insert %d node\n", i);
+ }
+
+ ins.hParent = second;
+ child = TreeView_InsertItemA(tv, &ins);
+ ok(child != NULL, "failed to insert child node\n");
+
+ ok(SendMessageA(tv, TVM_SELECTITEM, TVGN_CARET, (LPARAM)last), "last node selection failed\n");
+ ok(SendMessageA(tv, TVM_EXPAND, TVE_EXPAND, (LPARAM)second), "expand of second node failed\n");
+ ok(SendMessageA(tv, TVM_SELECTITEM, TVGN_CARET, (LPARAM)first), "first node selection failed\n");
+
+ *(HTREEITEM *)&rect = first;
+ visible = SendMessageA(tv, TVM_GETITEMRECT, FALSE, (LPARAM)&rect);
+ ok(visible, "first node should be visible\n");
+ ok(!rect.left, "rect.left = %d\n", rect.left);
+ ok(!rect.top, "rect.top = %d\n", rect.top);
+ ok(rect.right, "rect.right = 0\n");
+ ok(rect.bottom, "rect.bottom = 0\n");
+
+ DestroyWindow(tv);
+}
+
static void test_itemedit(void)
{
DWORD r;
item.mask = TVIF_TEXT;
item.hItem = hRoot;
item.pszText = buffA;
- item.cchTextMax = sizeof(buffA)/sizeof(CHAR);
+ item.cchTextMax = ARRAY_SIZE(buffA);
r = SendMessageA(hTree, TVM_GETITEMA, 0, (LPARAM)&item);
expect(TRUE, r);
ok(!strcmp("x", buffA), "Expected item text to change\n");
ok(IsWindow(edit), "Expected valid handle\n");
g_beginedit_alter_text = FALSE;
- GetWindowTextA(edit, buffA, sizeof(buffA)/sizeof(CHAR));
+ GetWindowTextA(edit, buffA, ARRAY_SIZE(buffA));
ok(!strcmp(buffA, "<edittextaltered>"), "got string %s\n", buffA);
DestroyWindow(hTree);
SetWindowLongA(hTree, GWL_STYLE, GetWindowLongA(hTree, GWL_STYLE) | TVS_SINGLEEXPAND);
/* to avoid painting related notifications */
ShowWindow(hTree, SW_HIDE);
- for (i = 0; i < sizeof(items)/sizeof(items[0]); i++)
+ for (i = 0; i < ARRAY_SIZE(items); i++)
{
ins.hParent = items[i].parent ? *items[i].parent : TVI_ROOT;
ins.hInsertAfter = TVI_FIRST;
*items[i].handle = TreeView_InsertItemA(hTree, &ins);
}
- for (i = 0; i < sizeof(sequence_tests)/sizeof(sequence_tests[0]); i++)
+ for (i = 0; i < ARRAY_SIZE(sequence_tests); i++)
{
flush_sequences(sequences, NUM_MSG_SEQUENCES);
ret = SendMessageA(hTree, TVM_SELECTITEM, TVGN_CARET, (LPARAM)(*sequence_tests[i].select));
ok_sequence(sequences, PARENT_SEQ_INDEX, sequence_tests[i].sequence, context, FALSE);
}
- for (i = 0; i < sizeof(items)/sizeof(items[0]); i++)
+ for (i = 0; i < ARRAY_SIZE(items); i++)
{
ret = SendMessageA(hTree, TVM_GETITEMSTATE, (WPARAM)(*items[i].handle), 0xFFFF);
ok(ret == items[i].final_state, "singleexpand items[%d]: expected state 0x%x got 0x%x\n",
HTREEITEM parent; /* for root value of parent field is unidetified */
HTREEITEM nextsibling;
HTREEITEM firstchild;
+ void *unk[2];
+ DWORD unk2;
+ WORD pad;
+ WORD width;
};
-static void _check_item(HTREEITEM item, HTREEITEM parent, HTREEITEM nextsibling, HTREEITEM firstchild, int line)
+struct _ITEM_DATA_V6
{
- struct _ITEM_DATA *data = (struct _ITEM_DATA*)item;
+ HTREEITEM parent; /* for root value of parent field is unidetified */
+ HTREEITEM nextsibling;
+ HTREEITEM firstchild;
+ void *unk[3];
+ DWORD unk2[2];
+ WORD pad;
+ WORD width;
+};
- ok_(__FILE__, line)(data->parent == parent, "parent %p, got %p\n", parent, data->parent);
- ok_(__FILE__, line)(data->nextsibling == nextsibling, "sibling %p, got %p\n", nextsibling, data->nextsibling);
- ok_(__FILE__, line)(data->firstchild == firstchild, "firstchild %p, got %p\n", firstchild, data->firstchild);
+static void _check_item(HWND hwnd, HTREEITEM item, BOOL is_version_6, int line)
+{
+ struct _ITEM_DATA *data = (struct _ITEM_DATA *)item;
+ HTREEITEM parent, nextsibling, firstchild, root;
+ RECT rect;
+ BOOL ret;
+
+ root = (HTREEITEM)SendMessageA(hwnd, TVM_GETNEXTITEM, TVGN_ROOT, (LPARAM)item);
+ parent = (HTREEITEM)SendMessageA(hwnd, TVM_GETNEXTITEM, TVGN_PARENT, (LPARAM)item);
+ nextsibling = (HTREEITEM)SendMessageA(hwnd, TVM_GETNEXTITEM, TVGN_NEXT, (LPARAM)item);
+ firstchild = (HTREEITEM)SendMessageA(hwnd, TVM_GETNEXTITEM, TVGN_CHILD, (LPARAM)item);
+
+ *(HTREEITEM*)&rect = item;
+ ret = SendMessageA(hwnd, TVM_GETITEMRECT, TRUE, (LPARAM)&rect);
+
+ ok_(__FILE__, line)(item == root ? data->parent != NULL : data->parent == parent,
+ "Unexpected parent item %p, got %p, %p\n", parent, data->parent, hwnd);
+ ok_(__FILE__, line)(data->nextsibling == nextsibling, "Unexpected sibling %p, got %p\n",
+ nextsibling, data->nextsibling);
+ ok_(__FILE__, line)(data->firstchild == firstchild, "Unexpected first child %p, got %p\n",
+ firstchild, data->firstchild);
+ if (ret)
+ {
+ WORD width;
+
+ if (is_version_6)
+ {
+ struct _ITEM_DATA_V6 *data_v6 = (struct _ITEM_DATA_V6 *)item;
+ width = data_v6->width;
+ }
+ else
+ width = data->width;
+ todo_wine
+ ok_(__FILE__, line)(width == (rect.right - rect.left) || broken(is_version_6 && width == 0) /* XP */,
+ "Width %d, rect width %d.\n", width, rect.right - rect.left);
+ }
}
-#define check_item(a, b, c, d) _check_item(a, b, c, d, __LINE__)
+#define CHECK_ITEM(a, b) _check_item(a, b, is_version_6, __LINE__)
-static void test_htreeitem_layout(void)
+static void test_htreeitem_layout(BOOL is_version_6)
{
TVINSERTSTRUCTA ins;
HTREEITEM item1, item2;
fill_tree(hTree);
/* root has some special pointer in parent field */
- check_item(hRoot, ((struct _ITEM_DATA*)hRoot)->parent, 0, hChild);
- check_item(hChild, hRoot, 0, 0);
+ CHECK_ITEM(hTree, hRoot);
+ CHECK_ITEM(hTree, hChild);
ins.hParent = hChild;
ins.hInsertAfter = TVI_FIRST;
U(ins).item.mask = 0;
item1 = TreeView_InsertItemA(hTree, &ins);
- check_item(item1, hChild, 0, 0);
+ CHECK_ITEM(hTree, item1);
ins.hParent = hRoot;
ins.hInsertAfter = TVI_FIRST;
U(ins).item.mask = 0;
item2 = TreeView_InsertItemA(hTree, &ins);
- check_item(item2, hRoot, hChild, 0);
+ CHECK_ITEM(hTree, item2);
SendMessageA(hTree, TVM_DELETEITEM, 0, (LPARAM)hChild);
/* without children now */
- check_item(hRoot, ((struct _ITEM_DATA*)hRoot)->parent, 0, item2);
+ CHECK_ITEM(hTree, hRoot);
DestroyWindow(hTree);
}
HTREEITEM selected;
RECT rc;
LRESULT result;
- POINT pt;
+ POINT pt, orig_pos;
hTree = create_treeview_control(0);
fill_tree(hTree);
pt.x = (rc.left + rc.right) / 2;
pt.y = (rc.top + rc.bottom) / 2;
ClientToScreen(hMainWnd, &pt);
+ GetCursorPos(&orig_pos);
+ SetCursorPos(pt.x, pt.y);
flush_events();
flush_sequences(sequences, NUM_MSG_SEQUENCES);
selected = (HTREEITEM)SendMessageA(hTree, TVM_GETNEXTITEM, TVGN_CARET, 0);
ok(selected == hChild, "child item should still be selected\n");
+ SetCursorPos(orig_pos.x, orig_pos.y);
DestroyWindow(hTree);
}
-START_TEST(treeview)
+static void init_functions(void)
{
- HMODULE hComctl32;
- BOOL (WINAPI *pInitCommonControlsEx)(const INITCOMMONCONTROLSEX*);
- WNDCLASSA wc;
- MSG msg;
+ HMODULE hComCtl32 = LoadLibraryA("comctl32.dll");
+#define X(f) p##f = (void*)GetProcAddress(hComCtl32, #f);
+ X(InitCommonControlsEx);
+#undef X
+}
+
+START_TEST(treeview)
+{
+ INITCOMMONCONTROLSEX iccex;
ULONG_PTR ctx_cookie;
HANDLE hCtx;
-
- hComctl32 = GetModuleHandleA("comctl32.dll");
- pInitCommonControlsEx = (void*)GetProcAddress(hComctl32, "InitCommonControlsEx");
- if (pInitCommonControlsEx)
- {
- INITCOMMONCONTROLSEX iccex;
- iccex.dwSize = sizeof(iccex);
- iccex.dwICC = ICC_TREEVIEW_CLASSES;
- pInitCommonControlsEx(&iccex);
- }
- else
- InitCommonControls();
+ WNDCLASSA wc;
+
+ init_functions();
+
+ iccex.dwSize = sizeof(iccex);
+ iccex.dwICC = ICC_TREEVIEW_CLASSES;
+ pInitCommonControlsEx(&iccex);
init_msg_sequences(sequences, NUM_MSG_SEQUENCES);
init_msg_sequences(item_sequence, 1);
test_WM_PAINT();
test_delete_items();
test_cchildren();
- test_htreeitem_layout();
+ test_htreeitem_layout(FALSE);
test_TVS_CHECKBOXES();
test_TVM_GETNEXTITEM();
test_TVM_HITTEST();
/* comctl32 version 6 tests start here */
g_v6 = TRUE;
+
+ test_fillroot();
+ test_getitemtext();
+ test_get_set_insertmark();
+ test_get_set_item();
+ test_get_set_scrolltime();
+ test_get_set_textcolor();
+ test_get_linecolor();
+ test_get_insertmarkcolor();
test_expandedimage();
- test_htreeitem_layout();
+ test_get_set_tooltips();
+ test_get_set_unicodeformat();
+ test_expandinvisible();
+ test_expand();
+ test_itemedit();
+ test_treeview_classinfo();
+ test_delete_items();
+ test_cchildren();
+ test_htreeitem_layout(TRUE);
+ test_TVM_GETNEXTITEM();
+ test_TVM_HITTEST();
test_WM_GETDLGCODE();
+ test_customdraw();
+ test_WM_KEYDOWN();
+ test_TVS_FULLROWSELECT();
+ test_TVM_SORTCHILDREN();
unload_v6_module(ctx_cookie, hCtx);
-
- PostMessageA(hMainWnd, WM_CLOSE, 0, 0);
- while(GetMessageA(&msg, 0, 0, 0))
- {
- TranslateMessage(&msg);
- DispatchMessageA(&msg);
- }
}