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/heap.h"
31 #include "wine/test.h"
42 static struct msg_sequence
*sequences
[NUM_MSG_SEQUENCES
];
44 /* encoded MEASUREITEMSTRUCT into a WPARAM */
58 } MEASURE_ITEM_STRUCT
;
60 static unsigned hash_Ly_W(const WCHAR
*str
)
65 hash
= hash
* 1664525u + (unsigned char)(*str
) + 1013904223u;
70 static unsigned hash_Ly(const char *str
)
75 hash
= hash
* 1664525u + (unsigned char)(*str
) + 1013904223u;
80 static const char * const strings
[4] = {
84 "Fourth added which is very long because at some time we only had a 256 byte character buffer and "
85 "that was overflowing in one of those applications that had a common dialog file open box and tried "
86 "to add a 300 characters long custom filter string which of course the code did not like and crashed. "
87 "Just make sure this string is longer than 256 characters."
90 static const char BAD_EXTENSION
[] = "*.badtxt";
94 static LRESULT WINAPI
listbox_wnd_proc(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
96 WNDPROC oldproc
= (WNDPROC
)GetWindowLongPtrA(hwnd
, GWLP_USERDATA
);
97 static LONG defwndproc_counter
= 0;
98 struct message msg
= { 0 };
107 case WM_WINDOWPOSCHANGING
:
108 case WM_WINDOWPOSCHANGED
:
112 case WM_DEVICECHANGE
:
116 msg
.message
= message
;
117 msg
.flags
= sent
|wparam
|lparam
;
118 if (defwndproc_counter
) msg
.flags
|= defwinproc
;
121 add_message(sequences
, LB_SEQ_INDEX
, &msg
);
124 defwndproc_counter
++;
125 ret
= CallWindowProcA(oldproc
, hwnd
, message
, wParam
, lParam
);
126 defwndproc_counter
--;
131 static HWND
create_listbox(DWORD add_style
, HWND parent
)
140 handle
= CreateWindowA(WC_LISTBOXA
, "TestList", (LBS_STANDARD
& ~LBS_SORT
) | add_style
, 0, 0, 100, 100,
141 parent
, (HMENU
)ctl_id
, NULL
, 0);
142 ok(handle
!= NULL
, "Failed to create listbox window.\n");
144 SendMessageA(handle
, LB_ADDSTRING
, 0, (LPARAM
) strings
[0]);
145 SendMessageA(handle
, LB_ADDSTRING
, 0, (LPARAM
) strings
[1]);
146 SendMessageA(handle
, LB_ADDSTRING
, 0, (LPARAM
) strings
[2]);
147 SendMessageA(handle
, LB_ADDSTRING
, 0, (LPARAM
) strings
[3]);
149 oldproc
= (WNDPROC
)SetWindowLongPtrA(handle
, GWLP_WNDPROC
, (LONG_PTR
)listbox_wnd_proc
);
150 SetWindowLongPtrA(handle
, GWLP_USERDATA
, (LONG_PTR
)oldproc
);
162 int selected
, anchor
, caret
, selcount
;
167 struct listbox_stat init
, init_todo
;
168 struct listbox_stat click
, click_todo
;
169 struct listbox_stat step
, step_todo
;
170 struct listbox_stat sel
, sel_todo
;
173 static void listbox_query(HWND handle
, struct listbox_stat
*results
)
175 results
->selected
= SendMessageA(handle
, LB_GETCURSEL
, 0, 0);
176 results
->anchor
= SendMessageA(handle
, LB_GETANCHORINDEX
, 0, 0);
177 results
->caret
= SendMessageA(handle
, LB_GETCARETINDEX
, 0, 0);
178 results
->selcount
= SendMessageA(handle
, LB_GETSELCOUNT
, 0, 0);
181 static void buttonpress(HWND handle
, WORD x
, WORD y
)
183 LPARAM lp
= x
+ (y
<< 16);
185 SendMessageA(handle
, WM_LBUTTONDOWN
, MK_LBUTTON
, lp
);
186 SendMessageA(handle
, WM_LBUTTONUP
, 0, lp
);
189 static void keypress(HWND handle
, WPARAM keycode
, BYTE scancode
, BOOL extended
)
191 LPARAM lp
= 1 + (scancode
<< 16) + (extended
? KEYEVENTF_EXTENDEDKEY
: 0);
193 SendMessageA(handle
, WM_KEYDOWN
, keycode
, lp
);
194 SendMessageA(handle
, WM_KEYUP
, keycode
, lp
| 0xc000000);
197 #define listbox_field_ok(t, s, f, got) \
198 ok (t.s.f==got.f, "style %#x, step " #s ", field " #f \
199 ": expected %d, got %d\n", style, t.s.f, got.f)
201 #define listbox_todo_field_ok(t, s, f, got) \
202 todo_wine_if (t.s##_todo.f) { listbox_field_ok(t, s, f, got); }
204 #define listbox_ok(t, s, got) \
205 listbox_todo_field_ok(t, s, selected, got); \
206 listbox_todo_field_ok(t, s, anchor, got); \
207 listbox_todo_field_ok(t, s, caret, got); \
208 listbox_todo_field_ok(t, s, selcount, got)
210 static void run_test(DWORD style
, const struct listbox_test test
)
212 static const struct message delete_seq
[] =
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_DELETESTRING
, sent
|wparam
|lparam
, 0, 0 },
218 { LB_RESETCONTENT
, sent
|wparam
|lparam
|defwinproc
, 0, 0 },
221 struct listbox_stat answer
;
226 hLB
= create_listbox (style
, 0);
228 listbox_query (hLB
, &answer
);
229 listbox_ok (test
, init
, answer
);
231 SendMessageA(hLB
, LB_GETITEMRECT
, 1, (LPARAM
) &second_item
);
232 buttonpress(hLB
, (WORD
)second_item
.left
, (WORD
)second_item
.top
);
234 listbox_query(hLB
, &answer
);
235 listbox_ok(test
, click
, answer
);
237 keypress(hLB
, VK_DOWN
, 0x50, TRUE
);
239 listbox_query(hLB
, &answer
);
240 listbox_ok(test
, step
, answer
);
244 hLB
= create_listbox(style
, 0);
246 SendMessageA(hLB
, LB_SELITEMRANGE
, TRUE
, MAKELPARAM(1, 2));
247 listbox_query(hLB
, &answer
);
248 listbox_ok(test
, sel
, answer
);
250 for (i
= 0; i
< 4 && !(style
& LBS_NODATA
); i
++)
252 DWORD size
= SendMessageA(hLB
, LB_GETTEXTLEN
, i
, 0);
257 txt
= heap_alloc_zero(size
+ 1);
258 resA
= SendMessageA(hLB
, LB_GETTEXT
, i
, (LPARAM
)txt
);
259 ok(!strcmp(txt
, strings
[i
]), "returned string for item %d does not match %s vs %s\n", i
, txt
, strings
[i
]);
261 txtw
= heap_alloc_zero((size
+ 1) * sizeof(*txtw
));
262 resW
= SendMessageW(hLB
, LB_GETTEXT
, i
, (LPARAM
)txtw
);
263 ok(resA
== resW
, "Unexpected text length.\n");
264 WideCharToMultiByte(CP_ACP
, 0, txtw
, -1, txt
, size
, NULL
, NULL
);
265 ok(!strcmp (txt
, strings
[i
]), "Unexpected string for item %d, %s vs %s.\n", i
, txt
, strings
[i
]);
271 /* Confirm the count of items, and that an invalid delete does not remove anything */
272 res
= SendMessageA(hLB
, LB_GETCOUNT
, 0, 0);
273 ok(res
== 4, "Expected 4 items, got %d\n", res
);
274 res
= SendMessageA(hLB
, LB_DELETESTRING
, -1, 0);
275 ok(res
== LB_ERR
, "Expected LB_ERR items, got %d\n", res
);
276 res
= SendMessageA(hLB
, LB_DELETESTRING
, 4, 0);
277 ok(res
== LB_ERR
, "Expected LB_ERR items, got %d\n", res
);
278 count
= SendMessageA(hLB
, LB_GETCOUNT
, 0, 0);
279 ok(count
== 4, "Unexpected item count %d.\n", count
);
281 /* Emptying listbox sends a LB_RESETCONTENT to itself. */
282 flush_sequence(sequences
, LB_SEQ_INDEX
);
283 for (i
= count
; i
--;)
285 res
= SendMessageA(hLB
, LB_DELETESTRING
, 0, 0);
286 ok(res
== i
, "Unexpected return value %d.\n", res
);
288 ok_sequence(sequences
, LB_SEQ_INDEX
, delete_seq
, "Emptying listbox", FALSE
);
293 static void test_item_height(void)
301 hLB
= create_listbox (0, 0);
302 ok ((hdc
= GetDCEx( hLB
, 0, DCX_CACHE
)) != 0, "Can't get hdc\n");
303 ok ((font
= GetCurrentObject(hdc
, OBJ_FONT
)) != 0, "Can't get the current font\n");
304 ok (GetTextMetricsA( hdc
, &tm
), "Can't read font metrics\n");
305 ReleaseDC( hLB
, hdc
);
307 ok (SendMessageA(hLB
, WM_SETFONT
, (WPARAM
)font
, 0) == 0, "Can't set font\n");
309 itemHeight
= SendMessageA(hLB
, LB_GETITEMHEIGHT
, 0, 0);
310 ok (itemHeight
== tm
.tmHeight
, "Item height wrong, got %d, expecting %d\n", itemHeight
, tm
.tmHeight
);
314 hLB
= CreateWindowA(WC_LISTBOXA
, "TestList", LBS_OWNERDRAWVARIABLE
, 0, 0, 100, 100, NULL
, NULL
, NULL
, 0);
316 itemHeight
= SendMessageA(hLB
, LB_GETITEMHEIGHT
, 0, 0);
317 ok(itemHeight
> 0 && itemHeight
<= tm
.tmHeight
, "Unexpected item height %d, expected %d.\n",
318 itemHeight
, tm
.tmHeight
);
319 itemHeight
= SendMessageA(hLB
, LB_GETITEMHEIGHT
, 5, 0);
320 ok(itemHeight
> 0 && itemHeight
<= tm
.tmHeight
, "Unexpected item height %d, expected %d.\n",
321 itemHeight
, tm
.tmHeight
);
322 itemHeight
= SendMessageA(hLB
, LB_GETITEMHEIGHT
, -5, 0);
323 ok(itemHeight
> 0 && itemHeight
<= tm
.tmHeight
, "Unexpected item height %d, expected %d.\n",
324 itemHeight
, tm
.tmHeight
);
329 static int got_selchange
;
331 static LRESULT WINAPI
main_window_proc(HWND hwnd
, UINT msg
, WPARAM wParam
, LPARAM lParam
)
333 static LONG defwndproc_counter
= 0;
334 struct message m
= { 0 };
338 m
.flags
= sent
|wparam
|lparam
;
339 if (defwndproc_counter
) m
.flags
|= defwinproc
;
347 MEASUREITEMSTRUCT
*mis
= (void *)lParam
;
348 BOOL is_unicode_data
= FALSE
;
349 MEASURE_ITEM_STRUCT mi
;
351 if (mis
->CtlType
== ODT_LISTBOX
)
353 HWND ctrl
= GetDlgItem(hwnd
, mis
->CtlID
);
354 is_unicode_data
= GetWindowLongA(ctrl
, GWL_STYLE
) & LBS_HASSTRINGS
;
358 mi
.u
.item
.CtlType
= mis
->CtlType
;
359 mi
.u
.item
.CtlID
= mis
->CtlID
;
360 mi
.u
.item
.itemID
= mis
->itemID
;
361 mi
.u
.item
.wParam
= wParam
;
365 m
.lParam
= mis
->itemData
? hash_Ly_W((const WCHAR
*)mis
->itemData
) : 0;
367 m
.lParam
= mis
->itemData
? hash_Ly((const char *)mis
->itemData
) : 0;
368 add_message(sequences
, PARENT_SEQ_INDEX
, &m
);
370 ok(wParam
== mis
->CtlID
, "got wParam=%08lx, expected %08x\n", wParam
, mis
->CtlID
);
371 ok(mis
->CtlType
== ODT_LISTBOX
, "mi->CtlType = %u\n", mis
->CtlType
);
372 ok(mis
->CtlID
== 1, "mi->CtlID = %u\n", mis
->CtlID
);
373 ok(mis
->itemHeight
, "mi->itemHeight = 0\n");
379 COMPAREITEMSTRUCT
*cis
= (COMPAREITEMSTRUCT
*)lParam
;
380 HWND ctrl
= GetDlgItem(hwnd
, cis
->CtlID
);
381 BOOL is_unicode_data
= TRUE
;
383 ok(wParam
== cis
->CtlID
, "expected %#x, got %#lx\n", cis
->CtlID
, wParam
);
384 ok(cis
->hwndItem
== ctrl
, "expected %p, got %p\n", ctrl
, cis
->hwndItem
);
385 ok((int)cis
->itemID1
>= 0, "expected >= 0, got %d\n", cis
->itemID1
);
386 ok((int)cis
->itemID2
== -1, "expected -1, got %d\n", cis
->itemID2
);
388 if (cis
->CtlType
== ODT_LISTBOX
)
389 is_unicode_data
= GetWindowLongA(ctrl
, GWL_STYLE
) & LBS_HASSTRINGS
;
393 m
.wParam
= cis
->itemData1
? hash_Ly_W((const WCHAR
*)cis
->itemData1
) : 0;
394 m
.lParam
= cis
->itemData2
? hash_Ly_W((const WCHAR
*)cis
->itemData2
) : 0;
398 m
.wParam
= cis
->itemData1
? hash_Ly((const char *)cis
->itemData1
) : 0;
399 m
.lParam
= cis
->itemData2
? hash_Ly((const char *)cis
->itemData2
) : 0;
401 add_message(sequences
, PARENT_SEQ_INDEX
, &m
);
406 RECT rc_item
, rc_client
, rc_clip
;
407 DRAWITEMSTRUCT
*dis
= (DRAWITEMSTRUCT
*)lParam
;
409 ok(wParam
== dis
->CtlID
, "got wParam=%08lx instead of %08x\n", wParam
, dis
->CtlID
);
410 ok(dis
->CtlType
== ODT_LISTBOX
, "wrong CtlType %04x\n", dis
->CtlType
);
412 GetClientRect(dis
->hwndItem
, &rc_client
);
413 GetClipBox(dis
->hDC
, &rc_clip
);
414 ok(EqualRect(&rc_client
, &rc_clip
) || IsRectEmpty(&rc_clip
),
415 "client rect of the listbox should be equal to the clip box,"
416 "or the clip box should be empty\n");
418 SendMessageA(dis
->hwndItem
, LB_GETITEMRECT
, dis
->itemID
, (LPARAM
)&rc_item
);
419 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
[] =
475 parent
= create_parent();
476 ok(parent
!= NULL
, "Failed to create parent window.\n");
478 for (i
= 0; i
< ARRAY_SIZE(styles
); i
++)
480 hLB
= create_listbox(LBS_OWNERDRAWFIXED
| WS_CHILD
| WS_VISIBLE
| styles
[i
], parent
);
481 ok(hLB
!= NULL
, "Failed to create listbox window.\n");
483 SetForegroundWindow(hLB
);
486 /* make height short enough */
487 SendMessageA(hLB
, LB_GETITEMRECT
, 0, (LPARAM
)&rc
);
488 SetWindowPos(hLB
, 0, 0, 0, 100, rc
.bottom
- rc
.top
+ 1, SWP_NOZORDER
| SWP_NOMOVE
);
490 /* make 0 item invisible */
491 SendMessageA(hLB
, LB_SETTOPINDEX
, 1, 0);
492 ret
= SendMessageA(hLB
, LB_GETTOPINDEX
, 0, 0);
493 ok(ret
== 1, "wrong top index %d\n", ret
);
495 SendMessageA(hLB
, LB_GETITEMRECT
, 0, (LPARAM
)&rc
);
496 ok(!IsRectEmpty(&rc
), "empty item rect\n");
497 ok(rc
.top
< 0, "rc.top is not negative (%d)\n", rc
.top
);
501 /* Both FIXED and VARIABLE, FIXED should override VARIABLE. */
502 hLB
= CreateWindowA(WC_LISTBOXA
, "TestList", LBS_OWNERDRAWFIXED
| LBS_OWNERDRAWVARIABLE
| styles
[i
],
503 0, 0, 100, 100, NULL
, NULL
, NULL
, 0);
504 ok(hLB
!= NULL
, "last error 0x%08x\n", GetLastError());
506 ok(GetWindowLongA(hLB
, GWL_STYLE
) & LBS_OWNERDRAWVARIABLE
, "Unexpected window style.\n");
508 ret
= SendMessageA(hLB
, LB_INSERTSTRING
, -1, 0);
509 ok(ret
== 0, "Unexpected return value %d.\n", ret
);
510 ret
= SendMessageA(hLB
, LB_INSERTSTRING
, -1, 0);
511 ok(ret
== 1, "Unexpected return value %d.\n", ret
);
513 ret
= SendMessageA(hLB
, LB_SETITEMHEIGHT
, 0, 13);
514 ok(ret
== LB_OKAY
, "Failed to set item height, %d.\n", ret
);
516 ret
= SendMessageA(hLB
, LB_GETITEMHEIGHT
, 0, 0);
517 ok(ret
== 13, "Unexpected item height %d.\n", ret
);
519 ret
= SendMessageA(hLB
, LB_SETITEMHEIGHT
, 1, 42);
520 ok(ret
== LB_OKAY
, "Failed to set item height, %d.\n", ret
);
522 ret
= SendMessageA(hLB
, LB_GETITEMHEIGHT
, 0, 0);
523 ok(ret
== 42, "Unexpected item height %d.\n", ret
);
525 ret
= SendMessageA(hLB
, LB_GETITEMHEIGHT
, 1, 0);
526 ok(ret
== 42, "Unexpected item height %d.\n", ret
);
531 DestroyWindow(parent
);
534 #define listbox_test_query(exp, got) \
535 ok(exp.selected == got.selected, "expected selected %d, got %d\n", exp.selected, got.selected); \
536 ok(exp.anchor == got.anchor, "expected anchor %d, got %d\n", exp.anchor, got.anchor); \
537 ok(exp.caret == got.caret, "expected caret %d, got %d\n", exp.caret, got.caret); \
538 ok(exp.selcount == got.selcount, "expected selcount %d, got %d\n", exp.selcount, got.selcount);
540 static void test_LB_SELITEMRANGE(void)
542 static const struct listbox_stat test_nosel
= { 0, LB_ERR
, 0, 0 };
543 static const struct listbox_stat test_1
= { 0, LB_ERR
, 0, 2 };
544 static const struct listbox_stat test_2
= { 0, LB_ERR
, 0, 3 };
545 static const struct listbox_stat test_3
= { 0, LB_ERR
, 0, 4 };
546 struct listbox_stat answer
;
550 hLB
= create_listbox(LBS_EXTENDEDSEL
, 0);
551 ok(hLB
!= NULL
, "Failed to create listbox window.\n");
553 listbox_query(hLB
, &answer
);
554 listbox_test_query(test_nosel
, answer
);
556 ret
= SendMessageA(hLB
, LB_SELITEMRANGE
, TRUE
, MAKELPARAM(1, 2));
557 ok(ret
== LB_OKAY
, "LB_SELITEMRANGE returned %d instead of LB_OKAY\n", ret
);
558 listbox_query(hLB
, &answer
);
559 listbox_test_query(test_1
, answer
);
561 SendMessageA(hLB
, LB_SETSEL
, FALSE
, -1);
562 listbox_query(hLB
, &answer
);
563 listbox_test_query(test_nosel
, answer
);
565 ret
= SendMessageA(hLB
, LB_SELITEMRANGE
, TRUE
, MAKELPARAM(0, 4));
566 ok(ret
== LB_OKAY
, "LB_SELITEMRANGE returned %d instead of LB_OKAY\n", ret
);
567 listbox_query(hLB
, &answer
);
568 listbox_test_query(test_3
, answer
);
570 SendMessageA(hLB
, LB_SETSEL
, FALSE
, -1);
571 listbox_query(hLB
, &answer
);
572 listbox_test_query(test_nosel
, answer
);
574 ret
= SendMessageA(hLB
, LB_SELITEMRANGE
, TRUE
, MAKELPARAM(-5, 5));
575 ok(ret
== LB_OKAY
, "LB_SELITEMRANGE returned %d instead of LB_OKAY\n", ret
);
576 listbox_query(hLB
, &answer
);
577 listbox_test_query(test_nosel
, answer
);
579 SendMessageA(hLB
, LB_SETSEL
, FALSE
, -1);
580 listbox_query(hLB
, &answer
);
581 listbox_test_query(test_nosel
, answer
);
583 ret
= SendMessageA(hLB
, LB_SELITEMRANGE
, TRUE
, MAKELPARAM(2, 10));
584 ok(ret
== LB_OKAY
, "LB_SELITEMRANGE returned %d instead of LB_OKAY\n", ret
);
585 listbox_query(hLB
, &answer
);
586 listbox_test_query(test_1
, answer
);
588 SendMessageA(hLB
, LB_SETSEL
, FALSE
, -1);
589 listbox_query(hLB
, &answer
);
590 listbox_test_query(test_nosel
, answer
);
592 ret
= SendMessageA(hLB
, LB_SELITEMRANGE
, TRUE
, MAKELPARAM(4, 10));
593 ok(ret
== LB_OKAY
, "LB_SELITEMRANGE returned %d instead of LB_OKAY\n", ret
);
594 listbox_query(hLB
, &answer
);
595 listbox_test_query(test_nosel
, answer
);
597 SendMessageA(hLB
, LB_SETSEL
, FALSE
, -1);
598 listbox_query(hLB
, &answer
);
599 listbox_test_query(test_nosel
, answer
);
601 ret
= SendMessageA(hLB
, LB_SELITEMRANGE
, TRUE
, MAKELPARAM(10, 1));
602 ok(ret
== LB_OKAY
, "LB_SELITEMRANGE returned %d instead of LB_OKAY\n", ret
);
603 listbox_query(hLB
, &answer
);
604 listbox_test_query(test_2
, answer
);
606 SendMessageA(hLB
, LB_SETSEL
, FALSE
, -1);
607 listbox_query(hLB
, &answer
);
608 listbox_test_query(test_nosel
, answer
);
610 ret
= SendMessageA(hLB
, LB_SELITEMRANGE
, TRUE
, MAKELPARAM(1, -1));
611 ok(ret
== LB_OKAY
, "LB_SELITEMRANGE returned %d instead of LB_OKAY\n", ret
);
612 listbox_query(hLB
, &answer
);
613 listbox_test_query(test_2
, answer
);
618 static void test_LB_SETCURSEL(void)
623 parent
= create_parent();
624 ok(parent
!= NULL
, "Failed to create parent window.\n");
626 hLB
= create_listbox(LBS_NOINTEGRALHEIGHT
| WS_CHILD
, parent
);
627 ok(hLB
!= NULL
, "Failed to create listbox.\n");
629 SendMessageA(hLB
, LB_SETITEMHEIGHT
, 0, 32);
631 ret
= SendMessageA(hLB
, LB_GETANCHORINDEX
, 0, 0);
632 ok(ret
== -1, "Unexpected anchor index %d.\n", ret
);
634 ret
= SendMessageA(hLB
, LB_SETCURSEL
, 2, 0);
635 ok(ret
== 2, "LB_SETCURSEL returned %d instead of 2\n", ret
);
636 ret
= GetScrollPos(hLB
, SB_VERT
);
637 ok(ret
== 0, "expected vscroll 0, got %d\n", ret
);
639 ret
= SendMessageA(hLB
, LB_GETANCHORINDEX
, 0, 0);
640 ok(ret
== -1, "Unexpected anchor index %d.\n", ret
);
642 ret
= SendMessageA(hLB
, LB_SETCURSEL
, 3, 0);
643 ok(ret
== 3, "LB_SETCURSEL returned %d instead of 3\n", ret
);
644 ret
= GetScrollPos(hLB
, SB_VERT
);
645 ok(ret
== 1, "expected vscroll 1, got %d\n", ret
);
647 ret
= SendMessageA(hLB
, LB_GETANCHORINDEX
, 0, 0);
648 ok(ret
== -1, "Unexpected anchor index %d.\n", ret
);
652 hLB
= create_listbox(0, 0);
653 ok(hLB
!= NULL
, "Failed to create ListBox window.\n");
655 ret
= SendMessageA(hLB
, LB_SETCURSEL
, 1, 0);
656 ok(ret
== 1, "Unexpected return value %d.\n", ret
);
658 ret
= SendMessageA(hLB
, LB_GETANCHORINDEX
, 0, 0);
659 ok(ret
== -1, "Unexpected anchor index %d.\n", ret
);
663 /* LBS_EXTENDEDSEL */
664 hLB
= create_listbox(LBS_EXTENDEDSEL
, 0);
665 ok(hLB
!= NULL
, "Failed to create listbox.\n");
667 ret
= SendMessageA(hLB
, LB_GETANCHORINDEX
, 0, 0);
668 ok(ret
== -1, "Unexpected anchor index %d.\n", ret
);
670 ret
= SendMessageA(hLB
, LB_SETCURSEL
, 2, 0);
671 ok(ret
== -1, "LB_SETCURSEL returned %d instead of 2\n", ret
);
673 ret
= SendMessageA(hLB
, LB_GETANCHORINDEX
, 0, 0);
674 ok(ret
== -1, "Unexpected anchor index %d.\n", ret
);
678 /* LBS_MULTIPLESEL */
679 hLB
= create_listbox(LBS_MULTIPLESEL
, 0);
680 ok(hLB
!= NULL
, "Failed to create listbox.\n");
682 ret
= SendMessageA(hLB
, LB_GETANCHORINDEX
, 0, 0);
683 ok(ret
== -1, "Unexpected anchor index %d.\n", ret
);
685 ret
= SendMessageA(hLB
, LB_SETCURSEL
, 2, 0);
686 ok(ret
== -1, "LB_SETCURSEL returned %d instead of 2\n", ret
);
688 ret
= SendMessageA(hLB
, LB_GETANCHORINDEX
, 0, 0);
689 ok(ret
== -1, "Unexpected anchor index %d.\n", ret
);
694 static void test_LB_SETSEL(void)
699 /* LBS_EXTENDEDSEL */
700 list
= create_listbox(LBS_EXTENDEDSEL
, 0);
701 ok(list
!= NULL
, "Failed to create ListBox window.\n");
703 ret
= SendMessageA(list
, LB_GETANCHORINDEX
, 0, 0);
704 ok(ret
== -1, "Unexpected anchor index %d.\n", ret
);
706 ret
= SendMessageA(list
, LB_SETSEL
, TRUE
, 0);
707 ok(ret
== 0, "Unexpected return value %d.\n", ret
);
708 ret
= SendMessageA(list
, LB_GETANCHORINDEX
, 0, 0);
709 ok(ret
== 0, "Unexpected anchor index %d.\n", ret
);
710 ret
= SendMessageA(list
, LB_GETCARETINDEX
, 0, 0);
711 ok(ret
== 0, "Unexpected caret index %d.\n", ret
);
713 ret
= SendMessageA(list
, LB_SETSEL
, TRUE
, 1);
714 ok(ret
== 0, "Unexpected return value %d.\n", ret
);
715 ret
= SendMessageA(list
, LB_GETANCHORINDEX
, 0, 0);
716 ok(ret
== 1, "Unexpected anchor index %d.\n", ret
);
717 ret
= SendMessageA(list
, LB_GETCARETINDEX
, 0, 0);
718 ok(ret
== 1, "Unexpected caret index %d.\n", ret
);
720 ret
= SendMessageA(list
, LB_SETSEL
, FALSE
, 1);
721 ok(ret
== 0, "Unexpected return value %d.\n", ret
);
722 ret
= SendMessageA(list
, LB_GETANCHORINDEX
, 0, 0);
723 ok(ret
== 1, "Unexpected anchor index %d.\n", ret
);
724 ret
= SendMessageA(list
, LB_GETCARETINDEX
, 0, 0);
725 ok(ret
== 1, "Unexpected caret index %d.\n", ret
);
729 /* LBS_MULTIPLESEL */
730 list
= create_listbox(LBS_MULTIPLESEL
, 0);
731 ok(list
!= NULL
, "Failed to create ListBox window.\n");
733 ret
= SendMessageA(list
, LB_GETANCHORINDEX
, 0, 0);
734 ok(ret
== -1, "Unexpected anchor index %d.\n", ret
);
736 ret
= SendMessageA(list
, LB_SETSEL
, TRUE
, 0);
737 ok(ret
== 0, "Unexpected return value %d.\n", ret
);
738 ret
= SendMessageA(list
, LB_GETANCHORINDEX
, 0, 0);
739 ok(ret
== 0, "Unexpected anchor index %d.\n", ret
);
740 ret
= SendMessageA(list
, LB_GETCARETINDEX
, 0, 0);
741 ok(ret
== 0, "Unexpected caret index %d.\n", ret
);
743 ret
= SendMessageA(list
, LB_SETSEL
, TRUE
, 1);
744 ok(ret
== 0, "Unexpected return value %d.\n", ret
);
745 ret
= SendMessageA(list
, LB_GETANCHORINDEX
, 0, 0);
746 ok(ret
== 1, "Unexpected anchor index %d.\n", ret
);
747 ret
= SendMessageA(list
, LB_GETCARETINDEX
, 0, 0);
748 ok(ret
== 1, "Unexpected caret index %d.\n", ret
);
750 ret
= SendMessageA(list
, LB_SETSEL
, FALSE
, 1);
751 ok(ret
== 0, "Unexpected return value %d.\n", ret
);
752 ret
= SendMessageA(list
, LB_GETANCHORINDEX
, 0, 0);
753 ok(ret
== 1, "Unexpected anchor index %d.\n", ret
);
754 ret
= SendMessageA(list
, LB_GETCARETINDEX
, 0, 0);
755 ok(ret
== 1, "Unexpected caret index %d.\n", ret
);
760 static void test_listbox_height(void)
765 hList
= CreateWindowA( WC_LISTBOXA
, "list test", 0,
766 1, 1, 600, 100, NULL
, NULL
, NULL
, NULL
);
767 ok( hList
!= NULL
, "failed to create listbox\n");
769 id
= SendMessageA( hList
, LB_ADDSTRING
, 0, (LPARAM
) "hi");
770 ok( id
== 0, "item id wrong\n");
772 r
= SendMessageA( hList
, LB_SETITEMHEIGHT
, 0, MAKELPARAM( 20, 0 ));
773 ok( r
== 0, "send message failed\n");
775 r
= SendMessageA(hList
, LB_GETITEMHEIGHT
, 0, 0 );
776 ok( r
== 20, "height wrong\n");
778 r
= SendMessageA( hList
, LB_SETITEMHEIGHT
, 0, MAKELPARAM( 0, 30 ));
779 ok( r
== -1, "send message failed\n");
781 r
= SendMessageA(hList
, LB_GETITEMHEIGHT
, 0, 0 );
782 ok( r
== 20, "height wrong\n");
784 /* Before Windows 10 1709 (or 1703?) the item height was limited to 255.
785 * Since then, with comctl32 V6 the limit is 65535.
787 r
= SendMessageA( hList
, LB_SETITEMHEIGHT
, 0, MAKELPARAM( 256, 0 ));
788 ok(r
== 0 || broken(r
== -1), "Failed to set item height, %d.\n", r
);
791 r
= SendMessageA(hList
, LB_GETITEMHEIGHT
, 0, 0 );
792 ok( r
== 20, "Unexpected item height %d.\n", r
);
796 r
= SendMessageA(hList
, LB_GETITEMHEIGHT
, 0, 0 );
797 ok( r
== 256, "Unexpected item height %d.\n", r
);
799 r
= SendMessageA( hList
, LB_SETITEMHEIGHT
, 0, MAKELPARAM( 65535, 0 ));
800 ok(r
== 0, "Failed to set item height, %d.\n", r
);
802 r
= SendMessageA(hList
, LB_GETITEMHEIGHT
, 0, 0 );
803 ok( r
== 65535, "Unexpected item height %d.\n", r
);
806 r
= SendMessageA( hList
, LB_SETITEMHEIGHT
, 0, MAKELPARAM( 0xff, 0 ));
807 ok( r
== 0, "send message failed\n");
809 r
= SendMessageA(hList
, LB_GETITEMHEIGHT
, 0, 0 );
810 ok( r
== 0xff, "height wrong\n");
812 DestroyWindow( hList
);
815 static void test_changing_selection_styles(void)
817 static const DWORD styles
[] =
820 LBS_NODATA
| LBS_OWNERDRAWFIXED
822 static const DWORD selstyles
[] =
827 LBS_MULTIPLESEL
| LBS_EXTENDEDSEL
829 static const LONG selexpect_single
[] = { 0, 0, 1 };
830 static const LONG selexpect_single2
[] = { 1, 0, 0 };
831 static const LONG selexpect_multi
[] = { 1, 0, 1 };
832 static const LONG selexpect_multi2
[] = { 1, 1, 0 };
834 HWND parent
, listbox
;
839 parent
= create_parent();
840 ok(parent
!= NULL
, "Failed to create parent window.\n");
841 for (i
= 0; i
< ARRAY_SIZE(styles
); i
++)
843 /* Test if changing selection styles affects selection storage */
844 for (j
= 0; j
< ARRAY_SIZE(selstyles
); j
++)
846 LONG setcursel_expect
, selitemrange_expect
, getselcount_expect
;
847 const LONG
*selexpect
;
849 listbox
= CreateWindowA(WC_LISTBOXA
, "TestList", styles
[i
] | selstyles
[j
] | WS_CHILD
| WS_VISIBLE
,
850 0, 0, 100, 100, parent
, (HMENU
)ID_LISTBOX
, NULL
, 0);
851 ok(listbox
!= NULL
, "%u: Failed to create ListBox window.\n", j
);
853 if (selstyles
[j
] & (LBS_MULTIPLESEL
| LBS_EXTENDEDSEL
))
855 setcursel_expect
= LB_ERR
;
856 selitemrange_expect
= LB_OKAY
;
857 getselcount_expect
= 2;
858 selexpect
= selexpect_multi
;
862 setcursel_expect
= 2;
863 selitemrange_expect
= LB_ERR
;
864 getselcount_expect
= LB_ERR
;
865 selexpect
= selexpect_single
;
868 for (k
= 0; k
< ARRAY_SIZE(selexpect_multi
); k
++)
870 ret
= SendMessageA(listbox
, LB_INSERTSTRING
, -1, (LPARAM
)"x");
871 ok(ret
== k
, "%u: Unexpected return value %d, expected %d.\n", j
, ret
, k
);
873 ret
= SendMessageA(listbox
, LB_GETCOUNT
, 0, 0);
874 ok(ret
== ARRAY_SIZE(selexpect_multi
), "%u: Unexpected count %d.\n", j
, ret
);
876 /* Select items with different methods */
877 ret
= SendMessageA(listbox
, LB_SETCURSEL
, 2, 0);
878 ok(ret
== setcursel_expect
, "%u: Unexpected return value %d.\n", j
, ret
);
879 ret
= SendMessageA(listbox
, LB_SELITEMRANGE
, TRUE
, MAKELPARAM(0, 0));
880 ok(ret
== selitemrange_expect
, "%u: Unexpected return value %d.\n", j
, ret
);
881 ret
= SendMessageA(listbox
, LB_SELITEMRANGE
, TRUE
, MAKELPARAM(2, 2));
882 ok(ret
== selitemrange_expect
, "%u: Unexpected return value %d.\n", j
, ret
);
884 /* Verify that the proper items are selected */
885 for (k
= 0; k
< ARRAY_SIZE(selexpect_multi
); k
++)
887 ret
= SendMessageA(listbox
, LB_GETSEL
, k
, 0);
888 ok(ret
== selexpect
[k
], "%u: Unexpected selection state %d, expected %d.\n",
889 j
, ret
, selexpect
[k
]);
892 /* Now change the selection style */
893 style
= GetWindowLongA(listbox
, GWL_STYLE
);
894 ok((style
& (LBS_MULTIPLESEL
| LBS_EXTENDEDSEL
)) == selstyles
[j
],
895 "%u: unexpected window styles %#x.\n", j
, style
);
896 if (selstyles
[j
] & (LBS_MULTIPLESEL
| LBS_EXTENDEDSEL
))
897 style
&= ~selstyles
[j
];
899 style
|= LBS_MULTIPLESEL
| LBS_EXTENDEDSEL
;
900 SetWindowLongA(listbox
, GWL_STYLE
, style
);
901 style
= GetWindowLongA(listbox
, GWL_STYLE
);
902 ok(!(style
& selstyles
[j
]), "%u: unexpected window styles %#x.\n", j
, style
);
904 /* Verify that the same items are selected */
905 ret
= SendMessageA(listbox
, LB_GETSELCOUNT
, 0, 0);
906 ok(ret
== getselcount_expect
, "%u: expected %d from LB_GETSELCOUNT, got %d\n",
907 j
, getselcount_expect
, ret
);
909 for (k
= 0; k
< ARRAY_SIZE(selexpect_multi
); k
++)
911 ret
= SendMessageA(listbox
, LB_GETSEL
, k
, 0);
912 ok(ret
== selexpect
[k
], "%u: Unexpected selection state %d, expected %d.\n",
913 j
, ret
, selexpect
[k
]);
916 /* Lastly see if we can still change the selection as before with old style */
917 if (setcursel_expect
!= LB_ERR
) setcursel_expect
= 0;
918 ret
= SendMessageA(listbox
, LB_SETCURSEL
, 0, 0);
919 ok(ret
== setcursel_expect
, "%u: Unexpected return value %d.\n", j
, ret
);
920 ret
= SendMessageA(listbox
, LB_SELITEMRANGE
, TRUE
, MAKELPARAM(1, 1));
921 ok(ret
== selitemrange_expect
, "%u: Unexpected return value %d.\n", j
, ret
);
922 ret
= SendMessageA(listbox
, LB_SELITEMRANGE
, FALSE
, MAKELPARAM(2, 2));
923 ok(ret
== selitemrange_expect
, "%u: Unexpected return value %d.\n", j
, ret
);
925 /* And verify the selections */
926 selexpect
= (selstyles
[j
] & (LBS_MULTIPLESEL
| LBS_EXTENDEDSEL
)) ? selexpect_multi2
: selexpect_single2
;
927 ret
= SendMessageA(listbox
, LB_GETSELCOUNT
, 0, 0);
928 ok(ret
== getselcount_expect
, "%u: expected %d from LB_GETSELCOUNT, got %d\n",
929 j
, getselcount_expect
, ret
);
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 %d, expected %d.\n",
935 j
, ret
, selexpect
[k
]);
938 DestroyWindow(listbox
);
941 DestroyWindow(parent
);
944 static void test_itemfrompoint(void)
946 /* WS_POPUP is required in order to have a more accurate size calculation (
947 without caption). LBS_NOINTEGRALHEIGHT is required in order to test
948 behavior of partially-displayed item.
950 HWND hList
= CreateWindowA( WC_LISTBOXA
, "list test",
951 WS_VISIBLE
|WS_POPUP
|LBS_NOINTEGRALHEIGHT
,
952 1, 1, 600, 100, NULL
, NULL
, NULL
, NULL
);
956 r
= SendMessageA(hList
, LB_ITEMFROMPOINT
, 0, MAKELPARAM( /* x */ 30, /* y */ 30 ));
957 ok( r
== MAKELPARAM(0xffff, 1), "Unexpected ret value %#x.\n", r
);
959 r
= SendMessageA(hList
, LB_ITEMFROMPOINT
, 0, MAKELPARAM( 700, 30 ));
960 ok( r
== MAKELPARAM(0xffff, 1), "Unexpected ret value %#x.\n", r
);
962 r
= SendMessageA(hList
, LB_ITEMFROMPOINT
, 0, MAKELPARAM( 30, 300 ));
963 ok( r
== MAKELPARAM(0xffff, 1), "Unexpected ret value %#x.\n", r
);
965 id
= SendMessageA( hList
, LB_ADDSTRING
, 0, (LPARAM
) "hi");
966 ok( id
== 0, "item id wrong\n");
967 id
= SendMessageA( hList
, LB_ADDSTRING
, 0, (LPARAM
) "hi1");
968 ok( id
== 1, "item id wrong\n");
970 r
= SendMessageA(hList
, LB_ITEMFROMPOINT
, 0, MAKELPARAM( /* x */ 30, /* y */ 30 ));
971 ok( r
== 0x1, "ret %x\n", r
);
973 r
= SendMessageA(hList
, LB_ITEMFROMPOINT
, 0, MAKELPARAM( /* x */ 30, /* y */ 601 ));
974 ok( r
== MAKELPARAM(1, 1), "Unexpected ret value %#x.\n", r
);
976 /* Resize control so that below assertions about sizes are valid */
977 r
= SendMessageA( hList
, LB_GETITEMRECT
, 0, (LPARAM
)&rc
);
978 ok( r
== 1, "ret %x\n", r
);
979 r
= MoveWindow(hList
, 1, 1, 600, (rc
.bottom
- rc
.top
+ 1) * 9 / 2, TRUE
);
980 ok( r
!= 0, "ret %x\n", r
);
982 id
= SendMessageA( hList
, LB_ADDSTRING
, 0, (LPARAM
) "hi2");
983 ok( id
== 2, "item id wrong\n");
984 id
= SendMessageA( hList
, LB_ADDSTRING
, 0, (LPARAM
) "hi3");
985 ok( id
== 3, "item id wrong\n");
986 id
= SendMessageA( hList
, LB_ADDSTRING
, 0, (LPARAM
) "hi4");
987 ok( id
== 4, "item id wrong\n");
988 id
= SendMessageA( hList
, LB_ADDSTRING
, 0, (LPARAM
) "hi5");
989 ok( id
== 5, "item id wrong\n");
990 id
= SendMessageA( hList
, LB_ADDSTRING
, 0, (LPARAM
) "hi6");
991 ok( id
== 6, "item id wrong\n");
992 id
= SendMessageA( hList
, LB_ADDSTRING
, 0, (LPARAM
) "hi7");
993 ok( id
== 7, "item id wrong\n");
995 /* Set the listbox up so that id 1 is at the top, this leaves 5
996 partially visible at the bottom and 6, 7 are invisible */
998 SendMessageA( hList
, LB_SETTOPINDEX
, 1, 0);
999 r
= SendMessageA( hList
, LB_GETTOPINDEX
, 0, 0);
1000 ok( r
== 1, "top %d\n", r
);
1002 r
= SendMessageA( hList
, LB_GETITEMRECT
, 5, (LPARAM
)&rc
);
1003 ok( r
== 1, "ret %x\n", r
);
1004 r
= SendMessageA( hList
, LB_GETITEMRECT
, 6, (LPARAM
)&rc
);
1005 ok( r
== 0, "ret %x\n", r
);
1007 r
= SendMessageA( hList
, LB_ITEMFROMPOINT
, 0, MAKELPARAM(/* x */ 10, /* y */ 10) );
1008 ok( r
== 1, "ret %x\n", r
);
1010 r
= SendMessageA( hList
, LB_ITEMFROMPOINT
, 0, MAKELPARAM(1000, 10) );
1011 ok( r
== 0x10001, "ret %x\n", r
);
1013 r
= SendMessageA( hList
, LB_ITEMFROMPOINT
, 0, MAKELPARAM(10, -10) );
1014 ok( r
== 0x10001, "ret %x\n", r
);
1016 r
= SendMessageA( hList
, LB_ITEMFROMPOINT
, 0, MAKELPARAM(10, 100) );
1017 ok( r
== 0x10005, "item %x\n", r
);
1019 r
= SendMessageA( hList
, LB_ITEMFROMPOINT
, 0, MAKELPARAM(10, 200) );
1020 ok( r
== 0x10005, "item %x\n", r
);
1022 DestroyWindow( hList
);
1025 static void test_listbox_item_data(void)
1030 hList
= CreateWindowA( WC_LISTBOXA
, "list test", 0,
1031 1, 1, 600, 100, NULL
, NULL
, NULL
, NULL
);
1032 ok( hList
!= NULL
, "failed to create listbox\n");
1034 id
= SendMessageA( hList
, LB_ADDSTRING
, 0, (LPARAM
) "hi");
1035 ok( id
== 0, "item id wrong\n");
1037 r
= SendMessageA( hList
, LB_SETITEMDATA
, 0, MAKELPARAM( 20, 0 ));
1038 ok(r
== TRUE
, "LB_SETITEMDATA returned %d instead of TRUE\n", r
);
1040 r
= SendMessageA( hList
, LB_GETITEMDATA
, 0, 0);
1041 ok( r
== 20, "get item data failed\n");
1043 DestroyWindow( hList
);
1046 static void test_listbox_LB_DIR(void)
1048 char path
[MAX_PATH
], curdir
[MAX_PATH
];
1051 int itemCount_justFiles
;
1052 int itemCount_justDrives
;
1053 int itemCount_allFiles
;
1054 int itemCount_allDirs
;
1056 char pathBuffer
[MAX_PATH
];
1059 const char *wildcard
= "*";
1063 GetCurrentDirectoryA(ARRAY_SIZE(curdir
), curdir
);
1065 GetTempPathA(ARRAY_SIZE(path
), path
);
1066 ret
= SetCurrentDirectoryA(path
);
1067 ok(ret
, "Failed to set current directory.\n");
1069 ret
= CreateDirectoryA("lb_dir_test", NULL
);
1070 ok(ret
, "Failed to create test directory.\n");
1072 file
= CreateFileA( "wtest1.tmp.c", GENERIC_READ
|GENERIC_WRITE
, 0, NULL
, CREATE_NEW
, FILE_ATTRIBUTE_NORMAL
, NULL
);
1073 ok(file
!= INVALID_HANDLE_VALUE
, "Error creating the test file: %d\n", GetLastError());
1074 CloseHandle( file
);
1076 /* NOTE: for this test to succeed, there must be no subdirectories
1077 under the current directory. In addition, there must be at least
1078 one file that fits the wildcard w*.c . Normally, the test
1079 directory itself satisfies both conditions.
1081 hList
= CreateWindowA( WC_LISTBOXA
, "list test", WS_VISIBLE
|WS_POPUP
,
1082 1, 1, 600, 100, NULL
, NULL
, NULL
, NULL
);
1083 ok(hList
!= NULL
, "Failed to create listbox window.\n");
1085 /* Test for standard usage */
1087 /* This should list all the files in the test directory. */
1088 strcpy(pathBuffer
, wildcard
);
1089 SendMessageA(hList
, LB_RESETCONTENT
, 0, 0);
1090 res
= SendMessageA(hList
, LB_DIR
, 0, (LPARAM
)pathBuffer
);
1091 if (res
== -1) /* "*" wildcard doesn't work on win9x */
1094 strcpy(pathBuffer
, wildcard
);
1095 res
= SendMessageA(hList
, LB_DIR
, 0, (LPARAM
)pathBuffer
);
1097 ok (res
>= 0, "SendMessage(LB_DIR, 0, *) failed - 0x%08x\n", GetLastError());
1099 /* There should be some content in the listbox */
1100 itemCount
= SendMessageA(hList
, LB_GETCOUNT
, 0, 0);
1101 ok (itemCount
> 0, "SendMessage(LB_DIR) did NOT fill the listbox!\n");
1102 itemCount_allFiles
= itemCount
;
1103 ok(res
+ 1 == itemCount
,
1104 "SendMessage(LB_DIR, 0, *) returned incorrect index (expected %d got %d)!\n",
1105 itemCount
- 1, res
);
1107 /* This tests behavior when no files match the wildcard */
1108 strcpy(pathBuffer
, BAD_EXTENSION
);
1109 SendMessageA(hList
, LB_RESETCONTENT
, 0, 0);
1110 res
= SendMessageA(hList
, LB_DIR
, 0, (LPARAM
)pathBuffer
);
1111 ok (res
== -1, "SendMessage(LB_DIR, 0, %s) returned %d, expected -1\n", BAD_EXTENSION
, res
);
1113 /* There should be NO content in the listbox */
1114 itemCount
= SendMessageA(hList
, LB_GETCOUNT
, 0, 0);
1115 ok (itemCount
== 0, "SendMessage(LB_DIR) DID fill the listbox!\n");
1118 /* This should list all the w*.c files in the test directory
1119 * As of this writing, this includes win.c, winstation.c, wsprintf.c
1121 strcpy(pathBuffer
, "w*.c");
1122 SendMessageA(hList
, LB_RESETCONTENT
, 0, 0);
1123 res
= SendMessageA(hList
, LB_DIR
, 0, (LPARAM
)pathBuffer
);
1124 ok (res
>= 0, "SendMessage(LB_DIR, 0, w*.c) failed - 0x%08x\n", GetLastError());
1126 /* Path specification does NOT converted to uppercase */
1127 ok (!strcmp(pathBuffer
, "w*.c"),
1128 "expected no change to pathBuffer, got %s\n", pathBuffer
);
1130 /* There should be some content in the listbox */
1131 itemCount
= SendMessageA(hList
, LB_GETCOUNT
, 0, 0);
1132 ok (itemCount
> 0, "SendMessage(LB_DIR) did NOT fill the listbox!\n");
1133 itemCount_justFiles
= itemCount
;
1134 ok(res
+ 1 == itemCount
,
1135 "SendMessage(LB_DIR, 0, w*.c) returned incorrect index (expected %d got %d)!\n",
1136 itemCount
- 1, res
);
1138 /* Every single item in the control should start with a w and end in .c */
1139 for (i
= 0; i
< itemCount
; i
++)
1141 memset(pathBuffer
, 0, MAX_PATH
);
1142 SendMessageA(hList
, LB_GETTEXT
, i
, (LPARAM
)pathBuffer
);
1143 p
= pathBuffer
+ strlen(pathBuffer
);
1144 ok(((pathBuffer
[0] == 'w' || pathBuffer
[0] == 'W') &&
1145 (*(p
-1) == 'c' || *(p
-1) == 'C') &&
1146 (*(p
-2) == '.')), "Element %d (%s) does not fit requested w*.c\n", i
, pathBuffer
);
1149 /* Test DDL_DIRECTORY */
1150 strcpy(pathBuffer
, wildcard
);
1151 SendMessageA(hList
, LB_RESETCONTENT
, 0, 0);
1152 res
= SendMessageA(hList
, LB_DIR
, DDL_DIRECTORY
, (LPARAM
)pathBuffer
);
1153 ok (res
> 0, "SendMessage(LB_DIR, DDL_DIRECTORY, *) failed - 0x%08x\n", GetLastError());
1155 /* There should be some content in the listbox.
1156 * All files plus "[..]"
1158 itemCount
= SendMessageA(hList
, LB_GETCOUNT
, 0, 0);
1159 itemCount_allDirs
= itemCount
- itemCount_allFiles
;
1160 ok (itemCount
>= itemCount_allFiles
,
1161 "SendMessage(LB_DIR, DDL_DIRECTORY, *) filled with %d entries, expected > %d\n",
1162 itemCount
, itemCount_allFiles
);
1163 ok(res
+ 1 == itemCount
,
1164 "SendMessage(LB_DIR, DDL_DIRECTORY, *) returned incorrect index (expected %d got %d)!\n",
1165 itemCount
- 1, res
);
1167 /* This tests behavior when no files match the wildcard */
1168 strcpy(pathBuffer
, BAD_EXTENSION
);
1169 SendMessageA(hList
, LB_RESETCONTENT
, 0, 0);
1170 res
= SendMessageA(hList
, LB_DIR
, DDL_DIRECTORY
, (LPARAM
)pathBuffer
);
1171 ok (res
== -1, "SendMessage(LB_DIR, DDL_DIRECTORY, %s) returned %d, expected -1\n", BAD_EXTENSION
, res
);
1173 /* There should be NO content in the listbox */
1174 itemCount
= SendMessageA(hList
, LB_GETCOUNT
, 0, 0);
1175 ok (itemCount
== 0, "SendMessage(LB_DIR) DID fill the listbox!\n");
1177 /* Test DDL_DIRECTORY */
1178 strcpy(pathBuffer
, "w*.c");
1179 SendMessageA(hList
, LB_RESETCONTENT
, 0, 0);
1180 res
= SendMessageA(hList
, LB_DIR
, DDL_DIRECTORY
, (LPARAM
)pathBuffer
);
1181 ok (res
>= 0, "SendMessage(LB_DIR, DDL_DIRECTORY, w*.c) failed - 0x%08x\n", GetLastError());
1183 /* There should be some content in the listbox. Since the parent directory does not
1184 * fit w*.c, there should be exactly the same number of items as without DDL_DIRECTORY
1186 itemCount
= SendMessageA(hList
, LB_GETCOUNT
, 0, 0);
1187 ok (itemCount
== itemCount_justFiles
,
1188 "SendMessage(LB_DIR, DDL_DIRECTORY, w*.c) filled with %d entries, expected %d\n",
1189 itemCount
, itemCount_justFiles
);
1190 ok(res
+ 1 == itemCount
,
1191 "SendMessage(LB_DIR, DDL_DIRECTORY, w*.c) returned incorrect index (expected %d got %d)!\n",
1192 itemCount
- 1, res
);
1194 /* Every single item in the control should start with a w and end in .c. */
1195 for (i
= 0; i
< itemCount
; i
++)
1197 memset(pathBuffer
, 0, MAX_PATH
);
1198 SendMessageA(hList
, LB_GETTEXT
, i
, (LPARAM
)pathBuffer
);
1199 p
= pathBuffer
+ strlen(pathBuffer
);
1201 ((pathBuffer
[0] == 'w' || pathBuffer
[0] == 'W') &&
1202 (*(p
-1) == 'c' || *(p
-1) == 'C') &&
1203 (*(p
-2) == '.')), "Element %d (%s) does not fit requested w*.c\n", i
, pathBuffer
);
1206 /* Test DDL_DRIVES|DDL_EXCLUSIVE */
1207 strcpy(pathBuffer
, wildcard
);
1208 SendMessageA(hList
, LB_RESETCONTENT
, 0, 0);
1209 res
= SendMessageA(hList
, LB_DIR
, DDL_DRIVES
|DDL_EXCLUSIVE
, (LPARAM
)pathBuffer
);
1210 ok (res
>= 0, "SendMessage(LB_DIR, DDL_DRIVES|DDL_EXCLUSIVE, *) failed - 0x%08x\n", GetLastError());
1212 /* There should be some content in the listbox. In particular, there should
1213 * be at least one element before, since the string "[-c-]" should
1214 * have been added. Depending on the user setting, more drives might have
1217 itemCount
= SendMessageA(hList
, LB_GETCOUNT
, 0, 0);
1219 "SendMessage(LB_DIR, DDL_DRIVES|DDL_EXCLUSIVE, *) filled with %d entries, expected at least %d\n",
1221 itemCount_justDrives
= itemCount
;
1222 ok(res
+ 1 == itemCount
, "SendMessage(LB_DIR, DDL_DRIVES|DDL_EXCLUSIVE, *) returned incorrect index!\n");
1224 /* Every single item in the control should fit the format [-c-] */
1225 for (i
= 0; i
< itemCount
; i
++)
1227 memset(pathBuffer
, 0, MAX_PATH
);
1229 SendMessageA(hList
, LB_GETTEXT
, i
, (LPARAM
)pathBuffer
);
1230 ok( strlen(pathBuffer
) == 5, "Length of drive string is not 5\n" );
1231 ok( sscanf(pathBuffer
, "[-%c-]", &driveletter
) == 1, "Element %d (%s) does not fit [-X-]\n", i
, pathBuffer
);
1232 ok( driveletter
>= 'a' && driveletter
<= 'z', "Drive letter not in range a..z, got ascii %d\n", driveletter
);
1233 if (!(driveletter
>= 'a' && driveletter
<= 'z'))
1235 /* Correct after invalid entry is found */
1236 itemCount_justDrives
--;
1240 /* This tests behavior when no files match the wildcard */
1241 strcpy(pathBuffer
, BAD_EXTENSION
);
1242 SendMessageA(hList
, LB_RESETCONTENT
, 0, 0);
1243 res
= SendMessageA(hList
, LB_DIR
, DDL_DRIVES
|DDL_EXCLUSIVE
, (LPARAM
)pathBuffer
);
1244 ok (res
== itemCount_justDrives
-1, "SendMessage(LB_DIR, DDL_DRIVES|DDL_EXCLUSIVE, %s) returned %d, expected %d\n",
1245 BAD_EXTENSION
, res
, itemCount_justDrives
-1);
1247 itemCount
= SendMessageA(hList
, LB_GETCOUNT
, 0, 0);
1248 ok (itemCount
== itemCount_justDrives
, "SendMessage(LB_DIR) returned %d expected %d\n",
1249 itemCount
, itemCount_justDrives
);
1251 /* Test DDL_DRIVES. */
1252 strcpy(pathBuffer
, wildcard
);
1253 SendMessageA(hList
, LB_RESETCONTENT
, 0, 0);
1254 res
= SendMessageA(hList
, LB_DIR
, DDL_DRIVES
, (LPARAM
)pathBuffer
);
1255 ok (res
> 0, "SendMessage(LB_DIR, DDL_DRIVES, *) failed - 0x%08x\n", GetLastError());
1257 /* There should be some content in the listbox. In particular, there should
1258 * be at least one element before, since the string "[-c-]" should
1259 * have been added. Depending on the user setting, more drives might have
1262 itemCount
= SendMessageA(hList
, LB_GETCOUNT
, 0, 0);
1263 ok (itemCount
== itemCount_justDrives
+ itemCount_allFiles
,
1264 "SendMessage(LB_DIR, DDL_DRIVES, *) filled with %d entries, expected %d\n",
1265 itemCount
, itemCount_justDrives
+ itemCount_allFiles
);
1266 ok(res
+ 1 == itemCount
, "SendMessage(LB_DIR, DDL_DRIVES, *) returned incorrect index!\n");
1268 /* This tests behavior when no files match the wildcard */
1269 strcpy(pathBuffer
, BAD_EXTENSION
);
1270 SendMessageA(hList
, LB_RESETCONTENT
, 0, 0);
1271 res
= SendMessageA(hList
, LB_DIR
, DDL_DRIVES
, (LPARAM
)pathBuffer
);
1272 ok (res
== itemCount_justDrives
-1, "SendMessage(LB_DIR, DDL_DRIVES, %s) returned %d, expected %d\n",
1273 BAD_EXTENSION
, res
, itemCount_justDrives
-1);
1275 itemCount
= SendMessageA(hList
, LB_GETCOUNT
, 0, 0);
1276 ok (itemCount
== res
+ 1, "SendMessage(LB_DIR) returned %d expected %d\n", itemCount
, res
+ 1);
1278 /* Test DDL_DRIVES. */
1279 strcpy(pathBuffer
, "w*.c");
1280 SendMessageA(hList
, LB_RESETCONTENT
, 0, 0);
1281 res
= SendMessageA(hList
, LB_DIR
, DDL_DRIVES
, (LPARAM
)pathBuffer
);
1282 ok (res
> 0, "SendMessage(LB_DIR, DDL_DRIVES, w*.c) failed - 0x%08x\n", GetLastError());
1284 /* There should be some content in the listbox. In particular, there should
1285 * be at least one element before, since the string "[-c-]" should
1286 * have been added. Depending on the user setting, more drives might have
1289 itemCount
= SendMessageA(hList
, LB_GETCOUNT
, 0, 0);
1290 ok (itemCount
== itemCount_justDrives
+ itemCount_justFiles
,
1291 "SendMessage(LB_DIR, DDL_DRIVES, w*.c) filled with %d entries, expected %d\n",
1292 itemCount
, itemCount_justDrives
+ itemCount_justFiles
);
1293 ok(res
+ 1 == itemCount
, "SendMessage(LB_DIR, DDL_DRIVES, w*.c) returned incorrect index!\n");
1295 /* Every single item in the control should fit the format [-c-], or w*.c */
1296 for (i
= 0; i
< itemCount
; i
++)
1298 memset(pathBuffer
, 0, MAX_PATH
);
1300 SendMessageA(hList
, LB_GETTEXT
, i
, (LPARAM
)pathBuffer
);
1301 p
= pathBuffer
+ strlen(pathBuffer
);
1302 if (sscanf(pathBuffer
, "[-%c-]", &driveletter
) == 1)
1304 ok( strlen(pathBuffer
) == 5, "Length of drive string is not 5\n" );
1305 ok( driveletter
>= 'a' && driveletter
<= 'z', "Drive letter not in range a..z, got ascii %d\n", driveletter
);
1310 ((pathBuffer
[0] == 'w' || pathBuffer
[0] == 'W') &&
1311 (*(p
-1) == 'c' || *(p
-1) == 'C') &&
1312 (*(p
-2) == '.')), "Element %d (%s) does not fit requested w*.c\n", i
, pathBuffer
);
1316 /* Test DDL_DIRECTORY|DDL_DRIVES. This does *not* imply DDL_EXCLUSIVE */
1317 strcpy(pathBuffer
, wildcard
);
1318 SendMessageA(hList
, LB_RESETCONTENT
, 0, 0);
1319 res
= SendMessageA(hList
, LB_DIR
, DDL_DIRECTORY
|DDL_DRIVES
, (LPARAM
)pathBuffer
);
1320 ok (res
> 0, "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_DRIVES, *) failed - 0x%08x\n", GetLastError());
1322 /* There should be some content in the listbox. In particular, there should
1323 * be exactly the number of plain files, plus the number of mapped drives.
1325 itemCount
= SendMessageA(hList
, LB_GETCOUNT
, 0, 0);
1326 ok (itemCount
== itemCount_allFiles
+ itemCount_justDrives
+ itemCount_allDirs
,
1327 "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_DRIVES) filled with %d entries, expected %d\n",
1328 itemCount
, itemCount_allFiles
+ itemCount_justDrives
+ itemCount_allDirs
);
1329 ok(res
+ 1 == itemCount
, "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_DRIVES, w*.c) returned incorrect index!\n");
1331 /* Every single item in the control should start with a w and end in .c,
1332 * except for the "[..]" string, which should appear exactly as it is,
1333 * and the mapped drives in the format "[-X-]".
1335 for (i
= 0; i
< itemCount
; i
++)
1337 memset(pathBuffer
, 0, MAX_PATH
);
1339 SendMessageA(hList
, LB_GETTEXT
, i
, (LPARAM
)pathBuffer
);
1340 if (sscanf(pathBuffer
, "[-%c-]", &driveletter
) == 1)
1341 ok( driveletter
>= 'a' && driveletter
<= 'z', "Drive letter not in range a..z, got ascii %d\n", driveletter
);
1344 /* This tests behavior when no files match the wildcard */
1345 strcpy(pathBuffer
, BAD_EXTENSION
);
1346 SendMessageA(hList
, LB_RESETCONTENT
, 0, 0);
1347 res
= SendMessageA(hList
, LB_DIR
, DDL_DIRECTORY
|DDL_DRIVES
, (LPARAM
)pathBuffer
);
1348 ok (res
== itemCount_justDrives
-1, "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_DRIVES, %s) returned %d, expected %d\n",
1349 BAD_EXTENSION
, res
, itemCount_justDrives
-1);
1351 itemCount
= SendMessageA(hList
, LB_GETCOUNT
, 0, 0);
1352 ok (itemCount
== res
+ 1, "SendMessage(LB_DIR) returned %d expected %d\n", itemCount
, res
+ 1);
1354 /* Test DDL_DIRECTORY|DDL_DRIVES. */
1355 strcpy(pathBuffer
, "w*.c");
1356 SendMessageA(hList
, LB_RESETCONTENT
, 0, 0);
1357 res
= SendMessageA(hList
, LB_DIR
, DDL_DIRECTORY
|DDL_DRIVES
, (LPARAM
)pathBuffer
);
1358 ok (res
> 0, "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_DRIVES, w*.c) failed - 0x%08x\n", GetLastError());
1360 /* There should be some content in the listbox. In particular, there should
1361 * be exactly the number of plain files, plus the number of mapped drives.
1363 itemCount
= SendMessageA(hList
, LB_GETCOUNT
, 0, 0);
1364 ok (itemCount
== itemCount_justFiles
+ itemCount_justDrives
,
1365 "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_DRIVES) filled with %d entries, expected %d\n",
1366 itemCount
, itemCount_justFiles
+ itemCount_justDrives
);
1367 ok(res
+ 1 == itemCount
, "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_DRIVES, w*.c) returned incorrect index!\n");
1369 /* Every single item in the control should start with a w and end in .c,
1370 * except the mapped drives in the format "[-X-]". The "[..]" directory
1371 * should not appear.
1373 for (i
= 0; i
< itemCount
; i
++)
1375 memset(pathBuffer
, 0, MAX_PATH
);
1377 SendMessageA(hList
, LB_GETTEXT
, i
, (LPARAM
)pathBuffer
);
1378 p
= pathBuffer
+ strlen(pathBuffer
);
1379 if (sscanf(pathBuffer
, "[-%c-]", &driveletter
) == 1)
1380 ok( driveletter
>= 'a' && driveletter
<= 'z', "Drive letter not in range a..z, got ascii %d\n", driveletter
);
1383 ((pathBuffer
[0] == 'w' || pathBuffer
[0] == 'W') &&
1384 (*(p
-1) == 'c' || *(p
-1) == 'C') &&
1385 (*(p
-2) == '.')), "Element %d (%s) does not fit requested w*.c\n", i
, pathBuffer
);
1388 /* Test DDL_DIRECTORY|DDL_EXCLUSIVE. */
1389 strcpy(pathBuffer
, wildcard
);
1390 SendMessageA(hList
, LB_RESETCONTENT
, 0, 0);
1391 res
= SendMessageA(hList
, LB_DIR
, DDL_DIRECTORY
|DDL_EXCLUSIVE
, (LPARAM
)pathBuffer
);
1392 ok (res
!= -1, "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_EXCLUSIVE, *) failed err %u\n",
1395 itemCount
= SendMessageA(hList
, LB_GETCOUNT
, 0, 0);
1396 ok (itemCount
== itemCount_allDirs
,
1397 "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_EXCLUSIVE) filled with %d entries, expected %d\n",
1398 itemCount
, itemCount_allDirs
);
1399 ok(res
+ 1 == itemCount
, "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_EXCLUSIVE, *) returned incorrect index!\n");
1403 memset(pathBuffer
, 0, MAX_PATH
);
1404 SendMessageA(hList
, LB_GETTEXT
, 0, (LPARAM
)pathBuffer
);
1405 ok( !strcmp(pathBuffer
, "[..]"), "First element is %s, not [..]\n", pathBuffer
);
1408 /* This tests behavior when no files match the wildcard */
1409 strcpy(pathBuffer
, BAD_EXTENSION
);
1410 SendMessageA(hList
, LB_RESETCONTENT
, 0, 0);
1411 res
= SendMessageA(hList
, LB_DIR
, DDL_DIRECTORY
|DDL_EXCLUSIVE
, (LPARAM
)pathBuffer
);
1412 ok (res
== -1, "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_EXCLUSIVE, %s) returned %d, expected %d\n",
1413 BAD_EXTENSION
, res
, -1);
1415 itemCount
= SendMessageA(hList
, LB_GETCOUNT
, 0, 0);
1416 ok (itemCount
== res
+ 1, "SendMessage(LB_DIR) returned %d expected %d\n", itemCount
, res
+ 1);
1419 /* Test DDL_DIRECTORY|DDL_EXCLUSIVE. */
1420 strcpy(pathBuffer
, "w*.c");
1421 SendMessageA(hList
, LB_RESETCONTENT
, 0, 0);
1422 res
= SendMessageA(hList
, LB_DIR
, DDL_DIRECTORY
|DDL_EXCLUSIVE
, (LPARAM
)pathBuffer
);
1423 ok (res
== LB_ERR
, "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_EXCLUSIVE, w*.c) returned %d expected %d\n", res
, LB_ERR
);
1425 /* There should be no elements, since "[..]" does not fit w*.c */
1426 itemCount
= SendMessageA(hList
, LB_GETCOUNT
, 0, 0);
1428 "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_EXCLUSIVE) filled with %d entries, expected %d\n",
1431 /* Test DDL_DIRECTORY|DDL_DRIVES|DDL_EXCLUSIVE. */
1432 strcpy(pathBuffer
, wildcard
);
1433 SendMessageA(hList
, LB_RESETCONTENT
, 0, 0);
1434 res
= SendMessageA(hList
, LB_DIR
, DDL_DIRECTORY
|DDL_DRIVES
|DDL_EXCLUSIVE
, (LPARAM
)pathBuffer
);
1435 ok (res
> 0, "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_DRIVES|DDL_EXCLUSIVE, w*.c,) failed - 0x%08x\n", GetLastError());
1437 /* There should be no plain files on the listbox */
1438 itemCount
= SendMessageA(hList
, LB_GETCOUNT
, 0, 0);
1439 ok (itemCount
== itemCount_justDrives
+ itemCount_allDirs
,
1440 "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_DRIVES|DDL_EXCLUSIVE) filled with %d entries, expected %d\n",
1441 itemCount
, itemCount_justDrives
+ itemCount_allDirs
);
1442 ok(res
+ 1 == itemCount
, "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_DRIVES|DDL_EXCLUSIVE, w*.c) returned incorrect index!\n");
1444 for (i
= 0; i
< itemCount
; i
++)
1446 memset(pathBuffer
, 0, MAX_PATH
);
1448 SendMessageA(hList
, LB_GETTEXT
, i
, (LPARAM
)pathBuffer
);
1449 if (sscanf(pathBuffer
, "[-%c-]", &driveletter
) == 1)
1450 ok( driveletter
>= 'a' && driveletter
<= 'z', "Drive letter not in range a..z, got ascii %d\n", driveletter
);
1452 ok( pathBuffer
[0] == '[' && pathBuffer
[strlen(pathBuffer
)-1] == ']',
1453 "Element %d (%s) does not fit expected [...]\n", i
, pathBuffer
);
1456 /* This tests behavior when no files match the wildcard */
1457 strcpy(pathBuffer
, BAD_EXTENSION
);
1458 SendMessageA(hList
, LB_RESETCONTENT
, 0, 0);
1459 res
= SendMessageA(hList
, LB_DIR
, DDL_DIRECTORY
|DDL_DRIVES
|DDL_EXCLUSIVE
, (LPARAM
)pathBuffer
);
1460 ok (res
== itemCount_justDrives
-1, "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_DRIVES|DDL_EXCLUSIVE, %s) returned %d, expected %d\n",
1461 BAD_EXTENSION
, res
, itemCount_justDrives
-1);
1463 itemCount
= SendMessageA(hList
, LB_GETCOUNT
, 0, 0);
1464 ok (itemCount
== res
+ 1, "SendMessage(LB_DIR) returned %d expected %d\n", itemCount
, res
+ 1);
1466 /* Test DDL_DIRECTORY|DDL_DRIVES|DDL_EXCLUSIVE. */
1467 strcpy(pathBuffer
, "w*.c");
1468 SendMessageA(hList
, LB_RESETCONTENT
, 0, 0);
1469 res
= SendMessageA(hList
, LB_DIR
, DDL_DIRECTORY
|DDL_DRIVES
|DDL_EXCLUSIVE
, (LPARAM
)pathBuffer
);
1470 ok (res
>= 0, "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_DRIVES|DDL_EXCLUSIVE, w*.c,) failed - 0x%08x\n", GetLastError());
1472 /* There should be no plain files on the listbox, and no [..], since it does not fit w*.c */
1473 itemCount
= SendMessageA(hList
, LB_GETCOUNT
, 0, 0);
1474 ok (itemCount
== itemCount_justDrives
,
1475 "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_DRIVES|DDL_EXCLUSIVE) filled with %d entries, expected %d\n",
1476 itemCount
, itemCount_justDrives
);
1477 ok(res
+ 1 == itemCount
, "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_DRIVES|DDL_EXCLUSIVE, w*.c) returned incorrect index!\n");
1479 for (i
= 0; i
< itemCount
; i
++)
1481 memset(pathBuffer
, 0, MAX_PATH
);
1483 SendMessageA(hList
, LB_GETTEXT
, i
, (LPARAM
)pathBuffer
);
1484 ok (sscanf(pathBuffer
, "[-%c-]", &driveletter
) == 1, "Element %d (%s) does not fit [-X-]\n", i
, pathBuffer
);
1485 ok( driveletter
>= 'a' && driveletter
<= 'z', "Drive letter not in range a..z, got ascii %d\n", driveletter
);
1487 DestroyWindow(hList
);
1489 DeleteFileA( "wtest1.tmp.c" );
1490 RemoveDirectoryA("lb_dir_test");
1492 SetCurrentDirectoryA(curdir
);
1495 static HWND g_listBox
;
1496 static HWND g_label
;
1498 #define ID_TEST_LABEL 1001
1499 #define ID_TEST_LISTBOX 1002
1501 static BOOL
on_listbox_container_create(HWND hwnd
, CREATESTRUCTA
*lpcs
)
1503 g_label
= CreateWindowA(WC_STATICA
, "Contents of static control before DlgDirList.",
1504 WS_CHILD
| WS_VISIBLE
, 10, 10, 512, 32, hwnd
, (HMENU
)ID_TEST_LABEL
, NULL
, 0);
1505 if (!g_label
) return FALSE
;
1507 g_listBox
= CreateWindowA(WC_LISTBOXA
, "DlgDirList test",
1508 WS_CHILD
| WS_VISIBLE
| WS_TABSTOP
| WS_BORDER
| WS_VSCROLL
, 10, 60, 256, 256,
1509 hwnd
, (HMENU
)ID_TEST_LISTBOX
, NULL
, 0);
1510 if (!g_listBox
) return FALSE
;
1515 static LRESULT CALLBACK
listbox_container_window_procA(HWND hwnd
, UINT uiMsg
, WPARAM wParam
, LPARAM lParam
)
1525 result
= on_listbox_container_create(hwnd
, (CREATESTRUCTA
*)lParam
) ? 0 : (LRESULT
)-1;
1528 result
= DefWindowProcA(hwnd
, uiMsg
, wParam
, lParam
);
1534 static BOOL
RegisterListboxWindowClass(HINSTANCE hInst
)
1541 cls
.hInstance
= hInst
;
1543 cls
.hCursor
= LoadCursorA (NULL
, (LPCSTR
)IDC_ARROW
);
1544 cls
.hbrBackground
= (HBRUSH
)(COLOR_WINDOW
+ 1);
1545 cls
.lpszMenuName
= NULL
;
1546 cls
.lpfnWndProc
= listbox_container_window_procA
;
1547 cls
.lpszClassName
= "ListboxContainerClass";
1548 if (!RegisterClassA (&cls
)) return FALSE
;
1553 static void test_listbox_dlgdir(void)
1558 int itemCount_allDirs
;
1559 int itemCount_justFiles
;
1560 int itemCount_justDrives
;
1562 char pathBuffer
[MAX_PATH
];
1563 char itemBuffer
[MAX_PATH
];
1564 char tempBuffer
[MAX_PATH
];
1570 file
= CreateFileA( "wtest1.tmp.c", GENERIC_READ
|GENERIC_WRITE
, 0, NULL
, CREATE_NEW
, FILE_ATTRIBUTE_NORMAL
, NULL
);
1571 ok(file
!= INVALID_HANDLE_VALUE
, "Error creating the test file: %d\n", GetLastError());
1572 CloseHandle( file
);
1574 /* NOTE: for this test to succeed, there must be no subdirectories
1575 under the current directory. In addition, there must be at least
1576 one file that fits the wildcard w*.c . Normally, the test
1577 directory itself satisfies both conditions.
1580 hInst
= GetModuleHandleA(0);
1581 ret
= RegisterListboxWindowClass(hInst
);
1582 ok(ret
, "Failed to register test class.\n");
1584 hWnd
= CreateWindowA("ListboxContainerClass", "ListboxContainerClass",
1585 WS_OVERLAPPEDWINDOW
| WS_VISIBLE
,
1586 CW_USEDEFAULT
, CW_USEDEFAULT
, CW_USEDEFAULT
, CW_USEDEFAULT
,
1587 NULL
, NULL
, hInst
, 0);
1588 ok(hWnd
!= NULL
, "Failed to create container window.\n");
1590 /* Test for standard usage */
1592 /* The following should be overwritten by the directory path */
1593 SendMessageA(g_label
, WM_SETTEXT
, 0, (LPARAM
)"default contents");
1595 /* This should list all the w*.c files in the test directory
1596 * As of this writing, this includes win.c, winstation.c, wsprintf.c
1598 strcpy(pathBuffer
, "w*.c");
1599 res
= DlgDirListA(hWnd
, pathBuffer
, ID_TEST_LISTBOX
, ID_TEST_LABEL
, 0);
1600 ok (res
== 1, "DlgDirList(*.c, 0) returned %d - expected 1 - 0x%08x\n", res
, GetLastError());
1602 /* Path specification gets converted to uppercase */
1603 ok (!strcmp(pathBuffer
, "W*.C"),
1604 "expected conversion to uppercase, got %s\n", pathBuffer
);
1606 /* Loaded path should have overwritten the label text */
1607 SendMessageA(g_label
, WM_GETTEXT
, MAX_PATH
, (LPARAM
)pathBuffer
);
1608 ok (strcmp("default contents", pathBuffer
), "DlgDirList() did not modify static control!\n");
1610 /* There should be some content in the listbox */
1611 itemCount
= SendMessageA(g_listBox
, LB_GETCOUNT
, 0, 0);
1612 ok (itemCount
> 0, "DlgDirList() did NOT fill the listbox!\n");
1613 itemCount_justFiles
= itemCount
;
1615 /* Every single item in the control should start with a w and end in .c */
1616 for (i
= 0; i
< itemCount
; i
++)
1618 memset(pathBuffer
, 0, MAX_PATH
);
1619 SendMessageA(g_listBox
, LB_GETTEXT
, i
, (LPARAM
)pathBuffer
);
1620 p
= pathBuffer
+ strlen(pathBuffer
);
1621 ok(((pathBuffer
[0] == 'w' || pathBuffer
[0] == 'W') &&
1622 (*(p
-1) == 'c' || *(p
-1) == 'C') &&
1623 (*(p
-2) == '.')), "Element %d (%s) does not fit requested w*.c\n", i
, pathBuffer
);
1626 /* Test behavior when no files match the wildcard */
1627 strcpy(pathBuffer
, BAD_EXTENSION
);
1628 res
= DlgDirListA(hWnd
, pathBuffer
, ID_TEST_LISTBOX
, ID_TEST_LABEL
, 0);
1629 ok (res
== 1, "DlgDirList(%s, 0) returned %d expected 1\n", BAD_EXTENSION
, res
);
1631 itemCount
= SendMessageA(g_listBox
, LB_GETCOUNT
, 0, 0);
1632 ok (itemCount
== 0, "DlgDirList() DID fill the listbox!\n");
1634 /* Test DDL_DIRECTORY */
1635 strcpy(pathBuffer
, "w*.c");
1636 res
= DlgDirListA(hWnd
, pathBuffer
, ID_TEST_LISTBOX
, ID_TEST_LABEL
, DDL_DIRECTORY
);
1637 ok (res
== 1, "DlgDirList(*.c, DDL_DIRECTORY) failed - 0x%08x\n", GetLastError());
1639 /* There should be some content in the listbox. In particular, there should
1640 * be exactly more elements than before, since the directories should
1643 itemCount
= SendMessageA(g_listBox
, LB_GETCOUNT
, 0, 0);
1644 itemCount_allDirs
= itemCount
- itemCount_justFiles
;
1645 ok (itemCount
>= itemCount_justFiles
, "DlgDirList(DDL_DIRECTORY) filled with %d entries, expected > %d\n",
1646 itemCount
, itemCount_justFiles
);
1648 /* Every single item in the control should start with a w and end in .c,
1649 * except for the "[..]" string, which should appear exactly as it is.
1651 for (i
= 0; i
< itemCount
; i
++)
1653 memset(pathBuffer
, 0, MAX_PATH
);
1654 SendMessageA(g_listBox
, LB_GETTEXT
, i
, (LPARAM
)pathBuffer
);
1655 p
= pathBuffer
+ strlen(pathBuffer
);
1656 ok( (pathBuffer
[0] == '[' && pathBuffer
[strlen(pathBuffer
)-1] == ']') ||
1657 ((pathBuffer
[0] == 'w' || pathBuffer
[0] == 'W') &&
1658 (*(p
-1) == 'c' || *(p
-1) == 'C') &&
1659 (*(p
-2) == '.')), "Element %d (%s) does not fit requested w*.c\n", i
, pathBuffer
);
1662 /* Test behavior when no files match the wildcard */
1663 strcpy(pathBuffer
, BAD_EXTENSION
);
1664 res
= DlgDirListA(hWnd
, pathBuffer
, ID_TEST_LISTBOX
, ID_TEST_LABEL
, DDL_DIRECTORY
);
1665 ok (res
== 1, "DlgDirList(%s, DDL_DIRECTORY) returned %d expected 1\n", BAD_EXTENSION
, res
);
1667 itemCount
= SendMessageA(g_listBox
, LB_GETCOUNT
, 0, 0);
1668 ok (itemCount
== itemCount_allDirs
, "DlgDirList() incorrectly filled the listbox! (expected %d got %d)\n",
1669 itemCount_allDirs
, itemCount
);
1670 for (i
= 0; i
< itemCount
; i
++)
1672 memset(pathBuffer
, 0, MAX_PATH
);
1673 SendMessageA(g_listBox
, LB_GETTEXT
, i
, (LPARAM
)pathBuffer
);
1674 ok( pathBuffer
[0] == '[' && pathBuffer
[strlen(pathBuffer
)-1] == ']',
1675 "Element %d (%s) does not fit requested [...]\n", i
, pathBuffer
);
1678 /* Test DDL_DRIVES. At least on WinXP-SP2, this implies DDL_EXCLUSIVE */
1679 strcpy(pathBuffer
, "w*.c");
1680 res
= DlgDirListA(hWnd
, pathBuffer
, ID_TEST_LISTBOX
, ID_TEST_LABEL
, DDL_DRIVES
);
1681 ok (res
== 1, "DlgDirList(*.c, DDL_DRIVES) failed - 0x%08x\n", GetLastError());
1683 /* There should be some content in the listbox. In particular, there should
1684 * be at least one element before, since the string "[-c-]" should
1685 * have been added. Depending on the user setting, more drives might have
1688 itemCount
= SendMessageA(g_listBox
, LB_GETCOUNT
, 0, 0);
1690 "DlgDirList(DDL_DRIVES) filled with %d entries, expected at least %d\n",
1692 itemCount_justDrives
= itemCount
;
1694 /* Every single item in the control should fit the format [-c-] */
1695 for (i
= 0; i
< itemCount
; i
++)
1697 memset(pathBuffer
, 0, MAX_PATH
);
1699 SendMessageA(g_listBox
, LB_GETTEXT
, i
, (LPARAM
)pathBuffer
);
1700 ok( strlen(pathBuffer
) == 5, "Length of drive string is not 5\n" );
1701 ok( sscanf(pathBuffer
, "[-%c-]", &driveletter
) == 1, "Element %d (%s) does not fit [-X-]\n", i
, pathBuffer
);
1702 ok( driveletter
>= 'a' && driveletter
<= 'z', "Drive letter not in range a..z, got ascii %d\n", driveletter
);
1703 if (!(driveletter
>= 'a' && driveletter
<= 'z')) {
1704 /* Correct after invalid entry is found */
1705 trace("removing count of invalid entry %s\n", pathBuffer
);
1706 itemCount_justDrives
--;
1710 /* Test behavior when no files match the wildcard */
1711 strcpy(pathBuffer
, BAD_EXTENSION
);
1712 res
= DlgDirListA(hWnd
, pathBuffer
, ID_TEST_LISTBOX
, ID_TEST_LABEL
, DDL_DRIVES
);
1713 ok (res
== 1, "DlgDirList(%s, DDL_DRIVES) returned %d expected 1\n", BAD_EXTENSION
, res
);
1715 itemCount
= SendMessageA(g_listBox
, LB_GETCOUNT
, 0, 0);
1716 ok (itemCount
== itemCount_justDrives
, "DlgDirList() incorrectly filled the listbox!\n");
1718 /* Test DDL_DIRECTORY|DDL_DRIVES. This does *not* imply DDL_EXCLUSIVE */
1719 strcpy(pathBuffer
, "w*.c");
1720 res
= DlgDirListA(hWnd
, pathBuffer
, ID_TEST_LISTBOX
, ID_TEST_LABEL
, DDL_DIRECTORY
|DDL_DRIVES
);
1721 ok (res
== 1, "DlgDirList(*.c, DDL_DIRECTORY|DDL_DRIVES) failed - 0x%08x\n", GetLastError());
1723 /* There should be some content in the listbox. In particular, there should
1724 * be exactly the number of plain files, plus the number of mapped drives,
1727 itemCount
= SendMessageA(g_listBox
, LB_GETCOUNT
, 0, 0);
1728 ok (itemCount
== itemCount_justFiles
+ itemCount_justDrives
+ itemCount_allDirs
,
1729 "DlgDirList(DDL_DIRECTORY|DDL_DRIVES) filled with %d entries, expected %d\n",
1730 itemCount
, itemCount_justFiles
+ itemCount_justDrives
+ itemCount_allDirs
);
1732 /* Every single item in the control should start with a w and end in .c,
1733 * except for the "[..]" string, which should appear exactly as it is,
1734 * and the mapped drives in the format "[-X-]".
1736 for (i
= 0; i
< itemCount
; i
++)
1738 memset(pathBuffer
, 0, MAX_PATH
);
1740 SendMessageA(g_listBox
, LB_GETTEXT
, i
, (LPARAM
)pathBuffer
);
1741 p
= pathBuffer
+ strlen(pathBuffer
);
1742 if (sscanf(pathBuffer
, "[-%c-]", &driveletter
) == 1)
1743 ok( driveletter
>= 'a' && driveletter
<= 'z', "Drive letter not in range a..z, got ascii %d\n", driveletter
);
1745 ok( (pathBuffer
[0] == '[' && pathBuffer
[strlen(pathBuffer
)-1] == ']') ||
1746 ((pathBuffer
[0] == 'w' || pathBuffer
[0] == 'W') &&
1747 (*(p
-1) == 'c' || *(p
-1) == 'C') &&
1748 (*(p
-2) == '.')), "Element %d (%s) does not fit requested w*.c\n", i
, pathBuffer
);
1751 /* Test behavior when no files match the wildcard */
1752 strcpy(pathBuffer
, BAD_EXTENSION
);
1753 res
= DlgDirListA(hWnd
, pathBuffer
, ID_TEST_LISTBOX
, ID_TEST_LABEL
, DDL_DIRECTORY
|DDL_DRIVES
);
1754 ok (res
== 1, "DlgDirList(%s, DDL_DIRECTORY|DDL_DRIVES) returned %d expected 1\n", BAD_EXTENSION
, res
);
1756 itemCount
= SendMessageA(g_listBox
, LB_GETCOUNT
, 0, 0);
1757 ok (itemCount
== itemCount_justDrives
+ itemCount_allDirs
,
1758 "DlgDirList() incorrectly filled the listbox! (expected %d got %d)\n",
1759 itemCount_justDrives
+ itemCount_allDirs
, itemCount
);
1761 /* Test DDL_DIRECTORY|DDL_EXCLUSIVE. */
1762 strcpy(pathBuffer
, "w*.c");
1763 res
= DlgDirListA(hWnd
, pathBuffer
, ID_TEST_LISTBOX
, ID_TEST_LABEL
, DDL_DIRECTORY
|DDL_EXCLUSIVE
);
1764 ok (res
== 1, "DlgDirList(*.c, DDL_DIRECTORY|DDL_EXCLUSIVE) failed - 0x%08x\n", GetLastError());
1766 /* There should be exactly one element: "[..]" */
1767 itemCount
= SendMessageA(g_listBox
, LB_GETCOUNT
, 0, 0);
1768 ok (itemCount
== itemCount_allDirs
,
1769 "DlgDirList(DDL_DIRECTORY|DDL_EXCLUSIVE) filled with %d entries, expected %d\n",
1770 itemCount
, itemCount_allDirs
);
1772 if (itemCount
&& GetCurrentDirectoryA( MAX_PATH
, pathBuffer
) > 3) /* there's no [..] in drive root */
1774 memset(pathBuffer
, 0, MAX_PATH
);
1775 SendMessageA(g_listBox
, LB_GETTEXT
, 0, (LPARAM
)pathBuffer
);
1776 ok( !strcmp(pathBuffer
, "[..]"), "First (and only) element is not [..]\n");
1779 /* Test behavior when no files match the wildcard */
1780 strcpy(pathBuffer
, BAD_EXTENSION
);
1781 res
= DlgDirListA(hWnd
, pathBuffer
, ID_TEST_LISTBOX
, ID_TEST_LABEL
, DDL_DIRECTORY
|DDL_EXCLUSIVE
);
1782 ok (res
== 1, "DlgDirList(%s, DDL_DIRECTORY|DDL_EXCLUSIVE) returned %d expected 1\n", BAD_EXTENSION
, res
);
1784 itemCount
= SendMessageA(g_listBox
, LB_GETCOUNT
, 0, 0);
1785 ok (itemCount
== itemCount_allDirs
, "DlgDirList() incorrectly filled the listbox!\n");
1787 /* Test DDL_DIRECTORY|DDL_DRIVES|DDL_EXCLUSIVE. */
1788 strcpy(pathBuffer
, "w*.c");
1789 res
= DlgDirListA(hWnd
, pathBuffer
, ID_TEST_LISTBOX
, ID_TEST_LABEL
, DDL_DIRECTORY
|DDL_DRIVES
|DDL_EXCLUSIVE
);
1790 ok (res
== 1, "DlgDirList(*.c, DDL_DIRECTORY|DDL_DRIVES|DDL_EXCLUSIVE) failed - 0x%08x\n", GetLastError());
1792 /* There should be no plain files on the listbox */
1793 itemCount
= SendMessageA(g_listBox
, LB_GETCOUNT
, 0, 0);
1794 ok (itemCount
== itemCount_justDrives
+ itemCount_allDirs
,
1795 "DlgDirList(DDL_DIRECTORY|DDL_EXCLUSIVE) filled with %d entries, expected %d\n",
1796 itemCount
, itemCount_justDrives
+ itemCount_allDirs
);
1798 for (i
= 0; i
< itemCount
; i
++)
1800 memset(pathBuffer
, 0, MAX_PATH
);
1802 SendMessageA(g_listBox
, LB_GETTEXT
, i
, (LPARAM
)pathBuffer
);
1803 if (sscanf(pathBuffer
, "[-%c-]", &driveletter
) == 1)
1804 ok( driveletter
>= 'a' && driveletter
<= 'z', "Drive letter not in range a..z, got ascii %d\n", driveletter
);
1806 ok( pathBuffer
[0] == '[' && pathBuffer
[strlen(pathBuffer
)-1] == ']',
1807 "Element %d (%s) does not fit expected [...]\n", i
, pathBuffer
);
1810 /* Test behavior when no files match the wildcard */
1811 strcpy(pathBuffer
, BAD_EXTENSION
);
1812 res
= DlgDirListA(hWnd
, pathBuffer
, ID_TEST_LISTBOX
, ID_TEST_LABEL
, DDL_DIRECTORY
|DDL_DRIVES
|DDL_EXCLUSIVE
);
1813 ok (res
== 1, "DlgDirList(%s, DDL_DIRECTORY|DDL_DRIVES|DDL_EXCLUSIVE) returned %d expected 1\n", BAD_EXTENSION
, res
);
1815 itemCount
= SendMessageA(g_listBox
, LB_GETCOUNT
, 0, 0);
1816 ok (itemCount
== itemCount_justDrives
+ itemCount_allDirs
, "DlgDirList() incorrectly filled the listbox!\n");
1818 /* Now test DlgDirSelectEx() in normal operation */
1819 /* Fill with everything - drives, directory and all plain files. */
1820 strcpy(pathBuffer
, "*");
1821 res
= DlgDirListA(hWnd
, pathBuffer
, ID_TEST_LISTBOX
, ID_TEST_LABEL
, DDL_DIRECTORY
|DDL_DRIVES
);
1822 ok (res
!= 0, "DlgDirList(*, DDL_DIRECTORY|DDL_DRIVES) failed - 0x%08x\n", GetLastError());
1824 SendMessageA(g_listBox
, LB_SETCURSEL
, -1, 0); /* Unselect any current selection */
1825 memset(pathBuffer
, 0, MAX_PATH
);
1826 SetLastError(0xdeadbeef);
1827 res
= DlgDirSelectExA(hWnd
, pathBuffer
, MAX_PATH
, ID_TEST_LISTBOX
);
1828 ok (GetLastError() == 0xdeadbeef,
1829 "DlgDirSelectEx() with no selection modified last error code from 0xdeadbeef to 0x%08x\n",
1831 ok (res
== 0, "DlgDirSelectEx() with no selection returned %d, expected 0\n", res
);
1832 /* WinXP-SP2 leaves pathBuffer untouched, but Win98 fills it with garbage. */
1834 ok (!*pathBuffer, "DlgDirSelectEx() with no selection filled buffer with %s\n", pathBuffer);
1836 /* Test proper drive/dir/file recognition */
1837 itemCount
= SendMessageA(g_listBox
, LB_GETCOUNT
, 0, 0);
1838 for (i
= 0; i
< itemCount
; i
++)
1840 memset(itemBuffer
, 0, MAX_PATH
);
1841 memset(pathBuffer
, 0, MAX_PATH
);
1842 memset(tempBuffer
, 0, MAX_PATH
);
1844 SendMessageA(g_listBox
, LB_GETTEXT
, i
, (LPARAM
)itemBuffer
);
1845 res
= SendMessageA(g_listBox
, LB_SETCURSEL
, i
, 0);
1846 ok (res
== i
, "SendMessageA(LB_SETCURSEL, %d) failed\n", i
);
1847 if (sscanf(itemBuffer
, "[-%c-]", &driveletter
) == 1)
1849 /* Current item is a drive letter */
1850 SetLastError(0xdeadbeef);
1851 res
= DlgDirSelectExA(hWnd
, pathBuffer
, MAX_PATH
, ID_TEST_LISTBOX
);
1852 ok (GetLastError() == 0xdeadbeef,
1853 "DlgDirSelectEx() with selection at %d modified last error code from 0xdeadbeef to 0x%08x\n",
1855 ok(res
== 1, "DlgDirSelectEx() thinks %s (%s) is not a drive/directory!\n", itemBuffer
, pathBuffer
);
1857 /* For drive letters, DlgDirSelectEx tacks on a colon */
1858 ok (pathBuffer
[0] == driveletter
&& pathBuffer
[1] == ':' && pathBuffer
[2] == '\0',
1859 "%d: got \"%s\" expected \"%c:\"\n", i
, pathBuffer
, driveletter
);
1861 else if (itemBuffer
[0] == '[')
1863 /* Current item is the parent directory */
1864 SetLastError(0xdeadbeef);
1865 res
= DlgDirSelectExA(hWnd
, pathBuffer
, MAX_PATH
, ID_TEST_LISTBOX
);
1866 ok (GetLastError() == 0xdeadbeef,
1867 "DlgDirSelectEx() with selection at %d modified last error code from 0xdeadbeef to 0x%08x\n",
1869 ok(res
== 1, "DlgDirSelectEx() thinks %s (%s) is not a drive/directory!\n", itemBuffer
, pathBuffer
);
1871 /* For directories, DlgDirSelectEx tacks on a backslash */
1872 p
= pathBuffer
+ strlen(pathBuffer
);
1873 ok (*(p
-1) == '\\', "DlgDirSelectEx did NOT tack on a backslash to dir, got %s\n", pathBuffer
);
1875 tempBuffer
[0] = '[';
1876 lstrcpynA(tempBuffer
+ 1, pathBuffer
, strlen(pathBuffer
));
1877 strcat(tempBuffer
, "]");
1878 ok (!strcmp(tempBuffer
, itemBuffer
), "Formatted directory should be %s, got %s\n", tempBuffer
, itemBuffer
);
1882 /* Current item is a plain file */
1883 SetLastError(0xdeadbeef);
1884 res
= DlgDirSelectExA(hWnd
, pathBuffer
, MAX_PATH
, ID_TEST_LISTBOX
);
1885 ok (GetLastError() == 0xdeadbeef,
1886 "DlgDirSelectEx() with selection at %d modified last error code from 0xdeadbeef to 0x%08x\n",
1888 ok(res
== 0, "DlgDirSelectEx() thinks %s (%s) is a drive/directory!\n", itemBuffer
, pathBuffer
);
1890 /* NOTE: WinXP tacks a period on all files that lack an extension. This affects
1891 * for example, "Makefile", which gets reported as "Makefile."
1893 strcpy(tempBuffer
, itemBuffer
);
1894 if (strchr(tempBuffer
, '.') == NULL
) strcat(tempBuffer
, ".");
1895 ok (!strcmp(pathBuffer
, tempBuffer
), "Formatted file should be %s, got %s\n", tempBuffer
, pathBuffer
);
1899 DeleteFileA( "wtest1.tmp.c" );
1901 /* Now test DlgDirSelectEx() in abnormal operation */
1902 /* Fill list with bogus entries, that look somewhat valid */
1903 SendMessageA(g_listBox
, LB_RESETCONTENT
, 0, 0);
1904 SendMessageA(g_listBox
, LB_ADDSTRING
, 0, (LPARAM
)"[notexist.dir]");
1905 SendMessageA(g_listBox
, LB_ADDSTRING
, 0, (LPARAM
)"notexist.fil");
1906 itemCount
= SendMessageA(g_listBox
, LB_GETCOUNT
, 0, 0);
1907 for (i
= 0; i
< itemCount
; i
++)
1909 memset(itemBuffer
, 0, MAX_PATH
);
1910 memset(pathBuffer
, 0, MAX_PATH
);
1911 memset(tempBuffer
, 0, MAX_PATH
);
1913 SendMessageA(g_listBox
, LB_GETTEXT
, i
, (LPARAM
)itemBuffer
);
1914 res
= SendMessageA(g_listBox
, LB_SETCURSEL
, i
, 0);
1915 ok (res
== i
, "SendMessage(LB_SETCURSEL, %d) failed\n", i
);
1916 if (sscanf(itemBuffer
, "[-%c-]", &driveletter
) == 1)
1918 /* Current item is a drive letter */
1919 SetLastError(0xdeadbeef);
1920 res
= DlgDirSelectExA(hWnd
, pathBuffer
, MAX_PATH
, ID_TEST_LISTBOX
);
1921 ok (GetLastError() == 0xdeadbeef,
1922 "DlgDirSelectEx() with selection at %d modified last error code from 0xdeadbeef to 0x%08x\n",
1924 ok(res
== 1, "DlgDirSelectEx() thinks %s (%s) is not a drive/directory!\n", itemBuffer
, pathBuffer
);
1926 /* For drive letters, DlgDirSelectEx tacks on a colon */
1927 ok (pathBuffer
[0] == driveletter
&& pathBuffer
[1] == ':' && pathBuffer
[2] == '\0',
1928 "%d: got \"%s\" expected \"%c:\"\n", i
, pathBuffer
, driveletter
);
1930 else if (itemBuffer
[0] == '[')
1932 /* Current item is the parent directory */
1933 SetLastError(0xdeadbeef);
1934 res
= DlgDirSelectExA(hWnd
, pathBuffer
, MAX_PATH
, ID_TEST_LISTBOX
);
1935 ok (GetLastError() == 0xdeadbeef,
1936 "DlgDirSelectEx() with selection at %d modified last error code from 0xdeadbeef to 0x%08x\n",
1938 ok(res
== 1, "DlgDirSelectEx() thinks %s (%s) is not a drive/directory!\n", itemBuffer
, pathBuffer
);
1940 /* For directories, DlgDirSelectEx tacks on a backslash */
1941 p
= pathBuffer
+ strlen(pathBuffer
);
1942 ok (*(p
-1) == '\\', "DlgDirSelectEx did NOT tack on a backslash to dir, got %s\n", pathBuffer
);
1944 tempBuffer
[0] = '[';
1945 lstrcpynA(tempBuffer
+ 1, pathBuffer
, strlen(pathBuffer
));
1946 strcat(tempBuffer
, "]");
1947 ok (!strcmp(tempBuffer
, itemBuffer
), "Formatted directory should be %s, got %s\n", tempBuffer
, itemBuffer
);
1951 /* Current item is a plain file */
1952 SetLastError(0xdeadbeef);
1953 res
= DlgDirSelectExA(hWnd
, pathBuffer
, MAX_PATH
, ID_TEST_LISTBOX
);
1954 ok (GetLastError() == 0xdeadbeef,
1955 "DlgDirSelectEx() with selection at %d modified last error code from 0xdeadbeef to 0x%08x\n",
1957 ok(res
== 0, "DlgDirSelectEx() thinks %s (%s) is a drive/directory!\n", itemBuffer
, pathBuffer
);
1959 /* NOTE: WinXP and Win98 tack a period on all files that lack an extension.
1960 * This affects for example, "Makefile", which gets reported as "Makefile."
1962 strcpy(tempBuffer
, itemBuffer
);
1963 if (strchr(tempBuffer
, '.') == NULL
) strcat(tempBuffer
, ".");
1964 ok (!strcmp(pathBuffer
, tempBuffer
), "Formatted file should be %s, got %s\n", tempBuffer
, pathBuffer
);
1968 /* Test behavior when loading folders from root with and without wildcard */
1969 strcpy(pathBuffer
, "C:\\");
1970 res
= DlgDirListA(hWnd
, pathBuffer
, ID_TEST_LISTBOX
, 0, DDL_DIRECTORY
| DDL_EXCLUSIVE
);
1971 ok(res
, "DlgDirList failed to list C:\\ folders\n");
1972 ok(!strcmp(pathBuffer
, "*"), "DlgDirList set the invalid path spec '%s', expected '*'\n", pathBuffer
);
1974 strcpy(pathBuffer
, "C:\\*");
1975 res
= DlgDirListA(hWnd
, pathBuffer
, ID_TEST_LISTBOX
, 0, DDL_DIRECTORY
| DDL_EXCLUSIVE
);
1976 ok(res
, "DlgDirList failed to list C:\\* folders\n");
1977 ok(!strcmp(pathBuffer
, "*"), "DlgDirList set the invalid path spec '%s', expected '*'\n", pathBuffer
);
1979 /* Try loading files from an invalid folder */
1980 SetLastError(0xdeadbeef);
1981 strcpy(pathBuffer
, "C:\\INVALID$$DIR");
1982 res
= DlgDirListA(hWnd
, pathBuffer
, ID_TEST_LISTBOX
, 0, DDL_DIRECTORY
| DDL_EXCLUSIVE
);
1983 ok(!res
, "DlgDirList should have failed with 0 but %d was returned\n", res
);
1984 ok(GetLastError() == ERROR_NO_WILDCARD_CHARACTERS
,
1985 "GetLastError should return 0x589, got 0x%X\n",GetLastError());
1987 DestroyWindow(hWnd
);
1990 static void test_set_count( void )
1992 static const DWORD styles
[] =
1997 HWND parent
, listbox
;
2002 parent
= create_parent();
2003 listbox
= create_listbox( LBS_OWNERDRAWFIXED
| LBS_NODATA
| WS_CHILD
| WS_VISIBLE
, parent
);
2005 UpdateWindow( listbox
);
2006 GetUpdateRect( listbox
, &r
, TRUE
);
2007 ok( IsRectEmpty( &r
), "got non-empty rect\n");
2009 ret
= SendMessageA( listbox
, LB_SETCOUNT
, 100, 0 );
2010 ok( ret
== 0, "got %d\n", ret
);
2011 ret
= SendMessageA( listbox
, LB_GETCOUNT
, 0, 0 );
2012 ok( ret
== 100, "got %d\n", ret
);
2014 GetUpdateRect( listbox
, &r
, TRUE
);
2015 ok( !IsRectEmpty( &r
), "got empty rect\n");
2017 ValidateRect( listbox
, NULL
);
2018 GetUpdateRect( listbox
, &r
, TRUE
);
2019 ok( IsRectEmpty( &r
), "got non-empty rect\n");
2021 ret
= SendMessageA( listbox
, LB_SETCOUNT
, 99, 0 );
2022 ok( ret
== 0, "got %d\n", ret
);
2024 GetUpdateRect( listbox
, &r
, TRUE
);
2025 ok( !IsRectEmpty( &r
), "got empty rect\n");
2027 ret
= SendMessageA( listbox
, LB_SETCOUNT
, -5, 0 );
2028 ok( ret
== 0, "got %d\n", ret
);
2029 ret
= SendMessageA( listbox
, LB_GETCOUNT
, 0, 0 );
2030 ok( ret
== -5, "got %d\n", ret
);
2032 DestroyWindow( listbox
);
2034 for (i
= 0; i
< ARRAY_SIZE(styles
); ++i
)
2036 listbox
= create_listbox( styles
[i
] | WS_CHILD
| WS_VISIBLE
, parent
);
2038 SetLastError( 0xdeadbeef );
2039 ret
= SendMessageA( listbox
, LB_SETCOUNT
, 100, 0 );
2040 ok( ret
== LB_ERR
, "expected %d, got %d\n", LB_ERR
, ret
);
2041 ok( GetLastError() == 0xdeadbeef, "Unexpected error %d.\n", GetLastError() );
2043 DestroyWindow( listbox
);
2046 DestroyWindow( parent
);
2049 static void test_GetListBoxInfo(void)
2051 static const struct message getlistboxinfo_seq
[] =
2053 { LB_GETLISTBOXINFO
, sent
},
2056 HWND listbox
, parent
;
2059 parent
= create_parent();
2060 listbox
= create_listbox(WS_CHILD
| WS_VISIBLE
, parent
);
2062 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
2063 ret
= GetListBoxInfo(listbox
);
2064 ok(ret
> 0, "got %d\n", ret
);
2065 ok_sequence(sequences
, LB_SEQ_INDEX
, getlistboxinfo_seq
, "GetListBoxInfo()", FALSE
);
2067 DestroyWindow(listbox
);
2068 DestroyWindow(parent
);
2071 static void test_init_storage( void )
2073 static const DWORD styles
[] =
2076 LBS_NODATA
| LBS_OWNERDRAWFIXED
,
2078 HWND parent
, listbox
;
2079 LONG ret
, items_size
;
2082 parent
= create_parent();
2083 for (i
= 0; i
< ARRAY_SIZE(styles
); i
++)
2085 listbox
= CreateWindowA(WC_LISTBOXA
, "TestList", styles
[i
] | WS_CHILD
,
2086 0, 0, 100, 100, parent
, (HMENU
)ID_LISTBOX
, NULL
, 0);
2088 items_size
= SendMessageA(listbox
, LB_INITSTORAGE
, 100, 0);
2089 ok(items_size
>= 100, "expected at least 100, got %d\n", items_size
);
2091 ret
= SendMessageA(listbox
, LB_INITSTORAGE
, 0, 0);
2092 ok(ret
== items_size
, "expected %d, got %d\n", items_size
, ret
);
2094 /* it doesn't grow since the space was already reserved */
2095 ret
= SendMessageA(listbox
, LB_INITSTORAGE
, items_size
, 0);
2096 ok(ret
== items_size
, "expected %d, got %d\n", items_size
, ret
);
2098 /* it doesn't shrink the reserved space */
2099 ret
= SendMessageA(listbox
, LB_INITSTORAGE
, 42, 0);
2100 ok(ret
== items_size
, "expected %d, got %d\n", items_size
, ret
);
2102 /* now populate almost all of it so it's not reserved anymore */
2103 if (styles
[i
] & LBS_NODATA
)
2105 ret
= SendMessageA(listbox
, LB_SETCOUNT
, items_size
- 1, 0);
2106 ok(ret
== 0, "unexpected return value %d\n", ret
);
2110 for (j
= 0; j
< items_size
- 1; j
++)
2112 ret
= SendMessageA(listbox
, LB_INSERTSTRING
, -1, (LPARAM
)"");
2113 ok(ret
== j
, "expected %d, got %d\n", j
, ret
);
2117 /* we still have one more reserved slot, so it doesn't grow yet */
2118 ret
= SendMessageA(listbox
, LB_INITSTORAGE
, 1, 0);
2119 ok(ret
== items_size
, "expected %d, got %d\n", items_size
, ret
);
2121 /* fill the slot and check again, it should grow this time */
2122 ret
= SendMessageA(listbox
, LB_INSERTSTRING
, -1, (LPARAM
)"");
2123 ok(ret
== items_size
- 1, "expected %d, got %d\n", items_size
- 1, ret
);
2124 ret
= SendMessageA(listbox
, LB_INITSTORAGE
, 0, 0);
2125 ok(ret
== items_size
, "expected %d, got %d\n", items_size
, ret
);
2126 ret
= SendMessageA(listbox
, LB_INITSTORAGE
, 1, 0);
2127 ok(ret
> items_size
, "expected it to grow past %d, got %d\n", items_size
, ret
);
2129 DestroyWindow(listbox
);
2131 DestroyWindow(parent
);
2134 static void test_missing_lbuttonup(void)
2136 HWND listbox
, parent
, capture
;
2138 parent
= create_parent();
2139 listbox
= create_listbox(WS_CHILD
| WS_VISIBLE
, parent
);
2141 /* Send button down without a corresponding button up */
2142 SendMessageA(listbox
, WM_LBUTTONDOWN
, 0, MAKELPARAM(10, 10));
2143 capture
= GetCapture();
2144 ok(capture
== listbox
, "got %p expected %p\n", capture
, listbox
);
2146 /* Capture is released and LBN_SELCHANGE sent during WM_KILLFOCUS */
2149 capture
= GetCapture();
2150 ok(capture
== NULL
, "got %p\n", capture
);
2151 ok(got_selchange
, "got %d\n", got_selchange
);
2153 DestroyWindow(listbox
);
2154 DestroyWindow(parent
);
2157 static void test_extents(void)
2159 HWND listbox
, parent
;
2164 parent
= create_parent();
2166 listbox
= create_listbox(WS_CHILD
| WS_VISIBLE
, parent
);
2168 res
= SendMessageA(listbox
, LB_GETHORIZONTALEXTENT
, 0, 0);
2169 ok(res
== 0, "Got wrong initial horizontal extent: %u\n", res
);
2171 sinfo
.cbSize
= sizeof(sinfo
);
2172 sinfo
.fMask
= SIF_RANGE
;
2173 br
= GetScrollInfo(listbox
, SB_HORZ
, &sinfo
);
2174 ok(br
== TRUE
, "GetScrollInfo failed\n");
2175 ok(sinfo
.nMin
== 0, "got wrong min: %u\n", sinfo
.nMin
);
2176 ok(sinfo
.nMax
== 100, "got wrong max: %u\n", sinfo
.nMax
);
2177 ok((GetWindowLongA(listbox
, GWL_STYLE
) & WS_HSCROLL
) == 0,
2178 "List box should not have a horizontal scroll bar\n");
2180 /* horizontal extent < width */
2181 SendMessageA(listbox
, LB_SETHORIZONTALEXTENT
, 64, 0);
2183 res
= SendMessageA(listbox
, LB_GETHORIZONTALEXTENT
, 0, 0);
2184 ok(res
== 64, "Got wrong horizontal extent: %u\n", res
);
2186 sinfo
.cbSize
= sizeof(sinfo
);
2187 sinfo
.fMask
= SIF_RANGE
;
2188 br
= GetScrollInfo(listbox
, SB_HORZ
, &sinfo
);
2189 ok(br
== TRUE
, "GetScrollInfo failed\n");
2190 ok(sinfo
.nMin
== 0, "got wrong min: %u\n", sinfo
.nMin
);
2191 ok(sinfo
.nMax
== 100, "got wrong max: %u\n", sinfo
.nMax
);
2192 ok((GetWindowLongA(listbox
, GWL_STYLE
) & WS_HSCROLL
) == 0,
2193 "List box should not have a horizontal scroll bar\n");
2195 /* horizontal extent > width */
2196 SendMessageA(listbox
, LB_SETHORIZONTALEXTENT
, 184, 0);
2198 res
= SendMessageA(listbox
, LB_GETHORIZONTALEXTENT
, 0, 0);
2199 ok(res
== 184, "Got wrong horizontal extent: %u\n", res
);
2201 sinfo
.cbSize
= sizeof(sinfo
);
2202 sinfo
.fMask
= SIF_RANGE
;
2203 br
= GetScrollInfo(listbox
, SB_HORZ
, &sinfo
);
2204 ok(br
== TRUE
, "GetScrollInfo failed\n");
2205 ok(sinfo
.nMin
== 0, "got wrong min: %u\n", sinfo
.nMin
);
2206 ok(sinfo
.nMax
== 100, "got wrong max: %u\n", sinfo
.nMax
);
2207 ok((GetWindowLongA(listbox
, GWL_STYLE
) & WS_HSCROLL
) == 0,
2208 "List box should not have a horizontal scroll bar\n");
2210 DestroyWindow(listbox
);
2212 listbox
= create_listbox(WS_CHILD
| WS_VISIBLE
| WS_HSCROLL
, parent
);
2214 res
= SendMessageA(listbox
, LB_GETHORIZONTALEXTENT
, 0, 0);
2215 ok(res
== 0, "Got wrong initial horizontal extent: %u\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: %u\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
== 63, "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: %u\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
== 183, "got wrong max: %u\n", sinfo
.nMax
);
2253 ok((GetWindowLongA(listbox
, GWL_STYLE
) & WS_HSCROLL
) != 0,
2254 "List box should have a horizontal scroll bar\n");
2256 SendMessageA(listbox
, LB_SETHORIZONTALEXTENT
, 0, 0);
2258 res
= SendMessageA(listbox
, LB_GETHORIZONTALEXTENT
, 0, 0);
2259 ok(res
== 0, "Got wrong horizontal extent: %u\n", res
);
2261 sinfo
.cbSize
= sizeof(sinfo
);
2262 sinfo
.fMask
= SIF_RANGE
;
2263 br
= GetScrollInfo(listbox
, SB_HORZ
, &sinfo
);
2264 ok(br
== TRUE
, "GetScrollInfo failed\n");
2265 ok(sinfo
.nMin
== 0, "got wrong min: %u\n", sinfo
.nMin
);
2266 ok(sinfo
.nMax
== 0, "got wrong max: %u\n", sinfo
.nMax
);
2267 ok((GetWindowLongA(listbox
, GWL_STYLE
) & WS_HSCROLL
) == 0,
2268 "List box should not have a horizontal scroll bar\n");
2270 DestroyWindow(listbox
);
2273 listbox
= create_listbox(WS_CHILD
| WS_VISIBLE
| WS_HSCROLL
| LBS_DISABLENOSCROLL
, parent
);
2275 res
= SendMessageA(listbox
, LB_GETHORIZONTALEXTENT
, 0, 0);
2276 ok(res
== 0, "Got wrong initial horizontal extent: %u\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
== 0, "got wrong max: %u\n", sinfo
.nMax
);
2284 ok((GetWindowLongA(listbox
, GWL_STYLE
) & WS_HSCROLL
) != 0,
2285 "List box should have a horizontal scroll bar\n");
2287 /* horizontal extent < width */
2288 SendMessageA(listbox
, LB_SETHORIZONTALEXTENT
, 64, 0);
2290 res
= SendMessageA(listbox
, LB_GETHORIZONTALEXTENT
, 0, 0);
2291 ok(res
== 64, "Got wrong horizontal extent: %u\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
== 63, "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 /* horizontal extent > width */
2303 SendMessageA(listbox
, LB_SETHORIZONTALEXTENT
, 184, 0);
2305 res
= SendMessageA(listbox
, LB_GETHORIZONTALEXTENT
, 0, 0);
2306 ok(res
== 184, "Got wrong horizontal extent: %u\n", res
);
2308 sinfo
.cbSize
= sizeof(sinfo
);
2309 sinfo
.fMask
= SIF_RANGE
;
2310 br
= GetScrollInfo(listbox
, SB_HORZ
, &sinfo
);
2311 ok(br
== TRUE
, "GetScrollInfo failed\n");
2312 ok(sinfo
.nMin
== 0, "got wrong min: %u\n", sinfo
.nMin
);
2313 ok(sinfo
.nMax
== 183, "got wrong max: %u\n", sinfo
.nMax
);
2314 ok((GetWindowLongA(listbox
, GWL_STYLE
) & WS_HSCROLL
) != 0,
2315 "List box should have a horizontal scroll bar\n");
2317 SendMessageA(listbox
, LB_SETHORIZONTALEXTENT
, 0, 0);
2319 res
= SendMessageA(listbox
, LB_GETHORIZONTALEXTENT
, 0, 0);
2320 ok(res
== 0, "Got wrong horizontal extent: %u\n", res
);
2322 sinfo
.cbSize
= sizeof(sinfo
);
2323 sinfo
.fMask
= SIF_RANGE
;
2324 br
= GetScrollInfo(listbox
, SB_HORZ
, &sinfo
);
2325 ok(br
== TRUE
, "GetScrollInfo failed\n");
2326 ok(sinfo
.nMin
== 0, "got wrong min: %u\n", sinfo
.nMin
);
2327 ok(sinfo
.nMax
== 0, "got wrong max: %u\n", sinfo
.nMax
);
2328 ok((GetWindowLongA(listbox
, GWL_STYLE
) & WS_HSCROLL
) != 0,
2329 "List box should have a horizontal scroll bar\n");
2331 DestroyWindow(listbox
);
2333 DestroyWindow(parent
);
2336 static void test_listbox(void)
2338 static const struct listbox_test SS
=
2340 {{LB_ERR
, LB_ERR
, 0, LB_ERR
}, {0,0,0,0},
2341 { 1, 1, 1, LB_ERR
}, {0,0,0,0},
2342 { 2, 2, 2, LB_ERR
}, {0,0,0,0},
2343 {LB_ERR
, LB_ERR
, 0, LB_ERR
}, {0,0,0,0}};
2345 /* {selected, anchor, caret, selcount}{TODO fields} */
2346 static const struct listbox_test SS_NS
=
2347 {{LB_ERR
, LB_ERR
, 0, LB_ERR
}, {0,0,0,0},
2348 { 1, 1, 1, LB_ERR
}, {0,0,0,0},
2349 { 2, 2, 2, LB_ERR
}, {0,0,0,0},
2350 {LB_ERR
, LB_ERR
, 0, LB_ERR
}, {0,0,0,0}};
2352 static const struct listbox_test MS
=
2353 {{ 0, LB_ERR
, 0, 0}, {0,0,0,0},
2354 { 1, 1, 1, 1}, {0,0,0,0},
2355 { 2, 1, 2, 1}, {0,0,0,0},
2356 { 0, LB_ERR
, 0, 2}, {0,0,0,0}};
2358 static const struct listbox_test MS_NS
=
2359 {{LB_ERR
, LB_ERR
, 0, LB_ERR
}, {0,0,0,0},
2360 { 1, 1, 1, LB_ERR
}, {0,0,0,0},
2361 { 2, 2, 2, LB_ERR
}, {0,0,0,0},
2362 {LB_ERR
, LB_ERR
, 0, LB_ERR
}, {0,0,0,0}};
2364 static const struct listbox_test ES
=
2365 {{ 0, LB_ERR
, 0, 0}, {0,0,0,0},
2366 { 1, 1, 1, 1}, {0,0,0,0},
2367 { 2, 2, 2, 1}, {0,0,0,0},
2368 { 0, LB_ERR
, 0, 2}, {0,0,0,0}};
2370 static const struct listbox_test ES_NS
=
2371 {{LB_ERR
, LB_ERR
, 0, LB_ERR
}, {0,0,0,0},
2372 { 1, 1, 1, LB_ERR
}, {0,0,0,0},
2373 { 2, 2, 2, LB_ERR
}, {0,0,0,0},
2374 {LB_ERR
, LB_ERR
, 0, LB_ERR
}, {0,0,0,0}};
2376 static const struct listbox_test EMS
=
2377 {{ 0, LB_ERR
, 0, 0}, {0,0,0,0},
2378 { 1, 1, 1, 1}, {0,0,0,0},
2379 { 2, 2, 2, 1}, {0,0,0,0},
2380 { 0, LB_ERR
, 0, 2}, {0,0,0,0}};
2382 static const struct listbox_test EMS_NS
=
2383 {{LB_ERR
, LB_ERR
, 0, LB_ERR
}, {0,0,0,0},
2384 { 1, 1, 1, LB_ERR
}, {0,0,0,0},
2385 { 2, 2, 2, LB_ERR
}, {0,0,0,0},
2386 {LB_ERR
, LB_ERR
, 0, LB_ERR
}, {0,0,0,0}};
2389 run_test(LBS_NOSEL
, SS_NS
);
2390 run_test(LBS_MULTIPLESEL
, MS
);
2391 run_test(LBS_MULTIPLESEL
| LBS_NOSEL
, MS_NS
);
2392 run_test(LBS_EXTENDEDSEL
, ES
);
2393 run_test(LBS_EXTENDEDSEL
| LBS_NOSEL
, ES_NS
);
2394 run_test(LBS_EXTENDEDSEL
| LBS_MULTIPLESEL
, EMS
);
2395 run_test(LBS_EXTENDEDSEL
| LBS_MULTIPLESEL
| LBS_NOSEL
, EMS_NS
);
2397 run_test(LBS_NODATA
| LBS_OWNERDRAWFIXED
, SS
);
2398 run_test(LBS_NODATA
| LBS_OWNERDRAWFIXED
| LBS_NOSEL
, SS_NS
);
2399 run_test(LBS_NODATA
| LBS_OWNERDRAWFIXED
| LBS_MULTIPLESEL
, MS
);
2400 run_test(LBS_NODATA
| LBS_OWNERDRAWFIXED
| LBS_MULTIPLESEL
| LBS_NOSEL
, MS_NS
);
2401 run_test(LBS_NODATA
| LBS_OWNERDRAWFIXED
| LBS_EXTENDEDSEL
, ES
);
2402 run_test(LBS_NODATA
| LBS_OWNERDRAWFIXED
| LBS_EXTENDEDSEL
| LBS_NOSEL
, ES_NS
);
2403 run_test(LBS_NODATA
| LBS_OWNERDRAWFIXED
| LBS_EXTENDEDSEL
| LBS_MULTIPLESEL
, EMS
);
2404 run_test(LBS_NODATA
| LBS_OWNERDRAWFIXED
| LBS_EXTENDEDSEL
| LBS_MULTIPLESEL
| LBS_NOSEL
, EMS_NS
);
2407 static const struct message lb_addstring_ownerdraw_parent_seq
[] =
2409 { WM_MEASUREITEM
, sent
|wparam
|lparam
, 0x1012, 0xf30604ed },
2410 { WM_MEASUREITEM
, sent
|wparam
|lparam
, 0x1112, 0xf30604ee },
2411 { WM_MEASUREITEM
, sent
|wparam
|lparam
, 0x1212, 0xf30604ef },
2415 static const struct message lb_addstring_sort_parent_seq
[] =
2417 { WM_MEASUREITEM
, sent
|wparam
|lparam
, 0x1012, 0xf30604ed },
2418 { WM_COMPAREITEM
, sent
|wparam
|lparam
, 0xf30604ed, 0xf30604ee },
2419 { WM_MEASUREITEM
, sent
|wparam
|lparam
, 0x1112, 0xf30604ee },
2420 { WM_COMPAREITEM
, sent
|wparam
|lparam
, 0xf30604ed, 0xf30604ef },
2421 { WM_COMPAREITEM
, sent
|wparam
|lparam
, 0xf30604ee, 0xf30604ef },
2422 { WM_MEASUREITEM
, sent
|wparam
|lparam
, 0x1212, 0xf30604ef },
2426 static const struct message empty_seq
[] =
2431 static void test_WM_MEASUREITEM(void)
2433 HWND parent
, listbox
;
2436 parent
= create_parent();
2437 listbox
= create_listbox(WS_CHILD
| LBS_OWNERDRAWVARIABLE
, parent
);
2439 data
= SendMessageA(listbox
, LB_GETITEMDATA
, 0, 0);
2440 ok(data
== (LRESULT
)strings
[0], "data = %08lx, expected %p\n", data
, strings
[0]);
2441 DestroyWindow(parent
);
2443 parent
= create_parent();
2444 listbox
= create_listbox(WS_CHILD
| LBS_OWNERDRAWVARIABLE
| LBS_HASSTRINGS
, parent
);
2446 data
= SendMessageA(listbox
, LB_GETITEMDATA
, 0, 0);
2447 ok(!data
, "data = %08lx\n", data
);
2449 /* LBS_HASSTRINGS */
2450 parent
= create_parent();
2451 listbox
= CreateWindowExA(WS_EX_NOPARENTNOTIFY
, WC_LISTBOXA
, NULL
,
2452 WS_CHILD
| LBS_NOTIFY
| LBS_OWNERDRAWVARIABLE
| LBS_HASSTRINGS
| WS_VISIBLE
,
2453 10, 10, 80, 80, parent
, (HMENU
)ID_LISTBOX
, 0, NULL
);
2455 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
2457 ret
= SendMessageA(listbox
, LB_ADDSTRING
, 0, (LPARAM
)"item 0");
2458 ok(ret
== 0, "expected 0, got %ld\n", ret
);
2459 ret
= SendMessageA(listbox
, LB_ADDSTRING
, 0, (LPARAM
)"item 1");
2460 ok(ret
== 1, "expected 1, got %ld\n", ret
);
2461 ret
= SendMessageA(listbox
, LB_ADDSTRING
, 0, (LPARAM
)"item 2");
2462 ok(ret
== 2, "expected 2, got %ld\n", ret
);
2464 ok_sequence(sequences
, PARENT_SEQ_INDEX
, lb_addstring_ownerdraw_parent_seq
,
2465 "LB_ADDSTRING (LBS_HASSTRINGS, ownerdraw)", FALSE
);
2466 DestroyWindow(listbox
);
2468 /* LBS_SORT, no LBS_HASSTRINGS */
2469 listbox
= CreateWindowExA(WS_EX_NOPARENTNOTIFY
, WC_LISTBOXA
, NULL
,
2470 WS_CHILD
| LBS_NOTIFY
| LBS_OWNERDRAWVARIABLE
| LBS_SORT
| WS_VISIBLE
,
2471 10, 10, 80, 80, parent
, (HMENU
)ID_LISTBOX
, 0, NULL
);
2473 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
2475 ret
= SendMessageA(listbox
, LB_ADDSTRING
, 0, (LPARAM
)"item 0");
2476 ok(ret
== 0, "expected 0, got %ld\n", ret
);
2477 ret
= SendMessageA(listbox
, LB_ADDSTRING
, 0, (LPARAM
)"item 1");
2478 ok(ret
== 1, "expected 1, got %ld\n", ret
);
2479 ret
= SendMessageA(listbox
, LB_ADDSTRING
, 0, (LPARAM
)"item 2");
2480 ok(ret
== 2, "expected 2, got %ld\n", ret
);
2482 ok_sequence(sequences
, PARENT_SEQ_INDEX
, lb_addstring_sort_parent_seq
, "LB_ADDSTRING (LBS_SORT)", FALSE
);
2483 DestroyWindow(listbox
);
2485 /* LBS_HASSTRINGS */
2486 listbox
= CreateWindowExA(WS_EX_NOPARENTNOTIFY
, WC_LISTBOXA
, NULL
,
2487 WS_CHILD
| LBS_NOTIFY
| LBS_HASSTRINGS
| WS_VISIBLE
,
2488 10, 10, 80, 80, parent
, (HMENU
)ID_LISTBOX
, 0, NULL
);
2490 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
2492 ret
= SendMessageA(listbox
, LB_ADDSTRING
, 0, (LPARAM
)"item 2");
2493 ok(ret
== 0, "expected 0, got %ld\n", ret
);
2494 ret
= SendMessageA(listbox
, LB_ADDSTRING
, 0, (LPARAM
)"item 0");
2495 ok(ret
== 1, "expected 1, got %ld\n", ret
);
2496 ret
= SendMessageA(listbox
, LB_ADDSTRING
, 0, (LPARAM
)"item 1");
2497 ok(ret
== 2, "expected 2, got %ld\n", ret
);
2499 ok_sequence(sequences
, PARENT_SEQ_INDEX
, empty_seq
, "LB_ADDSTRING (LBS_HASSTRINGS)", FALSE
);
2500 DestroyWindow(listbox
);
2502 /* LBS_HASSTRINGS, LBS_SORT */
2503 listbox
= CreateWindowExA(WS_EX_NOPARENTNOTIFY
, WC_LISTBOXA
, NULL
,
2504 WS_CHILD
| LBS_NOTIFY
| LBS_HASSTRINGS
| LBS_SORT
| WS_VISIBLE
,
2505 10, 10, 80, 80, parent
, (HMENU
)ID_LISTBOX
, 0, NULL
);
2507 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
2509 ret
= SendMessageA(listbox
, LB_ADDSTRING
, 0, (LPARAM
)"item 2");
2510 ok(ret
== 0, "expected 0, got %ld\n", ret
);
2511 ret
= SendMessageA(listbox
, LB_ADDSTRING
, 0, (LPARAM
)"item 0");
2512 ok(ret
== 0, "expected 0, got %ld\n", ret
);
2513 ret
= SendMessageA(listbox
, LB_ADDSTRING
, 0, (LPARAM
)"item 1");
2514 ok(ret
== 1, "expected 1, got %ld\n", ret
);
2516 ok_sequence(sequences
, PARENT_SEQ_INDEX
, empty_seq
, "LB_ADDSTRING (LBS_HASSTRINGS, LBS_SORT)", FALSE
);
2517 DestroyWindow(listbox
);
2519 DestroyWindow(parent
);
2522 static void test_LBS_NODATA(void)
2524 static const DWORD invalid_styles
[] =
2527 LBS_OWNERDRAWVARIABLE
,
2530 LBS_OWNERDRAWFIXED
| LBS_SORT
,
2531 LBS_OWNERDRAWFIXED
| LBS_HASSTRINGS
,
2533 static const UINT invalid_idx
[] = { -2, 2 };
2534 static const UINT valid_idx
[] = { 0, 1 };
2535 static const ULONG_PTR zero_data
;
2536 HWND listbox
, parent
;
2542 listbox
= CreateWindowA(WC_LISTBOXA
, "TestList", LBS_NODATA
| LBS_OWNERDRAWFIXED
| WS_VISIBLE
,
2543 0, 0, 100, 100, NULL
, NULL
, NULL
, 0);
2544 ok(listbox
!= NULL
, "Failed to create ListBox window.\n");
2546 ret
= SendMessageA(listbox
, LB_INSERTSTRING
, -1, 0);
2547 ok(ret
== 0, "Unexpected return value %d.\n", ret
);
2548 ret
= SendMessageA(listbox
, LB_INSERTSTRING
, -1, 0);
2549 ok(ret
== 1, "Unexpected return value %d.\n", ret
);
2550 ret
= SendMessageA(listbox
, LB_GETCOUNT
, 0, 0);
2551 ok(ret
== 2, "Unexpected return value %d.\n", ret
);
2553 /* Invalid indices. */
2554 for (i
= 0; i
< ARRAY_SIZE(invalid_idx
); ++i
)
2556 ret
= SendMessageA(listbox
, LB_SETITEMDATA
, invalid_idx
[i
], 42);
2557 ok(ret
== LB_ERR
, "Unexpected return value %d.\n", ret
);
2558 ret
= SendMessageA(listbox
, LB_GETTEXTLEN
, invalid_idx
[i
], 0);
2559 ok(ret
== LB_ERR
, "Unexpected return value %d.\n", ret
);
2562 ret
= SendMessageA(listbox
, LB_GETTEXT
, invalid_idx
[i
], (LPARAM
)&data
);
2563 ok(ret
== LB_ERR
, "Unexpected return value %d.\n", ret
);
2565 ret
= SendMessageA(listbox
, LB_GETITEMDATA
, invalid_idx
[i
], 0);
2566 ok(ret
== LB_ERR
, "Unexpected return value %d.\n", ret
);
2569 IsWow64Process(GetCurrentProcess(), &is_wow64
);
2573 text_len
= is_wow64
? 8 : 4;
2576 /* Valid indices. */
2577 for (i
= 0; i
< ARRAY_SIZE(valid_idx
); ++i
)
2579 ret
= SendMessageA(listbox
, LB_SETITEMDATA
, valid_idx
[i
], 42);
2580 ok(ret
== TRUE
, "Unexpected return value %d.\n", ret
);
2581 ret
= SendMessageA(listbox
, LB_GETTEXTLEN
, valid_idx
[i
], 0);
2582 todo_wine_if(is_wow64
)
2583 ok(ret
== text_len
, "Unexpected return value %d.\n", ret
);
2585 memset(&data
, 0xee, sizeof(data
));
2586 ret
= SendMessageA(listbox
, LB_GETTEXT
, valid_idx
[i
], (LPARAM
)&data
);
2587 ok(ret
== sizeof(data
), "Unexpected return value %d.\n", ret
);
2588 ok(!memcmp(&data
, &zero_data
, sizeof(data
)), "Unexpected item data.\n");
2590 ret
= SendMessageA(listbox
, LB_GETITEMDATA
, valid_idx
[i
], 0);
2591 ok(ret
== 0, "Unexpected return value %d.\n", ret
);
2594 /* More messages that don't work with LBS_NODATA. */
2595 ret
= SendMessageA(listbox
, LB_FINDSTRING
, 1, 0);
2596 ok(ret
== LB_ERR
, "Unexpected return value %d.\n", ret
);
2597 ret
= SendMessageA(listbox
, LB_FINDSTRING
, 1, 42);
2598 ok(ret
== LB_ERR
, "Unexpected return value %d.\n", ret
);
2599 ret
= SendMessageA(listbox
, LB_FINDSTRINGEXACT
, 1, 0);
2600 ok(ret
== LB_ERR
, "Unexpected return value %d.\n", ret
);
2601 ret
= SendMessageA(listbox
, LB_FINDSTRINGEXACT
, 1, 42);
2602 ok(ret
== LB_ERR
, "Unexpected return value %d.\n", ret
);
2603 ret
= SendMessageA(listbox
, LB_SELECTSTRING
, 1, 0);
2604 ok(ret
== LB_ERR
, "Unexpected return value %d.\n", ret
);
2605 ret
= SendMessageA(listbox
, LB_SELECTSTRING
, 1, 42);
2606 ok(ret
== LB_ERR
, "Unexpected return value %d.\n", ret
);
2608 DestroyWindow(listbox
);
2610 /* Invalid window style combinations. */
2611 parent
= create_parent();
2612 ok(parent
!= NULL
, "Failed to create parent window.\n");
2614 for (i
= 0; i
< ARRAY_SIZE(invalid_styles
); ++i
)
2618 listbox
= CreateWindowA(WC_LISTBOXA
, "TestList", LBS_NODATA
| WS_CHILD
| invalid_styles
[i
],
2619 0, 0, 100, 100, parent
, (HMENU
)ID_LISTBOX
, NULL
, 0);
2620 ok(listbox
!= NULL
, "Failed to create a listbox.\n");
2622 style
= GetWindowLongA(listbox
, GWL_STYLE
);
2623 ok((style
& invalid_styles
[i
]) == invalid_styles
[i
], "%u: unexpected window styles %#x.\n", i
, style
);
2624 ret
= SendMessageA(listbox
, LB_SETCOUNT
, 100, 0);
2625 ok(ret
== LB_ERR
, "%u: unexpected return value %d.\n", i
, ret
);
2626 DestroyWindow(listbox
);
2629 DestroyWindow(parent
);
2634 ULONG_PTR ctx_cookie
;
2637 if (!load_v6_module(&ctx_cookie
, &hCtx
))
2640 init_msg_sequences(sequences
, NUM_MSG_SEQUENCES
);
2645 test_LB_SELITEMRANGE();
2646 test_LB_SETCURSEL();
2647 test_listbox_height();
2648 test_changing_selection_styles();
2649 test_itemfrompoint();
2650 test_listbox_item_data();
2651 test_listbox_LB_DIR();
2652 test_listbox_dlgdir();
2654 test_init_storage();
2655 test_GetListBoxInfo();
2656 test_missing_lbuttonup();
2658 test_WM_MEASUREITEM();
2662 unload_v6_module(ctx_cookie
, hCtx
);