4 * Copyright 1998 Francis Beaudet
5 * Copyright 1999 Thuy Nguyen
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 * - Unicode property sheets
28 #define NONAMELESSUNION
29 #define NONAMELESSSTRUCT
37 #include "wine/debug.h"
38 #include "wine/unicode.h"
40 /******************************************************************************
64 } MyDLGITEMTEMPLATEEX
;
67 typedef struct tagPropPageInfo
69 HPROPSHEETPAGE hpage
; /* to keep track of pages not passed to PropertySheet */
78 typedef struct tagPropSheetInfo
81 PROPSHEETHEADERW ppshheader
;
82 LPWSTR strPropertiesFor
;
92 PropPageInfo
* proppage
;
97 HIMAGELIST hImageList
;
106 /******************************************************************************
107 * Defines and global variables
110 const WCHAR PropSheetInfoStr
[] =
111 {'P','r','o','p','e','r','t','y','S','h','e','e','t','I','n','f','o',0 };
113 #define MAX_CAPTION_LENGTH 255
114 #define MAX_TABTEXT_LENGTH 255
115 #define MAX_BUTTONTEXT_LENGTH 64
117 #define INTRNL_ANY_WIZARD (PSH_WIZARD | PSH_WIZARD97_OLD | PSH_WIZARD97_NEW | PSH_WIZARD_LITE)
119 /******************************************************************************
122 static BOOL
PROPSHEET_CreateDialog(PropSheetInfo
* psInfo
);
123 static BOOL
PROPSHEET_SizeMismatch(HWND hwndDlg
, PropSheetInfo
* psInfo
);
124 static BOOL
PROPSHEET_AdjustSize(HWND hwndDlg
, PropSheetInfo
* psInfo
);
125 static BOOL
PROPSHEET_AdjustButtons(HWND hwndParent
, PropSheetInfo
* psInfo
);
126 static BOOL
PROPSHEET_CollectSheetInfoA(LPCPROPSHEETHEADERA lppsh
,
127 PropSheetInfo
* psInfo
);
128 static BOOL
PROPSHEET_CollectSheetInfoW(LPCPROPSHEETHEADERW lppsh
,
129 PropSheetInfo
* psInfo
);
130 static BOOL
PROPSHEET_CollectPageInfo(LPCPROPSHEETPAGEW lppsp
,
131 PropSheetInfo
* psInfo
,
133 static BOOL
PROPSHEET_CreateTabControl(HWND hwndParent
,
134 PropSheetInfo
* psInfo
);
135 static BOOL
PROPSHEET_CreatePage(HWND hwndParent
, int index
,
136 const PropSheetInfo
* psInfo
,
137 LPCPROPSHEETPAGEW ppshpage
);
138 static BOOL
PROPSHEET_ShowPage(HWND hwndDlg
, int index
, PropSheetInfo
* psInfo
);
139 static PADDING_INFO
PROPSHEET_GetPaddingInfo(HWND hwndDlg
);
140 static BOOL
PROPSHEET_Back(HWND hwndDlg
);
141 static BOOL
PROPSHEET_Next(HWND hwndDlg
);
142 static BOOL
PROPSHEET_Finish(HWND hwndDlg
);
143 static BOOL
PROPSHEET_Apply(HWND hwndDlg
, LPARAM lParam
);
144 static void PROPSHEET_Cancel(HWND hwndDlg
, LPARAM lParam
);
145 static void PROPSHEET_Help(HWND hwndDlg
);
146 static void PROPSHEET_Changed(HWND hwndDlg
, HWND hwndDirtyPage
);
147 static void PROPSHEET_UnChanged(HWND hwndDlg
, HWND hwndCleanPage
);
148 static void PROPSHEET_PressButton(HWND hwndDlg
, int buttonID
);
149 static void PROPSHEET_SetFinishTextA(HWND hwndDlg
, LPCSTR lpszText
);
150 static void PROPSHEET_SetFinishTextW(HWND hwndDlg
, LPCWSTR lpszText
);
151 static void PROPSHEET_SetTitleA(HWND hwndDlg
, DWORD dwStyle
, LPCSTR lpszText
);
152 static void PROPSHEET_SetTitleW(HWND hwndDlg
, DWORD dwStyle
, LPCWSTR lpszText
);
153 static BOOL
PROPSHEET_CanSetCurSel(HWND hwndDlg
);
154 static BOOL
PROPSHEET_SetCurSel(HWND hwndDlg
,
157 HPROPSHEETPAGE hpage
);
158 static void PROPSHEET_SetCurSelId(HWND hwndDlg
, int id
);
159 static LRESULT
PROPSHEET_QuerySiblings(HWND hwndDlg
,
160 WPARAM wParam
, LPARAM lParam
);
161 static BOOL
PROPSHEET_AddPage(HWND hwndDlg
,
162 HPROPSHEETPAGE hpage
);
164 static BOOL
PROPSHEET_RemovePage(HWND hwndDlg
,
166 HPROPSHEETPAGE hpage
);
167 static void PROPSHEET_CleanUp();
168 static int PROPSHEET_GetPageIndex(HPROPSHEETPAGE hpage
, PropSheetInfo
* psInfo
);
169 static void PROPSHEET_SetWizButtons(HWND hwndDlg
, DWORD dwFlags
);
170 static PADDING_INFO
PROPSHEET_GetPaddingInfoWizard(HWND hwndDlg
, const PropSheetInfo
* psInfo
);
171 static BOOL
PROPSHEET_IsDialogMessage(HWND hwnd
, LPMSG lpMsg
);
172 static BOOL
PROPSHEET_DoCommand(HWND hwnd
, WORD wID
);
175 PROPSHEET_DialogProc(HWND hwnd
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
);
177 WINE_DEFAULT_DEBUG_CHANNEL(propsheet
);
179 #define add_flag(a) if (dwFlags & a) {strcat(string, #a );strcat(string," ");}
180 /******************************************************************************
181 * PROPSHEET_UnImplementedFlags
183 * Document use of flags we don't implement yet.
185 static VOID
PROPSHEET_UnImplementedFlags(DWORD dwFlags
)
192 * unhandled header flags:
193 * PSH_DEFAULT 0x00000000
194 * PSH_WIZARDHASFINISH 0x00000010
195 * PSH_RTLREADING 0x00000800
196 * PSH_WIZARDCONTEXTHELP 0x00001000
197 * PSH_WIZARD97 0x00002000 (pre IE 5)
198 * PSH_WATERMARK 0x00008000
199 * PSH_USEHBMWATERMARK 0x00010000
200 * PSH_USEHPLWATERMARK 0x00020000
201 * PSH_STRETCHWATERMARK 0x00040000
202 * PSH_HEADER 0x00080000
203 * PSH_USEHBMHEADER 0x00100000
204 * PSH_USEPAGELANG 0x00200000
205 * PSH_WIZARD_LITE 0x00400000 also not in .h
206 * PSH_WIZARD97 0x01000000 (IE 5 and above)
207 * PSH_NOCONTEXTHELP 0x02000000 also not in .h
210 add_flag(PSH_WIZARDHASFINISH
);
211 add_flag(PSH_RTLREADING
);
212 add_flag(PSH_WIZARDCONTEXTHELP
);
213 add_flag(PSH_WIZARD97_OLD
);
214 add_flag(PSH_WATERMARK
);
215 add_flag(PSH_USEHBMWATERMARK
);
216 add_flag(PSH_USEHPLWATERMARK
);
217 add_flag(PSH_STRETCHWATERMARK
);
218 add_flag(PSH_HEADER
);
219 add_flag(PSH_USEHBMHEADER
);
220 add_flag(PSH_USEPAGELANG
);
221 add_flag(PSH_WIZARD_LITE
);
222 add_flag(PSH_WIZARD97_NEW
);
223 add_flag(PSH_NOCONTEXTHELP
);
224 if (string
[0] != '\0')
225 FIXME("%s\n", string
);
229 /******************************************************************************
230 * PROPSHEET_GetPageRect
232 * Retrieve rect from tab control and map into the dialog for SetWindowPos
234 static void PROPSHEET_GetPageRect(const PropSheetInfo
* psInfo
, HWND hwndDlg
, RECT
*rc
)
236 HWND hwndTabCtrl
= GetDlgItem(hwndDlg
, IDC_TABCONTROL
);
238 GetClientRect(hwndTabCtrl
, rc
);
239 SendMessageW(hwndTabCtrl
, TCM_ADJUSTRECT
, FALSE
, (LPARAM
)rc
);
240 MapWindowPoints(hwndTabCtrl
, hwndDlg
, (LPPOINT
)rc
, 2);
243 /******************************************************************************
244 * PROPSHEET_FindPageByResId
246 * Find page index corresponding to page resource id.
248 INT
PROPSHEET_FindPageByResId(PropSheetInfo
* psInfo
, LRESULT resId
)
252 for (i
= 0; i
< psInfo
->nPages
; i
++)
254 LPCPROPSHEETPAGEA lppsp
= (LPCPROPSHEETPAGEA
)psInfo
->proppage
[i
].hpage
;
256 /* Fixme: if resource ID is a string shall we use strcmp ??? */
257 if (lppsp
->u
.pszTemplate
== (LPVOID
)resId
)
264 /******************************************************************************
267 * Convert ASCII to Unicode since all data is saved as Unicode.
269 static void PROPSHEET_AtoW(LPCWSTR
*tostr
, LPCSTR frstr
)
273 TRACE("<%s>\n", frstr
);
274 len
= MultiByteToWideChar(CP_ACP
, 0, frstr
, -1, 0, 0);
275 *tostr
= (LPWSTR
)HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
276 MultiByteToWideChar(CP_ACP
, 0, frstr
, -1, (LPWSTR
)*tostr
, len
);
279 /******************************************************************************
280 * PROPSHEET_CollectSheetInfoA
282 * Collect relevant data.
284 static BOOL
PROPSHEET_CollectSheetInfoA(LPCPROPSHEETHEADERA lppsh
,
285 PropSheetInfo
* psInfo
)
287 DWORD dwSize
= min(lppsh
->dwSize
,sizeof(PROPSHEETHEADERA
));
288 DWORD dwFlags
= lppsh
->dwFlags
;
290 psInfo
->hasHelp
= dwFlags
& PSH_HASHELP
;
291 psInfo
->hasApply
= !(dwFlags
& PSH_NOAPPLYNOW
);
292 psInfo
->useCallback
= (dwFlags
& PSH_USECALLBACK
)&& (lppsh
->pfnCallback
);
293 psInfo
->isModeless
= dwFlags
& PSH_MODELESS
;
295 memcpy(&psInfo
->ppshheader
,lppsh
,dwSize
);
296 TRACE("\n** PROPSHEETHEADER **\ndwSize\t\t%ld\ndwFlags\t\t%08lx\nhwndParent\t%p\nhInstance\t%p\npszCaption\t'%s'\nnPages\t\t%d\npfnCallback\t%p\n",
297 lppsh
->dwSize
, lppsh
->dwFlags
, lppsh
->hwndParent
, lppsh
->hInstance
,
298 debugstr_a(lppsh
->pszCaption
), lppsh
->nPages
, lppsh
->pfnCallback
);
300 PROPSHEET_UnImplementedFlags(lppsh
->dwFlags
);
302 if (HIWORD(lppsh
->pszCaption
))
304 int len
= strlen(lppsh
->pszCaption
);
305 psInfo
->ppshheader
.pszCaption
= HeapAlloc( GetProcessHeap(), 0, (len
+1)*sizeof (WCHAR
) );
306 MultiByteToWideChar(CP_ACP
, 0, lppsh
->pszCaption
, -1, (LPWSTR
) psInfo
->ppshheader
.pszCaption
, len
+1);
307 /* strcpy( (char *)psInfo->ppshheader.pszCaption, lppsh->pszCaption ); */
309 psInfo
->nPages
= lppsh
->nPages
;
311 if (dwFlags
& PSH_USEPSTARTPAGE
)
313 TRACE("PSH_USEPSTARTPAGE is on");
314 psInfo
->active_page
= 0;
317 psInfo
->active_page
= lppsh
->u2
.nStartPage
;
319 if (psInfo
->active_page
< 0 || psInfo
->active_page
>= psInfo
->nPages
)
320 psInfo
->active_page
= 0;
322 psInfo
->restartWindows
= FALSE
;
323 psInfo
->rebootSystem
= FALSE
;
324 psInfo
->hImageList
= 0;
325 psInfo
->activeValid
= FALSE
;
330 /******************************************************************************
331 * PROPSHEET_CollectSheetInfoW
333 * Collect relevant data.
335 static BOOL
PROPSHEET_CollectSheetInfoW(LPCPROPSHEETHEADERW lppsh
,
336 PropSheetInfo
* psInfo
)
338 DWORD dwSize
= min(lppsh
->dwSize
,sizeof(PROPSHEETHEADERW
));
339 DWORD dwFlags
= lppsh
->dwFlags
;
341 psInfo
->hasHelp
= dwFlags
& PSH_HASHELP
;
342 psInfo
->hasApply
= !(dwFlags
& PSH_NOAPPLYNOW
);
343 psInfo
->useCallback
= (dwFlags
& PSH_USECALLBACK
) && (lppsh
->pfnCallback
);
344 psInfo
->isModeless
= dwFlags
& PSH_MODELESS
;
346 memcpy(&psInfo
->ppshheader
,lppsh
,dwSize
);
347 TRACE("\n** PROPSHEETHEADER **\ndwSize\t\t%ld\ndwFlags\t\t%08lx\nhwndParent\t%p\nhInstance\t%p\npszCaption\t'%s'\nnPages\t\t%d\npfnCallback\t%p\n",
348 lppsh
->dwSize
, lppsh
->dwFlags
, lppsh
->hwndParent
, lppsh
->hInstance
, debugstr_w(lppsh
->pszCaption
), lppsh
->nPages
, lppsh
->pfnCallback
);
350 PROPSHEET_UnImplementedFlags(lppsh
->dwFlags
);
352 if (HIWORD(lppsh
->pszCaption
))
354 int len
= strlenW(lppsh
->pszCaption
);
355 psInfo
->ppshheader
.pszCaption
= HeapAlloc( GetProcessHeap(), 0, (len
+1)*sizeof(WCHAR
) );
356 strcpyW( (WCHAR
*)psInfo
->ppshheader
.pszCaption
, lppsh
->pszCaption
);
358 psInfo
->nPages
= lppsh
->nPages
;
360 if (dwFlags
& PSH_USEPSTARTPAGE
)
362 TRACE("PSH_USEPSTARTPAGE is on");
363 psInfo
->active_page
= 0;
366 psInfo
->active_page
= lppsh
->u2
.nStartPage
;
368 if (psInfo
->active_page
< 0 || psInfo
->active_page
>= psInfo
->nPages
)
369 psInfo
->active_page
= 0;
371 psInfo
->restartWindows
= FALSE
;
372 psInfo
->rebootSystem
= FALSE
;
373 psInfo
->hImageList
= 0;
374 psInfo
->activeValid
= FALSE
;
379 /******************************************************************************
380 * PROPSHEET_CollectPageInfo
382 * Collect property sheet data.
383 * With code taken from DIALOG_ParseTemplate32.
385 BOOL
PROPSHEET_CollectPageInfo(LPCPROPSHEETPAGEW lppsp
,
386 PropSheetInfo
* psInfo
,
389 DLGTEMPLATE
* pTemplate
;
395 psInfo
->proppage
[index
].hpage
= (HPROPSHEETPAGE
)lppsp
;
396 psInfo
->proppage
[index
].hwndPage
= 0;
397 psInfo
->proppage
[index
].isDirty
= FALSE
;
400 * Process property page flags.
402 dwFlags
= lppsp
->dwFlags
;
403 psInfo
->proppage
[index
].useCallback
= (dwFlags
& PSP_USECALLBACK
) && (lppsp
->pfnCallback
);
404 psInfo
->proppage
[index
].hasHelp
= dwFlags
& PSP_HASHELP
;
405 psInfo
->proppage
[index
].hasIcon
= dwFlags
& (PSP_USEHICON
| PSP_USEICONID
);
407 /* as soon as we have a page with the help flag, set the sheet flag on */
408 if (psInfo
->proppage
[index
].hasHelp
)
409 psInfo
->hasHelp
= TRUE
;
412 * Process page template.
414 if (dwFlags
& PSP_DLGINDIRECT
)
415 pTemplate
= (DLGTEMPLATE
*)lppsp
->u
.pResource
;
418 HRSRC hResource
= FindResourceW(lppsp
->hInstance
,
419 lppsp
->u
.pszTemplate
,
421 HGLOBAL hTemplate
= LoadResource(lppsp
->hInstance
,
423 pTemplate
= (LPDLGTEMPLATEW
)LockResource(hTemplate
);
427 * Extract the size of the page and the caption.
432 p
= (const WORD
*)pTemplate
;
434 if (((MyDLGTEMPLATEEX
*)pTemplate
)->signature
== 0xFFFF)
436 /* DLGTEMPLATEEX (not defined in any std. header file) */
440 p
+= 2; /* help ID */
441 p
+= 2; /* ext style */
449 p
+= 2; /* ext style */
455 width
= (WORD
)*p
; p
++;
456 height
= (WORD
)*p
; p
++;
458 /* remember the largest width and height */
459 if (width
> psInfo
->width
)
460 psInfo
->width
= width
;
462 if (height
> psInfo
->height
)
463 psInfo
->height
= height
;
475 p
+= lstrlenW( (LPCWSTR
)p
) + 1;
489 p
+= lstrlenW( (LPCWSTR
)p
) + 1;
493 /* Extract the caption */
494 psInfo
->proppage
[index
].pszText
= (LPCWSTR
)p
;
495 TRACE("Tab %d %s\n",index
,debugstr_w((LPCWSTR
)p
));
496 p
+= lstrlenW((LPCWSTR
)p
) + 1;
498 if (dwFlags
& PSP_USETITLE
)
502 static WCHAR pszNull
[] = { '(','n','u','l','l',')',0 };
505 if ( !HIWORD( lppsp
->pszTitle
) )
507 if (!LoadStringW( lppsp
->hInstance
, (UINT
)lppsp
->pszTitle
,szTitle
,sizeof szTitle
))
510 FIXME("Could not load resource #%04x?\n",LOWORD(lppsp
->pszTitle
));
516 pTitle
= lppsp
->pszTitle
;
518 len
= strlenW(pTitle
);
519 psInfo
->proppage
[index
].pszText
= COMCTL32_Alloc( (len
+1)*sizeof (WCHAR
) );
520 strcpyW( (LPWSTR
)psInfo
->proppage
[index
].pszText
,pTitle
);
524 * Build the image list for icons
526 if ((dwFlags
& PSP_USEHICON
) || (dwFlags
& PSP_USEICONID
))
529 int icon_cx
= GetSystemMetrics(SM_CXSMICON
);
530 int icon_cy
= GetSystemMetrics(SM_CYSMICON
);
532 if (dwFlags
& PSP_USEICONID
)
533 hIcon
= LoadImageW(lppsp
->hInstance
, lppsp
->u2
.pszIcon
, IMAGE_ICON
,
534 icon_cx
, icon_cy
, LR_DEFAULTCOLOR
);
536 hIcon
= lppsp
->u2
.hIcon
;
540 if (psInfo
->hImageList
== 0 )
541 psInfo
->hImageList
= ImageList_Create(icon_cx
, icon_cy
, ILC_COLOR
, 1, 1);
543 ImageList_AddIcon(psInfo
->hImageList
, hIcon
);
551 /******************************************************************************
552 * PROPSHEET_CreateDialog
554 * Creates the actual property sheet.
556 BOOL
PROPSHEET_CreateDialog(PropSheetInfo
* psInfo
)
563 WORD resID
= IDD_PROPSHEET
;
566 if (psInfo
->ppshheader
.dwFlags
& INTRNL_ANY_WIZARD
)
569 if(!(hRes
= FindResourceW(COMCTL32_hModule
,
570 MAKEINTRESOURCEW(resID
),
574 if(!(template = (LPVOID
)LoadResource(COMCTL32_hModule
, hRes
)))
578 * Make a copy of the dialog template.
580 resSize
= SizeofResource(COMCTL32_hModule
, hRes
);
582 temp
= COMCTL32_Alloc(resSize
);
587 memcpy(temp
, template, resSize
);
589 if (psInfo
->useCallback
)
590 (*(psInfo
->ppshheader
.pfnCallback
))(0, PSCB_PRECREATE
, (LPARAM
)temp
);
592 if (!(psInfo
->ppshheader
.dwFlags
& PSH_MODELESS
))
593 ret
= DialogBoxIndirectParamW(psInfo
->ppshheader
.hInstance
,
594 (LPDLGTEMPLATEW
) temp
,
595 psInfo
->ppshheader
.hwndParent
,
596 PROPSHEET_DialogProc
,
599 ret
= CreateDialogIndirectParamW(psInfo
->ppshheader
.hInstance
,
600 (LPDLGTEMPLATEW
) temp
,
601 psInfo
->ppshheader
.hwndParent
,
602 PROPSHEET_DialogProc
,
603 (LPARAM
)psInfo
) ? TRUE
: FALSE
;
610 /******************************************************************************
611 * PROPSHEET_SizeMismatch
613 * Verify that the tab control and the "largest" property sheet page dlg. template
616 static BOOL
PROPSHEET_SizeMismatch(HWND hwndDlg
, PropSheetInfo
* psInfo
)
618 HWND hwndTabCtrl
= GetDlgItem(hwndDlg
, IDC_TABCONTROL
);
619 RECT rcOrigTab
, rcPage
;
624 GetClientRect(hwndTabCtrl
, &rcOrigTab
);
625 TRACE("orig tab %ld %ld %ld %ld\n", rcOrigTab
.left
, rcOrigTab
.top
,
626 rcOrigTab
.right
, rcOrigTab
.bottom
);
631 rcPage
.left
= psInfo
->x
;
632 rcPage
.top
= psInfo
->y
;
633 rcPage
.right
= psInfo
->width
;
634 rcPage
.bottom
= psInfo
->height
;
636 MapDialogRect(hwndDlg
, &rcPage
);
637 TRACE("biggest page %ld %ld %ld %ld\n", rcPage
.left
, rcPage
.top
,
638 rcPage
.right
, rcPage
.bottom
);
640 if ( (rcPage
.right
- rcPage
.left
) != (rcOrigTab
.right
- rcOrigTab
.left
) )
642 if ( (rcPage
.bottom
- rcPage
.top
) != (rcOrigTab
.bottom
- rcOrigTab
.top
) )
648 /******************************************************************************
649 * PROPSHEET_IsTooSmallWizard
651 * Verify that the default property sheet is big enough.
653 static BOOL
PROPSHEET_IsTooSmallWizard(HWND hwndDlg
, PropSheetInfo
* psInfo
)
655 RECT rcSheetRect
, rcPage
, rcLine
, rcSheetClient
;
656 HWND hwndLine
= GetDlgItem(hwndDlg
, IDC_SUNKEN_LINE
);
657 PADDING_INFO padding
= PROPSHEET_GetPaddingInfoWizard(hwndDlg
, psInfo
);
659 GetClientRect(hwndDlg
, &rcSheetClient
);
660 GetWindowRect(hwndDlg
, &rcSheetRect
);
661 GetWindowRect(hwndLine
, &rcLine
);
663 /* Remove the space below the sunken line */
664 rcSheetClient
.bottom
-= (rcSheetRect
.bottom
- rcLine
.top
);
666 /* Remove the buffer zone all around the edge */
667 rcSheetClient
.bottom
-= (padding
.y
* 2);
668 rcSheetClient
.right
-= (padding
.x
* 2);
673 rcPage
.left
= psInfo
->x
;
674 rcPage
.top
= psInfo
->y
;
675 rcPage
.right
= psInfo
->width
;
676 rcPage
.bottom
= psInfo
->height
;
678 MapDialogRect(hwndDlg
, &rcPage
);
679 TRACE("biggest page %ld %ld %ld %ld\n", rcPage
.left
, rcPage
.top
,
680 rcPage
.right
, rcPage
.bottom
);
682 if (rcPage
.right
> rcSheetClient
.right
)
685 if (rcPage
.bottom
> rcSheetClient
.bottom
)
691 /******************************************************************************
692 * PROPSHEET_AdjustSize
694 * Resizes the property sheet and the tab control to fit the largest page.
696 static BOOL
PROPSHEET_AdjustSize(HWND hwndDlg
, PropSheetInfo
* psInfo
)
698 HWND hwndTabCtrl
= GetDlgItem(hwndDlg
, IDC_TABCONTROL
);
699 HWND hwndButton
= GetDlgItem(hwndDlg
, IDOK
);
701 int tabOffsetX
, tabOffsetY
, buttonHeight
;
702 PADDING_INFO padding
= PROPSHEET_GetPaddingInfo(hwndDlg
);
705 /* Get the height of buttons */
706 GetClientRect(hwndButton
, &rc
);
707 buttonHeight
= rc
.bottom
;
714 rc
.right
= psInfo
->width
;
715 rc
.bottom
= psInfo
->height
;
717 MapDialogRect(hwndDlg
, &rc
);
719 /* retrieve the dialog units */
720 units
.left
= units
.right
= 4;
721 units
.top
= units
.bottom
= 8;
722 MapDialogRect(hwndDlg
, &units
);
725 * Resize the tab control.
727 GetClientRect(hwndTabCtrl
,&tabRect
);
729 SendMessageW(hwndTabCtrl
, TCM_ADJUSTRECT
, FALSE
, (LPARAM
)&tabRect
);
731 if ((rc
.bottom
- rc
.top
) < (tabRect
.bottom
- tabRect
.top
))
733 rc
.bottom
= rc
.top
+ tabRect
.bottom
- tabRect
.top
;
734 psInfo
->height
= MulDiv((rc
.bottom
- rc
.top
),8,units
.top
);
737 if ((rc
.right
- rc
.left
) < (tabRect
.right
- tabRect
.left
))
739 rc
.right
= rc
.left
+ tabRect
.right
- tabRect
.left
;
740 psInfo
->width
= MulDiv((rc
.right
- rc
.left
),4,units
.left
);
743 SendMessageW(hwndTabCtrl
, TCM_ADJUSTRECT
, TRUE
, (LPARAM
)&rc
);
745 tabOffsetX
= -(rc
.left
);
746 tabOffsetY
= -(rc
.top
);
750 TRACE("setting tab %08lx, rc (0,0)-(%ld,%ld)\n",
751 (DWORD
)hwndTabCtrl
, rc
.right
, rc
.bottom
);
752 SetWindowPos(hwndTabCtrl
, 0, 0, 0, rc
.right
, rc
.bottom
,
753 SWP_NOMOVE
| SWP_NOZORDER
| SWP_NOACTIVATE
);
755 GetClientRect(hwndTabCtrl
, &rc
);
757 TRACE("tab client rc %ld %ld %ld %ld\n",
758 rc
.left
, rc
.top
, rc
.right
, rc
.bottom
);
760 rc
.right
+= ((padding
.x
* 2) + tabOffsetX
);
761 rc
.bottom
+= (buttonHeight
+ (3 * padding
.y
) + tabOffsetY
);
764 * Resize the property sheet.
766 TRACE("setting dialog %08lx, rc (0,0)-(%ld,%ld)\n",
767 (DWORD
)hwndDlg
, rc
.right
, rc
.bottom
);
768 SetWindowPos(hwndDlg
, 0, 0, 0, rc
.right
, rc
.bottom
,
769 SWP_NOMOVE
| SWP_NOZORDER
| SWP_NOACTIVATE
);
773 /******************************************************************************
774 * PROPSHEET_AdjustSizeWizard
776 * Resizes the property sheet to fit the largest page.
778 static BOOL
PROPSHEET_AdjustSizeWizard(HWND hwndDlg
, PropSheetInfo
* psInfo
)
780 HWND hwndButton
= GetDlgItem(hwndDlg
, IDCANCEL
);
781 HWND hwndLine
= GetDlgItem(hwndDlg
, IDC_SUNKEN_LINE
);
782 HWND hwndTabCtrl
= GetDlgItem(hwndDlg
, IDC_TABCONTROL
);
784 int buttonHeight
, lineHeight
;
785 PADDING_INFO padding
= PROPSHEET_GetPaddingInfoWizard(hwndDlg
, psInfo
);
788 /* Get the height of buttons */
789 GetClientRect(hwndButton
, &rc
);
790 buttonHeight
= rc
.bottom
;
792 GetClientRect(hwndLine
, &rc
);
793 lineHeight
= rc
.bottom
;
795 /* retrieve the dialog units */
796 units
.left
= units
.right
= 4;
797 units
.top
= units
.bottom
= 8;
798 MapDialogRect(hwndDlg
, &units
);
805 rc
.right
= psInfo
->width
;
806 rc
.bottom
= psInfo
->height
;
808 MapDialogRect(hwndDlg
, &rc
);
810 GetClientRect(hwndTabCtrl
,&tabRect
);
812 if ((rc
.bottom
- rc
.top
) < (tabRect
.bottom
- tabRect
.top
))
814 rc
.bottom
= rc
.top
+ tabRect
.bottom
- tabRect
.top
;
815 psInfo
->height
= MulDiv((rc
.bottom
- rc
.top
), 8, units
.top
);
818 if ((rc
.right
- rc
.left
) < (tabRect
.right
- tabRect
.left
))
820 rc
.right
= rc
.left
+ tabRect
.right
- tabRect
.left
;
821 psInfo
->width
= MulDiv((rc
.right
- rc
.left
), 4, units
.left
);
824 TRACE("Biggest page %ld %ld %ld %ld\n", rc
.left
, rc
.top
, rc
.right
, rc
.bottom
);
825 TRACE(" constants padx=%d, pady=%d, butH=%d, lH=%d\n",
826 padding
.x
, padding
.y
, buttonHeight
, lineHeight
);
829 rc
.right
+= (padding
.x
* 2);
830 rc
.bottom
+= (buttonHeight
+ (5 * padding
.y
) + lineHeight
);
833 * Resize the property sheet.
835 TRACE("setting dialog %08lx, rc (0,0)-(%ld,%ld)\n",
836 (DWORD
)hwndDlg
, rc
.right
, rc
.bottom
);
837 SetWindowPos(hwndDlg
, 0, 0, 0, rc
.right
, rc
.bottom
,
838 SWP_NOMOVE
| SWP_NOZORDER
| SWP_NOACTIVATE
);
842 /******************************************************************************
843 * PROPSHEET_AdjustButtons
845 * Adjusts the buttons' positions.
847 static BOOL
PROPSHEET_AdjustButtons(HWND hwndParent
, PropSheetInfo
* psInfo
)
849 HWND hwndButton
= GetDlgItem(hwndParent
, IDOK
);
853 int buttonWidth
, buttonHeight
;
854 PADDING_INFO padding
= PROPSHEET_GetPaddingInfo(hwndParent
);
856 if (psInfo
->hasApply
)
863 * Obtain the size of the buttons.
865 GetClientRect(hwndButton
, &rcSheet
);
866 buttonWidth
= rcSheet
.right
;
867 buttonHeight
= rcSheet
.bottom
;
870 * Get the size of the property sheet.
872 GetClientRect(hwndParent
, &rcSheet
);
875 * All buttons will be at this y coordinate.
877 y
= rcSheet
.bottom
- (padding
.y
+ buttonHeight
);
880 * Position OK button.
882 hwndButton
= GetDlgItem(hwndParent
, IDOK
);
884 x
= rcSheet
.right
- ((padding
.x
+ buttonWidth
) * num_buttons
);
886 SetWindowPos(hwndButton
, 0, x
, y
, 0, 0,
887 SWP_NOSIZE
| SWP_NOZORDER
| SWP_NOACTIVATE
);
890 * Position Cancel button.
892 hwndButton
= GetDlgItem(hwndParent
, IDCANCEL
);
894 x
= rcSheet
.right
- ((padding
.x
+ buttonWidth
) * (num_buttons
- 1));
896 SetWindowPos(hwndButton
, 0, x
, y
, 0, 0,
897 SWP_NOSIZE
| SWP_NOZORDER
| SWP_NOACTIVATE
);
900 * Position Apply button.
902 hwndButton
= GetDlgItem(hwndParent
, IDC_APPLY_BUTTON
);
904 if (psInfo
->hasApply
)
907 x
= rcSheet
.right
- ((padding
.x
+ buttonWidth
) * 2);
909 x
= rcSheet
.right
- (padding
.x
+ buttonWidth
);
911 SetWindowPos(hwndButton
, 0, x
, y
, 0, 0,
912 SWP_NOSIZE
| SWP_NOZORDER
| SWP_NOACTIVATE
);
914 EnableWindow(hwndButton
, FALSE
);
917 ShowWindow(hwndButton
, SW_HIDE
);
920 * Position Help button.
922 hwndButton
= GetDlgItem(hwndParent
, IDHELP
);
926 x
= rcSheet
.right
- (padding
.x
+ buttonWidth
);
928 SetWindowPos(hwndButton
, 0, x
, y
, 0, 0,
929 SWP_NOSIZE
| SWP_NOZORDER
| SWP_NOACTIVATE
);
932 ShowWindow(hwndButton
, SW_HIDE
);
937 /******************************************************************************
938 * PROPSHEET_AdjustButtonsWizard
940 * Adjusts the buttons' positions.
942 static BOOL
PROPSHEET_AdjustButtonsWizard(HWND hwndParent
,
943 PropSheetInfo
* psInfo
)
945 HWND hwndButton
= GetDlgItem(hwndParent
, IDCANCEL
);
946 HWND hwndLine
= GetDlgItem(hwndParent
, IDC_SUNKEN_LINE
);
950 int buttonWidth
, buttonHeight
, lineHeight
, lineWidth
;
951 PADDING_INFO padding
= PROPSHEET_GetPaddingInfoWizard(hwndParent
, psInfo
);
957 * Obtain the size of the buttons.
959 GetClientRect(hwndButton
, &rcSheet
);
960 buttonWidth
= rcSheet
.right
;
961 buttonHeight
= rcSheet
.bottom
;
963 GetClientRect(hwndLine
, &rcSheet
);
964 lineHeight
= rcSheet
.bottom
;
967 * Get the size of the property sheet.
969 GetClientRect(hwndParent
, &rcSheet
);
972 * All buttons will be at this y coordinate.
974 y
= rcSheet
.bottom
- (padding
.y
+ buttonHeight
);
977 * Position the Next and the Finish buttons.
979 hwndButton
= GetDlgItem(hwndParent
, IDC_NEXT_BUTTON
);
981 x
= rcSheet
.right
- ((padding
.x
+ buttonWidth
) * (num_buttons
- 1));
983 SetWindowPos(hwndButton
, 0, x
, y
, 0, 0,
984 SWP_NOSIZE
| SWP_NOZORDER
| SWP_NOACTIVATE
);
986 hwndButton
= GetDlgItem(hwndParent
, IDC_FINISH_BUTTON
);
988 SetWindowPos(hwndButton
, 0, x
, y
, 0, 0,
989 SWP_NOSIZE
| SWP_NOZORDER
| SWP_NOACTIVATE
);
991 ShowWindow(hwndButton
, SW_HIDE
);
994 * Position the Back button.
996 hwndButton
= GetDlgItem(hwndParent
, IDC_BACK_BUTTON
);
1000 SetWindowPos(hwndButton
, 0, x
, y
, 0, 0,
1001 SWP_NOSIZE
| SWP_NOZORDER
| SWP_NOACTIVATE
);
1004 * Position the Cancel button.
1006 hwndButton
= GetDlgItem(hwndParent
, IDCANCEL
);
1008 x
= rcSheet
.right
- ((padding
.x
+ buttonWidth
) * (num_buttons
- 2));
1010 SetWindowPos(hwndButton
, 0, x
, y
, 0, 0,
1011 SWP_NOSIZE
| SWP_NOZORDER
| SWP_NOACTIVATE
);
1014 * Position Help button.
1016 hwndButton
= GetDlgItem(hwndParent
, IDHELP
);
1018 if (psInfo
->hasHelp
)
1020 x
= rcSheet
.right
- (padding
.x
+ buttonWidth
);
1022 SetWindowPos(hwndButton
, 0, x
, y
, 0, 0,
1023 SWP_NOSIZE
| SWP_NOZORDER
| SWP_NOACTIVATE
);
1026 ShowWindow(hwndButton
, SW_HIDE
);
1029 * Position and resize the sunken line.
1032 y
= rcSheet
.bottom
- ((padding
.y
* 2) + buttonHeight
+ lineHeight
);
1034 GetClientRect(hwndParent
, &rcSheet
);
1035 lineWidth
= rcSheet
.right
- (padding
.x
* 2);
1037 SetWindowPos(hwndLine
, 0, x
, y
, lineWidth
, 2,
1038 SWP_NOZORDER
| SWP_NOACTIVATE
);
1043 /******************************************************************************
1044 * PROPSHEET_GetPaddingInfo
1046 * Returns the layout information.
1048 static PADDING_INFO
PROPSHEET_GetPaddingInfo(HWND hwndDlg
)
1050 HWND hwndTab
= GetDlgItem(hwndDlg
, IDC_TABCONTROL
);
1053 PADDING_INFO padding
;
1055 GetWindowRect(hwndTab
, &rcTab
);
1060 ScreenToClient(hwndDlg
, &tl
);
1068 /******************************************************************************
1069 * PROPSHEET_GetPaddingInfoWizard
1071 * Returns the layout information.
1072 * Vertical spacing is the distance between the line and the buttons.
1073 * Do NOT use the Help button to gather padding information when it isn't mapped
1074 * (PSH_HASHELP), as app writers aren't forced to supply correct coordinates
1075 * for it in this case !
1076 * FIXME: I'm not sure about any other coordinate problems with these evil
1077 * buttons. Fix it in case additional problems appear or maybe calculate
1078 * a padding in a completely different way, as this is somewhat messy.
1080 static PADDING_INFO
PROPSHEET_GetPaddingInfoWizard(HWND hwndDlg
, const PropSheetInfo
*
1083 PADDING_INFO padding
;
1087 POINT ptButton
, ptLine
;
1090 if (psInfo
->hasHelp
)
1096 if (psInfo
->ppshheader
.dwFlags
& INTRNL_ANY_WIZARD
)
1098 idButton
= IDC_NEXT_BUTTON
;
1102 /* hopefully this is ok */
1103 idButton
= IDCANCEL
;
1107 hwndControl
= GetDlgItem(hwndDlg
, idButton
);
1108 GetWindowRect(hwndControl
, &rc
);
1110 ptButton
.x
= rc
.left
;
1111 ptButton
.y
= rc
.top
;
1113 ScreenToClient(hwndDlg
, &ptButton
);
1116 hwndControl
= GetDlgItem(hwndDlg
, IDC_SUNKEN_LINE
);
1117 GetWindowRect(hwndControl
, &rc
);
1120 ptLine
.y
= rc
.bottom
;
1122 ScreenToClient(hwndDlg
, &ptLine
);
1124 padding
.y
= ptButton
.y
- ptLine
.y
;
1127 ERR("padding negative ! Please report this !\n");
1129 /* this is most probably not correct, but the best we have now */
1130 padding
.x
= padding
.y
;
1134 /******************************************************************************
1135 * PROPSHEET_CreateTabControl
1137 * Insert the tabs in the tab control.
1139 static BOOL
PROPSHEET_CreateTabControl(HWND hwndParent
,
1140 PropSheetInfo
* psInfo
)
1142 HWND hwndTabCtrl
= GetDlgItem(hwndParent
, IDC_TABCONTROL
);
1148 item
.mask
= TCIF_TEXT
;
1149 item
.cchTextMax
= MAX_TABTEXT_LENGTH
;
1151 nTabs
= psInfo
->nPages
;
1154 * Set the image list for icons.
1156 if (psInfo
->hImageList
)
1158 SendMessageW(hwndTabCtrl
, TCM_SETIMAGELIST
, 0, (LPARAM
)psInfo
->hImageList
);
1161 for (i
= 0; i
< nTabs
; i
++)
1163 if ( psInfo
->proppage
[i
].hasIcon
)
1165 item
.mask
|= TCIF_IMAGE
;
1166 item
.iImage
= iImage
++;
1170 item
.mask
&= ~TCIF_IMAGE
;
1173 item
.pszText
= (LPWSTR
) psInfo
->proppage
[i
].pszText
;
1174 SendMessageW(hwndTabCtrl
, TCM_INSERTITEMW
, (WPARAM
)i
, (LPARAM
)&item
);
1180 * Get the size of an in-memory Template
1182 *( Based on the code of PROPSHEET_CollectPageInfo)
1183 * See also dialog.c/DIALOG_ParseTemplate32().
1186 static UINT
GetTemplateSize(DLGTEMPLATE
* pTemplate
)
1189 const WORD
* p
= (const WORD
*)pTemplate
;
1190 BOOL istemplateex
= (((MyDLGTEMPLATEEX
*)pTemplate
)->signature
== 0xFFFF);
1195 /* DLGTEMPLATEEX (not defined in any std. header file) */
1197 TRACE("is DLGTEMPLATEEX\n");
1199 p
++; /* signature */
1200 p
+= 2; /* help ID */
1201 p
+= 2; /* ext style */
1208 TRACE("is DLGTEMPLATE\n");
1210 p
+= 2; /* ext style */
1213 nrofitems
= (WORD
)*p
; p
++; /* nb items */
1229 TRACE("menu %s\n",debugstr_w((LPCWSTR
)p
));
1230 p
+= lstrlenW( (LPCWSTR
)p
) + 1;
1241 p
+= 2; /* 0xffff plus predefined window class ordinal value */
1244 TRACE("class %s\n",debugstr_w((LPCWSTR
)p
));
1245 p
+= lstrlenW( (LPCWSTR
)p
) + 1;
1250 TRACE("title %s\n",debugstr_w((LPCWSTR
)p
));
1251 p
+= lstrlenW((LPCWSTR
)p
) + 1;
1253 /* font, if DS_SETFONT set */
1254 if ((DS_SETFONT
& ((istemplateex
)? ((MyDLGTEMPLATEEX
*)pTemplate
)->style
:
1257 p
+=(istemplateex
)?3:1;
1258 TRACE("font %s\n",debugstr_w((LPCWSTR
)p
));
1259 p
+= lstrlenW( (LPCWSTR
)p
) + 1; /* the font name */
1262 /* now process the DLGITEMTEMPLATE(EX) structs (plus custom data)
1263 * that are following the DLGTEMPLATE(EX) data */
1264 TRACE("%d items\n",nrofitems
);
1265 while (nrofitems
> 0)
1267 p
= (WORD
*)(((DWORD
)p
+ 3) & ~3); /* DWORD align */
1270 p
+= (istemplateex
? sizeof(MyDLGITEMTEMPLATEEX
) : sizeof(DLGITEMTEMPLATE
))/sizeof(WORD
);
1279 TRACE("class ordinal 0x%08lx\n",*(DWORD
*)p
);
1283 TRACE("class %s\n",debugstr_w((LPCWSTR
)p
));
1284 p
+= lstrlenW( (LPCWSTR
)p
) + 1;
1288 /* check title text */
1295 TRACE("text ordinal 0x%08lx\n",*(DWORD
*)p
);
1299 TRACE("text %s\n",debugstr_w((LPCWSTR
)p
));
1300 p
+= lstrlenW( (LPCWSTR
)p
) + 1;
1303 p
+= *p
+ 1; /* Skip extra data */
1307 TRACE("%p %p size 0x%08x\n",p
, (WORD
*)pTemplate
,sizeof(WORD
)*(p
- (WORD
*)pTemplate
));
1308 return (p
- (WORD
*)pTemplate
)*sizeof(WORD
);
1312 /******************************************************************************
1313 * PROPSHEET_CreatePage
1317 static BOOL
PROPSHEET_CreatePage(HWND hwndParent
,
1319 const PropSheetInfo
* psInfo
,
1320 LPCPROPSHEETPAGEW ppshpage
)
1322 DLGTEMPLATE
* pTemplate
;
1325 PropPageInfo
* ppInfo
= psInfo
->proppage
;
1326 PADDING_INFO padding
;
1327 UINT pageWidth
,pageHeight
;
1331 TRACE("index %d\n", index
);
1333 if (ppshpage
== NULL
)
1338 if (ppshpage
->dwFlags
& PSP_DLGINDIRECT
)
1340 pTemplate
= (DLGTEMPLATE
*)ppshpage
->u
.pResource
;
1341 resSize
= GetTemplateSize(pTemplate
);
1348 hResource
= FindResourceW(ppshpage
->hInstance
,
1349 ppshpage
->u
.pszTemplate
,
1354 resSize
= SizeofResource(ppshpage
->hInstance
, hResource
);
1356 hTemplate
= LoadResource(ppshpage
->hInstance
, hResource
);
1360 pTemplate
= (LPDLGTEMPLATEW
)LockResource(hTemplate
);
1362 * Make a copy of the dialog template to make it writable
1365 temp
= COMCTL32_Alloc(resSize
);
1369 TRACE("copying pTemplate %p into temp %p (%ld)\n", pTemplate
, temp
, resSize
);
1370 memcpy(temp
, pTemplate
, resSize
);
1373 if (((MyDLGTEMPLATEEX
*)pTemplate
)->signature
== 0xFFFF)
1375 ((MyDLGTEMPLATEEX
*)pTemplate
)->style
|= WS_CHILD
| DS_CONTROL
;
1376 ((MyDLGTEMPLATEEX
*)pTemplate
)->style
&= ~DS_MODALFRAME
;
1377 ((MyDLGTEMPLATEEX
*)pTemplate
)->style
&= ~WS_CAPTION
;
1378 ((MyDLGTEMPLATEEX
*)pTemplate
)->style
&= ~WS_SYSMENU
;
1379 ((MyDLGTEMPLATEEX
*)pTemplate
)->style
&= ~WS_POPUP
;
1380 ((MyDLGTEMPLATEEX
*)pTemplate
)->style
&= ~WS_DISABLED
;
1381 ((MyDLGTEMPLATEEX
*)pTemplate
)->style
&= ~WS_VISIBLE
;
1382 ((MyDLGTEMPLATEEX
*)pTemplate
)->style
&= ~WS_THICKFRAME
;
1386 pTemplate
->style
|= WS_CHILD
| DS_CONTROL
;
1387 pTemplate
->style
&= ~DS_MODALFRAME
;
1388 pTemplate
->style
&= ~WS_CAPTION
;
1389 pTemplate
->style
&= ~WS_SYSMENU
;
1390 pTemplate
->style
&= ~WS_POPUP
;
1391 pTemplate
->style
&= ~WS_DISABLED
;
1392 pTemplate
->style
&= ~WS_VISIBLE
;
1393 pTemplate
->style
&= ~WS_THICKFRAME
;
1396 if (psInfo
->proppage
[index
].useCallback
)
1397 (*(ppshpage
->pfnCallback
))(hwndParent
,
1399 (LPPROPSHEETPAGEW
)ppshpage
);
1401 hwndPage
= CreateDialogIndirectParamW(ppshpage
->hInstance
,
1404 ppshpage
->pfnDlgProc
,
1406 /* Free a no more needed copy */
1408 COMCTL32_Free(temp
);
1410 ppInfo
[index
].hwndPage
= hwndPage
;
1412 if (psInfo
->ppshheader
.dwFlags
& INTRNL_ANY_WIZARD
) {
1413 /* FIXME: This code may no longer be correct.
1414 * It was not for the non-wizard path. (GLA 6/02)
1416 rc
.left
= psInfo
->x
;
1418 rc
.right
= psInfo
->width
;
1419 rc
.bottom
= psInfo
->height
;
1421 MapDialogRect(hwndParent
, &rc
);
1423 pageWidth
= rc
.right
- rc
.left
;
1424 pageHeight
= rc
.bottom
- rc
.top
;
1426 padding
= PROPSHEET_GetPaddingInfoWizard(hwndParent
, psInfo
);
1427 TRACE("setting page %08lx, rc (%ld,%ld)-(%ld,%ld) w=%d, h=%d, padx=%d, pady=%d\n",
1428 (DWORD
)hwndPage
, rc
.left
, rc
.top
, rc
.right
, rc
.bottom
,
1429 pageWidth
, pageHeight
, padding
.x
, padding
.y
);
1430 SetWindowPos(hwndPage
, HWND_TOP
,
1431 rc
.left
+ padding
.x
/2,
1432 rc
.top
+ padding
.y
/2,
1433 pageWidth
, pageHeight
, 0);
1437 * Ask the Tab control to reduce the client rectangle to that
1440 PROPSHEET_GetPageRect(psInfo
, hwndParent
, &rc
);
1441 pageWidth
= rc
.right
- rc
.left
;
1442 pageHeight
= rc
.bottom
- rc
.top
;
1443 TRACE("setting page %08lx, rc (%ld,%ld)-(%ld,%ld) w=%d, h=%d\n",
1444 (DWORD
)hwndPage
, rc
.left
, rc
.top
, rc
.right
, rc
.bottom
,
1445 pageWidth
, pageHeight
);
1446 SetWindowPos(hwndPage
, HWND_TOP
,
1448 pageWidth
, pageHeight
, 0);
1454 /******************************************************************************
1455 * PROPSHEET_ShowPage
1457 * Displays or creates the specified page.
1459 static BOOL
PROPSHEET_ShowPage(HWND hwndDlg
, int index
, PropSheetInfo
* psInfo
)
1463 TRACE("active_page %d, index %d\n", psInfo
->active_page
, index
);
1464 if (index
== psInfo
->active_page
)
1466 if (GetTopWindow(hwndDlg
) != psInfo
->proppage
[index
].hwndPage
)
1467 SetWindowPos(psInfo
->proppage
[index
].hwndPage
, HWND_TOP
, 0, 0, 0, 0, SWP_NOSIZE
| SWP_NOMOVE
);
1471 if (psInfo
->proppage
[index
].hwndPage
== 0)
1473 LPCPROPSHEETPAGEW ppshpage
;
1475 ppshpage
= (LPCPROPSHEETPAGEW
)psInfo
->proppage
[index
].hpage
;
1476 PROPSHEET_CreatePage(hwndDlg
, index
, psInfo
, ppshpage
);
1479 if (psInfo
->active_page
!= -1)
1480 ShowWindow(psInfo
->proppage
[psInfo
->active_page
].hwndPage
, SW_HIDE
);
1482 ShowWindow(psInfo
->proppage
[index
].hwndPage
, SW_SHOW
);
1484 /* Synchronize current selection with tab control
1485 * It seems to be needed even in case of PSH_WIZARD (no tab controls there) */
1486 hwndTabCtrl
= GetDlgItem(hwndDlg
, IDC_TABCONTROL
);
1487 SendMessageW(hwndTabCtrl
, TCM_SETCURSEL
, index
, 0);
1489 psInfo
->active_page
= index
;
1490 psInfo
->activeValid
= TRUE
;
1495 /******************************************************************************
1498 static BOOL
PROPSHEET_Back(HWND hwndDlg
)
1502 PropSheetInfo
* psInfo
= (PropSheetInfo
*) GetPropW(hwndDlg
,
1507 TRACE("active_page %d\n", psInfo
->active_page
);
1508 if (psInfo
->active_page
< 0)
1511 psn
.hdr
.code
= PSN_WIZBACK
;
1512 psn
.hdr
.hwndFrom
= hwndDlg
;
1516 hwndPage
= psInfo
->proppage
[psInfo
->active_page
].hwndPage
;
1518 result
= SendMessageW(hwndPage
, WM_NOTIFY
, 0, (LPARAM
) &psn
);
1521 else if (result
== 0)
1522 idx
= psInfo
->active_page
- 1;
1524 idx
= PROPSHEET_FindPageByResId(psInfo
, result
);
1526 if (idx
>= 0 && idx
< psInfo
->nPages
)
1528 if (PROPSHEET_CanSetCurSel(hwndDlg
))
1529 PROPSHEET_SetCurSel(hwndDlg
, idx
, -1, 0);
1534 /******************************************************************************
1537 static BOOL
PROPSHEET_Next(HWND hwndDlg
)
1541 LRESULT msgResult
= 0;
1542 PropSheetInfo
* psInfo
= (PropSheetInfo
*) GetPropW(hwndDlg
,
1546 TRACE("active_page %d\n", psInfo
->active_page
);
1547 if (psInfo
->active_page
< 0)
1550 psn
.hdr
.code
= PSN_WIZNEXT
;
1551 psn
.hdr
.hwndFrom
= hwndDlg
;
1555 hwndPage
= psInfo
->proppage
[psInfo
->active_page
].hwndPage
;
1557 msgResult
= SendMessageA(hwndPage
, WM_NOTIFY
, 0, (LPARAM
) &psn
);
1558 if (msgResult
== -1)
1560 else if (msgResult
== 0)
1561 idx
= psInfo
->active_page
+ 1;
1563 idx
= PROPSHEET_FindPageByResId(psInfo
, msgResult
);
1565 if (idx
< psInfo
->nPages
)
1567 if (PROPSHEET_CanSetCurSel(hwndDlg
) != FALSE
)
1568 PROPSHEET_SetCurSel(hwndDlg
, idx
, 1, 0);
1574 /******************************************************************************
1577 static BOOL
PROPSHEET_Finish(HWND hwndDlg
)
1581 LRESULT msgResult
= 0;
1582 PropSheetInfo
* psInfo
= (PropSheetInfo
*) GetPropW(hwndDlg
,
1585 TRACE("active_page %d\n", psInfo
->active_page
);
1586 if (psInfo
->active_page
< 0)
1589 psn
.hdr
.code
= PSN_WIZFINISH
;
1590 psn
.hdr
.hwndFrom
= hwndDlg
;
1594 hwndPage
= psInfo
->proppage
[psInfo
->active_page
].hwndPage
;
1596 msgResult
= SendMessageW(hwndPage
, WM_NOTIFY
, 0, (LPARAM
) &psn
);
1598 TRACE("msg result %ld\n", msgResult
);
1603 if (psInfo
->isModeless
)
1604 psInfo
->activeValid
= FALSE
;
1606 EndDialog(hwndDlg
, TRUE
);
1611 /******************************************************************************
1614 static BOOL
PROPSHEET_Apply(HWND hwndDlg
, LPARAM lParam
)
1620 PropSheetInfo
* psInfo
= (PropSheetInfo
*) GetPropW(hwndDlg
,
1623 TRACE("active_page %d\n", psInfo
->active_page
);
1624 if (psInfo
->active_page
< 0)
1627 psn
.hdr
.hwndFrom
= hwndDlg
;
1633 * Send PSN_KILLACTIVE to the current page.
1635 psn
.hdr
.code
= PSN_KILLACTIVE
;
1637 hwndPage
= psInfo
->proppage
[psInfo
->active_page
].hwndPage
;
1639 if (SendMessageA(hwndPage
, WM_NOTIFY
, 0, (LPARAM
) &psn
) != FALSE
)
1643 * Send PSN_APPLY to all pages.
1645 psn
.hdr
.code
= PSN_APPLY
;
1646 psn
.lParam
= lParam
;
1648 for (i
= 0; i
< psInfo
->nPages
; i
++)
1650 hwndPage
= psInfo
->proppage
[i
].hwndPage
;
1653 msgResult
= SendMessageA(hwndPage
, WM_NOTIFY
, 0, (LPARAM
) &psn
);
1654 if (msgResult
== PSNRET_INVALID_NOCHANGEPAGE
)
1661 psInfo
->activeValid
= FALSE
;
1663 else if(psInfo
->active_page
>= 0)
1665 psn
.hdr
.code
= PSN_SETACTIVE
;
1667 hwndPage
= psInfo
->proppage
[psInfo
->active_page
].hwndPage
;
1668 SendMessageA(hwndPage
, WM_NOTIFY
, 0, (LPARAM
) &psn
);
1674 /******************************************************************************
1677 static void PROPSHEET_Cancel(HWND hwndDlg
, LPARAM lParam
)
1679 PropSheetInfo
* psInfo
= (PropSheetInfo
*) GetPropW(hwndDlg
,
1685 TRACE("active_page %d\n", psInfo
->active_page
);
1686 if (psInfo
->active_page
< 0)
1689 hwndPage
= psInfo
->proppage
[psInfo
->active_page
].hwndPage
;
1690 psn
.hdr
.code
= PSN_QUERYCANCEL
;
1691 psn
.hdr
.hwndFrom
= hwndDlg
;
1695 if (SendMessageA(hwndPage
, WM_NOTIFY
, 0, (LPARAM
) &psn
))
1698 psn
.hdr
.code
= PSN_RESET
;
1699 psn
.lParam
= lParam
;
1701 for (i
= 0; i
< psInfo
->nPages
; i
++)
1703 hwndPage
= psInfo
->proppage
[i
].hwndPage
;
1706 SendMessageA(hwndPage
, WM_NOTIFY
, 0, (LPARAM
) &psn
);
1709 if (psInfo
->isModeless
)
1711 /* makes PSM_GETCURRENTPAGEHWND return NULL */
1712 psInfo
->activeValid
= FALSE
;
1715 EndDialog(hwndDlg
, FALSE
);
1718 /******************************************************************************
1721 static void PROPSHEET_Help(HWND hwndDlg
)
1723 PropSheetInfo
* psInfo
= (PropSheetInfo
*) GetPropW(hwndDlg
,
1728 TRACE("active_page %d\n", psInfo
->active_page
);
1729 if (psInfo
->active_page
< 0)
1732 hwndPage
= psInfo
->proppage
[psInfo
->active_page
].hwndPage
;
1733 psn
.hdr
.code
= PSN_HELP
;
1734 psn
.hdr
.hwndFrom
= hwndDlg
;
1738 SendMessageA(hwndPage
, WM_NOTIFY
, 0, (LPARAM
) &psn
);
1741 /******************************************************************************
1744 static void PROPSHEET_Changed(HWND hwndDlg
, HWND hwndDirtyPage
)
1747 PropSheetInfo
* psInfo
= (PropSheetInfo
*) GetPropW(hwndDlg
,
1751 if (!psInfo
) return;
1753 * Set the dirty flag of this page.
1755 for (i
= 0; i
< psInfo
->nPages
; i
++)
1757 if (psInfo
->proppage
[i
].hwndPage
== hwndDirtyPage
)
1758 psInfo
->proppage
[i
].isDirty
= TRUE
;
1762 * Enable the Apply button.
1764 if (psInfo
->hasApply
)
1766 HWND hwndApplyBtn
= GetDlgItem(hwndDlg
, IDC_APPLY_BUTTON
);
1768 EnableWindow(hwndApplyBtn
, TRUE
);
1772 /******************************************************************************
1773 * PROPSHEET_UnChanged
1775 static void PROPSHEET_UnChanged(HWND hwndDlg
, HWND hwndCleanPage
)
1778 BOOL noPageDirty
= TRUE
;
1779 HWND hwndApplyBtn
= GetDlgItem(hwndDlg
, IDC_APPLY_BUTTON
);
1780 PropSheetInfo
* psInfo
= (PropSheetInfo
*) GetPropW(hwndDlg
,
1784 if ( !psInfo
) return;
1785 for (i
= 0; i
< psInfo
->nPages
; i
++)
1787 /* set the specified page as clean */
1788 if (psInfo
->proppage
[i
].hwndPage
== hwndCleanPage
)
1789 psInfo
->proppage
[i
].isDirty
= FALSE
;
1791 /* look to see if there's any dirty pages */
1792 if (psInfo
->proppage
[i
].isDirty
)
1793 noPageDirty
= FALSE
;
1797 * Disable Apply button.
1800 EnableWindow(hwndApplyBtn
, FALSE
);
1803 /******************************************************************************
1804 * PROPSHEET_PressButton
1806 static void PROPSHEET_PressButton(HWND hwndDlg
, int buttonID
)
1808 TRACE("buttonID %d\n", buttonID
);
1811 case PSBTN_APPLYNOW
:
1812 PROPSHEET_DoCommand(hwndDlg
, IDC_APPLY_BUTTON
);
1815 PROPSHEET_Back(hwndDlg
);
1818 PROPSHEET_DoCommand(hwndDlg
, IDCANCEL
);
1821 PROPSHEET_Finish(hwndDlg
);
1824 PROPSHEET_DoCommand(hwndDlg
, IDHELP
);
1827 PROPSHEET_Next(hwndDlg
);
1830 PROPSHEET_DoCommand(hwndDlg
, IDOK
);
1833 FIXME("Invalid button index %d\n", buttonID
);
1838 /*************************************************************************
1839 * BOOL PROPSHEET_CanSetCurSel [Internal]
1841 * Test whether the current page can be changed by sending a PSN_KILLACTIVE
1844 * hwndDlg [I] handle to a Dialog hWnd
1847 * TRUE if Current Selection can change
1851 static BOOL
PROPSHEET_CanSetCurSel(HWND hwndDlg
)
1853 PropSheetInfo
* psInfo
= (PropSheetInfo
*) GetPropW(hwndDlg
,
1859 TRACE("active_page %d\n", psInfo
->active_page
);
1866 if (psInfo
->active_page
< 0)
1873 * Notify the current page.
1875 hwndPage
= psInfo
->proppage
[psInfo
->active_page
].hwndPage
;
1876 psn
.hdr
.code
= PSN_KILLACTIVE
;
1877 psn
.hdr
.hwndFrom
= hwndDlg
;
1881 res
= !SendMessageA(hwndPage
, WM_NOTIFY
, 0, (LPARAM
) &psn
);
1884 TRACE("<-- %d\n", res
);
1888 /******************************************************************************
1889 * PROPSHEET_SetCurSel
1891 static BOOL
PROPSHEET_SetCurSel(HWND hwndDlg
,
1894 HPROPSHEETPAGE hpage
1897 PropSheetInfo
* psInfo
= (PropSheetInfo
*) GetPropW(hwndDlg
, PropSheetInfoStr
);
1898 HWND hwndHelp
= GetDlgItem(hwndDlg
, IDHELP
);
1899 HWND hwndTabControl
= GetDlgItem(hwndDlg
, IDC_TABCONTROL
);
1901 TRACE("index %d, skipdir %d, hpage %p\n", index
, skipdir
, hpage
);
1902 /* hpage takes precedence over index */
1904 index
= PROPSHEET_GetPageIndex(hpage
, psInfo
);
1906 if (index
< 0 || index
>= psInfo
->nPages
)
1908 TRACE("Could not find page to select!\n");
1917 SendMessageW(hwndTabControl
, TCM_SETCURSEL
, index
, 0);
1919 psn
.hdr
.code
= PSN_SETACTIVE
;
1920 psn
.hdr
.hwndFrom
= hwndDlg
;
1924 if (!psInfo
->proppage
[index
].hwndPage
) {
1925 LPCPROPSHEETPAGEW ppshpage
= (LPCPROPSHEETPAGEW
)psInfo
->proppage
[index
].hpage
;
1926 PROPSHEET_CreatePage(hwndDlg
, index
, psInfo
, ppshpage
);
1929 result
= SendMessageW(psInfo
->proppage
[index
].hwndPage
, WM_NOTIFY
, 0, (LPARAM
) &psn
);
1936 FIXME("Tried to skip before first property sheet page!\n");
1939 if (index
>= psInfo
->nPages
) {
1940 FIXME("Tried to skip after last property sheet page!\n");
1941 index
= psInfo
->nPages
-1;
1945 else if (result
!= 0)
1947 index
= PROPSHEET_FindPageByResId(psInfo
, result
);
1952 * Display the new page.
1954 PROPSHEET_ShowPage(hwndDlg
, index
, psInfo
);
1956 if (psInfo
->proppage
[index
].hasHelp
)
1957 EnableWindow(hwndHelp
, TRUE
);
1959 EnableWindow(hwndHelp
, FALSE
);
1964 /******************************************************************************
1965 * PROPSHEET_SetCurSelId
1967 * Selects the page, specified by resource id.
1969 static void PROPSHEET_SetCurSelId(HWND hwndDlg
, int id
)
1972 PropSheetInfo
* psInfo
=
1973 (PropSheetInfo
*) GetPropW(hwndDlg
, PropSheetInfoStr
);
1975 idx
= PROPSHEET_FindPageByResId(psInfo
, id
);
1976 if (idx
< psInfo
->nPages
)
1978 if (PROPSHEET_CanSetCurSel(hwndDlg
) != FALSE
)
1979 PROPSHEET_SetCurSel(hwndDlg
, idx
, 1, 0);
1983 /******************************************************************************
1984 * PROPSHEET_SetTitleA
1986 static void PROPSHEET_SetTitleA(HWND hwndDlg
, DWORD dwStyle
, LPCSTR lpszText
)
1988 if(HIWORD(lpszText
))
1991 MultiByteToWideChar(CP_ACP
, 0, lpszText
, -1,
1992 szTitle
, sizeof szTitle
);
1993 PROPSHEET_SetTitleW(hwndDlg
, dwStyle
, szTitle
);
1997 PROPSHEET_SetTitleW(hwndDlg
, dwStyle
, (LPCWSTR
)lpszText
);
2001 /******************************************************************************
2002 * PROPSHEET_SetTitleW
2004 static void PROPSHEET_SetTitleW(HWND hwndDlg
, DWORD dwStyle
, LPCWSTR lpszText
)
2006 PropSheetInfo
* psInfo
= (PropSheetInfo
*) GetPropW(hwndDlg
, PropSheetInfoStr
);
2009 TRACE("'%s' (style %08lx)\n", debugstr_w(lpszText
), dwStyle
);
2010 if (HIWORD(lpszText
) == 0) {
2011 if (!LoadStringW(psInfo
->ppshheader
.hInstance
,
2012 LOWORD(lpszText
), szTitle
, sizeof(szTitle
)-sizeof(WCHAR
)))
2016 if (dwStyle
& PSH_PROPTITLE
)
2019 int lentitle
= strlenW(lpszText
);
2020 int lenprop
= strlenW(psInfo
->strPropertiesFor
);
2022 dest
= COMCTL32_Alloc( (lentitle
+ lenprop
+ 1)*sizeof (WCHAR
));
2023 strcpyW(dest
, psInfo
->strPropertiesFor
);
2024 strcatW(dest
, lpszText
);
2026 SetWindowTextW(hwndDlg
, dest
);
2027 COMCTL32_Free(dest
);
2030 SetWindowTextW(hwndDlg
, lpszText
);
2033 /******************************************************************************
2034 * PROPSHEET_SetFinishTextA
2036 static void PROPSHEET_SetFinishTextA(HWND hwndDlg
, LPCSTR lpszText
)
2038 HWND hwndButton
= GetDlgItem(hwndDlg
, IDC_FINISH_BUTTON
);
2040 TRACE("'%s'\n", lpszText
);
2041 /* Set text, show and enable the Finish button */
2042 SetWindowTextA(hwndButton
, lpszText
);
2043 ShowWindow(hwndButton
, SW_SHOW
);
2044 EnableWindow(hwndButton
, TRUE
);
2046 /* Make it default pushbutton */
2047 SendMessageA(hwndDlg
, DM_SETDEFID
, IDC_FINISH_BUTTON
, 0);
2049 /* Hide Back button */
2050 hwndButton
= GetDlgItem(hwndDlg
, IDC_BACK_BUTTON
);
2051 ShowWindow(hwndButton
, SW_HIDE
);
2053 /* Hide Next button */
2054 hwndButton
= GetDlgItem(hwndDlg
, IDC_NEXT_BUTTON
);
2055 ShowWindow(hwndButton
, SW_HIDE
);
2058 /******************************************************************************
2059 * PROPSHEET_SetFinishTextW
2061 static void PROPSHEET_SetFinishTextW(HWND hwndDlg
, LPCWSTR lpszText
)
2063 HWND hwndButton
= GetDlgItem(hwndDlg
, IDC_FINISH_BUTTON
);
2065 TRACE("'%s'\n", debugstr_w(lpszText
));
2066 /* Set text, show and enable the Finish button */
2067 SetWindowTextW(hwndButton
, lpszText
);
2068 ShowWindow(hwndButton
, SW_SHOW
);
2069 EnableWindow(hwndButton
, TRUE
);
2071 /* Make it default pushbutton */
2072 SendMessageW(hwndDlg
, DM_SETDEFID
, IDC_FINISH_BUTTON
, 0);
2074 /* Hide Back button */
2075 hwndButton
= GetDlgItem(hwndDlg
, IDC_BACK_BUTTON
);
2076 ShowWindow(hwndButton
, SW_HIDE
);
2078 /* Hide Next button */
2079 hwndButton
= GetDlgItem(hwndDlg
, IDC_NEXT_BUTTON
);
2080 ShowWindow(hwndButton
, SW_HIDE
);
2083 /******************************************************************************
2084 * PROPSHEET_QuerySiblings
2086 static LRESULT
PROPSHEET_QuerySiblings(HWND hwndDlg
,
2087 WPARAM wParam
, LPARAM lParam
)
2091 LRESULT msgResult
= 0;
2092 PropSheetInfo
* psInfo
= (PropSheetInfo
*) GetPropW(hwndDlg
,
2095 while ((i
< psInfo
->nPages
) && (msgResult
== 0))
2097 hwndPage
= psInfo
->proppage
[i
].hwndPage
;
2098 msgResult
= SendMessageA(hwndPage
, PSM_QUERYSIBLINGS
, wParam
, lParam
);
2106 /******************************************************************************
2109 static BOOL
PROPSHEET_AddPage(HWND hwndDlg
,
2110 HPROPSHEETPAGE hpage
)
2112 PropSheetInfo
* psInfo
= (PropSheetInfo
*) GetPropW(hwndDlg
,
2114 HWND hwndTabControl
= GetDlgItem(hwndDlg
, IDC_TABCONTROL
);
2116 LPCPROPSHEETPAGEW ppsp
= (LPCPROPSHEETPAGEW
)hpage
;
2118 TRACE("hpage %p\n", hpage
);
2120 * Allocate and fill in a new PropPageInfo entry.
2122 psInfo
->proppage
= (PropPageInfo
*) COMCTL32_ReAlloc(psInfo
->proppage
,
2123 sizeof(PropPageInfo
) *
2124 (psInfo
->nPages
+ 1));
2125 if (!PROPSHEET_CollectPageInfo(ppsp
, psInfo
, psInfo
->nPages
))
2128 psInfo
->proppage
[psInfo
->nPages
].hpage
= hpage
;
2130 if (ppsp
->dwFlags
& PSP_PREMATURE
)
2132 /* Create the page but don't show it */
2133 PROPSHEET_CreatePage(hwndDlg
, psInfo
->nPages
, psInfo
, ppsp
);
2137 * Add a new tab to the tab control.
2139 item
.mask
= TCIF_TEXT
;
2140 item
.pszText
= (LPWSTR
) psInfo
->proppage
[psInfo
->nPages
].pszText
;
2141 item
.cchTextMax
= MAX_TABTEXT_LENGTH
;
2143 if (psInfo
->hImageList
)
2145 SendMessageW(hwndTabControl
, TCM_SETIMAGELIST
, 0, (LPARAM
)psInfo
->hImageList
);
2148 if ( psInfo
->proppage
[psInfo
->nPages
].hasIcon
)
2150 item
.mask
|= TCIF_IMAGE
;
2151 item
.iImage
= psInfo
->nPages
;
2154 SendMessageW(hwndTabControl
, TCM_INSERTITEMW
, psInfo
->nPages
+ 1,
2159 /* If it is the only page - show it */
2160 if(psInfo
->nPages
== 1)
2161 PROPSHEET_SetCurSel(hwndDlg
, 0, 1, 0);
2165 /******************************************************************************
2166 * PROPSHEET_RemovePage
2168 static BOOL
PROPSHEET_RemovePage(HWND hwndDlg
,
2170 HPROPSHEETPAGE hpage
)
2172 PropSheetInfo
* psInfo
= (PropSheetInfo
*) GetPropW(hwndDlg
,
2174 HWND hwndTabControl
= GetDlgItem(hwndDlg
, IDC_TABCONTROL
);
2175 PropPageInfo
* oldPages
;
2177 TRACE("index %d, hpage %p\n", index
, hpage
);
2181 oldPages
= psInfo
->proppage
;
2183 * hpage takes precedence over index.
2187 index
= PROPSHEET_GetPageIndex(hpage
, psInfo
);
2190 /* Make sure that index is within range */
2191 if (index
< 0 || index
>= psInfo
->nPages
)
2193 TRACE("Could not find page to remove!\n");
2197 TRACE("total pages %d removing page %d active page %d\n",
2198 psInfo
->nPages
, index
, psInfo
->active_page
);
2200 * Check if we're removing the active page.
2202 if (index
== psInfo
->active_page
)
2204 if (psInfo
->nPages
> 1)
2208 /* activate previous page */
2209 PROPSHEET_SetCurSel(hwndDlg
, index
- 1, -1, 0);
2213 /* activate the next page */
2214 PROPSHEET_SetCurSel(hwndDlg
, index
+ 1, 1, 0);
2215 psInfo
->active_page
= index
;
2220 psInfo
->active_page
= -1;
2221 if (!psInfo
->isModeless
)
2223 EndDialog(hwndDlg
, FALSE
);
2228 else if (index
< psInfo
->active_page
)
2229 psInfo
->active_page
--;
2231 /* Destroy page dialog window */
2232 DestroyWindow(psInfo
->proppage
[index
].hwndPage
);
2234 /* Free page resources */
2235 if(psInfo
->proppage
[index
].hpage
)
2237 PROPSHEETPAGEW
* psp
= (PROPSHEETPAGEW
*)psInfo
->proppage
[index
].hpage
;
2239 if ((psp
->dwFlags
& PSP_USETITLE
) && psInfo
->proppage
[index
].pszText
)
2240 HeapFree(GetProcessHeap(), 0, (LPVOID
)psInfo
->proppage
[index
].pszText
);
2242 DestroyPropertySheetPage(psInfo
->proppage
[index
].hpage
);
2245 /* Remove the tab */
2246 SendMessageW(hwndTabControl
, TCM_DELETEITEM
, index
, 0);
2249 psInfo
->proppage
= COMCTL32_Alloc(sizeof(PropPageInfo
) * psInfo
->nPages
);
2252 memcpy(&psInfo
->proppage
[0], &oldPages
[0], index
* sizeof(PropPageInfo
));
2254 if (index
< psInfo
->nPages
)
2255 memcpy(&psInfo
->proppage
[index
], &oldPages
[index
+ 1],
2256 (psInfo
->nPages
- index
) * sizeof(PropPageInfo
));
2258 COMCTL32_Free(oldPages
);
2263 /******************************************************************************
2264 * PROPSHEET_SetWizButtons
2266 * This code will work if (and assumes that) the Next button is on top of the
2267 * Finish button. ie. Finish comes after Next in the Z order.
2268 * This means make sure the dialog template reflects this.
2271 static void PROPSHEET_SetWizButtons(HWND hwndDlg
, DWORD dwFlags
)
2273 HWND hwndBack
= GetDlgItem(hwndDlg
, IDC_BACK_BUTTON
);
2274 HWND hwndNext
= GetDlgItem(hwndDlg
, IDC_NEXT_BUTTON
);
2275 HWND hwndFinish
= GetDlgItem(hwndDlg
, IDC_FINISH_BUTTON
);
2277 TRACE("%ld\n", dwFlags
);
2279 EnableWindow(hwndBack
, FALSE
);
2280 EnableWindow(hwndNext
, FALSE
);
2281 EnableWindow(hwndFinish
, FALSE
);
2283 if (dwFlags
& PSWIZB_BACK
)
2284 EnableWindow(hwndBack
, TRUE
);
2286 if (dwFlags
& PSWIZB_NEXT
)
2288 /* Hide the Finish button */
2289 ShowWindow(hwndFinish
, SW_HIDE
);
2291 /* Show and enable the Next button */
2292 ShowWindow(hwndNext
, SW_SHOW
);
2293 EnableWindow(hwndNext
, TRUE
);
2295 /* Set the Next button as the default pushbutton */
2296 SendMessageA(hwndDlg
, DM_SETDEFID
, IDC_NEXT_BUTTON
, 0);
2299 if ((dwFlags
& PSWIZB_FINISH
) || (dwFlags
& PSWIZB_DISABLEDFINISH
))
2301 /* Hide the Next button */
2302 ShowWindow(hwndNext
, SW_HIDE
);
2304 /* Show the Finish button */
2305 ShowWindow(hwndFinish
, SW_SHOW
);
2307 if (dwFlags
& PSWIZB_FINISH
)
2308 EnableWindow(hwndFinish
, TRUE
);
2310 /* Set the Finish button as the default pushbutton */
2311 SendMessageA(hwndDlg
, DM_SETDEFID
, IDC_FINISH_BUTTON
, 0);
2315 /******************************************************************************
2316 * PROPSHEET_GetPageIndex
2318 * Given a HPROPSHEETPAGE, returns the index of the corresponding page from
2319 * the array of PropPageInfo.
2321 static int PROPSHEET_GetPageIndex(HPROPSHEETPAGE hpage
, PropSheetInfo
* psInfo
)
2326 TRACE("hpage %p\n", hpage
);
2327 while ((index
< psInfo
->nPages
) && (found
== FALSE
))
2329 if (psInfo
->proppage
[index
].hpage
== hpage
)
2341 /******************************************************************************
2344 static void PROPSHEET_CleanUp(HWND hwndDlg
)
2347 PropSheetInfo
* psInfo
= (PropSheetInfo
*) RemovePropW(hwndDlg
,
2351 if (!psInfo
) return;
2352 if (HIWORD(psInfo
->ppshheader
.pszCaption
))
2353 HeapFree(GetProcessHeap(), 0, (LPVOID
)psInfo
->ppshheader
.pszCaption
);
2355 for (i
= 0; i
< psInfo
->nPages
; i
++)
2357 PROPSHEETPAGEA
* psp
= (PROPSHEETPAGEA
*)psInfo
->proppage
[i
].hpage
;
2359 if(psInfo
->proppage
[i
].hwndPage
)
2360 DestroyWindow(psInfo
->proppage
[i
].hwndPage
);
2364 if ((psp
->dwFlags
& PSP_USETITLE
) && psInfo
->proppage
[i
].pszText
)
2365 HeapFree(GetProcessHeap(), 0, (LPVOID
)psInfo
->proppage
[i
].pszText
);
2367 DestroyPropertySheetPage(psInfo
->proppage
[i
].hpage
);
2371 COMCTL32_Free(psInfo
->proppage
);
2372 COMCTL32_Free(psInfo
->strPropertiesFor
);
2373 ImageList_Destroy(psInfo
->hImageList
);
2375 GlobalFree((HGLOBAL
)psInfo
);
2378 /******************************************************************************
2379 * PropertySheet (COMCTL32.@)
2380 * PropertySheetA (COMCTL32.@)
2382 INT WINAPI
PropertySheetA(LPCPROPSHEETHEADERA lppsh
)
2385 PropSheetInfo
* psInfo
= (PropSheetInfo
*) GlobalAlloc(GPTR
,
2386 sizeof(PropSheetInfo
));
2390 TRACE("(%p)\n", lppsh
);
2392 PROPSHEET_CollectSheetInfoA(lppsh
, psInfo
);
2394 psInfo
->proppage
= (PropPageInfo
*) COMCTL32_Alloc(sizeof(PropPageInfo
) *
2396 pByte
= (BYTE
*) psInfo
->ppshheader
.u3
.ppsp
;
2398 for (n
= i
= 0; i
< lppsh
->nPages
; i
++, n
++)
2400 if (!(lppsh
->dwFlags
& PSH_PROPSHEETPAGE
))
2401 psInfo
->proppage
[n
].hpage
= psInfo
->ppshheader
.u3
.phpage
[i
];
2404 psInfo
->proppage
[n
].hpage
= CreatePropertySheetPageA((LPCPROPSHEETPAGEA
)pByte
);
2405 pByte
+= ((LPPROPSHEETPAGEA
)pByte
)->dwSize
;
2408 if (!PROPSHEET_CollectPageInfo((LPCPROPSHEETPAGEW
)psInfo
->proppage
[n
].hpage
,
2411 if (lppsh
->dwFlags
& PSH_PROPSHEETPAGE
)
2412 DestroyPropertySheetPage(psInfo
->proppage
[n
].hpage
);
2418 bRet
= PROPSHEET_CreateDialog(psInfo
);
2423 /******************************************************************************
2424 * PropertySheetW (COMCTL32.@)
2426 INT WINAPI
PropertySheetW(LPCPROPSHEETHEADERW lppsh
)
2429 PropSheetInfo
* psInfo
= (PropSheetInfo
*) GlobalAlloc(GPTR
,
2430 sizeof(PropSheetInfo
));
2434 TRACE("(%p)\n", lppsh
);
2436 PROPSHEET_CollectSheetInfoW(lppsh
, psInfo
);
2438 psInfo
->proppage
= (PropPageInfo
*) COMCTL32_Alloc(sizeof(PropPageInfo
) *
2440 pByte
= (BYTE
*) psInfo
->ppshheader
.u3
.ppsp
;
2442 for (n
= i
= 0; i
< lppsh
->nPages
; i
++, n
++)
2444 if (!(lppsh
->dwFlags
& PSH_PROPSHEETPAGE
))
2445 psInfo
->proppage
[n
].hpage
= psInfo
->ppshheader
.u3
.phpage
[i
];
2448 psInfo
->proppage
[n
].hpage
= CreatePropertySheetPageW((LPCPROPSHEETPAGEW
)pByte
);
2449 pByte
+= ((LPPROPSHEETPAGEW
)pByte
)->dwSize
;
2452 if (!PROPSHEET_CollectPageInfo((LPCPROPSHEETPAGEW
)psInfo
->proppage
[n
].hpage
,
2455 if (lppsh
->dwFlags
& PSH_PROPSHEETPAGE
)
2456 DestroyPropertySheetPage(psInfo
->proppage
[n
].hpage
);
2462 bRet
= PROPSHEET_CreateDialog(psInfo
);
2467 /******************************************************************************
2468 * CreatePropertySheetPage (COMCTL32.@)
2469 * CreatePropertySheetPageA (COMCTL32.@)
2471 HPROPSHEETPAGE WINAPI
CreatePropertySheetPageA(
2472 LPCPROPSHEETPAGEA lpPropSheetPage
)
2474 PROPSHEETPAGEW
* ppsp
= COMCTL32_Alloc(sizeof(PROPSHEETPAGEW
));
2476 memcpy(ppsp
,lpPropSheetPage
,min(lpPropSheetPage
->dwSize
,sizeof(PROPSHEETPAGEA
)));
2478 if ( !(ppsp
->dwFlags
& PSP_DLGINDIRECT
) && HIWORD( ppsp
->u
.pszTemplate
) )
2480 PROPSHEET_AtoW(&ppsp
->u
.pszTemplate
, lpPropSheetPage
->u
.pszTemplate
);
2482 if ( (ppsp
->dwFlags
& PSP_USEICONID
) && HIWORD( ppsp
->u2
.pszIcon
) )
2484 PROPSHEET_AtoW(&ppsp
->u2
.pszIcon
, lpPropSheetPage
->u2
.pszIcon
);
2487 if ((ppsp
->dwFlags
& PSP_USETITLE
) && HIWORD( ppsp
->pszTitle
))
2489 PROPSHEET_AtoW(&ppsp
->pszTitle
, lpPropSheetPage
->pszTitle
);
2491 else if ( !(ppsp
->dwFlags
& PSP_USETITLE
) )
2492 ppsp
->pszTitle
= NULL
;
2494 return (HPROPSHEETPAGE
)ppsp
;
2497 /******************************************************************************
2498 * CreatePropertySheetPageW (COMCTL32.@)
2500 HPROPSHEETPAGE WINAPI
CreatePropertySheetPageW(LPCPROPSHEETPAGEW lpPropSheetPage
)
2502 PROPSHEETPAGEW
* ppsp
= COMCTL32_Alloc(sizeof(PROPSHEETPAGEW
));
2504 memcpy(ppsp
,lpPropSheetPage
,min(lpPropSheetPage
->dwSize
,sizeof(PROPSHEETPAGEW
)));
2506 if ( !(ppsp
->dwFlags
& PSP_DLGINDIRECT
) && HIWORD( ppsp
->u
.pszTemplate
) )
2508 int len
= strlenW(lpPropSheetPage
->u
.pszTemplate
);
2510 ppsp
->u
.pszTemplate
= HeapAlloc( GetProcessHeap(),0,(len
+1)*sizeof (WCHAR
) );
2511 strcpyW( (WCHAR
*)ppsp
->u
.pszTemplate
, lpPropSheetPage
->u
.pszTemplate
);
2513 if ( (ppsp
->dwFlags
& PSP_USEICONID
) && HIWORD( ppsp
->u2
.pszIcon
) )
2515 int len
= strlenW(lpPropSheetPage
->u2
.pszIcon
);
2516 ppsp
->u2
.pszIcon
= HeapAlloc( GetProcessHeap(), 0, (len
+1)*sizeof (WCHAR
) );
2517 strcpyW( (WCHAR
*)ppsp
->u2
.pszIcon
, lpPropSheetPage
->u2
.pszIcon
);
2520 if ((ppsp
->dwFlags
& PSP_USETITLE
) && HIWORD( ppsp
->pszTitle
))
2522 int len
= strlenW(lpPropSheetPage
->pszTitle
);
2523 ppsp
->pszTitle
= HeapAlloc( GetProcessHeap(), 0, (len
+1)*sizeof (WCHAR
) );
2524 strcpyW( (WCHAR
*)ppsp
->pszTitle
, lpPropSheetPage
->pszTitle
);
2526 else if ( !(ppsp
->dwFlags
& PSP_USETITLE
) )
2527 ppsp
->pszTitle
= NULL
;
2529 return (HPROPSHEETPAGE
)ppsp
;
2532 /******************************************************************************
2533 * DestroyPropertySheetPage (COMCTL32.@)
2535 BOOL WINAPI
DestroyPropertySheetPage(HPROPSHEETPAGE hPropPage
)
2537 PROPSHEETPAGEW
*psp
= (PROPSHEETPAGEW
*)hPropPage
;
2542 if ( !(psp
->dwFlags
& PSP_DLGINDIRECT
) && HIWORD( psp
->u
.pszTemplate
) )
2543 HeapFree(GetProcessHeap(), 0, (LPVOID
)psp
->u
.pszTemplate
);
2545 if ( (psp
->dwFlags
& PSP_USEICONID
) && HIWORD( psp
->u2
.pszIcon
) )
2546 HeapFree(GetProcessHeap(), 0, (LPVOID
)psp
->u2
.pszIcon
);
2548 if ((psp
->dwFlags
& PSP_USETITLE
) && HIWORD( psp
->pszTitle
))
2549 HeapFree(GetProcessHeap(), 0, (LPVOID
)psp
->pszTitle
);
2551 COMCTL32_Free(hPropPage
);
2556 /******************************************************************************
2557 * PROPSHEET_IsDialogMessage
2559 static BOOL
PROPSHEET_IsDialogMessage(HWND hwnd
, LPMSG lpMsg
)
2561 PropSheetInfo
* psInfo
= (PropSheetInfo
*) GetPropW(hwnd
, PropSheetInfoStr
);
2564 if (!psInfo
|| (hwnd
!= lpMsg
->hwnd
&& !IsChild(hwnd
, lpMsg
->hwnd
)))
2567 if (lpMsg
->message
== WM_KEYDOWN
&& (GetKeyState(VK_CONTROL
) & 0x8000))
2570 INT dlgCode
= SendMessageA(lpMsg
->hwnd
, WM_GETDLGCODE
, 0, (LPARAM
)lpMsg
);
2572 if (!(dlgCode
& DLGC_WANTMESSAGE
))
2574 switch (lpMsg
->wParam
)
2577 if (GetKeyState(VK_SHIFT
) & 0x8000)
2583 case VK_NEXT
: new_page
= 1; break;
2584 case VK_PRIOR
: new_page
= -1; break;
2590 if (PROPSHEET_CanSetCurSel(hwnd
) != FALSE
)
2592 new_page
+= psInfo
->active_page
;
2595 new_page
= psInfo
->nPages
- 1;
2596 else if (new_page
>= psInfo
->nPages
)
2599 PROPSHEET_SetCurSel(hwnd
, new_page
, 1, 0);
2606 return IsDialogMessageA(hwnd
, lpMsg
);
2609 /******************************************************************************
2610 * PROPSHEET_DoCommand
2612 static BOOL
PROPSHEET_DoCommand(HWND hwnd
, WORD wID
)
2618 case IDC_APPLY_BUTTON
:
2620 HWND hwndApplyBtn
= GetDlgItem(hwnd
, IDC_APPLY_BUTTON
);
2622 if (PROPSHEET_Apply(hwnd
, wID
== IDOK
? 1: 0) == FALSE
)
2627 PropSheetInfo
* psInfo
= (PropSheetInfo
*) GetPropW(hwnd
,
2631 if (psInfo
->restartWindows
)
2632 result
= ID_PSRESTARTWINDOWS
;
2634 /* reboot system takes precedence over restart windows */
2635 if (psInfo
->rebootSystem
)
2636 result
= ID_PSREBOOTSYSTEM
;
2638 if (psInfo
->isModeless
)
2639 psInfo
->activeValid
= FALSE
;
2641 EndDialog(hwnd
, result
);
2644 EnableWindow(hwndApplyBtn
, FALSE
);
2649 case IDC_BACK_BUTTON
:
2650 PROPSHEET_Back(hwnd
);
2653 case IDC_NEXT_BUTTON
:
2654 PROPSHEET_Next(hwnd
);
2657 case IDC_FINISH_BUTTON
:
2658 PROPSHEET_Finish(hwnd
);
2662 PROPSHEET_Cancel(hwnd
, 0);
2666 PROPSHEET_Help(hwnd
);
2673 /******************************************************************************
2674 * PROPSHEET_DialogProc
2677 PROPSHEET_DialogProc(HWND hwnd
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
)
2679 TRACE("hwnd=%p msg=0x%04x wparam=%x lparam=%lx\n",
2680 hwnd
, uMsg
, wParam
, lParam
);
2686 PropSheetInfo
* psInfo
= (PropSheetInfo
*) lParam
;
2687 WCHAR
* strCaption
= (WCHAR
*)COMCTL32_Alloc(MAX_CAPTION_LENGTH
*sizeof(WCHAR
));
2688 HWND hwndTabCtrl
= GetDlgItem(hwnd
, IDC_TABCONTROL
);
2689 LPCPROPSHEETPAGEW ppshpage
;
2692 SetPropW(hwnd
, PropSheetInfoStr
, (HANDLE
)psInfo
);
2695 * psInfo->hwnd is not being used by WINE code - it exists
2696 * for compatibility with "real" Windoze. The same about
2697 * SetWindowLong - WINE is only using the PropSheetInfoStr
2700 psInfo
->hwnd
= hwnd
;
2701 SetWindowLongW(hwnd
,DWL_USER
,(LONG
)psInfo
);
2704 * Small icon in the title bar.
2706 if ((psInfo
->ppshheader
.dwFlags
& PSH_USEICONID
) ||
2707 (psInfo
->ppshheader
.dwFlags
& PSH_USEHICON
))
2710 int icon_cx
= GetSystemMetrics(SM_CXSMICON
);
2711 int icon_cy
= GetSystemMetrics(SM_CYSMICON
);
2713 if (psInfo
->ppshheader
.dwFlags
& PSH_USEICONID
)
2714 hIcon
= LoadImageW(psInfo
->ppshheader
.hInstance
,
2715 psInfo
->ppshheader
.u
.pszIcon
,
2720 hIcon
= psInfo
->ppshheader
.u
.hIcon
;
2722 SendMessageW(hwnd
, WM_SETICON
, 0, (LPARAM
)hIcon
);
2725 if (psInfo
->ppshheader
.dwFlags
& PSH_USEHICON
)
2726 SendMessageW(hwnd
, WM_SETICON
, 0, (LPARAM
)psInfo
->ppshheader
.u
.hIcon
);
2728 psInfo
->strPropertiesFor
= strCaption
;
2730 GetWindowTextW(hwnd
, psInfo
->strPropertiesFor
, MAX_CAPTION_LENGTH
);
2732 PROPSHEET_CreateTabControl(hwnd
, psInfo
);
2734 if (psInfo
->ppshheader
.dwFlags
& INTRNL_ANY_WIZARD
)
2736 if (PROPSHEET_IsTooSmallWizard(hwnd
, psInfo
))
2738 PROPSHEET_AdjustSizeWizard(hwnd
, psInfo
);
2739 PROPSHEET_AdjustButtonsWizard(hwnd
, psInfo
);
2744 if (PROPSHEET_SizeMismatch(hwnd
, psInfo
))
2746 PROPSHEET_AdjustSize(hwnd
, psInfo
);
2747 PROPSHEET_AdjustButtons(hwnd
, psInfo
);
2751 if (psInfo
->useCallback
)
2752 (*(psInfo
->ppshheader
.pfnCallback
))(hwnd
,
2753 PSCB_INITIALIZED
, (LPARAM
)0);
2755 idx
= psInfo
->active_page
;
2756 ppshpage
= (LPCPROPSHEETPAGEW
)psInfo
->proppage
[idx
].hpage
;
2757 psInfo
->active_page
= -1;
2759 PROPSHEET_SetCurSel(hwnd
, idx
, 1, psInfo
->proppage
[idx
].hpage
);
2761 /* doing TCM_SETCURSEL seems to be needed even in case of PSH_WIZARD,
2762 * as some programs call TCM_GETCURSEL to get the current selection
2763 * from which to switch to the next page */
2764 SendMessageW(hwndTabCtrl
, TCM_SETCURSEL
, psInfo
->active_page
, 0);
2766 if (!HIWORD(psInfo
->ppshheader
.pszCaption
) &&
2767 psInfo
->ppshheader
.hInstance
)
2771 if (LoadStringW(psInfo
->ppshheader
.hInstance
,
2772 (UINT
)psInfo
->ppshheader
.pszCaption
, szText
, 255))
2773 PROPSHEET_SetTitleW(hwnd
, psInfo
->ppshheader
.dwFlags
, szText
);
2777 PROPSHEET_SetTitleW(hwnd
, psInfo
->ppshheader
.dwFlags
,
2778 psInfo
->ppshheader
.pszCaption
);
2785 PROPSHEET_CleanUp(hwnd
);
2789 PROPSHEET_Cancel(hwnd
, 1);
2793 return PROPSHEET_DoCommand(hwnd
, LOWORD(wParam
));
2797 NMHDR
* pnmh
= (LPNMHDR
) lParam
;
2799 if (pnmh
->code
== TCN_SELCHANGE
)
2801 int index
= SendMessageW(pnmh
->hwndFrom
, TCM_GETCURSEL
, 0, 0);
2802 PROPSHEET_SetCurSel(hwnd
, index
, 1, 0);
2805 if(pnmh
->code
== TCN_SELCHANGING
)
2807 BOOL bRet
= PROPSHEET_CanSetCurSel(hwnd
);
2808 SetWindowLongW(hwnd
, DWL_MSGRESULT
, !bRet
);
2815 case PSM_GETCURRENTPAGEHWND
:
2817 PropSheetInfo
* psInfo
= (PropSheetInfo
*) GetPropW(hwnd
,
2821 if (psInfo
->activeValid
&& psInfo
->active_page
!= -1)
2822 hwndPage
= psInfo
->proppage
[psInfo
->active_page
].hwndPage
;
2824 SetWindowLongW(hwnd
, DWL_MSGRESULT
, (LONG
)hwndPage
);
2830 PROPSHEET_Changed(hwnd
, (HWND
)wParam
);
2834 PROPSHEET_UnChanged(hwnd
, (HWND
)wParam
);
2837 case PSM_GETTABCONTROL
:
2839 HWND hwndTabCtrl
= GetDlgItem(hwnd
, IDC_TABCONTROL
);
2841 SetWindowLongW(hwnd
, DWL_MSGRESULT
, (LONG
)hwndTabCtrl
);
2850 msgResult
= PROPSHEET_CanSetCurSel(hwnd
);
2851 if(msgResult
!= FALSE
)
2853 msgResult
= PROPSHEET_SetCurSel(hwnd
,
2856 (HPROPSHEETPAGE
)lParam
);
2859 SetWindowLongW(hwnd
, DWL_MSGRESULT
, msgResult
);
2864 case PSM_CANCELTOCLOSE
:
2866 WCHAR buf
[MAX_BUTTONTEXT_LENGTH
];
2867 HWND hwndOK
= GetDlgItem(hwnd
, IDOK
);
2868 HWND hwndCancel
= GetDlgItem(hwnd
, IDCANCEL
);
2870 EnableWindow(hwndCancel
, FALSE
);
2871 if (LoadStringW(COMCTL32_hModule
, IDS_CLOSE
, buf
, sizeof(buf
)))
2872 SetWindowTextW(hwndOK
, buf
);
2877 case PSM_RESTARTWINDOWS
:
2879 PropSheetInfo
* psInfo
= (PropSheetInfo
*) GetPropW(hwnd
,
2882 psInfo
->restartWindows
= TRUE
;
2886 case PSM_REBOOTSYSTEM
:
2888 PropSheetInfo
* psInfo
= (PropSheetInfo
*) GetPropW(hwnd
,
2891 psInfo
->rebootSystem
= TRUE
;
2896 PROPSHEET_SetTitleA(hwnd
, (DWORD
) wParam
, (LPCSTR
) lParam
);
2900 PROPSHEET_SetTitleW(hwnd
, (DWORD
) wParam
, (LPCWSTR
) lParam
);
2905 BOOL msgResult
= PROPSHEET_Apply(hwnd
, 0);
2907 SetWindowLongW(hwnd
, DWL_MSGRESULT
, msgResult
);
2912 case PSM_QUERYSIBLINGS
:
2914 LRESULT msgResult
= PROPSHEET_QuerySiblings(hwnd
, wParam
, lParam
);
2916 SetWindowLongW(hwnd
, DWL_MSGRESULT
, msgResult
);
2924 * Note: MSVC++ 6.0 documentation says that PSM_ADDPAGE does not have
2925 * a return value. This is not true. PSM_ADDPAGE returns TRUE
2926 * on success or FALSE otherwise, as specified on MSDN Online.
2927 * Also see the MFC code for
2928 * CPropertySheet::AddPage(CPropertyPage* pPage).
2931 BOOL msgResult
= PROPSHEET_AddPage(hwnd
, (HPROPSHEETPAGE
)lParam
);
2933 SetWindowLongW(hwnd
, DWL_MSGRESULT
, msgResult
);
2938 case PSM_REMOVEPAGE
:
2939 PROPSHEET_RemovePage(hwnd
, (int)wParam
, (HPROPSHEETPAGE
)lParam
);
2942 case PSM_ISDIALOGMESSAGE
:
2944 BOOL msgResult
= PROPSHEET_IsDialogMessage(hwnd
, (LPMSG
)lParam
);
2945 SetWindowLongA(hwnd
, DWL_MSGRESULT
, msgResult
);
2949 case PSM_PRESSBUTTON
:
2950 PROPSHEET_PressButton(hwnd
, (int)wParam
);
2953 case PSM_SETFINISHTEXTA
:
2954 PROPSHEET_SetFinishTextA(hwnd
, (LPCSTR
) lParam
);
2957 case PSM_SETWIZBUTTONS
:
2958 PROPSHEET_SetWizButtons(hwnd
, (DWORD
)lParam
);
2961 case PSM_SETCURSELID
:
2962 PROPSHEET_SetCurSelId(hwnd
, (int)lParam
);
2965 case PSM_SETFINISHTEXTW
:
2966 PROPSHEET_SetFinishTextW(hwnd
, (LPCWSTR
) lParam
);