2 * Unit tests for the pager control
4 * Copyright 2012 Alexandre Julliard
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
24 #include "wine/test.h"
27 #define NUM_MSG_SEQUENCES 1
28 #define PAGER_SEQ_INDEX 0
30 static HWND parent_wnd
, child1_wnd
, child2_wnd
;
31 static INT notify_format
;
32 static BOOL notify_query_received
;
33 static WCHAR test_w
[] = {'t', 'e', 's', 't', 0};
34 static CHAR test_a
[] = {'t', 'e', 's', 't', 0};
35 /* Double zero so that it's safe to cast it to WCHAR * */
36 static CHAR te_a
[] = {'t', 'e', 0, 0};
37 static WCHAR empty_w
[] = {0};
38 static CHAR empty_a
[] = {0};
39 static CHAR large_a
[] = "You should have received a copy of the GNU Lesser General Public License along with this ...";
40 static WCHAR large_w
[] =
42 'Y', 'o', 'u', ' ', 's', 'h', 'o', 'u', 'l', 'd', ' ', 'h', 'a', 'v', 'e', ' ', 'r', 'e', 'c', 'e', 'i', 'v', 'e',
43 'd', ' ', 'a', ' ', 'c', 'o', 'p', 'y', ' ', 'o', 'f', ' ', 't', 'h', 'e', ' ', 'G', 'N', 'U', ' ', 'L', 'e', 's',
44 's', 'e', 'r', ' ', 'G', 'e', 'n', 'e', 'r', 'a', 'l', ' ', 'P', 'u', 'b', 'l', 'i', 'c', ' ', 'L', 'i', 'c', 'e',
45 'n', 's', 'e', ' ', 'a', 'l', 'o', 'n', 'g', ' ', 'w', 'i', 't', 'h', ' ', 't', 'h', 'i', 's', ' ', '.', '.', '.', 0
47 static WCHAR large_truncated_65_w
[65] =
49 'Y', 'o', 'u', ' ', 's', 'h', 'o', 'u', 'l', 'd', ' ', 'h', 'a', 'v', 'e', ' ', 'r', 'e', 'c', 'e', 'i', 'v',
50 'e', 'd', ' ', 'a', ' ', 'c', 'o', 'p', 'y', ' ', 'o', 'f', ' ', 't', 'h', 'e', ' ', 'G', 'N', 'U', ' ', 'L',
51 'e', 's', 's', 'e', 'r', ' ', 'G', 'e', 'n', 'e', 'r', 'a', 'l', ' ', 'P', 'u', 'b', 'l', 'i', 'c', 0
53 static WCHAR large_truncated_80_w
[80] =
55 'Y', 'o', 'u', ' ', 's', 'h', 'o', 'u', 'l', 'd', ' ', 'h', 'a', 'v', 'e', ' ', 'r', 'e', 'c', 'e',
56 'i', 'v', 'e', 'd', ' ', 'a', ' ', 'c', 'o', 'p', 'y', ' ', 'o', 'f', ' ', 't', 'h', 'e', ' ', 'G',
57 'N', 'U', ' ', 'L', 'e', 's', 's', 'e', 'r', ' ', 'G', 'e', 'n', 'e', 'r', 'a', 'l', ' ', 'P', 'u',
58 'b', 'l', 'i', 'c', ' ', 'L', 'i', 'c', 'e', 'n', 's', 'e', ' ', 'a', 'l', 'o', 'n', 'g', ' ', 'w'
60 static WCHAR buffer
[64];
62 /* Text field conversion test behavior flags. */
63 enum test_conversion_flags
66 DONT_CONVERT_SEND
= 0x02,
67 CONVERT_RECEIVE
= 0x04,
68 DONT_CONVERT_RECEIVE
= 0x08,
69 SEND_EMPTY_IF_NULL
= 0x10,
70 DONT_SEND_EMPTY_IF_NULL
= 0x20,
71 SET_NULL_IF_NO_MASK
= 0x40,
81 static struct notify_test_info
87 /* Whether parent received notification */
92 /* Text field conversion test behavior flag */
96 struct notify_test_send
98 /* Data sent to pager */
102 /* Data expected by parent of pager */
106 struct notify_test_receive
108 /* Data sent to pager */
112 /* Data for parent to write */
117 /* Data when message returned */
122 struct generic_text_helper_para
136 static const struct notify_test_send test_convert_send_data
[] =
138 {test_w
, sizeof(test_w
), ARRAY_SIZE(buffer
), test_a
}
141 static const struct notify_test_send test_dont_convert_send_data
[] =
143 {test_w
, sizeof(test_w
), ARRAY_SIZE(buffer
), test_w
}
146 static const struct notify_test_receive test_convert_receive_data
[] =
148 {empty_w
, sizeof(empty_w
), ARRAY_SIZE(buffer
), NULL
, test_a
, sizeof(test_a
), -1, test_w
, ARRAY_SIZE(buffer
)},
149 {empty_w
, sizeof(empty_w
), ARRAY_SIZE(buffer
), test_a
, NULL
, 0, -1, test_w
, ARRAY_SIZE(buffer
)},
150 {NULL
, sizeof(empty_w
), ARRAY_SIZE(buffer
), test_a
, NULL
, 0, -1, NULL
, ARRAY_SIZE(buffer
)},
151 {empty_w
, sizeof(empty_w
), ARRAY_SIZE(buffer
), large_a
, NULL
, 0, -1, large_truncated_65_w
, ARRAY_SIZE(buffer
)},
152 {empty_w
, sizeof(empty_w
), ARRAY_SIZE(buffer
), empty_a
, 0, 0, 1, empty_w
, 1},
155 static const struct notify_test_receive test_dont_convert_receive_data
[] =
157 {empty_w
, sizeof(empty_w
), ARRAY_SIZE(buffer
), NULL
, test_a
, sizeof(test_a
), -1, test_a
, ARRAY_SIZE(buffer
)},
158 {empty_w
, sizeof(empty_w
), ARRAY_SIZE(buffer
), test_a
, NULL
, 0, -1, test_a
, ARRAY_SIZE(buffer
)},
161 static const struct notify_test_tooltip
163 /* Data for parent to write */
165 INT write_sztext_size
;
166 CHAR
*write_lpsztext
;
168 /* Data when message returned */
169 WCHAR
*return_sztext
;
170 INT return_sztext_size
;
171 WCHAR
*return_lpsztext
;
172 HMODULE return_hinst
;
173 /* Data expected by parent */
175 /* Data send to parent */
177 INT send_sztext_size
;
178 WCHAR
*send_lpsztext
;
179 } test_tooltip_data
[] =
181 {NULL
, 0, NULL
, NULL
, empty_w
, -1, empty_w
},
182 {test_a
, sizeof(test_a
), NULL
, NULL
, test_w
, -1, test_w
},
183 {test_a
, sizeof(test_a
), test_a
, NULL
, test_w
, -1, test_w
},
184 {test_a
, sizeof(test_a
), (CHAR
*)1, (HMODULE
)0xdeadbeef, empty_w
, -1, (WCHAR
*)1, (HMODULE
)0xdeadbeef},
185 {test_a
, sizeof(test_a
), test_a
, (HMODULE
)0xdeadbeef, test_w
, -1, test_w
, (HMODULE
)0xdeadbeef},
186 {NULL
, 0, test_a
, NULL
, test_w
, -1, test_w
},
187 {test_a
, 2, test_a
, NULL
, test_w
, -1, test_w
},
188 {NULL
, 0, NULL
, NULL
, test_w
, -1, test_w
, NULL
, test_a
, test_w
, sizeof(test_w
)},
189 {NULL
, 0, NULL
, NULL
, empty_w
, -1, empty_w
, NULL
, empty_a
, NULL
, 0, test_w
},
190 {NULL
, 0, large_a
, NULL
, large_truncated_80_w
, sizeof(large_truncated_80_w
), large_w
}
193 static const struct notify_test_datetime_format
195 /* Data send to parent */
196 WCHAR
*send_pszformat
;
197 /* Data expected by parent */
198 CHAR
*expect_pszformat
;
199 /* Data for parent to write */
200 CHAR
*write_szdisplay
;
201 INT write_szdisplay_size
;
202 CHAR
*write_pszdisplay
;
203 /* Data when message returned */
204 WCHAR
*return_szdisplay
;
205 INT return_szdisplay_size
;
206 WCHAR
*return_pszdisplay
;
207 } test_datetime_format_data
[] =
210 {NULL
, NULL
, NULL
, 0, test_a
, empty_w
, -1, test_w
},
211 {NULL
, NULL
, test_a
, sizeof(test_a
), NULL
, test_w
, -1, test_w
},
212 {NULL
, NULL
, test_a
, 2, test_a
, (WCHAR
*)te_a
, -1, test_w
},
213 {NULL
, NULL
, NULL
, 0, large_a
, NULL
, 0, large_w
}
219 static BOOL (WINAPI
*pInitCommonControlsEx
)(const INITCOMMONCONTROLSEX
*);
220 static BOOL (WINAPI
*pSetWindowSubclass
)(HWND
, SUBCLASSPROC
, UINT_PTR
, DWORD_PTR
);
222 static struct msg_sequence
*sequences
[NUM_MSG_SEQUENCES
];
224 static const struct message set_child_seq
[] = {
225 { PGM_SETCHILD
, sent
},
226 { WM_WINDOWPOSCHANGING
, sent
},
227 { WM_NCCALCSIZE
, sent
|wparam
, TRUE
},
228 { WM_NOTIFY
, sent
|id
|parent
, 0, 0, PGN_CALCSIZE
},
229 { WM_WINDOWPOSCHANGED
, sent
},
230 { WM_WINDOWPOSCHANGING
, sent
|id
, 0, 0, CHILD1_ID
},
231 { WM_NCCALCSIZE
, sent
|wparam
|id
|optional
, TRUE
, 0, CHILD1_ID
},
232 { WM_CHILDACTIVATE
, sent
|id
, 0, 0, CHILD1_ID
},
233 { WM_WINDOWPOSCHANGED
, sent
|id
, 0, 0, CHILD1_ID
},
234 { WM_SIZE
, sent
|id
|defwinproc
|optional
, 0, 0, CHILD1_ID
},
238 /* This differs from the above message list only in the child window that is
239 * expected to receive the child messages. No message is sent to the old child.
240 * Also child 2 is hidden while child 1 is visible. The pager does not make the
241 * hidden child visible. */
242 static const struct message switch_child_seq
[] = {
243 { PGM_SETCHILD
, sent
},
244 { WM_WINDOWPOSCHANGING
, sent
},
245 { WM_NCCALCSIZE
, sent
|wparam
, TRUE
},
246 { WM_NOTIFY
, sent
|id
|parent
, 0, 0, PGN_CALCSIZE
},
247 { WM_WINDOWPOSCHANGED
, sent
},
248 { WM_WINDOWPOSCHANGING
, sent
|id
, 0, 0, CHILD2_ID
},
249 { WM_NCCALCSIZE
, sent
|wparam
|id
, TRUE
, 0, CHILD2_ID
},
250 { WM_CHILDACTIVATE
, sent
|id
, 0, 0, CHILD2_ID
},
251 { WM_WINDOWPOSCHANGED
, sent
|id
, 0, 0, CHILD2_ID
},
252 { WM_SIZE
, sent
|id
|defwinproc
, 0, 0, CHILD2_ID
},
256 static const struct message set_pos_seq
[] = {
257 { PGM_SETPOS
, sent
},
258 { WM_WINDOWPOSCHANGING
, sent
},
259 { WM_NCCALCSIZE
, sent
|wparam
, TRUE
},
260 { WM_NOTIFY
, sent
|id
|parent
, 0, 0, PGN_CALCSIZE
},
261 { WM_WINDOWPOSCHANGED
, sent
},
262 { WM_MOVE
, sent
|optional
},
263 /* The WM_SIZE handler sends WM_WINDOWPOSCHANGING, WM_CHILDACTIVATE
264 * and WM_WINDOWPOSCHANGED (which sends WM_MOVE) to the child.
265 * Another WM_WINDOWPOSCHANGING is sent afterwards.
267 * The 2nd WM_WINDOWPOSCHANGING is unconditional, but the comparison
268 * function is too simple to roll back an accepted message, so we have
269 * to mark the 2nd message optional. */
270 { WM_SIZE
, sent
|optional
},
271 { WM_WINDOWPOSCHANGING
, sent
|id
, 0, 0, CHILD1_ID
}, /* Actually optional. */
272 { WM_CHILDACTIVATE
, sent
|id
, 0, 0, CHILD1_ID
}, /* Actually optional. */
273 { WM_WINDOWPOSCHANGED
, sent
|id
|optional
, TRUE
, 0, CHILD1_ID
},
274 { WM_MOVE
, sent
|id
|optional
|defwinproc
, 0, 0, CHILD1_ID
},
275 { WM_WINDOWPOSCHANGING
, sent
|id
|optional
, 0, 0, CHILD1_ID
}, /* Actually not optional. */
276 { WM_CHILDACTIVATE
, sent
|id
|optional
, 0, 0, CHILD1_ID
}, /* Actually not optional. */
280 static const struct message set_pos_empty_seq
[] = {
281 { PGM_SETPOS
, sent
},
285 static CHAR
*heap_strdup(const CHAR
*str
)
287 int len
= lstrlenA(str
) + 1;
288 CHAR
*ret
= heap_alloc(len
* sizeof(CHAR
));
293 static LRESULT WINAPI
parent_wnd_proc(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
295 static LONG defwndproc_counter
= 0;
299 /* log system messages, except for painting */
300 if (message
< WM_USER
&&
301 message
!= WM_PAINT
&&
302 message
!= WM_ERASEBKGND
&&
303 message
!= WM_NCPAINT
&&
304 message
!= WM_NCHITTEST
&&
305 message
!= WM_GETTEXT
&&
306 message
!= WM_GETICON
&&
307 message
!= WM_DEVICECHANGE
)
309 msg
.message
= message
;
310 msg
.flags
= sent
|wparam
|lparam
|parent
;
311 if (defwndproc_counter
) msg
.flags
|= defwinproc
;
314 if (message
== WM_NOTIFY
&& lParam
) msg
.id
= ((NMHDR
*)lParam
)->code
;
315 add_message(sequences
, PAGER_SEQ_INDEX
, &msg
);
318 if (message
== WM_NOTIFY
)
320 NMHDR
*nmhdr
= (NMHDR
*)lParam
;
326 NMPGCALCSIZE
*nmpgcs
= (NMPGCALCSIZE
*)lParam
;
327 DWORD style
= GetWindowLongA(nmpgcs
->hdr
.hwndFrom
, GWL_STYLE
);
329 if (style
& PGS_HORZ
)
330 ok(nmpgcs
->dwFlag
== PGF_CALCWIDTH
, "Unexpected flags %#x.\n", nmpgcs
->dwFlag
);
332 ok(nmpgcs
->dwFlag
== PGF_CALCHEIGHT
, "Unexpected flags %#x.\n", nmpgcs
->dwFlag
);
340 defwndproc_counter
++;
341 ret
= DefWindowProcA(hwnd
, message
, wParam
, lParam
);
342 defwndproc_counter
--;
347 static BOOL
register_parent_wnd_class(void)
352 cls
.lpfnWndProc
= parent_wnd_proc
;
355 cls
.hInstance
= GetModuleHandleA(NULL
);
357 cls
.hCursor
= LoadCursorA(0, (LPCSTR
)IDC_ARROW
);
358 cls
.hbrBackground
= GetStockObject(WHITE_BRUSH
);
359 cls
.lpszMenuName
= NULL
;
360 cls
.lpszClassName
= "Pager test parent class";
361 return RegisterClassA(&cls
);
364 static HWND
create_parent_window(void)
366 if (!register_parent_wnd_class())
369 return CreateWindowA("Pager test parent class", "Pager test parent window",
370 WS_OVERLAPPED
| WS_VISIBLE
,
371 0, 0, 200, 200, 0, NULL
, GetModuleHandleA(NULL
), NULL
);
374 static LRESULT WINAPI
pager_subclass_proc(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
376 WNDPROC oldproc
= (WNDPROC
)GetWindowLongPtrA(hwnd
, GWLP_USERDATA
);
377 struct message msg
= { 0 };
379 msg
.message
= message
;
380 msg
.flags
= sent
|wparam
|lparam
;
383 add_message(sequences
, PAGER_SEQ_INDEX
, &msg
);
384 return CallWindowProcA(oldproc
, hwnd
, message
, wParam
, lParam
);
387 static HWND
create_pager_control( DWORD style
)
393 GetClientRect( parent_wnd
, &rect
);
394 hwnd
= CreateWindowA( WC_PAGESCROLLERA
, "pager", WS_CHILD
| WS_BORDER
| WS_VISIBLE
| style
,
395 0, 0, 100, 100, parent_wnd
, 0, GetModuleHandleA(0), 0 );
396 oldproc
= (WNDPROC
)SetWindowLongPtrA(hwnd
, GWLP_WNDPROC
, (LONG_PTR
)pager_subclass_proc
);
397 SetWindowLongPtrA(hwnd
, GWLP_USERDATA
, (LONG_PTR
)oldproc
);
401 static LRESULT WINAPI
child_proc(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
403 static LONG defwndproc_counter
;
404 struct message msg
= { 0 };
407 msg
.message
= message
;
408 msg
.flags
= sent
| wparam
| lparam
;
409 if (defwndproc_counter
)
410 msg
.flags
|= defwinproc
;
414 if (hwnd
== child1_wnd
)
416 else if (hwnd
== child2_wnd
)
421 add_message(sequences
, PAGER_SEQ_INDEX
, &msg
);
423 defwndproc_counter
++;
424 ret
= DefWindowProcA(hwnd
, message
, wParam
, lParam
);
425 defwndproc_counter
--;
430 static BOOL
register_child_wnd_class(void)
435 cls
.lpfnWndProc
= child_proc
;
438 cls
.hInstance
= GetModuleHandleA(NULL
);
440 cls
.hCursor
= LoadCursorA(0, (LPCSTR
)IDC_ARROW
);
441 cls
.hbrBackground
= GetStockObject(WHITE_BRUSH
);
442 cls
.lpszMenuName
= NULL
;
443 cls
.lpszClassName
= "Pager test child class";
444 return RegisterClassA(&cls
);
447 static void test_pager(void)
452 pager
= create_pager_control( PGS_HORZ
);
453 ok(pager
!= NULL
, "Fail to create pager\n");
455 register_child_wnd_class();
457 child1_wnd
= CreateWindowA( "Pager test child class", "button", WS_CHILD
| WS_BORDER
| WS_VISIBLE
, 0, 0, 300, 300,
458 pager
, 0, GetModuleHandleA(0), 0 );
459 child2_wnd
= CreateWindowA("Pager test child class", "button", WS_CHILD
| WS_BORDER
, 0, 0, 300, 300,
460 pager
, 0, GetModuleHandleA(0), 0);
462 flush_sequences( sequences
, NUM_MSG_SEQUENCES
);
463 SendMessageA( pager
, PGM_SETCHILD
, 0, (LPARAM
)child1_wnd
);
464 ok_sequence(sequences
, PAGER_SEQ_INDEX
, set_child_seq
, "set child", FALSE
);
465 GetWindowRect( pager
, &rect
);
466 ok( rect
.right
- rect
.left
== 100 && rect
.bottom
- rect
.top
== 100,
467 "pager resized %dx%d\n", rect
.right
- rect
.left
, rect
.bottom
- rect
.top
);
469 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
470 SendMessageA(pager
, PGM_SETCHILD
, 0, (LPARAM
)child2_wnd
);
471 ok_sequence(sequences
, PAGER_SEQ_INDEX
, switch_child_seq
, "switch to invisible child", FALSE
);
472 GetWindowRect(pager
, &rect
);
473 ok(rect
.right
- rect
.left
== 100 && rect
.bottom
- rect
.top
== 100,
474 "pager resized %dx%d\n", rect
.right
- rect
.left
, rect
.bottom
- rect
.top
);
475 ok(!IsWindowVisible(child2_wnd
), "Child window 2 is visible\n");
477 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
478 SendMessageA(pager
, PGM_SETCHILD
, 0, (LPARAM
)child1_wnd
);
479 ok_sequence(sequences
, PAGER_SEQ_INDEX
, set_child_seq
, "switch to visible child", FALSE
);
480 GetWindowRect(pager
, &rect
);
481 ok(rect
.right
- rect
.left
== 100 && rect
.bottom
- rect
.top
== 100,
482 "pager resized %dx%d\n", rect
.right
- rect
.left
, rect
.bottom
- rect
.top
);
484 flush_sequences( sequences
, NUM_MSG_SEQUENCES
);
485 SendMessageA( pager
, PGM_SETPOS
, 0, 10 );
486 ok_sequence(sequences
, PAGER_SEQ_INDEX
, set_pos_seq
, "set pos", TRUE
);
487 GetWindowRect( pager
, &rect
);
488 ok( rect
.right
- rect
.left
== 100 && rect
.bottom
- rect
.top
== 100,
489 "pager resized %dx%d\n", rect
.right
- rect
.left
, rect
.bottom
- rect
.top
);
491 flush_sequences( sequences
, NUM_MSG_SEQUENCES
);
492 SendMessageA( pager
, PGM_SETPOS
, 0, 10 );
493 ok_sequence(sequences
, PAGER_SEQ_INDEX
, set_pos_empty_seq
, "set pos empty", TRUE
);
495 flush_sequences( sequences
, NUM_MSG_SEQUENCES
);
496 SendMessageA( pager
, PGM_SETPOS
, 0, 9 );
497 ok_sequence(sequences
, PAGER_SEQ_INDEX
, set_pos_seq
, "set pos", TRUE
);
499 DestroyWindow( pager
);
501 /* Test if resizing works */
502 pager
= create_pager_control( CCS_NORESIZE
);
503 ok(pager
!= NULL
, "failed to create pager control\n");
505 GetWindowRect( pager
, &rect
);
506 MoveWindow( pager
, 0, 0, 200, 100, TRUE
);
507 GetWindowRect( pager
, &rect2
);
508 ok(rect2
.right
- rect2
.left
> rect
.right
- rect
.left
, "expected pager window to resize, %s\n",
509 wine_dbgstr_rect( &rect2
));
511 DestroyWindow( pager
);
513 pager
= create_pager_control( CCS_NORESIZE
| PGS_HORZ
);
514 ok(pager
!= NULL
, "failed to create pager control\n");
516 GetWindowRect( pager
, &rect
);
517 MoveWindow( pager
, 0, 0, 100, 200, TRUE
);
518 GetWindowRect( pager
, &rect2
);
519 ok(rect2
.bottom
- rect2
.top
> rect
.bottom
- rect
.top
, "expected pager window to resize, %s\n",
520 wine_dbgstr_rect( &rect2
));
522 DestroyWindow( pager
);
525 static LRESULT WINAPI
test_notifyformat_proc(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
529 case WM_NOTIFYFORMAT
:
530 if (lParam
== NF_QUERY
)
532 notify_query_received
= TRUE
;
533 return notify_format
;
535 else if (lParam
== NF_REQUERY
)
536 return SendMessageA(GetParent(hwnd
), WM_NOTIFYFORMAT
, (WPARAM
)hwnd
, NF_QUERY
);
540 return notify_format
== NFR_UNICODE
? DefWindowProcW(hwnd
, message
, wParam
, lParam
)
541 : DefWindowProcA(hwnd
, message
, wParam
, lParam
);
545 static BOOL
register_notifyformat_class(void)
547 static const WCHAR class_w
[] = {'P', 'a', 'g', 'e', 'r', ' ', 'n', 'o', 't', 'i', 'f', 'y', 'f',
548 'o', 'r', 'm', 'a', 't', ' ', 'c', 'l', 'a', 's', 's', 0};
551 cls
.lpfnWndProc
= test_notifyformat_proc
;
552 cls
.hInstance
= GetModuleHandleW(NULL
);
553 cls
.lpszClassName
= class_w
;
554 return RegisterClassW(&cls
);
557 static void test_wm_notifyformat(void)
559 static const WCHAR class_w
[] = {'P', 'a', 'g', 'e', 'r', ' ', 'n', 'o', 't', 'i', 'f', 'y', 'f',
560 'o', 'r', 'm', 'a', 't', ' ', 'c', 'l', 'a', 's', 's', 0};
561 static const WCHAR parent_w
[] = {'p', 'a', 'r', 'e', 'n', 't', 0};
562 static const WCHAR pager_w
[] = {'p', 'a', 'g', 'e', 'r', 0};
563 static const WCHAR child_w
[] = {'c', 'h', 'i', 'l', 'd', 0};
564 static const INT formats
[] = {NFR_UNICODE
, NFR_ANSI
};
565 HWND parent
, pager
, child
;
569 ok(register_notifyformat_class(), "Register test class failed, error 0x%08x\n", GetLastError());
571 for (i
= 0; i
< ARRAY_SIZE(formats
); i
++)
573 notify_format
= formats
[i
];
574 parent
= CreateWindowW(class_w
, parent_w
, WS_OVERLAPPED
, 0, 0, 100, 100, 0, 0, GetModuleHandleW(0), 0);
575 ok(parent
!= NULL
, "CreateWindow failed\n");
576 pager
= CreateWindowW(WC_PAGESCROLLERW
, pager_w
, WS_CHILD
, 0, 0, 100, 100, parent
, 0, GetModuleHandleW(0), 0);
577 ok(pager
!= NULL
, "CreateWindow failed\n");
578 child
= CreateWindowW(class_w
, child_w
, WS_CHILD
, 0, 0, 100, 100, pager
, 0, GetModuleHandleW(0), 0);
579 ok(child
!= NULL
, "CreateWindow failed\n");
580 SendMessageW(pager
, PGM_SETCHILD
, 0, (LPARAM
)child
);
583 notify_query_received
= FALSE
;
584 ret
= SendMessageW(pager
, WM_NOTIFYFORMAT
, (WPARAM
)parent
, NF_REQUERY
);
585 ok(ret
== notify_format
, "Expect %d, got %ld\n", notify_format
, ret
);
586 ok(notify_query_received
, "Didn't receive notify\n");
588 /* Send NF_QUERY directly to parent */
589 notify_query_received
= FALSE
;
590 ret
= SendMessageW(parent
, WM_NOTIFYFORMAT
, (WPARAM
)pager
, NF_QUERY
);
591 ok(ret
== notify_format
, "Expect %d, got %ld\n", notify_format
, ret
);
592 ok(notify_query_received
, "Didn't receive notify\n");
594 /* Pager send notifications to its parent regardless of wParam */
595 notify_query_received
= FALSE
;
596 ret
= SendMessageW(pager
, WM_NOTIFYFORMAT
, (WPARAM
)parent_wnd
, NF_REQUERY
);
597 ok(ret
== notify_format
, "Expect %d, got %ld\n", notify_format
, ret
);
598 ok(notify_query_received
, "Didn't receive notify\n");
600 /* Pager always wants Unicode notifications from children */
601 ret
= SendMessageW(child
, WM_NOTIFYFORMAT
, (WPARAM
)pager
, NF_REQUERY
);
602 ok(ret
== NFR_UNICODE
, "Expect %d, got %ld\n", NFR_UNICODE
, ret
);
603 ret
= SendMessageW(pager
, WM_NOTIFYFORMAT
, (WPARAM
)child
, NF_QUERY
);
604 ok(ret
== NFR_UNICODE
, "Expect %d, got %ld\n", NFR_UNICODE
, ret
);
606 DestroyWindow(parent
);
609 UnregisterClassW(class_w
, GetModuleHandleW(NULL
));
612 static void notify_generic_text_handler(CHAR
**text
, INT
*text_max
)
614 const struct notify_test_send
*send_data
;
615 const struct notify_test_receive
*receive_data
;
617 switch (notify_test_info
.test_id
)
620 case DONT_CONVERT_SEND
:
622 send_data
= (notify_test_info
.test_id
== CONVERT_SEND
? test_convert_send_data
: test_dont_convert_send_data
)
623 + notify_test_info
.sub_test_id
;
624 if (notify_test_info
.flags
& ZERO_SEND
)
625 ok(!lstrcmpA(*text
, empty_a
), "Code 0x%08x test 0x%08x sub test %d expect empty text, got %s\n",
626 notify_test_info
.unicode
, notify_test_info
.test_id
, notify_test_info
.sub_test_id
, *text
);
627 else if (notify_test_info
.flags
& CONVERT_SEND
)
628 ok(!lstrcmpA(send_data
->expect_text
, *text
), "Code 0x%08x test 0x%08x sub test %d expect %s, got %s\n",
629 notify_test_info
.unicode
, notify_test_info
.test_id
, notify_test_info
.sub_test_id
,
630 (CHAR
*)send_data
->expect_text
, *text
);
632 ok(!lstrcmpW((WCHAR
*)send_data
->expect_text
, (WCHAR
*)*text
),
633 "Code 0x%08x test 0x%08x sub test %d expect %s, got %s\n", notify_test_info
.unicode
,
634 notify_test_info
.test_id
, notify_test_info
.sub_test_id
, wine_dbgstr_w((WCHAR
*)send_data
->expect_text
),
635 wine_dbgstr_w((WCHAR
*)*text
));
637 ok(*text_max
== send_data
->send_text_max
, "Code 0x%08x test 0x%08x sub test %d expect %d, got %d\n",
638 notify_test_info
.unicode
, notify_test_info
.test_id
, notify_test_info
.sub_test_id
,
639 send_data
->send_text_max
, *text_max
);
642 case CONVERT_RECEIVE
:
643 case DONT_CONVERT_RECEIVE
:
645 receive_data
= (notify_test_info
.test_id
== CONVERT_RECEIVE
? test_convert_receive_data
: test_dont_convert_receive_data
)
646 + notify_test_info
.sub_test_id
;
648 ok(*text_max
== receive_data
->send_text_max
, "Code 0x%08x test 0x%08x sub test %d expect %d, got %d\n",
649 notify_test_info
.unicode
, notify_test_info
.test_id
, notify_test_info
.sub_test_id
,
650 receive_data
->send_text_max
, *text_max
);
652 if (receive_data
->write_text
)
653 memcpy(*text
, receive_data
->write_text
, receive_data
->write_text_size
);
654 /* 64bit Windows will try to free the text pointer even if it's application provided when handling
655 * HDN_GETDISPINFOW. Deliberate leak here. */
656 else if(notify_test_info
.unicode
== HDN_GETDISPINFOW
)
657 *text
= heap_strdup(receive_data
->write_pointer
);
659 *text
= receive_data
->write_pointer
;
660 if (text_max
&& receive_data
->write_text_max
!= -1) *text_max
= receive_data
->write_text_max
;
663 case SEND_EMPTY_IF_NULL
:
664 ok(!lstrcmpA(*text
, empty_a
), "Code 0x%08x test 0x%08x sub test %d expect empty text, got %s\n",
665 notify_test_info
.unicode
, notify_test_info
.test_id
, notify_test_info
.sub_test_id
, *text
);
667 case DONT_SEND_EMPTY_IF_NULL
:
668 ok(!*text
, "Code 0x%08x test 0x%08x sub test %d expect null text\n", notify_test_info
.unicode
,
669 notify_test_info
.test_id
, notify_test_info
.sub_test_id
);
674 static void notify_tooltip_handler(NMTTDISPINFOA
*nm
)
676 const struct notify_test_tooltip
*data
= test_tooltip_data
+ notify_test_info
.sub_test_id
;
677 ok(nm
->lpszText
== nm
->szText
, "Sub test %d expect %p, got %p\n", notify_test_info
.sub_test_id
, nm
->szText
,
679 if (data
->expect_sztext
)
680 ok(!lstrcmpA(data
->expect_sztext
, nm
->szText
), "Sub test %d expect %s, got %s\n", notify_test_info
.sub_test_id
,
681 data
->expect_sztext
, nm
->szText
);
682 if (data
->write_sztext
) memcpy(nm
->szText
, data
->write_sztext
, data
->write_sztext_size
);
683 if (data
->write_lpsztext
) nm
->lpszText
= data
->write_lpsztext
;
684 if (data
->write_hinst
) nm
->hinst
= data
->write_hinst
;
687 static void notify_datetime_handler(NMDATETIMEFORMATA
*nm
)
689 const struct notify_test_datetime_format
*data
= test_datetime_format_data
+ notify_test_info
.sub_test_id
;
690 if (data
->expect_pszformat
)
691 ok(!lstrcmpA(data
->expect_pszformat
, nm
->pszFormat
), "Sub test %d expect %s, got %s\n",
692 notify_test_info
.sub_test_id
, data
->expect_pszformat
, nm
->pszFormat
);
693 ok(nm
->pszDisplay
== nm
->szDisplay
, "Test %d expect %p, got %p\n", notify_test_info
.sub_test_id
, nm
->szDisplay
,
695 if (data
->write_szdisplay
) memcpy(nm
->szDisplay
, data
->write_szdisplay
, data
->write_szdisplay_size
);
696 if (data
->write_pszdisplay
) nm
->pszDisplay
= data
->write_pszdisplay
;
699 static LRESULT WINAPI
test_notify_proc(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
701 static const WCHAR test
[] = {'t', 'e', 's', 't', 0};
706 NMHDR
*hdr
= (NMHDR
*)lParam
;
708 /* Not notifications we want to test */
709 if (!notify_test_info
.unicode
) break;
710 ok(!notify_test_info
.received
, "Extra notification received\n");
712 ok(wParam
== notify_test_info
.id_from
, "Expect %ld, got %ld\n", notify_test_info
.id_from
, wParam
);
713 ok(hdr
->code
== notify_test_info
.ansi
, "Expect 0x%08x, got 0x%08x\n", notify_test_info
.ansi
, hdr
->code
);
714 ok(hdr
->idFrom
== notify_test_info
.id_from
, "Expect %ld, got %ld\n", notify_test_info
.id_from
, wParam
);
715 ok(hdr
->hwndFrom
== notify_test_info
.hwnd_from
, "Expect %p, got %p\n", notify_test_info
.hwnd_from
, hdr
->hwndFrom
);
717 if (hdr
->code
!= notify_test_info
.ansi
)
719 skip("Notification code mismatch, skipping lParam check\n");
725 case CBEN_INSERTITEM
:
726 case CBEN_DELETEITEM
:
728 NMCOMBOBOXEXW
*nmcbe
= (NMCOMBOBOXEXW
*)hdr
;
729 notify_generic_text_handler((CHAR
**)&nmcbe
->ceItem
.pszText
, NULL
);
732 case CBEN_DRAGBEGINA
:
734 NMCBEDRAGBEGINA
*nmcbedb
= (NMCBEDRAGBEGINA
*)hdr
;
735 ok(!lstrcmpA(nmcbedb
->szText
, test_a
), "Expect %s, got %s\n", nmcbedb
->szText
, test_a
);
740 NMCBEENDEDITA
*nmcbeed
= (NMCBEENDEDITA
*)hdr
;
741 ok(!lstrcmpA(nmcbeed
->szText
, test_a
), "Expect %s, got %s\n", nmcbeed
->szText
, test_a
);
744 case CBEN_GETDISPINFOA
:
746 NMCOMBOBOXEXA
*nmcbe
= (NMCOMBOBOXEXA
*)hdr
;
747 notify_generic_text_handler(&nmcbe
->ceItem
.pszText
, &nmcbe
->ceItem
.cchTextMax
);
750 /* Date and Time Picker */
753 notify_datetime_handler((NMDATETIMEFORMATA
*)hdr
);
756 case DTN_FORMATQUERYA
:
758 NMDATETIMEFORMATQUERYA
*nmdtfq
= (NMDATETIMEFORMATQUERYA
*)hdr
;
759 notify_generic_text_handler((CHAR
**)&nmdtfq
->pszFormat
, NULL
);
764 NMDATETIMEWMKEYDOWNA
*nmdtkd
= (NMDATETIMEWMKEYDOWNA
*)hdr
;
765 notify_generic_text_handler((CHAR
**)&nmdtkd
->pszFormat
, NULL
);
768 case DTN_USERSTRINGA
:
770 NMDATETIMESTRINGA
*nmdts
= (NMDATETIMESTRINGA
*)hdr
;
771 notify_generic_text_handler((CHAR
**)&nmdts
->pszUserString
, NULL
);
777 case HDN_BEGINFILTEREDIT
:
778 case HDN_ENDFILTEREDIT
:
780 case HDN_FILTERCHANGE
:
781 case HDN_ITEMKEYDOWN
:
782 case HDN_ITEMSTATEICONCLICK
:
783 case HDN_OVERFLOWCLICK
:
785 NMHEADERW
*nmhd
= (NMHEADERW
*)hdr
;
786 ok(!lstrcmpW(nmhd
->pitem
->pszText
, test_w
), "Expect %s, got %s\n", wine_dbgstr_w(test_w
),
787 wine_dbgstr_w(nmhd
->pitem
->pszText
));
788 ok(!lstrcmpW(((HD_TEXTFILTERW
*)nmhd
->pitem
->pvFilter
)->pszText
, test_w
), "Expect %s, got %s\n",
789 wine_dbgstr_w(test_w
), wine_dbgstr_w(((HD_TEXTFILTERW
*)nmhd
->pitem
->pvFilter
)->pszText
));
792 case HDN_BEGINTRACKA
:
793 case HDN_DIVIDERDBLCLICKA
:
795 case HDN_ITEMCHANGEDA
:
796 case HDN_ITEMCHANGINGA
:
798 case HDN_ITEMDBLCLICKA
:
801 NMHEADERA
*nmhd
= (NMHEADERA
*)hdr
;
802 ok(!lstrcmpA(nmhd
->pitem
->pszText
, test_a
), "Expect %s, got %s\n", test_a
, nmhd
->pitem
->pszText
);
803 ok(!lstrcmpA(((HD_TEXTFILTERA
*)nmhd
->pitem
->pvFilter
)->pszText
, test_a
), "Expect %s, got %s\n", test_a
,
804 ((HD_TEXTFILTERA
*)nmhd
->pitem
->pvFilter
)->pszText
);
807 case HDN_GETDISPINFOA
:
809 NMHDDISPINFOA
*nmhddi
= (NMHDDISPINFOA
*)hdr
;
810 notify_generic_text_handler(&nmhddi
->pszText
, &nmhddi
->cchTextMax
);
814 case LVN_BEGINLABELEDITA
:
815 case LVN_ENDLABELEDITA
:
816 case LVN_GETDISPINFOA
:
817 case LVN_SETDISPINFOA
:
819 NMLVDISPINFOA
*nmlvdi
= (NMLVDISPINFOA
*)hdr
;
820 notify_generic_text_handler(&nmlvdi
->item
.pszText
, &nmlvdi
->item
.cchTextMax
);
823 case LVN_GETINFOTIPA
:
825 NMLVGETINFOTIPA
*nmlvgit
= (NMLVGETINFOTIPA
*)hdr
;
826 notify_generic_text_handler(&nmlvgit
->pszText
, &nmlvgit
->cchTextMax
);
829 case LVN_INCREMENTALSEARCHA
:
830 case LVN_ODFINDITEMA
:
832 NMLVFINDITEMA
*nmlvfi
= (NMLVFINDITEMA
*)hdr
;
833 notify_generic_text_handler((CHAR
**)&nmlvfi
->lvfi
.psz
, NULL
);
839 NMTBSAVE
*nmtbs
= (NMTBSAVE
*)hdr
;
840 notify_generic_text_handler((CHAR
**)&nmtbs
->tbButton
.iString
, NULL
);
845 NMTBRESTORE
*nmtbr
= (NMTBRESTORE
*)hdr
;
846 notify_generic_text_handler((CHAR
**)&nmtbr
->tbButton
.iString
, NULL
);
849 case TBN_GETBUTTONINFOA
:
851 NMTOOLBARA
*nmtb
= (NMTOOLBARA
*)hdr
;
852 notify_generic_text_handler(&nmtb
->pszText
, &nmtb
->cchText
);
855 case TBN_GETDISPINFOW
:
857 NMTBDISPINFOW
*nmtbdi
= (NMTBDISPINFOW
*)hdr
;
858 notify_generic_text_handler((CHAR
**)&nmtbdi
->pszText
, &nmtbdi
->cchText
);
861 case TBN_GETINFOTIPA
:
863 NMTBGETINFOTIPA
*nmtbgit
= (NMTBGETINFOTIPA
*)hdr
;
864 notify_generic_text_handler(&nmtbgit
->pszText
, &nmtbgit
->cchTextMax
);
868 case TTN_GETDISPINFOA
:
870 notify_tooltip_handler((NMTTDISPINFOA
*)hdr
);
874 case TVN_BEGINLABELEDITA
:
875 case TVN_ENDLABELEDITA
:
876 case TVN_GETDISPINFOA
:
877 case TVN_SETDISPINFOA
:
879 NMTVDISPINFOA
*nmtvdi
= (NMTVDISPINFOA
*)hdr
;
880 notify_generic_text_handler(&nmtvdi
->item
.pszText
, &nmtvdi
->item
.cchTextMax
);
883 case TVN_GETINFOTIPA
:
885 NMTVGETINFOTIPA
*nmtvgit
= (NMTVGETINFOTIPA
*)hdr
;
886 notify_generic_text_handler(&nmtvgit
->pszText
, &nmtvgit
->cchTextMax
);
889 case TVN_SINGLEEXPAND
:
891 case TVN_BEGINRDRAGA
:
892 case TVN_ITEMEXPANDEDA
:
893 case TVN_ITEMEXPANDINGA
:
894 case TVN_DELETEITEMA
:
895 case TVN_SELCHANGINGA
:
896 case TVN_SELCHANGEDA
:
898 NMTREEVIEWA
*nmtv
= (NMTREEVIEWA
*)hdr
;
899 if (notify_test_info
.handler_id
== TVITEM_NEW_HANDLER
)
900 notify_generic_text_handler((CHAR
**)&nmtv
->itemNew
.pszText
, &nmtv
->itemNew
.cchTextMax
);
902 notify_generic_text_handler((CHAR
**)&nmtv
->itemOld
.pszText
, &nmtv
->itemOld
.cchTextMax
);
907 ok(0, "Unexpected message 0x%08x\n", hdr
->code
);
909 notify_test_info
.received
= TRUE
;
910 ok(!lstrcmpA(test_a
, "test"), "test_a got modified\n");
911 ok(!lstrcmpW(test_w
, test
), "test_w got modified\n");
914 case WM_NOTIFYFORMAT
:
915 if (lParam
== NF_QUERY
) return NFR_ANSI
;
918 return DefWindowProcA(hwnd
, message
, wParam
, lParam
);
921 static BOOL
register_test_notify_class(void)
925 cls
.lpfnWndProc
= test_notify_proc
;
926 cls
.hInstance
= GetModuleHandleA(NULL
);
927 cls
.lpszClassName
= "Pager notify class";
928 return RegisterClassA(&cls
);
931 static void send_notify(HWND pager
, UINT unicode
, UINT ansi
, LPARAM lParam
, BOOL code_change
)
933 NMHDR
*hdr
= (NMHDR
*)lParam
;
935 notify_test_info
.unicode
= unicode
;
936 notify_test_info
.id_from
= 1;
937 notify_test_info
.hwnd_from
= child1_wnd
;
938 notify_test_info
.ansi
= ansi
;
939 notify_test_info
.received
= FALSE
;
943 hdr
->hwndFrom
= child1_wnd
;
945 SendMessageW(pager
, WM_NOTIFY
, hdr
->idFrom
, lParam
);
946 ok(notify_test_info
.received
, "Expect notification received\n");
947 ok(hdr
->code
== code_change
? ansi
: unicode
, "Expect 0x%08x, got 0x%08x\n", hdr
->code
,
948 code_change
? ansi
: unicode
);
951 /* Send notify to test text field conversion. In parent proc notify_generic_text_handler() handles these messages */
952 static void test_notify_generic_text_helper(HWND pager
, const struct generic_text_helper_para
*para
)
954 const struct notify_test_send
*send_data
;
955 const struct notify_test_receive
*receive_data
;
959 notify_test_info
.flags
= para
->flags
;
960 notify_test_info
.handler_id
= para
->handler_id
;
962 if (para
->flags
& (CONVERT_SEND
| DONT_CONVERT_SEND
))
964 if (para
->flags
& CONVERT_SEND
)
966 notify_test_info
.test_id
= CONVERT_SEND
;
967 send_data
= test_convert_send_data
;
968 array_size
= ARRAY_SIZE(test_convert_send_data
);
972 notify_test_info
.test_id
= DONT_CONVERT_SEND
;
973 send_data
= test_dont_convert_send_data
;
974 array_size
= ARRAY_SIZE(test_dont_convert_send_data
);
977 for (i
= 0; i
< array_size
; i
++)
979 const struct notify_test_send
*data
= send_data
+ i
;
980 notify_test_info
.sub_test_id
= i
;
982 memset(para
->ptr
, 0, para
->size
);
983 if (para
->mask
) *para
->mask
= para
->required_mask
;
986 memcpy(buffer
, data
->send_text
, data
->send_text_size
);
987 *para
->text
= buffer
;
989 if (para
->text_max
) *para
->text_max
= data
->send_text_max
;
990 send_notify(pager
, para
->code_unicode
, para
->code_ansi
, (LPARAM
)para
->ptr
, TRUE
);
994 if (para
->flags
& (CONVERT_RECEIVE
| DONT_CONVERT_RECEIVE
))
996 if (para
->flags
& CONVERT_RECEIVE
)
998 notify_test_info
.test_id
= CONVERT_RECEIVE
;
999 receive_data
= test_convert_receive_data
;
1000 array_size
= ARRAY_SIZE(test_convert_receive_data
);
1004 notify_test_info
.test_id
= DONT_CONVERT_RECEIVE
;
1005 receive_data
= test_dont_convert_receive_data
;
1006 array_size
= ARRAY_SIZE(test_dont_convert_receive_data
);
1009 for (i
= 0; i
< array_size
; i
++)
1011 const struct notify_test_receive
*data
= receive_data
+ i
;
1012 notify_test_info
.sub_test_id
= i
;
1014 memset(para
->ptr
, 0, para
->size
);
1015 if (para
->mask
) *para
->mask
= para
->required_mask
;
1016 if (data
->send_text
)
1018 memcpy(buffer
, data
->send_text
, data
->send_text_size
);
1019 *para
->text
= buffer
;
1021 if (para
->text_max
) *para
->text_max
= data
->send_text_max
;
1022 send_notify(pager
, para
->code_unicode
, para
->code_ansi
, (LPARAM
)para
->ptr
, TRUE
);
1023 if (data
->return_text
)
1025 if (para
->flags
& CONVERT_RECEIVE
)
1026 ok(!lstrcmpW(data
->return_text
, *para
->text
), "Code 0x%08x sub test %d expect %s, got %s\n",
1027 para
->code_unicode
, i
, wine_dbgstr_w((WCHAR
*)data
->return_text
), wine_dbgstr_w(*para
->text
));
1029 ok(!lstrcmpA(data
->return_text
, (CHAR
*)*para
->text
), "Code 0x%08x sub test %d expect %s, got %s\n",
1030 para
->code_unicode
, i
, (CHAR
*)data
->return_text
, (CHAR
*)*para
->text
);
1033 ok(data
->return_text_max
== *para
->text_max
, "Code 0x%08x sub test %d expect %d, got %d\n",
1034 para
->code_unicode
, i
, data
->return_text_max
, *para
->text_max
);
1038 /* Extra tests for other behavior flags that are not worth it to create their own test arrays */
1039 memset(para
->ptr
, 0, para
->size
);
1040 if (para
->mask
) *para
->mask
= para
->required_mask
;
1041 if (para
->text_max
) *para
->text_max
= 1;
1042 if (para
->flags
& SEND_EMPTY_IF_NULL
)
1043 notify_test_info
.test_id
= SEND_EMPTY_IF_NULL
;
1045 notify_test_info
.test_id
= DONT_SEND_EMPTY_IF_NULL
;
1046 send_notify(pager
, para
->code_unicode
, para
->code_ansi
, (LPARAM
)para
->ptr
, TRUE
);
1048 notify_test_info
.test_id
= SET_NULL_IF_NO_MASK
;
1049 memset(para
->ptr
, 0, para
->size
);
1050 memset(buffer
, 0, sizeof(buffer
));
1051 *para
->text
= buffer
;
1052 if (para
->text_max
) *para
->text_max
= ARRAY_SIZE(buffer
);
1053 send_notify(pager
, para
->code_unicode
, para
->code_ansi
, (LPARAM
)para
->ptr
, TRUE
);
1054 if(para
->flags
& SET_NULL_IF_NO_MASK
)
1055 ok(!*para
->text
, "Expect null text\n");
1058 static void test_wm_notify_comboboxex(HWND pager
)
1060 static NMCBEDRAGBEGINW nmcbedb
;
1061 static NMCBEENDEDITW nmcbeed
;
1063 /* CBEN_DRAGBEGIN */
1064 memset(&nmcbedb
, 0, sizeof(nmcbedb
));
1065 memcpy(nmcbedb
.szText
, test_w
, sizeof(test_w
));
1066 send_notify(pager
, CBEN_DRAGBEGINW
, CBEN_DRAGBEGINA
, (LPARAM
)&nmcbedb
, FALSE
);
1067 ok(!lstrcmpW(nmcbedb
.szText
, test_w
), "Expect %s, got %s\n", wine_dbgstr_w(test_w
), wine_dbgstr_w(nmcbedb
.szText
));
1070 memset(&nmcbeed
, 0, sizeof(nmcbeed
));
1071 memcpy(nmcbeed
.szText
, test_w
, sizeof(test_w
));
1072 send_notify(pager
, CBEN_ENDEDITW
, CBEN_ENDEDITA
, (LPARAM
)&nmcbeed
, FALSE
);
1073 ok(!lstrcmpW(nmcbeed
.szText
, test_w
), "Expect %s, got %s\n", wine_dbgstr_w(test_w
), wine_dbgstr_w(nmcbeed
.szText
));
1076 static void test_wm_notify_datetime(HWND pager
)
1078 const struct notify_test_datetime_format
*data
;
1079 NMDATETIMEFORMATW nmdtf
;
1082 for (i
= 0; i
< ARRAY_SIZE(test_datetime_format_data
); i
++)
1084 data
= test_datetime_format_data
+ i
;
1085 notify_test_info
.sub_test_id
= i
;
1087 memset(&nmdtf
, 0, sizeof(nmdtf
));
1088 if(data
->send_pszformat
) nmdtf
.pszFormat
= data
->send_pszformat
;
1089 nmdtf
.pszDisplay
= nmdtf
.szDisplay
;
1090 send_notify(pager
, DTN_FORMATW
, DTN_FORMATA
, (LPARAM
)&nmdtf
, TRUE
);
1091 if (data
->return_szdisplay
)
1092 ok(!lstrcmpW(nmdtf
.szDisplay
, data
->return_szdisplay
), "Sub test %d expect %s, got %s\n", i
,
1093 wine_dbgstr_w(data
->return_szdisplay
), wine_dbgstr_w(nmdtf
.szDisplay
));
1094 if (data
->return_pszdisplay
)
1095 ok(!lstrcmpW(nmdtf
.pszDisplay
, data
->return_pszdisplay
), "Sub test %d expect %s, got %s\n", i
,
1096 wine_dbgstr_w(data
->return_pszdisplay
), wine_dbgstr_w(nmdtf
.pszDisplay
));
1100 static void test_wm_notify_header(HWND pager
)
1102 NMHEADERW nmh
= {{0}};
1104 HD_TEXTFILTERW hdtf
= {0};
1106 hdi
.mask
= HDI_TEXT
| HDI_FILTER
;
1107 hdi
.pszText
= test_w
;
1108 hdtf
.pszText
= test_w
;
1110 nmh
.pitem
->pvFilter
= &hdtf
;
1111 send_notify(pager
, HDN_BEGINDRAG
, HDN_BEGINDRAG
, (LPARAM
)&nmh
, TRUE
);
1112 send_notify(pager
, HDN_ENDDRAG
, HDN_ENDDRAG
, (LPARAM
)&nmh
, TRUE
);
1113 send_notify(pager
, HDN_BEGINFILTEREDIT
, HDN_BEGINFILTEREDIT
, (LPARAM
)&nmh
, TRUE
);
1114 send_notify(pager
, HDN_ENDFILTEREDIT
, HDN_ENDFILTEREDIT
, (LPARAM
)&nmh
, TRUE
);
1115 send_notify(pager
, HDN_DROPDOWN
, HDN_DROPDOWN
, (LPARAM
)&nmh
, TRUE
);
1116 send_notify(pager
, HDN_FILTERCHANGE
, HDN_FILTERCHANGE
, (LPARAM
)&nmh
, TRUE
);
1117 send_notify(pager
, HDN_ITEMKEYDOWN
, HDN_ITEMKEYDOWN
, (LPARAM
)&nmh
, TRUE
);
1118 send_notify(pager
, HDN_ITEMSTATEICONCLICK
, HDN_ITEMSTATEICONCLICK
, (LPARAM
)&nmh
, TRUE
);
1119 send_notify(pager
, HDN_OVERFLOWCLICK
, HDN_OVERFLOWCLICK
, (LPARAM
)&nmh
, TRUE
);
1120 send_notify(pager
, HDN_BEGINTRACKW
, HDN_BEGINTRACKA
, (LPARAM
)&nmh
, TRUE
);
1121 send_notify(pager
, HDN_DIVIDERDBLCLICKW
, HDN_DIVIDERDBLCLICKA
, (LPARAM
)&nmh
, TRUE
);
1122 send_notify(pager
, HDN_ENDTRACKW
, HDN_ENDTRACKA
, (LPARAM
)&nmh
, TRUE
);
1123 send_notify(pager
, HDN_ITEMCHANGEDW
, HDN_ITEMCHANGEDA
, (LPARAM
)&nmh
, TRUE
);
1124 send_notify(pager
, HDN_ITEMCHANGINGW
, HDN_ITEMCHANGINGA
, (LPARAM
)&nmh
, TRUE
);
1125 send_notify(pager
, HDN_ITEMCLICKW
, HDN_ITEMCLICKA
, (LPARAM
)&nmh
, TRUE
);
1126 send_notify(pager
, HDN_ITEMDBLCLICKW
, HDN_ITEMDBLCLICKA
, (LPARAM
)&nmh
, TRUE
);
1127 send_notify(pager
, HDN_TRACKW
, HDN_TRACKA
, (LPARAM
)&nmh
, TRUE
);
1130 static void test_wm_notify_tooltip(HWND pager
)
1132 NMTTDISPINFOW nmttdi
;
1133 const struct notify_test_tooltip
*data
;
1136 for (i
= 0; i
< ARRAY_SIZE(test_tooltip_data
); i
++)
1138 data
= test_tooltip_data
+ i
;
1139 notify_test_info
.sub_test_id
= i
;
1141 memset(&nmttdi
, 0, sizeof(nmttdi
));
1142 if (data
->send_sztext
) memcpy(nmttdi
.szText
, data
->send_sztext
, data
->send_sztext_size
);
1143 if (data
->send_lpsztext
) nmttdi
.lpszText
= data
->send_lpsztext
;
1144 send_notify(pager
, TTN_GETDISPINFOW
, TTN_GETDISPINFOA
, (LPARAM
)&nmttdi
, FALSE
);
1145 if (data
->return_sztext
)
1147 if (data
->return_sztext_size
== -1)
1148 ok(!lstrcmpW(nmttdi
.szText
, data
->return_sztext
), "Sub test %d expect %s, got %s\n", i
,
1149 wine_dbgstr_w(data
->return_sztext
), wine_dbgstr_w(nmttdi
.szText
));
1151 ok(!memcmp(nmttdi
.szText
, data
->return_sztext
, data
->return_sztext_size
), "Wrong szText content\n");
1153 if (data
->return_lpsztext
)
1155 if (IS_INTRESOURCE(data
->return_lpsztext
))
1156 ok(nmttdi
.lpszText
== data
->return_lpsztext
, "Sub test %d expect %s, got %s\n", i
,
1157 wine_dbgstr_w(data
->return_lpsztext
), wine_dbgstr_w(nmttdi
.lpszText
));
1159 ok(!lstrcmpW(nmttdi
.lpszText
, data
->return_lpsztext
), "Test %d expect %s, got %s\n", i
,
1160 wine_dbgstr_w(data
->return_lpsztext
), wine_dbgstr_w(nmttdi
.lpszText
));
1162 if (data
->return_hinst
)
1163 ok(nmttdi
.hinst
== data
->return_hinst
, "Sub test %d expect %p, got %p\n", i
, data
->return_hinst
,
1168 static void test_wm_notify(void)
1170 static const CHAR
*class = "Pager notify class";
1173 static NMCOMBOBOXEXW nmcbe
;
1174 /* Date and Time Picker */
1175 static NMDATETIMEFORMATQUERYW nmdtfq
;
1176 static NMDATETIMEWMKEYDOWNW nmdtkd
;
1177 static NMDATETIMESTRINGW nmdts
;
1179 static NMHDDISPINFOW nmhddi
;
1181 static NMLVDISPINFOW nmlvdi
;
1182 static NMLVGETINFOTIPW nmlvgit
;
1183 static NMLVFINDITEMW nmlvfi
;
1185 static NMTBRESTORE nmtbr
;
1186 static NMTBSAVE nmtbs
;
1187 static NMTOOLBARW nmtb
;
1188 static NMTBDISPINFOW nmtbdi
;
1189 static NMTBGETINFOTIPW nmtbgit
;
1191 static NMTVDISPINFOW nmtvdi
;
1192 static NMTVGETINFOTIPW nmtvgit
;
1193 static NMTREEVIEWW nmtv
;
1194 static const struct generic_text_helper_para paras
[] =
1197 {&nmcbe
, sizeof(nmcbe
), &nmcbe
.ceItem
.mask
, CBEIF_TEXT
, &nmcbe
.ceItem
.pszText
, &nmcbe
.ceItem
.cchTextMax
,
1198 CBEN_INSERTITEM
, CBEN_INSERTITEM
, DONT_CONVERT_SEND
| DONT_CONVERT_RECEIVE
},
1199 {&nmcbe
, sizeof(nmcbe
), &nmcbe
.ceItem
.mask
, CBEIF_TEXT
, &nmcbe
.ceItem
.pszText
, &nmcbe
.ceItem
.cchTextMax
,
1200 CBEN_DELETEITEM
, CBEN_DELETEITEM
, DONT_CONVERT_SEND
| DONT_CONVERT_RECEIVE
},
1201 {&nmcbe
, sizeof(nmcbe
), &nmcbe
.ceItem
.mask
, CBEIF_TEXT
, &nmcbe
.ceItem
.pszText
, &nmcbe
.ceItem
.cchTextMax
,
1202 CBEN_GETDISPINFOW
, CBEN_GETDISPINFOA
, ZERO_SEND
| SET_NULL_IF_NO_MASK
| DONT_CONVERT_SEND
| CONVERT_RECEIVE
},
1203 /* Date and Time Picker */
1204 {&nmdtfq
, sizeof(nmdtfq
), NULL
, 0, (WCHAR
**)&nmdtfq
.pszFormat
, NULL
, DTN_FORMATQUERYW
, DTN_FORMATQUERYA
,
1206 {&nmdtkd
, sizeof(nmdtkd
), NULL
, 0, (WCHAR
**)&nmdtkd
.pszFormat
, NULL
, DTN_WMKEYDOWNW
, DTN_WMKEYDOWNA
,
1208 {&nmdts
, sizeof(nmdts
), NULL
, 0, (WCHAR
**)&nmdts
.pszUserString
, NULL
, DTN_USERSTRINGW
, DTN_USERSTRINGA
,
1211 {&nmhddi
, sizeof(nmhddi
), &nmhddi
.mask
, HDI_TEXT
, &nmhddi
.pszText
, &nmhddi
.cchTextMax
, HDN_GETDISPINFOW
,
1212 HDN_GETDISPINFOA
, SEND_EMPTY_IF_NULL
| CONVERT_SEND
| CONVERT_RECEIVE
},
1214 {&nmlvfi
, sizeof(nmlvfi
), &nmlvfi
.lvfi
.flags
, LVFI_STRING
, (WCHAR
**)&nmlvfi
.lvfi
.psz
, NULL
,
1215 LVN_INCREMENTALSEARCHW
, LVN_INCREMENTALSEARCHA
, CONVERT_SEND
},
1216 {&nmlvfi
, sizeof(nmlvfi
), &nmlvfi
.lvfi
.flags
, LVFI_SUBSTRING
, (WCHAR
**)&nmlvfi
.lvfi
.psz
, NULL
, LVN_ODFINDITEMW
,
1217 LVN_ODFINDITEMA
, CONVERT_SEND
},
1218 {&nmlvdi
, sizeof(nmlvdi
), &nmlvdi
.item
.mask
, LVIF_TEXT
, &nmlvdi
.item
.pszText
, &nmlvdi
.item
.cchTextMax
,
1219 LVN_BEGINLABELEDITW
, LVN_BEGINLABELEDITA
, SET_NULL_IF_NO_MASK
| CONVERT_SEND
| CONVERT_RECEIVE
},
1220 {&nmlvdi
, sizeof(nmlvdi
), &nmlvdi
.item
.mask
, LVIF_TEXT
, &nmlvdi
.item
.pszText
, &nmlvdi
.item
.cchTextMax
,
1221 LVN_ENDLABELEDITW
, LVN_ENDLABELEDITA
, SET_NULL_IF_NO_MASK
| CONVERT_SEND
| CONVERT_RECEIVE
},
1222 {&nmlvdi
, sizeof(nmlvdi
), &nmlvdi
.item
.mask
, LVIF_TEXT
, &nmlvdi
.item
.pszText
, &nmlvdi
.item
.cchTextMax
,
1223 LVN_GETDISPINFOW
, LVN_GETDISPINFOA
, DONT_CONVERT_SEND
| CONVERT_RECEIVE
},
1224 {&nmlvdi
, sizeof(nmlvdi
), &nmlvdi
.item
.mask
, LVIF_TEXT
, &nmlvdi
.item
.pszText
, &nmlvdi
.item
.cchTextMax
,
1225 LVN_SETDISPINFOW
, LVN_SETDISPINFOA
, SET_NULL_IF_NO_MASK
| CONVERT_SEND
| CONVERT_RECEIVE
},
1226 {&nmlvgit
, sizeof(nmlvgit
), NULL
, 0, &nmlvgit
.pszText
, &nmlvgit
.cchTextMax
, LVN_GETINFOTIPW
, LVN_GETINFOTIPA
,
1227 CONVERT_SEND
| CONVERT_RECEIVE
},
1229 {&nmtbs
, sizeof(nmtbs
), NULL
, 0, (WCHAR
**)&nmtbs
.tbButton
.iString
, NULL
, TBN_SAVE
, TBN_SAVE
,
1230 DONT_CONVERT_SEND
| DONT_CONVERT_RECEIVE
},
1231 {&nmtbr
, sizeof(nmtbr
), NULL
, 0, (WCHAR
**)&nmtbr
.tbButton
.iString
, NULL
, TBN_RESTORE
, TBN_RESTORE
,
1232 DONT_CONVERT_SEND
| DONT_CONVERT_RECEIVE
},
1233 {&nmtbdi
, sizeof(nmtbdi
), &nmtbdi
.dwMask
, TBNF_TEXT
, &nmtbdi
.pszText
, &nmtbdi
.cchText
, TBN_GETDISPINFOW
,
1234 TBN_GETDISPINFOW
, DONT_CONVERT_SEND
| DONT_CONVERT_RECEIVE
},
1235 {&nmtb
, sizeof(nmtb
), NULL
, 0, &nmtb
.pszText
, &nmtb
.cchText
, TBN_GETBUTTONINFOW
, TBN_GETBUTTONINFOA
,
1236 SEND_EMPTY_IF_NULL
| CONVERT_SEND
| CONVERT_RECEIVE
},
1237 {&nmtbgit
, sizeof(nmtbgit
), NULL
, 0, &nmtbgit
.pszText
, &nmtbgit
.cchTextMax
, TBN_GETINFOTIPW
, TBN_GETINFOTIPA
,
1238 DONT_CONVERT_SEND
| CONVERT_RECEIVE
},
1240 {&nmtvdi
, sizeof(nmtvdi
), &nmtvdi
.item
.mask
, TVIF_TEXT
, &nmtvdi
.item
.pszText
, &nmtvdi
.item
.cchTextMax
,
1241 TVN_BEGINLABELEDITW
, TVN_BEGINLABELEDITA
, SET_NULL_IF_NO_MASK
| CONVERT_SEND
| CONVERT_RECEIVE
},
1242 {&nmtvdi
, sizeof(nmtvdi
), &nmtvdi
.item
.mask
, TVIF_TEXT
, &nmtvdi
.item
.pszText
, &nmtvdi
.item
.cchTextMax
,
1243 TVN_ENDLABELEDITW
, TVN_ENDLABELEDITA
, SET_NULL_IF_NO_MASK
| CONVERT_SEND
| CONVERT_RECEIVE
},
1244 {&nmtvdi
, sizeof(nmtvdi
), &nmtvdi
.item
.mask
, TVIF_TEXT
, &nmtvdi
.item
.pszText
, &nmtvdi
.item
.cchTextMax
,
1245 TVN_GETDISPINFOW
, TVN_GETDISPINFOA
, ZERO_SEND
| DONT_CONVERT_SEND
| CONVERT_RECEIVE
},
1246 {&nmtvdi
, sizeof(nmtvdi
), &nmtvdi
.item
.mask
, TVIF_TEXT
, &nmtvdi
.item
.pszText
, &nmtvdi
.item
.cchTextMax
,
1247 TVN_SETDISPINFOW
, TVN_SETDISPINFOA
, SET_NULL_IF_NO_MASK
| CONVERT_SEND
| CONVERT_RECEIVE
},
1248 {&nmtvgit
, sizeof(nmtvgit
), NULL
, 0, &nmtvgit
.pszText
, &nmtvgit
.cchTextMax
, TVN_GETINFOTIPW
, TVN_GETINFOTIPA
,
1249 DONT_CONVERT_SEND
| CONVERT_RECEIVE
},
1250 {&nmtv
, sizeof(nmtv
), &nmtv
.itemNew
.mask
, TVIF_TEXT
, &nmtv
.itemNew
.pszText
, &nmtv
.itemNew
.cchTextMax
,
1251 TVN_SINGLEEXPAND
, TVN_SINGLEEXPAND
, DONT_CONVERT_SEND
| DONT_CONVERT_RECEIVE
, TVITEM_NEW_HANDLER
},
1252 {&nmtv
, sizeof(nmtv
), &nmtv
.itemOld
.mask
, TVIF_TEXT
, &nmtv
.itemOld
.pszText
, &nmtv
.itemOld
.cchTextMax
,
1253 TVN_SINGLEEXPAND
, TVN_SINGLEEXPAND
, DONT_CONVERT_SEND
| DONT_CONVERT_RECEIVE
, TVITEM_OLD_HANDLER
},
1254 {&nmtv
, sizeof(nmtv
), &nmtv
.itemNew
.mask
, TVIF_TEXT
, &nmtv
.itemNew
.pszText
, &nmtv
.itemNew
.cchTextMax
,
1255 TVN_BEGINDRAGW
, TVN_BEGINDRAGA
, CONVERT_SEND
, TVITEM_NEW_HANDLER
},
1256 {&nmtv
, sizeof(nmtv
), &nmtv
.itemOld
.mask
, TVIF_TEXT
, &nmtv
.itemOld
.pszText
, &nmtv
.itemOld
.cchTextMax
,
1257 TVN_BEGINDRAGW
, TVN_BEGINDRAGA
, DONT_CONVERT_SEND
, TVITEM_OLD_HANDLER
},
1258 {&nmtv
, sizeof(nmtv
), &nmtv
.itemNew
.mask
, TVIF_TEXT
, &nmtv
.itemNew
.pszText
, &nmtv
.itemNew
.cchTextMax
,
1259 TVN_BEGINRDRAGW
, TVN_BEGINRDRAGA
, CONVERT_SEND
, TVITEM_NEW_HANDLER
},
1260 {&nmtv
, sizeof(nmtv
), &nmtv
.itemOld
.mask
, TVIF_TEXT
, &nmtv
.itemOld
.pszText
, &nmtv
.itemOld
.cchTextMax
,
1261 TVN_BEGINRDRAGW
, TVN_BEGINRDRAGA
, DONT_CONVERT_SEND
, TVITEM_OLD_HANDLER
},
1262 {&nmtv
, sizeof(nmtv
), &nmtv
.itemNew
.mask
, TVIF_TEXT
, &nmtv
.itemNew
.pszText
, &nmtv
.itemNew
.cchTextMax
,
1263 TVN_ITEMEXPANDEDW
, TVN_ITEMEXPANDEDA
, CONVERT_SEND
, TVITEM_NEW_HANDLER
},
1264 {&nmtv
, sizeof(nmtv
), &nmtv
.itemOld
.mask
, TVIF_TEXT
, &nmtv
.itemOld
.pszText
, &nmtv
.itemOld
.cchTextMax
,
1265 TVN_ITEMEXPANDEDW
, TVN_ITEMEXPANDEDA
, DONT_CONVERT_SEND
, TVITEM_OLD_HANDLER
},
1266 {&nmtv
, sizeof(nmtv
), &nmtv
.itemNew
.mask
, TVIF_TEXT
, &nmtv
.itemNew
.pszText
, &nmtv
.itemNew
.cchTextMax
,
1267 TVN_ITEMEXPANDINGW
, TVN_ITEMEXPANDINGA
, CONVERT_SEND
, TVITEM_NEW_HANDLER
},
1268 {&nmtv
, sizeof(nmtv
), &nmtv
.itemOld
.mask
, TVIF_TEXT
, &nmtv
.itemOld
.pszText
, &nmtv
.itemOld
.cchTextMax
,
1269 TVN_ITEMEXPANDINGW
, TVN_ITEMEXPANDINGA
, DONT_CONVERT_SEND
, TVITEM_OLD_HANDLER
},
1270 {&nmtv
, sizeof(nmtv
), &nmtv
.itemNew
.mask
, TVIF_TEXT
, &nmtv
.itemNew
.pszText
, &nmtv
.itemNew
.cchTextMax
,
1271 TVN_DELETEITEMW
, TVN_DELETEITEMA
, DONT_CONVERT_SEND
, TVITEM_NEW_HANDLER
},
1272 {&nmtv
, sizeof(nmtv
), &nmtv
.itemOld
.mask
, TVIF_TEXT
, &nmtv
.itemOld
.pszText
, &nmtv
.itemOld
.cchTextMax
,
1273 TVN_DELETEITEMW
, TVN_DELETEITEMA
, CONVERT_SEND
, TVITEM_OLD_HANDLER
},
1274 {&nmtv
, sizeof(nmtv
), &nmtv
.itemNew
.mask
, TVIF_TEXT
, &nmtv
.itemNew
.pszText
, &nmtv
.itemNew
.cchTextMax
,
1275 TVN_SELCHANGINGW
, TVN_SELCHANGINGA
, CONVERT_SEND
, TVITEM_NEW_HANDLER
},
1276 {&nmtv
, sizeof(nmtv
), &nmtv
.itemOld
.mask
, TVIF_TEXT
, &nmtv
.itemOld
.pszText
, &nmtv
.itemOld
.cchTextMax
,
1277 TVN_SELCHANGINGW
, TVN_SELCHANGINGA
, CONVERT_SEND
, TVITEM_OLD_HANDLER
},
1278 {&nmtv
, sizeof(nmtv
), &nmtv
.itemNew
.mask
, TVIF_TEXT
, &nmtv
.itemNew
.pszText
, &nmtv
.itemNew
.cchTextMax
,
1279 TVN_SELCHANGEDW
, TVN_SELCHANGEDA
, CONVERT_SEND
, TVITEM_NEW_HANDLER
},
1280 {&nmtv
, sizeof(nmtv
), &nmtv
.itemOld
.mask
, TVIF_TEXT
, &nmtv
.itemOld
.pszText
, &nmtv
.itemOld
.cchTextMax
,
1281 TVN_SELCHANGEDW
, TVN_SELCHANGEDA
, CONVERT_SEND
, TVITEM_OLD_HANDLER
}
1285 ok(register_test_notify_class(), "Register test class failed, error 0x%08x\n", GetLastError());
1287 parent
= CreateWindowA(class, "parent", WS_OVERLAPPED
, 0, 0, 100, 100, 0, 0, GetModuleHandleA(0), 0);
1288 ok(parent
!= NULL
, "CreateWindow failed\n");
1289 pager
= CreateWindowA(WC_PAGESCROLLERA
, "pager", WS_CHILD
, 0, 0, 100, 100, parent
, 0, GetModuleHandleA(0), 0);
1290 ok(pager
!= NULL
, "CreateWindow failed\n");
1291 child1_wnd
= CreateWindowA(class, "child", WS_CHILD
, 0, 0, 100, 100, pager
, (HMENU
)1, GetModuleHandleA(0), 0);
1292 ok(child1_wnd
!= NULL
, "CreateWindow failed\n");
1293 SendMessageW(pager
, PGM_SETCHILD
, 0, (LPARAM
)child1_wnd
);
1295 for (i
= 0; i
< ARRAY_SIZE(paras
); i
++)
1296 test_notify_generic_text_helper(pager
, paras
+ i
);
1298 /* Tests for those that can't be covered by generic text test helper */
1299 test_wm_notify_comboboxex(pager
);
1300 test_wm_notify_datetime(pager
);
1301 test_wm_notify_header(pager
);
1302 test_wm_notify_tooltip(pager
);
1304 DestroyWindow(parent
);
1305 UnregisterClassA(class, GetModuleHandleA(NULL
));
1308 static void init_functions(void)
1310 HMODULE mod
= LoadLibraryA("comctl32.dll");
1312 #define X(f) p##f = (void*)GetProcAddress(mod, #f);
1313 X(InitCommonControlsEx
);
1316 pSetWindowSubclass
= (void*)GetProcAddress(mod
, (LPSTR
)410);
1321 INITCOMMONCONTROLSEX iccex
;
1325 iccex
.dwSize
= sizeof(iccex
);
1326 iccex
.dwICC
= ICC_PAGESCROLLER_CLASS
;
1327 pInitCommonControlsEx(&iccex
);
1329 init_msg_sequences(sequences
, NUM_MSG_SEQUENCES
);
1331 parent_wnd
= create_parent_window();
1332 ok(parent_wnd
!= NULL
, "Failed to create parent window!\n");
1335 test_wm_notifyformat();
1338 DestroyWindow(parent_wnd
);