diff --git a/rostests/winetests/comctl32/CMakeLists.txt b/rostests/winetests/comctl32/CMakeLists.txt index 006fadc66a8..47d677d1533 100644 --- a/rostests/winetests/comctl32/CMakeLists.txt +++ b/rostests/winetests/comctl32/CMakeLists.txt @@ -24,6 +24,7 @@ list(APPEND SOURCE subclass.c syslink.c tab.c + taskdialog.c toolbar.c tooltips.c trackbar.c diff --git a/rostests/winetests/comctl32/animate.c b/rostests/winetests/comctl32/animate.c index 0bb90a412f7..28cf55b9587 100644 --- a/rostests/winetests/comctl32/animate.c +++ b/rostests/winetests/comctl32/animate.c @@ -160,8 +160,9 @@ static void test_play(void) SetLastError(0xdeadbeef); res = SendMessageA(hAnimateWnd, ACM_PLAY, (WPARAM) -1, MAKELONG(0, -1)); + err = GetLastError(); ok(res == 0, "Play should have failed\n"); - ok(err == ERROR_RESOURCE_NAME_NOT_FOUND, "Expected 1814, got %u\n", err); + ok(err == 0xdeadbeef, "Expected 0xdeadbeef, got %u\n", err); destroy_animate(); create_animate(0, 0); diff --git a/rostests/winetests/comctl32/button.c b/rostests/winetests/comctl32/button.c index de813773c65..8cb5b5fc9b0 100644 --- a/rostests/winetests/comctl32/button.c +++ b/rostests/winetests/comctl32/button.c @@ -124,8 +124,8 @@ static BOOL ignore_message( UINT message ) static LRESULT CALLBACK button_subclass_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam, UINT_PTR id, DWORD_PTR ref_data) { static LONG defwndproc_counter = 0; + struct message msg = { 0 }; LRESULT ret; - struct message msg; if (ignore_message( message )) return pDefSubclassProc(hwnd, message, wParam, lParam); @@ -160,8 +160,8 @@ static LRESULT WINAPI test_parent_wndproc(HWND hwnd, UINT message, WPARAM wParam { static LONG defwndproc_counter = 0; static LONG beginpaint_counter = 0; + struct message msg = { 0 }; LRESULT ret; - struct message msg; if (ignore_message( message )) return 0; @@ -171,17 +171,6 @@ static LRESULT WINAPI test_parent_wndproc(HWND hwnd, UINT message, WPARAM wParam message == WM_DRAWITEM || message == WM_COMMAND || message == WM_IME_SETCONTEXT) { - switch (message) - { - /* ignore */ - case WM_NCHITTEST: - return HTCLIENT; - case WM_SETCURSOR: - case WM_MOUSEMOVE: - case WM_NCMOUSEMOVE: - return 0; - } - msg.message = message; msg.flags = sent|parent|wparam|lparam; if (defwndproc_counter) msg.flags |= defwinproc; diff --git a/rostests/winetests/comctl32/comboex.c b/rostests/winetests/comctl32/comboex.c index 23868eb6b17..ec13e22801a 100644 --- a/rostests/winetests/comctl32/comboex.c +++ b/rostests/winetests/comctl32/comboex.c @@ -90,8 +90,8 @@ static LRESULT WINAPI editbox_subclass_proc(HWND hwnd, UINT message, WPARAM wPar { WNDPROC oldproc = (WNDPROC)GetWindowLongPtrA(hwnd, GWLP_USERDATA); static LONG defwndproc_counter = 0; + struct message msg = { 0 }; LRESULT ret; - struct message msg; msg.message = message; msg.flags = sent|wparam|lparam; diff --git a/rostests/winetests/comctl32/datetime.c b/rostests/winetests/comctl32/datetime.c index c0ea37425f0..fcd7bee1439 100644 --- a/rostests/winetests/comctl32/datetime.c +++ b/rostests/winetests/comctl32/datetime.c @@ -142,15 +142,14 @@ static LRESULT WINAPI datetime_subclass_proc(HWND hwnd, UINT message, WPARAM wPa { WNDPROC oldproc = (WNDPROC)GetWindowLongPtrA(hwnd, GWLP_USERDATA); static LONG defwndproc_counter = 0; + struct message msg = { 0 }; LRESULT ret; - struct message msg; msg.message = message; msg.flags = sent|wparam|lparam; if (defwndproc_counter) msg.flags |= defwinproc; msg.wParam = wParam; msg.lParam = lParam; - msg.id = 0; add_message(sequences, DATETIME_SEQ_INDEX, &msg); defwndproc_counter++; diff --git a/rostests/winetests/comctl32/header.c b/rostests/winetests/comctl32/header.c index ab485e3fa3c..8be4db27dd3 100644 --- a/rostests/winetests/comctl32/header.c +++ b/rostests/winetests/comctl32/header.c @@ -394,7 +394,7 @@ static char pszOutOfRangeItem[] = "Out Of Range Item"; static char *str_items[] = {pszFirstItem, pszSecondItem, pszThirdItem, pszFourthItem, pszReplaceItem, pszOutOfRangeItem}; - + static char pszUniTestA[] = "TST"; static WCHAR pszUniTestW[] = {'T','S','T',0}; @@ -414,15 +414,14 @@ static LRESULT WINAPI header_subclass_proc(HWND hwnd, UINT message, WPARAM wPara { WNDPROC oldproc = (WNDPROC)GetWindowLongPtrA(hwnd, GWLP_USERDATA); static LONG defwndproc_counter = 0; + struct message msg = { 0 }; LRESULT ret; - struct message msg; msg.message = message; msg.flags = sent|wparam|lparam; if (defwndproc_counter) msg.flags |= defwinproc; msg.wParam = wParam; msg.lParam = lParam; - msg.id = 0; add_message(sequences, HEADER_SEQ_INDEX, &msg); defwndproc_counter++; @@ -1572,7 +1571,6 @@ static void test_header_order (void) { hdi.lParam = i; SendMessageA(hWndHeader, HDM_INSERTITEMA, rand1[i], (LPARAM)&hdi); - rand(); } check_order(ids1, ord1, 5, "insert without iOrder"); @@ -1582,7 +1580,6 @@ static void test_header_order (void) hdi.lParam = i + 5; hdi.iOrder = rand2[i]; SendMessageA(hWndHeader, HDM_INSERTITEMA, rand3[i], (LPARAM)&hdi); - rand(); rand(); } check_order(ids2, ord2, 10, "insert with order"); @@ -1591,7 +1588,6 @@ static void test_header_order (void) { hdi.iOrder = rand5[i]; SendMessageA(hWndHeader, HDM_SETITEMA, rand4[i], (LPARAM)&hdi); - rand(); rand(); } check_order(ids2, ord3, 10, "setitems changing order"); diff --git a/rostests/winetests/comctl32/imagelist.c b/rostests/winetests/comctl32/imagelist.c index ddcecbd336a..3ffa68be6a5 100644 --- a/rostests/winetests/comctl32/imagelist.c +++ b/rostests/winetests/comctl32/imagelist.c @@ -922,36 +922,34 @@ static void check_iml_data(HIMAGELIST himl, INT cx, INT cy, INT cur, INT max, IN char *data; HRESULT hr; - trace("%s\n", comment); - ret = ImageList_GetImageCount(himl); - ok(ret == cur, "expected image count %d got %d\n", cur, ret); + ok(ret == cur, "%s: expected image count %d got %d\n", comment, cur, ret); ret = ImageList_GetIconSize(himl, &cxx, &cyy); ok(ret, "ImageList_GetIconSize failed\n"); - ok(cxx == cx, "wrong cx %d (expected %d)\n", cxx, cx); - ok(cyy == cy, "wrong cy %d (expected %d)\n", cyy, cy); + ok(cxx == cx, "%s: wrong cx %d (expected %d)\n", comment, cxx, cx); + ok(cyy == cy, "%s: wrong cy %d (expected %d)\n", comment, cyy, cy); init_memstream(&stream); ret = ImageList_Write(himl, &stream.IStream_iface); - ok(ret, "ImageList_Write failed\n"); + ok(ret, "%s: ImageList_Write failed\n", comment); hr = GetHGlobalFromStream(stream.stream, &hglobal); - ok(hr == S_OK, "Failed to get hglobal, %#x\n", hr); + ok(hr == S_OK, "%s: Failed to get hglobal, %#x\n", comment, hr); IStream_Stat(stream.stream, &stat, STATFLAG_NONAME); data = GlobalLock(hglobal); - ok(data != 0, "ImageList_Write didn't write any data\n"); - ok(stat.cbSize.LowPart > sizeof(ILHEAD), "ImageList_Write wrote not enough data\n"); + ok(data != 0, "%s: ImageList_Write didn't write any data\n", comment); + ok(stat.cbSize.LowPart > sizeof(ILHEAD), "%s: ImageList_Write wrote not enough data\n", comment); check_ilhead_data(data, cx, cy, cur, max, grow, flags); size = check_bitmap_data(data + sizeof(ILHEAD), stat.cbSize.LowPart - sizeof(ILHEAD), width, height, flags & 0xfe, comment); if (size < stat.cbSize.LowPart - sizeof(ILHEAD)) /* mask is present */ { - ok( flags & ILC_MASK, "extra data %u/%u but mask not expected\n", stat.cbSize.LowPart, size ); + ok( flags & ILC_MASK, "%s: extra data %u/%u but mask not expected\n", comment, stat.cbSize.LowPart, size ); check_bitmap_data(data + sizeof(ILHEAD) + size, stat.cbSize.LowPart - sizeof(ILHEAD) - size, width, height, 1, comment); } @@ -960,7 +958,7 @@ static void check_iml_data(HIMAGELIST himl, INT cx, INT cy, INT cur, INT max, IN mv.QuadPart = 0; IStream_Seek(stream.stream, mv, STREAM_SEEK_SET, NULL); himl2 = ImageList_Read(&stream.IStream_iface); - ok(himl2 != NULL, "Failed to deserialize imagelist\n"); + ok(himl2 != NULL, "%s: Failed to deserialize imagelist\n", comment); ImageList_Destroy(himl2); GlobalUnlock(hglobal); @@ -2220,6 +2218,29 @@ static void test_color_table(UINT ilc) ImageList_Destroy(himl); } +static void test_copy(void) +{ + HIMAGELIST dst, src; + BOOL ret; + int count; + + dst = ImageList_Create(5, 11, ILC_COLOR, 1, 1); + count = ImageList_GetImageCount(dst); + ok(!count, "ImageList not empty.\n"); + src = createImageList(7, 13); + count = ImageList_GetImageCount(src); + ok(count > 2, "Tests need an ImageList with more than 2 images\n"); + + /* ImageList_Copy() cannot copy between two ImageLists */ + ret = ImageList_Copy(dst, 0, src, 2, ILCF_MOVE); + ok(!ret, "ImageList_Copy() should have returned FALSE\n"); + count = ImageList_GetImageCount(dst); + ok(count == 0, "Expected no image in dst ImageList, got %d\n", count); + + ImageList_Destroy(dst); + ImageList_Destroy(src); +} + static void test_IImageList_Clone(void) { IImageList *imgl, *imgl2; @@ -2370,6 +2391,7 @@ START_TEST(imagelist) test_iconsize(); test_color_table(ILC_COLOR4); test_color_table(ILC_COLOR8); + test_copy(); FreeLibrary(hComCtl32); diff --git a/rostests/winetests/comctl32/listview.c b/rostests/winetests/comctl32/listview.c index 2c4a7f36818..ba3700fead2 100644 --- a/rostests/winetests/comctl32/listview.c +++ b/rostests/winetests/comctl32/listview.c @@ -710,8 +710,8 @@ static LRESULT WINAPI header_subclass_proc(HWND hwnd, UINT message, WPARAM wPara { WNDPROC oldproc = (WNDPROC)GetWindowLongPtrA(hwnd, GWLP_USERDATA); static LONG defwndproc_counter = 0; + struct message msg = { 0 }; LRESULT ret; - struct message msg; msg.message = message; msg.flags = sent|wparam|lparam; @@ -744,15 +744,14 @@ static LRESULT WINAPI editbox_subclass_proc(HWND hwnd, UINT message, WPARAM wPar { WNDPROC oldproc = (WNDPROC)GetWindowLongPtrA(hwnd, GWLP_USERDATA); static LONG defwndproc_counter = 0; + struct message msg = { 0 }; LRESULT ret; - struct message msg; msg.message = message; msg.flags = sent|wparam|lparam; if (defwndproc_counter) msg.flags |= defwinproc; msg.wParam = wParam; msg.lParam = lParam; - msg.id = 0; /* all we need is sizing */ if (message == WM_WINDOWPOSCHANGING || @@ -5076,12 +5075,30 @@ static void test_finditem(void) fi.psz = f; r = SendMessageA(hwnd, LVM_FINDITEMA, -1, (LPARAM)&fi); expect(0, r); + + fi.flags = LVFI_STRING | LVFI_PARTIAL; + r = SendMessageA(hwnd, LVM_FINDITEMA, -1, (LPARAM)&fi); + expect(0, r); + + fi.flags = LVFI_PARTIAL; + r = SendMessageA(hwnd, LVM_FINDITEMA, -1, (LPARAM)&fi); + expect(0, r); + /* partial string search, inserted text was "foo" */ strcpy(f, "fo"); fi.flags = LVFI_STRING | LVFI_PARTIAL; fi.psz = f; r = SendMessageA(hwnd, LVM_FINDITEMA, -1, (LPARAM)&fi); expect(0, r); + + fi.flags = LVFI_STRING; + r = SendMessageA(hwnd, LVM_FINDITEMA, -1, (LPARAM)&fi); + expect(-1, r); + + fi.flags = LVFI_PARTIAL; + r = SendMessageA(hwnd, LVM_FINDITEMA, -1, (LPARAM)&fi); + expect(0, r); + /* partial string search, part after start char */ strcpy(f, "oo"); fi.flags = LVFI_STRING | LVFI_PARTIAL; @@ -5112,12 +5129,22 @@ static void test_finditem(void) r = SendMessageA(hwnd, LVM_FINDITEMA, -1, (LPARAM)&fi); expect(-1, r); + strcpy(f, "o"); + fi.flags = LVFI_SUBSTRING | LVFI_PARTIAL; + fi.psz = f; + r = SendMessageA(hwnd, LVM_FINDITEMA, -1, (LPARAM)&fi); + expect(-1, r); + strcpy(f, "f"); fi.flags = LVFI_SUBSTRING | LVFI_STRING; fi.psz = f; r = SendMessageA(hwnd, LVM_FINDITEMA, -1, (LPARAM)&fi); expect(0, r); + fi.flags = LVFI_SUBSTRING | LVFI_PARTIAL; + r = SendMessageA(hwnd, LVM_FINDITEMA, -1, (LPARAM)&fi); + expect(0, r); + DestroyWindow(hwnd); } @@ -5549,6 +5576,43 @@ static void test_LVM_SETITEMTEXT(void) DestroyWindow(hwnd); } +static void test_LVM_REDRAWITEMS(void) +{ + HWND list; + DWORD ret; + + list = create_listview_control(LVS_ICON); + ok(list != NULL, "failed to create listview window\n"); + + ret = SendMessageA(list, LVM_REDRAWITEMS, 0, 0); + expect(TRUE, ret); + + insert_item(list, 0); + + ret = SendMessageA(list, LVM_REDRAWITEMS, -1, 0); + expect(TRUE, ret); + + ret = SendMessageA(list, LVM_REDRAWITEMS, 0, -1); + expect(TRUE, ret); + + ret = SendMessageA(list, LVM_REDRAWITEMS, 0, 0); + expect(TRUE, ret); + + ret = SendMessageA(list, LVM_REDRAWITEMS, 0, 1); + expect(TRUE, ret); + + ret = SendMessageA(list, LVM_REDRAWITEMS, 0, 2); + expect(TRUE, ret); + + ret = SendMessageA(list, LVM_REDRAWITEMS, 1, 0); + expect(TRUE, ret); + + ret = SendMessageA(list, LVM_REDRAWITEMS, 2, 3); + expect(TRUE, ret); + + DestroyWindow(list); +} + static void test_imagelists(void) { HWND hwnd, header; @@ -5923,6 +5987,7 @@ START_TEST(listview) test_createdragimage(); test_dispinfo(); test_LVM_SETITEMTEXT(); + test_LVM_REDRAWITEMS(); test_imagelists(); test_deleteitem(); test_insertitem(); diff --git a/rostests/winetests/comctl32/misc.c b/rostests/winetests/comctl32/misc.c index 8b0781d1fcc..89fc5f73b5f 100644 --- a/rostests/winetests/comctl32/misc.c +++ b/rostests/winetests/comctl32/misc.c @@ -202,29 +202,6 @@ static void test_Alloc(void) ok(res == TRUE, "Expected TRUE, got %d\n", res); } -static void test_TaskDialogIndirect(void) -{ - HINSTANCE hinst; - void *ptr, *ptr2; - - hinst = LoadLibraryA("comctl32.dll"); - - ptr = GetProcAddress(hinst, "TaskDialogIndirect"); - if (!ptr) - { -#ifdef __REACTOS__ - /* Skipped on 2k3 */ - skip("TaskDialogIndirect not exported by name\n"); -#else - win_skip("TaskDialogIndirect not exported by name\n"); -#endif - return; - } - - ptr2 = GetProcAddress(hinst, (const CHAR*)345); - ok(ptr == ptr2, "got wrong pointer for ordinal 345, %p expected %p\n", ptr2, ptr); -} - static void test_LoadIconWithScaleDown(void) { static const WCHAR nonexisting_fileW[] = {'n','o','n','e','x','i','s','t','i','n','g','.','i','c','o',0}; @@ -413,7 +390,6 @@ START_TEST(misc) return; test_builtin_classes(); - test_TaskDialogIndirect(); test_LoadIconWithScaleDown(); unload_v6_module(ctx_cookie, hCtx); diff --git a/rostests/winetests/comctl32/monthcal.c b/rostests/winetests/comctl32/monthcal.c index ffe9d5d20a6..1ca593e6bbf 100644 --- a/rostests/winetests/comctl32/monthcal.c +++ b/rostests/winetests/comctl32/monthcal.c @@ -624,15 +624,14 @@ static LRESULT WINAPI monthcal_subclass_proc(HWND hwnd, UINT message, WPARAM wPa { WNDPROC oldproc = (WNDPROC)GetWindowLongPtrA(hwnd, GWLP_USERDATA); static LONG defwndproc_counter = 0; + struct message msg = { 0 }; LRESULT ret; - struct message msg; msg.message = message; msg.flags = sent|wparam|lparam; if (defwndproc_counter) msg.flags |= defwinproc; msg.wParam = wParam; msg.lParam = lParam; - msg.id = 0; add_message(sequences, MONTHCAL_SEQ_INDEX, &msg); /* some debug output for style changing */ diff --git a/rostests/winetests/comctl32/msg.h b/rostests/winetests/comctl32/msg.h index 2a2ee92508e..36327d1d724 100644 --- a/rostests/winetests/comctl32/msg.h +++ b/rostests/winetests/comctl32/msg.h @@ -371,7 +371,7 @@ static void ok_sequence_(struct msg_sequence **seq, int sequence_index, if(todo && !failcount) /* succeeded yet marked todo */ { - dump++; + if (!strcmp(winetest_platform, "wine")) dump++; todo_wine { ok_(file, line)(TRUE, "%s: marked \"todo_wine\" but succeeds\n", context); diff --git a/rostests/winetests/comctl32/pager.c b/rostests/winetests/comctl32/pager.c index 122742a39c8..4eb48be116f 100644 --- a/rostests/winetests/comctl32/pager.c +++ b/rostests/winetests/comctl32/pager.c @@ -30,7 +30,10 @@ #define NUM_MSG_SEQUENCES 1 #define PAGER_SEQ_INDEX 0 -static HWND parent_wnd; +static HWND parent_wnd, child1_wnd, child2_wnd; + +#define CHILD1_ID 1 +#define CHILD2_ID 2 static BOOL (WINAPI *pSetWindowSubclass)(HWND, SUBCLASSPROC, UINT_PTR, DWORD_PTR); @@ -42,6 +45,29 @@ static const struct message set_child_seq[] = { { WM_NCCALCSIZE, sent|wparam, TRUE }, { WM_NOTIFY, sent|id|parent, 0, 0, PGN_CALCSIZE }, { WM_WINDOWPOSCHANGED, sent }, + { WM_WINDOWPOSCHANGING, sent|id, 0, 0, CHILD1_ID }, + { WM_NCCALCSIZE, sent|wparam|id|optional, TRUE, 0, CHILD1_ID }, + { WM_CHILDACTIVATE, sent|id, 0, 0, CHILD1_ID }, + { WM_WINDOWPOSCHANGED, sent|id, 0, 0, CHILD1_ID }, + { WM_SIZE, sent|id|defwinproc|optional, 0, 0, CHILD1_ID }, + { 0 } +}; + +/* This differs from the above message list only in the child window that is + * expected to receive the child messages. No message is sent to the old child. + * Also child 2 is hidden while child 1 is visible. The pager does not make the + * hidden child visible. */ +static const struct message switch_child_seq[] = { + { PGM_SETCHILD, sent }, + { WM_WINDOWPOSCHANGING, sent }, + { WM_NCCALCSIZE, sent|wparam, TRUE }, + { WM_NOTIFY, sent|id|parent, 0, 0, PGN_CALCSIZE }, + { WM_WINDOWPOSCHANGED, sent }, + { WM_WINDOWPOSCHANGING, sent|id, 0, 0, CHILD2_ID }, + { WM_NCCALCSIZE, sent|wparam|id, TRUE, 0, CHILD2_ID }, + { WM_CHILDACTIVATE, sent|id, 0, 0, CHILD2_ID }, + { WM_WINDOWPOSCHANGED, sent|id, 0, 0, CHILD2_ID }, + { WM_SIZE, sent|id|defwinproc, 0, 0, CHILD2_ID }, { 0 } }; @@ -52,7 +78,20 @@ static const struct message set_pos_seq[] = { { WM_NOTIFY, sent|id|parent, 0, 0, PGN_CALCSIZE }, { WM_WINDOWPOSCHANGED, sent }, { WM_MOVE, sent|optional }, + /* The WM_SIZE handler sends WM_WINDOWPOSCHANGING, WM_CHILDACTIVATE + * and WM_WINDOWPOSCHANGED (which sends WM_MOVE) to the child. + * Another WM_WINDOWPOSCHANGING is sent afterwards. + * + * The 2nd WM_WINDOWPOSCHANGING is unconditional, but the comparison + * function is too simple to roll back an accepted message, so we have + * to mark the 2nd message optional. */ { WM_SIZE, sent|optional }, + { WM_WINDOWPOSCHANGING, sent|id, 0, 0, CHILD1_ID }, /* Actually optional. */ + { WM_CHILDACTIVATE, sent|id, 0, 0, CHILD1_ID }, /* Actually optional. */ + { WM_WINDOWPOSCHANGED, sent|id|optional, TRUE, 0, CHILD1_ID}, + { WM_MOVE, sent|id|optional|defwinproc, 0, 0, CHILD1_ID }, + { WM_WINDOWPOSCHANGING, sent|id|optional, 0, 0, CHILD1_ID }, /* Actually not optional. */ + { WM_CHILDACTIVATE, sent|id|optional, 0, 0, CHILD1_ID }, /* Actually not optional. */ { 0 } }; @@ -145,13 +184,12 @@ static HWND create_parent_window(void) static LRESULT WINAPI pager_subclass_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) { WNDPROC oldproc = (WNDPROC)GetWindowLongPtrA(hwnd, GWLP_USERDATA); - struct message msg; + struct message msg = { 0 }; msg.message = message; msg.flags = sent|wparam|lparam; msg.wParam = wParam; msg.lParam = lParam; - msg.id = 0; add_message(sequences, PAGER_SEQ_INDEX, &msg); return CallWindowProcA(oldproc, hwnd, message, wParam, lParam); } @@ -170,9 +208,55 @@ static HWND create_pager_control( DWORD style ) return hwnd; } +static LRESULT WINAPI child_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) +{ + static LONG defwndproc_counter; + struct message msg = { 0 }; + LRESULT ret; + + msg.message = message; + msg.flags = sent | wparam | lparam; + if (defwndproc_counter) + msg.flags |= defwinproc; + msg.wParam = wParam; + msg.lParam = lParam; + + if (hwnd == child1_wnd) + msg.id = CHILD1_ID; + else if (hwnd == child2_wnd) + msg.id = CHILD2_ID; + else + msg.id = 0; + + add_message(sequences, PAGER_SEQ_INDEX, &msg); + + defwndproc_counter++; + ret = DefWindowProcA(hwnd, message, wParam, lParam); + defwndproc_counter--; + + return ret; +} + +static BOOL register_child_wnd_class(void) +{ + WNDCLASSA cls; + + cls.style = 0; + cls.lpfnWndProc = child_proc; + cls.cbClsExtra = 0; + cls.cbWndExtra = 0; + cls.hInstance = GetModuleHandleA(NULL); + cls.hIcon = 0; + cls.hCursor = LoadCursorA(0, (LPCSTR)IDC_ARROW); + cls.hbrBackground = GetStockObject(WHITE_BRUSH); + cls.lpszMenuName = NULL; + cls.lpszClassName = "Pager test child class"; + return RegisterClassA(&cls); +} + static void test_pager(void) { - HWND pager, child; + HWND pager; RECT rect, rect2; pager = create_pager_control( PGS_HORZ ); @@ -181,16 +265,36 @@ static void test_pager(void) win_skip( "Pager control not supported\n" ); return; } - child = CreateWindowA( "BUTTON", "button", WS_CHILD | WS_BORDER | WS_VISIBLE, 0, 0, 300, 300, + + register_child_wnd_class(); + + child1_wnd = CreateWindowA( "Pager test child class", "button", WS_CHILD | WS_BORDER | WS_VISIBLE, 0, 0, 300, 300, pager, 0, GetModuleHandleA(0), 0 ); + child2_wnd = CreateWindowA("Pager test child class", "button", WS_CHILD | WS_BORDER, 0, 0, 300, 300, + pager, 0, GetModuleHandleA(0), 0); flush_sequences( sequences, NUM_MSG_SEQUENCES ); - SendMessageA( pager, PGM_SETCHILD, 0, (LPARAM)child ); - ok_sequence(sequences, PAGER_SEQ_INDEX, set_child_seq, "set child", TRUE); + SendMessageA( pager, PGM_SETCHILD, 0, (LPARAM)child1_wnd ); + ok_sequence(sequences, PAGER_SEQ_INDEX, set_child_seq, "set child", FALSE); GetWindowRect( pager, &rect ); ok( rect.right - rect.left == 100 && rect.bottom - rect.top == 100, "pager resized %dx%d\n", rect.right - rect.left, rect.bottom - rect.top ); + flush_sequences(sequences, NUM_MSG_SEQUENCES); + SendMessageA(pager, PGM_SETCHILD, 0, (LPARAM)child2_wnd); + ok_sequence(sequences, PAGER_SEQ_INDEX, switch_child_seq, "switch to invisible child", FALSE); + GetWindowRect(pager, &rect); + ok(rect.right - rect.left == 100 && rect.bottom - rect.top == 100, + "pager resized %dx%d\n", rect.right - rect.left, rect.bottom - rect.top); + ok(!IsWindowVisible(child2_wnd), "Child window 2 is visible\n"); + + flush_sequences(sequences, NUM_MSG_SEQUENCES); + SendMessageA(pager, PGM_SETCHILD, 0, (LPARAM)child1_wnd); + ok_sequence(sequences, PAGER_SEQ_INDEX, set_child_seq, "switch to visible child", FALSE); + GetWindowRect(pager, &rect); + ok(rect.right - rect.left == 100 && rect.bottom - rect.top == 100, + "pager resized %dx%d\n", rect.right - rect.left, rect.bottom - rect.top); + flush_sequences( sequences, NUM_MSG_SEQUENCES ); SendMessageA( pager, PGM_SETPOS, 0, 10 ); ok_sequence(sequences, PAGER_SEQ_INDEX, set_pos_seq, "set pos", TRUE); diff --git a/rostests/winetests/comctl32/propsheet.c b/rostests/winetests/comctl32/propsheet.c index 0189c6419ac..76e706a7b13 100644 --- a/rostests/winetests/comctl32/propsheet.c +++ b/rostests/winetests/comctl32/propsheet.c @@ -713,7 +713,7 @@ static const struct message property_sheet_seq[] = { static void save_message(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam, INT receiver) { - struct message msg; + struct message msg = { 0 }; if (message < WM_USER && message != WM_GETICON && @@ -990,6 +990,141 @@ if (0) DestroyWindow(hdlg); } +struct custom_proppage +{ + union + { + PROPSHEETPAGEA pageA; + PROPSHEETPAGEW pageW; + } u; + unsigned int addref_called; + unsigned int release_called; +}; + +static UINT CALLBACK proppage_callback_a(HWND hwnd, UINT msg, PROPSHEETPAGEA *psp) +{ + struct custom_proppage *cpage = (struct custom_proppage *)psp->lParam; + PROPSHEETPAGEA *psp_orig = &cpage->u.pageA; + + ok(hwnd == NULL, "Expected NULL hwnd, got %p\n", hwnd); + + ok(psp->lParam && psp->lParam != (LPARAM)psp, "Expected newly allocated page description, got %lx, %p\n", + psp->lParam, psp); + ok(psp_orig->pszTitle == psp->pszTitle, "Expected same page title pointer\n"); + ok(!lstrcmpA(psp_orig->pszTitle, psp->pszTitle), "Expected same page title string\n"); + + switch (msg) + { + case PSPCB_ADDREF: + ok(psp->dwSize > PROPSHEETPAGEA_V1_SIZE, "Expected ADDREF for V2+ only, got size %u\n", psp->dwSize); + cpage->addref_called++; + break; + case PSPCB_RELEASE: + ok(psp->dwSize >= PROPSHEETPAGEA_V1_SIZE, "Unexpected RELEASE, got size %u\n", psp->dwSize); + cpage->release_called++; + break; + default: + ok(0, "Unexpected message %u\n", msg); + } + + return 1; +} + +static UINT CALLBACK proppage_callback_w(HWND hwnd, UINT msg, PROPSHEETPAGEW *psp) +{ + struct custom_proppage *cpage = (struct custom_proppage *)psp->lParam; + PROPSHEETPAGEW *psp_orig = &cpage->u.pageW; + + ok(hwnd == NULL, "Expected NULL hwnd, got %p\n", hwnd); + ok(psp->lParam && psp->lParam != (LPARAM)psp, "Expected newly allocated page description, got %lx, %p\n", + psp->lParam, psp); + ok(psp_orig->pszTitle == psp->pszTitle, "Expected same page title pointer\n"); + ok(!lstrcmpW(psp_orig->pszTitle, psp->pszTitle), "Expected same page title string\n"); + + switch (msg) + { + case PSPCB_ADDREF: + ok(psp->dwSize > PROPSHEETPAGEW_V1_SIZE, "Expected ADDREF for V2+ only, got size %u\n", psp->dwSize); + cpage->addref_called++; + break; + case PSPCB_RELEASE: + ok(psp->dwSize >= PROPSHEETPAGEW_V1_SIZE, "Unexpected RELEASE, got size %u\n", psp->dwSize); + cpage->release_called++; + break; + default: + ok(0, "Unexpected message %u\n", msg); + } + + return 1; +} + +static void test_CreatePropertySheetPage(void) +{ + static const WCHAR titleW[] = {'T','i','t','l','e',0}; + struct custom_proppage page; + HPROPSHEETPAGE hpsp; + BOOL ret; + + memset(&page.u.pageA, 0, sizeof(page.u.pageA)); + page.u.pageA.dwFlags = PSP_USECALLBACK; + page.u.pageA.pfnDlgProc = page_dlg_proc_messages; + page.u.pageA.pfnCallback = proppage_callback_a; + page.u.pageA.lParam = (LPARAM)&page; + page.u.pageA.pszTitle = "Title"; + + /* Only minimal size validation is performed */ + for (page.u.pageA.dwSize = PROPSHEETPAGEA_V1_SIZE - 1; page.u.pageA.dwSize <= PROPSHEETPAGEA_V4_SIZE + 1; page.u.pageA.dwSize++) + { + page.addref_called = 0; + hpsp = CreatePropertySheetPageA(&page.u.pageA); + + if (page.u.pageA.dwSize < PROPSHEETPAGEA_V1_SIZE) + ok(hpsp == NULL, "Expected failure, size %u\n", page.u.pageA.dwSize); + else + { + ok(hpsp != NULL, "Failed to create a page, size %u\n", page.u.pageA.dwSize); + ok(page.addref_called == (page.u.pageA.dwSize > PROPSHEETPAGEA_V1_SIZE) ? 1 : 0, "Expected ADDREF callback message\n"); + } + + if (hpsp) + { + page.release_called = 0; + ret = DestroyPropertySheetPage(hpsp); + ok(ret, "Failed to destroy a page\n"); + ok(page.release_called == 1, "Expected RELEASE callback message\n"); + } + } + + memset(&page.u.pageW, 0, sizeof(page.u.pageW)); + page.u.pageW.dwFlags = PSP_USECALLBACK; + page.u.pageW.pfnDlgProc = page_dlg_proc_messages; + page.u.pageW.pfnCallback = proppage_callback_w; + page.u.pageW.lParam = (LPARAM)&page; + page.u.pageW.pszTitle = titleW; + + for (page.u.pageW.dwSize = PROPSHEETPAGEW_V1_SIZE - 1; page.u.pageW.dwSize <= PROPSHEETPAGEW_V4_SIZE + 1; page.u.pageW.dwSize++) + { + page.addref_called = 0; + hpsp = CreatePropertySheetPageW(&page.u.pageW); + + if (page.u.pageW.dwSize < PROPSHEETPAGEW_V1_SIZE) + ok(hpsp == NULL, "Expected failure, size %u\n", page.u.pageW.dwSize); + else + { + ok(hpsp != NULL, "Failed to create a page, size %u\n", page.u.pageW.dwSize); + ok(page.addref_called == (page.u.pageW.dwSize > PROPSHEETPAGEW_V1_SIZE) ? 1 : 0, "Expected ADDREF callback message\n"); + } + + if (hpsp) + { + page.release_called = 0; + ret = DestroyPropertySheetPage(hpsp); + ok(ret, "Failed to destroy a page\n"); + ok(page.release_called == 1, "Expected RELEASE callback message\n"); + } + } +} + START_TEST(propsheet) { test_title(); @@ -1001,4 +1136,5 @@ START_TEST(propsheet) test_messages(); test_PSM_ADDPAGE(); test_PSM_INSERTPAGE(); + test_CreatePropertySheetPage(); } diff --git a/rostests/winetests/comctl32/syslink.c b/rostests/winetests/comctl32/syslink.c index 0e523b9b080..9f7233fae77 100644 --- a/rostests/winetests/comctl32/syslink.c +++ b/rostests/winetests/comctl32/syslink.c @@ -146,15 +146,14 @@ static WNDPROC syslink_oldproc; static LRESULT WINAPI syslink_subclass_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) { static LONG defwndproc_counter = 0; + struct message msg = { 0 }; LRESULT ret; - struct message msg; msg.message = message; msg.flags = sent|wparam|lparam; if (defwndproc_counter) msg.flags |= defwinproc; msg.wParam = wParam; msg.lParam = lParam; - msg.id = 0; add_message(sequences, SYSLINK_SEQ_INDEX, &msg); defwndproc_counter++; diff --git a/rostests/winetests/comctl32/tab.c b/rostests/winetests/comctl32/tab.c index bbc1188e7a5..431a49de171 100644 --- a/rostests/winetests/comctl32/tab.c +++ b/rostests/winetests/comctl32/tab.c @@ -304,8 +304,8 @@ create_tabcontrol (DWORD style, DWORD mask) static LRESULT WINAPI parentWindowProcess(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) { static LONG defwndproc_counter = 0; + struct message msg = { 0 }; LRESULT ret; - struct message msg; /* do not log painting messages */ if (message != WM_PAINT && @@ -321,7 +321,6 @@ static LRESULT WINAPI parentWindowProcess(HWND hwnd, UINT message, WPARAM wParam if (defwndproc_counter) msg.flags |= defwinproc; msg.wParam = wParam; msg.lParam = lParam; - msg.id = 0; add_message(sequences, PARENT_SEQ_INDEX, &msg); } @@ -367,8 +366,8 @@ static LRESULT WINAPI tabSubclassProcess(HWND hwnd, UINT message, WPARAM wParam, { WNDPROC oldproc = (WNDPROC)GetWindowLongPtrA(hwnd, GWLP_USERDATA); static LONG defwndproc_counter = 0; + struct message msg = { 0 }; LRESULT ret; - struct message msg; /* do not log painting messages */ if (message != WM_PAINT && @@ -384,7 +383,6 @@ static LRESULT WINAPI tabSubclassProcess(HWND hwnd, UINT message, WPARAM wParam, if (defwndproc_counter) msg.flags |= defwinproc; msg.wParam = wParam; msg.lParam = lParam; - msg.id = 0; add_message(sequences, TAB_SEQ_INDEX, &msg); } diff --git a/rostests/winetests/comctl32/taskdialog.c b/rostests/winetests/comctl32/taskdialog.c new file mode 100644 index 00000000000..8a9d164a18a --- /dev/null +++ b/rostests/winetests/comctl32/taskdialog.c @@ -0,0 +1,58 @@ +/* Unit tests for the task dialog control. + * + * Copyright 2017 Fabian Maurer for the Wine project + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include + +#include "windef.h" +#include "winbase.h" +#include "winuser.h" +#include "commctrl.h" + +#include "wine/test.h" +#include "v6util.h" + +static HRESULT (WINAPI *pTaskDialogIndirect)(const TASKDIALOGCONFIG *, int *, int *, BOOL *); + +START_TEST(taskdialog) +{ + ULONG_PTR ctx_cookie; + void *ptr_ordinal; + HINSTANCE hinst; + HANDLE hCtx; + + if (!load_v6_module(&ctx_cookie, &hCtx)) + return; + + /* Check if task dialogs are available */ + hinst = LoadLibraryA("comctl32.dll"); + + pTaskDialogIndirect = (void *)GetProcAddress(hinst, "TaskDialogIndirect"); + if (!pTaskDialogIndirect) + { + win_skip("TaskDialogIndirect not exported by name\n"); + unload_v6_module(ctx_cookie, hCtx); + return; + } + + ptr_ordinal = GetProcAddress(hinst, (const char *)345); + ok(pTaskDialogIndirect == ptr_ordinal, "got wrong pointer for ordinal 345, %p expected %p\n", + ptr_ordinal, pTaskDialogIndirect); + + unload_v6_module(ctx_cookie, hCtx); +} diff --git a/rostests/winetests/comctl32/testlist.c b/rostests/winetests/comctl32/testlist.c index 7f91ecb52c3..2abb83ad7f1 100644 --- a/rostests/winetests/comctl32/testlist.c +++ b/rostests/winetests/comctl32/testlist.c @@ -23,6 +23,7 @@ extern void func_status(void); extern void func_subclass(void); extern void func_syslink(void); extern void func_tab(void); +extern void func_taskdialog(void); extern void func_toolbar(void); extern void func_tooltips(void); extern void func_trackbar(void); @@ -51,6 +52,7 @@ const struct test winetest_testlist[] = { "subclass", func_subclass }, { "syslink", func_syslink }, { "tab", func_tab }, + { "taskdialog", func_taskdialog }, { "toolbar", func_toolbar }, { "tooltips", func_tooltips }, { "trackbar", func_trackbar }, diff --git a/rostests/winetests/comctl32/toolbar.c b/rostests/winetests/comctl32/toolbar.c index a8bcd402380..2d12732b091 100644 --- a/rostests/winetests/comctl32/toolbar.c +++ b/rostests/winetests/comctl32/toolbar.c @@ -2276,7 +2276,8 @@ static void test_save(void) { HWND wnd = NULL; TBSAVEPARAMSW params; - static const WCHAR subkey[] = {'S','o','f','t','w','a','r','e','\\','W','i','n','e','T','e','s','t',0}; + static const WCHAR subkey[] = {'S','o','f','t','w','a','r','e','\\','W','i','n','e','\\', + 'W','i','n','e','T','e','s','t',0}; static const WCHAR value[] = {'t','o','o','l','b','a','r','t','e','s','t',0}; LONG res; HKEY key; diff --git a/rostests/winetests/comctl32/trackbar.c b/rostests/winetests/comctl32/trackbar.c index 3d486835b50..0bbe97c54a6 100644 --- a/rostests/winetests/comctl32/trackbar.c +++ b/rostests/winetests/comctl32/trackbar.c @@ -442,15 +442,14 @@ static HWND create_parent_window(void){ static LRESULT WINAPI trackbar_subclass_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam){ WNDPROC oldproc = (WNDPROC)GetWindowLongPtrA(hwnd, GWLP_USERDATA); static LONG defwndproc_counter = 0; + struct message msg = { 0 }; LRESULT ret; - struct message msg; msg.message = message; msg.flags = sent|wparam|lparam; if (defwndproc_counter) msg.flags |= defwinproc; msg.wParam = wParam; msg.lParam = lParam; - msg.id = 0; add_message(sequences, TRACKBAR_SEQ_INDEX, &msg); defwndproc_counter++; diff --git a/rostests/winetests/comctl32/treeview.c b/rostests/winetests/comctl32/treeview.c index a4b4747a5e1..83ba492b7b0 100644 --- a/rostests/winetests/comctl32/treeview.c +++ b/rostests/winetests/comctl32/treeview.c @@ -54,6 +54,21 @@ static BOOL g_v6; static struct msg_sequence *sequences[NUM_MSG_SEQUENCES]; static struct msg_sequence *item_sequence[1]; +static void flush_events(void) +{ + MSG msg; + int diff = 200; + int min_timeout = 100; + DWORD time = GetTickCount() + diff; + + while (diff > 0) + { + if (MsgWaitForMultipleObjects(0, NULL, FALSE, min_timeout, QS_ALLINPUT) == WAIT_TIMEOUT) break; + while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) DispatchMessageA(&msg); + diff = time - GetTickCount(); + } +} + static const struct message FillRootSeq[] = { { TVM_INSERTITEMA, sent }, { TVM_INSERTITEMA, sent }, @@ -201,6 +216,13 @@ static const struct message test_get_set_unicodeformat_seq[] = { { 0 } }; +static const struct message test_right_click_seq[] = { + { WM_RBUTTONDOWN, sent|wparam, MK_RBUTTON }, + { WM_CAPTURECHANGED, sent|defwinproc }, + { TVM_GETNEXTITEM, sent|wparam|lparam|defwinproc, TVGN_CARET, 0 }, + { 0 } +}; + static const struct message parent_expand_seq[] = { { WM_NOTIFY, sent|id, 0, 0, TVN_ITEMEXPANDINGA }, { WM_NOTIFY, sent|id, 0, 0, TVN_ITEMEXPANDEDA }, @@ -342,6 +364,12 @@ static const struct message parent_vk_return_seq[] = { { 0 } }; +static const struct message parent_right_click_seq[] = { + { WM_NOTIFY, sent|id, 0, 0, NM_RCLICK }, + { WM_CONTEXTMENU, sent }, + { 0 } +}; + static HWND hMainWnd; static HTREEITEM hRoot, hChild; @@ -383,15 +411,14 @@ static LRESULT WINAPI TreeviewWndProc(HWND hwnd, UINT message, WPARAM wParam, LP { static LONG defwndproc_counter = 0; LRESULT ret; - struct message msg; WNDPROC lpOldProc = (WNDPROC)GetWindowLongPtrA(hwnd, GWLP_USERDATA); + struct message msg = { 0 }; msg.message = message; msg.flags = sent|wparam|lparam; if (defwndproc_counter) msg.flags |= defwinproc; msg.wParam = wParam; msg.lParam = lParam; - msg.id = 0; add_message(sequences, TREEVIEW_SEQ_INDEX, &msg); defwndproc_counter++; @@ -1099,7 +1126,7 @@ static void test_get_set_unicodeformat(void) static LRESULT CALLBACK parent_wnd_proc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { static LONG defwndproc_counter = 0; - struct message msg; + struct message msg = { 0 }; LRESULT ret; RECT rect; HTREEITEM visibleItem; @@ -1111,8 +1138,6 @@ static LRESULT CALLBACK parent_wnd_proc(HWND hWnd, UINT message, WPARAM wParam, msg.lParam = lParam; if (message == WM_NOTIFY && lParam) msg.id = ((NMHDR*)lParam)->code; - else - msg.id = 0; /* log system messages, except for painting */ if (message < WM_USER && @@ -1299,6 +1324,13 @@ static LRESULT CALLBACK parent_wnd_proc(HWND hWnd, UINT message, WPARAM wParam, } break; } + case NM_RCLICK: + { + HTREEITEM selected = (HTREEITEM)SendMessageA(((NMHDR *)lParam)->hwndFrom, + TVM_GETNEXTITEM, TVGN_CARET, 0); + ok(selected == hChild, "child item should still be selected\n"); + break; + } } } break; @@ -2397,6 +2429,238 @@ static void test_TVS_FULLROWSELECT(void) DestroyWindow(hwnd); } +static void get_item_names_string(HWND hwnd, HTREEITEM item, char *str) +{ + TVITEMA tvitem = { 0 }; + HTREEITEM child; + char name[16]; + + if (!item) + { + item = (HTREEITEM)SendMessageA(hwnd, TVM_GETNEXTITEM, TVGN_ROOT, 0); + str[0] = 0; + } + + child = (HTREEITEM)SendMessageA(hwnd, TVM_GETNEXTITEM, TVGN_CHILD, (LPARAM)item); + + tvitem.mask = TVIF_TEXT; + tvitem.hItem = item; + tvitem.pszText = name; + tvitem.cchTextMax = sizeof(name); + SendMessageA(hwnd, TVM_GETITEMA, 0, (LPARAM)&tvitem); + strcat(str, tvitem.pszText); + + while (child != NULL) + { + get_item_names_string(hwnd, child, str); + child = (HTREEITEM)SendMessageA(hwnd, TVM_GETNEXTITEM, TVGN_NEXT, (LPARAM)child); + } +} + +static void fill_treeview_sort_test(HWND hwnd) +{ + static const char *itemnames[] = + { + "root", "Wasp", "Caribou", "Vacuum", + "Ocelot", "Newspaper", "Litter bin" + }; + + HTREEITEM root, children[2]; + TVINSERTSTRUCTA ins; + unsigned i = 0; + + SendMessageA(hwnd, TVM_DELETEITEM, 0, 0); + + /* root, two children, with two children each */ + ins.hParent = TVI_ROOT; + ins.hInsertAfter = TVI_ROOT; + U(ins).item.mask = TVIF_TEXT; + U(ins).item.pszText = (char *)itemnames[i++]; + root = (HTREEITEM)SendMessageA(hwnd, TVM_INSERTITEMA, 0, (LPARAM)&ins); + + ins.hParent = root; + ins.hInsertAfter = TVI_LAST; + U(ins).item.mask = TVIF_TEXT; + U(ins).item.pszText = (char *)itemnames[i++]; + children[0] = (HTREEITEM)SendMessageA(hwnd, TVM_INSERTITEMA, 0, (LPARAM)&ins); + + U(ins).item.pszText = (char *)itemnames[i++]; + children[1] = (HTREEITEM)SendMessageA(hwnd, TVM_INSERTITEMA, 0, (LPARAM)&ins); + + ins.hParent = children[0]; + U(ins).item.pszText = (char *)itemnames[i++]; + SendMessageA(hwnd, TVM_INSERTITEMA, 0, (LPARAM)&ins); + + U(ins).item.pszText = (char *)itemnames[i++]; + SendMessageA(hwnd, TVM_INSERTITEMA, 0, (LPARAM)&ins); + + ins.hParent = children[1]; + U(ins).item.pszText = (char *)itemnames[i++]; + SendMessageA(hwnd, TVM_INSERTITEMA, 0, (LPARAM)&ins); + + U(ins).item.pszText = (char *)itemnames[i++]; + SendMessageA(hwnd, TVM_INSERTITEMA, 0, (LPARAM)&ins); +} + +static void test_TVM_SORTCHILDREN(void) +{ + static const char *initial_order = "rootWaspVacuumOcelotCaribouNewspaperLitter bin"; + static const char *sorted_order = "rootCaribouNewspaperLitter binWaspVacuumOcelot"; + TVINSERTSTRUCTA ins; + char buff[256]; + HTREEITEM root; + HWND hwnd; + BOOL ret; + + hwnd = create_treeview_control(0); + + /* call on empty tree */ + ret = SendMessageA(hwnd, TVM_SORTCHILDREN, 0, 0); + ok(!ret, "Unexpected ret value %d\n", ret); + + ret = SendMessageA(hwnd, TVM_SORTCHILDREN, 0, (LPARAM)TVI_ROOT); + ok(!ret, "Unexpected ret value %d\n", ret); + + /* add only root, sort from it */ + ins.hParent = TVI_ROOT; + ins.hInsertAfter = TVI_ROOT; + U(ins).item.mask = TVIF_TEXT; + U(ins).item.pszText = (char *)"root"; + root = (HTREEITEM)SendMessageA(hwnd, TVM_INSERTITEMA, 0, (LPARAM)&ins); + ok(root != NULL, "Expected root node\n"); + + ret = SendMessageA(hwnd, TVM_SORTCHILDREN, 0, (LPARAM)root); + ok(!ret, "Unexpected ret value %d\n", ret); + + ret = SendMessageA(hwnd, TVM_SORTCHILDREN, TRUE, (LPARAM)root); + ok(!ret, "Unexpected ret value %d\n", ret); + + /* root, two children, with two children each */ + fill_treeview_sort_test(hwnd); + get_item_names_string(hwnd, NULL, buff); + ok(!strcmp(buff, initial_order), "Wrong initial order %s, expected %s\n", buff, initial_order); + + /* with NULL item nothing is sorted */ + fill_treeview_sort_test(hwnd); + ret = SendMessageA(hwnd, TVM_SORTCHILDREN, 0, 0); +todo_wine + ok(ret, "Unexpected ret value %d\n", ret); + get_item_names_string(hwnd, NULL, buff); + ok(!strcmp(buff, initial_order), "Wrong sorted order %s, expected %s\n", buff, initial_order); + + /* TVI_ROOT as item */ + fill_treeview_sort_test(hwnd); + ret = SendMessageA(hwnd, TVM_SORTCHILDREN, 0, (LPARAM)TVI_ROOT); +todo_wine + ok(ret, "Unexpected ret value %d\n", ret); + get_item_names_string(hwnd, NULL, buff); + ok(!strcmp(buff, initial_order), "Wrong sorted order %s, expected %s\n", buff, initial_order); + + /* zero WPARAM, item is specified */ + fill_treeview_sort_test(hwnd); + root = (HTREEITEM)SendMessageA(hwnd, TVM_GETNEXTITEM, TVGN_ROOT, 0); + ok(root != NULL, "Failed to get root item\n"); + ret = SendMessageA(hwnd, TVM_SORTCHILDREN, 0, (LPARAM)root); + ok(ret, "Unexpected ret value %d\n", ret); + get_item_names_string(hwnd, NULL, buff); + ok(!strcmp(buff, sorted_order), "Wrong sorted order %s, expected %s\n", buff, sorted_order); + + /* non-zero WPARAM, NULL item */ + fill_treeview_sort_test(hwnd); + ret = SendMessageA(hwnd, TVM_SORTCHILDREN, TRUE, 0); +todo_wine + ok(ret, "Unexpected ret value %d\n", ret); + get_item_names_string(hwnd, NULL, buff); + ok(!strcmp(buff, initial_order), "Wrong sorted order %s, expected %s\n", buff, sorted_order); + + /* TVI_ROOT as item */ + fill_treeview_sort_test(hwnd); + ret = SendMessageA(hwnd, TVM_SORTCHILDREN, TRUE, (LPARAM)TVI_ROOT); +todo_wine + ok(ret, "Unexpected ret value %d\n", ret); + get_item_names_string(hwnd, NULL, buff); + ok(!strcmp(buff, initial_order), "Wrong sorted order %s, expected %s\n", buff, sorted_order); + + /* non-zero WPARAM, item is specified */ + fill_treeview_sort_test(hwnd); + root = (HTREEITEM)SendMessageA(hwnd, TVM_GETNEXTITEM, TVGN_ROOT, 0); + ok(root != NULL, "Failed to get root item\n"); + ret = SendMessageA(hwnd, TVM_SORTCHILDREN, TRUE, (LPARAM)root); + ok(ret, "Unexpected ret value %d\n", ret); + get_item_names_string(hwnd, NULL, buff); + ok(!strcmp(buff, sorted_order), "Wrong sorted order %s, expected %s\n", buff, sorted_order); + + /* case insensitive comparison */ + SendMessageA(hwnd, TVM_DELETEITEM, 0, 0); + + ins.hParent = TVI_ROOT; + ins.hInsertAfter = TVI_ROOT; + U(ins).item.mask = TVIF_TEXT; + U(ins).item.pszText = (char *)"root"; + root = (HTREEITEM)SendMessageA(hwnd, TVM_INSERTITEMA, 0, (LPARAM)&ins); + ok(root != NULL, "Expected root node\n"); + + ins.hParent = root; + ins.hInsertAfter = TVI_LAST; + U(ins).item.pszText = (char *)"I1"; + SendMessageA(hwnd, TVM_INSERTITEMA, 0, (LPARAM)&ins); + + ins.hParent = root; + ins.hInsertAfter = TVI_LAST; + U(ins).item.pszText = (char *)"i1"; + SendMessageA(hwnd, TVM_INSERTITEMA, 0, (LPARAM)&ins); + + ret = SendMessageA(hwnd, TVM_SORTCHILDREN, TRUE, (LPARAM)root); + ok(ret, "Unexpected ret value %d\n", ret); + get_item_names_string(hwnd, NULL, buff); + ok(!strcmp(buff, "rootI1i1"), "Wrong sorted order %s\n", buff); + + DestroyWindow(hwnd); +} + +static void test_right_click(void) +{ + HWND hTree; + HTREEITEM selected; + RECT rc; + LRESULT result; + POINT pt; + + hTree = create_treeview_control(0); + fill_tree(hTree); + + SendMessageA(hTree, TVM_ENSUREVISIBLE, 0, (LPARAM)hChild); + SendMessageA(hTree, TVM_SELECTITEM, TVGN_CARET, (LPARAM)hChild); + selected = (HTREEITEM)SendMessageA(hTree, TVM_GETNEXTITEM, TVGN_CARET, 0); + ok(selected == hChild, "child item not selected\n"); + + *(HTREEITEM *)&rc = hRoot; + result = SendMessageA(hTree, TVM_GETITEMRECT, TRUE, (LPARAM)&rc); + ok(result, "TVM_GETITEMRECT failed\n"); + + flush_events(); + + pt.x = (rc.left + rc.right) / 2; + pt.y = (rc.top + rc.bottom) / 2; + ClientToScreen(hMainWnd, &pt); + + flush_events(); + flush_sequences(sequences, NUM_MSG_SEQUENCES); + + PostMessageA(hTree, WM_RBUTTONDOWN, MK_RBUTTON, MAKELPARAM(pt.x, pt.y)); + PostMessageA(hTree, WM_RBUTTONUP, 0, MAKELPARAM(pt.x, pt.y)); + + flush_events(); + + ok_sequence(sequences, TREEVIEW_SEQ_INDEX, test_right_click_seq, "right click sequence", FALSE); + ok_sequence(sequences, PARENT_SEQ_INDEX, parent_right_click_seq, "parent right click sequence", FALSE); + + selected = (HTREEITEM)SendMessageA(hTree, TVM_GETNEXTITEM, TVGN_CARET, 0); + ok(selected == hChild, "child item should still be selected\n"); + + DestroyWindow(hTree); +} + START_TEST(treeview) { HMODULE hComctl32; @@ -2473,6 +2737,8 @@ START_TEST(treeview) test_customdraw(); test_WM_KEYDOWN(); test_TVS_FULLROWSELECT(); + test_TVM_SORTCHILDREN(); + test_right_click(); if (!load_v6_module(&ctx_cookie, &hCtx)) { diff --git a/rostests/winetests/comctl32/updown.c b/rostests/winetests/comctl32/updown.c index 8a963d9d2f2..fb5ade4a72d 100644 --- a/rostests/winetests/comctl32/updown.c +++ b/rostests/winetests/comctl32/updown.c @@ -169,8 +169,8 @@ static const struct message test_updown_pos_nochange_seq[] = { static LRESULT WINAPI parent_wnd_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) { static LONG defwndproc_counter = 0; + struct message msg = { 0 }; LRESULT ret; - struct message msg; /* log system messages, except for painting */ if (message < WM_USER && @@ -187,7 +187,6 @@ static LRESULT WINAPI parent_wnd_proc(HWND hwnd, UINT message, WPARAM wParam, LP if (defwndproc_counter) msg.flags |= defwinproc; msg.wParam = wParam; msg.lParam = lParam; - msg.id = 0; add_message(sequences, PARENT_SEQ_INDEX, &msg); } @@ -232,8 +231,8 @@ static LRESULT WINAPI edit_subclass_proc(HWND hwnd, UINT message, WPARAM wParam, { WNDPROC oldproc = (WNDPROC)GetWindowLongPtrA(hwnd, GWLP_USERDATA); static LONG defwndproc_counter = 0; + struct message msg = { 0 }; LRESULT ret; - struct message msg; msg.message = message; msg.flags = sent|wparam|lparam; @@ -272,8 +271,8 @@ static LRESULT WINAPI updown_subclass_proc(HWND hwnd, UINT message, WPARAM wPara { WNDPROC oldproc = (WNDPROC)GetWindowLongPtrA(hwnd, GWLP_USERDATA); static LONG defwndproc_counter = 0; + struct message msg = { 0 }; LRESULT ret; - struct message msg; msg.message = message; msg.flags = sent|wparam|lparam;