mshtml: Populate dynamic properties table in get_dynamic_data.
[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
408     ddwidth = SendMessageA(hCombo, CB_SETDROPPEDWIDTH, -1, 0);
409     todo_wine ok( ddwidth == clwidth + 2, "drop-width is %d vs %d\n", ddwidth, clwidth + 2);
410     ddwidth = SendMessageA(hCombo, CB_GETDROPPEDWIDTH, 0, 0);
411     todo_wine ok( ddwidth == clwidth + 2, "drop-width is %d vs %d\n", ddwidth, clwidth + 2);
412
413     ddwidth = SendMessageA(hCombo, CB_SETDROPPEDWIDTH, 0, 0);
414     todo_wine ok( ddwidth == clwidth + 2, "drop-width is %d vs %d\n", ddwidth, clwidth + 2);
415     ddwidth = SendMessageA(hCombo, CB_GETDROPPEDWIDTH, 0, 0);
416     ok( ddwidth == clwidth + 2, "drop-width is %d vs %d\n", ddwidth, clwidth + 2);
417
418     ddwidth = SendMessageA(hCombo, CB_SETDROPPEDWIDTH, clwidth - 1, 0);
419     todo_wine ok( ddwidth == clwidth + 2, "drop-width is %d vs %d\n", ddwidth, clwidth + 2);
420     ddwidth = SendMessageA(hCombo, CB_GETDROPPEDWIDTH, 0, 0);
421     todo_wine ok( ddwidth == clwidth + 2, "drop-width is %d vs %d\n", ddwidth, clwidth + 2);
422
423     ddwidth = SendMessageA(hCombo, CB_SETDROPPEDWIDTH, clwidth << 1, 0);
424     todo_wine ok( ddwidth == (clwidth << 1), "drop-width is %d vs %d\n", ddwidth, clwidth << 1);
425     ddwidth = SendMessageA(hCombo, CB_GETDROPPEDWIDTH, 0, 0);
426     ok( ddwidth == (clwidth << 1), "drop-width is %d vs %d\n", ddwidth, clwidth << 1);
427
428     DestroyWindow(hCombo);
429 }
430
431 static void test_editselection(void)
432 {
433     HWND hCombo;
434     INT start,end;
435     HWND hEdit;
436     COMBOBOXINFO cbInfo;
437     BOOL ret;
438     DWORD len;
439     BOOL (WINAPI *pGetComboBoxInfo)(HWND, PCOMBOBOXINFO);
440     char edit[20];
441
442     pGetComboBoxInfo = (void*)GetProcAddress(GetModuleHandleA("user32.dll"), "GetComboBoxInfo");
443     if (!pGetComboBoxInfo){
444         win_skip("GetComboBoxInfo is not available\n");
445         return;
446     }
447
448     /* Build a combo */
449     hCombo = build_combo(CBS_SIMPLE);
450     cbInfo.cbSize = sizeof(COMBOBOXINFO);
451     SetLastError(0xdeadbeef);
452     ret = pGetComboBoxInfo(hCombo, &cbInfo);
453     ok(ret, "Failed to get combobox info structure. LastError=%d\n",
454        GetLastError());
455     hEdit = cbInfo.hwndItem;
456
457     /* Initially combo selection is empty*/
458     len = SendMessage(hCombo, CB_GETEDITSEL, 0,0);
459     ok(LOWORD(len)==0, "Unexpected start position for selection %d\n", LOWORD(len));
460     ok(HIWORD(len)==0, "Unexpected end position for selection %d\n", HIWORD(len));
461
462     /* Set some text, and press a key to replace it */
463     edit[0] = 0x00;
464     SendMessage(hCombo, WM_SETTEXT, 0, (LPARAM)"Jason1");
465     SendMessage(hCombo, WM_GETTEXT, sizeof(edit), (LPARAM)edit);
466     ok(strcmp(edit, "Jason1")==0, "Unexpected text retrieved %s\n", edit);
467
468     /* Now what is the selection - still empty */
469     SendMessage(hCombo, CB_GETEDITSEL, (WPARAM)&start, (WPARAM)&end);
470     len = SendMessage(hCombo, CB_GETEDITSEL, 0,0);
471     ok(LOWORD(len)==0, "Unexpected start position for selection %d\n", LOWORD(len));
472     ok(HIWORD(len)==0, "Unexpected end position for selection %d\n", HIWORD(len));
473
474     /* Give it focus, and it gets selected */
475     SendMessage(hCombo, WM_SETFOCUS, 0, (LPARAM)hEdit);
476     SendMessage(hCombo, CB_GETEDITSEL, (WPARAM)&start, (WPARAM)&end);
477     len = SendMessage(hCombo, CB_GETEDITSEL, 0,0);
478     ok(LOWORD(len)==0, "Unexpected start position for selection %d\n", LOWORD(len));
479     ok(HIWORD(len)==6, "Unexpected end position for selection %d\n", HIWORD(len));
480
481     /* Now emulate a key press */
482     edit[0] = 0x00;
483     SendMessage(hCombo, WM_CHAR, 'A', 0x1c0001);
484     SendMessage(hCombo, WM_GETTEXT, sizeof(edit), (LPARAM)edit);
485     ok(strcmp(edit, "A")==0, "Unexpected text retrieved %s\n", edit);
486
487     len = SendMessage(hCombo, CB_GETEDITSEL, 0,0);
488     ok(LOWORD(len)==1, "Unexpected start position for selection %d\n", LOWORD(len));
489     ok(HIWORD(len)==1, "Unexpected end position for selection %d\n", HIWORD(len));
490
491     /* Now what happens when it gets more focus a second time - it doesn't reselect */
492     SendMessage(hCombo, WM_SETFOCUS, 0, (LPARAM)hEdit);
493     len = SendMessage(hCombo, CB_GETEDITSEL, 0,0);
494     ok(LOWORD(len)==1, "Unexpected start position for selection %d\n", LOWORD(len));
495     ok(HIWORD(len)==1, "Unexpected end position for selection %d\n", HIWORD(len));
496     DestroyWindow(hCombo);
497
498     /* Start again - Build a combo */
499     hCombo = build_combo(CBS_SIMPLE);
500     cbInfo.cbSize = sizeof(COMBOBOXINFO);
501     SetLastError(0xdeadbeef);
502     ret = pGetComboBoxInfo(hCombo, &cbInfo);
503     ok(ret, "Failed to get combobox info structure. LastError=%d\n",
504        GetLastError());
505     hEdit = cbInfo.hwndItem;
506
507     /* Set some text and give focus so it gets selected */
508     edit[0] = 0x00;
509     SendMessage(hCombo, WM_SETTEXT, 0, (LPARAM)"Jason2");
510     SendMessage(hCombo, WM_GETTEXT, sizeof(edit), (LPARAM)edit);
511     ok(strcmp(edit, "Jason2")==0, "Unexpected text retrieved %s\n", edit);
512
513     SendMessage(hCombo, WM_SETFOCUS, 0, (LPARAM)hEdit);
514
515     /* Now what is the selection */
516     SendMessage(hCombo, CB_GETEDITSEL, (WPARAM)&start, (WPARAM)&end);
517     len = SendMessage(hCombo, CB_GETEDITSEL, 0,0);
518     ok(LOWORD(len)==0, "Unexpected start position for selection %d\n", LOWORD(len));
519     ok(HIWORD(len)==6, "Unexpected end position for selection %d\n", HIWORD(len));
520
521     /* Now change the selection to the apparently invalid start -1, end -1 and
522        show it means no selection (ie start -1) but cursor at end              */
523     SendMessage(hCombo, CB_SETEDITSEL, 0, -1);
524     edit[0] = 0x00;
525     SendMessage(hCombo, WM_CHAR, 'A', 0x1c0001);
526     SendMessage(hCombo, WM_GETTEXT, sizeof(edit), (LPARAM)edit);
527     ok(strcmp(edit, "Jason2A")==0, "Unexpected text retrieved %s\n", edit);
528     DestroyWindow(hCombo);
529 }
530
531 START_TEST(combo)
532 {
533     hMainWnd = CreateWindow("static", "Test", WS_OVERLAPPEDWINDOW, 10, 10, 300, 300, NULL, NULL, NULL, 0);
534     ShowWindow(hMainWnd, SW_SHOW);
535
536     test_setfont(CBS_DROPDOWN);
537     test_setfont(CBS_DROPDOWNLIST);
538     test_setitemheight(CBS_DROPDOWN);
539     test_setitemheight(CBS_DROPDOWNLIST);
540     test_CBN_SELCHANGE();
541     test_WM_LBUTTONDOWN();
542     test_changesize(CBS_DROPDOWN);
543     test_changesize(CBS_DROPDOWNLIST);
544     test_editselection();
545
546     DestroyWindow(hMainWnd);
547 }