Commit dadea2d1 authored by Nikolay Sivov's avatar Nikolay Sivov Committed by Alexandre Julliard

comctl32/edit: Force update on focus change.

parent 335f865e
...@@ -3382,16 +3382,23 @@ static LRESULT EDIT_WM_KeyDown(EDITSTATE *es, INT key) ...@@ -3382,16 +3382,23 @@ 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)
{ {
es->flags &= ~EF_FOCUSED; UINT flags = RDW_INVALIDATE | RDW_UPDATENOW;
DestroyCaret();
if(!(es->style & ES_NOHIDESEL)) es->flags &= ~EF_FOCUSED;
EDIT_InvalidateText(es, es->selection_start, es->selection_end); DestroyCaret();
EDIT_NOTIFY_PARENT(es, EN_KILLFOCUS); if (!(es->style & ES_NOHIDESEL))
/* throw away left over scroll when we lose focus */ EDIT_InvalidateText(es, es->selection_start, es->selection_end);
es->wheelDeltaRemainder = 0; EDIT_NOTIFY_PARENT(es, EN_KILLFOCUS);
return 0; /* Throw away left over scroll when we lose focus */
es->wheelDeltaRemainder = 0;
if (theme)
flags |= RDW_FRAME;
RedrawWindow(es->hwndSelf, NULL, NULL, flags);
return 0;
} }
...@@ -3656,26 +3663,24 @@ static void EDIT_WM_NCPaint(HWND hwnd, HRGN region) ...@@ -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)
{ {
es->flags |= EF_FOCUSED; UINT flags = RDW_INVALIDATE | RDW_UPDATENOW;
if (!(es->style & ES_NOHIDESEL)) es->flags |= EF_FOCUSED;
EDIT_InvalidateText(es, es->selection_start, es->selection_end);
/* single line edit updates itself */ if (!(es->style & ES_NOHIDESEL))
if (IsWindowVisible(es->hwndSelf) && !(es->style & ES_MULTILINE)) EDIT_InvalidateText(es, es->selection_start, es->selection_end);
{
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 ...@@ -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 ...@@ -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 @@ ...@@ -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 @@ ...@@ -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 ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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();
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment