comctl32: Test for window messages of a property sheet with custom dialog proc.
[wine] / dlls / comctl32 / tests / propsheet.c
1 /* Unit test suite for property sheet control.
2  *
3  * Copyright 2006 Huw Davies
4  * Copyright 2009 Jan de Mooij
5  *
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.
10  *
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.
15  *
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
19  */
20
21 #include <windows.h>
22 #include <commctrl.h>
23 #include "msg.h"
24
25 #include "resources.h"
26
27 #include "wine/test.h"
28
29 static HWND parenthwnd;
30 static HWND sheethwnd;
31
32 static LONG active_page = -1;
33
34 #define IDC_APPLY_BUTTON 12321
35
36 static int CALLBACK sheet_callback(HWND hwnd, UINT msg, LPARAM lparam)
37 {
38     switch(msg)
39     {
40     case PSCB_INITIALIZED:
41       {
42         char caption[256];
43         GetWindowTextA(hwnd, caption, sizeof(caption));
44         ok(!strcmp(caption,"test caption"), "caption: %s\n", caption);
45         sheethwnd = hwnd;
46         return 0;
47       }
48     }
49     return 0;
50 }
51
52 static INT_PTR CALLBACK page_dlg_proc(HWND hwnd, UINT msg, WPARAM wparam,
53                                       LPARAM lparam)
54 {
55     switch(msg)
56     {
57     case WM_INITDIALOG:
58       {
59         HWND sheet = GetParent(hwnd);
60         char caption[256];
61         GetWindowTextA(sheet, caption, sizeof(caption));
62         ok(!strcmp(caption,"test caption"), "caption: %s\n", caption);
63         return TRUE;
64       }
65
66     case WM_NOTIFY:
67       {
68         NMHDR *nmhdr = (NMHDR *)lparam;
69         switch(nmhdr->code)
70         {
71         case PSN_APPLY:
72             return TRUE;
73         default:
74             return FALSE;
75         }
76       }
77     case WM_NCDESTROY:
78         ok(!SendMessageA(sheethwnd, PSM_INDEXTOHWND, 400, 0),"Should always be 0\n");
79         return TRUE;
80
81     default:
82         return FALSE;
83     }
84 }
85
86 static void test_title(void)
87 {
88     HPROPSHEETPAGE hpsp[1];
89     PROPSHEETPAGEA psp;
90     PROPSHEETHEADERA psh;
91     HWND hdlg;
92
93     memset(&psp, 0, sizeof(psp));
94     psp.dwSize = sizeof(psp);
95     psp.dwFlags = 0;
96     psp.hInstance = GetModuleHandleA(NULL);
97     U(psp).pszTemplate = "prop_page1";
98     U2(psp).pszIcon = NULL;
99     psp.pfnDlgProc = page_dlg_proc;
100     psp.lParam = 0;
101
102     hpsp[0] = CreatePropertySheetPageA(&psp);
103
104     memset(&psh, 0, sizeof(psh));
105     psh.dwSize = sizeof(psh);
106     psh.dwFlags = PSH_MODELESS | PSH_USECALLBACK;
107     psh.pszCaption = "test caption";
108     psh.nPages = 1;
109     psh.hwndParent = GetDesktopWindow();
110     U3(psh).phpage = hpsp;
111     psh.pfnCallback = sheet_callback;
112
113     hdlg = (HWND)PropertySheetA(&psh);
114     if (hdlg == INVALID_HANDLE_VALUE)
115     {
116         win_skip("comctl32 4.70 needs dwSize adjustment\n");
117         psh.dwSize = sizeof(psh) - sizeof(HBITMAP) - sizeof(HPALETTE) - sizeof(HBITMAP);
118         hdlg = (HWND)PropertySheetA(&psh);
119     }
120     DestroyWindow(hdlg);
121 }
122
123 static void test_nopage(void)
124 {
125     HPROPSHEETPAGE hpsp[1];
126     PROPSHEETPAGEA psp;
127     PROPSHEETHEADERA psh;
128     HWND hdlg;
129
130     memset(&psp, 0, sizeof(psp));
131     psp.dwSize = sizeof(psp);
132     psp.dwFlags = 0;
133     psp.hInstance = GetModuleHandleA(NULL);
134     U(psp).pszTemplate = "prop_page1";
135     U2(psp).pszIcon = NULL;
136     psp.pfnDlgProc = page_dlg_proc;
137     psp.lParam = 0;
138
139     hpsp[0] = CreatePropertySheetPageA(&psp);
140
141     memset(&psh, 0, sizeof(psh));
142     psh.dwSize = sizeof(psh);
143     psh.dwFlags = PSH_MODELESS | PSH_USECALLBACK;
144     psh.pszCaption = "test caption";
145     psh.nPages = 1;
146     psh.hwndParent = GetDesktopWindow();
147     U3(psh).phpage = hpsp;
148     psh.pfnCallback = sheet_callback;
149
150     hdlg = (HWND)PropertySheetA(&psh);
151     if (hdlg == INVALID_HANDLE_VALUE)
152     {
153         win_skip("comctl32 4.70 needs dwSize adjustment\n");
154         psh.dwSize = sizeof(psh) - sizeof(HBITMAP) - sizeof(HPALETTE) - sizeof(HBITMAP);
155         hdlg = (HWND)PropertySheetA(&psh);
156     }
157     ShowWindow(hdlg,SW_NORMAL);
158     SendMessage(hdlg, PSM_REMOVEPAGE, 0, 0);
159     RedrawWindow(hdlg,NULL,NULL,RDW_UPDATENOW|RDW_ERASENOW);
160     DestroyWindow(hdlg);
161 }
162
163 static int CALLBACK disableowner_callback(HWND hwnd, UINT msg, LPARAM lparam)
164 {
165     switch(msg)
166     {
167     case PSCB_INITIALIZED:
168       {
169         ok(IsWindowEnabled(parenthwnd) == 0, "parent window should be disabled\n");
170         PostQuitMessage(0);
171         return FALSE;
172       }
173     }
174     return FALSE;
175 }
176
177 static void register_parent_wnd_class(void)
178 {
179     WNDCLASSA cls;
180
181     cls.style = 0;
182     cls.lpfnWndProc = DefWindowProcA;
183     cls.cbClsExtra = 0;
184     cls.cbWndExtra = 0;
185     cls.hInstance = GetModuleHandleA(NULL);
186     cls.hIcon = 0;
187     cls.hCursor = LoadCursorA(0, IDC_ARROW);
188     cls.hbrBackground = GetStockObject(WHITE_BRUSH);
189     cls.lpszMenuName = NULL;
190     cls.lpszClassName = "parent class";
191     RegisterClassA(&cls);
192 }
193
194 static void test_disableowner(void)
195 {
196     HPROPSHEETPAGE hpsp[1];
197     PROPSHEETPAGEA psp;
198     PROPSHEETHEADERA psh;
199     INT_PTR p;
200
201     register_parent_wnd_class();
202     parenthwnd = CreateWindowA("parent class", "", WS_CAPTION | WS_SYSMENU | WS_VISIBLE, 100, 100, 100, 100, GetDesktopWindow(), NULL, GetModuleHandleA(NULL), 0);
203
204     memset(&psp, 0, sizeof(psp));
205     psp.dwSize = sizeof(psp);
206     psp.dwFlags = 0;
207     psp.hInstance = GetModuleHandleA(NULL);
208     U(psp).pszTemplate = "prop_page1";
209     U2(psp).pszIcon = NULL;
210     psp.pfnDlgProc = NULL;
211     psp.lParam = 0;
212
213     hpsp[0] = CreatePropertySheetPageA(&psp);
214
215     memset(&psh, 0, sizeof(psh));
216     psh.dwSize = sizeof(psh);
217     psh.dwFlags = PSH_USECALLBACK;
218     psh.pszCaption = "test caption";
219     psh.nPages = 1;
220     psh.hwndParent = parenthwnd;
221     U3(psh).phpage = hpsp;
222     psh.pfnCallback = disableowner_callback;
223
224     p = PropertySheetA(&psh);
225     todo_wine
226     ok(p == 0, "Expected 0, got %ld\n", p);
227     ok(IsWindowEnabled(parenthwnd) != 0, "parent window should be enabled\n");
228     DestroyWindow(parenthwnd);
229 }
230
231 static INT_PTR CALLBACK nav_page_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
232 {
233     switch(msg){
234     case WM_NOTIFY:
235         {
236             LPNMHDR hdr = (LPNMHDR)lparam;
237             switch(hdr->code){
238             case PSN_SETACTIVE:
239                 active_page = PropSheet_HwndToIndex(hdr->hwndFrom, hwnd);
240                 return TRUE;
241             case PSN_KILLACTIVE:
242                 /* prevent navigation away from the fourth page */
243                 if(active_page == 3){
244                     SetWindowLongPtr(hwnd, DWLP_MSGRESULT, TRUE);
245                     return TRUE;
246                 }
247             }
248             break;
249         }
250     }
251     return FALSE;
252 }
253
254 static void test_wiznavigation(void)
255 {
256     HPROPSHEETPAGE hpsp[4];
257     PROPSHEETPAGEA psp[4];
258     PROPSHEETHEADERA psh;
259     HWND hdlg, control;
260     LONG_PTR controlID;
261     LRESULT defidres;
262     BOOL hwndtoindex_supported = TRUE;
263     const INT nextID = 12324;
264     const INT backID = 12323;
265
266     /* create the property sheet pages */
267     memset(psp, 0, sizeof(PROPSHEETPAGEA) * 4);
268
269     psp[0].dwSize = sizeof(PROPSHEETPAGEA);
270     psp[0].hInstance = GetModuleHandleA(NULL);
271     U(psp[0]).pszTemplate = MAKEINTRESOURCE(IDD_PROP_PAGE_INTRO);
272     psp[0].pfnDlgProc = nav_page_proc;
273     hpsp[0] = CreatePropertySheetPageA(&psp[0]);
274
275     psp[1].dwSize = sizeof(PROPSHEETPAGEA);
276     psp[1].hInstance = GetModuleHandleA(NULL);
277     U(psp[1]).pszTemplate = MAKEINTRESOURCE(IDD_PROP_PAGE_EDIT);
278     psp[1].pfnDlgProc = nav_page_proc;
279     hpsp[1] = CreatePropertySheetPageA(&psp[1]);
280
281     psp[2].dwSize = sizeof(PROPSHEETPAGEA);
282     psp[2].hInstance = GetModuleHandleA(NULL);
283     U(psp[2]).pszTemplate = MAKEINTRESOURCE(IDD_PROP_PAGE_RADIO);
284     psp[2].pfnDlgProc = nav_page_proc;
285     hpsp[2] = CreatePropertySheetPageA(&psp[2]);
286
287     psp[3].dwSize = sizeof(PROPSHEETPAGEA);
288     psp[3].hInstance = GetModuleHandleA(NULL);
289     U(psp[3]).pszTemplate = MAKEINTRESOURCE(IDD_PROP_PAGE_EXIT);
290     psp[3].pfnDlgProc = nav_page_proc;
291     hpsp[3] = CreatePropertySheetPageA(&psp[3]);
292
293     /* set up the property sheet dialog */
294     memset(&psh, 0, sizeof(psh));
295     psh.dwSize = sizeof(psh);
296     psh.dwFlags = PSH_MODELESS | PSH_WIZARD;
297     psh.pszCaption = "A Wizard";
298     psh.nPages = 4;
299     psh.hwndParent = GetDesktopWindow();
300     U3(psh).phpage = hpsp;
301     hdlg = (HWND)PropertySheetA(&psh);
302     if (hdlg == INVALID_HANDLE_VALUE)
303     {
304         win_skip("comctl32 4.70 needs dwSize adjustment\n");
305         psh.dwSize = sizeof(psh) - sizeof(HBITMAP) - sizeof(HPALETTE) - sizeof(HBITMAP);
306         hdlg = (HWND)PropertySheetA(&psh);
307     }
308
309     ok(active_page == 0, "Active page should be 0. Is: %d\n", active_page);
310
311     control = GetFocus();
312     controlID = GetWindowLongPtr(control, GWLP_ID);
313     ok(controlID == nextID, "Focus should have been set to the Next button. Expected: %d, Found: %ld\n", nextID, controlID);
314
315     /* simulate pressing the Next button */
316     SendMessage(hdlg, PSM_PRESSBUTTON, PSBTN_NEXT, 0);
317     if (!active_page) hwndtoindex_supported = FALSE;
318     if (hwndtoindex_supported)
319         ok(active_page == 1, "Active page should be 1 after pressing Next. Is: %d\n", active_page);
320
321     control = GetFocus();
322     controlID = GetWindowLongPtr(control, GWLP_ID);
323     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
325     defidres = SendMessage(hdlg, DM_GETDEFID, 0, 0);
326     ok(defidres == MAKELRESULT(nextID, DC_HASDEFID), "Expected default button ID to be %d, is %d\n", nextID, LOWORD(defidres));
327
328     /* set the focus to the second edit box on this page */
329     SetFocus(GetNextDlgTabItem(hdlg, control, FALSE));
330
331     /* press next again */
332     SendMessage(hdlg, PSM_PRESSBUTTON, PSBTN_NEXT, 0);
333     if (hwndtoindex_supported)
334         ok(active_page == 2, "Active page should be 2 after pressing Next. Is: %d\n", active_page);
335
336     control = GetFocus();
337     controlID = GetWindowLongPtr(control, GWLP_ID);
338     ok(controlID == IDC_PS_RADIO1, "Focus should have been set to item on third page. Expected: %d, Found %ld\n", IDC_PS_RADIO1, controlID);
339
340     /* back button */
341     SendMessage(hdlg, PSM_PRESSBUTTON, PSBTN_BACK, 0);
342     if (hwndtoindex_supported)
343         ok(active_page == 1, "Active page should be 1 after pressing Back. Is: %d\n", active_page);
344
345     control = GetFocus();
346     controlID = GetWindowLongPtr(control, GWLP_ID);
347     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
349     defidres = SendMessage(hdlg, DM_GETDEFID, 0, 0);
350     ok(defidres == MAKELRESULT(backID, DC_HASDEFID), "Expected default button ID to be %d, is %d\n", backID, LOWORD(defidres));
351
352     /* press next twice */
353     SendMessage(hdlg, PSM_PRESSBUTTON, PSBTN_NEXT, 0);
354     if (hwndtoindex_supported)
355         ok(active_page == 2, "Active page should be 2 after pressing Next. Is: %d\n", active_page);
356     SendMessage(hdlg, PSM_PRESSBUTTON, PSBTN_NEXT, 0);
357     if (hwndtoindex_supported)
358         ok(active_page == 3, "Active page should be 3 after pressing Next. Is: %d\n", active_page);
359     else
360         active_page = 3;
361
362     control = GetFocus();
363     controlID = GetWindowLongPtr(control, GWLP_ID);
364     ok(controlID == nextID, "Focus should have been set to the Next button. Expected: %d, Found: %ld\n", nextID, controlID);
365
366     /* try to navigate away, but shouldn't be able to */
367     SendMessage(hdlg, PSM_PRESSBUTTON, PSBTN_BACK, 0);
368     ok(active_page == 3, "Active page should still be 3 after pressing Back. Is: %d\n", active_page);
369
370     defidres = SendMessage(hdlg, DM_GETDEFID, 0, 0);
371     ok(defidres == MAKELRESULT(nextID, DC_HASDEFID), "Expected default button ID to be %d, is %d\n", nextID, LOWORD(defidres));
372
373     DestroyWindow(hdlg);
374 }
375
376 static void test_buttons(void)
377 {
378     HPROPSHEETPAGE hpsp[1];
379     PROPSHEETPAGEA psp;
380     PROPSHEETHEADERA psh;
381     HWND hdlg;
382     HWND button;
383     RECT rc;
384     int prevRight, top;
385
386     memset(&psp, 0, sizeof(psp));
387     psp.dwSize = sizeof(psp);
388     psp.dwFlags = 0;
389     psp.hInstance = GetModuleHandleA(NULL);
390     U(psp).pszTemplate = "prop_page1";
391     U2(psp).pszIcon = NULL;
392     psp.pfnDlgProc = page_dlg_proc;
393     psp.lParam = 0;
394
395     hpsp[0] = CreatePropertySheetPageA(&psp);
396
397     memset(&psh, 0, sizeof(psh));
398     psh.dwSize = sizeof(psh);
399     psh.dwFlags = PSH_MODELESS | PSH_USECALLBACK;
400     psh.pszCaption = "test caption";
401     psh.nPages = 1;
402     psh.hwndParent = GetDesktopWindow();
403     U3(psh).phpage = hpsp;
404     psh.pfnCallback = sheet_callback;
405
406     hdlg = (HWND)PropertySheetA(&psh);
407     if (hdlg == INVALID_HANDLE_VALUE)
408     {
409         win_skip("comctl32 4.70 needs dwSize adjustment\n");
410         psh.dwSize = sizeof(psh) - sizeof(HBITMAP) - sizeof(HPALETTE) - sizeof(HBITMAP);
411         hdlg = (HWND)PropertySheetA(&psh);
412     }
413
414     /* OK button */
415     button = GetDlgItem(hdlg, IDOK);
416     GetWindowRect(button, &rc);
417     prevRight = rc.right;
418     top = rc.top;
419
420     /* Cancel button */
421     button = GetDlgItem(hdlg, IDCANCEL);
422     GetWindowRect(button, &rc);
423     ok(rc.top == top, "Cancel button should have same top as OK button\n");
424     ok(rc.left > prevRight, "Cancel button should be to the right of OK button\n");
425     prevRight = rc.right;
426
427     button = GetDlgItem(hdlg, IDC_APPLY_BUTTON);
428     GetWindowRect(button, &rc);
429     ok(rc.top == top, "Apply button should have same top as OK button\n");
430     ok(rc.left > prevRight, "Apply button should be to the right of Cancel button\n");
431     prevRight = rc.right;
432
433     button = GetDlgItem(hdlg, IDHELP);
434     GetWindowRect(button, &rc);
435     ok(rc.top == top, "Help button should have same top as OK button\n");
436     ok(rc.left > prevRight, "Help button should be to the right of Apply button\n");
437
438     DestroyWindow(hdlg);
439 }
440
441 static BOOL add_button_has_been_pressed;
442
443 static INT_PTR CALLBACK
444 page_with_custom_default_button_dlg_proc(HWND hdlg, UINT msg, WPARAM wparam, LPARAM lparam)
445 {
446     switch (msg)
447     {
448     case WM_COMMAND:
449         switch(LOWORD(wparam))
450         {
451         case IDC_PS_PUSHBUTTON1:
452             switch(HIWORD(wparam))
453             {
454             case BN_CLICKED:
455                 add_button_has_been_pressed = TRUE;
456                 return TRUE;
457             }
458             break;
459         }
460         break;
461     }
462     return FALSE;
463 }
464
465 static void test_custom_default_button(void)
466 {
467     HWND hdlg;
468     PROPSHEETPAGEA psp[1];
469     PROPSHEETHEADERA psh;
470     MSG msg;
471     LRESULT result;
472
473     psp[0].dwSize = sizeof (PROPSHEETPAGEA);
474     psp[0].dwFlags = PSP_USETITLE;
475     psp[0].hInstance = GetModuleHandleA(NULL);
476     U(psp[0]).pszTemplate = MAKEINTRESOURCE(IDD_PROP_PAGE_WITH_CUSTOM_DEFAULT_BUTTON);
477     U2(psp[0]).pszIcon = NULL;
478     psp[0].pfnDlgProc = page_with_custom_default_button_dlg_proc;
479     psp[0].pszTitle = "Page1";
480     psp[0].lParam = 0;
481
482     psh.dwSize = sizeof (PROPSHEETHEADERA);
483     psh.dwFlags = PSH_PROPSHEETPAGE | PSH_MODELESS;
484     psh.hwndParent = GetDesktopWindow();
485     psh.hInstance = GetModuleHandleA(NULL);
486     U(psh).pszIcon = NULL;
487     psh.pszCaption =  "PropertySheet1";
488     psh.nPages = 1;
489     U3(psh).ppsp = psp;
490     U2(psh).nStartPage = 0;
491
492     /* The goal of the test is to make sure that the Add button is pressed
493      * when the ENTER key is pressed and a different control, a combobox,
494      * has the keyboard focus. */
495     add_button_has_been_pressed = FALSE;
496
497     /* Create the modeless property sheet. */
498     hdlg = (HWND)PropertySheetA(&psh);
499     ok(hdlg != INVALID_HANDLE_VALUE, "Cannot create the property sheet\n");
500
501     /* Set the Add button as the default button. */
502     SendMessage(hdlg, DM_SETDEFID, (WPARAM)IDC_PS_PUSHBUTTON1, 0);
503
504     /* Make sure the default button is the Add button. */
505     result = SendMessage(hdlg, DM_GETDEFID, 0, 0);
506     ok(DC_HASDEFID == HIWORD(result), "The property sheet does not have a default button\n");
507     ok(IDC_PS_PUSHBUTTON1 == LOWORD(result), "The default button is not the Add button\n");
508
509     /* At this point, the combobox should have keyboard focus, so we press ENTER.
510      * Pull the lever, Kronk! */
511     keybd_event(VK_RETURN, 0, 0, 0);
512
513     /* Process all the messages in the queue for this thread. */
514     while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
515     {
516         if (!PropSheet_IsDialogMessage(hdlg, &msg))
517         {
518             TranslateMessage(&msg);
519             DispatchMessage(&msg);
520         }
521     }
522
523     todo_wine
524     ok(add_button_has_been_pressed, "The Add button has not been pressed!\n");
525
526     DestroyWindow(hdlg);
527 }
528
529 #define RECEIVER_SHEET_CALLBACK 0
530 #define RECEIVER_SHEET_WINPROC  1
531 #define RECEIVER_PAGE           2
532
533 #define NUM_MSG_SEQUENCES   1
534 #define PROPSHEET_SEQ_INDEX 0
535
536 static struct msg_sequence *sequences[NUM_MSG_SEQUENCES];
537 static WNDPROC oldWndProc;
538
539 static const struct message property_sheet_seq[] = {
540     { PSCB_PRECREATE, sent|id, 0, 0, RECEIVER_SHEET_CALLBACK },
541     { PSCB_INITIALIZED, sent|id, 0, 0, RECEIVER_SHEET_CALLBACK },
542     { WM_WINDOWPOSCHANGING, sent|id, 0, 0, RECEIVER_SHEET_WINPROC },
543     /*{ WM_NCCALCSIZE, sent|id, 0, 0, RECEIVER_SHEET_WINPROC },*/
544     { WM_WINDOWPOSCHANGED, sent|id, 0, 0, RECEIVER_SHEET_WINPROC },
545     { WM_MOVE, sent|id, 0, 0, RECEIVER_SHEET_WINPROC },
546     { WM_SIZE, sent|id, 0, 0, RECEIVER_SHEET_WINPROC },
547     /*{ WM_GETTEXT, sent|id, 0, 0, RECEIVER_SHEET_WINPROC },
548     { WM_GETICON, sent|id, 0, 0, RECEIVER_SHEET_WINPROC },
549     { WM_GETICON, sent|id, 0, 0, RECEIVER_SHEET_WINPROC },
550     { WM_GETICON, sent|id, 0, 0, RECEIVER_SHEET_WINPROC },
551     { WM_NCCALCSIZE, sent|id|optional, 0, 0, RECEIVER_SHEET_WINPROC },
552     { DM_REPOSITION, sent|id, 0, 0, RECEIVER_SHEET_WINPROC },*/
553     { WM_WINDOWPOSCHANGING, sent|id, 0, 0, RECEIVER_SHEET_WINPROC },
554     { WM_WINDOWPOSCHANGING, sent|id, 0, 0, RECEIVER_SHEET_WINPROC },
555     { WM_ACTIVATEAPP, sent|id, 0, 0, RECEIVER_SHEET_WINPROC },
556     /*{ WM_NCACTIVATE, sent|id, 0, 0, RECEIVER_SHEET_WINPROC },
557     { WM_GETTEXT, sent|id, 0, 0, RECEIVER_SHEET_WINPROC },
558     { WM_GETICON, sent|id, 0, 0, RECEIVER_SHEET_WINPROC },
559     { WM_GETICON, sent|id, 0, 0, RECEIVER_SHEET_WINPROC },
560     { WM_GETICON, sent|id, 0, 0, RECEIVER_SHEET_WINPROC },
561     { WM_GETTEXT, sent|id, 0, 0, RECEIVER_SHEET_WINPROC },*/
562     { WM_ACTIVATE, sent|id, 0, 0, RECEIVER_SHEET_WINPROC },
563     /*{ WM_IME_SETCONTEXT, sent|id, 0, 0, RECEIVER_SHEET_WINPROC },
564     { WM_IME_NOTIFY, sent|id, 0, 0, RECEIVER_SHEET_WINPROC },*/
565     { WM_SETFOCUS, sent|id, 0, 0, RECEIVER_SHEET_WINPROC },
566     { WM_KILLFOCUS, sent|id, 0, 0, RECEIVER_SHEET_WINPROC },
567     /*{ WM_IME_SETCONTEXT, sent|id, 0, 0, RECEIVER_SHEET_WINPROC },*/
568     { WM_PARENTNOTIFY, sent|id, 0, 0, RECEIVER_SHEET_WINPROC },
569     { WM_INITDIALOG, sent|id, 0, 0, RECEIVER_PAGE },
570     { WM_WINDOWPOSCHANGING, sent|id, 0, 0, RECEIVER_PAGE },
571     /*{ WM_NCCALCSIZE, sent|id, 0, 0, RECEIVER_PAGE },*/
572     { WM_CHILDACTIVATE, sent|id, 0, 0, RECEIVER_PAGE },
573     { WM_WINDOWPOSCHANGED, sent|id, 0, 0, RECEIVER_PAGE },
574     { WM_MOVE, sent|id, 0, 0, RECEIVER_PAGE },
575     { WM_SIZE, sent|id, 0, 0, RECEIVER_PAGE },
576     { WM_NOTIFY, sent|id, 0, 0, RECEIVER_PAGE },
577     { WM_STYLECHANGING, sent|id|optional, 0, 0, RECEIVER_SHEET_WINPROC },
578     { WM_STYLECHANGED, sent|id|optional, 0, 0, RECEIVER_SHEET_WINPROC },
579     /*{ WM_GETTEXT, sent|id, 0, 0, RECEIVER_SHEET_WINPROC },
580     { WM_GETICON, sent|id, 0, 0, RECEIVER_SHEET_WINPROC },
581     { WM_GETICON, sent|id, 0, 0, RECEIVER_SHEET_WINPROC },
582     { WM_GETICON, sent|id, 0, 0, RECEIVER_SHEET_WINPROC },*/
583     { WM_SETTEXT, sent|id, 0, 0, RECEIVER_SHEET_WINPROC },
584     { WM_SHOWWINDOW, sent|id, 0, 0, RECEIVER_PAGE },
585     /*{ 0x00000401, sent|id, 0, 0, RECEIVER_SHEET_WINPROC },
586     { 0x00000400, sent|id, 0, 0, RECEIVER_SHEET_WINPROC },*/
587     { WM_CHANGEUISTATE, sent|id|optional, 0, 0, RECEIVER_SHEET_WINPROC },
588     { WM_UPDATEUISTATE, sent|id|optional, 0, 0, RECEIVER_SHEET_WINPROC },
589     { WM_UPDATEUISTATE, sent|id|optional, 0, 0, RECEIVER_PAGE },
590     { WM_SHOWWINDOW, sent|id, 0, 0, RECEIVER_SHEET_WINPROC },
591     { WM_WINDOWPOSCHANGING, sent|id, 0, 0, RECEIVER_SHEET_WINPROC },
592     /*{ WM_NCPAINT, sent|id, 0, 0, RECEIVER_SHEET_WINPROC },
593     { WM_GETICON, sent|id, 0, 0, RECEIVER_SHEET_WINPROC },
594     { WM_GETICON, sent|id, 0, 0, RECEIVER_SHEET_WINPROC },
595     { WM_GETICON, sent|id, 0, 0, RECEIVER_SHEET_WINPROC },
596     { WM_ERASEBKGND, sent|id, 0, 0, RECEIVER_SHEET_WINPROC },*/
597     { WM_CTLCOLORDLG, sent|id, 0, 0, RECEIVER_SHEET_WINPROC },
598     { WM_WINDOWPOSCHANGED, sent|id, 0, 0, RECEIVER_SHEET_WINPROC },
599     /*{ WM_GETICON, sent|id, 0, 0, RECEIVER_SHEET_WINPROC },
600     { WM_GETICON, sent|id, 0, 0, RECEIVER_SHEET_WINPROC },
601     { WM_GETICON, sent|id, 0, 0, RECEIVER_SHEET_WINPROC },
602     { WM_PAINT, sent|id, 0, 0, RECEIVER_SHEET_WINPROC },
603     { WM_PAINT, sent|id, 0, 0, RECEIVER_PAGE },
604     { WM_NCPAINT, sent|id, 0, 0, RECEIVER_PAGE },
605     { WM_ERASEBKGND, sent|id, 0, 0, RECEIVER_PAGE },*/
606     { WM_CTLCOLORDLG, sent|id, 0, 0, RECEIVER_PAGE },
607     { WM_CTLCOLORSTATIC, sent|id, 0, 0, RECEIVER_PAGE },
608     { WM_CTLCOLORSTATIC, sent|id, 0, 0, RECEIVER_SHEET_WINPROC },
609     { WM_CTLCOLORBTN, sent|id, 0, 0, RECEIVER_SHEET_WINPROC },
610     { WM_CTLCOLORBTN, sent|id, 0, 0, RECEIVER_SHEET_WINPROC },
611     { WM_CTLCOLORBTN, sent|id, 0, 0, RECEIVER_SHEET_WINPROC },
612     /*{ WM_GETICON, sent|id, 0, 0, RECEIVER_SHEET_WINPROC },
613     { WM_GETICON, sent|id, 0, 0, RECEIVER_SHEET_WINPROC },
614     { WM_GETICON, sent|id, 0, 0, RECEIVER_SHEET_WINPROC },*/
615     { WM_COMMAND, sent|id|optional, 0, 0, RECEIVER_SHEET_WINPROC },
616     { WM_NOTIFY, sent|id|optional, 0, 0, RECEIVER_PAGE },
617     { WM_NOTIFY, sent|id|optional, 0, 0, RECEIVER_PAGE },
618     { WM_WINDOWPOSCHANGING, sent|id|optional, 0, 0, RECEIVER_SHEET_WINPROC },
619     { WM_WINDOWPOSCHANGED, sent|id|optional, 0, 0, RECEIVER_SHEET_WINPROC },
620     /*{ WM_NCACTIVATE, sent|id, 0, 0, RECEIVER_SHEET_WINPROC },
621     { WM_GETICON, sent|id, 0, 0, RECEIVER_SHEET_WINPROC },
622     { WM_GETICON, sent|id, 0, 0, RECEIVER_SHEET_WINPROC },
623     { WM_GETICON, sent|id, 0, 0, RECEIVER_SHEET_WINPROC },*/
624     { WM_ACTIVATE, sent|id, 0, 0, RECEIVER_SHEET_WINPROC },
625     { WM_ACTIVATE, sent|id, 0, 0, RECEIVER_PAGE },
626     { WM_ACTIVATEAPP, sent|id, 0, 0, RECEIVER_SHEET_WINPROC },
627     { WM_ACTIVATEAPP, sent|id, 0, 0, RECEIVER_PAGE },
628     { WM_DESTROY, sent|id, 0, 0, RECEIVER_SHEET_WINPROC },
629     { WM_DESTROY, sent|id, 0, 0, RECEIVER_PAGE },
630     /*{ WM_NCDESTROY, sent|id, 0, 0, RECEIVER_PAGE },
631     { WM_NCDESTROY, sent|id, 0, 0, RECEIVER_SHEET_WINPROC },*/
632     { 0 }
633 };
634
635 static void save_message(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam, INT receiver)
636 {
637     struct message msg;
638
639     if (message < WM_USER &&
640         message != WM_GETICON &&
641         message != WM_GETTEXT &&
642         message != WM_IME_SETCONTEXT &&
643         message != WM_IME_NOTIFY &&
644         message != WM_PAINT &&
645         message != WM_ERASEBKGND &&
646         message != WM_SETCURSOR &&
647         (message < WM_NCCREATE || message > WM_NCMBUTTONDBLCLK) &&
648         (message < WM_MOUSEFIRST || message > WM_MOUSEHWHEEL) &&
649         message != 0x90)
650     {
651         /*trace("check_message: %04x, %04x\n", message, receiver);*/
652
653         msg.message = message;
654         msg.flags = sent|wparam|lparam|id;
655         msg.wParam = wParam;
656         msg.lParam = lParam;
657         msg.id = receiver;
658         add_message(sequences, PROPSHEET_SEQ_INDEX, &msg);
659     }
660 }
661
662 static LRESULT CALLBACK sheet_callback_messages_proc (HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
663 {
664     save_message(hwnd, msg, wParam, lParam, RECEIVER_SHEET_WINPROC);
665
666     switch (msg)
667     {
668     case WM_CTLCOLORSTATIC:
669         keybd_event(VK_ESCAPE, 0, 0, 0);
670         break;
671     }
672
673     return CallWindowProc (oldWndProc, hwnd, msg, wParam, lParam);
674 }
675
676 static int CALLBACK sheet_callback_messages(HWND hwnd, UINT msg, LPARAM lParam)
677 {
678     save_message(hwnd, msg, (WPARAM)NULL, lParam, RECEIVER_SHEET_CALLBACK);
679
680     switch (msg)
681     {
682     case PSCB_INITIALIZED:
683         oldWndProc = (WNDPROC)GetWindowLongPtr (hwnd, GWLP_WNDPROC);
684         SetWindowLongPtr (hwnd, GWLP_WNDPROC, (LONG_PTR)&sheet_callback_messages_proc);
685         return TRUE;
686     }
687
688     return TRUE;
689 }
690
691 static INT_PTR CALLBACK page_dlg_proc_messages(HWND hwnd, UINT msg, WPARAM wParam,
692                                                LPARAM lParam)
693 {
694     save_message(hwnd, msg, wParam, lParam, RECEIVER_PAGE);
695
696     return FALSE;
697 }
698
699 static void test_messages(void)
700 {
701     HPROPSHEETPAGE hpsp[1];
702     PROPSHEETPAGEA psp;
703     PROPSHEETHEADERA psh;
704     HWND hdlg;
705
706     init_msg_sequences(sequences, NUM_MSG_SEQUENCES);
707
708     memset(&psp, 0, sizeof(psp));
709     psp.dwSize = sizeof(psp);
710     psp.dwFlags = 0;
711     psp.hInstance = GetModuleHandleA(NULL);
712     U(psp).pszTemplate = MAKEINTRESOURCE(IDD_PROP_PAGE_MESSAGE_TEST);
713     U2(psp).pszIcon = NULL;
714     psp.pfnDlgProc = page_dlg_proc_messages;
715     psp.lParam = 0;
716
717     hpsp[0] = CreatePropertySheetPageA(&psp);
718
719     memset(&psh, 0, sizeof(psh));
720     psh.dwSize = sizeof(psh);
721     psh.dwFlags = PSH_NOAPPLYNOW | PSH_WIZARD | PSH_USECALLBACK
722                   /*| PSH_MODELESS */ | PSH_USEICONID;
723     psh.pszCaption = "test caption";
724     psh.nPages = 1;
725     psh.hwndParent = GetDesktopWindow();
726     U3(psh).phpage = hpsp;
727     psh.pfnCallback = sheet_callback_messages;
728
729     hdlg = (HWND)PropertySheetA(&psh);
730     if (hdlg == INVALID_HANDLE_VALUE)
731     {
732         win_skip("comctl32 4.70 needs dwSize adjustment\n");
733         psh.dwSize = sizeof(psh) - sizeof(HBITMAP) - sizeof(HPALETTE) - sizeof(HBITMAP);
734         hdlg = (HWND)PropertySheetA(&psh);
735     }
736     ShowWindow(hdlg,SW_NORMAL);
737
738     ok_sequence(sequences, PROPSHEET_SEQ_INDEX, property_sheet_seq, "property sheet with custom window proc", TRUE);
739
740     DestroyWindow(hdlg);
741 }
742
743 START_TEST(propsheet)
744 {
745     test_title();
746     test_nopage();
747     test_disableowner();
748     test_wiznavigation();
749     test_buttons();
750     test_custom_default_button();
751     test_messages();
752 }