https://git.reactos.org/?p=reactos.git;a=commitdiff;h=5f7243b5772eb2341e312…
commit 5f7243b5772eb2341e31263f1a1a5934fea6568b
Author: Amine Khaldi <amine.khaldi(a)reactos.org>
AuthorDate: Fri Jan 25 13:16:18 2019 +0100
Commit: Amine Khaldi <amine.khaldi(a)reactos.org>
CommitDate: Fri Jan 25 13:16:18 2019 +0100
[COMCTL32_WINETEST] Sync with Wine Staging 4.0. CORE-15682
---
modules/rostests/winetests/comctl32/button.c | 913 +++++++++++++++++++-
modules/rostests/winetests/comctl32/combo.c | 11 +-
modules/rostests/winetests/comctl32/datetime.c | 41 +
modules/rostests/winetests/comctl32/edit.c | 84 +-
modules/rostests/winetests/comctl32/header.c | 4 +-
modules/rostests/winetests/comctl32/imagelist.c | 15 +-
modules/rostests/winetests/comctl32/ipaddress.c | 4 +-
modules/rostests/winetests/comctl32/listbox.c | 713 ++++++++++++---
modules/rostests/winetests/comctl32/listview.c | 184 +++-
modules/rostests/winetests/comctl32/misc.c | 70 +-
modules/rostests/winetests/comctl32/monthcal.c | 13 +-
modules/rostests/winetests/comctl32/mru.c | 4 +-
modules/rostests/winetests/comctl32/pager.c | 1005 +++++++++++++++++++++-
modules/rostests/winetests/comctl32/progress.c | 2 +-
modules/rostests/winetests/comctl32/propsheet.c | 42 +-
modules/rostests/winetests/comctl32/rebar.c | 4 +-
modules/rostests/winetests/comctl32/resources.h | 1 +
modules/rostests/winetests/comctl32/rsrc.rc | 7 +
modules/rostests/winetests/comctl32/status.c | 128 ++-
modules/rostests/winetests/comctl32/subclass.c | 31 +-
modules/rostests/winetests/comctl32/taskdialog.c | 649 +++++++++++++-
modules/rostests/winetests/comctl32/toolbar.c | 19 +-
modules/rostests/winetests/comctl32/tooltips.c | 4 +-
modules/rostests/winetests/comctl32/trackbar.c | 52 ++
modules/rostests/winetests/comctl32/treeview.c | 143 ++-
modules/rostests/winetests/comctl32/updown.c | 12 +-
26 files changed, 3894 insertions(+), 261 deletions(-)
diff --git a/modules/rostests/winetests/comctl32/button.c
b/modules/rostests/winetests/comctl32/button.c
index d73fc1da9b..edfa447bab 100644
--- a/modules/rostests/winetests/comctl32/button.c
+++ b/modules/rostests/winetests/comctl32/button.c
@@ -20,7 +20,9 @@
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
+#ifdef __REACTOS__
#undef USE_WINE_TODOS
+#endif
#include <windows.h>
#include <commctrl.h>
@@ -29,11 +31,18 @@
#include "v6util.h"
#include "msg.h"
+#ifdef __REACTOS__
+#define BS_PUSHBOX 0x0000000AL
+#endif
+
#define IS_WNDPROC_HANDLE(x) (((ULONG_PTR)(x) >> 16) == (~0u >> 16))
static BOOL (WINAPI *pSetWindowSubclass)(HWND, SUBCLASSPROC, UINT_PTR, DWORD_PTR);
static BOOL (WINAPI *pRemoveWindowSubclass)(HWND, SUBCLASSPROC, UINT_PTR);
static LRESULT (WINAPI *pDefSubclassProc)(HWND, UINT, WPARAM, LPARAM);
+static HIMAGELIST (WINAPI *pImageList_Create)(int, int, UINT, int, int);
+static int (WINAPI *pImageList_Add)(HIMAGELIST, HBITMAP, HBITMAP);
+static BOOL (WINAPI *pImageList_Destroy)(HIMAGELIST);
/****************** button message test *************************/
#define ID_BUTTON 0x000e
@@ -78,6 +87,12 @@ static void init_functions(void)
MAKEFUNC_ORD(RemoveWindowSubclass, 412);
MAKEFUNC_ORD(DefSubclassProc, 413);
#undef MAKEFUNC_ORD
+
+#define X(f) p##f = (void *)GetProcAddress(hmod, #f);
+ X(ImageList_Create);
+ X(ImageList_Add);
+ X(ImageList_Destroy);
+#undef X
}
/* try to make sure pending X events have been processed before continuing */
@@ -550,15 +565,15 @@ static void test_button_messages(void)
hfont2 = CreateFontIndirectA(&logfont);
ok(hfont2 != NULL, "Failed to create Tahoma font\n");
- for (i = 0; i < sizeof(button)/sizeof(button[0]); i++)
+ for (i = 0; i < ARRAY_SIZE(button); i++)
{
HFONT prevfont, hfont;
MSG msg;
DWORD style, state;
HDC hdc;
- trace("%d: button test sequence\n", i);
hwnd = create_button(button[i].style, parent);
+ ok(hwnd != NULL, "Failed to create a button.\n");
style = GetWindowLongA(hwnd, GWL_STYLE);
style &= ~(WS_CHILD | BS_NOTIFY);
@@ -807,6 +822,395 @@ static void test_button_class(void)
DestroyWindow(hwnd);
}
+static void test_note(void)
+{
+ HWND hwnd;
+ BOOL ret;
+ WCHAR test_w[] = {'t', 'e', 's', 't', 0};
+ WCHAR tes_w[] = {'t', 'e', 's', 0};
+ WCHAR deadbeef_w[] = {'d', 'e', 'a', 'd',
'b', 'e', 'e', 'f', 0};
+ WCHAR buffer_w[10];
+ DWORD size;
+ DWORD error;
+ INT type;
+
+ hwnd = create_button(BS_COMMANDLINK, NULL);
+ ok(hwnd != NULL, "Expect hwnd not null\n");
+ SetLastError(0xdeadbeef);
+ size = ARRAY_SIZE(buffer_w);
+ ret = SendMessageA(hwnd, BCM_GETNOTE, (WPARAM)&size, (LPARAM)buffer_w);
+ error = GetLastError();
+ if (!ret && error == 0xdeadbeef)
+ {
+ win_skip("BCM_GETNOTE message is unavailable. Skipping note tests\n");
/* xp or 2003 */
+ DestroyWindow(hwnd);
+ return;
+ }
+ DestroyWindow(hwnd);
+
+ for (type = BS_PUSHBUTTON; type <= BS_DEFCOMMANDLINK; type++)
+ {
+ if (type == BS_DEFCOMMANDLINK || type == BS_COMMANDLINK)
+ {
+ hwnd = create_button(type, NULL);
+ ok(hwnd != NULL, "Expect hwnd not null\n");
+
+ /* Get note when note hasn't been not set yet */
+ SetLastError(0xdeadbeef);
+ lstrcpyW(buffer_w, deadbeef_w);
+ size = ARRAY_SIZE(buffer_w);
+ ret = SendMessageA(hwnd, BCM_GETNOTE, (WPARAM)&size, (LPARAM)buffer_w);
+ error = GetLastError();
+ ok(!ret, "Expect BCM_GETNOTE return false\n");
+ ok(!lstrcmpW(buffer_w, deadbeef_w), "Expect note: %s, got: %s\n",
+ wine_dbgstr_w(deadbeef_w), wine_dbgstr_w(buffer_w));
+ ok(size == ARRAY_SIZE(buffer_w), "Got: %d\n", size);
+ ok(error == ERROR_INVALID_PARAMETER, "Expect last error: 0x%08x, got:
0x%08x\n",
+ ERROR_INVALID_PARAMETER, error);
+
+ /* Get note length when note is not set */
+ ret = SendMessageA(hwnd, BCM_GETNOTELENGTH, 0, 0);
+ ok(ret == 0, "Expect note length: %d, got: %d\n", 0, ret);
+
+ /* Successful set note, get note and get note length */
+ SetLastError(0xdeadbeef);
+ ret = SendMessageA(hwnd, BCM_SETNOTE, 0, (LPARAM)test_w);
+ ok(ret, "Expect BCM_SETNOTE return true\n");
+ error = GetLastError();
+ ok(error == NO_ERROR, "Expect last error: 0x%08x, got: 0x%08x\n",
NO_ERROR, error);
+
+ SetLastError(0xdeadbeef);
+ lstrcpyW(buffer_w, deadbeef_w);
+ size = ARRAY_SIZE(buffer_w);
+ ret = SendMessageA(hwnd, BCM_GETNOTE, (WPARAM)&size, (LPARAM)buffer_w);
+ ok(ret, "Expect BCM_GETNOTE return true\n");
+ ok(!lstrcmpW(buffer_w, test_w), "Expect note: %s, got: %s\n",
wine_dbgstr_w(test_w),
+ wine_dbgstr_w(buffer_w));
+ ok(size == ARRAY_SIZE(buffer_w), "Got: %d\n", size);
+ error = GetLastError();
+ ok(error == NO_ERROR, "Expect last error: 0x%08x, got: 0x%08x\n",
NO_ERROR, error);
+
+ ret = SendMessageA(hwnd, BCM_GETNOTELENGTH, 0, 0);
+ ok(ret == ARRAY_SIZE(test_w) - 1, "Got: %d\n", ret);
+
+ /* Insufficient buffer, return partial string */
+ SetLastError(0xdeadbeef);
+ lstrcpyW(buffer_w, deadbeef_w);
+ size = ARRAY_SIZE(test_w) - 1;
+ ret = SendMessageA(hwnd, BCM_GETNOTE, (WPARAM)&size, (LPARAM)buffer_w);
+ ok(!ret, "Expect BCM_GETNOTE return false\n");
+ ok(!lstrcmpW(buffer_w, tes_w), "Expect note: %s, got: %s\n",
wine_dbgstr_w(tes_w),
+ wine_dbgstr_w(buffer_w));
+ ok(size == ARRAY_SIZE(test_w), "Got: %d\n", size);
+ error = GetLastError();
+ ok(error == ERROR_INSUFFICIENT_BUFFER, "Expect last error: 0x%08x, got:
0x%08x\n",
+ ERROR_INSUFFICIENT_BUFFER, error);
+
+ /* Set note with NULL buffer */
+ SetLastError(0xdeadbeef);
+ ret = SendMessageA(hwnd, BCM_SETNOTE, 0, 0);
+ ok(ret, "Expect BCM_SETNOTE return false\n");
+ error = GetLastError();
+ ok(error == NO_ERROR, "Expect last error: 0x%08x, got: 0x%08x\n",
NO_ERROR, error);
+
+ /* Check that set note with NULL buffer make note empty */
+ SetLastError(0xdeadbeef);
+ lstrcpyW(buffer_w, deadbeef_w);
+ size = ARRAY_SIZE(buffer_w);
+ ret = SendMessageA(hwnd, BCM_GETNOTE, (WPARAM)&size, (LPARAM)buffer_w);
+ ok(ret, "Expect BCM_GETNOTE return true\n");
+ ok(lstrlenW(buffer_w) == 0, "Expect note length 0\n");
+ ok(size == ARRAY_SIZE(buffer_w), "Got: %d\n", size);
+ error = GetLastError();
+ ok(error == NO_ERROR, "Expect last error: 0x%08x, got: 0x%08x\n",
NO_ERROR, error);
+ ret = SendMessageA(hwnd, BCM_GETNOTELENGTH, 0, 0);
+ ok(ret == 0, "Expect note length: %d, got: %d\n", 0, ret);
+
+ /* Get note with NULL buffer */
+ SetLastError(0xdeadbeef);
+ size = ARRAY_SIZE(buffer_w);
+ ret = SendMessageA(hwnd, BCM_GETNOTE, (WPARAM)&size, 0);
+ ok(!ret, "Expect BCM_SETNOTE return false\n");
+ ok(size == ARRAY_SIZE(buffer_w), "Got: %d\n", size);
+ error = GetLastError();
+ ok(error == ERROR_INVALID_PARAMETER, "Expect last error: 0x%08x, got:
0x%08x\n",
+ ERROR_INVALID_PARAMETER, error);
+
+ /* Get note with NULL size */
+ SetLastError(0xdeadbeef);
+ lstrcpyW(buffer_w, deadbeef_w);
+ ret = SendMessageA(hwnd, BCM_GETNOTE, 0, (LPARAM)buffer_w);
+ ok(!ret, "Expect BCM_SETNOTE return false\n");
+ ok(!lstrcmpW(buffer_w, deadbeef_w), "Expect note: %s, got: %s\n",
+ wine_dbgstr_w(deadbeef_w), wine_dbgstr_w(buffer_w));
+ error = GetLastError();
+ ok(error == ERROR_INVALID_PARAMETER, "Expect last error: 0x%08x, got:
0x%08x\n",
+ ERROR_INVALID_PARAMETER, error);
+
+ /* Get note with zero size */
+ SetLastError(0xdeadbeef);
+ size = 0;
+ lstrcpyW(buffer_w, deadbeef_w);
+ ret = SendMessageA(hwnd, BCM_GETNOTE, (WPARAM)&size, (LPARAM)buffer_w);
+ ok(!ret, "Expect BCM_GETNOTE return false\n");
+ ok(!lstrcmpW(buffer_w, deadbeef_w), "Expect note: %s, got: %s\n",
+ wine_dbgstr_w(deadbeef_w), wine_dbgstr_w(buffer_w));
+ ok(size == 1, "Got: %d\n", size);
+ error = GetLastError();
+ ok(error == ERROR_INSUFFICIENT_BUFFER, "Expect last error: 0x%08x, got:
0x%08x\n",
+ ERROR_INSUFFICIENT_BUFFER, error);
+
+ DestroyWindow(hwnd);
+ }
+ else
+ {
+ hwnd = create_button(type, NULL);
+ ok(hwnd != NULL, "Expect hwnd not null\n");
+ SetLastError(0xdeadbeef);
+ size = ARRAY_SIZE(buffer_w);
+ ret = SendMessageA(hwnd, BCM_GETNOTE, (WPARAM)&size, (LPARAM)buffer_w);
+ ok(!ret, "Expect BCM_GETNOTE return false\n");
+ error = GetLastError();
+ ok(error == ERROR_NOT_SUPPORTED, "Expect last error: 0x%08x, got:
0x%08x\n",
+ ERROR_NOT_SUPPORTED, error);
+ DestroyWindow(hwnd);
+ }
+ }
+}
+
+static void test_bm_get_set_image(void)
+{
+ HWND hwnd;
+ HDC hdc;
+ HBITMAP hbmp1x1;
+ HBITMAP hbmp2x2;
+ HBITMAP hmask2x2;
+ ICONINFO icon_info2x2;
+ HICON hicon2x2;
+ HBITMAP hbmp;
+ HICON hicon;
+ ICONINFO icon_info;
+ BITMAP bm;
+ static const DWORD default_style = BS_PUSHBUTTON | WS_TABSTOP | WS_POPUP |
WS_VISIBLE;
+
+ hdc = GetDC(0);
+ hbmp1x1 = CreateCompatibleBitmap(hdc, 1, 1);
+ hbmp2x2 = CreateCompatibleBitmap(hdc, 2, 2);
+ ZeroMemory(&bm, sizeof(bm));
+ ok(GetObjectW(hbmp1x1, sizeof(bm), &bm), "Expect GetObjectW()
success\n");
+ ok(bm.bmWidth == 1 && bm.bmHeight == 1, "Expect bitmap size: %d,%d, got:
%d,%d\n", 1, 1,
+ bm.bmWidth, bm.bmHeight);
+ ZeroMemory(&bm, sizeof(bm));
+ ok(GetObjectW(hbmp2x2, sizeof(bm), &bm), "Expect GetObjectW()
success\n");
+ ok(bm.bmWidth == 2 && bm.bmHeight == 2, "Expect bitmap size: %d,%d, got:
%d,%d\n", 2, 2,
+ bm.bmWidth, bm.bmHeight);
+
+ hmask2x2 = CreateCompatibleBitmap(hdc, 2, 2);
+ ZeroMemory(&icon_info2x2, sizeof(icon_info2x2));
+ icon_info2x2.fIcon = TRUE;
+ icon_info2x2.hbmMask = hmask2x2;
+ icon_info2x2.hbmColor = hbmp2x2;
+ hicon2x2 = CreateIconIndirect(&icon_info2x2);
+ ok(hicon2x2 !=NULL, "Expect CreateIconIndirect() success\n");
+
+ ZeroMemory(&icon_info, sizeof(icon_info));
+ ok(GetIconInfo(hicon2x2, &icon_info), "Expect GetIconInfo()
success\n");
+ ZeroMemory(&bm, sizeof(bm));
+ ok(GetObjectW(icon_info.hbmColor, sizeof(bm), &bm), "Expect GetObjectW()
success\n");
+ ok(bm.bmWidth == 2 && bm.bmHeight == 2, "Expect bitmap size: %d,%d, got:
%d,%d\n", 2, 2,
+ bm.bmWidth, bm.bmHeight);
+ DeleteObject(icon_info.hbmColor);
+ DeleteObject(icon_info.hbmMask);
+
+ hwnd = CreateWindowA(WC_BUTTONA, "test", default_style | BS_BITMAP, 0, 0,
100, 100, 0, 0,
+ 0, 0);
+ ok(hwnd != NULL, "Expect hwnd to be not NULL\n");
+ /* Get image when image is not set */
+ hbmp = (HBITMAP)SendMessageA(hwnd, BM_GETIMAGE, IMAGE_BITMAP, 0);
+ ok(hbmp == 0, "Expect hbmp == 0\n");
+ /* Set image */
+ hbmp = (HBITMAP)SendMessageA(hwnd, BM_SETIMAGE, IMAGE_BITMAP, (LPARAM)hbmp1x1);
+ ok(hbmp == 0, "Expect hbmp == 0\n");
+ hbmp = (HBITMAP)SendMessageA(hwnd, BM_GETIMAGE, IMAGE_BITMAP, 0);
+ ok(hbmp != 0, "Expect hbmp != 0\n");
+ /* Set null resets image */
+ hbmp = (HBITMAP)SendMessageA(hwnd, BM_SETIMAGE, IMAGE_BITMAP, 0);
+ ok(hbmp != 0, "Expect hbmp != 0\n");
+ hbmp = (HBITMAP)SendMessageA(hwnd, BM_GETIMAGE, IMAGE_BITMAP, 0);
+ ok(hbmp == 0, "Expect hbmp == 0\n");
+ DestroyWindow(hwnd);
+
+ /* Set bitmap with BS_BITMAP */
+ hwnd = CreateWindowA(WC_BUTTONA, "test", default_style | BS_BITMAP, 0, 0,
100, 100, 0, 0,
+ 0, 0);
+ ok(hwnd != NULL, "Expect hwnd to be not NULL\n");
+ hbmp = (HBITMAP)SendMessageA(hwnd, BM_SETIMAGE, IMAGE_BITMAP, (LPARAM)hbmp1x1);
+ ok(hbmp == 0, "Expect hbmp == 0\n");
+ hbmp = (HBITMAP)SendMessageA(hwnd, BM_GETIMAGE, IMAGE_BITMAP, 0);
+ ok(hbmp != 0, "Expect hbmp != 0\n");
+ ZeroMemory(&bm, sizeof(bm));
+ ok(GetObjectW(hbmp, sizeof(bm), &bm), "Expect GetObjectW()
success\n");
+ ok(bm.bmWidth == 1 && bm.bmHeight == 1, "Expect bitmap size: %d,%d, got:
%d,%d\n", 1, 1,
+ bm.bmWidth, bm.bmHeight);
+ DestroyWindow(hwnd);
+
+ /* Set bitmap without BS_BITMAP */
+ hwnd = CreateWindowA(WC_BUTTONA, "test", default_style, 0, 0, 100, 100, 0,
0, 0, 0);
+ ok(hwnd != NULL, "Expect hwnd to be not NULL\n");
+ hbmp = (HBITMAP)SendMessageA(hwnd, BM_SETIMAGE, IMAGE_BITMAP, (LPARAM)hbmp1x1);
+ ok(hbmp == 0, "Expect hbmp == 0\n");
+ hbmp = (HBITMAP)SendMessageA(hwnd, BM_GETIMAGE, IMAGE_BITMAP, 0);
+ if (hbmp == 0)
+ {
+ /* on xp or 2003*/
+ win_skip("Show both image and text is not supported. Skip following
tests.\n");
+ DestroyWindow(hwnd);
+ goto done;
+ }
+ ok(hbmp != 0, "Expect hbmp != 0\n");
+ ZeroMemory(&bm, sizeof(bm));
+ ok(GetObjectW(hbmp, sizeof(bm), &bm), "Expect GetObjectW()
success\n");
+ ok(bm.bmWidth == 1 && bm.bmHeight == 1, "Expect bitmap size: %d,%d, got:
%d,%d\n", 1, 1,
+ bm.bmWidth, bm.bmHeight);
+ DestroyWindow(hwnd);
+
+ /* Set icon with BS_ICON */
+ hwnd = CreateWindowA(WC_BUTTONA, "test", default_style | BS_ICON, 0, 0,
100, 100, 0, 0, 0,
+ 0);
+ ok(hwnd != NULL, "Expect hwnd to be not NULL\n");
+ hicon = (HICON)SendMessageA(hwnd, BM_SETIMAGE, IMAGE_ICON, (LPARAM)hicon2x2);
+ ok(hicon == 0, "Expect hicon == 0\n");
+ hicon = (HICON)SendMessageA(hwnd, BM_GETIMAGE, IMAGE_ICON, 0);
+ ok(hicon != 0, "Expect hicon != 0\n");
+ ZeroMemory(&icon_info, sizeof(icon_info));
+ ok(GetIconInfo(hicon, &icon_info), "Expect GetIconInfo() success\n");
+ ZeroMemory(&bm, sizeof(bm));
+ ok(GetObjectW(icon_info.hbmColor, sizeof(bm), &bm), "Expect GetObjectW()
success\n");
+ ok(bm.bmWidth == 2 && bm.bmHeight == 2, "Expect bitmap size: %d,%d, got:
%d,%d\n", 2, 2,
+ bm.bmWidth, bm.bmHeight);
+ DeleteObject(icon_info.hbmColor);
+ DeleteObject(icon_info.hbmMask);
+ DestroyWindow(hwnd);
+
+ /* Set icon without BS_ICON */
+ hwnd = CreateWindowA(WC_BUTTONA, "test", default_style, 0, 0, 100, 100, 0,
0, 0, 0);
+ ok(hwnd != NULL, "Expect hwnd to be not NULL\n");
+ hicon = (HICON)SendMessageA(hwnd, BM_SETIMAGE, IMAGE_ICON, (LPARAM)hicon2x2);
+ ok(hicon == 0, "Expect hicon == 0\n");
+ hicon = (HICON)SendMessageA(hwnd, BM_GETIMAGE, IMAGE_ICON, 0);
+ ok(hicon != 0, "Expect hicon != 0\n");
+ ZeroMemory(&icon_info, sizeof(icon_info));
+ ok(GetIconInfo(hicon, &icon_info), "Expect GetIconInfo() success\n");
+ ZeroMemory(&bm, sizeof(bm));
+ ok(GetObjectW(icon_info.hbmColor, sizeof(bm), &bm), "Expect GetObjectW()
success\n");
+ ok(bm.bmWidth == 2 && bm.bmHeight == 2, "Expect bitmap size: %d,%d, got:
%d,%d\n", 2, 2,
+ bm.bmWidth, bm.bmHeight);
+ DeleteObject(icon_info.hbmColor);
+ DeleteObject(icon_info.hbmMask);
+ DestroyWindow(hwnd);
+
+ /* Set icon with BS_BITMAP */
+ hwnd = CreateWindowA(WC_BUTTONA, "test", default_style | BS_BITMAP, 0, 0,
100, 100, 0, 0,
+ 0, 0);
+ ok(hwnd != NULL, "Expect hwnd to be not NULL\n");
+ hicon = (HICON)SendMessageA(hwnd, BM_SETIMAGE, IMAGE_ICON, (LPARAM)hicon2x2);
+ ok(hicon == 0, "Expect hicon == 0\n");
+ hicon = (HICON)SendMessageA(hwnd, BM_GETIMAGE, IMAGE_ICON, 0);
+ ok(hicon != 0, "Expect hicon != 0\n");
+ ZeroMemory(&icon_info, sizeof(icon_info));
+ ok(GetIconInfo(hicon, &icon_info), "Expect GetIconInfo() success\n");
+ ZeroMemory(&bm, sizeof(bm));
+ ok(GetObjectW(icon_info.hbmColor, sizeof(bm), &bm), "Expect GetObjectW()
success\n");
+ ok(bm.bmWidth == 2 && bm.bmHeight == 2, "Expect bitmap size: %d,%d, got:
%d,%d\n", 2, 2,
+ bm.bmWidth, bm.bmHeight);
+ DeleteObject(icon_info.hbmColor);
+ DeleteObject(icon_info.hbmMask);
+ DestroyWindow(hwnd);
+
+ /* Set bitmap with BS_ICON */
+ hwnd = CreateWindowA(WC_BUTTONA, "test", default_style | BS_ICON, 0, 0,
100, 100, 0, 0, 0,
+ 0);
+ ok(hwnd != NULL, "Expect hwnd to be not NULL\n");
+ hbmp = (HBITMAP)SendMessageA(hwnd, BM_SETIMAGE, IMAGE_BITMAP, (LPARAM)hbmp1x1);
+ ok(hbmp == 0, "Expect hbmp == 0\n");
+ hbmp = (HBITMAP)SendMessageA(hwnd, BM_GETIMAGE, IMAGE_BITMAP, 0);
+ ok(hbmp != 0, "Expect hbmp != 0\n");
+ ZeroMemory(&bm, sizeof(bm));
+ ok(GetObjectW(hbmp, sizeof(bm), &bm), "Expect GetObjectW()
success\n");
+ ok(bm.bmWidth == 1 && bm.bmHeight == 1, "Expect bitmap size: %d,%d, got:
%d,%d\n", 1, 1,
+ bm.bmWidth, bm.bmHeight);
+ DestroyWindow(hwnd);
+
+ /* Set bitmap with BS_BITMAP and IMAGE_ICON*/
+ hwnd = CreateWindowA(WC_BUTTONA, "test", default_style | BS_BITMAP, 0, 0,
100, 100, 0, 0,
+ 0, 0);
+ ok(hwnd != NULL, "Expect hwnd to be not NULL\n");
+ hbmp = (HBITMAP)SendMessageA(hwnd, BM_SETIMAGE, IMAGE_ICON, (LPARAM)hbmp1x1);
+ ok(hbmp == 0, "Expect hbmp == 0\n");
+ hbmp = (HBITMAP)SendMessageA(hwnd, BM_GETIMAGE, IMAGE_ICON, 0);
+ ok(hbmp != 0, "Expect hbmp != 0\n");
+ ZeroMemory(&bm, sizeof(bm));
+ ok(GetObjectW(hbmp, sizeof(bm), &bm), "Expect GetObjectW()
success\n");
+ ok(bm.bmWidth == 1 && bm.bmHeight == 1, "Expect bitmap size: %d,%d, got:
%d,%d\n", 1, 1,
+ bm.bmWidth, bm.bmHeight);
+ DestroyWindow(hwnd);
+
+ /* Set icon with BS_ICON and IMAGE_BITMAP */
+ hwnd = CreateWindowA(WC_BUTTONA, "test", default_style | BS_ICON, 0, 0,
100, 100, 0, 0, 0,
+ 0);
+ ok(hwnd != NULL, "Expect hwnd to be not NULL\n");
+ hicon = (HICON)SendMessageA(hwnd, BM_SETIMAGE, IMAGE_BITMAP, (LPARAM)hicon2x2);
+ ok(hicon == 0, "Expect hicon == 0\n");
+ hicon = (HICON)SendMessageA(hwnd, BM_GETIMAGE, IMAGE_BITMAP, 0);
+ ok(hicon != 0, "Expect hicon != 0\n");
+ ZeroMemory(&icon_info, sizeof(icon_info));
+ ok(GetIconInfo(hicon, &icon_info), "Expect GetIconInfo() success\n");
+ ZeroMemory(&bm, sizeof(bm));
+ ok(GetObjectW(icon_info.hbmColor, sizeof(BITMAP), &bm), "Expect GetObjectW()
success\n");
+ ok(bm.bmWidth == 2 && bm.bmHeight == 2, "Expect bitmap size: %d,%d, got:
%d,%d\n", 2, 2,
+ bm.bmWidth, bm.bmHeight);
+ DeleteObject(icon_info.hbmColor);
+ DeleteObject(icon_info.hbmMask);
+ DestroyWindow(hwnd);
+
+ /* Set bitmap with BS_ICON and IMAGE_ICON */
+ hwnd = CreateWindowA(WC_BUTTONA, "test", default_style | BS_ICON, 0, 0,
100, 100, 0, 0, 0, 0);
+ ok(hwnd != NULL, "Expect hwnd to be not NULL\n");
+ hbmp = (HBITMAP)SendMessageA(hwnd, BM_SETIMAGE, IMAGE_ICON, (LPARAM)hbmp1x1);
+ ok(hbmp == 0, "Expect hbmp == 0\n");
+ hbmp = (HBITMAP)SendMessageA(hwnd, BM_GETIMAGE, IMAGE_ICON, 0);
+ ok(hbmp != 0, "Expect hbmp != 0\n");
+ ZeroMemory(&bm, sizeof(bm));
+ ok(GetObjectW(hbmp, sizeof(bm), &bm), "Expect GetObjectW()
success\n");
+ ok(bm.bmWidth == 1 && bm.bmHeight == 1, "Expect bitmap size: %d,%d, got:
%d,%d\n", 1, 1,
+ bm.bmWidth, bm.bmHeight);
+ DestroyWindow(hwnd);
+
+ /* Set icon with BS_BITMAP and IMAGE_BITMAP */
+ hwnd = CreateWindowA(WC_BUTTONA, "test", default_style | BS_BITMAP, 0, 0,
100, 100, 0, 0, 0, 0);
+ ok(hwnd != NULL, "Expect hwnd to be not NULL\n");
+ hicon = (HICON)SendMessageA(hwnd, BM_SETIMAGE, IMAGE_BITMAP, (LPARAM)hicon2x2);
+ ok(hicon == 0, "Expect hicon == 0\n");
+ hicon = (HICON)SendMessageA(hwnd, BM_GETIMAGE, IMAGE_BITMAP, 0);
+ ok(hicon != 0, "Expect hicon != 0\n");
+ ZeroMemory(&icon_info, sizeof(icon_info));
+ ok(GetIconInfo(hicon, &icon_info), "Expect GetIconInfo() success\n");
+ ZeroMemory(&bm, sizeof(bm));
+ ok(GetObjectW(icon_info.hbmColor, sizeof(BITMAP), &bm), "Expect GetObjectW()
success\n");
+ ok(bm.bmWidth == 2 && bm.bmHeight == 2, "Expect bitmap size: %d,%d, got:
%d,%d\n", 2, 2,
+ bm.bmWidth, bm.bmHeight);
+ DeleteObject(icon_info.hbmColor);
+ DeleteObject(icon_info.hbmMask);
+ DestroyWindow(hwnd);
+
+done:
+ DestroyIcon(hicon2x2);
+ DeleteObject(hmask2x2);
+ DeleteObject(hbmp2x2);
+ DeleteObject(hbmp1x1);
+ ReleaseDC(0, hdc);
+}
+
static void register_parent_class(void)
{
WNDCLASSA cls;
@@ -824,6 +1228,504 @@ static void register_parent_class(void)
RegisterClassA(&cls);
}
+static void test_button_data(void)
+{
+ static const DWORD styles[] =
+ {
+ BS_PUSHBUTTON,
+ BS_DEFPUSHBUTTON,
+ BS_CHECKBOX,
+ BS_AUTOCHECKBOX,
+ BS_RADIOBUTTON,
+ BS_3STATE,
+ BS_AUTO3STATE,
+ BS_GROUPBOX,
+ BS_USERBUTTON,
+ BS_AUTORADIOBUTTON,
+ BS_OWNERDRAW,
+ BS_SPLITBUTTON,
+ BS_DEFSPLITBUTTON,
+ BS_COMMANDLINK,
+ BS_DEFCOMMANDLINK,
+ };
+
+ struct button_desc
+ {
+ HWND self;
+ HWND parent;
+ LONG style;
+ };
+ unsigned int i;
+ HWND parent;
+
+ parent = CreateWindowExA(0, "TestParentClass", "Test parent",
WS_OVERLAPPEDWINDOW | WS_VISIBLE,
+ 100, 100, 200, 200, 0, 0, 0, NULL);
+ ok(parent != 0, "Failed to create parent window\n");
+
+ for (i = 0; i < ARRAY_SIZE(styles); i++)
+ {
+ struct button_desc *desc;
+ HWND hwnd;
+
+ hwnd = create_button(styles[i], parent);
+ ok(hwnd != NULL, "Failed to create a button.\n");
+
+ desc = (void *)GetWindowLongPtrA(hwnd, 0);
+ ok(desc != NULL, "Expected window data.\n");
+
+ if (desc)
+ {
+ ok(desc->self == hwnd, "Unexpected 'self' field.\n");
+ ok(desc->parent == parent, "Unexpected 'parent'
field.\n");
+ ok(desc->style == (WS_CHILD | BS_NOTIFY | styles[i]), "Unexpected
'style' field.\n");
+ }
+
+ DestroyWindow(hwnd);
+ }
+
+ DestroyWindow(parent);
+}
+
+static void test_get_set_imagelist(void)
+{
+ HWND hwnd;
+ HIMAGELIST himl;
+ BUTTON_IMAGELIST biml = {0};
+ HDC hdc;
+ HBITMAP hbmp;
+ INT width = 16;
+ INT height = 16;
+ INT index;
+ DWORD type;
+ BOOL ret;
+
+ hdc = GetDC(0);
+ hbmp = CreateCompatibleBitmap(hdc, width, height);
+ ok(hbmp != NULL, "Expect hbmp not null\n");
+
+ himl = pImageList_Create(width, height, ILC_COLOR, 1, 0);
+ ok(himl != NULL, "Expect himl not null\n");
+ index = pImageList_Add(himl, hbmp, NULL);
+ ok(index == 0, "Expect index == 0\n");
+ DeleteObject(hbmp);
+ ReleaseDC(0, hdc);
+
+ for (type = BS_PUSHBUTTON; type <= BS_DEFCOMMANDLINK; type++)
+ {
+ hwnd = create_button(type, NULL);
+ ok(hwnd != NULL, "Expect hwnd not null\n");
+
+ /* Get imagelist when imagelist is unset yet */
+ ret = SendMessageA(hwnd, BCM_GETIMAGELIST, 0, (LPARAM)&biml);
+ ok(ret, "Expect BCM_GETIMAGELIST return true\n");
+ ok(biml.himl == 0 && IsRectEmpty(&biml.margin) && biml.uAlign
== 0,
+ "Expect BUTTON_IMAGELIST is empty\n");
+
+ /* Set imagelist with himl null */
+ biml.himl = 0;
+ biml.uAlign = BUTTON_IMAGELIST_ALIGN_CENTER;
+ ret = SendMessageA(hwnd, BCM_SETIMAGELIST, 0, (LPARAM)&biml);
+ ok(ret || broken(!ret), /* xp or 2003 */
+ "Expect BCM_SETIMAGELIST return true\n");
+
+ /* Set imagelist with uAlign invalid */
+ biml.himl = himl;
+ biml.uAlign = -1;
+ ret = SendMessageA(hwnd, BCM_SETIMAGELIST, 0, (LPARAM)&biml);
+ ok(ret, "Expect BCM_SETIMAGELIST return true\n");
+
+ /* Successful get and set imagelist */
+ biml.himl = himl;
+ biml.uAlign = BUTTON_IMAGELIST_ALIGN_CENTER;
+ ret = SendMessageA(hwnd, BCM_SETIMAGELIST, 0, (LPARAM)&biml);
+ ok(ret, "Expect BCM_SETIMAGELIST return true\n");
+ ret = SendMessageA(hwnd, BCM_GETIMAGELIST, 0, (LPARAM)&biml);
+ ok(ret, "Expect BCM_GETIMAGELIST return true\n");
+ ok(biml.himl == himl, "Expect himl to be same\n");
+ ok(biml.uAlign == BUTTON_IMAGELIST_ALIGN_CENTER, "Expect uAlign to be
%x\n",
+ BUTTON_IMAGELIST_ALIGN_CENTER);
+
+ /* BCM_SETIMAGELIST null pointer handling */
+ ret = SendMessageA(hwnd, BCM_SETIMAGELIST, 0, 0);
+ ok(!ret, "Expect BCM_SETIMAGELIST return false\n");
+ ret = SendMessageA(hwnd, BCM_GETIMAGELIST, 0, (LPARAM)&biml);
+ ok(ret, "Expect BCM_GETIMAGELIST return true\n");
+ ok(biml.himl == himl, "Expect himl to be same\n");
+
+ /* BCM_GETIMAGELIST null pointer handling */
+ biml.himl = himl;
+ biml.uAlign = BUTTON_IMAGELIST_ALIGN_CENTER;
+ ret = SendMessageA(hwnd, BCM_SETIMAGELIST, 0, (LPARAM)&biml);
+ ok(ret, "Expect BCM_SETIMAGELIST return true\n");
+ ret = SendMessageA(hwnd, BCM_GETIMAGELIST, 0, 0);
+ ok(!ret, "Expect BCM_GETIMAGELIST return false\n");
+
+ DestroyWindow(hwnd);
+ }
+
+ pImageList_Destroy(himl);
+}
+
+static void test_get_set_textmargin(void)
+{
+ HWND hwnd;
+ RECT margin_in;
+ RECT margin_out;
+ BOOL ret;
+ DWORD type;
+
+ SetRect(&margin_in, 2, 1, 3, 4);
+ for (type = BS_PUSHBUTTON; type <= BS_DEFCOMMANDLINK; type++)
+ {
+ hwnd = create_button(type, NULL);
+ ok(hwnd != NULL, "Expect hwnd not null\n");
+
+ /* Get text margin when it is unset */
+ ret = SendMessageA(hwnd, BCM_GETTEXTMARGIN, 0, (LPARAM)&margin_out);
+ ok(ret, "Expect ret to be true\n");
+ ok(IsRectEmpty(&margin_out), "Expect margin empty\n");
+
+ /* Successful get and set text margin */
+ ret = SendMessageA(hwnd, BCM_SETTEXTMARGIN, 0, (LPARAM)&margin_in);
+ ok(ret, "Expect ret to be true\n");
+ SetRectEmpty(&margin_out);
+ ret = SendMessageA(hwnd, BCM_GETTEXTMARGIN, 0, (LPARAM)&margin_out);
+ ok(ret, "Expect ret to be true\n");
+ ok(EqualRect(&margin_in, &margin_out), "Expect margins to be
equal\n");
+
+ /* BCM_SETTEXTMARGIN null pointer handling */
+ ret = SendMessageA(hwnd, BCM_SETTEXTMARGIN, 0, 0);
+ ok(!ret, "Expect ret to be false\n");
+ SetRectEmpty(&margin_out);
+ ret = SendMessageA(hwnd, BCM_GETTEXTMARGIN, 0, (LPARAM)&margin_out);
+ ok(ret, "Expect ret to be true\n");
+ ok(EqualRect(&margin_in, &margin_out), "Expect margins to be
equal\n");
+
+ /* BCM_GETTEXTMARGIN null pointer handling */
+ ret = SendMessageA(hwnd, BCM_SETTEXTMARGIN, 0, (LPARAM)&margin_in);
+ ok(ret, "Expect ret to be true\n");
+ ret = SendMessageA(hwnd, BCM_GETTEXTMARGIN, 0, 0);
+ ok(!ret, "Expect ret to be true\n");
+
+ DestroyWindow(hwnd);
+ }
+}
+
+static void test_state(void)
+{
+ HWND hwnd;
+ DWORD type;
+ LONG state;
+
+ /* Initial button state */
+ for (type = BS_PUSHBUTTON; type <= BS_DEFCOMMANDLINK; type++)
+ {
+ hwnd = create_button(type, NULL);
+ state = SendMessageA(hwnd, BM_GETSTATE, 0, 0);
+ ok(state == BST_UNCHECKED, "Expect state 0x%08x, got 0x%08x\n",
BST_UNCHECKED, state);
+ DestroyWindow(hwnd);
+ }
+}
+
+static void test_bcm_get_ideal_size(void)
+{
+ static const char *button_text2 = "WWWW\nWWWW";
+ static const char *button_text = "WWWW";
+ static const DWORD imagelist_aligns[] = {BUTTON_IMAGELIST_ALIGN_LEFT,
BUTTON_IMAGELIST_ALIGN_RIGHT,
+ BUTTON_IMAGELIST_ALIGN_TOP,
BUTTON_IMAGELIST_ALIGN_BOTTOM,
+ BUTTON_IMAGELIST_ALIGN_CENTER};
+ static const DWORD aligns[] = {0, BS_TOP, BS_LEFT, BS_RIGHT,
BS_BOTTOM,
+ BS_CENTER, BS_VCENTER, BS_RIGHTBUTTON, WS_EX_RIGHT};
+ DWORD default_style = WS_TABSTOP | WS_POPUP | WS_VISIBLE;
+ const LONG client_width = 400, client_height = 200;
+ LONG image_width, height, line_count, text_width;
+ HFONT hfont, prev_font;
+ DWORD style, type;
+ BOOL ret;
+ HWND hwnd;
+ HDC hdc;
+ LOGFONTA lf;
+ TEXTMETRICA tm;
+ SIZE size;
+ HBITMAP hmask, hbmp;
+ ICONINFO icon_info;
+ HICON hicon;
+ HIMAGELIST himl;
+ BUTTON_IMAGELIST biml = {0};
+ RECT rect;
+ INT i, j;
+
+ /* Check for NULL pointer handling */
+ hwnd = CreateWindowA(WC_BUTTONA, button_text, BS_PUSHBUTTON | default_style, 0, 0,
client_width, client_height,
+ NULL, NULL, 0, NULL);
+ ret = SendMessageA(hwnd, BCM_GETIDEALSIZE, 0, 0);
+ ok(!ret, "Expect BCM_GETIDEALSIZE message to return false.\n");
+
+ /* Set font so that the test is consistent on Wine and Windows */
+ ZeroMemory(&lf, sizeof(lf));
+ lf.lfWeight = FW_NORMAL;
+ lf.lfHeight = 20;
+ lstrcpyA(lf.lfFaceName, "Tahoma");
+ hfont = CreateFontIndirectA(&lf);
+ ok(hfont != NULL, "Failed to create test font.\n");
+
+ /* Get tmHeight */
+ hdc = GetDC(hwnd);
+ prev_font = SelectObject(hdc, hfont);
+ GetTextMetricsA(hdc, &tm);
+ SelectObject(hdc, prev_font);
+ DrawTextA(hdc, button_text, -1, &rect, DT_CALCRECT);
+ text_width = rect.right - rect.left;
+ ReleaseDC(hwnd, hdc);
+ DestroyWindow(hwnd);
+
+ /* XP and 2003 doesn't support command links, getting ideal size with button
having only text returns client size on these platforms. */
+ hwnd = CreateWindowA(WC_BUTTONA, button_text, BS_DEFCOMMANDLINK | default_style, 0,
0, client_width, client_height, NULL,
+ NULL, 0, NULL);
+ ok(hwnd != NULL, "Expect hwnd not NULL\n");
+ SendMessageA(hwnd, WM_SETFONT, (WPARAM)hfont, (LPARAM)TRUE);
+ ZeroMemory(&size, sizeof(size));
+ ret = SendMessageA(hwnd, BCM_GETIDEALSIZE, 0, (LPARAM)&size);
+ ok(ret, "Expect BCM_GETIDEALSIZE message to return true\n");
+ if (size.cx == client_width && size.cy == client_height)
+ {
+ /* on XP and 2003, buttons with image are not supported */
+ win_skip("Skipping further tests on XP and 2003\n");
+ return;
+ }
+
+ /* Tests for image placements */
+ /* Prepare bitmap */
+ image_width = 48;
+ height = 48;
+ hdc = GetDC(0);
+ hmask = CreateCompatibleBitmap(hdc, image_width, height);
+ hbmp = CreateCompatibleBitmap(hdc, image_width, height);
+
+ /* Only bitmap for push button, ideal size should be enough for image and text */
+ hwnd = CreateWindowA(WC_BUTTONA, button_text, BS_DEFPUSHBUTTON | BS_BITMAP |
default_style, 0, 0, client_width,
+ client_height, NULL, NULL, 0, NULL);
+ ok(hwnd != NULL, "Expect hwnd not NULL\n");
+ SendMessageA(hwnd, BM_SETIMAGE, (WPARAM)IMAGE_BITMAP, (LPARAM)hbmp);
+ SendMessageA(hwnd, WM_SETFONT, (WPARAM)hfont, (LPARAM)TRUE);
+ ZeroMemory(&size, sizeof(size));
+ ret = SendMessageA(hwnd, BCM_GETIDEALSIZE, 0, (LPARAM)&size);
+ ok(ret, "Expect BCM_GETIDEALSIZE message to return true\n");
+ /* Ideal size contains text rect even show bitmap only */
+ ok((size.cx >= image_width + text_width && size.cy >= max(height,
tm.tmHeight)),
+ "Expect ideal cx %d >= %d and ideal cy %d >= %d\n", size.cx,
image_width + text_width,
+ size.cy, max(height, tm.tmHeight));
+ DestroyWindow(hwnd);
+
+ /* Image alignments when button has bitmap and text*/
+ for (i = 0; i < ARRAY_SIZE(aligns); i++)
+ for (j = 0; j < ARRAY_SIZE(aligns); j++)
+ {
+ style = BS_DEFPUSHBUTTON | default_style | aligns[i] | aligns[j];
+ hwnd = CreateWindowA(WC_BUTTONA, button_text, style, 0, 0, client_width,
client_height, NULL, NULL, 0, NULL);
+ ok(hwnd != NULL, "Expect hwnd not NULL\n");
+ SendMessageA(hwnd, BM_SETIMAGE, (WPARAM)IMAGE_BITMAP, (LPARAM)hbmp);
+ SendMessageA(hwnd, WM_SETFONT, (WPARAM)hfont, (LPARAM)TRUE);
+ ZeroMemory(&size, sizeof(size));
+ ret = SendMessageA(hwnd, BCM_GETIDEALSIZE, 0, (LPARAM)&size);
+ ok(ret, "Expect BCM_GETIDEALSIZE message to return true\n");
+ if (!(style & (BS_CENTER | BS_VCENTER)) || ((style & BS_CENTER)
&& (style & BS_CENTER) != BS_CENTER)
+ || !(style & BS_VCENTER) || (style & BS_VCENTER) == BS_VCENTER)
+ ok((size.cx >= image_width + text_width && size.cy >=
max(height, tm.tmHeight)),
+ "Style: 0x%08x expect ideal cx %d >= %d and ideal cy %d >=
%d\n", style, size.cx,
+ image_width + text_width, size.cy, max(height, tm.tmHeight));
+ else
+ ok((size.cx >= max(text_width, height) && size.cy >= height
+ tm.tmHeight),
+ "Style: 0x%08x expect ideal cx %d >= %d and ideal cy %d >=
%d\n", style, size.cx,
+ max(text_width, height), size.cy, height + tm.tmHeight);
+ DestroyWindow(hwnd);
+ }
+
+ /* Image list alignments */
+ himl = pImageList_Create(image_width, height, ILC_COLOR, 1, 1);
+ pImageList_Add(himl, hbmp, 0);
+ biml.himl = himl;
+ for (i = 0; i < ARRAY_SIZE(imagelist_aligns); i++)
+ {
+ biml.uAlign = imagelist_aligns[i];
+ hwnd = CreateWindowA(WC_BUTTONA, button_text, BS_DEFPUSHBUTTON | default_style,
0, 0, client_width,
+ client_height, NULL, NULL, 0, NULL);
+ ok(hwnd != NULL, "Expect hwnd not NULL\n");
+ SendMessageA(hwnd, WM_SETFONT, (WPARAM)hfont, (LPARAM)TRUE);
+ SendMessageA(hwnd, BCM_SETIMAGELIST, 0, (LPARAM)&biml);
+ ZeroMemory(&size, sizeof(size));
+ ret = SendMessageA(hwnd, BCM_GETIDEALSIZE, 0, (LPARAM)&size);
+ ok(ret, "Expect BCM_GETIDEALSIZE message to return true\n");
+ if (biml.uAlign == BUTTON_IMAGELIST_ALIGN_TOP || biml.uAlign ==
BUTTON_IMAGELIST_ALIGN_BOTTOM)
+ ok((size.cx >= max(text_width, height) && size.cy >= height +
tm.tmHeight),
+ "Align:%d expect ideal cx %d >= %d and ideal cy %d >=
%d\n", biml.uAlign, size.cx,
+ max(text_width, height), size.cy, height + tm.tmHeight);
+ else if (biml.uAlign == BUTTON_IMAGELIST_ALIGN_LEFT || biml.uAlign ==
BUTTON_IMAGELIST_ALIGN_RIGHT)
+ ok((size.cx >= image_width + text_width && size.cy >=
max(height, tm.tmHeight)),
+ "Align:%d expect ideal cx %d >= %d and ideal cy %d >=
%d\n", biml.uAlign, size.cx,
+ image_width + text_width, size.cy, max(height, tm.tmHeight));
+ else
+ ok(size.cx >= image_width && size.cy >= height, "Align:%d
expect ideal cx %d >= %d and ideal cy %d >= %d\n",
+ biml.uAlign, size.cx, image_width, size.cy, height);
+ DestroyWindow(hwnd);
+ }
+
+ /* Icon as image */
+ /* Create icon from bitmap */
+ ZeroMemory(&icon_info, sizeof(icon_info));
+ icon_info.fIcon = TRUE;
+ icon_info.hbmMask = hmask;
+ icon_info.hbmColor = hbmp;
+ hicon = CreateIconIndirect(&icon_info);
+
+ /* Only icon, ideal size should be enough for image and text */
+ hwnd = CreateWindowA(WC_BUTTONA, button_text, BS_DEFPUSHBUTTON | BS_ICON |
default_style, 0, 0, client_width,
+ client_height, NULL, NULL, 0, NULL);
+ ok(hwnd != NULL, "Expect hwnd not NULL\n");
+ SendMessageA(hwnd, BM_SETIMAGE, (WPARAM)IMAGE_ICON, (LPARAM)hicon);
+ SendMessageA(hwnd, WM_SETFONT, (WPARAM)hfont, (LPARAM)TRUE);
+ ZeroMemory(&size, sizeof(size));
+ ret = SendMessageA(hwnd, BCM_GETIDEALSIZE, 0, (LPARAM)&size);
+ ok(ret, "Expect BCM_GETIDEALSIZE message to return true\n");
+ /* Ideal size contains text rect even show icons only */
+ ok((size.cx >= image_width + text_width && size.cy >= max(height,
tm.tmHeight)),
+ "Expect ideal cx %d >= %d and ideal cy %d >= %d\n", size.cx,
image_width + text_width, size.cy,
+ max(height, tm.tmHeight));
+ DestroyWindow(hwnd);
+
+ /* Show icon and text */
+ hwnd = CreateWindowA(WC_BUTTONA, button_text, BS_DEFPUSHBUTTON | default_style, 0, 0,
client_width,
+ client_height, NULL, NULL, 0, NULL);
+ ok(hwnd != NULL, "Expect hwnd not NULL\n");
+ SendMessageA(hwnd, BM_SETIMAGE, (WPARAM)IMAGE_ICON, (LPARAM)hicon);
+ SendMessageA(hwnd, WM_SETFONT, (WPARAM)hfont, (LPARAM)TRUE);
+ ZeroMemory(&size, sizeof(size));
+ ret = SendMessageA(hwnd, BCM_GETIDEALSIZE, 0, (LPARAM)&size);
+ ok(ret, "Expect BCM_GETIDEALSIZE message to return true\n");
+ ok((size.cx >= image_width + text_width && size.cy >= max(height,
tm.tmHeight)),
+ "Expect ideal cx %d >= %d and ideal cy %d >= %d\n", size.cx,
image_width + text_width, size.cy,
+ max(height, tm.tmHeight));
+ DestroyWindow(hwnd);
+
+ /* Checkbox */
+ /* Both bitmap and text for checkbox, ideal size is only enough for text because it
doesn't support image(but not image list)*/
+ hwnd = CreateWindowA(WC_BUTTONA, button_text, BS_AUTOCHECKBOX | default_style, 0, 0,
client_width, client_height,
+ NULL, NULL, 0, NULL);
+ ok(hwnd != NULL, "Expect hwnd not NULL\n");
+ SendMessageA(hwnd, BM_SETIMAGE, (WPARAM)IMAGE_BITMAP, (LPARAM)hbmp);
+ SendMessageA(hwnd, WM_SETFONT, (WPARAM)hfont, (LPARAM)TRUE);
+ ZeroMemory(&size, sizeof(size));
+ ret = SendMessageA(hwnd, BCM_GETIDEALSIZE, 0, (LPARAM)&size);
+ ok(ret, "Expect BCM_GETIDEALSIZE message to return true\n");
+ ok((size.cx <= image_width + text_width && size.cx >= text_width
&& size.cy <= max(height, tm.tmHeight)
+ && size.cy >= tm.tmHeight),
+ "Expect ideal cx %d within range (%d, %d ) and ideal cy %d within range (%d,
%d )\n", size.cx,
+ text_width, image_width + text_width, size.cy, tm.tmHeight, max(height,
tm.tmHeight));
+ DestroyWindow(hwnd);
+
+ /* Both image list and text for checkbox, ideal size should have enough for image
list and text */
+ biml.uAlign = BUTTON_IMAGELIST_ALIGN_LEFT;
+ hwnd = CreateWindowA(WC_BUTTONA, button_text, BS_AUTOCHECKBOX | BS_BITMAP |
default_style, 0, 0, client_width,
+ client_height, NULL, NULL, 0, NULL);
+ ok(hwnd != NULL, "Expect hwnd not NULL\n");
+ SendMessageA(hwnd, BCM_SETIMAGELIST, 0, (LPARAM)&biml);
+ SendMessageA(hwnd, WM_SETFONT, (WPARAM)hfont, (LPARAM)TRUE);
+ ZeroMemory(&size, sizeof(size));
+ ret = SendMessageA(hwnd, BCM_GETIDEALSIZE, 0, (LPARAM)&size);
+ ok(ret, "Expect BCM_GETIDEALSIZE message to return true\n");
+ ok((size.cx >= image_width + text_width && size.cy >= max(height,
tm.tmHeight)),
+ "Expect ideal cx %d >= %d and ideal cy %d >= %d\n", size.cx,
image_width + text_width, size.cy,
+ max(height, tm.tmHeight));
+ DestroyWindow(hwnd);
+
+ /* Only bitmap for checkbox, ideal size should have enough for image and text */
+ hwnd = CreateWindowA(WC_BUTTONA, button_text, BS_AUTOCHECKBOX | BS_BITMAP |
default_style, 0, 0, client_width,
+ client_height, NULL, NULL, 0, NULL);
+ ok(hwnd != NULL, "Expect hwnd not NULL\n");
+ SendMessageA(hwnd, BM_SETIMAGE, (WPARAM)IMAGE_BITMAP, (LPARAM)hbmp);
+ SendMessageA(hwnd, WM_SETFONT, (WPARAM)hfont, (LPARAM)TRUE);
+ ZeroMemory(&size, sizeof(size));
+ ret = SendMessageA(hwnd, BCM_GETIDEALSIZE, 0, (LPARAM)&size);
+ ok(ret, "Expect BCM_GETIDEALSIZE message to return true\n");
+ ok((size.cx >= image_width + text_width && size.cy >= max(height,
tm.tmHeight)),
+ "Expect ideal cx %d >= %d and ideal cy %d >= %d\n", size.cx,
image_width + text_width, size.cy,
+ max(height, tm.tmHeight));
+ DestroyWindow(hwnd);
+
+ /* Test button with only text */
+ /* No text */
+ for (type = BS_PUSHBUTTON; type <= BS_DEFCOMMANDLINK; type++)
+ {
+ style = type | default_style;
+ hwnd = CreateWindowA(WC_BUTTONA, "", style, 0, 0, client_width,
client_height, NULL, NULL, 0, NULL);
+ ok(hwnd != NULL, "Expect hwnd not NULL\n");
+ SendMessageA(hwnd, WM_SETFONT, (WPARAM)hfont, (LPARAM)TRUE);
+
+ ZeroMemory(&size, sizeof(size));
+ ret = SendMessageA(hwnd, BCM_GETIDEALSIZE, 0, (LPARAM)&size);
+ ok(ret, "Expect BCM_GETIDEALSIZE message to return true\n");
+
+ if (type == BS_COMMANDLINK || type == BS_DEFCOMMANDLINK)
+ {
+ todo_wine ok((size.cx == 0 && size.cy > 0), "Style 0x%08x
expect ideal cx %d >= %d and ideal cy %d >= %d\n",
+ style, size.cx, 0, size.cy, 0);
+ }
+ else
+ {
+ ok(size.cx == client_width && size.cy == client_height,
+ "Style 0x%08x expect size.cx == %d and size.cy == %d, got size.cx: %d
size.cy: %d\n", style,
+ client_width, client_height, size.cx, size.cy);
+ }
+ DestroyWindow(hwnd);
+ }
+
+ /* Single line and multiple lines text */
+ for (line_count = 1; line_count <= 2; line_count++)
+ {
+ for (type = BS_PUSHBUTTON; type <= BS_DEFCOMMANDLINK; type++)
+ {
+ style = line_count > 1 ? type | BS_MULTILINE : type;
+ style |= default_style;
+
+ hwnd = CreateWindowA(WC_BUTTONA, (line_count == 2 ? button_text2 :
button_text), style, 0, 0, client_width,
+ client_height, NULL, NULL, 0, NULL);
+ ok(hwnd != NULL, "Expect hwnd not NULL\n");
+ SendMessageA(hwnd, WM_SETFONT, (WPARAM)hfont, (LPARAM)TRUE);
+ ZeroMemory(&size, sizeof(size));
+ ret = SendMessageA(hwnd, BCM_GETIDEALSIZE, 0, (LPARAM)&size);
+ ok(ret, "Expect BCM_GETIDEALSIZE message to return true\n");
+
+ if (type == BS_3STATE || type == BS_AUTO3STATE || type == BS_GROUPBOX || type
== BS_PUSHBOX
+ || type == BS_OWNERDRAW)
+ {
+ ok(size.cx == client_width && size.cy == client_height,
+ "Style 0x%08x expect ideal size (%d,%d), got (%d,%d)\n",
style, client_width, client_height, size.cx,
+ size.cy);
+ }
+ else if (type == BS_COMMANDLINK || type == BS_DEFCOMMANDLINK)
+ {
+ todo_wine ok((size.cx == 0 && size.cy > 0),
+ "Style 0x%08x expect ideal cx %d >= %d and ideal cy
%d >= %d\n", style, size.cx, 0,
+ size.cy, 0);
+ }
+ else
+ {
+ height = line_count == 2 ? 2 * tm.tmHeight : tm.tmHeight;
+ ok(size.cx >= 0 && size.cy >= height, "Style 0x%08x
expect ideal cx %d >= 0 and ideal cy %d >= %d\n",
+ style, size.cx, size.cy, height);
+ }
+ DestroyWindow(hwnd);
+ }
+ }
+
+ pImageList_Destroy(himl);
+ DestroyIcon(hicon);
+ DeleteObject(hbmp);
+ DeleteObject(hmask);
+ ReleaseDC(0, hdc);
+ DeleteObject(hfont);
+}
+
START_TEST(button)
{
ULONG_PTR ctx_cookie;
@@ -839,6 +1741,13 @@ START_TEST(button)
test_button_class();
test_button_messages();
+ test_note();
+ test_button_data();
+ test_bm_get_set_image();
+ test_get_set_imagelist();
+ test_get_set_textmargin();
+ test_state();
+ test_bcm_get_ideal_size();
unload_v6_module(ctx_cookie, hCtx);
}
diff --git a/modules/rostests/winetests/comctl32/combo.c
b/modules/rostests/winetests/comctl32/combo.c
index 83b36f212f..923d826b30 100644
--- a/modules/rostests/winetests/comctl32/combo.c
+++ b/modules/rostests/winetests/comctl32/combo.c
@@ -264,7 +264,7 @@ static void test_comboex_WM_LBUTTONDOWN(void)
WS_VISIBLE|WS_CHILD|CBS_DROPDOWN, 0, 0, 200, 150,
hComboExParentWnd, NULL, hMainHinst, NULL);
- for (i = 0; i < sizeof(choices)/sizeof(UINT); i++){
+ for (i = 0; i < ARRAY_SIZE(choices); i++){
COMBOBOXEXITEMW cbexItem;
wsprintfW(buffer, stringFormat, choices[i]);
@@ -1165,11 +1165,11 @@ static void test_combo_dropdown_size(DWORD style)
int limit;
} info_height[] = {
{33, 50, -1},
- {35, 50, 40},
+ {35, 100, 40},
{15, 50, 3},
};
- for (test = 0; test < sizeof(info_height) / sizeof(info_height[0]); test++)
+ for (test = 0; test < ARRAY_SIZE(info_height); test++)
{
const struct list_size_info *info_test = &info_height[test];
int height_item; /* Height of a list item */
@@ -1182,7 +1182,6 @@ static void test_combo_dropdown_size(DWORD style)
info_test->height_combo, hMainWnd, (HMENU)COMBO_ID, NULL, 0);
min_visible_expected = SendMessageA(hCombo, CB_GETMINVISIBLE, 0, 0);
- todo_wine
ok(min_visible_expected == 30, "Unexpected number of items %d.\n",
min_visible_expected);
cbInfo.cbSize = sizeof(COMBOBOXINFO);
@@ -1202,10 +1201,8 @@ static void test_combo_dropdown_size(DWORD style)
min_visible_expected = info_test->limit;
ret = SendMessageA(hCombo, CB_SETMINVISIBLE, min_visible_expected, 0);
- todo_wine
ok(ret, "Failed to set visible limit.\n");
min_visible_actual = SendMessageA(hCombo, CB_GETMINVISIBLE, 0, 0);
- todo_wine
ok(min_visible_expected == min_visible_actual, "test %d: unexpected
number of items %d.\n",
test, min_visible_actual);
}
@@ -1242,7 +1239,6 @@ static void test_combo_dropdown_size(DWORD style)
if (expected_height_list < 0)
expected_height_list = 0;
- todo_wine
ok(expected_height_list == height_list, "Test %d, expected list height
to be %d, got %d\n",
test, expected_height_list, height_list);
}
@@ -1250,7 +1246,6 @@ static void test_combo_dropdown_size(DWORD style)
{
expected_height_list = min(info_test->num_items, min_visible_expected) *
height_item;
- todo_wine
ok(expected_height_list == height_list, "Test %d, expected list height
to be %d, got %d\n",
test, expected_height_list, height_list);
}
diff --git a/modules/rostests/winetests/comctl32/datetime.c
b/modules/rostests/winetests/comctl32/datetime.c
index 7742dc5d18..88abce9ed6 100644
--- a/modules/rostests/winetests/comctl32/datetime.c
+++ b/modules/rostests/winetests/comctl32/datetime.c
@@ -721,6 +721,46 @@ static void test_dtm_set_and_get_systemtime_with_limits(void)
DestroyWindow(hWnd);
}
+static void test_dtm_get_ideal_size(void)
+{
+ HWND hwnd;
+ HDC hdc;
+ HFONT hfont;
+ LOGFONTA lf;
+ TEXTMETRICA tm;
+ SIZE size;
+ BOOL r;
+
+ hwnd = create_datetime_control(0);
+ r = SendMessageA(hwnd, DTM_GETIDEALSIZE, 0, (LPARAM)&size);
+ if (!r)
+ {
+ win_skip("DTM_GETIDEALSIZE is not available\n");
+ DestroyWindow(hwnd);
+ return;
+ }
+
+ /* Set font so that the test is consistent on Wine and Windows */
+ ZeroMemory(&lf, sizeof(lf));
+ lf.lfWeight = FW_NORMAL;
+ lf.lfHeight = 20;
+ lstrcpyA(lf.lfFaceName, "Tahoma");
+ hfont = CreateFontIndirectA(&lf);
+ SendMessageA(hwnd, WM_SETFONT, (WPARAM)hfont, (LPARAM)TRUE);
+
+ hdc = GetDC(hwnd);
+ GetTextMetricsA(hdc, &tm);
+ ReleaseDC(hwnd, hdc);
+
+ r = SendMessageA(hwnd, DTM_GETIDEALSIZE, 0, (LPARAM)&size);
+ ok(r, "Expect DTM_GETIDEALSIZE message to return true\n");
+ ok(size.cx > 0 && size.cy >= tm.tmHeight,
+ "Expect size.cx > 0 and size.cy >= %d, got cx:%d cy:%d\n",
tm.tmHeight, size.cx, size.cy);
+
+ DestroyWindow(hwnd);
+ DeleteObject(hfont);
+}
+
static void test_wm_set_get_text(void)
{
static const CHAR a_str[] = "a";
@@ -821,6 +861,7 @@ START_TEST(datetime)
test_dtm_set_and_get_mccolor();
test_dtm_set_and_get_mcfont();
test_dtm_get_monthcal();
+ test_dtm_get_ideal_size();
test_wm_set_get_text();
test_dts_shownone();
diff --git a/modules/rostests/winetests/comctl32/edit.c
b/modules/rostests/winetests/comctl32/edit.c
index 7e9e7e7634..bc44d0c240 100644
--- a/modules/rostests/winetests/comctl32/edit.c
+++ b/modules/rostests/winetests/comctl32/edit.c
@@ -2969,7 +2969,7 @@ static void test_EM_GETLINE(void)
hwnd[0] = create_editcontrol(ES_AUTOHSCROLL | ES_AUTOVSCROLL, 0);
hwnd[1] = create_editcontrolW(ES_AUTOHSCROLL | ES_AUTOVSCROLL, 0);
- for (i = 0; i < sizeof(hwnd)/sizeof(hwnd[0]); i++)
+ for (i = 0; i < ARRAY_SIZE(hwnd); i++)
{
static const WCHAR strW[] = {'t','e','x','t',0};
static const char *str = "text";
@@ -2994,13 +2994,13 @@ static void test_EM_GETLINE(void)
ok(!strcmp(buff, str), "Unexpected line data %s.\n", buff);
memset(buffW, 0, sizeof(buffW));
- *(WORD *)buffW = sizeof(buffW)/sizeof(buffW[0]);
+ *(WORD *)buffW = ARRAY_SIZE(buffW);
r = SendMessageW(hwnd[i], EM_GETLINE, 0, (LPARAM)buffW);
ok(r == lstrlenW(strW), "Failed to get a line %d.\n", r);
ok(!lstrcmpW(buffW, strW), "Unexpected line data %s.\n",
wine_dbgstr_w(buffW));
memset(buffW, 0, sizeof(buffW));
- *(WORD *)buffW = sizeof(buffW)/sizeof(buffW[0]);
+ *(WORD *)buffW = ARRAY_SIZE(buffW);
r = SendMessageW(hwnd[i], EM_GETLINE, 1, (LPARAM)buffW);
ok(r == lstrlenW(strW), "Failed to get a line %d.\n", r);
ok(!lstrcmpW(buffW, strW), "Unexpected line data %s.\n",
wine_dbgstr_w(buffW));
@@ -3061,6 +3061,83 @@ static const struct message killfocus_combined_seq[] =
{ 0 }
};
+static void test_cue_banner(void)
+{
+ HWND hwnd_edit;
+ BOOL ret;
+ static WCHAR getcuetestW[5] = {'T',0};
+ static const WCHAR testcmp1W[] =
{'T','e','s','t',0};
+ static const WCHAR testcmp2W[] = {'T','e','s',0};
+ static const WCHAR emptyW[] = {0};
+
+ hwnd_edit = create_editcontrolW(ES_AUTOHSCROLL | ES_AUTOVSCROLL, 0);
+
+ ret = SendMessageW(hwnd_edit, EM_GETCUEBANNER, (WPARAM)getcuetestW, 5);
+ if (lstrcmpW(getcuetestW, emptyW) != 0)
+ {
+ win_skip("skipping for Win XP and 2003 Server.\n");
+ DestroyWindow(hwnd_edit);
+ return;
+ }
+ ok(lstrcmpW(getcuetestW, emptyW) == 0, "First char is %c\n",
getcuetestW[0]);
+ ok(ret == FALSE, "EM_GETCUEBANNER should have returned FALSE.\n");
+
+ lstrcpyW(getcuetestW, testcmp1W);
+ ret = SendMessageW(hwnd_edit, EM_GETCUEBANNER, (WPARAM)getcuetestW, 0);
+ ok(lstrcmpW(getcuetestW, testcmp1W) == 0, "String was %s.\n",
wine_dbgstr_w(getcuetestW));
+ ok(ret == FALSE, "EM_GETCUEBANNER should have returned FALSE.\n");
+
+ ret = SendMessageW(hwnd_edit, EM_GETCUEBANNER, 0, 0);
+ ok(ret == FALSE, "EM_GETCUEBANNER should have returned FALSE.\n");
+
+ ret = SendMessageW(hwnd_edit, EM_SETCUEBANNER, 0, 0);
+ ok(ret == FALSE, "EM_SETCUEBANNER should have returned FALSE.\n");
+
+ ret = SendMessageW(hwnd_edit, EM_GETCUEBANNER, 0, 0);
+ ok(ret == FALSE, "EM_GETCUEBANNER should have returned FALSE.\n");
+
+ lstrcpyW(getcuetestW, testcmp1W);
+ ret = SendMessageW(hwnd_edit, EM_SETCUEBANNER, 0, (LPARAM)getcuetestW);
+ ok(ret == TRUE, "EM_SETCUEBANNER should have returned TRUE.\n");
+
+ ret = SendMessageW(hwnd_edit, EM_GETCUEBANNER, 0, 5);
+ ok(ret == TRUE, "EM_GETCUEBANNER should have returned TRUE.\n");
+
+ ret = SendMessageW(hwnd_edit, EM_GETCUEBANNER, (WPARAM)getcuetestW, 5);
+ ok(ret == TRUE, "EM_GETCUEBANNER should have returned TRUE.\n");
+ ok(lstrcmpW(getcuetestW, testcmp1W) == 0, "EM_GETCUEBANNER returned string
%s.\n", wine_dbgstr_w(getcuetestW));
+
+ ret = SendMessageW(hwnd_edit, EM_SETCUEBANNER, 0, (LPARAM)emptyW);
+ ok(ret == TRUE, "EM_SETCUEBANNER should have returned TRUE.\n");
+
+ ret = SendMessageW(hwnd_edit, EM_GETCUEBANNER, (WPARAM)getcuetestW, 5);
+ ok(ret == TRUE, "EM_GETCUEBANNER should have returned TRUE.\n");
+ ok(lstrcmpW(getcuetestW, emptyW) == 0, "EM_GETCUEBANNER returned string
%s.\n", wine_dbgstr_w(getcuetestW));
+
+ /* EM_GETCUEBANNER's buffer size includes null char */
+ ret = SendMessageW(hwnd_edit, EM_SETCUEBANNER, 0, (LPARAM)testcmp1W);
+ ok(ret == TRUE, "EM_SETCUEBANNER should have returned TRUE.\n");
+ memset(getcuetestW, 0, lstrlenW(testcmp1W)*sizeof(WCHAR));
+ ret = SendMessageW(hwnd_edit, EM_GETCUEBANNER, (WPARAM)getcuetestW,
(LPARAM)lstrlenW(testcmp1W)+1);
+ ok(ret == TRUE, "EM_GETCUEBANNER should have returned TRUE.\n");
+ ok(lstrcmpW(getcuetestW, testcmp1W) == 0, "EM_GETCUEBANNER returned string
%s.\n", wine_dbgstr_w(getcuetestW));
+ memset(getcuetestW, 0, lstrlenW(testcmp1W)*sizeof(WCHAR));
+ ret = SendMessageW(hwnd_edit, EM_GETCUEBANNER, (WPARAM)getcuetestW,
(LPARAM)lstrlenW(testcmp1W));
+ ok(lstrcmpW(getcuetestW, testcmp2W) == 0, "EM_GETCUEBANNER returned string
%s.\n", wine_dbgstr_w(getcuetestW));
+ DestroyWindow(hwnd_edit);
+
+ /* setting cue banner fails for multi-line edit controls */
+ hwnd_edit = create_editcontrolW(ES_AUTOHSCROLL | ES_AUTOVSCROLL | ES_MULTILINE, 0);
+ lstrcpyW(getcuetestW, testcmp1W);
+ ret = SendMessageW(hwnd_edit, EM_GETCUEBANNER, (WPARAM)getcuetestW, 5);
+ ok(ret == FALSE, "EM_SETCUEBANNER.\n");
+ ok(lstrcmpW(getcuetestW, testcmp1W) == 0, "String was %s.\n",
wine_dbgstr_w(getcuetestW));
+ ret = SendMessageW(hwnd_edit, EM_SETCUEBANNER, 0, (LPARAM)getcuetestW);
+ ok(ret == FALSE, "EM_SETCUEBANNER.\n");
+
+ DestroyWindow(hwnd_edit);
+}
+
static void test_change_focus(void)
{
HWND hwnd, parent_wnd;
@@ -3138,6 +3215,7 @@ START_TEST(edit)
test_EM_GETLINE();
test_wordbreak_proc();
test_change_focus();
+ test_cue_banner();
UnregisterWindowClasses();
diff --git a/modules/rostests/winetests/comctl32/header.c
b/modules/rostests/winetests/comctl32/header.c
index 7ea80519a6..3428936cd7 100644
--- a/modules/rostests/winetests/comctl32/header.c
+++ b/modules/rostests/winetests/comctl32/header.c
@@ -1130,7 +1130,7 @@ static void test_hdm_index_messages(HWND hParent)
ok_sequence(sequences, PARENT_SEQ_INDEX, add_header_to_parent_seq,
"adder header control to parent", FALSE);
flush_sequences(sequences, NUM_MSG_SEQUENCES);
- for (i = 0; i < sizeof(item_texts)/sizeof(item_texts[0]); i++)
+ for (i = 0; i < ARRAY_SIZE(item_texts); i++)
{
hdItem.mask = HDI_TEXT | HDI_WIDTH | HDI_FORMAT;
hdItem.pszText = (char*)item_texts[i];
@@ -1170,7 +1170,7 @@ static void test_hdm_index_messages(HWND hParent)
hdItem.mask = HDI_TEXT | HDI_WIDTH;
hdItem.pszText = buffA;
- hdItem.cchTextMax = sizeof(buffA)/sizeof(buffA[0]);
+ hdItem.cchTextMax = ARRAY_SIZE(buffA);
retVal = SendMessageA(hChild, HDM_GETITEMA, 0, (LPARAM) &hdItem);
ok(retVal == TRUE, "Getting the 1st header item should return TRUE, got
%d\n", retVal);
diff --git a/modules/rostests/winetests/comctl32/imagelist.c
b/modules/rostests/winetests/comctl32/imagelist.c
index bcd62c9e9c..8064a2b98e 100644
--- a/modules/rostests/winetests/comctl32/imagelist.c
+++ b/modules/rostests/winetests/comctl32/imagelist.c
@@ -922,7 +922,6 @@ static void check_ilhead_data(const ILHEAD *ilh, INT cx, INT cy, INT
cur, INT ma
}
else
{
- grow = (WORD)(grow + 3) & ~3;
ok(ilh->cMaxImage == max, "wrong cMaxImage %d (expected %d)\n",
ilh->cMaxImage, max);
ok(ilh->cGrow == grow_aligned, "Unexpected cGrow %d, expected %d\n",
ilh->cGrow, grow_aligned);
}
@@ -1100,7 +1099,7 @@ static void image_list_init(HIMAGELIST himl, INT grow)
check_iml_data(himl, BMP_CX, BMP_CX, 0, 2, grow, ILC_COLOR24, "total 0");
- for (i = 0; i < sizeof(td)/sizeof(td[0]); i++)
+ for (i = 0; i < ARRAY_SIZE(td); i++)
{
image_list_add_bitmap(himl, td[i].grey, i + 1);
check_iml_data(himl, td[i].cx, td[i].cy, td[i].cur, td[i].max, grow, td[i].bpp,
td[i].comment);
@@ -2029,7 +2028,11 @@ static void check_color_table(const char *name, HDC hdc, HIMAGELIST
himl, UINT i
{
IMAGEINFO info;
INT ret;
+#ifdef __REACTOS__
char bmi_buffer[FIELD_OFFSET(BITMAPINFO, bmiColors) + 256 * sizeof(RGBQUAD)];
+#else
+ char bmi_buffer[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )];
+#endif
BITMAPINFO *bmi = (BITMAPINFO *)bmi_buffer;
int i, depth = ilc & 0xfe;
@@ -2061,7 +2064,11 @@ static void check_color_table(const char *name, HDC hdc, HIMAGELIST
himl, UINT i
static void get_default_color_table(HDC hdc, int bpp, RGBQUAD *table)
{
+#ifdef __REACTOS__
char bmi_buffer[FIELD_OFFSET(BITMAPINFO, bmiColors) + 256 * sizeof(RGBQUAD)];
+#else
+ char bmi_buffer[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )];
+#endif
BITMAPINFO *bmi = (BITMAPINFO *)bmi_buffer;
HBITMAP tmp;
int i;
@@ -2109,7 +2116,11 @@ static void test_color_table(UINT ilc)
{
HIMAGELIST himl;
INT ret;
+#ifdef __REACTOS__
char bmi_buffer[FIELD_OFFSET(BITMAPINFO, bmiColors) + 256 * sizeof(RGBQUAD)];
+#else
+ char bmi_buffer[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )];
+#endif
BITMAPINFO *bmi = (BITMAPINFO *)bmi_buffer;
HDC hdc = CreateCompatibleDC(0);
HBITMAP dib4, dib8, dib32;
diff --git a/modules/rostests/winetests/comctl32/ipaddress.c
b/modules/rostests/winetests/comctl32/ipaddress.c
index 52581899a7..cc79b7bf11 100644
--- a/modules/rostests/winetests/comctl32/ipaddress.c
+++ b/modules/rostests/winetests/comctl32/ipaddress.c
@@ -50,12 +50,12 @@ static void test_get_set_text(void)
}
/* check text just after creation */
- r = GetWindowTextA(hwnd, ip, sizeof(ip)/sizeof(CHAR));
+ r = GetWindowTextA(hwnd, ip, ARRAY_SIZE(ip));
expect(7, r);
ok(strcmp(ip, "0.0.0.0") == 0, "Expected null IP address, got
%s\n", ip);
SendMessageA(hwnd, IPM_SETADDRESS, 0, MAKEIPADDRESS(127, 0, 0, 1));
- r = GetWindowTextA(hwnd, ip, sizeof(ip)/sizeof(CHAR));
+ r = GetWindowTextA(hwnd, ip, ARRAY_SIZE(ip));
expect(9, r);
ok(strcmp(ip, "127.0.0.1") == 0, "Expected 127.0.0.1, got %s\n",
ip);
diff --git a/modules/rostests/winetests/comctl32/listbox.c
b/modules/rostests/winetests/comctl32/listbox.c
index 1513bea7f5..e789483983 100644
--- a/modules/rostests/winetests/comctl32/listbox.c
+++ b/modules/rostests/winetests/comctl32/listbox.c
@@ -30,6 +30,52 @@
#include "wine/heap.h"
#include "wine/test.h"
#include "v6util.h"
+#include "msg.h"
+
+enum seq_index
+{
+ LB_SEQ_INDEX,
+ PARENT_SEQ_INDEX,
+ NUM_MSG_SEQUENCES
+};
+
+static struct msg_sequence *sequences[NUM_MSG_SEQUENCES];
+
+/* encoded MEASUREITEMSTRUCT into a WPARAM */
+typedef struct
+{
+ union
+ {
+ struct
+ {
+ UINT CtlType : 4;
+ UINT CtlID : 4;
+ UINT itemID : 4;
+ UINT wParam : 20;
+ } item;
+ WPARAM wp;
+ } u;
+} MEASURE_ITEM_STRUCT;
+
+static unsigned hash_Ly_W(const WCHAR *str)
+{
+ unsigned hash = 0;
+
+ for (; *str; str++)
+ hash = hash * 1664525u + (unsigned char)(*str) + 1013904223u;
+
+ return hash;
+}
+
+static unsigned hash_Ly(const char *str)
+{
+ unsigned hash = 0;
+
+ for (; *str; str++)
+ hash = hash * 1664525u + (unsigned char)(*str) + 1013904223u;
+
+ return hash;
+}
static const char * const strings[4] = {
"First added",
@@ -43,22 +89,53 @@ static const char * const strings[4] = {
static const char BAD_EXTENSION[] = "*.badtxt";
-static int strcmp_aw(LPCWSTR strw, const char *stra)
+#define ID_LISTBOX 1
+
+static LRESULT WINAPI listbox_wnd_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM
lParam)
{
- WCHAR buf[1024];
+ WNDPROC oldproc = (WNDPROC)GetWindowLongPtrA(hwnd, GWLP_USERDATA);
+ static LONG defwndproc_counter = 0;
+ struct message msg = { 0 };
+ LRESULT ret;
+
+ switch (message)
+ {
+ case WM_SIZE:
+ case WM_GETTEXT:
+ case WM_PAINT:
+ case WM_ERASEBKGND:
+ case WM_WINDOWPOSCHANGING:
+ case WM_WINDOWPOSCHANGED:
+ case WM_NCCALCSIZE:
+ case WM_NCPAINT:
+ case WM_NCHITTEST:
+ case WM_DEVICECHANGE:
+ break;
+
+ default:
+ msg.message = message;
+ msg.flags = sent|wparam|lparam;
+ if (defwndproc_counter) msg.flags |= defwinproc;
+ msg.wParam = wParam;
+ msg.lParam = lParam;
+ add_message(sequences, LB_SEQ_INDEX, &msg);
+ }
+
+ defwndproc_counter++;
+ ret = CallWindowProcA(oldproc, hwnd, message, wParam, lParam);
+ defwndproc_counter--;
- if (!stra) return 1;
- MultiByteToWideChar(CP_ACP, 0, stra, -1, buf, sizeof(buf)/sizeof(WCHAR));
- return lstrcmpW(strw, buf);
+ return ret;
}
static HWND create_listbox(DWORD add_style, HWND parent)
{
INT_PTR ctl_id = 0;
+ WNDPROC oldproc;
HWND handle;
if (parent)
- ctl_id=1;
+ ctl_id = ID_LISTBOX;
handle = CreateWindowA(WC_LISTBOXA, "TestList", (LBS_STANDARD &
~LBS_SORT) | add_style, 0, 0, 100, 100,
parent, (HMENU)ctl_id, NULL, 0);
@@ -69,6 +146,9 @@ static HWND create_listbox(DWORD add_style, HWND parent)
SendMessageA(handle, LB_ADDSTRING, 0, (LPARAM) strings[2]);
SendMessageA(handle, LB_ADDSTRING, 0, (LPARAM) strings[3]);
+ oldproc = (WNDPROC)SetWindowLongPtrA(handle, GWLP_WNDPROC,
(LONG_PTR)listbox_wnd_proc);
+ SetWindowLongPtrA(handle, GWLP_USERDATA, (LONG_PTR)oldproc);
+
return handle;
}
@@ -84,7 +164,6 @@ struct listbox_stat
struct listbox_test
{
- struct listbox_prop prop;
struct listbox_stat init, init_todo;
struct listbox_stat click, click_todo;
struct listbox_stat step, step_todo;
@@ -117,8 +196,7 @@ static void keypress(HWND handle, WPARAM keycode, BYTE scancode, BOOL
extended)
#define listbox_field_ok(t, s, f, got) \
ok (t.s.f==got.f, "style %#x, step " #s ", field " #f \
- ": expected %d, got %d\n", (unsigned int)t.prop.add_style, \
- t.s.f, got.f)
+ ": expected %d, got %d\n", style, t.s.f, got.f)
#define listbox_todo_field_ok(t, s, f, got) \
todo_wine_if (t.s##_todo.f) { listbox_field_ok(t, s, f, got); }
@@ -129,12 +207,23 @@ static void keypress(HWND handle, WPARAM keycode, BYTE scancode,
BOOL extended)
listbox_todo_field_ok(t, s, caret, got); \
listbox_todo_field_ok(t, s, selcount, got)
-static void run_test(const struct listbox_test test)
+static void run_test(DWORD style, const struct listbox_test test)
{
+ static const struct message delete_seq[] =
+ {
+ { LB_DELETESTRING, sent|wparam|lparam, 0, 0 },
+ { LB_DELETESTRING, sent|wparam|lparam, 0, 0 },
+ { LB_DELETESTRING, sent|wparam|lparam, 0, 0 },
+ { LB_DELETESTRING, sent|wparam|lparam, 0, 0 },
+ { LB_RESETCONTENT, sent|wparam|lparam|defwinproc, 0, 0 },
+ { 0 }
+ };
struct listbox_stat answer;
- HWND hLB=create_listbox (test.prop.add_style, 0);
+ int i, res, count;
RECT second_item;
- int i, res;
+ HWND hLB;
+
+ hLB = create_listbox (style, 0);
listbox_query (hLB, &answer);
listbox_ok (test, init, answer);
@@ -152,13 +241,13 @@ static void run_test(const struct listbox_test test)
DestroyWindow(hLB);
- hLB = create_listbox(test.prop.add_style, 0);
+ hLB = create_listbox(style, 0);
SendMessageA(hLB, LB_SELITEMRANGE, TRUE, MAKELPARAM(1, 2));
listbox_query(hLB, &answer);
listbox_ok(test, sel, answer);
- for (i = 0; i < 4; i++)
+ for (i = 0; i < 4 && !(style & LBS_NODATA); i++)
{
DWORD size = SendMessageA(hLB, LB_GETTEXTLEN, i, 0);
int resA, resW;
@@ -171,13 +260,9 @@ static void run_test(const struct listbox_test test)
txtw = heap_alloc_zero((size + 1) * sizeof(*txtw));
resW = SendMessageW(hLB, LB_GETTEXT, i, (LPARAM)txtw);
- if (resA != resW)
- trace("SendMessageW(LB_GETTEXT) not supported on this platform (resA=%d
resW=%d), skipping...\n", resA, resW);
- else
- {
- WideCharToMultiByte(CP_ACP, 0, txtw, -1, txt, size, NULL, NULL);
- ok(!strcmp (txt, strings[i]), "returned string for item %d does not
match %s vs %s\n", i, txt, strings[i]);
- }
+ ok(resA == resW, "Unexpected text length.\n");
+ WideCharToMultiByte(CP_ACP, 0, txtw, -1, txt, size, NULL, NULL);
+ ok(!strcmp (txt, strings[i]), "Unexpected string for item %d, %s vs
%s.\n", i, txt, strings[i]);
heap_free(txtw);
heap_free(txt);
@@ -190,8 +275,17 @@ static void run_test(const struct listbox_test test)
ok(res == LB_ERR, "Expected LB_ERR items, got %d\n", res);
res = SendMessageA(hLB, LB_DELETESTRING, 4, 0);
ok(res == LB_ERR, "Expected LB_ERR items, got %d\n", res);
- res = SendMessageA(hLB, LB_GETCOUNT, 0, 0);
- ok(res == 4, "Expected 4 items, got %d\n", res);
+ count = SendMessageA(hLB, LB_GETCOUNT, 0, 0);
+ ok(count == 4, "Unexpected item count %d.\n", count);
+
+ /* Emptying listbox sends a LB_RESETCONTENT to itself. */
+ flush_sequence(sequences, LB_SEQ_INDEX);
+ for (i = count; i--;)
+ {
+ res = SendMessageA(hLB, LB_DELETESTRING, 0, 0);
+ ok(res == i, "Unexpected return value %d.\n", res);
+ }
+ ok_sequence(sequences, LB_SEQ_INDEX, delete_seq, "Emptying listbox",
FALSE);
DestroyWindow(hLB);
}
@@ -234,41 +328,85 @@ static void test_item_height(void)
static int got_selchange;
-static LRESULT WINAPI main_window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM
lparam)
+static LRESULT WINAPI main_window_proc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM
lParam)
{
+ static LONG defwndproc_counter = 0;
+ struct message m = { 0 };
+ LRESULT ret;
+
+ m.message = msg;
+ m.flags = sent|wparam|lparam;
+ if (defwndproc_counter) m.flags |= defwinproc;
+ m.wParam = wParam;
+ m.lParam = lParam;
+
switch (msg)
{
case WM_MEASUREITEM:
{
- DWORD style = GetWindowLongA(GetWindow(hwnd, GW_CHILD), GWL_STYLE);
- MEASUREITEMSTRUCT *mi = (void*)lparam;
+ MEASUREITEMSTRUCT *mis = (void *)lParam;
+ BOOL is_unicode_data = FALSE;
+ MEASURE_ITEM_STRUCT mi;
- ok(wparam == mi->CtlID, "got wParam=%08lx, expected %08x\n", wparam,
mi->CtlID);
- ok(mi->CtlType == ODT_LISTBOX, "mi->CtlType = %u\n",
mi->CtlType);
- ok(mi->CtlID == 1, "mi->CtlID = %u\n", mi->CtlID);
- ok(mi->itemHeight, "mi->itemHeight = 0\n");
+ if (mis->CtlType == ODT_LISTBOX)
+ {
+ HWND ctrl = GetDlgItem(hwnd, mis->CtlID);
+ is_unicode_data = GetWindowLongA(ctrl, GWL_STYLE) & LBS_HASSTRINGS;
+ }
- if (mi->itemID > 4 || style & LBS_OWNERDRAWFIXED)
- break;
+ mi.u.wp = 0;
+ mi.u.item.CtlType = mis->CtlType;
+ mi.u.item.CtlID = mis->CtlID;
+ mi.u.item.itemID = mis->itemID;
+ mi.u.item.wParam = wParam;
+
+ m.wParam = mi.u.wp;
+ if (is_unicode_data)
+ m.lParam = mis->itemData ? hash_Ly_W((const WCHAR *)mis->itemData) :
0;
+ else
+ m.lParam = mis->itemData ? hash_Ly((const char *)mis->itemData) : 0;
+ add_message(sequences, PARENT_SEQ_INDEX, &m);
+
+ ok(wParam == mis->CtlID, "got wParam=%08lx, expected %08x\n",
wParam, mis->CtlID);
+ ok(mis->CtlType == ODT_LISTBOX, "mi->CtlType = %u\n",
mis->CtlType);
+ ok(mis->CtlID == 1, "mi->CtlID = %u\n", mis->CtlID);
+ ok(mis->itemHeight, "mi->itemHeight = 0\n");
- if (style & LBS_HASSTRINGS)
+ break;
+ }
+ case WM_COMPAREITEM:
+ {
+ COMPAREITEMSTRUCT *cis = (COMPAREITEMSTRUCT *)lParam;
+ HWND ctrl = GetDlgItem(hwnd, cis->CtlID);
+ BOOL is_unicode_data = TRUE;
+
+ ok(wParam == cis->CtlID, "expected %#x, got %#lx\n", cis->CtlID,
wParam);
+ ok(cis->hwndItem == ctrl, "expected %p, got %p\n", ctrl,
cis->hwndItem);
+ ok((int)cis->itemID1 >= 0, "expected >= 0, got %d\n",
cis->itemID1);
+ ok((int)cis->itemID2 == -1, "expected -1, got %d\n",
cis->itemID2);
+
+ if (cis->CtlType == ODT_LISTBOX)
+ is_unicode_data = GetWindowLongA(ctrl, GWL_STYLE) & LBS_HASSTRINGS;
+
+ if (is_unicode_data)
{
- ok(!strcmp_aw((WCHAR*)mi->itemData, strings[mi->itemID]),
- "mi->itemData = %s (%d)\n",
wine_dbgstr_w((WCHAR*)mi->itemData), mi->itemID);
+ m.wParam = cis->itemData1 ? hash_Ly_W((const WCHAR *)cis->itemData1) :
0;
+ m.lParam = cis->itemData2 ? hash_Ly_W((const WCHAR *)cis->itemData2) :
0;
}
else
{
- ok((void*)mi->itemData == strings[mi->itemID],
- "mi->itemData = %08lx, expected %p\n", mi->itemData,
strings[mi->itemID]);
+ m.wParam = cis->itemData1 ? hash_Ly((const char *)cis->itemData1) : 0;
+ m.lParam = cis->itemData2 ? hash_Ly((const char *)cis->itemData2) : 0;
}
+ add_message(sequences, PARENT_SEQ_INDEX, &m);
break;
}
case WM_DRAWITEM:
{
RECT rc_item, rc_client, rc_clip;
- DRAWITEMSTRUCT *dis = (DRAWITEMSTRUCT *)lparam;
+ DRAWITEMSTRUCT *dis = (DRAWITEMSTRUCT *)lParam;
- ok(wparam == dis->CtlID, "got wParam=%08lx instead of %08x\n",
wparam, dis->CtlID);
+ ok(wParam == dis->CtlID, "got wParam=%08lx instead of %08x\n",
wParam, dis->CtlID);
ok(dis->CtlType == ODT_LISTBOX, "wrong CtlType %04x\n",
dis->CtlType);
GetClientRect(dis->hwndItem, &rc_client);
@@ -284,14 +422,18 @@ static LRESULT WINAPI main_window_proc(HWND hwnd, UINT msg, WPARAM
wparam, LPARA
}
case WM_COMMAND:
- if (HIWORD( wparam ) == LBN_SELCHANGE) got_selchange++;
+ if (HIWORD( wParam ) == LBN_SELCHANGE) got_selchange++;
break;
default:
break;
}
- return DefWindowProcA(hwnd, msg, wparam, lparam);
+ defwndproc_counter++;
+ ret = DefWindowProcA(hwnd, msg, wParam, lParam);
+ defwndproc_counter--;
+
+ return msg == WM_COMPAREITEM ? -1 : ret;
}
static HWND create_parent( void )
@@ -320,33 +462,72 @@ static HWND create_parent( void )
static void test_ownerdraw(void)
{
+ static const DWORD styles[] =
+ {
+ 0,
+ LBS_NODATA
+ };
HWND parent, hLB;
INT ret;
RECT rc;
+ UINT i;
parent = create_parent();
ok(parent != NULL, "Failed to create parent window.\n");
- hLB = create_listbox(LBS_OWNERDRAWFIXED | WS_CHILD | WS_VISIBLE, parent);
- ok(hLB != NULL, "Failed to create listbox window.\n");
+ for (i = 0; i < ARRAY_SIZE(styles); i++)
+ {
+ hLB = create_listbox(LBS_OWNERDRAWFIXED | WS_CHILD | WS_VISIBLE | styles[i],
parent);
+ ok(hLB != NULL, "Failed to create listbox window.\n");
- SetForegroundWindow(hLB);
- UpdateWindow(hLB);
+ SetForegroundWindow(hLB);
+ UpdateWindow(hLB);
- /* make height short enough */
- SendMessageA(hLB, LB_GETITEMRECT, 0, (LPARAM)&rc);
- SetWindowPos(hLB, 0, 0, 0, 100, rc.bottom - rc.top + 1, SWP_NOZORDER | SWP_NOMOVE);
+ /* make height short enough */
+ SendMessageA(hLB, LB_GETITEMRECT, 0, (LPARAM)&rc);
+ SetWindowPos(hLB, 0, 0, 0, 100, rc.bottom - rc.top + 1, SWP_NOZORDER |
SWP_NOMOVE);
- /* make 0 item invisible */
- SendMessageA(hLB, LB_SETTOPINDEX, 1, 0);
- ret = SendMessageA(hLB, LB_GETTOPINDEX, 0, 0);
- ok(ret == 1, "wrong top index %d\n", ret);
+ /* make 0 item invisible */
+ SendMessageA(hLB, LB_SETTOPINDEX, 1, 0);
+ ret = SendMessageA(hLB, LB_GETTOPINDEX, 0, 0);
+ ok(ret == 1, "wrong top index %d\n", ret);
- SendMessageA(hLB, LB_GETITEMRECT, 0, (LPARAM)&rc);
- ok(!IsRectEmpty(&rc), "empty item rect\n");
- ok(rc.top < 0, "rc.top is not negative (%d)\n", rc.top);
+ SendMessageA(hLB, LB_GETITEMRECT, 0, (LPARAM)&rc);
+ ok(!IsRectEmpty(&rc), "empty item rect\n");
+ ok(rc.top < 0, "rc.top is not negative (%d)\n", rc.top);
+
+ DestroyWindow(hLB);
+
+ /* Both FIXED and VARIABLE, FIXED should override VARIABLE. */
+ hLB = CreateWindowA(WC_LISTBOXA, "TestList", LBS_OWNERDRAWFIXED |
LBS_OWNERDRAWVARIABLE | styles[i],
+ 0, 0, 100, 100, NULL, NULL, NULL, 0);
+ ok(hLB != NULL, "last error 0x%08x\n", GetLastError());
+
+ ok(GetWindowLongA(hLB, GWL_STYLE) & LBS_OWNERDRAWVARIABLE, "Unexpected
window style.\n");
+
+ ret = SendMessageA(hLB, LB_INSERTSTRING, -1, 0);
+ ok(ret == 0, "Unexpected return value %d.\n", ret);
+ ret = SendMessageA(hLB, LB_INSERTSTRING, -1, 0);
+ ok(ret == 1, "Unexpected return value %d.\n", ret);
+
+ ret = SendMessageA(hLB, LB_SETITEMHEIGHT, 0, 13);
+ ok(ret == LB_OKAY, "Failed to set item height, %d.\n", ret);
+
+ ret = SendMessageA(hLB, LB_GETITEMHEIGHT, 0, 0);
+ ok(ret == 13, "Unexpected item height %d.\n", ret);
+
+ ret = SendMessageA(hLB, LB_SETITEMHEIGHT, 1, 42);
+ ok(ret == LB_OKAY, "Failed to set item height, %d.\n", ret);
+
+ ret = SendMessageA(hLB, LB_GETITEMHEIGHT, 0, 0);
+ ok(ret == 42, "Unexpected item height %d.\n", ret);
+
+ ret = SendMessageA(hLB, LB_GETITEMHEIGHT, 1, 0);
+ ok(ret == 42, "Unexpected item height %d.\n", ret);
+
+ DestroyWindow (hLB);
+ }
- DestroyWindow(hLB);
DestroyWindow(parent);
}
@@ -447,19 +628,123 @@ static void test_LB_SETCURSEL(void)
SendMessageA(hLB, LB_SETITEMHEIGHT, 0, 32);
+ ret = SendMessageA(hLB, LB_GETANCHORINDEX, 0, 0);
+ ok(ret == -1, "Unexpected anchor index %d.\n", ret);
+
ret = SendMessageA(hLB, LB_SETCURSEL, 2, 0);
ok(ret == 2, "LB_SETCURSEL returned %d instead of 2\n", ret);
ret = GetScrollPos(hLB, SB_VERT);
ok(ret == 0, "expected vscroll 0, got %d\n", ret);
+ ret = SendMessageA(hLB, LB_GETANCHORINDEX, 0, 0);
+ ok(ret == -1, "Unexpected anchor index %d.\n", ret);
+
ret = SendMessageA(hLB, LB_SETCURSEL, 3, 0);
ok(ret == 3, "LB_SETCURSEL returned %d instead of 3\n", ret);
ret = GetScrollPos(hLB, SB_VERT);
ok(ret == 1, "expected vscroll 1, got %d\n", ret);
+ ret = SendMessageA(hLB, LB_GETANCHORINDEX, 0, 0);
+ ok(ret == -1, "Unexpected anchor index %d.\n", ret);
+
+ DestroyWindow(hLB);
+
+ hLB = create_listbox(0, 0);
+ ok(hLB != NULL, "Failed to create ListBox window.\n");
+
+ ret = SendMessageA(hLB, LB_SETCURSEL, 1, 0);
+ ok(ret == 1, "Unexpected return value %d.\n", ret);
+
+ ret = SendMessageA(hLB, LB_GETANCHORINDEX, 0, 0);
+ ok(ret == -1, "Unexpected anchor index %d.\n", ret);
+
+ DestroyWindow(hLB);
+
+ /* LBS_EXTENDEDSEL */
+ hLB = create_listbox(LBS_EXTENDEDSEL, 0);
+ ok(hLB != NULL, "Failed to create listbox.\n");
+
+ ret = SendMessageA(hLB, LB_GETANCHORINDEX, 0, 0);
+ ok(ret == -1, "Unexpected anchor index %d.\n", ret);
+
+ ret = SendMessageA(hLB, LB_SETCURSEL, 2, 0);
+ ok(ret == -1, "LB_SETCURSEL returned %d instead of 2\n", ret);
+
+ ret = SendMessageA(hLB, LB_GETANCHORINDEX, 0, 0);
+ ok(ret == -1, "Unexpected anchor index %d.\n", ret);
+
+ DestroyWindow(hLB);
+
+ /* LBS_MULTIPLESEL */
+ hLB = create_listbox(LBS_MULTIPLESEL, 0);
+ ok(hLB != NULL, "Failed to create listbox.\n");
+
+ ret = SendMessageA(hLB, LB_GETANCHORINDEX, 0, 0);
+ ok(ret == -1, "Unexpected anchor index %d.\n", ret);
+
+ ret = SendMessageA(hLB, LB_SETCURSEL, 2, 0);
+ ok(ret == -1, "LB_SETCURSEL returned %d instead of 2\n", ret);
+
+ ret = SendMessageA(hLB, LB_GETANCHORINDEX, 0, 0);
+ ok(ret == -1, "Unexpected anchor index %d.\n", ret);
+
DestroyWindow(hLB);
}
+static void test_LB_SETSEL(void)
+{
+ HWND list;
+ int ret;
+
+ /* LBS_EXTENDEDSEL */
+ list = create_listbox(LBS_EXTENDEDSEL, 0);
+ ok(list != NULL, "Failed to create ListBox window.\n");
+
+ ret = SendMessageA(list, LB_GETANCHORINDEX, 0, 0);
+ ok(ret == -1, "Unexpected anchor index %d.\n", ret);
+
+ ret = SendMessageA(list, LB_SETSEL, TRUE, 0);
+ ok(ret == 0, "Unexpected return value %d.\n", ret);
+ ret = SendMessageA(list, LB_GETANCHORINDEX, 0, 0);
+ ok(ret == 0, "Unexpected anchor index %d.\n", ret);
+
+ ret = SendMessageA(list, LB_SETSEL, TRUE, 1);
+ ok(ret == 0, "Unexpected return value %d.\n", ret);
+ ret = SendMessageA(list, LB_GETANCHORINDEX, 0, 0);
+ ok(ret == 1, "Unexpected anchor index %d.\n", ret);
+
+ ret = SendMessageA(list, LB_SETSEL, FALSE, 1);
+ ok(ret == 0, "Unexpected return value %d.\n", ret);
+ ret = SendMessageA(list, LB_GETANCHORINDEX, 0, 0);
+ ok(ret == 1, "Unexpected anchor index %d.\n", ret);
+
+ DestroyWindow(list);
+
+ /* LBS_MULTIPLESEL */
+ list = create_listbox(LBS_MULTIPLESEL, 0);
+ ok(list != NULL, "Failed to create ListBox window.\n");
+
+ ret = SendMessageA(list, LB_GETANCHORINDEX, 0, 0);
+ ok(ret == -1, "Unexpected anchor index %d.\n", ret);
+
+ ret = SendMessageA(list, LB_SETSEL, TRUE, 0);
+ ok(ret == 0, "Unexpected return value %d.\n", ret);
+ ret = SendMessageA(list, LB_GETANCHORINDEX, 0, 0);
+ ok(ret == 0, "Unexpected anchor index %d.\n", ret);
+
+ ret = SendMessageA(list, LB_SETSEL, TRUE, 1);
+ ok(ret == 0, "Unexpected return value %d.\n", ret);
+ ret = SendMessageA(list, LB_GETANCHORINDEX, 0, 0);
+ ok(ret == 1, "Unexpected anchor index %d.\n", ret);
+
+ ret = SendMessageA(list, LB_SETSEL, FALSE, 1);
+ ok(ret == 0, "Unexpected return value %d.\n", ret);
+ ret = SendMessageA(list, LB_GETANCHORINDEX, 0, 0);
+ ok(ret == 1, "Unexpected anchor index %d.\n", ret);
+
+ DestroyWindow(list);
+}
+
static void test_listbox_height(void)
{
HWND hList;
@@ -603,6 +888,7 @@ static void test_listbox_item_data(void)
static void test_listbox_LB_DIR(void)
{
+ char path[MAX_PATH], curdir[MAX_PATH];
HWND hList;
int res, itemCount;
int itemCount_justFiles;
@@ -615,6 +901,16 @@ static void test_listbox_LB_DIR(void)
char driveletter;
const char *wildcard = "*";
HANDLE file;
+ BOOL ret;
+
+ GetCurrentDirectoryA(ARRAY_SIZE(curdir), curdir);
+
+ GetTempPathA(ARRAY_SIZE(path), path);
+ ret = SetCurrentDirectoryA(path);
+ ok(ret, "Failed to set current directory.\n");
+
+ ret = CreateDirectoryA("lb_dir_test", NULL);
+ ok(ret, "Failed to create test directory.\n");
file = CreateFileA( "wtest1.tmp.c", GENERIC_READ|GENERIC_WRITE, 0, NULL,
CREATE_NEW, FILE_ATTRIBUTE_NORMAL, NULL );
ok(file != INVALID_HANDLE_VALUE, "Error creating the test file: %d\n",
GetLastError());
@@ -945,11 +1241,11 @@ static void test_listbox_LB_DIR(void)
itemCount, itemCount_allDirs);
ok(res + 1 == itemCount, "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_EXCLUSIVE, *)
returned incorrect index!\n");
- if (itemCount && GetCurrentDirectoryA( MAX_PATH, pathBuffer ) > 3) /*
there's no [..] in drive root */
+ if (itemCount)
{
memset(pathBuffer, 0, MAX_PATH);
SendMessageA(hList, LB_GETTEXT, 0, (LPARAM)pathBuffer);
- ok( !strcmp(pathBuffer, "[..]"), "First element is not
[..]\n");
+ ok( !strcmp(pathBuffer, "[..]"), "First element is %s, not
[..]\n", pathBuffer);
}
/* This tests behavior when no files match the wildcard */
@@ -1034,6 +1330,9 @@ static void test_listbox_LB_DIR(void)
DestroyWindow(hList);
DeleteFileA( "wtest1.tmp.c" );
+ RemoveDirectoryA("lb_dir_test");
+
+ SetCurrentDirectoryA(curdir);
}
static HWND g_listBox;
@@ -1533,7 +1832,13 @@ static void test_listbox_dlgdir(void)
static void test_set_count( void )
{
+ static const DWORD styles[] =
+ {
+ LBS_OWNERDRAWFIXED,
+ LBS_HASSTRINGS,
+ };
HWND parent, listbox;
+ unsigned int i;
LONG ret;
RECT r;
@@ -1563,37 +1868,39 @@ static void test_set_count( void )
ok( !IsRectEmpty( &r ), "got empty rect\n");
DestroyWindow( listbox );
- DestroyWindow( parent );
-}
-static int lb_getlistboxinfo;
+ for (i = 0; i < ARRAY_SIZE(styles); ++i)
+ {
+ listbox = create_listbox( styles[i] | WS_CHILD | WS_VISIBLE, parent );
-static LRESULT WINAPI listbox_subclass_proc(HWND hwnd, UINT message, WPARAM wParam,
LPARAM lParam)
-{
- WNDPROC oldproc = (WNDPROC)GetWindowLongPtrA(hwnd, GWLP_USERDATA);
+ SetLastError( 0xdeadbeef );
+ ret = SendMessageA( listbox, LB_SETCOUNT, 100, 0 );
+ ok( ret == LB_ERR, "expected %d, got %d\n", LB_ERR, ret );
+ ok( GetLastError() == 0xdeadbeef, "Unexpected error %d.\n",
GetLastError() );
- if (message == LB_GETLISTBOXINFO)
- lb_getlistboxinfo++;
+ DestroyWindow( listbox );
+ }
- return CallWindowProcA(oldproc, hwnd, message, wParam, lParam);
+ DestroyWindow( parent );
}
static void test_GetListBoxInfo(void)
{
+ static const struct message getlistboxinfo_seq[] =
+ {
+ { LB_GETLISTBOXINFO, sent },
+ { 0 }
+ };
HWND listbox, parent;
- WNDPROC oldproc;
DWORD ret;
parent = create_parent();
listbox = create_listbox(WS_CHILD | WS_VISIBLE, parent);
- oldproc = (WNDPROC)SetWindowLongPtrA(listbox, GWLP_WNDPROC,
(LONG_PTR)listbox_subclass_proc);
- SetWindowLongPtrA(listbox, GWLP_USERDATA, (LONG_PTR)oldproc);
-
- lb_getlistboxinfo = 0;
+ flush_sequences(sequences, NUM_MSG_SEQUENCES);
ret = GetListBoxInfo(listbox);
ok(ret > 0, "got %d\n", ret);
- ok(lb_getlistboxinfo == 1, "got %d\n", lb_getlistboxinfo);
+ ok_sequence(sequences, LB_SEQ_INDEX, getlistboxinfo_seq,
"GetListBoxInfo()", FALSE);
DestroyWindow(listbox);
DestroyWindow(parent);
@@ -1805,76 +2112,101 @@ static void test_listbox(void)
{
static const struct listbox_test SS =
/* {add_style} */
- {{0},
- {LB_ERR, LB_ERR, 0, LB_ERR}, {0,0,0,0},
+ {{LB_ERR, LB_ERR, 0, LB_ERR}, {0,0,0,0},
{ 1, 1, 1, LB_ERR}, {0,0,0,0},
{ 2, 2, 2, LB_ERR}, {0,0,0,0},
{LB_ERR, LB_ERR, 0, LB_ERR}, {0,0,0,0}};
/* {selected, anchor, caret, selcount}{TODO fields} */
static const struct listbox_test SS_NS =
- {{LBS_NOSEL},
- {LB_ERR, LB_ERR, 0, LB_ERR}, {0,0,0,0},
+ {{LB_ERR, LB_ERR, 0, LB_ERR}, {0,0,0,0},
{ 1, 1, 1, LB_ERR}, {0,0,0,0},
{ 2, 2, 2, LB_ERR}, {0,0,0,0},
{LB_ERR, LB_ERR, 0, LB_ERR}, {0,0,0,0}};
static const struct listbox_test MS =
- {{LBS_MULTIPLESEL},
- { 0, LB_ERR, 0, 0}, {0,0,0,0},
+ {{ 0, LB_ERR, 0, 0}, {0,0,0,0},
{ 1, 1, 1, 1}, {0,0,0,0},
{ 2, 1, 2, 1}, {0,0,0,0},
{ 0, LB_ERR, 0, 2}, {0,0,0,0}};
static const struct listbox_test MS_NS =
- {{LBS_MULTIPLESEL | LBS_NOSEL},
- {LB_ERR, LB_ERR, 0, LB_ERR}, {0,0,0,0},
+ {{LB_ERR, LB_ERR, 0, LB_ERR}, {0,0,0,0},
{ 1, 1, 1, LB_ERR}, {0,0,0,0},
{ 2, 2, 2, LB_ERR}, {0,0,0,0},
{LB_ERR, LB_ERR, 0, LB_ERR}, {0,0,0,0}};
static const struct listbox_test ES =
- {{LBS_EXTENDEDSEL},
- { 0, LB_ERR, 0, 0}, {0,0,0,0},
+ {{ 0, LB_ERR, 0, 0}, {0,0,0,0},
{ 1, 1, 1, 1}, {0,0,0,0},
{ 2, 2, 2, 1}, {0,0,0,0},
{ 0, LB_ERR, 0, 2}, {0,0,0,0}};
static const struct listbox_test ES_NS =
- {{LBS_EXTENDEDSEL | LBS_NOSEL},
- {LB_ERR, LB_ERR, 0, LB_ERR}, {0,0,0,0},
+ {{LB_ERR, LB_ERR, 0, LB_ERR}, {0,0,0,0},
{ 1, 1, 1, LB_ERR}, {0,0,0,0},
{ 2, 2, 2, LB_ERR}, {0,0,0,0},
{LB_ERR, LB_ERR, 0, LB_ERR}, {0,0,0,0}};
static const struct listbox_test EMS =
- {{LBS_EXTENDEDSEL | LBS_MULTIPLESEL},
- { 0, LB_ERR, 0, 0}, {0,0,0,0},
+ {{ 0, LB_ERR, 0, 0}, {0,0,0,0},
{ 1, 1, 1, 1}, {0,0,0,0},
{ 2, 2, 2, 1}, {0,0,0,0},
{ 0, LB_ERR, 0, 2}, {0,0,0,0}};
static const struct listbox_test EMS_NS =
- {{LBS_EXTENDEDSEL | LBS_MULTIPLESEL | LBS_NOSEL},
- {LB_ERR, LB_ERR, 0, LB_ERR}, {0,0,0,0},
+ {{LB_ERR, LB_ERR, 0, LB_ERR}, {0,0,0,0},
{ 1, 1, 1, LB_ERR}, {0,0,0,0},
{ 2, 2, 2, LB_ERR}, {0,0,0,0},
{LB_ERR, LB_ERR, 0, LB_ERR}, {0,0,0,0}};
- run_test(SS);
- run_test(SS_NS);
- run_test(MS);
- run_test(MS_NS);
- run_test(ES);
- run_test(ES_NS);
- run_test(EMS);
- run_test(EMS_NS);
+ run_test(0, SS);
+ run_test(LBS_NOSEL, SS_NS);
+ run_test(LBS_MULTIPLESEL, MS);
+ run_test(LBS_MULTIPLESEL | LBS_NOSEL, MS_NS);
+ run_test(LBS_EXTENDEDSEL, ES);
+ run_test(LBS_EXTENDEDSEL | LBS_NOSEL, ES_NS);
+ run_test(LBS_EXTENDEDSEL | LBS_MULTIPLESEL, EMS);
+ run_test(LBS_EXTENDEDSEL | LBS_MULTIPLESEL | LBS_NOSEL, EMS_NS);
+
+ run_test(LBS_NODATA | LBS_OWNERDRAWFIXED, SS);
+ run_test(LBS_NODATA | LBS_OWNERDRAWFIXED | LBS_NOSEL, SS_NS);
+ run_test(LBS_NODATA | LBS_OWNERDRAWFIXED | LBS_MULTIPLESEL, MS);
+ run_test(LBS_NODATA | LBS_OWNERDRAWFIXED | LBS_MULTIPLESEL | LBS_NOSEL, MS_NS);
+ run_test(LBS_NODATA | LBS_OWNERDRAWFIXED | LBS_EXTENDEDSEL, ES);
+ run_test(LBS_NODATA | LBS_OWNERDRAWFIXED | LBS_EXTENDEDSEL | LBS_NOSEL, ES_NS);
+ run_test(LBS_NODATA | LBS_OWNERDRAWFIXED | LBS_EXTENDEDSEL | LBS_MULTIPLESEL, EMS);
+ run_test(LBS_NODATA | LBS_OWNERDRAWFIXED | LBS_EXTENDEDSEL | LBS_MULTIPLESEL |
LBS_NOSEL, EMS_NS);
}
+static const struct message lb_addstring_ownerdraw_parent_seq[] =
+{
+ { WM_MEASUREITEM, sent|wparam|lparam, 0x1012, 0xf30604ed },
+ { WM_MEASUREITEM, sent|wparam|lparam, 0x1112, 0xf30604ee },
+ { WM_MEASUREITEM, sent|wparam|lparam, 0x1212, 0xf30604ef },
+ { 0 }
+};
+
+static const struct message lb_addstring_sort_parent_seq[] =
+{
+ { WM_MEASUREITEM, sent|wparam|lparam, 0x1012, 0xf30604ed },
+ { WM_COMPAREITEM, sent|wparam|lparam, 0xf30604ed, 0xf30604ee },
+ { WM_MEASUREITEM, sent|wparam|lparam, 0x1112, 0xf30604ee },
+ { WM_COMPAREITEM, sent|wparam|lparam, 0xf30604ed, 0xf30604ef },
+ { WM_COMPAREITEM, sent|wparam|lparam, 0xf30604ee, 0xf30604ef },
+ { WM_MEASUREITEM, sent|wparam|lparam, 0x1212, 0xf30604ef },
+ { 0 }
+};
+
+static const struct message empty_seq[] =
+{
+ { 0 }
+};
+
static void test_WM_MEASUREITEM(void)
{
HWND parent, listbox;
- LRESULT data;
+ LRESULT data, ret;
parent = create_parent();
listbox = create_listbox(WS_CHILD | LBS_OWNERDRAWVARIABLE, parent);
@@ -1888,6 +2220,187 @@ static void test_WM_MEASUREITEM(void)
data = SendMessageA(listbox, LB_GETITEMDATA, 0, 0);
ok(!data, "data = %08lx\n", data);
+
+ /* LBS_HASSTRINGS */
+ parent = create_parent();
+ listbox = CreateWindowExA(WS_EX_NOPARENTNOTIFY, WC_LISTBOXA, NULL,
+ WS_CHILD | LBS_NOTIFY | LBS_OWNERDRAWVARIABLE |
LBS_HASSTRINGS | WS_VISIBLE,
+ 10, 10, 80, 80, parent, (HMENU)ID_LISTBOX, 0, NULL);
+
+ flush_sequences(sequences, NUM_MSG_SEQUENCES);
+
+ ret = SendMessageA(listbox, LB_ADDSTRING, 0, (LPARAM)"item 0");
+ ok(ret == 0, "expected 0, got %ld\n", ret);
+ ret = SendMessageA(listbox, LB_ADDSTRING, 0, (LPARAM)"item 1");
+ ok(ret == 1, "expected 1, got %ld\n", ret);
+ ret = SendMessageA(listbox, LB_ADDSTRING, 0, (LPARAM)"item 2");
+ ok(ret == 2, "expected 2, got %ld\n", ret);
+
+ ok_sequence(sequences, PARENT_SEQ_INDEX, lb_addstring_ownerdraw_parent_seq,
+ "LB_ADDSTRING (LBS_HASSTRINGS, ownerdraw)", FALSE);
+ DestroyWindow(listbox);
+
+ /* LBS_SORT, no LBS_HASSTRINGS */
+ listbox = CreateWindowExA(WS_EX_NOPARENTNOTIFY, WC_LISTBOXA, NULL,
+ WS_CHILD | LBS_NOTIFY | LBS_OWNERDRAWVARIABLE | LBS_SORT |
WS_VISIBLE,
+ 10, 10, 80, 80, parent, (HMENU)ID_LISTBOX, 0, NULL);
+
+ flush_sequences(sequences, NUM_MSG_SEQUENCES);
+
+ ret = SendMessageA(listbox, LB_ADDSTRING, 0, (LPARAM)"item 0");
+ ok(ret == 0, "expected 0, got %ld\n", ret);
+ ret = SendMessageA(listbox, LB_ADDSTRING, 0, (LPARAM)"item 1");
+ ok(ret == 1, "expected 1, got %ld\n", ret);
+ ret = SendMessageA(listbox, LB_ADDSTRING, 0, (LPARAM)"item 2");
+ ok(ret == 2, "expected 2, got %ld\n", ret);
+
+ ok_sequence(sequences, PARENT_SEQ_INDEX, lb_addstring_sort_parent_seq,
"LB_ADDSTRING (LBS_SORT)", FALSE);
+ DestroyWindow(listbox);
+
+ /* LBS_HASSTRINGS */
+ listbox = CreateWindowExA(WS_EX_NOPARENTNOTIFY, WC_LISTBOXA, NULL,
+ WS_CHILD | LBS_NOTIFY | LBS_HASSTRINGS | WS_VISIBLE,
+ 10, 10, 80, 80, parent, (HMENU)ID_LISTBOX, 0, NULL);
+
+ flush_sequences(sequences, NUM_MSG_SEQUENCES);
+
+ ret = SendMessageA(listbox, LB_ADDSTRING, 0, (LPARAM)"item 2");
+ ok(ret == 0, "expected 0, got %ld\n", ret);
+ ret = SendMessageA(listbox, LB_ADDSTRING, 0, (LPARAM)"item 0");
+ ok(ret == 1, "expected 1, got %ld\n", ret);
+ ret = SendMessageA(listbox, LB_ADDSTRING, 0, (LPARAM)"item 1");
+ ok(ret == 2, "expected 2, got %ld\n", ret);
+
+ ok_sequence(sequences, PARENT_SEQ_INDEX, empty_seq, "LB_ADDSTRING
(LBS_HASSTRINGS)", FALSE);
+ DestroyWindow(listbox);
+
+ /* LBS_HASSTRINGS, LBS_SORT */
+ listbox = CreateWindowExA(WS_EX_NOPARENTNOTIFY, WC_LISTBOXA, NULL,
+ WS_CHILD | LBS_NOTIFY | LBS_HASSTRINGS | LBS_SORT |
WS_VISIBLE,
+ 10, 10, 80, 80, parent, (HMENU)ID_LISTBOX, 0, NULL);
+
+ flush_sequences(sequences, NUM_MSG_SEQUENCES);
+
+ ret = SendMessageA(listbox, LB_ADDSTRING, 0, (LPARAM)"item 2");
+ ok(ret == 0, "expected 0, got %ld\n", ret);
+ ret = SendMessageA(listbox, LB_ADDSTRING, 0, (LPARAM)"item 0");
+ ok(ret == 0, "expected 0, got %ld\n", ret);
+ ret = SendMessageA(listbox, LB_ADDSTRING, 0, (LPARAM)"item 1");
+ ok(ret == 1, "expected 1, got %ld\n", ret);
+
+ ok_sequence(sequences, PARENT_SEQ_INDEX, empty_seq, "LB_ADDSTRING
(LBS_HASSTRINGS, LBS_SORT)", FALSE);
+ DestroyWindow(listbox);
+
+ DestroyWindow(parent);
+}
+
+static void test_LBS_NODATA(void)
+{
+ static const DWORD invalid_styles[] =
+ {
+ 0,
+ LBS_OWNERDRAWVARIABLE,
+ LBS_SORT,
+ LBS_HASSTRINGS,
+ LBS_OWNERDRAWFIXED | LBS_SORT,
+ LBS_OWNERDRAWFIXED | LBS_HASSTRINGS,
+ };
+ static const UINT invalid_idx[] = { -2, 2 };
+ static const UINT valid_idx[] = { 0, 1 };
+ static const ULONG_PTR zero_data;
+ HWND listbox, parent;
+ INT ret, text_len;
+ unsigned int i;
+ ULONG_PTR data;
+ BOOL is_wow64;
+
+ listbox = CreateWindowA(WC_LISTBOXA, "TestList", LBS_NODATA |
LBS_OWNERDRAWFIXED | WS_VISIBLE,
+ 0, 0, 100, 100, NULL, NULL, NULL, 0);
+ ok(listbox != NULL, "Failed to create ListBox window.\n");
+
+ ret = SendMessageA(listbox, LB_INSERTSTRING, -1, 0);
+ ok(ret == 0, "Unexpected return value %d.\n", ret);
+ ret = SendMessageA(listbox, LB_INSERTSTRING, -1, 0);
+ ok(ret == 1, "Unexpected return value %d.\n", ret);
+ ret = SendMessageA(listbox, LB_GETCOUNT, 0, 0);
+ ok(ret == 2, "Unexpected return value %d.\n", ret);
+
+ /* Invalid indices. */
+ for (i = 0; i < ARRAY_SIZE(invalid_idx); ++i)
+ {
+ ret = SendMessageA(listbox, LB_SETITEMDATA, invalid_idx[i], 42);
+ ok(ret == LB_ERR, "Unexpected return value %d.\n", ret);
+ ret = SendMessageA(listbox, LB_GETTEXTLEN, invalid_idx[i], 0);
+ ok(ret == LB_ERR, "Unexpected return value %d.\n", ret);
+ if (ret == LB_ERR)
+ {
+ ret = SendMessageA(listbox, LB_GETTEXT, invalid_idx[i], (LPARAM)&data);
+ ok(ret == LB_ERR, "Unexpected return value %d.\n", ret);
+ }
+ ret = SendMessageA(listbox, LB_GETITEMDATA, invalid_idx[i], 0);
+ ok(ret == LB_ERR, "Unexpected return value %d.\n", ret);
+ }
+
+ IsWow64Process(GetCurrentProcess(), &is_wow64);
+#ifdef _WIN64
+ text_len = 8;
+#else
+ text_len = is_wow64 ? 8 : 4;
+#endif
+
+ /* Valid indices. */
+ for (i = 0; i < ARRAY_SIZE(valid_idx); ++i)
+ {
+ ret = SendMessageA(listbox, LB_SETITEMDATA, valid_idx[i], 42);
+ ok(ret == TRUE, "Unexpected return value %d.\n", ret);
+ ret = SendMessageA(listbox, LB_GETTEXTLEN, valid_idx[i], 0);
+ todo_wine_if(is_wow64)
+ ok(ret == text_len, "Unexpected return value %d.\n", ret);
+
+ memset(&data, 0xee, sizeof(data));
+ ret = SendMessageA(listbox, LB_GETTEXT, valid_idx[i], (LPARAM)&data);
+ ok(ret == sizeof(data), "Unexpected return value %d.\n", ret);
+ ok(!memcmp(&data, &zero_data, sizeof(data)), "Unexpected item
data.\n");
+
+ ret = SendMessageA(listbox, LB_GETITEMDATA, valid_idx[i], 0);
+ ok(ret == 0, "Unexpected return value %d.\n", ret);
+ }
+
+ /* More messages that don't work with LBS_NODATA. */
+ ret = SendMessageA(listbox, LB_FINDSTRING, 1, 0);
+ ok(ret == LB_ERR, "Unexpected return value %d.\n", ret);
+ ret = SendMessageA(listbox, LB_FINDSTRING, 1, 42);
+ ok(ret == LB_ERR, "Unexpected return value %d.\n", ret);
+ ret = SendMessageA(listbox, LB_FINDSTRINGEXACT, 1, 0);
+ ok(ret == LB_ERR, "Unexpected return value %d.\n", ret);
+ ret = SendMessageA(listbox, LB_FINDSTRINGEXACT, 1, 42);
+ ok(ret == LB_ERR, "Unexpected return value %d.\n", ret);
+ ret = SendMessageA(listbox, LB_SELECTSTRING, 1, 0);
+ ok(ret == LB_ERR, "Unexpected return value %d.\n", ret);
+ ret = SendMessageA(listbox, LB_SELECTSTRING, 1, 42);
+ ok(ret == LB_ERR, "Unexpected return value %d.\n", ret);
+
+ DestroyWindow(listbox);
+
+ /* Invalid window style combinations. */
+ parent = create_parent();
+ ok(parent != NULL, "Failed to create parent window.\n");
+
+ for (i = 0; i < ARRAY_SIZE(invalid_styles); ++i)
+ {
+ DWORD style;
+
+ listbox = CreateWindowA(WC_LISTBOXA, "TestList", LBS_NODATA | WS_CHILD
| invalid_styles[i],
+ 0, 0, 100, 100, parent, (HMENU)ID_LISTBOX, NULL, 0);
+ ok(listbox != NULL, "Failed to create a listbox.\n");
+
+ style = GetWindowLongA(listbox, GWL_STYLE);
+ ok((style & invalid_styles[i]) == invalid_styles[i], "%u: unexpected
window styles %#x.\n", i, style);
+ ret = SendMessageA(listbox, LB_SETCOUNT, 100, 0);
+ ok(ret == LB_ERR, "%u: unexpected return value %d.\n", i, ret);
+ DestroyWindow(listbox);
+ }
+
DestroyWindow(parent);
}
@@ -1899,6 +2412,8 @@ START_TEST(listbox)
if (!load_v6_module(&ctx_cookie, &hCtx))
return;
+ init_msg_sequences(sequences, NUM_MSG_SEQUENCES);
+
test_listbox();
test_item_height();
test_ownerdraw();
@@ -1914,6 +2429,8 @@ START_TEST(listbox)
test_missing_lbuttonup();
test_extents();
test_WM_MEASUREITEM();
+ test_LB_SETSEL();
+ test_LBS_NODATA();
unload_v6_module(ctx_cookie, hCtx);
}
diff --git a/modules/rostests/winetests/comctl32/listview.c
b/modules/rostests/winetests/comctl32/listview.c
index ddeb991c81..ec289fa3f2 100644
--- a/modules/rostests/winetests/comctl32/listview.c
+++ b/modules/rostests/winetests/comctl32/listview.c
@@ -75,6 +75,8 @@ static BOOL g_disp_A_to_W;
static NMLVDISPINFOA g_editbox_disp_info;
/* when this is set focus will be tested on LVN_DELETEITEM */
static BOOL g_focus_test_LVN_DELETEITEM;
+/* Whether to send WM_KILLFOCUS to the edit control during LVN_ENDLABELEDIT */
+static BOOL g_WM_KILLFOCUS_on_LVN_ENDLABELEDIT;
static HWND subclass_editbox(HWND hwndListview);
@@ -445,6 +447,25 @@ static const struct message parent_list_cd_seq[] = {
{ 0 }
};
+static const struct message listview_end_label_edit[] = {
+ { WM_NOTIFY, sent|id, 0, 0, LVN_ENDLABELEDITA },
+ { WM_NOTIFY, sent|id, 0, 0, LVN_ITEMCHANGING},
+ { WM_NOTIFY, sent|id, 0, 0, LVN_ITEMCHANGED },
+ { WM_NOTIFY, sent|id|optional, 0, 0, NM_CUSTOMDRAW }, /* XP */
+ { WM_NOTIFY, sent|id, 0, 0, NM_SETFOCUS },
+ { 0 }
+};
+
+static const struct message listview_end_label_edit_kill_focus[] = {
+ { WM_NOTIFY, sent|id, 0, 0, LVN_ENDLABELEDITA },
+ { WM_COMMAND, sent|id|optional, 0, 0, EN_KILLFOCUS }, /* todo: not sent by wine yet
*/
+ { WM_NOTIFY, sent|id, 0, 0, LVN_ITEMCHANGING },
+ { WM_NOTIFY, sent|id, 0, 0, LVN_ITEMCHANGED },
+ { WM_NOTIFY, sent|id|optional, 0, 0, NM_CUSTOMDRAW }, /* XP */
+ { WM_NOTIFY, sent|id, 0, 0, NM_SETFOCUS },
+ { 0 }
+};
+
static LRESULT WINAPI parent_wnd_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM
lParam)
{
static LONG defwndproc_counter = 0;
@@ -457,6 +478,7 @@ static LRESULT WINAPI parent_wnd_proc(HWND hwnd, UINT message, WPARAM
wParam, LP
msg.wParam = wParam;
msg.lParam = lParam;
if (message == WM_NOTIFY && lParam) msg.id = ((NMHDR*)lParam)->code;
+ if (message == WM_COMMAND) msg.id = HIWORD(wParam);
/* log system messages, except for painting */
if (message < WM_USER &&
@@ -503,24 +525,17 @@ static LRESULT WINAPI parent_wnd_proc(HWND hwnd, UINT message,
WPARAM wParam, LP
/* always accept new item text */
NMLVDISPINFOA *di = (NMLVDISPINFOA*)lParam;
g_editbox_disp_info = *di;
- trace("LVN_ENDLABELEDIT: text=%s\n", di->item.pszText ?
di->item.pszText : "(null)");
/* edit control still available from this notification */
edit = (HWND)SendMessageA(((NMHDR*)lParam)->hwndFrom,
LVM_GETEDITCONTROL, 0, 0);
ok(IsWindow(edit), "expected valid edit control handle\n");
ok((GetWindowLongA(edit, GWL_STYLE) & ES_MULTILINE) == 0, "edit is
multiline\n");
- return TRUE;
- }
- case LVN_BEGINSCROLL:
- case LVN_ENDSCROLL:
- {
- NMLVSCROLL *pScroll = (NMLVSCROLL*)lParam;
+ if (g_WM_KILLFOCUS_on_LVN_ENDLABELEDIT)
+ SendMessageA(edit, WM_KILLFOCUS, 0, 0);
- trace("LVN_%sSCROLL: (%d,%d)\n", pScroll->hdr.code ==
LVN_BEGINSCROLL ?
- "BEGIN" : "END",
pScroll->dx, pScroll->dy);
+ return TRUE;
}
- break;
case LVN_ITEMCHANGING:
{
NMLISTVIEW *nmlv = (NMLISTVIEW*)lParam;
@@ -1781,6 +1796,7 @@ static void test_redraw(void)
HDC hdc;
BOOL res;
DWORD r;
+ RECT rect;
hwnd = create_listview_control(LVS_REPORT);
subclass_header(hwnd);
@@ -1838,6 +1854,13 @@ static void test_redraw(void)
ReleaseDC(hwndparent, hdc);
+ /* test setting the window style to what it already was */
+ UpdateWindow(hwnd);
+ SetWindowLongA(hwnd, GWL_STYLE, GetWindowLongA(hwnd, GWL_STYLE));
+ GetUpdateRect(hwnd, &rect, FALSE);
+ ok(rect.left == 0 && rect.top == 0 && rect.right == 0 &&
rect.bottom == 0,
+ "Expected empty update rect, got %s\n", wine_dbgstr_rect(&rect));
+
DestroyWindow(hwnd);
}
@@ -2337,7 +2360,7 @@ static void test_multiselect(void)
r = SendMessageA(hwnd, LVM_GETSELECTIONMARK, 0, 0);
ok(r == 0, "got %d\n", r);
- for (i = 0; i < sizeof(task_list)/sizeof(task_list[0]); i++) {
+ for (i = 0; i < ARRAY_SIZE(task_list); i++) {
DWORD selected_count;
LVITEMA item;
@@ -3490,7 +3513,7 @@ static void test_norecompute(void)
item.mask = LVIF_TEXT | LVIF_NORECOMPUTE;
item.iItem = 0;
item.pszText = buff;
- item.cchTextMax = sizeof(buff)/sizeof(CHAR);
+ item.cchTextMax = ARRAY_SIZE(buff);
res = SendMessageA(hwnd, LVM_GETITEMA, 0, (LPARAM)&item);
expect(TRUE, res);
ok(lstrcmpA(buff, testA) == 0, "Expected (%s), got (%s)\n", testA, buff);
@@ -3504,7 +3527,7 @@ static void test_norecompute(void)
item.mask = LVIF_TEXT | LVIF_NORECOMPUTE;
item.iItem = 1;
item.pszText = buff;
- item.cchTextMax = sizeof(buff)/sizeof(CHAR);
+ item.cchTextMax = ARRAY_SIZE(buff);
flush_sequences(sequences, NUM_MSG_SEQUENCES);
res = SendMessageA(hwnd, LVM_GETITEMA, 0, (LPARAM)&item);
@@ -3529,7 +3552,7 @@ static void test_norecompute(void)
item.mask = LVIF_TEXT | LVIF_NORECOMPUTE;
item.iItem = 0;
item.pszText = buff;
- item.cchTextMax = sizeof(buff)/sizeof(CHAR);
+ item.cchTextMax = ARRAY_SIZE(buff);
flush_sequences(sequences, NUM_MSG_SEQUENCES);
res = SendMessageA(hwnd, LVM_GETITEMA, 0, (LPARAM)&item);
expect(TRUE, res);
@@ -4671,7 +4694,7 @@ static void test_canceleditlabel(void)
ok(!IsWindow(hwndedit), "Expected edit control to be destroyed\n");
memset(&itema, 0, sizeof(itema));
itema.pszText = buff;
- itema.cchTextMax = sizeof(buff)/sizeof(CHAR);
+ itema.cchTextMax = ARRAY_SIZE(buff);
ret = SendMessageA(hwnd, LVM_GETITEMTEXTA, 0, (LPARAM)&itema);
expect(5, ret);
ok(strcmp(buff, test1) == 0, "Expected label text not to change\n");
@@ -5499,7 +5522,7 @@ static void test_header_notification2(void)
memset(&itemW, 0, sizeof(itemW));
itemW.mask = HDI_WIDTH | HDI_ORDER | HDI_TEXT;
itemW.pszText = buffer;
- itemW.cchTextMax = sizeof(buffer);
+ itemW.cchTextMax = ARRAY_SIZE(buffer);
ret = SendMessageW(header, HDM_GETITEMW, 0, (LPARAM)&itemW);
expect(1, ret);
@@ -5667,7 +5690,7 @@ static void test_dispinfo(void)
g_disp_A_to_W = TRUE;
item.pszText = (char*)buff;
- item.cchTextMax = sizeof(buff)/sizeof(WCHAR);
+ item.cchTextMax = ARRAY_SIZE(buff);
ret = SendMessageA(hwnd, LVM_GETITEMTEXTA, 0, (LPARAM)&item);
ok(ret == sizeof(testA)-1, "got %d, expected 4\n", ret);
g_disp_A_to_W = FALSE;
@@ -6186,7 +6209,7 @@ static void test_state_image(void)
};
int i;
- for (i = 0; i < sizeof(styles)/sizeof(styles[0]); i++)
+ for (i = 0; i < ARRAY_SIZE(styles); i++)
{
static char text[] = "Item";
static char subtext[] = "Subitem";
@@ -6331,6 +6354,127 @@ static void test_LVSCW_AUTOSIZE(void)
DestroyWindow(hwnd);
}
+static void test_LVN_ENDLABELEDIT(void)
+{
+ WCHAR text[] = {'l','a','l','a',0};
+ HWND hwnd, hwndedit;
+ LVITEMW item = {0};
+ DWORD ret;
+
+ hwnd = create_listview_control(LVS_REPORT | LVS_EDITLABELS);
+
+ insert_column(hwnd, 0);
+
+ item.mask = LVIF_TEXT;
+ item.pszText = text;
+ SendMessageW(hwnd, LVM_INSERTITEMW, 0, (LPARAM)&item);
+
+ /* Test normal editing */
+ SetFocus(hwnd);
+ hwndedit = (HWND)SendMessageW(hwnd, LVM_EDITLABELW, 0, 0);
+ ok(hwndedit != NULL, "Failed to get edit control.\n");
+
+ ret = SendMessageA(hwndedit, WM_SETTEXT, 0, (LPARAM)"test");
+ ok(ret, "Failed to set edit text.\n");
+
+ flush_sequences(sequences, NUM_MSG_SEQUENCES);
+
+ ret = SendMessageA(hwndedit, WM_KEYDOWN, VK_RETURN, 0);
+ ok_sequence(sequences, PARENT_SEQ_INDEX, listview_end_label_edit, "Label
edit", FALSE);
+
+ /* Test editing with kill focus */
+ SetFocus(hwnd);
+ hwndedit = (HWND)SendMessageW(hwnd, LVM_EDITLABELW, 0, 0);
+ ok(hwndedit != NULL, "Failed to get edit control.\n");
+
+ ret = SendMessageA(hwndedit, WM_SETTEXT, 0, (LPARAM)"test2");
+ ok(ret, "Failed to set edit text.\n");
+
+ flush_sequences(sequences, NUM_MSG_SEQUENCES);
+
+ g_WM_KILLFOCUS_on_LVN_ENDLABELEDIT = TRUE;
+ ret = SendMessageA(hwndedit, WM_KEYDOWN, VK_RETURN, 0);
+ g_WM_KILLFOCUS_on_LVN_ENDLABELEDIT = FALSE;
+
+ ok_sequence(sequences, PARENT_SEQ_INDEX, listview_end_label_edit_kill_focus,
+ "Label edit, kill focus", FALSE);
+ ok(GetFocus() == hwnd, "Unexpected focused window.\n");
+
+ flush_sequences(sequences, NUM_MSG_SEQUENCES);
+
+ DestroyWindow(hwnd);
+}
+
+static LRESULT CALLBACK create_item_height_wndproc(HWND hwnd, UINT msg, WPARAM wParam,
LPARAM lParam)
+{
+ if (msg == WM_CREATE)
+ return 0;
+
+ return CallWindowProcA(listviewWndProc, hwnd, msg, wParam, lParam);
+}
+
+static void test_LVM_GETCOUNTPERPAGE(void)
+{
+ static const DWORD styles[] = { LVS_ICON, LVS_LIST, LVS_REPORT, LVS_SMALLICON };
+ unsigned int i, j;
+ WNDCLASSEXA cls;
+ ATOM class;
+ HWND hwnd;
+ BOOL ret;
+
+ cls.cbSize = sizeof(WNDCLASSEXA);
+ ret = GetClassInfoExA(GetModuleHandleA(NULL), WC_LISTVIEWA, &cls);
+ ok(ret, "Failed to get class info.\n");
+ listviewWndProc = cls.lpfnWndProc;
+ cls.lpfnWndProc = create_item_height_wndproc;
+ cls.lpszClassName = "CountPerPageClass";
+ class = RegisterClassExA(&cls);
+ ok(class, "Failed to register class.\n");
+
+ for (i = 0; i < ARRAY_SIZE(styles); i++)
+ {
+ static char text[] = "item text";
+ LVITEMA item = { 0 };
+ UINT count, count2;
+
+ hwnd = create_listview_control(styles[i]);
+ ok(hwnd != NULL, "Failed to create listview window.\n");
+
+ count = SendMessageA(hwnd, LVM_GETCOUNTPERPAGE, 0, 0);
+ if (styles[i] == LVS_LIST || styles[i] == LVS_REPORT)
+ ok(count > 0 || broken(styles[i] == LVS_LIST && count == 0),
"%u: unexpected count %u.\n", i, count);
+ else
+ ok(count == 0, "%u: unexpected count %u.\n", i, count);
+
+ for (j = 0; j < 10; j++)
+ {
+ item.mask = LVIF_TEXT;
+ item.pszText = text;
+ SendMessageA(hwnd, LVM_INSERTITEMA, 0, (LPARAM)&item);
+ }
+
+ count2 = SendMessageA(hwnd, LVM_GETCOUNTPERPAGE, 0, 0);
+ if (styles[i] == LVS_LIST || styles[i] == LVS_REPORT)
+ ok(count == count2, "%u: unexpected count %u.\n", i, count2);
+ else
+ ok(count2 == 10, "%u: unexpected count %u.\n", i, count2);
+
+ DestroyWindow(hwnd);
+
+ hwnd = CreateWindowA("CountPerPageClass", "Test", WS_VISIBLE
| styles[i], 0, 0, 100, 100, NULL, NULL,
+ GetModuleHandleA(NULL), 0);
+ ok(hwnd != NULL, "Failed to create a window.\n");
+
+ count = SendMessageA(hwnd, LVM_GETCOUNTPERPAGE, 0, 0);
+ ok(count == 0, "%u: unexpected count %u.\n", i, count);
+
+ DestroyWindow(hwnd);
+ }
+
+ ret = UnregisterClassA("CountPerPageClass", NULL);
+ ok(ret, "Failed to unregister test class.\n");
+}
+
START_TEST(listview)
{
ULONG_PTR ctx_cookie;
@@ -6392,6 +6536,8 @@ START_TEST(listview)
test_callback_mask();
test_state_image();
test_LVSCW_AUTOSIZE();
+ test_LVN_ENDLABELEDIT();
+ test_LVM_GETCOUNTPERPAGE();
if (!load_v6_module(&ctx_cookie, &hCtx))
{
@@ -6434,6 +6580,8 @@ START_TEST(listview)
test_oneclickactivate();
test_state_image();
test_LVSCW_AUTOSIZE();
+ test_LVN_ENDLABELEDIT();
+ test_LVM_GETCOUNTPERPAGE();
unload_v6_module(ctx_cookie, hCtx);
diff --git a/modules/rostests/winetests/comctl32/misc.c
b/modules/rostests/winetests/comctl32/misc.c
index e18ca39453..a52744fc2e 100644
--- a/modules/rostests/winetests/comctl32/misc.c
+++ b/modules/rostests/winetests/comctl32/misc.c
@@ -269,8 +269,7 @@ static void test_LoadIconWithScaleDown(void)
/* non-existing filename */
hr = pLoadIconMetric(NULL, nonexisting_fileW, LIM_LARGE, &icon);
- todo_wine
- ok(hr == HRESULT_FROM_WIN32(ERROR_RESOURCE_TYPE_NOT_FOUND),
+ ok(hr == HRESULT_FROM_WIN32(ERROR_RESOURCE_TYPE_NOT_FOUND) || hr ==
HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) /* Win7 */,
"Expected HRESULT_FROM_WIN32(ERROR_RESOURCE_TYPE_NOT_FOUND), got %x\n",
hr);
hr = pLoadIconWithScaleDown(NULL, nonexisting_fileW, 32, 32, &icon);
@@ -343,23 +342,32 @@ static void test_LoadIconWithScaleDown(void)
FreeLibrary(hinst);
}
-static void check_class( const char *name, int must_exist, UINT style, UINT ignore )
+static void check_class( const char *name, int must_exist, UINT style, UINT ignore, BOOL
v6 )
{
WNDCLASSA wc;
if (GetClassInfoA( 0, name, &wc ))
{
-todo_wine_if(strcmp(name, "Button") &&
- strcmp(name, "ComboBox") &&
- strcmp(name, "Edit") &&
- strcmp(name, "Static") &&
- strcmp(name, "ListBox") &&
- strcmp(name, "ComboLBox"))
+ char buff[64];
+ HWND hwnd;
+
+todo_wine_if(!strcmp(name, "SysLink") && !must_exist && !v6)
+ ok( must_exist, "System class %s should %sexist\n", name, must_exist ?
"" : "NOT " );
+ if (!must_exist) return;
+
+todo_wine_if(!strcmp(name, "ScrollBar") || (!strcmp(name,
"tooltips_class32") && v6))
ok( !(~wc.style & style & ~ignore), "System class %s is missing bits
%x (%08x/%08x)\n",
name, ~wc.style & style, wc.style, style );
+todo_wine_if((!strcmp(name, "tooltips_class32") && v6) || !strcmp(name,
"SysLink"))
ok( !(wc.style & ~style), "System class %s has extra bits %x
(%08x/%08x)\n",
name, wc.style & ~style, wc.style, style );
ok( !wc.hInstance, "System class %s has hInstance %p\n", name,
wc.hInstance );
+
+ hwnd = CreateWindowA(name, 0, 0, 0, 0, 0, 0, 0, NULL, GetModuleHandleA(NULL),
0);
+ ok( hwnd != NULL, "Failed to create window for class %s.\n", name );
+ GetClassNameA(hwnd, buff, ARRAY_SIZE(buff));
+ ok( !strcmp(name, buff), "Unexpected class name %s, expected %s.\n",
buff, name );
+ DestroyWindow(hwnd);
}
else
ok( !must_exist, "System class %s does not exist\n", name );
@@ -369,13 +377,40 @@ todo_wine_if(strcmp(name, "Button") &&
static void test_builtin_classes(void)
{
/* check style bits */
- check_class( "Button", 1, CS_PARENTDC | CS_DBLCLKS | CS_HREDRAW |
CS_VREDRAW | CS_GLOBALCLASS, 0 );
- check_class( "ComboBox", 1, CS_PARENTDC | CS_DBLCLKS | CS_HREDRAW |
CS_VREDRAW | CS_GLOBALCLASS, 0 );
- check_class( "Edit", 1, CS_PARENTDC | CS_DBLCLKS | CS_GLOBALCLASS, 0
);
- check_class( "ListBox", 1, CS_PARENTDC | CS_DBLCLKS | CS_GLOBALCLASS, 0
);
- check_class( "ScrollBar", 1, CS_PARENTDC | CS_DBLCLKS | CS_HREDRAW |
CS_VREDRAW | CS_GLOBALCLASS, 0 );
- check_class( "Static", 1, CS_PARENTDC | CS_DBLCLKS | CS_GLOBALCLASS, 0
);
- check_class( "ComboLBox", 1, CS_SAVEBITS | CS_DBLCLKS | CS_DROPSHADOW |
CS_GLOBALCLASS, CS_DROPSHADOW );
+ check_class( "Button", 1, CS_PARENTDC | CS_DBLCLKS | CS_HREDRAW |
CS_VREDRAW | CS_GLOBALCLASS, 0, FALSE );
+ check_class( "ComboBox", 1, CS_PARENTDC | CS_DBLCLKS | CS_HREDRAW |
CS_VREDRAW | CS_GLOBALCLASS, 0, FALSE );
+ check_class( "Edit", 1, CS_PARENTDC | CS_DBLCLKS | CS_GLOBALCLASS, 0,
FALSE );
+ check_class( "ListBox", 1, CS_PARENTDC | CS_DBLCLKS | CS_GLOBALCLASS, 0,
FALSE );
+ check_class( "ScrollBar", 1, CS_PARENTDC | CS_DBLCLKS | CS_HREDRAW |
CS_VREDRAW | CS_GLOBALCLASS, 0, FALSE );
+ check_class( "Static", 1, CS_PARENTDC | CS_DBLCLKS | CS_GLOBALCLASS, 0,
FALSE );
+ check_class( "ComboLBox", 1, CS_SAVEBITS | CS_DBLCLKS | CS_DROPSHADOW |
CS_GLOBALCLASS, CS_DROPSHADOW, FALSE );
+}
+
+static void test_comctl32_classes(BOOL v6)
+{
+ check_class(ANIMATE_CLASSA, 1, CS_DBLCLKS | CS_GLOBALCLASS, 0, FALSE);
+ check_class(WC_COMBOBOXEXA, 1, CS_GLOBALCLASS, 0, FALSE);
+ check_class(DATETIMEPICK_CLASSA, 1, CS_GLOBALCLASS, 0, FALSE);
+ check_class(WC_HEADERA, 1, CS_DBLCLKS | CS_GLOBALCLASS, 0, FALSE);
+ check_class(HOTKEY_CLASSA, 1, CS_GLOBALCLASS, 0, FALSE);
+ check_class(WC_IPADDRESSA, 1, CS_DBLCLKS | CS_HREDRAW | CS_VREDRAW |
CS_GLOBALCLASS, 0, FALSE);
+ check_class(WC_LISTVIEWA, 1, CS_DBLCLKS | CS_GLOBALCLASS, 0, FALSE);
+ check_class(MONTHCAL_CLASSA, 1, CS_GLOBALCLASS, 0, FALSE);
+ check_class(WC_NATIVEFONTCTLA, 1, CS_GLOBALCLASS, 0, FALSE);
+ check_class(WC_PAGESCROLLERA, 1, CS_GLOBALCLASS, 0, FALSE);
+ check_class(PROGRESS_CLASSA, 1, CS_HREDRAW | CS_VREDRAW | CS_GLOBALCLASS, 0,
FALSE);
+ check_class(REBARCLASSNAMEA, 1, CS_DBLCLKS | CS_GLOBALCLASS, 0, FALSE);
+ check_class(STATUSCLASSNAMEA, 1, CS_DBLCLKS | CS_VREDRAW | CS_GLOBALCLASS, 0,
FALSE);
+ check_class(WC_TABCONTROLA, 1, CS_DBLCLKS | CS_HREDRAW | CS_VREDRAW |
CS_GLOBALCLASS, 0, FALSE);
+ check_class(TOOLBARCLASSNAMEA, 1, CS_DBLCLKS | CS_GLOBALCLASS, 0, FALSE);
+ if (v6)
+ check_class(TOOLTIPS_CLASSA, 1, CS_DBLCLKS | CS_HREDRAW | CS_VREDRAW |
CS_GLOBALCLASS | CS_DROPSHADOW, CS_SAVEBITS | CS_HREDRAW | CS_VREDRAW /* XP */, TRUE);
+ else
+ check_class(TOOLTIPS_CLASSA, 1, CS_DBLCLKS | CS_GLOBALCLASS | CS_SAVEBITS,
CS_HREDRAW | CS_VREDRAW /* XP */, FALSE);
+ check_class(TRACKBAR_CLASSA, 1, CS_GLOBALCLASS, 0, FALSE);
+ check_class(WC_TREEVIEWA, 1, CS_DBLCLKS | CS_GLOBALCLASS, 0, FALSE);
+ check_class(UPDOWN_CLASSA, 1, CS_HREDRAW | CS_VREDRAW | CS_GLOBALCLASS, 0,
FALSE);
+ check_class("SysLink", v6, CS_GLOBALCLASS, 0, FALSE);
}
START_TEST(misc)
@@ -389,9 +424,12 @@ START_TEST(misc)
test_GetPtrAW();
test_Alloc();
+ test_comctl32_classes(FALSE);
+
if (!load_v6_module(&ctx_cookie, &hCtx))
return;
+ test_comctl32_classes(TRUE);
test_builtin_classes();
test_LoadIconWithScaleDown();
diff --git a/modules/rostests/winetests/comctl32/monthcal.c
b/modules/rostests/winetests/comctl32/monthcal.c
index 85822a320c..11a637fb82 100644
--- a/modules/rostests/winetests/comctl32/monthcal.c
+++ b/modules/rostests/winetests/comctl32/monthcal.c
@@ -1216,7 +1216,7 @@ if (0)
} else {
title_index++;
- if (sizeof(title_hits) / sizeof(title_hits[0]) <= title_index)
+ if (ARRAY_SIZE(title_hits) <= title_index)
break;
todo_wine_if(title_hits[title_index].todo)
@@ -1241,8 +1241,7 @@ if (0)
todo_wine ok(month_count + year_count >= 1, "Not enough month and year
items\n");
- ok(r.right <= x && title_index + 1 == sizeof(title_hits) /
sizeof(title_hits[0]),
- "Wrong title layout\n");
+ ok(r.right <= x && title_index + 1 == ARRAY_SIZE(title_hits), "Wrong
title layout\n");
DestroyWindow(hwnd);
}
@@ -1799,7 +1798,7 @@ static void test_hittest_v6(void)
mchit.iOffset = -1;
mchit.iCol = mchit.iRow = -1;
mchit.uHit = 0;
- mchit.rc.left = mchit.rc.right = mchit.rc.top = mchit.rc.bottom = -1;
+ SetRect(&mchit.rc, -1, -1, -1, -1);
ret = SendMessageA(hwnd, MCM_HITTEST, 0, (LPARAM)&mchit);
expect_hex(MCHT_CALENDARDATE, ret);
expect_hex(MCHT_CALENDARDATE, mchit.uHit);
@@ -1816,7 +1815,7 @@ static void test_hittest_v6(void)
mchit.iOffset = -1;
mchit.iCol = mchit.iRow = -1;
mchit.uHit = 0;
- mchit.rc.left = mchit.rc.right = mchit.rc.top = mchit.rc.bottom = -1;
+ SetRect(&mchit.rc, -1, -1, -1, -1);
ret = SendMessageA(hwnd, MCM_HITTEST, 0, (LPARAM)&mchit);
expect_hex(MCHT_TITLE, ret);
expect_hex(MCHT_TITLE, mchit.uHit);
@@ -1835,7 +1834,7 @@ static void test_hittest_v6(void)
mchit.iOffset = -2;
mchit.iCol = mchit.iRow = -2;
mchit.uHit = ~0;
- mchit.rc.left = mchit.rc.right = mchit.rc.top = mchit.rc.bottom = -1;
+ SetRect(&mchit.rc, -1, -1, -1, -1);
ret = SendMessageA(hwnd, MCM_HITTEST, 0, (LPARAM)&mchit);
todo_wine expect_hex(MCHT_NOWHERE, ret);
todo_wine expect_hex(MCHT_NOWHERE, mchit.uHit);
@@ -2016,7 +2015,7 @@ static void test_sel_notify(void)
};
int i;
- for(i = 0; i < sizeof styles / sizeof styles[0]; i++)
+ for(i = 0; i < ARRAY_SIZE(styles); i++)
{
hwnd = create_monthcal_control(styles[i].val);
SetWindowLongPtrA(hwnd, GWLP_ID, SEL_NOTIFY_TEST_ID);
diff --git a/modules/rostests/winetests/comctl32/mru.c
b/modules/rostests/winetests/comctl32/mru.c
index dfad6f859d..b3d3e7a265 100644
--- a/modules/rostests/winetests/comctl32/mru.c
+++ b/modules/rostests/winetests/comctl32/mru.c
@@ -118,7 +118,7 @@ static LSTATUS mru_RegDeleteTreeA(HKEY hKey, LPCSTR lpszSubKey)
dwMaxSubkeyLen++;
dwMaxValueLen++;
dwMaxLen = max(dwMaxSubkeyLen, dwMaxValueLen);
- if (dwMaxLen > sizeof(szNameBuf)/sizeof(CHAR))
+ if (dwMaxLen > ARRAY_SIZE(szNameBuf))
{
/* Name too big: alloc a buffer for it */
if (!(lpszName = heap_alloc(dwMaxLen * sizeof(CHAR))))
@@ -480,7 +480,7 @@ static void test_CreateMRUListLazyA(void)
return;
}
- for (i = 0; i < sizeof(create_lazyA)/sizeof(create_lazya_t); i++)
+ for (i = 0; i < ARRAY_SIZE(create_lazyA); i++)
{
const create_lazya_t *ptr = &create_lazyA[i];
HANDLE hMRU;
diff --git a/modules/rostests/winetests/comctl32/pager.c
b/modules/rostests/winetests/comctl32/pager.c
index 0da396cdd1..f48dc03954 100644
--- a/modules/rostests/winetests/comctl32/pager.c
+++ b/modules/rostests/winetests/comctl32/pager.c
@@ -28,10 +28,195 @@
#define PAGER_SEQ_INDEX 0
static HWND parent_wnd, child1_wnd, child2_wnd;
+static INT notify_format;
+static BOOL notify_query_received;
+static WCHAR test_w[] = {'t', 'e', 's', 't', 0};
+static CHAR test_a[] = {'t', 'e', 's', 't', 0};
+/* Double zero so that it's safe to cast it to WCHAR * */
+static CHAR te_a[] = {'t', 'e', 0, 0};
+static WCHAR empty_w[] = {0};
+static CHAR empty_a[] = {0};
+static CHAR large_a[] = "You should have received a copy of the GNU Lesser General
Public License along with this ...";
+static WCHAR large_w[] =
+{
+ 'Y', 'o', 'u', ' ', 's', 'h',
'o', 'u', 'l', 'd', ' ', 'h', 'a',
'v', 'e', ' ', 'r', 'e', 'c', 'e',
'i', 'v', 'e',
+ 'd', ' ', 'a', ' ', 'c', 'o',
'p', 'y', ' ', 'o', 'f', ' ', 't',
'h', 'e', ' ', 'G', 'N', 'U', ' ',
'L', 'e', 's',
+ 's', 'e', 'r', ' ', 'G', 'e',
'n', 'e', 'r', 'a', 'l', ' ', 'P',
'u', 'b', 'l', 'i', 'c', ' ', 'L',
'i', 'c', 'e',
+ 'n', 's', 'e', ' ', 'a', 'l',
'o', 'n', 'g', ' ', 'w', 'i', 't',
'h', ' ', 't', 'h', 'i', 's', ' ',
'.', '.', '.', 0
+};
+static WCHAR large_truncated_65_w[65] =
+{
+ 'Y', 'o', 'u', ' ', 's', 'h',
'o', 'u', 'l', 'd', ' ', 'h', 'a',
'v', 'e', ' ', 'r', 'e', 'c', 'e',
'i', 'v',
+ 'e', 'd', ' ', 'a', ' ', 'c',
'o', 'p', 'y', ' ', 'o', 'f', ' ',
't', 'h', 'e', ' ', 'G', 'N', 'U',
' ', 'L',
+ 'e', 's', 's', 'e', 'r', ' ',
'G', 'e', 'n', 'e', 'r', 'a', 'l',
' ', 'P', 'u', 'b', 'l', 'i', 'c',
0
+};
+static WCHAR large_truncated_80_w[80] =
+{
+ 'Y', 'o', 'u', ' ', 's', 'h',
'o', 'u', 'l', 'd', ' ', 'h', 'a',
'v', 'e', ' ', 'r', 'e', 'c',
'e',
+ 'i', 'v', 'e', 'd', ' ', 'a', '
', 'c', 'o', 'p', 'y', ' ', 'o',
'f', ' ', 't', 'h', 'e', ' ',
'G',
+ 'N', 'U', ' ', 'L', 'e', 's',
's', 'e', 'r', ' ', 'G', 'e', 'n',
'e', 'r', 'a', 'l', ' ', 'P',
'u',
+ 'b', 'l', 'i', 'c', ' ', 'L',
'i', 'c', 'e', 'n', 's', 'e', ' ',
'a', 'l', 'o', 'n', 'g', ' ', 'w'
+};
+static WCHAR buffer[64];
+
+/* Text field conversion test behavior flags. */
+enum test_conversion_flags
+{
+ CONVERT_SEND = 0x01,
+ DONT_CONVERT_SEND = 0x02,
+ CONVERT_RECEIVE = 0x04,
+ DONT_CONVERT_RECEIVE = 0x08,
+ SEND_EMPTY_IF_NULL = 0x10,
+ DONT_SEND_EMPTY_IF_NULL = 0x20,
+ SET_NULL_IF_NO_MASK = 0x40,
+ ZERO_SEND = 0x80
+};
+
+enum handler_ids
+{
+ TVITEM_NEW_HANDLER,
+ TVITEM_OLD_HANDLER
+};
+
+static struct notify_test_info
+{
+ UINT unicode;
+ UINT ansi;
+ UINT_PTR id_from;
+ HWND hwnd_from;
+ /* Whether parent received notification */
+ BOOL received;
+ UINT test_id;
+ UINT sub_test_id;
+ UINT handler_id;
+ /* Text field conversion test behavior flag */
+ DWORD flags;
+} notify_test_info;
+
+struct notify_test_send
+{
+ /* Data sent to pager */
+ WCHAR *send_text;
+ INT send_text_size;
+ INT send_text_max;
+ /* Data expected by parent of pager */
+ void *expect_text;
+};
+
+struct notify_test_receive
+{
+ /* Data sent to pager */
+ WCHAR *send_text;
+ INT send_text_size;
+ INT send_text_max;
+ /* Data for parent to write */
+ CHAR *write_pointer;
+ CHAR *write_text;
+ INT write_text_size;
+ INT write_text_max;
+ /* Data when message returned */
+ void *return_text;
+ INT return_text_max;
+};
+
+struct generic_text_helper_para
+{
+ void *ptr;
+ size_t size;
+ UINT *mask;
+ UINT required_mask;
+ WCHAR **text;
+ INT *text_max;
+ UINT code_unicode;
+ UINT code_ansi;
+ DWORD flags;
+ UINT handler_id;
+};
+
+static const struct notify_test_send test_convert_send_data[] =
+{
+ {test_w, sizeof(test_w), ARRAY_SIZE(buffer), test_a}
+};
+
+static const struct notify_test_send test_dont_convert_send_data[] =
+{
+ {test_w, sizeof(test_w), ARRAY_SIZE(buffer), test_w}
+};
+
+static const struct notify_test_receive test_convert_receive_data[] =
+{
+ {empty_w, sizeof(empty_w), ARRAY_SIZE(buffer), NULL, test_a, sizeof(test_a), -1,
test_w, ARRAY_SIZE(buffer)},
+ {empty_w, sizeof(empty_w), ARRAY_SIZE(buffer), test_a, NULL, 0, -1, test_w,
ARRAY_SIZE(buffer)},
+ {NULL, sizeof(empty_w), ARRAY_SIZE(buffer), test_a, NULL, 0, -1, NULL,
ARRAY_SIZE(buffer)},
+ {empty_w, sizeof(empty_w), ARRAY_SIZE(buffer), large_a, NULL, 0, -1,
large_truncated_65_w, ARRAY_SIZE(buffer)},
+ {empty_w, sizeof(empty_w), ARRAY_SIZE(buffer), empty_a, 0, 0, 1, empty_w, 1},
+};
+
+static const struct notify_test_receive test_dont_convert_receive_data[] =
+{
+ {empty_w, sizeof(empty_w), ARRAY_SIZE(buffer), NULL, test_a, sizeof(test_a), -1,
test_a, ARRAY_SIZE(buffer)},
+ {empty_w, sizeof(empty_w), ARRAY_SIZE(buffer), test_a, NULL, 0, -1, test_a,
ARRAY_SIZE(buffer)},
+};
+
+static const struct notify_test_tooltip
+{
+ /* Data for parent to write */
+ CHAR *write_sztext;
+ INT write_sztext_size;
+ CHAR *write_lpsztext;
+ HMODULE write_hinst;
+ /* Data when message returned */
+ WCHAR *return_sztext;
+ INT return_sztext_size;
+ WCHAR *return_lpsztext;
+ HMODULE return_hinst;
+ /* Data expected by parent */
+ CHAR *expect_sztext;
+ /* Data send to parent */
+ WCHAR *send_sztext;
+ INT send_sztext_size;
+ WCHAR *send_lpsztext;
+} test_tooltip_data[] =
+{
+ {NULL, 0, NULL, NULL, empty_w, -1, empty_w},
+ {test_a, sizeof(test_a), NULL, NULL, test_w, -1, test_w},
+ {test_a, sizeof(test_a), test_a, NULL, test_w, -1, test_w},
+ {test_a, sizeof(test_a), (CHAR *)1, (HMODULE)0xdeadbeef, empty_w, -1, (WCHAR *)1,
(HMODULE)0xdeadbeef},
+ {test_a, sizeof(test_a), test_a, (HMODULE)0xdeadbeef, test_w, -1, test_w,
(HMODULE)0xdeadbeef},
+ {NULL, 0, test_a, NULL, test_w, -1, test_w},
+ {test_a, 2, test_a, NULL, test_w, -1, test_w},
+ {NULL, 0, NULL, NULL, test_w, -1, test_w, NULL, test_a, test_w, sizeof(test_w)},
+ {NULL, 0, NULL, NULL, empty_w, -1, empty_w, NULL, empty_a, NULL, 0, test_w},
+ {NULL, 0, large_a, NULL, large_truncated_80_w, sizeof(large_truncated_80_w),
large_w}
+};
+
+static const struct notify_test_datetime_format
+{
+ /* Data send to parent */
+ WCHAR *send_pszformat;
+ /* Data expected by parent */
+ CHAR *expect_pszformat;
+ /* Data for parent to write */
+ CHAR *write_szdisplay;
+ INT write_szdisplay_size;
+ CHAR *write_pszdisplay;
+ /* Data when message returned */
+ WCHAR *return_szdisplay;
+ INT return_szdisplay_size;
+ WCHAR *return_pszdisplay;
+} test_datetime_format_data[] =
+{
+ {test_w, test_a},
+ {NULL, NULL, NULL, 0, test_a, empty_w, -1, test_w},
+ {NULL, NULL, test_a, sizeof(test_a), NULL, test_w, -1, test_w},
+ {NULL, NULL, test_a, 2, test_a, (WCHAR *)te_a, -1, test_w},
+ {NULL, NULL, NULL, 0, large_a, NULL, 0, large_w}
+};
#define CHILD1_ID 1
#define CHILD2_ID 2
+static BOOL (WINAPI *pInitCommonControlsEx)(const INITCOMMONCONTROLSEX*);
static BOOL (WINAPI *pSetWindowSubclass)(HWND, SUBCLASSPROC, UINT_PTR, DWORD_PTR);
static struct msg_sequence *sequences[NUM_MSG_SEQUENCES];
@@ -97,6 +282,14 @@ static const struct message set_pos_empty_seq[] = {
{ 0 }
};
+static CHAR *heap_strdup(const CHAR *str)
+{
+ int len = lstrlenA(str) + 1;
+ CHAR *ret = heap_alloc(len * sizeof(CHAR));
+ lstrcpyA(ret, str);
+ return ret;
+}
+
static LRESULT WINAPI parent_wnd_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM
lParam)
{
static LONG defwndproc_counter = 0;
@@ -257,11 +450,7 @@ static void test_pager(void)
RECT rect, rect2;
pager = create_pager_control( PGS_HORZ );
- if (!pager)
- {
- win_skip( "Pager control not supported\n" );
- return;
- }
+ ok(pager != NULL, "Fail to create pager\n");
register_child_wnd_class();
@@ -333,11 +522,809 @@ static void test_pager(void)
DestroyWindow( pager );
}
-START_TEST(pager)
+static LRESULT WINAPI test_notifyformat_proc(HWND hwnd, UINT message, WPARAM wParam,
LPARAM lParam)
{
- HMODULE mod = GetModuleHandleA("comctl32.dll");
+ switch (message)
+ {
+ case WM_NOTIFYFORMAT:
+ if (lParam == NF_QUERY)
+ {
+ notify_query_received = TRUE;
+ return notify_format;
+ }
+ else if (lParam == NF_REQUERY)
+ return SendMessageA(GetParent(hwnd), WM_NOTIFYFORMAT, (WPARAM)hwnd,
NF_QUERY);
+ else
+ return 0;
+ default:
+ return notify_format == NFR_UNICODE ? DefWindowProcW(hwnd, message, wParam,
lParam)
+ : DefWindowProcA(hwnd, message, wParam,
lParam);
+ }
+}
+
+static BOOL register_notifyformat_class(void)
+{
+ static const WCHAR class_w[] = {'P', 'a', 'g', 'e',
'r', ' ', 'n', 'o', 't', 'i', 'f',
'y', 'f',
+ 'o', 'r', 'm', 'a',
't', ' ', 'c', 'l', 'a', 's', 's',
0};
+ WNDCLASSW cls = {0};
+
+ cls.lpfnWndProc = test_notifyformat_proc;
+ cls.hInstance = GetModuleHandleW(NULL);
+ cls.lpszClassName = class_w;
+ return RegisterClassW(&cls);
+}
+
+static void test_wm_notifyformat(void)
+{
+ static const WCHAR class_w[] = {'P', 'a', 'g', 'e',
'r', ' ', 'n', 'o', 't', 'i', 'f',
'y', 'f',
+ 'o', 'r', 'm', 'a',
't', ' ', 'c', 'l', 'a', 's', 's',
0};
+ static const WCHAR parent_w[] = {'p', 'a', 'r', 'e',
'n', 't', 0};
+ static const WCHAR pager_w[] = {'p', 'a', 'g', 'e',
'r', 0};
+ static const WCHAR child_w[] = {'c', 'h', 'i', 'l',
'd', 0};
+ static const INT formats[] = {NFR_UNICODE, NFR_ANSI};
+ HWND parent, pager, child;
+ LRESULT ret;
+ INT i;
+
+ ok(register_notifyformat_class(), "Register test class failed, error
0x%08x\n", GetLastError());
+
+ for (i = 0; i < ARRAY_SIZE(formats); i++)
+ {
+ notify_format = formats[i];
+ parent = CreateWindowW(class_w, parent_w, WS_OVERLAPPED, 0, 0, 100, 100, 0, 0,
GetModuleHandleW(0), 0);
+ ok(parent != NULL, "CreateWindow failed\n");
+ pager = CreateWindowW(WC_PAGESCROLLERW, pager_w, WS_CHILD, 0, 0, 100, 100,
parent, 0, GetModuleHandleW(0), 0);
+ ok(pager != NULL, "CreateWindow failed\n");
+ child = CreateWindowW(class_w, child_w, WS_CHILD, 0, 0, 100, 100, pager, 0,
GetModuleHandleW(0), 0);
+ ok(child != NULL, "CreateWindow failed\n");
+ SendMessageW(pager, PGM_SETCHILD, 0, (LPARAM)child);
+
+ /* Test parent */
+ notify_query_received = FALSE;
+ ret = SendMessageW(pager, WM_NOTIFYFORMAT, (WPARAM)parent, NF_REQUERY);
+ ok(ret == notify_format, "Expect %d, got %ld\n", notify_format, ret);
+ ok(notify_query_received, "Didn't receive notify\n");
+
+ /* Send NF_QUERY directly to parent */
+ notify_query_received = FALSE;
+ ret = SendMessageW(parent, WM_NOTIFYFORMAT, (WPARAM)pager, NF_QUERY);
+ ok(ret == notify_format, "Expect %d, got %ld\n", notify_format, ret);
+ ok(notify_query_received, "Didn't receive notify\n");
+
+ /* Pager send notifications to its parent regardless of wParam */
+ notify_query_received = FALSE;
+ ret = SendMessageW(pager, WM_NOTIFYFORMAT, (WPARAM)parent_wnd, NF_REQUERY);
+ ok(ret == notify_format, "Expect %d, got %ld\n", notify_format, ret);
+ ok(notify_query_received, "Didn't receive notify\n");
+
+ /* Pager always wants Unicode notifications from children */
+ ret = SendMessageW(child, WM_NOTIFYFORMAT, (WPARAM)pager, NF_REQUERY);
+ ok(ret == NFR_UNICODE, "Expect %d, got %ld\n", NFR_UNICODE, ret);
+ ret = SendMessageW(pager, WM_NOTIFYFORMAT, (WPARAM)child, NF_QUERY);
+ ok(ret == NFR_UNICODE, "Expect %d, got %ld\n", NFR_UNICODE, ret);
+
+ DestroyWindow(parent);
+ }
+
+ UnregisterClassW(class_w, GetModuleHandleW(NULL));
+}
+
+static void notify_generic_text_handler(CHAR **text, INT *text_max)
+{
+ const struct notify_test_send *send_data;
+ const struct notify_test_receive *receive_data;
+
+ switch (notify_test_info.test_id)
+ {
+ case CONVERT_SEND:
+ case DONT_CONVERT_SEND:
+ {
+ send_data = (notify_test_info.test_id == CONVERT_SEND ? test_convert_send_data :
test_dont_convert_send_data)
+ + notify_test_info.sub_test_id;
+ if (notify_test_info.flags & ZERO_SEND)
+ ok(!lstrcmpA(*text, empty_a), "Code 0x%08x test 0x%08x sub test %d
expect empty text, got %s\n",
+ notify_test_info.unicode, notify_test_info.test_id,
notify_test_info.sub_test_id, *text);
+ else if (notify_test_info.flags & CONVERT_SEND)
+ ok(!lstrcmpA(send_data->expect_text, *text), "Code 0x%08x test 0x%08x
sub test %d expect %s, got %s\n",
+ notify_test_info.unicode, notify_test_info.test_id,
notify_test_info.sub_test_id,
+ (CHAR *)send_data->expect_text, *text);
+ else
+ ok(!lstrcmpW((WCHAR *)send_data->expect_text, (WCHAR *)*text),
+ "Code 0x%08x test 0x%08x sub test %d expect %s, got %s\n",
notify_test_info.unicode,
+ notify_test_info.test_id, notify_test_info.sub_test_id,
wine_dbgstr_w((WCHAR *)send_data->expect_text),
+ wine_dbgstr_w((WCHAR *)*text));
+ if (text_max)
+ ok(*text_max == send_data->send_text_max, "Code 0x%08x test 0x%08x
sub test %d expect %d, got %d\n",
+ notify_test_info.unicode, notify_test_info.test_id,
notify_test_info.sub_test_id,
+ send_data->send_text_max, *text_max);
+ break;
+ }
+ case CONVERT_RECEIVE:
+ case DONT_CONVERT_RECEIVE:
+ {
+ receive_data = (notify_test_info.test_id == CONVERT_RECEIVE ?
test_convert_receive_data : test_dont_convert_receive_data)
+ + notify_test_info.sub_test_id;
+ if (text_max)
+ ok(*text_max == receive_data->send_text_max, "Code 0x%08x test 0x%08x
sub test %d expect %d, got %d\n",
+ notify_test_info.unicode, notify_test_info.test_id,
notify_test_info.sub_test_id,
+ receive_data->send_text_max, *text_max);
+
+ if (receive_data->write_text)
+ memcpy(*text, receive_data->write_text,
receive_data->write_text_size);
+ /* 64bit Windows will try to free the text pointer even if it's application
provided when handling
+ * HDN_GETDISPINFOW. Deliberate leak here. */
+ else if(notify_test_info.unicode == HDN_GETDISPINFOW)
+ *text = heap_strdup(receive_data->write_pointer);
+ else
+ *text = receive_data->write_pointer;
+ if (text_max && receive_data->write_text_max != -1) *text_max =
receive_data->write_text_max;
+ break;
+ }
+ case SEND_EMPTY_IF_NULL:
+ ok(!lstrcmpA(*text, empty_a), "Code 0x%08x test 0x%08x sub test %d expect
empty text, got %s\n",
+ notify_test_info.unicode, notify_test_info.test_id,
notify_test_info.sub_test_id, *text);
+ break;
+ case DONT_SEND_EMPTY_IF_NULL:
+ ok(!*text, "Code 0x%08x test 0x%08x sub test %d expect null text\n",
notify_test_info.unicode,
+ notify_test_info.test_id, notify_test_info.sub_test_id);
+ break;
+ }
+}
+
+static void notify_tooltip_handler(NMTTDISPINFOA *nm)
+{
+ const struct notify_test_tooltip *data = test_tooltip_data +
notify_test_info.sub_test_id;
+ ok(nm->lpszText == nm->szText, "Sub test %d expect %p, got %p\n",
notify_test_info.sub_test_id, nm->szText,
+ nm->lpszText);
+ if (data->expect_sztext)
+ ok(!lstrcmpA(data->expect_sztext, nm->szText), "Sub test %d expect %s,
got %s\n", notify_test_info.sub_test_id,
+ data->expect_sztext, nm->szText);
+ if (data->write_sztext) memcpy(nm->szText, data->write_sztext,
data->write_sztext_size);
+ if (data->write_lpsztext) nm->lpszText = data->write_lpsztext;
+ if (data->write_hinst) nm->hinst = data->write_hinst;
+}
+
+static void notify_datetime_handler(NMDATETIMEFORMATA *nm)
+{
+ const struct notify_test_datetime_format *data = test_datetime_format_data +
notify_test_info.sub_test_id;
+ if (data->expect_pszformat)
+ ok(!lstrcmpA(data->expect_pszformat, nm->pszFormat), "Sub test %d
expect %s, got %s\n",
+ notify_test_info.sub_test_id, data->expect_pszformat, nm->pszFormat);
+ ok(nm->pszDisplay == nm->szDisplay, "Test %d expect %p, got %p\n",
notify_test_info.sub_test_id, nm->szDisplay,
+ nm->pszDisplay);
+ if (data->write_szdisplay) memcpy(nm->szDisplay, data->write_szdisplay,
data->write_szdisplay_size);
+ if (data->write_pszdisplay) nm->pszDisplay = data->write_pszdisplay;
+}
+
+static LRESULT WINAPI test_notify_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM
lParam)
+{
+ static const WCHAR test[] = {'t', 'e', 's', 't', 0};
+ switch (message)
+ {
+ case WM_NOTIFY:
+ {
+ NMHDR *hdr = (NMHDR *)lParam;
+
+ /* Not notifications we want to test */
+ if (!notify_test_info.unicode) break;
+ ok(!notify_test_info.received, "Extra notification received\n");
+
+ ok(wParam == notify_test_info.id_from, "Expect %ld, got %ld\n",
notify_test_info.id_from, wParam);
+ ok(hdr->code == notify_test_info.ansi, "Expect 0x%08x, got
0x%08x\n", notify_test_info.ansi, hdr->code);
+ ok(hdr->idFrom == notify_test_info.id_from, "Expect %ld, got %ld\n",
notify_test_info.id_from, wParam);
+ ok(hdr->hwndFrom == notify_test_info.hwnd_from, "Expect %p, got
%p\n", notify_test_info.hwnd_from, hdr->hwndFrom);
+
+ if (hdr->code != notify_test_info.ansi)
+ {
+ skip("Notification code mismatch, skipping lParam check\n");
+ return 0;
+ }
+ switch (hdr->code)
+ {
+ /* ComboBoxEx */
+ case CBEN_INSERTITEM:
+ case CBEN_DELETEITEM:
+ {
+ NMCOMBOBOXEXW *nmcbe = (NMCOMBOBOXEXW *)hdr;
+ notify_generic_text_handler((CHAR **)&nmcbe->ceItem.pszText, NULL);
+ break;
+ }
+ case CBEN_DRAGBEGINA:
+ {
+ NMCBEDRAGBEGINA *nmcbedb = (NMCBEDRAGBEGINA *)hdr;
+ ok(!lstrcmpA(nmcbedb->szText, test_a), "Expect %s, got %s\n",
nmcbedb->szText, test_a);
+ break;
+ }
+ case CBEN_ENDEDITA:
+ {
+ NMCBEENDEDITA *nmcbeed = (NMCBEENDEDITA *)hdr;
+ ok(!lstrcmpA(nmcbeed->szText, test_a), "Expect %s, got %s\n",
nmcbeed->szText, test_a);
+ break;
+ }
+ case CBEN_GETDISPINFOA:
+ {
+ NMCOMBOBOXEXA *nmcbe = (NMCOMBOBOXEXA *)hdr;
+ notify_generic_text_handler(&nmcbe->ceItem.pszText,
&nmcbe->ceItem.cchTextMax);
+ break;
+ }
+ /* Date and Time Picker */
+ case DTN_FORMATA:
+ {
+ notify_datetime_handler((NMDATETIMEFORMATA *)hdr);
+ break;
+ }
+ case DTN_FORMATQUERYA:
+ {
+ NMDATETIMEFORMATQUERYA *nmdtfq = (NMDATETIMEFORMATQUERYA *)hdr;
+ notify_generic_text_handler((CHAR **)&nmdtfq->pszFormat, NULL);
+ break;
+ }
+ case DTN_WMKEYDOWNA:
+ {
+ NMDATETIMEWMKEYDOWNA *nmdtkd = (NMDATETIMEWMKEYDOWNA *)hdr;
+ notify_generic_text_handler((CHAR **)&nmdtkd->pszFormat, NULL);
+ break;
+ }
+ case DTN_USERSTRINGA:
+ {
+ NMDATETIMESTRINGA *nmdts = (NMDATETIMESTRINGA *)hdr;
+ notify_generic_text_handler((CHAR **)&nmdts->pszUserString, NULL);
+ break;
+ }
+ /* Header */
+ case HDN_BEGINDRAG:
+ case HDN_ENDDRAG:
+ case HDN_BEGINFILTEREDIT:
+ case HDN_ENDFILTEREDIT:
+ case HDN_DROPDOWN:
+ case HDN_FILTERCHANGE:
+ case HDN_ITEMKEYDOWN:
+ case HDN_ITEMSTATEICONCLICK:
+ case HDN_OVERFLOWCLICK:
+ {
+ NMHEADERW *nmhd = (NMHEADERW *)hdr;
+ ok(!lstrcmpW(nmhd->pitem->pszText, test_w), "Expect %s, got
%s\n", wine_dbgstr_w(test_w),
+ wine_dbgstr_w(nmhd->pitem->pszText));
+ ok(!lstrcmpW(((HD_TEXTFILTERW *)nmhd->pitem->pvFilter)->pszText,
test_w), "Expect %s, got %s\n",
+ wine_dbgstr_w(test_w), wine_dbgstr_w(((HD_TEXTFILTERW
*)nmhd->pitem->pvFilter)->pszText));
+ break;
+ }
+ case HDN_BEGINTRACKA:
+ case HDN_DIVIDERDBLCLICKA:
+ case HDN_ENDTRACKA:
+ case HDN_ITEMCHANGEDA:
+ case HDN_ITEMCHANGINGA:
+ case HDN_ITEMCLICKA:
+ case HDN_ITEMDBLCLICKA:
+ case HDN_TRACKA:
+ {
+ NMHEADERA *nmhd = (NMHEADERA *)hdr;
+ ok(!lstrcmpA(nmhd->pitem->pszText, test_a), "Expect %s, got
%s\n", test_a, nmhd->pitem->pszText);
+ ok(!lstrcmpA(((HD_TEXTFILTERA *)nmhd->pitem->pvFilter)->pszText,
test_a), "Expect %s, got %s\n", test_a,
+ ((HD_TEXTFILTERA *)nmhd->pitem->pvFilter)->pszText);
+ break;
+ }
+ case HDN_GETDISPINFOA:
+ {
+ NMHDDISPINFOA *nmhddi = (NMHDDISPINFOA *)hdr;
+ notify_generic_text_handler(&nmhddi->pszText,
&nmhddi->cchTextMax);
+ break;
+ }
+ /* List View */
+ case LVN_BEGINLABELEDITA:
+ case LVN_ENDLABELEDITA:
+ case LVN_GETDISPINFOA:
+ case LVN_SETDISPINFOA:
+ {
+ NMLVDISPINFOA *nmlvdi = (NMLVDISPINFOA *)hdr;
+ notify_generic_text_handler(&nmlvdi->item.pszText,
&nmlvdi->item.cchTextMax);
+ break;
+ }
+ case LVN_GETINFOTIPA:
+ {
+ NMLVGETINFOTIPA *nmlvgit = (NMLVGETINFOTIPA *)hdr;
+ notify_generic_text_handler(&nmlvgit->pszText,
&nmlvgit->cchTextMax);
+ break;
+ }
+ case LVN_INCREMENTALSEARCHA:
+ case LVN_ODFINDITEMA:
+ {
+ NMLVFINDITEMA *nmlvfi = (NMLVFINDITEMA *)hdr;
+ notify_generic_text_handler((CHAR **)&nmlvfi->lvfi.psz, NULL);
+ break;
+ }
+ /* Toolbar */
+ case TBN_SAVE:
+ {
+ NMTBSAVE *nmtbs = (NMTBSAVE *)hdr;
+ notify_generic_text_handler((CHAR **)&nmtbs->tbButton.iString, NULL);
+ break;
+ }
+ case TBN_RESTORE:
+ {
+ NMTBRESTORE *nmtbr = (NMTBRESTORE *)hdr;
+ notify_generic_text_handler((CHAR **)&nmtbr->tbButton.iString, NULL);
+ break;
+ }
+ case TBN_GETBUTTONINFOA:
+ {
+ NMTOOLBARA *nmtb = (NMTOOLBARA *)hdr;
+ notify_generic_text_handler(&nmtb->pszText, &nmtb->cchText);
+ break;
+ }
+ case TBN_GETDISPINFOW:
+ {
+ NMTBDISPINFOW *nmtbdi = (NMTBDISPINFOW *)hdr;
+ notify_generic_text_handler((CHAR **)&nmtbdi->pszText,
&nmtbdi->cchText);
+ break;
+ }
+ case TBN_GETINFOTIPA:
+ {
+ NMTBGETINFOTIPA *nmtbgit = (NMTBGETINFOTIPA *)hdr;
+ notify_generic_text_handler(&nmtbgit->pszText,
&nmtbgit->cchTextMax);
+ break;
+ }
+ /* Tooltip */
+ case TTN_GETDISPINFOA:
+ {
+ notify_tooltip_handler((NMTTDISPINFOA *)hdr);
+ break;
+ }
+ /* Tree View */
+ case TVN_BEGINLABELEDITA:
+ case TVN_ENDLABELEDITA:
+ case TVN_GETDISPINFOA:
+ case TVN_SETDISPINFOA:
+ {
+ NMTVDISPINFOA *nmtvdi = (NMTVDISPINFOA *)hdr;
+ notify_generic_text_handler(&nmtvdi->item.pszText,
&nmtvdi->item.cchTextMax);
+ break;
+ }
+ case TVN_GETINFOTIPA:
+ {
+ NMTVGETINFOTIPA *nmtvgit = (NMTVGETINFOTIPA *)hdr;
+ notify_generic_text_handler(&nmtvgit->pszText,
&nmtvgit->cchTextMax);
+ break;
+ }
+ case TVN_SINGLEEXPAND:
+ case TVN_BEGINDRAGA:
+ case TVN_BEGINRDRAGA:
+ case TVN_ITEMEXPANDEDA:
+ case TVN_ITEMEXPANDINGA:
+ case TVN_DELETEITEMA:
+ case TVN_SELCHANGINGA:
+ case TVN_SELCHANGEDA:
+ {
+ NMTREEVIEWA *nmtv = (NMTREEVIEWA *)hdr;
+ if (notify_test_info.handler_id == TVITEM_NEW_HANDLER)
+ notify_generic_text_handler((CHAR **)&nmtv->itemNew.pszText,
&nmtv->itemNew.cchTextMax);
+ else
+ notify_generic_text_handler((CHAR **)&nmtv->itemOld.pszText,
&nmtv->itemOld.cchTextMax);
+ break;
+ }
+
+ default:
+ ok(0, "Unexpected message 0x%08x\n", hdr->code);
+ }
+ notify_test_info.received = TRUE;
+ ok(!lstrcmpA(test_a, "test"), "test_a got modified\n");
+ ok(!lstrcmpW(test_w, test), "test_w got modified\n");
+ return 0;
+ }
+ case WM_NOTIFYFORMAT:
+ if (lParam == NF_QUERY) return NFR_ANSI;
+ break;
+ }
+ return DefWindowProcA(hwnd, message, wParam, lParam);
+}
+
+static BOOL register_test_notify_class(void)
+{
+ WNDCLASSA cls = {0};
+
+ cls.lpfnWndProc = test_notify_proc;
+ cls.hInstance = GetModuleHandleA(NULL);
+ cls.lpszClassName = "Pager notify class";
+ return RegisterClassA(&cls);
+}
+
+static void send_notify(HWND pager, UINT unicode, UINT ansi, LPARAM lParam, BOOL
code_change)
+{
+ NMHDR *hdr = (NMHDR *)lParam;
+
+ notify_test_info.unicode = unicode;
+ notify_test_info.id_from = 1;
+ notify_test_info.hwnd_from = child1_wnd;
+ notify_test_info.ansi = ansi;
+ notify_test_info.received = FALSE;
+
+ hdr->code = unicode;
+ hdr->idFrom = 1;
+ hdr->hwndFrom = child1_wnd;
+
+ SendMessageW(pager, WM_NOTIFY, hdr->idFrom, lParam);
+ ok(notify_test_info.received, "Expect notification received\n");
+ ok(hdr->code == code_change ? ansi : unicode, "Expect 0x%08x, got
0x%08x\n", hdr->code,
+ code_change ? ansi : unicode);
+}
+
+/* Send notify to test text field conversion. In parent proc
notify_generic_text_handler() handles these messages */
+static void test_notify_generic_text_helper(HWND pager, const struct
generic_text_helper_para *para)
+{
+ const struct notify_test_send *send_data;
+ const struct notify_test_receive *receive_data;
+ INT array_size;
+ INT i;
+
+ notify_test_info.flags = para->flags;
+ notify_test_info.handler_id = para->handler_id;
+
+ if (para->flags & (CONVERT_SEND | DONT_CONVERT_SEND))
+ {
+ if (para->flags & CONVERT_SEND)
+ {
+ notify_test_info.test_id = CONVERT_SEND;
+ send_data = test_convert_send_data;
+ array_size = ARRAY_SIZE(test_convert_send_data);
+ }
+ else
+ {
+ notify_test_info.test_id = DONT_CONVERT_SEND;
+ send_data = test_dont_convert_send_data;
+ array_size = ARRAY_SIZE(test_dont_convert_send_data);
+ }
+
+ for (i = 0; i < array_size; i++)
+ {
+ const struct notify_test_send *data = send_data + i;
+ notify_test_info.sub_test_id = i;
+
+ memset(para->ptr, 0, para->size);
+ if (para->mask) *para->mask = para->required_mask;
+ if (data->send_text)
+ {
+ memcpy(buffer, data->send_text, data->send_text_size);
+ *para->text = buffer;
+ }
+ if (para->text_max) *para->text_max = data->send_text_max;
+ send_notify(pager, para->code_unicode, para->code_ansi,
(LPARAM)para->ptr, TRUE);
+ }
+ }
+
+ if (para->flags & (CONVERT_RECEIVE | DONT_CONVERT_RECEIVE))
+ {
+ if (para->flags & CONVERT_RECEIVE)
+ {
+ notify_test_info.test_id = CONVERT_RECEIVE;
+ receive_data = test_convert_receive_data;
+ array_size = ARRAY_SIZE(test_convert_receive_data);
+ }
+ else
+ {
+ notify_test_info.test_id = DONT_CONVERT_RECEIVE;
+ receive_data = test_dont_convert_receive_data;
+ array_size = ARRAY_SIZE(test_dont_convert_receive_data);
+ }
+
+ for (i = 0; i < array_size; i++)
+ {
+ const struct notify_test_receive *data = receive_data + i;
+ notify_test_info.sub_test_id = i;
+
+ memset(para->ptr, 0, para->size);
+ if (para->mask) *para->mask = para->required_mask;
+ if (data->send_text)
+ {
+ memcpy(buffer, data->send_text, data->send_text_size);
+ *para->text = buffer;
+ }
+ if (para->text_max) *para->text_max = data->send_text_max;
+ send_notify(pager, para->code_unicode, para->code_ansi,
(LPARAM)para->ptr, TRUE);
+ if (data->return_text)
+ {
+ if (para->flags & CONVERT_RECEIVE)
+ ok(!lstrcmpW(data->return_text, *para->text), "Code 0x%08x
sub test %d expect %s, got %s\n",
+ para->code_unicode, i, wine_dbgstr_w((WCHAR
*)data->return_text), wine_dbgstr_w(*para->text));
+ else
+ ok(!lstrcmpA(data->return_text, (CHAR *)*para->text),
"Code 0x%08x sub test %d expect %s, got %s\n",
+ para->code_unicode, i, (CHAR *)data->return_text, (CHAR
*)*para->text);
+ }
+ if (para->text_max)
+ ok(data->return_text_max == *para->text_max, "Code 0x%08x sub
test %d expect %d, got %d\n",
+ para->code_unicode, i, data->return_text_max,
*para->text_max);
+ }
+ }
+
+ /* Extra tests for other behavior flags that are not worth it to create their own
test arrays */
+ memset(para->ptr, 0, para->size);
+ if (para->mask) *para->mask = para->required_mask;
+ if (para->text_max) *para->text_max = 1;
+ if (para->flags & SEND_EMPTY_IF_NULL)
+ notify_test_info.test_id = SEND_EMPTY_IF_NULL;
+ else
+ notify_test_info.test_id = DONT_SEND_EMPTY_IF_NULL;
+ send_notify(pager, para->code_unicode, para->code_ansi, (LPARAM)para->ptr,
TRUE);
+
+ notify_test_info.test_id = SET_NULL_IF_NO_MASK;
+ memset(para->ptr, 0, para->size);
+ memset(buffer, 0, sizeof(buffer));
+ *para->text = buffer;
+ if (para->text_max) *para->text_max = ARRAY_SIZE(buffer);
+ send_notify(pager, para->code_unicode, para->code_ansi, (LPARAM)para->ptr,
TRUE);
+ if(para->flags & SET_NULL_IF_NO_MASK)
+ ok(!*para->text, "Expect null text\n");
+}
+
+static void test_wm_notify_comboboxex(HWND pager)
+{
+ static NMCBEDRAGBEGINW nmcbedb;
+ static NMCBEENDEDITW nmcbeed;
+
+ /* CBEN_DRAGBEGIN */
+ memset(&nmcbedb, 0, sizeof(nmcbedb));
+ memcpy(nmcbedb.szText, test_w, sizeof(test_w));
+ send_notify(pager, CBEN_DRAGBEGINW, CBEN_DRAGBEGINA, (LPARAM)&nmcbedb, FALSE);
+ ok(!lstrcmpW(nmcbedb.szText, test_w), "Expect %s, got %s\n",
wine_dbgstr_w(test_w), wine_dbgstr_w(nmcbedb.szText));
+
+ /* CBEN_ENDEDIT */
+ memset(&nmcbeed, 0, sizeof(nmcbeed));
+ memcpy(nmcbeed.szText, test_w, sizeof(test_w));
+ send_notify(pager, CBEN_ENDEDITW, CBEN_ENDEDITA, (LPARAM)&nmcbeed, FALSE);
+ ok(!lstrcmpW(nmcbeed.szText, test_w), "Expect %s, got %s\n",
wine_dbgstr_w(test_w), wine_dbgstr_w(nmcbeed.szText));
+}
+
+static void test_wm_notify_datetime(HWND pager)
+{
+ const struct notify_test_datetime_format *data;
+ NMDATETIMEFORMATW nmdtf;
+ INT i;
+
+ for (i = 0; i < ARRAY_SIZE(test_datetime_format_data); i++)
+ {
+ data = test_datetime_format_data + i;
+ notify_test_info.sub_test_id = i;
+
+ memset(&nmdtf, 0, sizeof(nmdtf));
+ if(data->send_pszformat) nmdtf.pszFormat = data->send_pszformat;
+ nmdtf.pszDisplay = nmdtf.szDisplay;
+ send_notify(pager, DTN_FORMATW, DTN_FORMATA, (LPARAM)&nmdtf, TRUE);
+ if (data->return_szdisplay)
+ ok(!lstrcmpW(nmdtf.szDisplay, data->return_szdisplay), "Sub test %d
expect %s, got %s\n", i,
+ wine_dbgstr_w(data->return_szdisplay),
wine_dbgstr_w(nmdtf.szDisplay));
+ if (data->return_pszdisplay)
+ ok(!lstrcmpW(nmdtf.pszDisplay, data->return_pszdisplay), "Sub test %d
expect %s, got %s\n", i,
+ wine_dbgstr_w(data->return_pszdisplay),
wine_dbgstr_w(nmdtf.pszDisplay));
+ }
+}
+
+static void test_wm_notify_header(HWND pager)
+{
+ NMHEADERW nmh = {{0}};
+ HDITEMW hdi = {0};
+ HD_TEXTFILTERW hdtf = {0};
+
+ hdi.mask = HDI_TEXT | HDI_FILTER;
+ hdi.pszText = test_w;
+ hdtf.pszText = test_w;
+ nmh.pitem = &hdi;
+ nmh.pitem->pvFilter = &hdtf;
+ send_notify(pager, HDN_BEGINDRAG, HDN_BEGINDRAG, (LPARAM)&nmh, TRUE);
+ send_notify(pager, HDN_ENDDRAG, HDN_ENDDRAG, (LPARAM)&nmh, TRUE);
+ send_notify(pager, HDN_BEGINFILTEREDIT, HDN_BEGINFILTEREDIT, (LPARAM)&nmh,
TRUE);
+ send_notify(pager, HDN_ENDFILTEREDIT, HDN_ENDFILTEREDIT, (LPARAM)&nmh, TRUE);
+ send_notify(pager, HDN_DROPDOWN, HDN_DROPDOWN, (LPARAM)&nmh, TRUE);
+ send_notify(pager, HDN_FILTERCHANGE, HDN_FILTERCHANGE, (LPARAM)&nmh, TRUE);
+ send_notify(pager, HDN_ITEMKEYDOWN, HDN_ITEMKEYDOWN, (LPARAM)&nmh, TRUE);
+ send_notify(pager, HDN_ITEMSTATEICONCLICK, HDN_ITEMSTATEICONCLICK, (LPARAM)&nmh,
TRUE);
+ send_notify(pager, HDN_OVERFLOWCLICK, HDN_OVERFLOWCLICK, (LPARAM)&nmh, TRUE);
+ send_notify(pager, HDN_BEGINTRACKW, HDN_BEGINTRACKA, (LPARAM)&nmh, TRUE);
+ send_notify(pager, HDN_DIVIDERDBLCLICKW, HDN_DIVIDERDBLCLICKA, (LPARAM)&nmh,
TRUE);
+ send_notify(pager, HDN_ENDTRACKW, HDN_ENDTRACKA, (LPARAM)&nmh, TRUE);
+ send_notify(pager, HDN_ITEMCHANGEDW, HDN_ITEMCHANGEDA, (LPARAM)&nmh, TRUE);
+ send_notify(pager, HDN_ITEMCHANGINGW, HDN_ITEMCHANGINGA, (LPARAM)&nmh, TRUE);
+ send_notify(pager, HDN_ITEMCLICKW, HDN_ITEMCLICKA, (LPARAM)&nmh, TRUE);
+ send_notify(pager, HDN_ITEMDBLCLICKW, HDN_ITEMDBLCLICKA, (LPARAM)&nmh, TRUE);
+ send_notify(pager, HDN_TRACKW, HDN_TRACKA, (LPARAM)&nmh, TRUE);
+}
+
+static void test_wm_notify_tooltip(HWND pager)
+{
+ NMTTDISPINFOW nmttdi;
+ const struct notify_test_tooltip *data;
+ INT i;
+
+ for (i = 0; i < ARRAY_SIZE(test_tooltip_data); i++)
+ {
+ data = test_tooltip_data + i;
+ notify_test_info.sub_test_id = i;
+
+ memset(&nmttdi, 0, sizeof(nmttdi));
+ if (data->send_sztext) memcpy(nmttdi.szText, data->send_sztext,
data->send_sztext_size);
+ if (data->send_lpsztext) nmttdi.lpszText = data->send_lpsztext;
+ send_notify(pager, TTN_GETDISPINFOW, TTN_GETDISPINFOA, (LPARAM)&nmttdi,
FALSE);
+ if (data->return_sztext)
+ {
+ if (data->return_sztext_size == -1)
+ ok(!lstrcmpW(nmttdi.szText, data->return_sztext), "Sub test %d
expect %s, got %s\n", i,
+ wine_dbgstr_w(data->return_sztext), wine_dbgstr_w(nmttdi.szText));
+ else
+ ok(!memcmp(nmttdi.szText, data->return_sztext,
data->return_sztext_size), "Wrong szText content\n");
+ }
+ if (data->return_lpsztext)
+ {
+ if (IS_INTRESOURCE(data->return_lpsztext))
+ ok(nmttdi.lpszText == data->return_lpsztext, "Sub test %d expect
%s, got %s\n", i,
+ wine_dbgstr_w(data->return_lpsztext),
wine_dbgstr_w(nmttdi.lpszText));
+ else
+ ok(!lstrcmpW(nmttdi.lpszText, data->return_lpsztext), "Test %d
expect %s, got %s\n", i,
+ wine_dbgstr_w(data->return_lpsztext),
wine_dbgstr_w(nmttdi.lpszText));
+ }
+ if (data->return_hinst)
+ ok(nmttdi.hinst == data->return_hinst, "Sub test %d expect %p, got
%p\n", i, data->return_hinst,
+ nmttdi.hinst);
+ }
+}
+
+static void test_wm_notify(void)
+{
+ static const CHAR *class = "Pager notify class";
+ HWND parent, pager;
+ /* Combo Box Ex */
+ static NMCOMBOBOXEXW nmcbe;
+ /* Date and Time Picker */
+ static NMDATETIMEFORMATQUERYW nmdtfq;
+ static NMDATETIMEWMKEYDOWNW nmdtkd;
+ static NMDATETIMESTRINGW nmdts;
+ /* Header */
+ static NMHDDISPINFOW nmhddi;
+ /* List View */
+ static NMLVDISPINFOW nmlvdi;
+ static NMLVGETINFOTIPW nmlvgit;
+ static NMLVFINDITEMW nmlvfi;
+ /* Tool Bar */
+ static NMTBRESTORE nmtbr;
+ static NMTBSAVE nmtbs;
+ static NMTOOLBARW nmtb;
+ static NMTBDISPINFOW nmtbdi;
+ static NMTBGETINFOTIPW nmtbgit;
+ /* Tree View */
+ static NMTVDISPINFOW nmtvdi;
+ static NMTVGETINFOTIPW nmtvgit;
+ static NMTREEVIEWW nmtv;
+ static const struct generic_text_helper_para paras[] =
+ {
+ /* Combo Box Ex */
+ {&nmcbe, sizeof(nmcbe), &nmcbe.ceItem.mask, CBEIF_TEXT,
&nmcbe.ceItem.pszText, &nmcbe.ceItem.cchTextMax,
+ CBEN_INSERTITEM, CBEN_INSERTITEM, DONT_CONVERT_SEND | DONT_CONVERT_RECEIVE},
+ {&nmcbe, sizeof(nmcbe), &nmcbe.ceItem.mask, CBEIF_TEXT,
&nmcbe.ceItem.pszText, &nmcbe.ceItem.cchTextMax,
+ CBEN_DELETEITEM, CBEN_DELETEITEM, DONT_CONVERT_SEND | DONT_CONVERT_RECEIVE},
+ {&nmcbe, sizeof(nmcbe), &nmcbe.ceItem.mask, CBEIF_TEXT,
&nmcbe.ceItem.pszText, &nmcbe.ceItem.cchTextMax,
+ CBEN_GETDISPINFOW, CBEN_GETDISPINFOA, ZERO_SEND | SET_NULL_IF_NO_MASK |
DONT_CONVERT_SEND | CONVERT_RECEIVE},
+ /* Date and Time Picker */
+ {&nmdtfq, sizeof(nmdtfq), NULL, 0, (WCHAR **)&nmdtfq.pszFormat, NULL,
DTN_FORMATQUERYW, DTN_FORMATQUERYA,
+ CONVERT_SEND},
+ {&nmdtkd, sizeof(nmdtkd), NULL, 0, (WCHAR **)&nmdtkd.pszFormat, NULL,
DTN_WMKEYDOWNW, DTN_WMKEYDOWNA,
+ CONVERT_SEND},
+ {&nmdts, sizeof(nmdts), NULL, 0, (WCHAR **)&nmdts.pszUserString, NULL,
DTN_USERSTRINGW, DTN_USERSTRINGA,
+ CONVERT_SEND},
+ /* Header */
+ {&nmhddi, sizeof(nmhddi), &nmhddi.mask, HDI_TEXT, &nmhddi.pszText,
&nmhddi.cchTextMax, HDN_GETDISPINFOW,
+ HDN_GETDISPINFOA, SEND_EMPTY_IF_NULL | CONVERT_SEND | CONVERT_RECEIVE},
+ /* List View */
+ {&nmlvfi, sizeof(nmlvfi), &nmlvfi.lvfi.flags, LVFI_STRING, (WCHAR
**)&nmlvfi.lvfi.psz, NULL,
+ LVN_INCREMENTALSEARCHW, LVN_INCREMENTALSEARCHA, CONVERT_SEND},
+ {&nmlvfi, sizeof(nmlvfi), &nmlvfi.lvfi.flags, LVFI_SUBSTRING, (WCHAR
**)&nmlvfi.lvfi.psz, NULL, LVN_ODFINDITEMW,
+ LVN_ODFINDITEMA, CONVERT_SEND},
+ {&nmlvdi, sizeof(nmlvdi), &nmlvdi.item.mask, LVIF_TEXT,
&nmlvdi.item.pszText, &nmlvdi.item.cchTextMax,
+ LVN_BEGINLABELEDITW, LVN_BEGINLABELEDITA, SET_NULL_IF_NO_MASK | CONVERT_SEND |
CONVERT_RECEIVE},
+ {&nmlvdi, sizeof(nmlvdi), &nmlvdi.item.mask, LVIF_TEXT,
&nmlvdi.item.pszText, &nmlvdi.item.cchTextMax,
+ LVN_ENDLABELEDITW, LVN_ENDLABELEDITA, SET_NULL_IF_NO_MASK | CONVERT_SEND |
CONVERT_RECEIVE},
+ {&nmlvdi, sizeof(nmlvdi), &nmlvdi.item.mask, LVIF_TEXT,
&nmlvdi.item.pszText, &nmlvdi.item.cchTextMax,
+ LVN_GETDISPINFOW, LVN_GETDISPINFOA, DONT_CONVERT_SEND | CONVERT_RECEIVE},
+ {&nmlvdi, sizeof(nmlvdi), &nmlvdi.item.mask, LVIF_TEXT,
&nmlvdi.item.pszText, &nmlvdi.item.cchTextMax,
+ LVN_SETDISPINFOW, LVN_SETDISPINFOA, SET_NULL_IF_NO_MASK | CONVERT_SEND |
CONVERT_RECEIVE},
+ {&nmlvgit, sizeof(nmlvgit), NULL, 0, &nmlvgit.pszText,
&nmlvgit.cchTextMax, LVN_GETINFOTIPW, LVN_GETINFOTIPA,
+ CONVERT_SEND | CONVERT_RECEIVE},
+ /* Tool Bar */
+ {&nmtbs, sizeof(nmtbs), NULL, 0, (WCHAR **)&nmtbs.tbButton.iString, NULL,
TBN_SAVE, TBN_SAVE,
+ DONT_CONVERT_SEND | DONT_CONVERT_RECEIVE},
+ {&nmtbr, sizeof(nmtbr), NULL, 0, (WCHAR **)&nmtbr.tbButton.iString, NULL,
TBN_RESTORE, TBN_RESTORE,
+ DONT_CONVERT_SEND | DONT_CONVERT_RECEIVE},
+ {&nmtbdi, sizeof(nmtbdi), &nmtbdi.dwMask, TBNF_TEXT, &nmtbdi.pszText,
&nmtbdi.cchText, TBN_GETDISPINFOW,
+ TBN_GETDISPINFOW, DONT_CONVERT_SEND | DONT_CONVERT_RECEIVE},
+ {&nmtb, sizeof(nmtb), NULL, 0, &nmtb.pszText, &nmtb.cchText,
TBN_GETBUTTONINFOW, TBN_GETBUTTONINFOA,
+ SEND_EMPTY_IF_NULL | CONVERT_SEND | CONVERT_RECEIVE},
+ {&nmtbgit, sizeof(nmtbgit), NULL, 0, &nmtbgit.pszText,
&nmtbgit.cchTextMax, TBN_GETINFOTIPW, TBN_GETINFOTIPA,
+ DONT_CONVERT_SEND | CONVERT_RECEIVE},
+ /* Tree View */
+ {&nmtvdi, sizeof(nmtvdi), &nmtvdi.item.mask, TVIF_TEXT,
&nmtvdi.item.pszText, &nmtvdi.item.cchTextMax,
+ TVN_BEGINLABELEDITW, TVN_BEGINLABELEDITA, SET_NULL_IF_NO_MASK | CONVERT_SEND |
CONVERT_RECEIVE},
+ {&nmtvdi, sizeof(nmtvdi), &nmtvdi.item.mask, TVIF_TEXT,
&nmtvdi.item.pszText, &nmtvdi.item.cchTextMax,
+ TVN_ENDLABELEDITW, TVN_ENDLABELEDITA, SET_NULL_IF_NO_MASK | CONVERT_SEND |
CONVERT_RECEIVE},
+ {&nmtvdi, sizeof(nmtvdi), &nmtvdi.item.mask, TVIF_TEXT,
&nmtvdi.item.pszText, &nmtvdi.item.cchTextMax,
+ TVN_GETDISPINFOW, TVN_GETDISPINFOA, ZERO_SEND | DONT_CONVERT_SEND|
CONVERT_RECEIVE},
+ {&nmtvdi, sizeof(nmtvdi), &nmtvdi.item.mask, TVIF_TEXT,
&nmtvdi.item.pszText, &nmtvdi.item.cchTextMax,
+ TVN_SETDISPINFOW, TVN_SETDISPINFOA, SET_NULL_IF_NO_MASK | CONVERT_SEND |
CONVERT_RECEIVE},
+ {&nmtvgit, sizeof(nmtvgit), NULL, 0, &nmtvgit.pszText,
&nmtvgit.cchTextMax, TVN_GETINFOTIPW, TVN_GETINFOTIPA,
+ DONT_CONVERT_SEND | CONVERT_RECEIVE},
+ {&nmtv, sizeof(nmtv), &nmtv.itemNew.mask, TVIF_TEXT,
&nmtv.itemNew.pszText, &nmtv.itemNew.cchTextMax,
+ TVN_SINGLEEXPAND, TVN_SINGLEEXPAND, DONT_CONVERT_SEND | DONT_CONVERT_RECEIVE,
TVITEM_NEW_HANDLER},
+ {&nmtv, sizeof(nmtv), &nmtv.itemOld.mask, TVIF_TEXT,
&nmtv.itemOld.pszText, &nmtv.itemOld.cchTextMax,
+ TVN_SINGLEEXPAND, TVN_SINGLEEXPAND, DONT_CONVERT_SEND | DONT_CONVERT_RECEIVE,
TVITEM_OLD_HANDLER},
+ {&nmtv, sizeof(nmtv), &nmtv.itemNew.mask, TVIF_TEXT,
&nmtv.itemNew.pszText, &nmtv.itemNew.cchTextMax,
+ TVN_BEGINDRAGW, TVN_BEGINDRAGA, CONVERT_SEND, TVITEM_NEW_HANDLER},
+ {&nmtv, sizeof(nmtv), &nmtv.itemOld.mask, TVIF_TEXT,
&nmtv.itemOld.pszText, &nmtv.itemOld.cchTextMax,
+ TVN_BEGINDRAGW, TVN_BEGINDRAGA, DONT_CONVERT_SEND, TVITEM_OLD_HANDLER},
+ {&nmtv, sizeof(nmtv), &nmtv.itemNew.mask, TVIF_TEXT,
&nmtv.itemNew.pszText, &nmtv.itemNew.cchTextMax,
+ TVN_BEGINRDRAGW, TVN_BEGINRDRAGA, CONVERT_SEND, TVITEM_NEW_HANDLER},
+ {&nmtv, sizeof(nmtv), &nmtv.itemOld.mask, TVIF_TEXT,
&nmtv.itemOld.pszText, &nmtv.itemOld.cchTextMax,
+ TVN_BEGINRDRAGW, TVN_BEGINRDRAGA, DONT_CONVERT_SEND, TVITEM_OLD_HANDLER},
+ {&nmtv, sizeof(nmtv), &nmtv.itemNew.mask, TVIF_TEXT,
&nmtv.itemNew.pszText, &nmtv.itemNew.cchTextMax,
+ TVN_ITEMEXPANDEDW, TVN_ITEMEXPANDEDA, CONVERT_SEND, TVITEM_NEW_HANDLER},
+ {&nmtv, sizeof(nmtv), &nmtv.itemOld.mask, TVIF_TEXT,
&nmtv.itemOld.pszText, &nmtv.itemOld.cchTextMax,
+ TVN_ITEMEXPANDEDW, TVN_ITEMEXPANDEDA, DONT_CONVERT_SEND, TVITEM_OLD_HANDLER},
+ {&nmtv, sizeof(nmtv), &nmtv.itemNew.mask, TVIF_TEXT,
&nmtv.itemNew.pszText, &nmtv.itemNew.cchTextMax,
+ TVN_ITEMEXPANDINGW, TVN_ITEMEXPANDINGA, CONVERT_SEND, TVITEM_NEW_HANDLER},
+ {&nmtv, sizeof(nmtv), &nmtv.itemOld.mask, TVIF_TEXT,
&nmtv.itemOld.pszText, &nmtv.itemOld.cchTextMax,
+ TVN_ITEMEXPANDINGW, TVN_ITEMEXPANDINGA, DONT_CONVERT_SEND, TVITEM_OLD_HANDLER},
+ {&nmtv, sizeof(nmtv), &nmtv.itemNew.mask, TVIF_TEXT,
&nmtv.itemNew.pszText, &nmtv.itemNew.cchTextMax,
+ TVN_DELETEITEMW, TVN_DELETEITEMA, DONT_CONVERT_SEND, TVITEM_NEW_HANDLER},
+ {&nmtv, sizeof(nmtv), &nmtv.itemOld.mask, TVIF_TEXT,
&nmtv.itemOld.pszText, &nmtv.itemOld.cchTextMax,
+ TVN_DELETEITEMW, TVN_DELETEITEMA, CONVERT_SEND, TVITEM_OLD_HANDLER},
+ {&nmtv, sizeof(nmtv), &nmtv.itemNew.mask, TVIF_TEXT,
&nmtv.itemNew.pszText, &nmtv.itemNew.cchTextMax,
+ TVN_SELCHANGINGW, TVN_SELCHANGINGA, CONVERT_SEND, TVITEM_NEW_HANDLER},
+ {&nmtv, sizeof(nmtv), &nmtv.itemOld.mask, TVIF_TEXT,
&nmtv.itemOld.pszText, &nmtv.itemOld.cchTextMax,
+ TVN_SELCHANGINGW, TVN_SELCHANGINGA, CONVERT_SEND, TVITEM_OLD_HANDLER},
+ {&nmtv, sizeof(nmtv), &nmtv.itemNew.mask, TVIF_TEXT,
&nmtv.itemNew.pszText, &nmtv.itemNew.cchTextMax,
+ TVN_SELCHANGEDW, TVN_SELCHANGEDA, CONVERT_SEND, TVITEM_NEW_HANDLER},
+ {&nmtv, sizeof(nmtv), &nmtv.itemOld.mask, TVIF_TEXT,
&nmtv.itemOld.pszText, &nmtv.itemOld.cchTextMax,
+ TVN_SELCHANGEDW, TVN_SELCHANGEDA, CONVERT_SEND, TVITEM_OLD_HANDLER}
+ };
+ INT i;
+
+ ok(register_test_notify_class(), "Register test class failed, error
0x%08x\n", GetLastError());
+
+ parent = CreateWindowA(class, "parent", WS_OVERLAPPED, 0, 0, 100, 100, 0,
0, GetModuleHandleA(0), 0);
+ ok(parent != NULL, "CreateWindow failed\n");
+ pager = CreateWindowA(WC_PAGESCROLLERA, "pager", WS_CHILD, 0, 0, 100, 100,
parent, 0, GetModuleHandleA(0), 0);
+ ok(pager != NULL, "CreateWindow failed\n");
+ child1_wnd = CreateWindowA(class, "child", WS_CHILD, 0, 0, 100, 100, pager,
(HMENU)1, GetModuleHandleA(0), 0);
+ ok(child1_wnd != NULL, "CreateWindow failed\n");
+ SendMessageW(pager, PGM_SETCHILD, 0, (LPARAM)child1_wnd);
+
+ for (i = 0; i < ARRAY_SIZE(paras); i++)
+ test_notify_generic_text_helper(pager, paras + i);
+
+ /* Tests for those that can't be covered by generic text test helper */
+ test_wm_notify_comboboxex(pager);
+ test_wm_notify_datetime(pager);
+ test_wm_notify_header(pager);
+ test_wm_notify_tooltip(pager);
+
+ DestroyWindow(parent);
+ UnregisterClassA(class, GetModuleHandleA(NULL));
+}
+
+static void init_functions(void)
+{
+ HMODULE mod = LoadLibraryA("comctl32.dll");
+
+#define X(f) p##f = (void*)GetProcAddress(mod, #f);
+ X(InitCommonControlsEx);
+#undef X
pSetWindowSubclass = (void*)GetProcAddress(mod, (LPSTR)410);
+}
+
+START_TEST(pager)
+{
+ INITCOMMONCONTROLSEX iccex;
+
+ init_functions();
+
+ iccex.dwSize = sizeof(iccex);
+ iccex.dwICC = ICC_PAGESCROLLER_CLASS;
+ pInitCommonControlsEx(&iccex);
init_msg_sequences(sequences, NUM_MSG_SEQUENCES);
@@ -345,4 +1332,8 @@ START_TEST(pager)
ok(parent_wnd != NULL, "Failed to create parent window!\n");
test_pager();
+ test_wm_notifyformat();
+ test_wm_notify();
+
+ DestroyWindow(parent_wnd);
}
diff --git a/modules/rostests/winetests/comctl32/progress.c
b/modules/rostests/winetests/comctl32/progress.c
index b911021be0..497cb47d3c 100644
--- a/modules/rostests/winetests/comctl32/progress.c
+++ b/modules/rostests/winetests/comctl32/progress.c
@@ -258,7 +258,7 @@ static void test_PBM_STEPIT(void)
HWND progress;
int i, j;
- for (i = 0; i < sizeof(stepit_tests)/sizeof(stepit_tests[0]); i++)
+ for (i = 0; i < ARRAY_SIZE(stepit_tests); i++)
{
struct stepit_test *test = &stepit_tests[i];
LRESULT ret;
diff --git a/modules/rostests/winetests/comctl32/propsheet.c
b/modules/rostests/winetests/comctl32/propsheet.c
index 25d7cdec89..7d9da3f72b 100644
--- a/modules/rostests/winetests/comctl32/propsheet.c
+++ b/modules/rostests/winetests/comctl32/propsheet.c
@@ -280,7 +280,6 @@ static void test_disableowner(void)
psh.pfnCallback = disableowner_callback;
p = pPropertySheetA(&psh);
- todo_wine
ok(p == 0, "Expected 0, got %ld\n", p);
ok(IsWindowEnabled(parenthwnd) != 0, "parent window should be enabled\n");
DestroyWindow(parenthwnd);
@@ -1147,6 +1146,46 @@ static void test_CreatePropertySheetPage(void)
}
}
+static void test_bad_control_class(void)
+{
+ PROPSHEETPAGEA psp;
+ PROPSHEETHEADERA psh;
+ HPROPSHEETPAGE hpsp;
+ INT_PTR ret;
+
+ memset(&psp, 0, sizeof(psp));
+ psp.dwSize = sizeof(psp);
+ psp.hInstance = GetModuleHandleA(NULL);
+ U(psp).pszTemplate = (LPCSTR)MAKEINTRESOURCE(IDD_PROP_PAGE_BAD_CONTROL);
+ psp.pfnDlgProc = page_dlg_proc;
+
+ hpsp = pCreatePropertySheetPageA(&psp);
+ ok(hpsp != 0, "CreatePropertySheetPage failed\n");
+
+ memset(&psh, 0, sizeof(psh));
+ psh.dwSize = PROPSHEETHEADERA_V1_SIZE;
+ psh.nPages = 1;
+ psh.hwndParent = GetDesktopWindow();
+ U3(psh).phpage = &hpsp;
+
+#ifndef __REACTOS__ /* FIXME: Inspect why this causes a hang */
+ ret = pPropertySheetA(&psh);
+ ok(ret == 0, "got %ld\n", ret);
+#endif
+
+ /* Need to recreate hpsp otherwise the test fails under Windows */
+ hpsp = pCreatePropertySheetPageA(&psp);
+ ok(hpsp != 0, "CreatePropertySheetPage failed\n");
+ U3(psh).phpage = &hpsp;
+
+ psh.dwFlags = PSH_MODELESS;
+ ret = pPropertySheetA(&psh);
+ ok(ret != 0, "got %ld\n", ret);
+
+ ok(IsWindow((HWND)ret), "bad window handle %#lx\n", ret);
+ DestroyWindow((HWND)ret);
+}
+
static void init_functions(void)
{
HMODULE hComCtl32 = LoadLibraryA("comctl32.dll");
@@ -1172,6 +1211,7 @@ START_TEST(propsheet)
init_functions();
+ test_bad_control_class();
test_title();
test_nopage();
test_disableowner();
diff --git a/modules/rostests/winetests/comctl32/rebar.c
b/modules/rostests/winetests/comctl32/rebar.c
index b3e78009f5..501638c758 100644
--- a/modules/rostests/winetests/comctl32/rebar.c
+++ b/modules/rostests/winetests/comctl32/rebar.c
@@ -828,7 +828,7 @@ static DWORD resize_numtests = 0;
RECT r; \
int value; \
const rbresize_test_result_t *res = &resize_results[resize_numtests++]; \
- assert(resize_numtests <= sizeof(resize_results)/sizeof(resize_results[0]));
\
+ assert(resize_numtests <= ARRAY_SIZE(resize_results)); \
GetWindowRect(hRebar, &r); \
MapWindowPoints(HWND_DESKTOP, hMainWnd, (LPPOINT)&r, 2); \
if ((dwStyles[i] & (CCS_NOPARENTALIGN|CCS_NODIVIDER)) == CCS_NOPARENTALIGN)
{\
@@ -855,7 +855,7 @@ static void test_resize(void)
CCS_TOP | WS_BORDER, CCS_NOPARENTALIGN | CCS_NODIVIDER | WS_BORDER, CCS_NORESIZE
| WS_BORDER,
CCS_NOMOVEY | WS_BORDER};
- const int styles_count = sizeof(dwStyles) / sizeof(dwStyles[0]);
+ const int styles_count = ARRAY_SIZE(dwStyles);
int i;
for (i = 0; i < styles_count; i++)
diff --git a/modules/rostests/winetests/comctl32/resources.h
b/modules/rostests/winetests/comctl32/resources.h
index 3a89cd7baf..53522c0a09 100644
--- a/modules/rostests/winetests/comctl32/resources.h
+++ b/modules/rostests/winetests/comctl32/resources.h
@@ -39,6 +39,7 @@
#define IDD_PROP_PAGE_WITH_CUSTOM_DEFAULT_BUTTON 34
#define IDD_PROP_PAGE_MESSAGE_TEST 35
#define IDD_PROP_PAGE_ERROR 36
+#define IDD_PROP_PAGE_BAD_CONTROL 37
#define IDC_PS_EDIT1 1000
#define IDC_PS_EDIT2 1001
diff --git a/modules/rostests/winetests/comctl32/rsrc.rc
b/modules/rostests/winetests/comctl32/rsrc.rc
index 327aa225e1..6eb4fe8a0a 100644
--- a/modules/rostests/winetests/comctl32/rsrc.rc
+++ b/modules/rostests/winetests/comctl32/rsrc.rc
@@ -78,6 +78,13 @@ FONT 8, "MS Shell Dlg"
{
}
+IDD_PROP_PAGE_BAD_CONTROL DIALOG 0, 0, 100, 100
+STYLE WS_POPUP | WS_CAPTION | WS_CLIPSIBLINGS | WS_VISIBLE
+FONT 8, "MS Shell Dlg"
+{
+ CONTROL "", -1, "invalid class", 0, 0, 0, 0, 0
+}
+
STRINGTABLE
{
IDS_TBADD1 "abc"
diff --git a/modules/rostests/winetests/comctl32/status.c
b/modules/rostests/winetests/comctl32/status.c
index 2308974761..c7d9989218 100644
--- a/modules/rostests/winetests/comctl32/status.c
+++ b/modules/rostests/winetests/comctl32/status.c
@@ -127,7 +127,7 @@ static int CALLBACK check_height_font_enumproc(ENUMLOGFONTEXA *enumlf,
NEWTEXTME
if (type != TRUETYPE_FONTTYPE)
facename = enumlf->elfLogFont.lfFaceName;
- for (i = 0; i < sizeof(sizes)/sizeof(sizes[0]); i++)
+ for (i = 0; i < ARRAY_SIZE(sizes); i++)
{
HFONT hFont;
TEXTMETRICA tm;
@@ -586,6 +586,131 @@ static void test_notify(void)
ok(g_got_contextmenu, "WM_RBUTTONUP did not activate the context
menu!\n");
}
+static void test_sizegrip(void)
+{
+ HWND hwndStatus;
+ LONG style;
+ RECT rc, rcClient;
+ POINT pt;
+ int width, r;
+
+ hwndStatus = CreateWindowA(SUBCLASS_NAME, "",
WS_CHILD|WS_VISIBLE|SBARS_SIZEGRIP,
+ 0, 0, 100, 100, g_hMainWnd, NULL, NULL, NULL);
+
+ style = GetWindowLongPtrA(g_hMainWnd, GWL_STYLE);
+ width = GetSystemMetrics(SM_CXVSCROLL);
+
+ GetClientRect(hwndStatus, &rcClient);
+
+ pt.x = rcClient.right;
+ pt.y = rcClient.top;
+ ClientToScreen(hwndStatus, &pt);
+ rc.left = pt.x - width;
+ rc.right = pt.x;
+ rc.top = pt.y;
+
+ pt.y = rcClient.bottom;
+ ClientToScreen(hwndStatus, &pt);
+ rc.bottom = pt.y;
+
+ /* check bounds when not maximized */
+ r = SendMessageA(hwndStatus, WM_NCHITTEST, 0, MAKELPARAM(rc.left, rc.top));
+ expect(HTBOTTOMRIGHT, r);
+ r = SendMessageA(hwndStatus, WM_NCHITTEST, 0, MAKELPARAM(rc.left - 1, rc.top));
+ expect(HTCLIENT, r);
+ r = SendMessageA(hwndStatus, WM_NCHITTEST, 0, MAKELPARAM(rc.left, rc.top - 1));
+ expect(HTBOTTOMRIGHT, r);
+ r = SendMessageA(hwndStatus, WM_NCHITTEST, 0, MAKELPARAM(rc.right, rc.bottom));
+ expect(HTBOTTOMRIGHT, r);
+ r = SendMessageA(hwndStatus, WM_NCHITTEST, 0, MAKELPARAM(rc.right + 1, rc.bottom));
+ expect(HTBOTTOMRIGHT, r);
+ r = SendMessageA(hwndStatus, WM_NCHITTEST, 0, MAKELPARAM(rc.right, rc.bottom + 1));
+ expect(HTBOTTOMRIGHT, r);
+ r = SendMessageA(hwndStatus, WM_NCHITTEST, 0, MAKELPARAM(rc.right - 1, rc.bottom -
1));
+ expect(HTBOTTOMRIGHT, r);
+
+ /* not maximized and right-to-left */
+ SetWindowLongA(hwndStatus, GWL_EXSTYLE, WS_EX_LAYOUTRTL);
+
+ pt.x = rcClient.right;
+ ClientToScreen(hwndStatus, &pt);
+ rc.left = pt.x + width;
+ rc.right = pt.x;
+
+ r = SendMessageA(hwndStatus, WM_NCHITTEST, 0, MAKELPARAM(rc.left, rc.top));
+ expect(HTBOTTOMLEFT, r);
+ r = SendMessageA(hwndStatus, WM_NCHITTEST, 0, MAKELPARAM(rc.left + 1, rc.top));
+ expect(HTCLIENT, r);
+ r = SendMessageA(hwndStatus, WM_NCHITTEST, 0, MAKELPARAM(rc.left, rc.top - 1));
+ expect(HTBOTTOMLEFT, r);
+ r = SendMessageA(hwndStatus, WM_NCHITTEST, 0, MAKELPARAM(rc.right, rc.bottom));
+ expect(HTBOTTOMLEFT, r);
+ r = SendMessageA(hwndStatus, WM_NCHITTEST, 0, MAKELPARAM(rc.right - 1, rc.bottom));
+ expect(HTBOTTOMLEFT, r);
+ r = SendMessageA(hwndStatus, WM_NCHITTEST, 0, MAKELPARAM(rc.right, rc.bottom + 1));
+ expect(HTBOTTOMLEFT, r);
+ r = SendMessageA(hwndStatus, WM_NCHITTEST, 0, MAKELPARAM(rc.right + 1, rc.bottom -
1));
+ expect(HTBOTTOMLEFT, r);
+
+ /* maximize with left-to-right */
+ SetWindowLongA(g_hMainWnd, GWL_STYLE, style|WS_MAXIMIZE);
+ SetWindowLongA(hwndStatus, GWL_EXSTYLE, 0);
+
+ GetClientRect(hwndStatus, &rcClient);
+
+ pt.x = rcClient.right;
+ pt.y = rcClient.top;
+ ClientToScreen(hwndStatus, &pt);
+ rc.left = pt.x - width;
+ rc.right = pt.x;
+ rc.top = pt.y;
+
+ pt.y = rcClient.bottom;
+ ClientToScreen(hwndStatus, &pt);
+ rc.bottom = pt.y;
+
+ r = SendMessageA(hwndStatus, WM_NCHITTEST, 0, MAKELPARAM(rc.left, rc.top));
+ expect(HTCLIENT, r);
+ r = SendMessageA(hwndStatus, WM_NCHITTEST, 0, MAKELPARAM(rc.left - 1, rc.top));
+ expect(HTCLIENT, r);
+ r = SendMessageA(hwndStatus, WM_NCHITTEST, 0, MAKELPARAM(rc.left, rc.top - 1));
+ expect(HTNOWHERE, r);
+ r = SendMessageA(hwndStatus, WM_NCHITTEST, 0, MAKELPARAM(rc.right, rc.bottom));
+ expect(HTNOWHERE, r);
+ r = SendMessageA(hwndStatus, WM_NCHITTEST, 0, MAKELPARAM(rc.right + 1, rc.bottom));
+ expect(HTNOWHERE, r);
+ r = SendMessageA(hwndStatus, WM_NCHITTEST, 0, MAKELPARAM(rc.right, rc.bottom + 1));
+ expect(HTNOWHERE, r);
+ r = SendMessageA(hwndStatus, WM_NCHITTEST, 0, MAKELPARAM(rc.right - 1, rc.bottom -
1));
+ expect(HTCLIENT, r);
+
+ /* maximized with right-to-left */
+ SetWindowLongA(hwndStatus, GWL_EXSTYLE, WS_EX_LAYOUTRTL);
+
+ pt.x = rcClient.right;
+ ClientToScreen(hwndStatus, &pt);
+ rc.left = pt.x + width;
+ rc.right = pt.x;
+
+ r = SendMessageA(hwndStatus, WM_NCHITTEST, 0, MAKELPARAM(rc.left, rc.top));
+ expect(HTCLIENT, r);
+ r = SendMessageA(hwndStatus, WM_NCHITTEST, 0, MAKELPARAM(rc.left + 1, rc.top));
+ expect(HTCLIENT, r);
+ r = SendMessageA(hwndStatus, WM_NCHITTEST, 0, MAKELPARAM(rc.left, rc.top - 1));
+ expect(HTNOWHERE, r);
+ r = SendMessageA(hwndStatus, WM_NCHITTEST, 0, MAKELPARAM(rc.right, rc.bottom));
+ expect(HTNOWHERE, r);
+ r = SendMessageA(hwndStatus, WM_NCHITTEST, 0, MAKELPARAM(rc.right - 1, rc.bottom));
+ expect(HTNOWHERE, r);
+ r = SendMessageA(hwndStatus, WM_NCHITTEST, 0, MAKELPARAM(rc.right, rc.bottom + 1));
+ expect(HTNOWHERE, r);
+ r = SendMessageA(hwndStatus, WM_NCHITTEST, 0, MAKELPARAM(rc.right + 1, rc.bottom -
1));
+ expect(HTCLIENT, r);
+
+ SetWindowLongA(g_hMainWnd, GWL_STYLE, style);
+ DestroyWindow(hwndStatus);
+}
+
static void init_functions(void)
{
HMODULE hComCtl32 = LoadLibraryA("comctl32.dll");
@@ -620,4 +745,5 @@ START_TEST(status)
test_status_ownerdraw();
test_gettext();
test_notify();
+ test_sizegrip();
}
diff --git a/modules/rostests/winetests/comctl32/subclass.c
b/modules/rostests/winetests/comctl32/subclass.c
index 75a134352e..41ba06560a 100644
--- a/modules/rostests/winetests/comctl32/subclass.c
+++ b/modules/rostests/winetests/comctl32/subclass.c
@@ -218,46 +218,61 @@ static LRESULT WINAPI wnd_proc_sub(HWND hwnd, UINT message, WPARAM
wParam, LPARA
static void test_subclass(void)
{
+ BOOL ret;
HWND hwnd = CreateWindowExA(0, "TestSubclass", "Test subclass",
WS_OVERLAPPEDWINDOW,
100, 100, 200, 200, 0, 0, 0, NULL);
ok(hwnd != NULL, "failed to create test subclass wnd\n");
- pSetWindowSubclass(hwnd, wnd_proc_sub, 2, 0);
+ ret = pSetWindowSubclass(hwnd, wnd_proc_sub, 2, 0);
+ ok(ret == TRUE, "Expected TRUE\n");
SendMessageA(hwnd, WM_USER, 1, 0);
SendMessageA(hwnd, WM_USER, 2, 0);
ok_sequence(Sub_BasicTest, "Basic");
- pSetWindowSubclass(hwnd, wnd_proc_sub, 2, DELETE_SELF);
+ ret = pSetWindowSubclass(hwnd, wnd_proc_sub, 2, DELETE_SELF);
+ ok(ret == TRUE, "Expected TRUE\n");
SendMessageA(hwnd, WM_USER, 1, 1);
ok_sequence(Sub_DeletedTest, "Deleted");
SendMessageA(hwnd, WM_USER, 1, 0);
ok_sequence(Sub_AfterDeletedTest, "After Deleted");
- pSetWindowSubclass(hwnd, wnd_proc_sub, 2, 0);
+ ret = pSetWindowSubclass(hwnd, wnd_proc_sub, 2, 0);
+ ok(ret == TRUE, "Expected TRUE\n");
orig_proc_3 = (WNDPROC)SetWindowLongPtrA(hwnd, GWLP_WNDPROC, (LONG_PTR)wnd_proc_3);
SendMessageA(hwnd, WM_USER, 1, 0);
SendMessageA(hwnd, WM_USER, 2, 0);
ok_sequence(Sub_OldAfterNewTest, "Old after New");
- pSetWindowSubclass(hwnd, wnd_proc_sub, 4, 0);
+ ret = pSetWindowSubclass(hwnd, wnd_proc_sub, 4, 0);
+ ok(ret == TRUE, "Expected TRUE\n");
SendMessageA(hwnd, WM_USER, 1, 0);
ok_sequence(Sub_MixTest, "Mix");
/* Now the fun starts */
- pSetWindowSubclass(hwnd, wnd_proc_sub, 4, SEND_NEST);
+ ret = pSetWindowSubclass(hwnd, wnd_proc_sub, 4, SEND_NEST);
+ ok(ret == TRUE, "Expected TRUE\n");
SendMessageA(hwnd, WM_USER, 1, 1);
ok_sequence(Sub_MixAndNestTest, "Mix and nest");
- pSetWindowSubclass(hwnd, wnd_proc_sub, 4, SEND_NEST | DELETE_SELF);
+ ret = pSetWindowSubclass(hwnd, wnd_proc_sub, 4, SEND_NEST | DELETE_SELF);
+ ok(ret == TRUE, "Expected TRUE\n");
SendMessageA(hwnd, WM_USER, 1, 1);
ok_sequence(Sub_MixNestDelTest, "Mix, nest, del");
- pSetWindowSubclass(hwnd, wnd_proc_sub, 4, 0);
- pSetWindowSubclass(hwnd, wnd_proc_sub, 5, DELETE_PREV);
+ ret = pSetWindowSubclass(hwnd, wnd_proc_sub, 4, 0);
+ ok(ret == TRUE, "Expected TRUE\n");
+ ret = pSetWindowSubclass(hwnd, wnd_proc_sub, 5, DELETE_PREV);
+ ok(ret == TRUE, "Expected TRUE\n");
SendMessageA(hwnd, WM_USER, 1, 1);
ok_sequence(Sub_MixDelPrevTest, "Mix and del prev");
+ ret = pSetWindowSubclass(NULL, wnd_proc_sub, 1, 0);
+ ok(ret == FALSE, "Expected FALSE\n");
+
+ ret = pSetWindowSubclass(hwnd, NULL, 1, 0);
+ ok(ret == FALSE, "Expected FALSE\n");
+
DestroyWindow(hwnd);
}
diff --git a/modules/rostests/winetests/comctl32/taskdialog.c
b/modules/rostests/winetests/comctl32/taskdialog.c
index 3fcc634e07..35dde1cce5 100644
--- a/modules/rostests/winetests/comctl32/taskdialog.c
+++ b/modules/rostests/winetests/comctl32/taskdialog.c
@@ -29,15 +29,21 @@
#include "v6util.h"
#include "msg.h"
+#ifdef __REACTOS__
+#define WM_KEYF1 0x004d
+#endif
+
#define WM_TD_CALLBACK (WM_APP) /* Custom dummy message to wrap callback notifications
*/
#define NUM_MSG_SEQUENCES 1
#define TASKDIALOG_SEQ_INDEX 0
#define TEST_NUM_BUTTONS 10 /* Number of custom buttons to test with */
+#define TEST_NUM_RADIO_BUTTONS 3
#define ID_START 20 /* Lower IDs might be used by the system */
#define ID_START_BUTTON (ID_START + 0)
+#define ID_START_RADIO_BUTTON (ID_START + 20)
static HRESULT (WINAPI *pTaskDialogIndirect)(const TASKDIALOGCONFIG *, int *, int *, BOOL
*);
static HRESULT (WINAPI *pTaskDialog)(HWND, HINSTANCE, const WCHAR *, const WCHAR *, const
WCHAR *,
@@ -121,6 +127,261 @@ static const struct message_info msg_return_press_custom10[] =
{ 0 }
};
+static const struct message_info msg_send_click_ok[] =
+{
+ { TDM_CLICK_BUTTON, IDOK, 0 },
+ { 0 }
+};
+
+static const struct message_info msg_send_f1[] =
+{
+ { WM_KEYF1, 0, 0, 0},
+ { 0 }
+};
+
+static const struct message_info msg_got_tdn_help[] =
+{
+ { TDN_CREATED, 0, 0, S_OK, msg_send_f1 },
+ { TDN_HELP, 0, 0, S_OK, msg_send_click_ok },
+ { TDN_BUTTON_CLICKED, IDOK, 0, S_OK, NULL },
+ { 0 }
+};
+
+/* Three radio buttons */
+static const struct message_info msg_return_default_radio_button_1[] =
+{
+ { TDN_CREATED, 0, 0, S_OK, NULL },
+ { TDN_RADIO_BUTTON_CLICKED, ID_START_RADIO_BUTTON, 0, S_OK, msg_send_click_ok },
+ { TDN_BUTTON_CLICKED, IDOK, 0, S_OK, NULL },
+ { 0 }
+};
+
+static const struct message_info msg_return_default_radio_button_2[] =
+{
+ { TDN_CREATED, 0, 0, S_OK, NULL },
+ { TDN_RADIO_BUTTON_CLICKED, ID_START_RADIO_BUTTON + 1, 0, S_OK, msg_send_click_ok },
+ { TDN_BUTTON_CLICKED, IDOK, 0, S_OK, NULL },
+ { 0 }
+};
+
+static const struct message_info msg_return_default_radio_button_3[] =
+{
+ { TDN_CREATED, 0, 0, S_OK, NULL },
+ { TDN_RADIO_BUTTON_CLICKED, -2, 0, S_OK, msg_send_click_ok },
+ { TDN_BUTTON_CLICKED, IDOK, 0, S_OK, NULL },
+ { 0 }
+};
+
+static const struct message_info msg_select_first_radio_button[] =
+{
+ { TDM_CLICK_RADIO_BUTTON, ID_START_RADIO_BUTTON, 0 },
+ { 0 }
+};
+
+static const struct message_info msg_return_first_radio_button[] =
+{
+ { TDN_CREATED, 0, 0, S_OK, NULL },
+ { TDN_RADIO_BUTTON_CLICKED, ID_START_RADIO_BUTTON + 1, 0, S_OK,
msg_select_first_radio_button },
+ { TDN_RADIO_BUTTON_CLICKED, ID_START_RADIO_BUTTON, 0, S_OK, msg_send_click_ok },
+ { TDN_BUTTON_CLICKED, IDOK, 0, S_OK, NULL },
+ { 0 }
+};
+
+static const struct message_info msg_select_first_disabled_radio_button_and_press_ok[] =
+{
+ { TDM_ENABLE_RADIO_BUTTON, ID_START_RADIO_BUTTON, 0 },
+ { TDM_CLICK_RADIO_BUTTON, ID_START_RADIO_BUTTON, 0 },
+ { TDM_CLICK_BUTTON, IDOK, 0 },
+ { 0 }
+};
+
+static const struct message_info msg_return_default_radio_button_clicking_disabled[] =
+{
+ { TDN_CREATED, 0, 0, S_OK, NULL },
+ { TDN_RADIO_BUTTON_CLICKED, ID_START_RADIO_BUTTON + 1, 0, S_OK,
msg_select_first_disabled_radio_button_and_press_ok },
+ { TDN_RADIO_BUTTON_CLICKED, ID_START_RADIO_BUTTON, 0, S_OK, NULL },
+ { TDN_BUTTON_CLICKED, IDOK, 0, S_OK, NULL },
+ { 0 }
+};
+
+static const struct message_info msg_return_no_default_radio_button_flag[] =
+{
+ { TDN_CREATED, 0, 0, S_OK, msg_send_click_ok },
+ { TDN_RADIO_BUTTON_CLICKED, ID_START_RADIO_BUTTON, 0, S_OK, NULL },
+ { TDN_BUTTON_CLICKED, IDOK, 0, S_OK, NULL },
+ { 0 }
+};
+
+static const struct message_info msg_return_no_default_radio_button_id_and_flag[] =
+{
+ { TDN_CREATED, 0, 0, S_OK, msg_send_click_ok },
+ { TDN_BUTTON_CLICKED, IDOK, 0, S_OK, NULL },
+ { 0 }
+};
+
+static const struct message_info msg_select_negative_id_radio_button[] =
+{
+ { TDM_CLICK_RADIO_BUTTON, -2, 0 },
+ { 0 }
+};
+
+static const struct message_info msg_return_press_negative_id_radio_button[] =
+{
+ { TDN_CREATED, 0, 0, S_OK, msg_select_negative_id_radio_button },
+ { TDN_RADIO_BUTTON_CLICKED, -2, 0, S_OK, msg_send_click_ok },
+ { TDN_BUTTON_CLICKED, IDOK, 0, S_OK, NULL },
+ { 0 }
+};
+
+static const struct message_info msg_send_all_common_button_click[] =
+{
+ { TDM_CLICK_BUTTON, IDOK, 0 },
+ { TDM_CLICK_BUTTON, IDYES, 0 },
+ { TDM_CLICK_BUTTON, IDNO, 0 },
+ { TDM_CLICK_BUTTON, IDCANCEL, 0 },
+ { TDM_CLICK_BUTTON, IDRETRY, 0 },
+ { TDM_CLICK_BUTTON, IDCLOSE, 0 },
+ { TDM_CLICK_BUTTON, ID_START_BUTTON + 99, 0 },
+ { 0 }
+};
+
+static const struct message_info msg_press_nonexistent_buttons[] =
+{
+ { TDN_CREATED, 0, 0, S_OK, msg_send_all_common_button_click },
+ { TDN_BUTTON_CLICKED, IDOK, 0, S_FALSE, NULL },
+ { TDN_BUTTON_CLICKED, IDYES, 0, S_FALSE, NULL },
+ { TDN_BUTTON_CLICKED, IDNO, 0, S_FALSE, NULL },
+ { TDN_BUTTON_CLICKED, IDCANCEL, 0, S_FALSE, NULL },
+ { TDN_BUTTON_CLICKED, IDRETRY, 0, S_FALSE, NULL },
+ { TDN_BUTTON_CLICKED, IDCLOSE, 0, S_FALSE, NULL },
+ { TDN_BUTTON_CLICKED, ID_START_BUTTON + 99, 0, S_OK, NULL },
+ { 0 }
+};
+
+static const struct message_info msg_send_all_common_button_click_with_command[] =
+{
+ { WM_COMMAND, MAKEWORD(IDOK, BN_CLICKED), 0 },
+ { WM_COMMAND, MAKEWORD(IDYES, BN_CLICKED), 0 },
+ { WM_COMMAND, MAKEWORD(IDNO, BN_CLICKED), 0 },
+ { WM_COMMAND, MAKEWORD(IDCANCEL, BN_CLICKED), 0 },
+ { WM_COMMAND, MAKEWORD(IDRETRY, BN_CLICKED), 0 },
+ { WM_COMMAND, MAKEWORD(IDCLOSE, BN_CLICKED), 0 },
+ { WM_COMMAND, MAKEWORD(ID_START_BUTTON + 99, BN_CLICKED), 0 },
+ { WM_COMMAND, MAKEWORD(IDOK, BN_CLICKED), 0 },
+ { 0 }
+};
+
+static const struct message_info msg_press_nonexistent_buttons_with_command[] =
+{
+ { TDN_CREATED, 0, 0, S_OK, msg_send_all_common_button_click_with_command },
+ { TDN_BUTTON_CLICKED, ID_START_BUTTON, 0, S_FALSE, NULL },
+ { TDN_BUTTON_CLICKED, ID_START_BUTTON, 0, S_OK, NULL },
+ { 0 }
+};
+
+static const struct message_info msg_send_nonexistent_radio_button_click[] =
+{
+ { TDM_CLICK_RADIO_BUTTON, ID_START_RADIO_BUTTON + 99, 0 },
+ { TDM_CLICK_BUTTON, IDOK, 0 },
+ { 0 }
+};
+
+static const struct message_info msg_press_nonexistent_radio_button[] =
+{
+ { TDN_CREATED, 0, 0, S_OK, msg_send_nonexistent_radio_button_click },
+ { TDN_BUTTON_CLICKED, IDOK, 0, S_OK, NULL },
+ { 0 }
+};
+
+static const struct message_info msg_return_default_verification_unchecked[] =
+{
+ { TDN_CREATED, 0, 0, S_OK, msg_send_click_ok },
+ { TDN_BUTTON_CLICKED, IDOK, 0, S_OK, NULL },
+ { 0 }
+};
+
+static const struct message_info msg_return_default_verification_checked[] =
+{
+ { TDN_CREATED, 0, 0, S_OK, msg_send_click_ok },
+ { TDN_BUTTON_CLICKED, IDOK, 0, S_OK, NULL },
+ { 0 }
+};
+
+static const struct message_info msg_uncheck_verification[] =
+{
+ { TDM_CLICK_VERIFICATION, FALSE, 0 },
+ { 0 }
+};
+
+static const struct message_info msg_return_verification_unchecked[] =
+{
+ { TDN_CREATED, 0, 0, S_OK, msg_uncheck_verification },
+ { TDN_VERIFICATION_CLICKED, FALSE, 0, S_OK, msg_send_click_ok },
+ { TDN_BUTTON_CLICKED, IDOK, 0, S_OK, NULL },
+ { 0 }
+};
+
+static const struct message_info msg_check_verification[] =
+{
+ { TDM_CLICK_VERIFICATION, TRUE, 0 },
+ { 0 }
+};
+
+static const struct message_info msg_return_verification_checked[] =
+{
+ { TDN_CREATED, 0, 0, S_OK, msg_check_verification },
+ { TDN_VERIFICATION_CLICKED, TRUE, 0, S_OK, msg_send_click_ok },
+ { TDN_BUTTON_CLICKED, IDOK, 0, S_OK, NULL },
+ { 0 }
+};
+
+static TASKDIALOGCONFIG navigated_info = {0};
+
+static const struct message_info msg_send_navigate[] =
+{
+ { TDM_NAVIGATE_PAGE, 0, (LPARAM)&navigated_info, 0},
+ { 0 }
+};
+
+static const struct message_info msg_return_navigated_page[] =
+{
+ { TDN_CREATED, 0, 0, S_OK, NULL },
+ { TDN_RADIO_BUTTON_CLICKED, ID_START_RADIO_BUTTON, 0, S_OK, msg_send_navigate },
+ { TDN_DIALOG_CONSTRUCTED, 0, 0, S_OK, NULL },
+ { TDN_RADIO_BUTTON_CLICKED, ID_START_RADIO_BUTTON, 0, S_OK, NULL },
+ { TDN_NAVIGATED, 0, 0, S_OK, msg_send_click_ok },
+ { TDN_BUTTON_CLICKED, IDOK, 0, S_OK, NULL },
+ { 0 }
+};
+
+static const struct message_info msg_send_close[] =
+{
+ { WM_CLOSE, 0, 0, 0},
+ { 0 }
+};
+
+static const struct message_info msg_handle_wm_close[] =
+{
+ { TDN_CREATED, 0, 0, S_OK, msg_send_close },
+ { TDN_BUTTON_CLICKED, IDCANCEL, 0, S_FALSE, msg_send_close },
+ { TDN_BUTTON_CLICKED, IDCANCEL, 0, S_OK, NULL },
+ { 0 }
+};
+
+static const struct message_info msg_send_close_then_ok[] =
+{
+ { WM_CLOSE, 0, 0, 0},
+ { TDM_CLICK_BUTTON, IDOK, 0 },
+ { 0 }
+};
+
+static const struct message_info msg_handle_wm_close_without_cancel_button[] =
+{
+ { TDN_CREATED, 0, 0, S_OK, msg_send_close_then_ok },
+ { TDN_BUTTON_CLICKED, IDOK, 0, S_OK, NULL },
+ { 0 }
+};
+
static void init_test_message(UINT message, WPARAM wParam, LPARAM lParam, struct message
*msg)
{
msg->message = WM_TD_CALLBACK;
@@ -131,16 +392,18 @@ static void init_test_message(UINT message, WPARAM wParam, LPARAM
lParam, struct
msg->stage = 0;
}
-#define run_test(info, expect_button, seq, context) \
- run_test_(info, expect_button, seq, context, \
- sizeof(seq)/sizeof(seq[0]) - 1, __FILE__, __LINE__)
+#define run_test(info, expect_button, expect_radio_button, verification_checked, seq,
context) \
+ run_test_(info, expect_button, expect_radio_button, verification_checked, seq,
context, \
+ ARRAY_SIZE(seq) - 1, __FILE__, __LINE__)
-static void run_test_(TASKDIALOGCONFIG *info, int expect_button, const struct
message_info *test_messages,
- const char *context, int test_messages_len, const char *file, int line)
+static void run_test_(TASKDIALOGCONFIG *info, int expect_button, int expect_radio_button,
BOOL verification_checked,
+ const struct message_info *test_messages, const char *context, int
test_messages_len,
+ const char *file, int line)
{
struct message *msg, *msg_start;
int ret_button = 0;
int ret_radio = 0;
+ BOOL ret_verification = FALSE;
HRESULT hr;
int i;
@@ -157,12 +420,14 @@ static void run_test_(TASKDIALOGCONFIG *info, int expect_button,
const struct me
current_message_info = test_messages;
flush_sequences(sequences, NUM_MSG_SEQUENCES);
- hr = pTaskDialogIndirect(info, &ret_button, &ret_radio, NULL);
+ hr = pTaskDialogIndirect(info, &ret_button, &ret_radio,
&ret_verification);
ok_(file, line)(hr == S_OK, "TaskDialogIndirect() failed, got %#x.\n",
hr);
ok_sequence_(sequences, TASKDIALOG_SEQ_INDEX, msg_start, context, FALSE, file,
line);
ok_(file, line)(ret_button == expect_button,
"Wrong button. Expected %d, got %d\n", expect_button,
ret_button);
+ ok_(file, line)(ret_radio == expect_radio_button,
+ "Wrong radio button. Expected %d, got %d\n",
expect_radio_button, ret_radio);
heap_free(msg_start);
}
@@ -220,16 +485,17 @@ static void test_callback(void)
info.pfCallback = taskdialog_callback_proc;
info.lpCallbackData = test_ref_data;
- run_test(&info, IDOK, msg_return_press_ok, "Press VK_RETURN.");
+ run_test(&info, IDOK, 0, FALSE, msg_return_press_ok, "Press
VK_RETURN.");
}
static void test_buttons(void)
{
TASKDIALOGCONFIG info = {0};
-
- TASKDIALOG_BUTTON custom_buttons[TEST_NUM_BUTTONS];
+ static const DWORD command_link_flags[] = {0, TDF_USE_COMMAND_LINKS,
TDF_USE_COMMAND_LINKS_NO_ICON};
+ TASKDIALOG_BUTTON custom_buttons[TEST_NUM_BUTTONS],
radio_buttons[TEST_NUM_RADIO_BUTTONS];
const WCHAR button_format[] = {'%','0','2','d',0};
- WCHAR button_titles[TEST_NUM_BUTTONS * 3]; /* Each button has two digits as title,
plus null-terminator */
+ /* Each button has two digits as title, plus null-terminator */
+ WCHAR button_titles[TEST_NUM_BUTTONS * 3], radio_button_titles[TEST_NUM_BUTTONS *
3];
int i;
info.cbSize = sizeof(TASKDIALOGCONFIG);
@@ -247,48 +513,359 @@ static void test_buttons(void)
}
custom_buttons[TEST_NUM_BUTTONS - 1].nButtonID = -1;
+ /* Init radio buttons */
+ for (i = 0; i < TEST_NUM_RADIO_BUTTONS; i++)
+ {
+ WCHAR *text = &radio_button_titles[i * 3];
+ wsprintfW(text, button_format, i);
+
+ radio_buttons[i].pszButtonText = text;
+ radio_buttons[i].nButtonID = ID_START_RADIO_BUTTON + i;
+ }
+ radio_buttons[TEST_NUM_RADIO_BUTTONS - 1].nButtonID = -2;
+
/* Test nDefaultButton */
/* Test common buttons with invalid default ID */
info.nDefaultButton = 0; /* Should default to first created button */
info.dwCommonButtons = TDCBF_OK_BUTTON | TDCBF_YES_BUTTON | TDCBF_NO_BUTTON
| TDCBF_CANCEL_BUTTON | TDCBF_RETRY_BUTTON | TDCBF_CLOSE_BUTTON;
- run_test(&info, IDOK, msg_return_press_ok, "default button: unset
default");
+ run_test(&info, IDOK, 0, FALSE, msg_return_press_ok, "default button: unset
default");
info.dwCommonButtons = TDCBF_YES_BUTTON | TDCBF_NO_BUTTON
| TDCBF_CANCEL_BUTTON | TDCBF_RETRY_BUTTON | TDCBF_CLOSE_BUTTON;
- run_test(&info, IDYES, msg_return_press_yes, "default button: unset
default");
+ run_test(&info, IDYES, 0, FALSE, msg_return_press_yes, "default button:
unset default");
info.dwCommonButtons = TDCBF_NO_BUTTON | TDCBF_CANCEL_BUTTON | TDCBF_RETRY_BUTTON |
TDCBF_CLOSE_BUTTON;
- run_test(&info, IDNO, msg_return_press_no, "default button: unset
default");
+ run_test(&info, IDNO, 0, FALSE, msg_return_press_no, "default button: unset
default");
info.dwCommonButtons = TDCBF_CANCEL_BUTTON | TDCBF_RETRY_BUTTON |
TDCBF_CLOSE_BUTTON;
- run_test(&info, IDRETRY, msg_return_press_retry, "default button: unset
default");
+ run_test(&info, IDRETRY, 0, FALSE, msg_return_press_retry, "default button:
unset default");
info.dwCommonButtons = TDCBF_CANCEL_BUTTON | TDCBF_CLOSE_BUTTON;
- run_test(&info, IDCANCEL, msg_return_press_cancel, "default button: unset
default");
+ run_test(&info, IDCANCEL, 0, FALSE, msg_return_press_cancel, "default
button: unset default");
+
+ /* Custom buttons could be command links */
+ for (i = 0; i < ARRAY_SIZE(command_link_flags); i++)
+ {
+ info.dwFlags = command_link_flags[i];
+
+ /* Test with all common and custom buttons and invalid default ID */
+ info.nDefaultButton = 0xff; /* Random ID, should also default to first created
button */
+ info.cButtons = TEST_NUM_BUTTONS;
+ info.pButtons = custom_buttons;
+ run_test(&info, ID_START_BUTTON, 0, FALSE, msg_return_press_custom1,
+ "default button: invalid default, with common buttons - 1");
+
+ info.nDefaultButton = -1; /* Should work despite button ID -1 */
+ run_test(&info, -1, 0, FALSE, msg_return_press_custom10, "default
button: invalid default, with common buttons - 2");
+
+ info.nDefaultButton = -2; /* Should also default to first created button */
+ run_test(&info, ID_START_BUTTON, 0, FALSE, msg_return_press_custom1,
+ "default button: invalid default, with common buttons - 3");
+
+ /* Test with only custom buttons and invalid default ID */
+ info.dwCommonButtons = 0;
+ run_test(&info, ID_START_BUTTON, 0, FALSE, msg_return_press_custom1,
+ "default button: invalid default, no common buttons");
+
+ /* Test with common and custom buttons and valid default ID */
+ info.dwCommonButtons = TDCBF_OK_BUTTON | TDCBF_YES_BUTTON | TDCBF_NO_BUTTON |
TDCBF_CANCEL_BUTTON
+ | TDCBF_RETRY_BUTTON | TDCBF_CLOSE_BUTTON;
+ info.nDefaultButton = IDRETRY;
+ run_test(&info, IDRETRY, 0, FALSE, msg_return_press_retry, "default
button: valid default - 1");
+
+ /* Test with common and custom buttons and valid default ID */
+ info.nDefaultButton = ID_START_BUTTON + 3;
+ run_test(&info, ID_START_BUTTON + 3, 0, FALSE, msg_return_press_custom4,
"default button: valid default - 2");
+ }
- /* Test with all common and custom buttons and invalid default ID */
- info.nDefaultButton = 0xff; /* Random ID, should also default to first created button
*/
+ /* Test radio buttons */
+ info.nDefaultButton = 0;
+ info.cButtons = 0;
+ info.pButtons = 0;
+ info.dwCommonButtons = TDCBF_OK_BUTTON;
+ info.cRadioButtons = TEST_NUM_RADIO_BUTTONS;
+ info.pRadioButtons = radio_buttons;
+
+ /* Test default first radio button */
+ run_test(&info, IDOK, ID_START_RADIO_BUTTON, FALSE,
msg_return_default_radio_button_1,
+ "default radio button: default first radio button");
+
+ /* Test default radio button */
+ info.nDefaultRadioButton = ID_START_RADIO_BUTTON + 1;
+ run_test(&info, IDOK, info.nDefaultRadioButton, FALSE,
msg_return_default_radio_button_2,
+ "default radio button: default radio button");
+
+ /* Test default radio button with -2 */
+ info.nDefaultRadioButton = -2;
+ run_test(&info, IDOK, info.nDefaultRadioButton, FALSE,
msg_return_default_radio_button_3,
+ "default radio button: default radio button with id -2");
+
+ /* Test default radio button after clicking the first, messages still work even radio
button is disabled */
+ info.nDefaultRadioButton = ID_START_RADIO_BUTTON + 1;
+ run_test(&info, IDOK, ID_START_RADIO_BUTTON, FALSE,
msg_return_first_radio_button,
+ "default radio button: radio button after clicking");
+
+ /* Test radio button after disabling and clicking the first */
+ info.nDefaultRadioButton = ID_START_RADIO_BUTTON + 1;
+ run_test(&info, IDOK, ID_START_RADIO_BUTTON, FALSE,
msg_return_default_radio_button_clicking_disabled,
+ "default radio button: disable radio button before clicking");
+
+ /* Test no default radio button, TDF_NO_DEFAULT_RADIO_BUTTON is set,
TDN_RADIO_BUTTON_CLICKED will still be received, just radio button not selected */
+ info.nDefaultRadioButton = ID_START_RADIO_BUTTON;
+ info.dwFlags = TDF_NO_DEFAULT_RADIO_BUTTON;
+ run_test(&info, IDOK, info.nDefaultRadioButton, FALSE,
msg_return_no_default_radio_button_flag,
+ "default radio button: no default radio flag");
+
+ /* Test no default radio button, TDF_NO_DEFAULT_RADIO_BUTTON is set and
nDefaultRadioButton is 0.
+ * TDN_RADIO_BUTTON_CLICKED will not be sent, and just radio button not selected */
+ info.nDefaultRadioButton = 0;
+ info.dwFlags = TDF_NO_DEFAULT_RADIO_BUTTON;
+ run_test(&info, IDOK, 0, FALSE, msg_return_no_default_radio_button_id_and_flag,
+ "default radio button: no default radio id and flag");
+
+ /* Test no default radio button, TDF_NO_DEFAULT_RADIO_BUTTON is set and
nDefaultRadioButton is invalid.
+ * TDN_RADIO_BUTTON_CLICKED will not be sent, and just radio button not selected */
+ info.nDefaultRadioButton = 0xff;
+ info.dwFlags = TDF_NO_DEFAULT_RADIO_BUTTON;
+ run_test(&info, IDOK, 0, FALSE, msg_return_no_default_radio_button_id_and_flag,
+ "default radio button: no default flag, invalid id");
+
+ info.nDefaultRadioButton = 0;
+ info.dwFlags = TDF_NO_DEFAULT_RADIO_BUTTON;
+ run_test(&info, IDOK, -2, FALSE, msg_return_press_negative_id_radio_button,
+ "radio button: manually click radio button with negative id");
+
+ /* Test sending clicks to non-existent buttons. Notification of non-existent buttons
will be sent */
info.cButtons = TEST_NUM_BUTTONS;
info.pButtons = custom_buttons;
- run_test(&info, ID_START_BUTTON, msg_return_press_custom1, "default button:
invalid default, with common buttons - 1");
+ info.cRadioButtons = TEST_NUM_RADIO_BUTTONS;
+ info.pRadioButtons = radio_buttons;
+ info.dwCommonButtons = 0;
+ info.dwFlags = TDF_NO_DEFAULT_RADIO_BUTTON;
+ run_test(&info, ID_START_BUTTON + 99, 0, FALSE, msg_press_nonexistent_buttons,
"sends click to non-existent buttons");
- info.nDefaultButton = -1; /* Should work despite button ID -1 */
- run_test(&info, -1, msg_return_press_custom10, "default button: invalid
default, with common buttons - 2");
+ /* Non-existent button clicks sent by WM_COMMAND won't generate
TDN_BUTTON_CLICKED except IDOK.
+ * And will get the first existent button identifier instead of IDOK */
+ run_test(&info, ID_START_BUTTON, 0, FALSE,
msg_press_nonexistent_buttons_with_command,
+ "sends click to non-existent buttons with WM_COMMAND");
- info.nDefaultButton = -2; /* Should also default to first created button */
- run_test(&info, ID_START_BUTTON, msg_return_press_custom1, "default button:
invalid default, with common buttons - 3");
+ /* Non-existent radio button won't get notifications */
+ run_test(&info, IDOK, 0, FALSE, msg_press_nonexistent_radio_button, "sends
click to non-existent radio buttons");
+}
- /* Test with only custom buttons and invalid default ID */
- info.dwCommonButtons = 0;
- run_test(&info, ID_START_BUTTON, msg_return_press_custom1, "default button:
invalid default, no common buttons");
+static void test_help(void)
+{
+ TASKDIALOGCONFIG info = {0};
- /* Test with common and custom buttons and valid default ID */
- info.dwCommonButtons = TDCBF_OK_BUTTON | TDCBF_YES_BUTTON | TDCBF_NO_BUTTON
- | TDCBF_CANCEL_BUTTON | TDCBF_RETRY_BUTTON |
TDCBF_CLOSE_BUTTON;
- info.nDefaultButton = IDRETRY;
- run_test(&info, IDRETRY, msg_return_press_retry, "default button: valid
default - 1");
+ info.cbSize = sizeof(TASKDIALOGCONFIG);
+ info.pfCallback = taskdialog_callback_proc;
+ info.lpCallbackData = test_ref_data;
+ info.dwCommonButtons = TDCBF_OK_BUTTON;
+
+ run_test(&info, IDOK, 0, FALSE, msg_got_tdn_help, "send f1");
+}
+
+struct timer_notification_data
+{
+ DWORD last_elapsed_ms;
+ DWORD num_fired;
+};
+
+static HRESULT CALLBACK taskdialog_callback_proc_timer(HWND hwnd, UINT notification,
+ WPARAM wParam, LPARAM lParam, LONG_PTR ref_data)
+{
+ struct timer_notification_data *data = (struct timer_notification_data *)ref_data;
+
+ if (notification == TDN_TIMER)
+ {
+ DWORD elapsed_ms;
+ int delta;
+
+ elapsed_ms = (DWORD)wParam;
+
+ if (data->num_fired == 3)
+ ok(data->last_elapsed_ms > elapsed_ms, "Expected reference time
update.\n");
+ else
+ {
+ delta = elapsed_ms - data->last_elapsed_ms;
+ ok(delta > 0, "Expected positive time tick difference.\n");
+ }
+ data->last_elapsed_ms = elapsed_ms;
+
+ if (data->num_fired == 3)
+ PostMessageW(hwnd, TDM_CLICK_BUTTON, IDOK, 0);
+
+ ++data->num_fired;
+ return data->num_fired == 3 ? S_FALSE : S_OK;
+ }
+
+ return S_OK;
+}
+
+static void test_timer(void)
+{
+ struct timer_notification_data data = { 0 };
+ TASKDIALOGCONFIG info = { 0 };
+
+ info.cbSize = sizeof(TASKDIALOGCONFIG);
+ info.pfCallback = taskdialog_callback_proc_timer;
+ info.lpCallbackData = (LONG_PTR)&data;
+ info.dwFlags = TDF_CALLBACK_TIMER;
+ info.dwCommonButtons = TDCBF_OK_BUTTON;
+
+ pTaskDialogIndirect(&info, NULL, NULL, NULL);
+}
+
+static HRESULT CALLBACK taskdialog_callback_proc_progress_bar(HWND hwnd, UINT
notification, WPARAM wParam,
+ LPARAM lParam, LONG_PTR
ref_data)
+{
+ unsigned long ret;
+ LONG flags = (LONG)ref_data;
+ if (notification == TDN_CREATED)
+ {
+ /* TDM_SET_PROGRESS_BAR_STATE */
+ ret = SendMessageW(hwnd, TDM_SET_PROGRESS_BAR_STATE, PBST_NORMAL, 0);
+ ok(ret == PBST_NORMAL, "Expect state: %d got state: %lx\n",
PBST_NORMAL, ret);
+ ret = SendMessageW(hwnd, TDM_SET_PROGRESS_BAR_STATE, PBST_PAUSED, 0);
+ ok(ret == PBST_NORMAL, "Expect state: %d got state: %lx\n",
PBST_NORMAL, ret);
+ ret = SendMessageW(hwnd, TDM_SET_PROGRESS_BAR_STATE, PBST_ERROR, 0);
+ /* Progress bar has fixme on handling PBM_SETSTATE message */
+ todo_wine ok(ret == PBST_PAUSED, "Expect state: %d got state: %lx\n",
PBST_PAUSED, ret);
+ ret = SendMessageW(hwnd, TDM_SET_PROGRESS_BAR_STATE, PBST_NORMAL, 0);
+ todo_wine ok(ret == PBST_ERROR, "Expect state: %d got state: %lx\n",
PBST_ERROR, ret);
+
+ /* TDM_SET_PROGRESS_BAR_RANGE */
+ ret = SendMessageW(hwnd, TDM_SET_PROGRESS_BAR_RANGE, 0, MAKELPARAM(0, 200));
+ ok(ret == MAKELONG(0, 100), "Expect range:%x got:%lx\n", MAKELONG(0,
100), ret);
+ ret = SendMessageW(hwnd, TDM_SET_PROGRESS_BAR_RANGE, 0, MAKELPARAM(0, 200));
+ ok(ret == MAKELONG(0, 200), "Expect range:%x got:%lx\n", MAKELONG(0,
200), ret);
+
+ /* TDM_SET_PROGRESS_BAR_POS */
+ if (flags & TDF_SHOW_MARQUEE_PROGRESS_BAR)
+ {
+ ret = SendMessageW(hwnd, TDM_SET_PROGRESS_BAR_POS, 1, 0);
+ ok(ret == 0, "Expect position:%x got:%lx\n", 0, ret);
+ ret = SendMessageW(hwnd, TDM_SET_PROGRESS_BAR_POS, 2, 0);
+ ok(ret == 0, "Expect position:%x got:%lx\n", 0, ret);
+ }
+ else
+ {
+ ret = SendMessageW(hwnd, TDM_SET_PROGRESS_BAR_POS, 1, 0);
+ ok(ret == 0, "Expect position:%x got:%lx\n", 0, ret);
+ ret = SendMessageW(hwnd, TDM_SET_PROGRESS_BAR_POS, 2, 0);
+ ok(ret == 1, "Expect position:%x got:%lx\n", 1, ret);
+ }
+
+ SendMessageW(hwnd, TDM_CLICK_BUTTON, IDOK, 0);
+ }
+
+ return S_OK;
+}
+
+static void test_progress_bar(void)
+{
+ TASKDIALOGCONFIG info = {0};
+
+ info.cbSize = sizeof(TASKDIALOGCONFIG);
+ info.dwFlags = TDF_SHOW_PROGRESS_BAR;
+ info.pfCallback = taskdialog_callback_proc_progress_bar;
+ info.lpCallbackData = (LONG_PTR)info.dwFlags;
+ info.dwCommonButtons = TDCBF_OK_BUTTON;
+ pTaskDialogIndirect(&info, NULL, NULL, NULL);
+
+ info.dwFlags = TDF_SHOW_MARQUEE_PROGRESS_BAR;
+ info.lpCallbackData = (LONG_PTR)info.dwFlags;
+ pTaskDialogIndirect(&info, NULL, NULL, NULL);
+
+ info.dwFlags = TDF_SHOW_PROGRESS_BAR | TDF_SHOW_MARQUEE_PROGRESS_BAR;
+ info.lpCallbackData = (LONG_PTR)info.dwFlags;
+ pTaskDialogIndirect(&info, NULL, NULL, NULL);
+}
+
+static void test_verification_box(void)
+{
+ TASKDIALOGCONFIG info = {0};
+ WCHAR textW[] = {'t', 'e', 'x', 't', 0};
+
+ info.cbSize = sizeof(TASKDIALOGCONFIG);
+ info.pfCallback = taskdialog_callback_proc;
+ info.lpCallbackData = test_ref_data;
+ info.dwCommonButtons = TDCBF_OK_BUTTON;
+
+ /* TDF_VERIFICATION_FLAG_CHECKED works even if pszVerificationText is not set */
+ run_test(&info, IDOK, 0, FALSE, msg_return_default_verification_unchecked,
"default verification box: unchecked");
+
+ info.dwFlags = TDF_VERIFICATION_FLAG_CHECKED;
+ run_test(&info, IDOK, 0, FALSE, msg_return_default_verification_checked,
"default verification box: checked");
+
+ info.pszVerificationText = textW;
+ run_test(&info, IDOK, 0, FALSE, msg_return_default_verification_unchecked,
"default verification box: unchecked");
+
+ info.dwFlags = TDF_VERIFICATION_FLAG_CHECKED;
+ run_test(&info, IDOK, 0, FALSE, msg_return_default_verification_checked,
"default verification box: checked");
+
+ run_test(&info, IDOK, 0, FALSE, msg_return_verification_unchecked,
+ "default verification box: default checked and then unchecked");
+
+ info.dwFlags = 0;
+ run_test(&info, IDOK, 0, FALSE, msg_return_verification_checked,
+ "default verification box: default unchecked and then checked");
+}
+
+static void test_navigate_page(void)
+{
+ TASKDIALOGCONFIG info = {0};
+ static const WCHAR textW[] = {'t', 'e', 'x', 't',
0};
+ static const WCHAR button_format[] = {'%', '0', '2',
'd', 0};
+ TASKDIALOG_BUTTON radio_buttons[TEST_NUM_RADIO_BUTTONS];
+ WCHAR radio_button_titles[TEST_NUM_BUTTONS * 3];
+ int i;
+
+ /* Init radio buttons */
+ for (i = 0; i < TEST_NUM_RADIO_BUTTONS; i++)
+ {
+ WCHAR *text = &radio_button_titles[i * 3];
+ wsprintfW(text, button_format, i);
+
+ radio_buttons[i].pszButtonText = text;
+ radio_buttons[i].nButtonID = ID_START_RADIO_BUTTON + i;
+ }
+
+ info.cbSize = sizeof(TASKDIALOGCONFIG);
+ info.pfCallback = taskdialog_callback_proc;
+ info.lpCallbackData = test_ref_data;
+ info.dwCommonButtons = TDCBF_OK_BUTTON;
+ info.cRadioButtons = TEST_NUM_RADIO_BUTTONS;
+ info.pRadioButtons = radio_buttons;
+
+ navigated_info = info;
+ navigated_info.pszVerificationText = textW;
+ navigated_info.dwFlags = TDF_VERIFICATION_FLAG_CHECKED;
+
+ run_test(&info, IDOK, ID_START_RADIO_BUTTON, TRUE, msg_return_navigated_page,
"navigate page: default");
+
+ /* TDM_NAVIGATE_PAGE doesn't check cbSize.
+ * And null taskconfig pointer crash applicatioin, thus doesn't check pointer
either */
+ navigated_info.cbSize = 0;
+ run_test(&info, IDOK, ID_START_RADIO_BUTTON, TRUE, msg_return_navigated_page,
"navigate page: invalid taskconfig cbSize");
+}
+
+static void test_wm_close(void)
+{
+ TASKDIALOGCONFIG info = {0};
+
+ info.cbSize = sizeof(TASKDIALOGCONFIG);
+ info.pfCallback = taskdialog_callback_proc;
+ info.lpCallbackData = test_ref_data;
+
... 537 lines suppressed ...