comctl32/edit: Force update on focus change.
Signed-off-by: Nikolay Sivov <nsivov@codeweavers.com> Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
335f865ed5
commit
dadea2d11d
|
@ -3382,15 +3382,22 @@ static LRESULT EDIT_WM_KeyDown(EDITSTATE *es, INT key)
|
||||||
* WM_KILLFOCUS
|
* WM_KILLFOCUS
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
static LRESULT EDIT_WM_KillFocus(EDITSTATE *es)
|
static LRESULT EDIT_WM_KillFocus(HTHEME theme, EDITSTATE *es)
|
||||||
{
|
{
|
||||||
|
UINT flags = RDW_INVALIDATE | RDW_UPDATENOW;
|
||||||
|
|
||||||
es->flags &= ~EF_FOCUSED;
|
es->flags &= ~EF_FOCUSED;
|
||||||
DestroyCaret();
|
DestroyCaret();
|
||||||
if (!(es->style & ES_NOHIDESEL))
|
if (!(es->style & ES_NOHIDESEL))
|
||||||
EDIT_InvalidateText(es, es->selection_start, es->selection_end);
|
EDIT_InvalidateText(es, es->selection_start, es->selection_end);
|
||||||
EDIT_NOTIFY_PARENT(es, EN_KILLFOCUS);
|
EDIT_NOTIFY_PARENT(es, EN_KILLFOCUS);
|
||||||
/* throw away left over scroll when we lose focus */
|
/* Throw away left over scroll when we lose focus */
|
||||||
es->wheelDeltaRemainder = 0;
|
es->wheelDeltaRemainder = 0;
|
||||||
|
|
||||||
|
if (theme)
|
||||||
|
flags |= RDW_FRAME;
|
||||||
|
|
||||||
|
RedrawWindow(es->hwndSelf, NULL, NULL, flags);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3656,26 +3663,24 @@ static void EDIT_WM_NCPaint(HWND hwnd, HRGN region)
|
||||||
* WM_SETFOCUS
|
* WM_SETFOCUS
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
static void EDIT_WM_SetFocus(EDITSTATE *es)
|
static void EDIT_WM_SetFocus(HTHEME theme, EDITSTATE *es)
|
||||||
{
|
{
|
||||||
|
UINT flags = RDW_INVALIDATE | RDW_UPDATENOW;
|
||||||
|
|
||||||
es->flags |= EF_FOCUSED;
|
es->flags |= EF_FOCUSED;
|
||||||
|
|
||||||
if (!(es->style & ES_NOHIDESEL))
|
if (!(es->style & ES_NOHIDESEL))
|
||||||
EDIT_InvalidateText(es, es->selection_start, es->selection_end);
|
EDIT_InvalidateText(es, es->selection_start, es->selection_end);
|
||||||
|
|
||||||
/* single line edit updates itself */
|
|
||||||
if (IsWindowVisible(es->hwndSelf) && !(es->style & ES_MULTILINE))
|
|
||||||
{
|
|
||||||
HDC hdc = GetDC(es->hwndSelf);
|
|
||||||
EDIT_WM_Paint(es, hdc);
|
|
||||||
ReleaseDC(es->hwndSelf, hdc);
|
|
||||||
}
|
|
||||||
|
|
||||||
CreateCaret(es->hwndSelf, 0, 1, es->line_height);
|
CreateCaret(es->hwndSelf, 0, 1, es->line_height);
|
||||||
EDIT_SetCaretPos(es, es->selection_end,
|
EDIT_SetCaretPos(es, es->selection_end, es->flags & EF_AFTER_WRAP);
|
||||||
es->flags & EF_AFTER_WRAP);
|
|
||||||
ShowCaret(es->hwndSelf);
|
ShowCaret(es->hwndSelf);
|
||||||
EDIT_NOTIFY_PARENT(es, EN_SETFOCUS);
|
EDIT_NOTIFY_PARENT(es, EN_SETFOCUS);
|
||||||
|
|
||||||
|
if (theme)
|
||||||
|
flags |= RDW_FRAME | RDW_ERASE;
|
||||||
|
|
||||||
|
RedrawWindow(es->hwndSelf, NULL, NULL, flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -4827,9 +4832,7 @@ static LRESULT CALLBACK EDIT_WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPAR
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case WM_KILLFOCUS:
|
case WM_KILLFOCUS:
|
||||||
result = EDIT_WM_KillFocus(es);
|
result = EDIT_WM_KillFocus(theme, es);
|
||||||
if (theme)
|
|
||||||
RedrawWindow(hwnd, NULL, NULL, RDW_FRAME | RDW_INVALIDATE | RDW_UPDATENOW);
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case WM_LBUTTONDBLCLK:
|
case WM_LBUTTONDBLCLK:
|
||||||
|
@ -4866,9 +4869,7 @@ static LRESULT CALLBACK EDIT_WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPAR
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case WM_SETFOCUS:
|
case WM_SETFOCUS:
|
||||||
EDIT_WM_SetFocus(es);
|
EDIT_WM_SetFocus(theme, es);
|
||||||
if (theme)
|
|
||||||
RedrawWindow(hwnd, NULL, NULL, RDW_FRAME | RDW_INVALIDATE | RDW_UPDATENOW);
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case WM_SETFONT:
|
case WM_SETFONT:
|
||||||
|
|
|
@ -23,6 +23,7 @@
|
||||||
|
|
||||||
#include "wine/test.h"
|
#include "wine/test.h"
|
||||||
#include "v6util.h"
|
#include "v6util.h"
|
||||||
|
#include "msg.h"
|
||||||
|
|
||||||
#ifndef ES_COMBO
|
#ifndef ES_COMBO
|
||||||
#define ES_COMBO 0x200
|
#define ES_COMBO 0x200
|
||||||
|
@ -32,6 +33,20 @@
|
||||||
#define ID_EDITTEST2 99
|
#define ID_EDITTEST2 99
|
||||||
#define MAXLEN 200
|
#define MAXLEN 200
|
||||||
|
|
||||||
|
enum seq_index
|
||||||
|
{
|
||||||
|
COMBINED_SEQ_INDEX = 0,
|
||||||
|
NUM_MSG_SEQUENCES,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum msg_id
|
||||||
|
{
|
||||||
|
PARENT_ID,
|
||||||
|
EDIT_ID,
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct msg_sequence *sequences[NUM_MSG_SEQUENCES];
|
||||||
|
|
||||||
struct edit_notify {
|
struct edit_notify {
|
||||||
int en_change, en_maxtext, en_update;
|
int en_change, en_maxtext, en_update;
|
||||||
};
|
};
|
||||||
|
@ -865,6 +880,66 @@ static LRESULT CALLBACK edit3_wnd_procA(HWND hWnd, UINT msg, WPARAM wParam, LPAR
|
||||||
return DefWindowProcA(hWnd, msg, wParam, lParam);
|
return DefWindowProcA(hWnd, msg, wParam, lParam);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static LRESULT CALLBACK parent_wnd_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
|
||||||
|
{
|
||||||
|
static LONG defwndproc_counter = 0;
|
||||||
|
struct message msg = { 0 };
|
||||||
|
LRESULT ret;
|
||||||
|
|
||||||
|
msg.message = message;
|
||||||
|
msg.flags = sent|wparam|id;
|
||||||
|
if (defwndproc_counter) msg.flags |= defwinproc;
|
||||||
|
msg.wParam = wParam;
|
||||||
|
msg.id = PARENT_ID;
|
||||||
|
|
||||||
|
if (message != WM_IME_SETCONTEXT &&
|
||||||
|
message != WM_IME_NOTIFY &&
|
||||||
|
message != WM_GETICON &&
|
||||||
|
message != WM_DWMNCRENDERINGCHANGED &&
|
||||||
|
message != WM_GETMINMAXINFO &&
|
||||||
|
message != WM_PAINT &&
|
||||||
|
message != WM_CTLCOLOREDIT &&
|
||||||
|
message < 0xc000)
|
||||||
|
{
|
||||||
|
add_message(sequences, COMBINED_SEQ_INDEX, &msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
defwndproc_counter++;
|
||||||
|
ret = DefWindowProcA(hwnd, message, wParam, lParam);
|
||||||
|
defwndproc_counter--;
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static LRESULT CALLBACK edit_subclass_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
|
||||||
|
{
|
||||||
|
WNDPROC oldproc = (WNDPROC)GetWindowLongPtrA(hwnd, GWLP_USERDATA);
|
||||||
|
static LONG defwndproc_counter = 0;
|
||||||
|
struct message msg = { 0 };
|
||||||
|
LRESULT ret;
|
||||||
|
|
||||||
|
msg.message = message;
|
||||||
|
msg.flags = sent|wparam|id;
|
||||||
|
if (defwndproc_counter) msg.flags |= defwinproc;
|
||||||
|
msg.wParam = wParam;
|
||||||
|
msg.id = EDIT_ID;
|
||||||
|
|
||||||
|
if (message != WM_IME_SETCONTEXT &&
|
||||||
|
message != WM_IME_NOTIFY)
|
||||||
|
{
|
||||||
|
add_message(sequences, COMBINED_SEQ_INDEX, &msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
defwndproc_counter++;
|
||||||
|
if (IsWindowUnicode(hwnd))
|
||||||
|
ret = CallWindowProcW(oldproc, hwnd, message, wParam, lParam);
|
||||||
|
else
|
||||||
|
ret = CallWindowProcA(oldproc, hwnd, message, wParam, lParam);
|
||||||
|
defwndproc_counter--;
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
/* Test behaviour of WM_SETTEXT, WM_REPLACESEL and notifications sent in response
|
/* Test behaviour of WM_SETTEXT, WM_REPLACESEL and notifications sent in response
|
||||||
* to these messages.
|
* to these messages.
|
||||||
*/
|
*/
|
||||||
|
@ -2365,6 +2440,7 @@ static BOOL register_classes(void)
|
||||||
WNDCLASSA test3;
|
WNDCLASSA test3;
|
||||||
WNDCLASSA test4;
|
WNDCLASSA test4;
|
||||||
WNDCLASSA text_position;
|
WNDCLASSA text_position;
|
||||||
|
WNDCLASSA wc;
|
||||||
|
|
||||||
test2.style = 0;
|
test2.style = 0;
|
||||||
test2.lpfnWndProc = ET2_WndProc;
|
test2.lpfnWndProc = ET2_WndProc;
|
||||||
|
@ -2414,6 +2490,12 @@ static BOOL register_classes(void)
|
||||||
text_position.lpfnWndProc = DefWindowProcA;
|
text_position.lpfnWndProc = DefWindowProcA;
|
||||||
if (!RegisterClassA(&text_position)) return FALSE;
|
if (!RegisterClassA(&text_position)) return FALSE;
|
||||||
|
|
||||||
|
memset(&wc, 0, sizeof(wc));
|
||||||
|
wc.lpfnWndProc = parent_wnd_proc;
|
||||||
|
wc.hInstance = GetModuleHandleA(NULL);
|
||||||
|
wc.lpszClassName = "ParentWnd";
|
||||||
|
if (!RegisterClassA(&wc)) return FALSE;
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2958,6 +3040,60 @@ static void test_wordbreak_proc(void)
|
||||||
DestroyWindow(hwnd);
|
DestroyWindow(hwnd);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static const struct message setfocus_combined_seq[] =
|
||||||
|
{
|
||||||
|
{ WM_KILLFOCUS, sent|id, 0, 0, PARENT_ID },
|
||||||
|
{ WM_SETFOCUS, sent|id, 0, 0, EDIT_ID },
|
||||||
|
{ WM_COMMAND, sent|wparam|id, MAKEWPARAM(1, EN_SETFOCUS), 0, PARENT_ID },
|
||||||
|
{ WM_PAINT, sent|id, 0, 0, EDIT_ID },
|
||||||
|
{ WM_NCPAINT, sent|id|defwinproc|optional, 0, 0, EDIT_ID },
|
||||||
|
{ WM_ERASEBKGND, sent|id|defwinproc|optional, 0, 0, EDIT_ID },
|
||||||
|
{ 0 }
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct message killfocus_combined_seq[] =
|
||||||
|
{
|
||||||
|
{ WM_KILLFOCUS, sent|id, 0, 0, EDIT_ID },
|
||||||
|
{ WM_COMMAND, sent|wparam|id, MAKEWPARAM(1, EN_KILLFOCUS), 0, PARENT_ID },
|
||||||
|
{ WM_SETFOCUS, sent|id, 0, 0, PARENT_ID },
|
||||||
|
{ WM_PAINT, sent|id, 0, 0, EDIT_ID },
|
||||||
|
{ WM_NCPAINT, sent|id|defwinproc|optional, 0, 0, EDIT_ID },
|
||||||
|
{ 0 }
|
||||||
|
};
|
||||||
|
|
||||||
|
static void test_change_focus(void)
|
||||||
|
{
|
||||||
|
HWND hwnd, parent_wnd;
|
||||||
|
WNDPROC oldproc;
|
||||||
|
MSG msg;
|
||||||
|
|
||||||
|
parent_wnd = CreateWindowA("ParentWnd", "", WS_OVERLAPPEDWINDOW,
|
||||||
|
0, 0, 200, 200, NULL, NULL, GetModuleHandleA(NULL), NULL);
|
||||||
|
ok(parent_wnd != NULL, "Failed to create control parent.\n");
|
||||||
|
SetWindowPos(parent_wnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOSIZE|SWP_NOMOVE);
|
||||||
|
ShowWindow(parent_wnd, SW_SHOW);
|
||||||
|
|
||||||
|
hwnd = CreateWindowExA(0, WC_EDITA, "Test", WS_CHILD | WS_VISIBLE, 0, 0, 100, 100,
|
||||||
|
parent_wnd, (HMENU)1, GetModuleHandleA(NULL), NULL);
|
||||||
|
ok(hwnd != NULL, "Failed to create Edit control.\n");
|
||||||
|
|
||||||
|
oldproc = (WNDPROC)SetWindowLongPtrA(hwnd, GWLP_WNDPROC, (LONG_PTR)edit_subclass_proc);
|
||||||
|
SetWindowLongPtrA(hwnd, GWLP_USERDATA, (LONG_PTR)oldproc);
|
||||||
|
|
||||||
|
SetFocus(parent_wnd);
|
||||||
|
flush_sequences(sequences, NUM_MSG_SEQUENCES);
|
||||||
|
SetFocus(hwnd);
|
||||||
|
while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) DispatchMessageA(&msg);
|
||||||
|
ok_sequence(sequences, COMBINED_SEQ_INDEX, setfocus_combined_seq, "Set focus", TRUE);
|
||||||
|
|
||||||
|
flush_sequences(sequences, NUM_MSG_SEQUENCES);
|
||||||
|
SetFocus(parent_wnd);
|
||||||
|
while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) DispatchMessageA(&msg);
|
||||||
|
ok_sequence(sequences, COMBINED_SEQ_INDEX, killfocus_combined_seq, "Kill focus", TRUE);
|
||||||
|
|
||||||
|
DestroyWindow(hwnd);
|
||||||
|
}
|
||||||
|
|
||||||
START_TEST(edit)
|
START_TEST(edit)
|
||||||
{
|
{
|
||||||
ULONG_PTR ctx_cookie;
|
ULONG_PTR ctx_cookie;
|
||||||
|
@ -2967,6 +3103,8 @@ START_TEST(edit)
|
||||||
if (!load_v6_module(&ctx_cookie, &hCtx))
|
if (!load_v6_module(&ctx_cookie, &hCtx))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
init_msg_sequences(sequences, NUM_MSG_SEQUENCES);
|
||||||
|
|
||||||
hinst = GetModuleHandleA(NULL);
|
hinst = GetModuleHandleA(NULL);
|
||||||
b = register_classes();
|
b = register_classes();
|
||||||
ok(b, "Failed to register test classes.\n");
|
ok(b, "Failed to register test classes.\n");
|
||||||
|
@ -2999,6 +3137,7 @@ START_TEST(edit)
|
||||||
test_paste();
|
test_paste();
|
||||||
test_EM_GETLINE();
|
test_EM_GETLINE();
|
||||||
test_wordbreak_proc();
|
test_wordbreak_proc();
|
||||||
|
test_change_focus();
|
||||||
|
|
||||||
UnregisterWindowClasses();
|
UnregisterWindowClasses();
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue