4 * Copyright 1998 Francis Beaudet
5 * Copyright 1999 Thuy Nguyen
6 * Copyright 2004 Maxime Bellenge
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 * - Unicode property sheets
30 #define NONAMELESSUNION
31 #define NONAMELESSSTRUCT
41 #include "wine/debug.h"
42 #include "wine/unicode.h"
44 /******************************************************************************
68 } MyDLGITEMTEMPLATEEX
;
71 typedef struct tagPropPageInfo
73 HPROPSHEETPAGE hpage
; /* to keep track of pages not passed to PropertySheet */
82 typedef struct tagPropSheetInfo
85 PROPSHEETHEADERW ppshheader
;
87 LPWSTR strPropertiesFor
;
97 PropPageInfo
* proppage
;
104 HIMAGELIST hImageList
;
113 /******************************************************************************
114 * Defines and global variables
117 const WCHAR PropSheetInfoStr
[] =
118 {'P','r','o','p','e','r','t','y','S','h','e','e','t','I','n','f','o',0 };
120 #define PSP_INTERNAL_UNICODE 0x80000000
122 #define MAX_CAPTION_LENGTH 255
123 #define MAX_TABTEXT_LENGTH 255
124 #define MAX_BUTTONTEXT_LENGTH 64
126 #define INTRNL_ANY_WIZARD (PSH_WIZARD | PSH_WIZARD97_OLD | PSH_WIZARD97_NEW | PSH_WIZARD_LITE)
128 /******************************************************************************
131 static int PROPSHEET_CreateDialog(PropSheetInfo
* psInfo
);
132 static BOOL
PROPSHEET_SizeMismatch(HWND hwndDlg
, PropSheetInfo
* psInfo
);
133 static BOOL
PROPSHEET_AdjustSize(HWND hwndDlg
, PropSheetInfo
* psInfo
);
134 static BOOL
PROPSHEET_AdjustButtons(HWND hwndParent
, PropSheetInfo
* psInfo
);
135 static BOOL
PROPSHEET_CollectSheetInfoA(LPCPROPSHEETHEADERA lppsh
,
136 PropSheetInfo
* psInfo
);
137 static BOOL
PROPSHEET_CollectSheetInfoW(LPCPROPSHEETHEADERW lppsh
,
138 PropSheetInfo
* psInfo
);
139 static BOOL
PROPSHEET_CollectPageInfo(LPCPROPSHEETPAGEW lppsp
,
140 PropSheetInfo
* psInfo
,
142 static BOOL
PROPSHEET_CreateTabControl(HWND hwndParent
,
143 PropSheetInfo
* psInfo
);
144 static BOOL
PROPSHEET_CreatePage(HWND hwndParent
, int index
,
145 const PropSheetInfo
* psInfo
,
146 LPCPROPSHEETPAGEW ppshpage
);
147 static BOOL
PROPSHEET_ShowPage(HWND hwndDlg
, int index
, PropSheetInfo
* psInfo
);
148 static PADDING_INFO
PROPSHEET_GetPaddingInfo(HWND hwndDlg
);
149 static BOOL
PROPSHEET_Back(HWND hwndDlg
);
150 static BOOL
PROPSHEET_Next(HWND hwndDlg
);
151 static BOOL
PROPSHEET_Finish(HWND hwndDlg
);
152 static BOOL
PROPSHEET_Apply(HWND hwndDlg
, LPARAM lParam
);
153 static void PROPSHEET_Cancel(HWND hwndDlg
, LPARAM lParam
);
154 static void PROPSHEET_Help(HWND hwndDlg
);
155 static void PROPSHEET_Changed(HWND hwndDlg
, HWND hwndDirtyPage
);
156 static void PROPSHEET_UnChanged(HWND hwndDlg
, HWND hwndCleanPage
);
157 static void PROPSHEET_PressButton(HWND hwndDlg
, int buttonID
);
158 static void PROPSHEET_SetFinishTextA(HWND hwndDlg
, LPCSTR lpszText
);
159 static void PROPSHEET_SetFinishTextW(HWND hwndDlg
, LPCWSTR lpszText
);
160 static void PROPSHEET_SetTitleA(HWND hwndDlg
, DWORD dwStyle
, LPCSTR lpszText
);
161 static void PROPSHEET_SetTitleW(HWND hwndDlg
, DWORD dwStyle
, LPCWSTR lpszText
);
162 static BOOL
PROPSHEET_CanSetCurSel(HWND hwndDlg
);
163 static BOOL
PROPSHEET_SetCurSel(HWND hwndDlg
,
166 HPROPSHEETPAGE hpage
);
167 static void PROPSHEET_SetCurSelId(HWND hwndDlg
, int id
);
168 static LRESULT
PROPSHEET_QuerySiblings(HWND hwndDlg
,
169 WPARAM wParam
, LPARAM lParam
);
170 static BOOL
PROPSHEET_AddPage(HWND hwndDlg
,
171 HPROPSHEETPAGE hpage
);
173 static BOOL
PROPSHEET_RemovePage(HWND hwndDlg
,
175 HPROPSHEETPAGE hpage
);
176 static void PROPSHEET_CleanUp(HWND hwndDlg
);
177 static int PROPSHEET_GetPageIndex(HPROPSHEETPAGE hpage
, PropSheetInfo
* psInfo
);
178 static void PROPSHEET_SetWizButtons(HWND hwndDlg
, DWORD dwFlags
);
179 static PADDING_INFO
PROPSHEET_GetPaddingInfoWizard(HWND hwndDlg
, const PropSheetInfo
* psInfo
);
180 static BOOL
PROPSHEET_IsDialogMessage(HWND hwnd
, LPMSG lpMsg
);
181 static BOOL
PROPSHEET_DoCommand(HWND hwnd
, WORD wID
);
184 PROPSHEET_DialogProc(HWND hwnd
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
);
186 WINE_DEFAULT_DEBUG_CHANNEL(propsheet
);
188 #define add_flag(a) if (dwFlags & a) {strcat(string, #a );strcat(string," ");}
189 /******************************************************************************
190 * PROPSHEET_UnImplementedFlags
192 * Document use of flags we don't implement yet.
194 static VOID
PROPSHEET_UnImplementedFlags(DWORD dwFlags
)
201 * unhandled header flags:
202 * PSH_DEFAULT 0x00000000
203 * PSH_WIZARDHASFINISH 0x00000010
204 * PSH_RTLREADING 0x00000800
205 * PSH_WIZARDCONTEXTHELP 0x00001000
206 * PSH_WIZARD97 0x00002000 (pre IE 5)
207 * PSH_WATERMARK 0x00008000
208 * PSH_USEHBMWATERMARK 0x00010000
209 * PSH_USEHPLWATERMARK 0x00020000
210 * PSH_STRETCHWATERMARK 0x00040000
211 * PSH_HEADER 0x00080000
212 * PSH_USEHBMHEADER 0x00100000
213 * PSH_USEPAGELANG 0x00200000
214 * PSH_WIZARD_LITE 0x00400000 also not in .h
215 * PSH_WIZARD97 0x01000000 (IE 5 and above)
216 * PSH_NOCONTEXTHELP 0x02000000 also not in .h
219 add_flag(PSH_WIZARDHASFINISH
);
220 add_flag(PSH_RTLREADING
);
221 add_flag(PSH_WIZARDCONTEXTHELP
);
222 add_flag(PSH_WIZARD97_OLD
);
223 add_flag(PSH_STRETCHWATERMARK
);
224 add_flag(PSH_USEPAGELANG
);
225 add_flag(PSH_WIZARD_LITE
);
226 add_flag(PSH_NOCONTEXTHELP
);
227 if (string
[0] != '\0')
228 FIXME("%s\n", string
);
232 /******************************************************************************
233 * PROPSHEET_GetPageRect
235 * Retrieve rect from tab control and map into the dialog for SetWindowPos
237 static void PROPSHEET_GetPageRect(const PropSheetInfo
* psInfo
, HWND hwndDlg
, RECT
*rc
)
239 HWND hwndTabCtrl
= GetDlgItem(hwndDlg
, IDC_TABCONTROL
);
241 GetClientRect(hwndTabCtrl
, rc
);
242 SendMessageW(hwndTabCtrl
, TCM_ADJUSTRECT
, FALSE
, (LPARAM
)rc
);
243 MapWindowPoints(hwndTabCtrl
, hwndDlg
, (LPPOINT
)rc
, 2);
246 /******************************************************************************
247 * PROPSHEET_FindPageByResId
249 * Find page index corresponding to page resource id.
251 INT
PROPSHEET_FindPageByResId(PropSheetInfo
* psInfo
, LRESULT resId
)
255 for (i
= 0; i
< psInfo
->nPages
; i
++)
257 LPCPROPSHEETPAGEA lppsp
= (LPCPROPSHEETPAGEA
)psInfo
->proppage
[i
].hpage
;
259 /* Fixme: if resource ID is a string shall we use strcmp ??? */
260 if (lppsp
->u
.pszTemplate
== (LPVOID
)resId
)
267 /******************************************************************************
270 * Convert ASCII to Unicode since all data is saved as Unicode.
272 static void PROPSHEET_AtoW(LPCWSTR
*tostr
, LPCSTR frstr
)
276 TRACE("<%s>\n", frstr
);
277 len
= MultiByteToWideChar(CP_ACP
, 0, frstr
, -1, 0, 0);
278 *tostr
= (LPWSTR
)HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
279 MultiByteToWideChar(CP_ACP
, 0, frstr
, -1, (LPWSTR
)*tostr
, len
);
282 /******************************************************************************
283 * PROPSHEET_CollectSheetInfoA
285 * Collect relevant data.
287 static BOOL
PROPSHEET_CollectSheetInfoA(LPCPROPSHEETHEADERA lppsh
,
288 PropSheetInfo
* psInfo
)
290 DWORD dwSize
= min(lppsh
->dwSize
,sizeof(PROPSHEETHEADERA
));
291 DWORD dwFlags
= lppsh
->dwFlags
;
293 psInfo
->hasHelp
= dwFlags
& PSH_HASHELP
;
294 psInfo
->hasApply
= !(dwFlags
& PSH_NOAPPLYNOW
);
295 psInfo
->useCallback
= (dwFlags
& PSH_USECALLBACK
)&& (lppsh
->pfnCallback
);
296 psInfo
->isModeless
= dwFlags
& PSH_MODELESS
;
298 memcpy(&psInfo
->ppshheader
,lppsh
,dwSize
);
299 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",
300 lppsh
->dwSize
, lppsh
->dwFlags
, lppsh
->hwndParent
, lppsh
->hInstance
,
301 debugstr_a(lppsh
->pszCaption
), lppsh
->nPages
, lppsh
->pfnCallback
);
303 PROPSHEET_UnImplementedFlags(lppsh
->dwFlags
);
305 if (lppsh
->dwFlags
& INTRNL_ANY_WIZARD
)
306 psInfo
->ppshheader
.pszCaption
= NULL
;
309 if (HIWORD(lppsh
->pszCaption
))
311 int len
= MultiByteToWideChar(CP_ACP
, 0, lppsh
->pszCaption
, -1, NULL
, 0);
312 psInfo
->ppshheader
.pszCaption
= HeapAlloc( GetProcessHeap(), 0, len
*sizeof (WCHAR
) );
313 MultiByteToWideChar(CP_ACP
, 0, lppsh
->pszCaption
, -1, (LPWSTR
) psInfo
->ppshheader
.pszCaption
, len
);
316 psInfo
->nPages
= lppsh
->nPages
;
318 if (dwFlags
& PSH_USEPSTARTPAGE
)
320 TRACE("PSH_USEPSTARTPAGE is on\n");
321 psInfo
->active_page
= 0;
324 psInfo
->active_page
= lppsh
->u2
.nStartPage
;
326 if (psInfo
->active_page
< 0 || psInfo
->active_page
>= psInfo
->nPages
)
327 psInfo
->active_page
= 0;
329 psInfo
->restartWindows
= FALSE
;
330 psInfo
->rebootSystem
= FALSE
;
331 psInfo
->hImageList
= 0;
332 psInfo
->activeValid
= FALSE
;
337 /******************************************************************************
338 * PROPSHEET_CollectSheetInfoW
340 * Collect relevant data.
342 static BOOL
PROPSHEET_CollectSheetInfoW(LPCPROPSHEETHEADERW lppsh
,
343 PropSheetInfo
* psInfo
)
345 DWORD dwSize
= min(lppsh
->dwSize
,sizeof(PROPSHEETHEADERW
));
346 DWORD dwFlags
= lppsh
->dwFlags
;
348 psInfo
->hasHelp
= dwFlags
& PSH_HASHELP
;
349 psInfo
->hasApply
= !(dwFlags
& PSH_NOAPPLYNOW
);
350 psInfo
->useCallback
= (dwFlags
& PSH_USECALLBACK
) && (lppsh
->pfnCallback
);
351 psInfo
->isModeless
= dwFlags
& PSH_MODELESS
;
353 memcpy(&psInfo
->ppshheader
,lppsh
,dwSize
);
354 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",
355 lppsh
->dwSize
, lppsh
->dwFlags
, lppsh
->hwndParent
, lppsh
->hInstance
, debugstr_w(lppsh
->pszCaption
), lppsh
->nPages
, lppsh
->pfnCallback
);
357 PROPSHEET_UnImplementedFlags(lppsh
->dwFlags
);
359 if (lppsh
->dwFlags
& INTRNL_ANY_WIZARD
)
360 psInfo
->ppshheader
.pszCaption
= NULL
;
363 if (HIWORD(lppsh
->pszCaption
))
365 int len
= strlenW(lppsh
->pszCaption
);
366 psInfo
->ppshheader
.pszCaption
= HeapAlloc( GetProcessHeap(), 0, (len
+1)*sizeof(WCHAR
) );
367 strcpyW( (WCHAR
*)psInfo
->ppshheader
.pszCaption
, lppsh
->pszCaption
);
370 psInfo
->nPages
= lppsh
->nPages
;
372 if (dwFlags
& PSH_USEPSTARTPAGE
)
374 TRACE("PSH_USEPSTARTPAGE is on\n");
375 psInfo
->active_page
= 0;
378 psInfo
->active_page
= lppsh
->u2
.nStartPage
;
380 if (psInfo
->active_page
< 0 || psInfo
->active_page
>= psInfo
->nPages
)
381 psInfo
->active_page
= 0;
383 psInfo
->restartWindows
= FALSE
;
384 psInfo
->rebootSystem
= FALSE
;
385 psInfo
->hImageList
= 0;
386 psInfo
->activeValid
= FALSE
;
391 /******************************************************************************
392 * PROPSHEET_CollectPageInfo
394 * Collect property sheet data.
395 * With code taken from DIALOG_ParseTemplate32.
397 BOOL
PROPSHEET_CollectPageInfo(LPCPROPSHEETPAGEW lppsp
,
398 PropSheetInfo
* psInfo
,
401 DLGTEMPLATE
* pTemplate
;
407 psInfo
->proppage
[index
].hpage
= (HPROPSHEETPAGE
)lppsp
;
408 psInfo
->proppage
[index
].hwndPage
= 0;
409 psInfo
->proppage
[index
].isDirty
= FALSE
;
412 * Process property page flags.
414 dwFlags
= lppsp
->dwFlags
;
415 psInfo
->proppage
[index
].useCallback
= (dwFlags
& PSP_USECALLBACK
) && (lppsp
->pfnCallback
);
416 psInfo
->proppage
[index
].hasHelp
= dwFlags
& PSP_HASHELP
;
417 psInfo
->proppage
[index
].hasIcon
= dwFlags
& (PSP_USEHICON
| PSP_USEICONID
);
419 /* as soon as we have a page with the help flag, set the sheet flag on */
420 if (psInfo
->proppage
[index
].hasHelp
)
421 psInfo
->hasHelp
= TRUE
;
424 * Process page template.
426 if (dwFlags
& PSP_DLGINDIRECT
)
427 pTemplate
= (DLGTEMPLATE
*)lppsp
->u
.pResource
;
428 else if(dwFlags
& PSP_INTERNAL_UNICODE
)
430 HRSRC hResource
= FindResourceW(lppsp
->hInstance
,
431 lppsp
->u
.pszTemplate
,
433 HGLOBAL hTemplate
= LoadResource(lppsp
->hInstance
,
435 pTemplate
= (LPDLGTEMPLATEW
)LockResource(hTemplate
);
439 HRSRC hResource
= FindResourceA(lppsp
->hInstance
,
440 (LPSTR
)lppsp
->u
.pszTemplate
,
442 HGLOBAL hTemplate
= LoadResource(lppsp
->hInstance
,
444 pTemplate
= (LPDLGTEMPLATEA
)LockResource(hTemplate
);
448 * Extract the size of the page and the caption.
453 p
= (const WORD
*)pTemplate
;
455 if (((MyDLGTEMPLATEEX
*)pTemplate
)->signature
== 0xFFFF)
457 /* DLGTEMPLATEEX (not defined in any std. header file) */
461 p
+= 2; /* help ID */
462 p
+= 2; /* ext style */
470 p
+= 2; /* ext style */
476 width
= (WORD
)*p
; p
++;
477 height
= (WORD
)*p
; p
++;
479 /* remember the largest width and height */
480 if (width
> psInfo
->width
)
481 psInfo
->width
= width
;
483 if (height
> psInfo
->height
)
484 psInfo
->height
= height
;
496 p
+= lstrlenW( (LPCWSTR
)p
) + 1;
510 p
+= lstrlenW( (LPCWSTR
)p
) + 1;
514 /* Extract the caption */
515 psInfo
->proppage
[index
].pszText
= (LPCWSTR
)p
;
516 TRACE("Tab %d %s\n",index
,debugstr_w((LPCWSTR
)p
));
517 p
+= lstrlenW((LPCWSTR
)p
) + 1;
519 if (dwFlags
& PSP_USETITLE
)
523 static const WCHAR pszNull
[] = { '(','n','u','l','l',')',0 };
526 if ( !HIWORD( lppsp
->pszTitle
) )
528 if (!LoadStringW( lppsp
->hInstance
, (UINT
)lppsp
->pszTitle
,szTitle
,sizeof(szTitle
) ))
531 FIXME("Could not load resource #%04x?\n",LOWORD(lppsp
->pszTitle
));
537 pTitle
= lppsp
->pszTitle
;
539 len
= strlenW(pTitle
);
540 psInfo
->proppage
[index
].pszText
= Alloc( (len
+1)*sizeof (WCHAR
) );
541 strcpyW( (LPWSTR
)psInfo
->proppage
[index
].pszText
,pTitle
);
545 * Build the image list for icons
547 if ((dwFlags
& PSP_USEHICON
) || (dwFlags
& PSP_USEICONID
))
550 int icon_cx
= GetSystemMetrics(SM_CXSMICON
);
551 int icon_cy
= GetSystemMetrics(SM_CYSMICON
);
553 if (dwFlags
& PSP_USEICONID
)
554 hIcon
= LoadImageW(lppsp
->hInstance
, lppsp
->u2
.pszIcon
, IMAGE_ICON
,
555 icon_cx
, icon_cy
, LR_DEFAULTCOLOR
);
557 hIcon
= lppsp
->u2
.hIcon
;
561 if (psInfo
->hImageList
== 0 )
562 psInfo
->hImageList
= ImageList_Create(icon_cx
, icon_cy
, ILC_COLOR
, 1, 1);
564 ImageList_AddIcon(psInfo
->hImageList
, hIcon
);
572 /******************************************************************************
573 * PROPSHEET_CreateDialog
575 * Creates the actual property sheet.
577 int PROPSHEET_CreateDialog(PropSheetInfo
* psInfo
)
584 WORD resID
= IDD_PROPSHEET
;
587 if (psInfo
->ppshheader
.dwFlags
& INTRNL_ANY_WIZARD
)
590 if( psInfo
->unicode
)
592 if(!(hRes
= FindResourceW(COMCTL32_hModule
,
593 MAKEINTRESOURCEW(resID
),
599 if(!(hRes
= FindResourceA(COMCTL32_hModule
,
600 MAKEINTRESOURCEA(resID
),
605 if(!(template = (LPVOID
)LoadResource(COMCTL32_hModule
, hRes
)))
609 * Make a copy of the dialog template.
611 resSize
= SizeofResource(COMCTL32_hModule
, hRes
);
613 temp
= Alloc(resSize
);
618 memcpy(temp
, template, resSize
);
620 if (psInfo
->useCallback
)
621 (*(psInfo
->ppshheader
.pfnCallback
))(0, PSCB_PRECREATE
, (LPARAM
)temp
);
623 if( psInfo
->unicode
)
625 if (!(psInfo
->ppshheader
.dwFlags
& PSH_MODELESS
))
626 ret
= DialogBoxIndirectParamW(psInfo
->ppshheader
.hInstance
,
627 (LPDLGTEMPLATEW
) temp
,
628 psInfo
->ppshheader
.hwndParent
,
629 PROPSHEET_DialogProc
,
633 ret
= (int)CreateDialogIndirectParamW(psInfo
->ppshheader
.hInstance
,
634 (LPDLGTEMPLATEW
) temp
,
635 psInfo
->ppshheader
.hwndParent
,
636 PROPSHEET_DialogProc
,
638 if ( !ret
) ret
= -1;
643 if (!(psInfo
->ppshheader
.dwFlags
& PSH_MODELESS
))
644 ret
= DialogBoxIndirectParamA(psInfo
->ppshheader
.hInstance
,
645 (LPDLGTEMPLATEA
) temp
,
646 psInfo
->ppshheader
.hwndParent
,
647 PROPSHEET_DialogProc
,
651 ret
= (int)CreateDialogIndirectParamA(psInfo
->ppshheader
.hInstance
,
652 (LPDLGTEMPLATEA
) temp
,
653 psInfo
->ppshheader
.hwndParent
,
654 PROPSHEET_DialogProc
,
656 if ( !ret
) ret
= -1;
665 /******************************************************************************
666 * PROPSHEET_SizeMismatch
668 * Verify that the tab control and the "largest" property sheet page dlg. template
671 static BOOL
PROPSHEET_SizeMismatch(HWND hwndDlg
, PropSheetInfo
* psInfo
)
673 HWND hwndTabCtrl
= GetDlgItem(hwndDlg
, IDC_TABCONTROL
);
674 RECT rcOrigTab
, rcPage
;
679 GetClientRect(hwndTabCtrl
, &rcOrigTab
);
680 TRACE("orig tab %ld %ld %ld %ld\n", rcOrigTab
.left
, rcOrigTab
.top
,
681 rcOrigTab
.right
, rcOrigTab
.bottom
);
686 rcPage
.left
= psInfo
->x
;
687 rcPage
.top
= psInfo
->y
;
688 rcPage
.right
= psInfo
->width
;
689 rcPage
.bottom
= psInfo
->height
;
691 MapDialogRect(hwndDlg
, &rcPage
);
692 TRACE("biggest page %ld %ld %ld %ld\n", rcPage
.left
, rcPage
.top
,
693 rcPage
.right
, rcPage
.bottom
);
695 if ( (rcPage
.right
- rcPage
.left
) != (rcOrigTab
.right
- rcOrigTab
.left
) )
697 if ( (rcPage
.bottom
- rcPage
.top
) != (rcOrigTab
.bottom
- rcOrigTab
.top
) )
703 /******************************************************************************
704 * PROPSHEET_IsTooSmallWizard
706 * Verify that the default property sheet is big enough.
708 static BOOL
PROPSHEET_IsTooSmallWizard(HWND hwndDlg
, PropSheetInfo
* psInfo
)
710 RECT rcSheetRect
, rcPage
, rcLine
, rcSheetClient
;
711 HWND hwndLine
= GetDlgItem(hwndDlg
, IDC_SUNKEN_LINE
);
712 PADDING_INFO padding
= PROPSHEET_GetPaddingInfoWizard(hwndDlg
, psInfo
);
714 GetClientRect(hwndDlg
, &rcSheetClient
);
715 GetWindowRect(hwndDlg
, &rcSheetRect
);
716 GetWindowRect(hwndLine
, &rcLine
);
718 /* Remove the space below the sunken line */
719 rcSheetClient
.bottom
-= (rcSheetRect
.bottom
- rcLine
.top
);
721 /* Remove the buffer zone all around the edge */
722 rcSheetClient
.bottom
-= (padding
.y
* 2);
723 rcSheetClient
.right
-= (padding
.x
* 2);
728 rcPage
.left
= psInfo
->x
;
729 rcPage
.top
= psInfo
->y
;
730 rcPage
.right
= psInfo
->width
;
731 rcPage
.bottom
= psInfo
->height
;
733 MapDialogRect(hwndDlg
, &rcPage
);
734 TRACE("biggest page %ld %ld %ld %ld\n", rcPage
.left
, rcPage
.top
,
735 rcPage
.right
, rcPage
.bottom
);
737 if (rcPage
.right
> rcSheetClient
.right
)
740 if (rcPage
.bottom
> rcSheetClient
.bottom
)
746 /******************************************************************************
747 * PROPSHEET_AdjustSize
749 * Resizes the property sheet and the tab control to fit the largest page.
751 static BOOL
PROPSHEET_AdjustSize(HWND hwndDlg
, PropSheetInfo
* psInfo
)
753 HWND hwndTabCtrl
= GetDlgItem(hwndDlg
, IDC_TABCONTROL
);
754 HWND hwndButton
= GetDlgItem(hwndDlg
, IDOK
);
756 int tabOffsetX
, tabOffsetY
, buttonHeight
;
757 PADDING_INFO padding
= PROPSHEET_GetPaddingInfo(hwndDlg
);
760 /* Get the height of buttons */
761 GetClientRect(hwndButton
, &rc
);
762 buttonHeight
= rc
.bottom
;
769 rc
.right
= psInfo
->width
;
770 rc
.bottom
= psInfo
->height
;
772 MapDialogRect(hwndDlg
, &rc
);
774 /* retrieve the dialog units */
775 units
.left
= units
.right
= 4;
776 units
.top
= units
.bottom
= 8;
777 MapDialogRect(hwndDlg
, &units
);
780 * Resize the tab control.
782 GetClientRect(hwndTabCtrl
,&tabRect
);
784 SendMessageW(hwndTabCtrl
, TCM_ADJUSTRECT
, FALSE
, (LPARAM
)&tabRect
);
786 if ((rc
.bottom
- rc
.top
) < (tabRect
.bottom
- tabRect
.top
))
788 rc
.bottom
= rc
.top
+ tabRect
.bottom
- tabRect
.top
;
789 psInfo
->height
= MulDiv((rc
.bottom
- rc
.top
),8,units
.top
);
792 if ((rc
.right
- rc
.left
) < (tabRect
.right
- tabRect
.left
))
794 rc
.right
= rc
.left
+ tabRect
.right
- tabRect
.left
;
795 psInfo
->width
= MulDiv((rc
.right
- rc
.left
),4,units
.left
);
798 SendMessageW(hwndTabCtrl
, TCM_ADJUSTRECT
, TRUE
, (LPARAM
)&rc
);
800 tabOffsetX
= -(rc
.left
);
801 tabOffsetY
= -(rc
.top
);
805 TRACE("setting tab %08lx, rc (0,0)-(%ld,%ld)\n",
806 (DWORD
)hwndTabCtrl
, rc
.right
, rc
.bottom
);
807 SetWindowPos(hwndTabCtrl
, 0, 0, 0, rc
.right
, rc
.bottom
,
808 SWP_NOMOVE
| SWP_NOZORDER
| SWP_NOACTIVATE
);
810 GetClientRect(hwndTabCtrl
, &rc
);
812 TRACE("tab client rc %ld %ld %ld %ld\n",
813 rc
.left
, rc
.top
, rc
.right
, rc
.bottom
);
815 rc
.right
+= ((padding
.x
* 2) + tabOffsetX
);
816 rc
.bottom
+= (buttonHeight
+ (3 * padding
.y
) + tabOffsetY
);
819 * Resize the property sheet.
821 TRACE("setting dialog %08lx, rc (0,0)-(%ld,%ld)\n",
822 (DWORD
)hwndDlg
, rc
.right
, rc
.bottom
);
823 SetWindowPos(hwndDlg
, 0, 0, 0, rc
.right
, rc
.bottom
,
824 SWP_NOMOVE
| SWP_NOZORDER
| SWP_NOACTIVATE
);
828 /******************************************************************************
829 * PROPSHEET_AdjustSizeWizard
831 * Resizes the property sheet to fit the largest page.
833 static BOOL
PROPSHEET_AdjustSizeWizard(HWND hwndDlg
, PropSheetInfo
* psInfo
)
835 HWND hwndButton
= GetDlgItem(hwndDlg
, IDCANCEL
);
836 HWND hwndLine
= GetDlgItem(hwndDlg
, IDC_SUNKEN_LINE
);
837 HWND hwndTabCtrl
= GetDlgItem(hwndDlg
, IDC_TABCONTROL
);
839 int buttonHeight
, lineHeight
;
840 PADDING_INFO padding
= PROPSHEET_GetPaddingInfoWizard(hwndDlg
, psInfo
);
843 /* Get the height of buttons */
844 GetClientRect(hwndButton
, &rc
);
845 buttonHeight
= rc
.bottom
;
847 GetClientRect(hwndLine
, &rc
);
848 lineHeight
= rc
.bottom
;
850 /* retrieve the dialog units */
851 units
.left
= units
.right
= 4;
852 units
.top
= units
.bottom
= 8;
853 MapDialogRect(hwndDlg
, &units
);
860 rc
.right
= psInfo
->width
;
861 rc
.bottom
= psInfo
->height
;
863 MapDialogRect(hwndDlg
, &rc
);
865 GetClientRect(hwndTabCtrl
,&tabRect
);
867 if ((rc
.bottom
- rc
.top
) < (tabRect
.bottom
- tabRect
.top
))
869 rc
.bottom
= rc
.top
+ tabRect
.bottom
- tabRect
.top
;
870 psInfo
->height
= MulDiv((rc
.bottom
- rc
.top
), 8, units
.top
);
873 if ((rc
.right
- rc
.left
) < (tabRect
.right
- tabRect
.left
))
875 rc
.right
= rc
.left
+ tabRect
.right
- tabRect
.left
;
876 psInfo
->width
= MulDiv((rc
.right
- rc
.left
), 4, units
.left
);
879 TRACE("Biggest page %ld %ld %ld %ld\n", rc
.left
, rc
.top
, rc
.right
, rc
.bottom
);
880 TRACE(" constants padx=%d, pady=%d, butH=%d, lH=%d\n",
881 padding
.x
, padding
.y
, buttonHeight
, lineHeight
);
884 rc
.right
+= (padding
.x
* 2);
885 rc
.bottom
+= (buttonHeight
+ lineHeight
);
886 if (psInfo
->ppshheader
.dwFlags
& (PSH_WIZARD97_OLD
| PSH_WIZARD97_NEW
))
887 rc
.bottom
+= (4 * padding
.y
);
889 rc
.bottom
+= (5 * padding
.y
);
892 * Resize the property sheet.
894 TRACE("setting dialog %08lx, rc (0,0)-(%ld,%ld)\n",
895 (DWORD
)hwndDlg
, rc
.right
, rc
.bottom
);
896 SetWindowPos(hwndDlg
, 0, 0, 0, rc
.right
, rc
.bottom
,
897 SWP_NOMOVE
| SWP_NOZORDER
| SWP_NOACTIVATE
);
901 /******************************************************************************
902 * PROPSHEET_AdjustButtons
904 * Adjusts the buttons' positions.
906 static BOOL
PROPSHEET_AdjustButtons(HWND hwndParent
, PropSheetInfo
* psInfo
)
908 HWND hwndButton
= GetDlgItem(hwndParent
, IDOK
);
912 int buttonWidth
, buttonHeight
;
913 PADDING_INFO padding
= PROPSHEET_GetPaddingInfo(hwndParent
);
915 if (psInfo
->hasApply
)
922 * Obtain the size of the buttons.
924 GetClientRect(hwndButton
, &rcSheet
);
925 buttonWidth
= rcSheet
.right
;
926 buttonHeight
= rcSheet
.bottom
;
929 * Get the size of the property sheet.
931 GetClientRect(hwndParent
, &rcSheet
);
934 * All buttons will be at this y coordinate.
936 y
= rcSheet
.bottom
- (padding
.y
+ buttonHeight
);
939 * Position OK button.
941 hwndButton
= GetDlgItem(hwndParent
, IDOK
);
943 x
= rcSheet
.right
- ((padding
.x
+ buttonWidth
) * num_buttons
);
945 SetWindowPos(hwndButton
, 0, x
, y
, 0, 0,
946 SWP_NOSIZE
| SWP_NOZORDER
| SWP_NOACTIVATE
);
949 * Position Cancel button.
951 hwndButton
= GetDlgItem(hwndParent
, IDCANCEL
);
953 x
= rcSheet
.right
- ((padding
.x
+ buttonWidth
) * (num_buttons
- 1));
955 SetWindowPos(hwndButton
, 0, x
, y
, 0, 0,
956 SWP_NOSIZE
| SWP_NOZORDER
| SWP_NOACTIVATE
);
959 * Position Apply button.
961 hwndButton
= GetDlgItem(hwndParent
, IDC_APPLY_BUTTON
);
963 if (psInfo
->hasApply
)
966 x
= rcSheet
.right
- ((padding
.x
+ buttonWidth
) * 2);
968 x
= rcSheet
.right
- (padding
.x
+ buttonWidth
);
970 SetWindowPos(hwndButton
, 0, x
, y
, 0, 0,
971 SWP_NOSIZE
| SWP_NOZORDER
| SWP_NOACTIVATE
);
973 EnableWindow(hwndButton
, FALSE
);
976 ShowWindow(hwndButton
, SW_HIDE
);
979 * Position Help button.
981 hwndButton
= GetDlgItem(hwndParent
, IDHELP
);
985 x
= rcSheet
.right
- (padding
.x
+ buttonWidth
);
987 SetWindowPos(hwndButton
, 0, x
, y
, 0, 0,
988 SWP_NOSIZE
| SWP_NOZORDER
| SWP_NOACTIVATE
);
991 ShowWindow(hwndButton
, SW_HIDE
);
996 /******************************************************************************
997 * PROPSHEET_AdjustButtonsWizard
999 * Adjusts the buttons' positions.
1001 static BOOL
PROPSHEET_AdjustButtonsWizard(HWND hwndParent
,
1002 PropSheetInfo
* psInfo
)
1004 HWND hwndButton
= GetDlgItem(hwndParent
, IDCANCEL
);
1005 HWND hwndLine
= GetDlgItem(hwndParent
, IDC_SUNKEN_LINE
);
1006 HWND hwndLineHeader
= GetDlgItem(hwndParent
, IDC_SUNKEN_LINEHEADER
);
1009 int num_buttons
= 3;
1010 int buttonWidth
, buttonHeight
, lineHeight
, lineWidth
;
1011 PADDING_INFO padding
= PROPSHEET_GetPaddingInfoWizard(hwndParent
, psInfo
);
1013 if (psInfo
->hasHelp
)
1017 * Obtain the size of the buttons.
1019 GetClientRect(hwndButton
, &rcSheet
);
1020 buttonWidth
= rcSheet
.right
;
1021 buttonHeight
= rcSheet
.bottom
;
1023 GetClientRect(hwndLine
, &rcSheet
);
1024 lineHeight
= rcSheet
.bottom
;
1027 * Get the size of the property sheet.
1029 GetClientRect(hwndParent
, &rcSheet
);
1032 * All buttons will be at this y coordinate.
1034 y
= rcSheet
.bottom
- (padding
.y
+ buttonHeight
);
1037 * Position the Next and the Finish buttons.
1039 hwndButton
= GetDlgItem(hwndParent
, IDC_NEXT_BUTTON
);
1041 x
= rcSheet
.right
- ((padding
.x
+ buttonWidth
) * (num_buttons
- 1));
1043 SetWindowPos(hwndButton
, 0, x
, y
, 0, 0,
1044 SWP_NOSIZE
| SWP_NOZORDER
| SWP_NOACTIVATE
);
1046 hwndButton
= GetDlgItem(hwndParent
, IDC_FINISH_BUTTON
);
1048 SetWindowPos(hwndButton
, 0, x
, y
, 0, 0,
1049 SWP_NOSIZE
| SWP_NOZORDER
| SWP_NOACTIVATE
);
1051 ShowWindow(hwndButton
, SW_HIDE
);
1054 * Position the Back button.
1056 hwndButton
= GetDlgItem(hwndParent
, IDC_BACK_BUTTON
);
1060 SetWindowPos(hwndButton
, 0, x
, y
, 0, 0,
1061 SWP_NOSIZE
| SWP_NOZORDER
| SWP_NOACTIVATE
);
1064 * Position the Cancel button.
1066 hwndButton
= GetDlgItem(hwndParent
, IDCANCEL
);
1068 x
= rcSheet
.right
- ((padding
.x
+ buttonWidth
) * (num_buttons
- 2));
1070 SetWindowPos(hwndButton
, 0, x
, y
, 0, 0,
1071 SWP_NOSIZE
| SWP_NOZORDER
| SWP_NOACTIVATE
);
1074 * Position Help button.
1076 hwndButton
= GetDlgItem(hwndParent
, IDHELP
);
1078 if (psInfo
->hasHelp
)
1080 x
= rcSheet
.right
- (padding
.x
+ buttonWidth
);
1082 SetWindowPos(hwndButton
, 0, x
, y
, 0, 0,
1083 SWP_NOSIZE
| SWP_NOZORDER
| SWP_NOACTIVATE
);
1086 ShowWindow(hwndButton
, SW_HIDE
);
1088 if (psInfo
->ppshheader
.dwFlags
& (PSH_WIZARD97_OLD
| PSH_WIZARD97_NEW
))
1092 * Position and resize the sunken line.
1095 y
= rcSheet
.bottom
- ((padding
.y
* 2) + buttonHeight
+ lineHeight
);
1097 lineWidth
= rcSheet
.right
- (padding
.x
* 2);
1099 SetWindowPos(hwndLine
, 0, x
, y
, lineWidth
, 2,
1100 SWP_NOZORDER
| SWP_NOACTIVATE
);
1103 * Position and resize the header sunken line.
1106 SetWindowPos(hwndLineHeader
, 0, 0, 0, rcSheet
.right
, 2,
1107 SWP_NOZORDER
| SWP_NOMOVE
| SWP_NOACTIVATE
);
1108 if (!(psInfo
->ppshheader
.dwFlags
& (PSH_WIZARD97_OLD
| PSH_WIZARD97_NEW
)))
1109 ShowWindow(hwndLineHeader
, SW_HIDE
);
1114 /******************************************************************************
1115 * PROPSHEET_GetPaddingInfo
1117 * Returns the layout information.
1119 static PADDING_INFO
PROPSHEET_GetPaddingInfo(HWND hwndDlg
)
1121 HWND hwndTab
= GetDlgItem(hwndDlg
, IDC_TABCONTROL
);
1124 PADDING_INFO padding
;
1126 GetWindowRect(hwndTab
, &rcTab
);
1131 ScreenToClient(hwndDlg
, &tl
);
1139 /******************************************************************************
1140 * PROPSHEET_GetPaddingInfoWizard
1142 * Returns the layout information.
1143 * Vertical spacing is the distance between the line and the buttons.
1144 * Do NOT use the Help button to gather padding information when it isn't mapped
1145 * (PSH_HASHELP), as app writers aren't forced to supply correct coordinates
1146 * for it in this case !
1147 * FIXME: I'm not sure about any other coordinate problems with these evil
1148 * buttons. Fix it in case additional problems appear or maybe calculate
1149 * a padding in a completely different way, as this is somewhat messy.
1151 static PADDING_INFO
PROPSHEET_GetPaddingInfoWizard(HWND hwndDlg
, const PropSheetInfo
*
1154 PADDING_INFO padding
;
1158 POINT ptButton
, ptLine
;
1161 if (psInfo
->hasHelp
)
1167 if (psInfo
->ppshheader
.dwFlags
& INTRNL_ANY_WIZARD
)
1169 idButton
= IDC_NEXT_BUTTON
;
1173 /* hopefully this is ok */
1174 idButton
= IDCANCEL
;
1178 hwndControl
= GetDlgItem(hwndDlg
, idButton
);
1179 GetWindowRect(hwndControl
, &rc
);
1181 ptButton
.x
= rc
.left
;
1182 ptButton
.y
= rc
.top
;
1184 ScreenToClient(hwndDlg
, &ptButton
);
1187 hwndControl
= GetDlgItem(hwndDlg
, IDC_SUNKEN_LINE
);
1188 GetWindowRect(hwndControl
, &rc
);
1191 ptLine
.y
= rc
.bottom
;
1193 ScreenToClient(hwndDlg
, &ptLine
);
1195 padding
.y
= ptButton
.y
- ptLine
.y
;
1198 ERR("padding negative ! Please report this !\n");
1200 /* this is most probably not correct, but the best we have now */
1201 padding
.x
= padding
.y
;
1205 /******************************************************************************
1206 * PROPSHEET_CreateTabControl
1208 * Insert the tabs in the tab control.
1210 static BOOL
PROPSHEET_CreateTabControl(HWND hwndParent
,
1211 PropSheetInfo
* psInfo
)
1213 HWND hwndTabCtrl
= GetDlgItem(hwndParent
, IDC_TABCONTROL
);
1219 item
.mask
= TCIF_TEXT
;
1220 item
.cchTextMax
= MAX_TABTEXT_LENGTH
;
1222 nTabs
= psInfo
->nPages
;
1225 * Set the image list for icons.
1227 if (psInfo
->hImageList
)
1229 SendMessageW(hwndTabCtrl
, TCM_SETIMAGELIST
, 0, (LPARAM
)psInfo
->hImageList
);
1232 SendMessageW(GetDlgItem(hwndTabCtrl
, IDC_TABCONTROL
), WM_SETREDRAW
, 0, 0);
1233 for (i
= 0; i
< nTabs
; i
++)
1235 if ( psInfo
->proppage
[i
].hasIcon
)
1237 item
.mask
|= TCIF_IMAGE
;
1238 item
.iImage
= iImage
++;
1242 item
.mask
&= ~TCIF_IMAGE
;
1245 item
.pszText
= (LPWSTR
) psInfo
->proppage
[i
].pszText
;
1246 SendMessageW(hwndTabCtrl
, TCM_INSERTITEMW
, (WPARAM
)i
, (LPARAM
)&item
);
1248 SendMessageW(GetDlgItem(hwndTabCtrl
, IDC_TABCONTROL
), WM_SETREDRAW
, 1, 0);
1253 * Get the size of an in-memory Template
1255 *( Based on the code of PROPSHEET_CollectPageInfo)
1256 * See also dialog.c/DIALOG_ParseTemplate32().
1259 static UINT
GetTemplateSize(DLGTEMPLATE
* pTemplate
)
1262 const WORD
* p
= (const WORD
*)pTemplate
;
1263 BOOL istemplateex
= (((MyDLGTEMPLATEEX
*)pTemplate
)->signature
== 0xFFFF);
1268 /* DLGTEMPLATEEX (not defined in any std. header file) */
1270 TRACE("is DLGTEMPLATEEX\n");
1272 p
++; /* signature */
1273 p
+= 2; /* help ID */
1274 p
+= 2; /* ext style */
1281 TRACE("is DLGTEMPLATE\n");
1283 p
+= 2; /* ext style */
1286 nrofitems
= (WORD
)*p
; p
++; /* nb items */
1302 TRACE("menu %s\n",debugstr_w((LPCWSTR
)p
));
1303 p
+= lstrlenW( (LPCWSTR
)p
) + 1;
1314 p
+= 2; /* 0xffff plus predefined window class ordinal value */
1317 TRACE("class %s\n",debugstr_w((LPCWSTR
)p
));
1318 p
+= lstrlenW( (LPCWSTR
)p
) + 1;
1323 TRACE("title %s\n",debugstr_w((LPCWSTR
)p
));
1324 p
+= lstrlenW((LPCWSTR
)p
) + 1;
1326 /* font, if DS_SETFONT set */
1327 if ((DS_SETFONT
& ((istemplateex
)? ((MyDLGTEMPLATEEX
*)pTemplate
)->style
:
1330 p
+=(istemplateex
)?3:1;
1331 TRACE("font %s\n",debugstr_w((LPCWSTR
)p
));
1332 p
+= lstrlenW( (LPCWSTR
)p
) + 1; /* the font name */
1335 /* now process the DLGITEMTEMPLATE(EX) structs (plus custom data)
1336 * that are following the DLGTEMPLATE(EX) data */
1337 TRACE("%d items\n",nrofitems
);
1338 while (nrofitems
> 0)
1340 p
= (WORD
*)(((DWORD
)p
+ 3) & ~3); /* DWORD align */
1343 p
+= (istemplateex
? sizeof(MyDLGITEMTEMPLATEEX
) : sizeof(DLGITEMTEMPLATE
))/sizeof(WORD
);
1352 TRACE("class ordinal 0x%08lx\n",*(DWORD
*)p
);
1356 TRACE("class %s\n",debugstr_w((LPCWSTR
)p
));
1357 p
+= lstrlenW( (LPCWSTR
)p
) + 1;
1361 /* check title text */
1368 TRACE("text ordinal 0x%08lx\n",*(DWORD
*)p
);
1372 TRACE("text %s\n",debugstr_w((LPCWSTR
)p
));
1373 p
+= lstrlenW( (LPCWSTR
)p
) + 1;
1376 p
+= *p
+ 1; /* Skip extra data */
1380 TRACE("%p %p size 0x%08x\n",p
, (WORD
*)pTemplate
,sizeof(WORD
)*(p
- (WORD
*)pTemplate
));
1381 return (p
- (WORD
*)pTemplate
)*sizeof(WORD
);
1385 /******************************************************************************
1386 * PROPSHEET_CreatePage
1390 static BOOL
PROPSHEET_CreatePage(HWND hwndParent
,
1392 const PropSheetInfo
* psInfo
,
1393 LPCPROPSHEETPAGEW ppshpage
)
1395 DLGTEMPLATE
* pTemplate
;
1398 PADDING_INFO padding
;
1399 UINT pageWidth
,pageHeight
;
1403 TRACE("index %d\n", index
);
1405 if (ppshpage
== NULL
)
1410 if (ppshpage
->dwFlags
& PSP_DLGINDIRECT
)
1412 pTemplate
= (DLGTEMPLATE
*)ppshpage
->u
.pResource
;
1413 resSize
= GetTemplateSize(pTemplate
);
1415 else if(ppshpage
->dwFlags
& PSP_INTERNAL_UNICODE
)
1420 hResource
= FindResourceW(ppshpage
->hInstance
,
1421 ppshpage
->u
.pszTemplate
,
1426 resSize
= SizeofResource(ppshpage
->hInstance
, hResource
);
1428 hTemplate
= LoadResource(ppshpage
->hInstance
, hResource
);
1432 pTemplate
= (LPDLGTEMPLATEW
)LockResource(hTemplate
);
1434 * Make a copy of the dialog template to make it writable
1442 hResource
= FindResourceA(ppshpage
->hInstance
,
1443 (LPSTR
)ppshpage
->u
.pszTemplate
,
1448 resSize
= SizeofResource(ppshpage
->hInstance
, hResource
);
1450 hTemplate
= LoadResource(ppshpage
->hInstance
, hResource
);
1454 pTemplate
= (LPDLGTEMPLATEA
)LockResource(hTemplate
);
1456 * Make a copy of the dialog template to make it writable
1459 temp
= Alloc(resSize
);
1463 TRACE("copying pTemplate %p into temp %p (%ld)\n", pTemplate
, temp
, resSize
);
1464 memcpy(temp
, pTemplate
, resSize
);
1467 if (((MyDLGTEMPLATEEX
*)pTemplate
)->signature
== 0xFFFF)
1469 ((MyDLGTEMPLATEEX
*)pTemplate
)->style
|= WS_CHILD
| DS_CONTROL
;
1470 ((MyDLGTEMPLATEEX
*)pTemplate
)->style
&= ~DS_MODALFRAME
;
1471 ((MyDLGTEMPLATEEX
*)pTemplate
)->style
&= ~WS_CAPTION
;
1472 ((MyDLGTEMPLATEEX
*)pTemplate
)->style
&= ~WS_SYSMENU
;
1473 ((MyDLGTEMPLATEEX
*)pTemplate
)->style
&= ~WS_POPUP
;
1474 ((MyDLGTEMPLATEEX
*)pTemplate
)->style
&= ~WS_DISABLED
;
1475 ((MyDLGTEMPLATEEX
*)pTemplate
)->style
&= ~WS_VISIBLE
;
1476 ((MyDLGTEMPLATEEX
*)pTemplate
)->style
&= ~WS_THICKFRAME
;
1480 pTemplate
->style
|= WS_CHILD
| DS_CONTROL
;
1481 pTemplate
->style
&= ~DS_MODALFRAME
;
1482 pTemplate
->style
&= ~WS_CAPTION
;
1483 pTemplate
->style
&= ~WS_SYSMENU
;
1484 pTemplate
->style
&= ~WS_POPUP
;
1485 pTemplate
->style
&= ~WS_DISABLED
;
1486 pTemplate
->style
&= ~WS_VISIBLE
;
1487 pTemplate
->style
&= ~WS_THICKFRAME
;
1490 if (psInfo
->proppage
[index
].useCallback
)
1491 (*(ppshpage
->pfnCallback
))(0, PSPCB_CREATE
,
1492 (LPPROPSHEETPAGEW
)ppshpage
);
1494 if(ppshpage
->dwFlags
& PSP_INTERNAL_UNICODE
)
1495 hwndPage
= CreateDialogIndirectParamW(ppshpage
->hInstance
,
1498 ppshpage
->pfnDlgProc
,
1501 hwndPage
= CreateDialogIndirectParamA(ppshpage
->hInstance
,
1504 ppshpage
->pfnDlgProc
,
1506 /* Free a no more needed copy */
1510 psInfo
->proppage
[index
].hwndPage
= hwndPage
;
1512 if (psInfo
->ppshheader
.dwFlags
& INTRNL_ANY_WIZARD
) {
1517 rc
.left
= psInfo
->x
;
1519 rc
.right
= psInfo
->width
;
1520 rc
.bottom
= psInfo
->height
;
1522 MapDialogRect(hwndParent
, &rc
);
1524 pageWidth
= rc
.right
- rc
.left
;
1525 pageHeight
= rc
.bottom
- rc
.top
;
1527 padding
= PROPSHEET_GetPaddingInfoWizard(hwndParent
, psInfo
);
1528 TRACE("setting page %08lx, rc (%ld,%ld)-(%ld,%ld) w=%d, h=%d, padx=%d, pady=%d\n",
1529 (DWORD
)hwndPage
, rc
.left
, rc
.top
, rc
.right
, rc
.bottom
,
1530 pageWidth
, pageHeight
, padding
.x
, padding
.y
);
1532 if (psInfo
->ppshheader
.dwFlags
& (PSH_WIZARD97_NEW
| PSH_WIZARD97_OLD
) &&
1533 psInfo
->ppshheader
.dwFlags
& PSH_HEADER
)
1535 if ((ppshpage
->dwFlags
& PSP_USEHEADERTITLE
) &&
1536 (HIWORD(ppshpage
->pszHeaderTitle
) == 0))
1538 /* FIXME: load title string into ppshpage->pszHeaderTitle */
1541 if ((ppshpage
->dwFlags
& PSP_USEHEADERSUBTITLE
) &&
1542 (HIWORD(ppshpage
->pszHeaderSubTitle
) == 0))
1544 /* FIXME: load title string into ppshpage->pszHeaderSubTitle */
1547 hwndChild
= GetDlgItem(hwndParent
, IDC_SUNKEN_LINEHEADER
);
1549 GetClientRect(hwndChild
, &r
);
1550 MapWindowPoints(hwndChild
, hwndParent
, (LPPOINT
) &r
, 2);
1551 offsety
= (ppshpage
->dwFlags
& PSP_HIDEHEADER
)?0:r
.bottom
+ 1;
1554 SetWindowPos(hwndPage
, HWND_TOP
,
1555 rc
.left
+ padding
.x
/2,
1556 rc
.top
+ padding
.y
/2 + offsety
,
1557 pageWidth
, pageHeight
- offsety
, 0);
1561 * Ask the Tab control to reduce the client rectangle to that
1564 PROPSHEET_GetPageRect(psInfo
, hwndParent
, &rc
);
1565 pageWidth
= rc
.right
- rc
.left
;
1566 pageHeight
= rc
.bottom
- rc
.top
;
1567 TRACE("setting page %08lx, rc (%ld,%ld)-(%ld,%ld) w=%d, h=%d\n",
1568 (DWORD
)hwndPage
, rc
.left
, rc
.top
, rc
.right
, rc
.bottom
,
1569 pageWidth
, pageHeight
);
1570 SetWindowPos(hwndPage
, HWND_TOP
,
1572 pageWidth
, pageHeight
, 0);
1578 /******************************************************************************
1579 * PROPSHEET_LoadWizardBitmaps
1581 * Loads the watermark and header bitmaps for a wizard.
1583 static VOID
PROPSHEET_LoadWizardBitmaps(PropSheetInfo
*psInfo
)
1585 if (psInfo
->ppshheader
.dwFlags
& (PSH_WIZARD97_NEW
| PSH_WIZARD97_OLD
))
1587 /* if PSH_USEHBMWATERMARK is not set, load the resource from pszbmWatermark
1588 and put the HBITMAP in hbmWatermark. Thus all the rest of the code always
1589 considers hbmWatermark as valid. */
1590 if ((psInfo
->ppshheader
.dwFlags
& PSH_WATERMARK
) &&
1591 !(psInfo
->ppshheader
.dwFlags
& PSH_USEHBMWATERMARK
))
1593 ((PropSheetInfo
*)psInfo
)->ppshheader
.u4
.hbmWatermark
=
1594 CreateMappedBitmap(psInfo
->ppshheader
.hInstance
, (INT
)psInfo
->ppshheader
.u4
.pszbmWatermark
, 0, NULL
, 0);
1597 /* Same behavior as for watermarks */
1598 if ((psInfo
->ppshheader
.dwFlags
& PSH_HEADER
) &&
1599 !(psInfo
->ppshheader
.dwFlags
& PSH_USEHBMHEADER
))
1601 ((PropSheetInfo
*)psInfo
)->ppshheader
.u5
.hbmHeader
=
1602 CreateMappedBitmap(psInfo
->ppshheader
.hInstance
, (INT
)psInfo
->ppshheader
.u5
.pszbmHeader
, 0, NULL
, 0);
1608 /******************************************************************************
1609 * PROPSHEET_ShowPage
1611 * Displays or creates the specified page.
1613 static BOOL
PROPSHEET_ShowPage(HWND hwndDlg
, int index
, PropSheetInfo
* psInfo
)
1616 HWND hwndLineHeader
;
1617 LPCPROPSHEETPAGEW ppshpage
;
1619 TRACE("active_page %d, index %d\n", psInfo
->active_page
, index
);
1620 if (index
== psInfo
->active_page
)
1622 if (GetTopWindow(hwndDlg
) != psInfo
->proppage
[index
].hwndPage
)
1623 SetWindowPos(psInfo
->proppage
[index
].hwndPage
, HWND_TOP
, 0, 0, 0, 0, SWP_NOSIZE
| SWP_NOMOVE
);
1627 if (psInfo
->proppage
[index
].hwndPage
== 0)
1629 ppshpage
= (LPCPROPSHEETPAGEW
)psInfo
->proppage
[index
].hpage
;
1630 PROPSHEET_CreatePage(hwndDlg
, index
, psInfo
, ppshpage
);
1633 PROPSHEET_SetTitleW(hwndDlg
, psInfo
->ppshheader
.dwFlags
,
1634 psInfo
->proppage
[index
].pszText
);
1636 if (psInfo
->active_page
!= -1)
1637 ShowWindow(psInfo
->proppage
[psInfo
->active_page
].hwndPage
, SW_HIDE
);
1639 ShowWindow(psInfo
->proppage
[index
].hwndPage
, SW_SHOW
);
1641 /* Synchronize current selection with tab control
1642 * It seems to be needed even in case of PSH_WIZARD (no tab controls there) */
1643 hwndTabCtrl
= GetDlgItem(hwndDlg
, IDC_TABCONTROL
);
1644 SendMessageW(hwndTabCtrl
, TCM_SETCURSEL
, index
, 0);
1646 psInfo
->active_page
= index
;
1647 psInfo
->activeValid
= TRUE
;
1649 if (psInfo
->ppshheader
.dwFlags
& (PSH_WIZARD97_OLD
| PSH_WIZARD97_NEW
) )
1651 hwndLineHeader
= GetDlgItem(hwndDlg
, IDC_SUNKEN_LINEHEADER
);
1652 ppshpage
= (LPCPROPSHEETPAGEW
)psInfo
->proppage
[index
].hpage
;
1654 if ((ppshpage
->dwFlags
& PSP_HIDEHEADER
) || (!(psInfo
->ppshheader
.dwFlags
& PSH_HEADER
)) )
1655 ShowWindow(hwndLineHeader
, SW_HIDE
);
1657 ShowWindow(hwndLineHeader
, SW_SHOW
);
1659 InvalidateRgn(hwndDlg
, NULL
, TRUE
);
1660 UpdateWindow(hwndDlg
);
1666 /******************************************************************************
1669 static BOOL
PROPSHEET_Back(HWND hwndDlg
)
1673 PropSheetInfo
* psInfo
= (PropSheetInfo
*) GetPropW(hwndDlg
,
1678 TRACE("active_page %d\n", psInfo
->active_page
);
1679 if (psInfo
->active_page
< 0)
1682 psn
.hdr
.code
= PSN_WIZBACK
;
1683 psn
.hdr
.hwndFrom
= hwndDlg
;
1687 hwndPage
= psInfo
->proppage
[psInfo
->active_page
].hwndPage
;
1689 result
= SendMessageW(hwndPage
, WM_NOTIFY
, 0, (LPARAM
) &psn
);
1692 else if (result
== 0)
1693 idx
= psInfo
->active_page
- 1;
1695 idx
= PROPSHEET_FindPageByResId(psInfo
, result
);
1697 if (idx
>= 0 && idx
< psInfo
->nPages
)
1699 if (PROPSHEET_CanSetCurSel(hwndDlg
))
1700 PROPSHEET_SetCurSel(hwndDlg
, idx
, -1, 0);
1705 /******************************************************************************
1708 static BOOL
PROPSHEET_Next(HWND hwndDlg
)
1712 LRESULT msgResult
= 0;
1713 PropSheetInfo
* psInfo
= (PropSheetInfo
*) GetPropW(hwndDlg
,
1717 TRACE("active_page %d\n", psInfo
->active_page
);
1718 if (psInfo
->active_page
< 0)
1721 psn
.hdr
.code
= PSN_WIZNEXT
;
1722 psn
.hdr
.hwndFrom
= hwndDlg
;
1726 hwndPage
= psInfo
->proppage
[psInfo
->active_page
].hwndPage
;
1728 msgResult
= SendMessageA(hwndPage
, WM_NOTIFY
, 0, (LPARAM
) &psn
);
1729 if (msgResult
== -1)
1731 else if (msgResult
== 0)
1732 idx
= psInfo
->active_page
+ 1;
1734 idx
= PROPSHEET_FindPageByResId(psInfo
, msgResult
);
1736 if (idx
< psInfo
->nPages
)
1738 if (PROPSHEET_CanSetCurSel(hwndDlg
) != FALSE
)
1739 PROPSHEET_SetCurSel(hwndDlg
, idx
, 1, 0);
1745 /******************************************************************************
1748 static BOOL
PROPSHEET_Finish(HWND hwndDlg
)
1752 LRESULT msgResult
= 0;
1753 PropSheetInfo
* psInfo
= (PropSheetInfo
*) GetPropW(hwndDlg
,
1756 TRACE("active_page %d\n", psInfo
->active_page
);
1757 if (psInfo
->active_page
< 0)
1760 psn
.hdr
.code
= PSN_WIZFINISH
;
1761 psn
.hdr
.hwndFrom
= hwndDlg
;
1765 hwndPage
= psInfo
->proppage
[psInfo
->active_page
].hwndPage
;
1767 msgResult
= SendMessageW(hwndPage
, WM_NOTIFY
, 0, (LPARAM
) &psn
);
1769 TRACE("msg result %ld\n", msgResult
);
1774 if (psInfo
->isModeless
)
1775 psInfo
->activeValid
= FALSE
;
1777 EndDialog(hwndDlg
, TRUE
);
1782 /******************************************************************************
1785 static BOOL
PROPSHEET_Apply(HWND hwndDlg
, LPARAM lParam
)
1790 PropSheetInfo
* psInfo
= (PropSheetInfo
*) GetPropW(hwndDlg
,
1793 TRACE("active_page %d\n", psInfo
->active_page
);
1794 if (psInfo
->active_page
< 0)
1797 psn
.hdr
.hwndFrom
= hwndDlg
;
1803 * Send PSN_KILLACTIVE to the current page.
1805 psn
.hdr
.code
= PSN_KILLACTIVE
;
1807 hwndPage
= psInfo
->proppage
[psInfo
->active_page
].hwndPage
;
1809 if (SendMessageA(hwndPage
, WM_NOTIFY
, 0, (LPARAM
) &psn
) != FALSE
)
1813 * Send PSN_APPLY to all pages.
1815 psn
.hdr
.code
= PSN_APPLY
;
1816 psn
.lParam
= lParam
;
1818 for (i
= 0; i
< psInfo
->nPages
; i
++)
1820 hwndPage
= psInfo
->proppage
[i
].hwndPage
;
1823 switch (SendMessageA(hwndPage
, WM_NOTIFY
, 0, (LPARAM
) &psn
))
1825 case PSNRET_INVALID
:
1826 PROPSHEET_ShowPage(hwndDlg
, i
, psInfo
);
1828 case PSNRET_INVALID_NOCHANGEPAGE
:
1836 psInfo
->activeValid
= FALSE
;
1838 else if(psInfo
->active_page
>= 0)
1840 psn
.hdr
.code
= PSN_SETACTIVE
;
1842 hwndPage
= psInfo
->proppage
[psInfo
->active_page
].hwndPage
;
1843 SendMessageA(hwndPage
, WM_NOTIFY
, 0, (LPARAM
) &psn
);
1849 /******************************************************************************
1852 static void PROPSHEET_Cancel(HWND hwndDlg
, LPARAM lParam
)
1854 PropSheetInfo
* psInfo
= (PropSheetInfo
*) GetPropW(hwndDlg
,
1860 TRACE("active_page %d\n", psInfo
->active_page
);
1861 if (psInfo
->active_page
< 0)
1864 hwndPage
= psInfo
->proppage
[psInfo
->active_page
].hwndPage
;
1865 psn
.hdr
.code
= PSN_QUERYCANCEL
;
1866 psn
.hdr
.hwndFrom
= hwndDlg
;
1870 if (SendMessageA(hwndPage
, WM_NOTIFY
, 0, (LPARAM
) &psn
))
1873 psn
.hdr
.code
= PSN_RESET
;
1874 psn
.lParam
= lParam
;
1876 for (i
= 0; i
< psInfo
->nPages
; i
++)
1878 hwndPage
= psInfo
->proppage
[i
].hwndPage
;
1881 SendMessageA(hwndPage
, WM_NOTIFY
, 0, (LPARAM
) &psn
);
1884 if (psInfo
->isModeless
)
1886 /* makes PSM_GETCURRENTPAGEHWND return NULL */
1887 psInfo
->activeValid
= FALSE
;
1890 EndDialog(hwndDlg
, FALSE
);
1893 /******************************************************************************
1896 static void PROPSHEET_Help(HWND hwndDlg
)
1898 PropSheetInfo
* psInfo
= (PropSheetInfo
*) GetPropW(hwndDlg
,
1903 TRACE("active_page %d\n", psInfo
->active_page
);
1904 if (psInfo
->active_page
< 0)
1907 hwndPage
= psInfo
->proppage
[psInfo
->active_page
].hwndPage
;
1908 psn
.hdr
.code
= PSN_HELP
;
1909 psn
.hdr
.hwndFrom
= hwndDlg
;
1913 SendMessageA(hwndPage
, WM_NOTIFY
, 0, (LPARAM
) &psn
);
1916 /******************************************************************************
1919 static void PROPSHEET_Changed(HWND hwndDlg
, HWND hwndDirtyPage
)
1922 PropSheetInfo
* psInfo
= (PropSheetInfo
*) GetPropW(hwndDlg
,
1926 if (!psInfo
) return;
1928 * Set the dirty flag of this page.
1930 for (i
= 0; i
< psInfo
->nPages
; i
++)
1932 if (psInfo
->proppage
[i
].hwndPage
== hwndDirtyPage
)
1933 psInfo
->proppage
[i
].isDirty
= TRUE
;
1937 * Enable the Apply button.
1939 if (psInfo
->hasApply
)
1941 HWND hwndApplyBtn
= GetDlgItem(hwndDlg
, IDC_APPLY_BUTTON
);
1943 EnableWindow(hwndApplyBtn
, TRUE
);
1947 /******************************************************************************
1948 * PROPSHEET_UnChanged
1950 static void PROPSHEET_UnChanged(HWND hwndDlg
, HWND hwndCleanPage
)
1953 BOOL noPageDirty
= TRUE
;
1954 HWND hwndApplyBtn
= GetDlgItem(hwndDlg
, IDC_APPLY_BUTTON
);
1955 PropSheetInfo
* psInfo
= (PropSheetInfo
*) GetPropW(hwndDlg
,
1959 if ( !psInfo
) return;
1960 for (i
= 0; i
< psInfo
->nPages
; i
++)
1962 /* set the specified page as clean */
1963 if (psInfo
->proppage
[i
].hwndPage
== hwndCleanPage
)
1964 psInfo
->proppage
[i
].isDirty
= FALSE
;
1966 /* look to see if there's any dirty pages */
1967 if (psInfo
->proppage
[i
].isDirty
)
1968 noPageDirty
= FALSE
;
1972 * Disable Apply button.
1975 EnableWindow(hwndApplyBtn
, FALSE
);
1978 /******************************************************************************
1979 * PROPSHEET_PressButton
1981 static void PROPSHEET_PressButton(HWND hwndDlg
, int buttonID
)
1983 TRACE("buttonID %d\n", buttonID
);
1986 case PSBTN_APPLYNOW
:
1987 PROPSHEET_DoCommand(hwndDlg
, IDC_APPLY_BUTTON
);
1990 PROPSHEET_Back(hwndDlg
);
1993 PROPSHEET_DoCommand(hwndDlg
, IDCANCEL
);
1996 PROPSHEET_Finish(hwndDlg
);
1999 PROPSHEET_DoCommand(hwndDlg
, IDHELP
);
2002 PROPSHEET_Next(hwndDlg
);
2005 PROPSHEET_DoCommand(hwndDlg
, IDOK
);
2008 FIXME("Invalid button index %d\n", buttonID
);
2013 /*************************************************************************
2014 * BOOL PROPSHEET_CanSetCurSel [Internal]
2016 * Test whether the current page can be changed by sending a PSN_KILLACTIVE
2019 * hwndDlg [I] handle to a Dialog hWnd
2022 * TRUE if Current Selection can change
2026 static BOOL
PROPSHEET_CanSetCurSel(HWND hwndDlg
)
2028 PropSheetInfo
* psInfo
= (PropSheetInfo
*) GetPropW(hwndDlg
,
2034 TRACE("active_page %d\n", psInfo
->active_page
);
2041 if (psInfo
->active_page
< 0)
2048 * Notify the current page.
2050 hwndPage
= psInfo
->proppage
[psInfo
->active_page
].hwndPage
;
2051 psn
.hdr
.code
= PSN_KILLACTIVE
;
2052 psn
.hdr
.hwndFrom
= hwndDlg
;
2056 res
= !SendMessageA(hwndPage
, WM_NOTIFY
, 0, (LPARAM
) &psn
);
2059 TRACE("<-- %d\n", res
);
2063 /******************************************************************************
2064 * PROPSHEET_SetCurSel
2066 static BOOL
PROPSHEET_SetCurSel(HWND hwndDlg
,
2069 HPROPSHEETPAGE hpage
2072 PropSheetInfo
* psInfo
= (PropSheetInfo
*) GetPropW(hwndDlg
, PropSheetInfoStr
);
2073 HWND hwndHelp
= GetDlgItem(hwndDlg
, IDHELP
);
2074 HWND hwndTabControl
= GetDlgItem(hwndDlg
, IDC_TABCONTROL
);
2076 TRACE("index %d, skipdir %d, hpage %p\n", index
, skipdir
, hpage
);
2077 /* hpage takes precedence over index */
2079 index
= PROPSHEET_GetPageIndex(hpage
, psInfo
);
2081 if (index
< 0 || index
>= psInfo
->nPages
)
2083 TRACE("Could not find page to select!\n");
2092 SendMessageW(hwndTabControl
, TCM_SETCURSEL
, index
, 0);
2094 psn
.hdr
.code
= PSN_SETACTIVE
;
2095 psn
.hdr
.hwndFrom
= hwndDlg
;
2099 if (!psInfo
->proppage
[index
].hwndPage
) {
2100 LPCPROPSHEETPAGEW ppshpage
= (LPCPROPSHEETPAGEW
)psInfo
->proppage
[index
].hpage
;
2101 PROPSHEET_CreatePage(hwndDlg
, index
, psInfo
, ppshpage
);
2104 result
= SendMessageW(psInfo
->proppage
[index
].hwndPage
, WM_NOTIFY
, 0, (LPARAM
) &psn
);
2111 WARN("Tried to skip before first property sheet page!\n");
2114 if (index
>= psInfo
->nPages
) {
2115 WARN("Tried to skip after last property sheet page!\n");
2116 index
= psInfo
->nPages
-1;
2120 else if (result
!= 0)
2122 int old_index
= index
;
2123 index
= PROPSHEET_FindPageByResId(psInfo
, result
);
2124 if(index
>= psInfo
->nPages
) {
2126 WARN("Tried to skip to nonexistant page by res id\n");
2133 * Display the new page.
2135 PROPSHEET_ShowPage(hwndDlg
, index
, psInfo
);
2137 if (psInfo
->proppage
[index
].hasHelp
)
2138 EnableWindow(hwndHelp
, TRUE
);
2140 EnableWindow(hwndHelp
, FALSE
);
2145 /******************************************************************************
2146 * PROPSHEET_SetCurSelId
2148 * Selects the page, specified by resource id.
2150 static void PROPSHEET_SetCurSelId(HWND hwndDlg
, int id
)
2153 PropSheetInfo
* psInfo
=
2154 (PropSheetInfo
*) GetPropW(hwndDlg
, PropSheetInfoStr
);
2156 idx
= PROPSHEET_FindPageByResId(psInfo
, id
);
2157 if (idx
< psInfo
->nPages
)
2159 if (PROPSHEET_CanSetCurSel(hwndDlg
) != FALSE
)
2160 PROPSHEET_SetCurSel(hwndDlg
, idx
, 1, 0);
2164 /******************************************************************************
2165 * PROPSHEET_SetTitleA
2167 static void PROPSHEET_SetTitleA(HWND hwndDlg
, DWORD dwStyle
, LPCSTR lpszText
)
2169 if(HIWORD(lpszText
))
2172 MultiByteToWideChar(CP_ACP
, 0, lpszText
, -1,
2173 szTitle
, sizeof(szTitle
));
2174 PROPSHEET_SetTitleW(hwndDlg
, dwStyle
, szTitle
);
2178 PROPSHEET_SetTitleW(hwndDlg
, dwStyle
, (LPCWSTR
)lpszText
);
2182 /******************************************************************************
2183 * PROPSHEET_SetTitleW
2185 static void PROPSHEET_SetTitleW(HWND hwndDlg
, DWORD dwStyle
, LPCWSTR lpszText
)
2187 PropSheetInfo
* psInfo
= (PropSheetInfo
*) GetPropW(hwndDlg
, PropSheetInfoStr
);
2190 TRACE("'%s' (style %08lx)\n", debugstr_w(lpszText
), dwStyle
);
2191 if (HIWORD(lpszText
) == 0) {
2192 if (!LoadStringW(psInfo
->ppshheader
.hInstance
,
2193 LOWORD(lpszText
), szTitle
, sizeof(szTitle
)-sizeof(WCHAR
)))
2197 if (dwStyle
& PSH_PROPTITLE
)
2200 int lentitle
= strlenW(lpszText
);
2201 int lenprop
= strlenW(psInfo
->strPropertiesFor
);
2203 dest
= Alloc( (lentitle
+ lenprop
+ 1)*sizeof (WCHAR
));
2204 strcpyW(dest
, psInfo
->strPropertiesFor
);
2205 strcatW(dest
, lpszText
);
2207 SetWindowTextW(hwndDlg
, dest
);
2211 SetWindowTextW(hwndDlg
, lpszText
);
2214 /******************************************************************************
2215 * PROPSHEET_SetFinishTextA
2217 static void PROPSHEET_SetFinishTextA(HWND hwndDlg
, LPCSTR lpszText
)
2219 HWND hwndButton
= GetDlgItem(hwndDlg
, IDC_FINISH_BUTTON
);
2221 TRACE("'%s'\n", lpszText
);
2222 /* Set text, show and enable the Finish button */
2223 SetWindowTextA(hwndButton
, lpszText
);
2224 ShowWindow(hwndButton
, SW_SHOW
);
2225 EnableWindow(hwndButton
, TRUE
);
2227 /* Make it default pushbutton */
2228 SendMessageA(hwndDlg
, DM_SETDEFID
, IDC_FINISH_BUTTON
, 0);
2230 /* Hide Back button */
2231 hwndButton
= GetDlgItem(hwndDlg
, IDC_BACK_BUTTON
);
2232 ShowWindow(hwndButton
, SW_HIDE
);
2234 /* Hide Next button */
2235 hwndButton
= GetDlgItem(hwndDlg
, IDC_NEXT_BUTTON
);
2236 ShowWindow(hwndButton
, SW_HIDE
);
2239 /******************************************************************************
2240 * PROPSHEET_SetFinishTextW
2242 static void PROPSHEET_SetFinishTextW(HWND hwndDlg
, LPCWSTR lpszText
)
2244 HWND hwndButton
= GetDlgItem(hwndDlg
, IDC_FINISH_BUTTON
);
2246 TRACE("'%s'\n", debugstr_w(lpszText
));
2247 /* Set text, show and enable the Finish button */
2248 SetWindowTextW(hwndButton
, lpszText
);
2249 ShowWindow(hwndButton
, SW_SHOW
);
2250 EnableWindow(hwndButton
, TRUE
);
2252 /* Make it default pushbutton */
2253 SendMessageW(hwndDlg
, DM_SETDEFID
, IDC_FINISH_BUTTON
, 0);
2255 /* Hide Back button */
2256 hwndButton
= GetDlgItem(hwndDlg
, IDC_BACK_BUTTON
);
2257 ShowWindow(hwndButton
, SW_HIDE
);
2259 /* Hide Next button */
2260 hwndButton
= GetDlgItem(hwndDlg
, IDC_NEXT_BUTTON
);
2261 ShowWindow(hwndButton
, SW_HIDE
);
2264 /******************************************************************************
2265 * PROPSHEET_QuerySiblings
2267 static LRESULT
PROPSHEET_QuerySiblings(HWND hwndDlg
,
2268 WPARAM wParam
, LPARAM lParam
)
2272 LRESULT msgResult
= 0;
2273 PropSheetInfo
* psInfo
= (PropSheetInfo
*) GetPropW(hwndDlg
,
2276 while ((i
< psInfo
->nPages
) && (msgResult
== 0))
2278 hwndPage
= psInfo
->proppage
[i
].hwndPage
;
2279 msgResult
= SendMessageA(hwndPage
, PSM_QUERYSIBLINGS
, wParam
, lParam
);
2287 /******************************************************************************
2290 static BOOL
PROPSHEET_AddPage(HWND hwndDlg
,
2291 HPROPSHEETPAGE hpage
)
2293 PropSheetInfo
* psInfo
= (PropSheetInfo
*) GetPropW(hwndDlg
,
2295 HWND hwndTabControl
= GetDlgItem(hwndDlg
, IDC_TABCONTROL
);
2297 LPCPROPSHEETPAGEW ppsp
= (LPCPROPSHEETPAGEW
)hpage
;
2299 TRACE("hpage %p\n", hpage
);
2301 * Allocate and fill in a new PropPageInfo entry.
2303 psInfo
->proppage
= (PropPageInfo
*) ReAlloc(psInfo
->proppage
,
2304 sizeof(PropPageInfo
) *
2305 (psInfo
->nPages
+ 1));
2306 if (!PROPSHEET_CollectPageInfo(ppsp
, psInfo
, psInfo
->nPages
))
2309 psInfo
->proppage
[psInfo
->nPages
].hpage
= hpage
;
2311 if (ppsp
->dwFlags
& PSP_PREMATURE
)
2313 /* Create the page but don't show it */
2314 PROPSHEET_CreatePage(hwndDlg
, psInfo
->nPages
, psInfo
, ppsp
);
2318 * Add a new tab to the tab control.
2320 item
.mask
= TCIF_TEXT
;
2321 item
.pszText
= (LPWSTR
) psInfo
->proppage
[psInfo
->nPages
].pszText
;
2322 item
.cchTextMax
= MAX_TABTEXT_LENGTH
;
2324 if (psInfo
->hImageList
)
2326 SendMessageW(hwndTabControl
, TCM_SETIMAGELIST
, 0, (LPARAM
)psInfo
->hImageList
);
2329 if ( psInfo
->proppage
[psInfo
->nPages
].hasIcon
)
2331 item
.mask
|= TCIF_IMAGE
;
2332 item
.iImage
= psInfo
->nPages
;
2335 SendMessageW(hwndTabControl
, TCM_INSERTITEMW
, psInfo
->nPages
+ 1,
2340 /* If it is the only page - show it */
2341 if(psInfo
->nPages
== 1)
2342 PROPSHEET_SetCurSel(hwndDlg
, 0, 1, 0);
2346 /******************************************************************************
2347 * PROPSHEET_RemovePage
2349 static BOOL
PROPSHEET_RemovePage(HWND hwndDlg
,
2351 HPROPSHEETPAGE hpage
)
2353 PropSheetInfo
* psInfo
= (PropSheetInfo
*) GetPropW(hwndDlg
,
2355 HWND hwndTabControl
= GetDlgItem(hwndDlg
, IDC_TABCONTROL
);
2356 PropPageInfo
* oldPages
;
2358 TRACE("index %d, hpage %p\n", index
, hpage
);
2363 * hpage takes precedence over index.
2367 index
= PROPSHEET_GetPageIndex(hpage
, psInfo
);
2370 /* Make sure that index is within range */
2371 if (index
< 0 || index
>= psInfo
->nPages
)
2373 TRACE("Could not find page to remove!\n");
2377 TRACE("total pages %d removing page %d active page %d\n",
2378 psInfo
->nPages
, index
, psInfo
->active_page
);
2380 * Check if we're removing the active page.
2382 if (index
== psInfo
->active_page
)
2384 if (psInfo
->nPages
> 1)
2388 /* activate previous page */
2389 PROPSHEET_SetCurSel(hwndDlg
, index
- 1, -1, 0);
2393 /* activate the next page */
2394 PROPSHEET_SetCurSel(hwndDlg
, index
+ 1, 1, 0);
2395 psInfo
->active_page
= index
;
2400 psInfo
->active_page
= -1;
2401 if (!psInfo
->isModeless
)
2403 EndDialog(hwndDlg
, FALSE
);
2408 else if (index
< psInfo
->active_page
)
2409 psInfo
->active_page
--;
2411 /* Destroy page dialog window */
2412 DestroyWindow(psInfo
->proppage
[index
].hwndPage
);
2414 /* Free page resources */
2415 if(psInfo
->proppage
[index
].hpage
)
2417 PROPSHEETPAGEW
* psp
= (PROPSHEETPAGEW
*)psInfo
->proppage
[index
].hpage
;
2419 if ((psp
->dwFlags
& PSP_USETITLE
) && psInfo
->proppage
[index
].pszText
)
2420 HeapFree(GetProcessHeap(), 0, (LPVOID
)psInfo
->proppage
[index
].pszText
);
2422 DestroyPropertySheetPage(psInfo
->proppage
[index
].hpage
);
2425 /* Remove the tab */
2426 SendMessageW(hwndTabControl
, TCM_DELETEITEM
, index
, 0);
2428 oldPages
= psInfo
->proppage
;
2430 psInfo
->proppage
= Alloc(sizeof(PropPageInfo
) * psInfo
->nPages
);
2433 memcpy(&psInfo
->proppage
[0], &oldPages
[0], index
* sizeof(PropPageInfo
));
2435 if (index
< psInfo
->nPages
)
2436 memcpy(&psInfo
->proppage
[index
], &oldPages
[index
+ 1],
2437 (psInfo
->nPages
- index
) * sizeof(PropPageInfo
));
2444 /******************************************************************************
2445 * PROPSHEET_SetWizButtons
2447 * This code will work if (and assumes that) the Next button is on top of the
2448 * Finish button. ie. Finish comes after Next in the Z order.
2449 * This means make sure the dialog template reflects this.
2452 static void PROPSHEET_SetWizButtons(HWND hwndDlg
, DWORD dwFlags
)
2454 HWND hwndBack
= GetDlgItem(hwndDlg
, IDC_BACK_BUTTON
);
2455 HWND hwndNext
= GetDlgItem(hwndDlg
, IDC_NEXT_BUTTON
);
2456 HWND hwndFinish
= GetDlgItem(hwndDlg
, IDC_FINISH_BUTTON
);
2458 TRACE("%ld\n", dwFlags
);
2460 EnableWindow(hwndBack
, FALSE
);
2461 EnableWindow(hwndNext
, FALSE
);
2462 EnableWindow(hwndFinish
, FALSE
);
2464 if (dwFlags
& PSWIZB_BACK
)
2465 EnableWindow(hwndBack
, TRUE
);
2467 if (dwFlags
& PSWIZB_NEXT
)
2469 /* Hide the Finish button */
2470 ShowWindow(hwndFinish
, SW_HIDE
);
2472 /* Show and enable the Next button */
2473 ShowWindow(hwndNext
, SW_SHOW
);
2474 EnableWindow(hwndNext
, TRUE
);
2476 /* Set the Next button as the default pushbutton */
2477 SendMessageA(hwndDlg
, DM_SETDEFID
, IDC_NEXT_BUTTON
, 0);
2480 if ((dwFlags
& PSWIZB_FINISH
) || (dwFlags
& PSWIZB_DISABLEDFINISH
))
2482 /* Hide the Next button */
2483 ShowWindow(hwndNext
, SW_HIDE
);
2485 /* Show the Finish button */
2486 ShowWindow(hwndFinish
, SW_SHOW
);
2488 if (dwFlags
& PSWIZB_FINISH
)
2489 EnableWindow(hwndFinish
, TRUE
);
2491 /* Set the Finish button as the default pushbutton */
2492 SendMessageA(hwndDlg
, DM_SETDEFID
, IDC_FINISH_BUTTON
, 0);
2496 /******************************************************************************
2497 * PROPSHEET_InsertPage
2499 static BOOL
PROPSHEET_InsertPage(HWND hwndDlg
, HPROPSHEETPAGE hpageInsertAfter
, HPROPSHEETPAGE hpage
)
2501 if (!HIWORD(hpageInsertAfter
))
2502 FIXME("(%p, %d, %p): stub\n", hwndDlg
, LOWORD(hpageInsertAfter
), hpage
);
2504 FIXME("(%p, %p, %p): stub\n", hwndDlg
, hpageInsertAfter
, hpage
);
2508 /******************************************************************************
2509 * PROPSHEET_SetHeaderTitleW
2511 static void PROPSHEET_SetHeaderTitleW(HWND hwndDlg
, int iPageIndex
, LPCWSTR pszHeaderTitle
)
2513 FIXME("(%p, %d, %s): stub\n", hwndDlg
, iPageIndex
, debugstr_w(pszHeaderTitle
));
2516 /******************************************************************************
2517 * PROPSHEET_SetHeaderTitleA
2519 static void PROPSHEET_SetHeaderTitleA(HWND hwndDlg
, int iPageIndex
, LPCSTR pszHeaderTitle
)
2521 FIXME("(%p, %d, %s): stub\n", hwndDlg
, iPageIndex
, debugstr_a(pszHeaderTitle
));
2524 /******************************************************************************
2525 * PROPSHEET_SetHeaderSubTitleW
2527 static void PROPSHEET_SetHeaderSubTitleW(HWND hwndDlg
, int iPageIndex
, LPCWSTR pszHeaderSubTitle
)
2529 FIXME("(%p, %d, %s): stub\n", hwndDlg
, iPageIndex
, debugstr_w(pszHeaderSubTitle
));
2532 /******************************************************************************
2533 * PROPSHEET_SetHeaderSubTitleA
2535 static void PROPSHEET_SetHeaderSubTitleA(HWND hwndDlg
, int iPageIndex
, LPCSTR pszHeaderSubTitle
)
2537 FIXME("(%p, %d, %s): stub\n", hwndDlg
, iPageIndex
, debugstr_a(pszHeaderSubTitle
));
2540 /******************************************************************************
2541 * PROPSHEET_HwndToIndex
2543 static LRESULT
PROPSHEET_HwndToIndex(HWND hwndDlg
, HWND hPageDlg
)
2546 PropSheetInfo
* psInfo
= (PropSheetInfo
*) GetPropW(hwndDlg
,
2549 TRACE("(%p, %p)\n", hwndDlg
, hPageDlg
);
2551 for (index
= 0; index
< psInfo
->nPages
; index
++)
2552 if (psInfo
->proppage
[index
].hwndPage
== hPageDlg
)
2554 WARN("%p not found\n", hPageDlg
);
2558 /******************************************************************************
2559 * PROPSHEET_IndexToHwnd
2561 static LRESULT
PROPSHEET_IndexToHwnd(HWND hwndDlg
, int iPageIndex
)
2563 PropSheetInfo
* psInfo
= (PropSheetInfo
*) GetPropW(hwndDlg
,
2565 TRACE("(%p, %d)\n", hwndDlg
, iPageIndex
);
2566 if (iPageIndex
<0 || iPageIndex
>=psInfo
->nPages
) {
2567 WARN("%d out of range.\n", iPageIndex
);
2570 return (LRESULT
)psInfo
->proppage
[iPageIndex
].hwndPage
;
2573 /******************************************************************************
2574 * PROPSHEET_PageToIndex
2576 static LRESULT
PROPSHEET_PageToIndex(HWND hwndDlg
, HPROPSHEETPAGE hPage
)
2578 FIXME("(%p, %p): stub\n", hwndDlg
, hPage
);
2582 /******************************************************************************
2583 * PROPSHEET_IndexToPage
2585 static LRESULT
PROPSHEET_IndexToPage(HWND hwndDlg
, int iPageIndex
)
2587 FIXME("(%p, %d): stub\n", hwndDlg
, iPageIndex
);
2591 /******************************************************************************
2592 * PROPSHEET_IdToIndex
2594 static LRESULT
PROPSHEET_IdToIndex(HWND hwndDlg
, int iPageId
)
2596 FIXME("(%p, %d): stub\n", hwndDlg
, iPageId
);
2600 /******************************************************************************
2601 * PROPSHEET_IndexToId
2603 static LRESULT
PROPSHEET_IndexToId(HWND hwndDlg
, int iPageIndex
)
2605 FIXME("(%p, %d): stub\n", hwndDlg
, iPageIndex
);
2609 /******************************************************************************
2610 * PROPSHEET_GetResult
2612 static LRESULT
PROPSHEET_GetResult(HWND hwndDlg
)
2614 FIXME("(%p): stub\n", hwndDlg
);
2618 /******************************************************************************
2619 * PROPSHEET_RecalcPageSizes
2621 static BOOL
PROPSHEET_RecalcPageSizes(HWND hwndDlg
)
2623 FIXME("(%p): stub\n", hwndDlg
);
2627 /******************************************************************************
2628 * PROPSHEET_GetPageIndex
2630 * Given a HPROPSHEETPAGE, returns the index of the corresponding page from
2631 * the array of PropPageInfo.
2633 static int PROPSHEET_GetPageIndex(HPROPSHEETPAGE hpage
, PropSheetInfo
* psInfo
)
2638 TRACE("hpage %p\n", hpage
);
2639 while ((index
< psInfo
->nPages
) && (found
== FALSE
))
2641 if (psInfo
->proppage
[index
].hpage
== hpage
)
2653 /******************************************************************************
2656 static void PROPSHEET_CleanUp(HWND hwndDlg
)
2659 PropSheetInfo
* psInfo
= (PropSheetInfo
*) RemovePropW(hwndDlg
,
2663 if (!psInfo
) return;
2664 if (HIWORD(psInfo
->ppshheader
.pszCaption
))
2665 HeapFree(GetProcessHeap(), 0, (LPVOID
)psInfo
->ppshheader
.pszCaption
);
2667 for (i
= 0; i
< psInfo
->nPages
; i
++)
2669 PROPSHEETPAGEA
* psp
= (PROPSHEETPAGEA
*)psInfo
->proppage
[i
].hpage
;
2671 if(psInfo
->proppage
[i
].hwndPage
)
2672 DestroyWindow(psInfo
->proppage
[i
].hwndPage
);
2676 if ((psp
->dwFlags
& PSP_USETITLE
) && psInfo
->proppage
[i
].pszText
)
2677 HeapFree(GetProcessHeap(), 0, (LPVOID
)psInfo
->proppage
[i
].pszText
);
2679 DestroyPropertySheetPage(psInfo
->proppage
[i
].hpage
);
2683 DeleteObject(psInfo
->hFont
);
2684 DeleteObject(psInfo
->hFontBold
);
2685 /* If we created the bitmaps, destroy them */
2686 if ((psInfo
->ppshheader
.dwFlags
& PSH_WATERMARK
) &&
2687 (!(psInfo
->ppshheader
.dwFlags
& PSH_USEHBMWATERMARK
)) )
2688 DeleteObject(psInfo
->ppshheader
.u4
.hbmWatermark
);
2689 if ((psInfo
->ppshheader
.dwFlags
& PSH_HEADER
) &&
2690 (!(psInfo
->ppshheader
.dwFlags
& PSH_USEHBMHEADER
)) )
2691 DeleteObject(psInfo
->ppshheader
.u5
.hbmHeader
);
2693 Free(psInfo
->proppage
);
2694 Free(psInfo
->strPropertiesFor
);
2695 ImageList_Destroy(psInfo
->hImageList
);
2697 GlobalFree((HGLOBAL
)psInfo
);
2700 /******************************************************************************
2701 * PropertySheet (COMCTL32.@)
2702 * PropertySheetA (COMCTL32.@)
2704 * Creates a property sheet in the specified property sheet header.
2707 * Modal property sheets: Positive if successful or -1 otherwise.
2708 * Modeless property sheets: Property sheet handle.
2710 *| ID_PSREBOOTSYSTEM - The user must reboot the computer for the changes to take effect.
2711 *| ID_PSRESTARTWINDOWS - The user must restart Windows for the changes to take effect.
2713 INT WINAPI
PropertySheetA(LPCPROPSHEETHEADERA lppsh
)
2716 PropSheetInfo
* psInfo
= (PropSheetInfo
*) GlobalAlloc(GPTR
,
2717 sizeof(PropSheetInfo
));
2721 TRACE("(%p)\n", lppsh
);
2723 PROPSHEET_CollectSheetInfoA(lppsh
, psInfo
);
2725 psInfo
->proppage
= (PropPageInfo
*) Alloc(sizeof(PropPageInfo
) *
2727 pByte
= (BYTE
*) psInfo
->ppshheader
.u3
.ppsp
;
2729 for (n
= i
= 0; i
< lppsh
->nPages
; i
++, n
++)
2731 if (!(lppsh
->dwFlags
& PSH_PROPSHEETPAGE
))
2732 psInfo
->proppage
[n
].hpage
= psInfo
->ppshheader
.u3
.phpage
[i
];
2735 psInfo
->proppage
[n
].hpage
= CreatePropertySheetPageA((LPCPROPSHEETPAGEA
)pByte
);
2736 pByte
+= ((LPPROPSHEETPAGEA
)pByte
)->dwSize
;
2739 if (!PROPSHEET_CollectPageInfo((LPCPROPSHEETPAGEW
)psInfo
->proppage
[n
].hpage
,
2742 if (lppsh
->dwFlags
& PSH_PROPSHEETPAGE
)
2743 DestroyPropertySheetPage(psInfo
->proppage
[n
].hpage
);
2749 psInfo
->unicode
= FALSE
;
2750 bRet
= PROPSHEET_CreateDialog(psInfo
);
2755 /******************************************************************************
2756 * PropertySheetW (COMCTL32.@)
2758 * See PropertySheetA.
2760 INT WINAPI
PropertySheetW(LPCPROPSHEETHEADERW lppsh
)
2763 PropSheetInfo
* psInfo
= (PropSheetInfo
*) GlobalAlloc(GPTR
,
2764 sizeof(PropSheetInfo
));
2768 TRACE("(%p)\n", lppsh
);
2770 PROPSHEET_CollectSheetInfoW(lppsh
, psInfo
);
2772 psInfo
->proppage
= (PropPageInfo
*) Alloc(sizeof(PropPageInfo
) *
2774 pByte
= (BYTE
*) psInfo
->ppshheader
.u3
.ppsp
;
2776 for (n
= i
= 0; i
< lppsh
->nPages
; i
++, n
++)
2778 if (!(lppsh
->dwFlags
& PSH_PROPSHEETPAGE
))
2779 psInfo
->proppage
[n
].hpage
= psInfo
->ppshheader
.u3
.phpage
[i
];
2782 psInfo
->proppage
[n
].hpage
= CreatePropertySheetPageW((LPCPROPSHEETPAGEW
)pByte
);
2783 pByte
+= ((LPPROPSHEETPAGEW
)pByte
)->dwSize
;
2786 if (!PROPSHEET_CollectPageInfo((LPCPROPSHEETPAGEW
)psInfo
->proppage
[n
].hpage
,
2789 if (lppsh
->dwFlags
& PSH_PROPSHEETPAGE
)
2790 DestroyPropertySheetPage(psInfo
->proppage
[n
].hpage
);
2796 psInfo
->unicode
= TRUE
;
2797 bRet
= PROPSHEET_CreateDialog(psInfo
);
2802 /******************************************************************************
2803 * CreatePropertySheetPage (COMCTL32.@)
2804 * CreatePropertySheetPageA (COMCTL32.@)
2806 * Creates a new property sheet page.
2809 * Success: Handle to new property sheet page.
2813 * An application must use the PSM_ADDPAGE message to add the new page to
2814 * an existing property sheet.
2816 HPROPSHEETPAGE WINAPI
CreatePropertySheetPageA(
2817 LPCPROPSHEETPAGEA lpPropSheetPage
)
2819 PROPSHEETPAGEW
* ppsp
= Alloc(sizeof(PROPSHEETPAGEW
));
2821 memcpy(ppsp
,lpPropSheetPage
,min(lpPropSheetPage
->dwSize
,sizeof(PROPSHEETPAGEA
)));
2823 ppsp
->dwFlags
&= ~ PSP_INTERNAL_UNICODE
;
2824 if ( !(ppsp
->dwFlags
& PSP_DLGINDIRECT
) && HIWORD( ppsp
->u
.pszTemplate
) )
2826 int len
= strlen(lpPropSheetPage
->u
.pszTemplate
);
2828 ppsp
->u
.pszTemplate
= HeapAlloc( GetProcessHeap(),0,len
+1 );
2829 strcpy( (LPSTR
)ppsp
->u
.pszTemplate
, lpPropSheetPage
->u
.pszTemplate
);
2831 if ( (ppsp
->dwFlags
& PSP_USEICONID
) && HIWORD( ppsp
->u2
.pszIcon
) )
2833 PROPSHEET_AtoW(&ppsp
->u2
.pszIcon
, lpPropSheetPage
->u2
.pszIcon
);
2836 if ((ppsp
->dwFlags
& PSP_USETITLE
) && HIWORD( ppsp
->pszTitle
))
2838 PROPSHEET_AtoW(&ppsp
->pszTitle
, lpPropSheetPage
->pszTitle
);
2840 else if ( !(ppsp
->dwFlags
& PSP_USETITLE
) )
2841 ppsp
->pszTitle
= NULL
;
2843 return (HPROPSHEETPAGE
)ppsp
;
2846 /******************************************************************************
2847 * CreatePropertySheetPageW (COMCTL32.@)
2849 * See CreatePropertySheetA.
2851 HPROPSHEETPAGE WINAPI
CreatePropertySheetPageW(LPCPROPSHEETPAGEW lpPropSheetPage
)
2853 PROPSHEETPAGEW
* ppsp
= Alloc(sizeof(PROPSHEETPAGEW
));
2855 memcpy(ppsp
,lpPropSheetPage
,min(lpPropSheetPage
->dwSize
,sizeof(PROPSHEETPAGEW
)));
2857 ppsp
->dwFlags
|= PSP_INTERNAL_UNICODE
;
2859 if ( !(ppsp
->dwFlags
& PSP_DLGINDIRECT
) && HIWORD( ppsp
->u
.pszTemplate
) )
2861 int len
= strlenW(lpPropSheetPage
->u
.pszTemplate
);
2863 ppsp
->u
.pszTemplate
= HeapAlloc( GetProcessHeap(),0,(len
+1)*sizeof (WCHAR
) );
2864 strcpyW( (WCHAR
*)ppsp
->u
.pszTemplate
, lpPropSheetPage
->u
.pszTemplate
);
2866 if ( (ppsp
->dwFlags
& PSP_USEICONID
) && HIWORD( ppsp
->u2
.pszIcon
) )
2868 int len
= strlenW(lpPropSheetPage
->u2
.pszIcon
);
2869 ppsp
->u2
.pszIcon
= HeapAlloc( GetProcessHeap(), 0, (len
+1)*sizeof (WCHAR
) );
2870 strcpyW( (WCHAR
*)ppsp
->u2
.pszIcon
, lpPropSheetPage
->u2
.pszIcon
);
2873 if ((ppsp
->dwFlags
& PSP_USETITLE
) && HIWORD( ppsp
->pszTitle
))
2875 int len
= strlenW(lpPropSheetPage
->pszTitle
);
2876 ppsp
->pszTitle
= HeapAlloc( GetProcessHeap(), 0, (len
+1)*sizeof (WCHAR
) );
2877 strcpyW( (WCHAR
*)ppsp
->pszTitle
, lpPropSheetPage
->pszTitle
);
2879 else if ( !(ppsp
->dwFlags
& PSP_USETITLE
) )
2880 ppsp
->pszTitle
= NULL
;
2882 return (HPROPSHEETPAGE
)ppsp
;
2885 /******************************************************************************
2886 * DestroyPropertySheetPage (COMCTL32.@)
2888 * Destroys a property sheet page previously created with
2889 * CreatePropertySheetA() or CreatePropertySheetW() and frees the associated
2896 BOOL WINAPI
DestroyPropertySheetPage(HPROPSHEETPAGE hPropPage
)
2898 PROPSHEETPAGEW
*psp
= (PROPSHEETPAGEW
*)hPropPage
;
2903 if ( !(psp
->dwFlags
& PSP_DLGINDIRECT
) && HIWORD( psp
->u
.pszTemplate
) )
2904 HeapFree(GetProcessHeap(), 0, (LPVOID
)psp
->u
.pszTemplate
);
2906 if ( (psp
->dwFlags
& PSP_USEICONID
) && HIWORD( psp
->u2
.pszIcon
) )
2907 HeapFree(GetProcessHeap(), 0, (LPVOID
)psp
->u2
.pszIcon
);
2909 if ((psp
->dwFlags
& PSP_USETITLE
) && HIWORD( psp
->pszTitle
))
2910 HeapFree(GetProcessHeap(), 0, (LPVOID
)psp
->pszTitle
);
2917 /******************************************************************************
2918 * PROPSHEET_IsDialogMessage
2920 static BOOL
PROPSHEET_IsDialogMessage(HWND hwnd
, LPMSG lpMsg
)
2922 PropSheetInfo
* psInfo
= (PropSheetInfo
*) GetPropW(hwnd
, PropSheetInfoStr
);
2925 if (!psInfo
|| (hwnd
!= lpMsg
->hwnd
&& !IsChild(hwnd
, lpMsg
->hwnd
)))
2928 if (lpMsg
->message
== WM_KEYDOWN
&& (GetKeyState(VK_CONTROL
) & 0x8000))
2931 INT dlgCode
= SendMessageA(lpMsg
->hwnd
, WM_GETDLGCODE
, 0, (LPARAM
)lpMsg
);
2933 if (!(dlgCode
& DLGC_WANTMESSAGE
))
2935 switch (lpMsg
->wParam
)
2938 if (GetKeyState(VK_SHIFT
) & 0x8000)
2944 case VK_NEXT
: new_page
= 1; break;
2945 case VK_PRIOR
: new_page
= -1; break;
2951 if (PROPSHEET_CanSetCurSel(hwnd
) != FALSE
)
2953 new_page
+= psInfo
->active_page
;
2956 new_page
= psInfo
->nPages
- 1;
2957 else if (new_page
>= psInfo
->nPages
)
2960 PROPSHEET_SetCurSel(hwnd
, new_page
, 1, 0);
2967 return IsDialogMessageA(hwnd
, lpMsg
);
2970 /******************************************************************************
2971 * PROPSHEET_DoCommand
2973 static BOOL
PROPSHEET_DoCommand(HWND hwnd
, WORD wID
)
2979 case IDC_APPLY_BUTTON
:
2981 HWND hwndApplyBtn
= GetDlgItem(hwnd
, IDC_APPLY_BUTTON
);
2983 if (PROPSHEET_Apply(hwnd
, wID
== IDOK
? 1: 0) == FALSE
)
2988 PropSheetInfo
* psInfo
= (PropSheetInfo
*) GetPropW(hwnd
,
2992 if (psInfo
->restartWindows
)
2993 result
= ID_PSRESTARTWINDOWS
;
2995 /* reboot system takes precedence over restart windows */
2996 if (psInfo
->rebootSystem
)
2997 result
= ID_PSREBOOTSYSTEM
;
2999 if (psInfo
->isModeless
)
3000 psInfo
->activeValid
= FALSE
;
3002 EndDialog(hwnd
, result
);
3005 EnableWindow(hwndApplyBtn
, FALSE
);
3010 case IDC_BACK_BUTTON
:
3011 PROPSHEET_Back(hwnd
);
3014 case IDC_NEXT_BUTTON
:
3015 PROPSHEET_Next(hwnd
);
3018 case IDC_FINISH_BUTTON
:
3019 PROPSHEET_Finish(hwnd
);
3023 PROPSHEET_Cancel(hwnd
, 0);
3027 PROPSHEET_Help(hwnd
);
3037 /******************************************************************************
3040 static LRESULT
PROPSHEET_Paint(HWND hwnd
)
3042 PropSheetInfo
* psInfo
= (PropSheetInfo
*) GetPropW(hwnd
, PropSheetInfoStr
);
3047 HPALETTE hOldPal
= 0;
3051 LPCPROPSHEETPAGEW ppshpage
;
3053 hdc
= BeginPaint(hwnd
, &ps
);
3056 hdcSrc
= CreateCompatibleDC(0);
3057 ppshpage
= (LPCPROPSHEETPAGEW
)psInfo
->proppage
[psInfo
->active_page
].hpage
;
3059 if (psInfo
->ppshheader
.dwFlags
& PSH_USEHPLWATERMARK
)
3060 hOldPal
= SelectPalette(hdc
, psInfo
->ppshheader
.hplWatermark
, FALSE
);
3062 if ( (!(ppshpage
->dwFlags
& PSP_HIDEHEADER
)) &&
3063 (psInfo
->ppshheader
.dwFlags
& (PSH_WIZARD97_OLD
| PSH_WIZARD97_NEW
)) &&
3064 (psInfo
->ppshheader
.dwFlags
& PSH_HEADER
) )
3067 HWND hwndLineHeader
= GetDlgItem(hwnd
, IDC_SUNKEN_LINEHEADER
);
3069 COLORREF clrOld
= 0;
3072 hbmp
= SelectObject(hdcSrc
, psInfo
->ppshheader
.u5
.hbmHeader
);
3073 hOldFont
= SelectObject(hdc
, psInfo
->hFontBold
);
3075 GetClientRect(hwndLineHeader
, &r
);
3076 MapWindowPoints(hwndLineHeader
, hwnd
, (LPPOINT
) &r
, 2);
3077 SetRect(&rzone
, 0, 0, r
.right
, r
.top
- 1);
3078 hbr
= CreateSolidBrush(GetPixel(hdcSrc
, 0, 0));
3079 FillRect(hdc
, &rzone
, hbr
);
3082 GetObjectA(psInfo
->ppshheader
.u5
.hbmHeader
, sizeof(BITMAP
), (LPVOID
)&bm
);
3084 clrOld
= SetTextColor (hdc
, 0x00000000);
3085 oldBkMode
= SetBkMode (hdc
, TRANSPARENT
);
3087 if (ppshpage
->dwFlags
& PSP_USEHEADERTITLE
) {
3088 SetRect(&r
, 20, 10, rzone
.right
- bm
.bmWidth
, 18);
3089 if (psInfo
->unicode
)
3090 DrawTextW(hdc
, (LPWSTR
)ppshpage
->pszHeaderTitle
,
3091 -1, &r
, DT_LEFT
| DT_SINGLELINE
| DT_NOCLIP
);
3093 DrawTextA(hdc
, (LPCSTR
)ppshpage
->pszHeaderTitle
,
3094 -1, &r
, DT_LEFT
| DT_SINGLELINE
| DT_NOCLIP
);
3097 if (ppshpage
->dwFlags
& PSP_USEHEADERSUBTITLE
) {
3098 SelectObject(hdc
, psInfo
->hFont
);
3099 SetRect(&r
, 40, 25, rzone
.right
- bm
.bmWidth
, 43);
3100 if (psInfo
->unicode
)
3101 DrawTextW(hdc
, (LPWSTR
)ppshpage
->pszHeaderSubTitle
,
3102 -1, &r
, DT_LEFT
| DT_SINGLELINE
);
3104 DrawTextA(hdc
, (LPCSTR
)ppshpage
->pszHeaderSubTitle
,
3105 -1, &r
, DT_LEFT
| DT_SINGLELINE
);
3108 BitBlt(hdc
, rzone
.right
- bm
.bmWidth
, (rzone
.bottom
- bm
.bmHeight
)/2,
3109 bm
.bmWidth
, bm
.bmHeight
,
3110 hdcSrc
, 0, 0, SRCCOPY
);
3111 offsety
= rzone
.bottom
+ 2;
3113 SetTextColor(hdc
, clrOld
);
3114 SetBkMode(hdc
, oldBkMode
);
3115 SelectObject(hdc
, hOldFont
);
3116 SelectObject(hdcSrc
, hbmp
);
3119 if ( ((psInfo
->active_page
== 0) || (psInfo
->active_page
== psInfo
->nPages
- 1)) &&
3120 (psInfo
->ppshheader
.dwFlags
& (PSH_WIZARD97_OLD
| PSH_WIZARD97_NEW
)) &&
3121 (psInfo
->ppshheader
.dwFlags
& PSH_WATERMARK
) )
3123 HWND hwndLine
= GetDlgItem(hwnd
, IDC_SUNKEN_LINE
);
3125 GetClientRect(hwndLine
, &r
);
3126 MapWindowPoints(hwndLine
, hwnd
, (LPPOINT
) &r
, 2);
3128 GetObjectA(psInfo
->ppshheader
.u4
.hbmWatermark
, sizeof(BITMAP
), (LPVOID
)&bm
);
3129 hbmp
= SelectObject(hdcSrc
, psInfo
->ppshheader
.u4
.hbmWatermark
);
3131 BitBlt(hdc
, 0, offsety
, min(bm
.bmWidth
, r
.right
),
3132 min(bm
.bmHeight
, r
.bottom
), hdcSrc
, 0, 0, SRCCOPY
);
3134 /* If the bitmap is not big enough, fill the remaining area
3135 with the color of pixel (0,0) of bitmap - see MSDN */
3136 if (r
.top
> bm
.bmHeight
) {
3137 r
.bottom
= r
.top
- 1;
3138 r
.top
= bm
.bmHeight
;
3140 r
.right
= bm
.bmWidth
;
3141 hbr
= CreateSolidBrush(GetPixel(hdcSrc
, 0, 0));
3142 FillRect(hdc
, &r
, hbr
);
3146 SelectObject(hdcSrc
, hbmp
);
3149 if (psInfo
->ppshheader
.dwFlags
& PSH_USEHPLWATERMARK
)
3150 SelectPalette(hdc
, hOldPal
, FALSE
);
3154 EndPaint(hwnd
, &ps
);
3159 /******************************************************************************
3160 * PROPSHEET_DialogProc
3163 PROPSHEET_DialogProc(HWND hwnd
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
)
3165 TRACE("hwnd=%p msg=0x%04x wparam=%x lparam=%lx\n",
3166 hwnd
, uMsg
, wParam
, lParam
);
3172 PropSheetInfo
* psInfo
= (PropSheetInfo
*) lParam
;
3173 WCHAR
* strCaption
= (WCHAR
*)Alloc(MAX_CAPTION_LENGTH
*sizeof(WCHAR
));
3174 HWND hwndTabCtrl
= GetDlgItem(hwnd
, IDC_TABCONTROL
);
3175 LPCPROPSHEETPAGEW ppshpage
;
3179 /* Using PropSheetInfoStr to store extra data doesn't match the native
3180 * common control: native uses TCM_[GS]ETITEM
3182 SetPropW(hwnd
, PropSheetInfoStr
, (HANDLE
)psInfo
);
3185 * psInfo->hwnd is not being used by WINE code - it exists
3186 * for compatibility with "real" Windoze. The same about
3187 * SetWindowLong - WINE is only using the PropSheetInfoStr
3190 psInfo
->hwnd
= hwnd
;
3191 SetWindowLongW(hwnd
,DWL_USER
,(LONG
)psInfo
);
3193 /* set up the Next and Back buttons by default */
3194 PROPSHEET_SetWizButtons(hwnd
, PSWIZB_BACK
|PSWIZB_NEXT
);
3197 SystemParametersInfoA (SPI_GETICONTITLELOGFONT
, 0, &logFont
, 0);
3198 psInfo
->hFont
= CreateFontIndirectA (&logFont
);
3199 logFont
.lfWeight
= FW_BOLD
;
3200 psInfo
->hFontBold
= CreateFontIndirectA (&logFont
);
3203 * Small icon in the title bar.
3205 if ((psInfo
->ppshheader
.dwFlags
& PSH_USEICONID
) ||
3206 (psInfo
->ppshheader
.dwFlags
& PSH_USEHICON
))
3209 int icon_cx
= GetSystemMetrics(SM_CXSMICON
);
3210 int icon_cy
= GetSystemMetrics(SM_CYSMICON
);
3212 if (psInfo
->ppshheader
.dwFlags
& PSH_USEICONID
)
3213 hIcon
= LoadImageW(psInfo
->ppshheader
.hInstance
,
3214 psInfo
->ppshheader
.u
.pszIcon
,
3219 hIcon
= psInfo
->ppshheader
.u
.hIcon
;
3221 SendMessageW(hwnd
, WM_SETICON
, 0, (LPARAM
)hIcon
);
3224 if (psInfo
->ppshheader
.dwFlags
& PSH_USEHICON
)
3225 SendMessageW(hwnd
, WM_SETICON
, 0, (LPARAM
)psInfo
->ppshheader
.u
.hIcon
);
3227 psInfo
->strPropertiesFor
= strCaption
;
3229 GetWindowTextW(hwnd
, psInfo
->strPropertiesFor
, MAX_CAPTION_LENGTH
);
3231 PROPSHEET_CreateTabControl(hwnd
, psInfo
);
3233 PROPSHEET_LoadWizardBitmaps(psInfo
);
3235 if (psInfo
->ppshheader
.dwFlags
& INTRNL_ANY_WIZARD
)
3237 ShowWindow(hwndTabCtrl
, SW_HIDE
);
3238 if (PROPSHEET_IsTooSmallWizard(hwnd
, psInfo
))
3240 PROPSHEET_AdjustSizeWizard(hwnd
, psInfo
);
3241 PROPSHEET_AdjustButtonsWizard(hwnd
, psInfo
);
3246 if (PROPSHEET_SizeMismatch(hwnd
, psInfo
))
3248 PROPSHEET_AdjustSize(hwnd
, psInfo
);
3249 PROPSHEET_AdjustButtons(hwnd
, psInfo
);
3253 if (psInfo
->useCallback
)
3254 (*(psInfo
->ppshheader
.pfnCallback
))(hwnd
,
3255 PSCB_INITIALIZED
, (LPARAM
)0);
3257 idx
= psInfo
->active_page
;
3258 ppshpage
= (LPCPROPSHEETPAGEW
)psInfo
->proppage
[idx
].hpage
;
3259 psInfo
->active_page
= -1;
3261 PROPSHEET_SetCurSel(hwnd
, idx
, 1, psInfo
->proppage
[idx
].hpage
);
3263 /* doing TCM_SETCURSEL seems to be needed even in case of PSH_WIZARD,
3264 * as some programs call TCM_GETCURSEL to get the current selection
3265 * from which to switch to the next page */
3266 SendMessageW(hwndTabCtrl
, TCM_SETCURSEL
, psInfo
->active_page
, 0);
3268 if (!HIWORD(psInfo
->ppshheader
.pszCaption
) &&
3269 psInfo
->ppshheader
.hInstance
)
3273 if (LoadStringW(psInfo
->ppshheader
.hInstance
,
3274 (UINT
)psInfo
->ppshheader
.pszCaption
, szText
, 255))
3275 PROPSHEET_SetTitleW(hwnd
, psInfo
->ppshheader
.dwFlags
, szText
);
3279 PROPSHEET_SetTitleW(hwnd
, psInfo
->ppshheader
.dwFlags
,
3280 psInfo
->ppshheader
.pszCaption
);
3287 PROPSHEET_Paint(hwnd
);
3291 PROPSHEET_CleanUp(hwnd
);
3295 PROPSHEET_Cancel(hwnd
, 1);
3299 if (!PROPSHEET_DoCommand(hwnd
, LOWORD(wParam
)))
3301 PropSheetInfo
* psInfo
= (PropSheetInfo
*) GetPropW(hwnd
, PropSheetInfoStr
);
3303 /* No default handler, forward notification to active page */
3304 if (psInfo
->activeValid
&& psInfo
->active_page
!= -1)
3306 HWND hwndPage
= psInfo
->proppage
[psInfo
->active_page
].hwndPage
;
3307 SendMessageW(hwndPage
, WM_COMMAND
, wParam
, lParam
);
3314 NMHDR
* pnmh
= (LPNMHDR
) lParam
;
3316 if (pnmh
->code
== TCN_SELCHANGE
)
3318 int index
= SendMessageW(pnmh
->hwndFrom
, TCM_GETCURSEL
, 0, 0);
3319 PROPSHEET_SetCurSel(hwnd
, index
, 1, 0);
3322 if(pnmh
->code
== TCN_SELCHANGING
)
3324 BOOL bRet
= PROPSHEET_CanSetCurSel(hwnd
);
3325 SetWindowLongW(hwnd
, DWL_MSGRESULT
, !bRet
);
3332 case PSM_GETCURRENTPAGEHWND
:
3334 PropSheetInfo
* psInfo
= (PropSheetInfo
*) GetPropW(hwnd
,
3338 if (psInfo
->activeValid
&& psInfo
->active_page
!= -1)
3339 hwndPage
= psInfo
->proppage
[psInfo
->active_page
].hwndPage
;
3341 SetWindowLongW(hwnd
, DWL_MSGRESULT
, (LONG
)hwndPage
);
3347 PROPSHEET_Changed(hwnd
, (HWND
)wParam
);
3351 PROPSHEET_UnChanged(hwnd
, (HWND
)wParam
);
3354 case PSM_GETTABCONTROL
:
3356 HWND hwndTabCtrl
= GetDlgItem(hwnd
, IDC_TABCONTROL
);
3358 SetWindowLongW(hwnd
, DWL_MSGRESULT
, (LONG
)hwndTabCtrl
);
3367 msgResult
= PROPSHEET_CanSetCurSel(hwnd
);
3368 if(msgResult
!= FALSE
)
3370 msgResult
= PROPSHEET_SetCurSel(hwnd
,
3373 (HPROPSHEETPAGE
)lParam
);
3376 SetWindowLongW(hwnd
, DWL_MSGRESULT
, msgResult
);
3381 case PSM_CANCELTOCLOSE
:
3383 WCHAR buf
[MAX_BUTTONTEXT_LENGTH
];
3384 HWND hwndOK
= GetDlgItem(hwnd
, IDOK
);
3385 HWND hwndCancel
= GetDlgItem(hwnd
, IDCANCEL
);
3387 EnableWindow(hwndCancel
, FALSE
);
3388 if (LoadStringW(COMCTL32_hModule
, IDS_CLOSE
, buf
, sizeof(buf
)))
3389 SetWindowTextW(hwndOK
, buf
);
3394 case PSM_RESTARTWINDOWS
:
3396 PropSheetInfo
* psInfo
= (PropSheetInfo
*) GetPropW(hwnd
,
3399 psInfo
->restartWindows
= TRUE
;
3403 case PSM_REBOOTSYSTEM
:
3405 PropSheetInfo
* psInfo
= (PropSheetInfo
*) GetPropW(hwnd
,
3408 psInfo
->rebootSystem
= TRUE
;
3413 PROPSHEET_SetTitleA(hwnd
, (DWORD
) wParam
, (LPCSTR
) lParam
);
3417 PROPSHEET_SetTitleW(hwnd
, (DWORD
) wParam
, (LPCWSTR
) lParam
);
3422 BOOL msgResult
= PROPSHEET_Apply(hwnd
, 0);
3424 SetWindowLongW(hwnd
, DWL_MSGRESULT
, msgResult
);
3429 case PSM_QUERYSIBLINGS
:
3431 LRESULT msgResult
= PROPSHEET_QuerySiblings(hwnd
, wParam
, lParam
);
3433 SetWindowLongW(hwnd
, DWL_MSGRESULT
, msgResult
);
3441 * Note: MSVC++ 6.0 documentation says that PSM_ADDPAGE does not have
3442 * a return value. This is not true. PSM_ADDPAGE returns TRUE
3443 * on success or FALSE otherwise, as specified on MSDN Online.
3444 * Also see the MFC code for
3445 * CPropertySheet::AddPage(CPropertyPage* pPage).
3448 BOOL msgResult
= PROPSHEET_AddPage(hwnd
, (HPROPSHEETPAGE
)lParam
);
3450 SetWindowLongW(hwnd
, DWL_MSGRESULT
, msgResult
);
3455 case PSM_REMOVEPAGE
:
3456 PROPSHEET_RemovePage(hwnd
, (int)wParam
, (HPROPSHEETPAGE
)lParam
);
3459 case PSM_ISDIALOGMESSAGE
:
3461 BOOL msgResult
= PROPSHEET_IsDialogMessage(hwnd
, (LPMSG
)lParam
);
3462 SetWindowLongA(hwnd
, DWL_MSGRESULT
, msgResult
);
3466 case PSM_PRESSBUTTON
:
3467 PROPSHEET_PressButton(hwnd
, (int)wParam
);
3470 case PSM_SETFINISHTEXTA
:
3471 PROPSHEET_SetFinishTextA(hwnd
, (LPCSTR
) lParam
);
3474 case PSM_SETWIZBUTTONS
:
3475 PROPSHEET_SetWizButtons(hwnd
, (DWORD
)lParam
);
3478 case PSM_SETCURSELID
:
3479 PROPSHEET_SetCurSelId(hwnd
, (int)lParam
);
3482 case PSM_SETFINISHTEXTW
:
3483 PROPSHEET_SetFinishTextW(hwnd
, (LPCWSTR
) lParam
);
3486 case PSM_INSERTPAGE
:
3488 BOOL msgResult
= PROPSHEET_InsertPage(hwnd
, (HPROPSHEETPAGE
)wParam
, (HPROPSHEETPAGE
)lParam
);
3489 SetWindowLongW(hwnd
, DWL_MSGRESULT
, msgResult
);
3493 case PSM_SETHEADERTITLEW
:
3494 PROPSHEET_SetHeaderTitleW(hwnd
, (int)wParam
, (LPCWSTR
)lParam
);
3497 case PSM_SETHEADERTITLEA
:
3498 PROPSHEET_SetHeaderTitleA(hwnd
, (int)wParam
, (LPCSTR
)lParam
);
3501 case PSM_SETHEADERSUBTITLEW
:
3502 PROPSHEET_SetHeaderSubTitleW(hwnd
, (int)wParam
, (LPCWSTR
)lParam
);
3505 case PSM_SETHEADERSUBTITLEA
:
3506 PROPSHEET_SetHeaderSubTitleA(hwnd
, (int)wParam
, (LPCSTR
)lParam
);
3509 case PSM_HWNDTOINDEX
:
3511 LRESULT msgResult
= PROPSHEET_HwndToIndex(hwnd
, (HWND
)wParam
);
3512 SetWindowLongW(hwnd
, DWL_MSGRESULT
, msgResult
);
3516 case PSM_INDEXTOHWND
:
3518 LRESULT msgResult
= PROPSHEET_IndexToHwnd(hwnd
, (int)wParam
);
3519 SetWindowLongW(hwnd
, DWL_MSGRESULT
, msgResult
);
3523 case PSM_PAGETOINDEX
:
3525 LRESULT msgResult
= PROPSHEET_PageToIndex(hwnd
, (HPROPSHEETPAGE
)wParam
);
3526 SetWindowLongW(hwnd
, DWL_MSGRESULT
, msgResult
);
3530 case PSM_INDEXTOPAGE
:
3532 LRESULT msgResult
= PROPSHEET_IndexToPage(hwnd
, (int)wParam
);
3533 SetWindowLongW(hwnd
, DWL_MSGRESULT
, msgResult
);
3539 LRESULT msgResult
= PROPSHEET_IdToIndex(hwnd
, (int)lParam
);
3540 SetWindowLongW(hwnd
, DWL_MSGRESULT
, msgResult
);
3546 LRESULT msgResult
= PROPSHEET_IndexToId(hwnd
, (int)wParam
);
3547 SetWindowLongW(hwnd
, DWL_MSGRESULT
, msgResult
);
3553 LRESULT msgResult
= PROPSHEET_GetResult(hwnd
);
3554 SetWindowLongW(hwnd
, DWL_MSGRESULT
, msgResult
);
3558 case PSM_RECALCPAGESIZES
:
3560 LRESULT msgResult
= PROPSHEET_RecalcPageSizes(hwnd
);
3561 SetWindowLongW(hwnd
, DWL_MSGRESULT
, msgResult
);