winemac: Activate an app if it sets focus on a window shortly after a hot key is...
[wine.git] / dlls / user32 / tests / edit.c
blobfb4a8b31d70c2e27af77ada87ca912c2072ab559
1 /* Unit test suite for edit control.
3 * Copyright 2004 Vitaliy Margolen
4 * Copyright 2005 C. Scott Ananian
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21 #include <assert.h>
22 #include <windows.h>
23 #include <commctrl.h>
25 #include "wine/test.h"
27 #ifndef ES_COMBO
28 #define ES_COMBO 0x200
29 #endif
31 #define ID_EDITTESTDBUTTON 0x123
32 #define ID_EDITTEST2 99
33 #define MAXLEN 200
35 struct edit_notify {
36 int en_change, en_maxtext, en_update;
39 static struct edit_notify notifications;
41 static BOOL (WINAPI *pEndMenu) (void);
42 static BOOL (WINAPI *pGetMenuBarInfo)(HWND,LONG,LONG,PMENUBARINFO);
44 static void init_function_pointers(void)
46 HMODULE hdll = GetModuleHandleA("user32");
48 pEndMenu = (void*)GetProcAddress(hdll, "EndMenu");
49 pGetMenuBarInfo = (void*)GetProcAddress(hdll, "GetMenuBarInfo");
52 static INT_PTR CALLBACK multi_edit_dialog_proc(HWND hdlg, UINT msg, WPARAM wparam, LPARAM lparam)
54 static int num_ok_commands = 0;
55 switch (msg)
57 case WM_INITDIALOG:
59 HWND hedit = GetDlgItem(hdlg, 1000);
60 SetFocus(hedit);
61 switch (lparam)
63 /* test cases related to bug 12319 */
64 case 0:
65 PostMessage(hedit, WM_KEYDOWN, VK_TAB, 0xf0001);
66 PostMessage(hdlg, WM_USER, 0xdeadbeef, 0);
67 break;
68 case 1:
69 PostMessage(hedit, WM_CHAR, VK_TAB, 0xf0001);
70 PostMessage(hdlg, WM_USER, 0xdeadbeef, 0);
71 break;
72 case 2:
73 PostMessage(hedit, WM_KEYDOWN, VK_TAB, 0xf0001);
74 PostMessage(hedit, WM_CHAR, VK_TAB, 0xf0001);
75 PostMessage(hdlg, WM_USER, 0xdeadbeef, 0);
76 break;
78 /* test cases for pressing enter */
79 case 3:
80 num_ok_commands = 0;
81 PostMessage(hedit, WM_KEYDOWN, VK_RETURN, 0x1c0001);
82 PostMessage(hdlg, WM_USER, 0xdeadbeef, 1);
83 break;
85 default:
86 break;
88 break;
91 case WM_COMMAND:
92 if (HIWORD(wparam) != BN_CLICKED)
93 break;
95 switch (LOWORD(wparam))
97 case IDOK:
98 num_ok_commands++;
99 break;
101 default:
102 break;
104 break;
106 case WM_USER:
108 HWND hfocus = GetFocus();
109 HWND hedit = GetDlgItem(hdlg, 1000);
110 HWND hedit2 = GetDlgItem(hdlg, 1001);
111 HWND hedit3 = GetDlgItem(hdlg, 1002);
113 if (wparam != 0xdeadbeef)
114 break;
116 switch (lparam)
118 case 0:
119 if (hfocus == hedit)
120 EndDialog(hdlg, 1111);
121 else if (hfocus == hedit2)
122 EndDialog(hdlg, 2222);
123 else if (hfocus == hedit3)
124 EndDialog(hdlg, 3333);
125 else
126 EndDialog(hdlg, 4444);
127 break;
128 case 1:
129 if ((hfocus == hedit) && (num_ok_commands == 0))
130 EndDialog(hdlg, 11);
131 else
132 EndDialog(hdlg, 22);
133 break;
134 default:
135 EndDialog(hdlg, 5555);
137 break;
140 case WM_CLOSE:
141 EndDialog(hdlg, 333);
142 break;
144 default:
145 break;
148 return FALSE;
151 static INT_PTR CALLBACK edit_dialog_proc(HWND hdlg, UINT msg, WPARAM wparam, LPARAM lparam)
153 switch (msg)
155 case WM_INITDIALOG:
157 HWND hedit = GetDlgItem(hdlg, 1000);
158 SetFocus(hedit);
159 switch (lparam)
161 /* from bug 11841 */
162 case 0:
163 PostMessage(hedit, WM_KEYDOWN, VK_ESCAPE, 0x10001);
164 break;
165 case 1:
166 PostMessage(hedit, WM_KEYDOWN, VK_RETURN, 0x1c0001);
167 break;
168 case 2:
169 PostMessage(hedit, WM_KEYDOWN, VK_TAB, 0xf0001);
170 PostMessage(hdlg, WM_USER, 0xdeadbeef, 1);
171 break;
173 /* more test cases for WM_CHAR */
174 case 3:
175 PostMessage(hedit, WM_CHAR, VK_ESCAPE, 0x10001);
176 PostMessage(hdlg, WM_USER, 0xdeadbeef, 0);
177 break;
178 case 4:
179 PostMessage(hedit, WM_CHAR, VK_RETURN, 0x1c0001);
180 PostMessage(hdlg, WM_USER, 0xdeadbeef, 0);
181 break;
182 case 5:
183 PostMessage(hedit, WM_CHAR, VK_TAB, 0xf0001);
184 PostMessage(hdlg, WM_USER, 0xdeadbeef, 0);
185 break;
187 /* more test cases for WM_KEYDOWN + WM_CHAR */
188 case 6:
189 PostMessage(hedit, WM_KEYDOWN, VK_ESCAPE, 0x10001);
190 PostMessage(hedit, WM_CHAR, VK_ESCAPE, 0x10001);
191 PostMessage(hdlg, WM_USER, 0xdeadbeef, 0);
192 break;
193 case 7:
194 PostMessage(hedit, WM_KEYDOWN, VK_RETURN, 0x1c0001);
195 PostMessage(hedit, WM_CHAR, VK_RETURN, 0x1c0001);
196 PostMessage(hdlg, WM_USER, 0xdeadbeef, 1);
197 break;
198 case 8:
199 PostMessage(hedit, WM_KEYDOWN, VK_TAB, 0xf0001);
200 PostMessage(hedit, WM_CHAR, VK_TAB, 0xf0001);
201 PostMessage(hdlg, WM_USER, 0xdeadbeef, 1);
202 break;
204 /* multiple tab tests */
205 case 9:
206 PostMessage(hedit, WM_KEYDOWN, VK_TAB, 0xf0001);
207 PostMessage(hedit, WM_KEYDOWN, VK_TAB, 0xf0001);
208 PostMessage(hdlg, WM_USER, 0xdeadbeef, 2);
209 break;
210 case 10:
211 PostMessage(hedit, WM_KEYDOWN, VK_TAB, 0xf0001);
212 PostMessage(hedit, WM_KEYDOWN, VK_TAB, 0xf0001);
213 PostMessage(hedit, WM_KEYDOWN, VK_TAB, 0xf0001);
214 PostMessage(hdlg, WM_USER, 0xdeadbeef, 2);
215 break;
217 default:
218 break;
220 break;
223 case WM_COMMAND:
224 if (HIWORD(wparam) != BN_CLICKED)
225 break;
227 switch (LOWORD(wparam))
229 case IDOK:
230 EndDialog(hdlg, 111);
231 break;
233 case IDCANCEL:
234 EndDialog(hdlg, 222);
235 break;
237 default:
238 break;
240 break;
242 case WM_USER:
244 int len;
245 HWND hok = GetDlgItem(hdlg, IDOK);
246 HWND hcancel = GetDlgItem(hdlg, IDCANCEL);
247 HWND hedit = GetDlgItem(hdlg, 1000);
248 HWND hfocus = GetFocus();
250 if (wparam != 0xdeadbeef)
251 break;
253 switch (lparam)
255 case 0:
256 len = SendMessage(hedit, WM_GETTEXTLENGTH, 0, 0);
257 if (len == 0)
258 EndDialog(hdlg, 444);
259 else
260 EndDialog(hdlg, 555);
261 break;
263 case 1:
264 len = SendMessage(hedit, WM_GETTEXTLENGTH, 0, 0);
265 if ((hfocus == hok) && len == 0)
266 EndDialog(hdlg, 444);
267 else
268 EndDialog(hdlg, 555);
269 break;
271 case 2:
272 if (hfocus == hok)
273 EndDialog(hdlg, 11);
274 else if (hfocus == hcancel)
275 EndDialog(hdlg, 22);
276 else if (hfocus == hedit)
277 EndDialog(hdlg, 33);
278 else
279 EndDialog(hdlg, 44);
280 break;
282 default:
283 EndDialog(hdlg, 555);
285 break;
288 case WM_CLOSE:
289 EndDialog(hdlg, 333);
290 break;
292 default:
293 break;
296 return FALSE;
299 static INT_PTR CALLBACK edit_singleline_dialog_proc(HWND hdlg, UINT msg, WPARAM wparam, LPARAM lparam)
301 switch (msg)
303 case WM_INITDIALOG:
305 HWND hedit = GetDlgItem(hdlg, 1000);
306 SetFocus(hedit);
307 switch (lparam)
309 /* test cases for WM_KEYDOWN */
310 case 0:
311 PostMessage(hedit, WM_KEYDOWN, VK_ESCAPE, 0x10001);
312 break;
313 case 1:
314 PostMessage(hedit, WM_KEYDOWN, VK_RETURN, 0x1c0001);
315 break;
316 case 2:
317 PostMessage(hedit, WM_KEYDOWN, VK_TAB, 0xf0001);
318 PostMessage(hdlg, WM_USER, 0xdeadbeef, 1);
319 break;
321 /* test cases for WM_CHAR */
322 case 3:
323 PostMessage(hedit, WM_CHAR, VK_ESCAPE, 0x10001);
324 PostMessage(hdlg, WM_USER, 0xdeadbeef, 0);
325 break;
326 case 4:
327 PostMessage(hedit, WM_CHAR, VK_RETURN, 0x1c0001);
328 PostMessage(hdlg, WM_USER, 0xdeadbeef, 0);
329 break;
330 case 5:
331 PostMessage(hedit, WM_CHAR, VK_TAB, 0xf0001);
332 PostMessage(hdlg, WM_USER, 0xdeadbeef, 0);
333 break;
335 /* test cases for WM_KEYDOWN + WM_CHAR */
336 case 6:
337 PostMessage(hedit, WM_KEYDOWN, VK_ESCAPE, 0x10001);
338 PostMessage(hedit, WM_CHAR, VK_ESCAPE, 0x10001);
339 break;
340 case 7:
341 PostMessage(hedit, WM_KEYDOWN, VK_RETURN, 0x1c0001);
342 PostMessage(hedit, WM_CHAR, VK_RETURN, 0x1c0001);
343 break;
344 case 8:
345 PostMessage(hedit, WM_KEYDOWN, VK_TAB, 0xf0001);
346 PostMessage(hedit, WM_CHAR, VK_TAB, 0xf0001);
347 PostMessage(hdlg, WM_USER, 0xdeadbeef, 1);
348 break;
350 default:
351 break;
353 break;
356 case WM_COMMAND:
357 if (HIWORD(wparam) != BN_CLICKED)
358 break;
360 switch (LOWORD(wparam))
362 case IDOK:
363 EndDialog(hdlg, 111);
364 break;
366 case IDCANCEL:
367 EndDialog(hdlg, 222);
368 break;
370 default:
371 break;
373 break;
375 case WM_USER:
377 HWND hok = GetDlgItem(hdlg, IDOK);
378 HWND hedit = GetDlgItem(hdlg, 1000);
379 HWND hfocus = GetFocus();
380 int len = SendMessage(hedit, WM_GETTEXTLENGTH, 0, 0);
382 if (wparam != 0xdeadbeef)
383 break;
385 switch (lparam)
387 case 0:
388 if ((hfocus == hedit) && len == 0)
389 EndDialog(hdlg, 444);
390 else
391 EndDialog(hdlg, 555);
392 break;
394 case 1:
395 if ((hfocus == hok) && len == 0)
396 EndDialog(hdlg, 444);
397 else
398 EndDialog(hdlg, 555);
399 break;
401 default:
402 EndDialog(hdlg, 55);
404 break;
407 case WM_CLOSE:
408 EndDialog(hdlg, 333);
409 break;
411 default:
412 break;
415 return FALSE;
418 static INT_PTR CALLBACK edit_wantreturn_dialog_proc(HWND hdlg, UINT msg, WPARAM wparam, LPARAM lparam)
420 switch (msg)
422 case WM_INITDIALOG:
424 HWND hedit = GetDlgItem(hdlg, 1000);
425 SetFocus(hedit);
426 switch (lparam)
428 /* test cases for WM_KEYDOWN */
429 case 0:
430 PostMessage(hedit, WM_KEYDOWN, VK_ESCAPE, 0x10001);
431 break;
432 case 1:
433 PostMessage(hedit, WM_KEYDOWN, VK_RETURN, 0x1c0001);
434 PostMessage(hdlg, WM_USER, 0xdeadbeef, 0);
435 break;
436 case 2:
437 PostMessage(hedit, WM_KEYDOWN, VK_TAB, 0xf0001);
438 PostMessage(hdlg, WM_USER, 0xdeadbeef, 1);
439 break;
441 /* test cases for WM_CHAR */
442 case 3:
443 PostMessage(hedit, WM_CHAR, VK_ESCAPE, 0x10001);
444 PostMessage(hdlg, WM_USER, 0xdeadbeef, 0);
445 break;
446 case 4:
447 PostMessage(hedit, WM_CHAR, VK_RETURN, 0x1c0001);
448 PostMessage(hdlg, WM_USER, 0xdeadbeef, 2);
449 break;
450 case 5:
451 PostMessage(hedit, WM_CHAR, VK_TAB, 0xf0001);
452 PostMessage(hdlg, WM_USER, 0xdeadbeef, 0);
453 break;
455 /* test cases for WM_KEYDOWN + WM_CHAR */
456 case 6:
457 PostMessage(hedit, WM_KEYDOWN, VK_ESCAPE, 0x10001);
458 PostMessage(hedit, WM_CHAR, VK_ESCAPE, 0x10001);
459 PostMessage(hdlg, WM_USER, 0xdeadbeef, 0);
460 break;
461 case 7:
462 PostMessage(hedit, WM_KEYDOWN, VK_RETURN, 0x1c0001);
463 PostMessage(hedit, WM_CHAR, VK_RETURN, 0x1c0001);
464 PostMessage(hdlg, WM_USER, 0xdeadbeef, 2);
465 break;
466 case 8:
467 PostMessage(hedit, WM_KEYDOWN, VK_TAB, 0xf0001);
468 PostMessage(hedit, WM_CHAR, VK_TAB, 0xf0001);
469 PostMessage(hdlg, WM_USER, 0xdeadbeef, 1);
470 break;
472 default:
473 break;
475 break;
478 case WM_COMMAND:
479 if (HIWORD(wparam) != BN_CLICKED)
480 break;
482 switch (LOWORD(wparam))
484 case IDOK:
485 EndDialog(hdlg, 111);
486 break;
488 case IDCANCEL:
489 EndDialog(hdlg, 222);
490 break;
492 default:
493 break;
495 break;
497 case WM_USER:
499 HWND hok = GetDlgItem(hdlg, IDOK);
500 HWND hedit = GetDlgItem(hdlg, 1000);
501 HWND hfocus = GetFocus();
502 int len = SendMessage(hedit, WM_GETTEXTLENGTH, 0, 0);
504 if (wparam != 0xdeadbeef)
505 break;
507 switch (lparam)
509 case 0:
510 if ((hfocus == hedit) && len == 0)
511 EndDialog(hdlg, 444);
512 else
513 EndDialog(hdlg, 555);
514 break;
516 case 1:
517 if ((hfocus == hok) && len == 0)
518 EndDialog(hdlg, 444);
519 else
520 EndDialog(hdlg, 555);
521 break;
523 case 2:
524 if ((hfocus == hedit) && len == 2)
525 EndDialog(hdlg, 444);
526 else
527 EndDialog(hdlg, 555);
528 break;
530 default:
531 EndDialog(hdlg, 55);
533 break;
536 case WM_CLOSE:
537 EndDialog(hdlg, 333);
538 break;
540 default:
541 break;
544 return FALSE;
547 static HINSTANCE hinst;
548 static HWND hwndET2;
549 static const char szEditTest2Class[] = "EditTest2Class";
550 static const char szEditTest3Class[] = "EditTest3Class";
551 static const char szEditTest4Class[] = "EditTest4Class";
552 static const char szEditTextPositionClass[] = "EditTextPositionWindowClass";
554 static HWND create_editcontrol (DWORD style, DWORD exstyle)
556 HWND handle;
558 handle = CreateWindowEx(exstyle,
559 "EDIT",
560 "Test Text",
561 style,
562 10, 10, 300, 300,
563 NULL, NULL, hinst, NULL);
564 ok (handle != NULL, "CreateWindow EDIT Control failed\n");
565 assert (handle);
566 if (winetest_interactive)
567 ShowWindow (handle, SW_SHOW);
568 return handle;
571 static HWND create_child_editcontrol (DWORD style, DWORD exstyle)
573 HWND parentWnd;
574 HWND editWnd;
575 RECT rect;
576 BOOL b;
578 rect.left = 0;
579 rect.top = 0;
580 rect.right = 300;
581 rect.bottom = 300;
582 b = AdjustWindowRect(&rect, WS_OVERLAPPEDWINDOW, FALSE);
583 ok(b, "AdjustWindowRect failed\n");
585 parentWnd = CreateWindowEx(0,
586 szEditTextPositionClass,
587 "Edit Test",
588 WS_OVERLAPPEDWINDOW,
589 CW_USEDEFAULT, CW_USEDEFAULT,
590 rect.right - rect.left, rect.bottom - rect.top,
591 NULL, NULL, hinst, NULL);
592 ok (parentWnd != NULL, "CreateWindow EDIT Test failed\n");
593 assert(parentWnd);
595 editWnd = CreateWindowEx(exstyle,
596 "EDIT",
597 "Test Text",
598 WS_CHILD | style,
599 0, 0, 300, 300,
600 parentWnd, NULL, hinst, NULL);
601 ok (editWnd != NULL, "CreateWindow EDIT Test Text failed\n");
602 assert(editWnd);
603 if (winetest_interactive)
604 ShowWindow (parentWnd, SW_SHOW);
605 return editWnd;
608 static void destroy_child_editcontrol (HWND hwndEdit)
610 if (GetParent(hwndEdit))
611 DestroyWindow(GetParent(hwndEdit));
612 else {
613 trace("Edit control has no parent!\n");
614 DestroyWindow(hwndEdit);
618 static LONG get_edit_style (HWND hwnd)
620 return GetWindowLongA( hwnd, GWL_STYLE ) & (
621 ES_LEFT |
622 /* FIXME: not implemented
623 ES_CENTER |
624 ES_RIGHT |
625 ES_OEMCONVERT |
627 ES_MULTILINE |
628 ES_UPPERCASE |
629 ES_LOWERCASE |
630 ES_PASSWORD |
631 ES_AUTOVSCROLL |
632 ES_AUTOHSCROLL |
633 ES_NOHIDESEL |
634 ES_COMBO |
635 ES_READONLY |
636 ES_WANTRETURN |
637 ES_NUMBER
641 static void set_client_height(HWND Wnd, unsigned Height)
643 RECT ClientRect, WindowRect;
645 GetWindowRect(Wnd, &WindowRect);
646 GetClientRect(Wnd, &ClientRect);
647 SetWindowPos(Wnd, NULL, 0, 0,
648 WindowRect.right - WindowRect.left,
649 Height + (WindowRect.bottom - WindowRect.top) -
650 (ClientRect.bottom - ClientRect.top),
651 SWP_NOMOVE | SWP_NOACTIVATE | SWP_NOZORDER);
653 /* Workaround for a bug in Windows' edit control
654 (multi-line mode) */
655 GetWindowRect(Wnd, &WindowRect);
656 SetWindowPos(Wnd, NULL, 0, 0,
657 WindowRect.right - WindowRect.left + 1,
658 WindowRect.bottom - WindowRect.top + 1,
659 SWP_NOMOVE | SWP_NOACTIVATE | SWP_NOZORDER);
660 SetWindowPos(Wnd, NULL, 0, 0,
661 WindowRect.right - WindowRect.left,
662 WindowRect.bottom - WindowRect.top,
663 SWP_NOMOVE | SWP_NOACTIVATE | SWP_NOZORDER);
665 GetClientRect(Wnd, &ClientRect);
666 ok(ClientRect.bottom - ClientRect.top == Height,
667 "The client height should be %d, but is %d\n",
668 Height, ClientRect.bottom - ClientRect.top);
671 static void test_edit_control_1(void)
673 HWND hwEdit;
674 MSG msMessage;
675 int i;
676 LONG r;
678 msMessage.message = WM_KEYDOWN;
680 trace("EDIT: Single line\n");
681 hwEdit = create_editcontrol(ES_AUTOHSCROLL | ES_AUTOVSCROLL, 0);
682 r = get_edit_style(hwEdit);
683 ok(r == (ES_AUTOVSCROLL | ES_AUTOHSCROLL), "Wrong style expected 0xc0 got: 0x%x\n", r);
684 for (i=0;i<65535;i++)
686 msMessage.wParam = i;
687 r = SendMessage(hwEdit, WM_GETDLGCODE, 0, (LPARAM) &msMessage);
688 ok(r == (DLGC_WANTCHARS | DLGC_HASSETSEL | DLGC_WANTARROWS),
689 "Expected DLGC_WANTCHARS | DLGC_HASSETSEL | DLGC_WANTARROWS got %x\n", r);
691 DestroyWindow (hwEdit);
693 trace("EDIT: Single line want returns\n");
694 hwEdit = create_editcontrol(ES_WANTRETURN | ES_AUTOHSCROLL | ES_AUTOVSCROLL, 0);
695 r = get_edit_style(hwEdit);
696 ok(r == (ES_AUTOVSCROLL | ES_AUTOHSCROLL | ES_WANTRETURN), "Wrong style expected 0x10c0 got: 0x%x\n", r);
697 for (i=0;i<65535;i++)
699 msMessage.wParam = i;
700 r = SendMessage(hwEdit, WM_GETDLGCODE, 0, (LPARAM) &msMessage);
701 ok(r == (DLGC_WANTCHARS | DLGC_HASSETSEL | DLGC_WANTARROWS),
702 "Expected DLGC_WANTCHARS | DLGC_HASSETSEL | DLGC_WANTARROWS got %x\n", r);
704 DestroyWindow (hwEdit);
706 trace("EDIT: Multiline line\n");
707 hwEdit = create_editcontrol(ES_MULTILINE | WS_VSCROLL | ES_AUTOHSCROLL | ES_AUTOVSCROLL, 0);
708 r = get_edit_style(hwEdit);
709 ok(r == (ES_AUTOHSCROLL | ES_AUTOVSCROLL | ES_MULTILINE), "Wrong style expected 0xc4 got: 0x%x\n", r);
710 for (i=0;i<65535;i++)
712 msMessage.wParam = i;
713 r = SendMessage(hwEdit, WM_GETDLGCODE, 0, (LPARAM) &msMessage);
714 ok(r == (DLGC_WANTCHARS | DLGC_HASSETSEL | DLGC_WANTALLKEYS | DLGC_WANTARROWS),
715 "Expected DLGC_WANTCHARS | DLGC_HASSETSEL | DLGC_WANTALLKEYS | DLGC_WANTARROWS got %x\n", r);
717 DestroyWindow (hwEdit);
719 trace("EDIT: Multi line want returns\n");
720 hwEdit = create_editcontrol(ES_MULTILINE | WS_VSCROLL | ES_WANTRETURN | ES_AUTOHSCROLL | ES_AUTOVSCROLL, 0);
721 r = get_edit_style(hwEdit);
722 ok(r == (ES_WANTRETURN | ES_AUTOHSCROLL | ES_AUTOVSCROLL | ES_MULTILINE), "Wrong style expected 0x10c4 got: 0x%x\n", r);
723 for (i=0;i<65535;i++)
725 msMessage.wParam = i;
726 r = SendMessage(hwEdit, WM_GETDLGCODE, 0, (LPARAM) &msMessage);
727 ok(r == (DLGC_WANTCHARS | DLGC_HASSETSEL | DLGC_WANTALLKEYS | DLGC_WANTARROWS),
728 "Expected DLGC_WANTCHARS | DLGC_HASSETSEL | DLGC_WANTALLKEYS | DLGC_WANTARROWS got %x\n", r);
730 DestroyWindow (hwEdit);
733 /* WM_SETTEXT is implemented by selecting all text, and then replacing the
734 * selection. This test checks that the first 'select all' doesn't generate
735 * an UPDATE message which can escape and (via a handler) change the
736 * selection, which would cause WM_SETTEXT to break. This old bug
737 * was fixed 18-Mar-2005; we check here to ensure it doesn't regress.
739 static void test_edit_control_2(void)
741 HWND hwndMain, phwnd;
742 char szLocalString[MAXLEN];
743 LONG r, w = 150, h = 50;
744 POINT cpos;
746 /* Create main and edit windows. */
747 hwndMain = CreateWindow(szEditTest2Class, "ET2", WS_OVERLAPPEDWINDOW,
748 0, 0, 200, 200, NULL, NULL, hinst, NULL);
749 assert(hwndMain);
750 if (winetest_interactive)
751 ShowWindow (hwndMain, SW_SHOW);
753 hwndET2 = CreateWindow("EDIT", NULL,
754 WS_CHILD|WS_BORDER|ES_LEFT|ES_AUTOHSCROLL,
755 0, 0, w, h, /* important this not be 0 size. */
756 hwndMain, (HMENU) ID_EDITTEST2, hinst, NULL);
757 assert(hwndET2);
758 if (winetest_interactive)
759 ShowWindow (hwndET2, SW_SHOW);
761 trace("EDIT: SETTEXT atomicity\n");
762 /* Send messages to "type" in the word 'foo'. */
763 r = SendMessage(hwndET2, WM_CHAR, 'f', 1);
764 ok(1 == r, "Expected: %d, got: %d\n", 1, r);
765 r = SendMessage(hwndET2, WM_CHAR, 'o', 1);
766 ok(1 == r, "Expected: %d, got: %d\n", 1, r);
767 r = SendMessage(hwndET2, WM_CHAR, 'o', 1);
768 ok(1 == r, "Expected: %d, got: %d\n", 1, r);
769 /* 'foo' should have been changed to 'bar' by the UPDATE handler. */
770 GetWindowText(hwndET2, szLocalString, MAXLEN);
771 ok(lstrcmp(szLocalString, "bar")==0,
772 "Wrong contents of edit: %s\n", szLocalString);
774 /* try setting the caret before it's visible */
775 r = SetCaretPos(0, 0);
776 todo_wine ok(0 == r, "SetCaretPos succeeded unexpectedly, expected: 0, got: %d\n", r);
777 phwnd = SetFocus(hwndET2);
778 ok(phwnd != NULL, "SetFocus failed unexpectedly, expected non-zero, got NULL\n");
779 r = SetCaretPos(0, 0);
780 ok(1 == r, "SetCaretPos failed unexpectedly, expected: 1, got: %d\n", r);
781 r = GetCaretPos(&cpos);
782 ok(1 == r, "GetCaretPos failed unexpectedly, expected: 1, got: %d\n", r);
783 ok(cpos.x == 0 && cpos.y == 0, "Wrong caret position, expected: (0,0), got: (%d,%d)\n", cpos.x, cpos.y);
784 r = SetCaretPos(-1, -1);
785 ok(1 == r, "SetCaretPos failed unexpectedly, expected: 1, got: %d\n", r);
786 r = GetCaretPos(&cpos);
787 ok(1 == r, "GetCaretPos failed unexpectedly, expected: 1, got: %d\n", r);
788 ok(cpos.x == -1 && cpos.y == -1, "Wrong caret position, expected: (-1,-1), got: (%d,%d)\n", cpos.x, cpos.y);
789 r = SetCaretPos(w << 1, h << 1);
790 ok(1 == r, "SetCaretPos failed unexpectedly, expected: 1, got: %d\n", r);
791 r = GetCaretPos(&cpos);
792 ok(1 == r, "GetCaretPos failed unexpectedly, expected: 1, got: %d\n", r);
793 ok(cpos.x == (w << 1) && cpos.y == (h << 1), "Wrong caret position, expected: (%d,%d), got: (%d,%d)\n", w << 1, h << 1, cpos.x, cpos.y);
794 r = SetCaretPos(w, h);
795 ok(1 == r, "SetCaretPos failed unexpectedly, expected: 1, got: %d\n", r);
796 r = GetCaretPos(&cpos);
797 ok(1 == r, "GetCaretPos failed unexpectedly, expected: 1, got: %d\n", r);
798 ok(cpos.x == w && cpos.y == h, "Wrong caret position, expected: (%d,%d), got: (%d,%d)\n", w, h, cpos.x, cpos.y);
799 r = SetCaretPos(w - 1, h - 1);
800 ok(1 == r, "SetCaretPos failed unexpectedly, expected: 1, got: %d\n", r);
801 r = GetCaretPos(&cpos);
802 ok(1 == r, "GetCaretPos failed unexpectedly, expected: 1, got: %d\n", r);
803 ok(cpos.x == (w - 1) && cpos.y == (h - 1), "Wrong caret position, expected: (%d,%d), got: (%d,%d)\n", w - 1, h - 1, cpos.x, cpos.y);
805 /* OK, done! */
806 DestroyWindow (hwndET2);
807 DestroyWindow (hwndMain);
810 static void ET2_check_change(void) {
811 char szLocalString[MAXLEN];
812 /* This EN_UPDATE handler changes any 'foo' to 'bar'. */
813 GetWindowText(hwndET2, szLocalString, MAXLEN);
814 if (lstrcmp(szLocalString, "foo")==0) {
815 lstrcpy(szLocalString, "bar");
816 SendMessage(hwndET2, WM_SETTEXT, 0, (LPARAM) szLocalString);
818 /* always leave the cursor at the end. */
819 SendMessage(hwndET2, EM_SETSEL, MAXLEN - 1, MAXLEN - 1);
821 static void ET2_OnCommand(HWND hwnd, int id, HWND hwndCtl, UINT codeNotify)
823 if (id==ID_EDITTEST2 && codeNotify == EN_UPDATE)
824 ET2_check_change();
826 static LRESULT CALLBACK ET2_WndProc(HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam)
828 switch (iMsg) {
829 case WM_COMMAND:
830 ET2_OnCommand(hwnd, LOWORD(wParam), (HWND)lParam, HIWORD(wParam));
831 break;
833 return DefWindowProc(hwnd, iMsg, wParam, lParam);
836 static void zero_notify(void)
838 notifications.en_change = 0;
839 notifications.en_maxtext = 0;
840 notifications.en_update = 0;
843 #define test_notify(enchange, enmaxtext, enupdate) \
844 ok(notifications.en_change == enchange, "expected %d EN_CHANGE notifications, " \
845 "got %d\n", enchange, notifications.en_change); \
846 ok(notifications.en_maxtext == enmaxtext, "expected %d EN_MAXTEXT notifications, " \
847 "got %d\n", enmaxtext, notifications.en_maxtext); \
848 ok(notifications.en_update == enupdate, "expected %d EN_UPDATE notifications, " \
849 "got %d\n", enupdate, notifications.en_update)
852 static LRESULT CALLBACK edit3_wnd_procA(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
854 switch (msg) {
855 case WM_COMMAND:
856 switch (HIWORD(wParam)) {
857 case EN_MAXTEXT:
858 notifications.en_maxtext++;
859 break;
860 case EN_UPDATE:
861 notifications.en_update++;
862 break;
863 case EN_CHANGE:
864 notifications.en_change++;
865 break;
867 break;
869 return DefWindowProcA(hWnd, msg, wParam, lParam);
872 /* Test behaviour of WM_SETTEXT, WM_REPLACESEL and notificatisons sent in response
873 * to these messages.
875 static void test_edit_control_3(void)
877 HWND hWnd;
878 HWND hParent;
879 HDC hDC;
880 int len, dpi;
881 static const char *str = "this is a long string.";
882 static const char *str2 = "this is a long string.\r\nthis is a long string.\r\nthis is a long string.\r\nthis is a long string.";
884 hDC = GetDC(NULL);
885 dpi = GetDeviceCaps(hDC, LOGPIXELSY);
886 ReleaseDC(NULL, hDC);
888 trace("EDIT: Test notifications\n");
890 hParent = CreateWindowExA(0,
891 szEditTest3Class,
892 NULL,
894 CW_USEDEFAULT, CW_USEDEFAULT, 10, 10,
895 NULL, NULL, NULL, NULL);
896 assert(hParent);
898 trace("EDIT: Single line, no ES_AUTOHSCROLL\n");
899 hWnd = CreateWindowExA(0,
900 "EDIT",
901 NULL,
903 10, 10, 50, 50,
904 hParent, NULL, NULL, NULL);
905 assert(hWnd);
907 zero_notify();
908 SendMessageA(hWnd, EM_REPLACESEL, 0, (LPARAM)str);
909 len = SendMessageA(hWnd, WM_GETTEXTLENGTH, 0, 0);
910 ok(lstrlenA(str) > len, "text should have been truncated\n");
911 test_notify(1, 1, 1);
913 SendMessageA(hWnd, WM_SETTEXT, 0, (LPARAM)"");
914 zero_notify();
915 SendMessageA(hWnd, EM_REPLACESEL, 0, (LPARAM)"a");
916 len = SendMessageA(hWnd, WM_GETTEXTLENGTH, 0, 0);
917 ok(1 == len, "wrong text length, expected 1, got %d\n", len);
918 test_notify(1, 0, 1);
920 zero_notify();
921 SendMessageA(hWnd, WM_SETTEXT, 0, (LPARAM)str);
922 len = SendMessageA(hWnd, WM_GETTEXTLENGTH, 0, 0);
923 ok(lstrlenA(str) == len, "text shouldn't have been truncated\n");
924 test_notify(1, 0, 1);
926 len = SendMessageA(hWnd, EM_GETSEL, 0, 0);
927 ok(LOWORD(len)==0, "Unexpected start position for selection %d\n", LOWORD(len));
928 ok(HIWORD(len)==0, "Unexpected end position for selection %d\n", HIWORD(len));
929 SendMessage(hParent, WM_SETFOCUS, 0, (LPARAM)hWnd);
930 len = SendMessageA(hWnd, EM_GETSEL, 0, 0);
931 ok(LOWORD(len)==0, "Unexpected start position for selection %d\n", LOWORD(len));
932 ok(HIWORD(len)==0, "Unexpected end position for selection %d\n", HIWORD(len));
934 SendMessageA(hWnd, EM_SETLIMITTEXT, 5, 0);
936 SendMessageA(hWnd, WM_SETTEXT, 0, (LPARAM)"");
937 zero_notify();
938 SendMessageA(hWnd, EM_REPLACESEL, 0, (LPARAM)str);
939 len = SendMessageA(hWnd, WM_GETTEXTLENGTH, 0, 0);
940 ok(5 == len, "text should have been truncated to limit, expected 5, got %d\n", len);
941 test_notify(1, 1, 1);
943 zero_notify();
944 SendMessageA(hWnd, WM_SETTEXT, 0, (LPARAM)str);
945 len = SendMessageA(hWnd, WM_GETTEXTLENGTH, 0, 0);
946 ok(lstrlenA(str) == len, "text shouldn't have been truncated\n");
947 test_notify(1, 0, 1);
949 DestroyWindow(hWnd);
951 trace("EDIT: Single line, ES_AUTOHSCROLL\n");
952 hWnd = CreateWindowExA(0,
953 "EDIT",
954 NULL,
955 ES_AUTOHSCROLL,
956 10, 10, 50, 50,
957 hParent, NULL, NULL, NULL);
958 assert(hWnd);
960 zero_notify();
961 SendMessageA(hWnd, EM_REPLACESEL, 0, (LPARAM)str);
962 len = SendMessageA(hWnd, WM_GETTEXTLENGTH, 0, 0);
963 ok(lstrlenA(str) == len, "text shouldn't have been truncated\n");
964 test_notify(1, 0, 1);
966 zero_notify();
967 SendMessageA(hWnd, WM_SETTEXT, 0, (LPARAM)str);
968 len = SendMessageA(hWnd, WM_GETTEXTLENGTH, 0, 0);
969 ok(lstrlenA(str) == len, "text shouldn't have been truncated\n");
970 test_notify(1, 0, 1);
972 SendMessageA(hWnd, EM_SETLIMITTEXT, 5, 0);
974 SendMessageA(hWnd, WM_SETTEXT, 0, (LPARAM)"");
975 zero_notify();
976 SendMessageA(hWnd, EM_REPLACESEL, 0, (LPARAM)str);
977 len = SendMessageA(hWnd, WM_GETTEXTLENGTH, 0, 0);
978 ok(5 == len, "text should have been truncated to limit, expected 5, got %d\n", len);
979 test_notify(1, 1, 1);
981 zero_notify();
982 SendMessageA(hWnd, WM_SETTEXT, 0, (LPARAM)str);
983 len = SendMessageA(hWnd, WM_GETTEXTLENGTH, 0, 0);
984 ok(lstrlenA(str) == len, "text shouldn't have been truncated\n");
985 test_notify(1, 0, 1);
987 DestroyWindow(hWnd);
989 trace("EDIT: Multline, no ES_AUTOHSCROLL, no ES_AUTOVSCROLL\n");
990 hWnd = CreateWindowExA(0,
991 "EDIT",
992 NULL,
993 ES_MULTILINE,
994 10, 10, (50 * dpi) / 96, (50 * dpi) / 96,
995 hParent, NULL, NULL, NULL);
996 assert(hWnd);
998 zero_notify();
999 SendMessageA(hWnd, EM_REPLACESEL, 0, (LPARAM)str);
1000 len = SendMessageA(hWnd, WM_GETTEXTLENGTH, 0, 0);
1001 ok(0 == len, "text should have been truncated, expected 0, got %d\n", len);
1002 test_notify(1, 1, 1);
1004 SendMessageA(hWnd, WM_SETTEXT, 0, (LPARAM)"");
1005 zero_notify();
1006 SendMessageA(hWnd, EM_REPLACESEL, 0, (LPARAM)"a");
1007 len = SendMessageA(hWnd, WM_GETTEXTLENGTH, 0, 0);
1008 ok(1 == SendMessageA(hWnd, WM_GETTEXTLENGTH, 0, 0), "wrong text length, expected 1, got %d\n", len);
1009 test_notify(1, 0, 1);
1011 zero_notify();
1012 SendMessageA(hWnd, WM_SETTEXT, 0, (LPARAM)str);
1013 len = SendMessageA(hWnd, WM_GETTEXTLENGTH, 0, 0);
1014 ok(lstrlenA(str) == len, "text shouldn't have been truncated\n");
1015 test_notify(0, 0, 0);
1017 SendMessageA(hWnd, EM_SETLIMITTEXT, 5, 0);
1019 SendMessageA(hWnd, WM_SETTEXT, 0, (LPARAM)"");
1020 zero_notify();
1021 SendMessageA(hWnd, EM_REPLACESEL, 0, (LPARAM)str);
1022 len = SendMessageA(hWnd, WM_GETTEXTLENGTH, 0, 0);
1023 ok(5 == len, "text should have been truncated to limit, expected 5, got %d\n", len);
1024 test_notify(1, 1, 1);
1026 zero_notify();
1027 SendMessageA(hWnd, WM_SETTEXT, 0, (LPARAM)str);
1028 len = SendMessageA(hWnd, WM_GETTEXTLENGTH, 0, 0);
1029 ok(lstrlenA(str) == len, "text shouldn't have been truncated\n");
1030 test_notify(0, 0, 0);
1032 DestroyWindow(hWnd);
1034 trace("EDIT: Multline, ES_AUTOHSCROLL, no ES_AUTOVSCROLL\n");
1035 hWnd = CreateWindowExA(0,
1036 "EDIT",
1037 NULL,
1038 ES_MULTILINE | ES_AUTOHSCROLL,
1039 10, 10, (50 * dpi) / 96, (50 * dpi) / 96,
1040 hParent, NULL, NULL, NULL);
1041 assert(hWnd);
1043 zero_notify();
1044 SendMessageA(hWnd, EM_REPLACESEL, 0, (LPARAM)str2);
1045 len = SendMessageA(hWnd, WM_GETTEXTLENGTH, 0, 0);
1046 ok(0 == len, "text should have been truncated, expected 0, got %d\n", len);
1047 test_notify(1, 1, 1);
1049 SendMessageA(hWnd, WM_SETTEXT, 0, (LPARAM)"");
1050 zero_notify();
1051 SendMessageA(hWnd, EM_REPLACESEL, 0, (LPARAM)"a");
1052 len = SendMessageA(hWnd, WM_GETTEXTLENGTH, 0, 0);
1053 ok(1 == SendMessageA(hWnd, WM_GETTEXTLENGTH, 0, 0), "wrong text length, expected 1, got %d\n", len);
1054 test_notify(1, 0, 1);
1056 zero_notify();
1057 SendMessageA(hWnd, WM_SETTEXT, 0, (LPARAM)str2);
1058 len = SendMessageA(hWnd, WM_GETTEXTLENGTH, 0, 0);
1059 ok(lstrlenA(str2) == len, "text shouldn't have been truncated\n");
1060 test_notify(0, 0, 0);
1062 SendMessageA(hWnd, EM_SETLIMITTEXT, 5, 0);
1064 SendMessageA(hWnd, WM_SETTEXT, 0, (LPARAM)"");
1065 zero_notify();
1066 SendMessageA(hWnd, EM_REPLACESEL, 0, (LPARAM)str2);
1067 len = SendMessageA(hWnd, WM_GETTEXTLENGTH, 0, 0);
1068 ok(5 == len, "text should have been truncated to limit, expected 5, got %d\n", len);
1069 test_notify(1, 1, 1);
1071 zero_notify();
1072 SendMessageA(hWnd, WM_SETTEXT, 0, (LPARAM)str2);
1073 len = SendMessageA(hWnd, WM_GETTEXTLENGTH, 0, 0);
1074 ok(lstrlenA(str2) == len, "text shouldn't have been truncated\n");
1075 test_notify(0, 0, 0);
1077 DestroyWindow(hWnd);
1079 trace("EDIT: Multline, ES_AUTOHSCROLL and ES_AUTOVSCROLL\n");
1080 hWnd = CreateWindowExA(0,
1081 "EDIT",
1082 NULL,
1083 ES_MULTILINE | ES_AUTOHSCROLL | ES_AUTOVSCROLL,
1084 10, 10, 50, 50,
1085 hParent, NULL, NULL, NULL);
1086 assert(hWnd);
1088 zero_notify();
1089 SendMessageA(hWnd, EM_REPLACESEL, 0, (LPARAM)str2);
1090 len = SendMessageA(hWnd, WM_GETTEXTLENGTH, 0, 0);
1091 ok(lstrlenA(str2) == len, "text shouldn't have been truncated\n");
1092 test_notify(1, 0, 1);
1094 zero_notify();
1095 SendMessageA(hWnd, WM_SETTEXT, 0, (LPARAM)str2);
1096 len = SendMessageA(hWnd, WM_GETTEXTLENGTH, 0, 0);
1097 ok(lstrlenA(str2) == len, "text shouldn't have been truncated\n");
1098 test_notify(0, 0, 0);
1100 SendMessageA(hWnd, EM_SETLIMITTEXT, 5, 0);
1102 SendMessageA(hWnd, WM_SETTEXT, 0, (LPARAM)"");
1103 zero_notify();
1104 SendMessageA(hWnd, EM_REPLACESEL, 0, (LPARAM)str2);
1105 len = SendMessageA(hWnd, WM_GETTEXTLENGTH, 0, 0);
1106 ok(5 == len, "text should have been truncated to limit, expected 5, got %d\n", len);
1107 test_notify(1, 1, 1);
1109 zero_notify();
1110 SendMessageA(hWnd, WM_SETTEXT, 0, (LPARAM)str2);
1111 len = SendMessageA(hWnd, WM_GETTEXTLENGTH, 0, 0);
1112 ok(lstrlenA(str2) == len, "text shouldn't have been truncated\n");
1113 test_notify(0, 0, 0);
1115 DestroyWindow(hWnd);
1118 /* Test EM_CHARFROMPOS and EM_POSFROMCHAR
1120 static void test_edit_control_4(void)
1122 HWND hwEdit;
1123 int lo, hi, mid;
1124 int ret;
1125 int i;
1127 trace("EDIT: Test EM_CHARFROMPOS and EM_POSFROMCHAR\n");
1128 hwEdit = create_editcontrol(ES_AUTOHSCROLL | ES_AUTOVSCROLL, 0);
1129 SendMessage(hwEdit, WM_SETTEXT, 0, (LPARAM) "aa");
1130 lo = LOWORD(SendMessage(hwEdit, EM_POSFROMCHAR, 0, 0));
1131 hi = LOWORD(SendMessage(hwEdit, EM_POSFROMCHAR, 1, 0));
1132 mid = lo + (hi - lo) / 2;
1134 for (i = lo; i < mid; i++) {
1135 ret = LOWORD(SendMessage(hwEdit, EM_CHARFROMPOS, 0, i));
1136 ok(0 == ret, "expected 0 got %d\n", ret);
1138 for (i = mid; i <= hi; i++) {
1139 ret = LOWORD(SendMessage(hwEdit, EM_CHARFROMPOS, 0, i));
1140 ok(1 == ret, "expected 1 got %d\n", ret);
1142 ret = SendMessage(hwEdit, EM_POSFROMCHAR, 2, 0);
1143 ok(-1 == ret, "expected -1 got %d\n", ret);
1144 DestroyWindow(hwEdit);
1146 hwEdit = create_editcontrol(ES_RIGHT | ES_AUTOHSCROLL | ES_AUTOVSCROLL, 0);
1147 SendMessage(hwEdit, WM_SETTEXT, 0, (LPARAM) "aa");
1148 lo = LOWORD(SendMessage(hwEdit, EM_POSFROMCHAR, 0, 0));
1149 hi = LOWORD(SendMessage(hwEdit, EM_POSFROMCHAR, 1, 0));
1150 mid = lo + (hi - lo) / 2;
1152 for (i = lo; i < mid; i++) {
1153 ret = LOWORD(SendMessage(hwEdit, EM_CHARFROMPOS, 0, i));
1154 ok(0 == ret, "expected 0 got %d\n", ret);
1156 for (i = mid; i <= hi; i++) {
1157 ret = LOWORD(SendMessage(hwEdit, EM_CHARFROMPOS, 0, i));
1158 ok(1 == ret, "expected 1 got %d\n", ret);
1160 ret = SendMessage(hwEdit, EM_POSFROMCHAR, 2, 0);
1161 ok(-1 == ret, "expected -1 got %d\n", ret);
1162 DestroyWindow(hwEdit);
1164 hwEdit = create_editcontrol(ES_CENTER | ES_AUTOHSCROLL | ES_AUTOVSCROLL, 0);
1165 SendMessage(hwEdit, WM_SETTEXT, 0, (LPARAM) "aa");
1166 lo = LOWORD(SendMessage(hwEdit, EM_POSFROMCHAR, 0, 0));
1167 hi = LOWORD(SendMessage(hwEdit, EM_POSFROMCHAR, 1, 0));
1168 mid = lo + (hi - lo) / 2;
1170 for (i = lo; i < mid; i++) {
1171 ret = LOWORD(SendMessage(hwEdit, EM_CHARFROMPOS, 0, i));
1172 ok(0 == ret, "expected 0 got %d\n", ret);
1174 for (i = mid; i <= hi; i++) {
1175 ret = LOWORD(SendMessage(hwEdit, EM_CHARFROMPOS, 0, i));
1176 ok(1 == ret, "expected 1 got %d\n", ret);
1178 ret = SendMessage(hwEdit, EM_POSFROMCHAR, 2, 0);
1179 ok(-1 == ret, "expected -1 got %d\n", ret);
1180 DestroyWindow(hwEdit);
1182 hwEdit = create_editcontrol(ES_MULTILINE | ES_AUTOHSCROLL | ES_AUTOVSCROLL, 0);
1183 SendMessage(hwEdit, WM_SETTEXT, 0, (LPARAM) "aa");
1184 lo = LOWORD(SendMessage(hwEdit, EM_POSFROMCHAR, 0, 0));
1185 hi = LOWORD(SendMessage(hwEdit, EM_POSFROMCHAR, 1, 0));
1186 mid = lo + (hi - lo) / 2 +1;
1188 for (i = lo; i < mid; i++) {
1189 ret = LOWORD(SendMessage(hwEdit, EM_CHARFROMPOS, 0, i));
1190 ok((0 == ret || 1 == ret /* Vista */), "expected 0 or 1 got %d\n", ret);
1192 for (i = mid; i <= hi; i++) {
1193 ret = LOWORD(SendMessage(hwEdit, EM_CHARFROMPOS, 0, i));
1194 ok(1 == ret, "expected 1 got %d\n", ret);
1196 ret = SendMessage(hwEdit, EM_POSFROMCHAR, 2, 0);
1197 ok(-1 == ret, "expected -1 got %d\n", ret);
1198 DestroyWindow(hwEdit);
1200 hwEdit = create_editcontrol(ES_MULTILINE | ES_RIGHT | ES_AUTOHSCROLL | ES_AUTOVSCROLL, 0);
1201 SendMessage(hwEdit, WM_SETTEXT, 0, (LPARAM) "aa");
1202 lo = LOWORD(SendMessage(hwEdit, EM_POSFROMCHAR, 0, 0));
1203 hi = LOWORD(SendMessage(hwEdit, EM_POSFROMCHAR, 1, 0));
1204 mid = lo + (hi - lo) / 2 +1;
1206 for (i = lo; i < mid; i++) {
1207 ret = LOWORD(SendMessage(hwEdit, EM_CHARFROMPOS, 0, i));
1208 ok((0 == ret || 1 == ret /* Vista */), "expected 0 or 1 got %d\n", ret);
1210 for (i = mid; i <= hi; i++) {
1211 ret = LOWORD(SendMessage(hwEdit, EM_CHARFROMPOS, 0, i));
1212 ok(1 == ret, "expected 1 got %d\n", ret);
1214 ret = SendMessage(hwEdit, EM_POSFROMCHAR, 2, 0);
1215 ok(-1 == ret, "expected -1 got %d\n", ret);
1216 DestroyWindow(hwEdit);
1218 hwEdit = create_editcontrol(ES_MULTILINE | ES_CENTER | ES_AUTOHSCROLL | ES_AUTOVSCROLL, 0);
1219 SendMessage(hwEdit, WM_SETTEXT, 0, (LPARAM) "aa");
1220 lo = LOWORD(SendMessage(hwEdit, EM_POSFROMCHAR, 0, 0));
1221 hi = LOWORD(SendMessage(hwEdit, EM_POSFROMCHAR, 1, 0));
1222 mid = lo + (hi - lo) / 2 +1;
1224 for (i = lo; i < mid; i++) {
1225 ret = LOWORD(SendMessage(hwEdit, EM_CHARFROMPOS, 0, i));
1226 ok((0 == ret || 1 == ret /* Vista */), "expected 0 or 1 got %d\n", ret);
1228 for (i = mid; i <= hi; i++) {
1229 ret = LOWORD(SendMessage(hwEdit, EM_CHARFROMPOS, 0, i));
1230 ok(1 == ret, "expected 1 got %d\n", ret);
1232 ret = SendMessage(hwEdit, EM_POSFROMCHAR, 2, 0);
1233 ok(-1 == ret, "expected -1 got %d\n", ret);
1234 DestroyWindow(hwEdit);
1237 /* Test if creating edit control without ES_AUTOHSCROLL and ES_AUTOVSCROLL
1238 * truncates text that doesn't fit.
1240 static void test_edit_control_5(void)
1242 static const char *str = "test\r\ntest";
1243 HWND parentWnd;
1244 HWND hWnd;
1245 int len;
1246 RECT rc1 = { 10, 10, 11, 11};
1247 RECT rc;
1249 /* first show that a non-child won't do for this test */
1250 hWnd = CreateWindowEx(0,
1251 "EDIT",
1252 str,
1254 10, 10, 1, 1,
1255 NULL, NULL, NULL, NULL);
1256 assert(hWnd);
1257 /* size of non-child edit control is (much) bigger than requested */
1258 GetWindowRect( hWnd, &rc);
1259 ok( rc.right - rc.left > 20, "size of the window (%d) is smaller than expected\n",
1260 rc.right - rc.left);
1261 DestroyWindow(hWnd);
1262 /* so create a parent, and give it edit controls children to test with */
1263 parentWnd = CreateWindowEx(0,
1264 szEditTextPositionClass,
1265 "Edit Test", WS_VISIBLE |
1266 WS_OVERLAPPEDWINDOW,
1267 CW_USEDEFAULT, CW_USEDEFAULT,
1268 250, 250,
1269 NULL, NULL, hinst, NULL);
1270 assert(parentWnd);
1271 ShowWindow( parentWnd, SW_SHOW);
1272 /* single line */
1273 hWnd = CreateWindowEx(0,
1274 "EDIT",
1275 str, WS_VISIBLE | WS_BORDER |
1276 WS_CHILD,
1277 rc1.left, rc1.top, rc1.right - rc1.left, rc1.bottom - rc1.top,
1278 parentWnd, NULL, NULL, NULL);
1279 assert(hWnd);
1280 GetClientRect( hWnd, &rc);
1281 ok( rc.right == rc1.right - rc1.left && rc.bottom == rc1.bottom - rc1.top,
1282 "Client rectangle not the expected size (%d,%d,%d,%d)\n",
1283 rc.left, rc.top, rc.right, rc.bottom);
1284 len = SendMessageA(hWnd, WM_GETTEXTLENGTH, 0, 0);
1285 ok(lstrlenA(str) == len, "text shouldn't have been truncated\n");
1286 DestroyWindow(hWnd);
1287 /* multi line */
1288 hWnd = CreateWindowEx(0,
1289 "EDIT",
1290 str,
1291 WS_CHILD | ES_MULTILINE,
1292 rc1.left, rc1.top, rc1.right - rc1.left, rc1.bottom - rc1.top,
1293 parentWnd, NULL, NULL, NULL);
1294 assert(hWnd);
1295 GetClientRect( hWnd, &rc);
1296 ok( rc.right == rc1.right - rc1.left && rc.bottom == rc1.bottom - rc1.top,
1297 "Client rectangle not the expected size (%d,%d,%d,%d)\n",
1298 rc.left, rc.top, rc.right, rc.bottom);
1299 len = SendMessageA(hWnd, WM_GETTEXTLENGTH, 0, 0);
1300 ok(lstrlenA(str) == len, "text shouldn't have been truncated\n");
1301 DestroyWindow(hWnd);
1304 /* Test WM_GETTEXT processing
1305 * after destroy messages
1307 static void test_edit_control_6(void)
1309 static const char *str = "test\r\ntest";
1310 char buf[MAXLEN];
1311 LONG ret;
1312 HWND hWnd;
1314 hWnd = CreateWindowEx(0,
1315 "EDIT",
1316 "Test",
1318 10, 10, 1, 1,
1319 NULL, NULL, hinst, NULL);
1320 assert(hWnd);
1322 ret = SendMessageA(hWnd, WM_SETTEXT, 0, (LPARAM)str);
1323 ok(ret == TRUE, "Expected %d, got %d\n", TRUE, ret);
1324 ret = SendMessageA(hWnd, WM_GETTEXT, MAXLEN, (LPARAM)buf);
1325 ok(ret == lstrlen(str), "Expected %s, got len %d\n", str, ret);
1326 ok(!lstrcmp(buf, str), "Expected %s, got %s\n", str, buf);
1327 buf[0] = 0;
1328 ret = SendMessageA(hWnd, WM_DESTROY, 0, 0);
1329 ok(ret == 0, "Expected 0, got %d\n", ret);
1330 ret = SendMessageA(hWnd, WM_GETTEXT, MAXLEN, (LPARAM)buf);
1331 ok(ret == lstrlen(str), "Expected %s, got len %d\n", str, ret);
1332 ok(!lstrcmp(buf, str), "Expected %s, got %s\n", str, buf);
1333 buf[0] = 0;
1334 ret = SendMessageA(hWnd, WM_NCDESTROY, 0, 0);
1335 ok(ret == 0, "Expected 0, got %d\n", ret);
1336 ret = SendMessageA(hWnd, WM_GETTEXT, MAXLEN, (LPARAM)buf);
1337 ok(ret == 0, "Expected 0, got len %d\n", ret);
1338 ok(!lstrcmp(buf, ""), "Expected empty string, got %s\n", buf);
1340 DestroyWindow(hWnd);
1343 static void test_edit_control_limittext(void)
1345 HWND hwEdit;
1346 DWORD r;
1348 /* Test default limit for single-line control */
1349 trace("EDIT: buffer limit for single-line\n");
1350 hwEdit = create_editcontrol(ES_AUTOHSCROLL | ES_AUTOVSCROLL, 0);
1351 r = SendMessage(hwEdit, EM_GETLIMITTEXT, 0, 0);
1352 ok(r == 30000, "Incorrect default text limit, expected 30000 got %u\n", r);
1353 SendMessage(hwEdit, EM_SETLIMITTEXT, 0, 0);
1354 r = SendMessage(hwEdit, EM_GETLIMITTEXT, 0, 0);
1355 ok( r == 2147483646, "got limit %u (expected 2147483646)\n", r);
1356 DestroyWindow(hwEdit);
1358 /* Test default limit for multi-line control */
1359 trace("EDIT: buffer limit for multi-line\n");
1360 hwEdit = create_editcontrol(ES_MULTILINE | WS_VSCROLL | ES_AUTOHSCROLL | ES_AUTOVSCROLL, 0);
1361 r = SendMessage(hwEdit, EM_GETLIMITTEXT, 0, 0);
1362 ok(r == 30000, "Incorrect default text limit, expected 30000 got %u\n", r);
1363 SendMessage(hwEdit, EM_SETLIMITTEXT, 0, 0);
1364 r = SendMessage(hwEdit, EM_GETLIMITTEXT, 0, 0);
1365 ok( r == 4294967295U, "got limit %u (expected 4294967295)\n", r);
1366 DestroyWindow(hwEdit);
1369 /* Test EM_SCROLL */
1370 static void test_edit_control_scroll(void)
1372 static const char *single_line_str = "a";
1373 static const char *multiline_str = "Test\r\nText";
1374 HWND hwEdit;
1375 LONG ret;
1377 /* Check the return value when EM_SCROLL doesn't scroll
1378 * anything. Should not return true unless any lines were actually
1379 * scrolled. */
1380 hwEdit = CreateWindow(
1381 "EDIT",
1382 single_line_str,
1383 WS_VSCROLL | ES_MULTILINE,
1384 1, 1, 100, 100,
1385 NULL, NULL, hinst, NULL);
1387 assert(hwEdit);
1389 ret = SendMessage(hwEdit, EM_SCROLL, SB_PAGEDOWN, 0);
1390 ok(!ret, "Returned %x, expected 0.\n", ret);
1392 ret = SendMessage(hwEdit, EM_SCROLL, SB_PAGEUP, 0);
1393 ok(!ret, "Returned %x, expected 0.\n", ret);
1395 ret = SendMessage(hwEdit, EM_SCROLL, SB_LINEUP, 0);
1396 ok(!ret, "Returned %x, expected 0.\n", ret);
1398 ret = SendMessage(hwEdit, EM_SCROLL, SB_LINEDOWN, 0);
1399 ok(!ret, "Returned %x, expected 0.\n", ret);
1401 DestroyWindow (hwEdit);
1403 /* SB_PAGEDOWN while at the beginning of a buffer with few lines
1404 should not cause EM_SCROLL to return a negative value of
1405 scrolled lines that would put us "before" the beginning. */
1406 hwEdit = CreateWindow(
1407 "EDIT",
1408 multiline_str,
1409 WS_VSCROLL | ES_MULTILINE,
1410 0, 0, 100, 100,
1411 NULL, NULL, hinst, NULL);
1412 assert(hwEdit);
1414 ret = SendMessage(hwEdit, EM_SCROLL, SB_PAGEDOWN, 0);
1415 ok(!ret, "Returned %x, expected 0.\n", ret);
1417 DestroyWindow (hwEdit);
1420 static void test_margins(void)
1422 HWND hwEdit;
1423 RECT old_rect, new_rect;
1424 INT old_right_margin;
1425 DWORD old_margins, new_margins;
1427 hwEdit = create_editcontrol(WS_BORDER | ES_AUTOHSCROLL | ES_AUTOVSCROLL, 0);
1429 old_margins = SendMessage(hwEdit, EM_GETMARGINS, 0, 0);
1430 old_right_margin = HIWORD(old_margins);
1432 /* Check if setting the margins works */
1434 SendMessage(hwEdit, EM_SETMARGINS, EC_LEFTMARGIN, MAKELONG(10, 0));
1435 new_margins = SendMessage(hwEdit, EM_GETMARGINS, 0, 0);
1436 ok(LOWORD(new_margins) == 10, "Wrong left margin: %d\n", LOWORD(new_margins));
1437 ok(HIWORD(new_margins) == old_right_margin, "Wrong right margin: %d\n", HIWORD(new_margins));
1439 SendMessage(hwEdit, EM_SETMARGINS, EC_RIGHTMARGIN, MAKELONG(0, 10));
1440 new_margins = SendMessage(hwEdit, EM_GETMARGINS, 0, 0);
1441 ok(LOWORD(new_margins) == 10, "Wrong left margin: %d\n", LOWORD(new_margins));
1442 ok(HIWORD(new_margins) == 10, "Wrong right margin: %d\n", HIWORD(new_margins));
1445 /* The size of the rectangle must decrease if we increase the margin */
1447 SendMessage(hwEdit, EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN, MAKELONG(5, 5));
1448 SendMessage(hwEdit, EM_GETRECT, 0, (LPARAM)&old_rect);
1449 SendMessage(hwEdit, EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN, MAKELONG(15, 20));
1450 SendMessage(hwEdit, EM_GETRECT, 0, (LPARAM)&new_rect);
1451 ok(new_rect.left == old_rect.left + 10, "The left border of the rectangle is wrong\n");
1452 ok(new_rect.right == old_rect.right - 15, "The right border of the rectangle is wrong\n");
1453 ok(new_rect.top == old_rect.top, "The top border of the rectangle must not change\n");
1454 ok(new_rect.bottom == old_rect.bottom, "The bottom border of the rectangle must not change\n");
1457 /* If we set the margin to same value as the current margin,
1458 the rectangle must not change */
1460 SendMessage(hwEdit, EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN, MAKELONG(10, 10));
1461 old_rect.left = 1;
1462 old_rect.right = 99;
1463 old_rect.top = 1;
1464 old_rect.bottom = 99;
1465 SendMessage(hwEdit, EM_SETRECT, 0, (LPARAM)&old_rect);
1466 SendMessage(hwEdit, EM_GETRECT, 0, (LPARAM)&old_rect);
1467 SendMessage(hwEdit, EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN, MAKELONG(10, 10));
1468 SendMessage(hwEdit, EM_GETRECT, 0, (LPARAM)&new_rect);
1469 ok(new_rect.left == old_rect.left, "The left border of the rectangle has changed\n");
1470 ok(new_rect.right == old_rect.right, "The right border of the rectangle has changed\n");
1471 ok(new_rect.top == old_rect.top, "The top border of the rectangle has changed\n");
1472 ok(new_rect.bottom == old_rect.bottom, "The bottom border of the rectangle has changed\n");
1474 DestroyWindow (hwEdit);
1477 static INT CALLBACK find_font_proc(const LOGFONT *elf, const TEXTMETRIC *ntm, DWORD type, LPARAM lParam)
1479 return 0;
1482 static void test_margins_font_change(void)
1484 HWND hwEdit;
1485 DWORD margins, font_margins;
1486 LOGFONT lf;
1487 HFONT hfont, hfont2;
1488 HDC hdc = GetDC(0);
1490 if(EnumFontFamiliesA(hdc, "Arial", find_font_proc, 0))
1492 trace("Arial not found - skipping font change margin tests\n");
1493 ReleaseDC(0, hdc);
1494 return;
1496 ReleaseDC(0, hdc);
1498 hwEdit = create_child_editcontrol(0, 0);
1500 SetWindowPos(hwEdit, NULL, 10, 10, 1000, 100, SWP_NOZORDER | SWP_NOACTIVATE);
1502 memset(&lf, 0, sizeof(lf));
1503 strcpy(lf.lfFaceName, "Arial");
1504 lf.lfHeight = 16;
1505 lf.lfCharSet = DEFAULT_CHARSET;
1506 hfont = CreateFontIndirectA(&lf);
1507 lf.lfHeight = 30;
1508 hfont2 = CreateFontIndirectA(&lf);
1510 SendMessageA(hwEdit, WM_SETFONT, (WPARAM)hfont, 0);
1511 font_margins = SendMessage(hwEdit, EM_GETMARGINS, 0, 0);
1512 ok(LOWORD(font_margins) != 0, "got %d\n", LOWORD(font_margins));
1513 ok(HIWORD(font_margins) != 0, "got %d\n", HIWORD(font_margins));
1515 /* With 'small' edit controls, test that the margin doesn't get set */
1516 SetWindowPos(hwEdit, NULL, 10, 10, 16, 100, SWP_NOZORDER | SWP_NOACTIVATE);
1517 SendMessageA(hwEdit, EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN, MAKELONG(0,0));
1518 SendMessageA(hwEdit, WM_SETFONT, (WPARAM)hfont, 0);
1519 margins = SendMessage(hwEdit, EM_GETMARGINS, 0, 0);
1520 ok(LOWORD(margins) == 0 || broken(LOWORD(margins) == LOWORD(font_margins)), /* win95 */
1521 "got %d\n", LOWORD(margins));
1522 ok(HIWORD(margins) == 0 || broken(HIWORD(margins) == HIWORD(font_margins)), /* win95 */
1523 "got %d\n", HIWORD(margins));
1525 SendMessageA(hwEdit, EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN, MAKELONG(1,0));
1526 SendMessageA(hwEdit, WM_SETFONT, (WPARAM)hfont, 0);
1527 margins = SendMessage(hwEdit, EM_GETMARGINS, 0, 0);
1528 ok(LOWORD(margins) == 1 || broken(LOWORD(margins) == LOWORD(font_margins)), /* win95 */
1529 "got %d\n", LOWORD(margins));
1530 ok(HIWORD(margins) == 0 || broken(HIWORD(margins) == HIWORD(font_margins)), /* win95 */
1531 "got %d\n", HIWORD(margins));
1533 SendMessageA(hwEdit, EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN, MAKELONG(1,1));
1534 SendMessageA(hwEdit, WM_SETFONT, (WPARAM)hfont, 0);
1535 margins = SendMessage(hwEdit, EM_GETMARGINS, 0, 0);
1536 ok(LOWORD(margins) == 1 || broken(LOWORD(margins) == LOWORD(font_margins)), /* win95 */
1537 "got %d\n", LOWORD(margins));
1538 ok(HIWORD(margins) == 1 || broken(HIWORD(margins) == HIWORD(font_margins)), /* win95 */
1539 "got %d\n", HIWORD(margins));
1541 SendMessageA(hwEdit, EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN, MAKELONG(EC_USEFONTINFO,EC_USEFONTINFO));
1542 margins = SendMessage(hwEdit, EM_GETMARGINS, 0, 0);
1543 ok(LOWORD(margins) == 1 || broken(LOWORD(margins) == LOWORD(font_margins)), /* win95 */
1544 "got %d\n", LOWORD(margins));
1545 ok(HIWORD(margins) == 1 || broken(HIWORD(margins) == HIWORD(font_margins)), /* win95 */
1546 "got %d\n", HIWORD(margins));
1548 SendMessageA(hwEdit, WM_SETFONT, (WPARAM)hfont2, 0);
1549 margins = SendMessage(hwEdit, EM_GETMARGINS, 0, 0);
1550 ok(LOWORD(margins) == 1 || broken(LOWORD(margins) != 1 && LOWORD(margins) != LOWORD(font_margins)), /* win95 */
1551 "got %d\n", LOWORD(margins));
1552 ok(HIWORD(margins) == 1 || broken(HIWORD(margins) != 1 && HIWORD(margins) != HIWORD(font_margins)), /* win95 */
1553 "got %d\n", HIWORD(margins));
1555 /* Above a certain size threshold then the margin is updated */
1556 SetWindowPos(hwEdit, NULL, 10, 10, 1000, 100, SWP_NOZORDER | SWP_NOACTIVATE);
1557 SendMessageA(hwEdit, EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN, MAKELONG(1,0));
1558 SendMessageA(hwEdit, WM_SETFONT, (WPARAM)hfont, 0);
1559 margins = SendMessage(hwEdit, EM_GETMARGINS, 0, 0);
1560 ok(LOWORD(margins) == LOWORD(font_margins), "got %d\n", LOWORD(margins));
1561 ok(HIWORD(margins) == HIWORD(font_margins), "got %d\n", HIWORD(margins));
1563 SendMessageA(hwEdit, EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN, MAKELONG(1,1));
1564 SendMessageA(hwEdit, WM_SETFONT, (WPARAM)hfont, 0);
1565 margins = SendMessage(hwEdit, EM_GETMARGINS, 0, 0);
1566 ok(LOWORD(margins) == LOWORD(font_margins), "got %d\n", LOWORD(margins));
1567 ok(HIWORD(margins) == HIWORD(font_margins), "got %d\n", HIWORD(margins));
1569 SendMessageA(hwEdit, EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN, MAKELONG(EC_USEFONTINFO,EC_USEFONTINFO));
1570 SendMessageA(hwEdit, WM_SETFONT, (WPARAM)hfont, 0);
1571 margins = SendMessage(hwEdit, EM_GETMARGINS, 0, 0);
1572 ok(LOWORD(margins) == LOWORD(font_margins), "got %d\n", LOWORD(margins));
1573 ok(HIWORD(margins) == HIWORD(font_margins), "got %d\n", HIWORD(margins));
1574 SendMessageA(hwEdit, WM_SETFONT, (WPARAM)hfont2, 0);
1575 margins = SendMessage(hwEdit, EM_GETMARGINS, 0, 0);
1576 ok(LOWORD(margins) != LOWORD(font_margins) || broken(LOWORD(margins) == LOWORD(font_margins)), /* win98 */
1577 "got %d\n", LOWORD(margins));
1578 ok(HIWORD(margins) != HIWORD(font_margins), "got %d\n", HIWORD(margins));
1580 SendMessageA(hwEdit, WM_SETFONT, 0, 0);
1582 DeleteObject(hfont2);
1583 DeleteObject(hfont);
1584 destroy_child_editcontrol(hwEdit);
1588 #define edit_pos_ok(exp, got, txt) \
1589 ok(exp == got, "wrong " #txt " expected %d got %d\n", exp, got);
1591 #define check_pos(hwEdit, set_height, test_top, test_height, test_left) \
1592 do { \
1593 RECT format_rect; \
1594 int left_margin; \
1595 set_client_height(hwEdit, set_height); \
1596 SendMessage(hwEdit, EM_GETRECT, 0, (LPARAM) &format_rect); \
1597 left_margin = LOWORD(SendMessage(hwEdit, EM_GETMARGINS, 0, 0)); \
1598 edit_pos_ok(test_top, format_rect.top, vertical position); \
1599 edit_pos_ok((int)test_height, format_rect.bottom - format_rect.top, height); \
1600 edit_pos_ok(test_left, format_rect.left - left_margin, left); \
1601 } while(0)
1603 static void test_text_position_style(DWORD style)
1605 HWND hwEdit;
1606 HFONT font, oldFont;
1607 HDC dc;
1608 TEXTMETRIC metrics;
1609 INT b, bm, b2, b3;
1610 BOOL xb, single_line = !(style & ES_MULTILINE);
1612 b = GetSystemMetrics(SM_CYBORDER) + 1;
1613 b2 = 2 * b;
1614 b3 = 3 * b;
1615 bm = b2 - 1;
1617 /* Get a stock font for which we can determine the metrics */
1618 font = GetStockObject(SYSTEM_FONT);
1619 ok (font != NULL, "GetStockObjcet SYSTEM_FONT failed\n");
1620 dc = GetDC(NULL);
1621 ok (dc != NULL, "GetDC() failed\n");
1622 oldFont = SelectObject(dc, font);
1623 xb = GetTextMetrics(dc, &metrics);
1624 ok (xb, "GetTextMetrics failed\n");
1625 SelectObject(dc, oldFont);
1626 ReleaseDC(NULL, dc);
1628 /* Windows' edit control has some bugs in multi-line mode:
1629 * - Sometimes the format rectangle doesn't get updated
1630 * (see workaround in set_client_height())
1631 * - If the height of the control is smaller than the height of a text
1632 * line, the format rectangle is still as high as a text line
1633 * (higher than the client rectangle) and the caret is not shown
1636 /* Edit controls that are in a parent window */
1638 hwEdit = create_child_editcontrol(style | WS_VISIBLE, 0);
1639 SendMessage(hwEdit, WM_SETFONT, (WPARAM) font, FALSE);
1640 if (single_line)
1641 check_pos(hwEdit, metrics.tmHeight - 1, 0, metrics.tmHeight - 1, 0);
1642 check_pos(hwEdit, metrics.tmHeight , 0, metrics.tmHeight , 0);
1643 check_pos(hwEdit, metrics.tmHeight + 1, 0, metrics.tmHeight , 0);
1644 check_pos(hwEdit, metrics.tmHeight + 2, 0, metrics.tmHeight , 0);
1645 check_pos(hwEdit, metrics.tmHeight + 10, 0, metrics.tmHeight , 0);
1646 destroy_child_editcontrol(hwEdit);
1648 hwEdit = create_child_editcontrol(style | WS_BORDER | WS_VISIBLE, 0);
1649 SendMessage(hwEdit, WM_SETFONT, (WPARAM) font, FALSE);
1650 if (single_line)
1651 check_pos(hwEdit, metrics.tmHeight - 1, 0, metrics.tmHeight - 1, b);
1652 check_pos(hwEdit, metrics.tmHeight , 0, metrics.tmHeight , b);
1653 check_pos(hwEdit, metrics.tmHeight + 1, 0, metrics.tmHeight , b);
1654 check_pos(hwEdit, metrics.tmHeight + bm, 0, metrics.tmHeight , b);
1655 check_pos(hwEdit, metrics.tmHeight + b2, b, metrics.tmHeight , b);
1656 check_pos(hwEdit, metrics.tmHeight + b3, b, metrics.tmHeight , b);
1657 destroy_child_editcontrol(hwEdit);
1659 hwEdit = create_child_editcontrol(style | WS_VISIBLE, WS_EX_CLIENTEDGE);
1660 SendMessage(hwEdit, WM_SETFONT, (WPARAM) font, FALSE);
1661 if (single_line)
1662 check_pos(hwEdit, metrics.tmHeight - 1, 0, metrics.tmHeight - 1, 1);
1663 check_pos(hwEdit, metrics.tmHeight , 0, metrics.tmHeight , 1);
1664 check_pos(hwEdit, metrics.tmHeight + 1, 0, metrics.tmHeight , 1);
1665 check_pos(hwEdit, metrics.tmHeight + 2, 1, metrics.tmHeight , 1);
1666 check_pos(hwEdit, metrics.tmHeight + 10, 1, metrics.tmHeight , 1);
1667 destroy_child_editcontrol(hwEdit);
1669 hwEdit = create_child_editcontrol(style | WS_BORDER | WS_VISIBLE, WS_EX_CLIENTEDGE);
1670 SendMessage(hwEdit, WM_SETFONT, (WPARAM) font, FALSE);
1671 if (single_line)
1672 check_pos(hwEdit, metrics.tmHeight - 1, 0, metrics.tmHeight - 1, 1);
1673 check_pos(hwEdit, metrics.tmHeight , 0, metrics.tmHeight , 1);
1674 check_pos(hwEdit, metrics.tmHeight + 1, 0, metrics.tmHeight , 1);
1675 check_pos(hwEdit, metrics.tmHeight + 2, 1, metrics.tmHeight , 1);
1676 check_pos(hwEdit, metrics.tmHeight + 10, 1, metrics.tmHeight , 1);
1677 destroy_child_editcontrol(hwEdit);
1680 /* Edit controls that are popup windows */
1682 hwEdit = create_editcontrol(style | WS_POPUP, 0);
1683 SendMessage(hwEdit, WM_SETFONT, (WPARAM) font, FALSE);
1684 if (single_line)
1685 check_pos(hwEdit, metrics.tmHeight - 1, 0, metrics.tmHeight - 1, 0);
1686 check_pos(hwEdit, metrics.tmHeight , 0, metrics.tmHeight , 0);
1687 check_pos(hwEdit, metrics.tmHeight + 1, 0, metrics.tmHeight , 0);
1688 check_pos(hwEdit, metrics.tmHeight + 2, 0, metrics.tmHeight , 0);
1689 check_pos(hwEdit, metrics.tmHeight + 10, 0, metrics.tmHeight , 0);
1690 DestroyWindow(hwEdit);
1692 hwEdit = create_editcontrol(style | WS_POPUP | WS_BORDER, 0);
1693 SendMessage(hwEdit, WM_SETFONT, (WPARAM) font, FALSE);
1694 if (single_line)
1695 check_pos(hwEdit, metrics.tmHeight - 1, 0, metrics.tmHeight - 1, b);
1696 check_pos(hwEdit, metrics.tmHeight , 0, metrics.tmHeight , b);
1697 check_pos(hwEdit, metrics.tmHeight + 1, 0, metrics.tmHeight , b);
1698 check_pos(hwEdit, metrics.tmHeight + bm, 0, metrics.tmHeight , b);
1699 check_pos(hwEdit, metrics.tmHeight + b2, b, metrics.tmHeight , b);
1700 check_pos(hwEdit, metrics.tmHeight + b3, b, metrics.tmHeight , b);
1701 DestroyWindow(hwEdit);
1703 hwEdit = create_editcontrol(style | WS_POPUP, WS_EX_CLIENTEDGE);
1704 SendMessage(hwEdit, WM_SETFONT, (WPARAM) font, FALSE);
1705 if (single_line)
1706 check_pos(hwEdit, metrics.tmHeight - 1, 0, metrics.tmHeight - 1, 1);
1707 check_pos(hwEdit, metrics.tmHeight , 0, metrics.tmHeight , 1);
1708 check_pos(hwEdit, metrics.tmHeight + 1, 0, metrics.tmHeight , 1);
1709 check_pos(hwEdit, metrics.tmHeight + 2, 1, metrics.tmHeight , 1);
1710 check_pos(hwEdit, metrics.tmHeight + 10, 1, metrics.tmHeight , 1);
1711 DestroyWindow(hwEdit);
1713 hwEdit = create_editcontrol(style | WS_POPUP | WS_BORDER, WS_EX_CLIENTEDGE);
1714 SendMessage(hwEdit, WM_SETFONT, (WPARAM) font, FALSE);
1715 if (single_line)
1716 check_pos(hwEdit, metrics.tmHeight - 1, 0, metrics.tmHeight - 1, 1);
1717 check_pos(hwEdit, metrics.tmHeight , 0, metrics.tmHeight , 1);
1718 check_pos(hwEdit, metrics.tmHeight + 1, 0, metrics.tmHeight , 1);
1719 check_pos(hwEdit, metrics.tmHeight + 2, 1, metrics.tmHeight , 1);
1720 check_pos(hwEdit, metrics.tmHeight + 10, 1, metrics.tmHeight , 1);
1721 DestroyWindow(hwEdit);
1724 static void test_text_position(void)
1726 trace("EDIT: Text position (Single line)\n");
1727 test_text_position_style(ES_AUTOHSCROLL | ES_AUTOVSCROLL);
1728 trace("EDIT: Text position (Multi line)\n");
1729 test_text_position_style(ES_MULTILINE | ES_AUTOHSCROLL | ES_AUTOVSCROLL);
1732 static void test_espassword(void)
1734 HWND hwEdit;
1735 LONG r;
1736 char buffer[1024];
1737 const char* password = "secret";
1739 hwEdit = create_editcontrol(ES_PASSWORD, 0);
1740 r = get_edit_style(hwEdit);
1741 ok(r == ES_PASSWORD, "Wrong style expected ES_PASSWORD got: 0x%x\n", r);
1742 /* set text */
1743 r = SendMessage(hwEdit , WM_SETTEXT, 0, (LPARAM) password);
1744 ok(r == TRUE, "Expected: %d, got: %d\n", TRUE, r);
1746 /* select all, cut (ctrl-x) */
1747 SendMessage(hwEdit, EM_SETSEL, 0, -1);
1748 r = SendMessage(hwEdit, WM_CHAR, 24, 0);
1749 ok(1 == r, "Expected: %d, got: %d\n", 1, r);
1751 /* get text */
1752 r = SendMessage(hwEdit, WM_GETTEXT, 1024, (LPARAM) buffer);
1753 ok(r == strlen(password), "Expected: %s, got len %d\n", password, r);
1754 ok(strcmp(buffer, password) == 0, "expected %s, got %s\n", password, buffer);
1756 r = OpenClipboard(hwEdit);
1757 ok(r == TRUE, "expected %d, got %d\n", TRUE, r);
1758 r = EmptyClipboard();
1759 ok(r == TRUE, "expected %d, got %d\n", TRUE, r);
1760 r = CloseClipboard();
1761 ok(r == TRUE, "expected %d, got %d\n", TRUE, r);
1763 /* select all, copy (ctrl-c) and paste (ctrl-v) */
1764 SendMessage(hwEdit, EM_SETSEL, 0, -1);
1765 r = SendMessage(hwEdit, WM_CHAR, 3, 0);
1766 ok(1 == r, "Expected: %d, got: %d\n", 1, r);
1767 r = SendMessage(hwEdit, WM_CHAR, 22, 0);
1768 ok(1 == r, "Expected: %d, got: %d\n", 1, r);
1770 /* get text */
1771 buffer[0] = 0;
1772 r = SendMessage(hwEdit, WM_GETTEXT, 1024, (LPARAM) buffer);
1773 ok(r == 0, "Expected: 0, got: %d\n", r);
1774 ok(strcmp(buffer, "") == 0, "expected empty string, got %s\n", buffer);
1776 DestroyWindow (hwEdit);
1779 static void test_undo(void)
1781 HWND hwEdit;
1782 LONG r;
1783 DWORD cpMin, cpMax;
1784 char buffer[1024];
1785 const char* text = "undo this";
1787 hwEdit = create_editcontrol(0, 0);
1788 r = get_edit_style(hwEdit);
1789 ok(0 == r, "Wrong style expected 0x%x got: 0x%x\n", 0, r);
1791 /* set text */
1792 r = SendMessage(hwEdit , WM_SETTEXT, 0, (LPARAM) text);
1793 ok(TRUE == r, "Expected: %d, got: %d\n", TRUE, r);
1795 /* select all, */
1796 cpMin = cpMax = 0xdeadbeef;
1797 SendMessage(hwEdit, EM_SETSEL, 0, -1);
1798 r = SendMessage(hwEdit, EM_GETSEL, (WPARAM) &cpMin, (LPARAM) &cpMax);
1799 ok((strlen(text) << 16) == r, "Unexpected length %d\n", r);
1800 ok(0 == cpMin, "Expected: %d, got %d\n", 0, cpMin);
1801 ok(9 == cpMax, "Expected: %d, got %d\n", 9, cpMax);
1803 /* cut (ctrl-x) */
1804 r = SendMessage(hwEdit, WM_CHAR, 24, 0);
1805 ok(1 == r, "Expected: %d, got: %d\n", 1, r);
1807 /* get text */
1808 buffer[0] = 0;
1809 r = SendMessage(hwEdit, WM_GETTEXT, 1024, (LPARAM) buffer);
1810 ok(0 == r, "Expected: %d, got len %d\n", 0, r);
1811 ok(0 == strcmp(buffer, ""), "expected %s, got %s\n", "", buffer);
1813 /* undo (ctrl-z) */
1814 r = SendMessage(hwEdit, WM_CHAR, 26, 0);
1815 ok(1 == r, "Expected: %d, got: %d\n", 1, r);
1817 /* get text */
1818 buffer[0] = 0;
1819 r = SendMessage(hwEdit, WM_GETTEXT, 1024, (LPARAM) buffer);
1820 ok(strlen(text) == r, "Unexpected length %d\n", r);
1821 ok(0 == strcmp(buffer, text), "expected %s, got %s\n", text, buffer);
1823 /* undo again (ctrl-z) */
1824 r = SendMessage(hwEdit, WM_CHAR, 26, 0);
1825 ok(1 == r, "Expected: %d, got: %d\n", 1, r);
1827 /* get text */
1828 buffer[0] = 0;
1829 r = SendMessage(hwEdit, WM_GETTEXT, 1024, (LPARAM) buffer);
1830 ok(r == 0, "Expected: %d, got len %d\n", 0, r);
1831 ok(0 == strcmp(buffer, ""), "expected %s, got %s\n", "", buffer);
1833 DestroyWindow (hwEdit);
1836 static void test_enter(void)
1838 HWND hwEdit;
1839 LONG r;
1840 char buffer[16];
1842 /* multiline */
1843 hwEdit = create_editcontrol(ES_MULTILINE, 0);
1844 r = get_edit_style(hwEdit);
1845 ok(ES_MULTILINE == r, "Wrong style expected ES_MULTILINE got: 0x%x\n", r);
1847 /* set text */
1848 r = SendMessage(hwEdit , WM_SETTEXT, 0, (LPARAM) "");
1849 ok(TRUE == r, "Expected: %d, got: %d\n", TRUE, r);
1851 r = SendMessage(hwEdit, WM_CHAR, VK_RETURN, 0);
1852 ok(1 == r, "Expected: %d, got: %d\n", 1, r);
1854 /* get text */
1855 buffer[0] = 0;
1856 r = SendMessage(hwEdit, WM_GETTEXT, 16, (LPARAM) buffer);
1857 ok(2 == r, "Expected: %d, got len %d\n", 2, r);
1858 ok(0 == strcmp(buffer, "\r\n"), "expected \"\\r\\n\", got \"%s\"\n", buffer);
1860 DestroyWindow (hwEdit);
1862 /* single line */
1863 hwEdit = create_editcontrol(0, 0);
1864 r = get_edit_style(hwEdit);
1865 ok(0 == r, "Wrong style expected 0x%x got: 0x%x\n", 0, r);
1867 /* set text */
1868 r = SendMessage(hwEdit , WM_SETTEXT, 0, (LPARAM) "");
1869 ok(TRUE == r, "Expected: %d, got: %d\n", TRUE, r);
1871 r = SendMessage(hwEdit, WM_CHAR, VK_RETURN, 0);
1872 ok(1 == r, "Expected: %d, got: %d\n", 1, r);
1874 /* get text */
1875 buffer[0] = 0;
1876 r = SendMessage(hwEdit, WM_GETTEXT, 16, (LPARAM) buffer);
1877 ok(0 == r, "Expected: %d, got len %d\n", 0, r);
1878 ok(0 == strcmp(buffer, ""), "expected \"\", got \"%s\"\n", buffer);
1880 DestroyWindow (hwEdit);
1882 /* single line with ES_WANTRETURN */
1883 hwEdit = create_editcontrol(ES_WANTRETURN, 0);
1884 r = get_edit_style(hwEdit);
1885 ok(ES_WANTRETURN == r, "Wrong style expected ES_WANTRETURN got: 0x%x\n", r);
1887 /* set text */
1888 r = SendMessage(hwEdit , WM_SETTEXT, 0, (LPARAM) "");
1889 ok(TRUE == r, "Expected: %d, got: %d\n", TRUE, r);
1891 r = SendMessage(hwEdit, WM_CHAR, VK_RETURN, 0);
1892 ok(1 == r, "Expected: %d, got: %d\n", 1, r);
1894 /* get text */
1895 buffer[0] = 0;
1896 r = SendMessage(hwEdit, WM_GETTEXT, 16, (LPARAM) buffer);
1897 ok(0 == r, "Expected: %d, got len %d\n", 0, r);
1898 ok(0 == strcmp(buffer, ""), "expected \"\", got \"%s\"\n", buffer);
1900 DestroyWindow (hwEdit);
1903 static void test_tab(void)
1905 HWND hwEdit;
1906 LONG r;
1907 char buffer[16];
1909 /* multiline */
1910 hwEdit = create_editcontrol(ES_MULTILINE, 0);
1911 r = get_edit_style(hwEdit);
1912 ok(ES_MULTILINE == r, "Wrong style expected ES_MULTILINE got: 0x%x\n", r);
1914 /* set text */
1915 r = SendMessage(hwEdit , WM_SETTEXT, 0, (LPARAM) "");
1916 ok(TRUE == r, "Expected: %d, got: %d\n", TRUE, r);
1918 r = SendMessage(hwEdit, WM_CHAR, VK_TAB, 0);
1919 ok(1 == r, "Expected: %d, got: %d\n", 1, r);
1921 /* get text */
1922 buffer[0] = 0;
1923 r = SendMessage(hwEdit, WM_GETTEXT, 16, (LPARAM) buffer);
1924 ok(1 == r, "Expected: %d, got len %d\n", 1, r);
1925 ok(0 == strcmp(buffer, "\t"), "expected \"\\t\", got \"%s\"\n", buffer);
1927 DestroyWindow (hwEdit);
1929 /* single line */
1930 hwEdit = create_editcontrol(0, 0);
1931 r = get_edit_style(hwEdit);
1932 ok(0 == r, "Wrong style expected 0x%x got: 0x%x\n", 0, r);
1934 /* set text */
1935 r = SendMessage(hwEdit , WM_SETTEXT, 0, (LPARAM) "");
1936 ok(TRUE == r, "Expected: %d, got: %d\n", TRUE, r);
1938 r = SendMessage(hwEdit, WM_CHAR, VK_TAB, 0);
1939 ok(1 == r, "Expected: %d, got: %d\n", 1, r);
1941 /* get text */
1942 buffer[0] = 0;
1943 r = SendMessage(hwEdit, WM_GETTEXT, 16, (LPARAM) buffer);
1944 ok(0 == r, "Expected: %d, got len %d\n", 0, r);
1945 ok(0 == strcmp(buffer, ""), "expected \"\", got \"%s\"\n", buffer);
1947 DestroyWindow (hwEdit);
1950 static void test_edit_dialog(void)
1952 int r;
1954 /* from bug 11841 */
1955 r = DialogBoxParam(hinst, "EDIT_READONLY_DIALOG", NULL, edit_dialog_proc, 0);
1956 ok(333 == r, "Expected %d, got %d\n", 333, r);
1957 r = DialogBoxParam(hinst, "EDIT_READONLY_DIALOG", NULL, edit_dialog_proc, 1);
1958 ok(111 == r, "Expected %d, got %d\n", 111, r);
1959 r = DialogBoxParam(hinst, "EDIT_READONLY_DIALOG", NULL, edit_dialog_proc, 2);
1960 ok(444 == r, "Expected %d, got %d\n", 444, r);
1962 /* more tests for WM_CHAR */
1963 r = DialogBoxParam(hinst, "EDIT_READONLY_DIALOG", NULL, edit_dialog_proc, 3);
1964 ok(444 == r, "Expected %d, got %d\n", 444, r);
1965 r = DialogBoxParam(hinst, "EDIT_READONLY_DIALOG", NULL, edit_dialog_proc, 4);
1966 ok(444 == r, "Expected %d, got %d\n", 444, r);
1967 r = DialogBoxParam(hinst, "EDIT_READONLY_DIALOG", NULL, edit_dialog_proc, 5);
1968 ok(444 == r, "Expected %d, got %d\n", 444, r);
1970 /* more tests for WM_KEYDOWN + WM_CHAR */
1971 r = DialogBoxParam(hinst, "EDIT_READONLY_DIALOG", NULL, edit_dialog_proc, 6);
1972 ok(444 == r, "Expected %d, got %d\n", 444, r);
1973 r = DialogBoxParam(hinst, "EDIT_READONLY_DIALOG", NULL, edit_dialog_proc, 7);
1974 ok(444 == r, "Expected %d, got %d\n", 444, r);
1975 r = DialogBoxParam(hinst, "EDIT_READONLY_DIALOG", NULL, edit_dialog_proc, 8);
1976 ok(444 == r, "Expected %d, got %d\n", 444, r);
1978 /* tests with an editable edit control */
1979 r = DialogBoxParam(hinst, "EDIT_DIALOG", NULL, edit_dialog_proc, 0);
1980 ok(333 == r, "Expected %d, got %d\n", 333, r);
1981 r = DialogBoxParam(hinst, "EDIT_DIALOG", NULL, edit_dialog_proc, 1);
1982 ok(111 == r, "Expected %d, got %d\n", 111, r);
1983 r = DialogBoxParam(hinst, "EDIT_DIALOG", NULL, edit_dialog_proc, 2);
1984 ok(444 == r, "Expected %d, got %d\n", 444, r);
1986 /* tests for WM_CHAR */
1987 r = DialogBoxParam(hinst, "EDIT_DIALOG", NULL, edit_dialog_proc, 3);
1988 ok(444 == r, "Expected %d, got %d\n", 444, r);
1989 r = DialogBoxParam(hinst, "EDIT_DIALOG", NULL, edit_dialog_proc, 4);
1990 ok(444 == r, "Expected %d, got %d\n", 444, r);
1991 r = DialogBoxParam(hinst, "EDIT_DIALOG", NULL, edit_dialog_proc, 5);
1992 ok(444 == r, "Expected %d, got %d\n", 444, r);
1994 /* tests for WM_KEYDOWN + WM_CHAR */
1995 r = DialogBoxParam(hinst, "EDIT_DIALOG", NULL, edit_dialog_proc, 6);
1996 ok(444 == r, "Expected %d, got %d\n", 444, r);
1997 r = DialogBoxParam(hinst, "EDIT_DIALOG", NULL, edit_dialog_proc, 7);
1998 ok(444 == r, "Expected %d, got %d\n", 444, r);
1999 r = DialogBoxParam(hinst, "EDIT_DIALOG", NULL, edit_dialog_proc, 8);
2000 ok(444 == r, "Expected %d, got %d\n", 444, r);
2002 /* multiple tab tests */
2003 r = DialogBoxParam(hinst, "EDIT_DIALOG", NULL, edit_dialog_proc, 9);
2004 ok(22 == r, "Expected %d, got %d\n", 22, r);
2005 r = DialogBoxParam(hinst, "EDIT_DIALOG", NULL, edit_dialog_proc, 10);
2006 ok(33 == r, "Expected %d, got %d\n", 33, r);
2009 static void test_multi_edit_dialog(void)
2011 int r;
2013 /* test for multiple edit dialogs (bug 12319) */
2014 r = DialogBoxParam(hinst, "MULTI_EDIT_DIALOG", NULL, multi_edit_dialog_proc, 0);
2015 ok(2222 == r, "Expected %d, got %d\n", 2222, r);
2016 r = DialogBoxParam(hinst, "MULTI_EDIT_DIALOG", NULL, multi_edit_dialog_proc, 1);
2017 ok(1111 == r, "Expected %d, got %d\n", 1111, r);
2018 r = DialogBoxParam(hinst, "MULTI_EDIT_DIALOG", NULL, multi_edit_dialog_proc, 2);
2019 ok(2222 == r, "Expected %d, got %d\n", 2222, r);
2020 r = DialogBoxParam(hinst, "MULTI_EDIT_DIALOG", NULL, multi_edit_dialog_proc, 3);
2021 ok(11 == r, "Expected %d, got %d\n", 11, r);
2024 static void test_wantreturn_edit_dialog(void)
2026 int r;
2028 /* tests for WM_KEYDOWN */
2029 r = DialogBoxParam(hinst, "EDIT_WANTRETURN_DIALOG", NULL, edit_wantreturn_dialog_proc, 0);
2030 ok(333 == r, "Expected %d, got %d\n", 333, r);
2031 r = DialogBoxParam(hinst, "EDIT_WANTRETURN_DIALOG", NULL, edit_wantreturn_dialog_proc, 1);
2032 ok(444 == r, "Expected %d, got %d\n", 444, r);
2033 r = DialogBoxParam(hinst, "EDIT_WANTRETURN_DIALOG", NULL, edit_wantreturn_dialog_proc, 2);
2034 ok(444 == r, "Expected %d, got %d\n", 444, r);
2036 /* tests for WM_CHAR */
2037 r = DialogBoxParam(hinst, "EDIT_WANTRETURN_DIALOG", NULL, edit_wantreturn_dialog_proc, 3);
2038 ok(444 == r, "Expected %d, got %d\n", 444, r);
2039 r = DialogBoxParam(hinst, "EDIT_WANTRETURN_DIALOG", NULL, edit_wantreturn_dialog_proc, 4);
2040 ok(444 == r, "Expected %d, got %d\n", 444, r);
2041 r = DialogBoxParam(hinst, "EDIT_WANTRETURN_DIALOG", NULL, edit_wantreturn_dialog_proc, 5);
2042 ok(444 == r, "Expected %d, got %d\n", 444, r);
2044 /* tests for WM_KEYDOWN + WM_CHAR */
2045 r = DialogBoxParam(hinst, "EDIT_WANTRETURN_DIALOG", NULL, edit_wantreturn_dialog_proc, 6);
2046 ok(444 == r, "Expected %d, got %d\n", 444, r);
2047 r = DialogBoxParam(hinst, "EDIT_WANTRETURN_DIALOG", NULL, edit_wantreturn_dialog_proc, 7);
2048 ok(444 == r, "Expected %d, got %d\n", 444, r);
2049 r = DialogBoxParam(hinst, "EDIT_WANTRETURN_DIALOG", NULL, edit_wantreturn_dialog_proc, 8);
2050 ok(444 == r, "Expected %d, got %d\n", 444, r);
2053 static void test_singleline_wantreturn_edit_dialog(void)
2055 int r;
2057 /* tests for WM_KEYDOWN */
2058 r = DialogBoxParam(hinst, "EDIT_SINGLELINE_DIALOG", NULL, edit_singleline_dialog_proc, 0);
2059 ok(222 == r, "Expected %d, got %d\n", 222, r);
2060 r = DialogBoxParam(hinst, "EDIT_SINGLELINE_DIALOG", NULL, edit_singleline_dialog_proc, 1);
2061 ok(111 == r, "Expected %d, got %d\n", 111, r);
2062 r = DialogBoxParam(hinst, "EDIT_SINGLELINE_DIALOG", NULL, edit_singleline_dialog_proc, 2);
2063 ok(444 == r, "Expected %d, got %d\n", 444, r);
2065 /* tests for WM_CHAR */
2066 r = DialogBoxParam(hinst, "EDIT_SINGLELINE_DIALOG", NULL, edit_singleline_dialog_proc, 3);
2067 ok(444 == r, "Expected %d, got %d\n", 444, r);
2068 r = DialogBoxParam(hinst, "EDIT_SINGLELINE_DIALOG", NULL, edit_singleline_dialog_proc, 4);
2069 ok(444 == r, "Expected %d, got %d\n", 444, r);
2070 r = DialogBoxParam(hinst, "EDIT_SINGLELINE_DIALOG", NULL, edit_singleline_dialog_proc, 5);
2071 ok(444 == r, "Expected %d, got %d\n", 444, r);
2073 /* tests for WM_KEYDOWN + WM_CHAR */
2074 r = DialogBoxParam(hinst, "EDIT_SINGLELINE_DIALOG", NULL, edit_singleline_dialog_proc, 6);
2075 ok(222 == r, "Expected %d, got %d\n", 222, r);
2076 r = DialogBoxParam(hinst, "EDIT_SINGLELINE_DIALOG", NULL, edit_singleline_dialog_proc, 7);
2077 ok(111 == r, "Expected %d, got %d\n", 111, r);
2078 r = DialogBoxParam(hinst, "EDIT_SINGLELINE_DIALOG", NULL, edit_singleline_dialog_proc, 8);
2079 ok(444 == r, "Expected %d, got %d\n", 444, r);
2081 /* tests for WM_KEYDOWN */
2082 r = DialogBoxParam(hinst, "EDIT_SINGLELINE_WANTRETURN_DIALOG", NULL, edit_singleline_dialog_proc, 0);
2083 ok(222 == r, "Expected %d, got %d\n", 222, r);
2084 r = DialogBoxParam(hinst, "EDIT_SINGLELINE_WANTRETURN_DIALOG", NULL, edit_singleline_dialog_proc, 1);
2085 ok(111 == r, "Expected %d, got %d\n", 111, r);
2086 r = DialogBoxParam(hinst, "EDIT_SINGLELINE_WANTRETURN_DIALOG", NULL, edit_singleline_dialog_proc, 2);
2087 ok(444 == r, "Expected %d, got %d\n", 444, r);
2089 /* tests for WM_CHAR */
2090 r = DialogBoxParam(hinst, "EDIT_SINGLELINE_WANTRETURN_DIALOG", NULL, edit_singleline_dialog_proc, 3);
2091 ok(444 == r, "Expected %d, got %d\n", 444, r);
2092 r = DialogBoxParam(hinst, "EDIT_SINGLELINE_WANTRETURN_DIALOG", NULL, edit_singleline_dialog_proc, 4);
2093 ok(444 == r, "Expected %d, got %d\n", 444, r);
2094 r = DialogBoxParam(hinst, "EDIT_SINGLELINE_WANTRETURN_DIALOG", NULL, edit_singleline_dialog_proc, 5);
2095 ok(444 == r, "Expected %d, got %d\n", 444, r);
2097 /* tests for WM_KEYDOWN + WM_CHAR */
2098 r = DialogBoxParam(hinst, "EDIT_SINGLELINE_WANTRETURN_DIALOG", NULL, edit_singleline_dialog_proc, 6);
2099 ok(222 == r, "Expected %d, got %d\n", 222, r);
2100 r = DialogBoxParam(hinst, "EDIT_SINGLELINE_WANTRETURN_DIALOG", NULL, edit_singleline_dialog_proc, 7);
2101 ok(111 == r, "Expected %d, got %d\n", 111, r);
2102 r = DialogBoxParam(hinst, "EDIT_SINGLELINE_WANTRETURN_DIALOG", NULL, edit_singleline_dialog_proc, 8);
2103 ok(444 == r, "Expected %d, got %d\n", 444, r);
2106 static int child_edit_wmkeydown_num_messages = 0;
2107 static INT_PTR CALLBACK child_edit_wmkeydown_proc(HWND hdlg, UINT msg, WPARAM wparam, LPARAM lparam)
2109 switch (msg)
2111 case WM_DESTROY:
2112 case WM_NCDESTROY:
2113 break;
2115 default:
2116 child_edit_wmkeydown_num_messages++;
2117 break;
2120 return FALSE;
2123 static void test_child_edit_wmkeydown(void)
2125 HWND hwEdit, hwParent;
2126 int r;
2128 hwEdit = create_child_editcontrol(0, 0);
2129 hwParent = GetParent(hwEdit);
2130 SetWindowLongPtr(hwParent, GWLP_WNDPROC, (LONG_PTR)child_edit_wmkeydown_proc);
2131 r = SendMessage(hwEdit, WM_KEYDOWN, VK_RETURN, 0x1c0001);
2132 ok(1 == r, "expected 1, got %d\n", r);
2133 ok(0 == child_edit_wmkeydown_num_messages, "expected 0, got %d\n", child_edit_wmkeydown_num_messages);
2134 destroy_child_editcontrol(hwEdit);
2137 static int got_en_setfocus = 0;
2138 static int got_wm_capturechanged = 0;
2139 static LRESULT (CALLBACK *p_edit_proc)(HWND, UINT, WPARAM, LPARAM);
2141 static LRESULT CALLBACK edit4_wnd_procA(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
2143 switch (msg) {
2144 case WM_COMMAND:
2145 switch (HIWORD(wParam)) {
2146 case EN_SETFOCUS:
2147 got_en_setfocus = 1;
2148 break;
2150 break;
2151 case WM_CAPTURECHANGED:
2152 if (hWnd != (HWND)lParam)
2154 got_wm_capturechanged = 1;
2155 pEndMenu();
2157 break;
2159 return DefWindowProcA(hWnd, msg, wParam, lParam);
2162 static LRESULT CALLBACK edit_proc_proxy(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
2164 switch (msg) {
2165 case WM_ENTERIDLE: {
2166 MENUBARINFO mbi;
2167 BOOL ret;
2168 HWND ctx_menu = (HWND)lParam;
2170 memset(&mbi, 0, sizeof(mbi));
2171 mbi.cbSize = sizeof(mbi);
2172 SetLastError(0xdeadbeef);
2173 ret = pGetMenuBarInfo(ctx_menu, OBJID_CLIENT, 0, &mbi);
2174 ok(ret || broken(!ret && GetLastError()==ERROR_INVALID_WINDOW_HANDLE) /* NT */,
2175 "GetMenuBarInfo failed\n");
2176 if (ret)
2178 ok(mbi.hMenu != NULL, "mbi.hMenu = NULL\n");
2179 ok(!mbi.hwndMenu, "mbi.hwndMenu != NULL\n");
2180 ok(mbi.fBarFocused, "mbi.fBarFocused = FALSE\n");
2181 ok(mbi.fFocused, "mbi.fFocused = FALSE\n");
2184 memset(&mbi, 0, sizeof(mbi));
2185 mbi.cbSize = sizeof(mbi);
2186 SetLastError(0xdeadbeef);
2187 ret = pGetMenuBarInfo(ctx_menu, OBJID_CLIENT, 1, &mbi);
2188 ok(ret || broken(!ret && GetLastError()==ERROR_INVALID_WINDOW_HANDLE) /* NT */,
2189 "GetMenuBarInfo failed\n");
2190 if (ret)
2192 ok(mbi.hMenu != NULL, "mbi.hMenu = NULL\n");
2193 ok(!mbi.hwndMenu, "mbi.hwndMenu != NULL\n");
2194 ok(mbi.fBarFocused, "mbi.fBarFocused = FALSE\n");
2195 ok(!mbi.fFocused, "mbi.fFocused = TRUE\n");
2198 pEndMenu();
2199 break;
2202 return p_edit_proc(hWnd, msg, wParam, lParam);
2205 static void test_contextmenu(void)
2207 HWND hwndMain, hwndEdit;
2209 hwndMain = CreateWindow(szEditTest4Class, "ET4", WS_OVERLAPPEDWINDOW|WS_VISIBLE,
2210 0, 0, 200, 200, NULL, NULL, hinst, NULL);
2211 assert(hwndMain);
2213 hwndEdit = CreateWindow("EDIT", NULL,
2214 WS_CHILD|WS_BORDER|WS_VISIBLE|ES_LEFT|ES_AUTOHSCROLL,
2215 0, 0, 150, 50, /* important this not be 0 size. */
2216 hwndMain, (HMENU) ID_EDITTEST2, hinst, NULL);
2217 assert(hwndEdit);
2219 SetFocus(NULL);
2220 SetCapture(hwndMain);
2221 SendMessage(hwndEdit, WM_CONTEXTMENU, (WPARAM)hwndEdit, MAKEWORD(10, 10));
2222 ok(got_en_setfocus, "edit box didn't get focused\n");
2223 ok(got_wm_capturechanged, "main window capture did not change\n");
2225 if (pGetMenuBarInfo)
2227 p_edit_proc = (void*)SetWindowLongPtr(hwndEdit, GWLP_WNDPROC, (ULONG_PTR)edit_proc_proxy);
2228 SendMessage(hwndEdit, WM_CONTEXTMENU, (WPARAM)hwndEdit, MAKEWORD(10, 10));
2231 DestroyWindow (hwndEdit);
2232 DestroyWindow (hwndMain);
2235 static BOOL RegisterWindowClasses (void)
2237 WNDCLASSA test2;
2238 WNDCLASSA test3;
2239 WNDCLASSA test4;
2240 WNDCLASSA text_position;
2242 test2.style = 0;
2243 test2.lpfnWndProc = ET2_WndProc;
2244 test2.cbClsExtra = 0;
2245 test2.cbWndExtra = 0;
2246 test2.hInstance = hinst;
2247 test2.hIcon = NULL;
2248 test2.hCursor = LoadCursorA (NULL, IDC_ARROW);
2249 test2.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
2250 test2.lpszMenuName = NULL;
2251 test2.lpszClassName = szEditTest2Class;
2252 if (!RegisterClassA(&test2)) return FALSE;
2254 test3.style = 0;
2255 test3.lpfnWndProc = edit3_wnd_procA;
2256 test3.cbClsExtra = 0;
2257 test3.cbWndExtra = 0;
2258 test3.hInstance = hinst;
2259 test3.hIcon = 0;
2260 test3.hCursor = LoadCursorA(0, IDC_ARROW);
2261 test3.hbrBackground = GetStockObject(WHITE_BRUSH);
2262 test3.lpszMenuName = NULL;
2263 test3.lpszClassName = szEditTest3Class;
2264 if (!RegisterClassA(&test3)) return FALSE;
2266 test4.style = 0;
2267 test4.lpfnWndProc = edit4_wnd_procA;
2268 test4.cbClsExtra = 0;
2269 test4.cbWndExtra = 0;
2270 test4.hInstance = hinst;
2271 test4.hIcon = NULL;
2272 test4.hCursor = LoadCursorA (NULL, IDC_ARROW);
2273 test4.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
2274 test4.lpszMenuName = NULL;
2275 test4.lpszClassName = szEditTest4Class;
2276 if (!RegisterClassA(&test4)) return FALSE;
2278 text_position.style = CS_HREDRAW | CS_VREDRAW;
2279 text_position.cbClsExtra = 0;
2280 text_position.cbWndExtra = 0;
2281 text_position.hInstance = hinst;
2282 text_position.hIcon = NULL;
2283 text_position.hCursor = LoadCursorA(NULL, IDC_ARROW);
2284 text_position.hbrBackground = (HBRUSH)(COLOR_BTNFACE + 1);
2285 text_position.lpszMenuName = NULL;
2286 text_position.lpszClassName = szEditTextPositionClass;
2287 text_position.lpfnWndProc = DefWindowProc;
2288 if (!RegisterClassA(&text_position)) return FALSE;
2290 return TRUE;
2293 static void UnregisterWindowClasses (void)
2295 UnregisterClassA(szEditTest2Class, hinst);
2296 UnregisterClassA(szEditTest3Class, hinst);
2297 UnregisterClassA(szEditTest4Class, hinst);
2298 UnregisterClassA(szEditTextPositionClass, hinst);
2301 static void test_fontsize(void)
2303 HWND hwEdit;
2304 HFONT hfont;
2305 HDC hDC;
2306 LOGFONT lf;
2307 LONG r;
2308 char szLocalString[MAXLEN];
2309 int dpi;
2311 hDC = GetDC(NULL);
2312 dpi = GetDeviceCaps(hDC, LOGPIXELSY);
2313 ReleaseDC(NULL, hDC);
2315 memset(&lf,0,sizeof(LOGFONTA));
2316 strcpy(lf.lfFaceName,"Arial");
2317 lf.lfHeight = -300; /* taller than the edit box */
2318 lf.lfWeight = 500;
2319 hfont = CreateFontIndirect(&lf);
2321 trace("EDIT: Oversized font (Multi line)\n");
2322 hwEdit= CreateWindow("EDIT", NULL, ES_MULTILINE|ES_AUTOHSCROLL,
2323 0, 0, (150 * dpi) / 96, (50 * dpi) / 96, NULL, NULL,
2324 hinst, NULL);
2326 SendMessage(hwEdit,WM_SETFONT,(WPARAM)hfont,0);
2328 if (winetest_interactive)
2329 ShowWindow (hwEdit, SW_SHOW);
2331 r = SendMessage(hwEdit, WM_CHAR, 'A', 1);
2332 ok(1 == r, "Expected: %d, got: %d\n", 1, r);
2333 r = SendMessage(hwEdit, WM_CHAR, 'B', 1);
2334 ok(1 == r, "Expected: %d, got: %d\n", 1, r);
2335 r = SendMessage(hwEdit, WM_CHAR, 'C', 1);
2336 ok(1 == r, "Expected: %d, got: %d\n", 1, r);
2338 GetWindowText(hwEdit, szLocalString, MAXLEN);
2339 ok(lstrcmp(szLocalString, "ABC")==0,
2340 "Wrong contents of edit: %s\n", szLocalString);
2342 r = SendMessage(hwEdit, EM_POSFROMCHAR,0,0);
2343 ok(r != -1,"EM_POSFROMCHAR failed index 0\n");
2344 r = SendMessage(hwEdit, EM_POSFROMCHAR,1,0);
2345 ok(r != -1,"EM_POSFROMCHAR failed index 1\n");
2346 r = SendMessage(hwEdit, EM_POSFROMCHAR,2,0);
2347 ok(r != -1,"EM_POSFROMCHAR failed index 2\n");
2348 r = SendMessage(hwEdit, EM_POSFROMCHAR,3,0);
2349 ok(r == -1,"EM_POSFROMCHAR succeeded index 3\n");
2351 DestroyWindow (hwEdit);
2352 DeleteObject(hfont);
2355 struct dialog_mode_messages
2357 int wm_getdefid, wm_close, wm_command, wm_nextdlgctl;
2360 static struct dialog_mode_messages dm_messages;
2362 static void zero_dm_messages(void)
2364 dm_messages.wm_command = 0;
2365 dm_messages.wm_close = 0;
2366 dm_messages.wm_getdefid = 0;
2367 dm_messages.wm_nextdlgctl = 0;
2370 #define test_dm_messages(wmcommand, wmclose, wmgetdefid, wmnextdlgctl) \
2371 ok(dm_messages.wm_command == wmcommand, "expected %d WM_COMMAND messages, " \
2372 "got %d\n", wmcommand, dm_messages.wm_command); \
2373 ok(dm_messages.wm_close == wmclose, "expected %d WM_CLOSE messages, " \
2374 "got %d\n", wmclose, dm_messages.wm_close); \
2375 ok(dm_messages.wm_getdefid == wmgetdefid, "expected %d WM_GETDIFID messages, " \
2376 "got %d\n", wmgetdefid, dm_messages.wm_getdefid);\
2377 ok(dm_messages.wm_nextdlgctl == wmnextdlgctl, "expected %d WM_NEXTDLGCTL messages, " \
2378 "got %d\n", wmnextdlgctl, dm_messages.wm_nextdlgctl)
2380 static LRESULT CALLBACK dialog_mode_wnd_proc(HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam)
2382 switch (iMsg)
2384 case WM_COMMAND:
2385 dm_messages.wm_command++;
2386 break;
2387 case DM_GETDEFID:
2388 dm_messages.wm_getdefid++;
2389 return MAKELONG(ID_EDITTESTDBUTTON, DC_HASDEFID);
2390 case WM_NEXTDLGCTL:
2391 dm_messages.wm_nextdlgctl++;
2392 break;
2393 case WM_CLOSE:
2394 dm_messages.wm_close++;
2395 break;
2398 return DefWindowProc(hwnd, iMsg, wParam, lParam);
2401 static void test_dialogmode(void)
2403 HWND hwEdit, hwParent, hwButton;
2404 MSG msg= {0};
2405 int len, r;
2406 hwEdit = create_child_editcontrol(ES_MULTILINE, 0);
2408 r = SendMessage(hwEdit, WM_CHAR, VK_RETURN, 0x1c0001);
2409 ok(1 == r, "expected 1, got %d\n", r);
2410 len = SendMessage(hwEdit, WM_GETTEXTLENGTH, 0, 0);
2411 ok(11 == len, "expected 11, got %d\n", len);
2413 r = SendMessage(hwEdit, WM_GETDLGCODE, 0, 0);
2414 ok(0x8d == r, "expected 0x8d, got 0x%x\n", r);
2416 r = SendMessage(hwEdit, WM_CHAR, VK_RETURN, 0x1c0001);
2417 ok(1 == r, "expected 1, got %d\n", r);
2418 len = SendMessage(hwEdit, WM_GETTEXTLENGTH, 0, 0);
2419 ok(13 == len, "expected 13, got %d\n", len);
2421 r = SendMessage(hwEdit, WM_GETDLGCODE, 0, (LPARAM)&msg);
2422 ok(0x8d == r, "expected 0x8d, got 0x%x\n", r);
2423 r = SendMessage(hwEdit, WM_CHAR, VK_RETURN, 0x1c0001);
2424 ok(1 == r, "expected 1, got %d\n", r);
2425 len = SendMessage(hwEdit, WM_GETTEXTLENGTH, 0, 0);
2426 ok(13 == len, "expected 13, got %d\n", len);
2428 r = SendMessage(hwEdit, WM_CHAR, VK_RETURN, 0x1c0001);
2429 ok(1 == r, "expected 1, got %d\n", r);
2430 len = SendMessage(hwEdit, WM_GETTEXTLENGTH, 0, 0);
2431 ok(13 == len, "expected 13, got %d\n", len);
2433 destroy_child_editcontrol(hwEdit);
2435 hwEdit = create_editcontrol(ES_MULTILINE, 0);
2437 r = SendMessage(hwEdit, WM_CHAR, VK_RETURN, 0x1c0001);
2438 ok(1 == r, "expected 1, got %d\n", r);
2439 len = SendMessage(hwEdit, WM_GETTEXTLENGTH, 0, 0);
2440 ok(11 == len, "expected 11, got %d\n", len);
2442 msg.hwnd = hwEdit;
2443 msg.message = WM_KEYDOWN;
2444 msg.wParam = VK_BACK;
2445 msg.lParam = 0xe0001;
2446 r = SendMessage(hwEdit, WM_GETDLGCODE, VK_BACK, (LPARAM)&msg);
2447 ok(0x8d == r, "expected 0x8d, got 0x%x\n", r);
2449 r = SendMessage(hwEdit, WM_CHAR, VK_RETURN, 0x1c0001);
2450 ok(1 == r, "expected 1, got %d\n", r);
2451 len = SendMessage(hwEdit, WM_GETTEXTLENGTH, 0, 0);
2452 ok(11 == len, "expected 11, got %d\n", len);
2454 DestroyWindow(hwEdit);
2456 hwEdit = create_child_editcontrol(0, 0);
2457 hwParent = GetParent(hwEdit);
2458 SetWindowLongPtr(hwParent, GWLP_WNDPROC, (LONG_PTR)dialog_mode_wnd_proc);
2460 zero_dm_messages();
2461 r = SendMessage(hwEdit, WM_KEYDOWN, VK_ESCAPE, 0x10001);
2462 ok(1 == r, "expected 1, got %d\n", r);
2463 test_dm_messages(0, 0, 0, 0);
2464 zero_dm_messages();
2466 r = SendMessage(hwEdit, WM_KEYDOWN, VK_TAB, 0xf0001);
2467 ok(1 == r, "expected 1, got %d\n", r);
2468 test_dm_messages(0, 0, 0, 0);
2469 zero_dm_messages();
2471 msg.hwnd = hwEdit;
2472 msg.message = WM_KEYDOWN;
2473 msg.wParam = VK_TAB;
2474 msg.lParam = 0xf0001;
2475 r = SendMessage(hwEdit, WM_GETDLGCODE, VK_TAB, (LPARAM)&msg);
2476 ok(0x89 == r, "expected 0x89, got 0x%x\n", r);
2477 test_dm_messages(0, 0, 0, 0);
2478 zero_dm_messages();
2480 r = SendMessage(hwEdit, WM_KEYDOWN, VK_TAB, 0xf0001);
2481 ok(1 == r, "expected 1, got %d\n", r);
2482 test_dm_messages(0, 0, 0, 0);
2483 zero_dm_messages();
2485 destroy_child_editcontrol(hwEdit);
2487 hwEdit = create_child_editcontrol(ES_MULTILINE, 0);
2488 hwParent = GetParent(hwEdit);
2489 SetWindowLongPtr(hwParent, GWLP_WNDPROC, (LONG_PTR)dialog_mode_wnd_proc);
2491 r = SendMessage(hwEdit, WM_KEYDOWN, VK_TAB, 0xf0001);
2492 ok(1 == r, "expected 1, got %d\n", r);
2493 test_dm_messages(0, 0, 0, 0);
2494 zero_dm_messages();
2496 msg.hwnd = hwEdit;
2497 msg.message = WM_KEYDOWN;
2498 msg.wParam = VK_ESCAPE;
2499 msg.lParam = 0x10001;
2500 r = SendMessage(hwEdit, WM_GETDLGCODE, VK_ESCAPE, (LPARAM)&msg);
2501 ok(0x8d == r, "expected 0x8d, got 0x%x\n", r);
2502 test_dm_messages(0, 0, 0, 0);
2503 zero_dm_messages();
2505 r = SendMessage(hwEdit, WM_KEYDOWN, VK_ESCAPE, 0x10001);
2506 ok(1 == r, "expected 1, got %d\n", r);
2507 test_dm_messages(0, 0, 0, 0);
2508 zero_dm_messages();
2510 r = SendMessage(hwEdit, WM_KEYDOWN, VK_TAB, 0xf0001);
2511 ok(1 == r, "expected 1, got %d\n", r);
2512 test_dm_messages(0, 0, 0, 1);
2513 zero_dm_messages();
2515 r = SendMessage(hwEdit, WM_KEYDOWN, VK_RETURN, 0x1c0001);
2516 ok(1 == r, "expected 1, got %d\n", r);
2517 test_dm_messages(0, 0, 1, 0);
2518 zero_dm_messages();
2520 hwButton = CreateWindow("BUTTON", "OK", WS_VISIBLE|WS_CHILD|BS_PUSHBUTTON,
2521 100, 100, 50, 20, hwParent, (HMENU)ID_EDITTESTDBUTTON, hinst, NULL);
2522 ok(hwButton!=NULL, "CreateWindow failed with error code %d\n", GetLastError());
2524 r = SendMessage(hwEdit, WM_KEYDOWN, VK_RETURN, 0x1c0001);
2525 ok(1 == r, "expected 1, got %d\n", r);
2526 test_dm_messages(0, 0, 1, 1);
2527 zero_dm_messages();
2529 DestroyWindow(hwButton);
2530 destroy_child_editcontrol(hwEdit);
2533 static void test_EM_GETHANDLE(void)
2535 static const char str0[] = "untouched";
2536 static const char str1[] = "1111+1111+1111#";
2537 static const char str2[] = "2222-2222-2222-2222#";
2538 static const char str3[] = "3333*3333*3333*3333*3333#";
2539 CHAR current[42];
2540 HWND hEdit;
2541 HLOCAL hmem;
2542 HLOCAL hmem2;
2543 HLOCAL halloc;
2544 char *buffer;
2545 int len;
2546 int r;
2548 trace("EDIT: EM_GETHANDLE\n");
2550 /* EM_GETHANDLE is not supported for a single line edit control */
2551 hEdit = create_editcontrol(WS_BORDER, 0);
2552 ok(hEdit != NULL, "got %p (expected != NULL)\n", hEdit);
2554 hmem = (HGLOBAL) SendMessage(hEdit, EM_GETHANDLE, 0, 0);
2555 ok(hmem == NULL, "got %p (expected NULL)\n", hmem);
2556 DestroyWindow(hEdit);
2559 /* EM_GETHANDLE needs a multiline edit control */
2560 hEdit = create_editcontrol(WS_BORDER | ES_MULTILINE, 0);
2561 ok(hEdit != NULL, "got %p (expected != NULL)\n", hEdit);
2563 /* set some text */
2564 r = SendMessageA(hEdit, WM_SETTEXT, 0, (LPARAM)str1);
2565 len = SendMessageA(hEdit, WM_GETTEXTLENGTH, 0, 0);
2566 ok((r == 1) && (len == lstrlenA(str1)), "got %d and %d (expected 1 and %d)\n", r, len, lstrlenA(str1));
2568 lstrcpyA(current, str0);
2569 r = SendMessageA(hEdit, WM_GETTEXT, sizeof(current), (LPARAM)current);
2570 ok((r == lstrlenA(str1)) && !lstrcmpA(current, str1),
2571 "got %d and \"%s\" (expected %d and \"%s\")\n", r, current, lstrlenA(str1), str1);
2573 hmem = (HGLOBAL) SendMessage(hEdit, EM_GETHANDLE, 0, 0);
2574 ok(hmem != NULL, "got %p (expected != NULL)\n", hmem);
2575 /* The buffer belongs to the app now. According to MSDN, the app has to LocalFree the
2576 buffer, LocalAlloc a new buffer and pass it to the edit control with EM_SETHANDLE. */
2578 buffer = LocalLock(hmem);
2579 ok(buffer != NULL, "got %p (expected != NULL)\n", buffer);
2580 len = lstrlenA(buffer);
2581 ok((len == lstrlenA(str1)) && !lstrcmpA(buffer, str1),
2582 "got %d and \"%s\" (expected %d and \"%s\")\n", len, buffer, lstrlenA(str1), str1);
2583 LocalUnlock(hmem);
2585 /* use LocalAlloc first to get a different handle */
2586 halloc = LocalAlloc(LMEM_MOVEABLE, 42);
2587 ok(halloc != NULL, "got %p (expected != NULL)\n", halloc);
2588 /* prepare our new memory */
2589 buffer = LocalLock(halloc);
2590 ok(buffer != NULL, "got %p (expected != NULL)\n", buffer);
2591 lstrcpyA(buffer, str2);
2592 LocalUnlock(halloc);
2594 /* LocalFree the old memory handle before EM_SETHANDLE the new handle */
2595 LocalFree(hmem);
2596 /* use LocalAlloc after the LocalFree to likely consume the handle */
2597 hmem2 = LocalAlloc(LMEM_MOVEABLE, 42);
2598 ok(hmem2 != NULL, "got %p (expected != NULL)\n", hmem2);
2600 SendMessage(hEdit, EM_SETHANDLE, (WPARAM)halloc, 0);
2602 len = SendMessageA(hEdit, WM_GETTEXTLENGTH, 0, 0);
2603 ok(len == lstrlenA(str2), "got %d (expected %d)\n", len, lstrlenA(str2));
2605 lstrcpyA(current, str0);
2606 r = SendMessageA(hEdit, WM_GETTEXT, sizeof(current), (LPARAM)current);
2607 ok((r == lstrlenA(str2)) && !lstrcmpA(current, str2),
2608 "got %d and \"%s\" (expected %d and \"%s\")\n", r, current, lstrlenA(str2), str2);
2610 /* set a different text */
2611 r = SendMessageA(hEdit, WM_SETTEXT, 0, (LPARAM)str3);
2612 len = SendMessageA(hEdit, WM_GETTEXTLENGTH, 0, 0);
2613 ok((r == 1) && (len == lstrlenA(str3)), "got %d and %d (expected 1 and %d)\n", r, len, lstrlenA(str3));
2615 lstrcpyA(current, str0);
2616 r = SendMessageA(hEdit, WM_GETTEXT, sizeof(current), (LPARAM)current);
2617 ok((r == lstrlenA(str3)) && !lstrcmpA(current, str3),
2618 "got %d and \"%s\" (expected %d and \"%s\")\n", r, current, lstrlenA(str3), str3);
2620 LocalFree(hmem2);
2621 DestroyWindow(hEdit);
2623 /* Some apps have bugs ... */
2624 hEdit = create_editcontrol(WS_BORDER | ES_MULTILINE, 0);
2626 /* set some text */
2627 r = SendMessageA(hEdit, WM_SETTEXT, 0, (LPARAM)str1);
2628 len = SendMessageA(hEdit, WM_GETTEXTLENGTH, 0, 0);
2629 ok((r == 1) && (len == lstrlenA(str1)), "got %d and %d (expected 1 and %d)\n", r, len, lstrlenA(str1));
2631 /* everything is normal up to EM_GETHANDLE */
2632 hmem = (HGLOBAL) SendMessage(hEdit, EM_GETHANDLE, 0, 0);
2633 /* Some messages still work while other messages fail.
2634 After LocalFree the memory handle, messages can crash the app */
2636 /* A buggy editor used EM_GETHANDLE twice */
2637 hmem2 = (HGLOBAL) SendMessage(hEdit, EM_GETHANDLE, 0, 0);
2638 ok(hmem2 == hmem, "got %p (expected %p)\n", hmem2, hmem);
2640 /* Let the edit control free the memory handle */
2641 SendMessage(hEdit, EM_SETHANDLE, (WPARAM)hmem2, 0);
2643 DestroyWindow(hEdit);
2647 START_TEST(edit)
2649 BOOL b;
2651 init_function_pointers();
2653 hinst = GetModuleHandleA(NULL);
2654 b = RegisterWindowClasses();
2655 ok (b, "RegisterWindowClasses failed\n");
2656 if (!b) return;
2658 test_edit_control_1();
2659 test_edit_control_2();
2660 test_edit_control_3();
2661 test_edit_control_4();
2662 test_edit_control_5();
2663 test_edit_control_6();
2664 test_edit_control_limittext();
2665 test_edit_control_scroll();
2666 test_margins();
2667 test_margins_font_change();
2668 test_text_position();
2669 test_espassword();
2670 test_undo();
2671 test_enter();
2672 test_tab();
2673 test_edit_dialog();
2674 test_multi_edit_dialog();
2675 test_wantreturn_edit_dialog();
2676 test_singleline_wantreturn_edit_dialog();
2677 test_child_edit_wmkeydown();
2678 test_fontsize();
2679 test_dialogmode();
2680 if (pEndMenu)
2681 test_contextmenu();
2682 else
2683 win_skip("EndMenu is not available\n");
2685 test_EM_GETHANDLE();
2687 UnregisterWindowClasses();