[PATCH v2 5/8] shell32/autocomplete: Send messages directly to the edit control's procedure
Gabriel Ivăncescu
gabrielopcode at gmail.com
Thu Sep 20 06:55:38 CDT 2018
Send the messages directly to the edit control's window procedure to match
Windows behavior and reduce needless overhead. However, it appears that
Windows allows hijacking WM_GETTEXT and WM_GETTEXTLENGTH for autocompletion,
so handle that case separately.
Signed-off-by: Gabriel Ivăncescu <gabrielopcode at gmail.com>
---
See the tests in the series for examples of that.
dlls/shell32/autocomplete.c | 47 ++++++++++++++++++++++++++++++---------------
1 file changed, 31 insertions(+), 16 deletions(-)
diff --git a/dlls/shell32/autocomplete.c b/dlls/shell32/autocomplete.c
index 92afbe2..3326e31 100644
--- a/dlls/shell32/autocomplete.c
+++ b/dlls/shell32/autocomplete.c
@@ -90,6 +90,8 @@ static const WCHAR autocomplete_propertyW[] = {'W','i','n','e',' ','A','u','t','
'c','o','m','p','l','e','t','e',' ',
'c','o','n','t','r','o','l',0};
+static LRESULT APIENTRY ACEditSubclassProc(HWND, UINT, WPARAM, LPARAM);
+
static inline IAutoCompleteImpl *impl_from_IAutoComplete2(IAutoComplete2 *iface)
{
return CONTAINING_RECORD(iface, IAutoCompleteImpl, IAutoComplete2_iface);
@@ -100,6 +102,22 @@ static inline IAutoCompleteImpl *impl_from_IAutoCompleteDropDown(IAutoCompleteDr
return CONTAINING_RECORD(iface, IAutoCompleteImpl, IAutoCompleteDropDown_iface);
}
+static inline WNDPROC get_edit_proc(IAutoCompleteImpl *ac, HWND hwnd)
+{
+ WNDPROC edit_proc = (WNDPROC)GetWindowLongPtrW(hwnd, GWLP_WNDPROC);
+ return (edit_proc == ACEditSubclassProc) ? ac->wpOrigEditProc : edit_proc;
+}
+
+static void set_text_and_selection(IAutoCompleteImpl *ac, HWND hwnd, WCHAR *text, WPARAM start, LPARAM end)
+{
+ /* Send it directly to the edit control to match Windows XP behavior */
+ WNDPROC proc = ac->wpOrigEditProc;
+
+ /* FIXME: send WM_SETREDRAW when the edit control supports it */
+ if (CallWindowProcW(proc, hwnd, WM_SETTEXT, 0, (LPARAM)text))
+ CallWindowProcW(proc, hwnd, EM_SETSEL, start, end);
+}
+
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
@@ -142,8 +160,7 @@ static void autoappend_str(IAutoCompleteImpl *ac, WCHAR *text, UINT len, WCHAR *
}
else tmp = str;
- SendMessageW(hwnd, WM_SETTEXT, 0, (LPARAM)tmp);
- SendMessageW(hwnd, EM_SETSEL, len, size - 1);
+ set_text_and_selection(ac, hwnd, tmp, len, size - 1);
if (tmp != str)
heap_free(tmp);
}
@@ -152,7 +169,8 @@ static void autocomplete_text(IAutoCompleteImpl *ac, HWND hwnd, enum autoappend_
{
HRESULT hr;
WCHAR *text;
- UINT cpt, size, len = SendMessageW(hwnd, WM_GETTEXTLENGTH, 0, 0);
+ WNDPROC edit_proc = get_edit_proc(ac, hwnd);
+ UINT cpt, size, len = CallWindowProcW(edit_proc, hwnd, WM_GETTEXTLENGTH, 0, 0);
if (flag != autoappend_flag_displayempty && len == 0)
{
@@ -164,7 +182,7 @@ static void autocomplete_text(IAutoCompleteImpl *ac, HWND hwnd, enum autoappend_
size = len + 1;
if (!(text = heap_alloc(size * sizeof(WCHAR))))
return;
- len = SendMessageW(hwnd, WM_GETTEXT, size, (LPARAM)text);
+ len = CallWindowProcW(edit_proc, hwnd, WM_GETTEXT, size, (LPARAM)text);
if (len + 1 != size)
text = heap_realloc(text, (len + 1) * sizeof(WCHAR));
@@ -247,17 +265,18 @@ static LRESULT ACEditSubclassProc_KeyDown(IAutoCompleteImpl *ac, HWND hwnd, UINT
{
WCHAR *text, *buf;
size_t sz;
- UINT len = SendMessageW(hwnd, WM_GETTEXTLENGTH, 0, 0);
+ WNDPROC edit_proc = get_edit_proc(ac, hwnd);
+ UINT len = CallWindowProcW(edit_proc, hwnd, WM_GETTEXTLENGTH, 0, 0);
+
if (!(text = heap_alloc((len + 1) * sizeof(WCHAR))))
return 0;
- len = SendMessageW(hwnd, WM_GETTEXT, len + 1, (LPARAM)text);
+ len = CallWindowProcW(edit_proc, hwnd, WM_GETTEXT, len + 1, (LPARAM)text);
sz = strlenW(ac->quickComplete) + 1 + len;
if ((buf = heap_alloc(sz * sizeof(WCHAR))))
{
len = format_quick_complete(buf, ac->quickComplete, text, len);
- SendMessageW(hwnd, WM_SETTEXT, 0, (LPARAM)buf);
- SendMessageW(hwnd, EM_SETSEL, 0, len);
+ set_text_and_selection(ac, hwnd, buf, 0, len);
heap_free(buf);
}
@@ -309,16 +328,13 @@ static LRESULT ACEditSubclassProc_KeyDown(IAutoCompleteImpl *ac, HWND hwnd, UINT
if (!(msg = heap_alloc((len + 1) * sizeof(WCHAR))))
return 0;
len = SendMessageW(ac->hwndListBox, LB_GETTEXT, sel, (LPARAM)msg);
- SendMessageW(hwnd, WM_SETTEXT, 0, (LPARAM)msg);
- SendMessageW(hwnd, EM_SETSEL, len, len);
+ set_text_and_selection(ac, hwnd, msg, len, len);
heap_free(msg);
}
else
{
- UINT len;
- SendMessageW(hwnd, WM_SETTEXT, 0, (LPARAM)ac->txtbackup);
- len = strlenW(ac->txtbackup);
- SendMessageW(hwnd, EM_SETSEL, len, len);
+ UINT len = strlenW(ac->txtbackup);
+ set_text_and_selection(ac, hwnd, ac->txtbackup, len, len);
}
return 0;
}
@@ -409,8 +425,7 @@ static LRESULT APIENTRY ACLBoxSubclassProc(HWND hwnd, UINT uMsg, WPARAM wParam,
if (!(msg = heap_alloc((len + 1) * sizeof(WCHAR))))
break;
len = SendMessageW(hwnd, LB_GETTEXT, sel, (LPARAM)msg);
- SendMessageW(This->hwndEdit, WM_SETTEXT, 0, (LPARAM)msg);
- SendMessageW(This->hwndEdit, EM_SETSEL, 0, len);
+ set_text_and_selection(This, This->hwndEdit, msg, 0, len);
ShowWindow(hwnd, SW_HIDE);
heap_free(msg);
break;
--
1.9.1
More information about the wine-devel
mailing list