1 /* Unit test suite for list boxes.
3 * Copyright 2003 Ferenc Wagner
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
30 #include "wine/test.h"
41 static struct msg_sequence
*sequences
[NUM_MSG_SEQUENCES
];
43 /* encoded MEASUREITEMSTRUCT into a WPARAM */
57 } MEASURE_ITEM_STRUCT
;
59 static unsigned hash_Ly_W(const WCHAR
*str
)
64 hash
= hash
* 1664525u + (unsigned char)(*str
) + 1013904223u;
69 static unsigned hash_Ly(const char *str
)
74 hash
= hash
* 1664525u + (unsigned char)(*str
) + 1013904223u;
79 static const char * const strings
[4] = {
83 "Fourth added which is very long because at some time we only had a 256 byte character buffer and "
84 "that was overflowing in one of those applications that had a common dialog file open box and tried "
85 "to add a 300 characters long custom filter string which of course the code did not like and crashed. "
86 "Just make sure this string is longer than 256 characters."
89 static const char BAD_EXTENSION
[] = "*.badtxt";
93 static LRESULT WINAPI
listbox_wnd_proc(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
95 WNDPROC oldproc
= (WNDPROC
)GetWindowLongPtrA(hwnd
, GWLP_USERDATA
);
96 static LONG defwndproc_counter
= 0;
97 struct message msg
= { 0 };
106 case WM_WINDOWPOSCHANGING
:
107 case WM_WINDOWPOSCHANGED
:
111 case WM_DEVICECHANGE
:
115 msg
.message
= message
;
116 msg
.flags
= sent
|wparam
|lparam
;
117 if (defwndproc_counter
) msg
.flags
|= defwinproc
;
120 add_message(sequences
, LB_SEQ_INDEX
, &msg
);
123 defwndproc_counter
++;
124 ret
= CallWindowProcA(oldproc
, hwnd
, message
, wParam
, lParam
);
125 defwndproc_counter
--;
130 static HWND
create_listbox(DWORD add_style
, HWND parent
)
139 handle
= CreateWindowA(WC_LISTBOXA
, "TestList", (LBS_STANDARD
& ~LBS_SORT
) | add_style
, 0, 0, 100, 100,
140 parent
, (HMENU
)ctl_id
, NULL
, 0);
141 ok(handle
!= NULL
, "Failed to create listbox window.\n");
143 SendMessageA(handle
, LB_ADDSTRING
, 0, (LPARAM
) strings
[0]);
144 SendMessageA(handle
, LB_ADDSTRING
, 0, (LPARAM
) strings
[1]);
145 SendMessageA(handle
, LB_ADDSTRING
, 0, (LPARAM
) strings
[2]);
146 SendMessageA(handle
, LB_ADDSTRING
, 0, (LPARAM
) strings
[3]);
148 oldproc
= (WNDPROC
)SetWindowLongPtrA(handle
, GWLP_WNDPROC
, (LONG_PTR
)listbox_wnd_proc
);
149 SetWindowLongPtrA(handle
, GWLP_USERDATA
, (LONG_PTR
)oldproc
);
161 int selected
, anchor
, caret
, selcount
;
166 struct listbox_stat init
, init_todo
;
167 struct listbox_stat click
, click_todo
;
168 struct listbox_stat step
, step_todo
;
169 struct listbox_stat sel
, sel_todo
;
172 static void listbox_query(HWND handle
, struct listbox_stat
*results
)
174 results
->selected
= SendMessageA(handle
, LB_GETCURSEL
, 0, 0);
175 results
->anchor
= SendMessageA(handle
, LB_GETANCHORINDEX
, 0, 0);
176 results
->caret
= SendMessageA(handle
, LB_GETCARETINDEX
, 0, 0);
177 results
->selcount
= SendMessageA(handle
, LB_GETSELCOUNT
, 0, 0);
180 static void buttonpress(HWND handle
, WORD x
, WORD y
)
182 LPARAM lp
= x
+ (y
<< 16);
184 SendMessageA(handle
, WM_LBUTTONDOWN
, MK_LBUTTON
, lp
);
185 SendMessageA(handle
, WM_LBUTTONUP
, 0, lp
);
188 static void keypress(HWND handle
, WPARAM keycode
, BYTE scancode
, BOOL extended
)
190 LPARAM lp
= 1 + (scancode
<< 16) + (extended
? KEYEVENTF_EXTENDEDKEY
: 0);
192 SendMessageA(handle
, WM_KEYDOWN
, keycode
, lp
);
193 SendMessageA(handle
, WM_KEYUP
, keycode
, lp
| 0xc000000);
196 #define listbox_field_ok(t, s, f, got) \
197 ok (t.s.f==got.f, "style %#lx, step " #s ", field " #f \
198 ": expected %d, got %d\n", style, t.s.f, got.f)
200 #define listbox_todo_field_ok(t, s, f, got) \
201 todo_wine_if (t.s##_todo.f) { listbox_field_ok(t, s, f, got); }
203 #define listbox_ok(t, s, got) \
204 listbox_todo_field_ok(t, s, selected, got); \
205 listbox_todo_field_ok(t, s, anchor, got); \
206 listbox_todo_field_ok(t, s, caret, got); \
207 listbox_todo_field_ok(t, s, selcount, got)
209 static void run_test(DWORD style
, const struct listbox_test test
)
211 static const struct message delete_seq
[] =
213 { LB_DELETESTRING
, sent
|wparam
|lparam
, 0, 0 },
214 { LB_DELETESTRING
, sent
|wparam
|lparam
, 0, 0 },
215 { LB_DELETESTRING
, sent
|wparam
|lparam
, 0, 0 },
216 { LB_DELETESTRING
, sent
|wparam
|lparam
, 0, 0 },
217 { LB_RESETCONTENT
, sent
|wparam
|lparam
|defwinproc
, 0, 0 },
220 struct listbox_stat answer
;
225 hLB
= create_listbox (style
, 0);
227 listbox_query (hLB
, &answer
);
228 listbox_ok (test
, init
, answer
);
230 SendMessageA(hLB
, LB_GETITEMRECT
, 1, (LPARAM
) &second_item
);
231 buttonpress(hLB
, (WORD
)second_item
.left
, (WORD
)second_item
.top
);
233 listbox_query(hLB
, &answer
);
234 listbox_ok(test
, click
, answer
);
236 keypress(hLB
, VK_DOWN
, 0x50, TRUE
);
238 listbox_query(hLB
, &answer
);
239 listbox_ok(test
, step
, answer
);
243 hLB
= create_listbox(style
, 0);
245 SendMessageA(hLB
, LB_SELITEMRANGE
, TRUE
, MAKELPARAM(1, 2));
246 listbox_query(hLB
, &answer
);
247 listbox_ok(test
, sel
, answer
);
249 for (i
= 0; i
< 4 && !(style
& LBS_NODATA
); i
++)
251 DWORD size
= SendMessageA(hLB
, LB_GETTEXTLEN
, i
, 0);
256 txt
= calloc(1, size
+ 1);
257 resA
= SendMessageA(hLB
, LB_GETTEXT
, i
, (LPARAM
)txt
);
258 ok(!strcmp(txt
, strings
[i
]), "returned string for item %d does not match %s vs %s\n", i
, txt
, strings
[i
]);
260 txtw
= calloc(size
+ 1, sizeof(*txtw
));
261 resW
= SendMessageW(hLB
, LB_GETTEXT
, i
, (LPARAM
)txtw
);
262 ok(resA
== resW
, "Unexpected text length.\n");
263 WideCharToMultiByte(CP_ACP
, 0, txtw
, -1, txt
, size
, NULL
, NULL
);
264 ok(!strcmp (txt
, strings
[i
]), "Unexpected string for item %d, %s vs %s.\n", i
, txt
, strings
[i
]);
270 /* Confirm the count of items, and that an invalid delete does not remove anything */
271 res
= SendMessageA(hLB
, LB_GETCOUNT
, 0, 0);
272 ok(res
== 4, "Expected 4 items, got %d\n", res
);
273 res
= SendMessageA(hLB
, LB_DELETESTRING
, -1, 0);
274 ok(res
== LB_ERR
, "Expected LB_ERR items, got %d\n", res
);
275 res
= SendMessageA(hLB
, LB_DELETESTRING
, 4, 0);
276 ok(res
== LB_ERR
, "Expected LB_ERR items, got %d\n", res
);
277 count
= SendMessageA(hLB
, LB_GETCOUNT
, 0, 0);
278 ok(count
== 4, "Unexpected item count %d.\n", count
);
280 /* Emptying listbox sends a LB_RESETCONTENT to itself. */
281 flush_sequence(sequences
, LB_SEQ_INDEX
);
282 for (i
= count
; i
--;)
284 res
= SendMessageA(hLB
, LB_DELETESTRING
, 0, 0);
285 ok(res
== i
, "Unexpected return value %d.\n", res
);
287 ok_sequence(sequences
, LB_SEQ_INDEX
, delete_seq
, "Emptying listbox", FALSE
);
292 static void test_item_height(void)
300 hLB
= create_listbox (0, 0);
301 ok ((hdc
= GetDCEx( hLB
, 0, DCX_CACHE
)) != 0, "Can't get hdc\n");
302 ok ((font
= GetCurrentObject(hdc
, OBJ_FONT
)) != 0, "Can't get the current font\n");
303 ok (GetTextMetricsA( hdc
, &tm
), "Can't read font metrics\n");
304 ReleaseDC( hLB
, hdc
);
306 ok (SendMessageA(hLB
, WM_SETFONT
, (WPARAM
)font
, 0) == 0, "Can't set font\n");
308 itemHeight
= SendMessageA(hLB
, LB_GETITEMHEIGHT
, 0, 0);
309 ok (itemHeight
== tm
.tmHeight
, "Item height wrong, got %d, expecting %ld\n", itemHeight
, tm
.tmHeight
);
313 hLB
= CreateWindowA(WC_LISTBOXA
, "TestList", LBS_OWNERDRAWVARIABLE
, 0, 0, 100, 100, NULL
, NULL
, NULL
, 0);
315 itemHeight
= SendMessageA(hLB
, LB_GETITEMHEIGHT
, 0, 0);
316 ok(itemHeight
> 0 && itemHeight
<= tm
.tmHeight
, "Unexpected item height %d, expected %ld.\n",
317 itemHeight
, tm
.tmHeight
);
318 itemHeight
= SendMessageA(hLB
, LB_GETITEMHEIGHT
, 5, 0);
319 ok(itemHeight
> 0 && itemHeight
<= tm
.tmHeight
, "Unexpected item height %d, expected %ld.\n",
320 itemHeight
, tm
.tmHeight
);
321 itemHeight
= SendMessageA(hLB
, LB_GETITEMHEIGHT
, -5, 0);
322 ok(itemHeight
> 0 && itemHeight
<= tm
.tmHeight
, "Unexpected item height %d, expected %ld.\n",
323 itemHeight
, tm
.tmHeight
);
328 static unsigned int got_selchange
, got_drawitem
;
330 static LRESULT WINAPI
main_window_proc(HWND hwnd
, UINT msg
, WPARAM wParam
, LPARAM lParam
)
332 static LONG defwndproc_counter
= 0;
333 struct message m
= { 0 };
337 m
.flags
= sent
|wparam
|lparam
;
338 if (defwndproc_counter
) m
.flags
|= defwinproc
;
346 MEASUREITEMSTRUCT
*mis
= (void *)lParam
;
347 BOOL is_unicode_data
= FALSE
;
348 MEASURE_ITEM_STRUCT mi
;
350 if (mis
->CtlType
== ODT_LISTBOX
)
352 HWND ctrl
= GetDlgItem(hwnd
, mis
->CtlID
);
353 is_unicode_data
= GetWindowLongA(ctrl
, GWL_STYLE
) & LBS_HASSTRINGS
;
357 mi
.u
.item
.CtlType
= mis
->CtlType
;
358 mi
.u
.item
.CtlID
= mis
->CtlID
;
359 mi
.u
.item
.itemID
= mis
->itemID
;
360 mi
.u
.item
.wParam
= wParam
;
364 m
.lParam
= mis
->itemData
? hash_Ly_W((const WCHAR
*)mis
->itemData
) : 0;
366 m
.lParam
= mis
->itemData
? hash_Ly((const char *)mis
->itemData
) : 0;
367 add_message(sequences
, PARENT_SEQ_INDEX
, &m
);
369 ok(wParam
== mis
->CtlID
, "got wParam=%08Ix, expected %08x\n", wParam
, mis
->CtlID
);
370 ok(mis
->CtlType
== ODT_LISTBOX
, "mi->CtlType = %u\n", mis
->CtlType
);
371 ok(mis
->CtlID
== 1, "mi->CtlID = %u\n", mis
->CtlID
);
372 ok(mis
->itemHeight
, "mi->itemHeight = 0\n");
378 COMPAREITEMSTRUCT
*cis
= (COMPAREITEMSTRUCT
*)lParam
;
379 HWND ctrl
= GetDlgItem(hwnd
, cis
->CtlID
);
380 BOOL is_unicode_data
= TRUE
;
382 ok(wParam
== cis
->CtlID
, "expected %#x, got %#Ix\n", cis
->CtlID
, wParam
);
383 ok(cis
->hwndItem
== ctrl
, "expected %p, got %p\n", ctrl
, cis
->hwndItem
);
384 ok((int)cis
->itemID1
>= 0, "expected >= 0, got %d\n", cis
->itemID1
);
385 ok((int)cis
->itemID2
== -1, "expected -1, got %d\n", cis
->itemID2
);
387 if (cis
->CtlType
== ODT_LISTBOX
)
388 is_unicode_data
= GetWindowLongA(ctrl
, GWL_STYLE
) & LBS_HASSTRINGS
;
392 m
.wParam
= cis
->itemData1
? hash_Ly_W((const WCHAR
*)cis
->itemData1
) : 0;
393 m
.lParam
= cis
->itemData2
? hash_Ly_W((const WCHAR
*)cis
->itemData2
) : 0;
397 m
.wParam
= cis
->itemData1
? hash_Ly((const char *)cis
->itemData1
) : 0;
398 m
.lParam
= cis
->itemData2
? hash_Ly((const char *)cis
->itemData2
) : 0;
400 add_message(sequences
, PARENT_SEQ_INDEX
, &m
);
405 RECT rc_item
, rc_client
, rc_clip
;
406 DRAWITEMSTRUCT
*dis
= (DRAWITEMSTRUCT
*)lParam
;
408 ok(wParam
== dis
->CtlID
, "got wParam=%08Ix instead of %08x\n", wParam
, dis
->CtlID
);
409 ok(dis
->CtlType
== ODT_LISTBOX
, "wrong CtlType %04x\n", dis
->CtlType
);
411 GetClientRect(dis
->hwndItem
, &rc_client
);
412 GetClipBox(dis
->hDC
, &rc_clip
);
413 ok(EqualRect(&rc_client
, &rc_clip
) || IsRectEmpty(&rc_clip
),
414 "client rect of the listbox should be equal to the clip box,"
415 "or the clip box should be empty\n");
417 SendMessageA(dis
->hwndItem
, LB_GETITEMRECT
, dis
->itemID
, (LPARAM
)&rc_item
);
418 ok(EqualRect(&dis
->rcItem
, &rc_item
), "item rects are not equal\n");
425 if (HIWORD( wParam
) == LBN_SELCHANGE
) got_selchange
++;
432 defwndproc_counter
++;
433 ret
= DefWindowProcA(hwnd
, msg
, wParam
, lParam
);
434 defwndproc_counter
--;
436 return msg
== WM_COMPAREITEM
? -1 : ret
;
439 static HWND
create_parent( void )
447 cls
.lpfnWndProc
= main_window_proc
;
450 cls
.hInstance
= GetModuleHandleA(NULL
);
452 cls
.hCursor
= LoadCursorA(0, (LPCSTR
)IDC_ARROW
);
453 cls
.hbrBackground
= GetStockObject(WHITE_BRUSH
);
454 cls
.lpszMenuName
= NULL
;
455 cls
.lpszClassName
= "main_window_class";
456 class = RegisterClassA( &cls
);
459 return CreateWindowExA(0, "main_window_class", NULL
, WS_POPUP
| WS_VISIBLE
, 100, 100, 400, 400, GetDesktopWindow(),
460 0, GetModuleHandleA(NULL
), NULL
);
463 static void test_ownerdraw(void)
465 static const DWORD styles
[] =
470 static const struct {
476 { WM_NULL
, 0, 0, 0 },
477 { WM_PAINT
, 0, 0, 0 },
478 { LB_GETCOUNT
, 0, 0, 0 },
479 { LB_SETCOUNT
, ARRAY_SIZE(strings
), 0, ARRAY_SIZE(strings
) },
480 { LB_ADDSTRING
, 0, (LPARAM
)"foo", ARRAY_SIZE(strings
)+1 },
481 { LB_DELETESTRING
, 0, 0, ARRAY_SIZE(strings
)-1 },
488 parent
= create_parent();
489 ok(parent
!= NULL
, "Failed to create parent window.\n");
491 for (i
= 0; i
< ARRAY_SIZE(styles
); i
++)
493 hLB
= create_listbox(LBS_OWNERDRAWFIXED
| WS_CHILD
| WS_VISIBLE
| styles
[i
], parent
);
494 ok(hLB
!= NULL
, "Failed to create listbox window.\n");
496 SetForegroundWindow(hLB
);
499 /* make height short enough */
500 SendMessageA(hLB
, LB_GETITEMRECT
, 0, (LPARAM
)&rc
);
501 SetWindowPos(hLB
, 0, 0, 0, 100, rc
.bottom
- rc
.top
+ 1, SWP_NOZORDER
| SWP_NOMOVE
);
503 /* make 0 item invisible */
504 SendMessageA(hLB
, LB_SETTOPINDEX
, 1, 0);
505 ret
= SendMessageA(hLB
, LB_GETTOPINDEX
, 0, 0);
506 ok(ret
== 1, "wrong top index %d\n", ret
);
508 SendMessageA(hLB
, LB_GETITEMRECT
, 0, (LPARAM
)&rc
);
509 ok(!IsRectEmpty(&rc
), "empty item rect\n");
510 ok(rc
.top
< 0, "rc.top is not negative (%ld)\n", rc
.top
);
514 /* Both FIXED and VARIABLE, FIXED should override VARIABLE. */
515 hLB
= CreateWindowA(WC_LISTBOXA
, "TestList", LBS_OWNERDRAWFIXED
| LBS_OWNERDRAWVARIABLE
| styles
[i
],
516 0, 0, 100, 100, NULL
, NULL
, NULL
, 0);
517 ok(hLB
!= NULL
, "last error 0x%08lx\n", GetLastError());
519 ok(GetWindowLongA(hLB
, GWL_STYLE
) & LBS_OWNERDRAWVARIABLE
, "Unexpected window style.\n");
521 ret
= SendMessageA(hLB
, LB_INSERTSTRING
, -1, 0);
522 ok(ret
== 0, "Unexpected return value %d.\n", ret
);
523 ret
= SendMessageA(hLB
, LB_INSERTSTRING
, -1, 0);
524 ok(ret
== 1, "Unexpected return value %d.\n", ret
);
526 ret
= SendMessageA(hLB
, LB_SETITEMHEIGHT
, 0, 13);
527 ok(ret
== LB_OKAY
, "Failed to set item height, %d.\n", ret
);
529 ret
= SendMessageA(hLB
, LB_GETITEMHEIGHT
, 0, 0);
530 ok(ret
== 13, "Unexpected item height %d.\n", ret
);
532 ret
= SendMessageA(hLB
, LB_SETITEMHEIGHT
, 1, 42);
533 ok(ret
== LB_OKAY
, "Failed to set item height, %d.\n", ret
);
535 ret
= SendMessageA(hLB
, LB_GETITEMHEIGHT
, 0, 0);
536 ok(ret
== 42, "Unexpected item height %d.\n", ret
);
538 ret
= SendMessageA(hLB
, LB_GETITEMHEIGHT
, 1, 0);
539 ok(ret
== 42, "Unexpected item height %d.\n", ret
);
544 /* test pending redraw state */
545 for (i
= 0; i
< ARRAY_SIZE(testcase
); i
++)
547 winetest_push_context("%d", i
);
548 hLB
= create_listbox(LBS_OWNERDRAWFIXED
| LBS_NODATA
| WS_CHILD
| WS_VISIBLE
, parent
);
551 ret
= SendMessageA(hLB
, WM_SETREDRAW
, FALSE
, 0);
552 ok(!ret
, "got %d\n", ret
);
553 ret
= SendMessageA(hLB
, testcase
[i
].message
, testcase
[i
].wparam
, testcase
[i
].lparam
);
554 if (testcase
[i
].message
>= LB_ADDSTRING
&& testcase
[i
].message
< LB_MSGMAX
&&
555 testcase
[i
].message
!= LB_SETCOUNT
)
556 ok(ret
> 0, "expected > 0, got %d\n", ret
);
558 ok(!ret
, "expected 0, got %d\n", ret
);
561 ret
= RedrawWindow(hLB
, NULL
, 0, RDW_UPDATENOW
);
562 ok(ret
, "RedrawWindow failed\n");
563 ok(!got_drawitem
, "got %u\n", got_drawitem
);
565 ret
= SendMessageA(hLB
, WM_SETREDRAW
, TRUE
, 0);
566 ok(!ret
, "got %d\n", ret
);
569 ret
= RedrawWindow(hLB
, NULL
, 0, RDW_UPDATENOW
);
570 ok(ret
, "RedrawWindow failed\n");
571 ok(got_drawitem
== testcase
[i
].drawitem
, "expected %u, got %u\n", testcase
[i
].drawitem
, got_drawitem
);
574 winetest_pop_context();
577 DestroyWindow(parent
);
580 #define listbox_test_query(exp, got) \
581 ok(exp.selected == got.selected, "expected selected %d, got %d\n", exp.selected, got.selected); \
582 ok(exp.anchor == got.anchor, "expected anchor %d, got %d\n", exp.anchor, got.anchor); \
583 ok(exp.caret == got.caret, "expected caret %d, got %d\n", exp.caret, got.caret); \
584 ok(exp.selcount == got.selcount, "expected selcount %d, got %d\n", exp.selcount, got.selcount);
586 static void test_LB_SELITEMRANGE(void)
588 static const struct listbox_stat test_nosel
= { 0, LB_ERR
, 0, 0 };
589 static const struct listbox_stat test_1
= { 0, LB_ERR
, 0, 2 };
590 static const struct listbox_stat test_2
= { 0, LB_ERR
, 0, 3 };
591 static const struct listbox_stat test_3
= { 0, LB_ERR
, 0, 4 };
592 struct listbox_stat answer
;
596 hLB
= create_listbox(LBS_EXTENDEDSEL
, 0);
597 ok(hLB
!= NULL
, "Failed to create listbox window.\n");
599 listbox_query(hLB
, &answer
);
600 listbox_test_query(test_nosel
, answer
);
602 ret
= SendMessageA(hLB
, LB_SELITEMRANGE
, TRUE
, MAKELPARAM(1, 2));
603 ok(ret
== LB_OKAY
, "LB_SELITEMRANGE returned %d instead of LB_OKAY\n", ret
);
604 listbox_query(hLB
, &answer
);
605 listbox_test_query(test_1
, answer
);
607 SendMessageA(hLB
, LB_SETSEL
, FALSE
, -1);
608 listbox_query(hLB
, &answer
);
609 listbox_test_query(test_nosel
, answer
);
611 ret
= SendMessageA(hLB
, LB_SELITEMRANGE
, TRUE
, MAKELPARAM(0, 4));
612 ok(ret
== LB_OKAY
, "LB_SELITEMRANGE returned %d instead of LB_OKAY\n", ret
);
613 listbox_query(hLB
, &answer
);
614 listbox_test_query(test_3
, answer
);
616 SendMessageA(hLB
, LB_SETSEL
, FALSE
, -1);
617 listbox_query(hLB
, &answer
);
618 listbox_test_query(test_nosel
, answer
);
620 ret
= SendMessageA(hLB
, LB_SELITEMRANGE
, TRUE
, MAKELPARAM(-5, 5));
621 ok(ret
== LB_OKAY
, "LB_SELITEMRANGE returned %d instead of LB_OKAY\n", ret
);
622 listbox_query(hLB
, &answer
);
623 listbox_test_query(test_nosel
, answer
);
625 SendMessageA(hLB
, LB_SETSEL
, FALSE
, -1);
626 listbox_query(hLB
, &answer
);
627 listbox_test_query(test_nosel
, answer
);
629 ret
= SendMessageA(hLB
, LB_SELITEMRANGE
, TRUE
, MAKELPARAM(2, 10));
630 ok(ret
== LB_OKAY
, "LB_SELITEMRANGE returned %d instead of LB_OKAY\n", ret
);
631 listbox_query(hLB
, &answer
);
632 listbox_test_query(test_1
, answer
);
634 SendMessageA(hLB
, LB_SETSEL
, FALSE
, -1);
635 listbox_query(hLB
, &answer
);
636 listbox_test_query(test_nosel
, answer
);
638 ret
= SendMessageA(hLB
, LB_SELITEMRANGE
, TRUE
, MAKELPARAM(4, 10));
639 ok(ret
== LB_OKAY
, "LB_SELITEMRANGE returned %d instead of LB_OKAY\n", ret
);
640 listbox_query(hLB
, &answer
);
641 listbox_test_query(test_nosel
, answer
);
643 SendMessageA(hLB
, LB_SETSEL
, FALSE
, -1);
644 listbox_query(hLB
, &answer
);
645 listbox_test_query(test_nosel
, answer
);
647 ret
= SendMessageA(hLB
, LB_SELITEMRANGE
, TRUE
, MAKELPARAM(10, 1));
648 ok(ret
== LB_OKAY
, "LB_SELITEMRANGE returned %d instead of LB_OKAY\n", ret
);
649 listbox_query(hLB
, &answer
);
650 listbox_test_query(test_2
, answer
);
652 SendMessageA(hLB
, LB_SETSEL
, FALSE
, -1);
653 listbox_query(hLB
, &answer
);
654 listbox_test_query(test_nosel
, answer
);
656 ret
= SendMessageA(hLB
, LB_SELITEMRANGE
, TRUE
, MAKELPARAM(1, -1));
657 ok(ret
== LB_OKAY
, "LB_SELITEMRANGE returned %d instead of LB_OKAY\n", ret
);
658 listbox_query(hLB
, &answer
);
659 listbox_test_query(test_2
, answer
);
664 static void test_LB_SETCURSEL(void)
669 parent
= create_parent();
670 ok(parent
!= NULL
, "Failed to create parent window.\n");
672 hLB
= create_listbox(LBS_NOINTEGRALHEIGHT
| WS_CHILD
, parent
);
673 ok(hLB
!= NULL
, "Failed to create listbox.\n");
675 SendMessageA(hLB
, LB_SETITEMHEIGHT
, 0, 32);
677 ret
= SendMessageA(hLB
, LB_GETANCHORINDEX
, 0, 0);
678 ok(ret
== -1, "Unexpected anchor index %d.\n", ret
);
680 ret
= SendMessageA(hLB
, LB_SETCURSEL
, 2, 0);
681 ok(ret
== 2, "LB_SETCURSEL returned %d instead of 2\n", ret
);
682 ret
= GetScrollPos(hLB
, SB_VERT
);
683 ok(ret
== 0, "expected vscroll 0, got %d\n", ret
);
685 ret
= SendMessageA(hLB
, LB_GETANCHORINDEX
, 0, 0);
686 ok(ret
== -1, "Unexpected anchor index %d.\n", ret
);
688 ret
= SendMessageA(hLB
, LB_SETCURSEL
, 3, 0);
689 ok(ret
== 3, "LB_SETCURSEL returned %d instead of 3\n", ret
);
690 ret
= GetScrollPos(hLB
, SB_VERT
);
691 ok(ret
== 1, "expected vscroll 1, got %d\n", ret
);
693 ret
= SendMessageA(hLB
, LB_GETANCHORINDEX
, 0, 0);
694 ok(ret
== -1, "Unexpected anchor index %d.\n", ret
);
698 hLB
= create_listbox(0, 0);
699 ok(hLB
!= NULL
, "Failed to create ListBox window.\n");
701 ret
= SendMessageA(hLB
, LB_SETCURSEL
, 1, 0);
702 ok(ret
== 1, "Unexpected return value %d.\n", ret
);
704 ret
= SendMessageA(hLB
, LB_GETANCHORINDEX
, 0, 0);
705 ok(ret
== -1, "Unexpected anchor index %d.\n", ret
);
709 /* LBS_EXTENDEDSEL */
710 hLB
= create_listbox(LBS_EXTENDEDSEL
, 0);
711 ok(hLB
!= NULL
, "Failed to create listbox.\n");
713 ret
= SendMessageA(hLB
, LB_GETANCHORINDEX
, 0, 0);
714 ok(ret
== -1, "Unexpected anchor index %d.\n", ret
);
716 ret
= SendMessageA(hLB
, LB_SETCURSEL
, 2, 0);
717 ok(ret
== -1, "LB_SETCURSEL returned %d instead of 2\n", ret
);
719 ret
= SendMessageA(hLB
, LB_GETANCHORINDEX
, 0, 0);
720 ok(ret
== -1, "Unexpected anchor index %d.\n", ret
);
724 /* LBS_MULTIPLESEL */
725 hLB
= create_listbox(LBS_MULTIPLESEL
, 0);
726 ok(hLB
!= NULL
, "Failed to create listbox.\n");
728 ret
= SendMessageA(hLB
, LB_GETANCHORINDEX
, 0, 0);
729 ok(ret
== -1, "Unexpected anchor index %d.\n", ret
);
731 ret
= SendMessageA(hLB
, LB_SETCURSEL
, 2, 0);
732 ok(ret
== -1, "LB_SETCURSEL returned %d instead of 2\n", ret
);
734 ret
= SendMessageA(hLB
, LB_GETANCHORINDEX
, 0, 0);
735 ok(ret
== -1, "Unexpected anchor index %d.\n", ret
);
740 static void test_LB_SETSEL(void)
745 /* LBS_EXTENDEDSEL */
746 list
= create_listbox(LBS_EXTENDEDSEL
, 0);
747 ok(list
!= NULL
, "Failed to create ListBox window.\n");
749 ret
= SendMessageA(list
, LB_GETANCHORINDEX
, 0, 0);
750 ok(ret
== -1, "Unexpected anchor index %d.\n", ret
);
752 ret
= SendMessageA(list
, LB_SETSEL
, TRUE
, 0);
753 ok(ret
== 0, "Unexpected return value %d.\n", ret
);
754 ret
= SendMessageA(list
, LB_GETANCHORINDEX
, 0, 0);
755 ok(ret
== 0, "Unexpected anchor index %d.\n", ret
);
756 ret
= SendMessageA(list
, LB_GETCARETINDEX
, 0, 0);
757 ok(ret
== 0, "Unexpected caret index %d.\n", ret
);
759 ret
= SendMessageA(list
, LB_SETSEL
, TRUE
, 1);
760 ok(ret
== 0, "Unexpected return value %d.\n", ret
);
761 ret
= SendMessageA(list
, LB_GETANCHORINDEX
, 0, 0);
762 ok(ret
== 1, "Unexpected anchor index %d.\n", ret
);
763 ret
= SendMessageA(list
, LB_GETCARETINDEX
, 0, 0);
764 ok(ret
== 1, "Unexpected caret index %d.\n", ret
);
766 ret
= SendMessageA(list
, LB_SETSEL
, FALSE
, 1);
767 ok(ret
== 0, "Unexpected return value %d.\n", ret
);
768 ret
= SendMessageA(list
, LB_GETANCHORINDEX
, 0, 0);
769 ok(ret
== 1, "Unexpected anchor index %d.\n", ret
);
770 ret
= SendMessageA(list
, LB_GETCARETINDEX
, 0, 0);
771 ok(ret
== 1, "Unexpected caret index %d.\n", ret
);
775 /* LBS_MULTIPLESEL */
776 list
= create_listbox(LBS_MULTIPLESEL
, 0);
777 ok(list
!= NULL
, "Failed to create ListBox window.\n");
779 ret
= SendMessageA(list
, LB_GETANCHORINDEX
, 0, 0);
780 ok(ret
== -1, "Unexpected anchor index %d.\n", ret
);
782 ret
= SendMessageA(list
, LB_SETSEL
, TRUE
, 0);
783 ok(ret
== 0, "Unexpected return value %d.\n", ret
);
784 ret
= SendMessageA(list
, LB_GETANCHORINDEX
, 0, 0);
785 ok(ret
== 0, "Unexpected anchor index %d.\n", ret
);
786 ret
= SendMessageA(list
, LB_GETCARETINDEX
, 0, 0);
787 ok(ret
== 0, "Unexpected caret index %d.\n", ret
);
789 ret
= SendMessageA(list
, LB_SETSEL
, TRUE
, 1);
790 ok(ret
== 0, "Unexpected return value %d.\n", ret
);
791 ret
= SendMessageA(list
, LB_GETANCHORINDEX
, 0, 0);
792 ok(ret
== 1, "Unexpected anchor index %d.\n", ret
);
793 ret
= SendMessageA(list
, LB_GETCARETINDEX
, 0, 0);
794 ok(ret
== 1, "Unexpected caret index %d.\n", ret
);
796 ret
= SendMessageA(list
, LB_SETSEL
, FALSE
, 1);
797 ok(ret
== 0, "Unexpected return value %d.\n", ret
);
798 ret
= SendMessageA(list
, LB_GETANCHORINDEX
, 0, 0);
799 ok(ret
== 1, "Unexpected anchor index %d.\n", ret
);
800 ret
= SendMessageA(list
, LB_GETCARETINDEX
, 0, 0);
801 ok(ret
== 1, "Unexpected caret index %d.\n", ret
);
806 static void test_listbox_height(void)
811 hList
= CreateWindowA( WC_LISTBOXA
, "list test", 0,
812 1, 1, 600, 100, NULL
, NULL
, NULL
, NULL
);
813 ok( hList
!= NULL
, "failed to create listbox\n");
815 id
= SendMessageA( hList
, LB_ADDSTRING
, 0, (LPARAM
) "hi");
816 ok( id
== 0, "item id wrong\n");
818 r
= SendMessageA( hList
, LB_SETITEMHEIGHT
, 0, MAKELPARAM( 20, 0 ));
819 ok( r
== 0, "send message failed\n");
821 r
= SendMessageA(hList
, LB_GETITEMHEIGHT
, 0, 0 );
822 ok( r
== 20, "height wrong\n");
824 r
= SendMessageA( hList
, LB_SETITEMHEIGHT
, 0, MAKELPARAM( 0, 30 ));
825 ok( r
== -1, "send message failed\n");
827 r
= SendMessageA(hList
, LB_GETITEMHEIGHT
, 0, 0 );
828 ok( r
== 20, "height wrong\n");
830 /* Before Windows 10 1709 (or 1703?) the item height was limited to 255.
831 * Since then, with comctl32 V6 the limit is 65535.
833 r
= SendMessageA( hList
, LB_SETITEMHEIGHT
, 0, MAKELPARAM( 256, 0 ));
834 ok(r
== 0 || broken(r
== -1), "Failed to set item height, %d.\n", r
);
837 r
= SendMessageA(hList
, LB_GETITEMHEIGHT
, 0, 0 );
838 ok( r
== 20, "Unexpected item height %d.\n", r
);
842 r
= SendMessageA(hList
, LB_GETITEMHEIGHT
, 0, 0 );
843 ok( r
== 256, "Unexpected item height %d.\n", r
);
845 r
= SendMessageA( hList
, LB_SETITEMHEIGHT
, 0, MAKELPARAM( 65535, 0 ));
846 ok(r
== 0, "Failed to set item height, %d.\n", r
);
848 r
= SendMessageA(hList
, LB_GETITEMHEIGHT
, 0, 0 );
849 ok( r
== 65535, "Unexpected item height %d.\n", r
);
852 r
= SendMessageA( hList
, LB_SETITEMHEIGHT
, 0, MAKELPARAM( 0xff, 0 ));
853 ok( r
== 0, "send message failed\n");
855 r
= SendMessageA(hList
, LB_GETITEMHEIGHT
, 0, 0 );
856 ok( r
== 0xff, "height wrong\n");
858 DestroyWindow( hList
);
861 static void test_changing_selection_styles(void)
863 static const DWORD styles
[] =
866 LBS_NODATA
| LBS_OWNERDRAWFIXED
868 static const DWORD selstyles
[] =
873 LBS_MULTIPLESEL
| LBS_EXTENDEDSEL
875 static const LONG selexpect_single
[] = { 0, 0, 1 };
876 static const LONG selexpect_single2
[] = { 1, 0, 0 };
877 static const LONG selexpect_multi
[] = { 1, 0, 1 };
878 static const LONG selexpect_multi2
[] = { 1, 1, 0 };
880 HWND parent
, listbox
;
885 parent
= create_parent();
886 ok(parent
!= NULL
, "Failed to create parent window.\n");
887 for (i
= 0; i
< ARRAY_SIZE(styles
); i
++)
889 /* Test if changing selection styles affects selection storage */
890 for (j
= 0; j
< ARRAY_SIZE(selstyles
); j
++)
892 LONG setcursel_expect
, selitemrange_expect
, getselcount_expect
;
893 const LONG
*selexpect
;
895 listbox
= CreateWindowA(WC_LISTBOXA
, "TestList", styles
[i
] | selstyles
[j
] | WS_CHILD
| WS_VISIBLE
,
896 0, 0, 100, 100, parent
, (HMENU
)ID_LISTBOX
, NULL
, 0);
897 ok(listbox
!= NULL
, "%u: Failed to create ListBox window.\n", j
);
899 if (selstyles
[j
] & (LBS_MULTIPLESEL
| LBS_EXTENDEDSEL
))
901 setcursel_expect
= LB_ERR
;
902 selitemrange_expect
= LB_OKAY
;
903 getselcount_expect
= 2;
904 selexpect
= selexpect_multi
;
908 setcursel_expect
= 2;
909 selitemrange_expect
= LB_ERR
;
910 getselcount_expect
= LB_ERR
;
911 selexpect
= selexpect_single
;
914 for (k
= 0; k
< ARRAY_SIZE(selexpect_multi
); k
++)
916 ret
= SendMessageA(listbox
, LB_INSERTSTRING
, -1, (LPARAM
)"x");
917 ok(ret
== k
, "%u: Unexpected return value %ld, expected %d.\n", j
, ret
, k
);
919 ret
= SendMessageA(listbox
, LB_GETCOUNT
, 0, 0);
920 ok(ret
== ARRAY_SIZE(selexpect_multi
), "%u: Unexpected count %ld.\n", j
, ret
);
922 /* Select items with different methods */
923 ret
= SendMessageA(listbox
, LB_SETCURSEL
, 2, 0);
924 ok(ret
== setcursel_expect
, "%u: Unexpected return value %ld.\n", j
, ret
);
925 ret
= SendMessageA(listbox
, LB_SELITEMRANGE
, TRUE
, MAKELPARAM(0, 0));
926 ok(ret
== selitemrange_expect
, "%u: Unexpected return value %ld.\n", j
, ret
);
927 ret
= SendMessageA(listbox
, LB_SELITEMRANGE
, TRUE
, MAKELPARAM(2, 2));
928 ok(ret
== selitemrange_expect
, "%u: Unexpected return value %ld.\n", j
, ret
);
930 /* Verify that the proper items are selected */
931 for (k
= 0; k
< ARRAY_SIZE(selexpect_multi
); k
++)
933 ret
= SendMessageA(listbox
, LB_GETSEL
, k
, 0);
934 ok(ret
== selexpect
[k
], "%u: Unexpected selection state %ld, expected %ld.\n",
935 j
, ret
, selexpect
[k
]);
938 /* Now change the selection style */
939 style
= GetWindowLongA(listbox
, GWL_STYLE
);
940 ok((style
& (LBS_MULTIPLESEL
| LBS_EXTENDEDSEL
)) == selstyles
[j
],
941 "%u: unexpected window styles %#lx.\n", j
, style
);
942 if (selstyles
[j
] & (LBS_MULTIPLESEL
| LBS_EXTENDEDSEL
))
943 style
&= ~selstyles
[j
];
945 style
|= LBS_MULTIPLESEL
| LBS_EXTENDEDSEL
;
946 SetWindowLongA(listbox
, GWL_STYLE
, style
);
947 style
= GetWindowLongA(listbox
, GWL_STYLE
);
948 ok(!(style
& selstyles
[j
]), "%u: unexpected window styles %#lx.\n", j
, style
);
950 /* Verify that the same items are selected */
951 ret
= SendMessageA(listbox
, LB_GETSELCOUNT
, 0, 0);
952 ok(ret
== getselcount_expect
, "%u: expected %ld from LB_GETSELCOUNT, got %ld\n",
953 j
, getselcount_expect
, ret
);
955 for (k
= 0; k
< ARRAY_SIZE(selexpect_multi
); k
++)
957 ret
= SendMessageA(listbox
, LB_GETSEL
, k
, 0);
958 ok(ret
== selexpect
[k
], "%u: Unexpected selection state %ld, expected %ld.\n",
959 j
, ret
, selexpect
[k
]);
962 /* Lastly see if we can still change the selection as before with old style */
963 if (setcursel_expect
!= LB_ERR
) setcursel_expect
= 0;
964 ret
= SendMessageA(listbox
, LB_SETCURSEL
, 0, 0);
965 ok(ret
== setcursel_expect
, "%u: Unexpected return value %ld.\n", j
, ret
);
966 ret
= SendMessageA(listbox
, LB_SELITEMRANGE
, TRUE
, MAKELPARAM(1, 1));
967 ok(ret
== selitemrange_expect
, "%u: Unexpected return value %ld.\n", j
, ret
);
968 ret
= SendMessageA(listbox
, LB_SELITEMRANGE
, FALSE
, MAKELPARAM(2, 2));
969 ok(ret
== selitemrange_expect
, "%u: Unexpected return value %ld.\n", j
, ret
);
971 /* And verify the selections */
972 selexpect
= (selstyles
[j
] & (LBS_MULTIPLESEL
| LBS_EXTENDEDSEL
)) ? selexpect_multi2
: selexpect_single2
;
973 ret
= SendMessageA(listbox
, LB_GETSELCOUNT
, 0, 0);
974 ok(ret
== getselcount_expect
, "%u: expected %ld from LB_GETSELCOUNT, got %ld\n",
975 j
, getselcount_expect
, ret
);
977 for (k
= 0; k
< ARRAY_SIZE(selexpect_multi
); k
++)
979 ret
= SendMessageA(listbox
, LB_GETSEL
, k
, 0);
980 ok(ret
== selexpect
[k
], "%u: Unexpected selection state %ld, expected %ld.\n",
981 j
, ret
, selexpect
[k
]);
984 DestroyWindow(listbox
);
987 DestroyWindow(parent
);
990 static void test_itemfrompoint(void)
992 /* WS_POPUP is required in order to have a more accurate size calculation (
993 without caption). LBS_NOINTEGRALHEIGHT is required in order to test
994 behavior of partially-displayed item.
996 HWND hList
= CreateWindowA( WC_LISTBOXA
, "list test",
997 WS_VISIBLE
|WS_POPUP
|LBS_NOINTEGRALHEIGHT
,
998 1, 1, 600, 100, NULL
, NULL
, NULL
, NULL
);
1002 r
= SendMessageA(hList
, LB_ITEMFROMPOINT
, 0, MAKELPARAM( /* x */ 30, /* y */ 30 ));
1003 ok( r
== MAKELPARAM(0xffff, 1), "Unexpected ret value %#lx.\n", r
);
1005 r
= SendMessageA(hList
, LB_ITEMFROMPOINT
, 0, MAKELPARAM( 700, 30 ));
1006 ok( r
== MAKELPARAM(0xffff, 1), "Unexpected ret value %#lx.\n", r
);
1008 r
= SendMessageA(hList
, LB_ITEMFROMPOINT
, 0, MAKELPARAM( 30, 300 ));
1009 ok( r
== MAKELPARAM(0xffff, 1), "Unexpected ret value %#lx.\n", r
);
1011 id
= SendMessageA( hList
, LB_ADDSTRING
, 0, (LPARAM
) "hi");
1012 ok( id
== 0, "item id wrong\n");
1013 id
= SendMessageA( hList
, LB_ADDSTRING
, 0, (LPARAM
) "hi1");
1014 ok( id
== 1, "item id wrong\n");
1016 r
= SendMessageA(hList
, LB_ITEMFROMPOINT
, 0, MAKELPARAM( /* x */ 30, /* y */ 30 ));
1017 ok( r
== 0x1, "ret %lx\n", r
);
1019 r
= SendMessageA(hList
, LB_ITEMFROMPOINT
, 0, MAKELPARAM( /* x */ 30, /* y */ 601 ));
1020 ok( r
== MAKELPARAM(1, 1), "Unexpected ret value %#lx.\n", r
);
1022 /* Resize control so that below assertions about sizes are valid */
1023 r
= SendMessageA( hList
, LB_GETITEMRECT
, 0, (LPARAM
)&rc
);
1024 ok( r
== 1, "ret %lx\n", r
);
1025 r
= MoveWindow(hList
, 1, 1, 600, (rc
.bottom
- rc
.top
+ 1) * 9 / 2, TRUE
);
1026 ok( r
!= 0, "ret %lx\n", r
);
1028 id
= SendMessageA( hList
, LB_ADDSTRING
, 0, (LPARAM
) "hi2");
1029 ok( id
== 2, "item id wrong\n");
1030 id
= SendMessageA( hList
, LB_ADDSTRING
, 0, (LPARAM
) "hi3");
1031 ok( id
== 3, "item id wrong\n");
1032 id
= SendMessageA( hList
, LB_ADDSTRING
, 0, (LPARAM
) "hi4");
1033 ok( id
== 4, "item id wrong\n");
1034 id
= SendMessageA( hList
, LB_ADDSTRING
, 0, (LPARAM
) "hi5");
1035 ok( id
== 5, "item id wrong\n");
1036 id
= SendMessageA( hList
, LB_ADDSTRING
, 0, (LPARAM
) "hi6");
1037 ok( id
== 6, "item id wrong\n");
1038 id
= SendMessageA( hList
, LB_ADDSTRING
, 0, (LPARAM
) "hi7");
1039 ok( id
== 7, "item id wrong\n");
1041 /* Set the listbox up so that id 1 is at the top, this leaves 5
1042 partially visible at the bottom and 6, 7 are invisible */
1044 SendMessageA( hList
, LB_SETTOPINDEX
, 1, 0);
1045 r
= SendMessageA( hList
, LB_GETTOPINDEX
, 0, 0);
1046 ok( r
== 1, "top %ld\n", r
);
1048 r
= SendMessageA( hList
, LB_GETITEMRECT
, 5, (LPARAM
)&rc
);
1049 ok( r
== 1, "ret %lx\n", r
);
1050 r
= SendMessageA( hList
, LB_GETITEMRECT
, 6, (LPARAM
)&rc
);
1051 ok( r
== 0, "ret %lx\n", r
);
1053 r
= SendMessageA( hList
, LB_ITEMFROMPOINT
, 0, MAKELPARAM(/* x */ 10, /* y */ 10) );
1054 ok( r
== 1, "ret %lx\n", r
);
1056 r
= SendMessageA( hList
, LB_ITEMFROMPOINT
, 0, MAKELPARAM(1000, 10) );
1057 ok( r
== 0x10001, "ret %lx\n", r
);
1059 r
= SendMessageA( hList
, LB_ITEMFROMPOINT
, 0, MAKELPARAM(10, -10) );
1060 ok( r
== 0x10001, "ret %lx\n", r
);
1062 r
= SendMessageA( hList
, LB_ITEMFROMPOINT
, 0, MAKELPARAM(10, 100) );
1063 ok( r
== 0x10005, "item %lx\n", r
);
1065 r
= SendMessageA( hList
, LB_ITEMFROMPOINT
, 0, MAKELPARAM(10, 200) );
1066 ok( r
== 0x10005, "item %lx\n", r
);
1068 DestroyWindow( hList
);
1071 static void test_listbox_item_data(void)
1076 hList
= CreateWindowA( WC_LISTBOXA
, "list test", 0,
1077 1, 1, 600, 100, NULL
, NULL
, NULL
, NULL
);
1078 ok( hList
!= NULL
, "failed to create listbox\n");
1080 id
= SendMessageA( hList
, LB_ADDSTRING
, 0, (LPARAM
) "hi");
1081 ok( id
== 0, "item id wrong\n");
1083 r
= SendMessageA( hList
, LB_SETITEMDATA
, 0, MAKELPARAM( 20, 0 ));
1084 ok(r
== TRUE
, "LB_SETITEMDATA returned %d instead of TRUE\n", r
);
1086 r
= SendMessageA( hList
, LB_GETITEMDATA
, 0, 0);
1087 ok( r
== 20, "get item data failed\n");
1089 DestroyWindow( hList
);
1092 static void test_listbox_LB_DIR(void)
1094 char path
[MAX_PATH
], curdir
[MAX_PATH
];
1097 int itemCount_justFiles
;
1098 int itemCount_justDrives
;
1099 int itemCount_allFiles
;
1100 int itemCount_allDirs
;
1102 char pathBuffer
[MAX_PATH
];
1105 const char *wildcard
= "*";
1109 GetCurrentDirectoryA(ARRAY_SIZE(curdir
), curdir
);
1111 GetTempPathA(ARRAY_SIZE(path
), path
);
1112 ret
= SetCurrentDirectoryA(path
);
1113 ok(ret
, "Failed to set current directory.\n");
1115 ret
= CreateDirectoryA("lb_dir_test", NULL
);
1116 ok(ret
, "Failed to create test directory.\n");
1118 file
= CreateFileA( "wtest1.tmp.c", GENERIC_READ
|GENERIC_WRITE
, 0, NULL
, CREATE_NEW
, FILE_ATTRIBUTE_NORMAL
, NULL
);
1119 ok(file
!= INVALID_HANDLE_VALUE
, "Error creating the test file: %ld\n", GetLastError());
1120 CloseHandle( file
);
1122 /* NOTE: for this test to succeed, there must be no subdirectories
1123 under the current directory. In addition, there must be at least
1124 one file that fits the wildcard w*.c . Normally, the test
1125 directory itself satisfies both conditions.
1127 hList
= CreateWindowA( WC_LISTBOXA
, "list test", WS_VISIBLE
|WS_POPUP
,
1128 1, 1, 600, 100, NULL
, NULL
, NULL
, NULL
);
1129 ok(hList
!= NULL
, "Failed to create listbox window.\n");
1131 /* Test for standard usage */
1133 /* This should list all the files in the test directory. */
1134 strcpy(pathBuffer
, wildcard
);
1135 SendMessageA(hList
, LB_RESETCONTENT
, 0, 0);
1136 res
= SendMessageA(hList
, LB_DIR
, 0, (LPARAM
)pathBuffer
);
1137 if (res
== -1) /* "*" wildcard doesn't work on win9x */
1140 strcpy(pathBuffer
, wildcard
);
1141 res
= SendMessageA(hList
, LB_DIR
, 0, (LPARAM
)pathBuffer
);
1143 ok (res
>= 0, "SendMessage(LB_DIR, 0, *) failed - 0x%08lx\n", GetLastError());
1145 /* There should be some content in the listbox */
1146 itemCount
= SendMessageA(hList
, LB_GETCOUNT
, 0, 0);
1147 ok (itemCount
> 0, "SendMessage(LB_DIR) did NOT fill the listbox!\n");
1148 itemCount_allFiles
= itemCount
;
1149 ok(res
+ 1 == itemCount
,
1150 "SendMessage(LB_DIR, 0, *) returned incorrect index (expected %d got %d)!\n",
1151 itemCount
- 1, res
);
1153 /* This tests behavior when no files match the wildcard */
1154 strcpy(pathBuffer
, BAD_EXTENSION
);
1155 SendMessageA(hList
, LB_RESETCONTENT
, 0, 0);
1156 res
= SendMessageA(hList
, LB_DIR
, 0, (LPARAM
)pathBuffer
);
1157 ok (res
== -1, "SendMessage(LB_DIR, 0, %s) returned %d, expected -1\n", BAD_EXTENSION
, res
);
1159 /* There should be NO content in the listbox */
1160 itemCount
= SendMessageA(hList
, LB_GETCOUNT
, 0, 0);
1161 ok (itemCount
== 0, "SendMessage(LB_DIR) DID fill the listbox!\n");
1164 /* This should list all the w*.c files in the test directory
1165 * As of this writing, this includes win.c, winstation.c, wsprintf.c
1167 strcpy(pathBuffer
, "w*.c");
1168 SendMessageA(hList
, LB_RESETCONTENT
, 0, 0);
1169 res
= SendMessageA(hList
, LB_DIR
, 0, (LPARAM
)pathBuffer
);
1170 ok (res
>= 0, "SendMessage(LB_DIR, 0, w*.c) failed - 0x%08lx\n", GetLastError());
1172 /* Path specification does NOT converted to uppercase */
1173 ok (!strcmp(pathBuffer
, "w*.c"),
1174 "expected no change to pathBuffer, got %s\n", pathBuffer
);
1176 /* There should be some content in the listbox */
1177 itemCount
= SendMessageA(hList
, LB_GETCOUNT
, 0, 0);
1178 ok (itemCount
> 0, "SendMessage(LB_DIR) did NOT fill the listbox!\n");
1179 itemCount_justFiles
= itemCount
;
1180 ok(res
+ 1 == itemCount
,
1181 "SendMessage(LB_DIR, 0, w*.c) returned incorrect index (expected %d got %d)!\n",
1182 itemCount
- 1, res
);
1184 /* Every single item in the control should start with a w and end in .c */
1185 for (i
= 0; i
< itemCount
; i
++)
1187 memset(pathBuffer
, 0, MAX_PATH
);
1188 SendMessageA(hList
, LB_GETTEXT
, i
, (LPARAM
)pathBuffer
);
1189 p
= pathBuffer
+ strlen(pathBuffer
);
1190 ok(((pathBuffer
[0] == 'w' || pathBuffer
[0] == 'W') &&
1191 (*(p
-1) == 'c' || *(p
-1) == 'C') &&
1192 (*(p
-2) == '.')), "Element %d (%s) does not fit requested w*.c\n", i
, pathBuffer
);
1195 /* Test DDL_DIRECTORY */
1196 strcpy(pathBuffer
, wildcard
);
1197 SendMessageA(hList
, LB_RESETCONTENT
, 0, 0);
1198 res
= SendMessageA(hList
, LB_DIR
, DDL_DIRECTORY
, (LPARAM
)pathBuffer
);
1199 ok (res
> 0, "SendMessage(LB_DIR, DDL_DIRECTORY, *) failed - 0x%08lx\n", GetLastError());
1201 /* There should be some content in the listbox.
1202 * All files plus "[..]"
1204 itemCount
= SendMessageA(hList
, LB_GETCOUNT
, 0, 0);
1205 itemCount_allDirs
= itemCount
- itemCount_allFiles
;
1206 ok (itemCount
>= itemCount_allFiles
,
1207 "SendMessage(LB_DIR, DDL_DIRECTORY, *) filled with %d entries, expected > %d\n",
1208 itemCount
, itemCount_allFiles
);
1209 ok(res
+ 1 == itemCount
,
1210 "SendMessage(LB_DIR, DDL_DIRECTORY, *) returned incorrect index (expected %d got %d)!\n",
1211 itemCount
- 1, res
);
1213 /* This tests behavior when no files match the wildcard */
1214 strcpy(pathBuffer
, BAD_EXTENSION
);
1215 SendMessageA(hList
, LB_RESETCONTENT
, 0, 0);
1216 res
= SendMessageA(hList
, LB_DIR
, DDL_DIRECTORY
, (LPARAM
)pathBuffer
);
1217 ok (res
== -1, "SendMessage(LB_DIR, DDL_DIRECTORY, %s) returned %d, expected -1\n", BAD_EXTENSION
, res
);
1219 /* There should be NO content in the listbox */
1220 itemCount
= SendMessageA(hList
, LB_GETCOUNT
, 0, 0);
1221 ok (itemCount
== 0, "SendMessage(LB_DIR) DID fill the listbox!\n");
1223 /* Test DDL_DIRECTORY */
1224 strcpy(pathBuffer
, "w*.c");
1225 SendMessageA(hList
, LB_RESETCONTENT
, 0, 0);
1226 res
= SendMessageA(hList
, LB_DIR
, DDL_DIRECTORY
, (LPARAM
)pathBuffer
);
1227 ok (res
>= 0, "SendMessage(LB_DIR, DDL_DIRECTORY, w*.c) failed - 0x%08lx\n", GetLastError());
1229 /* There should be some content in the listbox. Since the parent directory does not
1230 * fit w*.c, there should be exactly the same number of items as without DDL_DIRECTORY
1232 itemCount
= SendMessageA(hList
, LB_GETCOUNT
, 0, 0);
1233 ok (itemCount
== itemCount_justFiles
,
1234 "SendMessage(LB_DIR, DDL_DIRECTORY, w*.c) filled with %d entries, expected %d\n",
1235 itemCount
, itemCount_justFiles
);
1236 ok(res
+ 1 == itemCount
,
1237 "SendMessage(LB_DIR, DDL_DIRECTORY, w*.c) returned incorrect index (expected %d got %d)!\n",
1238 itemCount
- 1, res
);
1240 /* Every single item in the control should start with a w and end in .c. */
1241 for (i
= 0; i
< itemCount
; i
++)
1243 memset(pathBuffer
, 0, MAX_PATH
);
1244 SendMessageA(hList
, LB_GETTEXT
, i
, (LPARAM
)pathBuffer
);
1245 p
= pathBuffer
+ strlen(pathBuffer
);
1247 ((pathBuffer
[0] == 'w' || pathBuffer
[0] == 'W') &&
1248 (*(p
-1) == 'c' || *(p
-1) == 'C') &&
1249 (*(p
-2) == '.')), "Element %d (%s) does not fit requested w*.c\n", i
, pathBuffer
);
1252 /* Test DDL_DRIVES|DDL_EXCLUSIVE */
1253 strcpy(pathBuffer
, wildcard
);
1254 SendMessageA(hList
, LB_RESETCONTENT
, 0, 0);
1255 res
= SendMessageA(hList
, LB_DIR
, DDL_DRIVES
|DDL_EXCLUSIVE
, (LPARAM
)pathBuffer
);
1256 ok (res
>= 0, "SendMessage(LB_DIR, DDL_DRIVES|DDL_EXCLUSIVE, *) failed - 0x%08lx\n", GetLastError());
1258 /* There should be some content in the listbox. In particular, there should
1259 * be at least one element before, since the string "[-c-]" should
1260 * have been added. Depending on the user setting, more drives might have
1263 itemCount
= SendMessageA(hList
, LB_GETCOUNT
, 0, 0);
1265 "SendMessage(LB_DIR, DDL_DRIVES|DDL_EXCLUSIVE, *) filled with %d entries, expected at least %d\n",
1267 itemCount_justDrives
= itemCount
;
1268 ok(res
+ 1 == itemCount
, "SendMessage(LB_DIR, DDL_DRIVES|DDL_EXCLUSIVE, *) returned incorrect index!\n");
1270 /* Every single item in the control should fit the format [-c-] */
1271 for (i
= 0; i
< itemCount
; i
++)
1273 memset(pathBuffer
, 0, MAX_PATH
);
1275 SendMessageA(hList
, LB_GETTEXT
, i
, (LPARAM
)pathBuffer
);
1276 ok( strlen(pathBuffer
) == 5, "Length of drive string is not 5\n" );
1277 ok( sscanf(pathBuffer
, "[-%c-]", &driveletter
) == 1, "Element %d (%s) does not fit [-X-]\n", i
, pathBuffer
);
1278 ok( driveletter
>= 'a' && driveletter
<= 'z', "Drive letter not in range a..z, got ascii %d\n", driveletter
);
1279 if (!(driveletter
>= 'a' && driveletter
<= 'z'))
1281 /* Correct after invalid entry is found */
1282 itemCount_justDrives
--;
1286 /* This tests behavior when no files match the wildcard */
1287 strcpy(pathBuffer
, BAD_EXTENSION
);
1288 SendMessageA(hList
, LB_RESETCONTENT
, 0, 0);
1289 res
= SendMessageA(hList
, LB_DIR
, DDL_DRIVES
|DDL_EXCLUSIVE
, (LPARAM
)pathBuffer
);
1290 ok (res
== itemCount_justDrives
-1, "SendMessage(LB_DIR, DDL_DRIVES|DDL_EXCLUSIVE, %s) returned %d, expected %d\n",
1291 BAD_EXTENSION
, res
, itemCount_justDrives
-1);
1293 itemCount
= SendMessageA(hList
, LB_GETCOUNT
, 0, 0);
1294 ok (itemCount
== itemCount_justDrives
, "SendMessage(LB_DIR) returned %d expected %d\n",
1295 itemCount
, itemCount_justDrives
);
1297 /* Test DDL_DRIVES. */
1298 strcpy(pathBuffer
, wildcard
);
1299 SendMessageA(hList
, LB_RESETCONTENT
, 0, 0);
1300 res
= SendMessageA(hList
, LB_DIR
, DDL_DRIVES
, (LPARAM
)pathBuffer
);
1301 ok (res
> 0, "SendMessage(LB_DIR, DDL_DRIVES, *) failed - 0x%08lx\n", GetLastError());
1303 /* There should be some content in the listbox. In particular, there should
1304 * be at least one element before, since the string "[-c-]" should
1305 * have been added. Depending on the user setting, more drives might have
1308 itemCount
= SendMessageA(hList
, LB_GETCOUNT
, 0, 0);
1309 ok (itemCount
== itemCount_justDrives
+ itemCount_allFiles
,
1310 "SendMessage(LB_DIR, DDL_DRIVES, *) filled with %d entries, expected %d\n",
1311 itemCount
, itemCount_justDrives
+ itemCount_allFiles
);
1312 ok(res
+ 1 == itemCount
, "SendMessage(LB_DIR, DDL_DRIVES, *) returned incorrect index!\n");
1314 /* This tests behavior when no files match the wildcard */
1315 strcpy(pathBuffer
, BAD_EXTENSION
);
1316 SendMessageA(hList
, LB_RESETCONTENT
, 0, 0);
1317 res
= SendMessageA(hList
, LB_DIR
, DDL_DRIVES
, (LPARAM
)pathBuffer
);
1318 ok (res
== itemCount_justDrives
-1, "SendMessage(LB_DIR, DDL_DRIVES, %s) returned %d, expected %d\n",
1319 BAD_EXTENSION
, res
, itemCount_justDrives
-1);
1321 itemCount
= SendMessageA(hList
, LB_GETCOUNT
, 0, 0);
1322 ok (itemCount
== res
+ 1, "SendMessage(LB_DIR) returned %d expected %d\n", itemCount
, res
+ 1);
1324 /* Test DDL_DRIVES. */
1325 strcpy(pathBuffer
, "w*.c");
1326 SendMessageA(hList
, LB_RESETCONTENT
, 0, 0);
1327 res
= SendMessageA(hList
, LB_DIR
, DDL_DRIVES
, (LPARAM
)pathBuffer
);
1328 ok (res
> 0, "SendMessage(LB_DIR, DDL_DRIVES, w*.c) failed - 0x%08lx\n", GetLastError());
1330 /* There should be some content in the listbox. In particular, there should
1331 * be at least one element before, since the string "[-c-]" should
1332 * have been added. Depending on the user setting, more drives might have
1335 itemCount
= SendMessageA(hList
, LB_GETCOUNT
, 0, 0);
1336 ok (itemCount
== itemCount_justDrives
+ itemCount_justFiles
,
1337 "SendMessage(LB_DIR, DDL_DRIVES, w*.c) filled with %d entries, expected %d\n",
1338 itemCount
, itemCount_justDrives
+ itemCount_justFiles
);
1339 ok(res
+ 1 == itemCount
, "SendMessage(LB_DIR, DDL_DRIVES, w*.c) returned incorrect index!\n");
1341 /* Every single item in the control should fit the format [-c-], or w*.c */
1342 for (i
= 0; i
< itemCount
; i
++)
1344 memset(pathBuffer
, 0, MAX_PATH
);
1346 SendMessageA(hList
, LB_GETTEXT
, i
, (LPARAM
)pathBuffer
);
1347 p
= pathBuffer
+ strlen(pathBuffer
);
1348 if (sscanf(pathBuffer
, "[-%c-]", &driveletter
) == 1)
1350 ok( strlen(pathBuffer
) == 5, "Length of drive string is not 5\n" );
1351 ok( driveletter
>= 'a' && driveletter
<= 'z', "Drive letter not in range a..z, got ascii %d\n", driveletter
);
1356 ((pathBuffer
[0] == 'w' || pathBuffer
[0] == 'W') &&
1357 (*(p
-1) == 'c' || *(p
-1) == 'C') &&
1358 (*(p
-2) == '.')), "Element %d (%s) does not fit requested w*.c\n", i
, pathBuffer
);
1362 /* Test DDL_DIRECTORY|DDL_DRIVES. This does *not* imply DDL_EXCLUSIVE */
1363 strcpy(pathBuffer
, wildcard
);
1364 SendMessageA(hList
, LB_RESETCONTENT
, 0, 0);
1365 res
= SendMessageA(hList
, LB_DIR
, DDL_DIRECTORY
|DDL_DRIVES
, (LPARAM
)pathBuffer
);
1366 ok (res
> 0, "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_DRIVES, *) failed - 0x%08lx\n", GetLastError());
1368 /* There should be some content in the listbox. In particular, there should
1369 * be exactly the number of plain files, plus the number of mapped drives.
1371 itemCount
= SendMessageA(hList
, LB_GETCOUNT
, 0, 0);
1372 ok (itemCount
== itemCount_allFiles
+ itemCount_justDrives
+ itemCount_allDirs
,
1373 "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_DRIVES) filled with %d entries, expected %d\n",
1374 itemCount
, itemCount_allFiles
+ itemCount_justDrives
+ itemCount_allDirs
);
1375 ok(res
+ 1 == itemCount
, "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_DRIVES, w*.c) returned incorrect index!\n");
1377 /* Every single item in the control should start with a w and end in .c,
1378 * except for the "[..]" string, which should appear exactly as it is,
1379 * and the mapped drives in the format "[-X-]".
1381 for (i
= 0; i
< itemCount
; i
++)
1383 memset(pathBuffer
, 0, MAX_PATH
);
1385 SendMessageA(hList
, LB_GETTEXT
, i
, (LPARAM
)pathBuffer
);
1386 if (sscanf(pathBuffer
, "[-%c-]", &driveletter
) == 1)
1387 ok( driveletter
>= 'a' && driveletter
<= 'z', "Drive letter not in range a..z, got ascii %d\n", driveletter
);
1390 /* This tests behavior when no files match the wildcard */
1391 strcpy(pathBuffer
, BAD_EXTENSION
);
1392 SendMessageA(hList
, LB_RESETCONTENT
, 0, 0);
1393 res
= SendMessageA(hList
, LB_DIR
, DDL_DIRECTORY
|DDL_DRIVES
, (LPARAM
)pathBuffer
);
1394 ok (res
== itemCount_justDrives
-1, "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_DRIVES, %s) returned %d, expected %d\n",
1395 BAD_EXTENSION
, res
, itemCount_justDrives
-1);
1397 itemCount
= SendMessageA(hList
, LB_GETCOUNT
, 0, 0);
1398 ok (itemCount
== res
+ 1, "SendMessage(LB_DIR) returned %d expected %d\n", itemCount
, res
+ 1);
1400 /* Test DDL_DIRECTORY|DDL_DRIVES. */
1401 strcpy(pathBuffer
, "w*.c");
1402 SendMessageA(hList
, LB_RESETCONTENT
, 0, 0);
1403 res
= SendMessageA(hList
, LB_DIR
, DDL_DIRECTORY
|DDL_DRIVES
, (LPARAM
)pathBuffer
);
1404 ok (res
> 0, "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_DRIVES, w*.c) failed - 0x%08lx\n", GetLastError());
1406 /* There should be some content in the listbox. In particular, there should
1407 * be exactly the number of plain files, plus the number of mapped drives.
1409 itemCount
= SendMessageA(hList
, LB_GETCOUNT
, 0, 0);
1410 ok (itemCount
== itemCount_justFiles
+ itemCount_justDrives
,
1411 "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_DRIVES) filled with %d entries, expected %d\n",
1412 itemCount
, itemCount_justFiles
+ itemCount_justDrives
);
1413 ok(res
+ 1 == itemCount
, "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_DRIVES, w*.c) returned incorrect index!\n");
1415 /* Every single item in the control should start with a w and end in .c,
1416 * except the mapped drives in the format "[-X-]". The "[..]" directory
1417 * should not appear.
1419 for (i
= 0; i
< itemCount
; i
++)
1421 memset(pathBuffer
, 0, MAX_PATH
);
1423 SendMessageA(hList
, LB_GETTEXT
, i
, (LPARAM
)pathBuffer
);
1424 p
= pathBuffer
+ strlen(pathBuffer
);
1425 if (sscanf(pathBuffer
, "[-%c-]", &driveletter
) == 1)
1426 ok( driveletter
>= 'a' && driveletter
<= 'z', "Drive letter not in range a..z, got ascii %d\n", driveletter
);
1429 ((pathBuffer
[0] == 'w' || pathBuffer
[0] == 'W') &&
1430 (*(p
-1) == 'c' || *(p
-1) == 'C') &&
1431 (*(p
-2) == '.')), "Element %d (%s) does not fit requested w*.c\n", i
, pathBuffer
);
1434 /* Test DDL_DIRECTORY|DDL_EXCLUSIVE. */
1435 strcpy(pathBuffer
, wildcard
);
1436 SendMessageA(hList
, LB_RESETCONTENT
, 0, 0);
1437 res
= SendMessageA(hList
, LB_DIR
, DDL_DIRECTORY
|DDL_EXCLUSIVE
, (LPARAM
)pathBuffer
);
1438 ok (res
!= -1, "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_EXCLUSIVE, *) failed err %lu\n",
1441 itemCount
= SendMessageA(hList
, LB_GETCOUNT
, 0, 0);
1442 ok (itemCount
== itemCount_allDirs
,
1443 "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_EXCLUSIVE) filled with %d entries, expected %d\n",
1444 itemCount
, itemCount_allDirs
);
1445 ok(res
+ 1 == itemCount
, "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_EXCLUSIVE, *) returned incorrect index!\n");
1449 memset(pathBuffer
, 0, MAX_PATH
);
1450 SendMessageA(hList
, LB_GETTEXT
, 0, (LPARAM
)pathBuffer
);
1451 ok( !strcmp(pathBuffer
, "[..]"), "First element is %s, not [..]\n", pathBuffer
);
1454 /* This tests behavior when no files match the wildcard */
1455 strcpy(pathBuffer
, BAD_EXTENSION
);
1456 SendMessageA(hList
, LB_RESETCONTENT
, 0, 0);
1457 res
= SendMessageA(hList
, LB_DIR
, DDL_DIRECTORY
|DDL_EXCLUSIVE
, (LPARAM
)pathBuffer
);
1458 ok (res
== -1, "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_EXCLUSIVE, %s) returned %d, expected %d\n",
1459 BAD_EXTENSION
, res
, -1);
1461 itemCount
= SendMessageA(hList
, LB_GETCOUNT
, 0, 0);
1462 ok (itemCount
== res
+ 1, "SendMessage(LB_DIR) returned %d expected %d\n", itemCount
, res
+ 1);
1465 /* Test DDL_DIRECTORY|DDL_EXCLUSIVE. */
1466 strcpy(pathBuffer
, "w*.c");
1467 SendMessageA(hList
, LB_RESETCONTENT
, 0, 0);
1468 res
= SendMessageA(hList
, LB_DIR
, DDL_DIRECTORY
|DDL_EXCLUSIVE
, (LPARAM
)pathBuffer
);
1469 ok (res
== LB_ERR
, "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_EXCLUSIVE, w*.c) returned %d expected %d\n", res
, LB_ERR
);
1471 /* There should be no elements, since "[..]" does not fit w*.c */
1472 itemCount
= SendMessageA(hList
, LB_GETCOUNT
, 0, 0);
1474 "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_EXCLUSIVE) filled with %d entries, expected %d\n",
1477 /* Test DDL_DIRECTORY|DDL_DRIVES|DDL_EXCLUSIVE. */
1478 strcpy(pathBuffer
, wildcard
);
1479 SendMessageA(hList
, LB_RESETCONTENT
, 0, 0);
1480 res
= SendMessageA(hList
, LB_DIR
, DDL_DIRECTORY
|DDL_DRIVES
|DDL_EXCLUSIVE
, (LPARAM
)pathBuffer
);
1481 ok (res
> 0, "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_DRIVES|DDL_EXCLUSIVE, w*.c,) failed - 0x%08lx\n", GetLastError());
1483 /* There should be no plain files on the listbox */
1484 itemCount
= SendMessageA(hList
, LB_GETCOUNT
, 0, 0);
1485 ok (itemCount
== itemCount_justDrives
+ itemCount_allDirs
,
1486 "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_DRIVES|DDL_EXCLUSIVE) filled with %d entries, expected %d\n",
1487 itemCount
, itemCount_justDrives
+ itemCount_allDirs
);
1488 ok(res
+ 1 == itemCount
, "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_DRIVES|DDL_EXCLUSIVE, w*.c) returned incorrect index!\n");
1490 for (i
= 0; i
< itemCount
; i
++)
1492 memset(pathBuffer
, 0, MAX_PATH
);
1494 SendMessageA(hList
, LB_GETTEXT
, i
, (LPARAM
)pathBuffer
);
1495 if (sscanf(pathBuffer
, "[-%c-]", &driveletter
) == 1)
1496 ok( driveletter
>= 'a' && driveletter
<= 'z', "Drive letter not in range a..z, got ascii %d\n", driveletter
);
1498 ok( pathBuffer
[0] == '[' && pathBuffer
[strlen(pathBuffer
)-1] == ']',
1499 "Element %d (%s) does not fit expected [...]\n", i
, pathBuffer
);
1502 /* This tests behavior when no files match the wildcard */
1503 strcpy(pathBuffer
, BAD_EXTENSION
);
1504 SendMessageA(hList
, LB_RESETCONTENT
, 0, 0);
1505 res
= SendMessageA(hList
, LB_DIR
, DDL_DIRECTORY
|DDL_DRIVES
|DDL_EXCLUSIVE
, (LPARAM
)pathBuffer
);
1506 ok (res
== itemCount_justDrives
-1, "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_DRIVES|DDL_EXCLUSIVE, %s) returned %d, expected %d\n",
1507 BAD_EXTENSION
, res
, itemCount_justDrives
-1);
1509 itemCount
= SendMessageA(hList
, LB_GETCOUNT
, 0, 0);
1510 ok (itemCount
== res
+ 1, "SendMessage(LB_DIR) returned %d expected %d\n", itemCount
, res
+ 1);
1512 /* Test DDL_DIRECTORY|DDL_DRIVES|DDL_EXCLUSIVE. */
1513 strcpy(pathBuffer
, "w*.c");
1514 SendMessageA(hList
, LB_RESETCONTENT
, 0, 0);
1515 res
= SendMessageA(hList
, LB_DIR
, DDL_DIRECTORY
|DDL_DRIVES
|DDL_EXCLUSIVE
, (LPARAM
)pathBuffer
);
1516 ok (res
>= 0, "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_DRIVES|DDL_EXCLUSIVE, w*.c,) failed - 0x%08lx\n", GetLastError());
1518 /* There should be no plain files on the listbox, and no [..], since it does not fit w*.c */
1519 itemCount
= SendMessageA(hList
, LB_GETCOUNT
, 0, 0);
1520 ok (itemCount
== itemCount_justDrives
,
1521 "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_DRIVES|DDL_EXCLUSIVE) filled with %d entries, expected %d\n",
1522 itemCount
, itemCount_justDrives
);
1523 ok(res
+ 1 == itemCount
, "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_DRIVES|DDL_EXCLUSIVE, w*.c) returned incorrect index!\n");
1525 for (i
= 0; i
< itemCount
; i
++)
1527 memset(pathBuffer
, 0, MAX_PATH
);
1529 SendMessageA(hList
, LB_GETTEXT
, i
, (LPARAM
)pathBuffer
);
1530 ok (sscanf(pathBuffer
, "[-%c-]", &driveletter
) == 1, "Element %d (%s) does not fit [-X-]\n", i
, pathBuffer
);
1531 ok( driveletter
>= 'a' && driveletter
<= 'z', "Drive letter not in range a..z, got ascii %d\n", driveletter
);
1533 DestroyWindow(hList
);
1535 DeleteFileA( "wtest1.tmp.c" );
1536 RemoveDirectoryA("lb_dir_test");
1538 SetCurrentDirectoryA(curdir
);
1541 static HWND g_listBox
;
1542 static HWND g_label
;
1544 #define ID_TEST_LABEL 1001
1545 #define ID_TEST_LISTBOX 1002
1547 static BOOL
on_listbox_container_create(HWND hwnd
, CREATESTRUCTA
*lpcs
)
1549 g_label
= CreateWindowA(WC_STATICA
, "Contents of static control before DlgDirList.",
1550 WS_CHILD
| WS_VISIBLE
, 10, 10, 512, 32, hwnd
, (HMENU
)ID_TEST_LABEL
, NULL
, 0);
1551 if (!g_label
) return FALSE
;
1553 g_listBox
= CreateWindowA(WC_LISTBOXA
, "DlgDirList test",
1554 WS_CHILD
| WS_VISIBLE
| WS_TABSTOP
| WS_BORDER
| WS_VSCROLL
, 10, 60, 256, 256,
1555 hwnd
, (HMENU
)ID_TEST_LISTBOX
, NULL
, 0);
1556 if (!g_listBox
) return FALSE
;
1561 static LRESULT CALLBACK
listbox_container_window_procA(HWND hwnd
, UINT uiMsg
, WPARAM wParam
, LPARAM lParam
)
1571 result
= on_listbox_container_create(hwnd
, (CREATESTRUCTA
*)lParam
) ? 0 : (LRESULT
)-1;
1574 result
= DefWindowProcA(hwnd
, uiMsg
, wParam
, lParam
);
1580 static BOOL
RegisterListboxWindowClass(HINSTANCE hInst
)
1587 cls
.hInstance
= hInst
;
1589 cls
.hCursor
= LoadCursorA (NULL
, (LPCSTR
)IDC_ARROW
);
1590 cls
.hbrBackground
= (HBRUSH
)(COLOR_WINDOW
+ 1);
1591 cls
.lpszMenuName
= NULL
;
1592 cls
.lpfnWndProc
= listbox_container_window_procA
;
1593 cls
.lpszClassName
= "ListboxContainerClass";
1594 if (!RegisterClassA (&cls
)) return FALSE
;
1599 static void test_listbox_dlgdir(void)
1604 int itemCount_allDirs
;
1605 int itemCount_justFiles
;
1606 int itemCount_justDrives
;
1608 char pathBuffer
[MAX_PATH
];
1609 char itemBuffer
[MAX_PATH
];
1610 char tempBuffer
[MAX_PATH
];
1616 file
= CreateFileA( "wtest1.tmp.c", GENERIC_READ
|GENERIC_WRITE
, 0, NULL
, CREATE_NEW
, FILE_ATTRIBUTE_NORMAL
, NULL
);
1617 ok(file
!= INVALID_HANDLE_VALUE
, "Error creating the test file: %ld\n", GetLastError());
1618 CloseHandle( file
);
1620 /* NOTE: for this test to succeed, there must be no subdirectories
1621 under the current directory. In addition, there must be at least
1622 one file that fits the wildcard w*.c . Normally, the test
1623 directory itself satisfies both conditions.
1626 hInst
= GetModuleHandleA(0);
1627 ret
= RegisterListboxWindowClass(hInst
);
1628 ok(ret
, "Failed to register test class.\n");
1630 hWnd
= CreateWindowA("ListboxContainerClass", "ListboxContainerClass",
1631 WS_OVERLAPPEDWINDOW
| WS_VISIBLE
,
1632 CW_USEDEFAULT
, CW_USEDEFAULT
, CW_USEDEFAULT
, CW_USEDEFAULT
,
1633 NULL
, NULL
, hInst
, 0);
1634 ok(hWnd
!= NULL
, "Failed to create container window.\n");
1636 /* Test for standard usage */
1638 /* The following should be overwritten by the directory path */
1639 SendMessageA(g_label
, WM_SETTEXT
, 0, (LPARAM
)"default contents");
1641 /* This should list all the w*.c files in the test directory
1642 * As of this writing, this includes win.c, winstation.c, wsprintf.c
1644 strcpy(pathBuffer
, "w*.c");
1645 res
= DlgDirListA(hWnd
, pathBuffer
, ID_TEST_LISTBOX
, ID_TEST_LABEL
, 0);
1646 ok (res
== 1, "DlgDirList(*.c, 0) returned %d - expected 1 - 0x%08lx\n", res
, GetLastError());
1648 /* Path specification gets converted to uppercase */
1649 ok (!strcmp(pathBuffer
, "W*.C"),
1650 "expected conversion to uppercase, got %s\n", pathBuffer
);
1652 /* Loaded path should have overwritten the label text */
1653 SendMessageA(g_label
, WM_GETTEXT
, MAX_PATH
, (LPARAM
)pathBuffer
);
1654 ok (strcmp("default contents", pathBuffer
), "DlgDirList() did not modify static control!\n");
1656 /* There should be some content in the listbox */
1657 itemCount
= SendMessageA(g_listBox
, LB_GETCOUNT
, 0, 0);
1658 ok (itemCount
> 0, "DlgDirList() did NOT fill the listbox!\n");
1659 itemCount_justFiles
= itemCount
;
1661 /* Every single item in the control should start with a w and end in .c */
1662 for (i
= 0; i
< itemCount
; i
++)
1664 memset(pathBuffer
, 0, MAX_PATH
);
1665 SendMessageA(g_listBox
, LB_GETTEXT
, i
, (LPARAM
)pathBuffer
);
1666 p
= pathBuffer
+ strlen(pathBuffer
);
1667 ok(((pathBuffer
[0] == 'w' || pathBuffer
[0] == 'W') &&
1668 (*(p
-1) == 'c' || *(p
-1) == 'C') &&
1669 (*(p
-2) == '.')), "Element %d (%s) does not fit requested w*.c\n", i
, pathBuffer
);
1672 /* Test behavior when no files match the wildcard */
1673 strcpy(pathBuffer
, BAD_EXTENSION
);
1674 res
= DlgDirListA(hWnd
, pathBuffer
, ID_TEST_LISTBOX
, ID_TEST_LABEL
, 0);
1675 ok (res
== 1, "DlgDirList(%s, 0) returned %d expected 1\n", BAD_EXTENSION
, res
);
1677 itemCount
= SendMessageA(g_listBox
, LB_GETCOUNT
, 0, 0);
1678 ok (itemCount
== 0, "DlgDirList() DID fill the listbox!\n");
1680 /* Test DDL_DIRECTORY */
1681 strcpy(pathBuffer
, "w*.c");
1682 res
= DlgDirListA(hWnd
, pathBuffer
, ID_TEST_LISTBOX
, ID_TEST_LABEL
, DDL_DIRECTORY
);
1683 ok (res
== 1, "DlgDirList(*.c, DDL_DIRECTORY) failed - 0x%08lx\n", GetLastError());
1685 /* There should be some content in the listbox. In particular, there should
1686 * be exactly more elements than before, since the directories should
1689 itemCount
= SendMessageA(g_listBox
, LB_GETCOUNT
, 0, 0);
1690 itemCount_allDirs
= itemCount
- itemCount_justFiles
;
1691 ok (itemCount
>= itemCount_justFiles
, "DlgDirList(DDL_DIRECTORY) filled with %d entries, expected > %d\n",
1692 itemCount
, itemCount_justFiles
);
1694 /* Every single item in the control should start with a w and end in .c,
1695 * except for the "[..]" string, which should appear exactly as it is.
1697 for (i
= 0; i
< itemCount
; i
++)
1699 memset(pathBuffer
, 0, MAX_PATH
);
1700 SendMessageA(g_listBox
, LB_GETTEXT
, i
, (LPARAM
)pathBuffer
);
1701 p
= pathBuffer
+ strlen(pathBuffer
);
1702 ok( (pathBuffer
[0] == '[' && pathBuffer
[strlen(pathBuffer
)-1] == ']') ||
1703 ((pathBuffer
[0] == 'w' || pathBuffer
[0] == 'W') &&
1704 (*(p
-1) == 'c' || *(p
-1) == 'C') &&
1705 (*(p
-2) == '.')), "Element %d (%s) does not fit requested w*.c\n", i
, pathBuffer
);
1708 /* Test behavior when no files match the wildcard */
1709 strcpy(pathBuffer
, BAD_EXTENSION
);
1710 res
= DlgDirListA(hWnd
, pathBuffer
, ID_TEST_LISTBOX
, ID_TEST_LABEL
, DDL_DIRECTORY
);
1711 ok (res
== 1, "DlgDirList(%s, DDL_DIRECTORY) returned %d expected 1\n", BAD_EXTENSION
, res
);
1713 itemCount
= SendMessageA(g_listBox
, LB_GETCOUNT
, 0, 0);
1714 ok (itemCount
== itemCount_allDirs
, "DlgDirList() incorrectly filled the listbox! (expected %d got %d)\n",
1715 itemCount_allDirs
, itemCount
);
1716 for (i
= 0; i
< itemCount
; i
++)
1718 memset(pathBuffer
, 0, MAX_PATH
);
1719 SendMessageA(g_listBox
, LB_GETTEXT
, i
, (LPARAM
)pathBuffer
);
1720 ok( pathBuffer
[0] == '[' && pathBuffer
[strlen(pathBuffer
)-1] == ']',
1721 "Element %d (%s) does not fit requested [...]\n", i
, pathBuffer
);
1724 /* Test DDL_DRIVES. At least on WinXP-SP2, this implies DDL_EXCLUSIVE */
1725 strcpy(pathBuffer
, "w*.c");
1726 res
= DlgDirListA(hWnd
, pathBuffer
, ID_TEST_LISTBOX
, ID_TEST_LABEL
, DDL_DRIVES
);
1727 ok (res
== 1, "DlgDirList(*.c, DDL_DRIVES) failed - 0x%08lx\n", GetLastError());
1729 /* There should be some content in the listbox. In particular, there should
1730 * be at least one element before, since the string "[-c-]" should
1731 * have been added. Depending on the user setting, more drives might have
1734 itemCount
= SendMessageA(g_listBox
, LB_GETCOUNT
, 0, 0);
1736 "DlgDirList(DDL_DRIVES) filled with %d entries, expected at least %d\n",
1738 itemCount_justDrives
= itemCount
;
1740 /* Every single item in the control should fit the format [-c-] */
1741 for (i
= 0; i
< itemCount
; i
++)
1743 memset(pathBuffer
, 0, MAX_PATH
);
1745 SendMessageA(g_listBox
, LB_GETTEXT
, i
, (LPARAM
)pathBuffer
);
1746 ok( strlen(pathBuffer
) == 5, "Length of drive string is not 5\n" );
1747 ok( sscanf(pathBuffer
, "[-%c-]", &driveletter
) == 1, "Element %d (%s) does not fit [-X-]\n", i
, pathBuffer
);
1748 ok( driveletter
>= 'a' && driveletter
<= 'z', "Drive letter not in range a..z, got ascii %d\n", driveletter
);
1749 if (!(driveletter
>= 'a' && driveletter
<= 'z')) {
1750 /* Correct after invalid entry is found */
1751 trace("removing count of invalid entry %s\n", pathBuffer
);
1752 itemCount_justDrives
--;
1756 /* Test behavior when no files match the wildcard */
1757 strcpy(pathBuffer
, BAD_EXTENSION
);
1758 res
= DlgDirListA(hWnd
, pathBuffer
, ID_TEST_LISTBOX
, ID_TEST_LABEL
, DDL_DRIVES
);
1759 ok (res
== 1, "DlgDirList(%s, DDL_DRIVES) returned %d expected 1\n", BAD_EXTENSION
, res
);
1761 itemCount
= SendMessageA(g_listBox
, LB_GETCOUNT
, 0, 0);
1762 ok (itemCount
== itemCount_justDrives
, "DlgDirList() incorrectly filled the listbox!\n");
1764 /* Test DDL_DIRECTORY|DDL_DRIVES. This does *not* imply DDL_EXCLUSIVE */
1765 strcpy(pathBuffer
, "w*.c");
1766 res
= DlgDirListA(hWnd
, pathBuffer
, ID_TEST_LISTBOX
, ID_TEST_LABEL
, DDL_DIRECTORY
|DDL_DRIVES
);
1767 ok (res
== 1, "DlgDirList(*.c, DDL_DIRECTORY|DDL_DRIVES) failed - 0x%08lx\n", GetLastError());
1769 /* There should be some content in the listbox. In particular, there should
1770 * be exactly the number of plain files, plus the number of mapped drives,
1773 itemCount
= SendMessageA(g_listBox
, LB_GETCOUNT
, 0, 0);
1774 ok (itemCount
== itemCount_justFiles
+ itemCount_justDrives
+ itemCount_allDirs
,
1775 "DlgDirList(DDL_DIRECTORY|DDL_DRIVES) filled with %d entries, expected %d\n",
1776 itemCount
, itemCount_justFiles
+ itemCount_justDrives
+ itemCount_allDirs
);
1778 /* Every single item in the control should start with a w and end in .c,
1779 * except for the "[..]" string, which should appear exactly as it is,
1780 * and the mapped drives in the format "[-X-]".
1782 for (i
= 0; i
< itemCount
; i
++)
1784 memset(pathBuffer
, 0, MAX_PATH
);
1786 SendMessageA(g_listBox
, LB_GETTEXT
, i
, (LPARAM
)pathBuffer
);
1787 p
= pathBuffer
+ strlen(pathBuffer
);
1788 if (sscanf(pathBuffer
, "[-%c-]", &driveletter
) == 1)
1789 ok( driveletter
>= 'a' && driveletter
<= 'z', "Drive letter not in range a..z, got ascii %d\n", driveletter
);
1791 ok( (pathBuffer
[0] == '[' && pathBuffer
[strlen(pathBuffer
)-1] == ']') ||
1792 ((pathBuffer
[0] == 'w' || pathBuffer
[0] == 'W') &&
1793 (*(p
-1) == 'c' || *(p
-1) == 'C') &&
1794 (*(p
-2) == '.')), "Element %d (%s) does not fit requested w*.c\n", i
, pathBuffer
);
1797 /* Test behavior when no files match the wildcard */
1798 strcpy(pathBuffer
, BAD_EXTENSION
);
1799 res
= DlgDirListA(hWnd
, pathBuffer
, ID_TEST_LISTBOX
, ID_TEST_LABEL
, DDL_DIRECTORY
|DDL_DRIVES
);
1800 ok (res
== 1, "DlgDirList(%s, DDL_DIRECTORY|DDL_DRIVES) returned %d expected 1\n", BAD_EXTENSION
, res
);
1802 itemCount
= SendMessageA(g_listBox
, LB_GETCOUNT
, 0, 0);
1803 ok (itemCount
== itemCount_justDrives
+ itemCount_allDirs
,
1804 "DlgDirList() incorrectly filled the listbox! (expected %d got %d)\n",
1805 itemCount_justDrives
+ itemCount_allDirs
, itemCount
);
1807 /* Test DDL_DIRECTORY|DDL_EXCLUSIVE. */
1808 strcpy(pathBuffer
, "w*.c");
1809 res
= DlgDirListA(hWnd
, pathBuffer
, ID_TEST_LISTBOX
, ID_TEST_LABEL
, DDL_DIRECTORY
|DDL_EXCLUSIVE
);
1810 ok (res
== 1, "DlgDirList(*.c, DDL_DIRECTORY|DDL_EXCLUSIVE) failed - 0x%08lx\n", GetLastError());
1812 /* There should be exactly one element: "[..]" */
1813 itemCount
= SendMessageA(g_listBox
, LB_GETCOUNT
, 0, 0);
1814 ok (itemCount
== itemCount_allDirs
,
1815 "DlgDirList(DDL_DIRECTORY|DDL_EXCLUSIVE) filled with %d entries, expected %d\n",
1816 itemCount
, itemCount_allDirs
);
1818 if (itemCount
&& GetCurrentDirectoryA( MAX_PATH
, pathBuffer
) > 3) /* there's no [..] in drive root */
1820 memset(pathBuffer
, 0, MAX_PATH
);
1821 SendMessageA(g_listBox
, LB_GETTEXT
, 0, (LPARAM
)pathBuffer
);
1822 ok( !strcmp(pathBuffer
, "[..]"), "First (and only) element is not [..]\n");
1825 /* Test behavior when no files match the wildcard */
1826 strcpy(pathBuffer
, BAD_EXTENSION
);
1827 res
= DlgDirListA(hWnd
, pathBuffer
, ID_TEST_LISTBOX
, ID_TEST_LABEL
, DDL_DIRECTORY
|DDL_EXCLUSIVE
);
1828 ok (res
== 1, "DlgDirList(%s, DDL_DIRECTORY|DDL_EXCLUSIVE) returned %d expected 1\n", BAD_EXTENSION
, res
);
1830 itemCount
= SendMessageA(g_listBox
, LB_GETCOUNT
, 0, 0);
1831 ok (itemCount
== itemCount_allDirs
, "DlgDirList() incorrectly filled the listbox!\n");
1833 /* Test DDL_DIRECTORY|DDL_DRIVES|DDL_EXCLUSIVE. */
1834 strcpy(pathBuffer
, "w*.c");
1835 res
= DlgDirListA(hWnd
, pathBuffer
, ID_TEST_LISTBOX
, ID_TEST_LABEL
, DDL_DIRECTORY
|DDL_DRIVES
|DDL_EXCLUSIVE
);
1836 ok (res
== 1, "DlgDirList(*.c, DDL_DIRECTORY|DDL_DRIVES|DDL_EXCLUSIVE) failed - 0x%08lx\n", GetLastError());
1838 /* There should be no plain files on the listbox */
1839 itemCount
= SendMessageA(g_listBox
, LB_GETCOUNT
, 0, 0);
1840 ok (itemCount
== itemCount_justDrives
+ itemCount_allDirs
,
1841 "DlgDirList(DDL_DIRECTORY|DDL_EXCLUSIVE) filled with %d entries, expected %d\n",
1842 itemCount
, itemCount_justDrives
+ itemCount_allDirs
);
1844 for (i
= 0; i
< itemCount
; i
++)
1846 memset(pathBuffer
, 0, MAX_PATH
);
1848 SendMessageA(g_listBox
, LB_GETTEXT
, i
, (LPARAM
)pathBuffer
);
1849 if (sscanf(pathBuffer
, "[-%c-]", &driveletter
) == 1)
1850 ok( driveletter
>= 'a' && driveletter
<= 'z', "Drive letter not in range a..z, got ascii %d\n", driveletter
);
1852 ok( pathBuffer
[0] == '[' && pathBuffer
[strlen(pathBuffer
)-1] == ']',
1853 "Element %d (%s) does not fit expected [...]\n", i
, pathBuffer
);
1856 /* Test behavior when no files match the wildcard */
1857 strcpy(pathBuffer
, BAD_EXTENSION
);
1858 res
= DlgDirListA(hWnd
, pathBuffer
, ID_TEST_LISTBOX
, ID_TEST_LABEL
, DDL_DIRECTORY
|DDL_DRIVES
|DDL_EXCLUSIVE
);
1859 ok (res
== 1, "DlgDirList(%s, DDL_DIRECTORY|DDL_DRIVES|DDL_EXCLUSIVE) returned %d expected 1\n", BAD_EXTENSION
, res
);
1861 itemCount
= SendMessageA(g_listBox
, LB_GETCOUNT
, 0, 0);
1862 ok (itemCount
== itemCount_justDrives
+ itemCount_allDirs
, "DlgDirList() incorrectly filled the listbox!\n");
1864 /* Now test DlgDirSelectEx() in normal operation */
1865 /* Fill with everything - drives, directory and all plain files. */
1866 strcpy(pathBuffer
, "*");
1867 res
= DlgDirListA(hWnd
, pathBuffer
, ID_TEST_LISTBOX
, ID_TEST_LABEL
, DDL_DIRECTORY
|DDL_DRIVES
);
1868 ok (res
!= 0, "DlgDirList(*, DDL_DIRECTORY|DDL_DRIVES) failed - 0x%08lx\n", GetLastError());
1870 SendMessageA(g_listBox
, LB_SETCURSEL
, -1, 0); /* Unselect any current selection */
1871 memset(pathBuffer
, 0, MAX_PATH
);
1872 SetLastError(0xdeadbeef);
1873 res
= DlgDirSelectExA(hWnd
, pathBuffer
, MAX_PATH
, ID_TEST_LISTBOX
);
1874 ok (GetLastError() == 0xdeadbeef,
1875 "DlgDirSelectEx() with no selection modified last error code from 0xdeadbeef to 0x%08lx\n",
1877 ok (res
== 0, "DlgDirSelectEx() with no selection returned %d, expected 0\n", res
);
1878 /* WinXP-SP2 leaves pathBuffer untouched, but Win98 fills it with garbage. */
1880 ok (!*pathBuffer, "DlgDirSelectEx() with no selection filled buffer with %s\n", pathBuffer);
1882 /* Test proper drive/dir/file recognition */
1883 itemCount
= SendMessageA(g_listBox
, LB_GETCOUNT
, 0, 0);
1884 for (i
= 0; i
< itemCount
; i
++)
1886 memset(itemBuffer
, 0, MAX_PATH
);
1887 memset(pathBuffer
, 0, MAX_PATH
);
1888 memset(tempBuffer
, 0, MAX_PATH
);
1890 SendMessageA(g_listBox
, LB_GETTEXT
, i
, (LPARAM
)itemBuffer
);
1891 res
= SendMessageA(g_listBox
, LB_SETCURSEL
, i
, 0);
1892 ok (res
== i
, "SendMessageA(LB_SETCURSEL, %d) failed\n", i
);
1893 if (sscanf(itemBuffer
, "[-%c-]", &driveletter
) == 1)
1895 /* Current item is a drive letter */
1896 SetLastError(0xdeadbeef);
1897 res
= DlgDirSelectExA(hWnd
, pathBuffer
, MAX_PATH
, ID_TEST_LISTBOX
);
1898 ok (GetLastError() == 0xdeadbeef,
1899 "DlgDirSelectEx() with selection at %d modified last error code from 0xdeadbeef to 0x%08lx\n",
1901 ok(res
== 1, "DlgDirSelectEx() thinks %s (%s) is not a drive/directory!\n", itemBuffer
, pathBuffer
);
1903 /* For drive letters, DlgDirSelectEx tacks on a colon */
1904 ok (pathBuffer
[0] == driveletter
&& pathBuffer
[1] == ':' && pathBuffer
[2] == '\0',
1905 "%d: got \"%s\" expected \"%c:\"\n", i
, pathBuffer
, driveletter
);
1907 else if (itemBuffer
[0] == '[')
1909 /* Current item is the parent directory */
1910 SetLastError(0xdeadbeef);
1911 res
= DlgDirSelectExA(hWnd
, pathBuffer
, MAX_PATH
, ID_TEST_LISTBOX
);
1912 ok (GetLastError() == 0xdeadbeef,
1913 "DlgDirSelectEx() with selection at %d modified last error code from 0xdeadbeef to 0x%08lx\n",
1915 ok(res
== 1, "DlgDirSelectEx() thinks %s (%s) is not a drive/directory!\n", itemBuffer
, pathBuffer
);
1917 /* For directories, DlgDirSelectEx tacks on a backslash */
1918 p
= pathBuffer
+ strlen(pathBuffer
);
1919 ok (*(p
-1) == '\\', "DlgDirSelectEx did NOT tack on a backslash to dir, got %s\n", pathBuffer
);
1921 tempBuffer
[0] = '[';
1922 lstrcpynA(tempBuffer
+ 1, pathBuffer
, strlen(pathBuffer
));
1923 strcat(tempBuffer
, "]");
1924 ok (!strcmp(tempBuffer
, itemBuffer
), "Formatted directory should be %s, got %s\n", tempBuffer
, itemBuffer
);
1928 /* Current item is a plain file */
1929 SetLastError(0xdeadbeef);
1930 res
= DlgDirSelectExA(hWnd
, pathBuffer
, MAX_PATH
, ID_TEST_LISTBOX
);
1931 ok (GetLastError() == 0xdeadbeef,
1932 "DlgDirSelectEx() with selection at %d modified last error code from 0xdeadbeef to 0x%08lx\n",
1934 ok(res
== 0, "DlgDirSelectEx() thinks %s (%s) is a drive/directory!\n", itemBuffer
, pathBuffer
);
1936 /* NOTE: WinXP tacks a period on all files that lack an extension. This affects
1937 * for example, "Makefile", which gets reported as "Makefile."
1939 strcpy(tempBuffer
, itemBuffer
);
1940 if (strchr(tempBuffer
, '.') == NULL
) strcat(tempBuffer
, ".");
1941 ok (!strcmp(pathBuffer
, tempBuffer
), "Formatted file should be %s, got %s\n", tempBuffer
, pathBuffer
);
1945 DeleteFileA( "wtest1.tmp.c" );
1947 /* Now test DlgDirSelectEx() in abnormal operation */
1948 /* Fill list with bogus entries, that look somewhat valid */
1949 SendMessageA(g_listBox
, LB_RESETCONTENT
, 0, 0);
1950 SendMessageA(g_listBox
, LB_ADDSTRING
, 0, (LPARAM
)"[notexist.dir]");
1951 SendMessageA(g_listBox
, LB_ADDSTRING
, 0, (LPARAM
)"notexist.fil");
1952 itemCount
= SendMessageA(g_listBox
, LB_GETCOUNT
, 0, 0);
1953 for (i
= 0; i
< itemCount
; i
++)
1955 memset(itemBuffer
, 0, MAX_PATH
);
1956 memset(pathBuffer
, 0, MAX_PATH
);
1957 memset(tempBuffer
, 0, MAX_PATH
);
1959 SendMessageA(g_listBox
, LB_GETTEXT
, i
, (LPARAM
)itemBuffer
);
1960 res
= SendMessageA(g_listBox
, LB_SETCURSEL
, i
, 0);
1961 ok (res
== i
, "SendMessage(LB_SETCURSEL, %d) failed\n", i
);
1962 if (sscanf(itemBuffer
, "[-%c-]", &driveletter
) == 1)
1964 /* Current item is a drive letter */
1965 SetLastError(0xdeadbeef);
1966 res
= DlgDirSelectExA(hWnd
, pathBuffer
, MAX_PATH
, ID_TEST_LISTBOX
);
1967 ok (GetLastError() == 0xdeadbeef,
1968 "DlgDirSelectEx() with selection at %d modified last error code from 0xdeadbeef to 0x%08lx\n",
1970 ok(res
== 1, "DlgDirSelectEx() thinks %s (%s) is not a drive/directory!\n", itemBuffer
, pathBuffer
);
1972 /* For drive letters, DlgDirSelectEx tacks on a colon */
1973 ok (pathBuffer
[0] == driveletter
&& pathBuffer
[1] == ':' && pathBuffer
[2] == '\0',
1974 "%d: got \"%s\" expected \"%c:\"\n", i
, pathBuffer
, driveletter
);
1976 else if (itemBuffer
[0] == '[')
1978 /* Current item is the parent directory */
1979 SetLastError(0xdeadbeef);
1980 res
= DlgDirSelectExA(hWnd
, pathBuffer
, MAX_PATH
, ID_TEST_LISTBOX
);
1981 ok (GetLastError() == 0xdeadbeef,
1982 "DlgDirSelectEx() with selection at %d modified last error code from 0xdeadbeef to 0x%08lx\n",
1984 ok(res
== 1, "DlgDirSelectEx() thinks %s (%s) is not a drive/directory!\n", itemBuffer
, pathBuffer
);
1986 /* For directories, DlgDirSelectEx tacks on a backslash */
1987 p
= pathBuffer
+ strlen(pathBuffer
);
1988 ok (*(p
-1) == '\\', "DlgDirSelectEx did NOT tack on a backslash to dir, got %s\n", pathBuffer
);
1990 tempBuffer
[0] = '[';
1991 lstrcpynA(tempBuffer
+ 1, pathBuffer
, strlen(pathBuffer
));
1992 strcat(tempBuffer
, "]");
1993 ok (!strcmp(tempBuffer
, itemBuffer
), "Formatted directory should be %s, got %s\n", tempBuffer
, itemBuffer
);
1997 /* Current item is a plain file */
1998 SetLastError(0xdeadbeef);
1999 res
= DlgDirSelectExA(hWnd
, pathBuffer
, MAX_PATH
, ID_TEST_LISTBOX
);
2000 ok (GetLastError() == 0xdeadbeef,
2001 "DlgDirSelectEx() with selection at %d modified last error code from 0xdeadbeef to 0x%08lx\n",
2003 ok(res
== 0, "DlgDirSelectEx() thinks %s (%s) is a drive/directory!\n", itemBuffer
, pathBuffer
);
2005 /* NOTE: WinXP and Win98 tack a period on all files that lack an extension.
2006 * This affects for example, "Makefile", which gets reported as "Makefile."
2008 strcpy(tempBuffer
, itemBuffer
);
2009 if (strchr(tempBuffer
, '.') == NULL
) strcat(tempBuffer
, ".");
2010 ok (!strcmp(pathBuffer
, tempBuffer
), "Formatted file should be %s, got %s\n", tempBuffer
, pathBuffer
);
2014 /* Test behavior when loading folders from root with and without wildcard */
2015 strcpy(pathBuffer
, "C:\\");
2016 res
= DlgDirListA(hWnd
, pathBuffer
, ID_TEST_LISTBOX
, 0, DDL_DIRECTORY
| DDL_EXCLUSIVE
);
2017 ok(res
, "DlgDirList failed to list C:\\ folders\n");
2018 ok(!strcmp(pathBuffer
, "*"), "DlgDirList set the invalid path spec '%s', expected '*'\n", pathBuffer
);
2020 strcpy(pathBuffer
, "C:\\*");
2021 res
= DlgDirListA(hWnd
, pathBuffer
, ID_TEST_LISTBOX
, 0, DDL_DIRECTORY
| DDL_EXCLUSIVE
);
2022 ok(res
, "DlgDirList failed to list C:\\* folders\n");
2023 ok(!strcmp(pathBuffer
, "*"), "DlgDirList set the invalid path spec '%s', expected '*'\n", pathBuffer
);
2025 /* Try loading files from an invalid folder */
2026 SetLastError(0xdeadbeef);
2027 strcpy(pathBuffer
, "C:\\INVALID$$DIR");
2028 res
= DlgDirListA(hWnd
, pathBuffer
, ID_TEST_LISTBOX
, 0, DDL_DIRECTORY
| DDL_EXCLUSIVE
);
2029 ok(!res
, "DlgDirList should have failed with 0 but %d was returned\n", res
);
2030 ok(GetLastError() == ERROR_NO_WILDCARD_CHARACTERS
,
2031 "GetLastError should return 0x589, got 0x%lX\n",GetLastError());
2033 DestroyWindow(hWnd
);
2036 static void test_set_count( void )
2038 static const DWORD styles
[] =
2043 HWND parent
, listbox
;
2048 parent
= create_parent();
2049 listbox
= create_listbox( LBS_OWNERDRAWFIXED
| LBS_NODATA
| WS_CHILD
| WS_VISIBLE
, parent
);
2051 UpdateWindow( listbox
);
2052 GetUpdateRect( listbox
, &r
, TRUE
);
2053 ok( IsRectEmpty( &r
), "got non-empty rect\n");
2055 ret
= SendMessageA( listbox
, LB_SETCOUNT
, 100, 0 );
2056 ok( ret
== 0, "got %ld\n", ret
);
2057 ret
= SendMessageA( listbox
, LB_GETCOUNT
, 0, 0 );
2058 ok( ret
== 100, "got %ld\n", ret
);
2060 GetUpdateRect( listbox
, &r
, TRUE
);
2061 ok( !IsRectEmpty( &r
), "got empty rect\n");
2063 ValidateRect( listbox
, NULL
);
2064 GetUpdateRect( listbox
, &r
, TRUE
);
2065 ok( IsRectEmpty( &r
), "got non-empty rect\n");
2067 ret
= SendMessageA( listbox
, LB_SETCOUNT
, 99, 0 );
2068 ok( ret
== 0, "got %ld\n", ret
);
2070 GetUpdateRect( listbox
, &r
, TRUE
);
2071 ok( !IsRectEmpty( &r
), "got empty rect\n");
2073 ret
= SendMessageA( listbox
, LB_SETCOUNT
, -5, 0 );
2074 ok( ret
== 0, "got %ld\n", ret
);
2075 ret
= SendMessageA( listbox
, LB_GETCOUNT
, 0, 0 );
2076 ok( ret
== -5, "got %ld\n", ret
);
2078 DestroyWindow( listbox
);
2080 for (i
= 0; i
< ARRAY_SIZE(styles
); ++i
)
2082 listbox
= create_listbox( styles
[i
] | WS_CHILD
| WS_VISIBLE
, parent
);
2084 SetLastError( 0xdeadbeef );
2085 ret
= SendMessageA( listbox
, LB_SETCOUNT
, 100, 0 );
2086 ok( ret
== LB_ERR
, "expected %d, got %ld\n", LB_ERR
, ret
);
2087 ok( GetLastError() == 0xdeadbeef, "Unexpected error %ld.\n", GetLastError() );
2089 DestroyWindow( listbox
);
2092 DestroyWindow( parent
);
2095 static void test_GetListBoxInfo(void)
2097 static const struct message getlistboxinfo_seq
[] =
2099 { LB_GETLISTBOXINFO
, sent
},
2102 HWND listbox
, parent
;
2105 parent
= create_parent();
2106 listbox
= create_listbox(WS_CHILD
| WS_VISIBLE
, parent
);
2108 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
2109 ret
= GetListBoxInfo(listbox
);
2110 ok(ret
> 0, "got %ld\n", ret
);
2111 ok_sequence(sequences
, LB_SEQ_INDEX
, getlistboxinfo_seq
, "GetListBoxInfo()", FALSE
);
2113 DestroyWindow(listbox
);
2114 DestroyWindow(parent
);
2117 static void test_init_storage( void )
2119 static const DWORD styles
[] =
2122 LBS_NODATA
| LBS_OWNERDRAWFIXED
,
2124 HWND parent
, listbox
;
2125 LONG ret
, items_size
;
2128 parent
= create_parent();
2129 for (i
= 0; i
< ARRAY_SIZE(styles
); i
++)
2131 listbox
= CreateWindowA(WC_LISTBOXA
, "TestList", styles
[i
] | WS_CHILD
,
2132 0, 0, 100, 100, parent
, (HMENU
)ID_LISTBOX
, NULL
, 0);
2134 items_size
= SendMessageA(listbox
, LB_INITSTORAGE
, 100, 0);
2135 ok(items_size
>= 100, "expected at least 100, got %ld\n", items_size
);
2137 ret
= SendMessageA(listbox
, LB_INITSTORAGE
, 0, 0);
2138 ok(ret
== items_size
, "expected %ld, got %ld\n", items_size
, ret
);
2140 /* it doesn't grow since the space was already reserved */
2141 ret
= SendMessageA(listbox
, LB_INITSTORAGE
, items_size
, 0);
2142 ok(ret
== items_size
, "expected %ld, got %ld\n", items_size
, ret
);
2144 /* it doesn't shrink the reserved space */
2145 ret
= SendMessageA(listbox
, LB_INITSTORAGE
, 42, 0);
2146 ok(ret
== items_size
, "expected %ld, got %ld\n", items_size
, ret
);
2148 /* now populate almost all of it so it's not reserved anymore */
2149 if (styles
[i
] & LBS_NODATA
)
2151 ret
= SendMessageA(listbox
, LB_SETCOUNT
, items_size
- 1, 0);
2152 ok(ret
== 0, "unexpected return value %ld\n", ret
);
2156 for (j
= 0; j
< items_size
- 1; j
++)
2158 ret
= SendMessageA(listbox
, LB_INSERTSTRING
, -1, (LPARAM
)"");
2159 ok(ret
== j
, "expected %d, got %ld\n", j
, ret
);
2163 /* we still have one more reserved slot, so it doesn't grow yet */
2164 ret
= SendMessageA(listbox
, LB_INITSTORAGE
, 1, 0);
2165 ok(ret
== items_size
, "expected %ld, got %ld\n", items_size
, ret
);
2167 /* fill the slot and check again, it should grow this time */
2168 ret
= SendMessageA(listbox
, LB_INSERTSTRING
, -1, (LPARAM
)"");
2169 ok(ret
== items_size
- 1, "expected %ld, got %ld\n", items_size
- 1, ret
);
2170 ret
= SendMessageA(listbox
, LB_INITSTORAGE
, 0, 0);
2171 ok(ret
== items_size
, "expected %ld, got %ld\n", items_size
, ret
);
2172 ret
= SendMessageA(listbox
, LB_INITSTORAGE
, 1, 0);
2173 ok(ret
> items_size
, "expected it to grow past %ld, got %ld\n", items_size
, ret
);
2175 DestroyWindow(listbox
);
2177 DestroyWindow(parent
);
2180 static void test_missing_lbuttonup(void)
2182 HWND listbox
, parent
, capture
;
2184 parent
= create_parent();
2185 listbox
= create_listbox(WS_CHILD
| WS_VISIBLE
, parent
);
2187 /* Send button down without a corresponding button up */
2188 SendMessageA(listbox
, WM_LBUTTONDOWN
, 0, MAKELPARAM(10, 10));
2189 capture
= GetCapture();
2190 ok(capture
== listbox
, "got %p expected %p\n", capture
, listbox
);
2192 /* Capture is released and LBN_SELCHANGE sent during WM_KILLFOCUS */
2195 capture
= GetCapture();
2196 ok(capture
== NULL
, "got %p\n", capture
);
2197 ok(got_selchange
, "got %d\n", got_selchange
);
2199 DestroyWindow(listbox
);
2200 DestroyWindow(parent
);
2203 static void test_extents(void)
2205 HWND listbox
, parent
;
2210 parent
= create_parent();
2212 listbox
= create_listbox(WS_CHILD
| WS_VISIBLE
, parent
);
2214 res
= SendMessageA(listbox
, LB_GETHORIZONTALEXTENT
, 0, 0);
2215 ok(res
== 0, "Got wrong initial horizontal extent: %lu\n", res
);
2217 sinfo
.cbSize
= sizeof(sinfo
);
2218 sinfo
.fMask
= SIF_RANGE
;
2219 br
= GetScrollInfo(listbox
, SB_HORZ
, &sinfo
);
2220 ok(br
== TRUE
, "GetScrollInfo failed\n");
2221 ok(sinfo
.nMin
== 0, "got wrong min: %u\n", sinfo
.nMin
);
2222 ok(sinfo
.nMax
== 100, "got wrong max: %u\n", sinfo
.nMax
);
2223 ok((GetWindowLongA(listbox
, GWL_STYLE
) & WS_HSCROLL
) == 0,
2224 "List box should not have a horizontal scroll bar\n");
2226 /* horizontal extent < width */
2227 SendMessageA(listbox
, LB_SETHORIZONTALEXTENT
, 64, 0);
2229 res
= SendMessageA(listbox
, LB_GETHORIZONTALEXTENT
, 0, 0);
2230 ok(res
== 64, "Got wrong horizontal extent: %lu\n", res
);
2232 sinfo
.cbSize
= sizeof(sinfo
);
2233 sinfo
.fMask
= SIF_RANGE
;
2234 br
= GetScrollInfo(listbox
, SB_HORZ
, &sinfo
);
2235 ok(br
== TRUE
, "GetScrollInfo failed\n");
2236 ok(sinfo
.nMin
== 0, "got wrong min: %u\n", sinfo
.nMin
);
2237 ok(sinfo
.nMax
== 100, "got wrong max: %u\n", sinfo
.nMax
);
2238 ok((GetWindowLongA(listbox
, GWL_STYLE
) & WS_HSCROLL
) == 0,
2239 "List box should not have a horizontal scroll bar\n");
2241 /* horizontal extent > width */
2242 SendMessageA(listbox
, LB_SETHORIZONTALEXTENT
, 184, 0);
2244 res
= SendMessageA(listbox
, LB_GETHORIZONTALEXTENT
, 0, 0);
2245 ok(res
== 184, "Got wrong horizontal extent: %lu\n", res
);
2247 sinfo
.cbSize
= sizeof(sinfo
);
2248 sinfo
.fMask
= SIF_RANGE
;
2249 br
= GetScrollInfo(listbox
, SB_HORZ
, &sinfo
);
2250 ok(br
== TRUE
, "GetScrollInfo failed\n");
2251 ok(sinfo
.nMin
== 0, "got wrong min: %u\n", sinfo
.nMin
);
2252 ok(sinfo
.nMax
== 100, "got wrong max: %u\n", sinfo
.nMax
);
2253 ok((GetWindowLongA(listbox
, GWL_STYLE
) & WS_HSCROLL
) == 0,
2254 "List box should not have a horizontal scroll bar\n");
2256 DestroyWindow(listbox
);
2258 listbox
= create_listbox(WS_CHILD
| WS_VISIBLE
| WS_HSCROLL
, parent
);
2260 res
= SendMessageA(listbox
, LB_GETHORIZONTALEXTENT
, 0, 0);
2261 ok(res
== 0, "Got wrong initial horizontal extent: %lu\n", res
);
2263 sinfo
.cbSize
= sizeof(sinfo
);
2264 sinfo
.fMask
= SIF_RANGE
;
2265 br
= GetScrollInfo(listbox
, SB_HORZ
, &sinfo
);
2266 ok(br
== TRUE
, "GetScrollInfo failed\n");
2267 ok(sinfo
.nMin
== 0, "got wrong min: %u\n", sinfo
.nMin
);
2268 ok(sinfo
.nMax
== 100, "got wrong max: %u\n", sinfo
.nMax
);
2269 ok((GetWindowLongA(listbox
, GWL_STYLE
) & WS_HSCROLL
) == 0,
2270 "List box should not have a horizontal scroll bar\n");
2272 /* horizontal extent < width */
2273 SendMessageA(listbox
, LB_SETHORIZONTALEXTENT
, 64, 0);
2275 res
= SendMessageA(listbox
, LB_GETHORIZONTALEXTENT
, 0, 0);
2276 ok(res
== 64, "Got wrong horizontal extent: %lu\n", res
);
2278 sinfo
.cbSize
= sizeof(sinfo
);
2279 sinfo
.fMask
= SIF_RANGE
;
2280 br
= GetScrollInfo(listbox
, SB_HORZ
, &sinfo
);
2281 ok(br
== TRUE
, "GetScrollInfo failed\n");
2282 ok(sinfo
.nMin
== 0, "got wrong min: %u\n", sinfo
.nMin
);
2283 ok(sinfo
.nMax
== 63, "got wrong max: %u\n", sinfo
.nMax
);
2284 ok((GetWindowLongA(listbox
, GWL_STYLE
) & WS_HSCROLL
) == 0,
2285 "List box should not have a horizontal scroll bar\n");
2287 /* horizontal extent > width */
2288 SendMessageA(listbox
, LB_SETHORIZONTALEXTENT
, 184, 0);
2290 res
= SendMessageA(listbox
, LB_GETHORIZONTALEXTENT
, 0, 0);
2291 ok(res
== 184, "Got wrong horizontal extent: %lu\n", res
);
2293 sinfo
.cbSize
= sizeof(sinfo
);
2294 sinfo
.fMask
= SIF_RANGE
;
2295 br
= GetScrollInfo(listbox
, SB_HORZ
, &sinfo
);
2296 ok(br
== TRUE
, "GetScrollInfo failed\n");
2297 ok(sinfo
.nMin
== 0, "got wrong min: %u\n", sinfo
.nMin
);
2298 ok(sinfo
.nMax
== 183, "got wrong max: %u\n", sinfo
.nMax
);
2299 ok((GetWindowLongA(listbox
, GWL_STYLE
) & WS_HSCROLL
) != 0,
2300 "List box should have a horizontal scroll bar\n");
2302 SendMessageA(listbox
, LB_SETHORIZONTALEXTENT
, 0, 0);
2304 res
= SendMessageA(listbox
, LB_GETHORIZONTALEXTENT
, 0, 0);
2305 ok(res
== 0, "Got wrong horizontal extent: %lu\n", res
);
2307 sinfo
.cbSize
= sizeof(sinfo
);
2308 sinfo
.fMask
= SIF_RANGE
;
2309 br
= GetScrollInfo(listbox
, SB_HORZ
, &sinfo
);
2310 ok(br
== TRUE
, "GetScrollInfo failed\n");
2311 ok(sinfo
.nMin
== 0, "got wrong min: %u\n", sinfo
.nMin
);
2312 ok(sinfo
.nMax
== 0, "got wrong max: %u\n", sinfo
.nMax
);
2313 ok((GetWindowLongA(listbox
, GWL_STYLE
) & WS_HSCROLL
) == 0,
2314 "List box should not have a horizontal scroll bar\n");
2316 DestroyWindow(listbox
);
2319 listbox
= create_listbox(WS_CHILD
| WS_VISIBLE
| WS_HSCROLL
| LBS_DISABLENOSCROLL
, parent
);
2321 res
= SendMessageA(listbox
, LB_GETHORIZONTALEXTENT
, 0, 0);
2322 ok(res
== 0, "Got wrong initial horizontal extent: %lu\n", res
);
2324 sinfo
.cbSize
= sizeof(sinfo
);
2325 sinfo
.fMask
= SIF_RANGE
;
2326 br
= GetScrollInfo(listbox
, SB_HORZ
, &sinfo
);
2327 ok(br
== TRUE
, "GetScrollInfo failed\n");
2328 ok(sinfo
.nMin
== 0, "got wrong min: %u\n", sinfo
.nMin
);
2329 ok(sinfo
.nMax
== 0, "got wrong max: %u\n", sinfo
.nMax
);
2330 ok((GetWindowLongA(listbox
, GWL_STYLE
) & WS_HSCROLL
) != 0,
2331 "List box should have a horizontal scroll bar\n");
2333 /* horizontal extent < width */
2334 SendMessageA(listbox
, LB_SETHORIZONTALEXTENT
, 64, 0);
2336 res
= SendMessageA(listbox
, LB_GETHORIZONTALEXTENT
, 0, 0);
2337 ok(res
== 64, "Got wrong horizontal extent: %lu\n", res
);
2339 sinfo
.cbSize
= sizeof(sinfo
);
2340 sinfo
.fMask
= SIF_RANGE
;
2341 br
= GetScrollInfo(listbox
, SB_HORZ
, &sinfo
);
2342 ok(br
== TRUE
, "GetScrollInfo failed\n");
2343 ok(sinfo
.nMin
== 0, "got wrong min: %u\n", sinfo
.nMin
);
2344 ok(sinfo
.nMax
== 63, "got wrong max: %u\n", sinfo
.nMax
);
2345 ok((GetWindowLongA(listbox
, GWL_STYLE
) & WS_HSCROLL
) != 0,
2346 "List box should have a horizontal scroll bar\n");
2348 /* horizontal extent > width */
2349 SendMessageA(listbox
, LB_SETHORIZONTALEXTENT
, 184, 0);
2351 res
= SendMessageA(listbox
, LB_GETHORIZONTALEXTENT
, 0, 0);
2352 ok(res
== 184, "Got wrong horizontal extent: %lu\n", res
);
2354 sinfo
.cbSize
= sizeof(sinfo
);
2355 sinfo
.fMask
= SIF_RANGE
;
2356 br
= GetScrollInfo(listbox
, SB_HORZ
, &sinfo
);
2357 ok(br
== TRUE
, "GetScrollInfo failed\n");
2358 ok(sinfo
.nMin
== 0, "got wrong min: %u\n", sinfo
.nMin
);
2359 ok(sinfo
.nMax
== 183, "got wrong max: %u\n", sinfo
.nMax
);
2360 ok((GetWindowLongA(listbox
, GWL_STYLE
) & WS_HSCROLL
) != 0,
2361 "List box should have a horizontal scroll bar\n");
2363 SendMessageA(listbox
, LB_SETHORIZONTALEXTENT
, 0, 0);
2365 res
= SendMessageA(listbox
, LB_GETHORIZONTALEXTENT
, 0, 0);
2366 ok(res
== 0, "Got wrong horizontal extent: %lu\n", res
);
2368 sinfo
.cbSize
= sizeof(sinfo
);
2369 sinfo
.fMask
= SIF_RANGE
;
2370 br
= GetScrollInfo(listbox
, SB_HORZ
, &sinfo
);
2371 ok(br
== TRUE
, "GetScrollInfo failed\n");
2372 ok(sinfo
.nMin
== 0, "got wrong min: %u\n", sinfo
.nMin
);
2373 ok(sinfo
.nMax
== 0, "got wrong max: %u\n", sinfo
.nMax
);
2374 ok((GetWindowLongA(listbox
, GWL_STYLE
) & WS_HSCROLL
) != 0,
2375 "List box should have a horizontal scroll bar\n");
2377 DestroyWindow(listbox
);
2379 DestroyWindow(parent
);
2382 static void test_listbox(void)
2384 static const struct listbox_test SS
=
2386 {{LB_ERR
, LB_ERR
, 0, LB_ERR
}, {0,0,0,0},
2387 { 1, 1, 1, LB_ERR
}, {0,0,0,0},
2388 { 2, 2, 2, LB_ERR
}, {0,0,0,0},
2389 {LB_ERR
, LB_ERR
, 0, LB_ERR
}, {0,0,0,0}};
2391 /* {selected, anchor, caret, selcount}{TODO fields} */
2392 static const struct listbox_test SS_NS
=
2393 {{LB_ERR
, LB_ERR
, 0, LB_ERR
}, {0,0,0,0},
2394 { 1, 1, 1, LB_ERR
}, {0,0,0,0},
2395 { 2, 2, 2, LB_ERR
}, {0,0,0,0},
2396 {LB_ERR
, LB_ERR
, 0, LB_ERR
}, {0,0,0,0}};
2398 static const struct listbox_test MS
=
2399 {{ 0, LB_ERR
, 0, 0}, {0,0,0,0},
2400 { 1, 1, 1, 1}, {0,0,0,0},
2401 { 2, 1, 2, 1}, {0,0,0,0},
2402 { 0, LB_ERR
, 0, 2}, {0,0,0,0}};
2404 static const struct listbox_test MS_NS
=
2405 {{LB_ERR
, LB_ERR
, 0, LB_ERR
}, {0,0,0,0},
2406 { 1, 1, 1, LB_ERR
}, {0,0,0,0},
2407 { 2, 2, 2, LB_ERR
}, {0,0,0,0},
2408 {LB_ERR
, LB_ERR
, 0, LB_ERR
}, {0,0,0,0}};
2410 static const struct listbox_test ES
=
2411 {{ 0, LB_ERR
, 0, 0}, {0,0,0,0},
2412 { 1, 1, 1, 1}, {0,0,0,0},
2413 { 2, 2, 2, 1}, {0,0,0,0},
2414 { 0, LB_ERR
, 0, 2}, {0,0,0,0}};
2416 static const struct listbox_test ES_NS
=
2417 {{LB_ERR
, LB_ERR
, 0, LB_ERR
}, {0,0,0,0},
2418 { 1, 1, 1, LB_ERR
}, {0,0,0,0},
2419 { 2, 2, 2, LB_ERR
}, {0,0,0,0},
2420 {LB_ERR
, LB_ERR
, 0, LB_ERR
}, {0,0,0,0}};
2422 static const struct listbox_test EMS
=
2423 {{ 0, LB_ERR
, 0, 0}, {0,0,0,0},
2424 { 1, 1, 1, 1}, {0,0,0,0},
2425 { 2, 2, 2, 1}, {0,0,0,0},
2426 { 0, LB_ERR
, 0, 2}, {0,0,0,0}};
2428 static const struct listbox_test EMS_NS
=
2429 {{LB_ERR
, LB_ERR
, 0, LB_ERR
}, {0,0,0,0},
2430 { 1, 1, 1, LB_ERR
}, {0,0,0,0},
2431 { 2, 2, 2, LB_ERR
}, {0,0,0,0},
2432 {LB_ERR
, LB_ERR
, 0, LB_ERR
}, {0,0,0,0}};
2435 run_test(LBS_NOSEL
, SS_NS
);
2436 run_test(LBS_MULTIPLESEL
, MS
);
2437 run_test(LBS_MULTIPLESEL
| LBS_NOSEL
, MS_NS
);
2438 run_test(LBS_EXTENDEDSEL
, ES
);
2439 run_test(LBS_EXTENDEDSEL
| LBS_NOSEL
, ES_NS
);
2440 run_test(LBS_EXTENDEDSEL
| LBS_MULTIPLESEL
, EMS
);
2441 run_test(LBS_EXTENDEDSEL
| LBS_MULTIPLESEL
| LBS_NOSEL
, EMS_NS
);
2443 run_test(LBS_NODATA
| LBS_OWNERDRAWFIXED
, SS
);
2444 run_test(LBS_NODATA
| LBS_OWNERDRAWFIXED
| LBS_NOSEL
, SS_NS
);
2445 run_test(LBS_NODATA
| LBS_OWNERDRAWFIXED
| LBS_MULTIPLESEL
, MS
);
2446 run_test(LBS_NODATA
| LBS_OWNERDRAWFIXED
| LBS_MULTIPLESEL
| LBS_NOSEL
, MS_NS
);
2447 run_test(LBS_NODATA
| LBS_OWNERDRAWFIXED
| LBS_EXTENDEDSEL
, ES
);
2448 run_test(LBS_NODATA
| LBS_OWNERDRAWFIXED
| LBS_EXTENDEDSEL
| LBS_NOSEL
, ES_NS
);
2449 run_test(LBS_NODATA
| LBS_OWNERDRAWFIXED
| LBS_EXTENDEDSEL
| LBS_MULTIPLESEL
, EMS
);
2450 run_test(LBS_NODATA
| LBS_OWNERDRAWFIXED
| LBS_EXTENDEDSEL
| LBS_MULTIPLESEL
| LBS_NOSEL
, EMS_NS
);
2453 static const struct message lb_addstring_ownerdraw_parent_seq
[] =
2455 { WM_MEASUREITEM
, sent
|wparam
|lparam
, 0x1012, 0xf30604ed },
2456 { WM_MEASUREITEM
, sent
|wparam
|lparam
, 0x1112, 0xf30604ee },
2457 { WM_MEASUREITEM
, sent
|wparam
|lparam
, 0x1212, 0xf30604ef },
2461 static const struct message lb_addstring_sort_parent_seq
[] =
2463 { WM_MEASUREITEM
, sent
|wparam
|lparam
, 0x1012, 0xf30604ed },
2464 { WM_COMPAREITEM
, sent
|wparam
|lparam
, 0xf30604ed, 0xf30604ee },
2465 { WM_MEASUREITEM
, sent
|wparam
|lparam
, 0x1112, 0xf30604ee },
2466 { WM_COMPAREITEM
, sent
|wparam
|lparam
, 0xf30604ed, 0xf30604ef },
2467 { WM_COMPAREITEM
, sent
|wparam
|lparam
, 0xf30604ee, 0xf30604ef },
2468 { WM_MEASUREITEM
, sent
|wparam
|lparam
, 0x1212, 0xf30604ef },
2472 static const struct message empty_seq
[] =
2477 static void test_WM_MEASUREITEM(void)
2479 HWND parent
, listbox
;
2482 parent
= create_parent();
2483 listbox
= create_listbox(WS_CHILD
| LBS_OWNERDRAWVARIABLE
, parent
);
2485 data
= SendMessageA(listbox
, LB_GETITEMDATA
, 0, 0);
2486 ok(data
== (LRESULT
)strings
[0], "data = %08Ix, expected %p\n", data
, strings
[0]);
2487 DestroyWindow(parent
);
2489 parent
= create_parent();
2490 listbox
= create_listbox(WS_CHILD
| LBS_OWNERDRAWVARIABLE
| LBS_HASSTRINGS
, parent
);
2492 data
= SendMessageA(listbox
, LB_GETITEMDATA
, 0, 0);
2493 ok(!data
, "data = %08Ix\n", data
);
2495 /* LBS_HASSTRINGS */
2496 parent
= create_parent();
2497 listbox
= CreateWindowExA(WS_EX_NOPARENTNOTIFY
, WC_LISTBOXA
, NULL
,
2498 WS_CHILD
| LBS_NOTIFY
| LBS_OWNERDRAWVARIABLE
| LBS_HASSTRINGS
| WS_VISIBLE
,
2499 10, 10, 80, 80, parent
, (HMENU
)ID_LISTBOX
, 0, NULL
);
2501 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
2503 ret
= SendMessageA(listbox
, LB_ADDSTRING
, 0, (LPARAM
)"item 0");
2504 ok(ret
== 0, "expected 0, got %Id\n", ret
);
2505 ret
= SendMessageA(listbox
, LB_ADDSTRING
, 0, (LPARAM
)"item 1");
2506 ok(ret
== 1, "expected 1, got %Id\n", ret
);
2507 ret
= SendMessageA(listbox
, LB_ADDSTRING
, 0, (LPARAM
)"item 2");
2508 ok(ret
== 2, "expected 2, got %Id\n", ret
);
2510 ok_sequence(sequences
, PARENT_SEQ_INDEX
, lb_addstring_ownerdraw_parent_seq
,
2511 "LB_ADDSTRING (LBS_HASSTRINGS, ownerdraw)", FALSE
);
2512 DestroyWindow(listbox
);
2514 /* LBS_SORT, no LBS_HASSTRINGS */
2515 listbox
= CreateWindowExA(WS_EX_NOPARENTNOTIFY
, WC_LISTBOXA
, NULL
,
2516 WS_CHILD
| LBS_NOTIFY
| LBS_OWNERDRAWVARIABLE
| LBS_SORT
| WS_VISIBLE
,
2517 10, 10, 80, 80, parent
, (HMENU
)ID_LISTBOX
, 0, NULL
);
2519 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
2521 ret
= SendMessageA(listbox
, LB_ADDSTRING
, 0, (LPARAM
)"item 0");
2522 ok(ret
== 0, "expected 0, got %Id\n", ret
);
2523 ret
= SendMessageA(listbox
, LB_ADDSTRING
, 0, (LPARAM
)"item 1");
2524 ok(ret
== 1, "expected 1, got %Id\n", ret
);
2525 ret
= SendMessageA(listbox
, LB_ADDSTRING
, 0, (LPARAM
)"item 2");
2526 ok(ret
== 2, "expected 2, got %Id\n", ret
);
2528 ok_sequence(sequences
, PARENT_SEQ_INDEX
, lb_addstring_sort_parent_seq
, "LB_ADDSTRING (LBS_SORT)", FALSE
);
2529 DestroyWindow(listbox
);
2531 /* LBS_HASSTRINGS */
2532 listbox
= CreateWindowExA(WS_EX_NOPARENTNOTIFY
, WC_LISTBOXA
, NULL
,
2533 WS_CHILD
| LBS_NOTIFY
| LBS_HASSTRINGS
| WS_VISIBLE
,
2534 10, 10, 80, 80, parent
, (HMENU
)ID_LISTBOX
, 0, NULL
);
2536 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
2538 ret
= SendMessageA(listbox
, LB_ADDSTRING
, 0, (LPARAM
)"item 2");
2539 ok(ret
== 0, "expected 0, got %Id\n", ret
);
2540 ret
= SendMessageA(listbox
, LB_ADDSTRING
, 0, (LPARAM
)"item 0");
2541 ok(ret
== 1, "expected 1, got %Id\n", ret
);
2542 ret
= SendMessageA(listbox
, LB_ADDSTRING
, 0, (LPARAM
)"item 1");
2543 ok(ret
== 2, "expected 2, got %Id\n", ret
);
2545 ok_sequence(sequences
, PARENT_SEQ_INDEX
, empty_seq
, "LB_ADDSTRING (LBS_HASSTRINGS)", FALSE
);
2546 DestroyWindow(listbox
);
2548 /* LBS_HASSTRINGS, LBS_SORT */
2549 listbox
= CreateWindowExA(WS_EX_NOPARENTNOTIFY
, WC_LISTBOXA
, NULL
,
2550 WS_CHILD
| LBS_NOTIFY
| LBS_HASSTRINGS
| LBS_SORT
| WS_VISIBLE
,
2551 10, 10, 80, 80, parent
, (HMENU
)ID_LISTBOX
, 0, NULL
);
2553 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
2555 ret
= SendMessageA(listbox
, LB_ADDSTRING
, 0, (LPARAM
)"item 2");
2556 ok(ret
== 0, "expected 0, got %Id\n", ret
);
2557 ret
= SendMessageA(listbox
, LB_ADDSTRING
, 0, (LPARAM
)"item 0");
2558 ok(ret
== 0, "expected 0, got %Id\n", ret
);
2559 ret
= SendMessageA(listbox
, LB_ADDSTRING
, 0, (LPARAM
)"item 1");
2560 ok(ret
== 1, "expected 1, got %Id\n", ret
);
2562 ok_sequence(sequences
, PARENT_SEQ_INDEX
, empty_seq
, "LB_ADDSTRING (LBS_HASSTRINGS, LBS_SORT)", FALSE
);
2563 DestroyWindow(listbox
);
2565 DestroyWindow(parent
);
2568 static void test_LBS_NODATA(void)
2570 static const DWORD invalid_styles
[] =
2573 LBS_OWNERDRAWVARIABLE
,
2576 LBS_OWNERDRAWFIXED
| LBS_SORT
,
2577 LBS_OWNERDRAWFIXED
| LBS_HASSTRINGS
,
2579 static const UINT invalid_idx
[] = { -2, 2 };
2580 static const UINT valid_idx
[] = { 0, 1 };
2581 static const ULONG_PTR zero_data
;
2582 HWND listbox
, parent
;
2588 listbox
= CreateWindowA(WC_LISTBOXA
, "TestList", LBS_NODATA
| LBS_OWNERDRAWFIXED
| WS_VISIBLE
,
2589 0, 0, 100, 100, NULL
, NULL
, NULL
, 0);
2590 ok(listbox
!= NULL
, "Failed to create ListBox window.\n");
2592 ret
= SendMessageA(listbox
, LB_INSERTSTRING
, -1, 0);
2593 ok(ret
== 0, "Unexpected return value %d.\n", ret
);
2594 ret
= SendMessageA(listbox
, LB_INSERTSTRING
, -1, 0);
2595 ok(ret
== 1, "Unexpected return value %d.\n", ret
);
2596 ret
= SendMessageA(listbox
, LB_GETCOUNT
, 0, 0);
2597 ok(ret
== 2, "Unexpected return value %d.\n", ret
);
2599 /* Invalid indices. */
2600 for (i
= 0; i
< ARRAY_SIZE(invalid_idx
); ++i
)
2602 ret
= SendMessageA(listbox
, LB_SETITEMDATA
, invalid_idx
[i
], 42);
2603 ok(ret
== LB_ERR
, "Unexpected return value %d.\n", ret
);
2604 ret
= SendMessageA(listbox
, LB_GETTEXTLEN
, invalid_idx
[i
], 0);
2605 ok(ret
== LB_ERR
, "Unexpected return value %d.\n", ret
);
2608 ret
= SendMessageA(listbox
, LB_GETTEXT
, invalid_idx
[i
], (LPARAM
)&data
);
2609 ok(ret
== LB_ERR
, "Unexpected return value %d.\n", ret
);
2611 ret
= SendMessageA(listbox
, LB_GETITEMDATA
, invalid_idx
[i
], 0);
2612 ok(ret
== LB_ERR
, "Unexpected return value %d.\n", ret
);
2615 IsWow64Process(GetCurrentProcess(), &is_wow64
);
2619 text_len
= is_wow64
? 8 : 4;
2622 /* Valid indices. */
2623 for (i
= 0; i
< ARRAY_SIZE(valid_idx
); ++i
)
2625 ret
= SendMessageA(listbox
, LB_SETITEMDATA
, valid_idx
[i
], 42);
2626 ok(ret
== TRUE
, "Unexpected return value %d.\n", ret
);
2627 ret
= SendMessageA(listbox
, LB_GETTEXTLEN
, valid_idx
[i
], 0);
2628 todo_wine_if(is_wow64
)
2629 ok(ret
== text_len
, "Unexpected return value %d.\n", ret
);
2631 memset(&data
, 0xee, sizeof(data
));
2632 ret
= SendMessageA(listbox
, LB_GETTEXT
, valid_idx
[i
], (LPARAM
)&data
);
2633 ok(ret
== sizeof(data
), "Unexpected return value %d.\n", ret
);
2634 ok(!memcmp(&data
, &zero_data
, sizeof(data
)), "Unexpected item data.\n");
2636 ret
= SendMessageA(listbox
, LB_GETITEMDATA
, valid_idx
[i
], 0);
2637 ok(ret
== 0, "Unexpected return value %d.\n", ret
);
2640 /* More messages that don't work with LBS_NODATA. */
2641 ret
= SendMessageA(listbox
, LB_FINDSTRING
, 1, 0);
2642 ok(ret
== LB_ERR
, "Unexpected return value %d.\n", ret
);
2643 ret
= SendMessageA(listbox
, LB_FINDSTRING
, 1, 42);
2644 ok(ret
== LB_ERR
, "Unexpected return value %d.\n", ret
);
2645 ret
= SendMessageA(listbox
, LB_FINDSTRINGEXACT
, 1, 0);
2646 ok(ret
== LB_ERR
, "Unexpected return value %d.\n", ret
);
2647 ret
= SendMessageA(listbox
, LB_FINDSTRINGEXACT
, 1, 42);
2648 ok(ret
== LB_ERR
, "Unexpected return value %d.\n", ret
);
2649 ret
= SendMessageA(listbox
, LB_SELECTSTRING
, 1, 0);
2650 ok(ret
== LB_ERR
, "Unexpected return value %d.\n", ret
);
2651 ret
= SendMessageA(listbox
, LB_SELECTSTRING
, 1, 42);
2652 ok(ret
== LB_ERR
, "Unexpected return value %d.\n", ret
);
2654 DestroyWindow(listbox
);
2656 /* Invalid window style combinations. */
2657 parent
= create_parent();
2658 ok(parent
!= NULL
, "Failed to create parent window.\n");
2660 for (i
= 0; i
< ARRAY_SIZE(invalid_styles
); ++i
)
2664 listbox
= CreateWindowA(WC_LISTBOXA
, "TestList", LBS_NODATA
| WS_CHILD
| invalid_styles
[i
],
2665 0, 0, 100, 100, parent
, (HMENU
)ID_LISTBOX
, NULL
, 0);
2666 ok(listbox
!= NULL
, "Failed to create a listbox.\n");
2668 style
= GetWindowLongA(listbox
, GWL_STYLE
);
2669 ok((style
& invalid_styles
[i
]) == invalid_styles
[i
], "%u: unexpected window styles %#lx.\n", i
, style
);
2670 ret
= SendMessageA(listbox
, LB_SETCOUNT
, 100, 0);
2671 ok(ret
== LB_ERR
, "%u: unexpected return value %d.\n", i
, ret
);
2672 DestroyWindow(listbox
);
2675 DestroyWindow(parent
);
2680 ULONG_PTR ctx_cookie
;
2683 if (!load_v6_module(&ctx_cookie
, &hCtx
))
2686 init_msg_sequences(sequences
, NUM_MSG_SEQUENCES
);
2691 test_LB_SELITEMRANGE();
2692 test_LB_SETCURSEL();
2693 test_listbox_height();
2694 test_changing_selection_styles();
2695 test_itemfrompoint();
2696 test_listbox_item_data();
2697 test_listbox_LB_DIR();
2698 test_listbox_dlgdir();
2700 test_init_storage();
2701 test_GetListBoxInfo();
2702 test_missing_lbuttonup();
2704 test_WM_MEASUREITEM();
2708 unload_v6_module(ctx_cookie
, hCtx
);