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
25 #include "wine/test.h"
30 #define ES_COMBO 0x200
33 #define ID_EDITTESTDBUTTON 0x123
34 #define ID_EDITTEST2 99
39 COMBINED_SEQ_INDEX
= 0,
49 static struct msg_sequence
*sequences
[NUM_MSG_SEQUENCES
];
52 int en_change
, en_maxtext
, en_update
;
55 static struct edit_notify notifications
;
57 /* try to make sure pending X events have been processed before continuing */
58 static void flush_events(void)
62 int min_timeout
= 100;
63 DWORD time
= GetTickCount() + diff
;
67 if (MsgWaitForMultipleObjects(0, NULL
, FALSE
, min_timeout
, QS_ALLINPUT
) == WAIT_TIMEOUT
)
69 while (PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
))
70 DispatchMessageA(&msg
);
71 diff
= time
- GetTickCount();
75 static INT_PTR CALLBACK
multi_edit_dialog_proc(HWND hdlg
, UINT msg
, WPARAM wparam
, LPARAM lparam
)
77 static int num_ok_commands
= 0;
82 HWND hedit
= GetDlgItem(hdlg
, 1000);
86 /* test cases related to bug 12319 */
88 PostMessageA(hedit
, WM_KEYDOWN
, VK_TAB
, 0xf0001);
89 PostMessageA(hdlg
, WM_USER
, 0xdeadbeef, 0);
92 PostMessageA(hedit
, WM_CHAR
, VK_TAB
, 0xf0001);
93 PostMessageA(hdlg
, WM_USER
, 0xdeadbeef, 0);
96 PostMessageA(hedit
, WM_KEYDOWN
, VK_TAB
, 0xf0001);
97 PostMessageA(hedit
, WM_CHAR
, VK_TAB
, 0xf0001);
98 PostMessageA(hdlg
, WM_USER
, 0xdeadbeef, 0);
101 /* test cases for pressing enter */
104 PostMessageA(hedit
, WM_KEYDOWN
, VK_RETURN
, 0x1c0001);
105 PostMessageA(hdlg
, WM_USER
, 0xdeadbeef, 1);
115 if (HIWORD(wparam
) != BN_CLICKED
)
118 switch (LOWORD(wparam
))
131 HWND hfocus
= GetFocus();
132 HWND hedit
= GetDlgItem(hdlg
, 1000);
133 HWND hedit2
= GetDlgItem(hdlg
, 1001);
134 HWND hedit3
= GetDlgItem(hdlg
, 1002);
136 if (wparam
!= 0xdeadbeef)
143 EndDialog(hdlg
, 1111);
144 else if (hfocus
== hedit2
)
145 EndDialog(hdlg
, 2222);
146 else if (hfocus
== hedit3
)
147 EndDialog(hdlg
, 3333);
149 EndDialog(hdlg
, 4444);
152 if ((hfocus
== hedit
) && (num_ok_commands
== 0))
158 EndDialog(hdlg
, 5555);
164 EndDialog(hdlg
, 333);
174 static INT_PTR CALLBACK
edit_dialog_proc(HWND hdlg
, UINT msg
, WPARAM wparam
, LPARAM lparam
)
180 HWND hedit
= GetDlgItem(hdlg
, 1000);
186 PostMessageA(hedit
, WM_KEYDOWN
, VK_ESCAPE
, 0x10001);
189 PostMessageA(hedit
, WM_KEYDOWN
, VK_RETURN
, 0x1c0001);
192 PostMessageA(hedit
, WM_KEYDOWN
, VK_TAB
, 0xf0001);
193 PostMessageA(hdlg
, WM_USER
, 0xdeadbeef, 1);
196 /* more test cases for WM_CHAR */
198 PostMessageA(hedit
, WM_CHAR
, VK_ESCAPE
, 0x10001);
199 PostMessageA(hdlg
, WM_USER
, 0xdeadbeef, 0);
202 PostMessageA(hedit
, WM_CHAR
, VK_RETURN
, 0x1c0001);
203 PostMessageA(hdlg
, WM_USER
, 0xdeadbeef, 0);
206 PostMessageA(hedit
, WM_CHAR
, VK_TAB
, 0xf0001);
207 PostMessageA(hdlg
, WM_USER
, 0xdeadbeef, 0);
210 /* more test cases for WM_KEYDOWN + WM_CHAR */
212 PostMessageA(hedit
, WM_KEYDOWN
, VK_ESCAPE
, 0x10001);
213 PostMessageA(hedit
, WM_CHAR
, VK_ESCAPE
, 0x10001);
214 PostMessageA(hdlg
, WM_USER
, 0xdeadbeef, 0);
217 PostMessageA(hedit
, WM_KEYDOWN
, VK_RETURN
, 0x1c0001);
218 PostMessageA(hedit
, WM_CHAR
, VK_RETURN
, 0x1c0001);
219 PostMessageA(hdlg
, WM_USER
, 0xdeadbeef, 1);
222 PostMessageA(hedit
, WM_KEYDOWN
, VK_TAB
, 0xf0001);
223 PostMessageA(hedit
, WM_CHAR
, VK_TAB
, 0xf0001);
224 PostMessageA(hdlg
, WM_USER
, 0xdeadbeef, 1);
227 /* multiple tab tests */
229 PostMessageA(hedit
, WM_KEYDOWN
, VK_TAB
, 0xf0001);
230 PostMessageA(hedit
, WM_KEYDOWN
, VK_TAB
, 0xf0001);
231 PostMessageA(hdlg
, WM_USER
, 0xdeadbeef, 2);
234 PostMessageA(hedit
, WM_KEYDOWN
, VK_TAB
, 0xf0001);
235 PostMessageA(hedit
, WM_KEYDOWN
, VK_TAB
, 0xf0001);
236 PostMessageA(hedit
, WM_KEYDOWN
, VK_TAB
, 0xf0001);
237 PostMessageA(hdlg
, WM_USER
, 0xdeadbeef, 2);
247 if (HIWORD(wparam
) != BN_CLICKED
)
250 switch (LOWORD(wparam
))
253 EndDialog(hdlg
, 111);
257 EndDialog(hdlg
, 222);
268 HWND hok
= GetDlgItem(hdlg
, IDOK
);
269 HWND hcancel
= GetDlgItem(hdlg
, IDCANCEL
);
270 HWND hedit
= GetDlgItem(hdlg
, 1000);
271 HWND hfocus
= GetFocus();
273 if (wparam
!= 0xdeadbeef)
279 len
= SendMessageA(hedit
, WM_GETTEXTLENGTH
, 0, 0);
281 EndDialog(hdlg
, 444);
283 EndDialog(hdlg
, 555);
287 len
= SendMessageA(hedit
, WM_GETTEXTLENGTH
, 0, 0);
288 if ((hfocus
== hok
) && len
== 0)
289 EndDialog(hdlg
, 444);
291 EndDialog(hdlg
, 555);
297 else if (hfocus
== hcancel
)
299 else if (hfocus
== hedit
)
306 EndDialog(hdlg
, 555);
312 EndDialog(hdlg
, 333);
322 static INT_PTR CALLBACK
edit_singleline_dialog_proc(HWND hdlg
, UINT msg
, WPARAM wparam
, LPARAM lparam
)
328 HWND hedit
= GetDlgItem(hdlg
, 1000);
332 /* test cases for WM_KEYDOWN */
334 PostMessageA(hedit
, WM_KEYDOWN
, VK_ESCAPE
, 0x10001);
337 PostMessageA(hedit
, WM_KEYDOWN
, VK_RETURN
, 0x1c0001);
340 PostMessageA(hedit
, WM_KEYDOWN
, VK_TAB
, 0xf0001);
341 PostMessageA(hdlg
, WM_USER
, 0xdeadbeef, 1);
344 /* test cases for WM_CHAR */
346 PostMessageA(hedit
, WM_CHAR
, VK_ESCAPE
, 0x10001);
347 PostMessageA(hdlg
, WM_USER
, 0xdeadbeef, 0);
350 PostMessageA(hedit
, WM_CHAR
, VK_RETURN
, 0x1c0001);
351 PostMessageA(hdlg
, WM_USER
, 0xdeadbeef, 0);
354 PostMessageA(hedit
, WM_CHAR
, VK_TAB
, 0xf0001);
355 PostMessageA(hdlg
, WM_USER
, 0xdeadbeef, 0);
358 /* test cases for WM_KEYDOWN + WM_CHAR */
360 PostMessageA(hedit
, WM_KEYDOWN
, VK_ESCAPE
, 0x10001);
361 PostMessageA(hedit
, WM_CHAR
, VK_ESCAPE
, 0x10001);
364 PostMessageA(hedit
, WM_KEYDOWN
, VK_RETURN
, 0x1c0001);
365 PostMessageA(hedit
, WM_CHAR
, VK_RETURN
, 0x1c0001);
368 PostMessageA(hedit
, WM_KEYDOWN
, VK_TAB
, 0xf0001);
369 PostMessageA(hedit
, WM_CHAR
, VK_TAB
, 0xf0001);
370 PostMessageA(hdlg
, WM_USER
, 0xdeadbeef, 1);
380 if (HIWORD(wparam
) != BN_CLICKED
)
383 switch (LOWORD(wparam
))
386 EndDialog(hdlg
, 111);
390 EndDialog(hdlg
, 222);
400 HWND hok
= GetDlgItem(hdlg
, IDOK
);
401 HWND hedit
= GetDlgItem(hdlg
, 1000);
402 HWND hfocus
= GetFocus();
403 int len
= SendMessageA(hedit
, WM_GETTEXTLENGTH
, 0, 0);
405 if (wparam
!= 0xdeadbeef)
411 if ((hfocus
== hedit
) && len
== 0)
412 EndDialog(hdlg
, 444);
414 EndDialog(hdlg
, 555);
418 if ((hfocus
== hok
) && len
== 0)
419 EndDialog(hdlg
, 444);
421 EndDialog(hdlg
, 555);
431 EndDialog(hdlg
, 333);
441 static INT_PTR CALLBACK
edit_wantreturn_dialog_proc(HWND hdlg
, UINT msg
, WPARAM wparam
, LPARAM lparam
)
447 HWND hedit
= GetDlgItem(hdlg
, 1000);
451 /* test cases for WM_KEYDOWN */
453 PostMessageA(hedit
, WM_KEYDOWN
, VK_ESCAPE
, 0x10001);
456 PostMessageA(hedit
, WM_KEYDOWN
, VK_RETURN
, 0x1c0001);
457 PostMessageA(hdlg
, WM_USER
, 0xdeadbeef, 0);
460 PostMessageA(hedit
, WM_KEYDOWN
, VK_TAB
, 0xf0001);
461 PostMessageA(hdlg
, WM_USER
, 0xdeadbeef, 1);
464 /* test cases for WM_CHAR */
466 PostMessageA(hedit
, WM_CHAR
, VK_ESCAPE
, 0x10001);
467 PostMessageA(hdlg
, WM_USER
, 0xdeadbeef, 0);
470 PostMessageA(hedit
, WM_CHAR
, VK_RETURN
, 0x1c0001);
471 PostMessageA(hdlg
, WM_USER
, 0xdeadbeef, 2);
474 PostMessageA(hedit
, WM_CHAR
, VK_TAB
, 0xf0001);
475 PostMessageA(hdlg
, WM_USER
, 0xdeadbeef, 0);
478 /* test cases for WM_KEYDOWN + WM_CHAR */
480 PostMessageA(hedit
, WM_KEYDOWN
, VK_ESCAPE
, 0x10001);
481 PostMessageA(hedit
, WM_CHAR
, VK_ESCAPE
, 0x10001);
482 PostMessageA(hdlg
, WM_USER
, 0xdeadbeef, 0);
485 PostMessageA(hedit
, WM_KEYDOWN
, VK_RETURN
, 0x1c0001);
486 PostMessageA(hedit
, WM_CHAR
, VK_RETURN
, 0x1c0001);
487 PostMessageA(hdlg
, WM_USER
, 0xdeadbeef, 2);
490 PostMessageA(hedit
, WM_KEYDOWN
, VK_TAB
, 0xf0001);
491 PostMessageA(hedit
, WM_CHAR
, VK_TAB
, 0xf0001);
492 PostMessageA(hdlg
, WM_USER
, 0xdeadbeef, 1);
502 if (HIWORD(wparam
) != BN_CLICKED
)
505 switch (LOWORD(wparam
))
508 EndDialog(hdlg
, 111);
512 EndDialog(hdlg
, 222);
522 HWND hok
= GetDlgItem(hdlg
, IDOK
);
523 HWND hedit
= GetDlgItem(hdlg
, 1000);
524 HWND hfocus
= GetFocus();
525 int len
= SendMessageA(hedit
, WM_GETTEXTLENGTH
, 0, 0);
527 if (wparam
!= 0xdeadbeef)
533 if ((hfocus
== hedit
) && len
== 0)
534 EndDialog(hdlg
, 444);
536 EndDialog(hdlg
, 555);
540 if ((hfocus
== hok
) && len
== 0)
541 EndDialog(hdlg
, 444);
543 EndDialog(hdlg
, 555);
547 if ((hfocus
== hedit
) && len
== 2)
548 EndDialog(hdlg
, 444);
550 EndDialog(hdlg
, 555);
560 EndDialog(hdlg
, 333);
570 static HINSTANCE hinst
;
572 static const char szEditTest2Class
[] = "EditTest2Class";
573 static const char szEditTest3Class
[] = "EditTest3Class";
574 static const char szEditTest4Class
[] = "EditTest4Class";
575 static const char szEditTextPositionClass
[] = "EditTextPositionWindowClass";
577 static HWND
create_editcontrol (DWORD style
, DWORD exstyle
)
581 handle
= CreateWindowExA(exstyle
, WC_EDITA
, "Text Text", style
, 10, 10, 300, 300,
582 NULL
, NULL
, hinst
, NULL
);
583 ok (handle
!= NULL
, "CreateWindow EDIT Control failed\n");
585 if (winetest_interactive
)
586 ShowWindow (handle
, SW_SHOW
);
590 static HWND
create_editcontrolW(DWORD style
, DWORD exstyle
)
592 static const WCHAR testtextW
[] = {'T','e','s','t',' ','t','e','x','t',0};
595 handle
= CreateWindowExW(exstyle
, WC_EDITW
, testtextW
, style
, 10, 10, 300, 300,
596 NULL
, NULL
, hinst
, NULL
);
597 ok(handle
!= NULL
, "Failed to create Edit control.\n");
601 static HWND
create_child_editcontrol (DWORD style
, DWORD exstyle
)
607 SetRect(&rect
, 0, 0, 300, 300);
608 b
= AdjustWindowRect(&rect
, WS_OVERLAPPEDWINDOW
, FALSE
);
609 ok(b
, "AdjustWindowRect failed\n");
611 parentWnd
= CreateWindowExA(0,
612 szEditTextPositionClass
,
615 CW_USEDEFAULT
, CW_USEDEFAULT
,
616 rect
.right
- rect
.left
, rect
.bottom
- rect
.top
,
617 NULL
, NULL
, hinst
, NULL
);
618 ok (parentWnd
!= NULL
, "CreateWindow EDIT Test failed\n");
620 editWnd
= CreateWindowExA(exstyle
,
625 parentWnd
, NULL
, hinst
, NULL
);
626 ok (editWnd
!= NULL
, "CreateWindow EDIT Test Text failed\n");
627 if (winetest_interactive
)
628 ShowWindow (parentWnd
, SW_SHOW
);
632 static void destroy_child_editcontrol (HWND hwndEdit
)
634 if (GetParent(hwndEdit
))
635 DestroyWindow(GetParent(hwndEdit
));
637 trace("Edit control has no parent!\n");
638 DestroyWindow(hwndEdit
);
642 static LONG
get_edit_style (HWND hwnd
)
644 return GetWindowLongA( hwnd
, GWL_STYLE
) & (
646 /* FIXME: not implemented
665 static void set_client_height(HWND Wnd
, unsigned Height
)
667 RECT ClientRect
, WindowRect
;
669 GetWindowRect(Wnd
, &WindowRect
);
670 GetClientRect(Wnd
, &ClientRect
);
671 SetWindowPos(Wnd
, NULL
, 0, 0,
672 WindowRect
.right
- WindowRect
.left
,
673 Height
+ (WindowRect
.bottom
- WindowRect
.top
) -
674 (ClientRect
.bottom
- ClientRect
.top
),
675 SWP_NOMOVE
| SWP_NOACTIVATE
| SWP_NOZORDER
);
677 /* Workaround for a bug in Windows' edit control
679 GetWindowRect(Wnd
, &WindowRect
);
680 SetWindowPos(Wnd
, NULL
, 0, 0,
681 WindowRect
.right
- WindowRect
.left
+ 1,
682 WindowRect
.bottom
- WindowRect
.top
+ 1,
683 SWP_NOMOVE
| SWP_NOACTIVATE
| SWP_NOZORDER
);
684 SetWindowPos(Wnd
, NULL
, 0, 0,
685 WindowRect
.right
- WindowRect
.left
,
686 WindowRect
.bottom
- WindowRect
.top
,
687 SWP_NOMOVE
| SWP_NOACTIVATE
| SWP_NOZORDER
);
689 GetClientRect(Wnd
, &ClientRect
);
690 ok(ClientRect
.bottom
- ClientRect
.top
== Height
,
691 "The client height should be %d, but is %ld\n",
692 Height
, ClientRect
.bottom
- ClientRect
.top
);
695 static void test_edit_control_1(void)
702 msMessage
.message
= WM_KEYDOWN
;
704 trace("EDIT: Single line\n");
705 hwEdit
= create_editcontrol(ES_AUTOHSCROLL
| ES_AUTOVSCROLL
, 0);
706 r
= get_edit_style(hwEdit
);
707 ok(r
== (ES_AUTOVSCROLL
| ES_AUTOHSCROLL
), "Wrong style expected 0xc0 got: 0x%lx\n", r
);
708 for (i
= 0; i
< 65535; i
++)
710 msMessage
.wParam
= i
;
711 r
= SendMessageA(hwEdit
, WM_GETDLGCODE
, 0, (LPARAM
) &msMessage
);
712 ok(r
== (DLGC_WANTCHARS
| DLGC_HASSETSEL
| DLGC_WANTARROWS
),
713 "Expected DLGC_WANTCHARS | DLGC_HASSETSEL | DLGC_WANTARROWS got %lx\n", r
);
715 DestroyWindow(hwEdit
);
717 trace("EDIT: Single line want returns\n");
718 hwEdit
= create_editcontrol(ES_WANTRETURN
| ES_AUTOHSCROLL
| ES_AUTOVSCROLL
, 0);
719 r
= get_edit_style(hwEdit
);
720 ok(r
== (ES_AUTOVSCROLL
| ES_AUTOHSCROLL
| ES_WANTRETURN
), "Wrong style expected 0x10c0 got: 0x%lx\n", r
);
721 for (i
= 0; i
< 65535; i
++)
723 msMessage
.wParam
= i
;
724 r
= SendMessageA(hwEdit
, WM_GETDLGCODE
, 0, (LPARAM
) &msMessage
);
725 ok(r
== (DLGC_WANTCHARS
| DLGC_HASSETSEL
| DLGC_WANTARROWS
),
726 "Expected DLGC_WANTCHARS | DLGC_HASSETSEL | DLGC_WANTARROWS got %lx\n", r
);
728 DestroyWindow(hwEdit
);
730 trace("EDIT: Multiline line\n");
731 hwEdit
= create_editcontrol(ES_MULTILINE
| WS_VSCROLL
| ES_AUTOHSCROLL
| ES_AUTOVSCROLL
, 0);
732 r
= get_edit_style(hwEdit
);
733 ok(r
== (ES_AUTOHSCROLL
| ES_AUTOVSCROLL
| ES_MULTILINE
), "Wrong style expected 0xc4 got: 0x%lx\n", r
);
734 for (i
= 0; i
< 65535; i
++)
736 msMessage
.wParam
= i
;
737 r
= SendMessageA(hwEdit
, WM_GETDLGCODE
, 0, (LPARAM
) &msMessage
);
738 ok(r
== (DLGC_WANTCHARS
| DLGC_HASSETSEL
| DLGC_WANTALLKEYS
| DLGC_WANTARROWS
),
739 "Expected DLGC_WANTCHARS | DLGC_HASSETSEL | DLGC_WANTALLKEYS | DLGC_WANTARROWS got %lx\n", r
);
741 DestroyWindow(hwEdit
);
743 trace("EDIT: Multi line want returns\n");
744 hwEdit
= create_editcontrol(ES_MULTILINE
| WS_VSCROLL
| ES_WANTRETURN
| ES_AUTOHSCROLL
| ES_AUTOVSCROLL
, 0);
745 r
= get_edit_style(hwEdit
);
746 ok(r
== (ES_WANTRETURN
| ES_AUTOHSCROLL
| ES_AUTOVSCROLL
| ES_MULTILINE
), "Wrong style expected 0x10c4 got: 0x%lx\n", r
);
747 for (i
= 0; i
< 65535; i
++)
749 msMessage
.wParam
= i
;
750 r
= SendMessageA(hwEdit
, WM_GETDLGCODE
, 0, (LPARAM
) &msMessage
);
751 ok(r
== (DLGC_WANTCHARS
| DLGC_HASSETSEL
| DLGC_WANTALLKEYS
| DLGC_WANTARROWS
),
752 "Expected DLGC_WANTCHARS | DLGC_HASSETSEL | DLGC_WANTALLKEYS | DLGC_WANTARROWS got %lx\n", r
);
754 DestroyWindow(hwEdit
);
757 /* WM_SETTEXT is implemented by selecting all text, and then replacing the
758 * selection. This test checks that the first 'select all' doesn't generate
759 * an UPDATE message which can escape and (via a handler) change the
760 * selection, which would cause WM_SETTEXT to break. This old bug
761 * was fixed 18-Mar-2005; we check here to ensure it doesn't regress.
763 static void test_edit_control_2(void)
765 HWND hwndMain
, phwnd
;
766 char szLocalString
[MAXLEN
];
767 LONG r
, w
= 150, h
= 50;
770 /* Create main and edit windows. */
771 hwndMain
= CreateWindowA(szEditTest2Class
, "ET2", WS_OVERLAPPEDWINDOW
,
772 0, 0, 200, 200, NULL
, NULL
, hinst
, NULL
);
773 ok(hwndMain
!= NULL
, "Failed to create control parent.\n");
774 if (winetest_interactive
)
775 ShowWindow (hwndMain
, SW_SHOW
);
777 hwndET2
= CreateWindowA(WC_EDITA
, NULL
, WS_CHILD
|WS_BORDER
|ES_LEFT
|ES_AUTOHSCROLL
,
778 0, 0, w
, h
, /* important this not be 0 size. */
779 hwndMain
, (HMENU
) ID_EDITTEST2
, hinst
, NULL
);
780 ok(hwndET2
!= NULL
, "Failed to create Edit control.\n");
781 if (winetest_interactive
)
782 ShowWindow (hwndET2
, SW_SHOW
);
784 trace("EDIT: SETTEXT atomicity\n");
785 /* Send messages to "type" in the word 'foo'. */
786 r
= SendMessageA(hwndET2
, WM_CHAR
, 'f', 1);
787 ok(1 == r
, "Expected: %d, got: %ld\n", 1, r
);
788 r
= SendMessageA(hwndET2
, WM_CHAR
, 'o', 1);
789 ok(1 == r
, "Expected: %d, got: %ld\n", 1, r
);
790 r
= SendMessageA(hwndET2
, WM_CHAR
, 'o', 1);
791 ok(1 == r
, "Expected: %d, got: %ld\n", 1, r
);
792 /* 'foo' should have been changed to 'bar' by the UPDATE handler. */
793 GetWindowTextA(hwndET2
, szLocalString
, MAXLEN
);
794 ok(strcmp(szLocalString
, "bar")==0,
795 "Wrong contents of edit: %s\n", szLocalString
);
797 /* try setting the caret before it's visible */
798 r
= SetCaretPos(0, 0);
799 todo_wine
ok(0 == r
, "SetCaretPos succeeded unexpectedly, expected: 0, got: %ld\n", r
);
800 phwnd
= SetFocus(hwndET2
);
801 ok(phwnd
!= NULL
, "SetFocus failed unexpectedly, expected non-zero, got NULL\n");
802 r
= SetCaretPos(0, 0);
803 ok(1 == r
, "SetCaretPos failed unexpectedly, expected: 1, got: %ld\n", r
);
804 r
= GetCaretPos(&cpos
);
805 ok(1 == r
, "GetCaretPos failed unexpectedly, expected: 1, got: %ld\n", r
);
806 ok(cpos
.x
== 0 && cpos
.y
== 0, "Wrong caret position, expected: (0,0), got: (%ld,%ld)\n", cpos
.x
, cpos
.y
);
807 r
= SetCaretPos(-1, -1);
808 ok(1 == r
, "SetCaretPos failed unexpectedly, expected: 1, got: %ld\n", r
);
809 r
= GetCaretPos(&cpos
);
810 ok(1 == r
, "GetCaretPos failed unexpectedly, expected: 1, got: %ld\n", r
);
811 ok(cpos
.x
== -1 && cpos
.y
== -1, "Wrong caret position, expected: (-1,-1), got: (%ld,%ld)\n", cpos
.x
, cpos
.y
);
812 r
= SetCaretPos(w
<< 1, h
<< 1);
813 ok(1 == r
, "SetCaretPos failed unexpectedly, expected: 1, got: %ld\n", r
);
814 r
= GetCaretPos(&cpos
);
815 ok(1 == r
, "GetCaretPos failed unexpectedly, expected: 1, got: %ld\n", r
);
816 ok(cpos
.x
== (w
<< 1) && cpos
.y
== (h
<< 1), "Wrong caret position, expected: (%ld,%ld), got: (%ld,%ld)\n", w
<< 1, h
<< 1, cpos
.x
, cpos
.y
);
817 r
= SetCaretPos(w
, h
);
818 ok(1 == r
, "SetCaretPos failed unexpectedly, expected: 1, got: %ld\n", r
);
819 r
= GetCaretPos(&cpos
);
820 ok(1 == r
, "GetCaretPos failed unexpectedly, expected: 1, got: %ld\n", r
);
821 ok(cpos
.x
== w
&& cpos
.y
== h
, "Wrong caret position, expected: (%ld,%ld), got: (%ld,%ld)\n", w
, h
, cpos
.x
, cpos
.y
);
822 r
= SetCaretPos(w
- 1, h
- 1);
823 ok(1 == r
, "SetCaretPos failed unexpectedly, expected: 1, got: %ld\n", r
);
824 r
= GetCaretPos(&cpos
);
825 ok(1 == r
, "GetCaretPos failed unexpectedly, expected: 1, got: %ld\n", r
);
826 ok(cpos
.x
== (w
- 1) && cpos
.y
== (h
- 1), "Wrong caret position, expected: (%ld,%ld), got: (%ld,%ld)\n", w
- 1, h
- 1, cpos
.x
, cpos
.y
);
828 DestroyWindow(hwndET2
);
829 DestroyWindow(hwndMain
);
832 static void ET2_check_change(void)
834 char szLocalString
[MAXLEN
];
835 /* This EN_UPDATE handler changes any 'foo' to 'bar'. */
836 GetWindowTextA(hwndET2
, szLocalString
, MAXLEN
);
837 if (!strcmp(szLocalString
, "foo"))
839 strcpy(szLocalString
, "bar");
840 SendMessageA(hwndET2
, WM_SETTEXT
, 0, (LPARAM
)szLocalString
);
842 /* always leave the cursor at the end. */
843 SendMessageA(hwndET2
, EM_SETSEL
, MAXLEN
- 1, MAXLEN
- 1);
846 static void ET2_OnCommand(HWND hwnd
, int id
, HWND hwndCtl
, UINT codeNotify
)
848 if (id
== ID_EDITTEST2
&& codeNotify
== EN_UPDATE
)
852 static LRESULT CALLBACK
ET2_WndProc(HWND hwnd
, UINT iMsg
, WPARAM wParam
, LPARAM lParam
)
857 ET2_OnCommand(hwnd
, LOWORD(wParam
), (HWND
)lParam
, HIWORD(wParam
));
860 return DefWindowProcA(hwnd
, iMsg
, wParam
, lParam
);
863 static void zero_notify(void)
865 notifications
.en_change
= 0;
866 notifications
.en_maxtext
= 0;
867 notifications
.en_update
= 0;
870 #define test_notify(enchange, enmaxtext, enupdate) \
872 ok(notifications.en_change == enchange, "expected %d EN_CHANGE notifications, " \
873 "got %d\n", enchange, notifications.en_change); \
874 ok(notifications.en_maxtext == enmaxtext, "expected %d EN_MAXTEXT notifications, " \
875 "got %d\n", enmaxtext, notifications.en_maxtext); \
876 ok(notifications.en_update == enupdate, "expected %d EN_UPDATE notifications, " \
877 "got %d\n", enupdate, notifications.en_update); \
880 static LRESULT CALLBACK
edit3_wnd_procA(HWND hWnd
, UINT msg
, WPARAM wParam
, LPARAM lParam
)
885 switch (HIWORD(wParam
))
888 notifications
.en_maxtext
++;
891 notifications
.en_update
++;
894 notifications
.en_change
++;
899 return DefWindowProcA(hWnd
, msg
, wParam
, lParam
);
902 static LRESULT CALLBACK
parent_wnd_proc(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
904 static LONG defwndproc_counter
= 0;
905 struct message msg
= { 0 };
908 msg
.message
= message
;
909 msg
.flags
= sent
|wparam
|id
;
910 if (defwndproc_counter
) msg
.flags
|= defwinproc
;
914 if (message
!= WM_IME_SETCONTEXT
&&
915 message
!= WM_IME_NOTIFY
&&
916 message
!= WM_GETICON
&&
917 message
!= WM_DWMNCRENDERINGCHANGED
&&
918 message
!= WM_GETMINMAXINFO
&&
919 message
!= WM_PAINT
&&
920 message
!= WM_CTLCOLOREDIT
&&
921 message
!= WM_WINDOWPOSCHANGING
&&
922 message
!= WM_WINDOWPOSCHANGED
&&
923 message
!= WM_MOVE
&&
924 message
!= WM_MOUSEACTIVATE
&&
927 add_message(sequences
, COMBINED_SEQ_INDEX
, &msg
);
930 defwndproc_counter
++;
931 ret
= DefWindowProcA(hwnd
, message
, wParam
, lParam
);
932 defwndproc_counter
--;
937 static LRESULT CALLBACK
edit_subclass_proc(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
939 WNDPROC oldproc
= (WNDPROC
)GetWindowLongPtrA(hwnd
, GWLP_USERDATA
);
940 static LONG defwndproc_counter
= 0;
941 struct message msg
= { 0 };
944 msg
.message
= message
;
945 msg
.flags
= sent
|wparam
|id
;
946 if (defwndproc_counter
) msg
.flags
|= defwinproc
;
950 if (message
!= WM_IME_SETCONTEXT
&&
951 message
!= WM_IME_NOTIFY
)
953 add_message(sequences
, COMBINED_SEQ_INDEX
, &msg
);
956 defwndproc_counter
++;
957 if (IsWindowUnicode(hwnd
))
958 ret
= CallWindowProcW(oldproc
, hwnd
, message
, wParam
, lParam
);
960 ret
= CallWindowProcA(oldproc
, hwnd
, message
, wParam
, lParam
);
961 defwndproc_counter
--;
966 /* Test behaviour of WM_SETTEXT, WM_REPLACESEL and notifications sent in response
969 static void test_edit_control_3(void)
971 static const char *str
= "this is a long string.";
972 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.";
978 dpi
= GetDeviceCaps(hDC
, LOGPIXELSY
);
979 ReleaseDC(NULL
, hDC
);
981 trace("EDIT: Test notifications\n");
983 hParent
= CreateWindowExA(0,
987 CW_USEDEFAULT
, CW_USEDEFAULT
, 10, 10,
988 NULL
, NULL
, NULL
, NULL
);
989 ok(hParent
!= NULL
, "Failed to create control parent.\n");
991 trace("EDIT: Single line, no ES_AUTOHSCROLL\n");
992 hWnd
= CreateWindowExA(0, WC_EDITA
, NULL
, 0, 10, 10, 50, 50, hParent
, NULL
, NULL
, NULL
);
993 ok(hWnd
!= NULL
, "Failed to create Edit control.\n");
996 SendMessageA(hWnd
, EM_REPLACESEL
, 0, (LPARAM
)str
);
997 len
= SendMessageA(hWnd
, WM_GETTEXTLENGTH
, 0, 0);
998 if (len
== lstrlenA(str
)) /* Win 8 */
999 test_notify(1, 0, 1);
1001 test_notify(1, 1, 1);
1003 SendMessageA(hWnd
, WM_SETTEXT
, 0, (LPARAM
)"");
1005 SendMessageA(hWnd
, EM_REPLACESEL
, 0, (LPARAM
)"a");
1006 len
= SendMessageA(hWnd
, WM_GETTEXTLENGTH
, 0, 0);
1007 ok(1 == len
, "wrong text length, expected 1, got %d\n", len
);
1008 test_notify(1, 0, 1);
1011 SendMessageA(hWnd
, WM_SETTEXT
, 0, (LPARAM
)str
);
1012 len
= SendMessageA(hWnd
, WM_GETTEXTLENGTH
, 0, 0);
1013 ok(lstrlenA(str
) == len
, "text shouldn't have been truncated\n");
1014 test_notify(1, 0, 1);
1016 len
= SendMessageA(hWnd
, EM_GETSEL
, 0, 0);
1017 ok(LOWORD(len
)==0, "Unexpected start position for selection %d\n", LOWORD(len
));
1018 ok(HIWORD(len
)==0, "Unexpected end position for selection %d\n", HIWORD(len
));
1019 SendMessageA(hParent
, WM_SETFOCUS
, 0, (LPARAM
)hWnd
);
1020 len
= SendMessageA(hWnd
, EM_GETSEL
, 0, 0);
1021 ok(LOWORD(len
)==0, "Unexpected start position for selection %d\n", LOWORD(len
));
1022 ok(HIWORD(len
)==0, "Unexpected end position for selection %d\n", HIWORD(len
));
1024 SendMessageA(hWnd
, EM_SETLIMITTEXT
, 5, 0);
1026 SendMessageA(hWnd
, WM_SETTEXT
, 0, (LPARAM
)"");
1028 SendMessageA(hWnd
, EM_REPLACESEL
, 0, (LPARAM
)str
);
1029 len
= SendMessageA(hWnd
, WM_GETTEXTLENGTH
, 0, 0);
1030 ok(5 == len
, "text should have been truncated to limit, expected 5, got %d\n", len
);
1031 test_notify(1, 1, 1);
1034 SendMessageA(hWnd
, WM_SETTEXT
, 0, (LPARAM
)str
);
1035 len
= SendMessageA(hWnd
, WM_GETTEXTLENGTH
, 0, 0);
1036 ok(lstrlenA(str
) == len
, "text shouldn't have been truncated\n");
1037 test_notify(1, 0, 1);
1039 DestroyWindow(hWnd
);
1041 trace("EDIT: Single line, ES_AUTOHSCROLL\n");
1042 hWnd
= CreateWindowExA(0, WC_EDITA
, NULL
, ES_AUTOHSCROLL
, 10, 10, 50, 50, hParent
, NULL
, NULL
, NULL
);
1043 ok(hWnd
!= NULL
, "Failed to create Edit control.\n");
1046 SendMessageA(hWnd
, EM_REPLACESEL
, 0, (LPARAM
)str
);
1047 len
= SendMessageA(hWnd
, WM_GETTEXTLENGTH
, 0, 0);
1048 ok(lstrlenA(str
) == len
, "text shouldn't have been truncated\n");
1049 test_notify(1, 0, 1);
1052 SendMessageA(hWnd
, WM_SETTEXT
, 0, (LPARAM
)str
);
1053 len
= SendMessageA(hWnd
, WM_GETTEXTLENGTH
, 0, 0);
1054 ok(lstrlenA(str
) == len
, "text shouldn't have been truncated\n");
1055 test_notify(1, 0, 1);
1057 SendMessageA(hWnd
, WM_SETTEXT
, 0, (LPARAM
)"");
1059 SendMessageA(hWnd
, EM_REPLACESEL
, 0, (LPARAM
)str2
);
1060 len
= SendMessageA(hWnd
, WM_GETTEXTLENGTH
, 0, 0);
1061 ok(lstrlenA(str2
) == len
, "text shouldn't have been truncated\n");
1062 test_notify(1, 0, 1);
1065 SendMessageA(hWnd
, WM_SETTEXT
, 0, (LPARAM
)str2
);
1066 len
= SendMessageA(hWnd
, WM_GETTEXTLENGTH
, 0, 0);
1067 ok(lstrlenA(str2
) == len
, "text shouldn't have been truncated\n");
1068 test_notify(1, 0, 1);
1070 SendMessageA(hWnd
, EM_SETLIMITTEXT
, 5, 0);
1072 SendMessageA(hWnd
, WM_SETTEXT
, 0, (LPARAM
)"");
1074 SendMessageA(hWnd
, EM_REPLACESEL
, 0, (LPARAM
)str
);
1075 len
= SendMessageA(hWnd
, WM_GETTEXTLENGTH
, 0, 0);
1076 ok(5 == len
, "text should have been truncated to limit, expected 5, got %d\n", len
);
1077 test_notify(1, 1, 1);
1080 SendMessageA(hWnd
, WM_SETTEXT
, 0, (LPARAM
)str
);
1081 len
= SendMessageA(hWnd
, WM_GETTEXTLENGTH
, 0, 0);
1082 ok(lstrlenA(str
) == len
, "text shouldn't have been truncated\n");
1083 test_notify(1, 0, 1);
1085 DestroyWindow(hWnd
);
1087 trace("EDIT: Multline, no ES_AUTOHSCROLL, no ES_AUTOVSCROLL\n");
1088 hWnd
= CreateWindowExA(0, WC_EDITA
, NULL
, ES_MULTILINE
,
1089 10, 10, (50 * dpi
) / 96, (50 * dpi
) / 96,
1090 hParent
, NULL
, NULL
, NULL
);
1091 ok(hWnd
!= NULL
, "Failed to create Edit control.\n");
1094 SendMessageA(hWnd
, EM_REPLACESEL
, 0, (LPARAM
)str
);
1095 len
= SendMessageA(hWnd
, WM_GETTEXTLENGTH
, 0, 0);
1096 if (len
== lstrlenA(str
)) /* Win 8 */
1097 test_notify(1, 0, 1);
1100 ok(0 == len
, "text should have been truncated, expected 0, got %d\n", len
);
1101 test_notify(1, 1, 1);
1104 SendMessageA(hWnd
, WM_SETTEXT
, 0, (LPARAM
)"");
1106 SendMessageA(hWnd
, EM_REPLACESEL
, 0, (LPARAM
)"a");
1107 len
= SendMessageA(hWnd
, WM_GETTEXTLENGTH
, 0, 0);
1108 ok(1 == SendMessageA(hWnd
, WM_GETTEXTLENGTH
, 0, 0), "wrong text length, expected 1, got %d\n", len
);
1109 test_notify(1, 0, 1);
1112 SendMessageA(hWnd
, WM_SETTEXT
, 0, (LPARAM
)str
);
1113 len
= SendMessageA(hWnd
, WM_GETTEXTLENGTH
, 0, 0);
1114 ok(lstrlenA(str
) == len
, "text shouldn't have been truncated\n");
1115 test_notify(0, 0, 0);
1117 SendMessageA(hWnd
, EM_SETLIMITTEXT
, 5, 0);
1119 SendMessageA(hWnd
, WM_SETTEXT
, 0, (LPARAM
)"");
1121 SendMessageA(hWnd
, EM_REPLACESEL
, 0, (LPARAM
)str
);
1122 len
= SendMessageA(hWnd
, WM_GETTEXTLENGTH
, 0, 0);
1123 ok(5 == len
, "text should have been truncated to limit, expected 5, got %d\n", len
);
1124 test_notify(1, 1, 1);
1127 SendMessageA(hWnd
, WM_SETTEXT
, 0, (LPARAM
)str
);
1128 len
= SendMessageA(hWnd
, WM_GETTEXTLENGTH
, 0, 0);
1129 ok(lstrlenA(str
) == len
, "text shouldn't have been truncated\n");
1130 test_notify(0, 0, 0);
1132 DestroyWindow(hWnd
);
1134 trace("EDIT: Multline, ES_AUTOHSCROLL, no ES_AUTOVSCROLL\n");
1135 hWnd
= CreateWindowExA(0, WC_EDITA
, NULL
, ES_MULTILINE
| ES_AUTOHSCROLL
,
1136 10, 10, (50 * dpi
) / 96, (50 * dpi
) / 96,
1137 hParent
, NULL
, NULL
, NULL
);
1138 ok(hWnd
!= NULL
, "Failed to create Edit control.\n");
1141 SendMessageA(hWnd
, EM_REPLACESEL
, 0, (LPARAM
)str2
);
1142 len
= SendMessageA(hWnd
, WM_GETTEXTLENGTH
, 0, 0);
1143 ok(0 == len
, "text should have been truncated, expected 0, got %d\n", len
);
1144 test_notify(1, 1, 1);
1146 SendMessageA(hWnd
, WM_SETTEXT
, 0, (LPARAM
)"");
1148 SendMessageA(hWnd
, EM_REPLACESEL
, 0, (LPARAM
)"a");
1149 len
= SendMessageA(hWnd
, WM_GETTEXTLENGTH
, 0, 0);
1150 ok(1 == SendMessageA(hWnd
, WM_GETTEXTLENGTH
, 0, 0), "wrong text length, expected 1, got %d\n", len
);
1151 test_notify(1, 0, 1);
1154 SendMessageA(hWnd
, WM_SETTEXT
, 0, (LPARAM
)str2
);
1155 len
= SendMessageA(hWnd
, WM_GETTEXTLENGTH
, 0, 0);
1156 ok(lstrlenA(str2
) == len
, "text shouldn't have been truncated\n");
1157 test_notify(0, 0, 0);
1159 SendMessageA(hWnd
, EM_SETLIMITTEXT
, 5, 0);
1161 SendMessageA(hWnd
, WM_SETTEXT
, 0, (LPARAM
)"");
1163 SendMessageA(hWnd
, EM_REPLACESEL
, 0, (LPARAM
)str2
);
1164 len
= SendMessageA(hWnd
, WM_GETTEXTLENGTH
, 0, 0);
1165 ok(5 == len
, "text should have been truncated to limit, expected 5, got %d\n", len
);
1166 test_notify(1, 1, 1);
1169 SendMessageA(hWnd
, WM_SETTEXT
, 0, (LPARAM
)str2
);
1170 len
= SendMessageA(hWnd
, WM_GETTEXTLENGTH
, 0, 0);
1171 ok(lstrlenA(str2
) == len
, "text shouldn't have been truncated\n");
1172 test_notify(0, 0, 0);
1174 DestroyWindow(hWnd
);
1176 trace("EDIT: Multline, ES_AUTOHSCROLL and ES_AUTOVSCROLL\n");
1177 hWnd
= CreateWindowExA(0, WC_EDITA
, NULL
, ES_MULTILINE
| ES_AUTOHSCROLL
| ES_AUTOVSCROLL
,
1178 10, 10, 50, 50, hParent
, NULL
, NULL
, NULL
);
1179 ok(hWnd
!= NULL
, "Failed to create Edit control.\n");
1182 SendMessageA(hWnd
, EM_REPLACESEL
, 0, (LPARAM
)str2
);
1183 len
= SendMessageA(hWnd
, WM_GETTEXTLENGTH
, 0, 0);
1184 ok(lstrlenA(str2
) == len
, "text shouldn't have been truncated\n");
1185 test_notify(1, 0, 1);
1188 SendMessageA(hWnd
, WM_SETTEXT
, 0, (LPARAM
)str2
);
1189 len
= SendMessageA(hWnd
, WM_GETTEXTLENGTH
, 0, 0);
1190 ok(lstrlenA(str2
) == len
, "text shouldn't have been truncated\n");
1191 test_notify(0, 0, 0);
1193 SendMessageA(hWnd
, EM_SETLIMITTEXT
, 5, 0);
1195 SendMessageA(hWnd
, WM_SETTEXT
, 0, (LPARAM
)"");
1197 SendMessageA(hWnd
, EM_REPLACESEL
, 0, (LPARAM
)str2
);
1198 len
= SendMessageA(hWnd
, WM_GETTEXTLENGTH
, 0, 0);
1199 ok(5 == len
, "text should have been truncated to limit, expected 5, got %d\n", len
);
1200 test_notify(1, 1, 1);
1203 SendMessageA(hWnd
, WM_SETTEXT
, 0, (LPARAM
)str2
);
1204 len
= SendMessageA(hWnd
, WM_GETTEXTLENGTH
, 0, 0);
1205 ok(lstrlenA(str2
) == len
, "text shouldn't have been truncated\n");
1206 test_notify(0, 0, 0);
1208 DestroyWindow(hWnd
);
1211 static void test_char_from_pos(void)
1213 int lo
, hi
, mid
, ret
, i
;
1218 hwEdit
= create_editcontrol(ES_AUTOHSCROLL
| ES_AUTOVSCROLL
, 0);
1219 SendMessageA(hwEdit
, WM_SETTEXT
, 0, (LPARAM
)"aa");
1220 lo
= LOWORD(SendMessageA(hwEdit
, EM_POSFROMCHAR
, 0, 0));
1221 hi
= LOWORD(SendMessageA(hwEdit
, EM_POSFROMCHAR
, 1, 0));
1222 mid
= lo
+ (hi
- lo
) / 2;
1224 for (i
= lo
; i
< mid
; i
++)
1226 ret
= LOWORD(SendMessageA(hwEdit
, EM_CHARFROMPOS
, 0, i
));
1227 ok(0 == ret
, "expected 0 got %d\n", ret
);
1230 for (i
= mid
; i
<= hi
; i
++)
1232 ret
= LOWORD(SendMessageA(hwEdit
, EM_CHARFROMPOS
, 0, i
));
1233 ok(1 == ret
, "expected 1 got %d\n", ret
);
1236 ret
= SendMessageA(hwEdit
, EM_POSFROMCHAR
, 2, 0);
1237 ok(-1 == ret
, "expected -1 got %d\n", ret
);
1238 DestroyWindow(hwEdit
);
1240 hwEdit
= create_editcontrol(ES_RIGHT
| ES_AUTOHSCROLL
| ES_AUTOVSCROLL
, 0);
1241 SendMessageA(hwEdit
, WM_SETTEXT
, 0, (LPARAM
)"aa");
1242 lo
= LOWORD(SendMessageA(hwEdit
, EM_POSFROMCHAR
, 0, 0));
1243 hi
= LOWORD(SendMessageA(hwEdit
, EM_POSFROMCHAR
, 1, 0));
1244 mid
= lo
+ (hi
- lo
) / 2;
1246 for (i
= lo
; i
< mid
; i
++)
1248 ret
= LOWORD(SendMessageA(hwEdit
, EM_CHARFROMPOS
, 0, i
));
1249 ok(0 == ret
, "expected 0 got %d\n", ret
);
1252 for (i
= mid
; i
<= hi
; i
++)
1254 ret
= LOWORD(SendMessageA(hwEdit
, EM_CHARFROMPOS
, 0, i
));
1255 ok(1 == ret
, "expected 1 got %d\n", ret
);
1258 ret
= SendMessageA(hwEdit
, EM_POSFROMCHAR
, 2, 0);
1259 ok(-1 == ret
, "expected -1 got %d\n", ret
);
1260 DestroyWindow(hwEdit
);
1262 hwEdit
= create_editcontrol(ES_CENTER
| ES_AUTOHSCROLL
| ES_AUTOVSCROLL
, 0);
1263 SendMessageA(hwEdit
, WM_SETTEXT
, 0, (LPARAM
)"aa");
1264 lo
= LOWORD(SendMessageA(hwEdit
, EM_POSFROMCHAR
, 0, 0));
1265 hi
= LOWORD(SendMessageA(hwEdit
, EM_POSFROMCHAR
, 1, 0));
1266 mid
= lo
+ (hi
- lo
) / 2;
1268 for (i
= lo
; i
< mid
; i
++)
1270 ret
= LOWORD(SendMessageA(hwEdit
, EM_CHARFROMPOS
, 0, i
));
1271 ok(0 == ret
, "expected 0 got %d\n", ret
);
1274 for (i
= mid
; i
<= hi
; i
++)
1276 ret
= LOWORD(SendMessageA(hwEdit
, EM_CHARFROMPOS
, 0, i
));
1277 ok(1 == ret
, "expected 1 got %d\n", ret
);
1280 ret
= SendMessageA(hwEdit
, EM_POSFROMCHAR
, 2, 0);
1281 ok(-1 == ret
, "expected -1 got %d\n", ret
);
1282 DestroyWindow(hwEdit
);
1284 hwEdit
= create_editcontrol(ES_MULTILINE
| ES_AUTOHSCROLL
| ES_AUTOVSCROLL
, 0);
1285 SendMessageA(hwEdit
, WM_SETTEXT
, 0, (LPARAM
)"aa");
1286 lo
= LOWORD(SendMessageA(hwEdit
, EM_POSFROMCHAR
, 0, 0));
1287 hi
= LOWORD(SendMessageA(hwEdit
, EM_POSFROMCHAR
, 1, 0));
1288 mid
= lo
+ (hi
- lo
) / 2 + 1;
1290 for (i
= lo
; i
< mid
; i
++)
1292 ret
= LOWORD(SendMessageA(hwEdit
, EM_CHARFROMPOS
, 0, i
));
1293 ok((0 == ret
|| 1 == ret
/* Vista */), "expected 0 or 1 got %d\n", ret
);
1296 for (i
= mid
; i
<= hi
; i
++)
1298 ret
= LOWORD(SendMessageA(hwEdit
, EM_CHARFROMPOS
, 0, i
));
1299 ok(1 == ret
, "expected 1 got %d\n", ret
);
1302 ret
= SendMessageA(hwEdit
, EM_POSFROMCHAR
, 2, 0);
1303 ok(-1 == ret
, "expected -1 got %d\n", ret
);
1304 DestroyWindow(hwEdit
);
1306 hwEdit
= create_editcontrol(ES_MULTILINE
| ES_RIGHT
| ES_AUTOHSCROLL
| ES_AUTOVSCROLL
, 0);
1307 SendMessageA(hwEdit
, WM_SETTEXT
, 0, (LPARAM
)"aa");
1308 lo
= LOWORD(SendMessageA(hwEdit
, EM_POSFROMCHAR
, 0, 0));
1309 hi
= LOWORD(SendMessageA(hwEdit
, EM_POSFROMCHAR
, 1, 0));
1310 mid
= lo
+ (hi
- lo
) / 2 + 1;
1312 for (i
= lo
; i
< mid
; i
++)
1314 ret
= LOWORD(SendMessageA(hwEdit
, EM_CHARFROMPOS
, 0, i
));
1315 ok((0 == ret
|| 1 == ret
/* Vista */), "expected 0 or 1 got %d\n", ret
);
1318 for (i
= mid
; i
<= hi
; i
++)
1320 ret
= LOWORD(SendMessageA(hwEdit
, EM_CHARFROMPOS
, 0, i
));
1321 ok(1 == ret
, "expected 1 got %d\n", ret
);
1324 ret
= SendMessageA(hwEdit
, EM_POSFROMCHAR
, 2, 0);
1325 ok(-1 == ret
, "expected -1 got %d\n", ret
);
1326 DestroyWindow(hwEdit
);
1328 hwEdit
= create_editcontrol(ES_MULTILINE
| ES_CENTER
| ES_AUTOHSCROLL
| ES_AUTOVSCROLL
, 0);
1329 SendMessageA(hwEdit
, WM_SETTEXT
, 0, (LPARAM
)"aa");
1330 lo
= LOWORD(SendMessageA(hwEdit
, EM_POSFROMCHAR
, 0, 0));
1331 hi
= LOWORD(SendMessageA(hwEdit
, EM_POSFROMCHAR
, 1, 0));
1332 mid
= lo
+ (hi
- lo
) / 2 + 1;
1334 for (i
= lo
; i
< mid
; i
++)
1336 ret
= LOWORD(SendMessageA(hwEdit
, EM_CHARFROMPOS
, 0, i
));
1337 ok((0 == ret
|| 1 == ret
/* Vista */), "expected 0 or 1 got %d\n", ret
);
1340 for (i
= mid
; i
<= hi
; i
++)
1342 ret
= LOWORD(SendMessageA(hwEdit
, EM_CHARFROMPOS
, 0, i
));
1343 ok(1 == ret
, "expected 1 got %d\n", ret
);
1346 ret
= SendMessageA(hwEdit
, EM_POSFROMCHAR
, 2, 0);
1347 ok(-1 == ret
, "expected -1 got %d\n", ret
);
1348 DestroyWindow(hwEdit
);
1350 /* Scrolled to the right with partially visible line, position on next line. */
1351 hwEdit
= create_editcontrol(ES_MULTILINE
| ES_AUTOHSCROLL
| ES_AUTOVSCROLL
, 0);
1354 GetTextExtentPoint32A(dc
, "w", 1, &size
);
1355 ReleaseDC(hwEdit
, dc
);
1357 SetWindowPos(hwEdit
, NULL
, 0, 0, size
.cx
* 15, size
.cy
* 5, SWP_NOMOVE
| SWP_NOZORDER
);
1358 SendMessageA(hwEdit
, WM_SETTEXT
, 0, (LPARAM
)"wwwwwwwwwwwwwwwwwwww\r\n\r\n");
1359 SendMessageA(hwEdit
, EM_SETSEL
, 40, 40);
1361 lo
= (short)SendMessageA(hwEdit
, EM_POSFROMCHAR
, 22, 0);
1362 ret
= (short)SendMessageA(hwEdit
, EM_POSFROMCHAR
, 20, 0);
1363 ret
-= 20 * size
.cx
; /* Calculate expected position, 20 characters back. */
1364 ok(ret
== lo
, "Unexpected position %d vs %d.\n", lo
, ret
);
1366 DestroyWindow(hwEdit
);
1369 /* Test if creating edit control without ES_AUTOHSCROLL and ES_AUTOVSCROLL
1370 * truncates text that doesn't fit.
1372 static void test_edit_control_5(void)
1374 static const char *str
= "test\r\ntest";
1378 RECT rc1
= { 10, 10, 11, 11};
1381 /* first show that a non-child won't do for this test */
1382 hWnd
= CreateWindowExA(0, WC_EDITA
, str
, 0, 10, 10, 1, 1, NULL
, NULL
, NULL
, NULL
);
1383 ok(hWnd
!= NULL
, "Failed to create Edit control.\n");
1385 /* size of non-child edit control is (much) bigger than requested */
1386 GetWindowRect( hWnd
, &rc
);
1387 ok( rc
.right
- rc
.left
> 20, "size of the window (%ld) is smaller than expected\n",
1388 rc
.right
- rc
.left
);
1389 DestroyWindow(hWnd
);
1390 /* so create a parent, and give it edit controls children to test with */
1391 parentWnd
= CreateWindowExA(0,
1392 szEditTextPositionClass
,
1393 "Edit Test", WS_VISIBLE
|
1394 WS_OVERLAPPEDWINDOW
,
1395 CW_USEDEFAULT
, CW_USEDEFAULT
,
1397 NULL
, NULL
, hinst
, NULL
);
1398 ok(parentWnd
!= NULL
, "Failed to create control parent.\n");
1399 ShowWindow( parentWnd
, SW_SHOW
);
1401 hWnd
= CreateWindowExA(0, WC_EDITA
, str
, WS_VISIBLE
| WS_BORDER
| WS_CHILD
,
1402 rc1
.left
, rc1
.top
, rc1
.right
- rc1
.left
, rc1
.bottom
- rc1
.top
,
1403 parentWnd
, NULL
, NULL
, NULL
);
1404 ok(hWnd
!= NULL
, "Failed to create Edit control.\n");
1405 GetClientRect( hWnd
, &rc
);
1406 ok( rc
.right
== rc1
.right
- rc1
.left
&& rc
.bottom
== rc1
.bottom
- rc1
.top
,
1407 "Client rectangle not the expected size %s\n", wine_dbgstr_rect( &rc
));
1408 len
= SendMessageA(hWnd
, WM_GETTEXTLENGTH
, 0, 0);
1409 ok(lstrlenA(str
) == len
, "text shouldn't have been truncated\n");
1410 DestroyWindow(hWnd
);
1412 hWnd
= CreateWindowExA(0, WC_EDITA
, str
, WS_CHILD
| ES_MULTILINE
,
1413 rc1
.left
, rc1
.top
, rc1
.right
- rc1
.left
, rc1
.bottom
- rc1
.top
,
1414 parentWnd
, NULL
, NULL
, NULL
);
1415 ok(hWnd
!= NULL
, "Failed to create Edit control.\n");
1416 GetClientRect( hWnd
, &rc
);
1417 ok( rc
.right
== rc1
.right
- rc1
.left
&& rc
.bottom
== rc1
.bottom
- rc1
.top
,
1418 "Client rectangle not the expected size %s\n", wine_dbgstr_rect( &rc
));
1419 len
= SendMessageA(hWnd
, WM_GETTEXTLENGTH
, 0, 0);
1420 ok(lstrlenA(str
) == len
, "text shouldn't have been truncated\n");
1421 DestroyWindow(hWnd
);
1422 DestroyWindow(parentWnd
);
1425 /* Test WM_GETTEXT processing
1426 * after destroy messages
1428 static void test_edit_control_6(void)
1430 static const char *str
= "test\r\ntest";
1435 hWnd
= CreateWindowExA(0, "EDIT", "Test", 0, 10, 10, 1, 1, NULL
, NULL
, hinst
, NULL
);
1436 ok(hWnd
!= NULL
, "Failed to create edit control.\n");
1438 ret
= SendMessageA(hWnd
, WM_SETTEXT
, 0, (LPARAM
)str
);
1439 ok(ret
== TRUE
, "Expected %d, got %ld\n", TRUE
, ret
);
1440 ret
= SendMessageA(hWnd
, WM_GETTEXT
, MAXLEN
, (LPARAM
)buf
);
1441 ok(ret
== strlen(str
), "Expected %s, got len %ld\n", str
, ret
);
1442 ok(!strcmp(buf
, str
), "Expected %s, got %s\n", str
, buf
);
1445 ret
= SendMessageA(hWnd
, WM_DESTROY
, 0, 0);
1447 ok(ret
== 1, "Unexpected return value %ld\n", ret
);
1448 ret
= SendMessageA(hWnd
, WM_GETTEXT
, MAXLEN
, (LPARAM
)buf
);
1449 ok(ret
== strlen(str
), "Expected %s, got len %ld\n", str
, ret
);
1450 ok(!strcmp(buf
, str
), "Expected %s, got %s\n", str
, buf
);
1453 ret
= SendMessageA(hWnd
, WM_NCDESTROY
, 0, 0);
1454 ok(ret
== 0, "Expected 0, got %ld\n", ret
);
1455 ret
= SendMessageA(hWnd
, WM_GETTEXT
, MAXLEN
, (LPARAM
)buf
);
1457 ok(ret
== strlen("Test"), "Unexpected text length %ld\n", ret
);
1458 ok(!strcmp(buf
, "Test"), "Unexpected text %s\n", buf
);
1460 DestroyWindow(hWnd
);
1463 static void test_edit_control_limittext(void)
1468 /* Test default limit for single-line control */
1469 trace("EDIT: buffer limit for single-line\n");
1470 hwEdit
= create_editcontrol(ES_AUTOHSCROLL
| ES_AUTOVSCROLL
, 0);
1471 r
= SendMessageA(hwEdit
, EM_GETLIMITTEXT
, 0, 0);
1472 ok(r
== 30000, "Incorrect default text limit, expected 30000 got %lu\n", r
);
1473 SendMessageA(hwEdit
, EM_SETLIMITTEXT
, 0, 0);
1474 r
= SendMessageA(hwEdit
, EM_GETLIMITTEXT
, 0, 0);
1475 ok( r
== 2147483646, "got limit %lu (expected 2147483646)\n", r
);
1476 DestroyWindow(hwEdit
);
1478 /* Test default limit for multi-line control */
1479 trace("EDIT: buffer limit for multi-line\n");
1480 hwEdit
= create_editcontrol(ES_MULTILINE
| WS_VSCROLL
| ES_AUTOHSCROLL
| ES_AUTOVSCROLL
, 0);
1481 r
= SendMessageA(hwEdit
, EM_GETLIMITTEXT
, 0, 0);
1482 ok(r
== 30000, "Incorrect default text limit, expected 30000 got %lu\n", r
);
1483 SendMessageA(hwEdit
, EM_SETLIMITTEXT
, 0, 0);
1484 r
= SendMessageA(hwEdit
, EM_GETLIMITTEXT
, 0, 0);
1485 ok( r
== 4294967295U, "got limit %lu (expected 4294967295)\n", r
);
1486 DestroyWindow(hwEdit
);
1489 /* Test EM_SCROLL */
1490 static void test_edit_control_scroll(void)
1492 static const char *single_line_str
= "a";
1493 static const char *multiline_str
= "Test\r\nText";
1497 /* Check the return value when EM_SCROLL doesn't scroll
1498 * anything. Should not return true unless any lines were actually
1500 hwEdit
= CreateWindowA(WC_EDITA
, single_line_str
, WS_VSCROLL
| ES_MULTILINE
,
1501 1, 1, 100, 100, NULL
, NULL
, hinst
, NULL
);
1502 ok(hwEdit
!= NULL
, "Failed to create Edit control.\n");
1504 ret
= SendMessageA(hwEdit
, EM_SCROLL
, SB_PAGEDOWN
, 0);
1505 ok(!ret
, "Returned %lx, expected 0.\n", ret
);
1507 ret
= SendMessageA(hwEdit
, EM_SCROLL
, SB_PAGEUP
, 0);
1508 ok(!ret
, "Returned %lx, expected 0.\n", ret
);
1510 ret
= SendMessageA(hwEdit
, EM_SCROLL
, SB_LINEUP
, 0);
1511 ok(!ret
, "Returned %lx, expected 0.\n", ret
);
1513 ret
= SendMessageA(hwEdit
, EM_SCROLL
, SB_LINEDOWN
, 0);
1514 ok(!ret
, "Returned %lx, expected 0.\n", ret
);
1516 DestroyWindow (hwEdit
);
1518 /* SB_PAGEDOWN while at the beginning of a buffer with few lines
1519 should not cause EM_SCROLL to return a negative value of
1520 scrolled lines that would put us "before" the beginning. */
1521 hwEdit
= CreateWindowA(WC_EDITA
, multiline_str
, WS_VSCROLL
| ES_MULTILINE
,
1522 0, 0, 100, 100, NULL
, NULL
, hinst
, NULL
);
1523 ok(hwEdit
!= NULL
, "Failed to create Edit control.\n");
1525 ret
= SendMessageA(hwEdit
, EM_SCROLL
, SB_PAGEDOWN
, 0);
1526 ok(!ret
, "Returned %lx, expected 0.\n", ret
);
1528 DestroyWindow (hwEdit
);
1531 static BOOL
is_cjk(HDC dc
)
1533 const DWORD FS_DBCS_MASK
= FS_JISJAPAN
|FS_CHINESESIMP
|FS_WANSUNG
|FS_CHINESETRAD
|FS_JOHAB
;
1536 switch (GdiGetCodePage(dc
)) {
1537 case 932: case 936: case 949: case 950: case 1361:
1540 return (GetTextCharsetInfo(dc
, &fs
, 0) != DEFAULT_CHARSET
&&
1541 (fs
.fsCsb
[0] & FS_DBCS_MASK
));
1545 static void test_margins_usefontinfo(UINT charset
)
1554 INT margins
, threshold
, expect
, empty_expect
;
1555 const UINT small_margins
= MAKELONG(1, 5);
1557 memset(&lf
, 0, sizeof(lf
));
1559 lf
.lfWeight
= FW_NORMAL
;
1560 lf
.lfCharSet
= charset
;
1561 strcpy(lf
.lfFaceName
, "Tahoma");
1563 hfont
= CreateFontIndirectA(&lf
);
1564 ok(hfont
!= NULL
, "got %p\n", hfont
);
1566 /* Big window rectangle */
1567 hwnd
= CreateWindowExA(0, "Edit", "A", WS_POPUP
, 0, 0, 5000, 1000, NULL
, NULL
, NULL
, NULL
);
1568 ok(hwnd
!= NULL
, "got %p\n", hwnd
);
1569 GetClientRect(hwnd
, &rect
);
1570 ok(!IsRectEmpty(&rect
), "got rect %s\n", wine_dbgstr_rect(&rect
));
1573 hfont
= SelectObject(hdc
, hfont
);
1574 size
.cx
= GdiGetCharDimensions( hdc
, &tm
, &size
.cy
);
1575 if ((charset
!= tm
.tmCharSet
&& charset
!= DEFAULT_CHARSET
) ||
1576 !(tm
.tmPitchAndFamily
& (TMPF_TRUETYPE
| TMPF_VECTOR
))) {
1577 skip("%s for charset %d isn't available\n", lf
.lfFaceName
, charset
);
1578 hfont
= SelectObject(hdc
, hfont
);
1579 ReleaseDC(hwnd
, hdc
);
1580 DestroyWindow(hwnd
);
1581 DeleteObject(hfont
);
1584 expect
= MAKELONG(size
.cx
/ 2, size
.cx
/ 2);
1585 hfont
= SelectObject(hdc
, hfont
);
1586 ReleaseDC(hwnd
, hdc
);
1588 margins
= SendMessageA(hwnd
, EM_GETMARGINS
, 0, 0);
1589 ok(margins
== 0, "got %x\n", margins
);
1590 SendMessageA(hwnd
, WM_SETFONT
, (WPARAM
)hfont
, MAKELPARAM(TRUE
, 0));
1591 SendMessageA(hwnd
, EM_SETMARGINS
, EC_LEFTMARGIN
| EC_RIGHTMARGIN
, MAKELONG(EC_USEFONTINFO
, EC_USEFONTINFO
));
1592 expect
= SendMessageA(hwnd
, EM_GETMARGINS
, 0, 0);
1593 DestroyWindow(hwnd
);
1595 threshold
= HIWORD(expect
) + LOWORD(expect
) + size
.cx
* 2;
1596 empty_expect
= threshold
> 80 ? small_margins
: expect
;
1598 /* Size below the threshold, margins remain unchanged */
1599 hwnd
= CreateWindowExA(0, "Edit", "A", WS_POPUP
, 0, 0, threshold
- 1, 100, NULL
, NULL
, NULL
, NULL
);
1600 ok(hwnd
!= NULL
, "got %p\n", hwnd
);
1601 GetClientRect(hwnd
, &rect
);
1602 ok(!IsRectEmpty(&rect
), "got rect %s\n", wine_dbgstr_rect(&rect
));
1604 margins
= SendMessageA(hwnd
, EM_GETMARGINS
, 0, 0);
1605 ok(margins
== 0, "got %x\n", margins
);
1607 SendMessageA(hwnd
, WM_SETFONT
, (WPARAM
)hfont
, MAKELPARAM(TRUE
, 0));
1608 SendMessageA(hwnd
, EM_SETMARGINS
, EC_LEFTMARGIN
| EC_RIGHTMARGIN
, small_margins
);
1609 SendMessageA(hwnd
, EM_SETMARGINS
, EC_LEFTMARGIN
| EC_RIGHTMARGIN
, MAKELONG(EC_USEFONTINFO
, EC_USEFONTINFO
));
1610 margins
= SendMessageA(hwnd
, EM_GETMARGINS
, 0, 0);
1611 ok(margins
== small_margins
, "%d: got %d, %d\n", charset
, HIWORD(margins
), LOWORD(margins
));
1612 DestroyWindow(hwnd
);
1614 /* Size at the threshold, margins become non-zero */
1615 hwnd
= CreateWindowExA(0, "Edit", "A", WS_POPUP
, 0, 0, threshold
, 100, NULL
, NULL
, NULL
, NULL
);
1616 ok(hwnd
!= NULL
, "got %p\n", hwnd
);
1617 GetClientRect(hwnd
, &rect
);
1618 ok(!IsRectEmpty(&rect
), "got rect %s\n", wine_dbgstr_rect(&rect
));
1620 margins
= SendMessageA(hwnd
, EM_GETMARGINS
, 0, 0);
1621 ok(margins
== 0, "got %x\n", margins
);
1623 SendMessageA(hwnd
, WM_SETFONT
, (WPARAM
)hfont
, MAKELPARAM(TRUE
, 0));
1624 SendMessageA(hwnd
, EM_SETMARGINS
, EC_LEFTMARGIN
| EC_RIGHTMARGIN
, small_margins
);
1625 SendMessageA(hwnd
, EM_SETMARGINS
, EC_LEFTMARGIN
| EC_RIGHTMARGIN
, MAKELONG(EC_USEFONTINFO
, EC_USEFONTINFO
));
1626 margins
= SendMessageA(hwnd
, EM_GETMARGINS
, 0, 0);
1627 ok(margins
== expect
, "%d: got %d, %d\n", charset
, HIWORD(margins
), LOWORD(margins
));
1628 DestroyWindow(hwnd
);
1631 hwnd
= CreateWindowExA(0, "Edit", "A", WS_POPUP
, 0, 0, 0, 0, NULL
, NULL
, NULL
, NULL
);
1632 ok(hwnd
!= NULL
, "got %p\n", hwnd
);
1633 GetClientRect(hwnd
, &rect
);
1634 ok(IsRectEmpty(&rect
), "got rect %s\n", wine_dbgstr_rect(&rect
));
1636 margins
= SendMessageA(hwnd
, EM_GETMARGINS
, 0, 0);
1637 ok(margins
== 0, "got %x\n", margins
);
1639 SendMessageA(hwnd
, WM_SETFONT
, (WPARAM
)hfont
, MAKELPARAM(TRUE
, 0));
1640 SendMessageA(hwnd
, EM_SETMARGINS
, EC_LEFTMARGIN
| EC_RIGHTMARGIN
, small_margins
);
1641 SendMessageA(hwnd
, EM_SETMARGINS
, EC_LEFTMARGIN
| EC_RIGHTMARGIN
, MAKELONG(EC_USEFONTINFO
, EC_USEFONTINFO
));
1642 margins
= SendMessageA(hwnd
, EM_GETMARGINS
, 0, 0);
1643 ok(margins
== empty_expect
, "%d: got %d, %d\n", charset
, HIWORD(margins
), LOWORD(margins
));
1644 DestroyWindow(hwnd
);
1646 DeleteObject(hfont
);
1649 static INT
get_cjk_fontinfo_margin(INT width
, INT side_bearing
)
1652 if (side_bearing
< 0)
1653 margin
= min(-side_bearing
, width
/2);
1659 static DWORD
get_cjk_font_margins(HDC hdc
)
1665 if (!GetCharABCWidthsW(hdc
, 0, 255, abc
))
1669 for (i
= 0; i
< ARRAY_SIZE(abc
); i
++) {
1670 if (-abc
[i
].abcA
> right
) right
= -abc
[i
].abcA
;
1671 if (-abc
[i
].abcC
> left
) left
= -abc
[i
].abcC
;
1673 return MAKELONG(left
, right
);
1676 static void test_margins_default(const char* facename
, UINT charset
)
1686 INT margins
, expect
, font_expect
;
1687 const UINT small_margins
= MAKELONG(1, 5);
1688 const WCHAR EditW
[] = {'E','d','i','t',0}, strW
[] = {'W',0};
1689 struct char_width_info
{
1690 INT lsb
, rsb
, unknown
;
1693 BOOL (WINAPI
*pGetCharWidthInfo
)(HDC
, struct char_width_info
*);
1695 hgdi32
= GetModuleHandleA("gdi32.dll");
1696 pGetCharWidthInfo
= (void *)GetProcAddress(hgdi32
, "GetCharWidthInfo");
1698 memset(&lf
, 0, sizeof(lf
));
1700 lf
.lfWeight
= FW_NORMAL
;
1701 lf
.lfCharSet
= charset
;
1702 strcpy(lf
.lfFaceName
, facename
);
1704 hfont
= CreateFontIndirectA(&lf
);
1705 ok(hfont
!= NULL
, "got %p\n", hfont
);
1707 /* Unicode version */
1708 hwnd
= CreateWindowExW(0, EditW
, strW
, WS_POPUP
, 0, 0, 5000, 1000, NULL
, NULL
, NULL
, NULL
);
1709 ok(hwnd
!= NULL
, "got %p\n", hwnd
);
1710 GetClientRect(hwnd
, &rect
);
1711 ok(!IsRectEmpty(&rect
), "got rect %s\n", wine_dbgstr_rect(&rect
));
1714 hfont
= SelectObject(hdc
, hfont
);
1715 size
.cx
= GdiGetCharDimensions( hdc
, &tm
, &size
.cy
);
1716 if ((charset
!= tm
.tmCharSet
&& charset
!= DEFAULT_CHARSET
) ||
1717 !(tm
.tmPitchAndFamily
& (TMPF_TRUETYPE
| TMPF_VECTOR
))) {
1718 skip("%s for charset %d isn't available\n", lf
.lfFaceName
, charset
);
1719 hfont
= SelectObject(hdc
, hfont
);
1720 ReleaseDC(hwnd
, hdc
);
1721 DestroyWindow(hwnd
);
1722 DeleteObject(hfont
);
1726 if (cjk
&& pGetCharWidthInfo
&& pGetCharWidthInfo(hdc
, &info
)) {
1729 left
= get_cjk_fontinfo_margin(size
.cx
, info
.lsb
);
1730 right
= get_cjk_fontinfo_margin(size
.cx
, info
.rsb
);
1731 expect
= MAKELONG(left
, right
);
1733 font_expect
= get_cjk_font_margins(hdc
);
1735 /* In this case, margins aren't updated */
1736 font_expect
= small_margins
;
1739 font_expect
= expect
= MAKELONG(size
.cx
/ 2, size
.cx
/ 2);
1741 hfont
= SelectObject(hdc
, hfont
);
1742 ReleaseDC(hwnd
, hdc
);
1744 margins
= SendMessageA(hwnd
, EM_GETMARGINS
, 0, 0);
1745 ok(margins
== 0, "got %x\n", margins
);
1746 SendMessageA(hwnd
, EM_SETMARGINS
, EC_LEFTMARGIN
| EC_RIGHTMARGIN
, small_margins
);
1747 SendMessageA(hwnd
, WM_SETFONT
, (WPARAM
)hfont
, MAKELPARAM(TRUE
, 0));
1748 margins
= SendMessageA(hwnd
, EM_GETMARGINS
, 0, 0);
1749 ok(margins
== font_expect
, "%s:%d: got %d, %d\n", facename
, charset
, HIWORD(margins
), LOWORD(margins
));
1750 SendMessageA(hwnd
, EM_SETMARGINS
, EC_LEFTMARGIN
| EC_RIGHTMARGIN
, small_margins
);
1751 SendMessageA(hwnd
, EM_SETMARGINS
, EC_LEFTMARGIN
| EC_RIGHTMARGIN
, MAKELONG(EC_USEFONTINFO
, EC_USEFONTINFO
));
1752 margins
= SendMessageA(hwnd
, EM_GETMARGINS
, 0, 0);
1753 ok(margins
== expect
, "%s:%d: expected %d, %d, got %d, %d\n", facename
, charset
, HIWORD(expect
), LOWORD(expect
), HIWORD(margins
), LOWORD(margins
));
1754 DestroyWindow(hwnd
);
1757 hwnd
= CreateWindowExA(0, "Edit", "A", WS_POPUP
, 0, 0, 5000, 1000, NULL
, NULL
, NULL
, NULL
);
1758 ok(hwnd
!= NULL
, "got %p\n", hwnd
);
1759 GetClientRect(hwnd
, &rect
);
1760 ok(!IsRectEmpty(&rect
), "got rect %s\n", wine_dbgstr_rect(&rect
));
1762 margins
= SendMessageA(hwnd
, EM_GETMARGINS
, 0, 0);
1763 ok(margins
== 0, "got %x\n", margins
);
1764 SendMessageA(hwnd
, EM_SETMARGINS
, EC_LEFTMARGIN
| EC_RIGHTMARGIN
, small_margins
);
1765 SendMessageA(hwnd
, WM_SETFONT
, (WPARAM
)hfont
, MAKELPARAM(TRUE
, 0));
1766 margins
= SendMessageA(hwnd
, EM_GETMARGINS
, 0, 0);
1767 ok(margins
== font_expect
, "%s:%d: got %d, %d\n", facename
, charset
, HIWORD(margins
), LOWORD(margins
));
1768 SendMessageA(hwnd
, EM_SETMARGINS
, EC_LEFTMARGIN
| EC_RIGHTMARGIN
, small_margins
);
1769 SendMessageA(hwnd
, EM_SETMARGINS
, EC_LEFTMARGIN
| EC_RIGHTMARGIN
, MAKELONG(EC_USEFONTINFO
, EC_USEFONTINFO
));
1770 margins
= SendMessageA(hwnd
, EM_GETMARGINS
, 0, 0);
1771 ok(margins
== expect
, "%s:%d: expected %d, %d, got %d, %d\n", facename
, charset
, HIWORD(expect
), LOWORD(expect
), HIWORD(margins
), LOWORD(margins
));
1772 DestroyWindow(hwnd
);
1774 DeleteObject(hfont
);
1777 static INT CALLBACK
find_font_proc(const LOGFONTA
*elf
, const TEXTMETRICA
*ntm
, DWORD type
, LPARAM lParam
)
1782 static BOOL
is_font_installed(const char*name
)
1784 HDC hdc
= GetDC(NULL
);
1787 if (!EnumFontFamiliesA(hdc
, name
, find_font_proc
, 0))
1790 ReleaseDC(NULL
, hdc
);
1794 static WNDPROC orig_class_proc
;
1796 static LRESULT CALLBACK
test_class_proc(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
1804 result
= CallWindowProcA(orig_class_proc
, hwnd
, message
, wParam
, lParam
);
1806 memset(&rect
, 0, sizeof(rect
));
1807 SendMessageA(hwnd
, EM_GETRECT
, 0, (LPARAM
)&rect
);
1808 ok(!rect
.right
&& !rect
.bottom
, "Invalid size after NCCREATE: %ld x %ld\n", rect
.right
, rect
.bottom
);
1810 /* test that messages between WM_NCCREATE and WM_CREATE
1811 don't crash or cause unexpected behavior */
1812 r
= SendMessageA(hwnd
, EM_SETSEL
, 0, 0);
1813 ok(r
== 1, "Returned %Id, expected 1.\n", r
);
1814 r
= SendMessageA(hwnd
, WM_SIZE
, 0, 0x00100010);
1815 todo_wine
ok(r
== 1, "Returned %Id, expected 1.\n", r
);
1816 r
= SendMessageA(hwnd
, EM_LINESCROLL
, 1, 1);
1817 ok(r
== 1, "Returned %Id, expected 1.\n", r
);
1822 /* test that messages between WM_NCCREATE and WM_CREATE
1823 don't crash or cause unexpected behavior */
1824 r
= SendMessageA(hwnd
, EM_SETSEL
, 0, 0);
1825 ok(r
== 1, "Returned %Id, expected 1.\n", r
);
1826 r
= SendMessageA(hwnd
, WM_SIZE
, 0, 0x00100010);
1827 todo_wine
ok(r
== 1, "Returned %Id, expected 1.\n", r
);
1828 r
= SendMessageA(hwnd
, EM_LINESCROLL
, 1, 1);
1829 ok(r
== 1, "Returned %Id, expected 1.\n", r
);
1834 return CallWindowProcA(orig_class_proc
, hwnd
, message
, wParam
, lParam
);
1837 static void test_initialization(void)
1844 ret
= GetClassInfoA(NULL
, "Edit", &cls
);
1845 ok(ret
, "Failed to get class info.\n");
1847 orig_class_proc
= cls
.lpfnWndProc
;
1848 cls
.lpfnWndProc
= test_class_proc
;
1849 cls
.lpszClassName
= "TestClassName";
1851 atom
= RegisterClassA(&cls
);
1852 ok(atom
!= 0, "Failed to register class.\n");
1854 hwEdit
= CreateWindowExA(0, (LPCSTR
)MAKEINTATOM(atom
), "Text Text",
1855 ES_MULTILINE
| WS_BORDER
| ES_AUTOHSCROLL
| ES_AUTOVSCROLL
| WS_VSCROLL
,
1856 10, 10, 300, 300, NULL
, NULL
, hinst
, NULL
);
1857 ok(hwEdit
!= NULL
, "Failed to create a window.\n");
1859 DestroyWindow(hwEdit
);
1860 UnregisterClassA((LPCSTR
)MAKEINTATOM(atom
), hinst
);
1863 static void test_margins(void)
1865 DWORD old_margins
, new_margins
;
1866 RECT old_rect
, new_rect
;
1867 INT old_right_margin
;
1870 hwEdit
= create_editcontrol(WS_BORDER
| ES_AUTOHSCROLL
| ES_AUTOVSCROLL
, 0);
1872 old_margins
= SendMessageA(hwEdit
, EM_GETMARGINS
, 0, 0);
1873 old_right_margin
= HIWORD(old_margins
);
1875 /* Check if setting the margins works */
1877 SendMessageA(hwEdit
, EM_SETMARGINS
, EC_LEFTMARGIN
, MAKELONG(10, 0));
1878 new_margins
= SendMessageA(hwEdit
, EM_GETMARGINS
, 0, 0);
1879 ok(LOWORD(new_margins
) == 10, "Wrong left margin: %d\n", LOWORD(new_margins
));
1880 ok(HIWORD(new_margins
) == old_right_margin
, "Wrong right margin: %d\n", HIWORD(new_margins
));
1882 SendMessageA(hwEdit
, EM_SETMARGINS
, EC_RIGHTMARGIN
, MAKELONG(0, 10));
1883 new_margins
= SendMessageA(hwEdit
, EM_GETMARGINS
, 0, 0);
1884 ok(LOWORD(new_margins
) == 10, "Wrong left margin: %d\n", LOWORD(new_margins
));
1885 ok(HIWORD(new_margins
) == 10, "Wrong right margin: %d\n", HIWORD(new_margins
));
1887 /* The size of the rectangle must decrease if we increase the margin */
1889 SendMessageA(hwEdit
, EM_SETMARGINS
, EC_LEFTMARGIN
| EC_RIGHTMARGIN
, MAKELONG(5, 5));
1890 SendMessageA(hwEdit
, EM_GETRECT
, 0, (LPARAM
)&old_rect
);
1891 SendMessageA(hwEdit
, EM_SETMARGINS
, EC_LEFTMARGIN
| EC_RIGHTMARGIN
, MAKELONG(15, 20));
1892 SendMessageA(hwEdit
, EM_GETRECT
, 0, (LPARAM
)&new_rect
);
1893 ok(new_rect
.left
== old_rect
.left
+ 10, "The left border of the rectangle is wrong\n");
1894 ok(new_rect
.right
== old_rect
.right
- 15, "The right border of the rectangle is wrong\n");
1895 ok(new_rect
.top
== old_rect
.top
, "The top border of the rectangle must not change\n");
1896 ok(new_rect
.bottom
== old_rect
.bottom
, "The bottom border of the rectangle must not change\n");
1898 /* If we set the margin to same value as the current margin,
1899 the rectangle must not change */
1901 SendMessageA(hwEdit
, EM_SETMARGINS
, EC_LEFTMARGIN
| EC_RIGHTMARGIN
, MAKELONG(10, 10));
1902 SetRect(&old_rect
, 1, 1, 99, 99);
1903 SendMessageA(hwEdit
, EM_SETRECT
, 0, (LPARAM
)&old_rect
);
1904 SendMessageA(hwEdit
, EM_GETRECT
, 0, (LPARAM
)&old_rect
);
1905 SendMessageA(hwEdit
, EM_SETMARGINS
, EC_LEFTMARGIN
| EC_RIGHTMARGIN
, MAKELONG(10, 10));
1906 SendMessageA(hwEdit
, EM_GETRECT
, 0, (LPARAM
)&new_rect
);
1907 ok(EqualRect(&old_rect
, &new_rect
), "The border of the rectangle has changed\n");
1909 /* The lParam argument of the WM_SIZE message should be ignored. */
1911 SendMessageA(hwEdit
, EM_GETRECT
, 0, (LPARAM
)&old_rect
);
1912 SendMessageA(hwEdit
, WM_SIZE
, SIZE_RESTORED
, 0);
1913 SendMessageA(hwEdit
, EM_GETRECT
, 0, (LPARAM
)&new_rect
);
1914 ok(EqualRect(&old_rect
, &new_rect
), "The border of the rectangle has changed\n");
1915 SendMessageA(hwEdit
, WM_SIZE
, SIZE_MINIMIZED
, 0);
1916 SendMessageA(hwEdit
, EM_GETRECT
, 0, (LPARAM
)&new_rect
);
1917 ok(EqualRect(&old_rect
, &new_rect
), "The border of the rectangle has changed\n");
1918 SendMessageA(hwEdit
, WM_SIZE
, SIZE_MAXIMIZED
, 0);
1919 SendMessageA(hwEdit
, EM_GETRECT
, 0, (LPARAM
)&new_rect
);
1920 ok(EqualRect(&old_rect
, &new_rect
), "The border of the rectangle has changed\n");
1921 SendMessageA(hwEdit
, WM_SIZE
, SIZE_RESTORED
, MAKELONG(10, 10));
1922 SendMessageA(hwEdit
, EM_GETRECT
, 0, (LPARAM
)&new_rect
);
1923 ok(EqualRect(&old_rect
, &new_rect
), "The border of the rectangle has changed\n");
1925 DestroyWindow (hwEdit
);
1927 test_margins_usefontinfo(ANSI_CHARSET
);
1928 test_margins_usefontinfo(EASTEUROPE_CHARSET
);
1930 test_margins_usefontinfo(SHIFTJIS_CHARSET
);
1931 test_margins_usefontinfo(HANGUL_CHARSET
);
1932 test_margins_usefontinfo(CHINESEBIG5_CHARSET
);
1933 /* Don't test JOHAB_CHARSET. Treated as CJK by Win 8,
1934 but not by < Win 8 and Win 10. */
1936 test_margins_usefontinfo(DEFAULT_CHARSET
);
1938 test_margins_default("Tahoma", ANSI_CHARSET
);
1939 test_margins_default("Tahoma", EASTEUROPE_CHARSET
);
1941 test_margins_default("Tahoma", HANGUL_CHARSET
);
1942 test_margins_default("Tahoma", CHINESEBIG5_CHARSET
);
1944 if (is_font_installed("MS PGothic")) {
1945 test_margins_default("MS PGothic", SHIFTJIS_CHARSET
);
1946 test_margins_default("MS PGothic", GREEK_CHARSET
);
1949 skip("MS PGothic is not available, skipping some margin tests\n");
1951 if (is_font_installed("Ume P Gothic")) {
1952 test_margins_default("Ume P Gothic", SHIFTJIS_CHARSET
);
1953 test_margins_default("Ume P Gothic", GREEK_CHARSET
);
1956 skip("Ume P Gothic is not available, skipping some margin tests\n");
1958 if (is_font_installed("SimSun")) {
1959 test_margins_default("SimSun", GB2312_CHARSET
);
1960 test_margins_default("SimSun", ANSI_CHARSET
);
1963 skip("SimSun is not available, skipping some margin tests\n");
1966 static void test_margins_font_change(void)
1968 DWORD margins
, font_margins
;
1969 HFONT hfont
, hfont2
;
1973 if (!is_font_installed("Arial"))
1975 skip("Arial not found - skipping font change margin tests\n");
1979 hwEdit
= create_child_editcontrol(0, 0);
1981 SetWindowPos(hwEdit
, NULL
, 10, 10, 1000, 100, SWP_NOZORDER
| SWP_NOACTIVATE
);
1983 memset(&lf
, 0, sizeof(lf
));
1984 strcpy(lf
.lfFaceName
, "Arial");
1986 lf
.lfCharSet
= GREEK_CHARSET
; /* to avoid associated charset feature */
1987 hfont
= CreateFontIndirectA(&lf
);
1989 hfont2
= CreateFontIndirectA(&lf
);
1991 SendMessageA(hwEdit
, WM_SETFONT
, (WPARAM
)hfont
, 0);
1992 font_margins
= SendMessageA(hwEdit
, EM_GETMARGINS
, 0, 0);
1993 ok(LOWORD(font_margins
) != 0, "got %d\n", LOWORD(font_margins
));
1994 ok(HIWORD(font_margins
) != 0, "got %d\n", HIWORD(font_margins
));
1996 /* With 'small' edit controls, test that the margin doesn't get set */
1997 SetWindowPos(hwEdit
, NULL
, 10, 10, 16, 100, SWP_NOZORDER
| SWP_NOACTIVATE
);
1998 SendMessageA(hwEdit
, EM_SETMARGINS
, EC_LEFTMARGIN
| EC_RIGHTMARGIN
, MAKELONG(0,0));
1999 SendMessageA(hwEdit
, WM_SETFONT
, (WPARAM
)hfont
, 0);
2000 margins
= SendMessageA(hwEdit
, EM_GETMARGINS
, 0, 0);
2001 ok(LOWORD(margins
) == 0, "got %d\n", LOWORD(margins
));
2002 ok(HIWORD(margins
) == 0, "got %d\n", HIWORD(margins
));
2004 SendMessageA(hwEdit
, EM_SETMARGINS
, EC_LEFTMARGIN
| EC_RIGHTMARGIN
, MAKELONG(1,0));
2005 SendMessageA(hwEdit
, WM_SETFONT
, (WPARAM
)hfont
, 0);
2006 margins
= SendMessageA(hwEdit
, EM_GETMARGINS
, 0, 0);
2007 ok(LOWORD(margins
) == 1, "got %d\n", LOWORD(margins
));
2008 ok(HIWORD(margins
) == 0, "got %d\n", HIWORD(margins
));
2010 SendMessageA(hwEdit
, EM_SETMARGINS
, EC_LEFTMARGIN
| EC_RIGHTMARGIN
, MAKELONG(1,1));
2011 SendMessageA(hwEdit
, WM_SETFONT
, (WPARAM
)hfont
, 0);
2012 margins
= SendMessageA(hwEdit
, EM_GETMARGINS
, 0, 0);
2013 ok(LOWORD(margins
) == 1, "got %d\n", LOWORD(margins
));
2014 ok(HIWORD(margins
) == 1, "got %d\n", HIWORD(margins
));
2016 SendMessageA(hwEdit
, EM_SETMARGINS
, EC_LEFTMARGIN
| EC_RIGHTMARGIN
, MAKELONG(EC_USEFONTINFO
,EC_USEFONTINFO
));
2017 margins
= SendMessageA(hwEdit
, EM_GETMARGINS
, 0, 0);
2018 ok(LOWORD(margins
) == 1, "got %d\n", LOWORD(margins
));
2019 ok(HIWORD(margins
) == 1, "got %d\n", HIWORD(margins
));
2021 SendMessageA(hwEdit
, WM_SETFONT
, (WPARAM
)hfont2
, 0);
2022 margins
= SendMessageA(hwEdit
, EM_GETMARGINS
, 0, 0);
2023 ok(LOWORD(margins
) == 1, "got %d\n", LOWORD(margins
));
2024 ok(HIWORD(margins
) == 1, "got %d\n", HIWORD(margins
));
2026 /* Above a certain size threshold then the margin is updated */
2027 SetWindowPos(hwEdit
, NULL
, 10, 10, 1000, 100, SWP_NOZORDER
| SWP_NOACTIVATE
);
2028 SendMessageA(hwEdit
, EM_SETMARGINS
, EC_LEFTMARGIN
| EC_RIGHTMARGIN
, MAKELONG(1,0));
2029 SendMessageA(hwEdit
, WM_SETFONT
, (WPARAM
)hfont
, 0);
2030 margins
= SendMessageA(hwEdit
, EM_GETMARGINS
, 0, 0);
2031 ok(LOWORD(margins
) == LOWORD(font_margins
), "got %d\n", LOWORD(margins
));
2032 ok(HIWORD(margins
) == HIWORD(font_margins
), "got %d\n", HIWORD(margins
));
2034 SendMessageA(hwEdit
, EM_SETMARGINS
, EC_LEFTMARGIN
| EC_RIGHTMARGIN
, MAKELONG(1,1));
2035 SendMessageA(hwEdit
, WM_SETFONT
, (WPARAM
)hfont
, 0);
2036 margins
= SendMessageA(hwEdit
, EM_GETMARGINS
, 0, 0);
2037 ok(LOWORD(margins
) == LOWORD(font_margins
), "got %d\n", LOWORD(margins
));
2038 ok(HIWORD(margins
) == HIWORD(font_margins
), "got %d\n", HIWORD(margins
));
2040 SendMessageA(hwEdit
, EM_SETMARGINS
, EC_LEFTMARGIN
| EC_RIGHTMARGIN
, MAKELONG(EC_USEFONTINFO
,EC_USEFONTINFO
));
2041 SendMessageA(hwEdit
, WM_SETFONT
, (WPARAM
)hfont
, 0);
2042 margins
= SendMessageA(hwEdit
, EM_GETMARGINS
, 0, 0);
2043 ok(LOWORD(margins
) == LOWORD(font_margins
), "got %d\n", LOWORD(margins
));
2044 ok(HIWORD(margins
) == HIWORD(font_margins
), "got %d\n", HIWORD(margins
));
2045 SendMessageA(hwEdit
, WM_SETFONT
, (WPARAM
)hfont2
, 0);
2046 margins
= SendMessageA(hwEdit
, EM_GETMARGINS
, 0, 0);
2047 ok(LOWORD(margins
) != LOWORD(font_margins
), "got %d\n", LOWORD(margins
));
2048 ok(HIWORD(margins
) != HIWORD(font_margins
), "got %d\n", HIWORD(margins
));
2050 SendMessageA(hwEdit
, WM_SETFONT
, 0, 0);
2052 DeleteObject(hfont2
);
2053 DeleteObject(hfont
);
2054 destroy_child_editcontrol(hwEdit
);
2058 #define edit_pos_ok(expected, got, txt) edit_pos_ok_(__LINE__, expected, got, #txt)
2059 static inline void edit_pos_ok_(unsigned line
, DWORD expected
, DWORD got
, const char* txt
)
2061 ok_(__FILE__
, line
)(expected
== got
, "wrong %s expected %ld got %ld\n", txt
, expected
, got
);
2064 #define check_pos(hwEdit, set_height, test_top, test_height, test_left) \
2068 set_client_height(hwEdit, set_height); \
2069 SendMessageA(hwEdit, EM_GETRECT, 0, (LPARAM) &format_rect); \
2070 left_margin = LOWORD(SendMessageA(hwEdit, EM_GETMARGINS, 0, 0)); \
2071 edit_pos_ok(test_top, format_rect.top, vertical position); \
2072 edit_pos_ok((int)test_height, format_rect.bottom - format_rect.top, height); \
2073 edit_pos_ok(test_left, format_rect.left - left_margin, left); \
2076 static void test_text_position_style(DWORD style
)
2079 HFONT font
, oldFont
;
2081 TEXTMETRICA metrics
;
2083 BOOL xb
, single_line
= !(style
& ES_MULTILINE
);
2085 b
= GetSystemMetrics(SM_CYBORDER
) + 1;
2090 /* Get a stock font for which we can determine the metrics */
2091 font
= GetStockObject(SYSTEM_FONT
);
2092 ok (font
!= NULL
, "GetStockObject SYSTEM_FONT failed\n");
2094 ok (dc
!= NULL
, "GetDC() failed\n");
2095 oldFont
= SelectObject(dc
, font
);
2096 xb
= GetTextMetricsA(dc
, &metrics
);
2097 ok (xb
, "GetTextMetrics failed\n");
2098 SelectObject(dc
, oldFont
);
2099 ReleaseDC(NULL
, dc
);
2101 /* Windows' edit control has some bugs in multi-line mode:
2102 * - Sometimes the format rectangle doesn't get updated
2103 * (see workaround in set_client_height())
2104 * - If the height of the control is smaller than the height of a text
2105 * line, the format rectangle is still as high as a text line
2106 * (higher than the client rectangle) and the caret is not shown
2109 /* Edit controls that are in a parent window */
2111 hwEdit
= create_child_editcontrol(style
| WS_VISIBLE
, 0);
2112 SendMessageA(hwEdit
, WM_SETFONT
, (WPARAM
) font
, FALSE
);
2114 check_pos(hwEdit
, metrics
.tmHeight
- 1, 0, metrics
.tmHeight
- 1, 0);
2115 check_pos(hwEdit
, metrics
.tmHeight
, 0, metrics
.tmHeight
, 0);
2116 check_pos(hwEdit
, metrics
.tmHeight
+ 1, 0, metrics
.tmHeight
, 0);
2117 check_pos(hwEdit
, metrics
.tmHeight
+ 2, 0, metrics
.tmHeight
, 0);
2118 check_pos(hwEdit
, metrics
.tmHeight
+ 10, 0, metrics
.tmHeight
, 0);
2119 destroy_child_editcontrol(hwEdit
);
2121 hwEdit
= create_child_editcontrol(style
| WS_BORDER
| WS_VISIBLE
, 0);
2122 SendMessageA(hwEdit
, WM_SETFONT
, (WPARAM
) font
, FALSE
);
2124 check_pos(hwEdit
, metrics
.tmHeight
- 1, 0, metrics
.tmHeight
- 1, b
);
2125 check_pos(hwEdit
, metrics
.tmHeight
, 0, metrics
.tmHeight
, b
);
2126 check_pos(hwEdit
, metrics
.tmHeight
+ 1, 0, metrics
.tmHeight
, b
);
2127 check_pos(hwEdit
, metrics
.tmHeight
+ bm
, 0, metrics
.tmHeight
, b
);
2128 check_pos(hwEdit
, metrics
.tmHeight
+ b2
, b
, metrics
.tmHeight
, b
);
2129 check_pos(hwEdit
, metrics
.tmHeight
+ b3
, b
, metrics
.tmHeight
, b
);
2130 destroy_child_editcontrol(hwEdit
);
2132 hwEdit
= create_child_editcontrol(style
| WS_VISIBLE
, WS_EX_CLIENTEDGE
);
2133 SendMessageA(hwEdit
, WM_SETFONT
, (WPARAM
) font
, FALSE
);
2135 check_pos(hwEdit
, metrics
.tmHeight
- 1, 0, metrics
.tmHeight
- 1, 1);
2136 check_pos(hwEdit
, metrics
.tmHeight
, 0, metrics
.tmHeight
, 1);
2137 check_pos(hwEdit
, metrics
.tmHeight
+ 1, 0, metrics
.tmHeight
, 1);
2138 check_pos(hwEdit
, metrics
.tmHeight
+ 2, 1, metrics
.tmHeight
, 1);
2139 check_pos(hwEdit
, metrics
.tmHeight
+ 10, 1, metrics
.tmHeight
, 1);
2140 destroy_child_editcontrol(hwEdit
);
2142 hwEdit
= create_child_editcontrol(style
| WS_BORDER
| WS_VISIBLE
, WS_EX_CLIENTEDGE
);
2143 SendMessageA(hwEdit
, WM_SETFONT
, (WPARAM
) font
, FALSE
);
2145 check_pos(hwEdit
, metrics
.tmHeight
- 1, 0, metrics
.tmHeight
- 1, 1);
2146 check_pos(hwEdit
, metrics
.tmHeight
, 0, metrics
.tmHeight
, 1);
2147 check_pos(hwEdit
, metrics
.tmHeight
+ 1, 0, metrics
.tmHeight
, 1);
2148 check_pos(hwEdit
, metrics
.tmHeight
+ 2, 1, metrics
.tmHeight
, 1);
2149 check_pos(hwEdit
, metrics
.tmHeight
+ 10, 1, metrics
.tmHeight
, 1);
2150 destroy_child_editcontrol(hwEdit
);
2153 /* Edit controls that are popup windows */
2155 hwEdit
= create_editcontrol(style
| WS_POPUP
, 0);
2156 SendMessageA(hwEdit
, WM_SETFONT
, (WPARAM
) font
, FALSE
);
2158 check_pos(hwEdit
, metrics
.tmHeight
- 1, 0, metrics
.tmHeight
- 1, 0);
2159 check_pos(hwEdit
, metrics
.tmHeight
, 0, metrics
.tmHeight
, 0);
2160 check_pos(hwEdit
, metrics
.tmHeight
+ 1, 0, metrics
.tmHeight
, 0);
2161 check_pos(hwEdit
, metrics
.tmHeight
+ 2, 0, metrics
.tmHeight
, 0);
2162 check_pos(hwEdit
, metrics
.tmHeight
+ 10, 0, metrics
.tmHeight
, 0);
2163 DestroyWindow(hwEdit
);
2165 hwEdit
= create_editcontrol(style
| WS_POPUP
| WS_BORDER
, 0);
2166 SendMessageA(hwEdit
, WM_SETFONT
, (WPARAM
) font
, FALSE
);
2168 check_pos(hwEdit
, metrics
.tmHeight
- 1, 0, metrics
.tmHeight
- 1, b
);
2169 check_pos(hwEdit
, metrics
.tmHeight
, 0, metrics
.tmHeight
, b
);
2170 check_pos(hwEdit
, metrics
.tmHeight
+ 1, 0, metrics
.tmHeight
, b
);
2171 check_pos(hwEdit
, metrics
.tmHeight
+ bm
, 0, metrics
.tmHeight
, b
);
2172 check_pos(hwEdit
, metrics
.tmHeight
+ b2
, b
, metrics
.tmHeight
, b
);
2173 check_pos(hwEdit
, metrics
.tmHeight
+ b3
, b
, metrics
.tmHeight
, b
);
2174 DestroyWindow(hwEdit
);
2176 hwEdit
= create_editcontrol(style
| WS_POPUP
, WS_EX_CLIENTEDGE
);
2177 SendMessageA(hwEdit
, WM_SETFONT
, (WPARAM
) font
, FALSE
);
2179 check_pos(hwEdit
, metrics
.tmHeight
- 1, 0, metrics
.tmHeight
- 1, 1);
2180 check_pos(hwEdit
, metrics
.tmHeight
, 0, metrics
.tmHeight
, 1);
2181 check_pos(hwEdit
, metrics
.tmHeight
+ 1, 0, metrics
.tmHeight
, 1);
2182 check_pos(hwEdit
, metrics
.tmHeight
+ 2, 1, metrics
.tmHeight
, 1);
2183 check_pos(hwEdit
, metrics
.tmHeight
+ 10, 1, metrics
.tmHeight
, 1);
2184 DestroyWindow(hwEdit
);
2186 hwEdit
= create_editcontrol(style
| WS_POPUP
| WS_BORDER
, WS_EX_CLIENTEDGE
);
2187 SendMessageA(hwEdit
, WM_SETFONT
, (WPARAM
) font
, FALSE
);
2189 check_pos(hwEdit
, metrics
.tmHeight
- 1, 0, metrics
.tmHeight
- 1, 1);
2190 check_pos(hwEdit
, metrics
.tmHeight
, 0, metrics
.tmHeight
, 1);
2191 check_pos(hwEdit
, metrics
.tmHeight
+ 1, 0, metrics
.tmHeight
, 1);
2192 check_pos(hwEdit
, metrics
.tmHeight
+ 2, 1, metrics
.tmHeight
, 1);
2193 check_pos(hwEdit
, metrics
.tmHeight
+ 10, 1, metrics
.tmHeight
, 1);
2194 DestroyWindow(hwEdit
);
2197 static void test_text_position(void)
2199 trace("EDIT: Text position (Single line)\n");
2200 test_text_position_style(ES_AUTOHSCROLL
| ES_AUTOVSCROLL
);
2201 trace("EDIT: Text position (Multi line)\n");
2202 test_text_position_style(ES_MULTILINE
| ES_AUTOHSCROLL
| ES_AUTOVSCROLL
);
2205 static void test_espassword(void)
2210 const char* password
= "secret";
2212 hwEdit
= create_editcontrol(ES_PASSWORD
, 0);
2213 r
= get_edit_style(hwEdit
);
2214 ok(r
== ES_PASSWORD
, "Wrong style expected ES_PASSWORD got: 0x%lx\n", r
);
2216 r
= SendMessageA(hwEdit
, WM_SETTEXT
, 0, (LPARAM
) password
);
2217 ok(r
== TRUE
, "Expected: %d, got: %ld\n", TRUE
, r
);
2219 /* select all, cut (ctrl-x) */
2220 SendMessageA(hwEdit
, EM_SETSEL
, 0, -1);
2221 r
= SendMessageA(hwEdit
, WM_CHAR
, 24, 0);
2222 ok(1 == r
, "Expected: %d, got: %ld\n", 1, r
);
2225 r
= SendMessageA(hwEdit
, WM_GETTEXT
, 1024, (LPARAM
) buffer
);
2226 ok(r
== strlen(password
), "Expected: %s, got len %ld\n", password
, r
);
2227 ok(strcmp(buffer
, password
) == 0, "expected %s, got %s\n", password
, buffer
);
2229 r
= OpenClipboard(hwEdit
);
2230 ok(r
== TRUE
, "expected %d, got %ld\n", TRUE
, r
);
2231 r
= EmptyClipboard();
2232 ok(r
== TRUE
, "expected %d, got %ld\n", TRUE
, r
);
2233 r
= CloseClipboard();
2234 ok(r
== TRUE
, "expected %d, got %ld\n", TRUE
, r
);
2236 /* select all, copy (ctrl-c) and paste (ctrl-v) */
2237 SendMessageA(hwEdit
, EM_SETSEL
, 0, -1);
2238 r
= SendMessageA(hwEdit
, WM_CHAR
, 3, 0);
2239 ok(1 == r
, "Expected: %d, got: %ld\n", 1, r
);
2240 r
= SendMessageA(hwEdit
, WM_CHAR
, 22, 0);
2241 ok(1 == r
, "Expected: %d, got: %ld\n", 1, r
);
2245 r
= SendMessageA(hwEdit
, WM_GETTEXT
, 1024, (LPARAM
) buffer
);
2246 ok(r
== 0, "Expected: 0, got: %ld\n", r
);
2247 ok(strcmp(buffer
, "") == 0, "expected empty string, got %s\n", buffer
);
2249 DestroyWindow(hwEdit
);
2252 static void test_undo(void)
2258 const char* text
= "undo this";
2260 hwEdit
= create_editcontrol(0, 0);
2261 r
= get_edit_style(hwEdit
);
2262 ok(0 == r
, "Wrong style expected 0x%x got: 0x%lx\n", 0, r
);
2265 r
= SendMessageA(hwEdit
, WM_SETTEXT
, 0, (LPARAM
) text
);
2266 ok(TRUE
== r
, "Expected: %d, got: %ld\n", TRUE
, r
);
2269 cpMin
= cpMax
= 0xdeadbeef;
2270 SendMessageA(hwEdit
, EM_SETSEL
, 0, -1);
2271 r
= SendMessageA(hwEdit
, EM_GETSEL
, (WPARAM
) &cpMin
, (LPARAM
) &cpMax
);
2272 ok((strlen(text
) << 16) == r
, "Unexpected length %ld\n", r
);
2273 ok(0 == cpMin
, "Expected: %d, got %ld\n", 0, cpMin
);
2274 ok(9 == cpMax
, "Expected: %d, got %ld\n", 9, cpMax
);
2277 r
= SendMessageA(hwEdit
, WM_CHAR
, 24, 0);
2278 ok(1 == r
, "Expected: %d, got: %ld\n", 1, r
);
2282 r
= SendMessageA(hwEdit
, WM_GETTEXT
, 1024, (LPARAM
) buffer
);
2283 ok(0 == r
, "Expected: %d, got len %ld\n", 0, r
);
2284 ok(0 == strcmp(buffer
, ""), "expected %s, got %s\n", "", buffer
);
2287 r
= SendMessageA(hwEdit
, WM_CHAR
, 26, 0);
2288 ok(1 == r
, "Expected: %d, got: %ld\n", 1, r
);
2292 r
= SendMessageA(hwEdit
, WM_GETTEXT
, 1024, (LPARAM
) buffer
);
2293 ok(strlen(text
) == r
, "Unexpected length %ld\n", r
);
2294 ok(0 == strcmp(buffer
, text
), "expected %s, got %s\n", text
, buffer
);
2296 /* undo again (ctrl-z) */
2297 r
= SendMessageA(hwEdit
, WM_CHAR
, 26, 0);
2298 ok(1 == r
, "Expected: %d, got: %ld\n", 1, r
);
2302 r
= SendMessageA(hwEdit
, WM_GETTEXT
, 1024, (LPARAM
) buffer
);
2303 ok(r
== 0, "Expected: %d, got len %ld\n", 0, r
);
2304 ok(0 == strcmp(buffer
, ""), "expected %s, got %s\n", "", buffer
);
2306 DestroyWindow(hwEdit
);
2309 static void test_enter(void)
2316 hwEdit
= create_editcontrol(ES_MULTILINE
, 0);
2317 r
= get_edit_style(hwEdit
);
2318 ok(ES_MULTILINE
== r
, "Wrong style expected ES_MULTILINE got: 0x%lx\n", r
);
2321 r
= SendMessageA(hwEdit
, WM_SETTEXT
, 0, (LPARAM
) "");
2322 ok(TRUE
== r
, "Expected: %d, got: %ld\n", TRUE
, r
);
2324 r
= SendMessageA(hwEdit
, WM_CHAR
, VK_RETURN
, 0);
2325 ok(1 == r
, "Expected: %d, got: %ld\n", 1, r
);
2329 r
= SendMessageA(hwEdit
, WM_GETTEXT
, 16, (LPARAM
) buffer
);
2330 ok(2 == r
, "Expected: %d, got len %ld\n", 2, r
);
2331 ok(0 == strcmp(buffer
, "\r\n"), "expected \"\\r\\n\", got \"%s\"\n", buffer
);
2333 DestroyWindow (hwEdit
);
2336 hwEdit
= create_editcontrol(0, 0);
2337 r
= get_edit_style(hwEdit
);
2338 ok(0 == r
, "Wrong style expected 0x%x got: 0x%lx\n", 0, r
);
2341 r
= SendMessageA(hwEdit
, WM_SETTEXT
, 0, (LPARAM
) "");
2342 ok(TRUE
== r
, "Expected: %d, got: %ld\n", TRUE
, r
);
2344 r
= SendMessageA(hwEdit
, WM_CHAR
, VK_RETURN
, 0);
2345 ok(1 == r
, "Expected: %d, got: %ld\n", 1, r
);
2349 r
= SendMessageA(hwEdit
, WM_GETTEXT
, 16, (LPARAM
) buffer
);
2350 ok(0 == r
, "Expected: %d, got len %ld\n", 0, r
);
2351 ok(0 == strcmp(buffer
, ""), "expected \"\", got \"%s\"\n", buffer
);
2353 DestroyWindow(hwEdit
);
2355 /* single line with ES_WANTRETURN */
2356 hwEdit
= create_editcontrol(ES_WANTRETURN
, 0);
2357 r
= get_edit_style(hwEdit
);
2358 ok(ES_WANTRETURN
== r
, "Wrong style expected ES_WANTRETURN got: 0x%lx\n", r
);
2361 r
= SendMessageA(hwEdit
, WM_SETTEXT
, 0, (LPARAM
) "");
2362 ok(TRUE
== r
, "Expected: %d, got: %ld\n", TRUE
, r
);
2364 r
= SendMessageA(hwEdit
, WM_CHAR
, VK_RETURN
, 0);
2365 ok(1 == r
, "Expected: %d, got: %ld\n", 1, r
);
2369 r
= SendMessageA(hwEdit
, WM_GETTEXT
, 16, (LPARAM
) buffer
);
2370 ok(0 == r
, "Expected: %d, got len %ld\n", 0, r
);
2371 ok(0 == strcmp(buffer
, ""), "expected \"\", got \"%s\"\n", buffer
);
2373 DestroyWindow(hwEdit
);
2376 static void test_tab(void)
2383 hwEdit
= create_editcontrol(ES_MULTILINE
, 0);
2384 r
= get_edit_style(hwEdit
);
2385 ok(ES_MULTILINE
== r
, "Wrong style expected ES_MULTILINE got: 0x%lx\n", r
);
2388 r
= SendMessageA(hwEdit
, WM_SETTEXT
, 0, (LPARAM
) "");
2389 ok(TRUE
== r
, "Expected: %d, got: %ld\n", TRUE
, r
);
2391 r
= SendMessageA(hwEdit
, WM_CHAR
, VK_TAB
, 0);
2392 ok(1 == r
, "Expected: %d, got: %ld\n", 1, r
);
2396 r
= SendMessageA(hwEdit
, WM_GETTEXT
, 16, (LPARAM
) buffer
);
2397 ok(1 == r
, "Expected: %d, got len %ld\n", 1, r
);
2398 ok(0 == strcmp(buffer
, "\t"), "expected \"\\t\", got \"%s\"\n", buffer
);
2400 DestroyWindow(hwEdit
);
2403 hwEdit
= create_editcontrol(0, 0);
2404 r
= get_edit_style(hwEdit
);
2405 ok(0 == r
, "Wrong style expected 0x%x got: 0x%lx\n", 0, r
);
2408 r
= SendMessageA(hwEdit
, WM_SETTEXT
, 0, (LPARAM
) "");
2409 ok(TRUE
== r
, "Expected: %d, got: %ld\n", TRUE
, r
);
2411 r
= SendMessageA(hwEdit
, WM_CHAR
, VK_TAB
, 0);
2412 ok(1 == r
, "Expected: %d, got: %ld\n", 1, r
);
2416 r
= SendMessageA(hwEdit
, WM_GETTEXT
, 16, (LPARAM
) buffer
);
2417 ok(0 == r
, "Expected: %d, got len %ld\n", 0, r
);
2418 ok(0 == strcmp(buffer
, ""), "expected \"\", got \"%s\"\n", buffer
);
2420 DestroyWindow(hwEdit
);
2423 static void test_edit_dialog(void)
2427 /* from bug 11841 */
2428 r
= DialogBoxParamA(hinst
, "EDIT_READONLY_DIALOG", NULL
, edit_dialog_proc
, 0);
2429 ok(333 == r
, "Expected %d, got %d\n", 333, r
);
2430 r
= DialogBoxParamA(hinst
, "EDIT_READONLY_DIALOG", NULL
, edit_dialog_proc
, 1);
2431 ok(111 == r
, "Expected %d, got %d\n", 111, r
);
2432 r
= DialogBoxParamA(hinst
, "EDIT_READONLY_DIALOG", NULL
, edit_dialog_proc
, 2);
2433 ok(444 == r
, "Expected %d, got %d\n", 444, r
);
2435 /* more tests for WM_CHAR */
2436 r
= DialogBoxParamA(hinst
, "EDIT_READONLY_DIALOG", NULL
, edit_dialog_proc
, 3);
2437 ok(444 == r
, "Expected %d, got %d\n", 444, r
);
2438 r
= DialogBoxParamA(hinst
, "EDIT_READONLY_DIALOG", NULL
, edit_dialog_proc
, 4);
2439 ok(444 == r
, "Expected %d, got %d\n", 444, r
);
2440 r
= DialogBoxParamA(hinst
, "EDIT_READONLY_DIALOG", NULL
, edit_dialog_proc
, 5);
2441 ok(444 == r
, "Expected %d, got %d\n", 444, r
);
2443 /* more tests for WM_KEYDOWN + WM_CHAR */
2444 r
= DialogBoxParamA(hinst
, "EDIT_READONLY_DIALOG", NULL
, edit_dialog_proc
, 6);
2445 ok(444 == r
, "Expected %d, got %d\n", 444, r
);
2446 r
= DialogBoxParamA(hinst
, "EDIT_READONLY_DIALOG", NULL
, edit_dialog_proc
, 7);
2447 ok(444 == r
, "Expected %d, got %d\n", 444, r
);
2448 r
= DialogBoxParamA(hinst
, "EDIT_READONLY_DIALOG", NULL
, edit_dialog_proc
, 8);
2449 ok(444 == r
, "Expected %d, got %d\n", 444, r
);
2451 /* tests with an editable edit control */
2452 r
= DialogBoxParamA(hinst
, "EDIT_DIALOG", NULL
, edit_dialog_proc
, 0);
2453 ok(333 == r
, "Expected %d, got %d\n", 333, r
);
2454 r
= DialogBoxParamA(hinst
, "EDIT_DIALOG", NULL
, edit_dialog_proc
, 1);
2455 ok(111 == r
, "Expected %d, got %d\n", 111, r
);
2456 r
= DialogBoxParamA(hinst
, "EDIT_DIALOG", NULL
, edit_dialog_proc
, 2);
2457 ok(444 == r
, "Expected %d, got %d\n", 444, r
);
2459 /* tests for WM_CHAR */
2460 r
= DialogBoxParamA(hinst
, "EDIT_DIALOG", NULL
, edit_dialog_proc
, 3);
2461 ok(444 == r
, "Expected %d, got %d\n", 444, r
);
2462 r
= DialogBoxParamA(hinst
, "EDIT_DIALOG", NULL
, edit_dialog_proc
, 4);
2463 ok(444 == r
, "Expected %d, got %d\n", 444, r
);
2464 r
= DialogBoxParamA(hinst
, "EDIT_DIALOG", NULL
, edit_dialog_proc
, 5);
2465 ok(444 == r
, "Expected %d, got %d\n", 444, r
);
2467 /* tests for WM_KEYDOWN + WM_CHAR */
2468 r
= DialogBoxParamA(hinst
, "EDIT_DIALOG", NULL
, edit_dialog_proc
, 6);
2469 ok(444 == r
, "Expected %d, got %d\n", 444, r
);
2470 r
= DialogBoxParamA(hinst
, "EDIT_DIALOG", NULL
, edit_dialog_proc
, 7);
2471 ok(444 == r
, "Expected %d, got %d\n", 444, r
);
2472 r
= DialogBoxParamA(hinst
, "EDIT_DIALOG", NULL
, edit_dialog_proc
, 8);
2473 ok(444 == r
, "Expected %d, got %d\n", 444, r
);
2475 /* multiple tab tests */
2476 r
= DialogBoxParamA(hinst
, "EDIT_DIALOG", NULL
, edit_dialog_proc
, 9);
2477 ok(22 == r
, "Expected %d, got %d\n", 22, r
);
2478 r
= DialogBoxParamA(hinst
, "EDIT_DIALOG", NULL
, edit_dialog_proc
, 10);
2479 ok(33 == r
, "Expected %d, got %d\n", 33, r
);
2482 static void test_multi_edit_dialog(void)
2486 /* test for multiple edit dialogs (bug 12319) */
2487 r
= DialogBoxParamA(hinst
, "MULTI_EDIT_DIALOG", NULL
, multi_edit_dialog_proc
, 0);
2488 ok(2222 == r
, "Expected %d, got %d\n", 2222, r
);
2489 r
= DialogBoxParamA(hinst
, "MULTI_EDIT_DIALOG", NULL
, multi_edit_dialog_proc
, 1);
2490 ok(1111 == r
, "Expected %d, got %d\n", 1111, r
);
2491 r
= DialogBoxParamA(hinst
, "MULTI_EDIT_DIALOG", NULL
, multi_edit_dialog_proc
, 2);
2492 ok(2222 == r
, "Expected %d, got %d\n", 2222, r
);
2493 r
= DialogBoxParamA(hinst
, "MULTI_EDIT_DIALOG", NULL
, multi_edit_dialog_proc
, 3);
2494 ok(11 == r
, "Expected %d, got %d\n", 11, r
);
2497 static void test_wantreturn_edit_dialog(void)
2501 /* tests for WM_KEYDOWN */
2502 r
= DialogBoxParamA(hinst
, "EDIT_WANTRETURN_DIALOG", NULL
, edit_wantreturn_dialog_proc
, 0);
2503 ok(333 == r
, "Expected %d, got %d\n", 333, r
);
2504 r
= DialogBoxParamA(hinst
, "EDIT_WANTRETURN_DIALOG", NULL
, edit_wantreturn_dialog_proc
, 1);
2505 ok(444 == r
, "Expected %d, got %d\n", 444, r
);
2506 r
= DialogBoxParamA(hinst
, "EDIT_WANTRETURN_DIALOG", NULL
, edit_wantreturn_dialog_proc
, 2);
2507 ok(444 == r
, "Expected %d, got %d\n", 444, r
);
2509 /* tests for WM_CHAR */
2510 r
= DialogBoxParamA(hinst
, "EDIT_WANTRETURN_DIALOG", NULL
, edit_wantreturn_dialog_proc
, 3);
2511 ok(444 == r
, "Expected %d, got %d\n", 444, r
);
2512 r
= DialogBoxParamA(hinst
, "EDIT_WANTRETURN_DIALOG", NULL
, edit_wantreturn_dialog_proc
, 4);
2513 ok(444 == r
, "Expected %d, got %d\n", 444, r
);
2514 r
= DialogBoxParamA(hinst
, "EDIT_WANTRETURN_DIALOG", NULL
, edit_wantreturn_dialog_proc
, 5);
2515 ok(444 == r
, "Expected %d, got %d\n", 444, r
);
2517 /* tests for WM_KEYDOWN + WM_CHAR */
2518 r
= DialogBoxParamA(hinst
, "EDIT_WANTRETURN_DIALOG", NULL
, edit_wantreturn_dialog_proc
, 6);
2519 ok(444 == r
, "Expected %d, got %d\n", 444, r
);
2520 r
= DialogBoxParamA(hinst
, "EDIT_WANTRETURN_DIALOG", NULL
, edit_wantreturn_dialog_proc
, 7);
2521 ok(444 == r
, "Expected %d, got %d\n", 444, r
);
2522 r
= DialogBoxParamA(hinst
, "EDIT_WANTRETURN_DIALOG", NULL
, edit_wantreturn_dialog_proc
, 8);
2523 ok(444 == r
, "Expected %d, got %d\n", 444, r
);
2526 static void test_singleline_wantreturn_edit_dialog(void)
2530 /* tests for WM_KEYDOWN */
2531 r
= DialogBoxParamA(hinst
, "EDIT_SINGLELINE_DIALOG", NULL
, edit_singleline_dialog_proc
, 0);
2532 ok(222 == r
, "Expected %d, got %d\n", 222, r
);
2533 r
= DialogBoxParamA(hinst
, "EDIT_SINGLELINE_DIALOG", NULL
, edit_singleline_dialog_proc
, 1);
2534 ok(111 == r
, "Expected %d, got %d\n", 111, r
);
2535 r
= DialogBoxParamA(hinst
, "EDIT_SINGLELINE_DIALOG", NULL
, edit_singleline_dialog_proc
, 2);
2536 ok(444 == r
, "Expected %d, got %d\n", 444, r
);
2538 /* tests for WM_CHAR */
2539 r
= DialogBoxParamA(hinst
, "EDIT_SINGLELINE_DIALOG", NULL
, edit_singleline_dialog_proc
, 3);
2540 ok(444 == r
, "Expected %d, got %d\n", 444, r
);
2541 r
= DialogBoxParamA(hinst
, "EDIT_SINGLELINE_DIALOG", NULL
, edit_singleline_dialog_proc
, 4);
2542 ok(444 == r
, "Expected %d, got %d\n", 444, r
);
2543 r
= DialogBoxParamA(hinst
, "EDIT_SINGLELINE_DIALOG", NULL
, edit_singleline_dialog_proc
, 5);
2544 ok(444 == r
, "Expected %d, got %d\n", 444, r
);
2546 /* tests for WM_KEYDOWN + WM_CHAR */
2547 r
= DialogBoxParamA(hinst
, "EDIT_SINGLELINE_DIALOG", NULL
, edit_singleline_dialog_proc
, 6);
2548 ok(222 == r
, "Expected %d, got %d\n", 222, r
);
2549 r
= DialogBoxParamA(hinst
, "EDIT_SINGLELINE_DIALOG", NULL
, edit_singleline_dialog_proc
, 7);
2550 ok(111 == r
, "Expected %d, got %d\n", 111, r
);
2551 r
= DialogBoxParamA(hinst
, "EDIT_SINGLELINE_DIALOG", NULL
, edit_singleline_dialog_proc
, 8);
2552 ok(444 == r
, "Expected %d, got %d\n", 444, r
);
2554 /* tests for WM_KEYDOWN */
2555 r
= DialogBoxParamA(hinst
, "EDIT_SINGLELINE_WANTRETURN_DIALOG", NULL
, edit_singleline_dialog_proc
, 0);
2556 ok(222 == r
, "Expected %d, got %d\n", 222, r
);
2557 r
= DialogBoxParamA(hinst
, "EDIT_SINGLELINE_WANTRETURN_DIALOG", NULL
, edit_singleline_dialog_proc
, 1);
2558 ok(111 == r
, "Expected %d, got %d\n", 111, r
);
2559 r
= DialogBoxParamA(hinst
, "EDIT_SINGLELINE_WANTRETURN_DIALOG", NULL
, edit_singleline_dialog_proc
, 2);
2560 ok(444 == r
, "Expected %d, got %d\n", 444, r
);
2562 /* tests for WM_CHAR */
2563 r
= DialogBoxParamA(hinst
, "EDIT_SINGLELINE_WANTRETURN_DIALOG", NULL
, edit_singleline_dialog_proc
, 3);
2564 ok(444 == r
, "Expected %d, got %d\n", 444, r
);
2565 r
= DialogBoxParamA(hinst
, "EDIT_SINGLELINE_WANTRETURN_DIALOG", NULL
, edit_singleline_dialog_proc
, 4);
2566 ok(444 == r
, "Expected %d, got %d\n", 444, r
);
2567 r
= DialogBoxParamA(hinst
, "EDIT_SINGLELINE_WANTRETURN_DIALOG", NULL
, edit_singleline_dialog_proc
, 5);
2568 ok(444 == r
, "Expected %d, got %d\n", 444, r
);
2570 /* tests for WM_KEYDOWN + WM_CHAR */
2571 r
= DialogBoxParamA(hinst
, "EDIT_SINGLELINE_WANTRETURN_DIALOG", NULL
, edit_singleline_dialog_proc
, 6);
2572 ok(222 == r
, "Expected %d, got %d\n", 222, r
);
2573 r
= DialogBoxParamA(hinst
, "EDIT_SINGLELINE_WANTRETURN_DIALOG", NULL
, edit_singleline_dialog_proc
, 7);
2574 ok(111 == r
, "Expected %d, got %d\n", 111, r
);
2575 r
= DialogBoxParamA(hinst
, "EDIT_SINGLELINE_WANTRETURN_DIALOG", NULL
, edit_singleline_dialog_proc
, 8);
2576 ok(444 == r
, "Expected %d, got %d\n", 444, r
);
2579 static int child_edit_wmkeydown_num_messages
= 0;
2580 static INT_PTR CALLBACK
child_edit_wmkeydown_proc(HWND hdlg
, UINT msg
, WPARAM wparam
, LPARAM lparam
)
2589 child_edit_wmkeydown_num_messages
++;
2596 static void test_child_edit_wmkeydown(void)
2598 HWND hwEdit
, hwParent
;
2601 hwEdit
= create_child_editcontrol(0, 0);
2602 hwParent
= GetParent(hwEdit
);
2603 SetWindowLongPtrA(hwParent
, GWLP_WNDPROC
, (LONG_PTR
)child_edit_wmkeydown_proc
);
2604 r
= SendMessageA(hwEdit
, WM_KEYDOWN
, VK_RETURN
, 0x1c0001);
2605 ok(1 == r
, "expected 1, got %d\n", r
);
2606 ok(0 == child_edit_wmkeydown_num_messages
, "expected 0, got %d\n", child_edit_wmkeydown_num_messages
);
2607 destroy_child_editcontrol(hwEdit
);
2610 static BOOL got_en_setfocus
= FALSE
;
2611 static BOOL got_wm_capturechanged
= FALSE
;
2612 static LRESULT (CALLBACK
*p_edit_proc
)(HWND
, UINT
, WPARAM
, LPARAM
);
2614 static LRESULT CALLBACK
edit4_wnd_procA(HWND hWnd
, UINT msg
, WPARAM wParam
, LPARAM lParam
)
2618 switch (HIWORD(wParam
))
2621 got_en_setfocus
= TRUE
;
2625 case WM_CAPTURECHANGED
:
2626 if (hWnd
!= (HWND
)lParam
)
2628 got_wm_capturechanged
= TRUE
;
2633 return DefWindowProcA(hWnd
, msg
, wParam
, lParam
);
2636 struct context_menu_messages
2638 unsigned int wm_command
, em_setsel
;
2641 static struct context_menu_messages menu_messages
;
2643 static LRESULT CALLBACK
child_edit_menu_proc(HWND hwnd
, UINT msg
, WPARAM wParam
, LPARAM lParam
)
2648 if (wParam
== MSGF_MENU
)
2650 HWND hwndMenu
= (HWND
)lParam
;
2651 MENUBARINFO mbi
= { sizeof(mbi
) };
2652 if (GetMenuBarInfo(hwndMenu
, OBJID_CLIENT
, 0, &mbi
))
2654 MENUITEMINFOA mii
= { sizeof(MENUITEMINFOA
), MIIM_STATE
};
2655 if (GetMenuItemInfoA(mbi
.hMenu
, EM_SETSEL
, FALSE
, &mii
))
2657 if (mii
.fState
& MFS_HILITE
)
2659 PostMessageA(hwnd
, WM_KEYDOWN
, VK_RETURN
, 0x1c0001);
2660 PostMessageA(hwnd
, WM_KEYUP
, VK_RETURN
, 0x1c0001);
2664 PostMessageA(hwnd
, WM_KEYDOWN
, VK_DOWN
, 0x500001);
2665 PostMessageA(hwnd
, WM_KEYUP
, VK_DOWN
, 0x500001);
2672 menu_messages
.wm_command
++;
2675 menu_messages
.em_setsel
++;
2678 return CallWindowProcA(p_edit_proc
, hwnd
, msg
, wParam
, lParam
);
2681 static void test_contextmenu(void)
2683 HWND hwndMain
, hwndEdit
;
2686 hwndMain
= CreateWindowA(szEditTest4Class
, "ET4", WS_OVERLAPPEDWINDOW
|WS_VISIBLE
,
2687 0, 0, 200, 200, NULL
, NULL
, hinst
, NULL
);
2688 ok(hwndMain
!= NULL
, "Failed to create control parent.\n");
2690 hwndEdit
= CreateWindowA(WC_EDITA
, NULL
, WS_CHILD
|WS_BORDER
|WS_VISIBLE
|ES_LEFT
|ES_AUTOHSCROLL
,
2691 0, 0, 150, 50, /* important this not be 0 size. */
2692 hwndMain
, (HMENU
) ID_EDITTEST2
, hinst
, NULL
);
2693 ok(hwndEdit
!= NULL
, "Failed to create Edit control.\n");
2696 SetCapture(hwndMain
);
2697 SendMessageA(hwndEdit
, WM_CONTEXTMENU
, (WPARAM
)hwndEdit
, MAKEWORD(10, 10));
2698 ok(got_en_setfocus
, "edit box didn't get focused\n");
2699 ok(got_wm_capturechanged
, "main window capture did not change\n");
2701 DestroyWindow(hwndEdit
);
2703 hwndEdit
= CreateWindowA("EDIT", "Test Text",
2704 WS_CHILD
| WS_BORDER
| WS_VISIBLE
,
2706 hwndMain
, NULL
, hinst
, NULL
);
2707 memset(&menu_messages
, 0, sizeof(menu_messages
));
2708 p_edit_proc
= (void*)SetWindowLongPtrA(hwndEdit
, GWLP_WNDPROC
,
2709 (ULONG_PTR
)child_edit_menu_proc
);
2712 SendMessageA(hwndEdit
, WM_SETTEXT
, 0, (LPARAM
)"foo");
2713 SendMessageA(hwndEdit
, WM_CONTEXTMENU
, (WPARAM
)hwndEdit
, MAKEWORD(-1, -1));
2714 while (PeekMessageA(&msg
, hwndEdit
, 0, 0, PM_REMOVE
)) DispatchMessageA(&msg
);
2715 ok(menu_messages
.wm_command
== 0,
2716 "Expected no WM_COMMAND messages, got %d\n", menu_messages
.wm_command
);
2717 ok(menu_messages
.em_setsel
== 1,
2718 "Expected 1 EM_SETSEL message, got %d\n", menu_messages
.em_setsel
);
2720 DestroyWindow(hwndEdit
);
2721 DestroyWindow(hwndMain
);
2724 static BOOL
register_classes(void)
2729 WNDCLASSA text_position
;
2733 test2
.lpfnWndProc
= ET2_WndProc
;
2734 test2
.cbClsExtra
= 0;
2735 test2
.cbWndExtra
= 0;
2736 test2
.hInstance
= hinst
;
2738 test2
.hCursor
= LoadCursorA (NULL
, (LPCSTR
)IDC_ARROW
);
2739 test2
.hbrBackground
= (HBRUSH
)(COLOR_WINDOW
+ 1);
2740 test2
.lpszMenuName
= NULL
;
2741 test2
.lpszClassName
= szEditTest2Class
;
2742 if (!RegisterClassA(&test2
)) return FALSE
;
2745 test3
.lpfnWndProc
= edit3_wnd_procA
;
2746 test3
.cbClsExtra
= 0;
2747 test3
.cbWndExtra
= 0;
2748 test3
.hInstance
= hinst
;
2750 test3
.hCursor
= LoadCursorA(0, (LPCSTR
)IDC_ARROW
);
2751 test3
.hbrBackground
= GetStockObject(WHITE_BRUSH
);
2752 test3
.lpszMenuName
= NULL
;
2753 test3
.lpszClassName
= szEditTest3Class
;
2754 if (!RegisterClassA(&test3
)) return FALSE
;
2757 test4
.lpfnWndProc
= edit4_wnd_procA
;
2758 test4
.cbClsExtra
= 0;
2759 test4
.cbWndExtra
= 0;
2760 test4
.hInstance
= hinst
;
2762 test4
.hCursor
= LoadCursorA (NULL
, (LPCSTR
)IDC_ARROW
);
2763 test4
.hbrBackground
= (HBRUSH
)(COLOR_WINDOW
+ 1);
2764 test4
.lpszMenuName
= NULL
;
2765 test4
.lpszClassName
= szEditTest4Class
;
2766 if (!RegisterClassA(&test4
)) return FALSE
;
2768 text_position
.style
= CS_HREDRAW
| CS_VREDRAW
;
2769 text_position
.cbClsExtra
= 0;
2770 text_position
.cbWndExtra
= 0;
2771 text_position
.hInstance
= hinst
;
2772 text_position
.hIcon
= NULL
;
2773 text_position
.hCursor
= LoadCursorA(NULL
, (LPCSTR
)IDC_ARROW
);
2774 text_position
.hbrBackground
= (HBRUSH
)(COLOR_BTNFACE
+ 1);
2775 text_position
.lpszMenuName
= NULL
;
2776 text_position
.lpszClassName
= szEditTextPositionClass
;
2777 text_position
.lpfnWndProc
= DefWindowProcA
;
2778 if (!RegisterClassA(&text_position
)) return FALSE
;
2780 memset(&wc
, 0, sizeof(wc
));
2781 wc
.lpfnWndProc
= parent_wnd_proc
;
2782 wc
.hInstance
= GetModuleHandleA(NULL
);
2783 wc
.lpszClassName
= "ParentWnd";
2784 if (!RegisterClassA(&wc
)) return FALSE
;
2789 static void UnregisterWindowClasses (void)
2791 UnregisterClassA(szEditTest2Class
, hinst
);
2792 UnregisterClassA(szEditTest3Class
, hinst
);
2793 UnregisterClassA(szEditTest4Class
, hinst
);
2794 UnregisterClassA(szEditTextPositionClass
, hinst
);
2797 static void test_fontsize(void)
2804 char szLocalString
[MAXLEN
];
2808 dpi
= GetDeviceCaps(hDC
, LOGPIXELSY
);
2809 ReleaseDC(NULL
, hDC
);
2811 memset(&lf
,0,sizeof(LOGFONTA
));
2812 strcpy(lf
.lfFaceName
,"Arial");
2813 lf
.lfHeight
= -300; /* taller than the edit box */
2815 hfont
= CreateFontIndirectA(&lf
);
2817 trace("EDIT: Oversized font (Multi line)\n");
2818 hwEdit
= CreateWindowA("EDIT", NULL
, ES_MULTILINE
|ES_AUTOHSCROLL
,
2819 0, 0, (150 * dpi
) / 96, (50 * dpi
) / 96, NULL
, NULL
,
2822 SendMessageA(hwEdit
,WM_SETFONT
,(WPARAM
)hfont
,0);
2824 if (winetest_interactive
)
2825 ShowWindow (hwEdit
, SW_SHOW
);
2827 r
= SendMessageA(hwEdit
, WM_CHAR
, 'A', 1);
2828 ok(1 == r
, "Expected: %d, got: %ld\n", 1, r
);
2829 r
= SendMessageA(hwEdit
, WM_CHAR
, 'B', 1);
2830 ok(1 == r
, "Expected: %d, got: %ld\n", 1, r
);
2831 r
= SendMessageA(hwEdit
, WM_CHAR
, 'C', 1);
2832 ok(1 == r
, "Expected: %d, got: %ld\n", 1, r
);
2834 GetWindowTextA(hwEdit
, szLocalString
, MAXLEN
);
2835 ok(strcmp(szLocalString
, "ABC")==0,
2836 "Wrong contents of edit: %s\n", szLocalString
);
2838 r
= SendMessageA(hwEdit
, EM_POSFROMCHAR
,0,0);
2839 ok(r
!= -1,"EM_POSFROMCHAR failed index 0\n");
2840 r
= SendMessageA(hwEdit
, EM_POSFROMCHAR
,1,0);
2841 ok(r
!= -1,"EM_POSFROMCHAR failed index 1\n");
2842 r
= SendMessageA(hwEdit
, EM_POSFROMCHAR
,2,0);
2843 ok(r
!= -1,"EM_POSFROMCHAR failed index 2\n");
2844 r
= SendMessageA(hwEdit
, EM_POSFROMCHAR
,3,0);
2845 ok(r
== -1,"EM_POSFROMCHAR succeeded index 3\n");
2847 DestroyWindow (hwEdit
);
2848 DeleteObject(hfont
);
2851 struct dialog_mode_messages
2853 int wm_getdefid
, wm_close
, wm_command
, wm_nextdlgctl
;
2856 static struct dialog_mode_messages dm_messages
;
2858 static void zero_dm_messages(void)
2860 dm_messages
.wm_command
= 0;
2861 dm_messages
.wm_close
= 0;
2862 dm_messages
.wm_getdefid
= 0;
2863 dm_messages
.wm_nextdlgctl
= 0;
2866 #define test_dm_messages(wmcommand, wmclose, wmgetdefid, wmnextdlgctl) \
2867 ok(dm_messages.wm_command == wmcommand, "expected %d WM_COMMAND messages, " \
2868 "got %d\n", wmcommand, dm_messages.wm_command); \
2869 ok(dm_messages.wm_close == wmclose, "expected %d WM_CLOSE messages, " \
2870 "got %d\n", wmclose, dm_messages.wm_close); \
2871 ok(dm_messages.wm_getdefid == wmgetdefid, "expected %d WM_GETDIFID messages, " \
2872 "got %d\n", wmgetdefid, dm_messages.wm_getdefid);\
2873 ok(dm_messages.wm_nextdlgctl == wmnextdlgctl, "expected %d WM_NEXTDLGCTL messages, " \
2874 "got %d\n", wmnextdlgctl, dm_messages.wm_nextdlgctl)
2876 static LRESULT CALLBACK
dialog_mode_wnd_proc(HWND hwnd
, UINT iMsg
, WPARAM wParam
, LPARAM lParam
)
2881 dm_messages
.wm_command
++;
2884 dm_messages
.wm_getdefid
++;
2885 return MAKELONG(ID_EDITTESTDBUTTON
, DC_HASDEFID
);
2887 dm_messages
.wm_nextdlgctl
++;
2890 dm_messages
.wm_close
++;
2894 return DefWindowProcA(hwnd
, iMsg
, wParam
, lParam
);
2897 static void test_dialogmode(void)
2899 HWND hwEdit
, hwParent
, hwButton
;
2902 hwEdit
= create_child_editcontrol(ES_MULTILINE
, 0);
2904 r
= SendMessageA(hwEdit
, WM_CHAR
, VK_RETURN
, 0x1c0001);
2905 ok(1 == r
, "expected 1, got %d\n", r
);
2906 len
= SendMessageA(hwEdit
, WM_GETTEXTLENGTH
, 0, 0);
2907 ok(11 == len
, "expected 11, got %d\n", len
);
2909 r
= SendMessageA(hwEdit
, WM_GETDLGCODE
, 0, 0);
2910 ok(0x8d == r
, "expected 0x8d, got 0x%x\n", r
);
2912 r
= SendMessageA(hwEdit
, WM_CHAR
, VK_RETURN
, 0x1c0001);
2913 ok(1 == r
, "expected 1, got %d\n", r
);
2914 len
= SendMessageA(hwEdit
, WM_GETTEXTLENGTH
, 0, 0);
2915 ok(13 == len
, "expected 13, got %d\n", len
);
2917 r
= SendMessageA(hwEdit
, WM_GETDLGCODE
, 0, (LPARAM
)&msg
);
2918 ok(0x8d == r
, "expected 0x8d, got 0x%x\n", r
);
2919 r
= SendMessageA(hwEdit
, WM_CHAR
, VK_RETURN
, 0x1c0001);
2920 ok(1 == r
, "expected 1, got %d\n", r
);
2921 len
= SendMessageA(hwEdit
, WM_GETTEXTLENGTH
, 0, 0);
2922 ok(13 == len
, "expected 13, got %d\n", len
);
2924 r
= SendMessageA(hwEdit
, WM_CHAR
, VK_RETURN
, 0x1c0001);
2925 ok(1 == r
, "expected 1, got %d\n", r
);
2926 len
= SendMessageA(hwEdit
, WM_GETTEXTLENGTH
, 0, 0);
2927 ok(13 == len
, "expected 13, got %d\n", len
);
2929 destroy_child_editcontrol(hwEdit
);
2931 hwEdit
= create_editcontrol(ES_MULTILINE
, 0);
2933 r
= SendMessageA(hwEdit
, WM_CHAR
, VK_RETURN
, 0x1c0001);
2934 ok(1 == r
, "expected 1, got %d\n", r
);
2935 len
= SendMessageA(hwEdit
, WM_GETTEXTLENGTH
, 0, 0);
2936 ok(11 == len
, "expected 11, got %d\n", len
);
2939 msg
.message
= WM_KEYDOWN
;
2940 msg
.wParam
= VK_BACK
;
2941 msg
.lParam
= 0xe0001;
2942 r
= SendMessageA(hwEdit
, WM_GETDLGCODE
, VK_BACK
, (LPARAM
)&msg
);
2943 ok(0x8d == r
, "expected 0x8d, got 0x%x\n", r
);
2945 r
= SendMessageA(hwEdit
, WM_CHAR
, VK_RETURN
, 0x1c0001);
2946 ok(1 == r
, "expected 1, got %d\n", r
);
2947 len
= SendMessageA(hwEdit
, WM_GETTEXTLENGTH
, 0, 0);
2948 ok(11 == len
, "expected 11, got %d\n", len
);
2950 DestroyWindow(hwEdit
);
2952 hwEdit
= create_child_editcontrol(0, 0);
2953 hwParent
= GetParent(hwEdit
);
2954 SetWindowLongPtrA(hwParent
, GWLP_WNDPROC
, (LONG_PTR
)dialog_mode_wnd_proc
);
2957 r
= SendMessageA(hwEdit
, WM_KEYDOWN
, VK_ESCAPE
, 0x10001);
2958 ok(1 == r
, "expected 1, got %d\n", r
);
2959 test_dm_messages(0, 0, 0, 0);
2962 r
= SendMessageA(hwEdit
, WM_KEYDOWN
, VK_TAB
, 0xf0001);
2963 ok(1 == r
, "expected 1, got %d\n", r
);
2964 test_dm_messages(0, 0, 0, 0);
2968 msg
.message
= WM_KEYDOWN
;
2969 msg
.wParam
= VK_TAB
;
2970 msg
.lParam
= 0xf0001;
2971 r
= SendMessageA(hwEdit
, WM_GETDLGCODE
, VK_TAB
, (LPARAM
)&msg
);
2972 ok(0x89 == r
, "expected 0x89, got 0x%x\n", r
);
2973 test_dm_messages(0, 0, 0, 0);
2976 r
= SendMessageA(hwEdit
, WM_KEYDOWN
, VK_TAB
, 0xf0001);
2977 ok(1 == r
, "expected 1, got %d\n", r
);
2978 test_dm_messages(0, 0, 0, 0);
2981 destroy_child_editcontrol(hwEdit
);
2983 hwEdit
= create_child_editcontrol(ES_MULTILINE
, 0);
2984 hwParent
= GetParent(hwEdit
);
2985 SetWindowLongPtrA(hwParent
, GWLP_WNDPROC
, (LONG_PTR
)dialog_mode_wnd_proc
);
2987 r
= SendMessageA(hwEdit
, WM_KEYDOWN
, VK_TAB
, 0xf0001);
2988 ok(1 == r
, "expected 1, got %d\n", r
);
2989 test_dm_messages(0, 0, 0, 0);
2993 msg
.message
= WM_KEYDOWN
;
2994 msg
.wParam
= VK_ESCAPE
;
2995 msg
.lParam
= 0x10001;
2996 r
= SendMessageA(hwEdit
, WM_GETDLGCODE
, VK_ESCAPE
, (LPARAM
)&msg
);
2997 ok(0x8d == r
, "expected 0x8d, got 0x%x\n", r
);
2998 test_dm_messages(0, 0, 0, 0);
3001 r
= SendMessageA(hwEdit
, WM_KEYDOWN
, VK_ESCAPE
, 0x10001);
3002 ok(1 == r
, "expected 1, got %d\n", r
);
3003 test_dm_messages(0, 0, 0, 0);
3006 r
= SendMessageA(hwEdit
, WM_KEYDOWN
, VK_TAB
, 0xf0001);
3007 ok(1 == r
, "expected 1, got %d\n", r
);
3008 test_dm_messages(0, 0, 0, 1);
3011 r
= SendMessageA(hwEdit
, WM_KEYDOWN
, VK_RETURN
, 0x1c0001);
3012 ok(1 == r
, "expected 1, got %d\n", r
);
3013 test_dm_messages(0, 0, 1, 0);
3016 hwButton
= CreateWindowA("BUTTON", "OK", WS_VISIBLE
|WS_CHILD
|BS_PUSHBUTTON
,
3017 100, 100, 50, 20, hwParent
, (HMENU
)ID_EDITTESTDBUTTON
, hinst
, NULL
);
3018 ok(hwButton
!=NULL
, "CreateWindow failed with error code %ld\n", GetLastError());
3020 r
= SendMessageA(hwEdit
, WM_KEYDOWN
, VK_RETURN
, 0x1c0001);
3021 ok(1 == r
, "expected 1, got %d\n", r
);
3022 test_dm_messages(0, 0, 1, 1);
3025 DestroyWindow(hwButton
);
3026 destroy_child_editcontrol(hwEdit
);
3029 static void test_EM_GETHANDLE(void)
3031 static const WCHAR str1W
[] = {'1','1','1','1','+','1','1','1','1','+','1','1','1','1','#',0};
3032 static const WCHAR str2W
[] = {'2','2','2','2','-','2','2','2','2','-','2','2','2','2','-','2','2','2','2','#',0};
3033 static const char str0
[] = "untouched";
3034 static const char str1
[] = "1111+1111+1111#";
3035 static const char str1_1
[] = "2111+1111+1111#";
3036 static const char str2
[] = "2222-2222-2222-2222#";
3037 static const char str3
[] = "3333*3333*3333*3333*3333#";
3047 trace("EDIT: EM_GETHANDLE\n");
3049 /* EM_GETHANDLE is not supported for a single line edit control */
3050 hEdit
= create_editcontrol(WS_BORDER
, 0);
3051 ok(hEdit
!= NULL
, "got %p (expected != NULL)\n", hEdit
);
3053 hmem
= (HGLOBAL
) SendMessageA(hEdit
, EM_GETHANDLE
, 0, 0);
3054 ok(hmem
== NULL
, "got %p (expected NULL)\n", hmem
);
3055 DestroyWindow(hEdit
);
3057 /* EM_GETHANDLE needs a multiline edit control */
3058 hEdit
= create_editcontrol(WS_BORDER
| ES_MULTILINE
, 0);
3059 ok(hEdit
!= NULL
, "got %p (expected != NULL)\n", hEdit
);
3062 r
= SendMessageA(hEdit
, WM_SETTEXT
, 0, (LPARAM
)str1
);
3063 len
= SendMessageA(hEdit
, WM_GETTEXTLENGTH
, 0, 0);
3064 ok((r
== 1) && (len
== lstrlenA(str1
)), "got %d and %d (expected 1 and %d)\n", r
, len
, lstrlenA(str1
));
3066 lstrcpyA(current
, str0
);
3067 r
= SendMessageA(hEdit
, WM_GETTEXT
, sizeof(current
), (LPARAM
)current
);
3068 ok((r
== lstrlenA(str1
)) && !lstrcmpA(current
, str1
),
3069 "got %d and \"%s\" (expected %d and \"%s\")\n", r
, current
, lstrlenA(str1
), str1
);
3071 hmem
= (HGLOBAL
) SendMessageA(hEdit
, EM_GETHANDLE
, 0, 0);
3072 ok(hmem
!= NULL
, "got %p (expected != NULL)\n", hmem
);
3073 /* The buffer belongs to the app now. According to MSDN, the app has to LocalFree the
3074 buffer, LocalAlloc a new buffer and pass it to the edit control with EM_SETHANDLE. */
3076 buffer
= LocalLock(hmem
);
3077 ok(buffer
!= NULL
, "got %p (expected != NULL)\n", buffer
);
3078 len
= lstrlenW(buffer
);
3079 ok(len
== lstrlenW(str1W
) && !lstrcmpW(buffer
, str1W
), "Unexpected buffer contents %s, length %d.\n",
3080 wine_dbgstr_w(buffer
), len
);
3083 /* See if WM_GETTEXTLENGTH/WM_GETTEXT still work. */
3084 len
= SendMessageA(hEdit
, WM_GETTEXTLENGTH
, 0, 0);
3085 ok(len
== lstrlenA(str1
), "Unexpected text length %d.\n", len
);
3087 lstrcpyA(current
, str0
);
3088 r
= SendMessageA(hEdit
, WM_GETTEXT
, sizeof(current
), (LPARAM
)current
);
3089 ok((r
== lstrlenA(str1
)) && !lstrcmpA(current
, str1
),
3090 "Unexpected retval %d and text \"%s\" (expected %d and \"%s\")\n", r
, current
, lstrlenA(str1
), str1
);
3092 /* Application altered buffer contents, see if WM_GETTEXTLENGTH/WM_GETTEXT pick that up. */
3093 buffer
= LocalLock(hmem
);
3094 ok(buffer
!= NULL
, "got %p (expected != NULL)\n", buffer
);
3098 len
= SendMessageA(hEdit
, WM_GETTEXTLENGTH
, 0, 0);
3099 ok(len
== lstrlenA(str1_1
), "Unexpected text length %d.\n", len
);
3101 lstrcpyA(current
, str0
);
3102 r
= SendMessageA(hEdit
, WM_GETTEXT
, sizeof(current
), (LPARAM
)current
);
3103 ok(r
== lstrlenA(str1_1
) && !lstrcmpA(current
, str1_1
),
3104 "Unexpected retval %d and text \"%s\" (expected %d and \"%s\")\n", r
, current
, lstrlenA(str1_1
), str1_1
);
3106 /* See if WM_SETTEXT/EM_REPLACESEL work. */
3107 r
= SendMessageA(hEdit
, WM_SETTEXT
, 0, (LPARAM
)str1
);
3108 ok(r
, "Failed to set text.\n");
3110 buffer
= LocalLock(hmem
);
3111 ok(buffer
!= NULL
&& buffer
[0] == '1', "Unexpected buffer contents\n");
3114 r
= SendMessageA(hEdit
, EM_REPLACESEL
, 0, (LPARAM
)str1_1
);
3115 ok(r
, "Failed to replace selection.\n");
3117 buffer
= LocalLock(hmem
);
3118 ok(buffer
!= NULL
&& buffer
[0] == '2', "Unexpected buffer contents\n");
3121 /* use LocalAlloc first to get a different handle */
3122 halloc
= LocalAlloc(LMEM_MOVEABLE
, 42);
3123 ok(halloc
!= NULL
, "got %p (expected != NULL)\n", halloc
);
3124 /* prepare our new memory */
3125 buffer
= LocalLock(halloc
);
3126 ok(buffer
!= NULL
, "got %p (expected != NULL)\n", buffer
);
3127 lstrcpyW(buffer
, str2W
);
3128 LocalUnlock(halloc
);
3130 /* LocalFree the old memory handle before EM_SETHANDLE the new handle */
3132 /* use LocalAlloc after the LocalFree to likely consume the handle */
3133 hmem2
= LocalAlloc(LMEM_MOVEABLE
, 42);
3134 ok(hmem2
!= NULL
, "got %p (expected != NULL)\n", hmem2
);
3136 SendMessageA(hEdit
, EM_SETHANDLE
, (WPARAM
)halloc
, 0);
3138 len
= SendMessageA(hEdit
, WM_GETTEXTLENGTH
, 0, 0);
3139 ok(len
== lstrlenA(str2
), "got %d (expected %d)\n", len
, lstrlenA(str2
));
3141 lstrcpyA(current
, str0
);
3142 r
= SendMessageA(hEdit
, WM_GETTEXT
, sizeof(current
), (LPARAM
)current
);
3143 ok(r
== lstrlenA(str2
) && !lstrcmpA(current
, str2
),
3144 "got %d and \"%s\" (expected %d and \"%s\")\n", r
, current
, lstrlenA(str2
), str2
);
3146 /* set a different text */
3147 r
= SendMessageA(hEdit
, WM_SETTEXT
, 0, (LPARAM
)str3
);
3148 len
= SendMessageA(hEdit
, WM_GETTEXTLENGTH
, 0, 0);
3149 ok((r
== 1) && (len
== lstrlenA(str3
)), "got %d and %d (expected 1 and %d)\n", r
, len
, lstrlenA(str3
));
3151 lstrcpyA(current
, str0
);
3152 r
= SendMessageA(hEdit
, WM_GETTEXT
, sizeof(current
), (LPARAM
)current
);
3153 ok((r
== lstrlenA(str3
)) && !lstrcmpA(current
, str3
),
3154 "got %d and \"%s\" (expected %d and \"%s\")\n", r
, current
, lstrlenA(str3
), str3
);
3157 DestroyWindow(hEdit
);
3159 /* Some apps have bugs ... */
3160 hEdit
= create_editcontrol(WS_BORDER
| ES_MULTILINE
, 0);
3163 r
= SendMessageA(hEdit
, WM_SETTEXT
, 0, (LPARAM
)str1
);
3164 len
= SendMessageA(hEdit
, WM_GETTEXTLENGTH
, 0, 0);
3165 ok((r
== 1) && (len
== lstrlenA(str1
)), "got %d and %d (expected 1 and %d)\n", r
, len
, lstrlenA(str1
));
3167 /* everything is normal up to EM_GETHANDLE */
3168 hmem
= (HGLOBAL
) SendMessageA(hEdit
, EM_GETHANDLE
, 0, 0);
3169 /* Some messages still work while other messages fail.
3170 After LocalFree the memory handle, messages can crash the app */
3172 /* A buggy editor used EM_GETHANDLE twice */
3173 hmem2
= (HGLOBAL
) SendMessageA(hEdit
, EM_GETHANDLE
, 0, 0);
3174 ok(hmem2
== hmem
, "got %p (expected %p)\n", hmem2
, hmem
);
3176 /* Let the edit control free the memory handle */
3177 SendMessageA(hEdit
, EM_SETHANDLE
, (WPARAM
)hmem2
, 0);
3179 DestroyWindow(hEdit
);
3182 static void test_paste(void)
3184 static const char *str
= "this is a simple text";
3185 static const char *str2
= "first line\r\nsecond line";
3186 HWND hEdit
, hMultilineEdit
;
3187 HANDLE hmem
, hmem_ret
;
3191 hEdit
= create_editcontrol(ES_AUTOHSCROLL
| ES_AUTOVSCROLL
, 0);
3192 hMultilineEdit
= create_editcontrol(ES_AUTOHSCROLL
| ES_AUTOVSCROLL
| ES_MULTILINE
, 0);
3194 /* Prepare clipboard data with simple text */
3195 hmem
= GlobalAlloc(GMEM_MOVEABLE
, 255);
3196 ok(hmem
!= NULL
, "got %p (expected != NULL)\n", hmem
);
3197 buffer
= GlobalLock(hmem
);
3198 ok(buffer
!= NULL
, "got %p (expected != NULL)\n", buffer
);
3199 strcpy(buffer
, str
);
3202 r
= OpenClipboard(hEdit
);
3203 ok(r
== TRUE
, "expected %d, got %d\n", TRUE
, r
);
3204 r
= EmptyClipboard();
3205 ok(r
== TRUE
, "expected %d, got %d\n", TRUE
, r
);
3206 hmem_ret
= SetClipboardData(CF_TEXT
, hmem
);
3207 ok(hmem_ret
== hmem
, "expected %p, got %p\n", hmem
, hmem_ret
);
3208 r
= CloseClipboard();
3209 ok(r
== TRUE
, "expected %d, got %d\n", TRUE
, r
);
3211 /* Paste single line */
3212 SendMessageA(hEdit
, WM_SETTEXT
, 0, (LPARAM
)"");
3213 r
= SendMessageA(hEdit
, WM_PASTE
, 0, 0);
3214 len
= SendMessageA(hEdit
, WM_GETTEXTLENGTH
, 0, 0);
3215 ok(strlen(str
) == len
, "got %d\n", len
);
3217 /* Prepare clipboard data with multiline text */
3218 hmem
= GlobalAlloc(GMEM_MOVEABLE
, 255);
3219 ok(hmem
!= NULL
, "got %p (expected != NULL)\n", hmem
);
3220 buffer
= GlobalLock(hmem
);
3221 ok(buffer
!= NULL
, "got %p (expected != NULL)\n", buffer
);
3222 strcpy(buffer
, str2
);
3225 r
= OpenClipboard(hEdit
);
3226 ok(r
== TRUE
, "expected %d, got %d\n", TRUE
, r
);
3227 r
= EmptyClipboard();
3228 ok(r
== TRUE
, "expected %d, got %d\n", TRUE
, r
);
3229 hmem_ret
= SetClipboardData(CF_TEXT
, hmem
);
3230 ok(hmem_ret
== hmem
, "expected %p, got %p\n", hmem
, hmem_ret
);
3231 r
= CloseClipboard();
3232 ok(r
== TRUE
, "expected %d, got %d\n", TRUE
, r
);
3234 /* Paste multiline text in singleline edit - should be cut */
3235 SendMessageA(hEdit
, WM_SETTEXT
, 0, (LPARAM
)"");
3236 r
= SendMessageA(hEdit
, WM_PASTE
, 0, 0);
3237 len
= SendMessageA(hEdit
, WM_GETTEXTLENGTH
, 0, 0);
3238 ok(strlen("first line") == len
, "got %d\n", len
);
3240 /* Paste multiline text in multiline edit */
3241 SendMessageA(hMultilineEdit
, WM_SETTEXT
, 0, (LPARAM
)"");
3242 r
= SendMessageA(hMultilineEdit
, WM_PASTE
, 0, 0);
3243 len
= SendMessageA(hMultilineEdit
, WM_GETTEXTLENGTH
, 0, 0);
3244 ok(strlen(str2
) == len
, "got %d\n", len
);
3247 DestroyWindow(hEdit
);
3248 DestroyWindow(hMultilineEdit
);
3251 static void test_EM_GETLINE(void)
3256 hwnd
[0] = create_editcontrol(ES_AUTOHSCROLL
| ES_AUTOVSCROLL
, 0);
3257 hwnd
[1] = create_editcontrolW(ES_AUTOHSCROLL
| ES_AUTOVSCROLL
, 0);
3259 for (i
= 0; i
< ARRAY_SIZE(hwnd
); i
++)
3261 static const WCHAR strW
[] = {'t','e','x','t',0};
3262 static const char *str
= "text";
3267 ok(IsWindowUnicode(hwnd
[i
]), "Expected unicode window.\n");
3269 SendMessageA(hwnd
[i
], WM_SETTEXT
, 0, (LPARAM
)str
);
3271 memset(buff
, 0, sizeof(buff
));
3272 *(WORD
*)buff
= sizeof(buff
);
3273 r
= SendMessageA(hwnd
[i
], EM_GETLINE
, 0, (LPARAM
)buff
);
3274 ok(r
== strlen(str
), "Failed to get a line %d.\n", r
);
3275 ok(!strcmp(buff
, str
), "Unexpected line data %s.\n", buff
);
3277 memset(buff
, 0, sizeof(buff
));
3278 *(WORD
*)buff
= sizeof(buff
);
3279 r
= SendMessageA(hwnd
[i
], EM_GETLINE
, 1, (LPARAM
)buff
);
3280 ok(r
== strlen(str
), "Failed to get a line %d.\n", r
);
3281 ok(!strcmp(buff
, str
), "Unexpected line data %s.\n", buff
);
3283 memset(buffW
, 0, sizeof(buffW
));
3284 *(WORD
*)buffW
= ARRAY_SIZE(buffW
);
3285 r
= SendMessageW(hwnd
[i
], EM_GETLINE
, 0, (LPARAM
)buffW
);
3286 ok(r
== lstrlenW(strW
), "Failed to get a line %d.\n", r
);
3287 ok(!lstrcmpW(buffW
, strW
), "Unexpected line data %s.\n", wine_dbgstr_w(buffW
));
3289 memset(buffW
, 0, sizeof(buffW
));
3290 *(WORD
*)buffW
= ARRAY_SIZE(buffW
);
3291 r
= SendMessageW(hwnd
[i
], EM_GETLINE
, 1, (LPARAM
)buffW
);
3292 ok(r
== lstrlenW(strW
), "Failed to get a line %d.\n", r
);
3293 ok(!lstrcmpW(buffW
, strW
), "Unexpected line data %s.\n", wine_dbgstr_w(buffW
));
3295 DestroyWindow(hwnd
[i
]);
3299 static int CALLBACK
test_wordbreak_procA(char *text
, int current
, int length
, int code
)
3304 static void test_wordbreak_proc(void)
3306 EDITWORDBREAKPROCA proc
;
3310 hwnd
= create_editcontrol(ES_AUTOHSCROLL
| ES_AUTOVSCROLL
, 0);
3312 proc
= (void *)SendMessageA(hwnd
, EM_GETWORDBREAKPROC
, 0, 0);
3313 ok(proc
== NULL
, "Unexpected wordbreak proc %p.\n", proc
);
3315 ret
= SendMessageA(hwnd
, EM_SETWORDBREAKPROC
, 0, (LPARAM
)test_wordbreak_procA
);
3316 ok(ret
== 1, "Unexpected return value %Id.\n", ret
);
3318 proc
= (void *)SendMessageA(hwnd
, EM_GETWORDBREAKPROC
, 0, 0);
3319 ok(proc
== test_wordbreak_procA
, "Unexpected wordbreak proc %p.\n", proc
);
3321 ret
= SendMessageA(hwnd
, EM_SETWORDBREAKPROC
, 0, 0);
3322 ok(ret
== 1, "Unexpected return value %Id.\n", ret
);
3324 proc
= (void *)SendMessageA(hwnd
, EM_GETWORDBREAKPROC
, 0, 0);
3325 ok(proc
== NULL
, "Unexpected wordbreak proc %p.\n", proc
);
3327 DestroyWindow(hwnd
);
3330 static const struct message setfocus_combined_seq
[] =
3332 { WM_KILLFOCUS
, sent
|id
, 0, 0, PARENT_ID
},
3333 { WM_SETFOCUS
, sent
|id
, 0, 0, EDIT_ID
},
3334 { WM_COMMAND
, sent
|wparam
|id
, MAKEWPARAM(1, EN_SETFOCUS
), 0, PARENT_ID
},
3335 { WM_PAINT
, sent
|id
, 0, 0, EDIT_ID
},
3336 { WM_NCPAINT
, sent
|id
|defwinproc
|optional
, 0, 0, EDIT_ID
},
3337 { WM_ERASEBKGND
, sent
|id
|defwinproc
|optional
, 0, 0, EDIT_ID
},
3341 static const struct message killfocus_combined_seq
[] =
3343 { WM_KILLFOCUS
, sent
|id
, 0, 0, EDIT_ID
},
3344 { WM_COMMAND
, sent
|wparam
|id
, MAKEWPARAM(1, EN_KILLFOCUS
), 0, PARENT_ID
},
3345 { WM_SETFOCUS
, sent
|id
, 0, 0, PARENT_ID
},
3346 { WM_PAINT
, sent
|id
, 0, 0, EDIT_ID
},
3347 { WM_NCPAINT
, sent
|id
|defwinproc
|optional
, 0, 0, EDIT_ID
},
3351 static const struct message setfocus_sent_only_combined_seq
[] =
3353 { WM_KILLFOCUS
, sent
|id
, 0, 0, PARENT_ID
},
3354 { WM_SETFOCUS
, sent
|id
, 0, 0, EDIT_ID
},
3355 { WM_COMMAND
, sent
|wparam
|id
, MAKEWPARAM(1, EN_SETFOCUS
), 0, PARENT_ID
},
3359 static const struct message killfocus_sent_only_combined_seq
[] =
3361 { WM_KILLFOCUS
, sent
|id
, 0, 0, EDIT_ID
},
3362 { WM_COMMAND
, sent
|wparam
|id
, MAKEWPARAM(1, EN_KILLFOCUS
), 0, PARENT_ID
},
3363 { WM_SETFOCUS
, sent
|id
, 0, 0, PARENT_ID
},
3367 static void test_cue_banner(void)
3371 static WCHAR getcuetestW
[5] = {'T',0};
3372 static const WCHAR testcmp1W
[] = {'T','e','s','t',0};
3373 static const WCHAR testcmp2W
[] = {'T','e','s',0};
3375 hwnd_edit
= create_editcontrolW(ES_AUTOHSCROLL
| ES_AUTOVSCROLL
, 0);
3377 ret
= SendMessageW(hwnd_edit
, EM_GETCUEBANNER
, (WPARAM
)getcuetestW
, 5);
3380 win_skip("skipping for Win XP and 2003 Server.\n");
3381 DestroyWindow(hwnd_edit
);
3384 ok(!getcuetestW
[0], "First char is %c\n", getcuetestW
[0]);
3385 ok(ret
== FALSE
, "EM_GETCUEBANNER should have returned FALSE.\n");
3387 lstrcpyW(getcuetestW
, testcmp1W
);
3388 ret
= SendMessageW(hwnd_edit
, EM_GETCUEBANNER
, (WPARAM
)getcuetestW
, 0);
3389 ok(lstrcmpW(getcuetestW
, testcmp1W
) == 0, "String was %s.\n", wine_dbgstr_w(getcuetestW
));
3390 ok(ret
== FALSE
, "EM_GETCUEBANNER should have returned FALSE.\n");
3392 ret
= SendMessageW(hwnd_edit
, EM_GETCUEBANNER
, 0, 0);
3393 ok(ret
== FALSE
, "EM_GETCUEBANNER should have returned FALSE.\n");
3395 ret
= SendMessageW(hwnd_edit
, EM_SETCUEBANNER
, 0, 0);
3396 ok(ret
== FALSE
, "EM_SETCUEBANNER should have returned FALSE.\n");
3398 ret
= SendMessageW(hwnd_edit
, EM_GETCUEBANNER
, 0, 0);
3399 ok(ret
== FALSE
, "EM_GETCUEBANNER should have returned FALSE.\n");
3401 lstrcpyW(getcuetestW
, testcmp1W
);
3402 ret
= SendMessageW(hwnd_edit
, EM_SETCUEBANNER
, 0, (LPARAM
)getcuetestW
);
3403 ok(ret
== TRUE
, "EM_SETCUEBANNER should have returned TRUE.\n");
3405 ret
= SendMessageW(hwnd_edit
, EM_GETCUEBANNER
, 0, 5);
3406 ok(ret
== TRUE
, "EM_GETCUEBANNER should have returned TRUE.\n");
3408 ret
= SendMessageW(hwnd_edit
, EM_GETCUEBANNER
, (WPARAM
)getcuetestW
, 5);
3409 ok(ret
== TRUE
, "EM_GETCUEBANNER should have returned TRUE.\n");
3410 ok(lstrcmpW(getcuetestW
, testcmp1W
) == 0, "EM_GETCUEBANNER returned string %s.\n", wine_dbgstr_w(getcuetestW
));
3412 ret
= SendMessageW(hwnd_edit
, EM_SETCUEBANNER
, 0, (LPARAM
)L
"");
3413 ok(ret
== TRUE
, "EM_SETCUEBANNER should have returned TRUE.\n");
3415 ret
= SendMessageW(hwnd_edit
, EM_GETCUEBANNER
, (WPARAM
)getcuetestW
, 5);
3416 ok(ret
== TRUE
, "EM_GETCUEBANNER should have returned TRUE.\n");
3417 ok(!getcuetestW
[0], "EM_GETCUEBANNER returned string %s.\n", wine_dbgstr_w(getcuetestW
));
3419 /* EM_GETCUEBANNER's buffer size includes null char */
3420 ret
= SendMessageW(hwnd_edit
, EM_SETCUEBANNER
, 0, (LPARAM
)testcmp1W
);
3421 ok(ret
== TRUE
, "EM_SETCUEBANNER should have returned TRUE.\n");
3422 memset(getcuetestW
, 0, lstrlenW(testcmp1W
)*sizeof(WCHAR
));
3423 ret
= SendMessageW(hwnd_edit
, EM_GETCUEBANNER
, (WPARAM
)getcuetestW
, (LPARAM
)lstrlenW(testcmp1W
)+1);
3424 ok(ret
== TRUE
, "EM_GETCUEBANNER should have returned TRUE.\n");
3425 ok(lstrcmpW(getcuetestW
, testcmp1W
) == 0, "EM_GETCUEBANNER returned string %s.\n", wine_dbgstr_w(getcuetestW
));
3426 memset(getcuetestW
, 0, lstrlenW(testcmp1W
)*sizeof(WCHAR
));
3427 ret
= SendMessageW(hwnd_edit
, EM_GETCUEBANNER
, (WPARAM
)getcuetestW
, (LPARAM
)lstrlenW(testcmp1W
));
3428 ok(lstrcmpW(getcuetestW
, testcmp2W
) == 0, "EM_GETCUEBANNER returned string %s.\n", wine_dbgstr_w(getcuetestW
));
3429 DestroyWindow(hwnd_edit
);
3431 /* setting cue banner fails for multi-line edit controls */
3432 hwnd_edit
= create_editcontrolW(ES_AUTOHSCROLL
| ES_AUTOVSCROLL
| ES_MULTILINE
, 0);
3433 lstrcpyW(getcuetestW
, testcmp1W
);
3434 ret
= SendMessageW(hwnd_edit
, EM_GETCUEBANNER
, (WPARAM
)getcuetestW
, 5);
3435 ok(ret
== FALSE
, "EM_SETCUEBANNER.\n");
3436 ok(lstrcmpW(getcuetestW
, testcmp1W
) == 0, "String was %s.\n", wine_dbgstr_w(getcuetestW
));
3437 ret
= SendMessageW(hwnd_edit
, EM_SETCUEBANNER
, 0, (LPARAM
)getcuetestW
);
3438 ok(ret
== FALSE
, "EM_SETCUEBANNER.\n");
3440 DestroyWindow(hwnd_edit
);
3443 static void test_change_focus(void)
3445 HWND hwnd
, parent_wnd
;
3450 GetCursorPos(&orig_pos
);
3452 parent_wnd
= CreateWindowA("ParentWnd", "", WS_OVERLAPPEDWINDOW
,
3453 0, 0, 200, 200, NULL
, NULL
, GetModuleHandleA(NULL
), NULL
);
3454 ok(parent_wnd
!= NULL
, "Failed to create control parent.\n");
3455 SetWindowPos(parent_wnd
, HWND_TOPMOST
, 0, 0, 0, 0, SWP_NOSIZE
|SWP_NOMOVE
);
3456 ShowWindow(parent_wnd
, SW_SHOW
);
3458 hwnd
= CreateWindowExA(0, WC_EDITA
, "Test", WS_CHILD
| WS_VISIBLE
, 0, 0, 100, 100,
3459 parent_wnd
, (HMENU
)1, GetModuleHandleA(NULL
), NULL
);
3460 ok(hwnd
!= NULL
, "Failed to create Edit control.\n");
3462 oldproc
= (WNDPROC
)SetWindowLongPtrA(hwnd
, GWLP_WNDPROC
, (LONG_PTR
)edit_subclass_proc
);
3463 SetWindowLongPtrA(hwnd
, GWLP_USERDATA
, (LONG_PTR
)oldproc
);
3465 SetCursorPos(400, 400);
3468 SetFocus(parent_wnd
);
3469 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
3471 while (PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
)) DispatchMessageA(&msg
);
3472 ok_sequence(sequences
, COMBINED_SEQ_INDEX
, setfocus_combined_seq
, "Set focus", TRUE
);
3474 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
3475 SetFocus(parent_wnd
);
3476 while (PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
)) DispatchMessageA(&msg
);
3477 ok_sequence(sequences
, COMBINED_SEQ_INDEX
, killfocus_combined_seq
, "Kill focus", FALSE
);
3479 /* Test message sequences without waiting for posted messages */
3480 SetFocus(parent_wnd
);
3481 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
3483 ok_sequence(sequences
, COMBINED_SEQ_INDEX
, setfocus_sent_only_combined_seq
,
3484 "Set focus sent only", FALSE
);
3486 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
3487 SetFocus(parent_wnd
);
3488 ok_sequence(sequences
, COMBINED_SEQ_INDEX
, killfocus_sent_only_combined_seq
,
3489 "Kill focus sent only", FALSE
);
3491 SetCursorPos(orig_pos
.x
, orig_pos
.y
);
3493 DestroyWindow(hwnd
);
3496 static const struct message wm_ime_composition_seq
[] =
3498 {WM_IME_STARTCOMPOSITION
, sent
},
3499 {WM_IME_COMPOSITION
, sent
| wparam
, 'W'},
3500 {WM_IME_CHAR
, sent
| wparam
| defwinproc
, 'W'},
3501 {WM_IME_CHAR
, sent
| wparam
| defwinproc
, 'i'},
3502 {WM_IME_CHAR
, sent
| wparam
| defwinproc
, 'n'},
3503 {WM_IME_CHAR
, sent
| wparam
| defwinproc
, 'e'},
3504 {WM_IME_ENDCOMPOSITION
, sent
},
3505 {WM_CHAR
, sent
| wparam
, 'W'},
3506 {WM_CHAR
, sent
| wparam
, 'i'},
3507 {WM_CHAR
, sent
| wparam
, 'n'},
3508 {WM_CHAR
, sent
| wparam
, 'e'},
3512 static const struct message wm_ime_char_seq
[] =
3514 {WM_IME_CHAR
, sent
| wparam
, '0'},
3515 {WM_CHAR
, sent
| wparam
, '0'},
3519 static const struct message eimes_getcompstratonce_seq
[] =
3521 {WM_IME_STARTCOMPOSITION
, sent
},
3522 {WM_IME_COMPOSITION
, sent
| wparam
, 'W'},
3523 {WM_IME_ENDCOMPOSITION
, sent
},
3527 static LRESULT CALLBACK
edit_ime_subclass_proc(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
3529 WNDPROC oldproc
= (WNDPROC
)GetWindowLongPtrA(hwnd
, GWLP_USERDATA
);
3530 static LONG defwndproc_counter
= 0;
3531 struct message msg
= {0};
3534 msg
.message
= message
;
3535 msg
.flags
= sent
| wparam
;
3536 if (defwndproc_counter
)
3537 msg
.flags
|= defwinproc
;
3538 msg
.wParam
= wParam
;
3540 if (message
< 0xc000 &&
3541 message
!= WM_GETTEXTLENGTH
&&
3542 message
!= WM_GETTEXT
&&
3543 message
!= WM_GETFONT
&&
3544 message
!= WM_GETICON
&&
3545 message
!= WM_IME_SETCONTEXT
&&
3546 message
!= WM_IME_NOTIFY
&&
3547 message
!= WM_CTLCOLOREDIT
&&
3548 message
!= WM_PAINT
&&
3549 message
!= WM_ERASEBKGND
&&
3550 message
!= WM_NCHITTEST
&&
3551 message
!= WM_SETCURSOR
&&
3552 message
!= WM_MOUSEMOVE
&&
3553 message
!= WM_MOUSEACTIVATE
&&
3554 message
!= WM_KEYUP
&&
3555 (message
< EM_GETSEL
|| message
> EM_GETIMESTATUS
))
3557 add_message(sequences
, COMBINED_SEQ_INDEX
, &msg
);
3560 defwndproc_counter
++;
3561 if (IsWindowUnicode(hwnd
))
3562 ret
= CallWindowProcW(oldproc
, hwnd
, message
, wParam
, lParam
);
3564 ret
= CallWindowProcA(oldproc
, hwnd
, message
, wParam
, lParam
);
3565 defwndproc_counter
--;
3570 static void test_ime(void)
3579 hwnd
= create_editcontrol(WS_POPUP
| WS_VISIBLE
, 0);
3581 /* Test EM_{GET|SET}IMESTATUS */
3582 lr
= SendMessageA(hwnd
, EM_GETIMESTATUS
, EMSIS_COMPOSITIONSTRING
, 0);
3583 ok(lr
== 0, "Got unexpected lr %#Ix.\n", lr
);
3585 /* Note that EM_SETIMESTATUS always return 1, which is contrary to what MSDN says about
3586 * returning the previous LPARAM value */
3587 lr
= SendMessageA(hwnd
, EM_SETIMESTATUS
, EMSIS_COMPOSITIONSTRING
, EIMES_GETCOMPSTRATONCE
);
3588 ok(lr
== 1, "Got unexpected lr %#Ix.\n", lr
);
3589 lr
= SendMessageA(hwnd
, EM_GETIMESTATUS
, EMSIS_COMPOSITIONSTRING
, 0);
3590 ok(lr
== EIMES_GETCOMPSTRATONCE
, "Got unexpected lr %#Ix.\n", lr
);
3592 lr
= SendMessageA(hwnd
, EM_SETIMESTATUS
, EMSIS_COMPOSITIONSTRING
, EIMES_CANCELCOMPSTRINFOCUS
);
3593 ok(lr
== 1, "Got unexpected lr %#Ix.\n", lr
);
3594 lr
= SendMessageA(hwnd
, EM_GETIMESTATUS
, EMSIS_COMPOSITIONSTRING
, 0);
3595 ok(lr
== EIMES_CANCELCOMPSTRINFOCUS
, "Got unexpected lr %#Ix.\n", lr
);
3597 lr
= SendMessageA(hwnd
, EM_SETIMESTATUS
, EMSIS_COMPOSITIONSTRING
, EIMES_COMPLETECOMPSTRKILLFOCUS
);
3598 ok(lr
== 1, "Got unexpected lr %#Ix.\n", lr
);
3599 lr
= SendMessageA(hwnd
, EM_GETIMESTATUS
, EMSIS_COMPOSITIONSTRING
, 0);
3600 ok(lr
== EIMES_COMPLETECOMPSTRKILLFOCUS
, "Got unexpected lr %#Ix.\n", lr
);
3602 lr
= SendMessageA(hwnd
, EM_SETIMESTATUS
, EMSIS_COMPOSITIONSTRING
, EIMES_GETCOMPSTRATONCE
3603 | EIMES_CANCELCOMPSTRINFOCUS
| EIMES_COMPLETECOMPSTRKILLFOCUS
);
3604 ok(lr
== 1, "Got unexpected lr %#Ix.\n", lr
);
3605 lr
= SendMessageA(hwnd
, EM_GETIMESTATUS
, EMSIS_COMPOSITIONSTRING
, 0);
3606 ok(lr
== (EIMES_GETCOMPSTRATONCE
| EIMES_CANCELCOMPSTRINFOCUS
| EIMES_COMPLETECOMPSTRKILLFOCUS
),
3607 "Got unexpected lr %#Ix.\n", lr
);
3609 lr
= SendMessageA(hwnd
, EM_SETIMESTATUS
, EMSIS_COMPOSITIONSTRING
, 0);
3610 ok(lr
== 1, "Got unexpected lr %#Ix.\n", lr
);
3611 lr
= SendMessageA(hwnd
, EM_GETIMESTATUS
, EMSIS_COMPOSITIONSTRING
, 0);
3612 ok(lr
== 0, "Got unexpected lr %#Ix.\n", lr
);
3614 /* Invalid EM_{GET|SET}IMESTATUS status types and flags */
3615 lr
= SendMessageA(hwnd
, EM_GETIMESTATUS
, 0, 0);
3616 ok(lr
== 1, "Got unexpected lr %#Ix.\n", lr
);
3618 lr
= SendMessageA(hwnd
, EM_GETIMESTATUS
, EMSIS_COMPOSITIONSTRING
+ 1, 0);
3619 ok(lr
== 1, "Got unexpected lr %#Ix.\n", lr
);
3621 lr
= SendMessageA(hwnd
, EM_SETIMESTATUS
, 0, EIMES_GETCOMPSTRATONCE
);
3622 ok(lr
== 1, "Got unexpected lr %#Ix.\n", lr
);
3623 lr
= SendMessageA(hwnd
, EM_GETIMESTATUS
, EMSIS_COMPOSITIONSTRING
, 0);
3624 ok(lr
== 0, "Got unexpected lr %#Ix.\n", lr
);
3626 lr
= SendMessageA(hwnd
, EM_SETIMESTATUS
, EMSIS_COMPOSITIONSTRING
+ 1, EIMES_GETCOMPSTRATONCE
);
3627 ok(lr
== 1, "Got unexpected lr %#Ix.\n", lr
);
3628 lr
= SendMessageA(hwnd
, EM_GETIMESTATUS
, EMSIS_COMPOSITIONSTRING
, 0);
3629 ok(lr
== 0, "Got unexpected lr %#Ix.\n", lr
);
3631 lr
= SendMessageA(hwnd
, EM_SETIMESTATUS
, EMSIS_COMPOSITIONSTRING
, 0xFFFFFFFF);
3632 ok(lr
== 1, "Got unexpected lr %#Ix.\n", lr
);
3633 lr
= SendMessageA(hwnd
, EM_GETIMESTATUS
, EMSIS_COMPOSITIONSTRING
, 0);
3634 ok(lr
== 0xFFFF, "Got unexpected lr %#Ix.\n", lr
);
3636 lr
= SendMessageA(hwnd
, EM_SETIMESTATUS
, EMSIS_COMPOSITIONSTRING
, 0);
3637 ok(lr
== 1, "Got unexpected lr %#Ix.\n", lr
);
3638 lr
= SendMessageA(hwnd
, EM_GETIMESTATUS
, EMSIS_COMPOSITIONSTRING
, 0);
3639 ok(lr
== 0, "Got unexpected lr %#Ix.\n", lr
);
3641 /* Test IME messages when EIMES_GETCOMPSTRATONCE is not set */
3642 old_proc
= (WNDPROC
)SetWindowLongPtrA(hwnd
, GWLP_WNDPROC
, (LONG_PTR
)edit_ime_subclass_proc
);
3643 SetWindowLongPtrA(hwnd
, GWLP_USERDATA
, (LONG_PTR
)old_proc
);
3645 himc
= ImmGetContext(hwnd
);
3646 ret
= ImmSetCompositionStringA(himc
, SCS_SETSTR
, "Wine", 4, NULL
, 0);
3647 ok(ret
, "ImmSetCompositionStringA failed.\n");
3648 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
3649 ret
= ImmNotifyIME(himc
, NI_COMPOSITIONSTR
, CPS_COMPLETE
, 0);
3650 ok(ret
, "ImmNotifyIME failed.\n");
3651 /* Note that the following message loop is necessary to get the WM_CHAR messages because they
3652 * are posted. Same for the later message loops in this function. */
3653 while (PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
)) DispatchMessageA(&msg
);
3654 ok_sequence(sequences
, COMBINED_SEQ_INDEX
, wm_ime_composition_seq
, "WM_IME_COMPOSITION", TRUE
);
3656 /* Test that WM_IME_CHAR is passed to DefWindowProc() to get WM_CHAR */
3657 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
3658 SendMessageA(hwnd
, WM_IME_CHAR
, '0', 1);
3659 while (PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
)) DispatchMessageA(&msg
);
3660 ok_sequence(sequences
, COMBINED_SEQ_INDEX
, wm_ime_char_seq
, "WM_IME_CHAR", FALSE
);
3662 /* Test IME messages when EIMES_GETCOMPSTRATONCE is set */
3663 lr
= SendMessageA(hwnd
, EM_SETIMESTATUS
, EMSIS_COMPOSITIONSTRING
, EIMES_GETCOMPSTRATONCE
);
3664 ok(lr
== 1, "Got unexpected lr %#Ix.\n", lr
);
3665 lr
= SendMessageA(hwnd
, EM_GETIMESTATUS
, EMSIS_COMPOSITIONSTRING
, 0);
3666 ok(lr
== EIMES_GETCOMPSTRATONCE
, "Got unexpected lr %#Ix.\n", lr
);
3668 ret
= ImmSetCompositionStringA(himc
, SCS_SETSTR
, "Wine", 4, NULL
, 0);
3669 ok(ret
, "ImmSetCompositionStringA failed.\n");
3670 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
3671 ret
= ImmNotifyIME(himc
, NI_COMPOSITIONSTR
, CPS_COMPLETE
, 0);
3672 ok(ret
, "ImmNotifyIME failed.\n");
3673 while (PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
)) DispatchMessageA(&msg
);
3674 ok_sequence(sequences
, COMBINED_SEQ_INDEX
, eimes_getcompstratonce_seq
,
3675 "WM_IME_COMPOSITION with EIMES_GETCOMPSTRATONCE", TRUE
);
3677 /* Test that WM_IME_CHAR is passed to DefWindowProc() to get WM_CHAR with EIMES_GETCOMPSTRATONCE */
3678 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
3679 SendMessageA(hwnd
, WM_IME_CHAR
, '0', 1);
3680 while (PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
)) DispatchMessageA(&msg
);
3681 ok_sequence(sequences
, COMBINED_SEQ_INDEX
, wm_ime_char_seq
, "WM_IME_CHAR", FALSE
);
3683 ImmReleaseContext(hwnd
, himc
);
3684 DestroyWindow(hwnd
);
3689 ULONG_PTR ctx_cookie
;
3693 if (!load_v6_module(&ctx_cookie
, &hCtx
))
3696 init_msg_sequences(sequences
, NUM_MSG_SEQUENCES
);
3698 hinst
= GetModuleHandleA(NULL
);
3699 b
= register_classes();
3700 ok(b
, "Failed to register test classes.\n");
3703 test_edit_control_1();
3704 test_edit_control_2();
3705 test_edit_control_3();
3706 test_char_from_pos();
3707 test_edit_control_5();
3708 test_edit_control_6();
3709 test_edit_control_limittext();
3710 test_edit_control_scroll();
3711 test_initialization();
3713 test_margins_font_change();
3714 test_text_position();
3720 test_multi_edit_dialog();
3721 test_wantreturn_edit_dialog();
3722 test_singleline_wantreturn_edit_dialog();
3723 test_child_edit_wmkeydown();
3727 test_EM_GETHANDLE();
3730 test_wordbreak_proc();
3731 test_change_focus();
3735 UnregisterWindowClasses();
3737 unload_v6_module(ctx_cookie
, hCtx
);