4 * Copyright 1998 Francis Beaudet
5 * Copyright 1999 Thuy Nguyen
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 * - Unicode property sheets
35 #include "wine/debug.h"
36 #include "wine/unicode.h"
38 /******************************************************************************
61 } MyDLGITEMTEMPLATEEX
;
64 typedef struct tagPropPageInfo
66 HPROPSHEETPAGE hpage
; /* to keep track of pages not passed to PropertySheet */
75 typedef struct tagPropSheetInfo
78 PROPSHEETHEADERW ppshheader
;
79 LPWSTR strPropertiesFor
;
89 PropPageInfo
* proppage
;
94 HIMAGELIST hImageList
;
103 /******************************************************************************
104 * Defines and global variables
107 const WCHAR PropSheetInfoStr
[] =
108 {'P','r','o','p','e','r','t','y','S','h','e','e','t','I','n','f','o',0 };
110 #define MAX_CAPTION_LENGTH 255
111 #define MAX_TABTEXT_LENGTH 255
112 #define MAX_BUTTONTEXT_LENGTH 64
114 #define PSH_WIZARD97_OLD 0x00002000
115 #define PSH_WIZARD97_NEW 0x01000000
116 #define INTRNL_ANY_WIZARD (PSH_WIZARD | PSH_WIZARD97_OLD | PSH_WIZARD97_NEW | PSH_WIZARD_LITE)
118 /******************************************************************************
121 static BOOL
PROPSHEET_CreateDialog(PropSheetInfo
* psInfo
);
122 static BOOL
PROPSHEET_SizeMismatch(HWND hwndDlg
, PropSheetInfo
* psInfo
);
123 static BOOL
PROPSHEET_AdjustSize(HWND hwndDlg
, PropSheetInfo
* psInfo
);
124 static BOOL
PROPSHEET_AdjustButtons(HWND hwndParent
, PropSheetInfo
* psInfo
);
125 static BOOL
PROPSHEET_CollectSheetInfoA(LPCPROPSHEETHEADERA lppsh
,
126 PropSheetInfo
* psInfo
);
127 static BOOL
PROPSHEET_CollectSheetInfoW(LPCPROPSHEETHEADERW lppsh
,
128 PropSheetInfo
* psInfo
);
129 static BOOL
PROPSHEET_CollectPageInfo(LPCPROPSHEETPAGEW lppsp
,
130 PropSheetInfo
* psInfo
,
132 static BOOL
PROPSHEET_CreateTabControl(HWND hwndParent
,
133 PropSheetInfo
* psInfo
);
134 static BOOL
PROPSHEET_CreatePage(HWND hwndParent
, int index
,
135 const PropSheetInfo
* psInfo
,
136 LPCPROPSHEETPAGEW ppshpage
);
137 static BOOL
PROPSHEET_ShowPage(HWND hwndDlg
, int index
, PropSheetInfo
* psInfo
);
138 static PADDING_INFO
PROPSHEET_GetPaddingInfo(HWND hwndDlg
);
139 static BOOL
PROPSHEET_Back(HWND hwndDlg
);
140 static BOOL
PROPSHEET_Next(HWND hwndDlg
);
141 static BOOL
PROPSHEET_Finish(HWND hwndDlg
);
142 static BOOL
PROPSHEET_Apply(HWND hwndDlg
, LPARAM lParam
);
143 static void PROPSHEET_Cancel(HWND hwndDlg
, LPARAM lParam
);
144 static void PROPSHEET_Help(HWND hwndDlg
);
145 static void PROPSHEET_Changed(HWND hwndDlg
, HWND hwndDirtyPage
);
146 static void PROPSHEET_UnChanged(HWND hwndDlg
, HWND hwndCleanPage
);
147 static void PROPSHEET_PressButton(HWND hwndDlg
, int buttonID
);
148 static void PROPSHEET_SetFinishTextA(HWND hwndDlg
, LPCSTR lpszText
);
149 static void PROPSHEET_SetFinishTextW(HWND hwndDlg
, LPCWSTR lpszText
);
150 static void PROPSHEET_SetTitleA(HWND hwndDlg
, DWORD dwStyle
, LPCSTR lpszText
);
151 static void PROPSHEET_SetTitleW(HWND hwndDlg
, DWORD dwStyle
, LPCWSTR lpszText
);
152 static BOOL
PROPSHEET_CanSetCurSel(HWND hwndDlg
);
153 static BOOL
PROPSHEET_SetCurSel(HWND hwndDlg
,
156 HPROPSHEETPAGE hpage
);
157 static void PROPSHEET_SetCurSelId(HWND hwndDlg
, int id
);
158 static LRESULT
PROPSHEET_QuerySiblings(HWND hwndDlg
,
159 WPARAM wParam
, LPARAM lParam
);
160 static BOOL
PROPSHEET_AddPage(HWND hwndDlg
,
161 HPROPSHEETPAGE hpage
);
163 static BOOL
PROPSHEET_RemovePage(HWND hwndDlg
,
165 HPROPSHEETPAGE hpage
);
166 static void PROPSHEET_CleanUp();
167 static int PROPSHEET_GetPageIndex(HPROPSHEETPAGE hpage
, PropSheetInfo
* psInfo
);
168 static void PROPSHEET_SetWizButtons(HWND hwndDlg
, DWORD dwFlags
);
169 static PADDING_INFO
PROPSHEET_GetPaddingInfoWizard(HWND hwndDlg
, const PropSheetInfo
* psInfo
);
170 static BOOL
PROPSHEET_IsDialogMessage(HWND hwnd
, LPMSG lpMsg
);
171 static BOOL
PROPSHEET_DoCommand(HWND hwnd
, WORD wID
);
174 PROPSHEET_DialogProc(HWND hwnd
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
);
176 WINE_DEFAULT_DEBUG_CHANNEL(propsheet
);
178 #define add_flag(a) if (dwFlags & a) {strcat(string, #a );strcat(string," ");}
179 /******************************************************************************
180 * PROPSHEET_UnImplementedFlags
182 * Document use of flags we don't implement yet.
184 static VOID
PROPSHEET_UnImplementedFlags(DWORD dwFlags
)
191 * unhandled header flags:
192 * PSH_DEFAULT 0x00000000
193 * PSH_WIZARDHASFINISH 0x00000010
194 * PSH_RTLREADING 0x00000800
195 * PSH_WIZARDCONTEXTHELP 0x00001000
196 * PSH_WIZARD97 0x00002000 (pre IE 5)
197 * PSH_WATERMARK 0x00008000
198 * PSH_USEHBMWATERMARK 0x00010000
199 * PSH_USEHPLWATERMARK 0x00020000
200 * PSH_STRETCHWATERMARK 0x00040000
201 * PSH_HEADER 0x00080000
202 * PSH_USEHBMHEADER 0x00100000
203 * PSH_USEPAGELANG 0x00200000
204 * PSH_WIZARD_LITE 0x00400000 also not in .h
205 * PSH_WIZARD97 0x01000000 (IE 5 and above)
206 * PSH_NOCONTEXTHELP 0x02000000 also not in .h
209 add_flag(PSH_WIZARDHASFINISH
);
210 add_flag(PSH_RTLREADING
);
211 add_flag(PSH_WIZARDCONTEXTHELP
);
212 add_flag(PSH_WIZARD97_OLD
);
213 add_flag(PSH_WATERMARK
);
214 add_flag(PSH_USEHBMWATERMARK
);
215 add_flag(PSH_USEHPLWATERMARK
);
216 add_flag(PSH_STRETCHWATERMARK
);
217 add_flag(PSH_HEADER
);
218 add_flag(PSH_USEHBMHEADER
);
219 add_flag(PSH_USEPAGELANG
);
220 add_flag(PSH_WIZARD_LITE
);
221 add_flag(PSH_WIZARD97_NEW
);
222 add_flag(PSH_NOCONTEXTHELP
);
223 if (string
[0] != '\0')
224 FIXME("%s\n", string
);
228 /******************************************************************************
229 * PROPSHEET_GetPageRect
231 * Retrieve rect from tab control and map into the dialog for SetWindowPos
233 static void PROPSHEET_GetPageRect(const PropSheetInfo
* psInfo
, HWND hwndDlg
, RECT
*rc
)
235 HWND hwndTabCtrl
= GetDlgItem(hwndDlg
, IDC_TABCONTROL
);
237 GetClientRect(hwndTabCtrl
, rc
);
238 SendMessageW(hwndTabCtrl
, TCM_ADJUSTRECT
, FALSE
, (LPARAM
)rc
);
239 MapWindowPoints(hwndTabCtrl
, hwndDlg
, (LPPOINT
)rc
, 2);
242 /******************************************************************************
243 * PROPSHEET_FindPageByResId
245 * Find page index corresponding to page resource id.
247 INT
PROPSHEET_FindPageByResId(PropSheetInfo
* psInfo
, LRESULT resId
)
251 for (i
= 0; i
< psInfo
->nPages
; i
++)
253 LPCPROPSHEETPAGEA lppsp
= (LPCPROPSHEETPAGEA
)psInfo
->proppage
[i
].hpage
;
255 /* Fixme: if resource ID is a string shall we use strcmp ??? */
256 if (lppsp
->u
.pszTemplate
== (LPVOID
)resId
)
263 /******************************************************************************
266 * Convert ASCII to Unicode since all data is saved as Unicode.
268 static void PROPSHEET_AtoW(LPCWSTR
*tostr
, LPCSTR frstr
)
272 TRACE("<%s>\n", frstr
);
273 len
= MultiByteToWideChar(CP_ACP
, 0, frstr
, -1, 0, 0);
274 *tostr
= (LPWSTR
)HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
275 MultiByteToWideChar(CP_ACP
, 0, frstr
, -1, (LPWSTR
)*tostr
, len
);
278 /******************************************************************************
279 * PROPSHEET_CollectSheetInfoA
281 * Collect relevant data.
283 static BOOL
PROPSHEET_CollectSheetInfoA(LPCPROPSHEETHEADERA lppsh
,
284 PropSheetInfo
* psInfo
)
286 DWORD dwSize
= min(lppsh
->dwSize
,sizeof(PROPSHEETHEADERA
));
287 DWORD dwFlags
= lppsh
->dwFlags
;
289 psInfo
->hasHelp
= dwFlags
& PSH_HASHELP
;
290 psInfo
->hasApply
= !(dwFlags
& PSH_NOAPPLYNOW
);
291 psInfo
->useCallback
= dwFlags
& PSH_USECALLBACK
;
292 psInfo
->isModeless
= dwFlags
& PSH_MODELESS
;
294 memcpy(&psInfo
->ppshheader
,lppsh
,dwSize
);
295 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",
296 lppsh
->dwSize
, lppsh
->dwFlags
, lppsh
->hwndParent
, lppsh
->hInstance
,
297 debugstr_a(lppsh
->pszCaption
), lppsh
->nPages
, lppsh
->pfnCallback
);
299 PROPSHEET_UnImplementedFlags(lppsh
->dwFlags
);
301 if (HIWORD(lppsh
->pszCaption
))
303 int len
= strlen(lppsh
->pszCaption
);
304 psInfo
->ppshheader
.pszCaption
= HeapAlloc( GetProcessHeap(), 0, (len
+1)*sizeof (WCHAR
) );
305 MultiByteToWideChar(CP_ACP
, 0, lppsh
->pszCaption
, -1, (LPWSTR
) psInfo
->ppshheader
.pszCaption
, len
+1);
306 /* strcpy( (char *)psInfo->ppshheader.pszCaption, lppsh->pszCaption ); */
308 psInfo
->nPages
= lppsh
->nPages
;
310 if (dwFlags
& PSH_USEPSTARTPAGE
)
312 TRACE("PSH_USEPSTARTPAGE is on");
313 psInfo
->active_page
= 0;
316 psInfo
->active_page
= lppsh
->u2
.nStartPage
;
318 if (psInfo
->active_page
< 0 || psInfo
->active_page
>= psInfo
->nPages
)
319 psInfo
->active_page
= 0;
321 psInfo
->restartWindows
= FALSE
;
322 psInfo
->rebootSystem
= FALSE
;
323 psInfo
->hImageList
= 0;
324 psInfo
->activeValid
= FALSE
;
329 /******************************************************************************
330 * PROPSHEET_CollectSheetInfoW
332 * Collect relevant data.
334 static BOOL
PROPSHEET_CollectSheetInfoW(LPCPROPSHEETHEADERW lppsh
,
335 PropSheetInfo
* psInfo
)
337 DWORD dwSize
= min(lppsh
->dwSize
,sizeof(PROPSHEETHEADERW
));
338 DWORD dwFlags
= lppsh
->dwFlags
;
340 psInfo
->hasHelp
= dwFlags
& PSH_HASHELP
;
341 psInfo
->hasApply
= !(dwFlags
& PSH_NOAPPLYNOW
);
342 psInfo
->useCallback
= dwFlags
& PSH_USECALLBACK
;
343 psInfo
->isModeless
= dwFlags
& PSH_MODELESS
;
345 memcpy(&psInfo
->ppshheader
,lppsh
,dwSize
);
346 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",
347 lppsh
->dwSize
, lppsh
->dwFlags
, lppsh
->hwndParent
, lppsh
->hInstance
, debugstr_w(lppsh
->pszCaption
), lppsh
->nPages
, lppsh
->pfnCallback
);
349 PROPSHEET_UnImplementedFlags(lppsh
->dwFlags
);
351 if (HIWORD(lppsh
->pszCaption
))
353 int len
= strlenW(lppsh
->pszCaption
);
354 psInfo
->ppshheader
.pszCaption
= HeapAlloc( GetProcessHeap(), 0, (len
+1)*sizeof(WCHAR
) );
355 strcpyW( (WCHAR
*)psInfo
->ppshheader
.pszCaption
, lppsh
->pszCaption
);
357 psInfo
->nPages
= lppsh
->nPages
;
359 if (dwFlags
& PSH_USEPSTARTPAGE
)
361 TRACE("PSH_USEPSTARTPAGE is on");
362 psInfo
->active_page
= 0;
365 psInfo
->active_page
= lppsh
->u2
.nStartPage
;
367 if (psInfo
->active_page
< 0 || psInfo
->active_page
>= psInfo
->nPages
)
368 psInfo
->active_page
= 0;
370 psInfo
->restartWindows
= FALSE
;
371 psInfo
->rebootSystem
= FALSE
;
372 psInfo
->hImageList
= 0;
373 psInfo
->activeValid
= FALSE
;
378 /******************************************************************************
379 * PROPSHEET_CollectPageInfo
381 * Collect property sheet data.
382 * With code taken from DIALOG_ParseTemplate32.
384 BOOL
PROPSHEET_CollectPageInfo(LPCPROPSHEETPAGEW lppsp
,
385 PropSheetInfo
* psInfo
,
388 DLGTEMPLATE
* pTemplate
;
394 psInfo
->proppage
[index
].hpage
= (HPROPSHEETPAGE
)lppsp
;
395 psInfo
->proppage
[index
].hwndPage
= 0;
396 psInfo
->proppage
[index
].isDirty
= FALSE
;
399 * Process property page flags.
401 dwFlags
= lppsp
->dwFlags
;
402 psInfo
->proppage
[index
].useCallback
= (dwFlags
& PSP_USECALLBACK
) && (lppsp
->pfnCallback
);
403 psInfo
->proppage
[index
].hasHelp
= dwFlags
& PSP_HASHELP
;
404 psInfo
->proppage
[index
].hasIcon
= dwFlags
& (PSP_USEHICON
| PSP_USEICONID
);
406 /* as soon as we have a page with the help flag, set the sheet flag on */
407 if (psInfo
->proppage
[index
].hasHelp
)
408 psInfo
->hasHelp
= TRUE
;
411 * Process page template.
413 if (dwFlags
& PSP_DLGINDIRECT
)
414 pTemplate
= (DLGTEMPLATE
*)lppsp
->u
.pResource
;
417 HRSRC hResource
= FindResourceW(lppsp
->hInstance
,
418 lppsp
->u
.pszTemplate
,
420 HGLOBAL hTemplate
= LoadResource(lppsp
->hInstance
,
422 pTemplate
= (LPDLGTEMPLATEW
)LockResource(hTemplate
);
426 * Extract the size of the page and the caption.
431 p
= (const WORD
*)pTemplate
;
433 if (((MyDLGTEMPLATEEX
*)pTemplate
)->signature
== 0xFFFF)
435 /* DIALOGEX template */
439 p
+= 2; /* help ID */
440 p
+= 2; /* ext style */
445 /* DIALOG template */
448 p
+= 2; /* ext style */
454 width
= (WORD
)*p
; p
++;
455 height
= (WORD
)*p
; p
++;
457 /* remember the largest width and height */
458 if (width
> psInfo
->width
)
459 psInfo
->width
= width
;
461 if (height
> psInfo
->height
)
462 psInfo
->height
= height
;
474 p
+= lstrlenW( (LPCWSTR
)p
) + 1;
488 p
+= lstrlenW( (LPCWSTR
)p
) + 1;
492 /* Extract the caption */
493 psInfo
->proppage
[index
].pszText
= (LPCWSTR
)p
;
494 TRACE("Tab %d %s\n",index
,debugstr_w((LPCWSTR
)p
));
495 p
+= lstrlenW((LPCWSTR
)p
) + 1;
497 if (dwFlags
& PSP_USETITLE
)
501 static WCHAR pszNull
[] = { '(','n','u','l','l',')',0 };
504 if ( !HIWORD( lppsp
->pszTitle
) )
506 if (!LoadStringW( lppsp
->hInstance
, (UINT
)lppsp
->pszTitle
,szTitle
,sizeof szTitle
))
509 FIXME("Could not load resource #%04x?\n",LOWORD(lppsp
->pszTitle
));
515 pTitle
= lppsp
->pszTitle
;
517 len
= strlenW(pTitle
);
518 psInfo
->proppage
[index
].pszText
= COMCTL32_Alloc( (len
+1)*sizeof (WCHAR
) );
519 strcpyW( (LPWSTR
)psInfo
->proppage
[index
].pszText
,pTitle
);
523 * Build the image list for icons
525 if ((dwFlags
& PSP_USEHICON
) || (dwFlags
& PSP_USEICONID
))
528 int icon_cx
= GetSystemMetrics(SM_CXSMICON
);
529 int icon_cy
= GetSystemMetrics(SM_CYSMICON
);
531 if (dwFlags
& PSP_USEICONID
)
532 hIcon
= LoadImageW(lppsp
->hInstance
, lppsp
->u2
.pszIcon
, IMAGE_ICON
,
533 icon_cx
, icon_cy
, LR_DEFAULTCOLOR
);
535 hIcon
= lppsp
->u2
.hIcon
;
539 if (psInfo
->hImageList
== 0 )
540 psInfo
->hImageList
= ImageList_Create(icon_cx
, icon_cy
, ILC_COLOR
, 1, 1);
542 ImageList_AddIcon(psInfo
->hImageList
, hIcon
);
550 /******************************************************************************
551 * PROPSHEET_CreateDialog
553 * Creates the actual property sheet.
555 BOOL
PROPSHEET_CreateDialog(PropSheetInfo
* psInfo
)
562 WORD resID
= IDD_PROPSHEET
;
565 if (psInfo
->ppshheader
.dwFlags
& INTRNL_ANY_WIZARD
)
568 if(!(hRes
= FindResourceW(COMCTL32_hModule
,
569 MAKEINTRESOURCEW(resID
),
573 if(!(template = (LPVOID
)LoadResource(COMCTL32_hModule
, hRes
)))
577 * Make a copy of the dialog template.
579 resSize
= SizeofResource(COMCTL32_hModule
, hRes
);
581 temp
= COMCTL32_Alloc(resSize
);
586 memcpy(temp
, template, resSize
);
588 if (psInfo
->useCallback
)
589 (*(psInfo
->ppshheader
.pfnCallback
))(0, PSCB_PRECREATE
, (LPARAM
)temp
);
591 if (!(psInfo
->ppshheader
.dwFlags
& PSH_MODELESS
))
592 ret
= DialogBoxIndirectParamW(psInfo
->ppshheader
.hInstance
,
593 (LPDLGTEMPLATEW
) temp
,
594 psInfo
->ppshheader
.hwndParent
,
595 PROPSHEET_DialogProc
,
598 ret
= CreateDialogIndirectParamW(psInfo
->ppshheader
.hInstance
,
599 (LPDLGTEMPLATEW
) temp
,
600 psInfo
->ppshheader
.hwndParent
,
601 PROPSHEET_DialogProc
,
602 (LPARAM
)psInfo
) ? TRUE
: FALSE
;
609 /******************************************************************************
610 * PROPSHEET_SizeMismatch
612 * Verify that the tab control and the "largest" property sheet page dlg. template
615 static BOOL
PROPSHEET_SizeMismatch(HWND hwndDlg
, PropSheetInfo
* psInfo
)
617 HWND hwndTabCtrl
= GetDlgItem(hwndDlg
, IDC_TABCONTROL
);
618 RECT rcOrigTab
, rcPage
;
623 GetClientRect(hwndTabCtrl
, &rcOrigTab
);
624 TRACE("orig tab %d %d %d %d\n", rcOrigTab
.left
, rcOrigTab
.top
,
625 rcOrigTab
.right
, rcOrigTab
.bottom
);
630 rcPage
.left
= psInfo
->x
;
631 rcPage
.top
= psInfo
->y
;
632 rcPage
.right
= psInfo
->width
;
633 rcPage
.bottom
= psInfo
->height
;
635 MapDialogRect(hwndDlg
, &rcPage
);
636 TRACE("biggest page %d %d %d %d\n", rcPage
.left
, rcPage
.top
,
637 rcPage
.right
, rcPage
.bottom
);
639 if ( (rcPage
.right
- rcPage
.left
) != (rcOrigTab
.right
- rcOrigTab
.left
) )
641 if ( (rcPage
.bottom
- rcPage
.top
) != (rcOrigTab
.bottom
- rcOrigTab
.top
) )
647 /******************************************************************************
648 * PROPSHEET_IsTooSmallWizard
650 * Verify that the default property sheet is big enough.
652 static BOOL
PROPSHEET_IsTooSmallWizard(HWND hwndDlg
, PropSheetInfo
* psInfo
)
654 RECT rcSheetRect
, rcPage
, rcLine
, rcSheetClient
;
655 HWND hwndLine
= GetDlgItem(hwndDlg
, IDC_SUNKEN_LINE
);
656 PADDING_INFO padding
= PROPSHEET_GetPaddingInfoWizard(hwndDlg
, psInfo
);
658 GetClientRect(hwndDlg
, &rcSheetClient
);
659 GetWindowRect(hwndDlg
, &rcSheetRect
);
660 GetWindowRect(hwndLine
, &rcLine
);
662 /* Remove the space below the sunken line */
663 rcSheetClient
.bottom
-= (rcSheetRect
.bottom
- rcLine
.top
);
665 /* Remove the buffer zone all around the edge */
666 rcSheetClient
.bottom
-= (padding
.y
* 2);
667 rcSheetClient
.right
-= (padding
.x
* 2);
672 rcPage
.left
= psInfo
->x
;
673 rcPage
.top
= psInfo
->y
;
674 rcPage
.right
= psInfo
->width
;
675 rcPage
.bottom
= psInfo
->height
;
677 MapDialogRect(hwndDlg
, &rcPage
);
678 TRACE("biggest page %d %d %d %d\n", rcPage
.left
, rcPage
.top
,
679 rcPage
.right
, rcPage
.bottom
);
681 if (rcPage
.right
> rcSheetClient
.right
)
684 if (rcPage
.bottom
> rcSheetClient
.bottom
)
690 /******************************************************************************
691 * PROPSHEET_AdjustSize
693 * Resizes the property sheet and the tab control to fit the largest page.
695 static BOOL
PROPSHEET_AdjustSize(HWND hwndDlg
, PropSheetInfo
* psInfo
)
697 HWND hwndTabCtrl
= GetDlgItem(hwndDlg
, IDC_TABCONTROL
);
698 HWND hwndButton
= GetDlgItem(hwndDlg
, IDOK
);
700 int tabOffsetX
, tabOffsetY
, buttonHeight
;
701 PADDING_INFO padding
= PROPSHEET_GetPaddingInfo(hwndDlg
);
704 /* Get the height of buttons */
705 GetClientRect(hwndButton
, &rc
);
706 buttonHeight
= rc
.bottom
;
713 rc
.right
= psInfo
->width
;
714 rc
.bottom
= psInfo
->height
;
716 MapDialogRect(hwndDlg
, &rc
);
718 /* retrieve the dialog units */
719 units
.left
= units
.right
= 4;
720 units
.top
= units
.bottom
= 8;
721 MapDialogRect(hwndDlg
, &units
);
724 * Resize the tab control.
726 GetClientRect(hwndTabCtrl
,&tabRect
);
728 SendMessageW(hwndTabCtrl
, TCM_ADJUSTRECT
, FALSE
, (LPARAM
)&tabRect
);
730 if ((rc
.bottom
- rc
.top
) < (tabRect
.bottom
- tabRect
.top
))
732 rc
.bottom
= rc
.top
+ tabRect
.bottom
- tabRect
.top
;
733 psInfo
->height
= MulDiv((rc
.bottom
- rc
.top
),8,units
.top
);
736 if ((rc
.right
- rc
.left
) < (tabRect
.right
- tabRect
.left
))
738 rc
.right
= rc
.left
+ tabRect
.right
- tabRect
.left
;
739 psInfo
->width
= MulDiv((rc
.right
- rc
.left
),4,units
.left
);
742 SendMessageW(hwndTabCtrl
, TCM_ADJUSTRECT
, TRUE
, (LPARAM
)&rc
);
744 tabOffsetX
= -(rc
.left
);
745 tabOffsetY
= -(rc
.top
);
749 TRACE("setting tab %08lx, rc (0,0)-(%d,%d)\n",
750 (DWORD
)hwndTabCtrl
, rc
.right
, rc
.bottom
);
751 SetWindowPos(hwndTabCtrl
, 0, 0, 0, rc
.right
, rc
.bottom
,
752 SWP_NOMOVE
| SWP_NOZORDER
| SWP_NOACTIVATE
);
754 GetClientRect(hwndTabCtrl
, &rc
);
756 TRACE("tab client rc %d %d %d %d\n",
757 rc
.left
, rc
.top
, rc
.right
, rc
.bottom
);
759 rc
.right
+= ((padding
.x
* 2) + tabOffsetX
);
760 rc
.bottom
+= (buttonHeight
+ (3 * padding
.y
) + tabOffsetY
);
763 * Resize the property sheet.
765 TRACE("setting dialog %08lx, rc (0,0)-(%d,%d)\n",
766 (DWORD
)hwndDlg
, rc
.right
, rc
.bottom
);
767 SetWindowPos(hwndDlg
, 0, 0, 0, rc
.right
, rc
.bottom
,
768 SWP_NOMOVE
| SWP_NOZORDER
| SWP_NOACTIVATE
);
772 /******************************************************************************
773 * PROPSHEET_AdjustSizeWizard
775 * Resizes the property sheet to fit the largest page.
777 static BOOL
PROPSHEET_AdjustSizeWizard(HWND hwndDlg
, PropSheetInfo
* psInfo
)
779 HWND hwndButton
= GetDlgItem(hwndDlg
, IDCANCEL
);
780 HWND hwndLine
= GetDlgItem(hwndDlg
, IDC_SUNKEN_LINE
);
781 HWND hwndTabCtrl
= GetDlgItem(hwndDlg
, IDC_TABCONTROL
);
783 int buttonHeight
, lineHeight
;
784 PADDING_INFO padding
= PROPSHEET_GetPaddingInfoWizard(hwndDlg
, psInfo
);
787 /* Get the height of buttons */
788 GetClientRect(hwndButton
, &rc
);
789 buttonHeight
= rc
.bottom
;
791 GetClientRect(hwndLine
, &rc
);
792 lineHeight
= rc
.bottom
;
794 /* retrieve the dialog units */
795 units
.left
= units
.right
= 4;
796 units
.top
= units
.bottom
= 8;
797 MapDialogRect(hwndDlg
, &units
);
804 rc
.right
= psInfo
->width
;
805 rc
.bottom
= psInfo
->height
;
807 MapDialogRect(hwndDlg
, &rc
);
809 GetClientRect(hwndTabCtrl
,&tabRect
);
811 if ((rc
.bottom
- rc
.top
) < (tabRect
.bottom
- tabRect
.top
))
813 rc
.bottom
= rc
.top
+ tabRect
.bottom
- tabRect
.top
;
814 psInfo
->height
= MulDiv((rc
.bottom
- rc
.top
), 8, units
.top
);
817 if ((rc
.right
- rc
.left
) < (tabRect
.right
- tabRect
.left
))
819 rc
.right
= rc
.left
+ tabRect
.right
- tabRect
.left
;
820 psInfo
->width
= MulDiv((rc
.right
- rc
.left
), 4, units
.left
);
823 TRACE("Biggest page %d %d %d %d\n", rc
.left
, rc
.top
, rc
.right
, rc
.bottom
);
824 TRACE(" constants padx=%d, pady=%d, butH=%d, lH=%d\n",
825 padding
.x
, padding
.y
, buttonHeight
, lineHeight
);
828 rc
.right
+= (padding
.x
* 2);
829 rc
.bottom
+= (buttonHeight
+ (5 * padding
.y
) + lineHeight
);
832 * Resize the property sheet.
834 TRACE("setting dialog %08lx, rc (0,0)-(%d,%d)\n",
835 (DWORD
)hwndDlg
, rc
.right
, rc
.bottom
);
836 SetWindowPos(hwndDlg
, 0, 0, 0, rc
.right
, rc
.bottom
,
837 SWP_NOMOVE
| SWP_NOZORDER
| SWP_NOACTIVATE
);
841 /******************************************************************************
842 * PROPSHEET_AdjustButtons
844 * Adjusts the buttons' positions.
846 static BOOL
PROPSHEET_AdjustButtons(HWND hwndParent
, PropSheetInfo
* psInfo
)
848 HWND hwndButton
= GetDlgItem(hwndParent
, IDOK
);
852 int buttonWidth
, buttonHeight
;
853 PADDING_INFO padding
= PROPSHEET_GetPaddingInfo(hwndParent
);
855 if (psInfo
->hasApply
)
862 * Obtain the size of the buttons.
864 GetClientRect(hwndButton
, &rcSheet
);
865 buttonWidth
= rcSheet
.right
;
866 buttonHeight
= rcSheet
.bottom
;
869 * Get the size of the property sheet.
871 GetClientRect(hwndParent
, &rcSheet
);
874 * All buttons will be at this y coordinate.
876 y
= rcSheet
.bottom
- (padding
.y
+ buttonHeight
);
879 * Position OK button.
881 hwndButton
= GetDlgItem(hwndParent
, IDOK
);
883 x
= rcSheet
.right
- ((padding
.x
+ buttonWidth
) * num_buttons
);
885 SetWindowPos(hwndButton
, 0, x
, y
, 0, 0,
886 SWP_NOSIZE
| SWP_NOZORDER
| SWP_NOACTIVATE
);
889 * Position Cancel button.
891 hwndButton
= GetDlgItem(hwndParent
, IDCANCEL
);
893 x
= rcSheet
.right
- ((padding
.x
+ buttonWidth
) * (num_buttons
- 1));
895 SetWindowPos(hwndButton
, 0, x
, y
, 0, 0,
896 SWP_NOSIZE
| SWP_NOZORDER
| SWP_NOACTIVATE
);
899 * Position Apply button.
901 hwndButton
= GetDlgItem(hwndParent
, IDC_APPLY_BUTTON
);
903 if (psInfo
->hasApply
)
906 x
= rcSheet
.right
- ((padding
.x
+ buttonWidth
) * 2);
908 x
= rcSheet
.right
- (padding
.x
+ buttonWidth
);
910 SetWindowPos(hwndButton
, 0, x
, y
, 0, 0,
911 SWP_NOSIZE
| SWP_NOZORDER
| SWP_NOACTIVATE
);
913 EnableWindow(hwndButton
, FALSE
);
916 ShowWindow(hwndButton
, SW_HIDE
);
919 * Position Help button.
921 hwndButton
= GetDlgItem(hwndParent
, IDHELP
);
925 x
= rcSheet
.right
- (padding
.x
+ buttonWidth
);
927 SetWindowPos(hwndButton
, 0, x
, y
, 0, 0,
928 SWP_NOSIZE
| SWP_NOZORDER
| SWP_NOACTIVATE
);
931 ShowWindow(hwndButton
, SW_HIDE
);
936 /******************************************************************************
937 * PROPSHEET_AdjustButtonsWizard
939 * Adjusts the buttons' positions.
941 static BOOL
PROPSHEET_AdjustButtonsWizard(HWND hwndParent
,
942 PropSheetInfo
* psInfo
)
944 HWND hwndButton
= GetDlgItem(hwndParent
, IDCANCEL
);
945 HWND hwndLine
= GetDlgItem(hwndParent
, IDC_SUNKEN_LINE
);
949 int buttonWidth
, buttonHeight
, lineHeight
, lineWidth
;
950 PADDING_INFO padding
= PROPSHEET_GetPaddingInfoWizard(hwndParent
, psInfo
);
956 * Obtain the size of the buttons.
958 GetClientRect(hwndButton
, &rcSheet
);
959 buttonWidth
= rcSheet
.right
;
960 buttonHeight
= rcSheet
.bottom
;
962 GetClientRect(hwndLine
, &rcSheet
);
963 lineHeight
= rcSheet
.bottom
;
966 * Get the size of the property sheet.
968 GetClientRect(hwndParent
, &rcSheet
);
971 * All buttons will be at this y coordinate.
973 y
= rcSheet
.bottom
- (padding
.y
+ buttonHeight
);
976 * Position the Next and the Finish buttons.
978 hwndButton
= GetDlgItem(hwndParent
, IDC_NEXT_BUTTON
);
980 x
= rcSheet
.right
- ((padding
.x
+ buttonWidth
) * (num_buttons
- 1));
982 SetWindowPos(hwndButton
, 0, x
, y
, 0, 0,
983 SWP_NOSIZE
| SWP_NOZORDER
| SWP_NOACTIVATE
);
985 hwndButton
= GetDlgItem(hwndParent
, IDC_FINISH_BUTTON
);
987 SetWindowPos(hwndButton
, 0, x
, y
, 0, 0,
988 SWP_NOSIZE
| SWP_NOZORDER
| SWP_NOACTIVATE
);
990 ShowWindow(hwndButton
, SW_HIDE
);
993 * Position the Back button.
995 hwndButton
= GetDlgItem(hwndParent
, IDC_BACK_BUTTON
);
999 SetWindowPos(hwndButton
, 0, x
, y
, 0, 0,
1000 SWP_NOSIZE
| SWP_NOZORDER
| SWP_NOACTIVATE
);
1003 * Position the Cancel button.
1005 hwndButton
= GetDlgItem(hwndParent
, IDCANCEL
);
1007 x
= rcSheet
.right
- ((padding
.x
+ buttonWidth
) * (num_buttons
- 2));
1009 SetWindowPos(hwndButton
, 0, x
, y
, 0, 0,
1010 SWP_NOSIZE
| SWP_NOZORDER
| SWP_NOACTIVATE
);
1013 * Position Help button.
1015 hwndButton
= GetDlgItem(hwndParent
, IDHELP
);
1017 if (psInfo
->hasHelp
)
1019 x
= rcSheet
.right
- (padding
.x
+ buttonWidth
);
1021 SetWindowPos(hwndButton
, 0, x
, y
, 0, 0,
1022 SWP_NOSIZE
| SWP_NOZORDER
| SWP_NOACTIVATE
);
1025 ShowWindow(hwndButton
, SW_HIDE
);
1028 * Position and resize the sunken line.
1031 y
= rcSheet
.bottom
- ((padding
.y
* 2) + buttonHeight
+ lineHeight
);
1033 GetClientRect(hwndParent
, &rcSheet
);
1034 lineWidth
= rcSheet
.right
- (padding
.x
* 2);
1036 SetWindowPos(hwndLine
, 0, x
, y
, lineWidth
, 2,
1037 SWP_NOZORDER
| SWP_NOACTIVATE
);
1042 /******************************************************************************
1043 * PROPSHEET_GetPaddingInfo
1045 * Returns the layout information.
1047 static PADDING_INFO
PROPSHEET_GetPaddingInfo(HWND hwndDlg
)
1049 HWND hwndTab
= GetDlgItem(hwndDlg
, IDC_TABCONTROL
);
1052 PADDING_INFO padding
;
1054 GetWindowRect(hwndTab
, &rcTab
);
1059 ScreenToClient(hwndDlg
, &tl
);
1067 /******************************************************************************
1068 * PROPSHEET_GetPaddingInfoWizard
1070 * Returns the layout information.
1071 * Vertical spacing is the distance between the line and the buttons.
1072 * Do NOT use the Help button to gather padding information when it isn't mapped
1073 * (PSH_HASHELP), as app writers aren't forced to supply correct coordinates
1074 * for it in this case !
1075 * FIXME: I'm not sure about any other coordinate problems with these evil
1076 * buttons. Fix it in case additional problems appear or maybe calculate
1077 * a padding in a completely different way, as this is somewhat messy.
1079 static PADDING_INFO
PROPSHEET_GetPaddingInfoWizard(HWND hwndDlg
, const PropSheetInfo
*
1082 PADDING_INFO padding
;
1086 POINT ptButton
, ptLine
;
1089 if (psInfo
->hasHelp
)
1095 if (psInfo
->ppshheader
.dwFlags
& INTRNL_ANY_WIZARD
)
1097 idButton
= IDC_NEXT_BUTTON
;
1101 /* hopefully this is ok */
1102 idButton
= IDCANCEL
;
1106 hwndControl
= GetDlgItem(hwndDlg
, idButton
);
1107 GetWindowRect(hwndControl
, &rc
);
1109 ptButton
.x
= rc
.left
;
1110 ptButton
.y
= rc
.top
;
1112 ScreenToClient(hwndDlg
, &ptButton
);
1115 hwndControl
= GetDlgItem(hwndDlg
, IDC_SUNKEN_LINE
);
1116 GetWindowRect(hwndControl
, &rc
);
1119 ptLine
.y
= rc
.bottom
;
1121 ScreenToClient(hwndDlg
, &ptLine
);
1123 padding
.y
= ptButton
.y
- ptLine
.y
;
1126 ERR("padding negative ! Please report this !\n");
1128 /* this is most probably not correct, but the best we have now */
1129 padding
.x
= padding
.y
;
1133 /******************************************************************************
1134 * PROPSHEET_CreateTabControl
1136 * Insert the tabs in the tab control.
1138 static BOOL
PROPSHEET_CreateTabControl(HWND hwndParent
,
1139 PropSheetInfo
* psInfo
)
1141 HWND hwndTabCtrl
= GetDlgItem(hwndParent
, IDC_TABCONTROL
);
1147 item
.mask
= TCIF_TEXT
;
1148 item
.cchTextMax
= MAX_TABTEXT_LENGTH
;
1150 nTabs
= psInfo
->nPages
;
1153 * Set the image list for icons.
1155 if (psInfo
->hImageList
)
1157 SendMessageW(hwndTabCtrl
, TCM_SETIMAGELIST
, 0, (LPARAM
)psInfo
->hImageList
);
1160 for (i
= 0; i
< nTabs
; i
++)
1162 if ( psInfo
->proppage
[i
].hasIcon
)
1164 item
.mask
|= TCIF_IMAGE
;
1165 item
.iImage
= iImage
++;
1169 item
.mask
&= ~TCIF_IMAGE
;
1172 item
.pszText
= (LPWSTR
) psInfo
->proppage
[i
].pszText
;
1173 SendMessageW(hwndTabCtrl
, TCM_INSERTITEMW
, (WPARAM
)i
, (LPARAM
)&item
);
1179 * Get the size of an in-memory Template
1181 *( Based on the code of PROPSHEET_CollectPageInfo)
1184 static UINT
GetTemplateSize(DLGTEMPLATE
* pTemplate
)
1187 const WORD
* p
= (const WORD
*)pTemplate
;
1188 BOOL istemplateex
= (((MyDLGTEMPLATEEX
*)pTemplate
)->signature
== 0xFFFF);
1193 /* DIALOGEX template */
1196 p
++; /* signature */
1197 p
+= 2; /* help ID */
1198 p
+= 2; /* ext style */
1203 /* DIALOG template */
1206 p
+= 2; /* ext style */
1209 nrofitems
= (WORD
)*p
; p
++; /* nb items */
1225 TRACE("menu %s\n",debugstr_w((LPCWSTR
)p
));
1226 p
+= lstrlenW( (LPCWSTR
)p
) + 1;
1240 TRACE("class %s\n",debugstr_w((LPCWSTR
)p
));
1241 p
+= lstrlenW( (LPCWSTR
)p
) + 1;
1246 TRACE("title %s\n",debugstr_w((LPCWSTR
)p
));
1247 p
+= lstrlenW((LPCWSTR
)p
) + 1;
1249 /* font, if DS_FONT set */
1250 if ((DS_SETFONT
& ((istemplateex
)? ((MyDLGTEMPLATEEX
*)pTemplate
)->style
:
1253 p
+=(istemplateex
)?3:1;
1254 TRACE("font %s\n",debugstr_w((LPCWSTR
)p
));
1255 p
+= lstrlenW( (LPCWSTR
)p
) + 1; /* the font name*/
1258 TRACE("%d items\n",nrofitems
);
1259 while (nrofitems
> 0)
1261 p
= (WORD
*)(((DWORD
)p
+ 3) & ~3); /* DWORD align */
1263 p
+= (istemplateex
? sizeof(MyDLGITEMTEMPLATEEX
) : sizeof(DLGITEMTEMPLATE
))/sizeof(WORD
);
1271 TRACE("class ordinal 0x%08lx\n",*(DWORD
*)p
);
1275 TRACE("class %s\n",debugstr_w((LPCWSTR
)p
));
1276 p
+= lstrlenW( (LPCWSTR
)p
) + 1;
1285 TRACE("text ordinal 0x%08lx\n",*(DWORD
*)p
);
1289 TRACE("text %s\n",debugstr_w((LPCWSTR
)p
));
1290 p
+= lstrlenW( (LPCWSTR
)p
) + 1;
1293 p
+= *p
+ 1; /* Skip extra data */
1297 TRACE("%p %p size 0x%08x\n",p
, (WORD
*)pTemplate
,sizeof(WORD
)*(p
- (WORD
*)pTemplate
));
1298 return (p
- (WORD
*)pTemplate
)*sizeof(WORD
);
1302 /******************************************************************************
1303 * PROPSHEET_CreatePage
1307 static BOOL
PROPSHEET_CreatePage(HWND hwndParent
,
1309 const PropSheetInfo
* psInfo
,
1310 LPCPROPSHEETPAGEW ppshpage
)
1312 DLGTEMPLATE
* pTemplate
;
1315 PropPageInfo
* ppInfo
= psInfo
->proppage
;
1316 PADDING_INFO padding
;
1317 UINT pageWidth
,pageHeight
;
1321 TRACE("index %d\n", index
);
1323 if (ppshpage
== NULL
)
1328 if (ppshpage
->dwFlags
& PSP_DLGINDIRECT
)
1330 pTemplate
= (DLGTEMPLATE
*)ppshpage
->u
.pResource
;
1331 resSize
= GetTemplateSize(pTemplate
);
1338 hResource
= FindResourceW(ppshpage
->hInstance
,
1339 ppshpage
->u
.pszTemplate
,
1344 resSize
= SizeofResource(ppshpage
->hInstance
, hResource
);
1346 hTemplate
= LoadResource(ppshpage
->hInstance
, hResource
);
1350 pTemplate
= (LPDLGTEMPLATEW
)LockResource(hTemplate
);
1352 * Make a copy of the dialog template to make it writable
1355 temp
= COMCTL32_Alloc(resSize
);
1359 memcpy(temp
, pTemplate
, resSize
);
1362 if (((MyDLGTEMPLATEEX
*)pTemplate
)->signature
== 0xFFFF)
1364 ((MyDLGTEMPLATEEX
*)pTemplate
)->style
|= WS_CHILD
| DS_CONTROL
;
1365 ((MyDLGTEMPLATEEX
*)pTemplate
)->style
&= ~DS_MODALFRAME
;
1366 ((MyDLGTEMPLATEEX
*)pTemplate
)->style
&= ~WS_CAPTION
;
1367 ((MyDLGTEMPLATEEX
*)pTemplate
)->style
&= ~WS_SYSMENU
;
1368 ((MyDLGTEMPLATEEX
*)pTemplate
)->style
&= ~WS_POPUP
;
1369 ((MyDLGTEMPLATEEX
*)pTemplate
)->style
&= ~WS_DISABLED
;
1370 ((MyDLGTEMPLATEEX
*)pTemplate
)->style
&= ~WS_VISIBLE
;
1371 ((MyDLGTEMPLATEEX
*)pTemplate
)->style
&= ~WS_THICKFRAME
;
1375 pTemplate
->style
|= WS_CHILD
| DS_CONTROL
;
1376 pTemplate
->style
&= ~DS_MODALFRAME
;
1377 pTemplate
->style
&= ~WS_CAPTION
;
1378 pTemplate
->style
&= ~WS_SYSMENU
;
1379 pTemplate
->style
&= ~WS_POPUP
;
1380 pTemplate
->style
&= ~WS_DISABLED
;
1381 pTemplate
->style
&= ~WS_VISIBLE
;
1382 pTemplate
->style
&= ~WS_THICKFRAME
;
1385 if (psInfo
->proppage
[index
].useCallback
)
1386 (*(ppshpage
->pfnCallback
))(hwndParent
,
1388 (LPPROPSHEETPAGEW
)ppshpage
);
1390 hwndPage
= CreateDialogIndirectParamW(ppshpage
->hInstance
,
1393 ppshpage
->pfnDlgProc
,
1395 /* Free a no more needed copy */
1397 COMCTL32_Free(temp
);
1399 ppInfo
[index
].hwndPage
= hwndPage
;
1401 if (psInfo
->ppshheader
.dwFlags
& INTRNL_ANY_WIZARD
) {
1402 /* FIXME: This code may no longer be correct.
1403 * It was not for the non-wizard path. (GLA 6/02)
1405 rc
.left
= psInfo
->x
;
1407 rc
.right
= psInfo
->width
;
1408 rc
.bottom
= psInfo
->height
;
1410 MapDialogRect(hwndParent
, &rc
);
1412 pageWidth
= rc
.right
- rc
.left
;
1413 pageHeight
= rc
.bottom
- rc
.top
;
1415 padding
= PROPSHEET_GetPaddingInfoWizard(hwndParent
, psInfo
);
1416 TRACE("setting page %08lx, rc (%d,%d)-(%d,%d) w=%d, h=%d, padx=%d, pady=%d\n",
1417 (DWORD
)hwndPage
, rc
.left
, rc
.top
, rc
.right
, rc
.bottom
,
1418 pageWidth
, pageHeight
, padding
.x
, padding
.y
);
1419 SetWindowPos(hwndPage
, HWND_TOP
,
1420 rc
.left
+ padding
.x
/2,
1421 rc
.top
+ padding
.y
/2,
1422 pageWidth
, pageHeight
, 0);
1426 * Ask the Tab control to reduce the client rectangle to that
1429 PROPSHEET_GetPageRect(psInfo
, hwndParent
, &rc
);
1430 pageWidth
= rc
.right
- rc
.left
;
1431 pageHeight
= rc
.bottom
- rc
.top
;
1432 TRACE("setting page %08lx, rc (%d,%d)-(%d,%d) w=%d, h=%d\n",
1433 (DWORD
)hwndPage
, rc
.left
, rc
.top
, rc
.right
, rc
.bottom
,
1434 pageWidth
, pageHeight
);
1435 SetWindowPos(hwndPage
, HWND_TOP
,
1437 pageWidth
, pageHeight
, 0);
1443 /******************************************************************************
1444 * PROPSHEET_ShowPage
1446 * Displays or creates the specified page.
1448 static BOOL
PROPSHEET_ShowPage(HWND hwndDlg
, int index
, PropSheetInfo
* psInfo
)
1452 TRACE("active_page %d, index %d\n", psInfo
->active_page
, index
);
1453 if (index
== psInfo
->active_page
)
1455 if (GetTopWindow(hwndDlg
) != psInfo
->proppage
[index
].hwndPage
)
1456 SetWindowPos(psInfo
->proppage
[index
].hwndPage
, HWND_TOP
, 0, 0, 0, 0, SWP_NOSIZE
| SWP_NOMOVE
);
1460 if (psInfo
->proppage
[index
].hwndPage
== 0)
1462 LPCPROPSHEETPAGEW ppshpage
;
1464 ppshpage
= (LPCPROPSHEETPAGEW
)psInfo
->proppage
[index
].hpage
;
1465 PROPSHEET_CreatePage(hwndDlg
, index
, psInfo
, ppshpage
);
1468 if (psInfo
->active_page
!= -1)
1469 ShowWindow(psInfo
->proppage
[psInfo
->active_page
].hwndPage
, SW_HIDE
);
1471 ShowWindow(psInfo
->proppage
[index
].hwndPage
, SW_SHOW
);
1473 /* Synchronize current selection with tab control
1474 * It seems to be needed even in case of PSH_WIZARD (no tab controls there) */
1475 hwndTabCtrl
= GetDlgItem(hwndDlg
, IDC_TABCONTROL
);
1476 SendMessageW(hwndTabCtrl
, TCM_SETCURSEL
, index
, 0);
1478 psInfo
->active_page
= index
;
1479 psInfo
->activeValid
= TRUE
;
1484 /******************************************************************************
1487 static BOOL
PROPSHEET_Back(HWND hwndDlg
)
1491 PropSheetInfo
* psInfo
= (PropSheetInfo
*) GetPropW(hwndDlg
,
1496 TRACE("active_page %d\n", psInfo
->active_page
);
1497 if (psInfo
->active_page
< 0)
1500 psn
.hdr
.code
= PSN_WIZBACK
;
1501 psn
.hdr
.hwndFrom
= hwndDlg
;
1505 hwndPage
= psInfo
->proppage
[psInfo
->active_page
].hwndPage
;
1507 result
= SendMessageW(hwndPage
, WM_NOTIFY
, 0, (LPARAM
) &psn
);
1510 else if (result
== 0)
1511 idx
= psInfo
->active_page
- 1;
1513 idx
= PROPSHEET_FindPageByResId(psInfo
, result
);
1515 if (idx
>= 0 && idx
< psInfo
->nPages
)
1517 if (PROPSHEET_CanSetCurSel(hwndDlg
))
1518 PROPSHEET_SetCurSel(hwndDlg
, idx
, -1, 0);
1523 /******************************************************************************
1526 static BOOL
PROPSHEET_Next(HWND hwndDlg
)
1530 LRESULT msgResult
= 0;
1531 PropSheetInfo
* psInfo
= (PropSheetInfo
*) GetPropW(hwndDlg
,
1535 TRACE("active_page %d\n", psInfo
->active_page
);
1536 if (psInfo
->active_page
< 0)
1539 psn
.hdr
.code
= PSN_WIZNEXT
;
1540 psn
.hdr
.hwndFrom
= hwndDlg
;
1544 hwndPage
= psInfo
->proppage
[psInfo
->active_page
].hwndPage
;
1546 msgResult
= SendMessageA(hwndPage
, WM_NOTIFY
, 0, (LPARAM
) &psn
);
1547 if (msgResult
== -1)
1549 else if (msgResult
== 0)
1550 idx
= psInfo
->active_page
+ 1;
1552 idx
= PROPSHEET_FindPageByResId(psInfo
, msgResult
);
1554 if (idx
< psInfo
->nPages
)
1556 if (PROPSHEET_CanSetCurSel(hwndDlg
) != FALSE
)
1557 PROPSHEET_SetCurSel(hwndDlg
, idx
, 1, 0);
1563 /******************************************************************************
1566 static BOOL
PROPSHEET_Finish(HWND hwndDlg
)
1570 LRESULT msgResult
= 0;
1571 PropSheetInfo
* psInfo
= (PropSheetInfo
*) GetPropW(hwndDlg
,
1574 TRACE("active_page %d\n", psInfo
->active_page
);
1575 if (psInfo
->active_page
< 0)
1578 psn
.hdr
.code
= PSN_WIZFINISH
;
1579 psn
.hdr
.hwndFrom
= hwndDlg
;
1583 hwndPage
= psInfo
->proppage
[psInfo
->active_page
].hwndPage
;
1585 msgResult
= SendMessageW(hwndPage
, WM_NOTIFY
, 0, (LPARAM
) &psn
);
1587 TRACE("msg result %ld\n", msgResult
);
1592 if (psInfo
->isModeless
)
1593 psInfo
->activeValid
= FALSE
;
1595 EndDialog(hwndDlg
, TRUE
);
1600 /******************************************************************************
1603 static BOOL
PROPSHEET_Apply(HWND hwndDlg
, LPARAM lParam
)
1609 PropSheetInfo
* psInfo
= (PropSheetInfo
*) GetPropW(hwndDlg
,
1612 TRACE("active_page %d\n", psInfo
->active_page
);
1613 if (psInfo
->active_page
< 0)
1616 psn
.hdr
.hwndFrom
= hwndDlg
;
1622 * Send PSN_KILLACTIVE to the current page.
1624 psn
.hdr
.code
= PSN_KILLACTIVE
;
1626 hwndPage
= psInfo
->proppage
[psInfo
->active_page
].hwndPage
;
1628 if (SendMessageA(hwndPage
, WM_NOTIFY
, 0, (LPARAM
) &psn
) != FALSE
)
1632 * Send PSN_APPLY to all pages.
1634 psn
.hdr
.code
= PSN_APPLY
;
1635 psn
.lParam
= lParam
;
1637 for (i
= 0; i
< psInfo
->nPages
; i
++)
1639 hwndPage
= psInfo
->proppage
[i
].hwndPage
;
1642 msgResult
= SendMessageA(hwndPage
, WM_NOTIFY
, 0, (LPARAM
) &psn
);
1643 if (msgResult
== PSNRET_INVALID_NOCHANGEPAGE
)
1650 psInfo
->activeValid
= FALSE
;
1652 else if(psInfo
->active_page
>= 0)
1654 psn
.hdr
.code
= PSN_SETACTIVE
;
1656 hwndPage
= psInfo
->proppage
[psInfo
->active_page
].hwndPage
;
1657 SendMessageA(hwndPage
, WM_NOTIFY
, 0, (LPARAM
) &psn
);
1663 /******************************************************************************
1666 static void PROPSHEET_Cancel(HWND hwndDlg
, LPARAM lParam
)
1668 PropSheetInfo
* psInfo
= (PropSheetInfo
*) GetPropW(hwndDlg
,
1674 TRACE("active_page %d\n", psInfo
->active_page
);
1675 if (psInfo
->active_page
< 0)
1678 hwndPage
= psInfo
->proppage
[psInfo
->active_page
].hwndPage
;
1679 psn
.hdr
.code
= PSN_QUERYCANCEL
;
1680 psn
.hdr
.hwndFrom
= hwndDlg
;
1684 if (SendMessageA(hwndPage
, WM_NOTIFY
, 0, (LPARAM
) &psn
))
1687 psn
.hdr
.code
= PSN_RESET
;
1688 psn
.lParam
= lParam
;
1690 for (i
= 0; i
< psInfo
->nPages
; i
++)
1692 hwndPage
= psInfo
->proppage
[i
].hwndPage
;
1695 SendMessageA(hwndPage
, WM_NOTIFY
, 0, (LPARAM
) &psn
);
1698 if (psInfo
->isModeless
)
1700 /* makes PSM_GETCURRENTPAGEHWND return NULL */
1701 psInfo
->activeValid
= FALSE
;
1704 EndDialog(hwndDlg
, FALSE
);
1707 /******************************************************************************
1710 static void PROPSHEET_Help(HWND hwndDlg
)
1712 PropSheetInfo
* psInfo
= (PropSheetInfo
*) GetPropW(hwndDlg
,
1717 TRACE("active_page %d\n", psInfo
->active_page
);
1718 if (psInfo
->active_page
< 0)
1721 hwndPage
= psInfo
->proppage
[psInfo
->active_page
].hwndPage
;
1722 psn
.hdr
.code
= PSN_HELP
;
1723 psn
.hdr
.hwndFrom
= hwndDlg
;
1727 SendMessageA(hwndPage
, WM_NOTIFY
, 0, (LPARAM
) &psn
);
1730 /******************************************************************************
1733 static void PROPSHEET_Changed(HWND hwndDlg
, HWND hwndDirtyPage
)
1736 PropSheetInfo
* psInfo
= (PropSheetInfo
*) GetPropW(hwndDlg
,
1740 if (!psInfo
) return;
1742 * Set the dirty flag of this page.
1744 for (i
= 0; i
< psInfo
->nPages
; i
++)
1746 if (psInfo
->proppage
[i
].hwndPage
== hwndDirtyPage
)
1747 psInfo
->proppage
[i
].isDirty
= TRUE
;
1751 * Enable the Apply button.
1753 if (psInfo
->hasApply
)
1755 HWND hwndApplyBtn
= GetDlgItem(hwndDlg
, IDC_APPLY_BUTTON
);
1757 EnableWindow(hwndApplyBtn
, TRUE
);
1761 /******************************************************************************
1762 * PROPSHEET_UnChanged
1764 static void PROPSHEET_UnChanged(HWND hwndDlg
, HWND hwndCleanPage
)
1767 BOOL noPageDirty
= TRUE
;
1768 HWND hwndApplyBtn
= GetDlgItem(hwndDlg
, IDC_APPLY_BUTTON
);
1769 PropSheetInfo
* psInfo
= (PropSheetInfo
*) GetPropW(hwndDlg
,
1773 if ( !psInfo
) return;
1774 for (i
= 0; i
< psInfo
->nPages
; i
++)
1776 /* set the specified page as clean */
1777 if (psInfo
->proppage
[i
].hwndPage
== hwndCleanPage
)
1778 psInfo
->proppage
[i
].isDirty
= FALSE
;
1780 /* look to see if there's any dirty pages */
1781 if (psInfo
->proppage
[i
].isDirty
)
1782 noPageDirty
= FALSE
;
1786 * Disable Apply button.
1789 EnableWindow(hwndApplyBtn
, FALSE
);
1792 /******************************************************************************
1793 * PROPSHEET_PressButton
1795 static void PROPSHEET_PressButton(HWND hwndDlg
, int buttonID
)
1797 TRACE("buttonID %d\n", buttonID
);
1800 case PSBTN_APPLYNOW
:
1801 PROPSHEET_DoCommand(hwndDlg
, IDC_APPLY_BUTTON
);
1804 PROPSHEET_Back(hwndDlg
);
1807 PROPSHEET_DoCommand(hwndDlg
, IDCANCEL
);
1810 PROPSHEET_Finish(hwndDlg
);
1813 PROPSHEET_DoCommand(hwndDlg
, IDHELP
);
1816 PROPSHEET_Next(hwndDlg
);
1819 PROPSHEET_DoCommand(hwndDlg
, IDOK
);
1822 FIXME("Invalid button index %d\n", buttonID
);
1827 /*************************************************************************
1828 * BOOL PROPSHEET_CanSetCurSel [Internal]
1830 * Test whether the current page can be changed by sending a PSN_KILLACTIVE
1833 * hwndDlg [I] handle to a Dialog hWnd
1836 * TRUE if Current Selection can change
1840 static BOOL
PROPSHEET_CanSetCurSel(HWND hwndDlg
)
1842 PropSheetInfo
* psInfo
= (PropSheetInfo
*) GetPropW(hwndDlg
,
1848 TRACE("active_page %d\n", psInfo
->active_page
);
1855 if (psInfo
->active_page
< 0)
1862 * Notify the current page.
1864 hwndPage
= psInfo
->proppage
[psInfo
->active_page
].hwndPage
;
1865 psn
.hdr
.code
= PSN_KILLACTIVE
;
1866 psn
.hdr
.hwndFrom
= hwndDlg
;
1870 res
= !SendMessageA(hwndPage
, WM_NOTIFY
, 0, (LPARAM
) &psn
);
1873 TRACE("<-- %d\n", res
);
1877 /******************************************************************************
1878 * PROPSHEET_SetCurSel
1880 static BOOL
PROPSHEET_SetCurSel(HWND hwndDlg
,
1883 HPROPSHEETPAGE hpage
1886 PropSheetInfo
* psInfo
= (PropSheetInfo
*) GetPropW(hwndDlg
, PropSheetInfoStr
);
1887 HWND hwndHelp
= GetDlgItem(hwndDlg
, IDHELP
);
1888 HWND hwndTabControl
= GetDlgItem(hwndDlg
, IDC_TABCONTROL
);
1890 TRACE("index %d, skipdir %d, hpage %p\n", index
, skipdir
, hpage
);
1891 /* hpage takes precedence over index */
1893 index
= PROPSHEET_GetPageIndex(hpage
, psInfo
);
1895 if (index
< 0 || index
>= psInfo
->nPages
)
1897 TRACE("Could not find page to select!\n");
1906 SendMessageW(hwndTabControl
, TCM_SETCURSEL
, index
, 0);
1908 psn
.hdr
.code
= PSN_SETACTIVE
;
1909 psn
.hdr
.hwndFrom
= hwndDlg
;
1913 if (!psInfo
->proppage
[index
].hwndPage
) {
1914 LPCPROPSHEETPAGEW ppshpage
= (LPCPROPSHEETPAGEW
)psInfo
->proppage
[index
].hpage
;
1915 PROPSHEET_CreatePage(hwndDlg
, index
, psInfo
, ppshpage
);
1918 result
= SendMessageW(psInfo
->proppage
[index
].hwndPage
, WM_NOTIFY
, 0, (LPARAM
) &psn
);
1925 FIXME("Tried to skip before first property sheet page!\n");
1928 if (index
>= psInfo
->nPages
) {
1929 FIXME("Tried to skip after last property sheet page!\n");
1930 index
= psInfo
->nPages
-1;
1934 else if (result
!= 0)
1936 index
= PROPSHEET_FindPageByResId(psInfo
, result
);
1941 * Display the new page.
1943 PROPSHEET_ShowPage(hwndDlg
, index
, psInfo
);
1945 if (psInfo
->proppage
[index
].hasHelp
)
1946 EnableWindow(hwndHelp
, TRUE
);
1948 EnableWindow(hwndHelp
, FALSE
);
1953 /******************************************************************************
1954 * PROPSHEET_SetCurSelId
1956 * Selects the page, specified by resource id.
1958 static void PROPSHEET_SetCurSelId(HWND hwndDlg
, int id
)
1961 PropSheetInfo
* psInfo
=
1962 (PropSheetInfo
*) GetPropW(hwndDlg
, PropSheetInfoStr
);
1964 idx
= PROPSHEET_FindPageByResId(psInfo
, id
);
1965 if (idx
< psInfo
->nPages
)
1967 if (PROPSHEET_CanSetCurSel(hwndDlg
) != FALSE
)
1968 PROPSHEET_SetCurSel(hwndDlg
, idx
, 1, 0);
1972 /******************************************************************************
1973 * PROPSHEET_SetTitleA
1975 static void PROPSHEET_SetTitleA(HWND hwndDlg
, DWORD dwStyle
, LPCSTR lpszText
)
1977 if(HIWORD(lpszText
))
1980 MultiByteToWideChar(CP_ACP
, 0, lpszText
, -1,
1981 szTitle
, sizeof szTitle
);
1982 PROPSHEET_SetTitleW(hwndDlg
, dwStyle
, szTitle
);
1986 PROPSHEET_SetTitleW(hwndDlg
, dwStyle
, (LPCWSTR
)lpszText
);
1990 /******************************************************************************
1991 * PROPSHEET_SetTitleW
1993 static void PROPSHEET_SetTitleW(HWND hwndDlg
, DWORD dwStyle
, LPCWSTR lpszText
)
1995 PropSheetInfo
* psInfo
= (PropSheetInfo
*) GetPropW(hwndDlg
, PropSheetInfoStr
);
1998 TRACE("'%s' (style %08lx)\n", debugstr_w(lpszText
), dwStyle
);
1999 if (HIWORD(lpszText
) == 0) {
2000 if (!LoadStringW(psInfo
->ppshheader
.hInstance
,
2001 LOWORD(lpszText
), szTitle
, sizeof(szTitle
)-sizeof(WCHAR
)))
2005 if (dwStyle
& PSH_PROPTITLE
)
2008 int lentitle
= strlenW(lpszText
);
2009 int lenprop
= strlenW(psInfo
->strPropertiesFor
);
2011 dest
= COMCTL32_Alloc( (lentitle
+ lenprop
+ 1)*sizeof (WCHAR
));
2012 strcpyW(dest
, psInfo
->strPropertiesFor
);
2013 strcatW(dest
, lpszText
);
2015 SetWindowTextW(hwndDlg
, dest
);
2016 COMCTL32_Free(dest
);
2019 SetWindowTextW(hwndDlg
, lpszText
);
2022 /******************************************************************************
2023 * PROPSHEET_SetFinishTextA
2025 static void PROPSHEET_SetFinishTextA(HWND hwndDlg
, LPCSTR lpszText
)
2027 HWND hwndButton
= GetDlgItem(hwndDlg
, IDC_FINISH_BUTTON
);
2029 TRACE("'%s'\n", lpszText
);
2030 /* Set text, show and enable the Finish button */
2031 SetWindowTextA(hwndButton
, lpszText
);
2032 ShowWindow(hwndButton
, SW_SHOW
);
2033 EnableWindow(hwndButton
, TRUE
);
2035 /* Make it default pushbutton */
2036 SendMessageA(hwndDlg
, DM_SETDEFID
, IDC_FINISH_BUTTON
, 0);
2038 /* Hide Back button */
2039 hwndButton
= GetDlgItem(hwndDlg
, IDC_BACK_BUTTON
);
2040 ShowWindow(hwndButton
, SW_HIDE
);
2042 /* Hide Next button */
2043 hwndButton
= GetDlgItem(hwndDlg
, IDC_NEXT_BUTTON
);
2044 ShowWindow(hwndButton
, SW_HIDE
);
2047 /******************************************************************************
2048 * PROPSHEET_SetFinishTextW
2050 static void PROPSHEET_SetFinishTextW(HWND hwndDlg
, LPCWSTR lpszText
)
2052 HWND hwndButton
= GetDlgItem(hwndDlg
, IDC_FINISH_BUTTON
);
2054 TRACE("'%s'\n", debugstr_w(lpszText
));
2055 /* Set text, show and enable the Finish button */
2056 SetWindowTextW(hwndButton
, lpszText
);
2057 ShowWindow(hwndButton
, SW_SHOW
);
2058 EnableWindow(hwndButton
, TRUE
);
2060 /* Make it default pushbutton */
2061 SendMessageW(hwndDlg
, DM_SETDEFID
, IDC_FINISH_BUTTON
, 0);
2063 /* Hide Back button */
2064 hwndButton
= GetDlgItem(hwndDlg
, IDC_BACK_BUTTON
);
2065 ShowWindow(hwndButton
, SW_HIDE
);
2067 /* Hide Next button */
2068 hwndButton
= GetDlgItem(hwndDlg
, IDC_NEXT_BUTTON
);
2069 ShowWindow(hwndButton
, SW_HIDE
);
2072 /******************************************************************************
2073 * PROPSHEET_QuerySiblings
2075 static LRESULT
PROPSHEET_QuerySiblings(HWND hwndDlg
,
2076 WPARAM wParam
, LPARAM lParam
)
2080 LRESULT msgResult
= 0;
2081 PropSheetInfo
* psInfo
= (PropSheetInfo
*) GetPropW(hwndDlg
,
2084 while ((i
< psInfo
->nPages
) && (msgResult
== 0))
2086 hwndPage
= psInfo
->proppage
[i
].hwndPage
;
2087 msgResult
= SendMessageA(hwndPage
, PSM_QUERYSIBLINGS
, wParam
, lParam
);
2095 /******************************************************************************
2098 static BOOL
PROPSHEET_AddPage(HWND hwndDlg
,
2099 HPROPSHEETPAGE hpage
)
2101 PropSheetInfo
* psInfo
= (PropSheetInfo
*) GetPropW(hwndDlg
,
2103 HWND hwndTabControl
= GetDlgItem(hwndDlg
, IDC_TABCONTROL
);
2105 LPCPROPSHEETPAGEW ppsp
= (LPCPROPSHEETPAGEW
)hpage
;
2107 TRACE("hpage %p\n", hpage
);
2109 * Allocate and fill in a new PropPageInfo entry.
2111 psInfo
->proppage
= (PropPageInfo
*) COMCTL32_ReAlloc(psInfo
->proppage
,
2112 sizeof(PropPageInfo
) *
2113 (psInfo
->nPages
+ 1));
2114 if (!PROPSHEET_CollectPageInfo(ppsp
, psInfo
, psInfo
->nPages
))
2117 psInfo
->proppage
[psInfo
->nPages
].hpage
= hpage
;
2119 if (ppsp
->dwFlags
& PSP_PREMATURE
)
2121 /* Create the page but don't show it */
2122 PROPSHEET_CreatePage(hwndDlg
, psInfo
->nPages
, psInfo
, ppsp
);
2126 * Add a new tab to the tab control.
2128 item
.mask
= TCIF_TEXT
;
2129 item
.pszText
= (LPWSTR
) psInfo
->proppage
[psInfo
->nPages
].pszText
;
2130 item
.cchTextMax
= MAX_TABTEXT_LENGTH
;
2132 if (psInfo
->hImageList
)
2134 SendMessageW(hwndTabControl
, TCM_SETIMAGELIST
, 0, (LPARAM
)psInfo
->hImageList
);
2137 if ( psInfo
->proppage
[psInfo
->nPages
].hasIcon
)
2139 item
.mask
|= TCIF_IMAGE
;
2140 item
.iImage
= psInfo
->nPages
;
2143 SendMessageW(hwndTabControl
, TCM_INSERTITEMW
, psInfo
->nPages
+ 1,
2148 /* If it is the only page - show it */
2149 if(psInfo
->nPages
== 1)
2150 PROPSHEET_SetCurSel(hwndDlg
, 0, 1, 0);
2154 /******************************************************************************
2155 * PROPSHEET_RemovePage
2157 static BOOL
PROPSHEET_RemovePage(HWND hwndDlg
,
2159 HPROPSHEETPAGE hpage
)
2161 PropSheetInfo
* psInfo
= (PropSheetInfo
*) GetPropW(hwndDlg
,
2163 HWND hwndTabControl
= GetDlgItem(hwndDlg
, IDC_TABCONTROL
);
2164 PropPageInfo
* oldPages
;
2166 TRACE("index %d, hpage %p\n", index
, hpage
);
2170 oldPages
= psInfo
->proppage
;
2172 * hpage takes precedence over index.
2176 index
= PROPSHEET_GetPageIndex(hpage
, psInfo
);
2179 /* Make sure that index is within range */
2180 if (index
< 0 || index
>= psInfo
->nPages
)
2182 TRACE("Could not find page to remove!\n");
2186 TRACE("total pages %d removing page %d active page %d\n",
2187 psInfo
->nPages
, index
, psInfo
->active_page
);
2189 * Check if we're removing the active page.
2191 if (index
== psInfo
->active_page
)
2193 if (psInfo
->nPages
> 1)
2197 /* activate previous page */
2198 PROPSHEET_SetCurSel(hwndDlg
, index
- 1, -1, 0);
2202 /* activate the next page */
2203 PROPSHEET_SetCurSel(hwndDlg
, index
+ 1, 1, 0);
2204 psInfo
->active_page
= index
;
2209 psInfo
->active_page
= -1;
2210 if (!psInfo
->isModeless
)
2212 EndDialog(hwndDlg
, FALSE
);
2217 else if (index
< psInfo
->active_page
)
2218 psInfo
->active_page
--;
2220 /* Destroy page dialog window */
2221 DestroyWindow(psInfo
->proppage
[index
].hwndPage
);
2223 /* Free page resources */
2224 if(psInfo
->proppage
[index
].hpage
)
2226 PROPSHEETPAGEW
* psp
= (PROPSHEETPAGEW
*)psInfo
->proppage
[index
].hpage
;
2228 if ((psp
->dwFlags
& PSP_USETITLE
) && psInfo
->proppage
[index
].pszText
)
2229 HeapFree(GetProcessHeap(), 0, (LPVOID
)psInfo
->proppage
[index
].pszText
);
2231 DestroyPropertySheetPage(psInfo
->proppage
[index
].hpage
);
2234 /* Remove the tab */
2235 SendMessageW(hwndTabControl
, TCM_DELETEITEM
, index
, 0);
2238 psInfo
->proppage
= COMCTL32_Alloc(sizeof(PropPageInfo
) * psInfo
->nPages
);
2241 memcpy(&psInfo
->proppage
[0], &oldPages
[0], index
* sizeof(PropPageInfo
));
2243 if (index
< psInfo
->nPages
)
2244 memcpy(&psInfo
->proppage
[index
], &oldPages
[index
+ 1],
2245 (psInfo
->nPages
- index
) * sizeof(PropPageInfo
));
2247 COMCTL32_Free(oldPages
);
2252 /******************************************************************************
2253 * PROPSHEET_SetWizButtons
2255 * This code will work if (and assumes that) the Next button is on top of the
2256 * Finish button. ie. Finish comes after Next in the Z order.
2257 * This means make sure the dialog template reflects this.
2260 static void PROPSHEET_SetWizButtons(HWND hwndDlg
, DWORD dwFlags
)
2262 HWND hwndBack
= GetDlgItem(hwndDlg
, IDC_BACK_BUTTON
);
2263 HWND hwndNext
= GetDlgItem(hwndDlg
, IDC_NEXT_BUTTON
);
2264 HWND hwndFinish
= GetDlgItem(hwndDlg
, IDC_FINISH_BUTTON
);
2266 TRACE("%ld\n", dwFlags
);
2268 EnableWindow(hwndBack
, FALSE
);
2269 EnableWindow(hwndNext
, FALSE
);
2270 EnableWindow(hwndFinish
, FALSE
);
2272 if (dwFlags
& PSWIZB_BACK
)
2273 EnableWindow(hwndBack
, TRUE
);
2275 if (dwFlags
& PSWIZB_NEXT
)
2277 /* Hide the Finish button */
2278 ShowWindow(hwndFinish
, SW_HIDE
);
2280 /* Show and enable the Next button */
2281 ShowWindow(hwndNext
, SW_SHOW
);
2282 EnableWindow(hwndNext
, TRUE
);
2284 /* Set the Next button as the default pushbutton */
2285 SendMessageA(hwndDlg
, DM_SETDEFID
, IDC_NEXT_BUTTON
, 0);
2288 if ((dwFlags
& PSWIZB_FINISH
) || (dwFlags
& PSWIZB_DISABLEDFINISH
))
2290 /* Hide the Next button */
2291 ShowWindow(hwndNext
, SW_HIDE
);
2293 /* Show the Finish button */
2294 ShowWindow(hwndFinish
, SW_SHOW
);
2296 if (dwFlags
& PSWIZB_FINISH
)
2297 EnableWindow(hwndFinish
, TRUE
);
2299 /* Set the Finish button as the default pushbutton */
2300 SendMessageA(hwndDlg
, DM_SETDEFID
, IDC_FINISH_BUTTON
, 0);
2304 /******************************************************************************
2305 * PROPSHEET_GetPageIndex
2307 * Given a HPROPSHEETPAGE, returns the index of the corresponding page from
2308 * the array of PropPageInfo.
2310 static int PROPSHEET_GetPageIndex(HPROPSHEETPAGE hpage
, PropSheetInfo
* psInfo
)
2315 TRACE("hpage %p\n", hpage
);
2316 while ((index
< psInfo
->nPages
) && (found
== FALSE
))
2318 if (psInfo
->proppage
[index
].hpage
== hpage
)
2330 /******************************************************************************
2333 static void PROPSHEET_CleanUp(HWND hwndDlg
)
2336 PropSheetInfo
* psInfo
= (PropSheetInfo
*) RemovePropW(hwndDlg
,
2340 if (!psInfo
) return;
2341 if (HIWORD(psInfo
->ppshheader
.pszCaption
))
2342 HeapFree(GetProcessHeap(), 0, (LPVOID
)psInfo
->ppshheader
.pszCaption
);
2344 for (i
= 0; i
< psInfo
->nPages
; i
++)
2346 PROPSHEETPAGEA
* psp
= (PROPSHEETPAGEA
*)psInfo
->proppage
[i
].hpage
;
2348 if(psInfo
->proppage
[i
].hwndPage
)
2349 DestroyWindow(psInfo
->proppage
[i
].hwndPage
);
2353 if ((psp
->dwFlags
& PSP_USETITLE
) && psInfo
->proppage
[i
].pszText
)
2354 HeapFree(GetProcessHeap(), 0, (LPVOID
)psInfo
->proppage
[i
].pszText
);
2356 DestroyPropertySheetPage(psInfo
->proppage
[i
].hpage
);
2360 COMCTL32_Free(psInfo
->proppage
);
2361 COMCTL32_Free(psInfo
->strPropertiesFor
);
2362 ImageList_Destroy(psInfo
->hImageList
);
2364 GlobalFree((HGLOBAL
)psInfo
);
2367 /******************************************************************************
2368 * PropertySheet (COMCTL32.@)
2369 * PropertySheetA (COMCTL32.@)
2371 INT WINAPI
PropertySheetA(LPCPROPSHEETHEADERA lppsh
)
2374 PropSheetInfo
* psInfo
= (PropSheetInfo
*) GlobalAlloc(GPTR
,
2375 sizeof(PropSheetInfo
));
2379 TRACE("(%p)\n", lppsh
);
2381 PROPSHEET_CollectSheetInfoA(lppsh
, psInfo
);
2383 psInfo
->proppage
= (PropPageInfo
*) COMCTL32_Alloc(sizeof(PropPageInfo
) *
2385 pByte
= (BYTE
*) psInfo
->ppshheader
.u3
.ppsp
;
2387 for (n
= i
= 0; i
< lppsh
->nPages
; i
++, n
++)
2389 if (!(lppsh
->dwFlags
& PSH_PROPSHEETPAGE
))
2390 psInfo
->proppage
[n
].hpage
= psInfo
->ppshheader
.u3
.phpage
[i
];
2393 psInfo
->proppage
[n
].hpage
= CreatePropertySheetPageA((LPCPROPSHEETPAGEA
)pByte
);
2394 pByte
+= ((LPPROPSHEETPAGEA
)pByte
)->dwSize
;
2397 if (!PROPSHEET_CollectPageInfo((LPCPROPSHEETPAGEW
)psInfo
->proppage
[n
].hpage
,
2400 if (lppsh
->dwFlags
& PSH_PROPSHEETPAGE
)
2401 DestroyPropertySheetPage(psInfo
->proppage
[n
].hpage
);
2407 bRet
= PROPSHEET_CreateDialog(psInfo
);
2412 /******************************************************************************
2413 * PropertySheetW (COMCTL32.@)
2415 INT WINAPI
PropertySheetW(LPCPROPSHEETHEADERW lppsh
)
2418 PropSheetInfo
* psInfo
= (PropSheetInfo
*) GlobalAlloc(GPTR
,
2419 sizeof(PropSheetInfo
));
2423 TRACE("(%p)\n", lppsh
);
2425 PROPSHEET_CollectSheetInfoW(lppsh
, psInfo
);
2427 psInfo
->proppage
= (PropPageInfo
*) COMCTL32_Alloc(sizeof(PropPageInfo
) *
2429 pByte
= (BYTE
*) psInfo
->ppshheader
.u3
.ppsp
;
2431 for (n
= i
= 0; i
< lppsh
->nPages
; i
++, n
++)
2433 if (!(lppsh
->dwFlags
& PSH_PROPSHEETPAGE
))
2434 psInfo
->proppage
[n
].hpage
= psInfo
->ppshheader
.u3
.phpage
[i
];
2437 psInfo
->proppage
[n
].hpage
= CreatePropertySheetPageW((LPCPROPSHEETPAGEW
)pByte
);
2438 pByte
+= ((LPPROPSHEETPAGEW
)pByte
)->dwSize
;
2441 if (!PROPSHEET_CollectPageInfo((LPCPROPSHEETPAGEW
)psInfo
->proppage
[n
].hpage
,
2444 if (lppsh
->dwFlags
& PSH_PROPSHEETPAGE
)
2445 DestroyPropertySheetPage(psInfo
->proppage
[n
].hpage
);
2451 bRet
= PROPSHEET_CreateDialog(psInfo
);
2456 /******************************************************************************
2457 * CreatePropertySheetPage (COMCTL32.@)
2458 * CreatePropertySheetPageA (COMCTL32.@)
2460 HPROPSHEETPAGE WINAPI
CreatePropertySheetPageA(
2461 LPCPROPSHEETPAGEA lpPropSheetPage
)
2463 PROPSHEETPAGEW
* ppsp
= COMCTL32_Alloc(sizeof(PROPSHEETPAGEW
));
2465 memcpy(ppsp
,lpPropSheetPage
,min(lpPropSheetPage
->dwSize
,sizeof(PROPSHEETPAGEA
)));
2467 if ( !(ppsp
->dwFlags
& PSP_DLGINDIRECT
) && HIWORD( ppsp
->u
.pszTemplate
) )
2469 PROPSHEET_AtoW(&ppsp
->u
.pszTemplate
, lpPropSheetPage
->u
.pszTemplate
);
2471 if ( (ppsp
->dwFlags
& PSP_USEICONID
) && HIWORD( ppsp
->u2
.pszIcon
) )
2473 PROPSHEET_AtoW(&ppsp
->u2
.pszIcon
, lpPropSheetPage
->u2
.pszIcon
);
2476 if ((ppsp
->dwFlags
& PSP_USETITLE
) && HIWORD( ppsp
->pszTitle
))
2478 PROPSHEET_AtoW(&ppsp
->pszTitle
, lpPropSheetPage
->pszTitle
);
2480 else if ( !(ppsp
->dwFlags
& PSP_USETITLE
) )
2481 ppsp
->pszTitle
= NULL
;
2483 return (HPROPSHEETPAGE
)ppsp
;
2486 /******************************************************************************
2487 * CreatePropertySheetPageW (COMCTL32.@)
2489 HPROPSHEETPAGE WINAPI
CreatePropertySheetPageW(LPCPROPSHEETPAGEW lpPropSheetPage
)
2491 PROPSHEETPAGEW
* ppsp
= COMCTL32_Alloc(sizeof(PROPSHEETPAGEW
));
2493 memcpy(ppsp
,lpPropSheetPage
,min(lpPropSheetPage
->dwSize
,sizeof(PROPSHEETPAGEW
)));
2495 if ( !(ppsp
->dwFlags
& PSP_DLGINDIRECT
) && HIWORD( ppsp
->u
.pszTemplate
) )
2497 int len
= strlenW(lpPropSheetPage
->u
.pszTemplate
);
2499 ppsp
->u
.pszTemplate
= HeapAlloc( GetProcessHeap(),0,(len
+1)*sizeof (WCHAR
) );
2500 strcpyW( (WCHAR
*)ppsp
->u
.pszTemplate
, lpPropSheetPage
->u
.pszTemplate
);
2502 if ( (ppsp
->dwFlags
& PSP_USEICONID
) && HIWORD( ppsp
->u2
.pszIcon
) )
2504 int len
= strlenW(lpPropSheetPage
->u2
.pszIcon
);
2505 ppsp
->u2
.pszIcon
= HeapAlloc( GetProcessHeap(), 0, (len
+1)*sizeof (WCHAR
) );
2506 strcpyW( (WCHAR
*)ppsp
->u2
.pszIcon
, lpPropSheetPage
->u2
.pszIcon
);
2509 if ((ppsp
->dwFlags
& PSP_USETITLE
) && HIWORD( ppsp
->pszTitle
))
2511 int len
= strlenW(lpPropSheetPage
->pszTitle
);
2512 ppsp
->pszTitle
= HeapAlloc( GetProcessHeap(), 0, (len
+1)*sizeof (WCHAR
) );
2513 strcpyW( (WCHAR
*)ppsp
->pszTitle
, lpPropSheetPage
->pszTitle
);
2515 else if ( !(ppsp
->dwFlags
& PSP_USETITLE
) )
2516 ppsp
->pszTitle
= NULL
;
2518 return (HPROPSHEETPAGE
)ppsp
;
2521 /******************************************************************************
2522 * DestroyPropertySheetPage (COMCTL32.@)
2524 BOOL WINAPI
DestroyPropertySheetPage(HPROPSHEETPAGE hPropPage
)
2526 PROPSHEETPAGEW
*psp
= (PROPSHEETPAGEW
*)hPropPage
;
2531 if ( !(psp
->dwFlags
& PSP_DLGINDIRECT
) && HIWORD( psp
->u
.pszTemplate
) )
2532 HeapFree(GetProcessHeap(), 0, (LPVOID
)psp
->u
.pszTemplate
);
2534 if ( (psp
->dwFlags
& PSP_USEICONID
) && HIWORD( psp
->u2
.pszIcon
) )
2535 HeapFree(GetProcessHeap(), 0, (LPVOID
)psp
->u2
.pszIcon
);
2537 if ((psp
->dwFlags
& PSP_USETITLE
) && HIWORD( psp
->pszTitle
))
2538 HeapFree(GetProcessHeap(), 0, (LPVOID
)psp
->pszTitle
);
2540 COMCTL32_Free(hPropPage
);
2545 /******************************************************************************
2546 * PROPSHEET_IsDialogMessage
2548 static BOOL
PROPSHEET_IsDialogMessage(HWND hwnd
, LPMSG lpMsg
)
2550 PropSheetInfo
* psInfo
= (PropSheetInfo
*) GetPropW(hwnd
, PropSheetInfoStr
);
2553 if (!psInfo
|| (hwnd
!= lpMsg
->hwnd
&& !IsChild(hwnd
, lpMsg
->hwnd
)))
2556 if (lpMsg
->message
== WM_KEYDOWN
&& (GetKeyState(VK_CONTROL
) & 0x8000))
2559 INT dlgCode
= SendMessageA(lpMsg
->hwnd
, WM_GETDLGCODE
, 0, (LPARAM
)lpMsg
);
2561 if (!(dlgCode
& DLGC_WANTMESSAGE
))
2563 switch (lpMsg
->wParam
)
2566 if (GetKeyState(VK_SHIFT
) & 0x8000)
2572 case VK_NEXT
: new_page
= 1; break;
2573 case VK_PRIOR
: new_page
= -1; break;
2579 if (PROPSHEET_CanSetCurSel(hwnd
) != FALSE
)
2581 new_page
+= psInfo
->active_page
;
2584 new_page
= psInfo
->nPages
- 1;
2585 else if (new_page
>= psInfo
->nPages
)
2588 PROPSHEET_SetCurSel(hwnd
, new_page
, 1, 0);
2595 return IsDialogMessageA(hwnd
, lpMsg
);
2598 /******************************************************************************
2599 * PROPSHEET_DoCommand
2601 static BOOL
PROPSHEET_DoCommand(HWND hwnd
, WORD wID
)
2607 case IDC_APPLY_BUTTON
:
2609 HWND hwndApplyBtn
= GetDlgItem(hwnd
, IDC_APPLY_BUTTON
);
2611 if (PROPSHEET_Apply(hwnd
, wID
== IDOK
? 1: 0) == FALSE
)
2616 PropSheetInfo
* psInfo
= (PropSheetInfo
*) GetPropW(hwnd
,
2620 if (psInfo
->restartWindows
)
2621 result
= ID_PSRESTARTWINDOWS
;
2623 /* reboot system takes precedence over restart windows */
2624 if (psInfo
->rebootSystem
)
2625 result
= ID_PSREBOOTSYSTEM
;
2627 if (psInfo
->isModeless
)
2628 psInfo
->activeValid
= FALSE
;
2630 EndDialog(hwnd
, result
);
2633 EnableWindow(hwndApplyBtn
, FALSE
);
2638 case IDC_BACK_BUTTON
:
2639 PROPSHEET_Back(hwnd
);
2642 case IDC_NEXT_BUTTON
:
2643 PROPSHEET_Next(hwnd
);
2646 case IDC_FINISH_BUTTON
:
2647 PROPSHEET_Finish(hwnd
);
2651 PROPSHEET_Cancel(hwnd
, 0);
2655 PROPSHEET_Help(hwnd
);
2662 /******************************************************************************
2663 * PROPSHEET_DialogProc
2666 PROPSHEET_DialogProc(HWND hwnd
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
)
2668 TRACE("hwnd=%p msg=%x wparam=%x lparam=%lx\n",
2669 hwnd
, uMsg
, wParam
, lParam
);
2675 PropSheetInfo
* psInfo
= (PropSheetInfo
*) lParam
;
2676 WCHAR
* strCaption
= (WCHAR
*)COMCTL32_Alloc(MAX_CAPTION_LENGTH
*sizeof(WCHAR
));
2677 HWND hwndTabCtrl
= GetDlgItem(hwnd
, IDC_TABCONTROL
);
2678 LPCPROPSHEETPAGEW ppshpage
;
2681 SetPropW(hwnd
, PropSheetInfoStr
, (HANDLE
)psInfo
);
2684 * psInfo->hwnd is not being used by WINE code - it exists
2685 * for compatibility with "real" Windoze. The same about
2686 * SetWindowLong - WINE is only using the PropSheetInfoStr
2689 psInfo
->hwnd
= hwnd
;
2690 SetWindowLongW(hwnd
,DWL_USER
,(LONG
)psInfo
);
2693 * Small icon in the title bar.
2695 if ((psInfo
->ppshheader
.dwFlags
& PSH_USEICONID
) ||
2696 (psInfo
->ppshheader
.dwFlags
& PSH_USEHICON
))
2699 int icon_cx
= GetSystemMetrics(SM_CXSMICON
);
2700 int icon_cy
= GetSystemMetrics(SM_CYSMICON
);
2702 if (psInfo
->ppshheader
.dwFlags
& PSH_USEICONID
)
2703 hIcon
= LoadImageW(psInfo
->ppshheader
.hInstance
,
2704 psInfo
->ppshheader
.u
.pszIcon
,
2709 hIcon
= psInfo
->ppshheader
.u
.hIcon
;
2711 SendMessageW(hwnd
, WM_SETICON
, 0, (LPARAM
)hIcon
);
2714 if (psInfo
->ppshheader
.dwFlags
& PSH_USEHICON
)
2715 SendMessageW(hwnd
, WM_SETICON
, 0, (LPARAM
)psInfo
->ppshheader
.u
.hIcon
);
2717 psInfo
->strPropertiesFor
= strCaption
;
2719 GetWindowTextW(hwnd
, psInfo
->strPropertiesFor
, MAX_CAPTION_LENGTH
);
2721 PROPSHEET_CreateTabControl(hwnd
, psInfo
);
2723 if (psInfo
->ppshheader
.dwFlags
& INTRNL_ANY_WIZARD
)
2725 if (PROPSHEET_IsTooSmallWizard(hwnd
, psInfo
))
2727 PROPSHEET_AdjustSizeWizard(hwnd
, psInfo
);
2728 PROPSHEET_AdjustButtonsWizard(hwnd
, psInfo
);
2733 if (PROPSHEET_SizeMismatch(hwnd
, psInfo
))
2735 PROPSHEET_AdjustSize(hwnd
, psInfo
);
2736 PROPSHEET_AdjustButtons(hwnd
, psInfo
);
2740 if (psInfo
->useCallback
)
2741 (*(psInfo
->ppshheader
.pfnCallback
))(hwnd
,
2742 PSCB_INITIALIZED
, (LPARAM
)0);
2744 idx
= psInfo
->active_page
;
2745 ppshpage
= (LPCPROPSHEETPAGEW
)psInfo
->proppage
[idx
].hpage
;
2746 psInfo
->active_page
= -1;
2748 PROPSHEET_SetCurSel(hwnd
, idx
, 1, psInfo
->proppage
[idx
].hpage
);
2750 /* doing TCM_SETCURSEL seems to be needed even in case of PSH_WIZARD,
2751 * as some programs call TCM_GETCURSEL to get the current selection
2752 * from which to switch to the next page */
2753 SendMessageW(hwndTabCtrl
, TCM_SETCURSEL
, psInfo
->active_page
, 0);
2755 if (!HIWORD(psInfo
->ppshheader
.pszCaption
) &&
2756 psInfo
->ppshheader
.hInstance
)
2760 if (LoadStringW(psInfo
->ppshheader
.hInstance
,
2761 (UINT
)psInfo
->ppshheader
.pszCaption
, szText
, 255))
2762 PROPSHEET_SetTitleW(hwnd
, psInfo
->ppshheader
.dwFlags
, szText
);
2766 PROPSHEET_SetTitleW(hwnd
, psInfo
->ppshheader
.dwFlags
,
2767 psInfo
->ppshheader
.pszCaption
);
2774 PROPSHEET_CleanUp(hwnd
);
2778 PROPSHEET_Cancel(hwnd
, 1);
2782 return PROPSHEET_DoCommand(hwnd
, LOWORD(wParam
));
2786 NMHDR
* pnmh
= (LPNMHDR
) lParam
;
2788 if (pnmh
->code
== TCN_SELCHANGE
)
2790 int index
= SendMessageW(pnmh
->hwndFrom
, TCM_GETCURSEL
, 0, 0);
2791 PROPSHEET_SetCurSel(hwnd
, index
, 1, 0);
2794 if(pnmh
->code
== TCN_SELCHANGING
)
2796 BOOL bRet
= PROPSHEET_CanSetCurSel(hwnd
);
2797 SetWindowLongW(hwnd
, DWL_MSGRESULT
, !bRet
);
2804 case PSM_GETCURRENTPAGEHWND
:
2806 PropSheetInfo
* psInfo
= (PropSheetInfo
*) GetPropW(hwnd
,
2810 if (psInfo
->activeValid
&& psInfo
->active_page
!= -1)
2811 hwndPage
= psInfo
->proppage
[psInfo
->active_page
].hwndPage
;
2813 SetWindowLongW(hwnd
, DWL_MSGRESULT
, (LONG
)hwndPage
);
2819 PROPSHEET_Changed(hwnd
, (HWND
)wParam
);
2823 PROPSHEET_UnChanged(hwnd
, (HWND
)wParam
);
2826 case PSM_GETTABCONTROL
:
2828 HWND hwndTabCtrl
= GetDlgItem(hwnd
, IDC_TABCONTROL
);
2830 SetWindowLongW(hwnd
, DWL_MSGRESULT
, (LONG
)hwndTabCtrl
);
2839 msgResult
= PROPSHEET_CanSetCurSel(hwnd
);
2840 if(msgResult
!= FALSE
)
2842 msgResult
= PROPSHEET_SetCurSel(hwnd
,
2845 (HPROPSHEETPAGE
)lParam
);
2848 SetWindowLongW(hwnd
, DWL_MSGRESULT
, msgResult
);
2853 case PSM_CANCELTOCLOSE
:
2855 WCHAR buf
[MAX_BUTTONTEXT_LENGTH
];
2856 HWND hwndOK
= GetDlgItem(hwnd
, IDOK
);
2857 HWND hwndCancel
= GetDlgItem(hwnd
, IDCANCEL
);
2859 EnableWindow(hwndCancel
, FALSE
);
2860 if (LoadStringW(COMCTL32_hModule
, IDS_CLOSE
, buf
, sizeof(buf
)))
2861 SetWindowTextW(hwndOK
, buf
);
2866 case PSM_RESTARTWINDOWS
:
2868 PropSheetInfo
* psInfo
= (PropSheetInfo
*) GetPropW(hwnd
,
2871 psInfo
->restartWindows
= TRUE
;
2875 case PSM_REBOOTSYSTEM
:
2877 PropSheetInfo
* psInfo
= (PropSheetInfo
*) GetPropW(hwnd
,
2880 psInfo
->rebootSystem
= TRUE
;
2885 PROPSHEET_SetTitleA(hwnd
, (DWORD
) wParam
, (LPCSTR
) lParam
);
2889 PROPSHEET_SetTitleW(hwnd
, (DWORD
) wParam
, (LPCWSTR
) lParam
);
2894 BOOL msgResult
= PROPSHEET_Apply(hwnd
, 0);
2896 SetWindowLongW(hwnd
, DWL_MSGRESULT
, msgResult
);
2901 case PSM_QUERYSIBLINGS
:
2903 LRESULT msgResult
= PROPSHEET_QuerySiblings(hwnd
, wParam
, lParam
);
2905 SetWindowLongW(hwnd
, DWL_MSGRESULT
, msgResult
);
2913 * Note: MSVC++ 6.0 documentation says that PSM_ADDPAGE does not have
2914 * a return value. This is not true. PSM_ADDPAGE returns TRUE
2915 * on success or FALSE otherwise, as specified on MSDN Online.
2916 * Also see the MFC code for
2917 * CPropertySheet::AddPage(CPropertyPage* pPage).
2920 BOOL msgResult
= PROPSHEET_AddPage(hwnd
, (HPROPSHEETPAGE
)lParam
);
2922 SetWindowLongW(hwnd
, DWL_MSGRESULT
, msgResult
);
2927 case PSM_REMOVEPAGE
:
2928 PROPSHEET_RemovePage(hwnd
, (int)wParam
, (HPROPSHEETPAGE
)lParam
);
2931 case PSM_ISDIALOGMESSAGE
:
2933 BOOL msgResult
= PROPSHEET_IsDialogMessage(hwnd
, (LPMSG
)lParam
);
2934 SetWindowLongA(hwnd
, DWL_MSGRESULT
, msgResult
);
2938 case PSM_PRESSBUTTON
:
2939 PROPSHEET_PressButton(hwnd
, (int)wParam
);
2942 case PSM_SETFINISHTEXTA
:
2943 PROPSHEET_SetFinishTextA(hwnd
, (LPCSTR
) lParam
);
2946 case PSM_SETWIZBUTTONS
:
2947 PROPSHEET_SetWizButtons(hwnd
, (DWORD
)lParam
);
2950 case PSM_SETCURSELID
:
2951 PROPSHEET_SetCurSelId(hwnd
, (int)lParam
);
2954 case PSM_SETFINISHTEXTW
:
2955 PROPSHEET_SetFinishTextW(hwnd
, (LPCWSTR
) lParam
);