[PATCH] comctl32/tests: Add some tests for ownerdrawn listbox.
Nikolay Sivov
nsivov at codeweavers.com
Wed Jul 4 05:40:57 CDT 2018
Adapted from user32 tests contributed by Dmitry Timoshkov.
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=42602
Signed-off-by: Nikolay Sivov <nsivov at codeweavers.com>
---
dlls/comctl32/tests/listbox.c | 243 ++++++++++++++++++++++++++++++----
1 file changed, 215 insertions(+), 28 deletions(-)
diff --git a/dlls/comctl32/tests/listbox.c b/dlls/comctl32/tests/listbox.c
index f44fdff77f..790c2c4357 100644
--- a/dlls/comctl32/tests/listbox.c
+++ b/dlls/comctl32/tests/listbox.c
@@ -30,6 +30,51 @@
#include "wine/heap.h"
#include "wine/test.h"
#include "v6util.h"
+#include "msg.h"
+
+enum 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,14 +88,7 @@ static const char * const strings[4] = {
static const char BAD_EXTENSION[] = "*.badtxt";
-static int strcmp_aw(LPCWSTR strw, const char *stra)
-{
- WCHAR buf[1024];
-
- if (!stra) return 1;
- MultiByteToWideChar(CP_ACP, 0, stra, -1, buf, ARRAY_SIZE(buf));
- return lstrcmpW(strw, buf);
-}
+#define ID_LISTBOX 1
static HWND create_listbox(DWORD add_style, HWND parent)
{
@@ -58,7 +96,7 @@ static HWND create_listbox(DWORD add_style, HWND parent)
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);
@@ -234,41 +272,87 @@ 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;
+
+ if (mis->CtlType == ODT_LISTBOX)
+ {
+ HWND ctrl = GetDlgItem(hwnd, mis->CtlID);
+ is_unicode_data = GetWindowLongA(ctrl, GWL_STYLE) & LBS_HASSTRINGS;
+ }
+
+ 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");
+
+ break;
+ }
+ case WM_COMPAREITEM:
+ {
+ COMPAREITEMSTRUCT *cis = (COMPAREITEMSTRUCT *)lParam;
+ HWND ctrl = GetDlgItem(hwnd, cis->CtlID);
+ BOOL is_unicode_data = TRUE;
- 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");
+ ok(wParam == cis->CtlID, "expected %#x, got %#lx\n", cis->CtlID, wParam);
+ ok(cis->hwndItem == ctrl, "expected %p, got %p\n", ctrl, cis->hwndItem);
+todo_wine
+ ok((int)cis->itemID1 >= 0, "expected >= 0, got %d\n", cis->itemID1);
+todo_wine
+ ok((int)cis->itemID2 == -1, "expected -1, got %d\n", cis->itemID2);
- if (mi->itemID > 4 || style & LBS_OWNERDRAWFIXED)
- break;
+ if (cis->CtlType == ODT_LISTBOX)
+ is_unicode_data = GetWindowLongA(ctrl, GWL_STYLE) & LBS_HASSTRINGS;
- if (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 +368,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 )
@@ -1871,10 +1959,34 @@ static void test_listbox(void)
run_test(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 +2000,79 @@ 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");
+todo_wine
+ ok(ret == 1, "expected 1, got %ld\n", ret);
+ ret = SendMessageA(listbox, LB_ADDSTRING, 0, (LPARAM)"item 2");
+todo_wine
+ ok(ret == 2, "expected 2, got %ld\n", ret);
+
+ ok_sequence(sequences, PARENT_SEQ_INDEX, lb_addstring_sort_parent_seq, "LB_ADDSTRING (LBS_SORT)", TRUE);
+ 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);
}
@@ -1899,6 +2084,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();
--
2.18.0
More information about the wine-devel
mailing list