2 * AutoComplete interfaces implementation.
4 * Copyright 2004 Maxime Bellengé <maxime.bellenge@laposte.net>
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
23 - ACO_AUTOAPPEND style
24 - ACO_AUTOSUGGEST style
25 - ACO_UPDOWNKEYDROPSLIST style
27 - Handle pwzsRegKeyPath and pwszQuickComplete in Init
30 - implement ACO_SEARCH style
31 - implement ACO_FILTERPREFIXES style
32 - implement ACO_USETAB style
33 - implement ACO_RTLREADING style
34 - implement ResetEnumerator
35 - string compares should be case-insensitive, the content of the list should be sorted
46 #include "wine/debug.h"
50 #include "undocshell.h"
59 #include "shell32_main.h"
61 #include "wine/unicode.h"
63 WINE_DEFAULT_DEBUG_CHANNEL(shell
);
67 IAutoComplete2 IAutoComplete2_iface
;
68 IAutoCompleteDropDown IAutoCompleteDropDown_iface
;
74 WNDPROC wpOrigEditProc
;
75 WNDPROC wpOrigLBoxProc
;
79 AUTOCOMPLETEOPTIONS options
;
86 autoappend_flag_displayempty
89 static const WCHAR autocomplete_propertyW
[] = {'W','i','n','e',' ','A','u','t','o',
90 'c','o','m','p','l','e','t','e',' ',
91 'c','o','n','t','r','o','l',0};
93 static inline IAutoCompleteImpl
*impl_from_IAutoComplete2(IAutoComplete2
*iface
)
95 return CONTAINING_RECORD(iface
, IAutoCompleteImpl
, IAutoComplete2_iface
);
98 static inline IAutoCompleteImpl
*impl_from_IAutoCompleteDropDown(IAutoCompleteDropDown
*iface
)
100 return CONTAINING_RECORD(iface
, IAutoCompleteImpl
, IAutoCompleteDropDown_iface
);
103 static void set_text_and_selection(IAutoCompleteImpl
*ac
, HWND hwnd
, WCHAR
*text
, WPARAM start
, LPARAM end
)
105 /* Send it directly to the edit control to match Windows behavior */
106 WNDPROC proc
= ac
->wpOrigEditProc
;
107 if (CallWindowProcW(proc
, hwnd
, WM_SETTEXT
, 0, (LPARAM
)text
))
108 CallWindowProcW(proc
, hwnd
, EM_SETSEL
, start
, end
);
111 static size_t format_quick_complete(WCHAR
*dst
, const WCHAR
*qc
, const WCHAR
*str
, size_t str_len
)
113 /* Replace the first %s directly without using snprintf, to avoid
114 exploits since the format string can be retrieved from the registry */
121 if (args
< 1 && qc
[1] == 's')
123 memcpy(dst
, str
, str_len
* sizeof(WCHAR
));
129 qc
+= (qc
[1] == '%');
137 static LRESULT
change_selection(IAutoCompleteImpl
*ac
, HWND hwnd
, UINT key
)
139 INT count
= SendMessageW(ac
->hwndListBox
, LB_GETCOUNT
, 0, 0);
140 INT sel
= SendMessageW(ac
->hwndListBox
, LB_GETCURSEL
, 0, 0);
141 if (key
== VK_PRIOR
|| key
== VK_NEXT
)
144 sel
= (key
== VK_PRIOR
) ? count
- 1 : 0;
147 INT base
= SendMessageW(ac
->hwndListBox
, LB_GETTOPINDEX
, 0, 0);
148 INT pgsz
= SendMessageW(ac
->hwndListBox
, LB_GETLISTBOXINFO
, 0, 0);
149 pgsz
= max(pgsz
- 1, 1);
156 if (sel
== base
) base
-= min(base
, pgsz
);
162 if (sel
== count
- 1)
167 if (sel
>= base
) base
+= pgsz
;
168 sel
= min(base
, count
- 1);
173 else if (key
== VK_UP
)
174 sel
= ((sel
- 1) < -1) ? count
- 1 : sel
- 1;
176 sel
= ((sel
+ 1) >= count
) ? -1 : sel
+ 1;
178 SendMessageW(ac
->hwndListBox
, LB_SETCURSEL
, sel
, 0);
182 UINT len
= SendMessageW(ac
->hwndListBox
, LB_GETTEXTLEN
, sel
, 0);
183 if (!(msg
= heap_alloc((len
+ 1) * sizeof(WCHAR
))))
185 len
= SendMessageW(ac
->hwndListBox
, LB_GETTEXT
, sel
, (LPARAM
)msg
);
186 set_text_and_selection(ac
, hwnd
, msg
, len
, len
);
191 UINT len
= strlenW(ac
->txtbackup
);
192 set_text_and_selection(ac
, hwnd
, ac
->txtbackup
, len
, len
);
197 static void autoappend_str(IAutoCompleteImpl
*ac
, WCHAR
*text
, UINT len
, WCHAR
*str
, HWND hwnd
)
203 /* Don't auto-append unless the caret is at the end */
204 SendMessageW(hwnd
, EM_GETSEL
, (WPARAM
)&sel_start
, 0);
205 if (sel_start
!= len
)
208 /* The character capitalization can be different,
209 so merge text and str into a new string */
210 size
= len
+ strlenW(&str
[len
]) + 1;
212 if ((tmp
= heap_alloc(size
* sizeof(*tmp
))))
214 memcpy(tmp
, text
, len
* sizeof(*tmp
));
215 memcpy(&tmp
[len
], &str
[len
], (size
- len
) * sizeof(*tmp
));
219 set_text_and_selection(ac
, hwnd
, tmp
, len
, size
- 1);
224 static void autocomplete_text(IAutoCompleteImpl
*ac
, HWND hwnd
, enum autoappend_flag flag
)
228 UINT cpt
, size
, len
= SendMessageW(hwnd
, WM_GETTEXTLENGTH
, 0, 0);
230 if (flag
!= autoappend_flag_displayempty
&& len
== 0)
232 if (ac
->options
& ACO_AUTOSUGGEST
)
233 ShowWindow(ac
->hwndListBox
, SW_HIDE
);
238 if (!(text
= heap_alloc(size
* sizeof(WCHAR
))))
240 len
= SendMessageW(hwnd
, WM_GETTEXT
, size
, (LPARAM
)text
);
242 text
= heap_realloc(text
, (len
+ 1) * sizeof(WCHAR
));
244 /* Set txtbackup to point to text itself (which must not be released) */
245 heap_free(ac
->txtbackup
);
246 ac
->txtbackup
= text
;
248 if (ac
->options
& ACO_AUTOSUGGEST
)
250 SendMessageW(ac
->hwndListBox
, WM_SETREDRAW
, FALSE
, 0);
251 SendMessageW(ac
->hwndListBox
, LB_RESETCONTENT
, 0, 0);
253 IEnumString_Reset(ac
->enumstr
);
256 LPOLESTR strs
= NULL
;
259 hr
= IEnumString_Next(ac
->enumstr
, 1, &strs
, &fetched
);
263 if (!strncmpiW(text
, strs
, len
))
265 if (cpt
== 0 && flag
== autoappend_flag_yes
)
267 autoappend_str(ac
, text
, len
, strs
, hwnd
);
268 if (!(ac
->options
& ACO_AUTOSUGGEST
))
275 if (ac
->options
& ACO_AUTOSUGGEST
)
276 SendMessageW(ac
->hwndListBox
, LB_ADDSTRING
, 0, (LPARAM
)strs
);
284 if (ac
->options
& ACO_AUTOSUGGEST
)
289 UINT height
= SendMessageW(ac
->hwndListBox
, LB_GETITEMHEIGHT
, 0, 0);
290 SendMessageW(ac
->hwndListBox
, LB_CARETOFF
, 0, 0);
291 GetWindowRect(hwnd
, &r
);
292 /* It seems that Windows XP displays 7 lines at most
293 and otherwise displays a vertical scroll bar */
294 SetWindowPos(ac
->hwndListBox
, HWND_TOP
,
295 r
.left
, r
.bottom
+ 1, r
.right
- r
.left
, height
* min(cpt
+ 1, 7),
297 SendMessageW(ac
->hwndListBox
, WM_SETREDRAW
, TRUE
, 0);
300 ShowWindow(ac
->hwndListBox
, SW_HIDE
);
304 static void destroy_autocomplete_object(IAutoCompleteImpl
*ac
)
308 DestroyWindow(ac
->hwndListBox
);
309 IAutoComplete2_Release(&ac
->IAutoComplete2_iface
);
313 Helper for ACEditSubclassProc
315 static LRESULT
ACEditSubclassProc_KeyDown(IAutoCompleteImpl
*ac
, HWND hwnd
, UINT uMsg
,
316 WPARAM wParam
, LPARAM lParam
)
321 /* If quickComplete is set and control is pressed, replace the string */
322 if (ac
->quickComplete
&& (GetKeyState(VK_CONTROL
) & 0x8000))
326 UINT len
= SendMessageW(hwnd
, WM_GETTEXTLENGTH
, 0, 0);
327 if (!(text
= heap_alloc((len
+ 1) * sizeof(WCHAR
))))
329 len
= SendMessageW(hwnd
, WM_GETTEXT
, len
+ 1, (LPARAM
)text
);
330 sz
= strlenW(ac
->quickComplete
) + 1 + len
;
332 if ((buf
= heap_alloc(sz
* sizeof(WCHAR
))))
334 len
= format_quick_complete(buf
, ac
->quickComplete
, text
, len
);
335 set_text_and_selection(ac
, hwnd
, buf
, 0, len
);
339 if (ac
->options
& ACO_AUTOSUGGEST
)
340 ShowWindow(ac
->hwndListBox
, SW_HIDE
);
345 if (ac
->options
& ACO_AUTOSUGGEST
)
346 ShowWindow(ac
->hwndListBox
, SW_HIDE
);
353 - if the listbox is not visible and ACO_UPDOWNKEYDROPSLIST is
354 set, display it with all the entries, without selecting any
355 - if the listbox is visible, change the selection
357 if (!(ac
->options
& ACO_AUTOSUGGEST
))
360 if (!IsWindowVisible(ac
->hwndListBox
))
362 if (ac
->options
& ACO_UPDOWNKEYDROPSLIST
)
364 autocomplete_text(ac
, hwnd
, autoappend_flag_displayempty
);
369 return change_selection(ac
, hwnd
, wParam
);
373 LRESULT ret
= CallWindowProcW(ac
->wpOrigEditProc
, hwnd
, uMsg
, wParam
, lParam
);
374 autocomplete_text(ac
, hwnd
, autoappend_flag_no
);
378 return CallWindowProcW(ac
->wpOrigEditProc
, hwnd
, uMsg
, wParam
, lParam
);
382 Window procedure for autocompletion
384 static LRESULT APIENTRY
ACEditSubclassProc(HWND hwnd
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
)
386 IAutoCompleteImpl
*This
= GetPropW(hwnd
, autocomplete_propertyW
);
389 if (!This
->enabled
) return CallWindowProcW(This
->wpOrigEditProc
, hwnd
, uMsg
, wParam
, lParam
);
393 case CB_SHOWDROPDOWN
:
394 if (This
->options
& ACO_AUTOSUGGEST
)
395 ShowWindow(This
->hwndListBox
, SW_HIDE
);
398 if ((This
->options
& ACO_AUTOSUGGEST
) && ((HWND
)wParam
!= This
->hwndListBox
))
400 ShowWindow(This
->hwndListBox
, SW_HIDE
);
404 return ACEditSubclassProc_KeyDown(This
, hwnd
, uMsg
, wParam
, lParam
);
407 /* Don't autocomplete at all on most control characters */
408 if (iscntrlW(wParam
) && !(wParam
>= '\b' && wParam
<= '\r'))
411 ret
= CallWindowProcW(This
->wpOrigEditProc
, hwnd
, uMsg
, wParam
, lParam
);
412 autocomplete_text(This
, hwnd
, (This
->options
& ACO_AUTOAPPEND
) && wParam
>= ' '
413 ? autoappend_flag_yes
: autoappend_flag_no
);
419 ret
= CallWindowProcW(This
->wpOrigEditProc
, hwnd
, uMsg
, wParam
, lParam
);
420 autocomplete_text(This
, hwnd
, autoappend_flag_no
);
423 ret
= CallWindowProcW(This
->wpOrigEditProc
, hwnd
, uMsg
, wParam
, lParam
);
424 autocomplete_text(This
, hwnd
, autoappend_flag_yes
);
427 if (This
->hwndListBox
)
428 SendMessageW(This
->hwndListBox
, WM_SETFONT
, wParam
, lParam
);
432 WNDPROC proc
= This
->wpOrigEditProc
;
434 SetWindowLongPtrW(hwnd
, GWLP_WNDPROC
, (LONG_PTR
)proc
);
435 RemovePropW(hwnd
, autocomplete_propertyW
);
436 destroy_autocomplete_object(This
);
437 return CallWindowProcW(proc
, hwnd
, uMsg
, wParam
, lParam
);
440 return CallWindowProcW(This
->wpOrigEditProc
, hwnd
, uMsg
, wParam
, lParam
);
443 static LRESULT APIENTRY
ACLBoxSubclassProc(HWND hwnd
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
)
445 IAutoCompleteImpl
*This
= (IAutoCompleteImpl
*)GetWindowLongPtrW(hwnd
, GWLP_USERDATA
);
451 sel
= SendMessageW(hwnd
, LB_ITEMFROMPOINT
, 0, lParam
);
452 SendMessageW(hwnd
, LB_SETCURSEL
, sel
, 0);
455 sel
= SendMessageW(hwnd
, LB_GETCURSEL
, 0, 0);
458 len
= SendMessageW(hwnd
, LB_GETTEXTLEN
, sel
, 0);
459 if (!(msg
= heap_alloc((len
+ 1) * sizeof(WCHAR
))))
461 len
= SendMessageW(hwnd
, LB_GETTEXT
, sel
, (LPARAM
)msg
);
462 set_text_and_selection(This
, This
->hwndEdit
, msg
, 0, len
);
463 ShowWindow(hwnd
, SW_HIDE
);
467 return CallWindowProcW(This
->wpOrigLBoxProc
, hwnd
, uMsg
, wParam
, lParam
);
472 static void create_listbox(IAutoCompleteImpl
*This
)
474 /* FIXME : The listbox should be resizable with the mouse. WS_THICKFRAME looks ugly */
475 This
->hwndListBox
= CreateWindowExW(0, WC_LISTBOXW
, NULL
,
476 WS_BORDER
| WS_CHILD
| WS_VSCROLL
| LBS_HASSTRINGS
| LBS_NOTIFY
| LBS_NOINTEGRALHEIGHT
,
477 0, 0, 0, 0, GetParent(This
->hwndEdit
), NULL
, shell32_hInstance
, NULL
);
479 if (This
->hwndListBox
) {
482 This
->wpOrigLBoxProc
= (WNDPROC
) SetWindowLongPtrW( This
->hwndListBox
, GWLP_WNDPROC
, (LONG_PTR
) ACLBoxSubclassProc
);
483 SetWindowLongPtrW( This
->hwndListBox
, GWLP_USERDATA
, (LONG_PTR
)This
);
484 SetParent(This
->hwndListBox
, HWND_DESKTOP
);
486 /* Use the same font as the edit control, as it gets destroyed before it anyway */
487 edit_font
= (HFONT
)SendMessageW(This
->hwndEdit
, WM_GETFONT
, 0, 0);
489 SendMessageW(This
->hwndListBox
, WM_SETFONT
, (WPARAM
)edit_font
, FALSE
);
492 This
->options
&= ~ACO_AUTOSUGGEST
;
495 /**************************************************************************
496 * AutoComplete_QueryInterface
498 static HRESULT WINAPI
IAutoComplete2_fnQueryInterface(
499 IAutoComplete2
* iface
,
503 IAutoCompleteImpl
*This
= impl_from_IAutoComplete2(iface
);
505 TRACE("(%p)->(IID:%s,%p)\n", This
, shdebugstr_guid(riid
), ppvObj
);
508 if (IsEqualIID(riid
, &IID_IUnknown
) ||
509 IsEqualIID(riid
, &IID_IAutoComplete
) ||
510 IsEqualIID(riid
, &IID_IAutoComplete2
))
512 *ppvObj
= &This
->IAutoComplete2_iface
;
514 else if (IsEqualIID(riid
, &IID_IAutoCompleteDropDown
))
516 *ppvObj
= &This
->IAutoCompleteDropDown_iface
;
521 IUnknown_AddRef((IUnknown
*)*ppvObj
);
522 TRACE("-- Interface: (%p)->(%p)\n", ppvObj
, *ppvObj
);
525 WARN("unsupported interface: %s\n", debugstr_guid(riid
));
526 return E_NOINTERFACE
;
529 /******************************************************************************
530 * IAutoComplete2_fnAddRef
532 static ULONG WINAPI
IAutoComplete2_fnAddRef(
533 IAutoComplete2
* iface
)
535 IAutoCompleteImpl
*This
= impl_from_IAutoComplete2(iface
);
536 ULONG refCount
= InterlockedIncrement(&This
->ref
);
538 TRACE("(%p)->(%u)\n", This
, refCount
- 1);
543 /******************************************************************************
544 * IAutoComplete2_fnRelease
546 static ULONG WINAPI
IAutoComplete2_fnRelease(
547 IAutoComplete2
* iface
)
549 IAutoCompleteImpl
*This
= impl_from_IAutoComplete2(iface
);
550 ULONG refCount
= InterlockedDecrement(&This
->ref
);
552 TRACE("(%p)->(%u)\n", This
, refCount
+ 1);
555 TRACE("destroying IAutoComplete(%p)\n", This
);
556 heap_free(This
->quickComplete
);
557 heap_free(This
->txtbackup
);
559 IEnumString_Release(This
->enumstr
);
565 /******************************************************************************
566 * IAutoComplete2_fnEnable
568 static HRESULT WINAPI
IAutoComplete2_fnEnable(
569 IAutoComplete2
* iface
,
572 IAutoCompleteImpl
*This
= impl_from_IAutoComplete2(iface
);
575 TRACE("(%p)->(%s)\n", This
, (fEnable
)?"true":"false");
577 This
->enabled
= fEnable
;
582 /******************************************************************************
583 * IAutoComplete2_fnInit
585 static HRESULT WINAPI
IAutoComplete2_fnInit(
586 IAutoComplete2
* iface
,
589 LPCOLESTR pwzsRegKeyPath
,
590 LPCOLESTR pwszQuickComplete
)
592 IAutoCompleteImpl
*prev
, *This
= impl_from_IAutoComplete2(iface
);
594 TRACE("(%p)->(%p, %p, %s, %s)\n",
595 This
, hwndEdit
, punkACL
, debugstr_w(pwzsRegKeyPath
), debugstr_w(pwszQuickComplete
));
597 if (This
->options
& ACO_SEARCH
) FIXME(" ACO_SEARCH not supported\n");
598 if (This
->options
& ACO_FILTERPREFIXES
) FIXME(" ACO_FILTERPREFIXES not supported\n");
599 if (This
->options
& ACO_USETAB
) FIXME(" ACO_USETAB not supported\n");
600 if (This
->options
& ACO_RTLREADING
) FIXME(" ACO_RTLREADING not supported\n");
602 if (!hwndEdit
|| !punkACL
)
605 if (This
->initialized
)
607 WARN("Autocompletion object is already initialized\n");
608 /* This->hwndEdit is set to NULL when the edit window is destroyed. */
609 return This
->hwndEdit
? E_FAIL
: E_UNEXPECTED
;
612 if (FAILED (IUnknown_QueryInterface (punkACL
, &IID_IEnumString
, (LPVOID
*)&This
->enumstr
))) {
613 WARN("No IEnumString interface\n");
614 return E_NOINTERFACE
;
617 This
->initialized
= TRUE
;
618 This
->hwndEdit
= hwndEdit
;
620 /* If another AutoComplete object was previously assigned to this edit control,
621 release it but keep the same callback on the control, to avoid an infinite
622 recursive loop in ACEditSubclassProc while the property is set to this object */
623 prev
= GetPropW(hwndEdit
, autocomplete_propertyW
);
624 SetPropW(hwndEdit
, autocomplete_propertyW
, This
);
626 if (prev
&& prev
->initialized
) {
627 This
->wpOrigEditProc
= prev
->wpOrigEditProc
;
628 destroy_autocomplete_object(prev
);
631 This
->wpOrigEditProc
= (WNDPROC
) SetWindowLongPtrW(hwndEdit
, GWLP_WNDPROC
, (LONG_PTR
) ACEditSubclassProc
);
633 /* Keep at least one reference to the object until the edit window is destroyed */
634 IAutoComplete2_AddRef(&This
->IAutoComplete2_iface
);
636 if (This
->options
& ACO_AUTOSUGGEST
)
637 create_listbox(This
);
641 static const HKEY roots
[] = { HKEY_CURRENT_USER
, HKEY_LOCAL_MACHINE
};
650 /* pwszRegKeyPath contains the key as well as the value, so split it */
651 value
= strrchrW(pwzsRegKeyPath
, '\\');
652 len
= value
- pwzsRegKeyPath
;
654 if (value
&& (key
= heap_alloc((len
+1) * sizeof(*key
))) != NULL
)
656 memcpy(key
, pwzsRegKeyPath
, len
* sizeof(*key
));
660 for (i
= 0; i
< ARRAY_SIZE(roots
); i
++)
662 if (RegOpenKeyExW(roots
[i
], key
, 0, KEY_READ
, &hKey
) != ERROR_SUCCESS
)
664 sz
= MAX_PATH
* sizeof(WCHAR
);
666 while ((qc
= heap_alloc(sz
)) != NULL
)
668 res
= RegQueryValueExW(hKey
, value
, NULL
, &type
, qc
, &sz
);
669 if (res
== ERROR_SUCCESS
&& type
== REG_SZ
)
671 This
->quickComplete
= heap_realloc(qc
, sz
);
672 i
= ARRAY_SIZE(roots
);
676 if (res
!= ERROR_MORE_DATA
|| type
!= REG_SZ
)
685 if (!This
->quickComplete
&& pwszQuickComplete
)
687 size_t len
= strlenW(pwszQuickComplete
)+1;
688 if ((This
->quickComplete
= heap_alloc(len
* sizeof(WCHAR
))) != NULL
)
689 memcpy(This
->quickComplete
, pwszQuickComplete
, len
* sizeof(WCHAR
));
695 /**************************************************************************
696 * IAutoComplete2_fnGetOptions
698 static HRESULT WINAPI
IAutoComplete2_fnGetOptions(
699 IAutoComplete2
* iface
,
702 IAutoCompleteImpl
*This
= impl_from_IAutoComplete2(iface
);
705 TRACE("(%p) -> (%p)\n", This
, pdwFlag
);
707 *pdwFlag
= This
->options
;
712 /**************************************************************************
713 * IAutoComplete2_fnSetOptions
715 static HRESULT WINAPI
IAutoComplete2_fnSetOptions(
716 IAutoComplete2
* iface
,
719 IAutoCompleteImpl
*This
= impl_from_IAutoComplete2(iface
);
722 TRACE("(%p) -> (0x%x)\n", This
, dwFlag
);
724 This
->options
= dwFlag
;
726 if ((This
->options
& ACO_AUTOSUGGEST
) && This
->hwndEdit
&& !This
->hwndListBox
)
727 create_listbox(This
);
732 /**************************************************************************
733 * IAutoComplete2 VTable
735 static const IAutoComplete2Vtbl acvt
=
737 IAutoComplete2_fnQueryInterface
,
738 IAutoComplete2_fnAddRef
,
739 IAutoComplete2_fnRelease
,
740 IAutoComplete2_fnInit
,
741 IAutoComplete2_fnEnable
,
743 IAutoComplete2_fnSetOptions
,
744 IAutoComplete2_fnGetOptions
,
748 static HRESULT WINAPI
IAutoCompleteDropDown_fnQueryInterface(IAutoCompleteDropDown
*iface
,
749 REFIID riid
, LPVOID
*ppvObj
)
751 IAutoCompleteImpl
*This
= impl_from_IAutoCompleteDropDown(iface
);
752 return IAutoComplete2_QueryInterface(&This
->IAutoComplete2_iface
, riid
, ppvObj
);
755 static ULONG WINAPI
IAutoCompleteDropDown_fnAddRef(IAutoCompleteDropDown
*iface
)
757 IAutoCompleteImpl
*This
= impl_from_IAutoCompleteDropDown(iface
);
758 return IAutoComplete2_AddRef(&This
->IAutoComplete2_iface
);
761 static ULONG WINAPI
IAutoCompleteDropDown_fnRelease(IAutoCompleteDropDown
*iface
)
763 IAutoCompleteImpl
*This
= impl_from_IAutoCompleteDropDown(iface
);
764 return IAutoComplete2_Release(&This
->IAutoComplete2_iface
);
767 /**************************************************************************
768 * IAutoCompleteDropDown_fnGetDropDownStatus
770 static HRESULT WINAPI
IAutoCompleteDropDown_fnGetDropDownStatus(
771 IAutoCompleteDropDown
*iface
,
775 IAutoCompleteImpl
*This
= impl_from_IAutoCompleteDropDown(iface
);
778 TRACE("(%p) -> (%p, %p)\n", This
, pdwFlags
, ppwszString
);
780 dropped
= IsWindowVisible(This
->hwndListBox
);
783 *pdwFlags
= (dropped
? ACDD_VISIBLE
: 0);
789 sel
= SendMessageW(This
->hwndListBox
, LB_GETCURSEL
, 0, 0);
794 len
= SendMessageW(This
->hwndListBox
, LB_GETTEXTLEN
, sel
, 0);
795 *ppwszString
= CoTaskMemAlloc((len
+1)*sizeof(WCHAR
));
796 SendMessageW(This
->hwndListBox
, LB_GETTEXT
, sel
, (LPARAM
)*ppwszString
);
808 /**************************************************************************
809 * IAutoCompleteDropDown_fnResetEnumarator
811 static HRESULT WINAPI
IAutoCompleteDropDown_fnResetEnumerator(
812 IAutoCompleteDropDown
*iface
)
814 IAutoCompleteImpl
*This
= impl_from_IAutoCompleteDropDown(iface
);
816 FIXME("(%p): stub\n", This
);
821 /**************************************************************************
822 * IAutoCompleteDropDown VTable
824 static const IAutoCompleteDropDownVtbl acdropdownvt
=
826 IAutoCompleteDropDown_fnQueryInterface
,
827 IAutoCompleteDropDown_fnAddRef
,
828 IAutoCompleteDropDown_fnRelease
,
829 IAutoCompleteDropDown_fnGetDropDownStatus
,
830 IAutoCompleteDropDown_fnResetEnumerator
,
833 /**************************************************************************
834 * IAutoComplete_Constructor
836 HRESULT WINAPI
IAutoComplete_Constructor(IUnknown
* pUnkOuter
, REFIID riid
, LPVOID
* ppv
)
838 IAutoCompleteImpl
*lpac
;
841 if (pUnkOuter
&& !IsEqualIID (riid
, &IID_IUnknown
))
842 return CLASS_E_NOAGGREGATION
;
844 lpac
= heap_alloc_zero(sizeof(*lpac
));
846 return E_OUTOFMEMORY
;
849 lpac
->IAutoComplete2_iface
.lpVtbl
= &acvt
;
850 lpac
->IAutoCompleteDropDown_iface
.lpVtbl
= &acdropdownvt
;
851 lpac
->enabled
= TRUE
;
852 lpac
->options
= ACO_AUTOAPPEND
;
854 hr
= IAutoComplete2_QueryInterface(&lpac
->IAutoComplete2_iface
, riid
, ppv
);
855 IAutoComplete2_Release(&lpac
->IAutoComplete2_iface
);
857 TRACE("-- (%p)->\n",lpac
);