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
24 #include "resources.h"
26 #include "wine/test.h"
29 static HWND sheethwnd
;
31 static LONG active_page
= -1;
33 #define IDC_APPLY_BUTTON 12321
35 static int CALLBACK
sheet_callback(HWND hwnd
, UINT msg
, LPARAM lparam
)
39 case PSCB_INITIALIZED
:
42 GetWindowTextA(hwnd
, caption
, sizeof(caption
));
43 ok(!strcmp(caption
,"test caption"), "caption: %s\n", caption
);
51 static INT_PTR CALLBACK
page_dlg_proc(HWND hwnd
, UINT msg
, WPARAM wparam
,
58 HWND sheet
= GetParent(hwnd
);
60 GetWindowTextA(sheet
, caption
, sizeof(caption
));
61 ok(!strcmp(caption
,"test caption"), "caption: %s\n", caption
);
67 NMHDR
*nmhdr
= (NMHDR
*)lparam
;
77 ok(!SendMessageA(sheethwnd
, PSM_INDEXTOHWND
, 400, 0),"Should always be 0\n");
85 static void test_title(void)
87 HPROPSHEETPAGE hpsp
[1];
92 memset(&psp
, 0, sizeof(psp
));
93 psp
.dwSize
= sizeof(psp
);
95 psp
.hInstance
= GetModuleHandleA(NULL
);
96 U(psp
).pszTemplate
= "prop_page1";
97 U2(psp
).pszIcon
= NULL
;
98 psp
.pfnDlgProc
= page_dlg_proc
;
101 hpsp
[0] = CreatePropertySheetPageA(&psp
);
103 memset(&psh
, 0, sizeof(psh
));
104 psh
.dwSize
= sizeof(psh
);
105 psh
.dwFlags
= PSH_MODELESS
| PSH_USECALLBACK
;
106 psh
.pszCaption
= "test caption";
108 psh
.hwndParent
= GetDesktopWindow();
109 U3(psh
).phpage
= hpsp
;
110 psh
.pfnCallback
= sheet_callback
;
112 hdlg
= (HWND
)PropertySheetA(&psh
);
113 if (hdlg
== INVALID_HANDLE_VALUE
)
115 win_skip("comctl32 4.70 needs dwSize adjustment\n");
116 psh
.dwSize
= sizeof(psh
) - sizeof(HBITMAP
) - sizeof(HPALETTE
) - sizeof(HBITMAP
);
117 hdlg
= (HWND
)PropertySheetA(&psh
);
122 static void test_nopage(void)
124 HPROPSHEETPAGE hpsp
[1];
126 PROPSHEETHEADERA psh
;
129 memset(&psp
, 0, sizeof(psp
));
130 psp
.dwSize
= sizeof(psp
);
132 psp
.hInstance
= GetModuleHandleA(NULL
);
133 U(psp
).pszTemplate
= "prop_page1";
134 U2(psp
).pszIcon
= NULL
;
135 psp
.pfnDlgProc
= page_dlg_proc
;
138 hpsp
[0] = CreatePropertySheetPageA(&psp
);
140 memset(&psh
, 0, sizeof(psh
));
141 psh
.dwSize
= sizeof(psh
);
142 psh
.dwFlags
= PSH_MODELESS
| PSH_USECALLBACK
;
143 psh
.pszCaption
= "test caption";
145 psh
.hwndParent
= GetDesktopWindow();
146 U3(psh
).phpage
= hpsp
;
147 psh
.pfnCallback
= sheet_callback
;
149 hdlg
= (HWND
)PropertySheetA(&psh
);
150 if (hdlg
== INVALID_HANDLE_VALUE
)
152 win_skip("comctl32 4.70 needs dwSize adjustment\n");
153 psh
.dwSize
= sizeof(psh
) - sizeof(HBITMAP
) - sizeof(HPALETTE
) - sizeof(HBITMAP
);
154 hdlg
= (HWND
)PropertySheetA(&psh
);
156 ShowWindow(hdlg
,SW_NORMAL
);
157 SendMessage(hdlg
, PSM_REMOVEPAGE
, 0, 0);
158 RedrawWindow(hdlg
,NULL
,NULL
,RDW_UPDATENOW
|RDW_ERASENOW
);
162 static int CALLBACK
disableowner_callback(HWND hwnd
, UINT msg
, LPARAM lparam
)
166 case PSCB_INITIALIZED
:
168 ok(IsWindowEnabled(parent
) == 0, "parent window should be disabled\n");
176 static void register_parent_wnd_class(void)
181 cls
.lpfnWndProc
= DefWindowProcA
;
184 cls
.hInstance
= GetModuleHandleA(NULL
);
186 cls
.hCursor
= LoadCursorA(0, IDC_ARROW
);
187 cls
.hbrBackground
= GetStockObject(WHITE_BRUSH
);
188 cls
.lpszMenuName
= NULL
;
189 cls
.lpszClassName
= "parent class";
190 RegisterClassA(&cls
);
193 static void test_disableowner(void)
195 HPROPSHEETPAGE hpsp
[1];
197 PROPSHEETHEADERA psh
;
200 register_parent_wnd_class();
201 parent
= CreateWindowA("parent class", "", WS_CAPTION
| WS_SYSMENU
| WS_VISIBLE
, 100, 100, 100, 100, GetDesktopWindow(), NULL
, GetModuleHandleA(NULL
), 0);
203 memset(&psp
, 0, sizeof(psp
));
204 psp
.dwSize
= sizeof(psp
);
206 psp
.hInstance
= GetModuleHandleA(NULL
);
207 U(psp
).pszTemplate
= "prop_page1";
208 U2(psp
).pszIcon
= NULL
;
209 psp
.pfnDlgProc
= NULL
;
212 hpsp
[0] = CreatePropertySheetPageA(&psp
);
214 memset(&psh
, 0, sizeof(psh
));
215 psh
.dwSize
= sizeof(psh
);
216 psh
.dwFlags
= PSH_USECALLBACK
;
217 psh
.pszCaption
= "test caption";
219 psh
.hwndParent
= parent
;
220 U3(psh
).phpage
= hpsp
;
221 psh
.pfnCallback
= disableowner_callback
;
223 p
= PropertySheetA(&psh
);
225 ok(p
== 0, "Expected 0, got %ld\n", p
);
226 ok(IsWindowEnabled(parent
) != 0, "parent window should be enabled\n");
227 DestroyWindow(parent
);
230 static INT_PTR CALLBACK
nav_page_proc(HWND hwnd
, UINT msg
, WPARAM wparam
, LPARAM lparam
)
235 LPNMHDR hdr
= (LPNMHDR
)lparam
;
238 active_page
= PropSheet_HwndToIndex(hdr
->hwndFrom
, hwnd
);
241 /* prevent navigation away from the fourth page */
242 if(active_page
== 3){
243 SetWindowLongPtr(hwnd
, DWLP_MSGRESULT
, TRUE
);
253 static void test_wiznavigation(void)
255 HPROPSHEETPAGE hpsp
[4];
256 PROPSHEETPAGEA psp
[4];
257 PROPSHEETHEADERA psh
;
261 BOOL hwndtoindex_supported
= TRUE
;
262 const INT nextID
= 12324;
263 const INT backID
= 12323;
265 /* create the property sheet pages */
266 memset(psp
, 0, sizeof(PROPSHEETPAGEA
) * 4);
268 psp
[0].dwSize
= sizeof(PROPSHEETPAGEA
);
269 psp
[0].hInstance
= GetModuleHandleA(NULL
);
270 U(psp
[0]).pszTemplate
= MAKEINTRESOURCE(IDD_PROP_PAGE_INTRO
);
271 psp
[0].pfnDlgProc
= nav_page_proc
;
272 hpsp
[0] = CreatePropertySheetPageA(&psp
[0]);
274 psp
[1].dwSize
= sizeof(PROPSHEETPAGEA
);
275 psp
[1].hInstance
= GetModuleHandleA(NULL
);
276 U(psp
[1]).pszTemplate
= MAKEINTRESOURCE(IDD_PROP_PAGE_EDIT
);
277 psp
[1].pfnDlgProc
= nav_page_proc
;
278 hpsp
[1] = CreatePropertySheetPageA(&psp
[1]);
280 psp
[2].dwSize
= sizeof(PROPSHEETPAGEA
);
281 psp
[2].hInstance
= GetModuleHandleA(NULL
);
282 U(psp
[2]).pszTemplate
= MAKEINTRESOURCE(IDD_PROP_PAGE_RADIO
);
283 psp
[2].pfnDlgProc
= nav_page_proc
;
284 hpsp
[2] = CreatePropertySheetPageA(&psp
[2]);
286 psp
[3].dwSize
= sizeof(PROPSHEETPAGEA
);
287 psp
[3].hInstance
= GetModuleHandleA(NULL
);
288 U(psp
[3]).pszTemplate
= MAKEINTRESOURCE(IDD_PROP_PAGE_EXIT
);
289 psp
[3].pfnDlgProc
= nav_page_proc
;
290 hpsp
[3] = CreatePropertySheetPageA(&psp
[3]);
292 /* set up the property sheet dialog */
293 memset(&psh
, 0, sizeof(psh
));
294 psh
.dwSize
= sizeof(psh
);
295 psh
.dwFlags
= PSH_MODELESS
| PSH_WIZARD
;
296 psh
.pszCaption
= "A Wizard";
298 psh
.hwndParent
= GetDesktopWindow();
299 U3(psh
).phpage
= hpsp
;
300 hdlg
= (HWND
)PropertySheetA(&psh
);
301 if (hdlg
== INVALID_HANDLE_VALUE
)
303 win_skip("comctl32 4.70 needs dwSize adjustment\n");
304 psh
.dwSize
= sizeof(psh
) - sizeof(HBITMAP
) - sizeof(HPALETTE
) - sizeof(HBITMAP
);
305 hdlg
= (HWND
)PropertySheetA(&psh
);
308 ok(active_page
== 0, "Active page should be 0. Is: %d\n", active_page
);
310 control
= GetFocus();
311 controlID
= GetWindowLongPtr(control
, GWLP_ID
);
312 ok(controlID
== nextID
, "Focus should have been set to the Next button. Expected: %d, Found: %ld\n", nextID
, controlID
);
314 /* simulate pressing the Next button */
315 SendMessage(hdlg
, PSM_PRESSBUTTON
, PSBTN_NEXT
, 0);
316 if (!active_page
) hwndtoindex_supported
= FALSE
;
317 if (hwndtoindex_supported
)
318 ok(active_page
== 1, "Active page should be 1 after pressing Next. Is: %d\n", active_page
);
320 control
= GetFocus();
321 controlID
= GetWindowLongPtr(control
, GWLP_ID
);
322 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
);
324 defidres
= SendMessage(hdlg
, DM_GETDEFID
, 0, 0);
325 ok(defidres
== MAKELRESULT(nextID
, DC_HASDEFID
), "Expected default button ID to be %d, is %d\n", nextID
, LOWORD(defidres
));
327 /* set the focus to the second edit box on this page */
328 SetFocus(GetNextDlgTabItem(hdlg
, control
, FALSE
));
330 /* press next again */
331 SendMessage(hdlg
, PSM_PRESSBUTTON
, PSBTN_NEXT
, 0);
332 if (hwndtoindex_supported
)
333 ok(active_page
== 2, "Active page should be 2 after pressing Next. Is: %d\n", active_page
);
335 control
= GetFocus();
336 controlID
= GetWindowLongPtr(control
, GWLP_ID
);
337 ok(controlID
== IDC_PS_RADIO1
, "Focus should have been set to item on third page. Expected: %d, Found %ld\n", IDC_PS_RADIO1
, controlID
);
340 SendMessage(hdlg
, PSM_PRESSBUTTON
, PSBTN_BACK
, 0);
341 if (hwndtoindex_supported
)
342 ok(active_page
== 1, "Active page should be 1 after pressing Back. Is: %d\n", active_page
);
344 control
= GetFocus();
345 controlID
= GetWindowLongPtr(control
, GWLP_ID
);
346 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
);
348 defidres
= SendMessage(hdlg
, DM_GETDEFID
, 0, 0);
349 ok(defidres
== MAKELRESULT(backID
, DC_HASDEFID
), "Expected default button ID to be %d, is %d\n", backID
, LOWORD(defidres
));
351 /* press next twice */
352 SendMessage(hdlg
, PSM_PRESSBUTTON
, PSBTN_NEXT
, 0);
353 if (hwndtoindex_supported
)
354 ok(active_page
== 2, "Active page should be 2 after pressing Next. Is: %d\n", active_page
);
355 SendMessage(hdlg
, PSM_PRESSBUTTON
, PSBTN_NEXT
, 0);
356 if (hwndtoindex_supported
)
357 ok(active_page
== 3, "Active page should be 3 after pressing Next. Is: %d\n", active_page
);
361 control
= GetFocus();
362 controlID
= GetWindowLongPtr(control
, GWLP_ID
);
363 ok(controlID
== nextID
, "Focus should have been set to the Next button. Expected: %d, Found: %ld\n", nextID
, controlID
);
365 /* try to navigate away, but shouldn't be able to */
366 SendMessage(hdlg
, PSM_PRESSBUTTON
, PSBTN_BACK
, 0);
367 ok(active_page
== 3, "Active page should still be 3 after pressing Back. Is: %d\n", active_page
);
369 defidres
= SendMessage(hdlg
, DM_GETDEFID
, 0, 0);
370 ok(defidres
== MAKELRESULT(nextID
, DC_HASDEFID
), "Expected default button ID to be %d, is %d\n", nextID
, LOWORD(defidres
));
375 static void test_buttons(void)
377 HPROPSHEETPAGE hpsp
[1];
379 PROPSHEETHEADERA psh
;
385 memset(&psp
, 0, sizeof(psp
));
386 psp
.dwSize
= sizeof(psp
);
388 psp
.hInstance
= GetModuleHandleA(NULL
);
389 U(psp
).pszTemplate
= "prop_page1";
390 U2(psp
).pszIcon
= NULL
;
391 psp
.pfnDlgProc
= page_dlg_proc
;
394 hpsp
[0] = CreatePropertySheetPageA(&psp
);
396 memset(&psh
, 0, sizeof(psh
));
397 psh
.dwSize
= sizeof(psh
);
398 psh
.dwFlags
= PSH_MODELESS
| PSH_USECALLBACK
;
399 psh
.pszCaption
= "test caption";
401 psh
.hwndParent
= GetDesktopWindow();
402 U3(psh
).phpage
= hpsp
;
403 psh
.pfnCallback
= sheet_callback
;
405 hdlg
= (HWND
)PropertySheetA(&psh
);
406 if (hdlg
== INVALID_HANDLE_VALUE
)
408 win_skip("comctl32 4.70 needs dwSize adjustment\n");
409 psh
.dwSize
= sizeof(psh
) - sizeof(HBITMAP
) - sizeof(HPALETTE
) - sizeof(HBITMAP
);
410 hdlg
= (HWND
)PropertySheetA(&psh
);
414 button
= GetDlgItem(hdlg
, IDOK
);
415 GetWindowRect(button
, &rc
);
416 prevRight
= rc
.right
;
420 button
= GetDlgItem(hdlg
, IDCANCEL
);
421 GetWindowRect(button
, &rc
);
422 ok(rc
.top
== top
, "Cancel button should have same top as OK button\n");
423 ok(rc
.left
> prevRight
, "Cancel button should be to the right of OK button\n");
424 prevRight
= rc
.right
;
426 button
= GetDlgItem(hdlg
, IDC_APPLY_BUTTON
);
427 GetWindowRect(button
, &rc
);
428 ok(rc
.top
== top
, "Apply button should have same top as OK button\n");
429 ok(rc
.left
> prevRight
, "Apply button should be to the right of Cancel button\n");
430 prevRight
= rc
.right
;
432 button
= GetDlgItem(hdlg
, IDHELP
);
433 GetWindowRect(button
, &rc
);
434 ok(rc
.top
== top
, "Help button should have same top as OK button\n");
435 ok(rc
.left
> prevRight
, "Help button should be to the right of Apply button\n");
440 static BOOL add_button_has_been_pressed
;
442 static INT_PTR CALLBACK
443 page_with_custom_default_button_dlg_proc(HWND hdlg
, UINT msg
, WPARAM wparam
, LPARAM lparam
)
448 switch(LOWORD(wparam
))
450 case IDC_PS_PUSHBUTTON1
:
451 switch(HIWORD(wparam
))
454 add_button_has_been_pressed
= TRUE
;
464 static void test_custom_default_button(void)
467 PROPSHEETPAGEA psp
[1];
468 PROPSHEETHEADERA psh
;
472 psp
[0].dwSize
= sizeof (PROPSHEETPAGEA
);
473 psp
[0].dwFlags
= PSP_USETITLE
;
474 psp
[0].hInstance
= GetModuleHandleA(NULL
);
475 U(psp
[0]).pszTemplate
= MAKEINTRESOURCE(IDD_PROP_PAGE_WITH_CUSTOM_DEFAULT_BUTTON
);
476 U2(psp
[0]).pszIcon
= NULL
;
477 psp
[0].pfnDlgProc
= page_with_custom_default_button_dlg_proc
;
478 psp
[0].pszTitle
= "Page1";
481 psh
.dwSize
= sizeof (PROPSHEETHEADERA
);
482 psh
.dwFlags
= PSH_PROPSHEETPAGE
| PSH_MODELESS
;
483 psh
.hwndParent
= GetDesktopWindow();
484 psh
.hInstance
= GetModuleHandleA(NULL
);
485 U(psh
).pszIcon
= NULL
;
486 psh
.pszCaption
= "PropertySheet1";
489 U2(psh
).nStartPage
= 0;
491 /* The goal of the test is to make sure that the Add button is pressed
492 * when the ENTER key is pressed and a different control, a combobox,
493 * has the keyboard focus. */
494 add_button_has_been_pressed
= FALSE
;
496 /* Create the modeless property sheet. */
497 hdlg
= (HWND
)PropertySheetA(&psh
);
498 ok(hdlg
!= INVALID_HANDLE_VALUE
, "Cannot create the property sheet\n");
500 /* Set the Add button as the default button. */
501 SendMessage(hdlg
, DM_SETDEFID
, (WPARAM
)IDC_PS_PUSHBUTTON1
, 0);
503 /* Make sure the default button is the Add button. */
504 result
= SendMessage(hdlg
, DM_GETDEFID
, 0, 0);
505 ok(DC_HASDEFID
== HIWORD(result
), "The property sheet does not have a default button\n");
506 ok(IDC_PS_PUSHBUTTON1
== LOWORD(result
), "The default button is not the Add button\n");
508 /* At this point, the combobox should have keyboard focus, so we press ENTER.
509 * Pull the lever, Kronk! */
510 keybd_event(VK_RETURN
, 0, 0, 0);
512 /* Process all the messages in the queue for this thread. */
513 while (PeekMessage(&msg
, NULL
, 0, 0, PM_REMOVE
))
515 if (!PropSheet_IsDialogMessage(hdlg
, &msg
))
517 TranslateMessage(&msg
);
518 DispatchMessage(&msg
);
523 ok(add_button_has_been_pressed
, "The Add button has not been pressed!\n");
528 START_TEST(propsheet
)
533 test_wiznavigation();
535 test_custom_default_button();