Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com --- dlls/shell32/autocomplete.c | 69 +++++++++++++++++++++++++++---------- 1 file changed, 51 insertions(+), 18 deletions(-)
diff --git a/dlls/shell32/autocomplete.c b/dlls/shell32/autocomplete.c index ed8b270..0ad8a9d 100644 --- a/dlls/shell32/autocomplete.c +++ b/dlls/shell32/autocomplete.c @@ -63,8 +63,10 @@ typedef struct WCHAR **enum_strs; HWND hwndEdit; HWND hwndListBox; + HWND hwndListBoxOwner; WNDPROC wpOrigEditProc; WNDPROC wpOrigLBoxProc; + WNDPROC wpOrigLBoxOwnerProc; WCHAR *txtbackup; WCHAR *quickComplete; IEnumString *enumstr; @@ -283,7 +285,7 @@ static void free_enum_strs(IAutoCompleteImpl *ac)
static void hide_listbox(IAutoCompleteImpl *ac, HWND hwnd, BOOL reset) { - ShowWindow(hwnd, SW_HIDE); + ShowWindow(ac->hwndListBoxOwner, SW_HIDE); SendMessageW(hwnd, LB_RESETCONTENT, 0, 0); if (reset) free_enum_strs(ac); } @@ -301,7 +303,7 @@ static void show_listbox(IAutoCompleteImpl *ac) height = SendMessageW(ac->hwndListBox, LB_GETITEMHEIGHT, 0, 0) * min(cnt + 1, 7); width = r.right - r.left;
- SetWindowPos(ac->hwndListBox, HWND_TOP, r.left, r.bottom + 1, width, height, SWP_SHOWWINDOW); + SetWindowPos(ac->hwndListBoxOwner, HWND_TOP, r.left, r.bottom + 1, width, height, SWP_SHOWWINDOW); }
static size_t format_quick_complete(WCHAR *dst, const WCHAR *qc, const WCHAR *str, size_t str_len) @@ -337,7 +339,7 @@ static BOOL select_item_with_return_key(IAutoCompleteImpl *ac, HWND hwnd) if (!(ac->options & ACO_AUTOSUGGEST)) return FALSE;
- if (IsWindowVisible(hwndListBox)) + if (IsWindowVisible(ac->hwndListBoxOwner)) { INT sel = SendMessageW(hwndListBox, LB_GETCURSEL, 0, 0); if (sel >= 0) @@ -611,8 +613,8 @@ static void destroy_autocomplete_object(IAutoCompleteImpl *ac) { ac->hwndEdit = NULL; free_enum_strs(ac); - if (ac->hwndListBox) - DestroyWindow(ac->hwndListBox); + if (ac->hwndListBoxOwner) + DestroyWindow(ac->hwndListBoxOwner); IAutoComplete2_Release(&ac->IAutoComplete2_iface); }
@@ -626,7 +628,7 @@ static LRESULT ACEditSubclassProc_KeyDown(IAutoCompleteImpl *ac, HWND hwnd, UINT { case VK_ESCAPE: /* When pressing ESC, Windows hides the auto-suggest listbox, if visible */ - if ((ac->options & ACO_AUTOSUGGEST) && IsWindowVisible(ac->hwndListBox)) + if ((ac->options & ACO_AUTOSUGGEST) && IsWindowVisible(ac->hwndListBoxOwner)) { hide_listbox(ac, ac->hwndListBox, FALSE); ac->no_fwd_char = 0x1B; /* ESC char */ @@ -665,7 +667,7 @@ static LRESULT ACEditSubclassProc_KeyDown(IAutoCompleteImpl *ac, HWND hwnd, UINT break; case VK_TAB: if ((ac->options & (ACO_AUTOSUGGEST | ACO_USETAB)) == (ACO_AUTOSUGGEST | ACO_USETAB) - && IsWindowVisible(ac->hwndListBox) && !(GetKeyState(VK_CONTROL) & 0x8000)) + && IsWindowVisible(ac->hwndListBoxOwner) && !(GetKeyState(VK_CONTROL) & 0x8000)) { ac->no_fwd_char = '\t'; return change_selection(ac, hwnd, wParam); @@ -683,7 +685,7 @@ static LRESULT ACEditSubclassProc_KeyDown(IAutoCompleteImpl *ac, HWND hwnd, UINT if (!(ac->options & ACO_AUTOSUGGEST)) break;
- if (!IsWindowVisible(ac->hwndListBox)) + if (!IsWindowVisible(ac->hwndListBoxOwner)) { if (ac->options & ACO_UPDOWNKEYDROPSLIST) { @@ -724,7 +726,9 @@ static LRESULT APIENTRY ACEditSubclassProc(HWND hwnd, UINT uMsg, WPARAM wParam, case WM_KILLFOCUS: if (This->options & ACO_AUTOSUGGEST) { - if ((HWND)wParam == This->hwndListBox) break; + if (This->hwndListBoxOwner == (HWND)wParam || + This->hwndListBoxOwner == GetAncestor((HWND)wParam, GA_PARENT)) + break; hide_listbox(This, This->hwndListBox, FALSE); }
@@ -736,7 +740,7 @@ static LRESULT APIENTRY ACEditSubclassProc(HWND hwnd, UINT uMsg, WPARAM wParam, WINDOWPOS *pos = (WINDOWPOS*)lParam;
if ((pos->flags & (SWP_NOMOVE | SWP_NOSIZE)) != (SWP_NOMOVE | SWP_NOSIZE) && - This->hwndListBox && IsWindowVisible(This->hwndListBox)) + This->hwndListBoxOwner && IsWindowVisible(This->hwndListBoxOwner)) show_listbox(This); break; } @@ -771,7 +775,7 @@ static LRESULT APIENTRY ACEditSubclassProc(HWND hwnd, UINT uMsg, WPARAM wParam, ? autoappend_flag_yes : autoappend_flag_no); return ret; case WM_MOUSEWHEEL: - if ((This->options & ACO_AUTOSUGGEST) && IsWindowVisible(This->hwndListBox)) + if ((This->options & ACO_AUTOSUGGEST) && IsWindowVisible(This->hwndListBoxOwner)) return SendMessageW(This->hwndListBox, WM_MOUSEWHEEL, wParam, lParam); break; case WM_SETFONT: @@ -818,27 +822,56 @@ static LRESULT APIENTRY ACLBoxSubclassProc(HWND hwnd, UINT uMsg, WPARAM wParam, return CallWindowProcW(This->wpOrigLBoxProc, hwnd, uMsg, wParam, lParam); }
+static LRESULT APIENTRY ACLBoxOwnerSubclassProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + IAutoCompleteImpl *This = (IAutoCompleteImpl*)GetWindowLongPtrW(hwnd, GWLP_USERDATA); + + switch (uMsg) + { + case WM_SIZE: + SetWindowPos(This->hwndListBox, NULL, 0, 0, LOWORD(lParam), HIWORD(lParam), + SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOZORDER | SWP_DEFERERASE); + break; + } + return CallWindowProcW(This->wpOrigLBoxOwnerProc, hwnd, uMsg, wParam, lParam); +} + static void create_listbox(IAutoCompleteImpl *This) { + This->hwndListBoxOwner = CreateWindowExW(WS_EX_NOPARENTNOTIFY, WC_STATICW, NULL, WS_BORDER | WS_CHILD | WS_CLIPCHILDREN, + 0, 0, 0, 0, This->hwndEdit, NULL, shell32_hInstance, NULL); + if (!This->hwndListBoxOwner) + { + This->options &= ~ACO_AUTOSUGGEST; + return; + } + /* FIXME : The listbox should be resizable with the mouse. WS_THICKFRAME looks ugly */ This->hwndListBox = CreateWindowExW(0, WC_LISTBOXW, NULL, - WS_BORDER | WS_CHILD | WS_VSCROLL | LBS_HASSTRINGS | LBS_NOTIFY | LBS_NOINTEGRALHEIGHT, - 0, 0, 0, 0, GetParent(This->hwndEdit), NULL, shell32_hInstance, NULL); + WS_CHILD | WS_VISIBLE | WS_VSCROLL | LBS_HASSTRINGS | LBS_NOINTEGRALHEIGHT, + 0, 0, 0, 0, This->hwndListBoxOwner, NULL, shell32_hInstance, NULL);
if (This->hwndListBox) { HFONT edit_font;
This->wpOrigLBoxProc = (WNDPROC) SetWindowLongPtrW( This->hwndListBox, GWLP_WNDPROC, (LONG_PTR) ACLBoxSubclassProc); SetWindowLongPtrW( This->hwndListBox, GWLP_USERDATA, (LONG_PTR)This); - SetParent(This->hwndListBox, HWND_DESKTOP); + + This->wpOrigLBoxOwnerProc = (WNDPROC)SetWindowLongPtrW(This->hwndListBoxOwner, GWLP_WNDPROC, (LONG_PTR)ACLBoxOwnerSubclassProc); + SetWindowLongPtrW(This->hwndListBoxOwner, GWLP_USERDATA, (LONG_PTR)This); + + SetParent(This->hwndListBoxOwner, HWND_DESKTOP);
/* Use the same font as the edit control, as it gets destroyed before it anyway */ edit_font = (HFONT)SendMessageW(This->hwndEdit, WM_GETFONT, 0, 0); if (edit_font) SendMessageW(This->hwndListBox, WM_SETFONT, (WPARAM)edit_font, FALSE); + return; } - else - This->options &= ~ACO_AUTOSUGGEST; + + DestroyWindow(This->hwndListBoxOwner); + This->hwndListBoxOwner = NULL; + This->options &= ~ACO_AUTOSUGGEST; }
/************************************************************************** @@ -1146,7 +1179,7 @@ static HRESULT WINAPI IAutoCompleteDropDown_fnGetDropDownStatus(
TRACE("(%p) -> (%p, %p)\n", This, pdwFlags, ppwszString);
- dropped = IsWindowVisible(This->hwndListBox); + dropped = IsWindowVisible(This->hwndListBoxOwner);
if (pdwFlags) *pdwFlags = (dropped ? ACDD_VISIBLE : 0); @@ -1187,7 +1220,7 @@ static HRESULT WINAPI IAutoCompleteDropDown_fnResetEnumerator( if (This->hwndEdit) { free_enum_strs(This); - if ((This->options & ACO_AUTOSUGGEST) && IsWindowVisible(This->hwndListBox)) + if ((This->options & ACO_AUTOSUGGEST) && IsWindowVisible(This->hwndListBoxOwner)) autocomplete_text(This, This->hwndEdit, autoappend_flag_displayempty); } return S_OK;