WCHAR buf[1024];
if (!stra) return 1;
- MultiByteToWideChar(CP_ACP, 0, stra, -1, buf, sizeof(buf)/sizeof(WCHAR));
+ MultiByteToWideChar(CP_ACP, 0, stra, -1, buf, ARRAY_SIZE(buf));
return lstrcmpW(strw, buf);
}
};
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;
#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); }
listbox_todo_field_ok(t, s, selcount, got)
static void
-check (const struct listbox_test test)
+check (DWORD style, const struct listbox_test test)
{
struct listbox_stat answer;
- HWND hLB=create_listbox (test.prop.add_style, 0);
RECT second_item;
int i;
int res;
+ HWND hLB;
+
+ hLB = create_listbox (style, 0);
listbox_query (hLB, &answer);
listbox_ok (test, init, answer);
listbox_ok (test, step, answer);
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);
CHAR *txt;
WCHAR *txtw;
txtw = HeapAlloc (GetProcessHeap(), HEAP_ZERO_MEMORY, 2*size+2);
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]), "returned string for item %d does not match %s vs %s\n", i, txt, strings[i]);
HeapFree (GetProcessHeap(), 0, txtw);
HeapFree (GetProcessHeap(), 0, txt);
static void test_ownerdraw(void)
{
+ static const DWORD styles[] =
+ {
+ 0,
+ LBS_NODATA
+ };
HWND parent, hLB;
INT ret;
RECT rc;
+ UINT i;
parent = create_parent();
assert(parent);
- hLB = create_listbox(LBS_OWNERDRAWFIXED | WS_CHILD | WS_VISIBLE, parent);
- assert(hLB);
+ for (i = 0; i < ARRAY_SIZE(styles); i++)
+ {
+ hLB = create_listbox(LBS_OWNERDRAWFIXED | WS_CHILD | WS_VISIBLE | styles[i], parent);
+ assert(hLB);
- 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);
- trace("item 0 rect %s\n", wine_dbgstr_rect(&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);
+ trace("item 0 rect %s\n", wine_dbgstr_rect(&rc));
+ ok(!IsRectEmpty(&rc), "empty item rect\n");
+ ok(rc.top < 0, "rc.top is not negative (%d)\n", rc.top);
- DestroyWindow(hLB);
+ DestroyWindow(hLB);
+
+ /* Both FIXED and VARIABLE, FIXED should override VARIABLE. */
+ hLB = CreateWindowA("listbox", "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(parent);
}
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 window.\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, "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_MULTIPLESEL */
+ hLB = create_listbox(LBS_MULTIPLESEL, 0);
+ ok(hLB != NULL, "Failed to create ListBox window.\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, "Unexpected return value %d.\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;
DestroyWindow( hList );
}
+static void test_changing_selection_styles(void)
+{
+ static const DWORD styles[] =
+ {
+ 0,
+ LBS_NODATA | LBS_OWNERDRAWFIXED
+ };
+ static const DWORD selstyles[] =
+ {
+ 0,
+ LBS_MULTIPLESEL,
+ LBS_EXTENDEDSEL,
+ LBS_MULTIPLESEL | LBS_EXTENDEDSEL
+ };
+ static const LONG selexpect_single[] = { 0, 0, 1 };
+ static const LONG selexpect_single2[] = { 1, 0, 0 };
+ static const LONG selexpect_multi[] = { 1, 0, 1 };
+ static const LONG selexpect_multi2[] = { 1, 1, 0 };
+
+ HWND parent, listbox;
+ DWORD style;
+ LONG ret;
+ UINT i, j, k;
+
+ parent = create_parent();
+ ok(parent != NULL, "Failed to create parent window.\n");
+ for (i = 0; i < ARRAY_SIZE(styles); i++)
+ {
+ /* Test if changing selection styles affects selection storage */
+ for (j = 0; j < ARRAY_SIZE(selstyles); j++)
+ {
+ LONG setcursel_expect, selitemrange_expect, getselcount_expect;
+ const LONG *selexpect;
+
+ listbox = CreateWindowA("listbox", "TestList", styles[i] | selstyles[j] | WS_CHILD | WS_VISIBLE,
+ 0, 0, 100, 100, parent, (HMENU)1, NULL, 0);
+ ok(listbox != NULL, "%u: Failed to create ListBox window.\n", j);
+
+ if (selstyles[j] & (LBS_MULTIPLESEL | LBS_EXTENDEDSEL))
+ {
+ setcursel_expect = LB_ERR;
+ selitemrange_expect = LB_OKAY;
+ getselcount_expect = 2;
+ selexpect = selexpect_multi;
+ }
+ else
+ {
+ setcursel_expect = 2;
+ selitemrange_expect = LB_ERR;
+ getselcount_expect = LB_ERR;
+ selexpect = selexpect_single;
+ }
+
+ for (k = 0; k < ARRAY_SIZE(selexpect_multi); k++)
+ {
+ ret = SendMessageA(listbox, LB_INSERTSTRING, -1, (LPARAM)"x");
+ ok(ret == k, "%u: Unexpected return value %d, expected %d.\n", j, ret, k);
+ }
+ ret = SendMessageA(listbox, LB_GETCOUNT, 0, 0);
+ ok(ret == ARRAY_SIZE(selexpect_multi), "%u: Unexpected count %d.\n", j, ret);
+
+ /* Select items with different methods */
+ ret = SendMessageA(listbox, LB_SETCURSEL, 2, 0);
+ ok(ret == setcursel_expect, "%u: Unexpected return value %d.\n", j, ret);
+ ret = SendMessageA(listbox, LB_SELITEMRANGE, TRUE, MAKELPARAM(0, 0));
+ ok(ret == selitemrange_expect, "%u: Unexpected return value %d.\n", j, ret);
+ ret = SendMessageA(listbox, LB_SELITEMRANGE, TRUE, MAKELPARAM(2, 2));
+ ok(ret == selitemrange_expect, "%u: Unexpected return value %d.\n", j, ret);
+
+ /* Verify that the proper items are selected */
+ for (k = 0; k < ARRAY_SIZE(selexpect_multi); k++)
+ {
+ ret = SendMessageA(listbox, LB_GETSEL, k, 0);
+ ok(ret == selexpect[k], "%u: Unexpected selection state %d, expected %d.\n",
+ j, ret, selexpect[k]);
+ }
+
+ /* Now change the selection style */
+ style = GetWindowLongA(listbox, GWL_STYLE);
+ ok((style & (LBS_MULTIPLESEL | LBS_EXTENDEDSEL)) == selstyles[j],
+ "%u: unexpected window styles %#x.\n", j, style);
+ if (selstyles[j] & (LBS_MULTIPLESEL | LBS_EXTENDEDSEL))
+ style &= ~selstyles[j];
+ else
+ style |= LBS_MULTIPLESEL | LBS_EXTENDEDSEL;
+ SetWindowLongA(listbox, GWL_STYLE, style);
+ style = GetWindowLongA(listbox, GWL_STYLE);
+ ok(!(style & selstyles[j]), "%u: unexpected window styles %#x.\n", j, style);
+
+ /* Verify that the same items are selected */
+ ret = SendMessageA(listbox, LB_GETSELCOUNT, 0, 0);
+ ok(ret == getselcount_expect, "%u: expected %d from LB_GETSELCOUNT, got %d\n",
+ j, getselcount_expect, ret);
+
+ for (k = 0; k < ARRAY_SIZE(selexpect_multi); k++)
+ {
+ ret = SendMessageA(listbox, LB_GETSEL, k, 0);
+ ok(ret == selexpect[k], "%u: Unexpected selection state %d, expected %d.\n",
+ j, ret, selexpect[k]);
+ }
+
+ /* Lastly see if we can still change the selection as before with old style */
+ if (setcursel_expect != LB_ERR) setcursel_expect = 0;
+ ret = SendMessageA(listbox, LB_SETCURSEL, 0, 0);
+ ok(ret == setcursel_expect, "%u: Unexpected return value %d.\n", j, ret);
+ ret = SendMessageA(listbox, LB_SELITEMRANGE, TRUE, MAKELPARAM(1, 1));
+ ok(ret == selitemrange_expect, "%u: Unexpected return value %d.\n", j, ret);
+ ret = SendMessageA(listbox, LB_SELITEMRANGE, FALSE, MAKELPARAM(2, 2));
+ ok(ret == selitemrange_expect, "%u: Unexpected return value %d.\n", j, ret);
+
+ /* And verify the selections */
+ selexpect = (selstyles[j] & (LBS_MULTIPLESEL | LBS_EXTENDEDSEL)) ? selexpect_multi2 : selexpect_single2;
+ ret = SendMessageA(listbox, LB_GETSELCOUNT, 0, 0);
+ ok(ret == getselcount_expect, "%u: expected %d from LB_GETSELCOUNT, got %d\n",
+ j, getselcount_expect, ret);
+
+ for (k = 0; k < ARRAY_SIZE(selexpect_multi); k++)
+ {
+ ret = SendMessageA(listbox, LB_GETSEL, k, 0);
+ ok(ret == selexpect[k], "%u: Unexpected selection state %d, expected %d.\n",
+ j, ret, selexpect[k]);
+ }
+
+ DestroyWindow(listbox);
+ }
+ }
+ DestroyWindow(parent);
+}
+
static void test_itemfrompoint(void)
{
/* WS_POPUP is required in order to have a more accurate size calculation (
static void test_listbox_LB_DIR(void)
{
+ char path[MAX_PATH], curdir[MAX_PATH];
HWND hList;
int res, itemCount;
int itemCount_justFiles;
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());
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 */
DestroyWindow(hList);
DeleteFileA( "wtest1.tmp.c" );
+ RemoveDirectoryA("lb_dir_test");
+
+ SetCurrentDirectoryA(curdir);
}
static HWND g_listBox;
strcpy(pathBuffer, "C:\\");
res = DlgDirListA(hWnd, pathBuffer, ID_TEST_LISTBOX, 0, DDL_DIRECTORY | DDL_EXCLUSIVE);
ok(res || broken(!res) /* NT4/W2K */, "DlgDirList failed to list C:\\ folders\n");
- todo_wine ok(!strcmp(pathBuffer, "*") || broken(!res) /* NT4/W2K */,
+ ok(!strcmp(pathBuffer, "*") || broken(!res) /* NT4/W2K */,
"DlgDirList set the invalid path spec '%s', expected '*'\n", pathBuffer);
strcpy(pathBuffer, "C:\\*");
SetLastError(0xdeadbeef);
strcpy(pathBuffer, "C:\\INVALID$$DIR");
res = DlgDirListA(hWnd, pathBuffer, ID_TEST_LISTBOX, 0, DDL_DIRECTORY | DDL_EXCLUSIVE);
- todo_wine ok(!res, "DlgDirList should have failed with 0 but %d was returned\n", res);
- todo_wine ok(GetLastError() == ERROR_NO_WILDCARD_CHARACTERS,
+ ok(!res, "DlgDirList should have failed with 0 but %d was returned\n", res);
+ ok(GetLastError() == ERROR_NO_WILDCARD_CHARACTERS,
"GetLastError should return 0x589, got 0x%X\n",GetLastError());
DestroyWindow(hWnd);
static void test_set_count( void )
{
+ static const DWORD styles[] =
+ {
+ LBS_OWNERDRAWFIXED,
+ LBS_HASSTRINGS,
+ };
HWND parent, listbox;
+ unsigned int i;
LONG ret;
RECT r;
GetUpdateRect( listbox, &r, TRUE );
ok( !IsRectEmpty( &r ), "got empty rect\n");
+ ret = SendMessageA( listbox, LB_SETCOUNT, -5, 0 );
+ ok( ret == 0, "got %d\n", ret );
+ ret = SendMessageA( listbox, LB_GETCOUNT, 0, 0 );
+ ok( ret == -5, "got %d\n", ret );
+
DestroyWindow( listbox );
+
+ for (i = 0; i < ARRAY_SIZE(styles); ++i)
+ {
+ listbox = create_listbox( styles[i] | WS_CHILD | WS_VISIBLE, parent );
+
+ SetLastError( 0xdeadbeef );
+ ret = SendMessageA( listbox, LB_SETCOUNT, 100, 0 );
+ ok( ret == LB_ERR, "expected %d, got %d\n", LB_ERR, ret );
+ ok( GetLastError() == ERROR_SETCOUNT_ON_BAD_LB, "Unexpected error %d.\n", GetLastError() );
+
+ DestroyWindow( listbox );
+ }
+
DestroyWindow( parent );
}
DestroyWindow(parent);
}
+static void test_init_storage( void )
+{
+ static const DWORD styles[] =
+ {
+ LBS_HASSTRINGS,
+ LBS_NODATA | LBS_OWNERDRAWFIXED,
+ };
+ HWND parent, listbox;
+ LONG ret, items_size;
+ int i, j;
+
+ parent = create_parent();
+ for (i = 0; i < ARRAY_SIZE(styles); i++)
+ {
+ listbox = CreateWindowA("listbox", "TestList", styles[i] | WS_CHILD,
+ 0, 0, 100, 100, parent, (HMENU)1, NULL, 0);
+
+ items_size = SendMessageA(listbox, LB_INITSTORAGE, 100, 0);
+ ok(items_size >= 100, "expected at least 100, got %d\n", items_size);
+
+ ret = SendMessageA(listbox, LB_INITSTORAGE, 0, 0);
+ ok(ret == items_size, "expected %d, got %d\n", items_size, ret);
+
+ /* it doesn't grow since the space was already reserved */
+ ret = SendMessageA(listbox, LB_INITSTORAGE, items_size, 0);
+ ok(ret == items_size, "expected %d, got %d\n", items_size, ret);
+
+ /* it doesn't shrink the reserved space */
+ ret = SendMessageA(listbox, LB_INITSTORAGE, 42, 0);
+ ok(ret == items_size, "expected %d, got %d\n", items_size, ret);
+
+ /* now populate almost all of it so it's not reserved anymore */
+ if (styles[i] & LBS_NODATA)
+ {
+ ret = SendMessageA(listbox, LB_SETCOUNT, items_size - 1, 0);
+ ok(ret == 0, "unexpected return value %d\n", ret);
+ }
+ else
+ {
+ for (j = 0; j < items_size - 1; j++)
+ {
+ ret = SendMessageA(listbox, LB_INSERTSTRING, -1, (LPARAM)"");
+ ok(ret == j, "expected %d, got %d\n", j, ret);
+ }
+ }
+
+ /* we still have one more reserved slot, so it doesn't grow yet */
+ ret = SendMessageA(listbox, LB_INITSTORAGE, 1, 0);
+ ok(ret == items_size, "expected %d, got %d\n", items_size, ret);
+
+ /* fill the slot and check again, it should grow this time */
+ ret = SendMessageA(listbox, LB_INSERTSTRING, -1, (LPARAM)"");
+ ok(ret == items_size - 1, "expected %d, got %d\n", items_size - 1, ret);
+ ret = SendMessageA(listbox, LB_INITSTORAGE, 0, 0);
+ ok(ret == items_size, "expected %d, got %d\n", items_size, ret);
+ ret = SendMessageA(listbox, LB_INITSTORAGE, 1, 0);
+ ok(ret > items_size, "expected it to grow past %d, got %d\n", items_size, ret);
+
+ DestroyWindow(listbox);
+ }
+ DestroyWindow(parent);
+}
+
static void test_missing_lbuttonup( void )
{
HWND listbox, parent, capture;
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;
+ unsigned int i;
+ ULONG_PTR data;
+ INT ret;
+
+ listbox = CreateWindowA("listbox", "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);
+ }
+
+ /* 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);
+ ok(ret == sizeof(data), "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. */
+ SetLastError(0xdeadbeef);
+ ret = SendMessageA(listbox, LB_FINDSTRING, 1, 0);
+ ok(ret == LB_ERR, "Unexpected return value %d.\n", ret);
+ ok(GetLastError() == ERROR_INVALID_PARAMETER, "GetLastError should return 0x57, got 0x%X\n", GetLastError());
+ SetLastError(0xdeadbeef);
+ ret = SendMessageA(listbox, LB_FINDSTRING, 1, 42);
+ ok(ret == LB_ERR, "Unexpected return value %d.\n", ret);
+ ok(GetLastError() == ERROR_INVALID_PARAMETER, "GetLastError should return 0x57, got 0x%X\n", GetLastError());
+ SetLastError(0xdeadbeef);
+ ret = SendMessageA(listbox, LB_FINDSTRINGEXACT, 1, 0);
+ ok(ret == LB_ERR, "Unexpected return value %d.\n", ret);
+ ok(GetLastError() == ERROR_INVALID_PARAMETER, "GetLastError should return 0x57, got 0x%X\n", GetLastError());
+ SetLastError(0xdeadbeef);
+ ret = SendMessageA(listbox, LB_FINDSTRINGEXACT, 1, 42);
+ ok(ret == LB_ERR, "Unexpected return value %d.\n", ret);
+ ok(GetLastError() == ERROR_INVALID_PARAMETER, "GetLastError should return 0x57, got 0x%X\n", GetLastError());
+ SetLastError(0xdeadbeef);
+ ret = SendMessageA(listbox, LB_SELECTSTRING, 1, 0);
+ ok(ret == LB_ERR, "Unexpected return value %d.\n", ret);
+ ok(GetLastError() == ERROR_INVALID_PARAMETER, "GetLastError should return 0x57, got 0x%X\n", GetLastError());
+ SetLastError(0xdeadbeef);
+ ret = SendMessageA(listbox, LB_SELECTSTRING, 1, 42);
+ ok(ret == LB_ERR, "Unexpected return value %d.\n", ret);
+ ok(GetLastError() == ERROR_INVALID_PARAMETER, "GetLastError should return 0x57, got 0x%X\n", GetLastError());
+
+ 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("listbox", "TestList", LBS_NODATA | WS_CHILD | invalid_styles[i],
+ 0, 0, 100, 100, parent, (HMENU)1, 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);
+}
+
START_TEST(listbox)
{
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} */
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}};
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}};
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}};
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}};
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}};
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}};
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}};
trace (" Testing single selection...\n");
- check (SS);
+ check (0, SS);
+ trace (" ... with NOSEL\n");
+ check (LBS_NOSEL, SS_NS);
+ trace (" ... LBS_NODATA variant ...\n");
+ check (LBS_NODATA | LBS_OWNERDRAWFIXED, SS);
trace (" ... with NOSEL\n");
- check (SS_NS);
+ check (LBS_NODATA | LBS_OWNERDRAWFIXED | LBS_NOSEL, SS_NS);
+
trace (" Testing multiple selection...\n");
- check (MS);
+ check (LBS_MULTIPLESEL, MS);
+ trace (" ... with NOSEL\n");
+ check (LBS_MULTIPLESEL | LBS_NOSEL, MS_NS);
+ trace (" ... LBS_NODATA variant ...\n");
+ check (LBS_NODATA | LBS_OWNERDRAWFIXED | LBS_MULTIPLESEL, MS);
trace (" ... with NOSEL\n");
- check (MS_NS);
+ check (LBS_NODATA | LBS_OWNERDRAWFIXED | LBS_MULTIPLESEL | LBS_NOSEL, MS_NS);
+
trace (" Testing extended selection...\n");
- check (ES);
+ check (LBS_EXTENDEDSEL, ES);
+ trace (" ... with NOSEL\n");
+ check (LBS_EXTENDEDSEL | LBS_NOSEL, ES_NS);
+ trace (" ... LBS_NODATA variant ...\n");
+ check (LBS_NODATA | LBS_OWNERDRAWFIXED | LBS_EXTENDEDSEL, ES);
trace (" ... with NOSEL\n");
- check (ES_NS);
+ check (LBS_NODATA | LBS_OWNERDRAWFIXED | LBS_EXTENDEDSEL | LBS_NOSEL, ES_NS);
+
trace (" Testing extended and multiple selection...\n");
- check (EMS);
+ check (LBS_EXTENDEDSEL | LBS_MULTIPLESEL, EMS);
+ trace (" ... with NOSEL\n");
+ check (LBS_EXTENDEDSEL | LBS_MULTIPLESEL | LBS_NOSEL, EMS_NS);
+ trace (" ... LBS_NODATA variant ...\n");
+ check (LBS_NODATA | LBS_OWNERDRAWFIXED | LBS_EXTENDEDSEL | LBS_MULTIPLESEL, EMS);
trace (" ... with NOSEL\n");
- check (EMS_NS);
+ check (LBS_NODATA | LBS_OWNERDRAWFIXED | LBS_EXTENDEDSEL | LBS_MULTIPLESEL | LBS_NOSEL, EMS_NS);
check_item_height();
test_ownerdraw();
test_LB_SELITEMRANGE();
test_LB_SETCURSEL();
test_listbox_height();
+ test_changing_selection_styles();
test_itemfrompoint();
test_listbox_item_data();
test_listbox_LB_DIR();
test_listbox_dlgdir();
test_set_count();
+ test_init_storage();
test_GetListBoxInfo();
test_missing_lbuttonup();
test_extents();
test_WM_MEASUREITEM();
+ test_LB_SETSEL();
+ test_LBS_NODATA();
}