>From 2514beda29a681fdc07910a456e39f19edb43f21 Mon Sep 17 00:00:00 2001 From: Sergey Khodych Date: Sat, 5 Sep 2009 22:24:54 +0300 Subject: riched20: Implement handling of WM_KEYDOWN VK_RETURN in a dialog mode. --- dlls/riched20/editor.c | 30 +++++- dlls/riched20/editor.h | 2 +- dlls/riched20/editstr.h | 2 + dlls/riched20/tests/editor.c | 271 ++++++++++++++++++++++++++++++++++++++++++ dlls/riched20/txthost.c | 4 +- 5 files changed, 305 insertions(+), 4 deletions(-) diff --git a/dlls/riched20/editor.c b/dlls/riched20/editor.c index 4726d4e..f611c0b 100644 --- a/dlls/riched20/editor.c +++ b/dlls/riched20/editor.c @@ -2145,6 +2145,28 @@ ME_KeyDown(ME_TextEditor *editor, WORD nKey) ME_SendRequestResize(editor, FALSE); return TRUE; case VK_RETURN: + if (editor->bDialogMode) + { + if (ctrl_is_down) + return TRUE; + + if (!(editor->styleFlags & ES_WANTRETURN)) + { + DWORD dw; + dw = SendMessageW(editor->hwndParent, DM_GETDEFID, 0, 0); + if (HIWORD(dw) == DC_HASDEFID) + { + HWND hwDefCtrl = GetDlgItem(editor->hwndParent, LOWORD(dw)); + if (hwDefCtrl) + { + SendMessageW(editor->hwndParent, WM_NEXTDLGCTL, (WPARAM)hwDefCtrl, (LPARAM)TRUE); + PostMessageW(hwDefCtrl, WM_KEYDOWN, VK_RETURN, 0); + } + } + return TRUE; + } + } + if (editor->styleFlags & ES_MULTILINE) { ME_Cursor cursor = editor->pCursors[0]; @@ -2612,6 +2634,7 @@ ME_TextEditor *ME_MakeEditor(ITextHost *texthost, BOOL bEmulateVersion10) LONG selbarwidth; ed->hWnd = NULL; + ed->hwndParent = NULL; ed->texthost = texthost; ed->bEmulateVersion10 = bEmulateVersion10; ITextHost_TxGetPropertyBits(texthost, @@ -2664,6 +2687,7 @@ ME_TextEditor *ME_MakeEditor(ITextHost *texthost, BOOL bEmulateVersion10) ed->mode |= (props & TXTBIT_RICHTEXT) ? TM_RICHTEXT : TM_PLAINTEXT; ed->AutoURLDetect_bEnable = FALSE; ed->bHaveFocus = FALSE; + ed->bDialogMode = FALSE; ed->bMouseCaptured = FALSE; for (i=0; ibDialogMode = TRUE; if (editor->styleFlags & ES_MULTILINE) code |= DLGC_WANTMESSAGE; return code; @@ -4371,7 +4397,7 @@ static LRESULT RichEditWndProc_common(HWND hWnd, UINT msg, WPARAM wParam, ITextHost *texthost; TRACE("WM_NCCREATE: hWnd %p style 0x%08x\n", hWnd, pcs->style); - texthost = ME_CreateTextHost(hWnd, FALSE); + texthost = ME_CreateTextHost(hWnd, pcs->hwndParent, FALSE); return texthost != NULL; } else if (msg != WM_NCDESTROY) @@ -4501,7 +4527,7 @@ LRESULT WINAPI RichEdit10ANSIWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM CREATESTRUCTW *pcs = (CREATESTRUCTW *)lParam; TRACE("WM_NCCREATE: hWnd %p style 0x%08x\n", hWnd, pcs->style); - texthost = ME_CreateTextHost(hWnd, TRUE); + texthost = ME_CreateTextHost(hWnd, pcs->hwndParent, TRUE); return texthost != NULL; } return RichEditANSIWndProc(hWnd, msg, wParam, lParam); diff --git a/dlls/riched20/editor.h b/dlls/riched20/editor.h index 7edd86f..7e583bc 100644 --- a/dlls/riched20/editor.h +++ b/dlls/riched20/editor.h @@ -271,7 +271,7 @@ struct RTFTable *ME_MakeTableDef(ME_TextEditor *editor); void ME_InitTableDef(ME_TextEditor *editor, struct RTFTable *tableDef); /* txthost.c */ -ITextHost *ME_CreateTextHost(HWND hwnd, BOOL bEmulateVersion10); +ITextHost *ME_CreateTextHost(HWND hwnd, HWND hwndParent, BOOL bEmulateVersion10); #ifdef __i386__ /* Use wrappers to perform thiscall on i386 */ #define TXTHOST_VTABLE(This) (&itextHostStdcallVtbl) #else /* __i386__ */ diff --git a/dlls/riched20/editstr.h b/dlls/riched20/editstr.h index c3f59b9..c526468 100644 --- a/dlls/riched20/editstr.h +++ b/dlls/riched20/editstr.h @@ -327,6 +327,7 @@ typedef struct tagME_FontCacheItem typedef struct tagME_TextEditor { HWND hWnd; + HWND hwndParent; ITextHost *texthost; BOOL bEmulateVersion10; ME_TextBuffer *pBuffer; @@ -370,6 +371,7 @@ typedef struct tagME_TextEditor BOOL AutoURLDetect_bEnable; WCHAR cPasswordMask; BOOL bHaveFocus; + BOOL bDialogMode; /* Indicates that we are inside a dialog window */ /*for IME */ int imeStartIndex; DWORD selofs; /* The size of the selection bar on the left side of control */ diff --git a/dlls/riched20/tests/editor.c b/dlls/riched20/tests/editor.c index ce164b3..333dd4f 100644 --- a/dlls/riched20/tests/editor.c +++ b/dlls/riched20/tests/editor.c @@ -33,6 +33,8 @@ #include #include +#define ID_RICHEDITTESTDBUTTON 0x123 + static CHAR string1[MAX_PATH], string2[MAX_PATH], string3[MAX_PATH]; #define ok_w3(format, szString1, szString2, szString3) \ @@ -6673,6 +6675,274 @@ static void test_zoom(void) DestroyWindow(hwnd); } +struct dialog_mode_messages +{ + int wm_getdefid, wm_close, wm_nextdlgctl; +}; + +static struct dialog_mode_messages dm_messages; + +#define test_dm_messages(wmclose, wmgetdefid, wmnextdlgctl) \ + ok(dm_messages.wm_close == wmclose, "expected %d WM_CLOSE message, " \ + "got %d\n", wmclose, dm_messages.wm_close); \ + ok(dm_messages.wm_getdefid == wmgetdefid, "expected %d WM_GETDIFID message, " \ + "got %d\n", wmgetdefid, dm_messages.wm_getdefid);\ + ok(dm_messages.wm_nextdlgctl == wmnextdlgctl, "expected %d WM_NEXTDLGCTL message, " \ + "got %d\n", wmnextdlgctl, dm_messages.wm_nextdlgctl) + +static LRESULT CALLBACK dialog_mode_wnd_proc(HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam) +{ + switch (iMsg) + { + case DM_GETDEFID: + dm_messages.wm_getdefid++; + return MAKELONG(ID_RICHEDITTESTDBUTTON, DC_HASDEFID); + case WM_NEXTDLGCTL: + dm_messages.wm_nextdlgctl++; + break; + case WM_CLOSE: + dm_messages.wm_close++; + break; + } + + return DefWindowProc(hwnd, iMsg, wParam, lParam); +} + +static void test_dialogmode(void) +{ + HWND hwRichEdit, hwParent, hwButton; + MSG msg= {0}; + int lcount, r; + WNDCLASSA cls; + + cls.style = 0; + cls.lpfnWndProc = dialog_mode_wnd_proc; + cls.cbClsExtra = 0; + cls.cbWndExtra = 0; + cls.hInstance = GetModuleHandleA(0); + cls.hIcon = 0; + cls.hCursor = LoadCursorA(0, IDC_ARROW); + cls.hbrBackground = GetStockObject(WHITE_BRUSH); + cls.lpszMenuName = NULL; + cls.lpszClassName = "DialogModeParentClass"; + if(!RegisterClassA(&cls)) assert(0); + + hwParent = CreateWindow("DialogModeParentClass", NULL, WS_OVERLAPPEDWINDOW, + CW_USEDEFAULT, 0, 200, 120, NULL, NULL, GetModuleHandleA(0), NULL); + + /* Test richedit(ES_MULTILINE) */ + + hwRichEdit = new_window(RICHEDIT_CLASS, ES_MULTILINE, hwParent); + + r = SendMessage(hwRichEdit, WM_KEYDOWN, VK_RETURN, 0x1c0001); + ok(0 == r, "expected 0, got %d\n", r); + lcount = SendMessage(hwRichEdit, EM_GETLINECOUNT, 0, 0); + ok(2 == lcount, "expected 2, got %d\n", lcount); + + r = SendMessage(hwRichEdit, WM_GETDLGCODE, 0, 0); + ok(0x8f == r, "expected 0x8f, got 0x%x\n", r); + + r = SendMessage(hwRichEdit, WM_KEYDOWN, VK_RETURN, 0x1c0001); + ok(0 == r, "expected 0, got %d\n", r); + lcount = SendMessage(hwRichEdit, EM_GETLINECOUNT, 0, 0); + ok(3 == lcount, "expected 3, got %d\n", lcount); + + r = SendMessage(hwRichEdit, WM_GETDLGCODE, 0, (LPARAM)&msg); + ok(0x8f == r, "expected 0x8f, got 0x%x\n", r); + r = SendMessage(hwRichEdit, WM_KEYDOWN, VK_RETURN, 0x1c0001); + ok(0 == r, "expected 0, got %d\n", r); + lcount = SendMessage(hwRichEdit, EM_GETLINECOUNT, 0, 0); + ok(3 == lcount, "expected 3, got %d\n", lcount); + + DestroyWindow(hwRichEdit); + + /* Test standalone richedit(ES_MULTILINE) */ + + hwRichEdit = new_window(RICHEDIT_CLASS, ES_MULTILINE, NULL); + + r = SendMessage(hwRichEdit, WM_KEYDOWN, VK_RETURN, 0x1c0001); + ok(0 == r, "expected 0, got %d\n", r); + lcount = SendMessage(hwRichEdit, EM_GETLINECOUNT, 0, 0); + ok(2 == lcount, "expected 2, got %d\n", lcount); + + r = SendMessage(hwRichEdit, WM_GETDLGCODE, 0, (LPARAM)&msg); + ok(0x8f == r, "expected 0x8f, got 0x%x\n", r); + + r = SendMessage(hwRichEdit, WM_KEYDOWN, VK_RETURN, 0x1c0001); + ok(0 == r, "expected 0, got %d\n", r); + lcount = SendMessage(hwRichEdit, EM_GETLINECOUNT, 0, 0); + ok(2 == lcount, "expected 2, got %d\n", lcount); + + DestroyWindow(hwRichEdit); + + /* Check a destination for messages */ + + hwRichEdit = new_window(RICHEDIT_CLASS, ES_MULTILINE, hwParent); + + SetWindowLong(hwRichEdit, GWL_STYLE, GetWindowLong(hwRichEdit, GWL_STYLE)& ~WS_POPUP); + SetParent( hwRichEdit, NULL); + + r = SendMessage(hwRichEdit, WM_GETDLGCODE, 0, (LPARAM)&msg); + ok(0x8f == r, "expected 0x8f, got 0x%x\n", r); + + memset(&dm_messages, 0, sizeof(dm_messages)); + r = SendMessage(hwRichEdit, WM_KEYDOWN, VK_RETURN, 0x1c0001); + ok(0 == r, "expected 0, got %d\n", r); + test_dm_messages(0, 1, 0); + memset(&dm_messages, 0, sizeof(dm_messages)); + + DestroyWindow(hwRichEdit); + + /* Check messages from richedit(ES_MULTILINE) */ + + hwRichEdit = new_window(RICHEDIT_CLASS, ES_MULTILINE, hwParent); + + memset(&dm_messages, 0, sizeof(dm_messages)); + r = SendMessage(hwRichEdit, WM_KEYDOWN, VK_RETURN, 0x1c0001); + ok(0 == r, "expected 0, got %d\n", r); + test_dm_messages(0, 0, 0); + memset(&dm_messages, 0, sizeof(dm_messages)); + + lcount = SendMessage(hwRichEdit, EM_GETLINECOUNT, 0, 0); + ok(2 == lcount, "expected 2, got %d\n", lcount); + + r = SendMessage(hwRichEdit, WM_GETDLGCODE, 0, (LPARAM)&msg); + ok(0x8f == r, "expected 0x8f, got 0x%x\n", r); + test_dm_messages(0, 0, 0); + memset(&dm_messages, 0, sizeof(dm_messages)); + + r = SendMessage(hwRichEdit, WM_KEYDOWN, VK_RETURN, 0x1c0001); + ok(0 == r, "expected 0, got %d\n", r); + test_dm_messages(0, 1, 0); + memset(&dm_messages, 0, sizeof(dm_messages)); + + lcount = SendMessage(hwRichEdit, EM_GETLINECOUNT, 0, 0); + ok(2 == lcount, "expected 2, got %d\n", lcount); + + hwButton = CreateWindow("BUTTON", "OK", WS_VISIBLE|WS_CHILD|BS_PUSHBUTTON, + 100, 100, 50, 20, hwParent, (HMENU)ID_RICHEDITTESTDBUTTON, GetModuleHandleA(0), NULL); + ok(hwButton!=NULL, "CreateWindow failed with error code %d\n", GetLastError()); + + memset(&dm_messages, 0, sizeof(dm_messages)); + r = SendMessage(hwRichEdit, WM_KEYDOWN, VK_RETURN, 0x1c0001); + ok(0 == r, "expected 0, got %d\n", r); + test_dm_messages(0, 1, 1); + memset(&dm_messages, 0, sizeof(dm_messages)); + + lcount = SendMessage(hwRichEdit, EM_GETLINECOUNT, 0, 0); + ok(2 == lcount, "expected 2, got %d\n", lcount); + + DestroyWindow(hwButton); + DestroyWindow(hwRichEdit); + + /* Check messages from richedit(ES_MULTILINE|ES_WANTRETURN) */ + + hwRichEdit = new_window(RICHEDIT_CLASS, ES_MULTILINE|ES_WANTRETURN, hwParent); + + memset(&dm_messages, 0, sizeof(dm_messages)); + r = SendMessage(hwRichEdit, WM_KEYDOWN, VK_RETURN, 0x1c0001); + ok(0 == r, "expected 0, got %d\n", r); + test_dm_messages(0, 0, 0); + memset(&dm_messages, 0, sizeof(dm_messages)); + + lcount = SendMessage(hwRichEdit, EM_GETLINECOUNT, 0, 0); + ok(2 == lcount, "expected 2, got %d\n", lcount); + + r = SendMessage(hwRichEdit, WM_GETDLGCODE, 0, (LPARAM)&msg); + ok(0x8f == r, "expected 0x8f, got 0x%x\n", r); + test_dm_messages(0, 0, 0); + memset(&dm_messages, 0, sizeof(dm_messages)); + + r = SendMessage(hwRichEdit, WM_KEYDOWN, VK_RETURN, 0x1c0001); + ok(0 == r, "expected 0, got %d\n", r); + test_dm_messages(0, 0, 0); + memset(&dm_messages, 0, sizeof(dm_messages)); + + lcount = SendMessage(hwRichEdit, EM_GETLINECOUNT, 0, 0); + ok(3 == lcount, "expected 3, got %d\n", lcount); + + hwButton = CreateWindow("BUTTON", "OK", WS_VISIBLE|WS_CHILD|BS_PUSHBUTTON, + 100, 100, 50, 20, hwParent, (HMENU)ID_RICHEDITTESTDBUTTON, GetModuleHandleA(0), NULL); + ok(hwButton!=NULL, "CreateWindow failed with error code %d\n", GetLastError()); + + memset(&dm_messages, 0, sizeof(dm_messages)); + r = SendMessage(hwRichEdit, WM_KEYDOWN, VK_RETURN, 0x1c0001); + ok(0 == r, "expected 0, got %d\n", r); + test_dm_messages(0, 0, 0); + memset(&dm_messages, 0, sizeof(dm_messages)); + + lcount = SendMessage(hwRichEdit, EM_GETLINECOUNT, 0, 0); + ok(4 == lcount, "expected 4, got %d\n", lcount); + + DestroyWindow(hwButton); + DestroyWindow(hwRichEdit); + + /* Check messages from richedit(0) */ + + hwRichEdit = new_window(RICHEDIT_CLASS, 0, hwParent); + + memset(&dm_messages, 0, sizeof(dm_messages)); + r = SendMessage(hwRichEdit, WM_KEYDOWN, VK_RETURN, 0x1c0001); + ok(0 == r, "expected 0, got %d\n", r); + test_dm_messages(0, 0, 0); + memset(&dm_messages, 0, sizeof(dm_messages)); + + r = SendMessage(hwRichEdit, WM_GETDLGCODE, 0, (LPARAM)&msg); + ok(0x8b == r, "expected 0x8b, got 0x%x\n", r); + test_dm_messages(0, 0, 0); + memset(&dm_messages, 0, sizeof(dm_messages)); + + r = SendMessage(hwRichEdit, WM_KEYDOWN, VK_RETURN, 0x1c0001); + ok(0 == r, "expected 0, got %d\n", r); + test_dm_messages(0, 1, 0); + memset(&dm_messages, 0, sizeof(dm_messages)); + + hwButton = CreateWindow("BUTTON", "OK", WS_VISIBLE|WS_CHILD|BS_PUSHBUTTON, + 100, 100, 50, 20, hwParent, (HMENU)ID_RICHEDITTESTDBUTTON, GetModuleHandleA(0), NULL); + ok(hwButton!=NULL, "CreateWindow failed with error code %d\n", GetLastError()); + + memset(&dm_messages, 0, sizeof(dm_messages)); + r = SendMessage(hwRichEdit, WM_KEYDOWN, VK_RETURN, 0x1c0001); + ok(0 == r, "expected 0, got %d\n", r); + test_dm_messages(0, 1, 1); + memset(&dm_messages, 0, sizeof(dm_messages)); + + DestroyWindow(hwRichEdit); + + /* Check messages from richedit(ES_WANTRETURN) */ + + hwRichEdit = new_window(RICHEDIT_CLASS, ES_WANTRETURN, hwParent); + + memset(&dm_messages, 0, sizeof(dm_messages)); + r = SendMessage(hwRichEdit, WM_KEYDOWN, VK_RETURN, 0x1c0001); + ok(0 == r, "expected 0, got %d\n", r); + test_dm_messages(0, 0, 0); + memset(&dm_messages, 0, sizeof(dm_messages)); + + r = SendMessage(hwRichEdit, WM_GETDLGCODE, 0, (LPARAM)&msg); + ok(0x8b == r, "expected 0x8b, got 0x%x\n", r); + test_dm_messages(0, 0, 0); + memset(&dm_messages, 0, sizeof(dm_messages)); + + r = SendMessage(hwRichEdit, WM_KEYDOWN, VK_RETURN, 0x1c0001); + ok(0 == r, "expected 0, got %d\n", r); + test_dm_messages(0, 0, 0); + memset(&dm_messages, 0, sizeof(dm_messages)); + + hwButton = CreateWindow("BUTTON", "OK", WS_VISIBLE|WS_CHILD|BS_PUSHBUTTON, + 100, 100, 50, 20, hwParent, (HMENU)ID_RICHEDITTESTDBUTTON, GetModuleHandleA(0), NULL); + ok(hwButton!=NULL, "CreateWindow failed with error code %d\n", GetLastError()); + + memset(&dm_messages, 0, sizeof(dm_messages)); + r = SendMessage(hwRichEdit, WM_KEYDOWN, VK_RETURN, 0x1c0001); + ok(0 == r, "expected 0, got %d\n", r); + test_dm_messages(0, 0, 0); + memset(&dm_messages, 0, sizeof(dm_messages)); + + DestroyWindow(hwRichEdit); + DestroyWindow(hwParent); +} + START_TEST( editor ) { /* Must explicitly LoadLibrary(). The test has no references to functions in @@ -6729,6 +6999,7 @@ START_TEST( editor ) test_format_rect(); test_WM_GETDLGCODE(); test_zoom(); + test_dialogmode(); /* Set the environment variable WINETEST_RICHED20 to keep windows * responsive and open for 30 seconds. This is useful for debugging. diff --git a/dlls/riched20/txthost.c b/dlls/riched20/txthost.c index ddf3d76..8056333 100644 --- a/dlls/riched20/txthost.c +++ b/dlls/riched20/txthost.c @@ -44,7 +44,7 @@ typedef struct ITextHostImpl { static ITextHostVtbl textHostVtbl; -ITextHost *ME_CreateTextHost(HWND hwnd, BOOL bEmulateVersion10) +ITextHost *ME_CreateTextHost(HWND hwnd, HWND hwndParent, BOOL bEmulateVersion10) { ITextHostImpl *texthost; texthost = CoTaskMemAlloc(sizeof(*texthost)); @@ -58,8 +58,10 @@ ITextHost *ME_CreateTextHost(HWND hwnd, BOOL bEmulateVersion10) texthost->bEmulateVersion10 = bEmulateVersion10; editor = ME_MakeEditor((ITextHost*)texthost, bEmulateVersion10); + editor->styleFlags |= GetWindowLongW(hwnd, GWL_STYLE) & ES_WANTRETURN; editor->exStyleFlags = GetWindowLongW(hwnd, GWL_EXSTYLE); editor->hWnd = hwnd; /* FIXME: Remove editor's dependence on hWnd */ + editor->hwndParent = hwndParent; SetWindowLongPtrW(hwnd, 0, (LONG_PTR)editor); } -- 1.5.3.3