2 * Tests for autocomplete
4 * Copyright 2008 Jan de Mooij
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
31 #include "wine/heap.h"
32 #include "wine/test.h"
34 static HWND hMainWnd
, hEdit
;
35 static HINSTANCE hinst
;
36 static int killfocus_count
;
38 static void test_invalid_init(void)
45 /* AutoComplete instance */
46 hr
= CoCreateInstance(&CLSID_AutoComplete
, NULL
, CLSCTX_INPROC_SERVER
,
47 &IID_IAutoComplete
, (void **)&ac
);
48 if (hr
== REGDB_E_CLASSNOTREG
)
50 win_skip("CLSID_AutoComplete is not registered\n");
53 ok(hr
== S_OK
, "no IID_IAutoComplete (0x%08x)\n", hr
);
55 /* AutoComplete source */
56 hr
= CoCreateInstance(&CLSID_ACLMulti
, NULL
, CLSCTX_INPROC_SERVER
,
57 &IID_IACList
, (void **)&acSource
);
58 if (hr
== REGDB_E_CLASSNOTREG
)
60 win_skip("CLSID_ACLMulti is not registered\n");
61 IAutoComplete_Release(ac
);
64 ok(hr
== S_OK
, "no IID_IACList (0x%08x)\n", hr
);
66 edit_control
= CreateWindowExA(0, "EDIT", "Some text", 0, 10, 10, 300, 300,
67 hMainWnd
, NULL
, hinst
, NULL
);
68 ok(edit_control
!= NULL
, "Can't create edit control\n");
70 /* The refcount of acSource would be incremented on older Windows. */
71 hr
= IAutoComplete_Init(ac
, NULL
, acSource
, NULL
, NULL
);
72 ok(hr
== E_INVALIDARG
||
73 broken(hr
== S_OK
), /* Win2k/XP/Win2k3 */
74 "Init returned 0x%08x\n", hr
);
75 if (hr
== E_INVALIDARG
)
79 IUnknown_AddRef(acSource
);
80 ref
= IUnknown_Release(acSource
);
81 ok(ref
== 1, "Expected AutoComplete source refcount to be 1, got %d\n", ref
);
86 /* Older Windows versions never check the window handle, while newer
87 * versions only check for NULL. Subsequent attempts to initialize the
88 * object after this call succeeds would fail, because initialization
89 * state is determined by whether a non-NULL window handle is stored. */
90 hr
= IAutoComplete_Init(ac
, (HWND
)0xdeadbeef, acSource
, NULL
, NULL
);
91 ok(hr
== S_OK
, "Init returned 0x%08x\n", hr
);
93 /* Tests crash on older Windows. */
94 hr
= IAutoComplete_Init(ac
, NULL
, NULL
, NULL
, NULL
);
95 ok(hr
== E_INVALIDARG
, "Init returned 0x%08x\n", hr
);
97 hr
= IAutoComplete_Init(ac
, edit_control
, NULL
, NULL
, NULL
);
98 ok(hr
== E_INVALIDARG
, "Init returned 0x%08x\n", hr
);
101 /* bind to edit control */
102 hr
= IAutoComplete_Init(ac
, edit_control
, acSource
, NULL
, NULL
);
103 ok(hr
== S_OK
, "Init returned 0x%08x\n", hr
);
105 /* try invalid parameters after successful initialization .*/
106 hr
= IAutoComplete_Init(ac
, NULL
, NULL
, NULL
, NULL
);
107 ok(hr
== E_INVALIDARG
||
108 hr
== E_FAIL
, /* Win2k/XP/Win2k3 */
109 "Init returned 0x%08x\n", hr
);
111 hr
= IAutoComplete_Init(ac
, NULL
, acSource
, NULL
, NULL
);
112 ok(hr
== E_INVALIDARG
||
113 hr
== E_FAIL
, /* Win2k/XP/Win2k3 */
114 "Init returned 0x%08x\n", hr
);
116 hr
= IAutoComplete_Init(ac
, edit_control
, NULL
, NULL
, NULL
);
117 ok(hr
== E_INVALIDARG
||
118 hr
== E_FAIL
, /* Win2k/XP/Win2k3 */
119 "Init returned 0x%08x\n", hr
);
121 /* try initializing twice on the same control */
122 hr
= IAutoComplete_Init(ac
, edit_control
, acSource
, NULL
, NULL
);
123 ok(hr
== E_FAIL
, "Init returned 0x%08x\n", hr
);
125 /* try initializing with a different control */
126 hr
= IAutoComplete_Init(ac
, hEdit
, acSource
, NULL
, NULL
);
127 ok(hr
== E_FAIL
, "Init returned 0x%08x\n", hr
);
129 DestroyWindow(edit_control
);
131 /* try initializing with a different control after
132 * destroying the original initialization control */
133 hr
= IAutoComplete_Init(ac
, hEdit
, acSource
, NULL
, NULL
);
134 ok(hr
== E_UNEXPECTED
||
135 hr
== E_FAIL
, /* Win2k/XP/Win2k3 */
136 "Init returned 0x%08x\n", hr
);
138 IUnknown_Release(acSource
);
139 IAutoComplete_Release(ac
);
141 static IAutoComplete
*test_init(void)
144 IAutoComplete
*ac
, *ac2
;
148 /* AutoComplete instance */
149 r
= CoCreateInstance(&CLSID_AutoComplete
, NULL
, CLSCTX_INPROC_SERVER
,
150 &IID_IAutoComplete
, (LPVOID
*)&ac
);
151 if (r
== REGDB_E_CLASSNOTREG
)
153 win_skip("CLSID_AutoComplete is not registered\n");
156 ok(r
== S_OK
, "no IID_IAutoComplete (0x%08x)\n", r
);
158 /* AutoComplete source */
159 r
= CoCreateInstance(&CLSID_ACLMulti
, NULL
, CLSCTX_INPROC_SERVER
,
160 &IID_IACList
, (LPVOID
*)&acSource
);
161 if (r
== REGDB_E_CLASSNOTREG
)
163 win_skip("CLSID_ACLMulti is not registered\n");
164 IAutoComplete_Release(ac
);
167 ok(r
== S_OK
, "no IID_IACList (0x%08x)\n", r
);
169 user_data
= GetWindowLongPtrA(hEdit
, GWLP_USERDATA
);
170 ok(user_data
== 0, "Expected the edit control user data to be zero\n");
172 /* bind to edit control */
173 r
= IAutoComplete_Init(ac
, hEdit
, acSource
, NULL
, NULL
);
174 ok(r
== S_OK
, "Init returned 0x%08x\n", r
);
176 user_data
= GetWindowLongPtrA(hEdit
, GWLP_USERDATA
);
177 ok(user_data
== 0, "Expected the edit control user data to be zero\n");
179 /* bind a different object to the same edit control */
180 r
= CoCreateInstance(&CLSID_AutoComplete
, NULL
, CLSCTX_INPROC_SERVER
,
181 &IID_IAutoComplete
, (LPVOID
*)&ac2
);
182 ok(r
== S_OK
, "no IID_IAutoComplete (0x%08x)\n", r
);
184 r
= IAutoComplete_Init(ac2
, hEdit
, acSource
, NULL
, NULL
);
185 ok(r
== S_OK
, "Init returned 0x%08x\n", r
);
186 IAutoComplete_Release(ac2
);
188 IUnknown_Release(acSource
);
193 static void test_killfocus(void)
195 /* Test if WM_KILLFOCUS messages are handled properly by checking if
196 * the parent receives an EN_KILLFOCUS message. */
200 ok(killfocus_count
== 1, "Expected one EN_KILLFOCUS message, got: %d\n", killfocus_count
);
203 static LRESULT CALLBACK
MyWndProc(HWND hWnd
, UINT msg
, WPARAM wParam
, LPARAM lParam
)
207 /* create edit control */
208 hEdit
= CreateWindowExA(0, "EDIT", "Some text", 0, 10, 10, 300, 300,
209 hWnd
, NULL
, hinst
, NULL
);
210 ok(hEdit
!= NULL
, "Can't create edit control\n");
213 if(HIWORD(wParam
) == EN_KILLFOCUS
)
217 return DefWindowProcA(hWnd
, msg
, wParam
, lParam
);
220 static void createMainWnd(void)
223 wc
.style
= CS_HREDRAW
| CS_VREDRAW
;
226 wc
.hInstance
= GetModuleHandleA(NULL
);
228 wc
.hCursor
= LoadCursorA(NULL
, (LPSTR
)IDC_IBEAM
);
229 wc
.hbrBackground
= GetSysColorBrush(COLOR_WINDOW
);
230 wc
.lpszMenuName
= NULL
;
231 wc
.lpszClassName
= "MyTestWnd";
232 wc
.lpfnWndProc
= MyWndProc
;
235 hMainWnd
= CreateWindowExA(0, "MyTestWnd", "Blah", WS_OVERLAPPEDWINDOW
,
236 CW_USEDEFAULT
, CW_USEDEFAULT
, 130, 105, NULL
, NULL
, GetModuleHandleA(NULL
), 0);
239 static WNDPROC HijackerWndProc_prev
;
240 static const WCHAR HijackerWndProc_txt
[] = {'H','i','j','a','c','k','e','d',0};
241 static LRESULT CALLBACK
HijackerWndProc(HWND hWnd
, UINT msg
, WPARAM wParam
, LPARAM lParam
)
246 size_t len
= min(wParam
, ARRAY_SIZE(HijackerWndProc_txt
));
247 memcpy((void*)lParam
, HijackerWndProc_txt
, len
* sizeof(WCHAR
));
250 case WM_GETTEXTLENGTH
:
251 return ARRAY_SIZE(HijackerWndProc_txt
) - 1;
253 return CallWindowProcW(HijackerWndProc_prev
, hWnd
, msg
, wParam
, lParam
);
256 static LRESULT CALLBACK
HijackerWndProc2(HWND hWnd
, UINT msg
, WPARAM wParam
, LPARAM lParam
)
263 lParam
= (LPARAM
)HijackerWndProc_txt
;
266 return CallWindowProcW(HijackerWndProc_prev
, hWnd
, msg
, wParam
, lParam
);
269 struct string_enumerator
271 IEnumString IEnumString_iface
;
272 IACList IACList_iface
;
279 WCHAR last_expand
[32];
282 static struct string_enumerator
*impl_from_IEnumString(IEnumString
*iface
)
284 return CONTAINING_RECORD(iface
, struct string_enumerator
, IEnumString_iface
);
287 static HRESULT WINAPI
string_enumerator_QueryInterface(IEnumString
*iface
, REFIID riid
, void **ppv
)
289 struct string_enumerator
*this = impl_from_IEnumString(iface
);
290 if (IsEqualGUID(riid
, &IID_IEnumString
) || IsEqualGUID(riid
, &IID_IUnknown
))
291 *ppv
= &this->IEnumString_iface
;
292 else if (IsEqualGUID(riid
, &IID_IACList
))
293 *ppv
= &this->IACList_iface
;
297 return E_NOINTERFACE
;
300 IUnknown_AddRef(&this->IEnumString_iface
);
304 static ULONG WINAPI
string_enumerator_AddRef(IEnumString
*iface
)
306 struct string_enumerator
*this = impl_from_IEnumString(iface
);
308 ULONG ref
= InterlockedIncrement(&this->ref
);
313 static ULONG WINAPI
string_enumerator_Release(IEnumString
*iface
)
315 struct string_enumerator
*this = impl_from_IEnumString(iface
);
317 ULONG ref
= InterlockedDecrement(&this->ref
);
325 static HRESULT WINAPI
string_enumerator_Next(IEnumString
*iface
, ULONG num
, LPOLESTR
*strings
, ULONG
*num_returned
)
327 struct string_enumerator
*this = impl_from_IEnumString(iface
);
331 for (i
= 0; i
< num
; i
++)
333 if (this->cur
>= this->data_len
)
336 len
= lstrlenW(this->data
[this->cur
]) + 1;
338 strings
[i
] = CoTaskMemAlloc(len
* sizeof(WCHAR
));
339 memcpy(strings
[i
], this->data
[this->cur
], len
* sizeof(WCHAR
));
348 static HRESULT WINAPI
string_enumerator_Reset(IEnumString
*iface
)
350 struct string_enumerator
*this = impl_from_IEnumString(iface
);
358 static HRESULT WINAPI
string_enumerator_Skip(IEnumString
*iface
, ULONG num
)
360 struct string_enumerator
*this = impl_from_IEnumString(iface
);
367 static HRESULT WINAPI
string_enumerator_Clone(IEnumString
*iface
, IEnumString
**out
)
373 static IEnumStringVtbl string_enumerator_vtbl
=
375 string_enumerator_QueryInterface
,
376 string_enumerator_AddRef
,
377 string_enumerator_Release
,
378 string_enumerator_Next
,
379 string_enumerator_Skip
,
380 string_enumerator_Reset
,
381 string_enumerator_Clone
384 static struct string_enumerator
*impl_from_IACList(IACList
*iface
)
386 return CONTAINING_RECORD(iface
, struct string_enumerator
, IACList_iface
);
389 static HRESULT WINAPI
aclist_QueryInterface(IACList
*iface
, REFIID riid
, void **ppv
)
391 return string_enumerator_QueryInterface(&impl_from_IACList(iface
)->IEnumString_iface
, riid
, ppv
);
394 static ULONG WINAPI
aclist_AddRef(IACList
*iface
)
396 return string_enumerator_AddRef(&impl_from_IACList(iface
)->IEnumString_iface
);
399 static ULONG WINAPI
aclist_Release(IACList
*iface
)
401 return string_enumerator_Release(&impl_from_IACList(iface
)->IEnumString_iface
);
404 static HRESULT WINAPI
aclist_Expand(IACList
*iface
, const WCHAR
*expand
)
406 struct string_enumerator
*this = impl_from_IACList(iface
);
408 /* see what we get called with and how many times,
409 don't actually do any expansion of the strings */
410 memcpy(this->last_expand
, expand
, min((lstrlenW(expand
) + 1)*sizeof(WCHAR
), sizeof(this->last_expand
)));
411 this->last_expand
[ARRAY_SIZE(this->last_expand
) - 1] = '\0';
417 static IACListVtbl aclist_vtbl
=
419 aclist_QueryInterface
,
425 static HRESULT
string_enumerator_create(void **ppv
, WCHAR
**suggestions
, int count
)
427 struct string_enumerator
*object
;
429 object
= heap_alloc_zero(sizeof(*object
));
430 object
->IEnumString_iface
.lpVtbl
= &string_enumerator_vtbl
;
431 object
->IACList_iface
.lpVtbl
= &aclist_vtbl
;
433 object
->data
= suggestions
;
434 object
->data_len
= count
;
437 *ppv
= &object
->IEnumString_iface
;
442 static void dispatch_messages(void)
446 while (PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
))
448 TranslateMessage(&msg
);
449 DispatchMessageA(&msg
);
453 #define check_dropdown(acdropdown, hwnd_edit, list, list_num) check_dropdown_(__FILE__, __LINE__, acdropdown, hwnd_edit, list, list_num)
454 static void check_dropdown_(const char *file
, UINT line
, IAutoCompleteDropDown
*acdropdown
, HWND hwnd_edit
, WCHAR
**list
, UINT list_num
)
461 hr
= IAutoCompleteDropDown_GetDropDownStatus(acdropdown
, &flags
, &str
);
462 ok_(file
, line
)(hr
== S_OK
, "IAutoCompleteDropDown_GetDropDownStatus failed: %x\n", hr
);
463 if (hr
!= S_OK
) return;
464 if (list_num
) ok_(file
, line
)(flags
& ACDD_VISIBLE
, "AutoComplete DropDown not visible\n");
467 ok_(file
, line
)(!(flags
& ACDD_VISIBLE
), "AutoComplete DropDown visible\n");
470 ok_(file
, line
)(str
== NULL
, "Expected (null), got %s\n", wine_dbgstr_w(str
));
477 for (i
= 0; i
<= list_num
; i
++)
480 SendMessageW(hwnd_edit
, WM_KEYDOWN
, VK_DOWN
, 0);
481 SendMessageW(hwnd_edit
, WM_KEYUP
, VK_DOWN
, 0xc0000000);
482 hr
= IAutoCompleteDropDown_GetDropDownStatus(acdropdown
, &flags
, &str
);
483 ok_(file
, line
)(hr
== S_OK
, "IAutoCompleteDropDown_GetDropDownStatus failed: %x\n", hr
);
484 ok_(file
, line
)(flags
& ACDD_VISIBLE
, "AutoComplete DropDown not visible\n");
488 ok_(file
, line
)(str
&& !lstrcmpW(list
[i
], str
), "Expected %s, got %s\n",
489 wine_dbgstr_w(list
[i
]), wine_dbgstr_w(str
));
491 ok_(file
, line
)(str
== NULL
, "Expected (null), got %s\n", wine_dbgstr_w(str
));
497 static void test_aclist_expand(HWND hwnd_edit
, void *enumerator
)
499 struct string_enumerator
*obj
= (struct string_enumerator
*)enumerator
;
500 static WCHAR str1
[] = {'t','e','s','t',0};
501 static WCHAR str1a
[] = {'t','e','s','t','\\',0};
502 static WCHAR str2
[] = {'t','e','s','t','\\','f','o','o','\\','b','a','r','\\','b','a',0};
503 static WCHAR str2a
[] = {'t','e','s','t','\\','f','o','o','\\','b','a','r','\\',0};
504 static WCHAR str2b
[] = {'t','e','s','t','\\','f','o','o','\\','b','a','r','\\','b','a','z','_','b','b','q','\\',0};
507 ok(obj
->num_expand
== 0, "Expected 0 expansions, got %u\n", obj
->num_expand
);
508 SendMessageW(hwnd_edit
, WM_SETTEXT
, 0, (LPARAM
)str1
);
509 SendMessageW(hwnd_edit
, EM_SETSEL
, ARRAY_SIZE(str1
) - 1, ARRAY_SIZE(str1
) - 1);
510 SendMessageW(hwnd_edit
, WM_CHAR
, '\\', 1);
512 ok(obj
->num_expand
== 1, "Expected 1 expansion, got %u\n", obj
->num_expand
);
513 ok(lstrcmpW(obj
->last_expand
, str1a
) == 0, "Expected %s, got %s\n", wine_dbgstr_w(str1a
), wine_dbgstr_w(obj
->last_expand
));
514 ok(obj
->num_resets
== 1, "Expected 1 reset, got %u\n", obj
->num_resets
);
515 SendMessageW(hwnd_edit
, WM_SETTEXT
, 0, (LPARAM
)str2
);
516 SendMessageW(hwnd_edit
, EM_SETSEL
, ARRAY_SIZE(str2
) - 1, ARRAY_SIZE(str2
) - 1);
517 SendMessageW(hwnd_edit
, WM_CHAR
, 'z', 1);
519 ok(obj
->num_expand
== 2, "Expected 2 expansions, got %u\n", obj
->num_expand
);
520 ok(lstrcmpW(obj
->last_expand
, str2a
) == 0, "Expected %s, got %s\n", wine_dbgstr_w(str2a
), wine_dbgstr_w(obj
->last_expand
));
521 ok(obj
->num_resets
== 2, "Expected 2 resets, got %u\n", obj
->num_resets
);
523 SendMessageW(hwnd_edit
, WM_CHAR
, '_', 1);
524 SendMessageW(hwnd_edit
, WM_CHAR
, 'b', 1);
527 SendMessageW(hwnd_edit
, WM_CHAR
, 'b', 1);
528 SendMessageW(hwnd_edit
, WM_CHAR
, 'q', 1);
530 ok(obj
->num_expand
== 2, "Expected 2 expansions, got %u\n", obj
->num_expand
);
531 ok(obj
->num_resets
== 2, "Expected 2 resets, got %u\n", obj
->num_resets
);
532 SendMessageW(hwnd_edit
, WM_CHAR
, '\\', 1);
534 ok(obj
->num_expand
== 3, "Expected 3 expansions, got %u\n", obj
->num_expand
);
535 ok(lstrcmpW(obj
->last_expand
, str2b
) == 0, "Expected %s, got %s\n", wine_dbgstr_w(str2b
), wine_dbgstr_w(obj
->last_expand
));
536 ok(obj
->num_resets
== 3, "Expected 3 resets, got %u\n", obj
->num_resets
);
537 SendMessageW(hwnd_edit
, EM_SETSEL
, ARRAY_SIZE(str1a
) - 1, -1);
538 SendMessageW(hwnd_edit
, WM_CHAR
, 'x', 1);
539 SendMessageW(hwnd_edit
, WM_CHAR
, 'y', 1);
541 ok(obj
->num_expand
== 4, "Expected 4 expansions, got %u\n", obj
->num_expand
);
542 ok(lstrcmpW(obj
->last_expand
, str1a
) == 0, "Expected %s, got %s\n", wine_dbgstr_w(str1a
), wine_dbgstr_w(obj
->last_expand
));
543 ok(obj
->num_resets
== 4, "Expected 4 resets, got %u\n", obj
->num_resets
);
544 SendMessageW(hwnd_edit
, EM_SETSEL
, ARRAY_SIZE(str1
) - 1, -1);
545 SendMessageW(hwnd_edit
, WM_CHAR
, 'x', 1);
547 ok(obj
->num_expand
== 4, "Expected 4 expansions, got %u\n", obj
->num_expand
);
548 ok(obj
->num_resets
== 5, "Expected 5 resets, got %u\n", obj
->num_resets
);
551 static void test_prefix_filtering(HWND hwnd_edit
)
553 static WCHAR htt
[] = {'h','t','t',0};
554 static WCHAR www
[] = {'w','w','w','.',0};
555 static WCHAR str0
[] = {'w','w','w','.','a','x',0};
556 static WCHAR str1
[] = {'h','t','t','p','s',':','/','/','w','w','w','.','a','c',0};
557 static WCHAR str2
[] = {'a','a',0};
558 static WCHAR str3
[] = {'a','b',0};
559 static WCHAR str4
[] = {'h','t','t','p',':','/','/','a','0',0};
560 static WCHAR str5
[] = {'h','t','t','p','s',':','/','/','h','t','a',0};
561 static WCHAR str6
[] = {'h','f','o','o',0};
562 static WCHAR str7
[] = {'h','t','t','p',':','/','/','w','w','w','.','a','d','d',0};
563 static WCHAR str8
[] = {'w','w','w','.','w','w','w','.','?',0};
564 static WCHAR str9
[] = {'h','t','t','p',':','/','/','a','b','c','.','a','a','.','c','o','m',0};
565 static WCHAR str10
[]= {'f','t','p',':','/','/','a','b','c',0};
566 static WCHAR str11
[]= {'f','i','l','e',':','/','/','a','a',0};
567 static WCHAR str12
[]= {'f','t','p',':','/','/','w','w','w','.','a','a',0};
568 static WCHAR
*suggestions
[] = { str0
, str1
, str2
, str3
, str4
, str5
, str6
, str7
, str8
, str9
, str10
, str11
, str12
};
569 static WCHAR
*sorted1
[] = { str4
, str2
, str3
, str9
, str1
, str7
, str0
};
570 static WCHAR
*sorted2
[] = { str3
, str9
};
571 static WCHAR
*sorted3
[] = { str1
, str7
, str0
};
572 static WCHAR
*sorted4
[] = { str6
, str5
};
573 static WCHAR
*sorted5
[] = { str5
};
574 static WCHAR
*sorted6
[] = { str4
, str9
};
575 static WCHAR
*sorted7
[] = { str11
, str10
, str12
};
576 IUnknown
*enumerator
;
577 IAutoComplete2
*autocomplete
;
578 IAutoCompleteDropDown
*acdropdown
;
582 hr
= CoCreateInstance(&CLSID_AutoComplete
, NULL
, CLSCTX_INPROC_SERVER
, &IID_IAutoComplete2
, (void**)&autocomplete
);
583 ok(hr
== S_OK
, "CoCreateInstance failed: %x\n", hr
);
585 hr
= IAutoComplete2_QueryInterface(autocomplete
, &IID_IAutoCompleteDropDown
, (LPVOID
*)&acdropdown
);
586 ok(hr
== S_OK
, "No IAutoCompleteDropDown interface: %x\n", hr
);
588 string_enumerator_create((void**)&enumerator
, suggestions
, ARRAY_SIZE(suggestions
));
590 hr
= IAutoComplete2_SetOptions(autocomplete
, ACO_FILTERPREFIXES
| ACO_AUTOSUGGEST
| ACO_AUTOAPPEND
);
591 ok(hr
== S_OK
, "IAutoComplete2_SetOptions failed: %x\n", hr
);
592 hr
= IAutoComplete2_Init(autocomplete
, hwnd_edit
, enumerator
, NULL
, NULL
);
593 ok(hr
== S_OK
, "IAutoComplete_Init failed: %x\n", hr
);
595 SendMessageW(hwnd_edit
, EM_SETSEL
, 0, -1);
596 SendMessageW(hwnd_edit
, WM_CHAR
, 'a', 1);
598 SendMessageW(hwnd_edit
, WM_GETTEXT
, ARRAY_SIZE(buffer
), (LPARAM
)buffer
);
599 ok(lstrcmpW(str4
+ 7, buffer
) == 0, "Expected %s, got %s\n", wine_dbgstr_w(str4
+ 7), wine_dbgstr_w(buffer
));
600 check_dropdown(acdropdown
, hwnd_edit
, sorted1
, ARRAY_SIZE(sorted1
));
602 SendMessageW(hwnd_edit
, EM_SETSEL
, 0, -1);
603 SendMessageW(hwnd_edit
, WM_CHAR
, 'a', 1);
604 SendMessageW(hwnd_edit
, WM_CHAR
, 'b', 1);
606 SendMessageW(hwnd_edit
, WM_GETTEXT
, ARRAY_SIZE(buffer
), (LPARAM
)buffer
);
607 ok(lstrcmpW(str3
, buffer
) == 0, "Expected %s, got %s\n", wine_dbgstr_w(str3
), wine_dbgstr_w(buffer
));
608 check_dropdown(acdropdown
, hwnd_edit
, sorted2
, ARRAY_SIZE(sorted2
));
609 SendMessageW(hwnd_edit
, EM_SETSEL
, 0, -1);
610 SendMessageW(hwnd_edit
, WM_CHAR
, 'a', 1);
611 SendMessageW(hwnd_edit
, WM_CHAR
, 'b', 1);
612 SendMessageW(hwnd_edit
, WM_CHAR
, 'c', 1);
614 SendMessageW(hwnd_edit
, WM_GETTEXT
, ARRAY_SIZE(buffer
), (LPARAM
)buffer
);
615 ok(lstrcmpW(str9
+ 7, buffer
) == 0, "Expected %s, got %s\n", wine_dbgstr_w(str9
+ 7), wine_dbgstr_w(buffer
));
617 SendMessageW(hwnd_edit
, WM_SETTEXT
, 0, (LPARAM
)www
);
618 SendMessageW(hwnd_edit
, EM_SETSEL
, ARRAY_SIZE(www
) - 1, ARRAY_SIZE(www
) - 1);
619 SendMessageW(hwnd_edit
, WM_CHAR
, 'a', 1);
621 SendMessageW(hwnd_edit
, WM_GETTEXT
, ARRAY_SIZE(buffer
), (LPARAM
)buffer
);
622 ok(lstrcmpW(str1
+ 8, buffer
) == 0, "Expected %s, got %s\n", wine_dbgstr_w(str1
+ 8), wine_dbgstr_w(buffer
));
623 check_dropdown(acdropdown
, hwnd_edit
, sorted3
, ARRAY_SIZE(sorted3
));
624 SendMessageW(hwnd_edit
, WM_SETTEXT
, 0, (LPARAM
)www
);
625 SendMessageW(hwnd_edit
, EM_SETSEL
, ARRAY_SIZE(www
) - 1, ARRAY_SIZE(www
) - 1);
626 SendMessageW(hwnd_edit
, WM_CHAR
, 'w', 1);
628 SendMessageW(hwnd_edit
, WM_GETTEXT
, ARRAY_SIZE(buffer
), (LPARAM
)buffer
);
629 ok(lstrcmpW(str8
, buffer
) == 0, "Expected %s, got %s\n", wine_dbgstr_w(str8
), wine_dbgstr_w(buffer
));
631 SendMessageW(hwnd_edit
, EM_SETSEL
, 0, -1);
632 SendMessageW(hwnd_edit
, WM_CHAR
, 'h', 1);
634 SendMessageW(hwnd_edit
, WM_GETTEXT
, ARRAY_SIZE(buffer
), (LPARAM
)buffer
);
635 ok(lstrcmpW(str6
, buffer
) == 0, "Expected %s, got %s\n", wine_dbgstr_w(str6
), wine_dbgstr_w(buffer
));
636 check_dropdown(acdropdown
, hwnd_edit
, sorted4
, ARRAY_SIZE(sorted4
));
637 SendMessageW(hwnd_edit
, WM_CHAR
, 't', 1);
638 SendMessageW(hwnd_edit
, WM_GETTEXT
, ARRAY_SIZE(buffer
), (LPARAM
)buffer
);
639 ok(lstrcmpW(str5
+ 8, buffer
) == 0, "Expected %s, got %s\n", wine_dbgstr_w(str5
+ 8), wine_dbgstr_w(buffer
));
640 check_dropdown(acdropdown
, hwnd_edit
, sorted5
, ARRAY_SIZE(sorted5
));
641 SendMessageW(hwnd_edit
, WM_CHAR
, 't', 1);
642 SendMessageW(hwnd_edit
, WM_GETTEXT
, ARRAY_SIZE(buffer
), (LPARAM
)buffer
);
643 ok(lstrcmpW(htt
, buffer
) == 0, "Expected %s, got %s\n", wine_dbgstr_w(htt
), wine_dbgstr_w(buffer
));
644 check_dropdown(acdropdown
, hwnd_edit
, NULL
, 0);
645 SendMessageW(hwnd_edit
, WM_CHAR
, 'p', 1);
646 SendMessageW(hwnd_edit
, WM_CHAR
, ':', 1);
647 SendMessageW(hwnd_edit
, WM_CHAR
, '/', 1);
648 SendMessageW(hwnd_edit
, WM_CHAR
, '/', 1);
649 SendMessageW(hwnd_edit
, WM_CHAR
, 'a', 1);
651 SendMessageW(hwnd_edit
, WM_GETTEXT
, ARRAY_SIZE(buffer
), (LPARAM
)buffer
);
652 ok(lstrcmpW(str4
, buffer
) == 0, "Expected %s, got %s\n", wine_dbgstr_w(str4
), wine_dbgstr_w(buffer
));
653 check_dropdown(acdropdown
, hwnd_edit
, sorted6
, ARRAY_SIZE(sorted6
));
654 SendMessageW(hwnd_edit
, EM_SETSEL
, 0, 2);
655 SendMessageW(hwnd_edit
, WM_CHAR
, 'H', 1);
657 check_dropdown(acdropdown
, hwnd_edit
, NULL
, 0);
658 SendMessageW(hwnd_edit
, WM_CHAR
, 't', 1);
660 check_dropdown(acdropdown
, hwnd_edit
, sorted6
, ARRAY_SIZE(sorted6
));
662 SendMessageW(hwnd_edit
, EM_SETSEL
, 0, -1);
663 SendMessageW(hwnd_edit
, WM_CHAR
, 'F', 1);
665 SendMessageW(hwnd_edit
, WM_GETTEXT
, ARRAY_SIZE(buffer
), (LPARAM
)buffer
);
666 check_dropdown(acdropdown
, hwnd_edit
, sorted7
, ARRAY_SIZE(sorted7
));
667 SendMessageW(hwnd_edit
, WM_CHAR
, 'i', 1);
668 SendMessageW(hwnd_edit
, WM_CHAR
, 'L', 1);
669 SendMessageW(hwnd_edit
, WM_GETTEXT
, ARRAY_SIZE(buffer
), (LPARAM
)buffer
);
670 check_dropdown(acdropdown
, hwnd_edit
, sorted7
, 1);
672 IAutoCompleteDropDown_Release(acdropdown
);
673 IAutoComplete2_Release(autocomplete
);
674 IUnknown_Release(enumerator
);
677 static void test_custom_source(void)
679 static WCHAR str_alpha
[] = {'t','e','s','t','1',0};
680 static WCHAR str_alpha2
[] = {'t','e','s','t','2',0};
681 static WCHAR str_beta
[] = {'a','u','t','o',' ','c','o','m','p','l','e','t','e',0};
682 static WCHAR str_au
[] = {'a','u',0};
683 static WCHAR str_aut
[] = {'a','u','t',0};
684 static WCHAR
*suggestions
[] = { str_alpha
, str_alpha2
, str_beta
};
685 struct string_enumerator
*obj
;
686 IUnknown
*enumerator
;
687 IAutoComplete2
*autocomplete
;
688 IAutoCompleteDropDown
*acdropdown
;
694 ShowWindow(hMainWnd
, SW_SHOW
);
696 hwnd_edit
= CreateWindowA("Edit", "", WS_OVERLAPPED
| WS_VISIBLE
| WS_CHILD
| WS_BORDER
, 50, 5, 200, 20, hMainWnd
, 0, NULL
, 0);
698 hr
= CoCreateInstance(&CLSID_AutoComplete
, NULL
, CLSCTX_INPROC_SERVER
, &IID_IAutoComplete2
, (void**)&autocomplete
);
699 ok(hr
== S_OK
, "CoCreateInstance failed: %x\n", hr
);
701 hr
= IAutoComplete2_QueryInterface(autocomplete
, &IID_IAutoCompleteDropDown
, (LPVOID
*)&acdropdown
);
702 ok(hr
== S_OK
, "No IAutoCompleteDropDown interface: %x\n", hr
);
704 string_enumerator_create((void**)&enumerator
, suggestions
, ARRAY_SIZE(suggestions
));
705 obj
= (struct string_enumerator
*)enumerator
;
707 hr
= IAutoComplete2_SetOptions(autocomplete
, ACO_AUTOSUGGEST
| ACO_AUTOAPPEND
);
708 ok(hr
== S_OK
, "IAutoComplete2_SetOptions failed: %x\n", hr
);
709 hr
= IAutoCompleteDropDown_ResetEnumerator(acdropdown
);
710 ok(hr
== S_OK
, "IAutoCompleteDropDown_ResetEnumerator failed: %x\n", hr
);
711 hr
= IAutoComplete2_Init(autocomplete
, hwnd_edit
, enumerator
, NULL
, NULL
);
712 ok(hr
== S_OK
, "IAutoComplete_Init failed: %x\n", hr
);
715 SendMessageW(hwnd_edit
, WM_CHAR
, 'a', 1);
716 SendMessageW(hwnd_edit
, WM_CHAR
, 'u', 1);
718 SendMessageW(hwnd_edit
, WM_GETTEXT
, ARRAY_SIZE(buffer
), (LPARAM
)buffer
);
719 ok(lstrcmpW(str_beta
, buffer
) == 0, "Expected %s, got %s\n", wine_dbgstr_w(str_beta
), wine_dbgstr_w(buffer
));
720 ok(obj
->num_resets
== 1, "Expected 1 reset, got %u\n", obj
->num_resets
);
721 SendMessageW(hwnd_edit
, EM_SETSEL
, 0, -1);
722 SendMessageW(hwnd_edit
, WM_CHAR
, '\b', 1);
724 SendMessageW(hwnd_edit
, WM_GETTEXT
, ARRAY_SIZE(buffer
), (LPARAM
)buffer
);
725 ok(buffer
[0] == '\0', "Expected empty string, got %s\n", wine_dbgstr_w(buffer
));
726 ok(obj
->num_resets
== 1, "Expected 1 reset, got %u\n", obj
->num_resets
);
727 hr
= IAutoCompleteDropDown_ResetEnumerator(acdropdown
);
728 ok(hr
== S_OK
, "IAutoCompleteDropDown_ResetEnumerator failed: %x\n", hr
);
729 ok(obj
->num_resets
== 1, "Expected 1 reset, got %u\n", obj
->num_resets
);
732 /* hijack the window procedure */
733 HijackerWndProc_prev
= (WNDPROC
)SetWindowLongPtrW(hwnd_edit
, GWLP_WNDPROC
, (LONG_PTR
)HijackerWndProc
);
734 SendMessageW(hwnd_edit
, WM_GETTEXT
, ARRAY_SIZE(buffer
), (LPARAM
)buffer
);
735 ok(lstrcmpW(HijackerWndProc_txt
, buffer
) == 0, "Expected %s, got %s\n", wine_dbgstr_w(HijackerWndProc_txt
), wine_dbgstr_w(buffer
));
737 SendMessageW(hwnd_edit
, WM_CHAR
, 'a', 1);
738 SendMessageW(hwnd_edit
, WM_CHAR
, 'u', 1);
739 SetWindowLongPtrW(hwnd_edit
, GWLP_WNDPROC
, (LONG_PTR
)HijackerWndProc_prev
);
741 SendMessageW(hwnd_edit
, WM_GETTEXT
, ARRAY_SIZE(buffer
), (LPARAM
)buffer
);
742 ok(lstrcmpW(str_au
, buffer
) == 0, "Expected %s, got %s\n", wine_dbgstr_w(str_au
), wine_dbgstr_w(buffer
));
743 ok(obj
->num_resets
== 1, "Expected 1 reset, got %u\n", obj
->num_resets
);
744 SendMessageW(hwnd_edit
, EM_SETSEL
, 0, -1);
745 SendMessageW(hwnd_edit
, WM_CHAR
, '\b', 1);
747 SendMessageW(hwnd_edit
, WM_GETTEXT
, ARRAY_SIZE(buffer
), (LPARAM
)buffer
);
748 ok(buffer
[0] == '\0', "Expected empty string, got %s\n", wine_dbgstr_w(buffer
));
749 hr
= IAutoCompleteDropDown_ResetEnumerator(acdropdown
);
750 ok(hr
== S_OK
, "IAutoCompleteDropDown_ResetEnumerator failed: %x\n", hr
);
752 HijackerWndProc_prev
= (WNDPROC
)SetWindowLongPtrW(hwnd_edit
, GWLP_WNDPROC
, (LONG_PTR
)HijackerWndProc2
);
753 SendMessageW(hwnd_edit
, WM_CHAR
, 'a', 1);
754 SendMessageW(hwnd_edit
, WM_CHAR
, 'u', 1);
755 SetWindowLongPtrW(hwnd_edit
, GWLP_WNDPROC
, (LONG_PTR
)HijackerWndProc_prev
);
757 SendMessageW(hwnd_edit
, WM_GETTEXT
, ARRAY_SIZE(buffer
), (LPARAM
)buffer
);
758 ok(lstrcmpW(str_beta
, buffer
) == 0, "Expected %s, got %s\n", wine_dbgstr_w(str_beta
), wine_dbgstr_w(buffer
));
759 ok(obj
->num_resets
== 2, "Expected 2 resets, got %u\n", obj
->num_resets
);
762 hr
= IAutoCompleteDropDown_GetDropDownStatus(acdropdown
, &flags
, NULL
);
763 ok(hr
== S_OK
, "IAutoCompleteDropDown_GetDropDownStatus failed: %x\n", hr
);
764 ok(flags
& ACDD_VISIBLE
, "AutoComplete DropDown should be visible\n");
765 SendMessageW(hwnd_edit
, WM_SETTEXT
, 0, (LPARAM
)str_au
);
767 hr
= IAutoCompleteDropDown_GetDropDownStatus(acdropdown
, &flags
, NULL
);
768 ok(hr
== S_OK
, "IAutoCompleteDropDown_GetDropDownStatus failed: %x\n", hr
);
769 ok(!(flags
& ACDD_VISIBLE
), "AutoComplete DropDown should have been hidden\n");
770 SendMessageW(hwnd_edit
, WM_SETTEXT
, 0, (LPARAM
)str_aut
);
772 hr
= IAutoCompleteDropDown_GetDropDownStatus(acdropdown
, &flags
, NULL
);
773 ok(hr
== S_OK
, "IAutoCompleteDropDown_GetDropDownStatus failed: %x\n", hr
);
774 ok(!(flags
& ACDD_VISIBLE
), "AutoComplete DropDown should be hidden\n");
775 SendMessageW(hwnd_edit
, WM_GETTEXT
, ARRAY_SIZE(buffer
), (LPARAM
)buffer
);
776 ok(lstrcmpW(str_aut
, buffer
) == 0, "Expected %s, got %s\n", wine_dbgstr_w(str_aut
), wine_dbgstr_w(buffer
));
778 test_aclist_expand(hwnd_edit
, enumerator
);
781 hr
= IAutoCompleteDropDown_ResetEnumerator(acdropdown
);
782 ok(hr
== S_OK
, "IAutoCompleteDropDown_ResetEnumerator failed: %x\n", hr
);
783 SendMessageW(hwnd_edit
, WM_CHAR
, 'x', 1);
785 ok(obj
->num_resets
== 1, "Expected 1 reset, got %u\n", obj
->num_resets
);
786 SendMessageW(hwnd_edit
, WM_CHAR
, 'x', 1);
788 ok(obj
->num_resets
== 1, "Expected 1 reset, got %u\n", obj
->num_resets
);
790 IAutoCompleteDropDown_Release(acdropdown
);
791 IAutoComplete2_Release(autocomplete
);
792 IUnknown_Release(enumerator
);
794 test_prefix_filtering(hwnd_edit
);
796 ShowWindow(hMainWnd
, SW_HIDE
);
797 DestroyWindow(hwnd_edit
);
800 START_TEST(autocomplete
)
808 r
= CoInitialize(NULL
);
809 ok(r
== S_OK
, "CoInitialize failed (0x%08x). Tests aborted.\n", r
);
814 ok(hMainWnd
!= NULL
, "Failed to create parent window. Tests aborted.\n");
815 if (!hMainWnd
) return;
817 /* Move the cursor away from the dropdown listbox */
818 GetWindowRect(hMainWnd
, &win_rect
);
819 GetCursorPos(&orig_pos
);
820 SetCursorPos(win_rect
.left
, win_rect
.top
);
828 test_custom_source();
831 while(GetMessageA(&msg
,0,0,0)) {
832 TranslateMessage(&msg
);
833 DispatchMessageA(&msg
);
836 IAutoComplete_Release(ac
);
839 SetCursorPos(orig_pos
.x
, orig_pos
.y
);
840 DestroyWindow(hEdit
);
841 DestroyWindow(hMainWnd
);