4 * Copyright 1998 Francis Beaudet
5 * Copyright 1999 Thuy Nguyen
9 * - Unicode property sheets
18 #include "debugtools.h"
22 /******************************************************************************
34 typedef struct tagPropPageInfo
36 HPROPSHEETPAGE hpage
; /* to keep track of pages not passed to PropertySheet */
45 typedef struct tagPropSheetInfo
48 PROPSHEETHEADERA ppshheader
;
49 LPSTR strPropertiesFor
;
59 PropPageInfo
* proppage
;
64 HIMAGELIST hImageList
;
73 /******************************************************************************
74 * Defines and global variables
77 const char * PropSheetInfoStr
= "PropertySheetInfo";
79 #define MAX_CAPTION_LENGTH 255
80 #define MAX_TABTEXT_LENGTH 255
81 #define MAX_BUTTONTEXT_LENGTH 64
83 /******************************************************************************
86 static BOOL
PROPSHEET_CreateDialog(PropSheetInfo
* psInfo
);
87 static BOOL
PROPSHEET_SizeMismatch(HWND hwndDlg
, PropSheetInfo
* psInfo
);
88 static BOOL
PROPSHEET_AdjustSize(HWND hwndDlg
, PropSheetInfo
* psInfo
);
89 static BOOL
PROPSHEET_AdjustButtons(HWND hwndParent
, PropSheetInfo
* psInfo
);
90 static BOOL
PROPSHEET_CollectSheetInfo(LPCPROPSHEETHEADERA lppsh
,
91 PropSheetInfo
* psInfo
);
92 static BOOL
PROPSHEET_CollectPageInfo(LPCPROPSHEETPAGEA lppsp
,
93 PropSheetInfo
* psInfo
,
95 static BOOL
PROPSHEET_CreateTabControl(HWND hwndParent
,
96 PropSheetInfo
* psInfo
);
97 static BOOL
PROPSHEET_CreatePage(HWND hwndParent
, int index
,
98 const PropSheetInfo
* psInfo
,
99 LPCPROPSHEETPAGEA ppshpage
);
100 static BOOL
PROPSHEET_ShowPage(HWND hwndDlg
, int index
, PropSheetInfo
* psInfo
);
101 static PADDING_INFO
PROPSHEET_GetPaddingInfo(HWND hwndDlg
);
102 static BOOL
PROPSHEET_Back(HWND hwndDlg
);
103 static BOOL
PROPSHEET_Next(HWND hwndDlg
);
104 static BOOL
PROPSHEET_Finish(HWND hwndDlg
);
105 static BOOL
PROPSHEET_Apply(HWND hwndDlg
, LPARAM lParam
);
106 static void PROPSHEET_Cancel(HWND hwndDlg
, LPARAM lParam
);
107 static void PROPSHEET_Help(HWND hwndDlg
);
108 static void PROPSHEET_Changed(HWND hwndDlg
, HWND hwndDirtyPage
);
109 static void PROPSHEET_UnChanged(HWND hwndDlg
, HWND hwndCleanPage
);
110 static void PROPSHEET_PressButton(HWND hwndDlg
, int buttonID
);
111 static void PROPSHEET_SetFinishTextA(HWND hwndDlg
, LPCSTR lpszText
);
112 static void PROPSHEET_SetTitleA(HWND hwndDlg
, DWORD dwStyle
, LPCSTR lpszText
);
113 static BOOL
PROPSHEET_CanSetCurSel(HWND hwndDlg
);
114 static BOOL
PROPSHEET_SetCurSel(HWND hwndDlg
,
117 HPROPSHEETPAGE hpage
);
118 static LRESULT
PROPSHEET_QuerySiblings(HWND hwndDlg
,
119 WPARAM wParam
, LPARAM lParam
);
120 static BOOL
PROPSHEET_AddPage(HWND hwndDlg
,
121 HPROPSHEETPAGE hpage
);
123 static BOOL
PROPSHEET_RemovePage(HWND hwndDlg
,
125 HPROPSHEETPAGE hpage
);
126 static void PROPSHEET_CleanUp();
127 static int PROPSHEET_GetPageIndex(HPROPSHEETPAGE hpage
, PropSheetInfo
* psInfo
);
128 static void PROPSHEET_SetWizButtons(HWND hwndDlg
, DWORD dwFlags
);
129 static PADDING_INFO
PROPSHEET_GetPaddingInfoWizard(HWND hwndDlg
, const PropSheetInfo
* psInfo
);
130 static BOOL
PROPSHEET_IsDialogMessage(HWND hwnd
, LPMSG lpMsg
);
133 PROPSHEET_DialogProc(HWND hwnd
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
);
135 DEFAULT_DEBUG_CHANNEL(propsheet
);
137 /******************************************************************************
138 * PROPSHEET_CollectSheetInfo
140 * Collect relevant data.
142 static BOOL
PROPSHEET_CollectSheetInfo(LPCPROPSHEETHEADERA lppsh
,
143 PropSheetInfo
* psInfo
)
145 DWORD dwSize
= min(lppsh
->dwSize
,sizeof(PROPSHEETHEADERA
));
146 DWORD dwFlags
= lppsh
->dwFlags
;
148 psInfo
->hasHelp
= dwFlags
& PSH_HASHELP
;
149 psInfo
->hasApply
= !(dwFlags
& PSH_NOAPPLYNOW
);
150 psInfo
->useCallback
= dwFlags
& PSH_USECALLBACK
;
151 psInfo
->isModeless
= dwFlags
& PSH_MODELESS
;
153 memcpy(&psInfo
->ppshheader
,lppsh
,dwSize
);
155 if (HIWORD(lppsh
->pszCaption
))
156 psInfo
->ppshheader
.pszCaption
= HEAP_strdupA( GetProcessHeap(),
157 0, lppsh
->pszCaption
);
159 psInfo
->nPages
= lppsh
->nPages
;
161 if (dwFlags
& PSH_USEPSTARTPAGE
)
163 TRACE("PSH_USEPSTARTPAGE is on");
164 psInfo
->active_page
= 0;
167 psInfo
->active_page
= lppsh
->u2
.nStartPage
;
169 if (psInfo
->active_page
< 0 || psInfo
->active_page
>= psInfo
->nPages
)
170 psInfo
->active_page
= 0;
172 psInfo
->restartWindows
= FALSE
;
173 psInfo
->rebootSystem
= FALSE
;
174 psInfo
->hImageList
= 0;
175 psInfo
->activeValid
= FALSE
;
180 /******************************************************************************
181 * PROPSHEET_CollectPageInfo
183 * Collect property sheet data.
184 * With code taken from DIALOG_ParseTemplate32.
186 BOOL
PROPSHEET_CollectPageInfo(LPCPROPSHEETPAGEA lppsp
,
187 PropSheetInfo
* psInfo
,
190 DLGTEMPLATE
* pTemplate
;
195 psInfo
->proppage
[index
].hpage
= (HPROPSHEETPAGE
)lppsp
;
196 psInfo
->proppage
[index
].hwndPage
= 0;
197 psInfo
->proppage
[index
].isDirty
= FALSE
;
200 * Process property page flags.
202 dwFlags
= lppsp
->dwFlags
;
203 psInfo
->proppage
[index
].useCallback
= (dwFlags
& PSP_USECALLBACK
) && (lppsp
->pfnCallback
);
204 psInfo
->proppage
[index
].hasHelp
= dwFlags
& PSP_HASHELP
;
205 psInfo
->proppage
[index
].hasIcon
= dwFlags
& (PSP_USEHICON
| PSP_USEICONID
);
207 /* as soon as we have a page with the help flag, set the sheet flag on */
208 if (psInfo
->proppage
[index
].hasHelp
)
209 psInfo
->hasHelp
= TRUE
;
212 * Process page template.
214 if (dwFlags
& PSP_DLGINDIRECT
)
215 pTemplate
= (DLGTEMPLATE
*)lppsp
->u
.pResource
;
218 HRSRC hResource
= FindResourceA(lppsp
->hInstance
,
219 lppsp
->u
.pszTemplate
,
221 HGLOBAL hTemplate
= LoadResource(lppsp
->hInstance
,
223 pTemplate
= (LPDLGTEMPLATEA
)LockResource(hTemplate
);
227 * Extract the size of the page and the caption.
232 p
= (const WORD
*)pTemplate
;
234 if (((MyDLGTEMPLATEEX
*)pTemplate
)->signature
== 0xFFFF)
236 /* DIALOGEX template */
240 p
+= 2; /* help ID */
241 p
+= 2; /* ext style */
246 /* DIALOG template */
249 p
+= 2; /* ext style */
255 width
= (WORD
)*p
; p
++;
256 height
= (WORD
)*p
; p
++;
258 /* remember the largest width and height */
259 if (width
> psInfo
->width
)
260 psInfo
->width
= width
;
262 if (height
> psInfo
->height
)
263 psInfo
->height
= height
;
275 p
+= lstrlenW( (LPCWSTR
)p
) + 1;
289 p
+= lstrlenW( (LPCWSTR
)p
) + 1;
293 /* Extract the caption */
294 psInfo
->proppage
[index
].pszText
= (LPCWSTR
)p
;
295 TRACE("Tab %d %s\n",index
,debugstr_w((LPCWSTR
)p
));
296 p
+= lstrlenW((LPCWSTR
)p
) + 1;
298 if (dwFlags
& PSP_USETITLE
)
300 if ( !HIWORD( lppsp
->pszTitle
) )
304 if ( !LoadStringA( lppsp
->hInstance
, (UINT
) lppsp
->pszTitle
, szTitle
, 256 ) )
307 psInfo
->proppage
[index
].pszText
= HEAP_strdupAtoW( GetProcessHeap(),
311 psInfo
->proppage
[index
].pszText
= HEAP_strdupAtoW(GetProcessHeap(),
317 * Build the image list for icons
319 if ((dwFlags
& PSP_USEHICON
) || (dwFlags
& PSP_USEICONID
))
322 int icon_cx
= GetSystemMetrics(SM_CXSMICON
);
323 int icon_cy
= GetSystemMetrics(SM_CYSMICON
);
325 if (dwFlags
& PSP_USEICONID
)
326 hIcon
= LoadImageA(lppsp
->hInstance
, lppsp
->u2
.pszIcon
, IMAGE_ICON
,
327 icon_cx
, icon_cy
, LR_DEFAULTCOLOR
);
329 hIcon
= lppsp
->u2
.hIcon
;
333 if (psInfo
->hImageList
== 0 )
334 psInfo
->hImageList
= ImageList_Create(icon_cx
, icon_cy
, ILC_COLOR
, 1, 1);
336 ImageList_AddIcon(psInfo
->hImageList
, hIcon
);
345 /******************************************************************************
346 * PROPSHEET_CreateDialog
348 * Creates the actual property sheet.
350 BOOL
PROPSHEET_CreateDialog(PropSheetInfo
* psInfo
)
357 WORD resID
= IDD_PROPSHEET
;
359 if (psInfo
->ppshheader
.dwFlags
& PSH_WIZARD
)
362 if(!(hRes
= FindResourceA(COMCTL32_hModule
,
363 MAKEINTRESOURCEA(resID
),
367 if(!(template = (LPVOID
)LoadResource(COMCTL32_hModule
, hRes
)))
371 * Make a copy of the dialog template.
373 resSize
= SizeofResource(COMCTL32_hModule
, hRes
);
375 temp
= COMCTL32_Alloc(resSize
);
380 memcpy(temp
, template, resSize
);
382 if (psInfo
->useCallback
)
383 (*(psInfo
->ppshheader
.pfnCallback
))(0, PSCB_PRECREATE
, (LPARAM
)temp
);
385 if (!(psInfo
->ppshheader
.dwFlags
& PSH_MODELESS
))
386 ret
= DialogBoxIndirectParamA(psInfo
->ppshheader
.hInstance
,
387 (LPDLGTEMPLATEA
) temp
,
388 psInfo
->ppshheader
.hwndParent
,
389 (DLGPROC
) PROPSHEET_DialogProc
,
392 ret
= CreateDialogIndirectParamA(psInfo
->ppshheader
.hInstance
,
393 (LPDLGTEMPLATEA
) temp
,
394 psInfo
->ppshheader
.hwndParent
,
395 (DLGPROC
) PROPSHEET_DialogProc
,
403 /******************************************************************************
404 * PROPSHEET_SizeMismatch
406 * Verify that the tab control and the "largest" property sheet page dlg. template
409 static BOOL
PROPSHEET_SizeMismatch(HWND hwndDlg
, PropSheetInfo
* psInfo
)
411 HWND hwndTabCtrl
= GetDlgItem(hwndDlg
, IDC_TABCONTROL
);
412 RECT rcOrigTab
, rcPage
;
417 GetClientRect(hwndTabCtrl
, &rcOrigTab
);
418 TRACE("orig tab %d %d %d %d\n", rcOrigTab
.left
, rcOrigTab
.top
,
419 rcOrigTab
.right
, rcOrigTab
.bottom
);
424 rcPage
.left
= psInfo
->x
;
425 rcPage
.top
= psInfo
->y
;
426 rcPage
.right
= psInfo
->width
;
427 rcPage
.bottom
= psInfo
->height
;
429 MapDialogRect(hwndDlg
, &rcPage
);
430 TRACE("biggest page %d %d %d %d\n", rcPage
.left
, rcPage
.top
,
431 rcPage
.right
, rcPage
.bottom
);
433 if ( (rcPage
.right
- rcPage
.left
) != (rcOrigTab
.right
- rcOrigTab
.left
) )
435 if ( (rcPage
.bottom
- rcPage
.top
) != (rcOrigTab
.bottom
- rcOrigTab
.top
) )
441 /******************************************************************************
442 * PROPSHEET_IsTooSmallWizard
444 * Verify that the default property sheet is big enough.
446 static BOOL
PROPSHEET_IsTooSmallWizard(HWND hwndDlg
, PropSheetInfo
* psInfo
)
448 RECT rcSheetRect
, rcPage
, rcLine
, rcSheetClient
;
449 HWND hwndLine
= GetDlgItem(hwndDlg
, IDC_SUNKEN_LINE
);
450 PADDING_INFO padding
= PROPSHEET_GetPaddingInfoWizard(hwndDlg
, psInfo
);
452 GetClientRect(hwndDlg
, &rcSheetClient
);
453 GetWindowRect(hwndDlg
, &rcSheetRect
);
454 GetWindowRect(hwndLine
, &rcLine
);
456 /* Remove the space below the sunken line */
457 rcSheetClient
.bottom
-= (rcSheetRect
.bottom
- rcLine
.top
);
459 /* Remove the buffer zone all around the edge */
460 rcSheetClient
.bottom
-= (padding
.y
* 2);
461 rcSheetClient
.right
-= (padding
.x
* 2);
466 rcPage
.left
= psInfo
->x
;
467 rcPage
.top
= psInfo
->y
;
468 rcPage
.right
= psInfo
->width
;
469 rcPage
.bottom
= psInfo
->height
;
471 MapDialogRect(hwndDlg
, &rcPage
);
472 TRACE("biggest page %d %d %d %d\n", rcPage
.left
, rcPage
.top
,
473 rcPage
.right
, rcPage
.bottom
);
475 if (rcPage
.right
> rcSheetClient
.right
)
478 if (rcPage
.bottom
> rcSheetClient
.bottom
)
484 /******************************************************************************
485 * PROPSHEET_AdjustSize
487 * Resizes the property sheet and the tab control to fit the largest page.
489 static BOOL
PROPSHEET_AdjustSize(HWND hwndDlg
, PropSheetInfo
* psInfo
)
491 HWND hwndTabCtrl
= GetDlgItem(hwndDlg
, IDC_TABCONTROL
);
492 HWND hwndButton
= GetDlgItem(hwndDlg
, IDOK
);
494 int tabOffsetX
, tabOffsetY
, buttonHeight
;
495 PADDING_INFO padding
= PROPSHEET_GetPaddingInfo(hwndDlg
);
498 /* Get the height of buttons */
499 GetClientRect(hwndButton
, &rc
);
500 buttonHeight
= rc
.bottom
;
507 rc
.right
= psInfo
->width
;
508 rc
.bottom
= psInfo
->height
;
510 MapDialogRect(hwndDlg
, &rc
);
512 /* retrieve the dialog units */
513 units
.left
= units
.right
= 4;
514 units
.top
= units
.bottom
= 8;
515 MapDialogRect(hwndDlg
, &units
);
518 * Resize the tab control.
520 GetClientRect(hwndTabCtrl
,&tabRect
);
522 SendMessageA(hwndTabCtrl
, TCM_ADJUSTRECT
, FALSE
, (LPARAM
)&tabRect
);
524 if ((rc
.bottom
- rc
.top
) < (tabRect
.bottom
- tabRect
.top
))
526 rc
.bottom
= rc
.top
+ tabRect
.bottom
- tabRect
.top
;
527 psInfo
->height
= MulDiv((rc
.bottom
- rc
.top
),8,units
.top
);
530 if ((rc
.right
- rc
.left
) < (tabRect
.right
- tabRect
.left
))
532 rc
.right
= rc
.left
+ tabRect
.right
- tabRect
.left
;
533 psInfo
->width
= MulDiv((rc
.right
- rc
.left
),4,units
.left
);
536 SendMessageA(hwndTabCtrl
, TCM_ADJUSTRECT
, TRUE
, (LPARAM
)&rc
);
538 tabOffsetX
= -(rc
.left
);
539 tabOffsetY
= -(rc
.top
);
543 SetWindowPos(hwndTabCtrl
, 0, 0, 0, rc
.right
, rc
.bottom
,
544 SWP_NOMOVE
| SWP_NOZORDER
| SWP_NOACTIVATE
);
546 GetClientRect(hwndTabCtrl
, &rc
);
548 TRACE("tab client rc %d %d %d %d\n",
549 rc
.left
, rc
.top
, rc
.right
, rc
.bottom
);
551 rc
.right
+= ((padding
.x
* 2) + tabOffsetX
);
552 rc
.bottom
+= (buttonHeight
+ (3 * padding
.y
) + tabOffsetY
);
555 * Resize the property sheet.
557 SetWindowPos(hwndDlg
, 0, 0, 0, rc
.right
, rc
.bottom
,
558 SWP_NOMOVE
| SWP_NOZORDER
| SWP_NOACTIVATE
);
562 /******************************************************************************
563 * PROPSHEET_AdjustSizeWizard
565 * Resizes the property sheet to fit the largest page.
567 static BOOL
PROPSHEET_AdjustSizeWizard(HWND hwndDlg
, PropSheetInfo
* psInfo
)
569 HWND hwndButton
= GetDlgItem(hwndDlg
, IDCANCEL
);
570 HWND hwndLine
= GetDlgItem(hwndDlg
, IDC_SUNKEN_LINE
);
571 HWND hwndTabCtrl
= GetDlgItem(hwndDlg
, IDC_TABCONTROL
);
573 int buttonHeight
, lineHeight
;
574 PADDING_INFO padding
= PROPSHEET_GetPaddingInfoWizard(hwndDlg
, psInfo
);
577 /* Get the height of buttons */
578 GetClientRect(hwndButton
, &rc
);
579 buttonHeight
= rc
.bottom
;
581 GetClientRect(hwndLine
, &rc
);
582 lineHeight
= rc
.bottom
;
584 /* retrieve the dialog units */
585 units
.left
= units
.right
= 4;
586 units
.top
= units
.bottom
= 8;
587 MapDialogRect(hwndDlg
, &units
);
594 rc
.right
= psInfo
->width
;
595 rc
.bottom
= psInfo
->height
;
597 MapDialogRect(hwndDlg
, &rc
);
599 GetClientRect(hwndTabCtrl
,&tabRect
);
601 if ((rc
.bottom
- rc
.top
) < (tabRect
.bottom
- tabRect
.top
))
603 rc
.bottom
= rc
.top
+ tabRect
.bottom
- tabRect
.top
;
604 psInfo
->height
= MulDiv((rc
.bottom
- rc
.top
), 8, units
.top
);
607 if ((rc
.right
- rc
.left
) < (tabRect
.right
- tabRect
.left
))
609 rc
.right
= rc
.left
+ tabRect
.right
- tabRect
.left
;
610 psInfo
->width
= MulDiv((rc
.right
- rc
.left
), 4, units
.left
);
613 TRACE("Biggest page %d %d %d %d\n", rc
.left
, rc
.top
, rc
.right
, rc
.bottom
);
616 rc
.right
+= (padding
.x
* 2);
617 rc
.bottom
+= (buttonHeight
+ (5 * padding
.y
) + lineHeight
);
620 * Resize the property sheet.
622 SetWindowPos(hwndDlg
, 0, 0, 0, rc
.right
, rc
.bottom
,
623 SWP_NOMOVE
| SWP_NOZORDER
| SWP_NOACTIVATE
);
627 /******************************************************************************
628 * PROPSHEET_AdjustButtons
630 * Adjusts the buttons' positions.
632 static BOOL
PROPSHEET_AdjustButtons(HWND hwndParent
, PropSheetInfo
* psInfo
)
634 HWND hwndButton
= GetDlgItem(hwndParent
, IDOK
);
638 int buttonWidth
, buttonHeight
;
639 PADDING_INFO padding
= PROPSHEET_GetPaddingInfo(hwndParent
);
641 if (psInfo
->hasApply
)
648 * Obtain the size of the buttons.
650 GetClientRect(hwndButton
, &rcSheet
);
651 buttonWidth
= rcSheet
.right
;
652 buttonHeight
= rcSheet
.bottom
;
655 * Get the size of the property sheet.
657 GetClientRect(hwndParent
, &rcSheet
);
660 * All buttons will be at this y coordinate.
662 y
= rcSheet
.bottom
- (padding
.y
+ buttonHeight
);
665 * Position OK button.
667 hwndButton
= GetDlgItem(hwndParent
, IDOK
);
669 x
= rcSheet
.right
- ((padding
.x
+ buttonWidth
) * num_buttons
);
671 SetWindowPos(hwndButton
, 0, x
, y
, 0, 0,
672 SWP_NOSIZE
| SWP_NOZORDER
| SWP_NOACTIVATE
);
675 * Position Cancel button.
677 hwndButton
= GetDlgItem(hwndParent
, IDCANCEL
);
679 x
= rcSheet
.right
- ((padding
.x
+ buttonWidth
) * (num_buttons
- 1));
681 SetWindowPos(hwndButton
, 0, x
, y
, 0, 0,
682 SWP_NOSIZE
| SWP_NOZORDER
| SWP_NOACTIVATE
);
685 * Position Apply button.
687 hwndButton
= GetDlgItem(hwndParent
, IDC_APPLY_BUTTON
);
689 if (psInfo
->hasApply
)
692 x
= rcSheet
.right
- ((padding
.x
+ buttonWidth
) * 2);
694 x
= rcSheet
.right
- (padding
.x
+ buttonWidth
);
696 SetWindowPos(hwndButton
, 0, x
, y
, 0, 0,
697 SWP_NOSIZE
| SWP_NOZORDER
| SWP_NOACTIVATE
);
699 EnableWindow(hwndButton
, FALSE
);
702 ShowWindow(hwndButton
, SW_HIDE
);
705 * Position Help button.
707 hwndButton
= GetDlgItem(hwndParent
, IDHELP
);
711 x
= rcSheet
.right
- (padding
.x
+ buttonWidth
);
713 SetWindowPos(hwndButton
, 0, x
, y
, 0, 0,
714 SWP_NOSIZE
| SWP_NOZORDER
| SWP_NOACTIVATE
);
717 ShowWindow(hwndButton
, SW_HIDE
);
722 /******************************************************************************
723 * PROPSHEET_AdjustButtonsWizard
725 * Adjusts the buttons' positions.
727 static BOOL
PROPSHEET_AdjustButtonsWizard(HWND hwndParent
,
728 PropSheetInfo
* psInfo
)
730 HWND hwndButton
= GetDlgItem(hwndParent
, IDCANCEL
);
731 HWND hwndLine
= GetDlgItem(hwndParent
, IDC_SUNKEN_LINE
);
735 int buttonWidth
, buttonHeight
, lineHeight
, lineWidth
;
736 PADDING_INFO padding
= PROPSHEET_GetPaddingInfoWizard(hwndParent
, psInfo
);
742 * Obtain the size of the buttons.
744 GetClientRect(hwndButton
, &rcSheet
);
745 buttonWidth
= rcSheet
.right
;
746 buttonHeight
= rcSheet
.bottom
;
748 GetClientRect(hwndLine
, &rcSheet
);
749 lineHeight
= rcSheet
.bottom
;
752 * Get the size of the property sheet.
754 GetClientRect(hwndParent
, &rcSheet
);
757 * All buttons will be at this y coordinate.
759 y
= rcSheet
.bottom
- (padding
.y
+ buttonHeight
);
762 * Position the Next and the Finish buttons.
764 hwndButton
= GetDlgItem(hwndParent
, IDC_NEXT_BUTTON
);
766 x
= rcSheet
.right
- ((padding
.x
+ buttonWidth
) * (num_buttons
- 1));
768 SetWindowPos(hwndButton
, 0, x
, y
, 0, 0,
769 SWP_NOSIZE
| SWP_NOZORDER
| SWP_NOACTIVATE
);
771 hwndButton
= GetDlgItem(hwndParent
, IDC_FINISH_BUTTON
);
773 SetWindowPos(hwndButton
, 0, x
, y
, 0, 0,
774 SWP_NOSIZE
| SWP_NOZORDER
| SWP_NOACTIVATE
);
776 ShowWindow(hwndButton
, SW_HIDE
);
779 * Position the Back button.
781 hwndButton
= GetDlgItem(hwndParent
, IDC_BACK_BUTTON
);
785 SetWindowPos(hwndButton
, 0, x
, y
, 0, 0,
786 SWP_NOSIZE
| SWP_NOZORDER
| SWP_NOACTIVATE
);
789 * Position the Cancel button.
791 hwndButton
= GetDlgItem(hwndParent
, IDCANCEL
);
793 x
= rcSheet
.right
- ((padding
.x
+ buttonWidth
) * (num_buttons
- 2));
795 SetWindowPos(hwndButton
, 0, x
, y
, 0, 0,
796 SWP_NOSIZE
| SWP_NOZORDER
| SWP_NOACTIVATE
);
799 * Position Help button.
801 hwndButton
= GetDlgItem(hwndParent
, IDHELP
);
805 x
= rcSheet
.right
- (padding
.x
+ buttonWidth
);
807 SetWindowPos(hwndButton
, 0, x
, y
, 0, 0,
808 SWP_NOSIZE
| SWP_NOZORDER
| SWP_NOACTIVATE
);
811 ShowWindow(hwndButton
, SW_HIDE
);
814 * Position and resize the sunken line.
817 y
= rcSheet
.bottom
- ((padding
.y
* 2) + buttonHeight
+ lineHeight
);
819 GetClientRect(hwndParent
, &rcSheet
);
820 lineWidth
= rcSheet
.right
- (padding
.x
* 2);
822 SetWindowPos(hwndLine
, 0, x
, y
, lineWidth
, 2,
823 SWP_NOZORDER
| SWP_NOACTIVATE
);
828 /******************************************************************************
829 * PROPSHEET_GetPaddingInfo
831 * Returns the layout information.
833 static PADDING_INFO
PROPSHEET_GetPaddingInfo(HWND hwndDlg
)
835 HWND hwndTab
= GetDlgItem(hwndDlg
, IDC_TABCONTROL
);
838 PADDING_INFO padding
;
840 GetWindowRect(hwndTab
, &rcTab
);
845 ScreenToClient(hwndDlg
, &tl
);
853 /******************************************************************************
854 * PROPSHEET_GetPaddingInfoWizard
856 * Returns the layout information.
857 * Vertical spacing is the distance between the line and the buttons.
858 * Do NOT use the Help button to gather padding information when it isn't mapped
859 * (PSH_HASHELP), as app writers aren't forced to supply correct coordinates
860 * for it in this case !
861 * FIXME: I'm not sure about any other coordinate problems with these evil
862 * buttons. Fix it in case additional problems appear or maybe calculate
863 * a padding in a completely different way, as this is somewhat messy.
865 static PADDING_INFO
PROPSHEET_GetPaddingInfoWizard(HWND hwndDlg
, const PropSheetInfo
*
868 PADDING_INFO padding
;
872 POINT ptButton
, ptLine
;
880 if (psInfo
->ppshheader
.dwFlags
& PSH_WIZARD
)
882 idButton
= IDC_NEXT_BUTTON
;
886 /* hopefully this is ok */
891 hwndControl
= GetDlgItem(hwndDlg
, idButton
);
892 GetWindowRect(hwndControl
, &rc
);
894 ptButton
.x
= rc
.left
;
897 ScreenToClient(hwndDlg
, &ptButton
);
900 hwndControl
= GetDlgItem(hwndDlg
, IDC_SUNKEN_LINE
);
901 GetWindowRect(hwndControl
, &rc
);
904 ptLine
.y
= rc
.bottom
;
906 ScreenToClient(hwndDlg
, &ptLine
);
908 padding
.y
= ptButton
.y
- ptLine
.y
;
911 ERR("padding negative ! Please report this !\n");
913 /* this is most probably not correct, but the best we have now */
914 padding
.x
= padding
.y
;
918 /******************************************************************************
919 * PROPSHEET_CreateTabControl
921 * Insert the tabs in the tab control.
923 static BOOL
PROPSHEET_CreateTabControl(HWND hwndParent
,
924 PropSheetInfo
* psInfo
)
926 HWND hwndTabCtrl
= GetDlgItem(hwndParent
, IDC_TABCONTROL
);
930 char tabtext
[MAX_TABTEXT_LENGTH
] = "Tab text";
932 item
.mask
= TCIF_TEXT
;
933 item
.pszText
= tabtext
;
934 item
.cchTextMax
= MAX_TABTEXT_LENGTH
;
936 nTabs
= psInfo
->nPages
;
939 * Set the image list for icons.
941 if (psInfo
->hImageList
)
943 SendMessageA(hwndTabCtrl
, TCM_SETIMAGELIST
, 0, (LPARAM
)psInfo
->hImageList
);
946 for (i
= 0; i
< nTabs
; i
++)
948 if ( psInfo
->proppage
[i
].hasIcon
)
950 item
.mask
|= TCIF_IMAGE
;
951 item
.iImage
= iImage
++;
955 item
.mask
&= ~TCIF_IMAGE
;
958 WideCharToMultiByte(CP_ACP
, 0,
959 (LPCWSTR
)psInfo
->proppage
[i
].pszText
,
960 -1, tabtext
, MAX_TABTEXT_LENGTH
, NULL
, NULL
);
962 SendMessageA(hwndTabCtrl
, TCM_INSERTITEMA
, (WPARAM
)i
, (LPARAM
)&item
);
968 /******************************************************************************
969 * PROPSHEET_CreatePage
973 static BOOL
PROPSHEET_CreatePage(HWND hwndParent
,
975 const PropSheetInfo
* psInfo
,
976 LPCPROPSHEETPAGEA ppshpage
)
978 DLGTEMPLATE
* pTemplate
;
981 PropPageInfo
* ppInfo
= psInfo
->proppage
;
982 PADDING_INFO padding
;
983 UINT pageWidth
,pageHeight
;
987 TRACE("index %d\n", index
);
989 if (ppshpage
->dwFlags
& PSP_DLGINDIRECT
)
990 pTemplate
= (DLGTEMPLATE
*)ppshpage
->u
.pResource
;
996 hResource
= FindResourceA(ppshpage
->hInstance
,
997 ppshpage
->u
.pszTemplate
,
1002 resSize
= SizeofResource(ppshpage
->hInstance
, hResource
);
1004 hTemplate
= LoadResource(ppshpage
->hInstance
, hResource
);
1008 pTemplate
= (LPDLGTEMPLATEA
)LockResource(hTemplate
);
1010 * Make a copy of the dialog template to make it writable
1012 temp
= COMCTL32_Alloc(resSize
);
1016 memcpy(temp
, pTemplate
, resSize
);
1020 if (((MyDLGTEMPLATEEX
*)pTemplate
)->signature
== 0xFFFF)
1022 ((MyDLGTEMPLATEEX
*)pTemplate
)->style
|= WS_CHILD
| DS_CONTROL
;
1023 ((MyDLGTEMPLATEEX
*)pTemplate
)->style
&= ~DS_MODALFRAME
;
1024 ((MyDLGTEMPLATEEX
*)pTemplate
)->style
&= ~WS_CAPTION
;
1025 ((MyDLGTEMPLATEEX
*)pTemplate
)->style
&= ~WS_SYSMENU
;
1026 ((MyDLGTEMPLATEEX
*)pTemplate
)->style
&= ~WS_POPUP
;
1027 ((MyDLGTEMPLATEEX
*)pTemplate
)->style
&= ~WS_DISABLED
;
1028 ((MyDLGTEMPLATEEX
*)pTemplate
)->style
&= ~WS_VISIBLE
;
1032 pTemplate
->style
|= WS_CHILD
| DS_CONTROL
;
1033 pTemplate
->style
&= ~DS_MODALFRAME
;
1034 pTemplate
->style
&= ~WS_CAPTION
;
1035 pTemplate
->style
&= ~WS_SYSMENU
;
1036 pTemplate
->style
&= ~WS_POPUP
;
1037 pTemplate
->style
&= ~WS_DISABLED
;
1038 pTemplate
->style
&= ~WS_VISIBLE
;
1041 if (psInfo
->proppage
[index
].useCallback
)
1042 (*(ppshpage
->pfnCallback
))(hwndParent
,
1044 (LPPROPSHEETPAGEA
)ppshpage
);
1046 hwndPage
= CreateDialogIndirectParamA(ppshpage
->hInstance
,
1049 ppshpage
->pfnDlgProc
,
1051 /* Free a no more needed copy */
1053 COMCTL32_Free(temp
);
1055 ppInfo
[index
].hwndPage
= hwndPage
;
1057 rc
.left
= psInfo
->x
;
1059 rc
.right
= psInfo
->width
;
1060 rc
.bottom
= psInfo
->height
;
1062 MapDialogRect(hwndParent
, &rc
);
1064 pageWidth
= rc
.right
- rc
.left
;
1065 pageHeight
= rc
.bottom
- rc
.top
;
1067 if (psInfo
->ppshheader
.dwFlags
& PSH_WIZARD
)
1068 padding
= PROPSHEET_GetPaddingInfoWizard(hwndParent
, psInfo
);
1072 * Ask the Tab control to fit this page in.
1075 HWND hwndTabCtrl
= GetDlgItem(hwndParent
, IDC_TABCONTROL
);
1076 SendMessageA(hwndTabCtrl
, TCM_ADJUSTRECT
, FALSE
, (LPARAM
)&rc
);
1077 padding
= PROPSHEET_GetPaddingInfo(hwndParent
);
1080 SetWindowPos(hwndPage
, HWND_TOP
,
1081 rc
.left
+ padding
.x
,
1083 pageWidth
, pageHeight
, 0);
1088 /******************************************************************************
1089 * PROPSHEET_ShowPage
1091 * Displays or creates the specified page.
1093 static BOOL
PROPSHEET_ShowPage(HWND hwndDlg
, int index
, PropSheetInfo
* psInfo
)
1095 if (index
== psInfo
->active_page
)
1097 if (GetTopWindow(hwndDlg
) != psInfo
->proppage
[index
].hwndPage
)
1098 SetWindowPos(psInfo
->proppage
[index
].hwndPage
, HWND_TOP
, 0, 0, 0, 0, SWP_NOSIZE
| SWP_NOMOVE
);
1102 if (psInfo
->proppage
[index
].hwndPage
== 0)
1104 LPCPROPSHEETPAGEA ppshpage
;
1106 ppshpage
= (LPCPROPSHEETPAGEA
)psInfo
->proppage
[index
].hpage
;
1107 PROPSHEET_CreatePage(hwndDlg
, index
, psInfo
, ppshpage
);
1110 if (psInfo
->active_page
!= -1)
1111 ShowWindow(psInfo
->proppage
[psInfo
->active_page
].hwndPage
, SW_HIDE
);
1113 ShowWindow(psInfo
->proppage
[index
].hwndPage
, SW_SHOW
);
1115 if (!(psInfo
->ppshheader
.dwFlags
& PSH_WIZARD
))
1119 /* Synchronize current selection with tab control */
1120 hwndTabCtrl
= GetDlgItem(hwndDlg
, IDC_TABCONTROL
);
1121 SendMessageA(hwndTabCtrl
, TCM_SETCURSEL
, index
, 0);
1124 psInfo
->active_page
= index
;
1125 psInfo
->activeValid
= TRUE
;
1130 /******************************************************************************
1133 static BOOL
PROPSHEET_Back(HWND hwndDlg
)
1138 PropSheetInfo
* psInfo
= (PropSheetInfo
*) GetPropA(hwndDlg
,
1142 if (psInfo
->active_page
< 0)
1145 psn
.hdr
.code
= PSN_WIZBACK
;
1146 psn
.hdr
.hwndFrom
= hwndDlg
;
1150 hwndPage
= psInfo
->proppage
[psInfo
->active_page
].hwndPage
;
1152 result
= SendMessageA(hwndPage
, WM_NOTIFY
, 0, (LPARAM
) &psn
);
1156 if (psInfo
->active_page
> 0)
1158 res
= PROPSHEET_CanSetCurSel(hwndDlg
);
1161 res
= PROPSHEET_SetCurSel(hwndDlg
, psInfo
->active_page
- 1, -1, 0);
1168 /******************************************************************************
1171 static BOOL
PROPSHEET_Next(HWND hwndDlg
)
1175 LRESULT msgResult
= 0;
1176 PropSheetInfo
* psInfo
= (PropSheetInfo
*) GetPropA(hwndDlg
,
1179 if (psInfo
->active_page
< 0)
1182 psn
.hdr
.code
= PSN_WIZNEXT
;
1183 psn
.hdr
.hwndFrom
= hwndDlg
;
1187 hwndPage
= psInfo
->proppage
[psInfo
->active_page
].hwndPage
;
1189 msgResult
= SendMessageA(hwndPage
, WM_NOTIFY
, 0, (LPARAM
) &psn
);
1190 if (msgResult
== -1)
1193 if(PROPSHEET_CanSetCurSel(hwndDlg
) != FALSE
)
1195 PROPSHEET_SetCurSel(hwndDlg
, psInfo
->active_page
+ 1, 1, 0);
1201 /******************************************************************************
1204 static BOOL
PROPSHEET_Finish(HWND hwndDlg
)
1208 LRESULT msgResult
= 0;
1209 PropSheetInfo
* psInfo
= (PropSheetInfo
*) GetPropA(hwndDlg
,
1212 if (psInfo
->active_page
< 0)
1215 psn
.hdr
.code
= PSN_WIZFINISH
;
1216 psn
.hdr
.hwndFrom
= hwndDlg
;
1220 hwndPage
= psInfo
->proppage
[psInfo
->active_page
].hwndPage
;
1222 msgResult
= SendMessageA(hwndPage
, WM_NOTIFY
, 0, (LPARAM
) &psn
);
1224 TRACE("msg result %ld\n", msgResult
);
1229 if (psInfo
->isModeless
)
1230 psInfo
->activeValid
= FALSE
;
1232 EndDialog(hwndDlg
, TRUE
);
1237 /******************************************************************************
1240 static BOOL
PROPSHEET_Apply(HWND hwndDlg
, LPARAM lParam
)
1246 PropSheetInfo
* psInfo
= (PropSheetInfo
*) GetPropA(hwndDlg
,
1249 if (psInfo
->active_page
< 0)
1252 psn
.hdr
.hwndFrom
= hwndDlg
;
1258 * Send PSN_KILLACTIVE to the current page.
1260 psn
.hdr
.code
= PSN_KILLACTIVE
;
1262 hwndPage
= psInfo
->proppage
[psInfo
->active_page
].hwndPage
;
1264 if (SendMessageA(hwndPage
, WM_NOTIFY
, 0, (LPARAM
) &psn
) != FALSE
)
1268 * Send PSN_APPLY to all pages.
1270 psn
.hdr
.code
= PSN_APPLY
;
1271 psn
.lParam
= lParam
;
1273 for (i
= 0; i
< psInfo
->nPages
; i
++)
1275 hwndPage
= psInfo
->proppage
[i
].hwndPage
;
1278 msgResult
= SendMessageA(hwndPage
, WM_NOTIFY
, 0, (LPARAM
) &psn
);
1279 if (msgResult
== PSNRET_INVALID_NOCHANGEPAGE
)
1286 psInfo
->activeValid
= FALSE
;
1288 else if(psInfo
->active_page
>= 0)
1290 psn
.hdr
.code
= PSN_SETACTIVE
;
1292 hwndPage
= psInfo
->proppage
[psInfo
->active_page
].hwndPage
;
1293 SendMessageA(hwndPage
, WM_NOTIFY
, 0, (LPARAM
) &psn
);
1299 /******************************************************************************
1302 static void PROPSHEET_Cancel(HWND hwndDlg
, LPARAM lParam
)
1304 PropSheetInfo
* psInfo
= (PropSheetInfo
*) GetPropA(hwndDlg
,
1310 if (psInfo
->active_page
< 0)
1313 hwndPage
= psInfo
->proppage
[psInfo
->active_page
].hwndPage
;
1314 psn
.hdr
.code
= PSN_QUERYCANCEL
;
1315 psn
.hdr
.hwndFrom
= hwndDlg
;
1319 if (SendMessageA(hwndPage
, WM_NOTIFY
, 0, (LPARAM
) &psn
))
1322 psn
.hdr
.code
= PSN_RESET
;
1323 psn
.lParam
= lParam
;
1325 for (i
= 0; i
< psInfo
->nPages
; i
++)
1327 hwndPage
= psInfo
->proppage
[i
].hwndPage
;
1330 SendMessageA(hwndPage
, WM_NOTIFY
, 0, (LPARAM
) &psn
);
1333 if (psInfo
->isModeless
)
1335 /* makes PSM_GETCURRENTPAGEHWND return NULL */
1336 psInfo
->activeValid
= FALSE
;
1339 EndDialog(hwndDlg
, FALSE
);
1342 /******************************************************************************
1345 static void PROPSHEET_Help(HWND hwndDlg
)
1347 PropSheetInfo
* psInfo
= (PropSheetInfo
*) GetPropA(hwndDlg
,
1352 if (psInfo
->active_page
< 0)
1355 hwndPage
= psInfo
->proppage
[psInfo
->active_page
].hwndPage
;
1356 psn
.hdr
.code
= PSN_HELP
;
1357 psn
.hdr
.hwndFrom
= hwndDlg
;
1361 SendMessageA(hwndPage
, WM_NOTIFY
, 0, (LPARAM
) &psn
);
1364 /******************************************************************************
1367 static void PROPSHEET_Changed(HWND hwndDlg
, HWND hwndDirtyPage
)
1370 PropSheetInfo
* psInfo
= (PropSheetInfo
*) GetPropA(hwndDlg
,
1373 if (!psInfo
) return;
1375 * Set the dirty flag of this page.
1377 for (i
= 0; i
< psInfo
->nPages
; i
++)
1379 if (psInfo
->proppage
[i
].hwndPage
== hwndDirtyPage
)
1380 psInfo
->proppage
[i
].isDirty
= TRUE
;
1384 * Enable the Apply button.
1386 if (psInfo
->hasApply
)
1388 HWND hwndApplyBtn
= GetDlgItem(hwndDlg
, IDC_APPLY_BUTTON
);
1390 EnableWindow(hwndApplyBtn
, TRUE
);
1394 /******************************************************************************
1395 * PROPSHEET_UnChanged
1397 static void PROPSHEET_UnChanged(HWND hwndDlg
, HWND hwndCleanPage
)
1400 BOOL noPageDirty
= TRUE
;
1401 HWND hwndApplyBtn
= GetDlgItem(hwndDlg
, IDC_APPLY_BUTTON
);
1402 PropSheetInfo
* psInfo
= (PropSheetInfo
*) GetPropA(hwndDlg
,
1405 if ( !psInfo
) return;
1406 for (i
= 0; i
< psInfo
->nPages
; i
++)
1408 /* set the specified page as clean */
1409 if (psInfo
->proppage
[i
].hwndPage
== hwndCleanPage
)
1410 psInfo
->proppage
[i
].isDirty
= FALSE
;
1412 /* look to see if there's any dirty pages */
1413 if (psInfo
->proppage
[i
].isDirty
)
1414 noPageDirty
= FALSE
;
1418 * Disable Apply button.
1421 EnableWindow(hwndApplyBtn
, FALSE
);
1424 /******************************************************************************
1425 * PROPSHEET_PressButton
1427 static void PROPSHEET_PressButton(HWND hwndDlg
, int buttonID
)
1431 case PSBTN_APPLYNOW
:
1432 SendMessageA(hwndDlg
, WM_COMMAND
, IDC_APPLY_BUTTON
, 0);
1435 PROPSHEET_Back(hwndDlg
);
1438 SendMessageA(hwndDlg
, WM_COMMAND
, IDCANCEL
, 0);
1441 PROPSHEET_Finish(hwndDlg
);
1444 SendMessageA(hwndDlg
, WM_COMMAND
, IDHELP
, 0);
1447 PROPSHEET_Next(hwndDlg
);
1450 SendMessageA(hwndDlg
, WM_COMMAND
, IDOK
, 0);
1453 FIXME("Invalid button index %d\n", buttonID
);
1458 /*************************************************************************
1459 * BOOL PROPSHEET_CanSetCurSel [Internal]
1461 * Test whether the current page can be changed by sending a PSN_KILLACTIVE
1464 * hwndDlg [I] handle to a Dialog hWnd
1467 * TRUE if Current Selection can change
1471 static BOOL
PROPSHEET_CanSetCurSel(HWND hwndDlg
)
1473 PropSheetInfo
* psInfo
= (PropSheetInfo
*) GetPropA(hwndDlg
,
1481 if (psInfo
->active_page
< 0)
1485 * Notify the current page.
1487 hwndPage
= psInfo
->proppage
[psInfo
->active_page
].hwndPage
;
1488 psn
.hdr
.code
= PSN_KILLACTIVE
;
1489 psn
.hdr
.hwndFrom
= hwndDlg
;
1493 return !SendMessageA(hwndPage
, WM_NOTIFY
, 0, (LPARAM
) &psn
);
1496 /******************************************************************************
1497 * PROPSHEET_SetCurSel
1499 static BOOL
PROPSHEET_SetCurSel(HWND hwndDlg
,
1502 HPROPSHEETPAGE hpage
1505 PropSheetInfo
* psInfo
= (PropSheetInfo
*) GetPropA(hwndDlg
, PropSheetInfoStr
);
1506 HWND hwndHelp
= GetDlgItem(hwndDlg
, IDHELP
);
1508 /* hpage takes precedence over index */
1510 index
= PROPSHEET_GetPageIndex(hpage
, psInfo
);
1512 if (index
< 0 || index
>= psInfo
->nPages
)
1514 TRACE("Could not find page to select!\n");
1522 psn
.hdr
.code
= PSN_SETACTIVE
;
1523 psn
.hdr
.hwndFrom
= hwndDlg
;
1527 if (!psInfo
->proppage
[index
].hwndPage
) {
1528 LPCPROPSHEETPAGEA ppshpage
= (LPCPROPSHEETPAGEA
)psInfo
->proppage
[index
].hpage
;
1529 PROPSHEET_CreatePage(hwndDlg
, index
, psInfo
, ppshpage
);
1532 result
= SendMessageA(psInfo
->proppage
[index
].hwndPage
, WM_NOTIFY
, 0, (LPARAM
) &psn
);
1539 FIXME("Tried to skip before first property sheet page!\n");
1542 if (index
>= psInfo
->nPages
) {
1543 FIXME("Tried to skip after last property sheet page!\n");
1544 index
= psInfo
->nPages
-1;
1550 * Display the new page.
1552 PROPSHEET_ShowPage(hwndDlg
, index
, psInfo
);
1554 if (psInfo
->proppage
[index
].hasHelp
)
1555 EnableWindow(hwndHelp
, TRUE
);
1557 EnableWindow(hwndHelp
, FALSE
);
1562 /******************************************************************************
1563 * PROPSHEET_SetTitleA
1565 static void PROPSHEET_SetTitleA(HWND hwndDlg
, DWORD dwStyle
, LPCSTR lpszText
)
1567 PropSheetInfo
* psInfo
= (PropSheetInfo
*) GetPropA(hwndDlg
, PropSheetInfoStr
);
1570 if (HIWORD(lpszText
) == 0) {
1571 if (!LoadStringA(psInfo
->ppshheader
.hInstance
,
1572 LOWORD(lpszText
), szTitle
, sizeof(szTitle
)-1))
1576 if (dwStyle
& PSH_PROPTITLE
)
1579 int lentitle
= strlen(lpszText
);
1580 int lenprop
= strlen(psInfo
->strPropertiesFor
);
1582 dest
= COMCTL32_Alloc(lentitle
+ lenprop
+ 1);
1583 strcpy(dest
, psInfo
->strPropertiesFor
);
1584 strcat(dest
, lpszText
);
1586 SetWindowTextA(hwndDlg
, dest
);
1587 COMCTL32_Free(dest
);
1590 SetWindowTextA(hwndDlg
, lpszText
);
1593 /******************************************************************************
1594 * PROPSHEET_SetFinishTextA
1596 static void PROPSHEET_SetFinishTextA(HWND hwndDlg
, LPCSTR lpszText
)
1598 HWND hwndButton
= GetDlgItem(hwndDlg
, IDC_FINISH_BUTTON
);
1600 /* Set text, show and enable the Finish button */
1601 SetWindowTextA(hwndButton
, lpszText
);
1602 ShowWindow(hwndButton
, SW_SHOW
);
1603 EnableWindow(hwndButton
, TRUE
);
1605 /* Make it default pushbutton */
1606 SendMessageA(hwndDlg
, DM_SETDEFID
, IDC_FINISH_BUTTON
, 0);
1608 /* Hide Back button */
1609 hwndButton
= GetDlgItem(hwndDlg
, IDC_BACK_BUTTON
);
1610 ShowWindow(hwndButton
, SW_HIDE
);
1612 /* Hide Next button */
1613 hwndButton
= GetDlgItem(hwndDlg
, IDC_NEXT_BUTTON
);
1614 ShowWindow(hwndButton
, SW_HIDE
);
1617 /******************************************************************************
1618 * PROPSHEET_QuerySiblings
1620 static LRESULT
PROPSHEET_QuerySiblings(HWND hwndDlg
,
1621 WPARAM wParam
, LPARAM lParam
)
1625 LRESULT msgResult
= 0;
1626 PropSheetInfo
* psInfo
= (PropSheetInfo
*) GetPropA(hwndDlg
,
1629 while ((i
< psInfo
->nPages
) && (msgResult
== 0))
1631 hwndPage
= psInfo
->proppage
[i
].hwndPage
;
1632 msgResult
= SendMessageA(hwndPage
, PSM_QUERYSIBLINGS
, wParam
, lParam
);
1640 /******************************************************************************
1643 static BOOL
PROPSHEET_AddPage(HWND hwndDlg
,
1644 HPROPSHEETPAGE hpage
)
1646 PropSheetInfo
* psInfo
= (PropSheetInfo
*) GetPropA(hwndDlg
,
1648 HWND hwndTabControl
= GetDlgItem(hwndDlg
, IDC_TABCONTROL
);
1650 char tabtext
[MAX_TABTEXT_LENGTH
] = "Tab text";
1651 LPCPROPSHEETPAGEA ppsp
= (LPCPROPSHEETPAGEA
)hpage
;
1654 * Allocate and fill in a new PropPageInfo entry.
1656 psInfo
->proppage
= (PropPageInfo
*) COMCTL32_ReAlloc(psInfo
->proppage
,
1657 sizeof(PropPageInfo
) *
1658 (psInfo
->nPages
+ 1));
1659 if (!PROPSHEET_CollectPageInfo(ppsp
, psInfo
, psInfo
->nPages
))
1662 psInfo
->proppage
[psInfo
->nPages
].hpage
= hpage
;
1664 if (ppsp
->dwFlags
& PSP_PREMATURE
)
1666 /* Create the page but don't show it */
1667 PROPSHEET_CreatePage(hwndDlg
, psInfo
->nPages
, psInfo
, ppsp
);
1671 * Add a new tab to the tab control.
1673 item
.mask
= TCIF_TEXT
;
1674 item
.pszText
= tabtext
;
1675 item
.cchTextMax
= MAX_TABTEXT_LENGTH
;
1677 WideCharToMultiByte(CP_ACP
, 0,
1678 (LPCWSTR
)psInfo
->proppage
[psInfo
->nPages
].pszText
,
1679 -1, tabtext
, MAX_TABTEXT_LENGTH
, NULL
, NULL
);
1681 SendMessageA(hwndTabControl
, TCM_INSERTITEMA
, psInfo
->nPages
+ 1,
1686 /* If it is the only page - show it */
1687 if(psInfo
->nPages
== 1)
1688 PROPSHEET_SetCurSel(hwndDlg
, 0, 1, 0);
1692 /******************************************************************************
1693 * PROPSHEET_RemovePage
1695 static BOOL
PROPSHEET_RemovePage(HWND hwndDlg
,
1697 HPROPSHEETPAGE hpage
)
1699 PropSheetInfo
* psInfo
= (PropSheetInfo
*) GetPropA(hwndDlg
,
1701 HWND hwndTabControl
= GetDlgItem(hwndDlg
, IDC_TABCONTROL
);
1702 PropPageInfo
* oldPages
;
1707 oldPages
= psInfo
->proppage
;
1709 * hpage takes precedence over index.
1713 index
= PROPSHEET_GetPageIndex(hpage
, psInfo
);
1716 /* Make sure that index is within range */
1717 if (index
< 0 || index
>= psInfo
->nPages
)
1719 TRACE("Could not find page to remove!\n");
1723 TRACE("total pages %d removing page %d active page %d\n",
1724 psInfo
->nPages
, index
, psInfo
->active_page
);
1726 * Check if we're removing the active page.
1728 if (index
== psInfo
->active_page
)
1730 if (psInfo
->nPages
> 1)
1734 /* activate previous page */
1735 PROPSHEET_SetCurSel(hwndDlg
, index
- 1, -1, 0);
1739 /* activate the next page */
1740 PROPSHEET_SetCurSel(hwndDlg
, index
+ 1, 1, 0);
1741 psInfo
->active_page
= index
;
1746 psInfo
->active_page
= -1;
1747 if (!psInfo
->isModeless
)
1749 EndDialog(hwndDlg
, FALSE
);
1754 else if (index
< psInfo
->active_page
)
1755 psInfo
->active_page
--;
1757 /* Destroy page dialog window */
1758 DestroyWindow(psInfo
->proppage
[index
].hwndPage
);
1760 /* Free page resources */
1761 if(psInfo
->proppage
[index
].hpage
)
1763 PROPSHEETPAGEA
* psp
= (PROPSHEETPAGEA
*)psInfo
->proppage
[index
].hpage
;
1765 if ((psp
->dwFlags
& PSP_USETITLE
) && psInfo
->proppage
[index
].pszText
)
1766 HeapFree(GetProcessHeap(), 0, (LPVOID
)psInfo
->proppage
[index
].pszText
);
1768 DestroyPropertySheetPage(psInfo
->proppage
[index
].hpage
);
1771 /* Remove the tab */
1772 SendMessageA(hwndTabControl
, TCM_DELETEITEM
, index
, 0);
1775 psInfo
->proppage
= COMCTL32_Alloc(sizeof(PropPageInfo
) * psInfo
->nPages
);
1778 memcpy(&psInfo
->proppage
[0], &oldPages
[0], index
* sizeof(PropPageInfo
));
1780 if (index
< psInfo
->nPages
)
1781 memcpy(&psInfo
->proppage
[index
], &oldPages
[index
+ 1],
1782 (psInfo
->nPages
- index
) * sizeof(PropPageInfo
));
1784 COMCTL32_Free(oldPages
);
1789 /******************************************************************************
1790 * PROPSHEET_SetWizButtons
1792 * This code will work if (and assumes that) the Next button is on top of the
1793 * Finish button. ie. Finish comes after Next in the Z order.
1794 * This means make sure the dialog template reflects this.
1797 static void PROPSHEET_SetWizButtons(HWND hwndDlg
, DWORD dwFlags
)
1799 HWND hwndBack
= GetDlgItem(hwndDlg
, IDC_BACK_BUTTON
);
1800 HWND hwndNext
= GetDlgItem(hwndDlg
, IDC_NEXT_BUTTON
);
1801 HWND hwndFinish
= GetDlgItem(hwndDlg
, IDC_FINISH_BUTTON
);
1803 TRACE("%ld\n", dwFlags
);
1805 EnableWindow(hwndBack
, FALSE
);
1806 EnableWindow(hwndNext
, FALSE
);
1807 EnableWindow(hwndFinish
, FALSE
);
1809 if (dwFlags
& PSWIZB_BACK
)
1810 EnableWindow(hwndBack
, TRUE
);
1812 if (dwFlags
& PSWIZB_NEXT
)
1814 /* Hide the Finish button */
1815 ShowWindow(hwndFinish
, SW_HIDE
);
1817 /* Show and enable the Next button */
1818 ShowWindow(hwndNext
, SW_SHOW
);
1819 EnableWindow(hwndNext
, TRUE
);
1821 /* Set the Next button as the default pushbutton */
1822 SendMessageA(hwndDlg
, DM_SETDEFID
, IDC_NEXT_BUTTON
, 0);
1825 if ((dwFlags
& PSWIZB_FINISH
) || (dwFlags
& PSWIZB_DISABLEDFINISH
))
1827 /* Hide the Next button */
1828 ShowWindow(hwndNext
, SW_HIDE
);
1830 /* Show the Finish button */
1831 ShowWindow(hwndFinish
, SW_SHOW
);
1833 if (dwFlags
& PSWIZB_FINISH
)
1834 EnableWindow(hwndFinish
, TRUE
);
1836 /* Set the Finish button as the default pushbutton */
1837 SendMessageA(hwndDlg
, DM_SETDEFID
, IDC_FINISH_BUTTON
, 0);
1841 /******************************************************************************
1842 * PROPSHEET_GetPageIndex
1844 * Given a HPROPSHEETPAGE, returns the index of the corresponding page from
1845 * the array of PropPageInfo.
1847 static int PROPSHEET_GetPageIndex(HPROPSHEETPAGE hpage
, PropSheetInfo
* psInfo
)
1852 while ((index
< psInfo
->nPages
) && (found
== FALSE
))
1854 if (psInfo
->proppage
[index
].hpage
== hpage
)
1866 /******************************************************************************
1869 static void PROPSHEET_CleanUp(HWND hwndDlg
)
1872 PropSheetInfo
* psInfo
= (PropSheetInfo
*) RemovePropA(hwndDlg
,
1876 if (HIWORD(psInfo
->ppshheader
.pszCaption
))
1877 HeapFree(GetProcessHeap(), 0, (LPVOID
)psInfo
->ppshheader
.pszCaption
);
1879 for (i
= 0; i
< psInfo
->nPages
; i
++)
1881 PROPSHEETPAGEA
* psp
= (PROPSHEETPAGEA
*)psInfo
->proppage
[i
].hpage
;
1883 if(psInfo
->proppage
[i
].hwndPage
)
1884 DestroyWindow(psInfo
->proppage
[i
].hwndPage
);
1888 if ((psp
->dwFlags
& PSP_USETITLE
) && psInfo
->proppage
[i
].pszText
)
1889 HeapFree(GetProcessHeap(), 0, (LPVOID
)psInfo
->proppage
[i
].pszText
);
1891 DestroyPropertySheetPage(psInfo
->proppage
[i
].hpage
);
1895 COMCTL32_Free(psInfo
->proppage
);
1896 COMCTL32_Free(psInfo
->strPropertiesFor
);
1897 ImageList_Destroy(psInfo
->hImageList
);
1899 GlobalFree((HGLOBAL
)psInfo
);
1902 /******************************************************************************
1903 * PropertySheet (COMCTL32.87)
1904 * PropertySheetA (COMCTL32.88)
1906 INT WINAPI
PropertySheetA(LPCPROPSHEETHEADERA lppsh
)
1909 PropSheetInfo
* psInfo
= (PropSheetInfo
*) GlobalAlloc(GPTR
,
1910 sizeof(PropSheetInfo
));
1914 PROPSHEET_CollectSheetInfo(lppsh
, psInfo
);
1916 psInfo
->proppage
= (PropPageInfo
*) COMCTL32_Alloc(sizeof(PropPageInfo
) *
1918 pByte
= (BYTE
*) psInfo
->ppshheader
.u3
.ppsp
;
1920 for (n
= i
= 0; i
< lppsh
->nPages
; i
++, n
++)
1922 if (!(lppsh
->dwFlags
& PSH_PROPSHEETPAGE
))
1923 psInfo
->proppage
[n
].hpage
= psInfo
->ppshheader
.u3
.phpage
[i
];
1926 psInfo
->proppage
[n
].hpage
= CreatePropertySheetPageA((LPCPROPSHEETPAGEA
)pByte
);
1927 pByte
+= ((LPPROPSHEETPAGEA
)pByte
)->dwSize
;
1930 if (!PROPSHEET_CollectPageInfo((LPCPROPSHEETPAGEA
)psInfo
->proppage
[n
].hpage
,
1933 if (lppsh
->dwFlags
& PSH_PROPSHEETPAGE
)
1934 DestroyPropertySheetPage(psInfo
->proppage
[n
].hpage
);
1940 bRet
= PROPSHEET_CreateDialog(psInfo
);
1945 /******************************************************************************
1946 * PropertySheetW (COMCTL32.89)
1948 INT WINAPI
PropertySheetW(LPCPROPSHEETHEADERW propertySheetHeader
)
1950 FIXME("(%p): stub\n", propertySheetHeader
);
1955 /******************************************************************************
1956 * CreatePropertySheetPage (COMCTL32.18)
1957 * CreatePropertySheetPageA (COMCTL32.19)
1959 HPROPSHEETPAGE WINAPI
CreatePropertySheetPageA(
1960 LPCPROPSHEETPAGEA lpPropSheetPage
)
1962 PROPSHEETPAGEA
* ppsp
= COMCTL32_Alloc(sizeof(PROPSHEETPAGEA
));
1964 memcpy(ppsp
,lpPropSheetPage
,min(lpPropSheetPage
->dwSize
,sizeof(PROPSHEETPAGEA
)));
1966 if ( !(ppsp
->dwFlags
& PSP_DLGINDIRECT
) && HIWORD( ppsp
->u
.pszTemplate
) )
1967 ppsp
->u
.pszTemplate
= HEAP_strdupA( GetProcessHeap(), 0, lpPropSheetPage
->u
.pszTemplate
);
1969 if ( (ppsp
->dwFlags
& PSP_USEICONID
) && HIWORD( ppsp
->u2
.pszIcon
) )
1970 ppsp
->u2
.pszIcon
= HEAP_strdupA( GetProcessHeap(), 0, lpPropSheetPage
->u2
.pszIcon
);
1973 if ((ppsp
->dwFlags
& PSP_USETITLE
) && HIWORD( ppsp
->pszTitle
))
1974 ppsp
->pszTitle
= HEAP_strdupA( GetProcessHeap(), 0, lpPropSheetPage
->pszTitle
);
1975 else if ( !(ppsp
->dwFlags
& PSP_USETITLE
) )
1976 ppsp
->pszTitle
= NULL
;
1978 return (HPROPSHEETPAGE
)ppsp
;
1981 /******************************************************************************
1982 * CreatePropertySheetPageW (COMCTL32.20)
1984 HPROPSHEETPAGE WINAPI
CreatePropertySheetPageW(LPCPROPSHEETPAGEW lpPropSheetPage
)
1986 FIXME("(%p): stub\n", lpPropSheetPage
);
1991 /******************************************************************************
1992 * DestroyPropertySheetPage (COMCTL32.24)
1994 BOOL WINAPI
DestroyPropertySheetPage(HPROPSHEETPAGE hPropPage
)
1996 PROPSHEETPAGEA
*psp
= (PROPSHEETPAGEA
*)hPropPage
;
2001 if ( !(psp
->dwFlags
& PSP_DLGINDIRECT
) && HIWORD( psp
->u
.pszTemplate
) )
2002 HeapFree(GetProcessHeap(), 0, (LPVOID
)psp
->u
.pszTemplate
);
2004 if ( (psp
->dwFlags
& PSP_USEICONID
) && HIWORD( psp
->u2
.pszIcon
) )
2005 HeapFree(GetProcessHeap(), 0, (LPVOID
)psp
->u2
.pszIcon
);
2007 if ((psp
->dwFlags
& PSP_USETITLE
) && HIWORD( psp
->pszTitle
))
2008 HeapFree(GetProcessHeap(), 0, (LPVOID
)psp
->pszTitle
);
2010 COMCTL32_Free(hPropPage
);
2015 /******************************************************************************
2016 * PROPSHEET_IsDialogMessage
2018 static BOOL
PROPSHEET_IsDialogMessage(HWND hwnd
, LPMSG lpMsg
)
2020 PropSheetInfo
* psInfo
= (PropSheetInfo
*) GetPropA(hwnd
, PropSheetInfoStr
);
2022 if (!psInfo
|| (hwnd
!= lpMsg
->hwnd
&& !IsChild(hwnd
, lpMsg
->hwnd
)))
2025 if (lpMsg
->message
== WM_KEYDOWN
&& (GetKeyState(VK_CONTROL
) & 0x8000))
2028 INT dlgCode
= SendMessageA(lpMsg
->hwnd
, WM_GETDLGCODE
, 0, (LPARAM
)lpMsg
);
2030 if (!(dlgCode
& DLGC_WANTMESSAGE
))
2032 switch (lpMsg
->wParam
)
2035 if (GetKeyState(VK_SHIFT
) & 0x8000)
2041 case VK_NEXT
: new_page
= 1; break;
2042 case VK_PRIOR
: new_page
= -1; break;
2048 if (PROPSHEET_CanSetCurSel(hwnd
) != FALSE
)
2050 new_page
+= psInfo
->active_page
;
2053 new_page
= psInfo
->nPages
- 1;
2054 else if (new_page
>= psInfo
->nPages
)
2057 PROPSHEET_SetCurSel(hwnd
, new_page
, 1, 0);
2064 return IsDialogMessageA(hwnd
, lpMsg
);
2067 /******************************************************************************
2068 * PROPSHEET_DialogProc
2071 PROPSHEET_DialogProc(HWND hwnd
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
)
2077 PropSheetInfo
* psInfo
= (PropSheetInfo
*) lParam
;
2078 char* strCaption
= (char*)COMCTL32_Alloc(MAX_CAPTION_LENGTH
);
2079 HWND hwndTabCtrl
= GetDlgItem(hwnd
, IDC_TABCONTROL
);
2080 LPCPROPSHEETPAGEA ppshpage
;
2083 SetPropA(hwnd
, PropSheetInfoStr
, (HANDLE
)psInfo
);
2086 * psInfo->hwnd is not being used by WINE code - it exists
2087 * for compatibility with "real" Windoze. The same about
2088 * SetWindowLong - WINE is only using the PropSheetInfoStr
2091 psInfo
->hwnd
= hwnd
;
2092 SetWindowLongA(hwnd
,DWL_USER
,(LONG
)psInfo
);
2095 * Small icon in the title bar.
2097 if ((psInfo
->ppshheader
.dwFlags
& PSH_USEICONID
) ||
2098 (psInfo
->ppshheader
.dwFlags
& PSH_USEHICON
))
2101 int icon_cx
= GetSystemMetrics(SM_CXSMICON
);
2102 int icon_cy
= GetSystemMetrics(SM_CYSMICON
);
2104 if (psInfo
->ppshheader
.dwFlags
& PSH_USEICONID
)
2105 hIcon
= LoadImageA(psInfo
->ppshheader
.hInstance
,
2106 psInfo
->ppshheader
.u
.pszIcon
,
2111 hIcon
= psInfo
->ppshheader
.u
.hIcon
;
2113 SendMessageA(hwnd
, WM_SETICON
, 0, hIcon
);
2116 if (psInfo
->ppshheader
.dwFlags
& PSH_USEHICON
)
2117 SendMessageA(hwnd
, WM_SETICON
, 0, psInfo
->ppshheader
.u
.hIcon
);
2119 psInfo
->strPropertiesFor
= strCaption
;
2121 GetWindowTextA(hwnd
, psInfo
->strPropertiesFor
, MAX_CAPTION_LENGTH
);
2123 PROPSHEET_CreateTabControl(hwnd
, psInfo
);
2125 if (psInfo
->ppshheader
.dwFlags
& PSH_WIZARD
)
2127 if (PROPSHEET_IsTooSmallWizard(hwnd
, psInfo
))
2129 PROPSHEET_AdjustSizeWizard(hwnd
, psInfo
);
2130 PROPSHEET_AdjustButtonsWizard(hwnd
, psInfo
);
2135 if (PROPSHEET_SizeMismatch(hwnd
, psInfo
))
2137 PROPSHEET_AdjustSize(hwnd
, psInfo
);
2138 PROPSHEET_AdjustButtons(hwnd
, psInfo
);
2142 if (psInfo
->useCallback
)
2143 (*(psInfo
->ppshheader
.pfnCallback
))(hwnd
,
2144 PSCB_INITIALIZED
, (LPARAM
)0);
2146 idx
= psInfo
->active_page
;
2147 ppshpage
= (LPCPROPSHEETPAGEA
)psInfo
->proppage
[idx
].hpage
;
2148 psInfo
->active_page
= -1;
2150 PROPSHEET_SetCurSel(hwnd
, idx
, 1, psInfo
->proppage
[idx
].hpage
);
2152 if (!(psInfo
->ppshheader
.dwFlags
& PSH_WIZARD
))
2153 SendMessageA(hwndTabCtrl
, TCM_SETCURSEL
, psInfo
->active_page
, 0);
2155 if (!HIWORD(psInfo
->ppshheader
.pszCaption
) &&
2156 psInfo
->ppshheader
.hInstance
)
2160 if (LoadStringA(psInfo
->ppshheader
.hInstance
,
2161 (UINT
)psInfo
->ppshheader
.pszCaption
, szText
, 255))
2162 PROPSHEET_SetTitleA(hwnd
, psInfo
->ppshheader
.dwFlags
, szText
);
2166 PROPSHEET_SetTitleA(hwnd
, psInfo
->ppshheader
.dwFlags
,
2167 psInfo
->ppshheader
.pszCaption
);
2174 PROPSHEET_CleanUp(hwnd
);
2178 PROPSHEET_Cancel(hwnd
, 1);
2183 WORD wID
= LOWORD(wParam
);
2188 case IDC_APPLY_BUTTON
:
2190 HWND hwndApplyBtn
= GetDlgItem(hwnd
, IDC_APPLY_BUTTON
);
2192 if (PROPSHEET_Apply(hwnd
, wID
== IDOK
? 1: 0) == FALSE
)
2197 PropSheetInfo
* psInfo
= (PropSheetInfo
*) GetPropA(hwnd
,
2201 if (psInfo
->restartWindows
)
2202 result
= ID_PSRESTARTWINDOWS
;
2204 /* reboot system takes precedence over restart windows */
2205 if (psInfo
->rebootSystem
)
2206 result
= ID_PSREBOOTSYSTEM
;
2208 if (psInfo
->isModeless
)
2209 psInfo
->activeValid
= FALSE
;
2211 EndDialog(hwnd
, result
);
2214 EnableWindow(hwndApplyBtn
, FALSE
);
2219 case IDC_BACK_BUTTON
:
2220 PROPSHEET_Back(hwnd
);
2223 case IDC_NEXT_BUTTON
:
2224 PROPSHEET_Next(hwnd
);
2227 case IDC_FINISH_BUTTON
:
2228 PROPSHEET_Finish(hwnd
);
2232 PROPSHEET_Cancel(hwnd
, 0);
2236 PROPSHEET_Help(hwnd
);
2245 NMHDR
* pnmh
= (LPNMHDR
) lParam
;
2247 if (pnmh
->code
== TCN_SELCHANGE
)
2249 int index
= SendMessageA(pnmh
->hwndFrom
, TCM_GETCURSEL
, 0, 0);
2250 PROPSHEET_SetCurSel(hwnd
, index
, 1, 0);
2253 if(pnmh
->code
== TCN_SELCHANGING
)
2255 BOOL bRet
= PROPSHEET_CanSetCurSel(hwnd
);
2256 SetWindowLongA(hwnd
, DWL_MSGRESULT
, !bRet
);
2263 case PSM_GETCURRENTPAGEHWND
:
2265 PropSheetInfo
* psInfo
= (PropSheetInfo
*) GetPropA(hwnd
,
2269 if (psInfo
->activeValid
&& psInfo
->active_page
!= -1)
2270 hwndPage
= psInfo
->proppage
[psInfo
->active_page
].hwndPage
;
2272 SetWindowLongA(hwnd
, DWL_MSGRESULT
, hwndPage
);
2278 PROPSHEET_Changed(hwnd
, (HWND
)wParam
);
2282 PROPSHEET_UnChanged(hwnd
, (HWND
)wParam
);
2285 case PSM_GETTABCONTROL
:
2287 HWND hwndTabCtrl
= GetDlgItem(hwnd
, IDC_TABCONTROL
);
2289 SetWindowLongA(hwnd
, DWL_MSGRESULT
, hwndTabCtrl
);
2298 msgResult
= PROPSHEET_CanSetCurSel(hwnd
);
2299 if(msgResult
!= FALSE
)
2301 msgResult
= PROPSHEET_SetCurSel(hwnd
,
2304 (HPROPSHEETPAGE
)lParam
);
2307 SetWindowLongA(hwnd
, DWL_MSGRESULT
, msgResult
);
2312 case PSM_CANCELTOCLOSE
:
2314 char buf
[MAX_BUTTONTEXT_LENGTH
];
2315 HWND hwndOK
= GetDlgItem(hwnd
, IDOK
);
2316 HWND hwndCancel
= GetDlgItem(hwnd
, IDCANCEL
);
2318 EnableWindow(hwndCancel
, FALSE
);
2319 if (LoadStringA(COMCTL32_hModule
, IDS_CLOSE
, buf
, sizeof(buf
)))
2320 SetWindowTextA(hwndOK
, buf
);
2325 case PSM_RESTARTWINDOWS
:
2327 PropSheetInfo
* psInfo
= (PropSheetInfo
*) GetPropA(hwnd
,
2330 psInfo
->restartWindows
= TRUE
;
2334 case PSM_REBOOTSYSTEM
:
2336 PropSheetInfo
* psInfo
= (PropSheetInfo
*) GetPropA(hwnd
,
2339 psInfo
->rebootSystem
= TRUE
;
2344 PROPSHEET_SetTitleA(hwnd
, (DWORD
) wParam
, (LPCSTR
) lParam
);
2349 BOOL msgResult
= PROPSHEET_Apply(hwnd
, 0);
2351 SetWindowLongA(hwnd
, DWL_MSGRESULT
, msgResult
);
2356 case PSM_QUERYSIBLINGS
:
2358 LRESULT msgResult
= PROPSHEET_QuerySiblings(hwnd
, wParam
, lParam
);
2360 SetWindowLongA(hwnd
, DWL_MSGRESULT
, msgResult
);
2368 * Note: MSVC++ 6.0 documentation says that PSM_ADDPAGE does not have
2369 * a return value. This is not true. PSM_ADDPAGE returns TRUE
2370 * on success or FALSE otherwise, as specified on MSDN Online.
2371 * Also see the MFC code for
2372 * CPropertySheet::AddPage(CPropertyPage* pPage).
2375 BOOL msgResult
= PROPSHEET_AddPage(hwnd
, (HPROPSHEETPAGE
)lParam
);
2377 SetWindowLongA(hwnd
, DWL_MSGRESULT
, msgResult
);
2382 case PSM_REMOVEPAGE
:
2383 PROPSHEET_RemovePage(hwnd
, (int)wParam
, (HPROPSHEETPAGE
)lParam
);
2386 case PSM_ISDIALOGMESSAGE
:
2388 BOOL msgResult
= PROPSHEET_IsDialogMessage(hwnd
, (LPMSG
)lParam
);
2389 SetWindowLongA(hwnd
, DWL_MSGRESULT
, msgResult
);
2393 case PSM_PRESSBUTTON
:
2394 PROPSHEET_PressButton(hwnd
, (int)wParam
);
2397 case PSM_SETFINISHTEXTA
:
2398 PROPSHEET_SetFinishTextA(hwnd
, (LPCSTR
) lParam
);
2401 case PSM_SETWIZBUTTONS
:
2402 PROPSHEET_SetWizButtons(hwnd
, (DWORD
)lParam
);
2406 FIXME("Unimplemented msg PSM_SETTITLE32W\n");
2409 case PSM_SETCURSELID
:
2410 FIXME("Unimplemented msg PSM_SETCURSELID\n");
2413 case PSM_SETFINISHTEXTW
:
2414 FIXME("Unimplemented msg PSM_SETFINISHTEXT32W\n");