1 /* Unit test suite for property sheet control.
3 * Copyright 2006 Huw Davies
4 * Copyright 2009 Jan de Mooij
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 "resources.h"
27 #include "wine/test.h"
29 static HWND parenthwnd
;
30 static HWND sheethwnd
;
33 static LONG active_page
= -1;
35 #define IDC_APPLY_BUTTON 12321
37 static HPROPSHEETPAGE (WINAPI
*pCreatePropertySheetPageA
)(const PROPSHEETPAGEA
*desc
);
38 static HPROPSHEETPAGE (WINAPI
*pCreatePropertySheetPageW
)(const PROPSHEETPAGEW
*desc
);
39 static BOOL (WINAPI
*pDestroyPropertySheetPage
)(HPROPSHEETPAGE proppage
);
40 static INT_PTR (WINAPI
*pPropertySheetA
)(const PROPSHEETHEADERA
*header
);
42 static void detect_locale(void)
45 rtl
= GetLocaleInfoW(LOCALE_USER_DEFAULT
, LOCALE_IREADINGLAYOUT
| LOCALE_RETURN_NUMBER
,
46 (void *)&reading_layout
, sizeof(reading_layout
)) && reading_layout
== 1;
49 /* try to make sure pending X events have been processed before continuing */
50 static void flush_events(void)
54 int min_timeout
= 100;
55 DWORD time
= GetTickCount() + diff
;
59 if (MsgWaitForMultipleObjects( 0, NULL
, FALSE
, min_timeout
, QS_ALLINPUT
) == WAIT_TIMEOUT
) break;
60 while (PeekMessageA( &msg
, 0, 0, 0, PM_REMOVE
)) DispatchMessageA( &msg
);
61 diff
= time
- GetTickCount();
66 static int CALLBACK
sheet_callback(HWND hwnd
, UINT msg
, LPARAM lparam
)
72 HMODULE module
= GetModuleHandleA("comctl32.dll");
73 DWORD size
, buffer_size
;
76 hrsrc
= FindResourceA(module
, MAKEINTRESOURCEA(1006 /* IDD_PROPSHEET */),
78 size
= SizeofResource(module
, hrsrc
);
79 ok(size
!= 0, "Failed to get size of propsheet dialog resource\n");
80 buffer_size
= HeapSize(GetProcessHeap(), 0, (void *)lparam
);
81 ok(buffer_size
== 2 * size
, "Unexpected template buffer size %u, resource size %u\n",
85 case PSCB_INITIALIZED
:
88 GetWindowTextA(hwnd
, caption
, sizeof(caption
));
89 ok(!strcmp(caption
,"test caption"), "caption: %s\n", caption
);
97 static INT_PTR CALLBACK
page_dlg_proc(HWND hwnd
, UINT msg
, WPARAM wparam
,
104 HWND sheet
= GetParent(hwnd
);
106 GetWindowTextA(sheet
, caption
, sizeof(caption
));
107 ok(!strcmp(caption
,"test caption"), "caption: %s\n", caption
);
113 NMHDR
*nmhdr
= (NMHDR
*)lparam
;
123 ok(!SendMessageA(sheethwnd
, PSM_INDEXTOHWND
, 400, 0),"Should always be 0\n");
131 static void test_title(void)
133 HPROPSHEETPAGE hpsp
[1];
135 PROPSHEETHEADERA psh
;
139 memset(&psp
, 0, sizeof(psp
));
140 psp
.dwSize
= sizeof(psp
);
142 psp
.hInstance
= GetModuleHandleA(NULL
);
143 U(psp
).pszTemplate
= "prop_page1";
144 U2(psp
).pszIcon
= NULL
;
145 psp
.pfnDlgProc
= page_dlg_proc
;
148 hpsp
[0] = pCreatePropertySheetPageA(&psp
);
150 memset(&psh
, 0, sizeof(psh
));
151 psh
.dwSize
= PROPSHEETHEADERA_V1_SIZE
;
152 psh
.dwFlags
= PSH_MODELESS
| PSH_USECALLBACK
;
153 psh
.pszCaption
= "test caption";
155 psh
.hwndParent
= GetDesktopWindow();
156 U3(psh
).phpage
= hpsp
;
157 psh
.pfnCallback
= sheet_callback
;
159 hdlg
= (HWND
)pPropertySheetA(&psh
);
160 ok(hdlg
!= INVALID_HANDLE_VALUE
, "got invalid handle value %p\n", hdlg
);
162 style
= GetWindowLongA(hdlg
, GWL_STYLE
);
163 ok(style
== (WS_POPUP
|WS_VISIBLE
|WS_CLIPSIBLINGS
|WS_CAPTION
|WS_SYSMENU
|
164 DS_CONTEXTHELP
|DS_MODALFRAME
|DS_SETFONT
|DS_3DLOOK
),
165 "got unexpected style: %x\n", style
);
170 static void test_nopage(void)
172 HPROPSHEETPAGE hpsp
[1];
174 PROPSHEETHEADERA psh
;
178 memset(&psp
, 0, sizeof(psp
));
179 psp
.dwSize
= sizeof(psp
);
181 psp
.hInstance
= GetModuleHandleA(NULL
);
182 U(psp
).pszTemplate
= "prop_page1";
183 U2(psp
).pszIcon
= NULL
;
184 psp
.pfnDlgProc
= page_dlg_proc
;
187 hpsp
[0] = pCreatePropertySheetPageA(&psp
);
189 memset(&psh
, 0, sizeof(psh
));
190 psh
.dwSize
= PROPSHEETHEADERA_V1_SIZE
;
191 psh
.dwFlags
= PSH_MODELESS
| PSH_USECALLBACK
;
192 psh
.pszCaption
= "test caption";
194 psh
.hwndParent
= GetDesktopWindow();
195 U3(psh
).phpage
= hpsp
;
196 psh
.pfnCallback
= sheet_callback
;
198 hdlg
= (HWND
)pPropertySheetA(&psh
);
199 ok(hdlg
!= INVALID_HANDLE_VALUE
, "got invalid handle value %p\n", hdlg
);
201 ShowWindow(hdlg
,SW_NORMAL
);
202 SendMessageA(hdlg
, PSM_REMOVEPAGE
, 0, 0);
203 hpage
= /* PropSheet_GetCurrentPageHwnd(hdlg); */
204 (HWND
)SendMessageA(hdlg
, PSM_GETCURRENTPAGEHWND
, 0, 0);
205 active_page
= /* PropSheet_HwndToIndex(hdlg, hpage)); */
206 (int)SendMessageA(hdlg
, PSM_HWNDTOINDEX
, (WPARAM
)hpage
, 0);
207 ok(hpage
== NULL
, "expected no current page, got %p, index=%d\n", hpage
, active_page
);
209 RedrawWindow(hdlg
,NULL
,NULL
,RDW_UPDATENOW
|RDW_ERASENOW
);
211 /* Check that the property sheet was fully redrawn */
212 ok(!PeekMessageA(&msg
, 0, WM_PAINT
, WM_PAINT
, PM_NOREMOVE
),
213 "expected no pending WM_PAINT messages\n");
217 static int CALLBACK
disableowner_callback(HWND hwnd
, UINT msg
, LPARAM lparam
)
221 case PSCB_INITIALIZED
:
223 ok(IsWindowEnabled(parenthwnd
) == 0, "parent window should be disabled\n");
231 static void register_parent_wnd_class(void)
236 cls
.lpfnWndProc
= DefWindowProcA
;
239 cls
.hInstance
= GetModuleHandleA(NULL
);
241 cls
.hCursor
= LoadCursorA(0, (LPCSTR
)IDC_ARROW
);
242 cls
.hbrBackground
= GetStockObject(WHITE_BRUSH
);
243 cls
.lpszMenuName
= NULL
;
244 cls
.lpszClassName
= "parent class";
245 RegisterClassA(&cls
);
248 static void test_disableowner(void)
250 HPROPSHEETPAGE hpsp
[1];
252 PROPSHEETHEADERA psh
;
255 register_parent_wnd_class();
256 parenthwnd
= CreateWindowA("parent class", "", WS_CAPTION
| WS_SYSMENU
| WS_VISIBLE
, 100, 100, 100, 100, GetDesktopWindow(), NULL
, GetModuleHandleA(NULL
), 0);
258 memset(&psp
, 0, sizeof(psp
));
259 psp
.dwSize
= sizeof(psp
);
261 psp
.hInstance
= GetModuleHandleA(NULL
);
262 U(psp
).pszTemplate
= "prop_page1";
263 U2(psp
).pszIcon
= NULL
;
264 psp
.pfnDlgProc
= NULL
;
267 hpsp
[0] = pCreatePropertySheetPageA(&psp
);
269 memset(&psh
, 0, sizeof(psh
));
270 psh
.dwSize
= PROPSHEETHEADERA_V1_SIZE
;
271 psh
.dwFlags
= PSH_USECALLBACK
;
272 psh
.pszCaption
= "test caption";
274 psh
.hwndParent
= parenthwnd
;
275 U3(psh
).phpage
= hpsp
;
276 psh
.pfnCallback
= disableowner_callback
;
278 p
= pPropertySheetA(&psh
);
279 ok(p
== 0, "Expected 0, got %ld\n", p
);
280 ok(IsWindowEnabled(parenthwnd
) != 0, "parent window should be enabled\n");
281 DestroyWindow(parenthwnd
);
284 static INT_PTR CALLBACK
nav_page_proc(HWND hwnd
, UINT msg
, WPARAM wparam
, LPARAM lparam
)
289 LPNMHDR hdr
= (LPNMHDR
)lparam
;
292 active_page
= /* PropSheet_HwndToIndex(hdr->hwndFrom, hwnd); */
293 (int)SendMessageA(hdr
->hwndFrom
, PSM_HWNDTOINDEX
, (WPARAM
)hwnd
, 0);
296 /* prevent navigation away from the fourth page */
297 if(active_page
== 3){
298 SetWindowLongPtrA(hwnd
, DWLP_MSGRESULT
, TRUE
);
308 static WNDPROC old_nav_dialog_proc
;
310 static LRESULT CALLBACK
new_nav_dialog_proc( HWND hwnd
, UINT msg
, WPARAM wp
, LPARAM lp
)
315 ok( IsWindowEnabled( GetDlgItem(hwnd
, wp
) ), "button is not enabled\n" );
318 return CallWindowProcW( old_nav_dialog_proc
, hwnd
, msg
, wp
, lp
);
321 static LRESULT CALLBACK
hook_proc( int code
, WPARAM wp
, LPARAM lp
)
324 if (code
== HCBT_CREATEWND
)
326 CBT_CREATEWNDW
*c
= (CBT_CREATEWNDW
*)lp
;
328 /* The first dialog created will be the parent dialog */
329 if (!done
&& c
->lpcs
->lpszClass
== (LPWSTR
)WC_DIALOG
)
331 old_nav_dialog_proc
= (WNDPROC
)SetWindowLongPtrW( (HWND
)wp
, GWLP_WNDPROC
, (LONG_PTR
)new_nav_dialog_proc
);
336 return CallNextHookEx( NULL
, code
, wp
, lp
);
339 static void test_wiznavigation(void)
341 HPROPSHEETPAGE hpsp
[4];
342 PROPSHEETPAGEA psp
[4];
343 PROPSHEETHEADERA psh
;
348 BOOL hwndtoindex_supported
= TRUE
;
349 const INT nextID
= 12324;
350 const INT backID
= 12323;
353 /* set up a hook proc in order to subclass the main dialog early on */
354 hook
= SetWindowsHookExW( WH_CBT
, hook_proc
, NULL
, GetCurrentThreadId() );
356 /* create the property sheet pages */
357 memset(psp
, 0, sizeof(PROPSHEETPAGEA
) * 4);
359 psp
[0].dwSize
= sizeof(PROPSHEETPAGEA
);
360 psp
[0].hInstance
= GetModuleHandleA(NULL
);
361 U(psp
[0]).pszTemplate
= (LPCSTR
)MAKEINTRESOURCE(IDD_PROP_PAGE_INTRO
);
362 psp
[0].pfnDlgProc
= nav_page_proc
;
363 hpsp
[0] = pCreatePropertySheetPageA(&psp
[0]);
365 psp
[1].dwSize
= sizeof(PROPSHEETPAGEA
);
366 psp
[1].hInstance
= GetModuleHandleA(NULL
);
367 U(psp
[1]).pszTemplate
= (LPCSTR
)MAKEINTRESOURCE(IDD_PROP_PAGE_EDIT
);
368 psp
[1].pfnDlgProc
= nav_page_proc
;
369 hpsp
[1] = pCreatePropertySheetPageA(&psp
[1]);
371 psp
[2].dwSize
= sizeof(PROPSHEETPAGEA
);
372 psp
[2].hInstance
= GetModuleHandleA(NULL
);
373 U(psp
[2]).pszTemplate
= (LPCSTR
)MAKEINTRESOURCE(IDD_PROP_PAGE_RADIO
);
374 psp
[2].pfnDlgProc
= nav_page_proc
;
375 hpsp
[2] = pCreatePropertySheetPageA(&psp
[2]);
377 psp
[3].dwSize
= sizeof(PROPSHEETPAGEA
);
378 psp
[3].hInstance
= GetModuleHandleA(NULL
);
379 U(psp
[3]).pszTemplate
= (LPCSTR
)MAKEINTRESOURCE(IDD_PROP_PAGE_EXIT
);
380 psp
[3].pfnDlgProc
= nav_page_proc
;
381 hpsp
[3] = pCreatePropertySheetPageA(&psp
[3]);
383 /* set up the property sheet dialog */
384 memset(&psh
, 0, sizeof(psh
));
385 psh
.dwSize
= PROPSHEETHEADERA_V1_SIZE
;
386 psh
.dwFlags
= PSH_MODELESS
| PSH_WIZARD
;
387 psh
.pszCaption
= "A Wizard";
389 psh
.hwndParent
= GetDesktopWindow();
390 U3(psh
).phpage
= hpsp
;
391 hdlg
= (HWND
)pPropertySheetA(&psh
);
392 ok(hdlg
!= INVALID_HANDLE_VALUE
, "got invalid handle %p\n", hdlg
);
394 ok(active_page
== 0, "Active page should be 0. Is: %d\n", active_page
);
396 style
= GetWindowLongA(hdlg
, GWL_STYLE
) & ~(DS_CONTEXTHELP
|WS_SYSMENU
);
397 ok(style
== (WS_POPUP
|WS_VISIBLE
|WS_CLIPSIBLINGS
|WS_CAPTION
|
398 DS_MODALFRAME
|DS_SETFONT
|DS_3DLOOK
),
399 "got unexpected style: %x\n", style
);
401 control
= GetFocus();
402 controlID
= GetWindowLongPtrA(control
, GWLP_ID
);
403 ok(controlID
== nextID
, "Focus should have been set to the Next button. Expected: %d, Found: %ld\n", nextID
, controlID
);
405 /* simulate pressing the Next button */
406 SendMessageA(hdlg
, PSM_PRESSBUTTON
, PSBTN_NEXT
, 0);
407 if (!active_page
) hwndtoindex_supported
= FALSE
;
408 if (hwndtoindex_supported
)
409 ok(active_page
== 1, "Active page should be 1 after pressing Next. Is: %d\n", active_page
);
411 control
= GetFocus();
412 controlID
= GetWindowLongPtrA(control
, GWLP_ID
);
413 ok(controlID
== IDC_PS_EDIT1
, "Focus should be set to the first item on the second page. Expected: %d, Found: %ld\n", IDC_PS_EDIT1
, controlID
);
415 defidres
= SendMessageA(hdlg
, DM_GETDEFID
, 0, 0);
416 ok(defidres
== MAKELRESULT(nextID
, DC_HASDEFID
), "Expected default button ID to be %d, is %d\n", nextID
, LOWORD(defidres
));
418 /* set the focus to the second edit box on this page */
419 SetFocus(GetNextDlgTabItem(hdlg
, control
, FALSE
));
421 /* press next again */
422 SendMessageA(hdlg
, PSM_PRESSBUTTON
, PSBTN_NEXT
, 0);
423 if (hwndtoindex_supported
)
424 ok(active_page
== 2, "Active page should be 2 after pressing Next. Is: %d\n", active_page
);
426 control
= GetFocus();
427 controlID
= GetWindowLongPtrA(control
, GWLP_ID
);
428 ok(controlID
== IDC_PS_RADIO1
, "Focus should have been set to item on third page. Expected: %d, Found %ld\n", IDC_PS_RADIO1
, controlID
);
431 SendMessageA(hdlg
, PSM_PRESSBUTTON
, PSBTN_BACK
, 0);
432 if (hwndtoindex_supported
)
433 ok(active_page
== 1, "Active page should be 1 after pressing Back. Is: %d\n", active_page
);
435 control
= GetFocus();
436 controlID
= GetWindowLongPtrA(control
, GWLP_ID
);
437 ok(controlID
== IDC_PS_EDIT1
, "Focus should have been set to the first item on second page. Expected: %d, Found %ld\n", IDC_PS_EDIT1
, controlID
);
439 defidres
= SendMessageA(hdlg
, DM_GETDEFID
, 0, 0);
440 ok(defidres
== MAKELRESULT(backID
, DC_HASDEFID
), "Expected default button ID to be %d, is %d\n", backID
, LOWORD(defidres
));
442 /* press next twice */
443 SendMessageA(hdlg
, PSM_PRESSBUTTON
, PSBTN_NEXT
, 0);
444 if (hwndtoindex_supported
)
445 ok(active_page
== 2, "Active page should be 2 after pressing Next. Is: %d\n", active_page
);
446 SendMessageA(hdlg
, PSM_PRESSBUTTON
, PSBTN_NEXT
, 0);
447 if (hwndtoindex_supported
)
448 ok(active_page
== 3, "Active page should be 3 after pressing Next. Is: %d\n", active_page
);
452 control
= GetFocus();
453 controlID
= GetWindowLongPtrA(control
, GWLP_ID
);
454 ok(controlID
== nextID
, "Focus should have been set to the Next button. Expected: %d, Found: %ld\n", nextID
, controlID
);
456 /* try to navigate away, but shouldn't be able to */
457 SendMessageA(hdlg
, PSM_PRESSBUTTON
, PSBTN_BACK
, 0);
458 ok(active_page
== 3, "Active page should still be 3 after pressing Back. Is: %d\n", active_page
);
460 defidres
= SendMessageA(hdlg
, DM_GETDEFID
, 0, 0);
461 ok(defidres
== MAKELRESULT(nextID
, DC_HASDEFID
), "Expected default button ID to be %d, is %d\n", nextID
, LOWORD(defidres
));
464 UnhookWindowsHookEx( hook
);
467 static void test_buttons(void)
469 HPROPSHEETPAGE hpsp
[1];
471 PROPSHEETHEADERA psh
;
477 memset(&psp
, 0, sizeof(psp
));
478 psp
.dwSize
= sizeof(psp
);
480 psp
.hInstance
= GetModuleHandleA(NULL
);
481 U(psp
).pszTemplate
= "prop_page1";
482 U2(psp
).pszIcon
= NULL
;
483 psp
.pfnDlgProc
= page_dlg_proc
;
486 hpsp
[0] = pCreatePropertySheetPageA(&psp
);
488 memset(&psh
, 0, sizeof(psh
));
489 psh
.dwSize
= PROPSHEETHEADERA_V1_SIZE
;
490 psh
.dwFlags
= PSH_MODELESS
| PSH_USECALLBACK
;
491 psh
.pszCaption
= "test caption";
493 psh
.hwndParent
= GetDesktopWindow();
494 U3(psh
).phpage
= hpsp
;
495 psh
.pfnCallback
= sheet_callback
;
497 hdlg
= (HWND
)pPropertySheetA(&psh
);
498 ok(hdlg
!= INVALID_HANDLE_VALUE
, "got null handle\n");
501 button
= GetDlgItem(hdlg
, IDOK
);
502 GetWindowRect(button
, &rc
);
503 prevRight
= rc
.right
;
507 button
= GetDlgItem(hdlg
, IDCANCEL
);
508 GetWindowRect(button
, &rc
);
509 ok(rc
.top
== top
, "Cancel button should have same top as OK button\n");
511 ok(rc
.left
< prevRight
, "Cancel button should be to the left of OK button\n");
513 ok(rc
.left
> prevRight
, "Cancel button should be to the right of OK button\n");
514 prevRight
= rc
.right
;
516 button
= GetDlgItem(hdlg
, IDC_APPLY_BUTTON
);
517 GetWindowRect(button
, &rc
);
518 ok(rc
.top
== top
, "Apply button should have same top as OK button\n");
520 ok(rc
.left
< prevRight
, "Apply button should be to the left of Cancel button\n");
522 ok(rc
.left
> prevRight
, "Apply button should be to the right of Cancel button\n");
523 prevRight
= rc
.right
;
525 button
= GetDlgItem(hdlg
, IDHELP
);
526 GetWindowRect(button
, &rc
);
527 ok(rc
.top
== top
, "Help button should have same top as OK button\n");
529 ok(rc
.left
< prevRight
, "Help button should be to the left of Apply button\n");
531 ok(rc
.left
> prevRight
, "Help button should be to the right of Apply button\n");
536 static BOOL add_button_has_been_pressed
;
538 static INT_PTR CALLBACK
539 page_with_custom_default_button_dlg_proc(HWND hdlg
, UINT msg
, WPARAM wparam
, LPARAM lparam
)
544 switch(LOWORD(wparam
))
546 case IDC_PS_PUSHBUTTON1
:
547 switch(HIWORD(wparam
))
550 add_button_has_been_pressed
= TRUE
;
560 static void test_custom_default_button(void)
563 PROPSHEETPAGEA psp
[1];
564 PROPSHEETHEADERA psh
;
568 psp
[0].dwSize
= sizeof (PROPSHEETPAGEA
);
569 psp
[0].dwFlags
= PSP_USETITLE
;
570 psp
[0].hInstance
= GetModuleHandleA(NULL
);
571 U(psp
[0]).pszTemplate
= (LPCSTR
)MAKEINTRESOURCE(IDD_PROP_PAGE_WITH_CUSTOM_DEFAULT_BUTTON
);
572 U2(psp
[0]).pszIcon
= NULL
;
573 psp
[0].pfnDlgProc
= page_with_custom_default_button_dlg_proc
;
574 psp
[0].pszTitle
= "Page1";
577 psh
.dwSize
= PROPSHEETHEADERA_V1_SIZE
;
578 psh
.dwFlags
= PSH_PROPSHEETPAGE
| PSH_MODELESS
;
579 psh
.hwndParent
= GetDesktopWindow();
580 psh
.hInstance
= GetModuleHandleA(NULL
);
581 U(psh
).pszIcon
= NULL
;
582 psh
.pszCaption
= "PropertySheet1";
585 U2(psh
).nStartPage
= 0;
587 /* The goal of the test is to make sure that the Add button is pressed
588 * when the ENTER key is pressed and a different control, a combobox,
589 * has the keyboard focus. */
590 add_button_has_been_pressed
= FALSE
;
592 /* Create the modeless property sheet. */
593 hdlg
= (HWND
)pPropertySheetA(&psh
);
594 ok(hdlg
!= INVALID_HANDLE_VALUE
, "Cannot create the property sheet\n");
596 /* Set the Add button as the default button. */
597 SendMessageA(hdlg
, DM_SETDEFID
, (WPARAM
)IDC_PS_PUSHBUTTON1
, 0);
599 /* Make sure the default button is the Add button. */
600 result
= SendMessageA(hdlg
, DM_GETDEFID
, 0, 0);
601 ok(DC_HASDEFID
== HIWORD(result
), "The property sheet does not have a default button\n");
602 ok(IDC_PS_PUSHBUTTON1
== LOWORD(result
), "The default button is not the Add button\n");
604 /* At this point, the combobox should have keyboard focus, so we press ENTER.
605 * Pull the lever, Kronk! */
606 page
= (HWND
)SendMessageW(hdlg
, PSM_GETCURRENTPAGEHWND
, 0, 0);
607 PostMessageW(GetDlgItem(page
, IDC_PS_COMBO1
), WM_KEYDOWN
, VK_RETURN
, 0);
609 /* Process all the messages in the queue for this thread. */
610 while (PeekMessageA(&msg
, NULL
, 0, 0, PM_REMOVE
))
612 /* (!PropSheet_IsDialogMessage(hdlg, &msg)) */
613 if (!((BOOL
)SendMessageA(hdlg
, PSM_ISDIALOGMESSAGE
, 0, (LPARAM
)&msg
)))
615 TranslateMessage(&msg
);
616 DispatchMessageA(&msg
);
620 ok(add_button_has_been_pressed
, "The Add button has not been pressed!\n");
625 #define RECEIVER_SHEET_CALLBACK 0
626 #define RECEIVER_SHEET_WINPROC 1
627 #define RECEIVER_PAGE 2
629 #define NUM_MSG_SEQUENCES 1
630 #define PROPSHEET_SEQ_INDEX 0
632 static struct msg_sequence
*sequences
[NUM_MSG_SEQUENCES
];
633 static WNDPROC oldWndProc
;
635 static const struct message property_sheet_seq
[] = {
636 { PSCB_PRECREATE
, sent
|id
, 0, 0, RECEIVER_SHEET_CALLBACK
},
637 { PSCB_INITIALIZED
, sent
|id
, 0, 0, RECEIVER_SHEET_CALLBACK
},
638 { WM_WINDOWPOSCHANGING
, sent
|id
, 0, 0, RECEIVER_SHEET_WINPROC
},
639 /*{ WM_NCCALCSIZE, sent|id, 0, 0, RECEIVER_SHEET_WINPROC },*/
640 { WM_WINDOWPOSCHANGED
, sent
|id
, 0, 0, RECEIVER_SHEET_WINPROC
},
641 { WM_MOVE
, sent
|id
, 0, 0, RECEIVER_SHEET_WINPROC
},
642 { WM_SIZE
, sent
|id
, 0, 0, RECEIVER_SHEET_WINPROC
},
643 /*{ WM_GETTEXT, sent|id, 0, 0, RECEIVER_SHEET_WINPROC },
644 { WM_GETICON, sent|id, 0, 0, RECEIVER_SHEET_WINPROC },
645 { WM_GETICON, sent|id, 0, 0, RECEIVER_SHEET_WINPROC },
646 { WM_GETICON, sent|id, 0, 0, RECEIVER_SHEET_WINPROC },
647 { WM_NCCALCSIZE, sent|id|optional, 0, 0, RECEIVER_SHEET_WINPROC },
648 { DM_REPOSITION, sent|id, 0, 0, RECEIVER_SHEET_WINPROC },*/
649 { WM_WINDOWPOSCHANGING
, sent
|id
, 0, 0, RECEIVER_SHEET_WINPROC
},
650 { WM_WINDOWPOSCHANGING
, sent
|id
, 0, 0, RECEIVER_SHEET_WINPROC
},
651 { WM_ACTIVATEAPP
, sent
|id
, 0, 0, RECEIVER_SHEET_WINPROC
},
652 /*{ WM_NCACTIVATE, sent|id, 0, 0, RECEIVER_SHEET_WINPROC },
653 { WM_GETTEXT, sent|id, 0, 0, RECEIVER_SHEET_WINPROC },
654 { WM_GETICON, sent|id, 0, 0, RECEIVER_SHEET_WINPROC },
655 { WM_GETICON, sent|id, 0, 0, RECEIVER_SHEET_WINPROC },
656 { WM_GETICON, sent|id, 0, 0, RECEIVER_SHEET_WINPROC },
657 { WM_GETTEXT, sent|id, 0, 0, RECEIVER_SHEET_WINPROC },*/
658 { WM_ACTIVATE
, sent
|id
, 0, 0, RECEIVER_SHEET_WINPROC
},
659 /*{ WM_IME_SETCONTEXT, sent|id, 0, 0, RECEIVER_SHEET_WINPROC },
660 { WM_IME_NOTIFY, sent|id, 0, 0, RECEIVER_SHEET_WINPROC },*/
661 { WM_SETFOCUS
, sent
|id
, 0, 0, RECEIVER_SHEET_WINPROC
},
662 { WM_KILLFOCUS
, sent
|id
, 0, 0, RECEIVER_SHEET_WINPROC
},
663 /*{ WM_IME_SETCONTEXT, sent|id, 0, 0, RECEIVER_SHEET_WINPROC },*/
664 { WM_PARENTNOTIFY
, sent
|id
, 0, 0, RECEIVER_SHEET_WINPROC
},
665 { WM_INITDIALOG
, sent
|id
, 0, 0, RECEIVER_PAGE
},
666 { WM_WINDOWPOSCHANGING
, sent
|id
, 0, 0, RECEIVER_PAGE
},
667 /*{ WM_NCCALCSIZE, sent|id, 0, 0, RECEIVER_PAGE },*/
668 { WM_CHILDACTIVATE
, sent
|id
, 0, 0, RECEIVER_PAGE
},
669 { WM_WINDOWPOSCHANGED
, sent
|id
, 0, 0, RECEIVER_PAGE
},
670 { WM_MOVE
, sent
|id
, 0, 0, RECEIVER_PAGE
},
671 { WM_SIZE
, sent
|id
, 0, 0, RECEIVER_PAGE
},
672 { WM_NOTIFY
, sent
|id
, 0, 0, RECEIVER_PAGE
},
673 { WM_STYLECHANGING
, sent
|id
|optional
, 0, 0, RECEIVER_SHEET_WINPROC
},
674 { WM_STYLECHANGED
, sent
|id
|optional
, 0, 0, RECEIVER_SHEET_WINPROC
},
675 /*{ WM_GETTEXT, sent|id, 0, 0, RECEIVER_SHEET_WINPROC },
676 { WM_GETICON, sent|id, 0, 0, RECEIVER_SHEET_WINPROC },
677 { WM_GETICON, sent|id, 0, 0, RECEIVER_SHEET_WINPROC },
678 { WM_GETICON, sent|id, 0, 0, RECEIVER_SHEET_WINPROC },*/
679 { WM_SETTEXT
, sent
|id
, 0, 0, RECEIVER_SHEET_WINPROC
},
680 { WM_SHOWWINDOW
, sent
|id
, 0, 0, RECEIVER_PAGE
},
681 /*{ 0x00000401, sent|id, 0, 0, RECEIVER_SHEET_WINPROC },
682 { 0x00000400, sent|id, 0, 0, RECEIVER_SHEET_WINPROC },*/
683 { WM_CHANGEUISTATE
, sent
|id
|optional
, 0, 0, RECEIVER_SHEET_WINPROC
},
684 { WM_UPDATEUISTATE
, sent
|id
|optional
, 0, 0, RECEIVER_SHEET_WINPROC
},
685 { WM_UPDATEUISTATE
, sent
|id
|optional
, 0, 0, RECEIVER_PAGE
},
686 { WM_SHOWWINDOW
, sent
|id
, 0, 0, RECEIVER_SHEET_WINPROC
},
687 { WM_WINDOWPOSCHANGING
, sent
|id
, 0, 0, RECEIVER_SHEET_WINPROC
},
688 /*{ WM_NCPAINT, sent|id, 0, 0, RECEIVER_SHEET_WINPROC },
689 { WM_GETICON, sent|id, 0, 0, RECEIVER_SHEET_WINPROC },
690 { WM_GETICON, sent|id, 0, 0, RECEIVER_SHEET_WINPROC },
691 { WM_GETICON, sent|id, 0, 0, RECEIVER_SHEET_WINPROC },
692 { WM_ERASEBKGND, sent|id, 0, 0, RECEIVER_SHEET_WINPROC },*/
693 { WM_CTLCOLORDLG
, sent
|id
, 0, 0, RECEIVER_SHEET_WINPROC
},
694 { WM_WINDOWPOSCHANGED
, sent
|id
, 0, 0, RECEIVER_SHEET_WINPROC
},
695 /*{ WM_GETICON, sent|id, 0, 0, RECEIVER_SHEET_WINPROC },
696 { WM_GETICON, sent|id, 0, 0, RECEIVER_SHEET_WINPROC },
697 { WM_GETICON, sent|id, 0, 0, RECEIVER_SHEET_WINPROC },
698 { WM_PAINT, sent|id, 0, 0, RECEIVER_SHEET_WINPROC },
699 { WM_PAINT, sent|id, 0, 0, RECEIVER_PAGE },
700 { WM_NCPAINT, sent|id, 0, 0, RECEIVER_PAGE },
701 { WM_ERASEBKGND, sent|id, 0, 0, RECEIVER_PAGE },*/
702 { WM_CTLCOLORDLG
, sent
|id
, 0, 0, RECEIVER_PAGE
},
703 { WM_CTLCOLORSTATIC
, sent
|id
, 0, 0, RECEIVER_PAGE
},
704 { WM_CTLCOLORSTATIC
, sent
|id
, 0, 0, RECEIVER_SHEET_WINPROC
},
705 { WM_CTLCOLORBTN
, sent
|id
, 0, 0, RECEIVER_SHEET_WINPROC
},
706 { WM_CTLCOLORBTN
, sent
|id
, 0, 0, RECEIVER_SHEET_WINPROC
},
707 { WM_CTLCOLORBTN
, sent
|id
, 0, 0, RECEIVER_SHEET_WINPROC
},
708 /*{ WM_GETICON, sent|id, 0, 0, RECEIVER_SHEET_WINPROC },
709 { WM_GETICON, sent|id, 0, 0, RECEIVER_SHEET_WINPROC },
710 { WM_GETICON, sent|id, 0, 0, RECEIVER_SHEET_WINPROC },*/
711 { WM_COMMAND
, sent
|id
|optional
, 0, 0, RECEIVER_SHEET_WINPROC
},
712 { WM_NOTIFY
, sent
|id
|optional
, 0, 0, RECEIVER_PAGE
},
713 { WM_NOTIFY
, sent
|id
|optional
, 0, 0, RECEIVER_PAGE
},
714 { WM_WINDOWPOSCHANGING
, sent
|id
|optional
, 0, 0, RECEIVER_SHEET_WINPROC
},
715 { WM_WINDOWPOSCHANGED
, sent
|id
|optional
, 0, 0, RECEIVER_SHEET_WINPROC
},
716 /*{ WM_NCACTIVATE, sent|id, 0, 0, RECEIVER_SHEET_WINPROC },
717 { WM_GETICON, sent|id, 0, 0, RECEIVER_SHEET_WINPROC },
718 { WM_GETICON, sent|id, 0, 0, RECEIVER_SHEET_WINPROC },
719 { WM_GETICON, sent|id, 0, 0, RECEIVER_SHEET_WINPROC },*/
720 /*{ WM_ACTIVATE, sent|id, 0, 0, RECEIVER_SHEET_WINPROC },
721 { WM_ACTIVATE, sent|id, 0, 0, RECEIVER_PAGE },
722 { WM_ACTIVATEAPP, sent|id, 0, 0, RECEIVER_SHEET_WINPROC },
723 { WM_ACTIVATEAPP, sent|id, 0, 0, RECEIVER_PAGE },
724 { WM_DESTROY, sent|id, 0, 0, RECEIVER_SHEET_WINPROC },
725 { WM_DESTROY, sent|id, 0, 0, RECEIVER_PAGE },*/
726 /*{ WM_NCDESTROY, sent|id, 0, 0, RECEIVER_PAGE },
727 { WM_NCDESTROY, sent|id, 0, 0, RECEIVER_SHEET_WINPROC },*/
731 static void save_message(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
, INT receiver
)
733 struct message msg
= { 0 };
735 if (message
< WM_USER
&&
736 message
!= WM_GETICON
&&
737 message
!= WM_GETTEXT
&&
738 message
!= WM_IME_SETCONTEXT
&&
739 message
!= WM_IME_NOTIFY
&&
740 message
!= WM_PAINT
&&
741 message
!= WM_ERASEBKGND
&&
742 message
!= WM_SETCURSOR
&&
743 (message
< WM_NCCREATE
|| message
> WM_NCMBUTTONDBLCLK
) &&
744 (message
< WM_MOUSEFIRST
|| message
> WM_MOUSEHWHEEL
) &&
747 msg
.message
= message
;
748 msg
.flags
= sent
|wparam
|lparam
|id
;
752 add_message(sequences
, PROPSHEET_SEQ_INDEX
, &msg
);
756 static LRESULT CALLBACK
sheet_callback_messages_proc (HWND hwnd
, UINT msg
, WPARAM wParam
, LPARAM lParam
)
758 save_message(hwnd
, msg
, wParam
, lParam
, RECEIVER_SHEET_WINPROC
);
760 return CallWindowProcA(oldWndProc
, hwnd
, msg
, wParam
, lParam
);
763 static int CALLBACK
sheet_callback_messages(HWND hwnd
, UINT msg
, LPARAM lParam
)
765 save_message(hwnd
, msg
, 0, lParam
, RECEIVER_SHEET_CALLBACK
);
769 case PSCB_INITIALIZED
:
770 oldWndProc
= (WNDPROC
)GetWindowLongPtrA(hwnd
, GWLP_WNDPROC
);
771 SetWindowLongPtrA(hwnd
, GWLP_WNDPROC
, (LONG_PTR
)&sheet_callback_messages_proc
);
778 static INT_PTR CALLBACK
page_dlg_proc_messages(HWND hwnd
, UINT msg
, WPARAM wParam
,
781 save_message(hwnd
, msg
, wParam
, lParam
, RECEIVER_PAGE
);
786 static void test_messages(void)
788 HPROPSHEETPAGE hpsp
[1];
790 PROPSHEETHEADERA psh
;
793 init_msg_sequences(sequences
, NUM_MSG_SEQUENCES
);
795 memset(&psp
, 0, sizeof(psp
));
796 psp
.dwSize
= sizeof(psp
);
798 psp
.hInstance
= GetModuleHandleA(NULL
);
799 U(psp
).pszTemplate
= (LPCSTR
)MAKEINTRESOURCE(IDD_PROP_PAGE_MESSAGE_TEST
);
800 U2(psp
).pszIcon
= NULL
;
801 psp
.pfnDlgProc
= page_dlg_proc_messages
;
804 hpsp
[0] = pCreatePropertySheetPageA(&psp
);
806 memset(&psh
, 0, sizeof(psh
));
807 psh
.dwSize
= PROPSHEETHEADERA_V1_SIZE
;
808 psh
.dwFlags
= PSH_NOAPPLYNOW
| PSH_WIZARD
| PSH_USECALLBACK
809 | PSH_MODELESS
| PSH_USEICONID
;
810 psh
.pszCaption
= "test caption";
812 psh
.hwndParent
= GetDesktopWindow();
813 U3(psh
).phpage
= hpsp
;
814 psh
.pfnCallback
= sheet_callback_messages
;
816 hdlg
= (HWND
)pPropertySheetA(&psh
);
817 ok(hdlg
!= INVALID_HANDLE_VALUE
, "got invalid handle %p\n", hdlg
);
819 ShowWindow(hdlg
,SW_NORMAL
);
821 ok_sequence(sequences
, PROPSHEET_SEQ_INDEX
, property_sheet_seq
, "property sheet with custom window proc", TRUE
);
826 static void test_PSM_ADDPAGE(void)
828 HPROPSHEETPAGE hpsp
[5];
830 PROPSHEETHEADERA psh
;
835 memset(&psp
, 0, sizeof(psp
));
836 psp
.dwSize
= sizeof(psp
);
838 psp
.hInstance
= GetModuleHandleA(NULL
);
839 U(psp
).pszTemplate
= (LPCSTR
)MAKEINTRESOURCE(IDD_PROP_PAGE_MESSAGE_TEST
);
840 U2(psp
).pszIcon
= NULL
;
841 psp
.pfnDlgProc
= page_dlg_proc_messages
;
844 /* multiple pages with the same data */
845 hpsp
[0] = pCreatePropertySheetPageA(&psp
);
846 hpsp
[1] = pCreatePropertySheetPageA(&psp
);
847 hpsp
[2] = pCreatePropertySheetPageA(&psp
);
849 U(psp
).pszTemplate
= (LPCSTR
)MAKEINTRESOURCE(IDD_PROP_PAGE_ERROR
);
850 hpsp
[3] = pCreatePropertySheetPageA(&psp
);
852 psp
.dwFlags
= PSP_PREMATURE
;
853 hpsp
[4] = pCreatePropertySheetPageA(&psp
);
855 memset(&psh
, 0, sizeof(psh
));
856 psh
.dwSize
= PROPSHEETHEADERA_V1_SIZE
;
857 psh
.dwFlags
= PSH_MODELESS
;
858 psh
.pszCaption
= "test caption";
860 psh
.hwndParent
= GetDesktopWindow();
861 U3(psh
).phpage
= hpsp
;
863 hdlg
= (HWND
)pPropertySheetA(&psh
);
864 ok(hdlg
!= INVALID_HANDLE_VALUE
, "got invalid handle %p\n", hdlg
);
866 /* add pages one by one */
867 ret
= SendMessageA(hdlg
, PSM_ADDPAGE
, 0, (LPARAM
)hpsp
[1]);
868 ok(ret
== TRUE
, "got %d\n", ret
);
870 /* try with null and invalid value */
871 ret
= SendMessageA(hdlg
, PSM_ADDPAGE
, 0, 0);
872 ok(ret
== FALSE
, "got %d\n", ret
);
876 /* crashes on native */
877 ret
= SendMessageA(hdlg
, PSM_ADDPAGE
, 0, (LPARAM
)INVALID_HANDLE_VALUE
);
879 /* check item count */
880 tab
= (HWND
)SendMessageA(hdlg
, PSM_GETTABCONTROL
, 0, 0);
882 r
= SendMessageA(tab
, TCM_GETITEMCOUNT
, 0, 0);
883 ok(r
== 2, "got %d\n", r
);
885 ret
= SendMessageA(hdlg
, PSM_ADDPAGE
, 0, (LPARAM
)hpsp
[2]);
886 ok(ret
== TRUE
, "got %d\n", ret
);
888 r
= SendMessageA(tab
, TCM_GETITEMCOUNT
, 0, 0);
889 ok(r
== 3, "got %d\n", r
);
891 /* add property sheet page that can't be created */
892 ret
= SendMessageA(hdlg
, PSM_ADDPAGE
, 0, (LPARAM
)hpsp
[3]);
893 ok(ret
== TRUE
, "got %d\n", ret
);
895 r
= SendMessageA(tab
, TCM_GETITEMCOUNT
, 0, 0);
896 ok(r
== 4, "got %d\n", r
);
898 /* select page that can't be created */
899 ret
= SendMessageA(hdlg
, PSM_SETCURSEL
, 3, 1);
900 ok(ret
== TRUE
, "got %d\n", ret
);
902 r
= SendMessageA(tab
, TCM_GETITEMCOUNT
, 0, 0);
903 ok(r
== 3, "got %d\n", r
);
905 /* test PSP_PREMATURE flag with incorrect property sheet page */
906 ret
= SendMessageA(hdlg
, PSM_ADDPAGE
, 0, (LPARAM
)hpsp
[4]);
907 ok(ret
== FALSE
, "got %d\n", ret
);
909 r
= SendMessageA(tab
, TCM_GETITEMCOUNT
, 0, 0);
910 ok(r
== 3, "got %d\n", r
);
912 pDestroyPropertySheetPage(hpsp
[4]);
916 static void test_PSM_INSERTPAGE(void)
918 HPROPSHEETPAGE hpsp
[5];
920 PROPSHEETHEADERA psh
;
925 memset(&psp
, 0, sizeof(psp
));
926 psp
.dwSize
= sizeof(psp
);
928 psp
.hInstance
= GetModuleHandleA(NULL
);
929 U(psp
).pszTemplate
= (LPCSTR
)MAKEINTRESOURCE(IDD_PROP_PAGE_MESSAGE_TEST
);
930 U2(psp
).pszIcon
= NULL
;
931 psp
.pfnDlgProc
= page_dlg_proc_messages
;
934 /* multiple pages with the same data */
935 hpsp
[0] = pCreatePropertySheetPageA(&psp
);
936 hpsp
[1] = pCreatePropertySheetPageA(&psp
);
937 hpsp
[2] = pCreatePropertySheetPageA(&psp
);
939 U(psp
).pszTemplate
= (LPCSTR
)MAKEINTRESOURCE(IDD_PROP_PAGE_ERROR
);
940 hpsp
[3] = pCreatePropertySheetPageA(&psp
);
942 psp
.dwFlags
= PSP_PREMATURE
;
943 hpsp
[4] = pCreatePropertySheetPageA(&psp
);
945 memset(&psh
, 0, sizeof(psh
));
946 psh
.dwSize
= PROPSHEETHEADERA_V1_SIZE
;
947 psh
.dwFlags
= PSH_MODELESS
;
948 psh
.pszCaption
= "test caption";
950 psh
.hwndParent
= GetDesktopWindow();
951 U3(psh
).phpage
= hpsp
;
953 hdlg
= (HWND
)pPropertySheetA(&psh
);
954 ok(hdlg
!= INVALID_HANDLE_VALUE
, "got invalid handle %p\n", hdlg
);
956 /* add pages one by one */
957 ret
= SendMessageA(hdlg
, PSM_INSERTPAGE
, 5, (LPARAM
)hpsp
[1]);
958 ok(ret
== TRUE
, "got %d\n", ret
);
960 /* try with invalid values */
961 ret
= SendMessageA(hdlg
, PSM_INSERTPAGE
, 0, 0);
962 ok(ret
== FALSE
, "got %d\n", ret
);
966 /* crashes on native */
967 ret
= SendMessageA(hdlg
, PSM_INSERTPAGE
, 0, (LPARAM
)INVALID_HANDLE_VALUE
);
970 ret
= SendMessageA(hdlg
, PSM_INSERTPAGE
, (WPARAM
)INVALID_HANDLE_VALUE
, (LPARAM
)hpsp
[2]);
971 ok(ret
== FALSE
, "got %d\n", ret
);
973 /* check item count */
974 tab
= (HWND
)SendMessageA(hdlg
, PSM_GETTABCONTROL
, 0, 0);
976 r
= SendMessageA(tab
, TCM_GETITEMCOUNT
, 0, 0);
977 ok(r
== 2, "got %d\n", r
);
979 ret
= SendMessageA(hdlg
, PSM_INSERTPAGE
, (WPARAM
)hpsp
[1], (LPARAM
)hpsp
[2]);
980 ok(ret
== TRUE
, "got %d\n", ret
);
982 r
= SendMessageA(tab
, TCM_GETITEMCOUNT
, 0, 0);
983 ok(r
== 3, "got %d\n", r
);
985 /* add property sheet page that can't be created */
986 ret
= SendMessageA(hdlg
, PSM_INSERTPAGE
, 1, (LPARAM
)hpsp
[3]);
987 ok(ret
== TRUE
, "got %d\n", ret
);
989 r
= SendMessageA(tab
, TCM_GETITEMCOUNT
, 0, 0);
990 ok(r
== 4, "got %d\n", r
);
992 /* select page that can't be created */
993 ret
= SendMessageA(hdlg
, PSM_SETCURSEL
, 1, 0);
994 ok(ret
== TRUE
, "got %d\n", ret
);
996 r
= SendMessageA(tab
, TCM_GETITEMCOUNT
, 0, 0);
997 ok(r
== 3, "got %d\n", r
);
999 /* test PSP_PREMATURE flag with incorrect property sheet page */
1000 ret
= SendMessageA(hdlg
, PSM_INSERTPAGE
, 0, (LPARAM
)hpsp
[4]);
1001 ok(ret
== FALSE
, "got %d\n", ret
);
1003 r
= SendMessageA(tab
, TCM_GETITEMCOUNT
, 0, 0);
1004 ok(r
== 3, "got %d\n", r
);
1006 pDestroyPropertySheetPage(hpsp
[4]);
1007 DestroyWindow(hdlg
);
1010 struct custom_proppage
1014 PROPSHEETPAGEA pageA
;
1015 PROPSHEETPAGEW pageW
;
1017 unsigned int addref_called
;
1018 unsigned int release_called
;
1021 static UINT CALLBACK
proppage_callback_a(HWND hwnd
, UINT msg
, PROPSHEETPAGEA
*psp
)
1023 struct custom_proppage
*cpage
= (struct custom_proppage
*)psp
->lParam
;
1024 PROPSHEETPAGEA
*psp_orig
= &cpage
->u
.pageA
;
1026 ok(hwnd
== NULL
, "Expected NULL hwnd, got %p\n", hwnd
);
1028 ok(psp
->lParam
&& psp
->lParam
!= (LPARAM
)psp
, "Expected newly allocated page description, got %lx, %p\n",
1030 ok(psp_orig
->pszTitle
== psp
->pszTitle
, "Expected same page title pointer\n");
1031 ok(!lstrcmpA(psp_orig
->pszTitle
, psp
->pszTitle
), "Expected same page title string\n");
1036 ok(psp
->dwSize
> PROPSHEETPAGEA_V1_SIZE
, "Expected ADDREF for V2+ only, got size %u\n", psp
->dwSize
);
1037 cpage
->addref_called
++;
1040 ok(psp
->dwSize
>= PROPSHEETPAGEA_V1_SIZE
, "Unexpected RELEASE, got size %u\n", psp
->dwSize
);
1041 cpage
->release_called
++;
1044 ok(0, "Unexpected message %u\n", msg
);
1050 static UINT CALLBACK
proppage_callback_w(HWND hwnd
, UINT msg
, PROPSHEETPAGEW
*psp
)
1052 struct custom_proppage
*cpage
= (struct custom_proppage
*)psp
->lParam
;
1053 PROPSHEETPAGEW
*psp_orig
= &cpage
->u
.pageW
;
1055 ok(hwnd
== NULL
, "Expected NULL hwnd, got %p\n", hwnd
);
1056 ok(psp
->lParam
&& psp
->lParam
!= (LPARAM
)psp
, "Expected newly allocated page description, got %lx, %p\n",
1058 ok(psp_orig
->pszTitle
== psp
->pszTitle
, "Expected same page title pointer\n");
1059 ok(!lstrcmpW(psp_orig
->pszTitle
, psp
->pszTitle
), "Expected same page title string\n");
1064 ok(psp
->dwSize
> PROPSHEETPAGEW_V1_SIZE
, "Expected ADDREF for V2+ only, got size %u\n", psp
->dwSize
);
1065 cpage
->addref_called
++;
1068 ok(psp
->dwSize
>= PROPSHEETPAGEW_V1_SIZE
, "Unexpected RELEASE, got size %u\n", psp
->dwSize
);
1069 cpage
->release_called
++;
1072 ok(0, "Unexpected message %u\n", msg
);
1078 static void test_CreatePropertySheetPage(void)
1080 struct custom_proppage page
;
1081 HPROPSHEETPAGE hpsp
;
1084 memset(&page
.u
.pageA
, 0, sizeof(page
.u
.pageA
));
1085 page
.u
.pageA
.dwFlags
= PSP_USECALLBACK
;
1086 page
.u
.pageA
.pfnDlgProc
= page_dlg_proc_messages
;
1087 page
.u
.pageA
.pfnCallback
= proppage_callback_a
;
1088 page
.u
.pageA
.lParam
= (LPARAM
)&page
;
1089 page
.u
.pageA
.pszTitle
= "Title";
1091 /* Only minimal size validation is performed */
1092 for (page
.u
.pageA
.dwSize
= PROPSHEETPAGEA_V1_SIZE
- 1; page
.u
.pageA
.dwSize
<= PROPSHEETPAGEA_V4_SIZE
+ 1; page
.u
.pageA
.dwSize
++)
1094 page
.addref_called
= 0;
1095 hpsp
= pCreatePropertySheetPageA(&page
.u
.pageA
);
1097 if (page
.u
.pageA
.dwSize
< PROPSHEETPAGEA_V1_SIZE
)
1098 ok(hpsp
== NULL
, "Expected failure, size %u\n", page
.u
.pageA
.dwSize
);
1101 ok(hpsp
!= NULL
, "Failed to create a page, size %u\n", page
.u
.pageA
.dwSize
);
1102 ok(page
.addref_called
== (page
.u
.pageA
.dwSize
> PROPSHEETPAGEA_V1_SIZE
) ? 1 : 0, "Expected ADDREF callback message\n");
1107 page
.release_called
= 0;
1108 ret
= pDestroyPropertySheetPage(hpsp
);
1109 ok(ret
, "Failed to destroy a page\n");
1110 ok(page
.release_called
== 1, "Expected RELEASE callback message\n");
1114 memset(&page
.u
.pageW
, 0, sizeof(page
.u
.pageW
));
1115 page
.u
.pageW
.dwFlags
= PSP_USECALLBACK
;
1116 page
.u
.pageW
.pfnDlgProc
= page_dlg_proc_messages
;
1117 page
.u
.pageW
.pfnCallback
= proppage_callback_w
;
1118 page
.u
.pageW
.lParam
= (LPARAM
)&page
;
1119 page
.u
.pageW
.pszTitle
= L
"Title";
1121 for (page
.u
.pageW
.dwSize
= PROPSHEETPAGEW_V1_SIZE
- 1; page
.u
.pageW
.dwSize
<= PROPSHEETPAGEW_V4_SIZE
+ 1; page
.u
.pageW
.dwSize
++)
1123 page
.addref_called
= 0;
1124 hpsp
= pCreatePropertySheetPageW(&page
.u
.pageW
);
1126 if (page
.u
.pageW
.dwSize
< PROPSHEETPAGEW_V1_SIZE
)
1127 ok(hpsp
== NULL
, "Expected failure, size %u\n", page
.u
.pageW
.dwSize
);
1130 ok(hpsp
!= NULL
, "Failed to create a page, size %u\n", page
.u
.pageW
.dwSize
);
1131 ok(page
.addref_called
== (page
.u
.pageW
.dwSize
> PROPSHEETPAGEW_V1_SIZE
) ? 1 : 0, "Expected ADDREF callback message\n");
1136 page
.release_called
= 0;
1137 ret
= pDestroyPropertySheetPage(hpsp
);
1138 ok(ret
, "Failed to destroy a page\n");
1139 ok(page
.release_called
== 1, "Expected RELEASE callback message\n");
1144 static void test_bad_control_class(void)
1147 PROPSHEETHEADERA psh
;
1148 HPROPSHEETPAGE hpsp
;
1151 memset(&psp
, 0, sizeof(psp
));
1152 psp
.dwSize
= sizeof(psp
);
1153 psp
.hInstance
= GetModuleHandleA(NULL
);
1154 U(psp
).pszTemplate
= (LPCSTR
)MAKEINTRESOURCE(IDD_PROP_PAGE_BAD_CONTROL
);
1155 psp
.pfnDlgProc
= page_dlg_proc
;
1157 hpsp
= pCreatePropertySheetPageA(&psp
);
1158 ok(hpsp
!= 0, "CreatePropertySheetPage failed\n");
1160 memset(&psh
, 0, sizeof(psh
));
1161 psh
.dwSize
= PROPSHEETHEADERA_V1_SIZE
;
1163 psh
.hwndParent
= GetDesktopWindow();
1164 U3(psh
).phpage
= &hpsp
;
1166 ret
= pPropertySheetA(&psh
);
1167 ok(ret
== 0, "got %ld\n", ret
);
1169 /* Need to recreate hpsp otherwise the test fails under Windows */
1170 hpsp
= pCreatePropertySheetPageA(&psp
);
1171 ok(hpsp
!= 0, "CreatePropertySheetPage failed\n");
1172 U3(psh
).phpage
= &hpsp
;
1174 psh
.dwFlags
= PSH_MODELESS
;
1175 ret
= pPropertySheetA(&psh
);
1176 ok(ret
!= 0, "got %ld\n", ret
);
1178 ok(IsWindow((HWND
)ret
), "bad window handle %#lx\n", ret
);
1179 DestroyWindow((HWND
)ret
);
1182 static void init_functions(void)
1184 HMODULE hComCtl32
= LoadLibraryA("comctl32.dll");
1186 #define X(f) p##f = (void*)GetProcAddress(hComCtl32, #f);
1187 X(CreatePropertySheetPageA
);
1188 X(CreatePropertySheetPageW
);
1189 X(DestroyPropertySheetPage
);
1194 START_TEST(propsheet
)
1199 /* use locale-specific RTL resources when on an RTL locale */
1200 /* without this, propsheets on RTL locales use English LTR resources */
1201 trace("RTL locale detected\n");
1202 SetProcessDefaultLayout(LAYOUT_RTL
);
1207 test_bad_control_class();
1210 test_disableowner();
1211 test_wiznavigation();
1213 test_custom_default_button();
1216 test_PSM_INSERTPAGE();
1217 test_CreatePropertySheetPage();