ddraw: Separate IDirectDrawSurface4 vtable.
[wine] / dlls / user32 / tests / combo.c
1 /* Unit test suite for combo boxes.
2  *
3  * Copyright 2007 Mikolaj Zalewski
4  *
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.
9  *
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.
14  *
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
18  */
19
20 #include <assert.h>
21 #include <stdarg.h>
22 #include <stdio.h>
23
24 #define STRICT
25 #define WIN32_LEAN_AND_MEAN
26 #include <windows.h>
27
28 #include "wine/test.h"
29
30 #define COMBO_ID 1995
31
32 static HWND hMainWnd;
33
34 #define expect_eq(expr, value, type, fmt); { type val = expr; ok(val == (value), #expr " expected " #fmt " got " #fmt "\n", (value), val); }
35 #define expect_rect(r, _left, _top, _right, _bottom) ok(r.left == _left && r.top == _top && \
36     r.bottom == _bottom && r.right == _right, "Invalid rect (%d,%d) (%d,%d) vs (%d,%d) (%d,%d)\n", \
37     r.left, r.top, r.right, r.bottom, _left, _top, _right, _bottom);
38
39 static HWND build_combo(DWORD style)
40 {
41     return CreateWindow("ComboBox", "Combo", WS_VISIBLE|WS_CHILD|style, 5, 5, 100, 100, hMainWnd, (HMENU)COMBO_ID, NULL, 0);
42 }
43
44 static int font_height(HFONT hFont)
45 {
46     TEXTMETRIC tm;
47     HFONT hFontOld;
48     HDC hDC;
49
50     hDC = CreateCompatibleDC(NULL);
51     hFontOld = SelectObject(hDC, hFont);
52     GetTextMetrics(hDC, &tm);
53     SelectObject(hDC, hFontOld);
54     DeleteDC(hDC);
55
56     return tm.tmHeight;
57 }
58
59 static INT CALLBACK is_font_installed_proc(const LOGFONT *elf, const TEXTMETRIC *tm, DWORD type, LPARAM lParam)
60 {
61     return 0;
62 }
63
64 static int is_font_installed(const char *name)
65 {
66     HDC hdc = GetDC(NULL);
67     BOOL ret = !EnumFontFamilies(hdc, name, is_font_installed_proc, 0);
68     ReleaseDC(NULL, hdc);
69     return ret;
70 }
71
72 static void test_setitemheight(DWORD style)
73 {
74     HWND hCombo = build_combo(style);
75     RECT r;
76     int i;
77
78     trace("Style %x\n", style);
79     GetClientRect(hCombo, &r);
80     expect_rect(r, 0, 0, 100, font_height(GetStockObject(SYSTEM_FONT)) + 8);
81     SendMessageA(hCombo, CB_GETDROPPEDCONTROLRECT, 0, (LPARAM)&r);
82     MapWindowPoints(HWND_DESKTOP, hMainWnd, (LPPOINT)&r, 2);
83     todo_wine expect_rect(r, 5, 5, 105, 105);
84
85     for (i = 1; i < 30; i++)
86     {
87         SendMessage(hCombo, CB_SETITEMHEIGHT, -1, i);
88         GetClientRect(hCombo, &r);
89         expect_eq(r.bottom - r.top, i + 6, int, "%d");
90     }
91
92     DestroyWindow(hCombo);
93 }
94
95 static void test_setfont(DWORD style)
96 {
97     HWND hCombo;
98     HFONT hFont1, hFont2;
99     RECT r;
100     int i;
101
102     if (!is_font_installed("Marlett"))
103     {
104         skip("Marlett font not available\n");
105         return;
106     }
107
108     trace("Style %x\n", style);
109
110     hCombo = build_combo(style);
111     hFont1 = CreateFont(10, 0, 0, 0, FW_DONTCARE, FALSE, FALSE, FALSE, SYMBOL_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH|FF_DONTCARE, "Marlett");
112     hFont2 = CreateFont(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
114     GetClientRect(hCombo, &r);
115     expect_rect(r, 0, 0, 100, font_height(GetStockObject(SYSTEM_FONT)) + 8);
116     SendMessageA(hCombo, CB_GETDROPPEDCONTROLRECT, 0, (LPARAM)&r);
117     MapWindowPoints(HWND_DESKTOP, hMainWnd, (LPPOINT)&r, 2);
118     todo_wine expect_rect(r, 5, 5, 105, 105);
119
120     /* The size of the dropped control is initially equal to the size
121        of the window when it was created.  The size of the calculated
122        dropped area changes only by how much the selection area
123        changes, not by how much the list area changes.  */
124     if (font_height(hFont1) == 10 && font_height(hFont2) == 8)
125     {
126         SendMessage(hCombo, WM_SETFONT, (WPARAM)hFont1, FALSE);
127         GetClientRect(hCombo, &r);
128         expect_rect(r, 0, 0, 100, 18);
129         SendMessageA(hCombo, CB_GETDROPPEDCONTROLRECT, 0, (LPARAM)&r);
130         MapWindowPoints(HWND_DESKTOP, hMainWnd, (LPPOINT)&r, 2);
131         todo_wine expect_rect(r, 5, 5, 105, 105 - (font_height(GetStockObject(SYSTEM_FONT)) - font_height(hFont1)));
132
133         SendMessage(hCombo, WM_SETFONT, (WPARAM)hFont2, FALSE);
134         GetClientRect(hCombo, &r);
135         expect_rect(r, 0, 0, 100, 16);
136         SendMessageA(hCombo, CB_GETDROPPEDCONTROLRECT, 0, (LPARAM)&r);
137         MapWindowPoints(HWND_DESKTOP, hMainWnd, (LPPOINT)&r, 2);
138         todo_wine expect_rect(r, 5, 5, 105, 105 - (font_height(GetStockObject(SYSTEM_FONT)) - font_height(hFont2)));
139
140         SendMessage(hCombo, WM_SETFONT, (WPARAM)hFont1, FALSE);
141         GetClientRect(hCombo, &r);
142         expect_rect(r, 0, 0, 100, 18);
143         SendMessageA(hCombo, CB_GETDROPPEDCONTROLRECT, 0, (LPARAM)&r);
144         MapWindowPoints(HWND_DESKTOP, hMainWnd, (LPPOINT)&r, 2);
145         todo_wine expect_rect(r, 5, 5, 105, 105 - (font_height(GetStockObject(SYSTEM_FONT)) - font_height(hFont1)));
146     }
147     else
148     {
149         ok(0, "Expected Marlett font heights 10/8, got %d/%d\n",
150            font_height(hFont1), font_height(hFont2));
151     }
152
153     for (i = 1; i < 30; i++)
154     {
155         HFONT hFont = CreateFont(i, 0, 0, 0, FW_DONTCARE, FALSE, FALSE, FALSE, SYMBOL_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH|FF_DONTCARE, "Marlett");
156         int height = font_height(hFont);
157
158         SendMessage(hCombo, WM_SETFONT, (WPARAM)hFont, FALSE);
159         GetClientRect(hCombo, &r);
160         expect_eq(r.bottom - r.top, height + 8, int, "%d");
161         SendMessage(hCombo, WM_SETFONT, 0, FALSE);
162         DeleteObject(hFont);
163     }
164
165     DestroyWindow(hCombo);
166     DeleteObject(hFont1);
167     DeleteObject(hFont2);
168 }
169
170 static LRESULT (CALLBACK *old_parent_proc)(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam);
171 static LPCSTR expected_edit_text;
172 static LPCSTR expected_list_text;
173 static BOOL selchange_fired;
174
175 static LRESULT CALLBACK parent_wnd_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
176 {
177     switch (msg)
178     {
179     case WM_COMMAND:
180         switch (wparam)
181         {
182             case MAKEWPARAM(COMBO_ID, CBN_SELCHANGE):
183             {
184                 HWND hCombo = (HWND)lparam;
185                 int idx;
186                 char list[20], edit[20];
187
188                 memset(list, 0, sizeof(list));
189                 memset(edit, 0, sizeof(edit));
190
191                 idx = SendMessage(hCombo, CB_GETCURSEL, 0, 0);
192                 SendMessage(hCombo, CB_GETLBTEXT, idx, (LPARAM)list);
193                 SendMessage(hCombo, WM_GETTEXT, sizeof(edit), (LPARAM)edit);
194
195                 ok(!strcmp(edit, expected_edit_text), "edit: got %s, expected %s\n",
196                    edit, expected_edit_text);
197                 ok(!strcmp(list, expected_list_text), "list: got %s, expected %s\n",
198                    list, expected_list_text);
199
200                 selchange_fired = TRUE;
201             }
202             break;
203         }
204         break;
205     }
206
207     return CallWindowProc(old_parent_proc, hwnd, msg, wparam, lparam);
208 }
209
210 static void test_selection(DWORD style, const char * const text[],
211                            const int *edit, const int *list)
212 {
213     INT idx;
214     HWND hCombo;
215
216     hCombo = build_combo(style);
217
218     SendMessage(hCombo, CB_ADDSTRING, 0, (LPARAM)text[0]);
219     SendMessage(hCombo, CB_ADDSTRING, 0, (LPARAM)text[1]);
220     SendMessage(hCombo, CB_SETCURSEL, -1, 0);
221
222     old_parent_proc = (void *)SetWindowLongPtr(hMainWnd, GWLP_WNDPROC, (ULONG_PTR)parent_wnd_proc);
223
224     idx = SendMessage(hCombo, CB_GETCURSEL, 0, 0);
225     ok(idx == -1, "expected selection -1, got %d\n", idx);
226
227     /* keyboard navigation */
228
229     expected_list_text = text[list[0]];
230     expected_edit_text = text[edit[0]];
231     selchange_fired = FALSE;
232     SendMessage(hCombo, WM_KEYDOWN, VK_DOWN, 0);
233     ok(selchange_fired, "CBN_SELCHANGE not sent!\n");
234
235     expected_list_text = text[list[1]];
236     expected_edit_text = text[edit[1]];
237     selchange_fired = FALSE;
238     SendMessage(hCombo, WM_KEYDOWN, VK_DOWN, 0);
239     ok(selchange_fired, "CBN_SELCHANGE not sent!\n");
240
241     expected_list_text = text[list[2]];
242     expected_edit_text = text[edit[2]];
243     selchange_fired = FALSE;
244     SendMessage(hCombo, WM_KEYDOWN, VK_UP, 0);
245     ok(selchange_fired, "CBN_SELCHANGE not sent!\n");
246
247     /* programmatic navigation */
248
249     expected_list_text = text[list[3]];
250     expected_edit_text = text[edit[3]];
251     selchange_fired = FALSE;
252     SendMessage(hCombo, CB_SETCURSEL, list[3], 0);
253     ok(!selchange_fired, "CBN_SELCHANGE sent!\n");
254
255     expected_list_text = text[list[4]];
256     expected_edit_text = text[edit[4]];
257     selchange_fired = FALSE;
258     SendMessage(hCombo, CB_SETCURSEL, list[4], 0);
259     ok(!selchange_fired, "CBN_SELCHANGE sent!\n");
260
261     SetWindowLongPtr(hMainWnd, GWLP_WNDPROC, (ULONG_PTR)old_parent_proc);
262     DestroyWindow(hCombo);
263 }
264
265 static void test_CBN_SELCHANGE(void)
266 {
267     static const char * const text[] = { "alpha", "beta", "" };
268     static const int sel_1[] = { 2, 0, 1, 0, 1 };
269     static const int sel_2[] = { 0, 1, 0, 0, 1 };
270
271     test_selection(CBS_SIMPLE, text, sel_1, sel_2);
272     test_selection(CBS_DROPDOWN, text, sel_1, sel_2);
273     test_selection(CBS_DROPDOWNLIST, text, sel_2, sel_2);
274 }
275
276 static void test_WM_LBUTTONDOWN(void)
277 {
278     HWND hCombo, hEdit, hList;
279     COMBOBOXINFO cbInfo;
280     UINT x, y, item_height;
281     LRESULT result;
282     int i, idx;
283     RECT rect;
284     CHAR buffer[3];
285     static const UINT choices[] = {8,9,10,11,12,14,16,18,20,22,24,26,28,36,48,72};
286     static const CHAR stringFormat[] = "%2d";
287     BOOL ret;
288     BOOL (WINAPI *pGetComboBoxInfo)(HWND, PCOMBOBOXINFO);
289
290     pGetComboBoxInfo = (void*)GetProcAddress(GetModuleHandleA("user32.dll"), "GetComboBoxInfo");
291     if (!pGetComboBoxInfo){
292         win_skip("GetComboBoxInfo is not available\n");
293         return;
294     }
295
296     hCombo = CreateWindow("ComboBox", "Combo", WS_VISIBLE|WS_CHILD|CBS_DROPDOWN,
297             0, 0, 200, 150, hMainWnd, (HMENU)COMBO_ID, NULL, 0);
298
299     for (i = 0; i < sizeof(choices)/sizeof(UINT); i++){
300         sprintf(buffer, stringFormat, choices[i]);
301         result = SendMessageA(hCombo, CB_ADDSTRING, 0, (LPARAM)buffer);
302         ok(result == i,
303            "Failed to add item %d\n", i);
304     }
305
306     cbInfo.cbSize = sizeof(COMBOBOXINFO);
307     SetLastError(0xdeadbeef);
308     ret = pGetComboBoxInfo(hCombo, &cbInfo);
309     ok(ret, "Failed to get combobox info structure. LastError=%d\n",
310        GetLastError());
311     hEdit = cbInfo.hwndItem;
312     hList = cbInfo.hwndList;
313
314     trace("hMainWnd=%p, hCombo=%p, hList=%p, hEdit=%p\n", hMainWnd, hCombo, hList, hEdit);
315     ok(GetFocus() == hMainWnd, "Focus not on Main Window, instead on %p\n", GetFocus());
316
317     /* Click on the button to drop down the list */
318     x = cbInfo.rcButton.left + (cbInfo.rcButton.right-cbInfo.rcButton.left)/2;
319     y = cbInfo.rcButton.top + (cbInfo.rcButton.bottom-cbInfo.rcButton.top)/2;
320     result = SendMessage(hCombo, WM_LBUTTONDOWN, 0, MAKELPARAM(x, y));
321     ok(result, "WM_LBUTTONDOWN was not processed. LastError=%d\n",
322        GetLastError());
323     ok(SendMessage(hCombo, CB_GETDROPPEDSTATE, 0, 0),
324        "The dropdown list should have appeared after clicking the button.\n");
325
326     ok(GetFocus() == hEdit,
327        "Focus not on ComboBox's Edit Control, instead on %p\n", GetFocus());
328     result = SendMessage(hCombo, WM_LBUTTONUP, 0, MAKELPARAM(x, y));
329     ok(result, "WM_LBUTTONUP was not processed. LastError=%d\n",
330        GetLastError());
331     ok(GetFocus() == hEdit,
332        "Focus not on ComboBox's Edit Control, instead on %p\n", GetFocus());
333
334     /* Click on the 5th item in the list */
335     item_height = SendMessage(hCombo, CB_GETITEMHEIGHT, 0, 0);
336     ok(GetClientRect(hList, &rect), "Failed to get list's client rect.\n");
337     x = rect.left + (rect.right-rect.left)/2;
338     y = item_height/2 + item_height*4;
339     result = SendMessage(hList, WM_LBUTTONDOWN, 0, MAKELPARAM(x, y));
340     ok(!result, "WM_LBUTTONDOWN was not processed. LastError=%d\n",
341        GetLastError());
342     ok(GetFocus() == hEdit,
343        "Focus not on ComboBox's Edit Control, instead on %p\n", GetFocus());
344
345     result = SendMessage(hList, WM_MOUSEMOVE, 0, MAKELPARAM(x, y));
346     ok(!result, "WM_MOUSEMOVE was not processed. LastError=%d\n",
347        GetLastError());
348     ok(GetFocus() == hEdit,
349        "Focus not on ComboBox's Edit Control, instead on %p\n", GetFocus());
350     ok(SendMessage(hCombo, CB_GETDROPPEDSTATE, 0, 0),
351        "The dropdown list should still be visible.\n");
352
353     result = SendMessage(hList, WM_LBUTTONUP, 0, MAKELPARAM(x, y));
354     ok(!result, "WM_LBUTTONUP was not processed. LastError=%d\n",
355        GetLastError());
356     ok(GetFocus() == hEdit,
357        "Focus not on ComboBox's Edit Control, instead on %p\n", GetFocus());
358     ok(!SendMessage(hCombo, CB_GETDROPPEDSTATE, 0, 0),
359        "The dropdown list should have been rolled up.\n");
360     idx = SendMessage(hCombo, CB_GETCURSEL, 0, 0);
361     ok(idx, "Current Selection: expected %d, got %d\n", 4, idx);
362
363     DestroyWindow(hCombo);
364 }
365
366 static void test_changesize( DWORD style)
367 {
368     HWND hCombo = build_combo(style);
369     RECT rc;
370     INT ddheight, clheight, ddwidth, clwidth;
371     /* get initial measurements */
372     GetClientRect( hCombo, &rc);
373     clheight = rc.bottom - rc.top;
374     clwidth = rc.right - rc.left;
375     SendMessageA(hCombo, CB_GETDROPPEDCONTROLRECT, 0, (LPARAM)&rc);
376     ddheight = rc.bottom - rc.top;
377     ddwidth = rc.right - rc.left;
378     /* use MoveWindow to move & resize the combo */
379     /* first make it slightly smaller */
380     MoveWindow( hCombo, 10, 10, clwidth - 2, clheight - 2, TRUE);
381     GetClientRect( hCombo, &rc);
382     ok( rc.right - rc.left == clwidth - 2, "clientrect witdh is %d vs %d\n",
383             rc.right - rc.left, clwidth - 2);
384     ok( rc.bottom - rc.top == clheight, "clientrect height is %d vs %d\n",
385                 rc.bottom - rc.top, clheight);
386     SendMessageA(hCombo, CB_GETDROPPEDCONTROLRECT, 0, (LPARAM)&rc);
387     ok( rc.right - rc.left == clwidth - 2, "drop-down rect witdh is %d vs %d\n",
388             rc.right - rc.left, clwidth - 2);
389     ok( rc.bottom - rc.top == ddheight, "drop-down rect height is %d vs %d\n",
390             rc.bottom - rc.top, ddheight);
391     ok( rc.right - rc.left == ddwidth -2, "drop-down rect width is %d vs %d\n",
392             rc.right - rc.left, ddwidth - 2);
393     /* new cx, cy is slightly bigger than the initial values */
394     MoveWindow( hCombo, 10, 10, clwidth + 2, clheight + 2, TRUE);
395     GetClientRect( hCombo, &rc);
396     ok( rc.right - rc.left == clwidth + 2, "clientrect witdh is %d vs %d\n",
397             rc.right - rc.left, clwidth + 2);
398     ok( rc.bottom - rc.top == clheight, "clientrect height is %d vs %d\n",
399             rc.bottom - rc.top, clheight);
400     SendMessageA(hCombo, CB_GETDROPPEDCONTROLRECT, 0, (LPARAM)&rc);
401     ok( rc.right - rc.left == clwidth + 2, "drop-down rect witdh is %d vs %d\n",
402             rc.right - rc.left, clwidth + 2);
403     todo_wine {
404         ok( rc.bottom - rc.top == clheight + 2, "drop-down rect height is %d vs %d\n",
405                 rc.bottom - rc.top, clheight + 2);
406     }
407     DestroyWindow(hCombo);
408 }
409
410 static void test_editselection(void)
411 {
412     HWND hCombo;
413     INT start,end;
414     HWND hEdit;
415     COMBOBOXINFO cbInfo;
416     BOOL ret;
417     DWORD len;
418     BOOL (WINAPI *pGetComboBoxInfo)(HWND, PCOMBOBOXINFO);
419     char edit[20];
420
421     pGetComboBoxInfo = (void*)GetProcAddress(GetModuleHandleA("user32.dll"), "GetComboBoxInfo");
422     if (!pGetComboBoxInfo){
423         win_skip("GetComboBoxInfo is not available\n");
424         return;
425     }
426
427     /* Build a combo */
428     hCombo = build_combo(CBS_SIMPLE);
429     cbInfo.cbSize = sizeof(COMBOBOXINFO);
430     SetLastError(0xdeadbeef);
431     ret = pGetComboBoxInfo(hCombo, &cbInfo);
432     ok(ret, "Failed to get combobox info structure. LastError=%d\n",
433        GetLastError());
434     hEdit = cbInfo.hwndItem;
435
436     /* Initially combo selection is empty*/
437     len = SendMessage(hCombo, CB_GETEDITSEL, 0,0);
438     ok(LOWORD(len)==0, "Unexpected start position for selection %d\n", LOWORD(len));
439     ok(HIWORD(len)==0, "Unexpected end position for selection %d\n", HIWORD(len));
440
441     /* Set some text, and press a key to replace it */
442     edit[0] = 0x00;
443     SendMessage(hCombo, WM_SETTEXT, 0, (LPARAM)"Jason1");
444     SendMessage(hCombo, WM_GETTEXT, sizeof(edit), (LPARAM)edit);
445     ok(strcmp(edit, "Jason1")==0, "Unexpected text retrieved %s\n", edit);
446
447     /* Now what is the selection - still empty */
448     SendMessage(hCombo, CB_GETEDITSEL, (WPARAM)&start, (WPARAM)&end);
449     len = SendMessage(hCombo, CB_GETEDITSEL, 0,0);
450     ok(LOWORD(len)==0, "Unexpected start position for selection %d\n", LOWORD(len));
451     ok(HIWORD(len)==0, "Unexpected end position for selection %d\n", HIWORD(len));
452
453     /* Give it focus, and it gets selected */
454     SendMessage(hCombo, WM_SETFOCUS, 0, (LPARAM)hEdit);
455     SendMessage(hCombo, CB_GETEDITSEL, (WPARAM)&start, (WPARAM)&end);
456     len = SendMessage(hCombo, CB_GETEDITSEL, 0,0);
457     ok(LOWORD(len)==0, "Unexpected start position for selection %d\n", LOWORD(len));
458     ok(HIWORD(len)==6, "Unexpected end position for selection %d\n", HIWORD(len));
459
460     /* Now emulate a key press */
461     edit[0] = 0x00;
462     SendMessage(hCombo, WM_CHAR, 'A', 0x1c0001);
463     SendMessage(hCombo, WM_GETTEXT, sizeof(edit), (LPARAM)edit);
464     ok(strcmp(edit, "A")==0, "Unexpected text retrieved %s\n", edit);
465
466     len = SendMessage(hCombo, CB_GETEDITSEL, 0,0);
467     ok(LOWORD(len)==1, "Unexpected start position for selection %d\n", LOWORD(len));
468     ok(HIWORD(len)==1, "Unexpected end position for selection %d\n", HIWORD(len));
469
470     /* Now what happens when it gets more focus a second time - it doesn't reselect */
471     SendMessage(hCombo, WM_SETFOCUS, 0, (LPARAM)hEdit);
472     len = SendMessage(hCombo, CB_GETEDITSEL, 0,0);
473     ok(LOWORD(len)==1, "Unexpected start position for selection %d\n", LOWORD(len));
474     ok(HIWORD(len)==1, "Unexpected end position for selection %d\n", HIWORD(len));
475     DestroyWindow(hCombo);
476
477     /* Start again - Build a combo */
478     hCombo = build_combo(CBS_SIMPLE);
479     cbInfo.cbSize = sizeof(COMBOBOXINFO);
480     SetLastError(0xdeadbeef);
481     ret = pGetComboBoxInfo(hCombo, &cbInfo);
482     ok(ret, "Failed to get combobox info structure. LastError=%d\n",
483        GetLastError());
484     hEdit = cbInfo.hwndItem;
485
486     /* Set some text and give focus so it gets selected */
487     edit[0] = 0x00;
488     SendMessage(hCombo, WM_SETTEXT, 0, (LPARAM)"Jason2");
489     SendMessage(hCombo, WM_GETTEXT, sizeof(edit), (LPARAM)edit);
490     ok(strcmp(edit, "Jason2")==0, "Unexpected text retrieved %s\n", edit);
491
492     SendMessage(hCombo, WM_SETFOCUS, 0, (LPARAM)hEdit);
493
494     /* Now what is the selection */
495     SendMessage(hCombo, CB_GETEDITSEL, (WPARAM)&start, (WPARAM)&end);
496     len = SendMessage(hCombo, CB_GETEDITSEL, 0,0);
497     ok(LOWORD(len)==0, "Unexpected start position for selection %d\n", LOWORD(len));
498     ok(HIWORD(len)==6, "Unexpected end position for selection %d\n", HIWORD(len));
499
500     /* Now change the selection to the apparently invalid start -1, end -1 and
501        show it means no selection (ie start -1) but cursor at end              */
502     SendMessage(hCombo, CB_SETEDITSEL, 0, -1);
503     edit[0] = 0x00;
504     SendMessage(hCombo, WM_CHAR, 'A', 0x1c0001);
505     SendMessage(hCombo, WM_GETTEXT, sizeof(edit), (LPARAM)edit);
506     ok(strcmp(edit, "Jason2A")==0, "Unexpected text retrieved %s\n", edit);
507     DestroyWindow(hCombo);
508 }
509
510 START_TEST(combo)
511 {
512     hMainWnd = CreateWindow("static", "Test", WS_OVERLAPPEDWINDOW, 10, 10, 300, 300, NULL, NULL, NULL, 0);
513     ShowWindow(hMainWnd, SW_SHOW);
514
515     test_setfont(CBS_DROPDOWN);
516     test_setfont(CBS_DROPDOWNLIST);
517     test_setitemheight(CBS_DROPDOWN);
518     test_setitemheight(CBS_DROPDOWNLIST);
519     test_CBN_SELCHANGE();
520     test_WM_LBUTTONDOWN();
521     test_changesize(CBS_DROPDOWN);
522     test_changesize(CBS_DROPDOWNLIST);
523     test_editselection();
524
525     DestroyWindow(hMainWnd);
526 }