1 /* Unit test suite for combo boxes.
3 * Copyright 2007 Mikolaj Zalewski
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
24 #define WIN32_LEAN_AND_MEAN
27 #include "wine/test.h"
33 #define expect_eq(expr, value, type, fmt); { type val = expr; ok(val == (value), #expr " expected " #fmt " got " #fmt "\n", (value), val); }
34 #define expect_rect(r, _left, _top, _right, _bottom) ok(r.left == _left && r.top == _top && \
35 r.bottom == _bottom && r.right == _right, "Invalid rect (%d,%d) (%d,%d) vs (%d,%d) (%d,%d)\n", \
36 r.left, r.top, r.right, r.bottom, _left, _top, _right, _bottom);
38 static HWND
build_combo(DWORD style
)
40 return CreateWindowA("ComboBox", "Combo", WS_VISIBLE
|WS_CHILD
|style
, 5, 5, 100, 100, hMainWnd
, (HMENU
)COMBO_ID
, NULL
, 0);
43 static int font_height(HFONT hFont
)
49 hDC
= CreateCompatibleDC(NULL
);
50 hFontOld
= SelectObject(hDC
, hFont
);
51 GetTextMetricsA(hDC
, &tm
);
52 SelectObject(hDC
, hFontOld
);
58 static INT CALLBACK
is_font_installed_proc(const LOGFONTA
*elf
, const TEXTMETRICA
*tm
, DWORD type
, LPARAM lParam
)
63 static BOOL
is_font_installed(const char *name
)
65 HDC hdc
= GetDC(NULL
);
66 BOOL ret
= !EnumFontFamiliesA(hdc
, name
, is_font_installed_proc
, 0);
71 static void test_setitemheight(DWORD style
)
73 HWND hCombo
= build_combo(style
);
77 trace("Style %x\n", style
);
78 GetClientRect(hCombo
, &r
);
79 expect_rect(r
, 0, 0, 100, font_height(GetStockObject(SYSTEM_FONT
)) + 8);
80 SendMessageA(hCombo
, CB_GETDROPPEDCONTROLRECT
, 0, (LPARAM
)&r
);
81 MapWindowPoints(HWND_DESKTOP
, hMainWnd
, (LPPOINT
)&r
, 2);
82 todo_wine
expect_rect(r
, 5, 5, 105, 105);
84 for (i
= 1; i
< 30; i
++)
86 SendMessageA(hCombo
, CB_SETITEMHEIGHT
, -1, i
);
87 GetClientRect(hCombo
, &r
);
88 expect_eq(r
.bottom
- r
.top
, i
+ 6, int, "%d");
91 DestroyWindow(hCombo
);
94 static void test_setfont(DWORD style
)
101 if (!is_font_installed("Marlett"))
103 skip("Marlett font not available\n");
107 trace("Style %x\n", style
);
109 hCombo
= build_combo(style
);
110 hFont1
= CreateFontA(10, 0, 0, 0, FW_DONTCARE
, FALSE
, FALSE
, FALSE
, SYMBOL_CHARSET
, OUT_DEFAULT_PRECIS
, CLIP_DEFAULT_PRECIS
, DEFAULT_QUALITY
, DEFAULT_PITCH
|FF_DONTCARE
, "Marlett");
111 hFont2
= CreateFontA(8, 0, 0, 0, FW_DONTCARE
, FALSE
, FALSE
, FALSE
, SYMBOL_CHARSET
, OUT_DEFAULT_PRECIS
, CLIP_DEFAULT_PRECIS
, DEFAULT_QUALITY
, DEFAULT_PITCH
|FF_DONTCARE
, "Marlett");
113 GetClientRect(hCombo
, &r
);
114 expect_rect(r
, 0, 0, 100, font_height(GetStockObject(SYSTEM_FONT
)) + 8);
115 SendMessageA(hCombo
, CB_GETDROPPEDCONTROLRECT
, 0, (LPARAM
)&r
);
116 MapWindowPoints(HWND_DESKTOP
, hMainWnd
, (LPPOINT
)&r
, 2);
117 todo_wine
expect_rect(r
, 5, 5, 105, 105);
119 /* The size of the dropped control is initially equal to the size
120 of the window when it was created. The size of the calculated
121 dropped area changes only by how much the selection area
122 changes, not by how much the list area changes. */
123 if (font_height(hFont1
) == 10 && font_height(hFont2
) == 8)
125 SendMessageA(hCombo
, WM_SETFONT
, (WPARAM
)hFont1
, FALSE
);
126 GetClientRect(hCombo
, &r
);
127 expect_rect(r
, 0, 0, 100, 18);
128 SendMessageA(hCombo
, CB_GETDROPPEDCONTROLRECT
, 0, (LPARAM
)&r
);
129 MapWindowPoints(HWND_DESKTOP
, hMainWnd
, (LPPOINT
)&r
, 2);
130 todo_wine
expect_rect(r
, 5, 5, 105, 105 - (font_height(GetStockObject(SYSTEM_FONT
)) - font_height(hFont1
)));
132 SendMessageA(hCombo
, WM_SETFONT
, (WPARAM
)hFont2
, FALSE
);
133 GetClientRect(hCombo
, &r
);
134 expect_rect(r
, 0, 0, 100, 16);
135 SendMessageA(hCombo
, CB_GETDROPPEDCONTROLRECT
, 0, (LPARAM
)&r
);
136 MapWindowPoints(HWND_DESKTOP
, hMainWnd
, (LPPOINT
)&r
, 2);
137 todo_wine
expect_rect(r
, 5, 5, 105, 105 - (font_height(GetStockObject(SYSTEM_FONT
)) - font_height(hFont2
)));
139 SendMessageA(hCombo
, WM_SETFONT
, (WPARAM
)hFont1
, FALSE
);
140 GetClientRect(hCombo
, &r
);
141 expect_rect(r
, 0, 0, 100, 18);
142 SendMessageA(hCombo
, CB_GETDROPPEDCONTROLRECT
, 0, (LPARAM
)&r
);
143 MapWindowPoints(HWND_DESKTOP
, hMainWnd
, (LPPOINT
)&r
, 2);
144 todo_wine
expect_rect(r
, 5, 5, 105, 105 - (font_height(GetStockObject(SYSTEM_FONT
)) - font_height(hFont1
)));
148 ok(0, "Expected Marlett font heights 10/8, got %d/%d\n",
149 font_height(hFont1
), font_height(hFont2
));
152 for (i
= 1; i
< 30; i
++)
154 HFONT hFont
= CreateFontA(i
, 0, 0, 0, FW_DONTCARE
, FALSE
, FALSE
, FALSE
, SYMBOL_CHARSET
, OUT_DEFAULT_PRECIS
, CLIP_DEFAULT_PRECIS
, DEFAULT_QUALITY
, DEFAULT_PITCH
|FF_DONTCARE
, "Marlett");
155 int height
= font_height(hFont
);
157 SendMessageA(hCombo
, WM_SETFONT
, (WPARAM
)hFont
, FALSE
);
158 GetClientRect(hCombo
, &r
);
159 expect_eq(r
.bottom
- r
.top
, height
+ 8, int, "%d");
160 SendMessageA(hCombo
, WM_SETFONT
, 0, FALSE
);
164 DestroyWindow(hCombo
);
165 DeleteObject(hFont1
);
166 DeleteObject(hFont2
);
169 static LRESULT (CALLBACK
*old_parent_proc
)(HWND hwnd
, UINT msg
, WPARAM wparam
, LPARAM lparam
);
170 static LPCSTR expected_edit_text
;
171 static LPCSTR expected_list_text
;
172 static BOOL selchange_fired
;
174 static LRESULT CALLBACK
parent_wnd_proc(HWND hwnd
, UINT msg
, WPARAM wparam
, LPARAM lparam
)
181 case MAKEWPARAM(COMBO_ID
, CBN_SELCHANGE
):
183 HWND hCombo
= (HWND
)lparam
;
185 char list
[20], edit
[20];
187 memset(list
, 0, sizeof(list
));
188 memset(edit
, 0, sizeof(edit
));
190 idx
= SendMessageA(hCombo
, CB_GETCURSEL
, 0, 0);
191 SendMessageA(hCombo
, CB_GETLBTEXT
, idx
, (LPARAM
)list
);
192 SendMessageA(hCombo
, WM_GETTEXT
, sizeof(edit
), (LPARAM
)edit
);
194 ok(!strcmp(edit
, expected_edit_text
), "edit: got %s, expected %s\n",
195 edit
, expected_edit_text
);
196 ok(!strcmp(list
, expected_list_text
), "list: got %s, expected %s\n",
197 list
, expected_list_text
);
199 selchange_fired
= TRUE
;
206 return CallWindowProcA(old_parent_proc
, hwnd
, msg
, wparam
, lparam
);
209 static void test_selection(DWORD style
, const char * const text
[],
210 const int *edit
, const int *list
)
215 hCombo
= build_combo(style
);
217 SendMessageA(hCombo
, CB_ADDSTRING
, 0, (LPARAM
)text
[0]);
218 SendMessageA(hCombo
, CB_ADDSTRING
, 0, (LPARAM
)text
[1]);
219 SendMessageA(hCombo
, CB_SETCURSEL
, -1, 0);
221 old_parent_proc
= (void *)SetWindowLongPtrA(hMainWnd
, GWLP_WNDPROC
, (ULONG_PTR
)parent_wnd_proc
);
223 idx
= SendMessageA(hCombo
, CB_GETCURSEL
, 0, 0);
224 ok(idx
== -1, "expected selection -1, got %d\n", idx
);
226 /* keyboard navigation */
228 expected_list_text
= text
[list
[0]];
229 expected_edit_text
= text
[edit
[0]];
230 selchange_fired
= FALSE
;
231 SendMessageA(hCombo
, WM_KEYDOWN
, VK_DOWN
, 0);
232 ok(selchange_fired
, "CBN_SELCHANGE not sent!\n");
234 expected_list_text
= text
[list
[1]];
235 expected_edit_text
= text
[edit
[1]];
236 selchange_fired
= FALSE
;
237 SendMessageA(hCombo
, WM_KEYDOWN
, VK_DOWN
, 0);
238 ok(selchange_fired
, "CBN_SELCHANGE not sent!\n");
240 expected_list_text
= text
[list
[2]];
241 expected_edit_text
= text
[edit
[2]];
242 selchange_fired
= FALSE
;
243 SendMessageA(hCombo
, WM_KEYDOWN
, VK_UP
, 0);
244 ok(selchange_fired
, "CBN_SELCHANGE not sent!\n");
246 /* programmatic navigation */
248 expected_list_text
= text
[list
[3]];
249 expected_edit_text
= text
[edit
[3]];
250 selchange_fired
= FALSE
;
251 SendMessageA(hCombo
, CB_SETCURSEL
, list
[3], 0);
252 ok(!selchange_fired
, "CBN_SELCHANGE sent!\n");
254 expected_list_text
= text
[list
[4]];
255 expected_edit_text
= text
[edit
[4]];
256 selchange_fired
= FALSE
;
257 SendMessageA(hCombo
, CB_SETCURSEL
, list
[4], 0);
258 ok(!selchange_fired
, "CBN_SELCHANGE sent!\n");
260 SetWindowLongPtrA(hMainWnd
, GWLP_WNDPROC
, (ULONG_PTR
)old_parent_proc
);
261 DestroyWindow(hCombo
);
264 static void test_CBN_SELCHANGE(void)
266 static const char * const text
[] = { "alpha", "beta", "" };
267 static const int sel_1
[] = { 2, 0, 1, 0, 1 };
268 static const int sel_2
[] = { 0, 1, 0, 0, 1 };
270 test_selection(CBS_SIMPLE
, text
, sel_1
, sel_2
);
271 test_selection(CBS_DROPDOWN
, text
, sel_1
, sel_2
);
272 test_selection(CBS_DROPDOWNLIST
, text
, sel_2
, sel_2
);
275 static void test_WM_LBUTTONDOWN(void)
277 HWND hCombo
, hEdit
, hList
;
279 UINT x
, y
, item_height
;
284 static const UINT choices
[] = {8,9,10,11,12,14,16,18,20,22,24,26,28,36,48,72};
285 static const CHAR stringFormat
[] = "%2d";
287 BOOL (WINAPI
*pGetComboBoxInfo
)(HWND
, PCOMBOBOXINFO
);
289 pGetComboBoxInfo
= (void*)GetProcAddress(GetModuleHandleA("user32.dll"), "GetComboBoxInfo");
290 if (!pGetComboBoxInfo
){
291 win_skip("GetComboBoxInfo is not available\n");
295 hCombo
= CreateWindowA("ComboBox", "Combo", WS_VISIBLE
|WS_CHILD
|CBS_DROPDOWN
,
296 0, 0, 200, 150, hMainWnd
, (HMENU
)COMBO_ID
, NULL
, 0);
298 for (i
= 0; i
< sizeof(choices
)/sizeof(UINT
); i
++){
299 sprintf(buffer
, stringFormat
, choices
[i
]);
300 result
= SendMessageA(hCombo
, CB_ADDSTRING
, 0, (LPARAM
)buffer
);
302 "Failed to add item %d\n", i
);
305 cbInfo
.cbSize
= sizeof(COMBOBOXINFO
);
306 SetLastError(0xdeadbeef);
307 ret
= pGetComboBoxInfo(hCombo
, &cbInfo
);
308 ok(ret
, "Failed to get combobox info structure. LastError=%d\n",
310 hEdit
= cbInfo
.hwndItem
;
311 hList
= cbInfo
.hwndList
;
313 trace("hMainWnd=%p, hCombo=%p, hList=%p, hEdit=%p\n", hMainWnd
, hCombo
, hList
, hEdit
);
314 ok(GetFocus() == hMainWnd
, "Focus not on Main Window, instead on %p\n", GetFocus());
316 /* Click on the button to drop down the list */
317 x
= cbInfo
.rcButton
.left
+ (cbInfo
.rcButton
.right
-cbInfo
.rcButton
.left
)/2;
318 y
= cbInfo
.rcButton
.top
+ (cbInfo
.rcButton
.bottom
-cbInfo
.rcButton
.top
)/2;
319 result
= SendMessageA(hCombo
, WM_LBUTTONDOWN
, 0, MAKELPARAM(x
, y
));
320 ok(result
, "WM_LBUTTONDOWN was not processed. LastError=%d\n",
322 ok(SendMessageA(hCombo
, CB_GETDROPPEDSTATE
, 0, 0),
323 "The dropdown list should have appeared after clicking the button.\n");
325 ok(GetFocus() == hEdit
,
326 "Focus not on ComboBox's Edit Control, instead on %p\n", GetFocus());
327 result
= SendMessageA(hCombo
, WM_LBUTTONUP
, 0, MAKELPARAM(x
, y
));
328 ok(result
, "WM_LBUTTONUP was not processed. LastError=%d\n",
330 ok(GetFocus() == hEdit
,
331 "Focus not on ComboBox's Edit Control, instead on %p\n", GetFocus());
333 /* Click on the 5th item in the list */
334 item_height
= SendMessageA(hCombo
, CB_GETITEMHEIGHT
, 0, 0);
335 ok(GetClientRect(hList
, &rect
), "Failed to get list's client rect.\n");
336 x
= rect
.left
+ (rect
.right
-rect
.left
)/2;
337 y
= item_height
/2 + item_height
*4;
338 result
= SendMessageA(hList
, WM_LBUTTONDOWN
, 0, MAKELPARAM(x
, y
));
339 ok(!result
, "WM_LBUTTONDOWN was not processed. LastError=%d\n",
341 ok(GetFocus() == hEdit
,
342 "Focus not on ComboBox's Edit Control, instead on %p\n", GetFocus());
344 result
= SendMessageA(hList
, WM_MOUSEMOVE
, 0, MAKELPARAM(x
, y
));
345 ok(!result
, "WM_MOUSEMOVE was not processed. LastError=%d\n",
347 ok(GetFocus() == hEdit
,
348 "Focus not on ComboBox's Edit Control, instead on %p\n", GetFocus());
349 ok(SendMessageA(hCombo
, CB_GETDROPPEDSTATE
, 0, 0),
350 "The dropdown list should still be visible.\n");
352 result
= SendMessageA(hList
, WM_LBUTTONUP
, 0, MAKELPARAM(x
, y
));
353 ok(!result
, "WM_LBUTTONUP was not processed. LastError=%d\n",
355 ok(GetFocus() == hEdit
,
356 "Focus not on ComboBox's Edit Control, instead on %p\n", GetFocus());
357 ok(!SendMessageA(hCombo
, CB_GETDROPPEDSTATE
, 0, 0),
358 "The dropdown list should have been rolled up.\n");
359 idx
= SendMessageA(hCombo
, CB_GETCURSEL
, 0, 0);
360 ok(idx
, "Current Selection: expected %d, got %d\n", 4, idx
);
362 DestroyWindow(hCombo
);
365 static void test_changesize( DWORD style
)
367 HWND hCombo
= build_combo(style
);
369 INT ddheight
, clheight
, ddwidth
, clwidth
;
370 /* get initial measurements */
371 GetClientRect( hCombo
, &rc
);
372 clheight
= rc
.bottom
- rc
.top
;
373 clwidth
= rc
.right
- rc
.left
;
374 SendMessageA(hCombo
, CB_GETDROPPEDCONTROLRECT
, 0, (LPARAM
)&rc
);
375 ddheight
= rc
.bottom
- rc
.top
;
376 ddwidth
= rc
.right
- rc
.left
;
377 /* use MoveWindow to move & resize the combo */
378 /* first make it slightly smaller */
379 MoveWindow( hCombo
, 10, 10, clwidth
- 2, clheight
- 2, TRUE
);
380 GetClientRect( hCombo
, &rc
);
381 ok( rc
.right
- rc
.left
== clwidth
- 2, "clientrect width is %d vs %d\n",
382 rc
.right
- rc
.left
, clwidth
- 2);
383 ok( rc
.bottom
- rc
.top
== clheight
, "clientrect height is %d vs %d\n",
384 rc
.bottom
- rc
.top
, clheight
);
385 SendMessageA(hCombo
, CB_GETDROPPEDCONTROLRECT
, 0, (LPARAM
)&rc
);
386 ok( rc
.right
- rc
.left
== clwidth
- 2, "drop-down rect width is %d vs %d\n",
387 rc
.right
- rc
.left
, clwidth
- 2);
388 ok( rc
.bottom
- rc
.top
== ddheight
, "drop-down rect height is %d vs %d\n",
389 rc
.bottom
- rc
.top
, ddheight
);
390 ok( rc
.right
- rc
.left
== ddwidth
-2, "drop-down rect width is %d vs %d\n",
391 rc
.right
- rc
.left
, ddwidth
- 2);
392 /* new cx, cy is slightly bigger than the initial values */
393 MoveWindow( hCombo
, 10, 10, clwidth
+ 2, clheight
+ 2, TRUE
);
394 GetClientRect( hCombo
, &rc
);
395 ok( rc
.right
- rc
.left
== clwidth
+ 2, "clientrect width is %d vs %d\n",
396 rc
.right
- rc
.left
, clwidth
+ 2);
397 ok( rc
.bottom
- rc
.top
== clheight
, "clientrect height is %d vs %d\n",
398 rc
.bottom
- rc
.top
, clheight
);
399 SendMessageA(hCombo
, CB_GETDROPPEDCONTROLRECT
, 0, (LPARAM
)&rc
);
400 ok( rc
.right
- rc
.left
== clwidth
+ 2, "drop-down rect width is %d vs %d\n",
401 rc
.right
- rc
.left
, clwidth
+ 2);
403 ok( rc
.bottom
- rc
.top
== clheight
+ 2, "drop-down rect height is %d vs %d\n",
404 rc
.bottom
- rc
.top
, clheight
+ 2);
407 ddwidth
= SendMessageA(hCombo
, CB_SETDROPPEDWIDTH
, -1, 0);
408 ok( ddwidth
== clwidth
+ 2, "drop-width is %d vs %d\n", ddwidth
, clwidth
+ 2);
409 ddwidth
= SendMessageA(hCombo
, CB_GETDROPPEDWIDTH
, 0, 0);
410 ok( ddwidth
== clwidth
+ 2, "drop-width is %d vs %d\n", ddwidth
, clwidth
+ 2);
412 ddwidth
= SendMessageA(hCombo
, CB_SETDROPPEDWIDTH
, 0, 0);
413 ok( ddwidth
== clwidth
+ 2, "drop-width is %d vs %d\n", ddwidth
, clwidth
+ 2);
414 ddwidth
= SendMessageA(hCombo
, CB_GETDROPPEDWIDTH
, 0, 0);
415 ok( ddwidth
== clwidth
+ 2, "drop-width is %d vs %d\n", ddwidth
, clwidth
+ 2);
417 ddwidth
= SendMessageA(hCombo
, CB_SETDROPPEDWIDTH
, clwidth
- 1, 0);
418 ok( ddwidth
== clwidth
+ 2, "drop-width is %d vs %d\n", ddwidth
, clwidth
+ 2);
419 ddwidth
= SendMessageA(hCombo
, CB_GETDROPPEDWIDTH
, 0, 0);
420 ok( ddwidth
== clwidth
+ 2, "drop-width is %d vs %d\n", ddwidth
, clwidth
+ 2);
422 ddwidth
= SendMessageA(hCombo
, CB_SETDROPPEDWIDTH
, clwidth
<< 1, 0);
423 ok( ddwidth
== (clwidth
<< 1), "drop-width is %d vs %d\n", ddwidth
, clwidth
<< 1);
424 ddwidth
= SendMessageA(hCombo
, CB_GETDROPPEDWIDTH
, 0, 0);
425 ok( ddwidth
== (clwidth
<< 1), "drop-width is %d vs %d\n", ddwidth
, clwidth
<< 1);
427 ddwidth
= SendMessageA(hCombo
, CB_SETDROPPEDWIDTH
, 0, 0);
428 ok( ddwidth
== (clwidth
<< 1), "drop-width is %d vs %d\n", ddwidth
, clwidth
<< 1);
429 ddwidth
= SendMessageA(hCombo
, CB_GETDROPPEDWIDTH
, 0, 0);
430 ok( ddwidth
== (clwidth
<< 1), "drop-width is %d vs %d\n", ddwidth
, clwidth
<< 1);
432 ddwidth
= SendMessageA(hCombo
, CB_SETDROPPEDWIDTH
, 1, 0);
433 ok( ddwidth
== clwidth
+ 2, "drop-width is %d vs %d\n", ddwidth
, clwidth
+ 2);
434 ddwidth
= SendMessageA(hCombo
, CB_GETDROPPEDWIDTH
, 0, 0);
435 ok( ddwidth
== clwidth
+ 2, "drop-width is %d vs %d\n", ddwidth
, clwidth
+ 2);
437 DestroyWindow(hCombo
);
440 static void test_editselection(void)
448 BOOL (WINAPI
*pGetComboBoxInfo
)(HWND
, PCOMBOBOXINFO
);
451 pGetComboBoxInfo
= (void*)GetProcAddress(GetModuleHandleA("user32.dll"), "GetComboBoxInfo");
452 if (!pGetComboBoxInfo
){
453 win_skip("GetComboBoxInfo is not available\n");
458 hCombo
= build_combo(CBS_SIMPLE
);
459 cbInfo
.cbSize
= sizeof(COMBOBOXINFO
);
460 SetLastError(0xdeadbeef);
461 ret
= pGetComboBoxInfo(hCombo
, &cbInfo
);
462 ok(ret
, "Failed to get combobox info structure. LastError=%d\n",
464 hEdit
= cbInfo
.hwndItem
;
466 /* Initially combo selection is empty*/
467 len
= SendMessageA(hCombo
, CB_GETEDITSEL
, 0,0);
468 ok(LOWORD(len
)==0, "Unexpected start position for selection %d\n", LOWORD(len
));
469 ok(HIWORD(len
)==0, "Unexpected end position for selection %d\n", HIWORD(len
));
471 /* Set some text, and press a key to replace it */
473 SendMessageA(hCombo
, WM_SETTEXT
, 0, (LPARAM
)"Jason1");
474 SendMessageA(hCombo
, WM_GETTEXT
, sizeof(edit
), (LPARAM
)edit
);
475 ok(strcmp(edit
, "Jason1")==0, "Unexpected text retrieved %s\n", edit
);
477 /* Now what is the selection - still empty */
478 SendMessageA(hCombo
, CB_GETEDITSEL
, (WPARAM
)&start
, (WPARAM
)&end
);
479 ok(start
==0, "Unexpected start position for selection %d\n", start
);
480 ok(end
==0, "Unexpected end position for selection %d\n", end
);
481 len
= SendMessageA(hCombo
, CB_GETEDITSEL
, 0,0);
482 ok(LOWORD(len
)==0, "Unexpected start position for selection %d\n", LOWORD(len
));
483 ok(HIWORD(len
)==0, "Unexpected end position for selection %d\n", HIWORD(len
));
485 /* Give it focus, and it gets selected */
486 SendMessageA(hCombo
, WM_SETFOCUS
, 0, (LPARAM
)hEdit
);
487 SendMessageA(hCombo
, CB_GETEDITSEL
, (WPARAM
)&start
, (WPARAM
)&end
);
488 ok(start
==0, "Unexpected start position for selection %d\n", start
);
489 ok(end
==6, "Unexpected end position for selection %d\n", end
);
490 len
= SendMessageA(hCombo
, CB_GETEDITSEL
, 0,0);
491 ok(LOWORD(len
)==0, "Unexpected start position for selection %d\n", LOWORD(len
));
492 ok(HIWORD(len
)==6, "Unexpected end position for selection %d\n", HIWORD(len
));
494 /* Now emulate a key press */
496 SendMessageA(hCombo
, WM_CHAR
, 'A', 0x1c0001);
497 SendMessageA(hCombo
, WM_GETTEXT
, sizeof(edit
), (LPARAM
)edit
);
498 ok(strcmp(edit
, "A")==0, "Unexpected text retrieved %s\n", edit
);
500 len
= SendMessageA(hCombo
, CB_GETEDITSEL
, 0,0);
501 ok(LOWORD(len
)==1, "Unexpected start position for selection %d\n", LOWORD(len
));
502 ok(HIWORD(len
)==1, "Unexpected end position for selection %d\n", HIWORD(len
));
504 /* Now what happens when it gets more focus a second time - it doesn't reselect */
505 SendMessageA(hCombo
, WM_SETFOCUS
, 0, (LPARAM
)hEdit
);
506 len
= SendMessageA(hCombo
, CB_GETEDITSEL
, 0,0);
507 ok(LOWORD(len
)==1, "Unexpected start position for selection %d\n", LOWORD(len
));
508 ok(HIWORD(len
)==1, "Unexpected end position for selection %d\n", HIWORD(len
));
509 DestroyWindow(hCombo
);
511 /* Start again - Build a combo */
512 hCombo
= build_combo(CBS_SIMPLE
);
513 cbInfo
.cbSize
= sizeof(COMBOBOXINFO
);
514 SetLastError(0xdeadbeef);
515 ret
= pGetComboBoxInfo(hCombo
, &cbInfo
);
516 ok(ret
, "Failed to get combobox info structure. LastError=%d\n",
518 hEdit
= cbInfo
.hwndItem
;
520 /* Set some text and give focus so it gets selected */
522 SendMessageA(hCombo
, WM_SETTEXT
, 0, (LPARAM
)"Jason2");
523 SendMessageA(hCombo
, WM_GETTEXT
, sizeof(edit
), (LPARAM
)edit
);
524 ok(strcmp(edit
, "Jason2")==0, "Unexpected text retrieved %s\n", edit
);
526 SendMessageA(hCombo
, WM_SETFOCUS
, 0, (LPARAM
)hEdit
);
528 /* Now what is the selection */
529 SendMessageA(hCombo
, CB_GETEDITSEL
, (WPARAM
)&start
, (WPARAM
)&end
);
530 ok(start
==0, "Unexpected start position for selection %d\n", start
);
531 ok(end
==6, "Unexpected end position for selection %d\n", end
);
532 len
= SendMessageA(hCombo
, CB_GETEDITSEL
, 0,0);
533 ok(LOWORD(len
)==0, "Unexpected start position for selection %d\n", LOWORD(len
));
534 ok(HIWORD(len
)==6, "Unexpected end position for selection %d\n", HIWORD(len
));
536 /* Now change the selection to the apparently invalid start -1, end -1 and
537 show it means no selection (ie start -1) but cursor at end */
538 SendMessageA(hCombo
, CB_SETEDITSEL
, 0, -1);
540 SendMessageA(hCombo
, WM_CHAR
, 'A', 0x1c0001);
541 SendMessageA(hCombo
, WM_GETTEXT
, sizeof(edit
), (LPARAM
)edit
);
542 ok(strcmp(edit
, "Jason2A")==0, "Unexpected text retrieved %s\n", edit
);
543 DestroyWindow(hCombo
);
546 static WNDPROC edit_window_proc
;
547 static long setsel_start
= 1, setsel_end
= 1;
548 static HWND hCBN_SetFocus
, hCBN_KillFocus
;
550 static LRESULT CALLBACK
combobox_subclass_proc(HWND hwnd
, UINT msg
, WPARAM wParam
, LPARAM lParam
)
552 if (msg
== EM_SETSEL
)
554 setsel_start
= wParam
;
557 return CallWindowProcA(edit_window_proc
, hwnd
, msg
, wParam
, lParam
);
560 static LRESULT CALLBACK
test_window_proc(HWND hwnd
, UINT msg
, WPARAM wParam
, LPARAM lParam
)
565 switch (HIWORD(wParam
))
568 hCBN_SetFocus
= (HWND
)lParam
;
571 hCBN_KillFocus
= (HWND
)lParam
;
576 SetFocus((HWND
)wParam
);
579 return CallWindowProcA(old_parent_proc
, hwnd
, msg
, wParam
, lParam
);
582 static void test_editselection_focus(DWORD style
)
584 BOOL (WINAPI
*pGetComboBoxInfo
)(HWND
, PCOMBOBOXINFO
);
585 HWND hCombo
, hEdit
, hButton
;
588 const char wine_test
[] = "Wine Test";
589 char buffer
[16] = {0};
592 pGetComboBoxInfo
= (void *)GetProcAddress(GetModuleHandleA("user32.dll"), "GetComboBoxInfo");
593 if (!pGetComboBoxInfo
)
595 win_skip("GetComboBoxInfo is not available\n");
599 hCombo
= build_combo(style
);
600 cbInfo
.cbSize
= sizeof(COMBOBOXINFO
);
601 SetLastError(0xdeadbeef);
602 ret
= pGetComboBoxInfo(hCombo
, &cbInfo
);
603 ok(ret
, "Failed to get COMBOBOXINFO structure; LastError: %u\n", GetLastError());
604 hEdit
= cbInfo
.hwndItem
;
606 hButton
= CreateWindowA("Button", "OK", WS_VISIBLE
|WS_CHILD
|BS_DEFPUSHBUTTON
,
607 5, 50, 100, 20, hMainWnd
, NULL
,
608 (HINSTANCE
)GetWindowLongPtrA(hMainWnd
, GWLP_HINSTANCE
), NULL
);
610 old_parent_proc
= (WNDPROC
)SetWindowLongPtrA(hMainWnd
, GWLP_WNDPROC
, (ULONG_PTR
)test_window_proc
);
611 edit_window_proc
= (WNDPROC
)SetWindowLongPtrA(hEdit
, GWLP_WNDPROC
, (ULONG_PTR
)combobox_subclass_proc
);
613 SendMessageA(hCombo
, WM_SETFOCUS
, 0, (LPARAM
)hEdit
);
614 ok(setsel_start
== 0, "Unexpected EM_SETSEL start value; got %ld\n", setsel_start
);
615 todo_wine
ok(setsel_end
== INT_MAX
, "Unexpected EM_SETSEL end value; got %ld\n", setsel_end
);
616 ok(hCBN_SetFocus
== hCombo
, "Wrong handle set by CBN_SETFOCUS; got %p\n", hCBN_SetFocus
);
617 ok(GetFocus() == hEdit
, "hEdit should have keyboard focus\n");
619 SendMessageA(hMainWnd
, WM_NEXTDLGCTL
, (WPARAM
)hButton
, TRUE
);
620 ok(setsel_start
== 0, "Unexpected EM_SETSEL start value; got %ld\n", setsel_start
);
621 todo_wine
ok(setsel_end
== 0, "Unexpected EM_SETSEL end value; got %ld\n", setsel_end
);
622 ok(hCBN_KillFocus
== hCombo
, "Wrong handle set by CBN_KILLFOCUS; got %p\n", hCBN_KillFocus
);
623 ok(GetFocus() == hButton
, "hButton should have keyboard focus\n");
625 SendMessageA(hCombo
, WM_SETTEXT
, 0, (LPARAM
)wine_test
);
626 SendMessageA(hMainWnd
, WM_NEXTDLGCTL
, (WPARAM
)hCombo
, TRUE
);
627 ok(setsel_start
== 0, "Unexpected EM_SETSEL start value; got %ld\n", setsel_start
);
628 todo_wine
ok(setsel_end
== INT_MAX
, "Unexpected EM_SETSEL end value; got %ld\n", setsel_end
);
629 ok(hCBN_SetFocus
== hCombo
, "Wrong handle set by CBN_SETFOCUS; got %p\n", hCBN_SetFocus
);
630 ok(GetFocus() == hEdit
, "hEdit should have keyboard focus\n");
631 SendMessageA(hCombo
, WM_GETTEXT
, sizeof(buffer
), (LPARAM
)buffer
);
632 ok(!strcmp(buffer
, wine_test
), "Unexpected text in edit control; got '%s'\n", buffer
);
634 SendMessageA(hMainWnd
, WM_NEXTDLGCTL
, (WPARAM
)hButton
, TRUE
);
635 ok(setsel_start
== 0, "Unexpected EM_SETSEL start value; got %ld\n", setsel_start
);
636 todo_wine
ok(setsel_end
== 0, "Unexpected EM_SETSEL end value; got %ld\n", setsel_end
);
637 ok(hCBN_KillFocus
== hCombo
, "Wrong handle set by CBN_KILLFOCUS; got %p\n", hCBN_KillFocus
);
638 ok(GetFocus() == hButton
, "hButton should have keyboard focus\n");
639 len
= SendMessageA(hCombo
, CB_GETEDITSEL
, 0, 0);
640 ok(len
== 0, "Unexpected text selection; start: %u, end: %u\n", LOWORD(len
), HIWORD(len
));
642 SetWindowLongPtrA(hMainWnd
, GWLP_WNDPROC
, (ULONG_PTR
)old_parent_proc
);
643 DestroyWindow(hButton
);
644 DestroyWindow(hCombo
);
647 static void test_listbox_styles(DWORD cb_style
)
649 BOOL (WINAPI
*pGetComboBoxInfo
)(HWND
, PCOMBOBOXINFO
);
652 DWORD style
, exstyle
, expect_style
, expect_exstyle
;
655 pGetComboBoxInfo
= (void*)GetProcAddress(GetModuleHandleA("user32.dll"), "GetComboBoxInfo");
656 if (!pGetComboBoxInfo
){
657 win_skip("GetComboBoxInfo is not available\n");
661 expect_style
= WS_CHILD
|WS_CLIPSIBLINGS
|LBS_COMBOBOX
|LBS_HASSTRINGS
|LBS_NOTIFY
;
662 if (cb_style
== CBS_SIMPLE
)
664 expect_style
|= WS_VISIBLE
;
665 expect_exstyle
= WS_EX_CLIENTEDGE
;
669 expect_style
|= WS_BORDER
;
670 expect_exstyle
= WS_EX_TOOLWINDOW
;
673 combo
= build_combo(cb_style
);
674 info
.cbSize
= sizeof(COMBOBOXINFO
);
675 SetLastError(0xdeadbeef);
676 ret
= pGetComboBoxInfo(combo
, &info
);
677 ok(ret
, "Failed to get combobox info structure.\n");
679 style
= GetWindowLongW( info
.hwndList
, GWL_STYLE
);
680 exstyle
= GetWindowLongW( info
.hwndList
, GWL_EXSTYLE
);
681 ok(style
== expect_style
, "%08x: got %08x\n", cb_style
, style
);
682 ok(exstyle
== expect_exstyle
, "%08x: got %08x\n", cb_style
, exstyle
);
684 if (cb_style
!= CBS_SIMPLE
)
685 expect_exstyle
|= WS_EX_TOPMOST
;
687 SendMessageW(combo
, CB_SHOWDROPDOWN
, TRUE
, 0 );
688 style
= GetWindowLongW( info
.hwndList
, GWL_STYLE
);
689 exstyle
= GetWindowLongW( info
.hwndList
, GWL_EXSTYLE
);
690 ok(style
== (expect_style
| WS_VISIBLE
), "%08x: got %08x\n", cb_style
, style
);
691 ok(exstyle
== expect_exstyle
, "%08x: got %08x\n", cb_style
, exstyle
);
693 SendMessageW(combo
, CB_SHOWDROPDOWN
, FALSE
, 0 );
694 style
= GetWindowLongW( info
.hwndList
, GWL_STYLE
);
695 exstyle
= GetWindowLongW( info
.hwndList
, GWL_EXSTYLE
);
696 ok(style
== expect_style
, "%08x: got %08x\n", cb_style
, style
);
697 ok(exstyle
== expect_exstyle
, "%08x: got %08x\n", cb_style
, exstyle
);
699 DestroyWindow(combo
);
704 hMainWnd
= CreateWindowA("static", "Test", WS_OVERLAPPEDWINDOW
, 10, 10, 300, 300, NULL
, NULL
, NULL
, 0);
705 ShowWindow(hMainWnd
, SW_SHOW
);
707 test_setfont(CBS_DROPDOWN
);
708 test_setfont(CBS_DROPDOWNLIST
);
709 test_setitemheight(CBS_DROPDOWN
);
710 test_setitemheight(CBS_DROPDOWNLIST
);
711 test_CBN_SELCHANGE();
712 test_WM_LBUTTONDOWN();
713 test_changesize(CBS_DROPDOWN
);
714 test_changesize(CBS_DROPDOWNLIST
);
715 test_editselection();
716 test_editselection_focus(CBS_SIMPLE
);
717 test_editselection_focus(CBS_DROPDOWN
);
718 test_listbox_styles(CBS_SIMPLE
);
719 test_listbox_styles(CBS_DROPDOWN
);
720 test_listbox_styles(CBS_DROPDOWNLIST
);
722 DestroyWindow(hMainWnd
);