4 * Copyright 1998 Francis Beaudet
5 * Copyright 1999 Thuy Nguyen
9 * - Unicode property sheets
20 #include "debugtools.h"
24 /******************************************************************************
36 typedef struct tagPropPageInfo
38 HPROPSHEETPAGE hpage
; /* to keep track of pages not passed to PropertySheet */
47 typedef struct tagPropSheetInfo
50 PROPSHEETHEADERA ppshheader
;
51 LPSTR strPropertiesFor
;
61 PropPageInfo
* proppage
;
66 HIMAGELIST hImageList
;
75 /******************************************************************************
76 * Defines and global variables
79 const char * PropSheetInfoStr
= "PropertySheetInfo";
81 #define MAX_CAPTION_LENGTH 255
82 #define MAX_TABTEXT_LENGTH 255
83 #define MAX_BUTTONTEXT_LENGTH 64
85 /******************************************************************************
88 static BOOL
PROPSHEET_CreateDialog(PropSheetInfo
* psInfo
);
89 static BOOL
PROPSHEET_SizeMismatch(HWND hwndDlg
, PropSheetInfo
* psInfo
);
90 static BOOL
PROPSHEET_AdjustSize(HWND hwndDlg
, PropSheetInfo
* psInfo
);
91 static BOOL
PROPSHEET_AdjustButtons(HWND hwndParent
, PropSheetInfo
* psInfo
);
92 static BOOL
PROPSHEET_CollectSheetInfo(LPCPROPSHEETHEADERA lppsh
,
93 PropSheetInfo
* psInfo
);
94 static BOOL
PROPSHEET_CollectPageInfo(LPCPROPSHEETPAGEA lppsp
,
95 PropSheetInfo
* psInfo
,
97 static BOOL
PROPSHEET_CreateTabControl(HWND hwndParent
,
98 PropSheetInfo
* psInfo
);
99 static BOOL
PROPSHEET_CreatePage(HWND hwndParent
, int index
,
100 const PropSheetInfo
* psInfo
,
101 LPCPROPSHEETPAGEA ppshpage
);
102 static BOOL
PROPSHEET_ShowPage(HWND hwndDlg
, int index
, PropSheetInfo
* psInfo
);
103 static PADDING_INFO
PROPSHEET_GetPaddingInfo(HWND hwndDlg
);
104 static BOOL
PROPSHEET_Back(HWND hwndDlg
);
105 static BOOL
PROPSHEET_Next(HWND hwndDlg
);
106 static BOOL
PROPSHEET_Finish(HWND hwndDlg
);
107 static BOOL
PROPSHEET_Apply(HWND hwndDlg
, LPARAM lParam
);
108 static void PROPSHEET_Cancel(HWND hwndDlg
, LPARAM lParam
);
109 static void PROPSHEET_Help(HWND hwndDlg
);
110 static void PROPSHEET_Changed(HWND hwndDlg
, HWND hwndDirtyPage
);
111 static void PROPSHEET_UnChanged(HWND hwndDlg
, HWND hwndCleanPage
);
112 static void PROPSHEET_PressButton(HWND hwndDlg
, int buttonID
);
113 static void PROPSHEET_SetFinishTextA(HWND hwndDlg
, LPCSTR lpszText
);
114 static void PROPSHEET_SetTitleA(HWND hwndDlg
, DWORD dwStyle
, LPCSTR lpszText
);
115 static BOOL
PROPSHEET_CanSetCurSel(HWND hwndDlg
);
116 static BOOL
PROPSHEET_SetCurSel(HWND hwndDlg
,
118 HPROPSHEETPAGE hpage
);
119 static LRESULT
PROPSHEET_QuerySiblings(HWND hwndDlg
,
120 WPARAM wParam
, LPARAM lParam
);
121 static BOOL
PROPSHEET_AddPage(HWND hwndDlg
,
122 HPROPSHEETPAGE hpage
);
124 static BOOL
PROPSHEET_RemovePage(HWND hwndDlg
,
126 HPROPSHEETPAGE hpage
);
127 static void PROPSHEET_CleanUp();
128 static int PROPSHEET_GetPageIndex(HPROPSHEETPAGE hpage
, PropSheetInfo
* psInfo
);
129 static void PROPSHEET_SetWizButtons(HWND hwndDlg
, DWORD dwFlags
);
130 static PADDING_INFO
PROPSHEET_GetPaddingInfoWizard(HWND hwndDlg
, const PropSheetInfo
* psInfo
);
131 static BOOL
PROPSHEET_IsDialogMessage(HWND hwnd
, LPMSG lpMsg
);
132 static INT
PROPSHEET_DoDialogBox( HWND hwnd
, HWND owner
);
135 PROPSHEET_DialogProc(HWND hwnd
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
);
137 DEFAULT_DEBUG_CHANNEL(propsheet
);
139 /******************************************************************************
140 * PROPSHEET_CollectSheetInfo
142 * Collect relevant data.
144 static BOOL
PROPSHEET_CollectSheetInfo(LPCPROPSHEETHEADERA lppsh
,
145 PropSheetInfo
* psInfo
)
147 DWORD dwSize
= min(lppsh
->dwSize
,sizeof(PROPSHEETHEADERA
));
148 DWORD dwFlags
= lppsh
->dwFlags
;
150 psInfo
->hasHelp
= dwFlags
& PSH_HASHELP
;
151 psInfo
->hasApply
= !(dwFlags
& PSH_NOAPPLYNOW
);
152 psInfo
->useCallback
= dwFlags
& PSH_USECALLBACK
;
153 psInfo
->isModeless
= dwFlags
& PSH_MODELESS
;
155 memcpy(&psInfo
->ppshheader
,lppsh
,dwSize
);
157 if (HIWORD(lppsh
->pszCaption
))
158 psInfo
->ppshheader
.pszCaption
= HEAP_strdupA( GetProcessHeap(),
159 0, lppsh
->pszCaption
);
161 psInfo
->nPages
= lppsh
->nPages
;
163 if (dwFlags
& PSH_USEPSTARTPAGE
)
165 TRACE("PSH_USEPSTARTPAGE is on");
166 psInfo
->active_page
= 0;
169 psInfo
->active_page
= lppsh
->u2
.nStartPage
;
171 if (psInfo
->active_page
< 0 || psInfo
->active_page
>= psInfo
->nPages
)
172 psInfo
->active_page
= 0;
174 psInfo
->restartWindows
= FALSE
;
175 psInfo
->rebootSystem
= FALSE
;
176 psInfo
->hImageList
= 0;
177 psInfo
->activeValid
= FALSE
;
182 /******************************************************************************
183 * PROPSHEET_CollectPageInfo
185 * Collect property sheet data.
186 * With code taken from DIALOG_ParseTemplate32.
188 BOOL
PROPSHEET_CollectPageInfo(LPCPROPSHEETPAGEA lppsp
,
189 PropSheetInfo
* psInfo
,
192 DLGTEMPLATE
* pTemplate
;
197 psInfo
->proppage
[index
].hpage
= (HPROPSHEETPAGE
)lppsp
;
198 psInfo
->proppage
[index
].hwndPage
= 0;
199 psInfo
->proppage
[index
].isDirty
= FALSE
;
202 * Process property page flags.
204 dwFlags
= lppsp
->dwFlags
;
205 psInfo
->proppage
[index
].useCallback
= dwFlags
& PSP_USECALLBACK
;
206 psInfo
->proppage
[index
].hasHelp
= dwFlags
& PSP_HASHELP
;
207 psInfo
->proppage
[index
].hasIcon
= dwFlags
& (PSP_USEHICON
| PSP_USEICONID
);
209 /* as soon as we have a page with the help flag, set the sheet flag on */
210 if (psInfo
->proppage
[index
].hasHelp
)
211 psInfo
->hasHelp
= TRUE
;
214 * Process page template.
216 if (dwFlags
& PSP_DLGINDIRECT
)
217 pTemplate
= (DLGTEMPLATE
*)lppsp
->u
.pResource
;
220 HRSRC hResource
= FindResourceA(lppsp
->hInstance
,
221 lppsp
->u
.pszTemplate
,
223 HGLOBAL hTemplate
= LoadResource(lppsp
->hInstance
,
225 pTemplate
= (LPDLGTEMPLATEA
)LockResource(hTemplate
);
229 * Extract the size of the page and the caption.
234 p
= (const WORD
*)pTemplate
;
236 if (((MyDLGTEMPLATEEX
*)pTemplate
)->signature
== 0xFFFF)
238 /* DIALOGEX template */
242 p
+= 2; /* help ID */
243 p
+= 2; /* ext style */
248 /* DIALOG template */
251 p
+= 2; /* ext style */
257 width
= (WORD
)*p
; p
++;
258 height
= (WORD
)*p
; p
++;
260 /* remember the largest width and height */
261 if (width
> psInfo
->width
)
262 psInfo
->width
= width
;
264 if (height
> psInfo
->height
)
265 psInfo
->height
= height
;
277 p
+= lstrlenW( (LPCWSTR
)p
) + 1;
291 p
+= lstrlenW( (LPCWSTR
)p
) + 1;
295 /* Extract the caption */
296 psInfo
->proppage
[index
].pszText
= (LPCWSTR
)p
;
297 TRACE("Tab %d %s\n",index
,debugstr_w((LPCWSTR
)p
));
298 p
+= lstrlenW((LPCWSTR
)p
) + 1;
300 if (dwFlags
& PSP_USETITLE
)
302 if ( !HIWORD( lppsp
->pszTitle
) )
306 if ( !LoadStringA( lppsp
->hInstance
, (UINT
) lppsp
->pszTitle
, szTitle
, 256 ) )
309 psInfo
->proppage
[index
].pszText
= HEAP_strdupAtoW( GetProcessHeap(),
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
);
346 /******************************************************************************
347 * PROPSHEET_DoDialogBox
349 * Copied from windows/dialog.c:DIALOG_DoDialogBox
351 static INT
PROPSHEET_DoDialogBox( HWND hwnd
, HWND owner
)
354 DIALOGINFO
* dlgInfo
;
358 /* Owner must be a top-level window */
359 owner
= WIN_GetTopParent( owner
);
360 if (!(wndPtr
= WIN_FindWndPtr( hwnd
))) return -1;
361 dlgInfo
= (DIALOGINFO
*)wndPtr
->wExtra
;
363 if (!(dlgInfo
->flags
& DF_END
)) /* was EndDialog called in WM_INITDIALOG ? */
365 EnableWindow( owner
, FALSE
);
366 ShowWindow( hwnd
, SW_SHOW
);
367 while (GetMessageA(&msg
, 0, 0, 0))
369 if (!PROPSHEET_IsDialogMessage( hwnd
, &msg
))
371 TranslateMessage( &msg
);
372 DispatchMessageA( &msg
);
374 if (dlgInfo
->flags
& DF_END
) break;
376 EnableWindow( owner
, TRUE
);
378 retval
= dlgInfo
->idResult
;
379 WIN_ReleaseWndPtr(wndPtr
);
380 DestroyWindow( hwnd
);
385 /******************************************************************************
386 * PROPSHEET_CreateDialog
388 * Creates the actual property sheet.
390 BOOL
PROPSHEET_CreateDialog(PropSheetInfo
* psInfo
)
397 WORD resID
= IDD_PROPSHEET
;
399 if (psInfo
->ppshheader
.dwFlags
& PSH_WIZARD
)
402 if(!(hRes
= FindResourceA(COMCTL32_hModule
,
403 MAKEINTRESOURCEA(resID
),
407 if(!(template = (LPVOID
)LoadResource(COMCTL32_hModule
, hRes
)))
411 * Make a copy of the dialog template.
413 resSize
= SizeofResource(COMCTL32_hModule
, hRes
);
415 temp
= COMCTL32_Alloc(resSize
);
420 memcpy(temp
, template, resSize
);
422 if (psInfo
->useCallback
)
423 (*(psInfo
->ppshheader
.pfnCallback
))(0, PSCB_PRECREATE
, (LPARAM
)temp
);
425 ret
= CreateDialogIndirectParamA(psInfo
->ppshheader
.hInstance
,
426 (LPDLGTEMPLATEA
) temp
,
427 psInfo
->ppshheader
.hwndParent
,
428 (DLGPROC
) PROPSHEET_DialogProc
,
431 if (!(psInfo
->ppshheader
.dwFlags
& PSH_MODELESS
))
432 ret
= PROPSHEET_DoDialogBox((HWND
)ret
, psInfo
->ppshheader
.hwndParent
);
439 /******************************************************************************
440 * PROPSHEET_SizeMismatch
442 * Verify that the tab control and the "largest" property sheet page dlg. template
445 static BOOL
PROPSHEET_SizeMismatch(HWND hwndDlg
, PropSheetInfo
* psInfo
)
447 HWND hwndTabCtrl
= GetDlgItem(hwndDlg
, IDC_TABCONTROL
);
448 RECT rcOrigTab
, rcPage
;
453 GetClientRect(hwndTabCtrl
, &rcOrigTab
);
454 TRACE("orig tab %d %d %d %d\n", rcOrigTab
.left
, rcOrigTab
.top
,
455 rcOrigTab
.right
, rcOrigTab
.bottom
);
460 rcPage
.left
= psInfo
->x
;
461 rcPage
.top
= psInfo
->y
;
462 rcPage
.right
= psInfo
->width
;
463 rcPage
.bottom
= psInfo
->height
;
465 MapDialogRect(hwndDlg
, &rcPage
);
466 TRACE("biggest page %d %d %d %d\n", rcPage
.left
, rcPage
.top
,
467 rcPage
.right
, rcPage
.bottom
);
469 if ( (rcPage
.right
- rcPage
.left
) != (rcOrigTab
.right
- rcOrigTab
.left
) )
471 if ( (rcPage
.bottom
- rcPage
.top
) != (rcOrigTab
.bottom
- rcOrigTab
.top
) )
477 /******************************************************************************
478 * PROPSHEET_IsTooSmallWizard
480 * Verify that the default property sheet is big enough.
482 static BOOL
PROPSHEET_IsTooSmallWizard(HWND hwndDlg
, PropSheetInfo
* psInfo
)
484 RECT rcSheetRect
, rcPage
, rcLine
, rcSheetClient
;
485 HWND hwndLine
= GetDlgItem(hwndDlg
, IDC_SUNKEN_LINE
);
486 PADDING_INFO padding
= PROPSHEET_GetPaddingInfoWizard(hwndDlg
, psInfo
);
488 GetClientRect(hwndDlg
, &rcSheetClient
);
489 GetWindowRect(hwndDlg
, &rcSheetRect
);
490 GetWindowRect(hwndLine
, &rcLine
);
492 /* Remove the space below the sunken line */
493 rcSheetClient
.bottom
-= (rcSheetRect
.bottom
- rcLine
.top
);
495 /* Remove the buffer zone all around the edge */
496 rcSheetClient
.bottom
-= (padding
.y
* 2);
497 rcSheetClient
.right
-= (padding
.x
* 2);
502 rcPage
.left
= psInfo
->x
;
503 rcPage
.top
= psInfo
->y
;
504 rcPage
.right
= psInfo
->width
;
505 rcPage
.bottom
= psInfo
->height
;
507 MapDialogRect(hwndDlg
, &rcPage
);
508 TRACE("biggest page %d %d %d %d\n", rcPage
.left
, rcPage
.top
,
509 rcPage
.right
, rcPage
.bottom
);
511 if (rcPage
.right
> rcSheetClient
.right
)
514 if (rcPage
.bottom
> rcSheetClient
.bottom
)
520 /******************************************************************************
521 * PROPSHEET_AdjustSize
523 * Resizes the property sheet and the tab control to fit the largest page.
525 static BOOL
PROPSHEET_AdjustSize(HWND hwndDlg
, PropSheetInfo
* psInfo
)
527 HWND hwndTabCtrl
= GetDlgItem(hwndDlg
, IDC_TABCONTROL
);
528 HWND hwndButton
= GetDlgItem(hwndDlg
, IDOK
);
530 int tabOffsetX
, tabOffsetY
, buttonHeight
;
531 PADDING_INFO padding
= PROPSHEET_GetPaddingInfo(hwndDlg
);
532 WND
* wndPtr
= WIN_FindWndPtr( hwndDlg
);
533 DIALOGINFO
* dlgInfo
= (DIALOGINFO
*)wndPtr
->wExtra
;
535 /* Get the height of buttons */
536 GetClientRect(hwndButton
, &rc
);
537 buttonHeight
= rc
.bottom
;
544 rc
.right
= psInfo
->width
;
545 rc
.bottom
= psInfo
->height
;
547 MapDialogRect(hwndDlg
, &rc
);
550 * Resize the tab control.
552 GetClientRect(hwndTabCtrl
,&tabRect
);
554 SendMessageA(hwndTabCtrl
, TCM_ADJUSTRECT
, FALSE
, (LPARAM
)&tabRect
);
556 if ((rc
.bottom
- rc
.top
) < (tabRect
.bottom
- tabRect
.top
))
558 rc
.bottom
= rc
.top
+ tabRect
.bottom
- tabRect
.top
;
559 psInfo
->height
= MulDiv((rc
.bottom
- rc
.top
),8,dlgInfo
->yBaseUnit
);
562 if ((rc
.right
- rc
.left
) < (tabRect
.right
- tabRect
.left
))
564 rc
.right
= rc
.left
+ tabRect
.right
- tabRect
.left
;
565 psInfo
->width
= MulDiv((rc
.right
- rc
.left
),4,dlgInfo
->xBaseUnit
);
568 SendMessageA(hwndTabCtrl
, TCM_ADJUSTRECT
, TRUE
, (LPARAM
)&rc
);
570 tabOffsetX
= -(rc
.left
);
571 tabOffsetY
= -(rc
.top
);
575 SetWindowPos(hwndTabCtrl
, 0, 0, 0, rc
.right
, rc
.bottom
,
576 SWP_NOMOVE
| SWP_NOZORDER
| SWP_NOACTIVATE
);
578 GetClientRect(hwndTabCtrl
, &rc
);
580 TRACE("tab client rc %d %d %d %d\n",
581 rc
.left
, rc
.top
, rc
.right
, rc
.bottom
);
583 rc
.right
+= ((padding
.x
* 2) + tabOffsetX
);
584 rc
.bottom
+= (buttonHeight
+ (3 * padding
.y
) + tabOffsetY
);
587 * Resize the property sheet.
589 SetWindowPos(hwndDlg
, 0, 0, 0, rc
.right
, rc
.bottom
,
590 SWP_NOMOVE
| SWP_NOZORDER
| SWP_NOACTIVATE
);
592 WIN_ReleaseWndPtr(wndPtr
);
596 /******************************************************************************
597 * PROPSHEET_AdjustSizeWizard
599 * Resizes the property sheet to fit the largest page.
601 static BOOL
PROPSHEET_AdjustSizeWizard(HWND hwndDlg
, PropSheetInfo
* psInfo
)
603 HWND hwndButton
= GetDlgItem(hwndDlg
, IDCANCEL
);
604 HWND hwndLine
= GetDlgItem(hwndDlg
, IDC_SUNKEN_LINE
);
605 HWND hwndTabCtrl
= GetDlgItem(hwndDlg
, IDC_TABCONTROL
);
607 int buttonHeight
, lineHeight
;
608 PADDING_INFO padding
= PROPSHEET_GetPaddingInfoWizard(hwndDlg
, psInfo
);
609 WND
* wndPtr
= WIN_FindWndPtr( hwndDlg
);
610 DIALOGINFO
* dlgInfo
= (DIALOGINFO
*)wndPtr
->wExtra
;
612 /* Get the height of buttons */
613 GetClientRect(hwndButton
, &rc
);
614 buttonHeight
= rc
.bottom
;
616 GetClientRect(hwndLine
, &rc
);
617 lineHeight
= rc
.bottom
;
624 rc
.right
= psInfo
->width
;
625 rc
.bottom
= psInfo
->height
;
627 MapDialogRect(hwndDlg
, &rc
);
629 GetClientRect(hwndTabCtrl
,&tabRect
);
631 if ((rc
.bottom
- rc
.top
) < (tabRect
.bottom
- tabRect
.top
))
633 rc
.bottom
= rc
.top
+ tabRect
.bottom
- tabRect
.top
;
634 psInfo
->height
= MulDiv((rc
.bottom
- rc
.top
), 8, dlgInfo
->yBaseUnit
);
637 if ((rc
.right
- rc
.left
) < (tabRect
.right
- tabRect
.left
))
639 rc
.right
= rc
.left
+ tabRect
.right
- tabRect
.left
;
640 psInfo
->width
= MulDiv((rc
.right
- rc
.left
), 4, dlgInfo
->xBaseUnit
);
643 TRACE("Biggest page %d %d %d %d\n", rc
.left
, rc
.top
, rc
.right
, rc
.bottom
);
646 rc
.right
+= (padding
.x
* 2);
647 rc
.bottom
+= (buttonHeight
+ (5 * padding
.y
) + lineHeight
);
650 * Resize the property sheet.
652 SetWindowPos(hwndDlg
, 0, 0, 0, rc
.right
, rc
.bottom
,
653 SWP_NOMOVE
| SWP_NOZORDER
| SWP_NOACTIVATE
);
655 WIN_ReleaseWndPtr(wndPtr
);
659 /******************************************************************************
660 * PROPSHEET_AdjustButtons
662 * Adjusts the buttons' positions.
664 static BOOL
PROPSHEET_AdjustButtons(HWND hwndParent
, PropSheetInfo
* psInfo
)
666 HWND hwndButton
= GetDlgItem(hwndParent
, IDOK
);
670 int buttonWidth
, buttonHeight
;
671 PADDING_INFO padding
= PROPSHEET_GetPaddingInfo(hwndParent
);
673 if (psInfo
->hasApply
)
680 * Obtain the size of the buttons.
682 GetClientRect(hwndButton
, &rcSheet
);
683 buttonWidth
= rcSheet
.right
;
684 buttonHeight
= rcSheet
.bottom
;
687 * Get the size of the property sheet.
689 GetClientRect(hwndParent
, &rcSheet
);
692 * All buttons will be at this y coordinate.
694 y
= rcSheet
.bottom
- (padding
.y
+ buttonHeight
);
697 * Position OK button.
699 hwndButton
= GetDlgItem(hwndParent
, IDOK
);
701 x
= rcSheet
.right
- ((padding
.x
+ buttonWidth
) * num_buttons
);
703 SetWindowPos(hwndButton
, 0, x
, y
, 0, 0,
704 SWP_NOSIZE
| SWP_NOZORDER
| SWP_NOACTIVATE
);
707 * Position Cancel button.
709 hwndButton
= GetDlgItem(hwndParent
, IDCANCEL
);
711 x
= rcSheet
.right
- ((padding
.x
+ buttonWidth
) * (num_buttons
- 1));
713 SetWindowPos(hwndButton
, 0, x
, y
, 0, 0,
714 SWP_NOSIZE
| SWP_NOZORDER
| SWP_NOACTIVATE
);
717 * Position Apply button.
719 hwndButton
= GetDlgItem(hwndParent
, IDC_APPLY_BUTTON
);
721 if (psInfo
->hasApply
)
724 x
= rcSheet
.right
- ((padding
.x
+ buttonWidth
) * 2);
726 x
= rcSheet
.right
- (padding
.x
+ buttonWidth
);
728 SetWindowPos(hwndButton
, 0, x
, y
, 0, 0,
729 SWP_NOSIZE
| SWP_NOZORDER
| SWP_NOACTIVATE
);
731 EnableWindow(hwndButton
, FALSE
);
734 ShowWindow(hwndButton
, SW_HIDE
);
737 * Position Help button.
739 hwndButton
= GetDlgItem(hwndParent
, IDHELP
);
743 x
= rcSheet
.right
- (padding
.x
+ buttonWidth
);
745 SetWindowPos(hwndButton
, 0, x
, y
, 0, 0,
746 SWP_NOSIZE
| SWP_NOZORDER
| SWP_NOACTIVATE
);
749 ShowWindow(hwndButton
, SW_HIDE
);
754 /******************************************************************************
755 * PROPSHEET_AdjustButtonsWizard
757 * Adjusts the buttons' positions.
759 static BOOL
PROPSHEET_AdjustButtonsWizard(HWND hwndParent
,
760 PropSheetInfo
* psInfo
)
762 HWND hwndButton
= GetDlgItem(hwndParent
, IDCANCEL
);
763 HWND hwndLine
= GetDlgItem(hwndParent
, IDC_SUNKEN_LINE
);
767 int buttonWidth
, buttonHeight
, lineHeight
, lineWidth
;
768 PADDING_INFO padding
= PROPSHEET_GetPaddingInfoWizard(hwndParent
, psInfo
);
774 * Obtain the size of the buttons.
776 GetClientRect(hwndButton
, &rcSheet
);
777 buttonWidth
= rcSheet
.right
;
778 buttonHeight
= rcSheet
.bottom
;
780 GetClientRect(hwndLine
, &rcSheet
);
781 lineHeight
= rcSheet
.bottom
;
784 * Get the size of the property sheet.
786 GetClientRect(hwndParent
, &rcSheet
);
789 * All buttons will be at this y coordinate.
791 y
= rcSheet
.bottom
- (padding
.y
+ buttonHeight
);
794 * Position the Next and the Finish buttons.
796 hwndButton
= GetDlgItem(hwndParent
, IDC_NEXT_BUTTON
);
798 x
= rcSheet
.right
- ((padding
.x
+ buttonWidth
) * (num_buttons
- 1));
800 SetWindowPos(hwndButton
, 0, x
, y
, 0, 0,
801 SWP_NOSIZE
| SWP_NOZORDER
| SWP_NOACTIVATE
);
803 hwndButton
= GetDlgItem(hwndParent
, IDC_FINISH_BUTTON
);
805 SetWindowPos(hwndButton
, 0, x
, y
, 0, 0,
806 SWP_NOSIZE
| SWP_NOZORDER
| SWP_NOACTIVATE
);
808 ShowWindow(hwndButton
, SW_HIDE
);
811 * Position the Back button.
813 hwndButton
= GetDlgItem(hwndParent
, IDC_BACK_BUTTON
);
817 SetWindowPos(hwndButton
, 0, x
, y
, 0, 0,
818 SWP_NOSIZE
| SWP_NOZORDER
| SWP_NOACTIVATE
);
821 * Position the Cancel button.
823 hwndButton
= GetDlgItem(hwndParent
, IDCANCEL
);
825 x
= rcSheet
.right
- ((padding
.x
+ buttonWidth
) * (num_buttons
- 2));
827 SetWindowPos(hwndButton
, 0, x
, y
, 0, 0,
828 SWP_NOSIZE
| SWP_NOZORDER
| SWP_NOACTIVATE
);
831 * Position Help button.
833 hwndButton
= GetDlgItem(hwndParent
, IDHELP
);
837 x
= rcSheet
.right
- (padding
.x
+ buttonWidth
);
839 SetWindowPos(hwndButton
, 0, x
, y
, 0, 0,
840 SWP_NOSIZE
| SWP_NOZORDER
| SWP_NOACTIVATE
);
843 ShowWindow(hwndButton
, SW_HIDE
);
846 * Position and resize the sunken line.
849 y
= rcSheet
.bottom
- ((padding
.y
* 2) + buttonHeight
+ lineHeight
);
851 GetClientRect(hwndParent
, &rcSheet
);
852 lineWidth
= rcSheet
.right
- (padding
.x
* 2);
854 SetWindowPos(hwndLine
, 0, x
, y
, lineWidth
, 2,
855 SWP_NOZORDER
| SWP_NOACTIVATE
);
860 /******************************************************************************
861 * PROPSHEET_GetPaddingInfo
863 * Returns the layout information.
865 static PADDING_INFO
PROPSHEET_GetPaddingInfo(HWND hwndDlg
)
867 HWND hwndTab
= GetDlgItem(hwndDlg
, IDC_TABCONTROL
);
870 PADDING_INFO padding
;
872 GetWindowRect(hwndTab
, &rcTab
);
877 ScreenToClient(hwndDlg
, &tl
);
885 /******************************************************************************
886 * PROPSHEET_GetPaddingInfoWizard
888 * Returns the layout information.
889 * Vertical spacing is the distance between the line and the buttons.
890 * Do NOT use the Help button to gather padding information when it isn't mapped
891 * (PSH_HASHELP), as app writers aren't forced to supply correct coordinates
892 * for it in this case !
893 * FIXME: I'm not sure about any other coordinate problems with these evil
894 * buttons. Fix it in case additional problems appear or maybe calculate
895 * a padding in a completely different way, as this is somewhat messy.
897 static PADDING_INFO
PROPSHEET_GetPaddingInfoWizard(HWND hwndDlg
, const PropSheetInfo
*
900 PADDING_INFO padding
;
904 POINT ptButton
, ptLine
;
912 if (psInfo
->ppshheader
.dwFlags
& PSH_WIZARD
)
914 idButton
= IDC_NEXT_BUTTON
;
918 /* hopefully this is ok */
923 hwndControl
= GetDlgItem(hwndDlg
, idButton
);
924 GetWindowRect(hwndControl
, &rc
);
926 ptButton
.x
= rc
.left
;
929 ScreenToClient(hwndDlg
, &ptButton
);
932 hwndControl
= GetDlgItem(hwndDlg
, IDC_SUNKEN_LINE
);
933 GetWindowRect(hwndControl
, &rc
);
936 ptLine
.y
= rc
.bottom
;
938 ScreenToClient(hwndDlg
, &ptLine
);
940 padding
.y
= ptButton
.y
- ptLine
.y
;
943 ERR("padding negative ! Please report this !\n");
945 /* this is most probably not correct, but the best we have now */
946 padding
.x
= padding
.y
;
950 /******************************************************************************
951 * PROPSHEET_CreateTabControl
953 * Insert the tabs in the tab control.
955 static BOOL
PROPSHEET_CreateTabControl(HWND hwndParent
,
956 PropSheetInfo
* psInfo
)
958 HWND hwndTabCtrl
= GetDlgItem(hwndParent
, IDC_TABCONTROL
);
962 char tabtext
[MAX_TABTEXT_LENGTH
] = "Tab text";
964 item
.mask
= TCIF_TEXT
;
965 item
.pszText
= tabtext
;
966 item
.cchTextMax
= MAX_TABTEXT_LENGTH
;
968 nTabs
= psInfo
->nPages
;
971 * Set the image list for icons.
973 if (psInfo
->hImageList
)
975 SendMessageA(hwndTabCtrl
, TCM_SETIMAGELIST
, 0, (LPARAM
)psInfo
->hImageList
);
978 for (i
= 0; i
< nTabs
; i
++)
980 if ( psInfo
->proppage
[i
].hasIcon
)
982 item
.mask
|= TCIF_IMAGE
;
983 item
.iImage
= iImage
++;
987 item
.mask
&= ~TCIF_IMAGE
;
990 WideCharToMultiByte(CP_ACP
, 0,
991 (LPCWSTR
)psInfo
->proppage
[i
].pszText
,
992 -1, tabtext
, MAX_TABTEXT_LENGTH
, NULL
, NULL
);
994 SendMessageA(hwndTabCtrl
, TCM_INSERTITEMA
, (WPARAM
)i
, (LPARAM
)&item
);
1000 /******************************************************************************
1001 * PROPSHEET_CreatePage
1005 static BOOL
PROPSHEET_CreatePage(HWND hwndParent
,
1007 const PropSheetInfo
* psInfo
,
1008 LPCPROPSHEETPAGEA ppshpage
)
1010 DLGTEMPLATE
* pTemplate
;
1013 PropPageInfo
* ppInfo
= psInfo
->proppage
;
1014 PADDING_INFO padding
;
1015 UINT pageWidth
,pageHeight
;
1019 TRACE("index %d\n", index
);
1021 if (ppshpage
->dwFlags
& PSP_DLGINDIRECT
)
1022 pTemplate
= (DLGTEMPLATE
*)ppshpage
->u
.pResource
;
1028 hResource
= FindResourceA(ppshpage
->hInstance
,
1029 ppshpage
->u
.pszTemplate
,
1034 resSize
= SizeofResource(ppshpage
->hInstance
, hResource
);
1036 hTemplate
= LoadResource(ppshpage
->hInstance
, hResource
);
1040 pTemplate
= (LPDLGTEMPLATEA
)LockResource(hTemplate
);
1042 * Make a copy of the dialog template to make it writable
1044 temp
= COMCTL32_Alloc(resSize
);
1048 memcpy(temp
, pTemplate
, resSize
);
1052 if (((MyDLGTEMPLATEEX
*)pTemplate
)->signature
== 0xFFFF)
1054 ((MyDLGTEMPLATEEX
*)pTemplate
)->style
|= WS_CHILD
| DS_CONTROL
;
1055 ((MyDLGTEMPLATEEX
*)pTemplate
)->style
&= ~DS_MODALFRAME
;
1056 ((MyDLGTEMPLATEEX
*)pTemplate
)->style
&= ~WS_CAPTION
;
1057 ((MyDLGTEMPLATEEX
*)pTemplate
)->style
&= ~WS_SYSMENU
;
1058 ((MyDLGTEMPLATEEX
*)pTemplate
)->style
&= ~WS_POPUP
;
1059 ((MyDLGTEMPLATEEX
*)pTemplate
)->style
&= ~WS_DISABLED
;
1060 ((MyDLGTEMPLATEEX
*)pTemplate
)->style
&= ~WS_VISIBLE
;
1064 pTemplate
->style
|= WS_CHILD
| DS_CONTROL
;
1065 pTemplate
->style
&= ~DS_MODALFRAME
;
1066 pTemplate
->style
&= ~WS_CAPTION
;
1067 pTemplate
->style
&= ~WS_SYSMENU
;
1068 pTemplate
->style
&= ~WS_POPUP
;
1069 pTemplate
->style
&= ~WS_DISABLED
;
1070 pTemplate
->style
&= ~WS_VISIBLE
;
1073 if (psInfo
->proppage
[index
].useCallback
)
1074 (*(ppshpage
->pfnCallback
))(hwndParent
,
1076 (LPPROPSHEETPAGEA
)ppshpage
);
1078 hwndPage
= CreateDialogIndirectParamA(ppshpage
->hInstance
,
1081 ppshpage
->pfnDlgProc
,
1083 /* Free a no more needed copy */
1085 COMCTL32_Free(temp
);
1087 ppInfo
[index
].hwndPage
= hwndPage
;
1089 rc
.left
= psInfo
->x
;
1091 rc
.right
= psInfo
->width
;
1092 rc
.bottom
= psInfo
->height
;
1094 MapDialogRect(hwndParent
, &rc
);
1096 pageWidth
= rc
.right
- rc
.left
;
1097 pageHeight
= rc
.bottom
- rc
.top
;
1099 if (psInfo
->ppshheader
.dwFlags
& PSH_WIZARD
)
1100 padding
= PROPSHEET_GetPaddingInfoWizard(hwndParent
, psInfo
);
1104 * Ask the Tab control to fit this page in.
1107 HWND hwndTabCtrl
= GetDlgItem(hwndParent
, IDC_TABCONTROL
);
1108 SendMessageA(hwndTabCtrl
, TCM_ADJUSTRECT
, FALSE
, (LPARAM
)&rc
);
1109 padding
= PROPSHEET_GetPaddingInfo(hwndParent
);
1112 SetWindowPos(hwndPage
, HWND_TOP
,
1113 rc
.left
+ padding
.x
,
1115 pageWidth
, pageHeight
, 0);
1120 /******************************************************************************
1121 * PROPSHEET_ShowPage
1123 * Displays or creates the specified page.
1125 static BOOL
PROPSHEET_ShowPage(HWND hwndDlg
, int index
, PropSheetInfo
* psInfo
)
1127 if (index
== psInfo
->active_page
)
1129 if (GetTopWindow(hwndDlg
) != psInfo
->proppage
[index
].hwndPage
)
1130 SetWindowPos(psInfo
->proppage
[index
].hwndPage
, HWND_TOP
, 0, 0, 0, 0, SWP_NOSIZE
| SWP_NOMOVE
);
1134 if (psInfo
->proppage
[index
].hwndPage
== 0)
1136 LPCPROPSHEETPAGEA ppshpage
;
1139 ppshpage
= (LPCPROPSHEETPAGEA
)psInfo
->proppage
[index
].hpage
;
1140 PROPSHEET_CreatePage(hwndDlg
, index
, psInfo
, ppshpage
);
1142 psn
.hdr
.hwndFrom
= hwndDlg
;
1143 psn
.hdr
.code
= PSN_SETACTIVE
;
1147 /* Send the notification before showing the page. */
1148 SendMessageA(psInfo
->proppage
[index
].hwndPage
,
1149 WM_NOTIFY
, 0, (LPARAM
) &psn
);
1152 * TODO: check return value.
1156 if (psInfo
->active_page
!= -1)
1157 ShowWindow(psInfo
->proppage
[psInfo
->active_page
].hwndPage
, SW_HIDE
);
1159 ShowWindow(psInfo
->proppage
[index
].hwndPage
, SW_SHOW
);
1161 if (!(psInfo
->ppshheader
.dwFlags
& PSH_WIZARD
))
1165 /* Synchronize current selection with tab control */
1166 hwndTabCtrl
= GetDlgItem(hwndDlg
, IDC_TABCONTROL
);
1167 SendMessageA(hwndTabCtrl
, TCM_SETCURSEL
, index
, 0);
1170 psInfo
->active_page
= index
;
1171 psInfo
->activeValid
= TRUE
;
1176 /******************************************************************************
1179 static BOOL
PROPSHEET_Back(HWND hwndDlg
)
1184 PropSheetInfo
* psInfo
= (PropSheetInfo
*) GetPropA(hwndDlg
,
1187 if (psInfo
->active_page
< 0)
1190 psn
.hdr
.code
= PSN_WIZBACK
;
1191 psn
.hdr
.hwndFrom
= hwndDlg
;
1195 hwndPage
= psInfo
->proppage
[psInfo
->active_page
].hwndPage
;
1197 if (SendMessageA(hwndPage
, WM_NOTIFY
, 0, (LPARAM
) &psn
) == -1)
1200 if (psInfo
->active_page
> 0)
1202 res
= PROPSHEET_CanSetCurSel(hwndDlg
);
1205 res
= PROPSHEET_SetCurSel(hwndDlg
, psInfo
->active_page
- 1, 0);
1212 /******************************************************************************
1215 static BOOL
PROPSHEET_Next(HWND hwndDlg
)
1219 LRESULT msgResult
= 0;
1220 PropSheetInfo
* psInfo
= (PropSheetInfo
*) GetPropA(hwndDlg
,
1223 if (psInfo
->active_page
< 0)
1226 psn
.hdr
.code
= PSN_WIZNEXT
;
1227 psn
.hdr
.hwndFrom
= hwndDlg
;
1231 hwndPage
= psInfo
->proppage
[psInfo
->active_page
].hwndPage
;
1233 msgResult
= SendMessageA(hwndPage
, WM_NOTIFY
, 0, (LPARAM
) &psn
);
1235 TRACE("msg result %ld\n", msgResult
);
1237 if (msgResult
== -1)
1240 if(PROPSHEET_CanSetCurSel(hwndDlg
) != FALSE
)
1242 PROPSHEET_SetCurSel(hwndDlg
, psInfo
->active_page
+ 1, 0);
1248 /******************************************************************************
1251 static BOOL
PROPSHEET_Finish(HWND hwndDlg
)
1255 LRESULT msgResult
= 0;
1256 PropSheetInfo
* psInfo
= (PropSheetInfo
*) GetPropA(hwndDlg
,
1259 if (psInfo
->active_page
< 0)
1262 psn
.hdr
.code
= PSN_WIZFINISH
;
1263 psn
.hdr
.hwndFrom
= hwndDlg
;
1267 hwndPage
= psInfo
->proppage
[psInfo
->active_page
].hwndPage
;
1269 msgResult
= SendMessageA(hwndPage
, WM_NOTIFY
, 0, (LPARAM
) &psn
);
1271 TRACE("msg result %ld\n", msgResult
);
1276 if (psInfo
->isModeless
)
1277 psInfo
->activeValid
= FALSE
;
1279 EndDialog(hwndDlg
, TRUE
);
1284 /******************************************************************************
1287 static BOOL
PROPSHEET_Apply(HWND hwndDlg
, LPARAM lParam
)
1293 PropSheetInfo
* psInfo
= (PropSheetInfo
*) GetPropA(hwndDlg
,
1296 if (psInfo
->active_page
< 0)
1299 psn
.hdr
.hwndFrom
= hwndDlg
;
1305 * Send PSN_KILLACTIVE to the current page.
1307 psn
.hdr
.code
= PSN_KILLACTIVE
;
1309 hwndPage
= psInfo
->proppage
[psInfo
->active_page
].hwndPage
;
1311 if (SendMessageA(hwndPage
, WM_NOTIFY
, 0, (LPARAM
) &psn
) != FALSE
)
1315 * Send PSN_APPLY to all pages.
1317 psn
.hdr
.code
= PSN_APPLY
;
1318 psn
.lParam
= lParam
;
1320 for (i
= 0; i
< psInfo
->nPages
; i
++)
1322 hwndPage
= psInfo
->proppage
[i
].hwndPage
;
1325 msgResult
= SendMessageA(hwndPage
, WM_NOTIFY
, 0, (LPARAM
) &psn
);
1326 if (msgResult
== PSNRET_INVALID_NOCHANGEPAGE
)
1333 psInfo
->activeValid
= FALSE
;
1335 else if(psInfo
->active_page
>= 0)
1337 psn
.hdr
.code
= PSN_SETACTIVE
;
1339 hwndPage
= psInfo
->proppage
[psInfo
->active_page
].hwndPage
;
1340 SendMessageA(hwndPage
, WM_NOTIFY
, 0, (LPARAM
) &psn
);
1346 /******************************************************************************
1349 static void PROPSHEET_Cancel(HWND hwndDlg
, LPARAM lParam
)
1351 PropSheetInfo
* psInfo
= (PropSheetInfo
*) GetPropA(hwndDlg
,
1357 if (psInfo
->active_page
< 0)
1360 hwndPage
= psInfo
->proppage
[psInfo
->active_page
].hwndPage
;
1361 psn
.hdr
.code
= PSN_QUERYCANCEL
;
1362 psn
.hdr
.hwndFrom
= hwndDlg
;
1366 if (SendMessageA(hwndPage
, WM_NOTIFY
, 0, (LPARAM
) &psn
))
1369 psn
.hdr
.code
= PSN_RESET
;
1370 psn
.lParam
= lParam
;
1372 for (i
= 0; i
< psInfo
->nPages
; i
++)
1374 hwndPage
= psInfo
->proppage
[i
].hwndPage
;
1377 SendMessageA(hwndPage
, WM_NOTIFY
, 0, (LPARAM
) &psn
);
1380 if (psInfo
->isModeless
)
1382 /* makes PSM_GETCURRENTPAGEHWND return NULL */
1383 psInfo
->activeValid
= FALSE
;
1386 EndDialog(hwndDlg
, FALSE
);
1389 /******************************************************************************
1392 static void PROPSHEET_Help(HWND hwndDlg
)
1394 PropSheetInfo
* psInfo
= (PropSheetInfo
*) GetPropA(hwndDlg
,
1399 if (psInfo
->active_page
< 0)
1402 hwndPage
= psInfo
->proppage
[psInfo
->active_page
].hwndPage
;
1403 psn
.hdr
.code
= PSN_HELP
;
1404 psn
.hdr
.hwndFrom
= hwndDlg
;
1408 SendMessageA(hwndPage
, WM_NOTIFY
, 0, (LPARAM
) &psn
);
1411 /******************************************************************************
1414 static void PROPSHEET_Changed(HWND hwndDlg
, HWND hwndDirtyPage
)
1417 PropSheetInfo
* psInfo
= (PropSheetInfo
*) GetPropA(hwndDlg
,
1420 if (!psInfo
) return;
1422 * Set the dirty flag of this page.
1424 for (i
= 0; i
< psInfo
->nPages
; i
++)
1426 if (psInfo
->proppage
[i
].hwndPage
== hwndDirtyPage
)
1427 psInfo
->proppage
[i
].isDirty
= TRUE
;
1431 * Enable the Apply button.
1433 if (psInfo
->hasApply
)
1435 HWND hwndApplyBtn
= GetDlgItem(hwndDlg
, IDC_APPLY_BUTTON
);
1437 EnableWindow(hwndApplyBtn
, TRUE
);
1441 /******************************************************************************
1442 * PROPSHEET_UnChanged
1444 static void PROPSHEET_UnChanged(HWND hwndDlg
, HWND hwndCleanPage
)
1447 BOOL noPageDirty
= TRUE
;
1448 HWND hwndApplyBtn
= GetDlgItem(hwndDlg
, IDC_APPLY_BUTTON
);
1449 PropSheetInfo
* psInfo
= (PropSheetInfo
*) GetPropA(hwndDlg
,
1452 if ( !psInfo
) return;
1453 for (i
= 0; i
< psInfo
->nPages
; i
++)
1455 /* set the specified page as clean */
1456 if (psInfo
->proppage
[i
].hwndPage
== hwndCleanPage
)
1457 psInfo
->proppage
[i
].isDirty
= FALSE
;
1459 /* look to see if there's any dirty pages */
1460 if (psInfo
->proppage
[i
].isDirty
)
1461 noPageDirty
= FALSE
;
1465 * Disable Apply button.
1468 EnableWindow(hwndApplyBtn
, FALSE
);
1471 /******************************************************************************
1472 * PROPSHEET_PressButton
1474 static void PROPSHEET_PressButton(HWND hwndDlg
, int buttonID
)
1478 case PSBTN_APPLYNOW
:
1479 SendMessageA(hwndDlg
, WM_COMMAND
, IDC_APPLY_BUTTON
, 0);
1482 PROPSHEET_Back(hwndDlg
);
1485 SendMessageA(hwndDlg
, WM_COMMAND
, IDCANCEL
, 0);
1488 PROPSHEET_Finish(hwndDlg
);
1491 SendMessageA(hwndDlg
, WM_COMMAND
, IDHELP
, 0);
1494 PROPSHEET_Next(hwndDlg
);
1497 SendMessageA(hwndDlg
, WM_COMMAND
, IDOK
, 0);
1500 FIXME("Invalid button index %d\n", buttonID
);
1505 /*************************************************************************
1506 * BOOL PROPSHEET_CanSetCurSel [Internal]
1508 * Test weither the current page can be changed by sending a PSN_KILLACTIVE
1511 * hwndDlg [I] handle to a Dialog hWnd
1514 * TRUE if Current Selection can change
1518 static BOOL
PROPSHEET_CanSetCurSel(HWND hwndDlg
)
1520 PropSheetInfo
* psInfo
= (PropSheetInfo
*) GetPropA(hwndDlg
,
1528 if (psInfo
->active_page
< 0)
1532 * Notify the current page.
1534 hwndPage
= psInfo
->proppage
[psInfo
->active_page
].hwndPage
;
1535 psn
.hdr
.code
= PSN_KILLACTIVE
;
1536 psn
.hdr
.hwndFrom
= hwndDlg
;
1540 return !SendMessageA(hwndPage
, WM_NOTIFY
, 0, (LPARAM
) &psn
);
1543 /******************************************************************************
1544 * PROPSHEET_SetCurSel
1546 static BOOL
PROPSHEET_SetCurSel(HWND hwndDlg
,
1548 HPROPSHEETPAGE hpage
)
1550 PropSheetInfo
* psInfo
= (PropSheetInfo
*) GetPropA(hwndDlg
,
1553 HWND hwndHelp
= GetDlgItem(hwndDlg
, IDHELP
);
1555 /* hpage takes precedence over index */
1557 index
= PROPSHEET_GetPageIndex(hpage
, psInfo
);
1559 if (index
< 0 || index
>= psInfo
->nPages
)
1561 TRACE("Could not find page to select!\n");
1565 hwndPage
= psInfo
->proppage
[index
].hwndPage
;
1568 * Notify the new page if it's already created.
1569 * If not it will get created and notified in PROPSHEET_ShowPage.
1576 psn
.hdr
.code
= PSN_SETACTIVE
;
1577 psn
.hdr
.hwndFrom
= hwndDlg
;
1581 result
= SendMessageA(hwndPage
, WM_NOTIFY
, 0, (LPARAM
) &psn
);
1584 * TODO: check return value.
1589 * Display the new page.
1591 PROPSHEET_ShowPage(hwndDlg
, index
, psInfo
);
1593 if (psInfo
->proppage
[index
].hasHelp
)
1594 EnableWindow(hwndHelp
, TRUE
);
1596 EnableWindow(hwndHelp
, FALSE
);
1601 /******************************************************************************
1602 * PROPSHEET_SetTitleA
1604 static void PROPSHEET_SetTitleA(HWND hwndDlg
, DWORD dwStyle
, LPCSTR lpszText
)
1606 PropSheetInfo
* psInfo
= (PropSheetInfo
*) GetPropA(hwndDlg
, PropSheetInfoStr
);
1609 if (HIWORD(lpszText
) == 0) {
1610 if (!LoadStringA(psInfo
->ppshheader
.hInstance
,
1611 LOWORD(lpszText
), szTitle
, sizeof(szTitle
)-1))
1615 if (dwStyle
& PSH_PROPTITLE
)
1618 int lentitle
= strlen(lpszText
);
1619 int lenprop
= strlen(psInfo
->strPropertiesFor
);
1621 dest
= COMCTL32_Alloc(lentitle
+ lenprop
+ 1);
1622 strcpy(dest
, psInfo
->strPropertiesFor
);
1623 strcat(dest
, lpszText
);
1625 SetWindowTextA(hwndDlg
, dest
);
1626 COMCTL32_Free(dest
);
1629 SetWindowTextA(hwndDlg
, lpszText
);
1632 /******************************************************************************
1633 * PROPSHEET_SetFinishTextA
1635 static void PROPSHEET_SetFinishTextA(HWND hwndDlg
, LPCSTR lpszText
)
1637 HWND hwndButton
= GetDlgItem(hwndDlg
, IDC_FINISH_BUTTON
);
1639 /* Set text, show and enable the Finish button */
1640 SetWindowTextA(hwndButton
, lpszText
);
1641 ShowWindow(hwndButton
, SW_SHOW
);
1642 EnableWindow(hwndButton
, TRUE
);
1644 /* Make it default pushbutton */
1645 SendMessageA(hwndDlg
, DM_SETDEFID
, IDC_FINISH_BUTTON
, 0);
1647 /* Hide Back button */
1648 hwndButton
= GetDlgItem(hwndDlg
, IDC_BACK_BUTTON
);
1649 ShowWindow(hwndButton
, SW_HIDE
);
1651 /* Hide Next button */
1652 hwndButton
= GetDlgItem(hwndDlg
, IDC_NEXT_BUTTON
);
1653 ShowWindow(hwndButton
, SW_HIDE
);
1656 /******************************************************************************
1657 * PROPSHEET_QuerySiblings
1659 static LRESULT
PROPSHEET_QuerySiblings(HWND hwndDlg
,
1660 WPARAM wParam
, LPARAM lParam
)
1664 LRESULT msgResult
= 0;
1665 PropSheetInfo
* psInfo
= (PropSheetInfo
*) GetPropA(hwndDlg
,
1668 while ((i
< psInfo
->nPages
) && (msgResult
== 0))
1670 hwndPage
= psInfo
->proppage
[i
].hwndPage
;
1671 msgResult
= SendMessageA(hwndPage
, PSM_QUERYSIBLINGS
, wParam
, lParam
);
1679 /******************************************************************************
1682 static BOOL
PROPSHEET_AddPage(HWND hwndDlg
,
1683 HPROPSHEETPAGE hpage
)
1685 PropSheetInfo
* psInfo
= (PropSheetInfo
*) GetPropA(hwndDlg
,
1687 HWND hwndTabControl
= GetDlgItem(hwndDlg
, IDC_TABCONTROL
);
1689 char tabtext
[MAX_TABTEXT_LENGTH
] = "Tab text";
1690 LPCPROPSHEETPAGEA ppsp
= (LPCPROPSHEETPAGEA
)hpage
;
1693 * Allocate and fill in a new PropPageInfo entry.
1695 psInfo
->proppage
= (PropPageInfo
*) COMCTL32_ReAlloc(psInfo
->proppage
,
1696 sizeof(PropPageInfo
) *
1697 (psInfo
->nPages
+ 1));
1698 if (!PROPSHEET_CollectPageInfo(ppsp
, psInfo
, psInfo
->nPages
))
1701 psInfo
->proppage
[psInfo
->nPages
].hpage
= hpage
;
1703 if (ppsp
->dwFlags
& PSP_PREMATURE
)
1705 /* Create the page but don't show it */
1706 PROPSHEET_CreatePage(hwndDlg
, psInfo
->nPages
, psInfo
, ppsp
);
1710 * Add a new tab to the tab control.
1712 item
.mask
= TCIF_TEXT
;
1713 item
.pszText
= tabtext
;
1714 item
.cchTextMax
= MAX_TABTEXT_LENGTH
;
1716 WideCharToMultiByte(CP_ACP
, 0,
1717 (LPCWSTR
)psInfo
->proppage
[psInfo
->nPages
].pszText
,
1718 -1, tabtext
, MAX_TABTEXT_LENGTH
, NULL
, NULL
);
1720 SendMessageA(hwndTabControl
, TCM_INSERTITEMA
, psInfo
->nPages
+ 1,
1725 /* If it is the only page - show it */
1726 if(psInfo
->nPages
== 1)
1727 PROPSHEET_ShowPage(hwndDlg
, 0, psInfo
);
1732 /******************************************************************************
1733 * PROPSHEET_RemovePage
1735 static BOOL
PROPSHEET_RemovePage(HWND hwndDlg
,
1737 HPROPSHEETPAGE hpage
)
1739 PropSheetInfo
* psInfo
= (PropSheetInfo
*) GetPropA(hwndDlg
,
1741 HWND hwndTabControl
= GetDlgItem(hwndDlg
, IDC_TABCONTROL
);
1742 PropPageInfo
* oldPages
;
1747 oldPages
= psInfo
->proppage
;
1749 * hpage takes precedence over index.
1753 index
= PROPSHEET_GetPageIndex(hpage
, psInfo
);
1756 /* Make sure that index is within range */
1757 if (index
< 0 || index
>= psInfo
->nPages
)
1759 TRACE("Could not find page to remove!\n");
1763 TRACE("total pages %d removing page %d active page %d\n",
1764 psInfo
->nPages
, index
, psInfo
->active_page
);
1766 * Check if we're removing the active page.
1768 if (index
== psInfo
->active_page
)
1770 if (psInfo
->nPages
> 1)
1774 /* activate previous page */
1775 PROPSHEET_ShowPage(hwndDlg
, index
- 1, psInfo
);
1779 /* activate the next page */
1780 PROPSHEET_ShowPage(hwndDlg
, index
+ 1, psInfo
);
1781 psInfo
->active_page
= index
;
1786 psInfo
->active_page
= -1;
1787 if (!psInfo
->isModeless
)
1789 EndDialog(hwndDlg
, FALSE
);
1794 else if (index
< psInfo
->active_page
)
1795 psInfo
->active_page
--;
1797 /* Destroy page dialog window */
1798 DestroyWindow(psInfo
->proppage
[index
].hwndPage
);
1800 /* Free page resources */
1801 if(psInfo
->proppage
[index
].hpage
)
1803 PROPSHEETPAGEA
* psp
= (PROPSHEETPAGEA
*)psInfo
->proppage
[index
].hpage
;
1805 if ((psp
->dwFlags
& PSP_USETITLE
) && psInfo
->proppage
[index
].pszText
)
1806 HeapFree(GetProcessHeap(), 0, (LPVOID
)psInfo
->proppage
[index
].pszText
);
1808 DestroyPropertySheetPage(psInfo
->proppage
[index
].hpage
);
1811 /* Remove the tab */
1812 SendMessageA(hwndTabControl
, TCM_DELETEITEM
, index
, 0);
1815 psInfo
->proppage
= COMCTL32_Alloc(sizeof(PropPageInfo
) * psInfo
->nPages
);
1818 memcpy(&psInfo
->proppage
[0], &oldPages
[0], index
* sizeof(PropPageInfo
));
1820 if (index
< psInfo
->nPages
)
1821 memcpy(&psInfo
->proppage
[index
], &oldPages
[index
+ 1],
1822 (psInfo
->nPages
- index
) * sizeof(PropPageInfo
));
1824 COMCTL32_Free(oldPages
);
1829 /******************************************************************************
1830 * PROPSHEET_SetWizButtons
1832 * This code will work if (and assumes that) the Next button is on top of the
1833 * Finish button. ie. Finish comes after Next in the Z order.
1834 * This means make sure the dialog template reflects this.
1837 static void PROPSHEET_SetWizButtons(HWND hwndDlg
, DWORD dwFlags
)
1839 HWND hwndBack
= GetDlgItem(hwndDlg
, IDC_BACK_BUTTON
);
1840 HWND hwndNext
= GetDlgItem(hwndDlg
, IDC_NEXT_BUTTON
);
1841 HWND hwndFinish
= GetDlgItem(hwndDlg
, IDC_FINISH_BUTTON
);
1843 TRACE("%ld\n", dwFlags
);
1845 EnableWindow(hwndBack
, FALSE
);
1846 EnableWindow(hwndNext
, FALSE
);
1847 EnableWindow(hwndFinish
, FALSE
);
1849 if (dwFlags
& PSWIZB_BACK
)
1850 EnableWindow(hwndBack
, TRUE
);
1852 if (dwFlags
& PSWIZB_NEXT
)
1854 /* Hide the Finish button */
1855 ShowWindow(hwndFinish
, SW_HIDE
);
1857 /* Show and enable the Next button */
1858 ShowWindow(hwndNext
, SW_SHOW
);
1859 EnableWindow(hwndNext
, TRUE
);
1861 /* Set the Next button as the default pushbutton */
1862 SendMessageA(hwndDlg
, DM_SETDEFID
, IDC_NEXT_BUTTON
, 0);
1865 if ((dwFlags
& PSWIZB_FINISH
) || (dwFlags
& PSWIZB_DISABLEDFINISH
))
1867 /* Hide the Next button */
1868 ShowWindow(hwndNext
, SW_HIDE
);
1870 /* Show the Finish button */
1871 ShowWindow(hwndFinish
, SW_SHOW
);
1873 if (dwFlags
& PSWIZB_FINISH
)
1874 EnableWindow(hwndFinish
, TRUE
);
1876 /* Set the Finish button as the default pushbutton */
1877 SendMessageA(hwndDlg
, DM_SETDEFID
, IDC_FINISH_BUTTON
, 0);
1881 /******************************************************************************
1882 * PROPSHEET_GetPageIndex
1884 * Given a HPROPSHEETPAGE, returns the index of the corresponding page from
1885 * the array of PropPageInfo.
1887 static int PROPSHEET_GetPageIndex(HPROPSHEETPAGE hpage
, PropSheetInfo
* psInfo
)
1892 while ((index
< psInfo
->nPages
) && (found
== FALSE
))
1894 if (psInfo
->proppage
[index
].hpage
== hpage
)
1906 /******************************************************************************
1909 static void PROPSHEET_CleanUp(HWND hwndDlg
)
1912 PropSheetInfo
* psInfo
= (PropSheetInfo
*) RemovePropA(hwndDlg
,
1916 if (HIWORD(psInfo
->ppshheader
.pszCaption
))
1917 HeapFree(GetProcessHeap(), 0, (LPVOID
)psInfo
->ppshheader
.pszCaption
);
1919 for (i
= 0; i
< psInfo
->nPages
; i
++)
1921 PROPSHEETPAGEA
* psp
= (PROPSHEETPAGEA
*)psInfo
->proppage
[i
].hpage
;
1923 if(psInfo
->proppage
[i
].hwndPage
)
1924 DestroyWindow(psInfo
->proppage
[i
].hwndPage
);
1928 if ((psp
->dwFlags
& PSP_USETITLE
) && psInfo
->proppage
[i
].pszText
)
1929 HeapFree(GetProcessHeap(), 0, (LPVOID
)psInfo
->proppage
[i
].pszText
);
1931 DestroyPropertySheetPage(psInfo
->proppage
[i
].hpage
);
1935 COMCTL32_Free(psInfo
->proppage
);
1936 COMCTL32_Free(psInfo
->strPropertiesFor
);
1937 ImageList_Destroy(psInfo
->hImageList
);
1939 GlobalFree((HGLOBAL
)psInfo
);
1942 /******************************************************************************
1943 * PropertySheetA (COMCTL32.84)(COMCTL32.83)
1945 INT WINAPI
PropertySheetA(LPCPROPSHEETHEADERA lppsh
)
1948 PropSheetInfo
* psInfo
= (PropSheetInfo
*) GlobalAlloc(GPTR
,
1949 sizeof(PropSheetInfo
));
1953 PROPSHEET_CollectSheetInfo(lppsh
, psInfo
);
1955 psInfo
->proppage
= (PropPageInfo
*) COMCTL32_Alloc(sizeof(PropPageInfo
) *
1957 pByte
= (BYTE
*) psInfo
->ppshheader
.u3
.ppsp
;
1959 for (n
= i
= 0; i
< lppsh
->nPages
; i
++, n
++)
1961 if (!(lppsh
->dwFlags
& PSH_PROPSHEETPAGE
))
1962 psInfo
->proppage
[n
].hpage
= psInfo
->ppshheader
.u3
.phpage
[i
];
1965 psInfo
->proppage
[n
].hpage
= CreatePropertySheetPageA((LPCPROPSHEETPAGEA
)pByte
);
1966 pByte
+= ((LPPROPSHEETPAGEA
)pByte
)->dwSize
;
1969 if (!PROPSHEET_CollectPageInfo((LPCPROPSHEETPAGEA
)psInfo
->proppage
[n
].hpage
,
1972 if (lppsh
->dwFlags
& PSH_PROPSHEETPAGE
)
1973 DestroyPropertySheetPage(psInfo
->proppage
[n
].hpage
);
1979 bRet
= PROPSHEET_CreateDialog(psInfo
);
1984 /******************************************************************************
1985 * PropertySheetW (COMCTL32.85)
1987 INT WINAPI
PropertySheetW(LPCPROPSHEETHEADERW propertySheetHeader
)
1989 FIXME("(%p): stub\n", propertySheetHeader
);
1994 /******************************************************************************
1995 * CreatePropertySheetPageA (COMCTL32.19)(COMCTL32.18)
1997 HPROPSHEETPAGE WINAPI
CreatePropertySheetPageA(
1998 LPCPROPSHEETPAGEA lpPropSheetPage
)
2000 PROPSHEETPAGEA
* ppsp
= COMCTL32_Alloc(sizeof(PROPSHEETPAGEA
));
2002 *ppsp
= *lpPropSheetPage
;
2004 if ( !(ppsp
->dwFlags
& PSP_DLGINDIRECT
) && HIWORD( ppsp
->u
.pszTemplate
) )
2005 ppsp
->u
.pszTemplate
= HEAP_strdupA( GetProcessHeap(), 0, lpPropSheetPage
->u
.pszTemplate
);
2007 if ( (ppsp
->dwFlags
& PSP_USEICONID
) && HIWORD( ppsp
->u2
.pszIcon
) )
2008 ppsp
->u2
.pszIcon
= HEAP_strdupA( GetProcessHeap(), 0, lpPropSheetPage
->u2
.pszIcon
);
2011 if ((ppsp
->dwFlags
& PSP_USETITLE
) && HIWORD( ppsp
->pszTitle
))
2012 ppsp
->pszTitle
= HEAP_strdupA( GetProcessHeap(), 0, lpPropSheetPage
->pszTitle
);
2013 else if ( !(ppsp
->dwFlags
& PSP_USETITLE
) )
2014 ppsp
->pszTitle
= NULL
;
2016 return (HPROPSHEETPAGE
)ppsp
;
2019 /******************************************************************************
2020 * CreatePropertySheetPageW (COMCTL32.20)
2022 HPROPSHEETPAGE WINAPI
CreatePropertySheetPageW(LPCPROPSHEETPAGEW lpPropSheetPage
)
2024 FIXME("(%p): stub\n", lpPropSheetPage
);
2029 /******************************************************************************
2030 * DestroyPropertySheetPage (COMCTL32.24)
2032 BOOL WINAPI
DestroyPropertySheetPage(HPROPSHEETPAGE hPropPage
)
2034 PROPSHEETPAGEA
*psp
= (PROPSHEETPAGEA
*)hPropPage
;
2039 if ( !(psp
->dwFlags
& PSP_DLGINDIRECT
) && HIWORD( psp
->u
.pszTemplate
) )
2040 HeapFree(GetProcessHeap(), 0, (LPVOID
)psp
->u
.pszTemplate
);
2042 if ( (psp
->dwFlags
& PSP_USEICONID
) && HIWORD( psp
->u2
.pszIcon
) )
2043 HeapFree(GetProcessHeap(), 0, (LPVOID
)psp
->u2
.pszIcon
);
2045 if ((psp
->dwFlags
& PSP_USETITLE
) && HIWORD( psp
->pszTitle
))
2046 HeapFree(GetProcessHeap(), 0, (LPVOID
)psp
->pszTitle
);
2048 COMCTL32_Free(hPropPage
);
2053 /******************************************************************************
2054 * PROPSHEET_IsDialogMessage
2056 static BOOL
PROPSHEET_IsDialogMessage(HWND hwnd
, LPMSG lpMsg
)
2058 PropSheetInfo
* psInfo
= (PropSheetInfo
*) GetPropA(hwnd
, PropSheetInfoStr
);
2060 if (!psInfo
|| (hwnd
!= lpMsg
->hwnd
&& !IsChild(hwnd
, lpMsg
->hwnd
)))
2063 if (lpMsg
->message
== WM_KEYDOWN
&& (GetKeyState(VK_CONTROL
) & 0x8000))
2066 INT dlgCode
= SendMessageA(lpMsg
->hwnd
, WM_GETDLGCODE
, 0, (LPARAM
)lpMsg
);
2068 if (!(dlgCode
& DLGC_WANTMESSAGE
))
2070 switch (lpMsg
->wParam
)
2073 if (GetKeyState(VK_SHIFT
) & 0x8000)
2079 case VK_NEXT
: new_page
= 1; break;
2080 case VK_PRIOR
: new_page
= -1; break;
2086 if (PROPSHEET_CanSetCurSel(hwnd
) != FALSE
)
2088 new_page
+= psInfo
->active_page
;
2091 new_page
= psInfo
->nPages
- 1;
2092 else if (new_page
>= psInfo
->nPages
)
2095 PROPSHEET_SetCurSel(hwnd
, new_page
, 0);
2102 return IsDialogMessageA(hwnd
, lpMsg
);
2105 /******************************************************************************
2106 * PROPSHEET_DialogProc
2109 PROPSHEET_DialogProc(HWND hwnd
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
)
2115 PropSheetInfo
* psInfo
= (PropSheetInfo
*) lParam
;
2116 char* strCaption
= (char*)COMCTL32_Alloc(MAX_CAPTION_LENGTH
);
2117 HWND hwndTabCtrl
= GetDlgItem(hwnd
, IDC_TABCONTROL
);
2118 LPCPROPSHEETPAGEA ppshpage
;
2121 SetPropA(hwnd
, PropSheetInfoStr
, (HANDLE
)psInfo
);
2124 * psInfo->hwnd is not being used by WINE code - it exists
2125 * for compatibility with "real" Windoze. The same about
2126 * SetWindowLong - WINE is only using the PropSheetInfoStr
2129 psInfo
->hwnd
= hwnd
;
2130 SetWindowLongA(hwnd
,DWL_USER
,(LONG
)psInfo
);
2133 * Small icon in the title bar.
2135 if ((psInfo
->ppshheader
.dwFlags
& PSH_USEICONID
) ||
2136 (psInfo
->ppshheader
.dwFlags
& PSH_USEHICON
))
2139 int icon_cx
= GetSystemMetrics(SM_CXSMICON
);
2140 int icon_cy
= GetSystemMetrics(SM_CYSMICON
);
2142 if (psInfo
->ppshheader
.dwFlags
& PSH_USEICONID
)
2143 hIcon
= LoadImageA(psInfo
->ppshheader
.hInstance
,
2144 psInfo
->ppshheader
.u
.pszIcon
,
2149 hIcon
= psInfo
->ppshheader
.u
.hIcon
;
2151 SendMessageA(hwnd
, WM_SETICON
, 0, hIcon
);
2154 if (psInfo
->ppshheader
.dwFlags
& PSH_USEHICON
)
2155 SendMessageA(hwnd
, WM_SETICON
, 0, psInfo
->ppshheader
.u
.hIcon
);
2157 psInfo
->strPropertiesFor
= strCaption
;
2159 GetWindowTextA(hwnd
, psInfo
->strPropertiesFor
, MAX_CAPTION_LENGTH
);
2161 PROPSHEET_CreateTabControl(hwnd
, psInfo
);
2163 if (psInfo
->ppshheader
.dwFlags
& PSH_WIZARD
)
2165 if (PROPSHEET_IsTooSmallWizard(hwnd
, psInfo
))
2167 PROPSHEET_AdjustSizeWizard(hwnd
, psInfo
);
2168 PROPSHEET_AdjustButtonsWizard(hwnd
, psInfo
);
2173 if (PROPSHEET_SizeMismatch(hwnd
, psInfo
))
2175 PROPSHEET_AdjustSize(hwnd
, psInfo
);
2176 PROPSHEET_AdjustButtons(hwnd
, psInfo
);
2180 if (psInfo
->useCallback
)
2181 (*(psInfo
->ppshheader
.pfnCallback
))(hwnd
,
2182 PSCB_INITIALIZED
, (LPARAM
)0);
2184 idx
= psInfo
->active_page
;
2185 ppshpage
= (LPCPROPSHEETPAGEA
)psInfo
->proppage
[idx
].hpage
;
2186 psInfo
->active_page
= -1;
2188 PROPSHEET_SetCurSel(hwnd
, idx
, psInfo
->proppage
[idx
].hpage
);
2190 if (!(psInfo
->ppshheader
.dwFlags
& PSH_WIZARD
))
2191 SendMessageA(hwndTabCtrl
, TCM_SETCURSEL
, psInfo
->active_page
, 0);
2193 if (!HIWORD(psInfo
->ppshheader
.pszCaption
) &&
2194 psInfo
->ppshheader
.hInstance
)
2198 if (LoadStringA(psInfo
->ppshheader
.hInstance
,
2199 (UINT
)psInfo
->ppshheader
.pszCaption
, szText
, 255))
2200 PROPSHEET_SetTitleA(hwnd
, psInfo
->ppshheader
.dwFlags
, szText
);
2204 PROPSHEET_SetTitleA(hwnd
, psInfo
->ppshheader
.dwFlags
,
2205 psInfo
->ppshheader
.pszCaption
);
2212 PROPSHEET_CleanUp(hwnd
);
2216 PROPSHEET_Cancel(hwnd
, 1);
2221 WORD wID
= LOWORD(wParam
);
2226 case IDC_APPLY_BUTTON
:
2228 HWND hwndApplyBtn
= GetDlgItem(hwnd
, IDC_APPLY_BUTTON
);
2230 if (PROPSHEET_Apply(hwnd
, wID
== IDOK
? 1: 0) == FALSE
)
2235 PropSheetInfo
* psInfo
= (PropSheetInfo
*) GetPropA(hwnd
,
2239 if (psInfo
->restartWindows
)
2240 result
= ID_PSRESTARTWINDOWS
;
2242 /* reboot system takes precedence over restart windows */
2243 if (psInfo
->rebootSystem
)
2244 result
= ID_PSREBOOTSYSTEM
;
2246 if (psInfo
->isModeless
)
2247 psInfo
->activeValid
= FALSE
;
2249 EndDialog(hwnd
, result
);
2252 EnableWindow(hwndApplyBtn
, FALSE
);
2257 case IDC_BACK_BUTTON
:
2258 PROPSHEET_Back(hwnd
);
2261 case IDC_NEXT_BUTTON
:
2262 PROPSHEET_Next(hwnd
);
2265 case IDC_FINISH_BUTTON
:
2266 PROPSHEET_Finish(hwnd
);
2270 PROPSHEET_Cancel(hwnd
, 0);
2274 PROPSHEET_Help(hwnd
);
2283 NMHDR
* pnmh
= (LPNMHDR
) lParam
;
2285 if (pnmh
->code
== TCN_SELCHANGE
)
2287 int index
= SendMessageA(pnmh
->hwndFrom
, TCM_GETCURSEL
, 0, 0);
2288 PROPSHEET_SetCurSel(hwnd
, index
, 0);
2291 if(pnmh
->code
== TCN_SELCHANGING
)
2293 BOOL bRet
= PROPSHEET_CanSetCurSel(hwnd
);
2294 SetWindowLongA(hwnd
, DWL_MSGRESULT
, !bRet
);
2301 case PSM_GETCURRENTPAGEHWND
:
2303 PropSheetInfo
* psInfo
= (PropSheetInfo
*) GetPropA(hwnd
,
2307 if (psInfo
->activeValid
&& psInfo
->active_page
!= -1)
2308 hwndPage
= psInfo
->proppage
[psInfo
->active_page
].hwndPage
;
2310 SetWindowLongA(hwnd
, DWL_MSGRESULT
, hwndPage
);
2316 PROPSHEET_Changed(hwnd
, (HWND
)wParam
);
2320 PROPSHEET_UnChanged(hwnd
, (HWND
)wParam
);
2323 case PSM_GETTABCONTROL
:
2325 HWND hwndTabCtrl
= GetDlgItem(hwnd
, IDC_TABCONTROL
);
2327 SetWindowLongA(hwnd
, DWL_MSGRESULT
, hwndTabCtrl
);
2336 msgResult
= PROPSHEET_CanSetCurSel(hwnd
);
2337 if(msgResult
!= FALSE
)
2339 msgResult
= PROPSHEET_SetCurSel(hwnd
,
2341 (HPROPSHEETPAGE
)lParam
);
2344 SetWindowLongA(hwnd
, DWL_MSGRESULT
, msgResult
);
2349 case PSM_CANCELTOCLOSE
:
2351 char buf
[MAX_BUTTONTEXT_LENGTH
];
2352 HWND hwndOK
= GetDlgItem(hwnd
, IDOK
);
2353 HWND hwndCancel
= GetDlgItem(hwnd
, IDCANCEL
);
2355 EnableWindow(hwndCancel
, FALSE
);
2356 if (LoadStringA(COMCTL32_hModule
, IDS_CLOSE
, buf
, sizeof(buf
)))
2357 SetWindowTextA(hwndOK
, buf
);
2362 case PSM_RESTARTWINDOWS
:
2364 PropSheetInfo
* psInfo
= (PropSheetInfo
*) GetPropA(hwnd
,
2367 psInfo
->restartWindows
= TRUE
;
2371 case PSM_REBOOTSYSTEM
:
2373 PropSheetInfo
* psInfo
= (PropSheetInfo
*) GetPropA(hwnd
,
2376 psInfo
->rebootSystem
= TRUE
;
2381 PROPSHEET_SetTitleA(hwnd
, (DWORD
) wParam
, (LPCSTR
) lParam
);
2386 BOOL msgResult
= PROPSHEET_Apply(hwnd
, 0);
2388 SetWindowLongA(hwnd
, DWL_MSGRESULT
, msgResult
);
2393 case PSM_QUERYSIBLINGS
:
2395 LRESULT msgResult
= PROPSHEET_QuerySiblings(hwnd
, wParam
, lParam
);
2397 SetWindowLongA(hwnd
, DWL_MSGRESULT
, msgResult
);
2405 * Note: MSVC++ 6.0 documentation says that PSM_ADDPAGE does not have
2406 * a return value. This is not true. PSM_ADDPAGE returns TRUE
2407 * on success or FALSE otherwise, as specified on MSDN Online.
2408 * Also see the MFC code for
2409 * CPropertySheet::AddPage(CPropertyPage* pPage).
2412 BOOL msgResult
= PROPSHEET_AddPage(hwnd
, (HPROPSHEETPAGE
)lParam
);
2414 SetWindowLongA(hwnd
, DWL_MSGRESULT
, msgResult
);
2419 case PSM_REMOVEPAGE
:
2420 PROPSHEET_RemovePage(hwnd
, (int)wParam
, (HPROPSHEETPAGE
)lParam
);
2423 case PSM_ISDIALOGMESSAGE
:
2425 BOOL msgResult
= PROPSHEET_IsDialogMessage(hwnd
, (LPMSG
)lParam
);
2426 SetWindowLongA(hwnd
, DWL_MSGRESULT
, msgResult
);
2430 case PSM_PRESSBUTTON
:
2431 PROPSHEET_PressButton(hwnd
, (int)wParam
);
2434 case PSM_SETFINISHTEXTA
:
2435 PROPSHEET_SetFinishTextA(hwnd
, (LPCSTR
) lParam
);
2438 case PSM_SETWIZBUTTONS
:
2439 PROPSHEET_SetWizButtons(hwnd
, (DWORD
)lParam
);
2443 FIXME("Unimplemented msg PSM_SETTITLE32W\n");
2446 case PSM_SETCURSELID
:
2447 FIXME("Unimplemented msg PSM_SETCURSELID\n");
2450 case PSM_SETFINISHTEXTW
:
2451 FIXME("Unimplemented msg PSM_SETFINISHTEXT32W\n");