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_WATERMARK 0x00008000
207 * PSH_USEHBMWATERMARK 0x00010000
208 * PSH_USEHPLWATERMARK 0x00020000
209 * PSH_STRETCHWATERMARK 0x00040000
210 * PSH_HEADER 0x00080000
211 * PSH_USEHBMHEADER 0x00100000
212 * PSH_USEPAGELANG 0x00200000
213 * PSH_WIZARD_LITE 0x00400000 also not in .h
214 * PSH_WIZARD97 0x01000000 (IE 5 and above)
215 * PSH_NOCONTEXTHELP 0x02000000 also not in .h
218 add_flag(PSH_WIZARDHASFINISH
);
219 add_flag(PSH_RTLREADING
);
220 add_flag(PSH_WIZARDCONTEXTHELP
);
221 add_flag(PSH_STRETCHWATERMARK
);
222 add_flag(PSH_USEPAGELANG
);
223 add_flag(PSH_WIZARD_LITE
);
224 add_flag(PSH_NOCONTEXTHELP
);
225 if (string
[0] != '\0')
226 FIXME("%s\n", string
);
230 /******************************************************************************
231 * PROPSHEET_GetPageRect
233 * Retrieve rect from tab control and map into the dialog for SetWindowPos
235 static void PROPSHEET_GetPageRect(const PropSheetInfo
* psInfo
, HWND hwndDlg
, RECT
*rc
)
237 HWND hwndTabCtrl
= GetDlgItem(hwndDlg
, IDC_TABCONTROL
);
239 GetClientRect(hwndTabCtrl
, rc
);
240 SendMessageW(hwndTabCtrl
, TCM_ADJUSTRECT
, FALSE
, (LPARAM
)rc
);
241 MapWindowPoints(hwndTabCtrl
, hwndDlg
, (LPPOINT
)rc
, 2);
244 /******************************************************************************
245 * PROPSHEET_FindPageByResId
247 * Find page index corresponding to page resource id.
249 INT
PROPSHEET_FindPageByResId(PropSheetInfo
* psInfo
, LRESULT resId
)
253 for (i
= 0; i
< psInfo
->nPages
; i
++)
255 LPCPROPSHEETPAGEA lppsp
= (LPCPROPSHEETPAGEA
)psInfo
->proppage
[i
].hpage
;
257 /* Fixme: if resource ID is a string shall we use strcmp ??? */
258 if (lppsp
->u
.pszTemplate
== (LPVOID
)resId
)
265 /******************************************************************************
268 * Convert ASCII to Unicode since all data is saved as Unicode.
270 static void PROPSHEET_AtoW(LPCWSTR
*tostr
, LPCSTR frstr
)
274 TRACE("<%s>\n", frstr
);
275 len
= MultiByteToWideChar(CP_ACP
, 0, frstr
, -1, 0, 0);
276 *tostr
= (LPWSTR
)HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
277 MultiByteToWideChar(CP_ACP
, 0, frstr
, -1, (LPWSTR
)*tostr
, len
);
280 /******************************************************************************
281 * PROPSHEET_CollectSheetInfoA
283 * Collect relevant data.
285 static BOOL
PROPSHEET_CollectSheetInfoA(LPCPROPSHEETHEADERA lppsh
,
286 PropSheetInfo
* psInfo
)
288 DWORD dwSize
= min(lppsh
->dwSize
,sizeof(PROPSHEETHEADERA
));
289 DWORD dwFlags
= lppsh
->dwFlags
;
291 psInfo
->hasHelp
= dwFlags
& PSH_HASHELP
;
292 psInfo
->hasApply
= !(dwFlags
& PSH_NOAPPLYNOW
);
293 psInfo
->useCallback
= (dwFlags
& PSH_USECALLBACK
)&& (lppsh
->pfnCallback
);
294 psInfo
->isModeless
= dwFlags
& PSH_MODELESS
;
296 memcpy(&psInfo
->ppshheader
,lppsh
,dwSize
);
297 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",
298 lppsh
->dwSize
, lppsh
->dwFlags
, lppsh
->hwndParent
, lppsh
->hInstance
,
299 debugstr_a(lppsh
->pszCaption
), lppsh
->nPages
, lppsh
->pfnCallback
);
301 PROPSHEET_UnImplementedFlags(lppsh
->dwFlags
);
303 if (lppsh
->dwFlags
& INTRNL_ANY_WIZARD
)
304 psInfo
->ppshheader
.pszCaption
= NULL
;
307 if (HIWORD(lppsh
->pszCaption
))
309 int len
= MultiByteToWideChar(CP_ACP
, 0, lppsh
->pszCaption
, -1, NULL
, 0);
310 psInfo
->ppshheader
.pszCaption
= HeapAlloc( GetProcessHeap(), 0, len
*sizeof (WCHAR
) );
311 MultiByteToWideChar(CP_ACP
, 0, lppsh
->pszCaption
, -1, (LPWSTR
) psInfo
->ppshheader
.pszCaption
, len
);
314 psInfo
->nPages
= lppsh
->nPages
;
316 if (dwFlags
& PSH_USEPSTARTPAGE
)
318 TRACE("PSH_USEPSTARTPAGE is on\n");
319 psInfo
->active_page
= 0;
322 psInfo
->active_page
= lppsh
->u2
.nStartPage
;
324 if (psInfo
->active_page
< 0 || psInfo
->active_page
>= psInfo
->nPages
)
325 psInfo
->active_page
= 0;
327 psInfo
->restartWindows
= FALSE
;
328 psInfo
->rebootSystem
= FALSE
;
329 psInfo
->hImageList
= 0;
330 psInfo
->activeValid
= FALSE
;
335 /******************************************************************************
336 * PROPSHEET_CollectSheetInfoW
338 * Collect relevant data.
340 static BOOL
PROPSHEET_CollectSheetInfoW(LPCPROPSHEETHEADERW lppsh
,
341 PropSheetInfo
* psInfo
)
343 DWORD dwSize
= min(lppsh
->dwSize
,sizeof(PROPSHEETHEADERW
));
344 DWORD dwFlags
= lppsh
->dwFlags
;
346 psInfo
->hasHelp
= dwFlags
& PSH_HASHELP
;
347 psInfo
->hasApply
= !(dwFlags
& PSH_NOAPPLYNOW
);
348 psInfo
->useCallback
= (dwFlags
& PSH_USECALLBACK
) && (lppsh
->pfnCallback
);
349 psInfo
->isModeless
= dwFlags
& PSH_MODELESS
;
351 memcpy(&psInfo
->ppshheader
,lppsh
,dwSize
);
352 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",
353 lppsh
->dwSize
, lppsh
->dwFlags
, lppsh
->hwndParent
, lppsh
->hInstance
, debugstr_w(lppsh
->pszCaption
), lppsh
->nPages
, lppsh
->pfnCallback
);
355 PROPSHEET_UnImplementedFlags(lppsh
->dwFlags
);
357 if (lppsh
->dwFlags
& INTRNL_ANY_WIZARD
)
358 psInfo
->ppshheader
.pszCaption
= NULL
;
361 if (HIWORD(lppsh
->pszCaption
))
363 int len
= strlenW(lppsh
->pszCaption
);
364 psInfo
->ppshheader
.pszCaption
= HeapAlloc( GetProcessHeap(), 0, (len
+1)*sizeof(WCHAR
) );
365 strcpyW( (WCHAR
*)psInfo
->ppshheader
.pszCaption
, lppsh
->pszCaption
);
368 psInfo
->nPages
= lppsh
->nPages
;
370 if (dwFlags
& PSH_USEPSTARTPAGE
)
372 TRACE("PSH_USEPSTARTPAGE is on\n");
373 psInfo
->active_page
= 0;
376 psInfo
->active_page
= lppsh
->u2
.nStartPage
;
378 if (psInfo
->active_page
< 0 || psInfo
->active_page
>= psInfo
->nPages
)
379 psInfo
->active_page
= 0;
381 psInfo
->restartWindows
= FALSE
;
382 psInfo
->rebootSystem
= FALSE
;
383 psInfo
->hImageList
= 0;
384 psInfo
->activeValid
= FALSE
;
389 /******************************************************************************
390 * PROPSHEET_CollectPageInfo
392 * Collect property sheet data.
393 * With code taken from DIALOG_ParseTemplate32.
395 BOOL
PROPSHEET_CollectPageInfo(LPCPROPSHEETPAGEW lppsp
,
396 PropSheetInfo
* psInfo
,
399 DLGTEMPLATE
* pTemplate
;
405 psInfo
->proppage
[index
].hpage
= (HPROPSHEETPAGE
)lppsp
;
406 psInfo
->proppage
[index
].hwndPage
= 0;
407 psInfo
->proppage
[index
].isDirty
= FALSE
;
410 * Process property page flags.
412 dwFlags
= lppsp
->dwFlags
;
413 psInfo
->proppage
[index
].useCallback
= (dwFlags
& PSP_USECALLBACK
) && (lppsp
->pfnCallback
);
414 psInfo
->proppage
[index
].hasHelp
= dwFlags
& PSP_HASHELP
;
415 psInfo
->proppage
[index
].hasIcon
= dwFlags
& (PSP_USEHICON
| PSP_USEICONID
);
417 /* as soon as we have a page with the help flag, set the sheet flag on */
418 if (psInfo
->proppage
[index
].hasHelp
)
419 psInfo
->hasHelp
= TRUE
;
422 * Process page template.
424 if (dwFlags
& PSP_DLGINDIRECT
)
425 pTemplate
= (DLGTEMPLATE
*)lppsp
->u
.pResource
;
426 else if(dwFlags
& PSP_INTERNAL_UNICODE
)
428 HRSRC hResource
= FindResourceW(lppsp
->hInstance
,
429 lppsp
->u
.pszTemplate
,
431 HGLOBAL hTemplate
= LoadResource(lppsp
->hInstance
,
433 pTemplate
= (LPDLGTEMPLATEW
)LockResource(hTemplate
);
437 HRSRC hResource
= FindResourceA(lppsp
->hInstance
,
438 (LPSTR
)lppsp
->u
.pszTemplate
,
440 HGLOBAL hTemplate
= LoadResource(lppsp
->hInstance
,
442 pTemplate
= (LPDLGTEMPLATEA
)LockResource(hTemplate
);
446 * Extract the size of the page and the caption.
451 p
= (const WORD
*)pTemplate
;
453 if (((MyDLGTEMPLATEEX
*)pTemplate
)->signature
== 0xFFFF)
455 /* DLGTEMPLATEEX (not defined in any std. header file) */
459 p
+= 2; /* help ID */
460 p
+= 2; /* ext style */
468 p
+= 2; /* ext style */
474 width
= (WORD
)*p
; p
++;
475 height
= (WORD
)*p
; p
++;
477 /* remember the largest width and height */
478 if (width
> psInfo
->width
)
479 psInfo
->width
= width
;
481 if (height
> psInfo
->height
)
482 psInfo
->height
= height
;
494 p
+= lstrlenW( (LPCWSTR
)p
) + 1;
508 p
+= lstrlenW( (LPCWSTR
)p
) + 1;
512 /* Extract the caption */
513 psInfo
->proppage
[index
].pszText
= (LPCWSTR
)p
;
514 TRACE("Tab %d %s\n",index
,debugstr_w((LPCWSTR
)p
));
515 p
+= lstrlenW((LPCWSTR
)p
) + 1;
517 if (dwFlags
& PSP_USETITLE
)
521 static const WCHAR pszNull
[] = { '(','n','u','l','l',')',0 };
524 if ( !HIWORD( lppsp
->pszTitle
) )
526 if (!LoadStringW( lppsp
->hInstance
, (UINT
)lppsp
->pszTitle
,szTitle
,sizeof(szTitle
) ))
529 FIXME("Could not load resource #%04x?\n",LOWORD(lppsp
->pszTitle
));
535 pTitle
= lppsp
->pszTitle
;
537 len
= strlenW(pTitle
);
538 psInfo
->proppage
[index
].pszText
= Alloc( (len
+1)*sizeof (WCHAR
) );
539 strcpyW( (LPWSTR
)psInfo
->proppage
[index
].pszText
,pTitle
);
543 * Build the image list for icons
545 if ((dwFlags
& PSP_USEHICON
) || (dwFlags
& PSP_USEICONID
))
548 int icon_cx
= GetSystemMetrics(SM_CXSMICON
);
549 int icon_cy
= GetSystemMetrics(SM_CYSMICON
);
551 if (dwFlags
& PSP_USEICONID
)
552 hIcon
= LoadImageW(lppsp
->hInstance
, lppsp
->u2
.pszIcon
, IMAGE_ICON
,
553 icon_cx
, icon_cy
, LR_DEFAULTCOLOR
);
555 hIcon
= lppsp
->u2
.hIcon
;
559 if (psInfo
->hImageList
== 0 )
560 psInfo
->hImageList
= ImageList_Create(icon_cx
, icon_cy
, ILC_COLOR
, 1, 1);
562 ImageList_AddIcon(psInfo
->hImageList
, hIcon
);
570 /******************************************************************************
571 * PROPSHEET_CreateDialog
573 * Creates the actual property sheet.
575 int PROPSHEET_CreateDialog(PropSheetInfo
* psInfo
)
582 WORD resID
= IDD_PROPSHEET
;
585 if (psInfo
->ppshheader
.dwFlags
& INTRNL_ANY_WIZARD
)
588 if( psInfo
->unicode
)
590 if(!(hRes
= FindResourceW(COMCTL32_hModule
,
591 MAKEINTRESOURCEW(resID
),
597 if(!(hRes
= FindResourceA(COMCTL32_hModule
,
598 MAKEINTRESOURCEA(resID
),
603 if(!(template = (LPVOID
)LoadResource(COMCTL32_hModule
, hRes
)))
607 * Make a copy of the dialog template.
609 resSize
= SizeofResource(COMCTL32_hModule
, hRes
);
611 temp
= Alloc(resSize
);
616 memcpy(temp
, template, resSize
);
618 if (psInfo
->useCallback
)
619 (*(psInfo
->ppshheader
.pfnCallback
))(0, PSCB_PRECREATE
, (LPARAM
)temp
);
621 if( psInfo
->unicode
)
623 if (!(psInfo
->ppshheader
.dwFlags
& PSH_MODELESS
))
624 ret
= DialogBoxIndirectParamW(psInfo
->ppshheader
.hInstance
,
625 (LPDLGTEMPLATEW
) temp
,
626 psInfo
->ppshheader
.hwndParent
,
627 PROPSHEET_DialogProc
,
631 ret
= (int)CreateDialogIndirectParamW(psInfo
->ppshheader
.hInstance
,
632 (LPDLGTEMPLATEW
) temp
,
633 psInfo
->ppshheader
.hwndParent
,
634 PROPSHEET_DialogProc
,
636 if ( !ret
) ret
= -1;
641 if (!(psInfo
->ppshheader
.dwFlags
& PSH_MODELESS
))
642 ret
= DialogBoxIndirectParamA(psInfo
->ppshheader
.hInstance
,
643 (LPDLGTEMPLATEA
) temp
,
644 psInfo
->ppshheader
.hwndParent
,
645 PROPSHEET_DialogProc
,
649 ret
= (int)CreateDialogIndirectParamA(psInfo
->ppshheader
.hInstance
,
650 (LPDLGTEMPLATEA
) temp
,
651 psInfo
->ppshheader
.hwndParent
,
652 PROPSHEET_DialogProc
,
654 if ( !ret
) ret
= -1;
663 /******************************************************************************
664 * PROPSHEET_SizeMismatch
666 * Verify that the tab control and the "largest" property sheet page dlg. template
669 static BOOL
PROPSHEET_SizeMismatch(HWND hwndDlg
, PropSheetInfo
* psInfo
)
671 HWND hwndTabCtrl
= GetDlgItem(hwndDlg
, IDC_TABCONTROL
);
672 RECT rcOrigTab
, rcPage
;
677 GetClientRect(hwndTabCtrl
, &rcOrigTab
);
678 TRACE("orig tab %ld %ld %ld %ld\n", rcOrigTab
.left
, rcOrigTab
.top
,
679 rcOrigTab
.right
, rcOrigTab
.bottom
);
684 rcPage
.left
= psInfo
->x
;
685 rcPage
.top
= psInfo
->y
;
686 rcPage
.right
= psInfo
->width
;
687 rcPage
.bottom
= psInfo
->height
;
689 MapDialogRect(hwndDlg
, &rcPage
);
690 TRACE("biggest page %ld %ld %ld %ld\n", rcPage
.left
, rcPage
.top
,
691 rcPage
.right
, rcPage
.bottom
);
693 if ( (rcPage
.right
- rcPage
.left
) != (rcOrigTab
.right
- rcOrigTab
.left
) )
695 if ( (rcPage
.bottom
- rcPage
.top
) != (rcOrigTab
.bottom
- rcOrigTab
.top
) )
701 /******************************************************************************
702 * PROPSHEET_IsTooSmallWizard
704 * Verify that the default property sheet is big enough.
706 static BOOL
PROPSHEET_IsTooSmallWizard(HWND hwndDlg
, PropSheetInfo
* psInfo
)
708 RECT rcSheetRect
, rcPage
, rcLine
, rcSheetClient
;
709 HWND hwndLine
= GetDlgItem(hwndDlg
, IDC_SUNKEN_LINE
);
710 PADDING_INFO padding
= PROPSHEET_GetPaddingInfoWizard(hwndDlg
, psInfo
);
712 GetClientRect(hwndDlg
, &rcSheetClient
);
713 GetWindowRect(hwndDlg
, &rcSheetRect
);
714 GetWindowRect(hwndLine
, &rcLine
);
716 /* Remove the space below the sunken line */
717 rcSheetClient
.bottom
-= (rcSheetRect
.bottom
- rcLine
.top
);
719 /* Remove the buffer zone all around the edge */
720 rcSheetClient
.bottom
-= (padding
.y
* 2);
721 rcSheetClient
.right
-= (padding
.x
* 2);
726 rcPage
.left
= psInfo
->x
;
727 rcPage
.top
= psInfo
->y
;
728 rcPage
.right
= psInfo
->width
;
729 rcPage
.bottom
= psInfo
->height
;
731 MapDialogRect(hwndDlg
, &rcPage
);
732 TRACE("biggest page %ld %ld %ld %ld\n", rcPage
.left
, rcPage
.top
,
733 rcPage
.right
, rcPage
.bottom
);
735 if (rcPage
.right
> rcSheetClient
.right
)
738 if (rcPage
.bottom
> rcSheetClient
.bottom
)
744 /******************************************************************************
745 * PROPSHEET_AdjustSize
747 * Resizes the property sheet and the tab control to fit the largest page.
749 static BOOL
PROPSHEET_AdjustSize(HWND hwndDlg
, PropSheetInfo
* psInfo
)
751 HWND hwndTabCtrl
= GetDlgItem(hwndDlg
, IDC_TABCONTROL
);
752 HWND hwndButton
= GetDlgItem(hwndDlg
, IDOK
);
754 int tabOffsetX
, tabOffsetY
, buttonHeight
;
755 PADDING_INFO padding
= PROPSHEET_GetPaddingInfo(hwndDlg
);
758 /* Get the height of buttons */
759 GetClientRect(hwndButton
, &rc
);
760 buttonHeight
= rc
.bottom
;
767 rc
.right
= psInfo
->width
;
768 rc
.bottom
= psInfo
->height
;
770 MapDialogRect(hwndDlg
, &rc
);
772 /* retrieve the dialog units */
773 units
.left
= units
.right
= 4;
774 units
.top
= units
.bottom
= 8;
775 MapDialogRect(hwndDlg
, &units
);
778 * Resize the tab control.
780 GetClientRect(hwndTabCtrl
,&tabRect
);
782 SendMessageW(hwndTabCtrl
, TCM_ADJUSTRECT
, FALSE
, (LPARAM
)&tabRect
);
784 if ((rc
.bottom
- rc
.top
) < (tabRect
.bottom
- tabRect
.top
))
786 rc
.bottom
= rc
.top
+ tabRect
.bottom
- tabRect
.top
;
787 psInfo
->height
= MulDiv((rc
.bottom
- rc
.top
),8,units
.top
);
790 if ((rc
.right
- rc
.left
) < (tabRect
.right
- tabRect
.left
))
792 rc
.right
= rc
.left
+ tabRect
.right
- tabRect
.left
;
793 psInfo
->width
= MulDiv((rc
.right
- rc
.left
),4,units
.left
);
796 SendMessageW(hwndTabCtrl
, TCM_ADJUSTRECT
, TRUE
, (LPARAM
)&rc
);
798 tabOffsetX
= -(rc
.left
);
799 tabOffsetY
= -(rc
.top
);
803 TRACE("setting tab %08lx, rc (0,0)-(%ld,%ld)\n",
804 (DWORD
)hwndTabCtrl
, rc
.right
, rc
.bottom
);
805 SetWindowPos(hwndTabCtrl
, 0, 0, 0, rc
.right
, rc
.bottom
,
806 SWP_NOMOVE
| SWP_NOZORDER
| SWP_NOACTIVATE
);
808 GetClientRect(hwndTabCtrl
, &rc
);
810 TRACE("tab client rc %ld %ld %ld %ld\n",
811 rc
.left
, rc
.top
, rc
.right
, rc
.bottom
);
813 rc
.right
+= ((padding
.x
* 2) + tabOffsetX
);
814 rc
.bottom
+= (buttonHeight
+ (3 * padding
.y
) + tabOffsetY
);
817 * Resize the property sheet.
819 TRACE("setting dialog %08lx, rc (0,0)-(%ld,%ld)\n",
820 (DWORD
)hwndDlg
, rc
.right
, rc
.bottom
);
821 SetWindowPos(hwndDlg
, 0, 0, 0, rc
.right
, rc
.bottom
,
822 SWP_NOMOVE
| SWP_NOZORDER
| SWP_NOACTIVATE
);
826 /******************************************************************************
827 * PROPSHEET_AdjustSizeWizard
829 * Resizes the property sheet to fit the largest page.
831 static BOOL
PROPSHEET_AdjustSizeWizard(HWND hwndDlg
, PropSheetInfo
* psInfo
)
833 HWND hwndButton
= GetDlgItem(hwndDlg
, IDCANCEL
);
834 HWND hwndLine
= GetDlgItem(hwndDlg
, IDC_SUNKEN_LINE
);
835 HWND hwndTabCtrl
= GetDlgItem(hwndDlg
, IDC_TABCONTROL
);
837 int buttonHeight
, lineHeight
;
838 PADDING_INFO padding
= PROPSHEET_GetPaddingInfoWizard(hwndDlg
, psInfo
);
841 /* Get the height of buttons */
842 GetClientRect(hwndButton
, &rc
);
843 buttonHeight
= rc
.bottom
;
845 GetClientRect(hwndLine
, &rc
);
846 lineHeight
= rc
.bottom
;
848 /* retrieve the dialog units */
849 units
.left
= units
.right
= 4;
850 units
.top
= units
.bottom
= 8;
851 MapDialogRect(hwndDlg
, &units
);
858 rc
.right
= psInfo
->width
;
859 rc
.bottom
= psInfo
->height
;
861 MapDialogRect(hwndDlg
, &rc
);
863 GetClientRect(hwndTabCtrl
,&tabRect
);
865 if ((rc
.bottom
- rc
.top
) < (tabRect
.bottom
- tabRect
.top
))
867 rc
.bottom
= rc
.top
+ tabRect
.bottom
- tabRect
.top
;
868 psInfo
->height
= MulDiv((rc
.bottom
- rc
.top
), 8, units
.top
);
871 if ((rc
.right
- rc
.left
) < (tabRect
.right
- tabRect
.left
))
873 rc
.right
= rc
.left
+ tabRect
.right
- tabRect
.left
;
874 psInfo
->width
= MulDiv((rc
.right
- rc
.left
), 4, units
.left
);
877 TRACE("Biggest page %ld %ld %ld %ld\n", rc
.left
, rc
.top
, rc
.right
, rc
.bottom
);
878 TRACE(" constants padx=%d, pady=%d, butH=%d, lH=%d\n",
879 padding
.x
, padding
.y
, buttonHeight
, lineHeight
);
882 rc
.right
+= (padding
.x
* 2);
883 rc
.bottom
+= (buttonHeight
+ lineHeight
);
884 if (psInfo
->ppshheader
.dwFlags
& (PSH_WIZARD97_OLD
| PSH_WIZARD97_NEW
))
885 rc
.bottom
+= (4 * padding
.y
);
887 rc
.bottom
+= (5 * padding
.y
);
890 * Resize the property sheet.
892 TRACE("setting dialog %08lx, rc (0,0)-(%ld,%ld)\n",
893 (DWORD
)hwndDlg
, rc
.right
, rc
.bottom
);
894 SetWindowPos(hwndDlg
, 0, 0, 0, rc
.right
, rc
.bottom
,
895 SWP_NOMOVE
| SWP_NOZORDER
| SWP_NOACTIVATE
);
899 /******************************************************************************
900 * PROPSHEET_AdjustButtons
902 * Adjusts the buttons' positions.
904 static BOOL
PROPSHEET_AdjustButtons(HWND hwndParent
, PropSheetInfo
* psInfo
)
906 HWND hwndButton
= GetDlgItem(hwndParent
, IDOK
);
910 int buttonWidth
, buttonHeight
;
911 PADDING_INFO padding
= PROPSHEET_GetPaddingInfo(hwndParent
);
913 if (psInfo
->hasApply
)
920 * Obtain the size of the buttons.
922 GetClientRect(hwndButton
, &rcSheet
);
923 buttonWidth
= rcSheet
.right
;
924 buttonHeight
= rcSheet
.bottom
;
927 * Get the size of the property sheet.
929 GetClientRect(hwndParent
, &rcSheet
);
932 * All buttons will be at this y coordinate.
934 y
= rcSheet
.bottom
- (padding
.y
+ buttonHeight
);
937 * Position OK button and make it default.
939 hwndButton
= GetDlgItem(hwndParent
, IDOK
);
941 x
= rcSheet
.right
- ((padding
.x
+ buttonWidth
) * num_buttons
);
943 SetWindowPos(hwndButton
, 0, x
, y
, 0, 0,
944 SWP_NOSIZE
| SWP_NOZORDER
| SWP_NOACTIVATE
);
946 SendMessageA(hwndParent
, DM_SETDEFID
, IDOK
, 0);
950 * Position Cancel button.
952 hwndButton
= GetDlgItem(hwndParent
, IDCANCEL
);
954 x
= rcSheet
.right
- ((padding
.x
+ buttonWidth
) * (num_buttons
- 1));
956 SetWindowPos(hwndButton
, 0, x
, y
, 0, 0,
957 SWP_NOSIZE
| SWP_NOZORDER
| SWP_NOACTIVATE
);
960 * Position Apply button.
962 hwndButton
= GetDlgItem(hwndParent
, IDC_APPLY_BUTTON
);
964 if (psInfo
->hasApply
)
967 x
= rcSheet
.right
- ((padding
.x
+ buttonWidth
) * 2);
969 x
= rcSheet
.right
- (padding
.x
+ buttonWidth
);
971 SetWindowPos(hwndButton
, 0, x
, y
, 0, 0,
972 SWP_NOSIZE
| SWP_NOZORDER
| SWP_NOACTIVATE
);
974 EnableWindow(hwndButton
, FALSE
);
977 ShowWindow(hwndButton
, SW_HIDE
);
980 * Position Help button.
982 hwndButton
= GetDlgItem(hwndParent
, IDHELP
);
986 x
= rcSheet
.right
- (padding
.x
+ buttonWidth
);
988 SetWindowPos(hwndButton
, 0, x
, y
, 0, 0,
989 SWP_NOSIZE
| SWP_NOZORDER
| SWP_NOACTIVATE
);
992 ShowWindow(hwndButton
, SW_HIDE
);
997 /******************************************************************************
998 * PROPSHEET_AdjustButtonsWizard
1000 * Adjusts the buttons' positions.
1002 static BOOL
PROPSHEET_AdjustButtonsWizard(HWND hwndParent
,
1003 PropSheetInfo
* psInfo
)
1005 HWND hwndButton
= GetDlgItem(hwndParent
, IDCANCEL
);
1006 HWND hwndLine
= GetDlgItem(hwndParent
, IDC_SUNKEN_LINE
);
1007 HWND hwndLineHeader
= GetDlgItem(hwndParent
, IDC_SUNKEN_LINEHEADER
);
1010 int num_buttons
= 3;
1011 int buttonWidth
, buttonHeight
, lineHeight
, lineWidth
;
1012 PADDING_INFO padding
= PROPSHEET_GetPaddingInfoWizard(hwndParent
, psInfo
);
1014 if (psInfo
->hasHelp
)
1018 * Obtain the size of the buttons.
1020 GetClientRect(hwndButton
, &rcSheet
);
1021 buttonWidth
= rcSheet
.right
;
1022 buttonHeight
= rcSheet
.bottom
;
1024 GetClientRect(hwndLine
, &rcSheet
);
1025 lineHeight
= rcSheet
.bottom
;
1028 * Get the size of the property sheet.
1030 GetClientRect(hwndParent
, &rcSheet
);
1033 * All buttons will be at this y coordinate.
1035 y
= rcSheet
.bottom
- (padding
.y
+ buttonHeight
);
1038 * Position the Next and the Finish buttons.
1040 hwndButton
= GetDlgItem(hwndParent
, IDC_NEXT_BUTTON
);
1042 x
= rcSheet
.right
- ((padding
.x
+ buttonWidth
) * (num_buttons
- 1));
1044 SetWindowPos(hwndButton
, 0, x
, y
, 0, 0,
1045 SWP_NOSIZE
| SWP_NOZORDER
| SWP_NOACTIVATE
);
1047 hwndButton
= GetDlgItem(hwndParent
, IDC_FINISH_BUTTON
);
1049 SetWindowPos(hwndButton
, 0, x
, y
, 0, 0,
1050 SWP_NOSIZE
| SWP_NOZORDER
| SWP_NOACTIVATE
);
1052 ShowWindow(hwndButton
, SW_HIDE
);
1055 * Position the Back button.
1057 hwndButton
= GetDlgItem(hwndParent
, IDC_BACK_BUTTON
);
1061 SetWindowPos(hwndButton
, 0, x
, y
, 0, 0,
1062 SWP_NOSIZE
| SWP_NOZORDER
| SWP_NOACTIVATE
);
1065 * Position the Cancel button.
1067 hwndButton
= GetDlgItem(hwndParent
, IDCANCEL
);
1069 x
= rcSheet
.right
- ((padding
.x
+ buttonWidth
) * (num_buttons
- 2));
1071 SetWindowPos(hwndButton
, 0, x
, y
, 0, 0,
1072 SWP_NOSIZE
| SWP_NOZORDER
| SWP_NOACTIVATE
);
1075 * Position Help button.
1077 hwndButton
= GetDlgItem(hwndParent
, IDHELP
);
1079 if (psInfo
->hasHelp
)
1081 x
= rcSheet
.right
- (padding
.x
+ buttonWidth
);
1083 SetWindowPos(hwndButton
, 0, x
, y
, 0, 0,
1084 SWP_NOSIZE
| SWP_NOZORDER
| SWP_NOACTIVATE
);
1087 ShowWindow(hwndButton
, SW_HIDE
);
1089 if (psInfo
->ppshheader
.dwFlags
& (PSH_WIZARD97_OLD
| PSH_WIZARD97_NEW
))
1093 * Position and resize the sunken line.
1096 y
= rcSheet
.bottom
- ((padding
.y
* 2) + buttonHeight
+ lineHeight
);
1098 lineWidth
= rcSheet
.right
- (padding
.x
* 2);
1100 SetWindowPos(hwndLine
, 0, x
, y
, lineWidth
, 2,
1101 SWP_NOZORDER
| SWP_NOACTIVATE
);
1104 * Position and resize the header sunken line.
1107 SetWindowPos(hwndLineHeader
, 0, 0, 0, rcSheet
.right
, 2,
1108 SWP_NOZORDER
| SWP_NOMOVE
| SWP_NOACTIVATE
);
1109 if (!(psInfo
->ppshheader
.dwFlags
& (PSH_WIZARD97_OLD
| PSH_WIZARD97_NEW
)))
1110 ShowWindow(hwndLineHeader
, SW_HIDE
);
1115 /******************************************************************************
1116 * PROPSHEET_GetPaddingInfo
1118 * Returns the layout information.
1120 static PADDING_INFO
PROPSHEET_GetPaddingInfo(HWND hwndDlg
)
1122 HWND hwndTab
= GetDlgItem(hwndDlg
, IDC_TABCONTROL
);
1125 PADDING_INFO padding
;
1127 GetWindowRect(hwndTab
, &rcTab
);
1132 ScreenToClient(hwndDlg
, &tl
);
1140 /******************************************************************************
1141 * PROPSHEET_GetPaddingInfoWizard
1143 * Returns the layout information.
1144 * Vertical spacing is the distance between the line and the buttons.
1145 * Do NOT use the Help button to gather padding information when it isn't mapped
1146 * (PSH_HASHELP), as app writers aren't forced to supply correct coordinates
1147 * for it in this case !
1148 * FIXME: I'm not sure about any other coordinate problems with these evil
1149 * buttons. Fix it in case additional problems appear or maybe calculate
1150 * a padding in a completely different way, as this is somewhat messy.
1152 static PADDING_INFO
PROPSHEET_GetPaddingInfoWizard(HWND hwndDlg
, const PropSheetInfo
*
1155 PADDING_INFO padding
;
1159 POINT ptButton
, ptLine
;
1162 if (psInfo
->hasHelp
)
1168 if (psInfo
->ppshheader
.dwFlags
& INTRNL_ANY_WIZARD
)
1170 idButton
= IDC_NEXT_BUTTON
;
1174 /* hopefully this is ok */
1175 idButton
= IDCANCEL
;
1179 hwndControl
= GetDlgItem(hwndDlg
, idButton
);
1180 GetWindowRect(hwndControl
, &rc
);
1182 ptButton
.x
= rc
.left
;
1183 ptButton
.y
= rc
.top
;
1185 ScreenToClient(hwndDlg
, &ptButton
);
1188 hwndControl
= GetDlgItem(hwndDlg
, IDC_SUNKEN_LINE
);
1189 GetWindowRect(hwndControl
, &rc
);
1192 ptLine
.y
= rc
.bottom
;
1194 ScreenToClient(hwndDlg
, &ptLine
);
1196 padding
.y
= ptButton
.y
- ptLine
.y
;
1199 ERR("padding negative ! Please report this !\n");
1201 /* this is most probably not correct, but the best we have now */
1202 padding
.x
= padding
.y
;
1206 /******************************************************************************
1207 * PROPSHEET_CreateTabControl
1209 * Insert the tabs in the tab control.
1211 static BOOL
PROPSHEET_CreateTabControl(HWND hwndParent
,
1212 PropSheetInfo
* psInfo
)
1214 HWND hwndTabCtrl
= GetDlgItem(hwndParent
, IDC_TABCONTROL
);
1220 item
.mask
= TCIF_TEXT
;
1221 item
.cchTextMax
= MAX_TABTEXT_LENGTH
;
1223 nTabs
= psInfo
->nPages
;
1226 * Set the image list for icons.
1228 if (psInfo
->hImageList
)
1230 SendMessageW(hwndTabCtrl
, TCM_SETIMAGELIST
, 0, (LPARAM
)psInfo
->hImageList
);
1233 SendMessageW(GetDlgItem(hwndTabCtrl
, IDC_TABCONTROL
), WM_SETREDRAW
, 0, 0);
1234 for (i
= 0; i
< nTabs
; i
++)
1236 if ( psInfo
->proppage
[i
].hasIcon
)
1238 item
.mask
|= TCIF_IMAGE
;
1239 item
.iImage
= iImage
++;
1243 item
.mask
&= ~TCIF_IMAGE
;
1246 item
.pszText
= (LPWSTR
) psInfo
->proppage
[i
].pszText
;
1247 SendMessageW(hwndTabCtrl
, TCM_INSERTITEMW
, (WPARAM
)i
, (LPARAM
)&item
);
1249 SendMessageW(GetDlgItem(hwndTabCtrl
, IDC_TABCONTROL
), WM_SETREDRAW
, 1, 0);
1254 * Get the size of an in-memory Template
1256 *( Based on the code of PROPSHEET_CollectPageInfo)
1257 * See also dialog.c/DIALOG_ParseTemplate32().
1260 static UINT
GetTemplateSize(DLGTEMPLATE
* pTemplate
)
1263 const WORD
* p
= (const WORD
*)pTemplate
;
1264 BOOL istemplateex
= (((MyDLGTEMPLATEEX
*)pTemplate
)->signature
== 0xFFFF);
1269 /* DLGTEMPLATEEX (not defined in any std. header file) */
1271 TRACE("is DLGTEMPLATEEX\n");
1273 p
++; /* signature */
1274 p
+= 2; /* help ID */
1275 p
+= 2; /* ext style */
1282 TRACE("is DLGTEMPLATE\n");
1284 p
+= 2; /* ext style */
1287 nrofitems
= (WORD
)*p
; p
++; /* nb items */
1303 TRACE("menu %s\n",debugstr_w((LPCWSTR
)p
));
1304 p
+= lstrlenW( (LPCWSTR
)p
) + 1;
1315 p
+= 2; /* 0xffff plus predefined window class ordinal value */
1318 TRACE("class %s\n",debugstr_w((LPCWSTR
)p
));
1319 p
+= lstrlenW( (LPCWSTR
)p
) + 1;
1324 TRACE("title %s\n",debugstr_w((LPCWSTR
)p
));
1325 p
+= lstrlenW((LPCWSTR
)p
) + 1;
1327 /* font, if DS_SETFONT set */
1328 if ((DS_SETFONT
& ((istemplateex
)? ((MyDLGTEMPLATEEX
*)pTemplate
)->style
:
1331 p
+=(istemplateex
)?3:1;
1332 TRACE("font %s\n",debugstr_w((LPCWSTR
)p
));
1333 p
+= lstrlenW( (LPCWSTR
)p
) + 1; /* the font name */
1336 /* now process the DLGITEMTEMPLATE(EX) structs (plus custom data)
1337 * that are following the DLGTEMPLATE(EX) data */
1338 TRACE("%d items\n",nrofitems
);
1339 while (nrofitems
> 0)
1341 p
= (WORD
*)(((DWORD
)p
+ 3) & ~3); /* DWORD align */
1344 p
+= (istemplateex
? sizeof(MyDLGITEMTEMPLATEEX
) : sizeof(DLGITEMTEMPLATE
))/sizeof(WORD
);
1353 TRACE("class ordinal 0x%08lx\n",*(DWORD
*)p
);
1357 TRACE("class %s\n",debugstr_w((LPCWSTR
)p
));
1358 p
+= lstrlenW( (LPCWSTR
)p
) + 1;
1362 /* check title text */
1369 TRACE("text ordinal 0x%08lx\n",*(DWORD
*)p
);
1373 TRACE("text %s\n",debugstr_w((LPCWSTR
)p
));
1374 p
+= lstrlenW( (LPCWSTR
)p
) + 1;
1377 p
+= *p
/ sizeof(WORD
) + 1; /* Skip extra data */
1381 TRACE("%p %p size 0x%08x\n",p
, (WORD
*)pTemplate
,sizeof(WORD
)*(p
- (WORD
*)pTemplate
));
1382 return (p
- (WORD
*)pTemplate
)*sizeof(WORD
);
1386 /******************************************************************************
1387 * PROPSHEET_CreatePage
1391 static BOOL
PROPSHEET_CreatePage(HWND hwndParent
,
1393 const PropSheetInfo
* psInfo
,
1394 LPCPROPSHEETPAGEW ppshpage
)
1396 DLGTEMPLATE
* pTemplate
;
1399 PADDING_INFO padding
;
1400 UINT pageWidth
,pageHeight
;
1404 TRACE("index %d\n", index
);
1406 if (ppshpage
== NULL
)
1411 if (ppshpage
->dwFlags
& PSP_DLGINDIRECT
)
1413 pTemplate
= (DLGTEMPLATE
*)ppshpage
->u
.pResource
;
1414 resSize
= GetTemplateSize(pTemplate
);
1416 else if(ppshpage
->dwFlags
& PSP_INTERNAL_UNICODE
)
1421 hResource
= FindResourceW(ppshpage
->hInstance
,
1422 ppshpage
->u
.pszTemplate
,
1427 resSize
= SizeofResource(ppshpage
->hInstance
, hResource
);
1429 hTemplate
= LoadResource(ppshpage
->hInstance
, hResource
);
1433 pTemplate
= (LPDLGTEMPLATEW
)LockResource(hTemplate
);
1435 * Make a copy of the dialog template to make it writable
1443 hResource
= FindResourceA(ppshpage
->hInstance
,
1444 (LPSTR
)ppshpage
->u
.pszTemplate
,
1449 resSize
= SizeofResource(ppshpage
->hInstance
, hResource
);
1451 hTemplate
= LoadResource(ppshpage
->hInstance
, hResource
);
1455 pTemplate
= (LPDLGTEMPLATEA
)LockResource(hTemplate
);
1457 * Make a copy of the dialog template to make it writable
1460 temp
= Alloc(resSize
);
1464 TRACE("copying pTemplate %p into temp %p (%ld)\n", pTemplate
, temp
, resSize
);
1465 memcpy(temp
, pTemplate
, resSize
);
1468 if (((MyDLGTEMPLATEEX
*)pTemplate
)->signature
== 0xFFFF)
1470 ((MyDLGTEMPLATEEX
*)pTemplate
)->style
|= WS_CHILD
| DS_CONTROL
;
1471 ((MyDLGTEMPLATEEX
*)pTemplate
)->style
&= ~DS_MODALFRAME
;
1472 ((MyDLGTEMPLATEEX
*)pTemplate
)->style
&= ~WS_CAPTION
;
1473 ((MyDLGTEMPLATEEX
*)pTemplate
)->style
&= ~WS_SYSMENU
;
1474 ((MyDLGTEMPLATEEX
*)pTemplate
)->style
&= ~WS_POPUP
;
1475 ((MyDLGTEMPLATEEX
*)pTemplate
)->style
&= ~WS_DISABLED
;
1476 ((MyDLGTEMPLATEEX
*)pTemplate
)->style
&= ~WS_VISIBLE
;
1477 ((MyDLGTEMPLATEEX
*)pTemplate
)->style
&= ~WS_THICKFRAME
;
1479 ((MyDLGTEMPLATEEX
*)pTemplate
)->exStyle
|= WS_EX_CONTROLPARENT
;
1483 pTemplate
->style
|= WS_CHILD
| DS_CONTROL
;
1484 pTemplate
->style
&= ~DS_MODALFRAME
;
1485 pTemplate
->style
&= ~WS_CAPTION
;
1486 pTemplate
->style
&= ~WS_SYSMENU
;
1487 pTemplate
->style
&= ~WS_POPUP
;
1488 pTemplate
->style
&= ~WS_DISABLED
;
1489 pTemplate
->style
&= ~WS_VISIBLE
;
1490 pTemplate
->style
&= ~WS_THICKFRAME
;
1492 pTemplate
->dwExtendedStyle
|= WS_EX_CONTROLPARENT
;
1495 if (psInfo
->proppage
[index
].useCallback
)
1496 (*(ppshpage
->pfnCallback
))(0, PSPCB_CREATE
,
1497 (LPPROPSHEETPAGEW
)ppshpage
);
1499 if(ppshpage
->dwFlags
& PSP_INTERNAL_UNICODE
)
1500 hwndPage
= CreateDialogIndirectParamW(ppshpage
->hInstance
,
1503 ppshpage
->pfnDlgProc
,
1506 hwndPage
= CreateDialogIndirectParamA(ppshpage
->hInstance
,
1509 ppshpage
->pfnDlgProc
,
1511 /* Free a no more needed copy */
1515 psInfo
->proppage
[index
].hwndPage
= hwndPage
;
1517 /* NOTE: This code should be most probably moved to PROPSHEET_SetCurSel,
1518 * but until it will be proved with test case it's left here. */
1519 if (psInfo
->ppshheader
.dwFlags
& INTRNL_ANY_WIZARD
) {
1524 rc
.left
= psInfo
->x
;
1526 rc
.right
= psInfo
->width
;
1527 rc
.bottom
= psInfo
->height
;
1529 MapDialogRect(hwndParent
, &rc
);
1531 pageWidth
= rc
.right
- rc
.left
;
1532 pageHeight
= rc
.bottom
- rc
.top
;
1534 padding
= PROPSHEET_GetPaddingInfoWizard(hwndParent
, psInfo
);
1535 TRACE("setting page %08lx, rc (%ld,%ld)-(%ld,%ld) w=%d, h=%d, padx=%d, pady=%d\n",
1536 (DWORD
)hwndPage
, rc
.left
, rc
.top
, rc
.right
, rc
.bottom
,
1537 pageWidth
, pageHeight
, padding
.x
, padding
.y
);
1539 if (psInfo
->ppshheader
.dwFlags
& (PSH_WIZARD97_NEW
| PSH_WIZARD97_OLD
) &&
1540 psInfo
->ppshheader
.dwFlags
& PSH_HEADER
)
1542 hwndChild
= GetDlgItem(hwndParent
, IDC_SUNKEN_LINEHEADER
);
1544 GetClientRect(hwndChild
, &r
);
1545 MapWindowPoints(hwndChild
, hwndParent
, (LPPOINT
) &r
, 2);
1546 offsety
= (ppshpage
->dwFlags
& PSP_HIDEHEADER
)?0:r
.bottom
+ 1;
1549 SetWindowPos(hwndPage
, HWND_TOP
,
1550 rc
.left
+ padding
.x
/2,
1551 rc
.top
+ padding
.y
/2 + offsety
,
1552 pageWidth
, pageHeight
- offsety
, 0);
1558 /******************************************************************************
1559 * PROPSHEET_LoadWizardBitmaps
1561 * Loads the watermark and header bitmaps for a wizard.
1563 static VOID
PROPSHEET_LoadWizardBitmaps(PropSheetInfo
*psInfo
)
1565 if (psInfo
->ppshheader
.dwFlags
& (PSH_WIZARD97_NEW
| PSH_WIZARD97_OLD
))
1567 /* if PSH_USEHBMWATERMARK is not set, load the resource from pszbmWatermark
1568 and put the HBITMAP in hbmWatermark. Thus all the rest of the code always
1569 considers hbmWatermark as valid. */
1570 if ((psInfo
->ppshheader
.dwFlags
& PSH_WATERMARK
) &&
1571 !(psInfo
->ppshheader
.dwFlags
& PSH_USEHBMWATERMARK
))
1573 ((PropSheetInfo
*)psInfo
)->ppshheader
.u4
.hbmWatermark
=
1574 CreateMappedBitmap(psInfo
->ppshheader
.hInstance
, (INT
)psInfo
->ppshheader
.u4
.pszbmWatermark
, 0, NULL
, 0);
1577 /* Same behavior as for watermarks */
1578 if ((psInfo
->ppshheader
.dwFlags
& PSH_HEADER
) &&
1579 !(psInfo
->ppshheader
.dwFlags
& PSH_USEHBMHEADER
))
1581 ((PropSheetInfo
*)psInfo
)->ppshheader
.u5
.hbmHeader
=
1582 CreateMappedBitmap(psInfo
->ppshheader
.hInstance
, (INT
)psInfo
->ppshheader
.u5
.pszbmHeader
, 0, NULL
, 0);
1588 /******************************************************************************
1589 * PROPSHEET_ShowPage
1591 * Displays or creates the specified page.
1593 static BOOL
PROPSHEET_ShowPage(HWND hwndDlg
, int index
, PropSheetInfo
* psInfo
)
1596 HWND hwndLineHeader
;
1597 LPCPROPSHEETPAGEW ppshpage
;
1599 TRACE("active_page %d, index %d\n", psInfo
->active_page
, index
);
1600 if (index
== psInfo
->active_page
)
1602 if (GetTopWindow(hwndDlg
) != psInfo
->proppage
[index
].hwndPage
)
1603 SetWindowPos(psInfo
->proppage
[index
].hwndPage
, HWND_TOP
, 0, 0, 0, 0, SWP_NOSIZE
| SWP_NOMOVE
);
1607 ppshpage
= (LPCPROPSHEETPAGEW
)psInfo
->proppage
[index
].hpage
;
1608 if (psInfo
->proppage
[index
].hwndPage
== 0)
1610 PROPSHEET_CreatePage(hwndDlg
, index
, psInfo
, ppshpage
);
1613 if ((psInfo
->ppshheader
.dwFlags
& INTRNL_ANY_WIZARD
) &&
1614 (ppshpage
->dwFlags
& PSP_USETITLE
))
1616 PROPSHEET_SetTitleW(hwndDlg
, psInfo
->ppshheader
.dwFlags
,
1617 psInfo
->proppage
[index
].pszText
);
1620 if (psInfo
->active_page
!= -1)
1621 ShowWindow(psInfo
->proppage
[psInfo
->active_page
].hwndPage
, SW_HIDE
);
1623 ShowWindow(psInfo
->proppage
[index
].hwndPage
, SW_SHOW
);
1625 /* Synchronize current selection with tab control
1626 * It seems to be needed even in case of PSH_WIZARD (no tab controls there) */
1627 hwndTabCtrl
= GetDlgItem(hwndDlg
, IDC_TABCONTROL
);
1628 SendMessageW(hwndTabCtrl
, TCM_SETCURSEL
, index
, 0);
1630 psInfo
->active_page
= index
;
1631 psInfo
->activeValid
= TRUE
;
1633 if (psInfo
->ppshheader
.dwFlags
& (PSH_WIZARD97_OLD
| PSH_WIZARD97_NEW
) )
1635 hwndLineHeader
= GetDlgItem(hwndDlg
, IDC_SUNKEN_LINEHEADER
);
1636 ppshpage
= (LPCPROPSHEETPAGEW
)psInfo
->proppage
[index
].hpage
;
1638 if ((ppshpage
->dwFlags
& PSP_HIDEHEADER
) || (!(psInfo
->ppshheader
.dwFlags
& PSH_HEADER
)) )
1639 ShowWindow(hwndLineHeader
, SW_HIDE
);
1641 ShowWindow(hwndLineHeader
, SW_SHOW
);
1644 InvalidateRgn(hwndDlg
, NULL
, TRUE
);
1645 UpdateWindow(hwndDlg
);
1650 /******************************************************************************
1653 static BOOL
PROPSHEET_Back(HWND hwndDlg
)
1657 PropSheetInfo
* psInfo
= (PropSheetInfo
*) GetPropW(hwndDlg
,
1662 TRACE("active_page %d\n", psInfo
->active_page
);
1663 if (psInfo
->active_page
< 0)
1666 psn
.hdr
.code
= PSN_WIZBACK
;
1667 psn
.hdr
.hwndFrom
= hwndDlg
;
1671 hwndPage
= psInfo
->proppage
[psInfo
->active_page
].hwndPage
;
1673 result
= SendMessageW(hwndPage
, WM_NOTIFY
, 0, (LPARAM
) &psn
);
1676 else if (result
== 0)
1677 idx
= psInfo
->active_page
- 1;
1679 idx
= PROPSHEET_FindPageByResId(psInfo
, result
);
1681 if (idx
>= 0 && idx
< psInfo
->nPages
)
1683 if (PROPSHEET_CanSetCurSel(hwndDlg
))
1684 PROPSHEET_SetCurSel(hwndDlg
, idx
, -1, 0);
1689 /******************************************************************************
1692 static BOOL
PROPSHEET_Next(HWND hwndDlg
)
1696 LRESULT msgResult
= 0;
1697 PropSheetInfo
* psInfo
= (PropSheetInfo
*) GetPropW(hwndDlg
,
1701 TRACE("active_page %d\n", psInfo
->active_page
);
1702 if (psInfo
->active_page
< 0)
1705 psn
.hdr
.code
= PSN_WIZNEXT
;
1706 psn
.hdr
.hwndFrom
= hwndDlg
;
1710 hwndPage
= psInfo
->proppage
[psInfo
->active_page
].hwndPage
;
1712 msgResult
= SendMessageA(hwndPage
, WM_NOTIFY
, 0, (LPARAM
) &psn
);
1713 if (msgResult
== -1)
1715 else if (msgResult
== 0)
1716 idx
= psInfo
->active_page
+ 1;
1718 idx
= PROPSHEET_FindPageByResId(psInfo
, msgResult
);
1720 if (idx
< psInfo
->nPages
)
1722 if (PROPSHEET_CanSetCurSel(hwndDlg
) != FALSE
)
1723 PROPSHEET_SetCurSel(hwndDlg
, idx
, 1, 0);
1729 /******************************************************************************
1732 static BOOL
PROPSHEET_Finish(HWND hwndDlg
)
1736 LRESULT msgResult
= 0;
1737 PropSheetInfo
* psInfo
= (PropSheetInfo
*) GetPropW(hwndDlg
,
1740 TRACE("active_page %d\n", psInfo
->active_page
);
1741 if (psInfo
->active_page
< 0)
1744 psn
.hdr
.code
= PSN_WIZFINISH
;
1745 psn
.hdr
.hwndFrom
= hwndDlg
;
1749 hwndPage
= psInfo
->proppage
[psInfo
->active_page
].hwndPage
;
1751 msgResult
= SendMessageW(hwndPage
, WM_NOTIFY
, 0, (LPARAM
) &psn
);
1753 TRACE("msg result %ld\n", msgResult
);
1758 if (psInfo
->isModeless
)
1759 psInfo
->activeValid
= FALSE
;
1761 EndDialog(hwndDlg
, TRUE
);
1766 /******************************************************************************
1769 static BOOL
PROPSHEET_Apply(HWND hwndDlg
, LPARAM lParam
)
1774 PropSheetInfo
* psInfo
= (PropSheetInfo
*) GetPropW(hwndDlg
,
1777 TRACE("active_page %d\n", psInfo
->active_page
);
1778 if (psInfo
->active_page
< 0)
1781 psn
.hdr
.hwndFrom
= hwndDlg
;
1787 * Send PSN_KILLACTIVE to the current page.
1789 psn
.hdr
.code
= PSN_KILLACTIVE
;
1791 hwndPage
= psInfo
->proppage
[psInfo
->active_page
].hwndPage
;
1793 if (SendMessageA(hwndPage
, WM_NOTIFY
, 0, (LPARAM
) &psn
) != FALSE
)
1797 * Send PSN_APPLY to all pages.
1799 psn
.hdr
.code
= PSN_APPLY
;
1800 psn
.lParam
= lParam
;
1802 for (i
= 0; i
< psInfo
->nPages
; i
++)
1804 hwndPage
= psInfo
->proppage
[i
].hwndPage
;
1807 switch (SendMessageA(hwndPage
, WM_NOTIFY
, 0, (LPARAM
) &psn
))
1809 case PSNRET_INVALID
:
1810 PROPSHEET_ShowPage(hwndDlg
, i
, psInfo
);
1812 case PSNRET_INVALID_NOCHANGEPAGE
:
1820 psInfo
->activeValid
= FALSE
;
1822 else if(psInfo
->active_page
>= 0)
1824 psn
.hdr
.code
= PSN_SETACTIVE
;
1826 hwndPage
= psInfo
->proppage
[psInfo
->active_page
].hwndPage
;
1827 SendMessageA(hwndPage
, WM_NOTIFY
, 0, (LPARAM
) &psn
);
1833 /******************************************************************************
1836 static void PROPSHEET_Cancel(HWND hwndDlg
, LPARAM lParam
)
1838 PropSheetInfo
* psInfo
= (PropSheetInfo
*) GetPropW(hwndDlg
,
1844 TRACE("active_page %d\n", psInfo
->active_page
);
1845 if (psInfo
->active_page
< 0)
1848 hwndPage
= psInfo
->proppage
[psInfo
->active_page
].hwndPage
;
1849 psn
.hdr
.code
= PSN_QUERYCANCEL
;
1850 psn
.hdr
.hwndFrom
= hwndDlg
;
1854 if (SendMessageA(hwndPage
, WM_NOTIFY
, 0, (LPARAM
) &psn
))
1857 psn
.hdr
.code
= PSN_RESET
;
1858 psn
.lParam
= lParam
;
1860 for (i
= 0; i
< psInfo
->nPages
; i
++)
1862 hwndPage
= psInfo
->proppage
[i
].hwndPage
;
1865 SendMessageA(hwndPage
, WM_NOTIFY
, 0, (LPARAM
) &psn
);
1868 if (psInfo
->isModeless
)
1870 /* makes PSM_GETCURRENTPAGEHWND return NULL */
1871 psInfo
->activeValid
= FALSE
;
1874 EndDialog(hwndDlg
, FALSE
);
1877 /******************************************************************************
1880 static void PROPSHEET_Help(HWND hwndDlg
)
1882 PropSheetInfo
* psInfo
= (PropSheetInfo
*) GetPropW(hwndDlg
,
1887 TRACE("active_page %d\n", psInfo
->active_page
);
1888 if (psInfo
->active_page
< 0)
1891 hwndPage
= psInfo
->proppage
[psInfo
->active_page
].hwndPage
;
1892 psn
.hdr
.code
= PSN_HELP
;
1893 psn
.hdr
.hwndFrom
= hwndDlg
;
1897 SendMessageA(hwndPage
, WM_NOTIFY
, 0, (LPARAM
) &psn
);
1900 /******************************************************************************
1903 static void PROPSHEET_Changed(HWND hwndDlg
, HWND hwndDirtyPage
)
1906 PropSheetInfo
* psInfo
= (PropSheetInfo
*) GetPropW(hwndDlg
,
1910 if (!psInfo
) return;
1912 * Set the dirty flag of this page.
1914 for (i
= 0; i
< psInfo
->nPages
; i
++)
1916 if (psInfo
->proppage
[i
].hwndPage
== hwndDirtyPage
)
1917 psInfo
->proppage
[i
].isDirty
= TRUE
;
1921 * Enable the Apply button.
1923 if (psInfo
->hasApply
)
1925 HWND hwndApplyBtn
= GetDlgItem(hwndDlg
, IDC_APPLY_BUTTON
);
1927 EnableWindow(hwndApplyBtn
, TRUE
);
1931 /******************************************************************************
1932 * PROPSHEET_UnChanged
1934 static void PROPSHEET_UnChanged(HWND hwndDlg
, HWND hwndCleanPage
)
1937 BOOL noPageDirty
= TRUE
;
1938 HWND hwndApplyBtn
= GetDlgItem(hwndDlg
, IDC_APPLY_BUTTON
);
1939 PropSheetInfo
* psInfo
= (PropSheetInfo
*) GetPropW(hwndDlg
,
1943 if ( !psInfo
) return;
1944 for (i
= 0; i
< psInfo
->nPages
; i
++)
1946 /* set the specified page as clean */
1947 if (psInfo
->proppage
[i
].hwndPage
== hwndCleanPage
)
1948 psInfo
->proppage
[i
].isDirty
= FALSE
;
1950 /* look to see if there's any dirty pages */
1951 if (psInfo
->proppage
[i
].isDirty
)
1952 noPageDirty
= FALSE
;
1956 * Disable Apply button.
1959 EnableWindow(hwndApplyBtn
, FALSE
);
1962 /******************************************************************************
1963 * PROPSHEET_PressButton
1965 static void PROPSHEET_PressButton(HWND hwndDlg
, int buttonID
)
1967 TRACE("buttonID %d\n", buttonID
);
1970 case PSBTN_APPLYNOW
:
1971 PROPSHEET_DoCommand(hwndDlg
, IDC_APPLY_BUTTON
);
1974 PROPSHEET_Back(hwndDlg
);
1977 PROPSHEET_DoCommand(hwndDlg
, IDCANCEL
);
1980 PROPSHEET_Finish(hwndDlg
);
1983 PROPSHEET_DoCommand(hwndDlg
, IDHELP
);
1986 PROPSHEET_Next(hwndDlg
);
1989 PROPSHEET_DoCommand(hwndDlg
, IDOK
);
1992 FIXME("Invalid button index %d\n", buttonID
);
1997 /*************************************************************************
1998 * BOOL PROPSHEET_CanSetCurSel [Internal]
2000 * Test whether the current page can be changed by sending a PSN_KILLACTIVE
2003 * hwndDlg [I] handle to a Dialog hWnd
2006 * TRUE if Current Selection can change
2010 static BOOL
PROPSHEET_CanSetCurSel(HWND hwndDlg
)
2012 PropSheetInfo
* psInfo
= (PropSheetInfo
*) GetPropW(hwndDlg
,
2018 TRACE("active_page %d\n", psInfo
->active_page
);
2025 if (psInfo
->active_page
< 0)
2032 * Notify the current page.
2034 hwndPage
= psInfo
->proppage
[psInfo
->active_page
].hwndPage
;
2035 psn
.hdr
.code
= PSN_KILLACTIVE
;
2036 psn
.hdr
.hwndFrom
= hwndDlg
;
2040 res
= !SendMessageA(hwndPage
, WM_NOTIFY
, 0, (LPARAM
) &psn
);
2043 TRACE("<-- %d\n", res
);
2047 /******************************************************************************
2048 * PROPSHEET_SetCurSel
2050 static BOOL
PROPSHEET_SetCurSel(HWND hwndDlg
,
2053 HPROPSHEETPAGE hpage
2056 PropSheetInfo
* psInfo
= (PropSheetInfo
*) GetPropW(hwndDlg
, PropSheetInfoStr
);
2057 HWND hwndHelp
= GetDlgItem(hwndDlg
, IDHELP
);
2058 HWND hwndTabControl
= GetDlgItem(hwndDlg
, IDC_TABCONTROL
);
2060 TRACE("index %d, skipdir %d, hpage %p\n", index
, skipdir
, hpage
);
2061 /* hpage takes precedence over index */
2063 index
= PROPSHEET_GetPageIndex(hpage
, psInfo
);
2065 if (index
< 0 || index
>= psInfo
->nPages
)
2067 TRACE("Could not find page to select!\n");
2077 SendMessageW(hwndTabControl
, TCM_SETCURSEL
, index
, 0);
2079 psn
.hdr
.code
= PSN_SETACTIVE
;
2080 psn
.hdr
.hwndFrom
= hwndDlg
;
2084 if (!psInfo
->proppage
[index
].hwndPage
) {
2085 LPCPROPSHEETPAGEW ppshpage
= (LPCPROPSHEETPAGEW
)psInfo
->proppage
[index
].hpage
;
2086 PROPSHEET_CreatePage(hwndDlg
, index
, psInfo
, ppshpage
);
2089 /* NOTE: The resizing happens every time the page is selected and
2090 * not only when it's created (some applications depend on it). */
2091 if (!(psInfo
->ppshheader
.dwFlags
& INTRNL_ANY_WIZARD
)) {
2093 * Ask the Tab control to reduce the client rectangle to that
2096 PROPSHEET_GetPageRect(psInfo
, hwndDlg
, &rc
);
2097 TRACE("setting page %p, rc (%ld,%ld)-(%ld,%ld) w=%ld, h=%ld\n",
2098 psInfo
->proppage
[index
].hwndPage
, rc
.left
, rc
.top
, rc
.right
, rc
.bottom
,
2099 rc
.right
- rc
.left
, rc
.bottom
- rc
.top
);
2100 SetWindowPos(psInfo
->proppage
[index
].hwndPage
, HWND_TOP
,
2102 rc
.right
- rc
.left
, rc
.bottom
- rc
.top
, 0);
2105 result
= SendMessageW(psInfo
->proppage
[index
].hwndPage
, WM_NOTIFY
, 0, (LPARAM
) &psn
);
2112 WARN("Tried to skip before first property sheet page!\n");
2115 if (index
>= psInfo
->nPages
) {
2116 WARN("Tried to skip after last property sheet page!\n");
2117 index
= psInfo
->nPages
-1;
2121 else if (result
!= 0)
2123 int old_index
= index
;
2124 index
= PROPSHEET_FindPageByResId(psInfo
, result
);
2125 if(index
>= psInfo
->nPages
) {
2127 WARN("Tried to skip to nonexistant page by res id\n");
2134 * Display the new page.
2136 PROPSHEET_ShowPage(hwndDlg
, index
, psInfo
);
2138 if (psInfo
->proppage
[index
].hasHelp
)
2139 EnableWindow(hwndHelp
, TRUE
);
2141 EnableWindow(hwndHelp
, FALSE
);
2146 /******************************************************************************
2147 * PROPSHEET_SetCurSelId
2149 * Selects the page, specified by resource id.
2151 static void PROPSHEET_SetCurSelId(HWND hwndDlg
, int id
)
2154 PropSheetInfo
* psInfo
=
2155 (PropSheetInfo
*) GetPropW(hwndDlg
, PropSheetInfoStr
);
2157 idx
= PROPSHEET_FindPageByResId(psInfo
, id
);
2158 if (idx
< psInfo
->nPages
)
2160 if (PROPSHEET_CanSetCurSel(hwndDlg
) != FALSE
)
2161 PROPSHEET_SetCurSel(hwndDlg
, idx
, 1, 0);
2165 /******************************************************************************
2166 * PROPSHEET_SetTitleA
2168 static void PROPSHEET_SetTitleA(HWND hwndDlg
, DWORD dwStyle
, LPCSTR lpszText
)
2170 if(HIWORD(lpszText
))
2173 MultiByteToWideChar(CP_ACP
, 0, lpszText
, -1,
2174 szTitle
, sizeof(szTitle
));
2175 PROPSHEET_SetTitleW(hwndDlg
, dwStyle
, szTitle
);
2179 PROPSHEET_SetTitleW(hwndDlg
, dwStyle
, (LPCWSTR
)lpszText
);
2183 /******************************************************************************
2184 * PROPSHEET_SetTitleW
2186 static void PROPSHEET_SetTitleW(HWND hwndDlg
, DWORD dwStyle
, LPCWSTR lpszText
)
2188 PropSheetInfo
* psInfo
= (PropSheetInfo
*) GetPropW(hwndDlg
, PropSheetInfoStr
);
2191 TRACE("'%s' (style %08lx)\n", debugstr_w(lpszText
), dwStyle
);
2192 if (HIWORD(lpszText
) == 0) {
2193 if (!LoadStringW(psInfo
->ppshheader
.hInstance
,
2194 LOWORD(lpszText
), szTitle
, sizeof(szTitle
)-sizeof(WCHAR
)))
2198 if (dwStyle
& PSH_PROPTITLE
)
2201 int lentitle
= strlenW(lpszText
);
2202 int lenprop
= strlenW(psInfo
->strPropertiesFor
);
2204 dest
= Alloc( (lentitle
+ lenprop
+ 1)*sizeof (WCHAR
));
2205 strcpyW(dest
, psInfo
->strPropertiesFor
);
2206 strcatW(dest
, lpszText
);
2208 SetWindowTextW(hwndDlg
, dest
);
2212 SetWindowTextW(hwndDlg
, lpszText
);
2215 /******************************************************************************
2216 * PROPSHEET_SetFinishTextA
2218 static void PROPSHEET_SetFinishTextA(HWND hwndDlg
, LPCSTR lpszText
)
2220 HWND hwndButton
= GetDlgItem(hwndDlg
, IDC_FINISH_BUTTON
);
2222 TRACE("'%s'\n", lpszText
);
2223 /* Set text, show and enable the Finish button */
2224 SetWindowTextA(hwndButton
, lpszText
);
2225 ShowWindow(hwndButton
, SW_SHOW
);
2226 EnableWindow(hwndButton
, TRUE
);
2228 /* Make it default pushbutton */
2229 SendMessageA(hwndDlg
, DM_SETDEFID
, IDC_FINISH_BUTTON
, 0);
2231 /* Hide Back button */
2232 hwndButton
= GetDlgItem(hwndDlg
, IDC_BACK_BUTTON
);
2233 ShowWindow(hwndButton
, SW_HIDE
);
2235 /* Hide Next button */
2236 hwndButton
= GetDlgItem(hwndDlg
, IDC_NEXT_BUTTON
);
2237 ShowWindow(hwndButton
, SW_HIDE
);
2240 /******************************************************************************
2241 * PROPSHEET_SetFinishTextW
2243 static void PROPSHEET_SetFinishTextW(HWND hwndDlg
, LPCWSTR lpszText
)
2245 HWND hwndButton
= GetDlgItem(hwndDlg
, IDC_FINISH_BUTTON
);
2247 TRACE("'%s'\n", debugstr_w(lpszText
));
2248 /* Set text, show and enable the Finish button */
2249 SetWindowTextW(hwndButton
, lpszText
);
2250 ShowWindow(hwndButton
, SW_SHOW
);
2251 EnableWindow(hwndButton
, TRUE
);
2253 /* Make it default pushbutton */
2254 SendMessageW(hwndDlg
, DM_SETDEFID
, IDC_FINISH_BUTTON
, 0);
2256 /* Hide Back button */
2257 hwndButton
= GetDlgItem(hwndDlg
, IDC_BACK_BUTTON
);
2258 ShowWindow(hwndButton
, SW_HIDE
);
2260 /* Hide Next button */
2261 hwndButton
= GetDlgItem(hwndDlg
, IDC_NEXT_BUTTON
);
2262 ShowWindow(hwndButton
, SW_HIDE
);
2265 /******************************************************************************
2266 * PROPSHEET_QuerySiblings
2268 static LRESULT
PROPSHEET_QuerySiblings(HWND hwndDlg
,
2269 WPARAM wParam
, LPARAM lParam
)
2273 LRESULT msgResult
= 0;
2274 PropSheetInfo
* psInfo
= (PropSheetInfo
*) GetPropW(hwndDlg
,
2277 while ((i
< psInfo
->nPages
) && (msgResult
== 0))
2279 hwndPage
= psInfo
->proppage
[i
].hwndPage
;
2280 msgResult
= SendMessageA(hwndPage
, PSM_QUERYSIBLINGS
, wParam
, lParam
);
2288 /******************************************************************************
2291 static BOOL
PROPSHEET_AddPage(HWND hwndDlg
,
2292 HPROPSHEETPAGE hpage
)
2294 PropSheetInfo
* psInfo
= (PropSheetInfo
*) GetPropW(hwndDlg
,
2296 HWND hwndTabControl
= GetDlgItem(hwndDlg
, IDC_TABCONTROL
);
2298 LPCPROPSHEETPAGEW ppsp
= (LPCPROPSHEETPAGEW
)hpage
;
2300 TRACE("hpage %p\n", hpage
);
2302 * Allocate and fill in a new PropPageInfo entry.
2304 psInfo
->proppage
= (PropPageInfo
*) ReAlloc(psInfo
->proppage
,
2305 sizeof(PropPageInfo
) *
2306 (psInfo
->nPages
+ 1));
2307 if (!PROPSHEET_CollectPageInfo(ppsp
, psInfo
, psInfo
->nPages
))
2310 psInfo
->proppage
[psInfo
->nPages
].hpage
= hpage
;
2312 if (ppsp
->dwFlags
& PSP_PREMATURE
)
2314 /* Create the page but don't show it */
2315 PROPSHEET_CreatePage(hwndDlg
, psInfo
->nPages
, psInfo
, ppsp
);
2319 * Add a new tab to the tab control.
2321 item
.mask
= TCIF_TEXT
;
2322 item
.pszText
= (LPWSTR
) psInfo
->proppage
[psInfo
->nPages
].pszText
;
2323 item
.cchTextMax
= MAX_TABTEXT_LENGTH
;
2325 if (psInfo
->hImageList
)
2327 SendMessageW(hwndTabControl
, TCM_SETIMAGELIST
, 0, (LPARAM
)psInfo
->hImageList
);
2330 if ( psInfo
->proppage
[psInfo
->nPages
].hasIcon
)
2332 item
.mask
|= TCIF_IMAGE
;
2333 item
.iImage
= psInfo
->nPages
;
2336 SendMessageW(hwndTabControl
, TCM_INSERTITEMW
, psInfo
->nPages
+ 1,
2341 /* If it is the only page - show it */
2342 if(psInfo
->nPages
== 1)
2343 PROPSHEET_SetCurSel(hwndDlg
, 0, 1, 0);
2347 /******************************************************************************
2348 * PROPSHEET_RemovePage
2350 static BOOL
PROPSHEET_RemovePage(HWND hwndDlg
,
2352 HPROPSHEETPAGE hpage
)
2354 PropSheetInfo
* psInfo
= (PropSheetInfo
*) GetPropW(hwndDlg
,
2356 HWND hwndTabControl
= GetDlgItem(hwndDlg
, IDC_TABCONTROL
);
2357 PropPageInfo
* oldPages
;
2359 TRACE("index %d, hpage %p\n", index
, hpage
);
2364 * hpage takes precedence over index.
2368 index
= PROPSHEET_GetPageIndex(hpage
, psInfo
);
2371 /* Make sure that index is within range */
2372 if (index
< 0 || index
>= psInfo
->nPages
)
2374 TRACE("Could not find page to remove!\n");
2378 TRACE("total pages %d removing page %d active page %d\n",
2379 psInfo
->nPages
, index
, psInfo
->active_page
);
2381 * Check if we're removing the active page.
2383 if (index
== psInfo
->active_page
)
2385 if (psInfo
->nPages
> 1)
2389 /* activate previous page */
2390 PROPSHEET_SetCurSel(hwndDlg
, index
- 1, -1, 0);
2394 /* activate the next page */
2395 PROPSHEET_SetCurSel(hwndDlg
, index
+ 1, 1, 0);
2396 psInfo
->active_page
= index
;
2401 psInfo
->active_page
= -1;
2402 if (!psInfo
->isModeless
)
2404 EndDialog(hwndDlg
, FALSE
);
2409 else if (index
< psInfo
->active_page
)
2410 psInfo
->active_page
--;
2412 /* Destroy page dialog window */
2413 DestroyWindow(psInfo
->proppage
[index
].hwndPage
);
2415 /* Free page resources */
2416 if(psInfo
->proppage
[index
].hpage
)
2418 PROPSHEETPAGEW
* psp
= (PROPSHEETPAGEW
*)psInfo
->proppage
[index
].hpage
;
2420 if ((psp
->dwFlags
& PSP_USETITLE
) && psInfo
->proppage
[index
].pszText
)
2421 HeapFree(GetProcessHeap(), 0, (LPVOID
)psInfo
->proppage
[index
].pszText
);
2423 DestroyPropertySheetPage(psInfo
->proppage
[index
].hpage
);
2426 /* Remove the tab */
2427 SendMessageW(hwndTabControl
, TCM_DELETEITEM
, index
, 0);
2429 oldPages
= psInfo
->proppage
;
2431 psInfo
->proppage
= Alloc(sizeof(PropPageInfo
) * psInfo
->nPages
);
2434 memcpy(&psInfo
->proppage
[0], &oldPages
[0], index
* sizeof(PropPageInfo
));
2436 if (index
< psInfo
->nPages
)
2437 memcpy(&psInfo
->proppage
[index
], &oldPages
[index
+ 1],
2438 (psInfo
->nPages
- index
) * sizeof(PropPageInfo
));
2445 /******************************************************************************
2446 * PROPSHEET_SetWizButtons
2448 * This code will work if (and assumes that) the Next button is on top of the
2449 * Finish button. ie. Finish comes after Next in the Z order.
2450 * This means make sure the dialog template reflects this.
2453 static void PROPSHEET_SetWizButtons(HWND hwndDlg
, DWORD dwFlags
)
2455 HWND hwndBack
= GetDlgItem(hwndDlg
, IDC_BACK_BUTTON
);
2456 HWND hwndNext
= GetDlgItem(hwndDlg
, IDC_NEXT_BUTTON
);
2457 HWND hwndFinish
= GetDlgItem(hwndDlg
, IDC_FINISH_BUTTON
);
2459 TRACE("%ld\n", dwFlags
);
2461 EnableWindow(hwndBack
, FALSE
);
2462 EnableWindow(hwndNext
, FALSE
);
2463 EnableWindow(hwndFinish
, FALSE
);
2465 if (dwFlags
& PSWIZB_BACK
)
2466 EnableWindow(hwndBack
, TRUE
);
2468 if (dwFlags
& PSWIZB_NEXT
)
2470 /* Hide the Finish button */
2471 ShowWindow(hwndFinish
, SW_HIDE
);
2473 /* Show and enable the Next button */
2474 ShowWindow(hwndNext
, SW_SHOW
);
2475 EnableWindow(hwndNext
, TRUE
);
2477 /* Set the Next button as the default pushbutton */
2478 SendMessageA(hwndDlg
, DM_SETDEFID
, IDC_NEXT_BUTTON
, 0);
2481 if ((dwFlags
& PSWIZB_FINISH
) || (dwFlags
& PSWIZB_DISABLEDFINISH
))
2483 /* Hide the Next button */
2484 ShowWindow(hwndNext
, SW_HIDE
);
2486 /* Show the Finish button */
2487 ShowWindow(hwndFinish
, SW_SHOW
);
2489 if (dwFlags
& PSWIZB_FINISH
)
2490 EnableWindow(hwndFinish
, TRUE
);
2492 /* Set the Finish button as the default pushbutton */
2493 SendMessageA(hwndDlg
, DM_SETDEFID
, IDC_FINISH_BUTTON
, 0);
2497 /******************************************************************************
2498 * PROPSHEET_InsertPage
2500 static BOOL
PROPSHEET_InsertPage(HWND hwndDlg
, HPROPSHEETPAGE hpageInsertAfter
, HPROPSHEETPAGE hpage
)
2502 if (!HIWORD(hpageInsertAfter
))
2503 FIXME("(%p, %d, %p): stub\n", hwndDlg
, LOWORD(hpageInsertAfter
), hpage
);
2505 FIXME("(%p, %p, %p): stub\n", hwndDlg
, hpageInsertAfter
, hpage
);
2509 /******************************************************************************
2510 * PROPSHEET_SetHeaderTitleW
2512 static void PROPSHEET_SetHeaderTitleW(HWND hwndDlg
, int iPageIndex
, LPCWSTR pszHeaderTitle
)
2514 FIXME("(%p, %d, %s): stub\n", hwndDlg
, iPageIndex
, debugstr_w(pszHeaderTitle
));
2517 /******************************************************************************
2518 * PROPSHEET_SetHeaderTitleA
2520 static void PROPSHEET_SetHeaderTitleA(HWND hwndDlg
, int iPageIndex
, LPCSTR pszHeaderTitle
)
2522 FIXME("(%p, %d, %s): stub\n", hwndDlg
, iPageIndex
, debugstr_a(pszHeaderTitle
));
2525 /******************************************************************************
2526 * PROPSHEET_SetHeaderSubTitleW
2528 static void PROPSHEET_SetHeaderSubTitleW(HWND hwndDlg
, int iPageIndex
, LPCWSTR pszHeaderSubTitle
)
2530 FIXME("(%p, %d, %s): stub\n", hwndDlg
, iPageIndex
, debugstr_w(pszHeaderSubTitle
));
2533 /******************************************************************************
2534 * PROPSHEET_SetHeaderSubTitleA
2536 static void PROPSHEET_SetHeaderSubTitleA(HWND hwndDlg
, int iPageIndex
, LPCSTR pszHeaderSubTitle
)
2538 FIXME("(%p, %d, %s): stub\n", hwndDlg
, iPageIndex
, debugstr_a(pszHeaderSubTitle
));
2541 /******************************************************************************
2542 * PROPSHEET_HwndToIndex
2544 static LRESULT
PROPSHEET_HwndToIndex(HWND hwndDlg
, HWND hPageDlg
)
2547 PropSheetInfo
* psInfo
= (PropSheetInfo
*) GetPropW(hwndDlg
,
2550 TRACE("(%p, %p)\n", hwndDlg
, hPageDlg
);
2552 for (index
= 0; index
< psInfo
->nPages
; index
++)
2553 if (psInfo
->proppage
[index
].hwndPage
== hPageDlg
)
2555 WARN("%p not found\n", hPageDlg
);
2559 /******************************************************************************
2560 * PROPSHEET_IndexToHwnd
2562 static LRESULT
PROPSHEET_IndexToHwnd(HWND hwndDlg
, int iPageIndex
)
2564 PropSheetInfo
* psInfo
= (PropSheetInfo
*) GetPropW(hwndDlg
,
2566 TRACE("(%p, %d)\n", hwndDlg
, iPageIndex
);
2567 if (iPageIndex
<0 || iPageIndex
>=psInfo
->nPages
) {
2568 WARN("%d out of range.\n", iPageIndex
);
2571 return (LRESULT
)psInfo
->proppage
[iPageIndex
].hwndPage
;
2574 /******************************************************************************
2575 * PROPSHEET_PageToIndex
2577 static LRESULT
PROPSHEET_PageToIndex(HWND hwndDlg
, HPROPSHEETPAGE hPage
)
2579 FIXME("(%p, %p): stub\n", hwndDlg
, hPage
);
2583 /******************************************************************************
2584 * PROPSHEET_IndexToPage
2586 static LRESULT
PROPSHEET_IndexToPage(HWND hwndDlg
, int iPageIndex
)
2588 FIXME("(%p, %d): stub\n", hwndDlg
, iPageIndex
);
2592 /******************************************************************************
2593 * PROPSHEET_IdToIndex
2595 static LRESULT
PROPSHEET_IdToIndex(HWND hwndDlg
, int iPageId
)
2597 FIXME("(%p, %d): stub\n", hwndDlg
, iPageId
);
2601 /******************************************************************************
2602 * PROPSHEET_IndexToId
2604 static LRESULT
PROPSHEET_IndexToId(HWND hwndDlg
, int iPageIndex
)
2606 FIXME("(%p, %d): stub\n", hwndDlg
, iPageIndex
);
2610 /******************************************************************************
2611 * PROPSHEET_GetResult
2613 static LRESULT
PROPSHEET_GetResult(HWND hwndDlg
)
2615 FIXME("(%p): stub\n", hwndDlg
);
2619 /******************************************************************************
2620 * PROPSHEET_RecalcPageSizes
2622 static BOOL
PROPSHEET_RecalcPageSizes(HWND hwndDlg
)
2624 FIXME("(%p): stub\n", hwndDlg
);
2628 /******************************************************************************
2629 * PROPSHEET_GetPageIndex
2631 * Given a HPROPSHEETPAGE, returns the index of the corresponding page from
2632 * the array of PropPageInfo.
2634 static int PROPSHEET_GetPageIndex(HPROPSHEETPAGE hpage
, PropSheetInfo
* psInfo
)
2639 TRACE("hpage %p\n", hpage
);
2640 while ((index
< psInfo
->nPages
) && (found
== FALSE
))
2642 if (psInfo
->proppage
[index
].hpage
== hpage
)
2654 /******************************************************************************
2657 static void PROPSHEET_CleanUp(HWND hwndDlg
)
2660 PropSheetInfo
* psInfo
= (PropSheetInfo
*) RemovePropW(hwndDlg
,
2664 if (!psInfo
) return;
2665 if (HIWORD(psInfo
->ppshheader
.pszCaption
))
2666 HeapFree(GetProcessHeap(), 0, (LPVOID
)psInfo
->ppshheader
.pszCaption
);
2668 for (i
= 0; i
< psInfo
->nPages
; i
++)
2670 PROPSHEETPAGEA
* psp
= (PROPSHEETPAGEA
*)psInfo
->proppage
[i
].hpage
;
2672 if(psInfo
->proppage
[i
].hwndPage
)
2673 DestroyWindow(psInfo
->proppage
[i
].hwndPage
);
2677 if ((psp
->dwFlags
& PSP_USETITLE
) && psInfo
->proppage
[i
].pszText
)
2678 HeapFree(GetProcessHeap(), 0, (LPVOID
)psInfo
->proppage
[i
].pszText
);
2680 DestroyPropertySheetPage(psInfo
->proppage
[i
].hpage
);
2684 DeleteObject(psInfo
->hFont
);
2685 DeleteObject(psInfo
->hFontBold
);
2686 /* If we created the bitmaps, destroy them */
2687 if ((psInfo
->ppshheader
.dwFlags
& PSH_WATERMARK
) &&
2688 (!(psInfo
->ppshheader
.dwFlags
& PSH_USEHBMWATERMARK
)) )
2689 DeleteObject(psInfo
->ppshheader
.u4
.hbmWatermark
);
2690 if ((psInfo
->ppshheader
.dwFlags
& PSH_HEADER
) &&
2691 (!(psInfo
->ppshheader
.dwFlags
& PSH_USEHBMHEADER
)) )
2692 DeleteObject(psInfo
->ppshheader
.u5
.hbmHeader
);
2694 Free(psInfo
->proppage
);
2695 Free(psInfo
->strPropertiesFor
);
2696 ImageList_Destroy(psInfo
->hImageList
);
2698 GlobalFree((HGLOBAL
)psInfo
);
2701 /******************************************************************************
2702 * PropertySheet (COMCTL32.@)
2703 * PropertySheetA (COMCTL32.@)
2705 * Creates a property sheet in the specified property sheet header.
2708 * Modal property sheets: Positive if successful or -1 otherwise.
2709 * Modeless property sheets: Property sheet handle.
2711 *| ID_PSREBOOTSYSTEM - The user must reboot the computer for the changes to take effect.
2712 *| ID_PSRESTARTWINDOWS - The user must restart Windows for the changes to take effect.
2714 INT WINAPI
PropertySheetA(LPCPROPSHEETHEADERA lppsh
)
2717 PropSheetInfo
* psInfo
= (PropSheetInfo
*) GlobalAlloc(GPTR
,
2718 sizeof(PropSheetInfo
));
2722 TRACE("(%p)\n", lppsh
);
2724 PROPSHEET_CollectSheetInfoA(lppsh
, psInfo
);
2726 psInfo
->proppage
= (PropPageInfo
*) Alloc(sizeof(PropPageInfo
) *
2728 pByte
= (BYTE
*) psInfo
->ppshheader
.u3
.ppsp
;
2730 for (n
= i
= 0; i
< lppsh
->nPages
; i
++, n
++)
2732 if (!(lppsh
->dwFlags
& PSH_PROPSHEETPAGE
))
2733 psInfo
->proppage
[n
].hpage
= psInfo
->ppshheader
.u3
.phpage
[i
];
2736 psInfo
->proppage
[n
].hpage
= CreatePropertySheetPageA((LPCPROPSHEETPAGEA
)pByte
);
2737 pByte
+= ((LPPROPSHEETPAGEA
)pByte
)->dwSize
;
2740 if (!PROPSHEET_CollectPageInfo((LPCPROPSHEETPAGEW
)psInfo
->proppage
[n
].hpage
,
2743 if (lppsh
->dwFlags
& PSH_PROPSHEETPAGE
)
2744 DestroyPropertySheetPage(psInfo
->proppage
[n
].hpage
);
2750 psInfo
->unicode
= FALSE
;
2751 bRet
= PROPSHEET_CreateDialog(psInfo
);
2756 /******************************************************************************
2757 * PropertySheetW (COMCTL32.@)
2759 * See PropertySheetA.
2761 INT WINAPI
PropertySheetW(LPCPROPSHEETHEADERW lppsh
)
2764 PropSheetInfo
* psInfo
= (PropSheetInfo
*) GlobalAlloc(GPTR
,
2765 sizeof(PropSheetInfo
));
2769 TRACE("(%p)\n", lppsh
);
2771 PROPSHEET_CollectSheetInfoW(lppsh
, psInfo
);
2773 psInfo
->proppage
= (PropPageInfo
*) Alloc(sizeof(PropPageInfo
) *
2775 pByte
= (BYTE
*) psInfo
->ppshheader
.u3
.ppsp
;
2777 for (n
= i
= 0; i
< lppsh
->nPages
; i
++, n
++)
2779 if (!(lppsh
->dwFlags
& PSH_PROPSHEETPAGE
))
2780 psInfo
->proppage
[n
].hpage
= psInfo
->ppshheader
.u3
.phpage
[i
];
2783 psInfo
->proppage
[n
].hpage
= CreatePropertySheetPageW((LPCPROPSHEETPAGEW
)pByte
);
2784 pByte
+= ((LPPROPSHEETPAGEW
)pByte
)->dwSize
;
2787 if (!PROPSHEET_CollectPageInfo((LPCPROPSHEETPAGEW
)psInfo
->proppage
[n
].hpage
,
2790 if (lppsh
->dwFlags
& PSH_PROPSHEETPAGE
)
2791 DestroyPropertySheetPage(psInfo
->proppage
[n
].hpage
);
2797 psInfo
->unicode
= TRUE
;
2798 bRet
= PROPSHEET_CreateDialog(psInfo
);
2803 /******************************************************************************
2804 * CreatePropertySheetPage (COMCTL32.@)
2805 * CreatePropertySheetPageA (COMCTL32.@)
2807 * Creates a new property sheet page.
2810 * Success: Handle to new property sheet page.
2814 * An application must use the PSM_ADDPAGE message to add the new page to
2815 * an existing property sheet.
2817 HPROPSHEETPAGE WINAPI
CreatePropertySheetPageA(
2818 LPCPROPSHEETPAGEA lpPropSheetPage
)
2820 PROPSHEETPAGEW
* ppsp
= Alloc(sizeof(PROPSHEETPAGEW
));
2822 memcpy(ppsp
,lpPropSheetPage
,min(lpPropSheetPage
->dwSize
,sizeof(PROPSHEETPAGEA
)));
2824 ppsp
->dwFlags
&= ~ PSP_INTERNAL_UNICODE
;
2825 if ( !(ppsp
->dwFlags
& PSP_DLGINDIRECT
) && HIWORD( ppsp
->u
.pszTemplate
) )
2827 int len
= strlen(lpPropSheetPage
->u
.pszTemplate
);
2829 ppsp
->u
.pszTemplate
= HeapAlloc( GetProcessHeap(),0,len
+1 );
2830 strcpy( (LPSTR
)ppsp
->u
.pszTemplate
, lpPropSheetPage
->u
.pszTemplate
);
2832 if ( (ppsp
->dwFlags
& PSP_USEICONID
) && HIWORD( ppsp
->u2
.pszIcon
) )
2834 PROPSHEET_AtoW(&ppsp
->u2
.pszIcon
, lpPropSheetPage
->u2
.pszIcon
);
2837 if ((ppsp
->dwFlags
& PSP_USETITLE
) && HIWORD( ppsp
->pszTitle
))
2839 PROPSHEET_AtoW(&ppsp
->pszTitle
, lpPropSheetPage
->pszTitle
);
2841 else if ( !(ppsp
->dwFlags
& PSP_USETITLE
) )
2842 ppsp
->pszTitle
= NULL
;
2844 return (HPROPSHEETPAGE
)ppsp
;
2847 /******************************************************************************
2848 * CreatePropertySheetPageW (COMCTL32.@)
2850 * See CreatePropertySheetA.
2852 HPROPSHEETPAGE WINAPI
CreatePropertySheetPageW(LPCPROPSHEETPAGEW lpPropSheetPage
)
2854 PROPSHEETPAGEW
* ppsp
= Alloc(sizeof(PROPSHEETPAGEW
));
2856 memcpy(ppsp
,lpPropSheetPage
,min(lpPropSheetPage
->dwSize
,sizeof(PROPSHEETPAGEW
)));
2858 ppsp
->dwFlags
|= PSP_INTERNAL_UNICODE
;
2860 if ( !(ppsp
->dwFlags
& PSP_DLGINDIRECT
) && HIWORD( ppsp
->u
.pszTemplate
) )
2862 int len
= strlenW(lpPropSheetPage
->u
.pszTemplate
);
2864 ppsp
->u
.pszTemplate
= HeapAlloc( GetProcessHeap(),0,(len
+1)*sizeof (WCHAR
) );
2865 strcpyW( (WCHAR
*)ppsp
->u
.pszTemplate
, lpPropSheetPage
->u
.pszTemplate
);
2867 if ( (ppsp
->dwFlags
& PSP_USEICONID
) && HIWORD( ppsp
->u2
.pszIcon
) )
2869 int len
= strlenW(lpPropSheetPage
->u2
.pszIcon
);
2870 ppsp
->u2
.pszIcon
= HeapAlloc( GetProcessHeap(), 0, (len
+1)*sizeof (WCHAR
) );
2871 strcpyW( (WCHAR
*)ppsp
->u2
.pszIcon
, lpPropSheetPage
->u2
.pszIcon
);
2874 if ((ppsp
->dwFlags
& PSP_USETITLE
) && HIWORD( ppsp
->pszTitle
))
2876 int len
= strlenW(lpPropSheetPage
->pszTitle
);
2877 ppsp
->pszTitle
= HeapAlloc( GetProcessHeap(), 0, (len
+1)*sizeof (WCHAR
) );
2878 strcpyW( (WCHAR
*)ppsp
->pszTitle
, lpPropSheetPage
->pszTitle
);
2880 else if ( !(ppsp
->dwFlags
& PSP_USETITLE
) )
2881 ppsp
->pszTitle
= NULL
;
2883 return (HPROPSHEETPAGE
)ppsp
;
2886 /******************************************************************************
2887 * DestroyPropertySheetPage (COMCTL32.@)
2889 * Destroys a property sheet page previously created with
2890 * CreatePropertySheetA() or CreatePropertySheetW() and frees the associated
2897 BOOL WINAPI
DestroyPropertySheetPage(HPROPSHEETPAGE hPropPage
)
2899 PROPSHEETPAGEW
*psp
= (PROPSHEETPAGEW
*)hPropPage
;
2904 if ( !(psp
->dwFlags
& PSP_DLGINDIRECT
) && HIWORD( psp
->u
.pszTemplate
) )
2905 HeapFree(GetProcessHeap(), 0, (LPVOID
)psp
->u
.pszTemplate
);
2907 if ( (psp
->dwFlags
& PSP_USEICONID
) && HIWORD( psp
->u2
.pszIcon
) )
2908 HeapFree(GetProcessHeap(), 0, (LPVOID
)psp
->u2
.pszIcon
);
2910 if ((psp
->dwFlags
& PSP_USETITLE
) && HIWORD( psp
->pszTitle
))
2911 HeapFree(GetProcessHeap(), 0, (LPVOID
)psp
->pszTitle
);
2918 /******************************************************************************
2919 * PROPSHEET_IsDialogMessage
2921 static BOOL
PROPSHEET_IsDialogMessage(HWND hwnd
, LPMSG lpMsg
)
2923 PropSheetInfo
* psInfo
= (PropSheetInfo
*) GetPropW(hwnd
, PropSheetInfoStr
);
2926 if (!psInfo
|| (hwnd
!= lpMsg
->hwnd
&& !IsChild(hwnd
, lpMsg
->hwnd
)))
2929 if (lpMsg
->message
== WM_KEYDOWN
&& (GetKeyState(VK_CONTROL
) & 0x8000))
2932 INT dlgCode
= SendMessageA(lpMsg
->hwnd
, WM_GETDLGCODE
, 0, (LPARAM
)lpMsg
);
2934 if (!(dlgCode
& DLGC_WANTMESSAGE
))
2936 switch (lpMsg
->wParam
)
2939 if (GetKeyState(VK_SHIFT
) & 0x8000)
2945 case VK_NEXT
: new_page
= 1; break;
2946 case VK_PRIOR
: new_page
= -1; break;
2952 if (PROPSHEET_CanSetCurSel(hwnd
) != FALSE
)
2954 new_page
+= psInfo
->active_page
;
2957 new_page
= psInfo
->nPages
- 1;
2958 else if (new_page
>= psInfo
->nPages
)
2961 PROPSHEET_SetCurSel(hwnd
, new_page
, 1, 0);
2968 return IsDialogMessageA(hwnd
, lpMsg
);
2971 /******************************************************************************
2972 * PROPSHEET_DoCommand
2974 static BOOL
PROPSHEET_DoCommand(HWND hwnd
, WORD wID
)
2980 case IDC_APPLY_BUTTON
:
2982 HWND hwndApplyBtn
= GetDlgItem(hwnd
, IDC_APPLY_BUTTON
);
2984 if (PROPSHEET_Apply(hwnd
, wID
== IDOK
? 1: 0) == FALSE
)
2989 PropSheetInfo
* psInfo
= (PropSheetInfo
*) GetPropW(hwnd
,
2993 if (psInfo
->restartWindows
)
2994 result
= ID_PSRESTARTWINDOWS
;
2996 /* reboot system takes precedence over restart windows */
2997 if (psInfo
->rebootSystem
)
2998 result
= ID_PSREBOOTSYSTEM
;
3000 if (psInfo
->isModeless
)
3001 psInfo
->activeValid
= FALSE
;
3003 EndDialog(hwnd
, result
);
3006 EnableWindow(hwndApplyBtn
, FALSE
);
3011 case IDC_BACK_BUTTON
:
3012 PROPSHEET_Back(hwnd
);
3015 case IDC_NEXT_BUTTON
:
3016 PROPSHEET_Next(hwnd
);
3019 case IDC_FINISH_BUTTON
:
3020 PROPSHEET_Finish(hwnd
);
3024 PROPSHEET_Cancel(hwnd
, 0);
3028 PROPSHEET_Help(hwnd
);
3038 /******************************************************************************
3041 static LRESULT
PROPSHEET_Paint(HWND hwnd
)
3043 PropSheetInfo
* psInfo
= (PropSheetInfo
*) GetPropW(hwnd
, PropSheetInfoStr
);
3048 HPALETTE hOldPal
= 0;
3052 LPCPROPSHEETPAGEW ppshpage
;
3053 WCHAR szBuffer
[256];
3056 hdc
= BeginPaint(hwnd
, &ps
);
3059 hdcSrc
= CreateCompatibleDC(0);
3060 ppshpage
= (LPCPROPSHEETPAGEW
)psInfo
->proppage
[psInfo
->active_page
].hpage
;
3062 if (psInfo
->ppshheader
.dwFlags
& PSH_USEHPLWATERMARK
)
3063 hOldPal
= SelectPalette(hdc
, psInfo
->ppshheader
.hplWatermark
, FALSE
);
3065 if ( (!(ppshpage
->dwFlags
& PSP_HIDEHEADER
)) &&
3066 (psInfo
->ppshheader
.dwFlags
& (PSH_WIZARD97_OLD
| PSH_WIZARD97_NEW
)) &&
3067 (psInfo
->ppshheader
.dwFlags
& PSH_HEADER
) )
3070 HWND hwndLineHeader
= GetDlgItem(hwnd
, IDC_SUNKEN_LINEHEADER
);
3072 COLORREF clrOld
= 0;
3075 hbmp
= SelectObject(hdcSrc
, psInfo
->ppshheader
.u5
.hbmHeader
);
3076 hOldFont
= SelectObject(hdc
, psInfo
->hFontBold
);
3078 GetClientRect(hwndLineHeader
, &r
);
3079 MapWindowPoints(hwndLineHeader
, hwnd
, (LPPOINT
) &r
, 2);
3080 SetRect(&rzone
, 0, 0, r
.right
+ 1, r
.top
- 1);
3082 GetObjectA(psInfo
->ppshheader
.u5
.hbmHeader
, sizeof(BITMAP
), (LPVOID
)&bm
);
3084 if (psInfo
->ppshheader
.dwFlags
& PSH_WIZARD97_OLD
)
3086 /* Fill the unoccupied part of the header with color of the
3087 * left-top pixel, but do it only when needed.
3089 if (bm
.bmWidth
< r
.right
|| bm
.bmHeight
< r
.bottom
)
3091 hbr
= CreateSolidBrush(GetPixel(hdcSrc
, 0, 0));
3092 CopyRect(&r
, &rzone
);
3093 if (bm
.bmWidth
< r
.right
)
3095 r
.left
= bm
.bmWidth
;
3096 FillRect(hdc
, &r
, hbr
);
3098 if (bm
.bmHeight
< r
.bottom
)
3101 r
.top
= bm
.bmHeight
;
3102 FillRect(hdc
, &r
, hbr
);
3107 /* Draw the header itself. */
3109 bm
.bmWidth
, min(bm
.bmHeight
, rzone
.bottom
),
3110 hdcSrc
, 0, 0, SRCCOPY
);
3114 hbr
= CreateSolidBrush(GetSysColor(COLOR_WINDOW
));
3115 FillRect(hdc
, &rzone
, hbr
);
3118 /* Draw the header bitmap. It's always centered like a
3119 * common 49 x 49 bitmap. */
3120 BitBlt(hdc
, rzone
.right
- 49 - ((rzone
.bottom
- 49) / 2),
3121 (rzone
.bottom
- 49) / 2,
3122 bm
.bmWidth
, bm
.bmHeight
,
3123 hdcSrc
, 0, 0, SRCCOPY
);
3125 /* NOTE: Native COMCTL32 draws a white stripe over the bitmap
3126 * if its height is smaller than 49 pixels. Because the reason
3127 * for this bug is unknown the current code doesn't try to
3131 clrOld
= SetTextColor (hdc
, 0x00000000);
3132 oldBkMode
= SetBkMode (hdc
, TRANSPARENT
);
3134 if (ppshpage
->dwFlags
& PSP_USEHEADERTITLE
) {
3135 SetRect(&r
, 20, 10, 0, 0);
3136 if (HIWORD(ppshpage
->pszHeaderTitle
))
3138 if (psInfo
->unicode
)
3139 DrawTextW(hdc
, (LPWSTR
)ppshpage
->pszHeaderTitle
,
3140 -1, &r
, DT_LEFT
| DT_SINGLELINE
| DT_NOCLIP
);
3142 DrawTextA(hdc
, (LPCSTR
)ppshpage
->pszHeaderTitle
,
3143 -1, &r
, DT_LEFT
| DT_SINGLELINE
| DT_NOCLIP
);
3147 nLength
= LoadStringW(ppshpage
->hInstance
, (UINT
)ppshpage
->pszHeaderTitle
,
3151 DrawTextW(hdc
, szBuffer
, nLength
,
3152 &r
, DT_LEFT
| DT_SINGLELINE
| DT_NOCLIP
);
3157 if (ppshpage
->dwFlags
& PSP_USEHEADERSUBTITLE
) {
3158 SelectObject(hdc
, psInfo
->hFont
);
3159 SetRect(&r
, 40, 25, 0, 0);
3160 if (HIWORD(ppshpage
->pszHeaderTitle
))
3162 if (psInfo
->unicode
)
3163 DrawTextW(hdc
, (LPWSTR
)ppshpage
->pszHeaderSubTitle
,
3164 -1, &r
, DT_LEFT
| DT_SINGLELINE
);
3166 DrawTextA(hdc
, (LPCSTR
)ppshpage
->pszHeaderSubTitle
,
3167 -1, &r
, DT_LEFT
| DT_SINGLELINE
);
3171 nLength
= LoadStringW(ppshpage
->hInstance
, (UINT
)ppshpage
->pszHeaderSubTitle
,
3175 DrawTextW(hdc
, szBuffer
, nLength
,
3176 &r
, DT_LEFT
| DT_SINGLELINE
| DT_NOCLIP
);
3181 offsety
= rzone
.bottom
+ 2;
3183 SetTextColor(hdc
, clrOld
);
3184 SetBkMode(hdc
, oldBkMode
);
3185 SelectObject(hdc
, hOldFont
);
3186 SelectObject(hdcSrc
, hbmp
);
3189 if ( ((psInfo
->active_page
== 0) || (psInfo
->active_page
== psInfo
->nPages
- 1)) &&
3190 (psInfo
->ppshheader
.dwFlags
& (PSH_WIZARD97_OLD
| PSH_WIZARD97_NEW
)) &&
3191 (psInfo
->ppshheader
.dwFlags
& PSH_WATERMARK
) )
3193 HWND hwndLine
= GetDlgItem(hwnd
, IDC_SUNKEN_LINE
);
3195 GetClientRect(hwndLine
, &r
);
3196 MapWindowPoints(hwndLine
, hwnd
, (LPPOINT
) &r
, 2);
3198 GetObjectA(psInfo
->ppshheader
.u4
.hbmWatermark
, sizeof(BITMAP
), (LPVOID
)&bm
);
3199 hbmp
= SelectObject(hdcSrc
, psInfo
->ppshheader
.u4
.hbmWatermark
);
3201 BitBlt(hdc
, 0, offsety
, min(bm
.bmWidth
, r
.right
),
3202 min(bm
.bmHeight
, r
.bottom
), hdcSrc
, 0, 0, SRCCOPY
);
3204 /* If the bitmap is not big enough, fill the remaining area
3205 with the color of pixel (0,0) of bitmap - see MSDN */
3206 if (r
.top
> bm
.bmHeight
) {
3207 r
.bottom
= r
.top
- 1;
3208 r
.top
= bm
.bmHeight
;
3210 r
.right
= bm
.bmWidth
;
3211 hbr
= CreateSolidBrush(GetPixel(hdcSrc
, 0, 0));
3212 FillRect(hdc
, &r
, hbr
);
3216 SelectObject(hdcSrc
, hbmp
);
3219 if (psInfo
->ppshheader
.dwFlags
& PSH_USEHPLWATERMARK
)
3220 SelectPalette(hdc
, hOldPal
, FALSE
);
3224 EndPaint(hwnd
, &ps
);
3229 /******************************************************************************
3230 * PROPSHEET_DialogProc
3233 PROPSHEET_DialogProc(HWND hwnd
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
)
3235 TRACE("hwnd=%p msg=0x%04x wparam=%x lparam=%lx\n",
3236 hwnd
, uMsg
, wParam
, lParam
);
3242 PropSheetInfo
* psInfo
= (PropSheetInfo
*) lParam
;
3243 WCHAR
* strCaption
= (WCHAR
*)Alloc(MAX_CAPTION_LENGTH
*sizeof(WCHAR
));
3244 HWND hwndTabCtrl
= GetDlgItem(hwnd
, IDC_TABCONTROL
);
3245 LPCPROPSHEETPAGEW ppshpage
;
3249 /* Using PropSheetInfoStr to store extra data doesn't match the native
3250 * common control: native uses TCM_[GS]ETITEM
3252 SetPropW(hwnd
, PropSheetInfoStr
, (HANDLE
)psInfo
);
3255 * psInfo->hwnd is not being used by WINE code - it exists
3256 * for compatibility with "real" Windoze. The same about
3257 * SetWindowLongPtr - WINE is only using the PropSheetInfoStr
3260 psInfo
->hwnd
= hwnd
;
3261 SetWindowLongPtrW(hwnd
, DWLP_USER
, (DWORD_PTR
)psInfo
);
3263 /* set up the Next and Back buttons by default */
3264 PROPSHEET_SetWizButtons(hwnd
, PSWIZB_BACK
|PSWIZB_NEXT
);
3267 SystemParametersInfoA (SPI_GETICONTITLELOGFONT
, 0, &logFont
, 0);
3268 psInfo
->hFont
= CreateFontIndirectA (&logFont
);
3269 logFont
.lfWeight
= FW_BOLD
;
3270 psInfo
->hFontBold
= CreateFontIndirectA (&logFont
);
3273 * Small icon in the title bar.
3275 if ((psInfo
->ppshheader
.dwFlags
& PSH_USEICONID
) ||
3276 (psInfo
->ppshheader
.dwFlags
& PSH_USEHICON
))
3279 int icon_cx
= GetSystemMetrics(SM_CXSMICON
);
3280 int icon_cy
= GetSystemMetrics(SM_CYSMICON
);
3282 if (psInfo
->ppshheader
.dwFlags
& PSH_USEICONID
)
3283 hIcon
= LoadImageW(psInfo
->ppshheader
.hInstance
,
3284 psInfo
->ppshheader
.u
.pszIcon
,
3289 hIcon
= psInfo
->ppshheader
.u
.hIcon
;
3291 SendMessageW(hwnd
, WM_SETICON
, 0, (LPARAM
)hIcon
);
3294 if (psInfo
->ppshheader
.dwFlags
& PSH_USEHICON
)
3295 SendMessageW(hwnd
, WM_SETICON
, 0, (LPARAM
)psInfo
->ppshheader
.u
.hIcon
);
3297 psInfo
->strPropertiesFor
= strCaption
;
3299 GetWindowTextW(hwnd
, psInfo
->strPropertiesFor
, MAX_CAPTION_LENGTH
);
3301 PROPSHEET_CreateTabControl(hwnd
, psInfo
);
3303 PROPSHEET_LoadWizardBitmaps(psInfo
);
3305 if (psInfo
->ppshheader
.dwFlags
& INTRNL_ANY_WIZARD
)
3307 ShowWindow(hwndTabCtrl
, SW_HIDE
);
3308 if (PROPSHEET_IsTooSmallWizard(hwnd
, psInfo
))
3310 PROPSHEET_AdjustSizeWizard(hwnd
, psInfo
);
3311 PROPSHEET_AdjustButtonsWizard(hwnd
, psInfo
);
3316 if (PROPSHEET_SizeMismatch(hwnd
, psInfo
))
3318 PROPSHEET_AdjustSize(hwnd
, psInfo
);
3319 PROPSHEET_AdjustButtons(hwnd
, psInfo
);
3323 if (psInfo
->useCallback
)
3324 (*(psInfo
->ppshheader
.pfnCallback
))(hwnd
,
3325 PSCB_INITIALIZED
, (LPARAM
)0);
3327 idx
= psInfo
->active_page
;
3328 ppshpage
= (LPCPROPSHEETPAGEW
)psInfo
->proppage
[idx
].hpage
;
3329 psInfo
->active_page
= -1;
3331 PROPSHEET_SetCurSel(hwnd
, idx
, 1, psInfo
->proppage
[idx
].hpage
);
3333 /* doing TCM_SETCURSEL seems to be needed even in case of PSH_WIZARD,
3334 * as some programs call TCM_GETCURSEL to get the current selection
3335 * from which to switch to the next page */
3336 SendMessageW(hwndTabCtrl
, TCM_SETCURSEL
, psInfo
->active_page
, 0);
3338 if (!HIWORD(psInfo
->ppshheader
.pszCaption
) &&
3339 psInfo
->ppshheader
.hInstance
)
3343 if (LoadStringW(psInfo
->ppshheader
.hInstance
,
3344 (UINT
)psInfo
->ppshheader
.pszCaption
, szText
, 255))
3345 PROPSHEET_SetTitleW(hwnd
, psInfo
->ppshheader
.dwFlags
, szText
);
3349 PROPSHEET_SetTitleW(hwnd
, psInfo
->ppshheader
.dwFlags
,
3350 psInfo
->ppshheader
.pszCaption
);
3357 PROPSHEET_Paint(hwnd
);
3361 PROPSHEET_CleanUp(hwnd
);
3365 PROPSHEET_Cancel(hwnd
, 1);
3369 if (!PROPSHEET_DoCommand(hwnd
, LOWORD(wParam
)))
3371 PropSheetInfo
* psInfo
= (PropSheetInfo
*) GetPropW(hwnd
, PropSheetInfoStr
);
3373 /* No default handler, forward notification to active page */
3374 if (psInfo
->activeValid
&& psInfo
->active_page
!= -1)
3376 HWND hwndPage
= psInfo
->proppage
[psInfo
->active_page
].hwndPage
;
3377 SendMessageW(hwndPage
, WM_COMMAND
, wParam
, lParam
);
3384 NMHDR
* pnmh
= (LPNMHDR
) lParam
;
3386 if (pnmh
->code
== TCN_SELCHANGE
)
3388 int index
= SendMessageW(pnmh
->hwndFrom
, TCM_GETCURSEL
, 0, 0);
3389 PROPSHEET_SetCurSel(hwnd
, index
, 1, 0);
3392 if(pnmh
->code
== TCN_SELCHANGING
)
3394 BOOL bRet
= PROPSHEET_CanSetCurSel(hwnd
);
3395 SetWindowLongPtrW(hwnd
, DWLP_MSGRESULT
, !bRet
);
3402 case PSM_GETCURRENTPAGEHWND
:
3404 PropSheetInfo
* psInfo
= (PropSheetInfo
*) GetPropW(hwnd
,
3408 if (psInfo
->activeValid
&& psInfo
->active_page
!= -1)
3409 hwndPage
= psInfo
->proppage
[psInfo
->active_page
].hwndPage
;
3411 SetWindowLongPtrW(hwnd
, DWLP_MSGRESULT
, (DWORD_PTR
)hwndPage
);
3417 PROPSHEET_Changed(hwnd
, (HWND
)wParam
);
3421 PROPSHEET_UnChanged(hwnd
, (HWND
)wParam
);
3424 case PSM_GETTABCONTROL
:
3426 HWND hwndTabCtrl
= GetDlgItem(hwnd
, IDC_TABCONTROL
);
3428 SetWindowLongPtrW(hwnd
, DWLP_MSGRESULT
, (DWORD_PTR
)hwndTabCtrl
);
3437 msgResult
= PROPSHEET_CanSetCurSel(hwnd
);
3438 if(msgResult
!= FALSE
)
3440 msgResult
= PROPSHEET_SetCurSel(hwnd
,
3443 (HPROPSHEETPAGE
)lParam
);
3446 SetWindowLongPtrW(hwnd
, DWLP_MSGRESULT
, msgResult
);
3451 case PSM_CANCELTOCLOSE
:
3453 WCHAR buf
[MAX_BUTTONTEXT_LENGTH
];
3454 HWND hwndOK
= GetDlgItem(hwnd
, IDOK
);
3455 HWND hwndCancel
= GetDlgItem(hwnd
, IDCANCEL
);
3457 EnableWindow(hwndCancel
, FALSE
);
3458 if (LoadStringW(COMCTL32_hModule
, IDS_CLOSE
, buf
, sizeof(buf
)))
3459 SetWindowTextW(hwndOK
, buf
);
3464 case PSM_RESTARTWINDOWS
:
3466 PropSheetInfo
* psInfo
= (PropSheetInfo
*) GetPropW(hwnd
,
3469 psInfo
->restartWindows
= TRUE
;
3473 case PSM_REBOOTSYSTEM
:
3475 PropSheetInfo
* psInfo
= (PropSheetInfo
*) GetPropW(hwnd
,
3478 psInfo
->rebootSystem
= TRUE
;
3483 PROPSHEET_SetTitleA(hwnd
, (DWORD
) wParam
, (LPCSTR
) lParam
);
3487 PROPSHEET_SetTitleW(hwnd
, (DWORD
) wParam
, (LPCWSTR
) lParam
);
3492 BOOL msgResult
= PROPSHEET_Apply(hwnd
, 0);
3494 SetWindowLongPtrW(hwnd
, DWLP_MSGRESULT
, msgResult
);
3499 case PSM_QUERYSIBLINGS
:
3501 LRESULT msgResult
= PROPSHEET_QuerySiblings(hwnd
, wParam
, lParam
);
3503 SetWindowLongPtrW(hwnd
, DWLP_MSGRESULT
, msgResult
);
3511 * Note: MSVC++ 6.0 documentation says that PSM_ADDPAGE does not have
3512 * a return value. This is not true. PSM_ADDPAGE returns TRUE
3513 * on success or FALSE otherwise, as specified on MSDN Online.
3514 * Also see the MFC code for
3515 * CPropertySheet::AddPage(CPropertyPage* pPage).
3518 BOOL msgResult
= PROPSHEET_AddPage(hwnd
, (HPROPSHEETPAGE
)lParam
);
3520 SetWindowLongPtrW(hwnd
, DWLP_MSGRESULT
, msgResult
);
3525 case PSM_REMOVEPAGE
:
3526 PROPSHEET_RemovePage(hwnd
, (int)wParam
, (HPROPSHEETPAGE
)lParam
);
3529 case PSM_ISDIALOGMESSAGE
:
3531 BOOL msgResult
= PROPSHEET_IsDialogMessage(hwnd
, (LPMSG
)lParam
);
3532 SetWindowLongPtrW(hwnd
, DWLP_MSGRESULT
, msgResult
);
3536 case PSM_PRESSBUTTON
:
3537 PROPSHEET_PressButton(hwnd
, (int)wParam
);
3540 case PSM_SETFINISHTEXTA
:
3541 PROPSHEET_SetFinishTextA(hwnd
, (LPCSTR
) lParam
);
3544 case PSM_SETWIZBUTTONS
:
3545 PROPSHEET_SetWizButtons(hwnd
, (DWORD
)lParam
);
3548 case PSM_SETCURSELID
:
3549 PROPSHEET_SetCurSelId(hwnd
, (int)lParam
);
3552 case PSM_SETFINISHTEXTW
:
3553 PROPSHEET_SetFinishTextW(hwnd
, (LPCWSTR
) lParam
);
3556 case PSM_INSERTPAGE
:
3558 BOOL msgResult
= PROPSHEET_InsertPage(hwnd
, (HPROPSHEETPAGE
)wParam
, (HPROPSHEETPAGE
)lParam
);
3559 SetWindowLongPtrW(hwnd
, DWLP_MSGRESULT
, msgResult
);
3563 case PSM_SETHEADERTITLEW
:
3564 PROPSHEET_SetHeaderTitleW(hwnd
, (int)wParam
, (LPCWSTR
)lParam
);
3567 case PSM_SETHEADERTITLEA
:
3568 PROPSHEET_SetHeaderTitleA(hwnd
, (int)wParam
, (LPCSTR
)lParam
);
3571 case PSM_SETHEADERSUBTITLEW
:
3572 PROPSHEET_SetHeaderSubTitleW(hwnd
, (int)wParam
, (LPCWSTR
)lParam
);
3575 case PSM_SETHEADERSUBTITLEA
:
3576 PROPSHEET_SetHeaderSubTitleA(hwnd
, (int)wParam
, (LPCSTR
)lParam
);
3579 case PSM_HWNDTOINDEX
:
3581 LRESULT msgResult
= PROPSHEET_HwndToIndex(hwnd
, (HWND
)wParam
);
3582 SetWindowLongPtrW(hwnd
, DWLP_MSGRESULT
, msgResult
);
3586 case PSM_INDEXTOHWND
:
3588 LRESULT msgResult
= PROPSHEET_IndexToHwnd(hwnd
, (int)wParam
);
3589 SetWindowLongPtrW(hwnd
, DWLP_MSGRESULT
, msgResult
);
3593 case PSM_PAGETOINDEX
:
3595 LRESULT msgResult
= PROPSHEET_PageToIndex(hwnd
, (HPROPSHEETPAGE
)wParam
);
3596 SetWindowLongPtrW(hwnd
, DWLP_MSGRESULT
, msgResult
);
3600 case PSM_INDEXTOPAGE
:
3602 LRESULT msgResult
= PROPSHEET_IndexToPage(hwnd
, (int)wParam
);
3603 SetWindowLongPtrW(hwnd
, DWLP_MSGRESULT
, msgResult
);
3609 LRESULT msgResult
= PROPSHEET_IdToIndex(hwnd
, (int)lParam
);
3610 SetWindowLongPtrW(hwnd
, DWLP_MSGRESULT
, msgResult
);
3616 LRESULT msgResult
= PROPSHEET_IndexToId(hwnd
, (int)wParam
);
3617 SetWindowLongPtrW(hwnd
, DWLP_MSGRESULT
, msgResult
);
3623 LRESULT msgResult
= PROPSHEET_GetResult(hwnd
);
3624 SetWindowLongPtrW(hwnd
, DWLP_MSGRESULT
, msgResult
);
3628 case PSM_RECALCPAGESIZES
:
3630 LRESULT msgResult
= PROPSHEET_RecalcPageSizes(hwnd
);
3631 SetWindowLongPtrW(hwnd
, DWLP_MSGRESULT
, msgResult
);