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)
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 IUnknown_Release(acSource
);
184 static void test_killfocus(void)
186 /* Test if WM_KILLFOCUS messages are handled properly by checking if
187 * the parent receives an EN_KILLFOCUS message. */
191 ok(killfocus_count
== 1, "Expected one EN_KILLFOCUS message, got: %d\n", killfocus_count
);
194 static LRESULT CALLBACK
MyWndProc(HWND hWnd
, UINT msg
, WPARAM wParam
, LPARAM lParam
)
198 /* create edit control */
199 hEdit
= CreateWindowExA(0, "EDIT", "Some text", 0, 10, 10, 300, 300,
200 hWnd
, NULL
, hinst
, NULL
);
201 ok(hEdit
!= NULL
, "Can't create edit control\n");
204 if(HIWORD(wParam
) == EN_KILLFOCUS
)
208 return DefWindowProcA(hWnd
, msg
, wParam
, lParam
);
211 static void createMainWnd(void)
214 wc
.style
= CS_HREDRAW
| CS_VREDRAW
;
217 wc
.hInstance
= GetModuleHandleA(NULL
);
219 wc
.hCursor
= LoadCursorA(NULL
, (LPSTR
)IDC_IBEAM
);
220 wc
.hbrBackground
= GetSysColorBrush(COLOR_WINDOW
);
221 wc
.lpszMenuName
= NULL
;
222 wc
.lpszClassName
= "MyTestWnd";
223 wc
.lpfnWndProc
= MyWndProc
;
226 hMainWnd
= CreateWindowExA(0, "MyTestWnd", "Blah", WS_OVERLAPPEDWINDOW
,
227 CW_USEDEFAULT
, CW_USEDEFAULT
, 130, 105, NULL
, NULL
, GetModuleHandleA(NULL
), 0);
230 struct string_enumerator
232 IEnumString IEnumString_iface
;
239 static struct string_enumerator
*impl_from_IEnumString(IEnumString
*iface
)
241 return CONTAINING_RECORD(iface
, struct string_enumerator
, IEnumString_iface
);
244 static HRESULT WINAPI
string_enumerator_QueryInterface(IEnumString
*iface
, REFIID riid
, void **ppv
)
246 if (IsEqualGUID(riid
, &IID_IEnumString
) || IsEqualGUID(riid
, &IID_IUnknown
))
248 IUnknown_AddRef(iface
);
254 return E_NOINTERFACE
;
257 static ULONG WINAPI
string_enumerator_AddRef(IEnumString
*iface
)
259 struct string_enumerator
*this = impl_from_IEnumString(iface
);
261 ULONG ref
= InterlockedIncrement(&this->ref
);
266 static ULONG WINAPI
string_enumerator_Release(IEnumString
*iface
)
268 struct string_enumerator
*this = impl_from_IEnumString(iface
);
270 ULONG ref
= InterlockedDecrement(&this->ref
);
278 static HRESULT WINAPI
string_enumerator_Next(IEnumString
*iface
, ULONG num
, LPOLESTR
*strings
, ULONG
*num_returned
)
280 struct string_enumerator
*this = impl_from_IEnumString(iface
);
284 for (i
= 0; i
< num
; i
++)
286 if (this->cur
>= this->data_len
)
289 len
= lstrlenW(this->data
[this->cur
]) + 1;
291 strings
[i
] = CoTaskMemAlloc(len
* sizeof(WCHAR
));
292 memcpy(strings
[i
], this->data
[this->cur
], len
* sizeof(WCHAR
));
301 static HRESULT WINAPI
string_enumerator_Reset(IEnumString
*iface
)
303 struct string_enumerator
*this = impl_from_IEnumString(iface
);
310 static HRESULT WINAPI
string_enumerator_Skip(IEnumString
*iface
, ULONG num
)
312 struct string_enumerator
*this = impl_from_IEnumString(iface
);
319 static HRESULT WINAPI
string_enumerator_Clone(IEnumString
*iface
, IEnumString
**out
)
325 static IEnumStringVtbl string_enumerator_vtlb
=
327 string_enumerator_QueryInterface
,
328 string_enumerator_AddRef
,
329 string_enumerator_Release
,
330 string_enumerator_Next
,
331 string_enumerator_Skip
,
332 string_enumerator_Reset
,
333 string_enumerator_Clone
336 static HRESULT
string_enumerator_create(void **ppv
, WCHAR
**suggestions
, int count
)
338 struct string_enumerator
*object
;
340 object
= heap_alloc_zero(sizeof(*object
));
341 object
->IEnumString_iface
.lpVtbl
= &string_enumerator_vtlb
;
343 object
->data
= suggestions
;
344 object
->data_len
= count
;
347 *ppv
= &object
->IEnumString_iface
;
352 static void test_custom_source(void)
354 static WCHAR str_alpha
[] = {'t','e','s','t','1',0};
355 static WCHAR str_alpha2
[] = {'t','e','s','t','2',0};
356 static WCHAR str_beta
[] = {'a','u','t','o',' ','c','o','m','p','l','e','t','e',0};
357 static WCHAR
*suggestions
[] = { str_alpha
, str_alpha2
, str_beta
};
358 IUnknown
*enumerator
;
359 IAutoComplete2
*autocomplete
;
365 ShowWindow(hMainWnd
, SW_SHOW
);
367 hwnd_edit
= CreateWindowA("Edit", "", WS_OVERLAPPED
| WS_VISIBLE
| WS_CHILD
| WS_BORDER
, 50, 5, 200, 20, hMainWnd
, 0, NULL
, 0);
369 hr
= CoCreateInstance(&CLSID_AutoComplete
, NULL
, CLSCTX_INPROC_SERVER
, &IID_IAutoComplete2
, (void**)&autocomplete
);
370 ok(hr
== S_OK
, "CoCreateInstance failed: %x\n", hr
);
372 string_enumerator_create((void**)&enumerator
, suggestions
, sizeof(suggestions
) / sizeof(*suggestions
));
374 hr
= IAutoComplete2_SetOptions(autocomplete
, ACO_AUTOSUGGEST
| ACO_AUTOAPPEND
);
375 ok(hr
== S_OK
, "IAutoComplete2_SetOptions failed: %x\n", hr
);
376 hr
= IAutoComplete2_Init(autocomplete
, hwnd_edit
, enumerator
, NULL
, NULL
);
377 ok(hr
== S_OK
, "IAutoComplete_Init failed: %x\n", hr
);
379 SendMessageW(hwnd_edit
, WM_CHAR
, 'a', 1);
380 /* Send a keyup message since wine doesn't handle WM_CHAR yet */
381 SendMessageW(hwnd_edit
, WM_KEYUP
, 'u', 1);
383 while (PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
))
385 TranslateMessage(&msg
);
386 DispatchMessageA(&msg
);
388 SendMessageW(hwnd_edit
, WM_GETTEXT
, sizeof(buffer
) / sizeof(*buffer
), (LPARAM
)buffer
);
389 ok(lstrcmpW(str_beta
, buffer
) == 0, "Expected %s, got %s\n", wine_dbgstr_w(str_beta
), wine_dbgstr_w(buffer
));
391 ShowWindow(hMainWnd
, SW_HIDE
);
392 DestroyWindow(hwnd_edit
);
395 START_TEST(autocomplete
)
401 r
= CoInitialize(NULL
);
402 ok(r
== S_OK
, "CoInitialize failed (0x%08x). Tests aborted.\n", r
);
407 ok(hMainWnd
!= NULL
, "Failed to create parent window. Tests aborted.\n");
408 if (!hMainWnd
) return;
416 test_custom_source();
419 while(GetMessageA(&msg
,0,0,0)) {
420 TranslateMessage(&msg
);
421 DispatchMessageA(&msg
);
424 IAutoComplete_Release(ac
);
427 DestroyWindow(hEdit
);
428 DestroyWindow(hMainWnd
);