Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com ---
v2: Split the owner-drawn patch into two patches.
dlls/shell32/autocomplete.c | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-)
diff --git a/dlls/shell32/autocomplete.c b/dlls/shell32/autocomplete.c index bd9b872..ed8b270 100644 --- a/dlls/shell32/autocomplete.c +++ b/dlls/shell32/autocomplete.c @@ -801,23 +801,21 @@ static LRESULT APIENTRY ACLBoxSubclassProc(HWND hwnd, UINT uMsg, WPARAM wParam, case WM_MOUSEMOVE: sel = SendMessageW(hwnd, LB_ITEMFROMPOINT, 0, lParam); SendMessageW(hwnd, LB_SETCURSEL, sel, 0); - break; + return 0; case WM_LBUTTONDOWN: sel = SendMessageW(hwnd, LB_GETCURSEL, 0, 0); if (sel < 0) - break; + return 0; len = SendMessageW(hwnd, LB_GETTEXTLEN, sel, 0); if (!(msg = heap_alloc((len + 1) * sizeof(WCHAR)))) - break; + return 0; len = SendMessageW(hwnd, LB_GETTEXT, sel, (LPARAM)msg); set_text_and_selection(This, This->hwndEdit, msg, 0, len); hide_listbox(This, hwnd, TRUE); heap_free(msg); - break; - default: - return CallWindowProcW(This->wpOrigLBoxProc, hwnd, uMsg, wParam, lParam); + return 0; } - return 0; + return CallWindowProcW(This->wpOrigLBoxProc, hwnd, uMsg, wParam, lParam); }
static void create_listbox(IAutoCompleteImpl *This)
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;
On Thu, Mar 28, 2019 at 02:24:30PM +0200, Gabriel Ivăncescu wrote:
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com
dlls/shell32/autocomplete.c | 69 +++++++++++++++++++++++++++---------- 1 file changed, 51 insertions(+), 18 deletions(-)
This doesn't look good:
../../../tools/runtest -q -P wine -T ../../.. -M shell32.dll -p shell32_test.exe.so autocomplete && touch autocomplete.ok 0009:fixme:msg:pack_message msg 138 (WM_CTLCOLORSTATIC) not supported yet 0009:err:win:DefWindowProcW called for other process window 0x10020
Huw.
On 4/1/19 10:55 AM, Huw Davies wrote:
On Thu, Mar 28, 2019 at 02:24:30PM +0200, Gabriel Ivăncescu wrote:
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com
dlls/shell32/autocomplete.c | 69 +++++++++++++++++++++++++++---------- 1 file changed, 51 insertions(+), 18 deletions(-)
This doesn't look good:
../../../tools/runtest -q -P wine -T ../../.. -M shell32.dll -p shell32_test.exe.so autocomplete && touch autocomplete.ok 0009:fixme:msg:pack_message msg 138 (WM_CTLCOLORSTATIC) not supported yet 0009:err:win:DefWindowProcW called for other process window 0x10020
Huw.
Sorry, I'm not sure what causes that, it doesn't show up here or on the testbot. Is there a chance it's a one-off error, or is it consistent on your setup? I'll try to investigate it more regardless.
Thanks.
On Mon, Apr 01, 2019 at 02:14:18PM +0300, Gabriel Ivăncescu wrote:
On 4/1/19 10:55 AM, Huw Davies wrote:
On Thu, Mar 28, 2019 at 02:24:30PM +0200, Gabriel Ivăncescu wrote:
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com
dlls/shell32/autocomplete.c | 69 +++++++++++++++++++++++++++---------- 1 file changed, 51 insertions(+), 18 deletions(-)
This doesn't look good:
../../../tools/runtest -q -P wine -T ../../.. -M shell32.dll -p shell32_test.exe.so autocomplete && touch autocomplete.ok 0009:fixme:msg:pack_message msg 138 (WM_CTLCOLORSTATIC) not supported yet 0009:err:win:DefWindowProcW called for other process window 0x10020
Huw.
Sorry, I'm not sure what causes that, it doesn't show up here or on the testbot. Is there a chance it's a one-off error, or is it consistent on your setup? I'll try to investigate it more regardless.
Yes, this is consistent for me, at least on macOS. It's because you set the parent of the static window to be the desktop window.
Huw.
On 4/1/19 3:22 PM, Huw Davies wrote:
On Mon, Apr 01, 2019 at 02:14:18PM +0300, Gabriel Ivăncescu wrote:
On 4/1/19 10:55 AM, Huw Davies wrote:
On Thu, Mar 28, 2019 at 02:24:30PM +0200, Gabriel Ivăncescu wrote:
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com
dlls/shell32/autocomplete.c | 69 +++++++++++++++++++++++++++---------- 1 file changed, 51 insertions(+), 18 deletions(-)
This doesn't look good:
../../../tools/runtest -q -P wine -T ../../.. -M shell32.dll -p shell32_test.exe.so autocomplete && touch autocomplete.ok 0009:fixme:msg:pack_message msg 138 (WM_CTLCOLORSTATIC) not supported yet 0009:err:win:DefWindowProcW called for other process window 0x10020
Huw.
Sorry, I'm not sure what causes that, it doesn't show up here or on the testbot. Is there a chance it's a one-off error, or is it consistent on your setup? I'll try to investigate it more regardless.
Yes, this is consistent for me, at least on macOS. It's because you set the parent of the static window to be the desktop window.
Huw.
Ah I see, thanks. I guess it's time to finally use a proper WS_POPUP window instead of the WS_CHILD hack (which was there from the beginning)? Or should I find another way?
On Mon, Apr 01, 2019 at 03:24:40PM +0300, Gabriel Ivăncescu wrote:
On 4/1/19 3:22 PM, Huw Davies wrote:
On Mon, Apr 01, 2019 at 02:14:18PM +0300, Gabriel Ivăncescu wrote:
On 4/1/19 10:55 AM, Huw Davies wrote:
On Thu, Mar 28, 2019 at 02:24:30PM +0200, Gabriel Ivăncescu wrote:
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com
dlls/shell32/autocomplete.c | 69 +++++++++++++++++++++++++++---------- 1 file changed, 51 insertions(+), 18 deletions(-)
This doesn't look good:
../../../tools/runtest -q -P wine -T ../../.. -M shell32.dll -p shell32_test.exe.so autocomplete && touch autocomplete.ok 0009:fixme:msg:pack_message msg 138 (WM_CTLCOLORSTATIC) not supported yet 0009:err:win:DefWindowProcW called for other process window 0x10020
Huw.
Sorry, I'm not sure what causes that, it doesn't show up here or on the testbot. Is there a chance it's a one-off error, or is it consistent on your setup? I'll try to investigate it more regardless.
Yes, this is consistent for me, at least on macOS. It's because you set the parent of the static window to be the desktop window.
Huw.
Ah I see, thanks. I guess it's time to finally use a proper WS_POPUP window instead of the WS_CHILD hack (which was there from the beginning)? Or should I find another way?
Yes, I don't see why it needs to be a child window.
Huw.
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com --- dlls/shell32/autocomplete.c | 72 ++++++++++++++++++++++++++++++++++--- 1 file changed, 68 insertions(+), 4 deletions(-)
diff --git a/dlls/shell32/autocomplete.c b/dlls/shell32/autocomplete.c index 0ad8a9d..1a88a1d 100644 --- a/dlls/shell32/autocomplete.c +++ b/dlls/shell32/autocomplete.c @@ -61,6 +61,7 @@ typedef struct BOOL enabled; UINT enum_strs_num; WCHAR **enum_strs; + WCHAR **listbox_strs; HWND hwndEdit; HWND hwndListBox; HWND hwndListBoxOwner; @@ -296,7 +297,6 @@ static void show_listbox(IAutoCompleteImpl *ac) UINT cnt, width, height;
GetWindowRect(ac->hwndEdit, &r); - SendMessageW(ac->hwndListBox, LB_CARETOFF, 0, 0);
/* Windows XP displays 7 lines at most, then it uses a scroll bar */ cnt = SendMessageW(ac->hwndListBox, LB_GETCOUNT, 0, 0); @@ -306,6 +306,60 @@ static void show_listbox(IAutoCompleteImpl *ac) SetWindowPos(ac->hwndListBoxOwner, HWND_TOP, r.left, r.bottom + 1, width, height, SWP_SHOWWINDOW); }
+static void set_listbox_font(IAutoCompleteImpl *ac, HFONT font) +{ + /* We have to calculate the item height manually due to owner-drawn */ + HFONT old_font = NULL; + UINT height = 16; + HDC hdc; + + if ((hdc = GetDCEx(ac->hwndListBox, 0, DCX_CACHE))) + { + TEXTMETRICW metrics; + if (font) old_font = SelectObject(hdc, font); + if (GetTextMetricsW(hdc, &metrics)) + height = metrics.tmHeight; + if (old_font) SelectObject(hdc, old_font); + ReleaseDC(ac->hwndListBox, hdc); + } + SendMessageW(ac->hwndListBox, WM_SETFONT, (WPARAM)font, FALSE); + SendMessageW(ac->hwndListBox, LB_SETITEMHEIGHT, 0, height); +} + +static BOOL draw_listbox_item(IAutoCompleteImpl *ac, DRAWITEMSTRUCT *info, UINT id) +{ + COLORREF old_text, old_bk; + HDC hdc = info->hDC; + UINT state; + WCHAR *str; + + if (info->CtlType != ODT_LISTBOX || info->CtlID != id || + id != (UINT)GetWindowLongPtrW(ac->hwndListBox, GWLP_ID)) + return FALSE; + + if ((INT)info->itemID < 0 || info->itemAction == ODA_FOCUS) + return TRUE; + + state = info->itemState; + if (state & ODS_SELECTED) + { + old_bk = SetBkColor(hdc, GetSysColor(COLOR_HIGHLIGHT)); + old_text = SetTextColor(hdc, GetSysColor(COLOR_HIGHLIGHTTEXT)); + } + + str = ac->listbox_strs[info->itemID]; + ExtTextOutW(hdc, info->rcItem.left + 1, info->rcItem.top, + ETO_OPAQUE | ETO_CLIPPED, &info->rcItem, str, + strlenW(str), NULL); + + if (state & ODS_SELECTED) + { + SetBkColor(hdc, old_bk); + SetTextColor(hdc, old_text); + } + return TRUE; +} + static size_t format_quick_complete(WCHAR *dst, const WCHAR *qc, const WCHAR *str, size_t str_len) { /* Replace the first %s directly without using snprintf, to avoid @@ -540,6 +594,8 @@ static BOOL display_matching_strs(IAutoCompleteImpl *ac, WCHAR *text, UINT len,
SendMessageW(ac->hwndListBox, WM_SETREDRAW, FALSE, 0); SendMessageW(ac->hwndListBox, LB_RESETCONTENT, 0, 0); + + ac->listbox_strs = str + start; SendMessageW(ac->hwndListBox, LB_INITSTORAGE, end - start, 0); for (; start < end; start++) SendMessageW(ac->hwndListBox, LB_INSERTSTRING, -1, (LPARAM)str[start]); @@ -581,7 +637,11 @@ static void autocomplete_text(IAutoCompleteImpl *ac, HWND hwnd, enum autoappend_
size = len + 1; if (!(text = heap_alloc(size * sizeof(WCHAR)))) + { + /* Reset the listbox to prevent potential crash from ResetEnumerator */ + SendMessageW(ac->hwndListBox, LB_RESETCONTENT, 0, 0); return; + } len = SendMessageW(hwnd, WM_GETTEXT, size, (LPARAM)text); if (len + 1 != size) text = heap_realloc(text, (len + 1) * sizeof(WCHAR)); @@ -780,7 +840,7 @@ static LRESULT APIENTRY ACEditSubclassProc(HWND hwnd, UINT uMsg, WPARAM wParam, break; case WM_SETFONT: if (This->hwndListBox) - SendMessageW(This->hwndListBox, WM_SETFONT, wParam, lParam); + set_listbox_font(This, (HFONT)wParam); break; case WM_DESTROY: { @@ -828,6 +888,10 @@ static LRESULT APIENTRY ACLBoxOwnerSubclassProc(HWND hwnd, UINT uMsg, WPARAM wPa
switch (uMsg) { + case WM_DRAWITEM: + if (draw_listbox_item(This, (DRAWITEMSTRUCT*)lParam, wParam)) + return TRUE; + break; case WM_SIZE: SetWindowPos(This->hwndListBox, NULL, 0, 0, LOWORD(lParam), HIWORD(lParam), SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOZORDER | SWP_DEFERERASE); @@ -848,7 +912,7 @@ static void create_listbox(IAutoCompleteImpl *This)
/* FIXME : The listbox should be resizable with the mouse. WS_THICKFRAME looks ugly */ This->hwndListBox = CreateWindowExW(0, WC_LISTBOXW, NULL, - WS_CHILD | WS_VISIBLE | WS_VSCROLL | LBS_HASSTRINGS | LBS_NOINTEGRALHEIGHT, + WS_CHILD | WS_VISIBLE | WS_VSCROLL | LBS_HASSTRINGS | LBS_OWNERDRAWFIXED | LBS_NOINTEGRALHEIGHT, 0, 0, 0, 0, This->hwndListBoxOwner, NULL, shell32_hInstance, NULL);
if (This->hwndListBox) { @@ -865,7 +929,7 @@ static void create_listbox(IAutoCompleteImpl *This) /* 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); + set_listbox_font(This, edit_font); return; }
This eliminates the overhead of populating the listbox completely and simplifies the code.
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com --- dlls/shell32/autocomplete.c | 63 ++++++++++++++----------------------- 1 file changed, 23 insertions(+), 40 deletions(-)
diff --git a/dlls/shell32/autocomplete.c b/dlls/shell32/autocomplete.c index 1a88a1d..0acdaa6 100644 --- a/dlls/shell32/autocomplete.c +++ b/dlls/shell32/autocomplete.c @@ -398,16 +398,11 @@ static BOOL select_item_with_return_key(IAutoCompleteImpl *ac, HWND hwnd) INT sel = SendMessageW(hwndListBox, LB_GETCURSEL, 0, 0); if (sel >= 0) { - UINT len = SendMessageW(hwndListBox, LB_GETTEXTLEN, sel, 0); - if ((text = heap_alloc((len + 1) * sizeof(WCHAR)))) - { - len = SendMessageW(hwndListBox, LB_GETTEXT, sel, (LPARAM)text); - set_text_and_selection(ac, hwnd, text, 0, len); - hide_listbox(ac, hwndListBox, TRUE); - ac->no_fwd_char = '\r'; /* RETURN char */ - heap_free(text); - return TRUE; - } + text = ac->listbox_strs[sel]; + set_text_and_selection(ac, hwnd, text, 0, strlenW(text)); + hide_listbox(ac, hwndListBox, TRUE); + ac->no_fwd_char = '\r'; /* RETURN char */ + return TRUE; } } hide_listbox(ac, hwndListBox, TRUE); @@ -416,6 +411,9 @@ static BOOL select_item_with_return_key(IAutoCompleteImpl *ac, HWND hwnd)
static LRESULT change_selection(IAutoCompleteImpl *ac, HWND hwnd, UINT key) { + WCHAR *msg; + UINT len; + INT count = SendMessageW(ac->hwndListBox, LB_GETCOUNT, 0, 0); INT sel = SendMessageW(ac->hwndListBox, LB_GETCURSEL, 0, 0); if (key == VK_PRIOR || key == VK_NEXT) @@ -456,21 +454,11 @@ static LRESULT change_selection(IAutoCompleteImpl *ac, HWND hwnd, UINT key) sel = ((sel + 1) >= count) ? -1 : sel + 1;
SendMessageW(ac->hwndListBox, LB_SETCURSEL, sel, 0); - if (sel >= 0) - { - WCHAR *msg; - UINT len = SendMessageW(ac->hwndListBox, LB_GETTEXTLEN, sel, 0); - if (!(msg = heap_alloc((len + 1) * sizeof(WCHAR)))) - return 0; - len = SendMessageW(ac->hwndListBox, LB_GETTEXT, sel, (LPARAM)msg); - set_text_and_selection(ac, hwnd, msg, len, len); - heap_free(msg); - } - else - { - UINT len = strlenW(ac->txtbackup); - set_text_and_selection(ac, hwnd, ac->txtbackup, len, len); - } + + msg = (sel >= 0) ? ac->listbox_strs[sel] : ac->txtbackup; + len = strlenW(msg); + set_text_and_selection(ac, hwnd, msg, len, len); + return 0; }
@@ -596,9 +584,7 @@ static BOOL display_matching_strs(IAutoCompleteImpl *ac, WCHAR *text, UINT len, SendMessageW(ac->hwndListBox, LB_RESETCONTENT, 0, 0);
ac->listbox_strs = str + start; - SendMessageW(ac->hwndListBox, LB_INITSTORAGE, end - start, 0); - for (; start < end; start++) - SendMessageW(ac->hwndListBox, LB_INSERTSTRING, -1, (LPARAM)str[start]); + SendMessageW(ac->hwndListBox, LB_SETCOUNT, end - start, 0);
show_listbox(ac); SendMessageW(ac->hwndListBox, WM_SETREDRAW, TRUE, 0); @@ -859,7 +845,7 @@ static LRESULT APIENTRY ACLBoxSubclassProc(HWND hwnd, UINT uMsg, WPARAM wParam, { IAutoCompleteImpl *This = (IAutoCompleteImpl *)GetWindowLongPtrW(hwnd, GWLP_USERDATA); WCHAR *msg; - int sel, len; + INT sel;
switch (uMsg) { case WM_MOUSEMOVE: @@ -870,13 +856,9 @@ static LRESULT APIENTRY ACLBoxSubclassProc(HWND hwnd, UINT uMsg, WPARAM wParam, sel = SendMessageW(hwnd, LB_GETCURSEL, 0, 0); if (sel < 0) return 0; - len = SendMessageW(hwnd, LB_GETTEXTLEN, sel, 0); - if (!(msg = heap_alloc((len + 1) * sizeof(WCHAR)))) - return 0; - len = SendMessageW(hwnd, LB_GETTEXT, sel, (LPARAM)msg); - set_text_and_selection(This, This->hwndEdit, msg, 0, len); + msg = This->listbox_strs[sel]; + set_text_and_selection(This, This->hwndEdit, msg, 0, strlenW(msg)); hide_listbox(This, hwnd, TRUE); - heap_free(msg); return 0; } return CallWindowProcW(This->wpOrigLBoxProc, hwnd, uMsg, wParam, lParam); @@ -912,7 +894,7 @@ static void create_listbox(IAutoCompleteImpl *This)
/* FIXME : The listbox should be resizable with the mouse. WS_THICKFRAME looks ugly */ This->hwndListBox = CreateWindowExW(0, WC_LISTBOXW, NULL, - WS_CHILD | WS_VISIBLE | WS_VSCROLL | LBS_HASSTRINGS | LBS_OWNERDRAWFIXED | LBS_NOINTEGRALHEIGHT, + WS_CHILD | WS_VISIBLE | WS_VSCROLL | LBS_NODATA | LBS_OWNERDRAWFIXED | LBS_NOINTEGRALHEIGHT, 0, 0, 0, 0, This->hwndListBoxOwner, NULL, shell32_hInstance, NULL);
if (This->hwndListBox) { @@ -1255,11 +1237,12 @@ static HRESULT WINAPI IAutoCompleteDropDown_fnGetDropDownStatus( sel = SendMessageW(This->hwndListBox, LB_GETCURSEL, 0, 0); if (sel >= 0) { - DWORD len; + WCHAR *str = This->listbox_strs[sel]; + size_t size = (strlenW(str) + 1) * sizeof(*str);
- len = SendMessageW(This->hwndListBox, LB_GETTEXTLEN, sel, 0); - *ppwszString = CoTaskMemAlloc((len+1)*sizeof(WCHAR)); - SendMessageW(This->hwndListBox, LB_GETTEXT, sel, (LPARAM)*ppwszString); + if (!(*ppwszString = CoTaskMemAlloc(size))) + return E_OUTOFMEMORY; + memcpy(*ppwszString, str, size); } else *ppwszString = NULL;
Hi,
While running your changed tests, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check?
Full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=50084
Your paranoid android.
=== debian9 (32 bit report) ===
shell32: progman_dde.c:249: Test failed: expected DMLERR_NO_ERROR, got 16393 progman_dde.c:250: Test failed: directory should not exist