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
))
157 psInfo
->ppshheader
.pszCaption
= HeapAlloc( GetProcessHeap(), 0, strlen(lppsh
->pszCaption
)+1 );
158 strcpy( (char *)psInfo
->ppshheader
.pszCaption
, lppsh
->pszCaption
);
160 psInfo
->nPages
= lppsh
->nPages
;
162 if (dwFlags
& PSH_USEPSTARTPAGE
)
164 TRACE("PSH_USEPSTARTPAGE is on");
165 psInfo
->active_page
= 0;
168 psInfo
->active_page
= lppsh
->u2
.nStartPage
;
170 if (psInfo
->active_page
< 0 || psInfo
->active_page
>= psInfo
->nPages
)
171 psInfo
->active_page
= 0;
173 psInfo
->restartWindows
= FALSE
;
174 psInfo
->rebootSystem
= FALSE
;
175 psInfo
->hImageList
= 0;
176 psInfo
->activeValid
= FALSE
;
181 /******************************************************************************
182 * PROPSHEET_CollectPageInfo
184 * Collect property sheet data.
185 * With code taken from DIALOG_ParseTemplate32.
187 BOOL
PROPSHEET_CollectPageInfo(LPCPROPSHEETPAGEA lppsp
,
188 PropSheetInfo
* psInfo
,
191 DLGTEMPLATE
* pTemplate
;
196 psInfo
->proppage
[index
].hpage
= (HPROPSHEETPAGE
)lppsp
;
197 psInfo
->proppage
[index
].hwndPage
= 0;
198 psInfo
->proppage
[index
].isDirty
= FALSE
;
201 * Process property page flags.
203 dwFlags
= lppsp
->dwFlags
;
204 psInfo
->proppage
[index
].useCallback
= (dwFlags
& PSP_USECALLBACK
) && (lppsp
->pfnCallback
);
205 psInfo
->proppage
[index
].hasHelp
= dwFlags
& PSP_HASHELP
;
206 psInfo
->proppage
[index
].hasIcon
= dwFlags
& (PSP_USEHICON
| PSP_USEICONID
);
208 /* as soon as we have a page with the help flag, set the sheet flag on */
209 if (psInfo
->proppage
[index
].hasHelp
)
210 psInfo
->hasHelp
= TRUE
;
213 * Process page template.
215 if (dwFlags
& PSP_DLGINDIRECT
)
216 pTemplate
= (DLGTEMPLATE
*)lppsp
->u
.pResource
;
219 HRSRC hResource
= FindResourceA(lppsp
->hInstance
,
220 lppsp
->u
.pszTemplate
,
222 HGLOBAL hTemplate
= LoadResource(lppsp
->hInstance
,
224 pTemplate
= (LPDLGTEMPLATEA
)LockResource(hTemplate
);
228 * Extract the size of the page and the caption.
233 p
= (const WORD
*)pTemplate
;
235 if (((MyDLGTEMPLATEEX
*)pTemplate
)->signature
== 0xFFFF)
237 /* DIALOGEX template */
241 p
+= 2; /* help ID */
242 p
+= 2; /* ext style */
247 /* DIALOG template */
250 p
+= 2; /* ext style */
256 width
= (WORD
)*p
; p
++;
257 height
= (WORD
)*p
; p
++;
259 /* remember the largest width and height */
260 if (width
> psInfo
->width
)
261 psInfo
->width
= width
;
263 if (height
> psInfo
->height
)
264 psInfo
->height
= height
;
276 p
+= lstrlenW( (LPCWSTR
)p
) + 1;
290 p
+= lstrlenW( (LPCWSTR
)p
) + 1;
294 /* Extract the caption */
295 psInfo
->proppage
[index
].pszText
= (LPCWSTR
)p
;
296 TRACE("Tab %d %s\n",index
,debugstr_w((LPCWSTR
)p
));
297 p
+= lstrlenW((LPCWSTR
)p
) + 1;
299 if (dwFlags
& PSP_USETITLE
)
301 if ( !HIWORD( lppsp
->pszTitle
) )
305 if (LoadStringA( lppsp
->hInstance
, (UINT
)lppsp
->pszTitle
,szTitle
,256 )) {
306 psInfo
->proppage
[index
].pszText
= HEAP_strdupAtoW( GetProcessHeap(), 0, szTitle
);
308 psInfo
->proppage
[index
].pszText
= HEAP_strdupAtoW( GetProcessHeap(), 0, "(null)" );
309 FIXME("Could not load resource #%04x?\n",LOWORD(lppsp
->pszTitle
));
313 psInfo
->proppage
[index
].pszText
= HEAP_strdupAtoW(GetProcessHeap(),
319 * Build the image list for icons
321 if ((dwFlags
& PSP_USEHICON
) || (dwFlags
& PSP_USEICONID
))
324 int icon_cx
= GetSystemMetrics(SM_CXSMICON
);
325 int icon_cy
= GetSystemMetrics(SM_CYSMICON
);
327 if (dwFlags
& PSP_USEICONID
)
328 hIcon
= LoadImageA(lppsp
->hInstance
, lppsp
->u2
.pszIcon
, IMAGE_ICON
,
329 icon_cx
, icon_cy
, LR_DEFAULTCOLOR
);
331 hIcon
= lppsp
->u2
.hIcon
;
335 if (psInfo
->hImageList
== 0 )
336 psInfo
->hImageList
= ImageList_Create(icon_cx
, icon_cy
, ILC_COLOR
, 1, 1);
338 ImageList_AddIcon(psInfo
->hImageList
, hIcon
);
347 /******************************************************************************
348 * PROPSHEET_CreateDialog
350 * Creates the actual property sheet.
352 BOOL
PROPSHEET_CreateDialog(PropSheetInfo
* psInfo
)
359 WORD resID
= IDD_PROPSHEET
;
361 if (psInfo
->ppshheader
.dwFlags
& PSH_WIZARD
)
364 if(!(hRes
= FindResourceA(COMCTL32_hModule
,
365 MAKEINTRESOURCEA(resID
),
369 if(!(template = (LPVOID
)LoadResource(COMCTL32_hModule
, hRes
)))
373 * Make a copy of the dialog template.
375 resSize
= SizeofResource(COMCTL32_hModule
, hRes
);
377 temp
= COMCTL32_Alloc(resSize
);
382 memcpy(temp
, template, resSize
);
384 if (psInfo
->useCallback
)
385 (*(psInfo
->ppshheader
.pfnCallback
))(0, PSCB_PRECREATE
, (LPARAM
)temp
);
387 if (!(psInfo
->ppshheader
.dwFlags
& PSH_MODELESS
))
388 ret
= DialogBoxIndirectParamA(psInfo
->ppshheader
.hInstance
,
389 (LPDLGTEMPLATEA
) temp
,
390 psInfo
->ppshheader
.hwndParent
,
391 (DLGPROC
) PROPSHEET_DialogProc
,
394 ret
= CreateDialogIndirectParamA(psInfo
->ppshheader
.hInstance
,
395 (LPDLGTEMPLATEA
) temp
,
396 psInfo
->ppshheader
.hwndParent
,
397 (DLGPROC
) PROPSHEET_DialogProc
,
405 /******************************************************************************
406 * PROPSHEET_SizeMismatch
408 * Verify that the tab control and the "largest" property sheet page dlg. template
411 static BOOL
PROPSHEET_SizeMismatch(HWND hwndDlg
, PropSheetInfo
* psInfo
)
413 HWND hwndTabCtrl
= GetDlgItem(hwndDlg
, IDC_TABCONTROL
);
414 RECT rcOrigTab
, rcPage
;
419 GetClientRect(hwndTabCtrl
, &rcOrigTab
);
420 TRACE("orig tab %d %d %d %d\n", rcOrigTab
.left
, rcOrigTab
.top
,
421 rcOrigTab
.right
, rcOrigTab
.bottom
);
426 rcPage
.left
= psInfo
->x
;
427 rcPage
.top
= psInfo
->y
;
428 rcPage
.right
= psInfo
->width
;
429 rcPage
.bottom
= psInfo
->height
;
431 MapDialogRect(hwndDlg
, &rcPage
);
432 TRACE("biggest page %d %d %d %d\n", rcPage
.left
, rcPage
.top
,
433 rcPage
.right
, rcPage
.bottom
);
435 if ( (rcPage
.right
- rcPage
.left
) != (rcOrigTab
.right
- rcOrigTab
.left
) )
437 if ( (rcPage
.bottom
- rcPage
.top
) != (rcOrigTab
.bottom
- rcOrigTab
.top
) )
443 /******************************************************************************
444 * PROPSHEET_IsTooSmallWizard
446 * Verify that the default property sheet is big enough.
448 static BOOL
PROPSHEET_IsTooSmallWizard(HWND hwndDlg
, PropSheetInfo
* psInfo
)
450 RECT rcSheetRect
, rcPage
, rcLine
, rcSheetClient
;
451 HWND hwndLine
= GetDlgItem(hwndDlg
, IDC_SUNKEN_LINE
);
452 PADDING_INFO padding
= PROPSHEET_GetPaddingInfoWizard(hwndDlg
, psInfo
);
454 GetClientRect(hwndDlg
, &rcSheetClient
);
455 GetWindowRect(hwndDlg
, &rcSheetRect
);
456 GetWindowRect(hwndLine
, &rcLine
);
458 /* Remove the space below the sunken line */
459 rcSheetClient
.bottom
-= (rcSheetRect
.bottom
- rcLine
.top
);
461 /* Remove the buffer zone all around the edge */
462 rcSheetClient
.bottom
-= (padding
.y
* 2);
463 rcSheetClient
.right
-= (padding
.x
* 2);
468 rcPage
.left
= psInfo
->x
;
469 rcPage
.top
= psInfo
->y
;
470 rcPage
.right
= psInfo
->width
;
471 rcPage
.bottom
= psInfo
->height
;
473 MapDialogRect(hwndDlg
, &rcPage
);
474 TRACE("biggest page %d %d %d %d\n", rcPage
.left
, rcPage
.top
,
475 rcPage
.right
, rcPage
.bottom
);
477 if (rcPage
.right
> rcSheetClient
.right
)
480 if (rcPage
.bottom
> rcSheetClient
.bottom
)
486 /******************************************************************************
487 * PROPSHEET_AdjustSize
489 * Resizes the property sheet and the tab control to fit the largest page.
491 static BOOL
PROPSHEET_AdjustSize(HWND hwndDlg
, PropSheetInfo
* psInfo
)
493 HWND hwndTabCtrl
= GetDlgItem(hwndDlg
, IDC_TABCONTROL
);
494 HWND hwndButton
= GetDlgItem(hwndDlg
, IDOK
);
496 int tabOffsetX
, tabOffsetY
, buttonHeight
;
497 PADDING_INFO padding
= PROPSHEET_GetPaddingInfo(hwndDlg
);
500 /* Get the height of buttons */
501 GetClientRect(hwndButton
, &rc
);
502 buttonHeight
= rc
.bottom
;
509 rc
.right
= psInfo
->width
;
510 rc
.bottom
= psInfo
->height
;
512 MapDialogRect(hwndDlg
, &rc
);
514 /* retrieve the dialog units */
515 units
.left
= units
.right
= 4;
516 units
.top
= units
.bottom
= 8;
517 MapDialogRect(hwndDlg
, &units
);
520 * Resize the tab control.
522 GetClientRect(hwndTabCtrl
,&tabRect
);
524 SendMessageA(hwndTabCtrl
, TCM_ADJUSTRECT
, FALSE
, (LPARAM
)&tabRect
);
526 if ((rc
.bottom
- rc
.top
) < (tabRect
.bottom
- tabRect
.top
))
528 rc
.bottom
= rc
.top
+ tabRect
.bottom
- tabRect
.top
;
529 psInfo
->height
= MulDiv((rc
.bottom
- rc
.top
),8,units
.top
);
532 if ((rc
.right
- rc
.left
) < (tabRect
.right
- tabRect
.left
))
534 rc
.right
= rc
.left
+ tabRect
.right
- tabRect
.left
;
535 psInfo
->width
= MulDiv((rc
.right
- rc
.left
),4,units
.left
);
538 SendMessageA(hwndTabCtrl
, TCM_ADJUSTRECT
, TRUE
, (LPARAM
)&rc
);
540 tabOffsetX
= -(rc
.left
);
541 tabOffsetY
= -(rc
.top
);
545 SetWindowPos(hwndTabCtrl
, 0, 0, 0, rc
.right
, rc
.bottom
,
546 SWP_NOMOVE
| SWP_NOZORDER
| SWP_NOACTIVATE
);
548 GetClientRect(hwndTabCtrl
, &rc
);
550 TRACE("tab client rc %d %d %d %d\n",
551 rc
.left
, rc
.top
, rc
.right
, rc
.bottom
);
553 rc
.right
+= ((padding
.x
* 2) + tabOffsetX
);
554 rc
.bottom
+= (buttonHeight
+ (3 * padding
.y
) + tabOffsetY
);
557 * Resize the property sheet.
559 SetWindowPos(hwndDlg
, 0, 0, 0, rc
.right
, rc
.bottom
,
560 SWP_NOMOVE
| SWP_NOZORDER
| SWP_NOACTIVATE
);
564 /******************************************************************************
565 * PROPSHEET_AdjustSizeWizard
567 * Resizes the property sheet to fit the largest page.
569 static BOOL
PROPSHEET_AdjustSizeWizard(HWND hwndDlg
, PropSheetInfo
* psInfo
)
571 HWND hwndButton
= GetDlgItem(hwndDlg
, IDCANCEL
);
572 HWND hwndLine
= GetDlgItem(hwndDlg
, IDC_SUNKEN_LINE
);
573 HWND hwndTabCtrl
= GetDlgItem(hwndDlg
, IDC_TABCONTROL
);
575 int buttonHeight
, lineHeight
;
576 PADDING_INFO padding
= PROPSHEET_GetPaddingInfoWizard(hwndDlg
, psInfo
);
579 /* Get the height of buttons */
580 GetClientRect(hwndButton
, &rc
);
581 buttonHeight
= rc
.bottom
;
583 GetClientRect(hwndLine
, &rc
);
584 lineHeight
= rc
.bottom
;
586 /* retrieve the dialog units */
587 units
.left
= units
.right
= 4;
588 units
.top
= units
.bottom
= 8;
589 MapDialogRect(hwndDlg
, &units
);
596 rc
.right
= psInfo
->width
;
597 rc
.bottom
= psInfo
->height
;
599 MapDialogRect(hwndDlg
, &rc
);
601 GetClientRect(hwndTabCtrl
,&tabRect
);
603 if ((rc
.bottom
- rc
.top
) < (tabRect
.bottom
- tabRect
.top
))
605 rc
.bottom
= rc
.top
+ tabRect
.bottom
- tabRect
.top
;
606 psInfo
->height
= MulDiv((rc
.bottom
- rc
.top
), 8, units
.top
);
609 if ((rc
.right
- rc
.left
) < (tabRect
.right
- tabRect
.left
))
611 rc
.right
= rc
.left
+ tabRect
.right
- tabRect
.left
;
612 psInfo
->width
= MulDiv((rc
.right
- rc
.left
), 4, units
.left
);
615 TRACE("Biggest page %d %d %d %d\n", rc
.left
, rc
.top
, rc
.right
, rc
.bottom
);
618 rc
.right
+= (padding
.x
* 2);
619 rc
.bottom
+= (buttonHeight
+ (5 * padding
.y
) + lineHeight
);
622 * Resize the property sheet.
624 SetWindowPos(hwndDlg
, 0, 0, 0, rc
.right
, rc
.bottom
,
625 SWP_NOMOVE
| SWP_NOZORDER
| SWP_NOACTIVATE
);
629 /******************************************************************************
630 * PROPSHEET_AdjustButtons
632 * Adjusts the buttons' positions.
634 static BOOL
PROPSHEET_AdjustButtons(HWND hwndParent
, PropSheetInfo
* psInfo
)
636 HWND hwndButton
= GetDlgItem(hwndParent
, IDOK
);
640 int buttonWidth
, buttonHeight
;
641 PADDING_INFO padding
= PROPSHEET_GetPaddingInfo(hwndParent
);
643 if (psInfo
->hasApply
)
650 * Obtain the size of the buttons.
652 GetClientRect(hwndButton
, &rcSheet
);
653 buttonWidth
= rcSheet
.right
;
654 buttonHeight
= rcSheet
.bottom
;
657 * Get the size of the property sheet.
659 GetClientRect(hwndParent
, &rcSheet
);
662 * All buttons will be at this y coordinate.
664 y
= rcSheet
.bottom
- (padding
.y
+ buttonHeight
);
667 * Position OK button.
669 hwndButton
= GetDlgItem(hwndParent
, IDOK
);
671 x
= rcSheet
.right
- ((padding
.x
+ buttonWidth
) * num_buttons
);
673 SetWindowPos(hwndButton
, 0, x
, y
, 0, 0,
674 SWP_NOSIZE
| SWP_NOZORDER
| SWP_NOACTIVATE
);
677 * Position Cancel button.
679 hwndButton
= GetDlgItem(hwndParent
, IDCANCEL
);
681 x
= rcSheet
.right
- ((padding
.x
+ buttonWidth
) * (num_buttons
- 1));
683 SetWindowPos(hwndButton
, 0, x
, y
, 0, 0,
684 SWP_NOSIZE
| SWP_NOZORDER
| SWP_NOACTIVATE
);
687 * Position Apply button.
689 hwndButton
= GetDlgItem(hwndParent
, IDC_APPLY_BUTTON
);
691 if (psInfo
->hasApply
)
694 x
= rcSheet
.right
- ((padding
.x
+ buttonWidth
) * 2);
696 x
= rcSheet
.right
- (padding
.x
+ buttonWidth
);
698 SetWindowPos(hwndButton
, 0, x
, y
, 0, 0,
699 SWP_NOSIZE
| SWP_NOZORDER
| SWP_NOACTIVATE
);
701 EnableWindow(hwndButton
, FALSE
);
704 ShowWindow(hwndButton
, SW_HIDE
);
707 * Position Help button.
709 hwndButton
= GetDlgItem(hwndParent
, IDHELP
);
713 x
= rcSheet
.right
- (padding
.x
+ buttonWidth
);
715 SetWindowPos(hwndButton
, 0, x
, y
, 0, 0,
716 SWP_NOSIZE
| SWP_NOZORDER
| SWP_NOACTIVATE
);
719 ShowWindow(hwndButton
, SW_HIDE
);
724 /******************************************************************************
725 * PROPSHEET_AdjustButtonsWizard
727 * Adjusts the buttons' positions.
729 static BOOL
PROPSHEET_AdjustButtonsWizard(HWND hwndParent
,
730 PropSheetInfo
* psInfo
)
732 HWND hwndButton
= GetDlgItem(hwndParent
, IDCANCEL
);
733 HWND hwndLine
= GetDlgItem(hwndParent
, IDC_SUNKEN_LINE
);
737 int buttonWidth
, buttonHeight
, lineHeight
, lineWidth
;
738 PADDING_INFO padding
= PROPSHEET_GetPaddingInfoWizard(hwndParent
, psInfo
);
744 * Obtain the size of the buttons.
746 GetClientRect(hwndButton
, &rcSheet
);
747 buttonWidth
= rcSheet
.right
;
748 buttonHeight
= rcSheet
.bottom
;
750 GetClientRect(hwndLine
, &rcSheet
);
751 lineHeight
= rcSheet
.bottom
;
754 * Get the size of the property sheet.
756 GetClientRect(hwndParent
, &rcSheet
);
759 * All buttons will be at this y coordinate.
761 y
= rcSheet
.bottom
- (padding
.y
+ buttonHeight
);
764 * Position the Next and the Finish buttons.
766 hwndButton
= GetDlgItem(hwndParent
, IDC_NEXT_BUTTON
);
768 x
= rcSheet
.right
- ((padding
.x
+ buttonWidth
) * (num_buttons
- 1));
770 SetWindowPos(hwndButton
, 0, x
, y
, 0, 0,
771 SWP_NOSIZE
| SWP_NOZORDER
| SWP_NOACTIVATE
);
773 hwndButton
= GetDlgItem(hwndParent
, IDC_FINISH_BUTTON
);
775 SetWindowPos(hwndButton
, 0, x
, y
, 0, 0,
776 SWP_NOSIZE
| SWP_NOZORDER
| SWP_NOACTIVATE
);
778 ShowWindow(hwndButton
, SW_HIDE
);
781 * Position the Back button.
783 hwndButton
= GetDlgItem(hwndParent
, IDC_BACK_BUTTON
);
787 SetWindowPos(hwndButton
, 0, x
, y
, 0, 0,
788 SWP_NOSIZE
| SWP_NOZORDER
| SWP_NOACTIVATE
);
791 * Position the Cancel button.
793 hwndButton
= GetDlgItem(hwndParent
, IDCANCEL
);
795 x
= rcSheet
.right
- ((padding
.x
+ buttonWidth
) * (num_buttons
- 2));
797 SetWindowPos(hwndButton
, 0, x
, y
, 0, 0,
798 SWP_NOSIZE
| SWP_NOZORDER
| SWP_NOACTIVATE
);
801 * Position Help button.
803 hwndButton
= GetDlgItem(hwndParent
, IDHELP
);
807 x
= rcSheet
.right
- (padding
.x
+ buttonWidth
);
809 SetWindowPos(hwndButton
, 0, x
, y
, 0, 0,
810 SWP_NOSIZE
| SWP_NOZORDER
| SWP_NOACTIVATE
);
813 ShowWindow(hwndButton
, SW_HIDE
);
816 * Position and resize the sunken line.
819 y
= rcSheet
.bottom
- ((padding
.y
* 2) + buttonHeight
+ lineHeight
);
821 GetClientRect(hwndParent
, &rcSheet
);
822 lineWidth
= rcSheet
.right
- (padding
.x
* 2);
824 SetWindowPos(hwndLine
, 0, x
, y
, lineWidth
, 2,
825 SWP_NOZORDER
| SWP_NOACTIVATE
);
830 /******************************************************************************
831 * PROPSHEET_GetPaddingInfo
833 * Returns the layout information.
835 static PADDING_INFO
PROPSHEET_GetPaddingInfo(HWND hwndDlg
)
837 HWND hwndTab
= GetDlgItem(hwndDlg
, IDC_TABCONTROL
);
840 PADDING_INFO padding
;
842 GetWindowRect(hwndTab
, &rcTab
);
847 ScreenToClient(hwndDlg
, &tl
);
855 /******************************************************************************
856 * PROPSHEET_GetPaddingInfoWizard
858 * Returns the layout information.
859 * Vertical spacing is the distance between the line and the buttons.
860 * Do NOT use the Help button to gather padding information when it isn't mapped
861 * (PSH_HASHELP), as app writers aren't forced to supply correct coordinates
862 * for it in this case !
863 * FIXME: I'm not sure about any other coordinate problems with these evil
864 * buttons. Fix it in case additional problems appear or maybe calculate
865 * a padding in a completely different way, as this is somewhat messy.
867 static PADDING_INFO
PROPSHEET_GetPaddingInfoWizard(HWND hwndDlg
, const PropSheetInfo
*
870 PADDING_INFO padding
;
874 POINT ptButton
, ptLine
;
882 if (psInfo
->ppshheader
.dwFlags
& PSH_WIZARD
)
884 idButton
= IDC_NEXT_BUTTON
;
888 /* hopefully this is ok */
893 hwndControl
= GetDlgItem(hwndDlg
, idButton
);
894 GetWindowRect(hwndControl
, &rc
);
896 ptButton
.x
= rc
.left
;
899 ScreenToClient(hwndDlg
, &ptButton
);
902 hwndControl
= GetDlgItem(hwndDlg
, IDC_SUNKEN_LINE
);
903 GetWindowRect(hwndControl
, &rc
);
906 ptLine
.y
= rc
.bottom
;
908 ScreenToClient(hwndDlg
, &ptLine
);
910 padding
.y
= ptButton
.y
- ptLine
.y
;
913 ERR("padding negative ! Please report this !\n");
915 /* this is most probably not correct, but the best we have now */
916 padding
.x
= padding
.y
;
920 /******************************************************************************
921 * PROPSHEET_CreateTabControl
923 * Insert the tabs in the tab control.
925 static BOOL
PROPSHEET_CreateTabControl(HWND hwndParent
,
926 PropSheetInfo
* psInfo
)
928 HWND hwndTabCtrl
= GetDlgItem(hwndParent
, IDC_TABCONTROL
);
932 char tabtext
[MAX_TABTEXT_LENGTH
] = "Tab text";
934 item
.mask
= TCIF_TEXT
;
935 item
.pszText
= tabtext
;
936 item
.cchTextMax
= MAX_TABTEXT_LENGTH
;
938 nTabs
= psInfo
->nPages
;
941 * Set the image list for icons.
943 if (psInfo
->hImageList
)
945 SendMessageA(hwndTabCtrl
, TCM_SETIMAGELIST
, 0, (LPARAM
)psInfo
->hImageList
);
948 for (i
= 0; i
< nTabs
; i
++)
950 if ( psInfo
->proppage
[i
].hasIcon
)
952 item
.mask
|= TCIF_IMAGE
;
953 item
.iImage
= iImage
++;
957 item
.mask
&= ~TCIF_IMAGE
;
960 WideCharToMultiByte(CP_ACP
, 0,
961 (LPCWSTR
)psInfo
->proppage
[i
].pszText
,
962 -1, tabtext
, MAX_TABTEXT_LENGTH
, NULL
, NULL
);
964 SendMessageA(hwndTabCtrl
, TCM_INSERTITEMA
, (WPARAM
)i
, (LPARAM
)&item
);
970 /******************************************************************************
971 * PROPSHEET_CreatePage
975 static BOOL
PROPSHEET_CreatePage(HWND hwndParent
,
977 const PropSheetInfo
* psInfo
,
978 LPCPROPSHEETPAGEA ppshpage
)
980 DLGTEMPLATE
* pTemplate
;
983 PropPageInfo
* ppInfo
= psInfo
->proppage
;
984 PADDING_INFO padding
;
985 UINT pageWidth
,pageHeight
;
989 TRACE("index %d\n", index
);
991 if (ppshpage
->dwFlags
& PSP_DLGINDIRECT
)
992 pTemplate
= (DLGTEMPLATE
*)ppshpage
->u
.pResource
;
998 hResource
= FindResourceA(ppshpage
->hInstance
,
999 ppshpage
->u
.pszTemplate
,
1004 resSize
= SizeofResource(ppshpage
->hInstance
, hResource
);
1006 hTemplate
= LoadResource(ppshpage
->hInstance
, hResource
);
1010 pTemplate
= (LPDLGTEMPLATEA
)LockResource(hTemplate
);
1012 * Make a copy of the dialog template to make it writable
1014 temp
= COMCTL32_Alloc(resSize
);
1018 memcpy(temp
, pTemplate
, resSize
);
1022 if (((MyDLGTEMPLATEEX
*)pTemplate
)->signature
== 0xFFFF)
1024 ((MyDLGTEMPLATEEX
*)pTemplate
)->style
|= WS_CHILD
| DS_CONTROL
;
1025 ((MyDLGTEMPLATEEX
*)pTemplate
)->style
&= ~DS_MODALFRAME
;
1026 ((MyDLGTEMPLATEEX
*)pTemplate
)->style
&= ~WS_CAPTION
;
1027 ((MyDLGTEMPLATEEX
*)pTemplate
)->style
&= ~WS_SYSMENU
;
1028 ((MyDLGTEMPLATEEX
*)pTemplate
)->style
&= ~WS_POPUP
;
1029 ((MyDLGTEMPLATEEX
*)pTemplate
)->style
&= ~WS_DISABLED
;
1030 ((MyDLGTEMPLATEEX
*)pTemplate
)->style
&= ~WS_VISIBLE
;
1034 pTemplate
->style
|= WS_CHILD
| DS_CONTROL
;
1035 pTemplate
->style
&= ~DS_MODALFRAME
;
1036 pTemplate
->style
&= ~WS_CAPTION
;
1037 pTemplate
->style
&= ~WS_SYSMENU
;
1038 pTemplate
->style
&= ~WS_POPUP
;
1039 pTemplate
->style
&= ~WS_DISABLED
;
1040 pTemplate
->style
&= ~WS_VISIBLE
;
1043 if (psInfo
->proppage
[index
].useCallback
)
1044 (*(ppshpage
->pfnCallback
))(hwndParent
,
1046 (LPPROPSHEETPAGEA
)ppshpage
);
1048 hwndPage
= CreateDialogIndirectParamA(ppshpage
->hInstance
,
1051 ppshpage
->pfnDlgProc
,
1053 /* Free a no more needed copy */
1055 COMCTL32_Free(temp
);
1057 ppInfo
[index
].hwndPage
= hwndPage
;
1059 rc
.left
= psInfo
->x
;
1061 rc
.right
= psInfo
->width
;
1062 rc
.bottom
= psInfo
->height
;
1064 MapDialogRect(hwndParent
, &rc
);
1066 pageWidth
= rc
.right
- rc
.left
;
1067 pageHeight
= rc
.bottom
- rc
.top
;
1069 if (psInfo
->ppshheader
.dwFlags
& PSH_WIZARD
)
1070 padding
= PROPSHEET_GetPaddingInfoWizard(hwndParent
, psInfo
);
1074 * Ask the Tab control to fit this page in.
1077 HWND hwndTabCtrl
= GetDlgItem(hwndParent
, IDC_TABCONTROL
);
1078 SendMessageA(hwndTabCtrl
, TCM_ADJUSTRECT
, FALSE
, (LPARAM
)&rc
);
1079 padding
= PROPSHEET_GetPaddingInfo(hwndParent
);
1082 SetWindowPos(hwndPage
, HWND_TOP
,
1083 rc
.left
+ padding
.x
,
1085 pageWidth
, pageHeight
, 0);
1090 /******************************************************************************
1091 * PROPSHEET_ShowPage
1093 * Displays or creates the specified page.
1095 static BOOL
PROPSHEET_ShowPage(HWND hwndDlg
, int index
, PropSheetInfo
* psInfo
)
1097 if (index
== psInfo
->active_page
)
1099 if (GetTopWindow(hwndDlg
) != psInfo
->proppage
[index
].hwndPage
)
1100 SetWindowPos(psInfo
->proppage
[index
].hwndPage
, HWND_TOP
, 0, 0, 0, 0, SWP_NOSIZE
| SWP_NOMOVE
);
1104 if (psInfo
->proppage
[index
].hwndPage
== 0)
1106 LPCPROPSHEETPAGEA ppshpage
;
1108 ppshpage
= (LPCPROPSHEETPAGEA
)psInfo
->proppage
[index
].hpage
;
1109 PROPSHEET_CreatePage(hwndDlg
, index
, psInfo
, ppshpage
);
1112 if (psInfo
->active_page
!= -1)
1113 ShowWindow(psInfo
->proppage
[psInfo
->active_page
].hwndPage
, SW_HIDE
);
1115 ShowWindow(psInfo
->proppage
[index
].hwndPage
, SW_SHOW
);
1117 if (!(psInfo
->ppshheader
.dwFlags
& PSH_WIZARD
))
1121 /* Synchronize current selection with tab control */
1122 hwndTabCtrl
= GetDlgItem(hwndDlg
, IDC_TABCONTROL
);
1123 SendMessageA(hwndTabCtrl
, TCM_SETCURSEL
, index
, 0);
1126 psInfo
->active_page
= index
;
1127 psInfo
->activeValid
= TRUE
;
1132 /******************************************************************************
1135 static BOOL
PROPSHEET_Back(HWND hwndDlg
)
1140 PropSheetInfo
* psInfo
= (PropSheetInfo
*) GetPropA(hwndDlg
,
1144 if (psInfo
->active_page
< 0)
1147 psn
.hdr
.code
= PSN_WIZBACK
;
1148 psn
.hdr
.hwndFrom
= hwndDlg
;
1152 hwndPage
= psInfo
->proppage
[psInfo
->active_page
].hwndPage
;
1154 result
= SendMessageA(hwndPage
, WM_NOTIFY
, 0, (LPARAM
) &psn
);
1158 if (psInfo
->active_page
> 0)
1160 res
= PROPSHEET_CanSetCurSel(hwndDlg
);
1163 res
= PROPSHEET_SetCurSel(hwndDlg
, psInfo
->active_page
- 1, -1, 0);
1170 /******************************************************************************
1173 static BOOL
PROPSHEET_Next(HWND hwndDlg
)
1177 LRESULT msgResult
= 0;
1178 PropSheetInfo
* psInfo
= (PropSheetInfo
*) GetPropA(hwndDlg
,
1181 if (psInfo
->active_page
< 0)
1184 psn
.hdr
.code
= PSN_WIZNEXT
;
1185 psn
.hdr
.hwndFrom
= hwndDlg
;
1189 hwndPage
= psInfo
->proppage
[psInfo
->active_page
].hwndPage
;
1191 msgResult
= SendMessageA(hwndPage
, WM_NOTIFY
, 0, (LPARAM
) &psn
);
1192 if (msgResult
== -1)
1195 if(PROPSHEET_CanSetCurSel(hwndDlg
) != FALSE
)
1197 PROPSHEET_SetCurSel(hwndDlg
, psInfo
->active_page
+ 1, 1, 0);
1203 /******************************************************************************
1206 static BOOL
PROPSHEET_Finish(HWND hwndDlg
)
1210 LRESULT msgResult
= 0;
1211 PropSheetInfo
* psInfo
= (PropSheetInfo
*) GetPropA(hwndDlg
,
1214 if (psInfo
->active_page
< 0)
1217 psn
.hdr
.code
= PSN_WIZFINISH
;
1218 psn
.hdr
.hwndFrom
= hwndDlg
;
1222 hwndPage
= psInfo
->proppage
[psInfo
->active_page
].hwndPage
;
1224 msgResult
= SendMessageA(hwndPage
, WM_NOTIFY
, 0, (LPARAM
) &psn
);
1226 TRACE("msg result %ld\n", msgResult
);
1231 if (psInfo
->isModeless
)
1232 psInfo
->activeValid
= FALSE
;
1234 EndDialog(hwndDlg
, TRUE
);
1239 /******************************************************************************
1242 static BOOL
PROPSHEET_Apply(HWND hwndDlg
, LPARAM lParam
)
1248 PropSheetInfo
* psInfo
= (PropSheetInfo
*) GetPropA(hwndDlg
,
1251 if (psInfo
->active_page
< 0)
1254 psn
.hdr
.hwndFrom
= hwndDlg
;
1260 * Send PSN_KILLACTIVE to the current page.
1262 psn
.hdr
.code
= PSN_KILLACTIVE
;
1264 hwndPage
= psInfo
->proppage
[psInfo
->active_page
].hwndPage
;
1266 if (SendMessageA(hwndPage
, WM_NOTIFY
, 0, (LPARAM
) &psn
) != FALSE
)
1270 * Send PSN_APPLY to all pages.
1272 psn
.hdr
.code
= PSN_APPLY
;
1273 psn
.lParam
= lParam
;
1275 for (i
= 0; i
< psInfo
->nPages
; i
++)
1277 hwndPage
= psInfo
->proppage
[i
].hwndPage
;
1280 msgResult
= SendMessageA(hwndPage
, WM_NOTIFY
, 0, (LPARAM
) &psn
);
1281 if (msgResult
== PSNRET_INVALID_NOCHANGEPAGE
)
1288 psInfo
->activeValid
= FALSE
;
1290 else if(psInfo
->active_page
>= 0)
1292 psn
.hdr
.code
= PSN_SETACTIVE
;
1294 hwndPage
= psInfo
->proppage
[psInfo
->active_page
].hwndPage
;
1295 SendMessageA(hwndPage
, WM_NOTIFY
, 0, (LPARAM
) &psn
);
1301 /******************************************************************************
1304 static void PROPSHEET_Cancel(HWND hwndDlg
, LPARAM lParam
)
1306 PropSheetInfo
* psInfo
= (PropSheetInfo
*) GetPropA(hwndDlg
,
1312 if (psInfo
->active_page
< 0)
1315 hwndPage
= psInfo
->proppage
[psInfo
->active_page
].hwndPage
;
1316 psn
.hdr
.code
= PSN_QUERYCANCEL
;
1317 psn
.hdr
.hwndFrom
= hwndDlg
;
1321 if (SendMessageA(hwndPage
, WM_NOTIFY
, 0, (LPARAM
) &psn
))
1324 psn
.hdr
.code
= PSN_RESET
;
1325 psn
.lParam
= lParam
;
1327 for (i
= 0; i
< psInfo
->nPages
; i
++)
1329 hwndPage
= psInfo
->proppage
[i
].hwndPage
;
1332 SendMessageA(hwndPage
, WM_NOTIFY
, 0, (LPARAM
) &psn
);
1335 if (psInfo
->isModeless
)
1337 /* makes PSM_GETCURRENTPAGEHWND return NULL */
1338 psInfo
->activeValid
= FALSE
;
1341 EndDialog(hwndDlg
, FALSE
);
1344 /******************************************************************************
1347 static void PROPSHEET_Help(HWND hwndDlg
)
1349 PropSheetInfo
* psInfo
= (PropSheetInfo
*) GetPropA(hwndDlg
,
1354 if (psInfo
->active_page
< 0)
1357 hwndPage
= psInfo
->proppage
[psInfo
->active_page
].hwndPage
;
1358 psn
.hdr
.code
= PSN_HELP
;
1359 psn
.hdr
.hwndFrom
= hwndDlg
;
1363 SendMessageA(hwndPage
, WM_NOTIFY
, 0, (LPARAM
) &psn
);
1366 /******************************************************************************
1369 static void PROPSHEET_Changed(HWND hwndDlg
, HWND hwndDirtyPage
)
1372 PropSheetInfo
* psInfo
= (PropSheetInfo
*) GetPropA(hwndDlg
,
1375 if (!psInfo
) return;
1377 * Set the dirty flag of this page.
1379 for (i
= 0; i
< psInfo
->nPages
; i
++)
1381 if (psInfo
->proppage
[i
].hwndPage
== hwndDirtyPage
)
1382 psInfo
->proppage
[i
].isDirty
= TRUE
;
1386 * Enable the Apply button.
1388 if (psInfo
->hasApply
)
1390 HWND hwndApplyBtn
= GetDlgItem(hwndDlg
, IDC_APPLY_BUTTON
);
1392 EnableWindow(hwndApplyBtn
, TRUE
);
1396 /******************************************************************************
1397 * PROPSHEET_UnChanged
1399 static void PROPSHEET_UnChanged(HWND hwndDlg
, HWND hwndCleanPage
)
1402 BOOL noPageDirty
= TRUE
;
1403 HWND hwndApplyBtn
= GetDlgItem(hwndDlg
, IDC_APPLY_BUTTON
);
1404 PropSheetInfo
* psInfo
= (PropSheetInfo
*) GetPropA(hwndDlg
,
1407 if ( !psInfo
) return;
1408 for (i
= 0; i
< psInfo
->nPages
; i
++)
1410 /* set the specified page as clean */
1411 if (psInfo
->proppage
[i
].hwndPage
== hwndCleanPage
)
1412 psInfo
->proppage
[i
].isDirty
= FALSE
;
1414 /* look to see if there's any dirty pages */
1415 if (psInfo
->proppage
[i
].isDirty
)
1416 noPageDirty
= FALSE
;
1420 * Disable Apply button.
1423 EnableWindow(hwndApplyBtn
, FALSE
);
1426 /******************************************************************************
1427 * PROPSHEET_PressButton
1429 static void PROPSHEET_PressButton(HWND hwndDlg
, int buttonID
)
1433 case PSBTN_APPLYNOW
:
1434 SendMessageA(hwndDlg
, WM_COMMAND
, IDC_APPLY_BUTTON
, 0);
1437 PROPSHEET_Back(hwndDlg
);
1440 SendMessageA(hwndDlg
, WM_COMMAND
, IDCANCEL
, 0);
1443 PROPSHEET_Finish(hwndDlg
);
1446 SendMessageA(hwndDlg
, WM_COMMAND
, IDHELP
, 0);
1449 PROPSHEET_Next(hwndDlg
);
1452 SendMessageA(hwndDlg
, WM_COMMAND
, IDOK
, 0);
1455 FIXME("Invalid button index %d\n", buttonID
);
1460 /*************************************************************************
1461 * BOOL PROPSHEET_CanSetCurSel [Internal]
1463 * Test whether the current page can be changed by sending a PSN_KILLACTIVE
1466 * hwndDlg [I] handle to a Dialog hWnd
1469 * TRUE if Current Selection can change
1473 static BOOL
PROPSHEET_CanSetCurSel(HWND hwndDlg
)
1475 PropSheetInfo
* psInfo
= (PropSheetInfo
*) GetPropA(hwndDlg
,
1483 if (psInfo
->active_page
< 0)
1487 * Notify the current page.
1489 hwndPage
= psInfo
->proppage
[psInfo
->active_page
].hwndPage
;
1490 psn
.hdr
.code
= PSN_KILLACTIVE
;
1491 psn
.hdr
.hwndFrom
= hwndDlg
;
1495 return !SendMessageA(hwndPage
, WM_NOTIFY
, 0, (LPARAM
) &psn
);
1498 /******************************************************************************
1499 * PROPSHEET_SetCurSel
1501 static BOOL
PROPSHEET_SetCurSel(HWND hwndDlg
,
1504 HPROPSHEETPAGE hpage
1507 PropSheetInfo
* psInfo
= (PropSheetInfo
*) GetPropA(hwndDlg
, PropSheetInfoStr
);
1508 HWND hwndHelp
= GetDlgItem(hwndDlg
, IDHELP
);
1510 /* hpage takes precedence over index */
1512 index
= PROPSHEET_GetPageIndex(hpage
, psInfo
);
1514 if (index
< 0 || index
>= psInfo
->nPages
)
1516 TRACE("Could not find page to select!\n");
1524 psn
.hdr
.code
= PSN_SETACTIVE
;
1525 psn
.hdr
.hwndFrom
= hwndDlg
;
1529 if (!psInfo
->proppage
[index
].hwndPage
) {
1530 LPCPROPSHEETPAGEA ppshpage
= (LPCPROPSHEETPAGEA
)psInfo
->proppage
[index
].hpage
;
1531 PROPSHEET_CreatePage(hwndDlg
, index
, psInfo
, ppshpage
);
1534 result
= SendMessageA(psInfo
->proppage
[index
].hwndPage
, WM_NOTIFY
, 0, (LPARAM
) &psn
);
1541 FIXME("Tried to skip before first property sheet page!\n");
1544 if (index
>= psInfo
->nPages
) {
1545 FIXME("Tried to skip after last property sheet page!\n");
1546 index
= psInfo
->nPages
-1;
1552 * Display the new page.
1554 PROPSHEET_ShowPage(hwndDlg
, index
, psInfo
);
1556 if (psInfo
->proppage
[index
].hasHelp
)
1557 EnableWindow(hwndHelp
, TRUE
);
1559 EnableWindow(hwndHelp
, FALSE
);
1564 /******************************************************************************
1565 * PROPSHEET_SetTitleA
1567 static void PROPSHEET_SetTitleA(HWND hwndDlg
, DWORD dwStyle
, LPCSTR lpszText
)
1569 PropSheetInfo
* psInfo
= (PropSheetInfo
*) GetPropA(hwndDlg
, PropSheetInfoStr
);
1572 if (HIWORD(lpszText
) == 0) {
1573 if (!LoadStringA(psInfo
->ppshheader
.hInstance
,
1574 LOWORD(lpszText
), szTitle
, sizeof(szTitle
)-1))
1578 if (dwStyle
& PSH_PROPTITLE
)
1581 int lentitle
= strlen(lpszText
);
1582 int lenprop
= strlen(psInfo
->strPropertiesFor
);
1584 dest
= COMCTL32_Alloc(lentitle
+ lenprop
+ 1);
1585 strcpy(dest
, psInfo
->strPropertiesFor
);
1586 strcat(dest
, lpszText
);
1588 SetWindowTextA(hwndDlg
, dest
);
1589 COMCTL32_Free(dest
);
1592 SetWindowTextA(hwndDlg
, lpszText
);
1595 /******************************************************************************
1596 * PROPSHEET_SetFinishTextA
1598 static void PROPSHEET_SetFinishTextA(HWND hwndDlg
, LPCSTR lpszText
)
1600 HWND hwndButton
= GetDlgItem(hwndDlg
, IDC_FINISH_BUTTON
);
1602 /* Set text, show and enable the Finish button */
1603 SetWindowTextA(hwndButton
, lpszText
);
1604 ShowWindow(hwndButton
, SW_SHOW
);
1605 EnableWindow(hwndButton
, TRUE
);
1607 /* Make it default pushbutton */
1608 SendMessageA(hwndDlg
, DM_SETDEFID
, IDC_FINISH_BUTTON
, 0);
1610 /* Hide Back button */
1611 hwndButton
= GetDlgItem(hwndDlg
, IDC_BACK_BUTTON
);
1612 ShowWindow(hwndButton
, SW_HIDE
);
1614 /* Hide Next button */
1615 hwndButton
= GetDlgItem(hwndDlg
, IDC_NEXT_BUTTON
);
1616 ShowWindow(hwndButton
, SW_HIDE
);
1619 /******************************************************************************
1620 * PROPSHEET_QuerySiblings
1622 static LRESULT
PROPSHEET_QuerySiblings(HWND hwndDlg
,
1623 WPARAM wParam
, LPARAM lParam
)
1627 LRESULT msgResult
= 0;
1628 PropSheetInfo
* psInfo
= (PropSheetInfo
*) GetPropA(hwndDlg
,
1631 while ((i
< psInfo
->nPages
) && (msgResult
== 0))
1633 hwndPage
= psInfo
->proppage
[i
].hwndPage
;
1634 msgResult
= SendMessageA(hwndPage
, PSM_QUERYSIBLINGS
, wParam
, lParam
);
1642 /******************************************************************************
1645 static BOOL
PROPSHEET_AddPage(HWND hwndDlg
,
1646 HPROPSHEETPAGE hpage
)
1648 PropSheetInfo
* psInfo
= (PropSheetInfo
*) GetPropA(hwndDlg
,
1650 HWND hwndTabControl
= GetDlgItem(hwndDlg
, IDC_TABCONTROL
);
1652 char tabtext
[MAX_TABTEXT_LENGTH
] = "Tab text";
1653 LPCPROPSHEETPAGEA ppsp
= (LPCPROPSHEETPAGEA
)hpage
;
1656 * Allocate and fill in a new PropPageInfo entry.
1658 psInfo
->proppage
= (PropPageInfo
*) COMCTL32_ReAlloc(psInfo
->proppage
,
1659 sizeof(PropPageInfo
) *
1660 (psInfo
->nPages
+ 1));
1661 if (!PROPSHEET_CollectPageInfo(ppsp
, psInfo
, psInfo
->nPages
))
1664 psInfo
->proppage
[psInfo
->nPages
].hpage
= hpage
;
1666 if (ppsp
->dwFlags
& PSP_PREMATURE
)
1668 /* Create the page but don't show it */
1669 PROPSHEET_CreatePage(hwndDlg
, psInfo
->nPages
, psInfo
, ppsp
);
1673 * Add a new tab to the tab control.
1675 item
.mask
= TCIF_TEXT
;
1676 item
.pszText
= tabtext
;
1677 item
.cchTextMax
= MAX_TABTEXT_LENGTH
;
1679 WideCharToMultiByte(CP_ACP
, 0,
1680 (LPCWSTR
)psInfo
->proppage
[psInfo
->nPages
].pszText
,
1681 -1, tabtext
, MAX_TABTEXT_LENGTH
, NULL
, NULL
);
1683 SendMessageA(hwndTabControl
, TCM_INSERTITEMA
, psInfo
->nPages
+ 1,
1688 /* If it is the only page - show it */
1689 if(psInfo
->nPages
== 1)
1690 PROPSHEET_SetCurSel(hwndDlg
, 0, 1, 0);
1694 /******************************************************************************
1695 * PROPSHEET_RemovePage
1697 static BOOL
PROPSHEET_RemovePage(HWND hwndDlg
,
1699 HPROPSHEETPAGE hpage
)
1701 PropSheetInfo
* psInfo
= (PropSheetInfo
*) GetPropA(hwndDlg
,
1703 HWND hwndTabControl
= GetDlgItem(hwndDlg
, IDC_TABCONTROL
);
1704 PropPageInfo
* oldPages
;
1709 oldPages
= psInfo
->proppage
;
1711 * hpage takes precedence over index.
1715 index
= PROPSHEET_GetPageIndex(hpage
, psInfo
);
1718 /* Make sure that index is within range */
1719 if (index
< 0 || index
>= psInfo
->nPages
)
1721 TRACE("Could not find page to remove!\n");
1725 TRACE("total pages %d removing page %d active page %d\n",
1726 psInfo
->nPages
, index
, psInfo
->active_page
);
1728 * Check if we're removing the active page.
1730 if (index
== psInfo
->active_page
)
1732 if (psInfo
->nPages
> 1)
1736 /* activate previous page */
1737 PROPSHEET_SetCurSel(hwndDlg
, index
- 1, -1, 0);
1741 /* activate the next page */
1742 PROPSHEET_SetCurSel(hwndDlg
, index
+ 1, 1, 0);
1743 psInfo
->active_page
= index
;
1748 psInfo
->active_page
= -1;
1749 if (!psInfo
->isModeless
)
1751 EndDialog(hwndDlg
, FALSE
);
1756 else if (index
< psInfo
->active_page
)
1757 psInfo
->active_page
--;
1759 /* Destroy page dialog window */
1760 DestroyWindow(psInfo
->proppage
[index
].hwndPage
);
1762 /* Free page resources */
1763 if(psInfo
->proppage
[index
].hpage
)
1765 PROPSHEETPAGEA
* psp
= (PROPSHEETPAGEA
*)psInfo
->proppage
[index
].hpage
;
1767 if ((psp
->dwFlags
& PSP_USETITLE
) && psInfo
->proppage
[index
].pszText
)
1768 HeapFree(GetProcessHeap(), 0, (LPVOID
)psInfo
->proppage
[index
].pszText
);
1770 DestroyPropertySheetPage(psInfo
->proppage
[index
].hpage
);
1773 /* Remove the tab */
1774 SendMessageA(hwndTabControl
, TCM_DELETEITEM
, index
, 0);
1777 psInfo
->proppage
= COMCTL32_Alloc(sizeof(PropPageInfo
) * psInfo
->nPages
);
1780 memcpy(&psInfo
->proppage
[0], &oldPages
[0], index
* sizeof(PropPageInfo
));
1782 if (index
< psInfo
->nPages
)
1783 memcpy(&psInfo
->proppage
[index
], &oldPages
[index
+ 1],
1784 (psInfo
->nPages
- index
) * sizeof(PropPageInfo
));
1786 COMCTL32_Free(oldPages
);
1791 /******************************************************************************
1792 * PROPSHEET_SetWizButtons
1794 * This code will work if (and assumes that) the Next button is on top of the
1795 * Finish button. ie. Finish comes after Next in the Z order.
1796 * This means make sure the dialog template reflects this.
1799 static void PROPSHEET_SetWizButtons(HWND hwndDlg
, DWORD dwFlags
)
1801 HWND hwndBack
= GetDlgItem(hwndDlg
, IDC_BACK_BUTTON
);
1802 HWND hwndNext
= GetDlgItem(hwndDlg
, IDC_NEXT_BUTTON
);
1803 HWND hwndFinish
= GetDlgItem(hwndDlg
, IDC_FINISH_BUTTON
);
1805 TRACE("%ld\n", dwFlags
);
1807 EnableWindow(hwndBack
, FALSE
);
1808 EnableWindow(hwndNext
, FALSE
);
1809 EnableWindow(hwndFinish
, FALSE
);
1811 if (dwFlags
& PSWIZB_BACK
)
1812 EnableWindow(hwndBack
, TRUE
);
1814 if (dwFlags
& PSWIZB_NEXT
)
1816 /* Hide the Finish button */
1817 ShowWindow(hwndFinish
, SW_HIDE
);
1819 /* Show and enable the Next button */
1820 ShowWindow(hwndNext
, SW_SHOW
);
1821 EnableWindow(hwndNext
, TRUE
);
1823 /* Set the Next button as the default pushbutton */
1824 SendMessageA(hwndDlg
, DM_SETDEFID
, IDC_NEXT_BUTTON
, 0);
1827 if ((dwFlags
& PSWIZB_FINISH
) || (dwFlags
& PSWIZB_DISABLEDFINISH
))
1829 /* Hide the Next button */
1830 ShowWindow(hwndNext
, SW_HIDE
);
1832 /* Show the Finish button */
1833 ShowWindow(hwndFinish
, SW_SHOW
);
1835 if (dwFlags
& PSWIZB_FINISH
)
1836 EnableWindow(hwndFinish
, TRUE
);
1838 /* Set the Finish button as the default pushbutton */
1839 SendMessageA(hwndDlg
, DM_SETDEFID
, IDC_FINISH_BUTTON
, 0);
1843 /******************************************************************************
1844 * PROPSHEET_GetPageIndex
1846 * Given a HPROPSHEETPAGE, returns the index of the corresponding page from
1847 * the array of PropPageInfo.
1849 static int PROPSHEET_GetPageIndex(HPROPSHEETPAGE hpage
, PropSheetInfo
* psInfo
)
1854 while ((index
< psInfo
->nPages
) && (found
== FALSE
))
1856 if (psInfo
->proppage
[index
].hpage
== hpage
)
1868 /******************************************************************************
1871 static void PROPSHEET_CleanUp(HWND hwndDlg
)
1874 PropSheetInfo
* psInfo
= (PropSheetInfo
*) RemovePropA(hwndDlg
,
1878 if (HIWORD(psInfo
->ppshheader
.pszCaption
))
1879 HeapFree(GetProcessHeap(), 0, (LPVOID
)psInfo
->ppshheader
.pszCaption
);
1881 for (i
= 0; i
< psInfo
->nPages
; i
++)
1883 PROPSHEETPAGEA
* psp
= (PROPSHEETPAGEA
*)psInfo
->proppage
[i
].hpage
;
1885 if(psInfo
->proppage
[i
].hwndPage
)
1886 DestroyWindow(psInfo
->proppage
[i
].hwndPage
);
1890 if ((psp
->dwFlags
& PSP_USETITLE
) && psInfo
->proppage
[i
].pszText
)
1891 HeapFree(GetProcessHeap(), 0, (LPVOID
)psInfo
->proppage
[i
].pszText
);
1893 DestroyPropertySheetPage(psInfo
->proppage
[i
].hpage
);
1897 COMCTL32_Free(psInfo
->proppage
);
1898 COMCTL32_Free(psInfo
->strPropertiesFor
);
1899 ImageList_Destroy(psInfo
->hImageList
);
1901 GlobalFree((HGLOBAL
)psInfo
);
1904 /******************************************************************************
1905 * PropertySheet (COMCTL32.87)
1906 * PropertySheetA (COMCTL32.88)
1908 INT WINAPI
PropertySheetA(LPCPROPSHEETHEADERA lppsh
)
1911 PropSheetInfo
* psInfo
= (PropSheetInfo
*) GlobalAlloc(GPTR
,
1912 sizeof(PropSheetInfo
));
1916 PROPSHEET_CollectSheetInfo(lppsh
, psInfo
);
1918 psInfo
->proppage
= (PropPageInfo
*) COMCTL32_Alloc(sizeof(PropPageInfo
) *
1920 pByte
= (BYTE
*) psInfo
->ppshheader
.u3
.ppsp
;
1922 for (n
= i
= 0; i
< lppsh
->nPages
; i
++, n
++)
1924 if (!(lppsh
->dwFlags
& PSH_PROPSHEETPAGE
))
1925 psInfo
->proppage
[n
].hpage
= psInfo
->ppshheader
.u3
.phpage
[i
];
1928 psInfo
->proppage
[n
].hpage
= CreatePropertySheetPageA((LPCPROPSHEETPAGEA
)pByte
);
1929 pByte
+= ((LPPROPSHEETPAGEA
)pByte
)->dwSize
;
1932 if (!PROPSHEET_CollectPageInfo((LPCPROPSHEETPAGEA
)psInfo
->proppage
[n
].hpage
,
1935 if (lppsh
->dwFlags
& PSH_PROPSHEETPAGE
)
1936 DestroyPropertySheetPage(psInfo
->proppage
[n
].hpage
);
1942 bRet
= PROPSHEET_CreateDialog(psInfo
);
1947 /******************************************************************************
1948 * PropertySheetW (COMCTL32.89)
1950 INT WINAPI
PropertySheetW(LPCPROPSHEETHEADERW propertySheetHeader
)
1952 FIXME("(%p): stub\n", propertySheetHeader
);
1957 /******************************************************************************
1958 * CreatePropertySheetPage (COMCTL32.18)
1959 * CreatePropertySheetPageA (COMCTL32.19)
1961 HPROPSHEETPAGE WINAPI
CreatePropertySheetPageA(
1962 LPCPROPSHEETPAGEA lpPropSheetPage
)
1964 PROPSHEETPAGEA
* ppsp
= COMCTL32_Alloc(sizeof(PROPSHEETPAGEA
));
1966 memcpy(ppsp
,lpPropSheetPage
,min(lpPropSheetPage
->dwSize
,sizeof(PROPSHEETPAGEA
)));
1968 if ( !(ppsp
->dwFlags
& PSP_DLGINDIRECT
) && HIWORD( ppsp
->u
.pszTemplate
) )
1970 ppsp
->u
.pszTemplate
= HeapAlloc( GetProcessHeap(),0,strlen(lpPropSheetPage
->u
.pszTemplate
)+1 );
1971 strcpy( (char *)ppsp
->u
.pszTemplate
, lpPropSheetPage
->u
.pszTemplate
);
1973 if ( (ppsp
->dwFlags
& PSP_USEICONID
) && HIWORD( ppsp
->u2
.pszIcon
) )
1975 ppsp
->u2
.pszIcon
= HeapAlloc( GetProcessHeap(), 0, strlen(lpPropSheetPage
->u2
.pszIcon
)+1 );
1976 strcpy( (char *)ppsp
->u2
.pszIcon
, lpPropSheetPage
->u2
.pszIcon
);
1979 if ((ppsp
->dwFlags
& PSP_USETITLE
) && HIWORD( ppsp
->pszTitle
))
1981 ppsp
->pszTitle
= HeapAlloc( GetProcessHeap(), 0, strlen(lpPropSheetPage
->pszTitle
)+1 );
1982 strcpy( (char *)ppsp
->pszTitle
, lpPropSheetPage
->pszTitle
);
1984 else if ( !(ppsp
->dwFlags
& PSP_USETITLE
) )
1985 ppsp
->pszTitle
= NULL
;
1987 return (HPROPSHEETPAGE
)ppsp
;
1990 /******************************************************************************
1991 * CreatePropertySheetPageW (COMCTL32.20)
1993 HPROPSHEETPAGE WINAPI
CreatePropertySheetPageW(LPCPROPSHEETPAGEW lpPropSheetPage
)
1995 FIXME("(%p): stub\n", lpPropSheetPage
);
2000 /******************************************************************************
2001 * DestroyPropertySheetPage (COMCTL32.24)
2003 BOOL WINAPI
DestroyPropertySheetPage(HPROPSHEETPAGE hPropPage
)
2005 PROPSHEETPAGEA
*psp
= (PROPSHEETPAGEA
*)hPropPage
;
2010 if ( !(psp
->dwFlags
& PSP_DLGINDIRECT
) && HIWORD( psp
->u
.pszTemplate
) )
2011 HeapFree(GetProcessHeap(), 0, (LPVOID
)psp
->u
.pszTemplate
);
2013 if ( (psp
->dwFlags
& PSP_USEICONID
) && HIWORD( psp
->u2
.pszIcon
) )
2014 HeapFree(GetProcessHeap(), 0, (LPVOID
)psp
->u2
.pszIcon
);
2016 if ((psp
->dwFlags
& PSP_USETITLE
) && HIWORD( psp
->pszTitle
))
2017 HeapFree(GetProcessHeap(), 0, (LPVOID
)psp
->pszTitle
);
2019 COMCTL32_Free(hPropPage
);
2024 /******************************************************************************
2025 * PROPSHEET_IsDialogMessage
2027 static BOOL
PROPSHEET_IsDialogMessage(HWND hwnd
, LPMSG lpMsg
)
2029 PropSheetInfo
* psInfo
= (PropSheetInfo
*) GetPropA(hwnd
, PropSheetInfoStr
);
2031 if (!psInfo
|| (hwnd
!= lpMsg
->hwnd
&& !IsChild(hwnd
, lpMsg
->hwnd
)))
2034 if (lpMsg
->message
== WM_KEYDOWN
&& (GetKeyState(VK_CONTROL
) & 0x8000))
2037 INT dlgCode
= SendMessageA(lpMsg
->hwnd
, WM_GETDLGCODE
, 0, (LPARAM
)lpMsg
);
2039 if (!(dlgCode
& DLGC_WANTMESSAGE
))
2041 switch (lpMsg
->wParam
)
2044 if (GetKeyState(VK_SHIFT
) & 0x8000)
2050 case VK_NEXT
: new_page
= 1; break;
2051 case VK_PRIOR
: new_page
= -1; break;
2057 if (PROPSHEET_CanSetCurSel(hwnd
) != FALSE
)
2059 new_page
+= psInfo
->active_page
;
2062 new_page
= psInfo
->nPages
- 1;
2063 else if (new_page
>= psInfo
->nPages
)
2066 PROPSHEET_SetCurSel(hwnd
, new_page
, 1, 0);
2073 return IsDialogMessageA(hwnd
, lpMsg
);
2076 /******************************************************************************
2077 * PROPSHEET_DialogProc
2080 PROPSHEET_DialogProc(HWND hwnd
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
)
2086 PropSheetInfo
* psInfo
= (PropSheetInfo
*) lParam
;
2087 char* strCaption
= (char*)COMCTL32_Alloc(MAX_CAPTION_LENGTH
);
2088 HWND hwndTabCtrl
= GetDlgItem(hwnd
, IDC_TABCONTROL
);
2089 LPCPROPSHEETPAGEA ppshpage
;
2092 SetPropA(hwnd
, PropSheetInfoStr
, (HANDLE
)psInfo
);
2095 * psInfo->hwnd is not being used by WINE code - it exists
2096 * for compatibility with "real" Windoze. The same about
2097 * SetWindowLong - WINE is only using the PropSheetInfoStr
2100 psInfo
->hwnd
= hwnd
;
2101 SetWindowLongA(hwnd
,DWL_USER
,(LONG
)psInfo
);
2104 * Small icon in the title bar.
2106 if ((psInfo
->ppshheader
.dwFlags
& PSH_USEICONID
) ||
2107 (psInfo
->ppshheader
.dwFlags
& PSH_USEHICON
))
2110 int icon_cx
= GetSystemMetrics(SM_CXSMICON
);
2111 int icon_cy
= GetSystemMetrics(SM_CYSMICON
);
2113 if (psInfo
->ppshheader
.dwFlags
& PSH_USEICONID
)
2114 hIcon
= LoadImageA(psInfo
->ppshheader
.hInstance
,
2115 psInfo
->ppshheader
.u
.pszIcon
,
2120 hIcon
= psInfo
->ppshheader
.u
.hIcon
;
2122 SendMessageA(hwnd
, WM_SETICON
, 0, hIcon
);
2125 if (psInfo
->ppshheader
.dwFlags
& PSH_USEHICON
)
2126 SendMessageA(hwnd
, WM_SETICON
, 0, psInfo
->ppshheader
.u
.hIcon
);
2128 psInfo
->strPropertiesFor
= strCaption
;
2130 GetWindowTextA(hwnd
, psInfo
->strPropertiesFor
, MAX_CAPTION_LENGTH
);
2132 PROPSHEET_CreateTabControl(hwnd
, psInfo
);
2134 if (psInfo
->ppshheader
.dwFlags
& PSH_WIZARD
)
2136 if (PROPSHEET_IsTooSmallWizard(hwnd
, psInfo
))
2138 PROPSHEET_AdjustSizeWizard(hwnd
, psInfo
);
2139 PROPSHEET_AdjustButtonsWizard(hwnd
, psInfo
);
2144 if (PROPSHEET_SizeMismatch(hwnd
, psInfo
))
2146 PROPSHEET_AdjustSize(hwnd
, psInfo
);
2147 PROPSHEET_AdjustButtons(hwnd
, psInfo
);
2151 if (psInfo
->useCallback
)
2152 (*(psInfo
->ppshheader
.pfnCallback
))(hwnd
,
2153 PSCB_INITIALIZED
, (LPARAM
)0);
2155 idx
= psInfo
->active_page
;
2156 ppshpage
= (LPCPROPSHEETPAGEA
)psInfo
->proppage
[idx
].hpage
;
2157 psInfo
->active_page
= -1;
2159 PROPSHEET_SetCurSel(hwnd
, idx
, 1, psInfo
->proppage
[idx
].hpage
);
2161 if (!(psInfo
->ppshheader
.dwFlags
& PSH_WIZARD
))
2162 SendMessageA(hwndTabCtrl
, TCM_SETCURSEL
, psInfo
->active_page
, 0);
2164 if (!HIWORD(psInfo
->ppshheader
.pszCaption
) &&
2165 psInfo
->ppshheader
.hInstance
)
2169 if (LoadStringA(psInfo
->ppshheader
.hInstance
,
2170 (UINT
)psInfo
->ppshheader
.pszCaption
, szText
, 255))
2171 PROPSHEET_SetTitleA(hwnd
, psInfo
->ppshheader
.dwFlags
, szText
);
2175 PROPSHEET_SetTitleA(hwnd
, psInfo
->ppshheader
.dwFlags
,
2176 psInfo
->ppshheader
.pszCaption
);
2183 PROPSHEET_CleanUp(hwnd
);
2187 PROPSHEET_Cancel(hwnd
, 1);
2192 WORD wID
= LOWORD(wParam
);
2197 case IDC_APPLY_BUTTON
:
2199 HWND hwndApplyBtn
= GetDlgItem(hwnd
, IDC_APPLY_BUTTON
);
2201 if (PROPSHEET_Apply(hwnd
, wID
== IDOK
? 1: 0) == FALSE
)
2206 PropSheetInfo
* psInfo
= (PropSheetInfo
*) GetPropA(hwnd
,
2210 if (psInfo
->restartWindows
)
2211 result
= ID_PSRESTARTWINDOWS
;
2213 /* reboot system takes precedence over restart windows */
2214 if (psInfo
->rebootSystem
)
2215 result
= ID_PSREBOOTSYSTEM
;
2217 if (psInfo
->isModeless
)
2218 psInfo
->activeValid
= FALSE
;
2220 EndDialog(hwnd
, result
);
2223 EnableWindow(hwndApplyBtn
, FALSE
);
2228 case IDC_BACK_BUTTON
:
2229 PROPSHEET_Back(hwnd
);
2232 case IDC_NEXT_BUTTON
:
2233 PROPSHEET_Next(hwnd
);
2236 case IDC_FINISH_BUTTON
:
2237 PROPSHEET_Finish(hwnd
);
2241 PROPSHEET_Cancel(hwnd
, 0);
2245 PROPSHEET_Help(hwnd
);
2254 NMHDR
* pnmh
= (LPNMHDR
) lParam
;
2256 if (pnmh
->code
== TCN_SELCHANGE
)
2258 int index
= SendMessageA(pnmh
->hwndFrom
, TCM_GETCURSEL
, 0, 0);
2259 PROPSHEET_SetCurSel(hwnd
, index
, 1, 0);
2262 if(pnmh
->code
== TCN_SELCHANGING
)
2264 BOOL bRet
= PROPSHEET_CanSetCurSel(hwnd
);
2265 SetWindowLongA(hwnd
, DWL_MSGRESULT
, !bRet
);
2272 case PSM_GETCURRENTPAGEHWND
:
2274 PropSheetInfo
* psInfo
= (PropSheetInfo
*) GetPropA(hwnd
,
2278 if (psInfo
->activeValid
&& psInfo
->active_page
!= -1)
2279 hwndPage
= psInfo
->proppage
[psInfo
->active_page
].hwndPage
;
2281 SetWindowLongA(hwnd
, DWL_MSGRESULT
, hwndPage
);
2287 PROPSHEET_Changed(hwnd
, (HWND
)wParam
);
2291 PROPSHEET_UnChanged(hwnd
, (HWND
)wParam
);
2294 case PSM_GETTABCONTROL
:
2296 HWND hwndTabCtrl
= GetDlgItem(hwnd
, IDC_TABCONTROL
);
2298 SetWindowLongA(hwnd
, DWL_MSGRESULT
, hwndTabCtrl
);
2307 msgResult
= PROPSHEET_CanSetCurSel(hwnd
);
2308 if(msgResult
!= FALSE
)
2310 msgResult
= PROPSHEET_SetCurSel(hwnd
,
2313 (HPROPSHEETPAGE
)lParam
);
2316 SetWindowLongA(hwnd
, DWL_MSGRESULT
, msgResult
);
2321 case PSM_CANCELTOCLOSE
:
2323 char buf
[MAX_BUTTONTEXT_LENGTH
];
2324 HWND hwndOK
= GetDlgItem(hwnd
, IDOK
);
2325 HWND hwndCancel
= GetDlgItem(hwnd
, IDCANCEL
);
2327 EnableWindow(hwndCancel
, FALSE
);
2328 if (LoadStringA(COMCTL32_hModule
, IDS_CLOSE
, buf
, sizeof(buf
)))
2329 SetWindowTextA(hwndOK
, buf
);
2334 case PSM_RESTARTWINDOWS
:
2336 PropSheetInfo
* psInfo
= (PropSheetInfo
*) GetPropA(hwnd
,
2339 psInfo
->restartWindows
= TRUE
;
2343 case PSM_REBOOTSYSTEM
:
2345 PropSheetInfo
* psInfo
= (PropSheetInfo
*) GetPropA(hwnd
,
2348 psInfo
->rebootSystem
= TRUE
;
2353 PROPSHEET_SetTitleA(hwnd
, (DWORD
) wParam
, (LPCSTR
) lParam
);
2358 BOOL msgResult
= PROPSHEET_Apply(hwnd
, 0);
2360 SetWindowLongA(hwnd
, DWL_MSGRESULT
, msgResult
);
2365 case PSM_QUERYSIBLINGS
:
2367 LRESULT msgResult
= PROPSHEET_QuerySiblings(hwnd
, wParam
, lParam
);
2369 SetWindowLongA(hwnd
, DWL_MSGRESULT
, msgResult
);
2377 * Note: MSVC++ 6.0 documentation says that PSM_ADDPAGE does not have
2378 * a return value. This is not true. PSM_ADDPAGE returns TRUE
2379 * on success or FALSE otherwise, as specified on MSDN Online.
2380 * Also see the MFC code for
2381 * CPropertySheet::AddPage(CPropertyPage* pPage).
2384 BOOL msgResult
= PROPSHEET_AddPage(hwnd
, (HPROPSHEETPAGE
)lParam
);
2386 SetWindowLongA(hwnd
, DWL_MSGRESULT
, msgResult
);
2391 case PSM_REMOVEPAGE
:
2392 PROPSHEET_RemovePage(hwnd
, (int)wParam
, (HPROPSHEETPAGE
)lParam
);
2395 case PSM_ISDIALOGMESSAGE
:
2397 BOOL msgResult
= PROPSHEET_IsDialogMessage(hwnd
, (LPMSG
)lParam
);
2398 SetWindowLongA(hwnd
, DWL_MSGRESULT
, msgResult
);
2402 case PSM_PRESSBUTTON
:
2403 PROPSHEET_PressButton(hwnd
, (int)wParam
);
2406 case PSM_SETFINISHTEXTA
:
2407 PROPSHEET_SetFinishTextA(hwnd
, (LPCSTR
) lParam
);
2410 case PSM_SETWIZBUTTONS
:
2411 PROPSHEET_SetWizButtons(hwnd
, (DWORD
)lParam
);
2415 FIXME("Unimplemented msg PSM_SETTITLE32W\n");
2418 case PSM_SETCURSELID
:
2419 FIXME("Unimplemented msg PSM_SETCURSELID\n");
2422 case PSM_SETFINISHTEXTW
:
2423 FIXME("Unimplemented msg PSM_SETFINISHTEXT32W\n");