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 /******************************************************************************
62 } MyDLGITEMTEMPLATEEX
;
65 typedef struct tagPropPageInfo
67 HPROPSHEETPAGE hpage
; /* to keep track of pages not passed to PropertySheet */
76 typedef struct tagPropSheetInfo
79 PROPSHEETHEADERW ppshheader
;
80 LPWSTR strPropertiesFor
;
90 PropPageInfo
* proppage
;
95 HIMAGELIST hImageList
;
104 /******************************************************************************
105 * Defines and global variables
108 const WCHAR PropSheetInfoStr
[] =
109 {'P','r','o','p','e','r','t','y','S','h','e','e','t','I','n','f','o',0 };
111 #define MAX_CAPTION_LENGTH 255
112 #define MAX_TABTEXT_LENGTH 255
113 #define MAX_BUTTONTEXT_LENGTH 64
115 #define INTRNL_ANY_WIZARD (PSH_WIZARD | PSH_WIZARD97_OLD | PSH_WIZARD97_NEW | PSH_WIZARD_LITE)
117 /******************************************************************************
120 static BOOL
PROPSHEET_CreateDialog(PropSheetInfo
* psInfo
);
121 static BOOL
PROPSHEET_SizeMismatch(HWND hwndDlg
, PropSheetInfo
* psInfo
);
122 static BOOL
PROPSHEET_AdjustSize(HWND hwndDlg
, PropSheetInfo
* psInfo
);
123 static BOOL
PROPSHEET_AdjustButtons(HWND hwndParent
, PropSheetInfo
* psInfo
);
124 static BOOL
PROPSHEET_CollectSheetInfoA(LPCPROPSHEETHEADERA lppsh
,
125 PropSheetInfo
* psInfo
);
126 static BOOL
PROPSHEET_CollectSheetInfoW(LPCPROPSHEETHEADERW lppsh
,
127 PropSheetInfo
* psInfo
);
128 static BOOL
PROPSHEET_CollectPageInfo(LPCPROPSHEETPAGEW lppsp
,
129 PropSheetInfo
* psInfo
,
131 static BOOL
PROPSHEET_CreateTabControl(HWND hwndParent
,
132 PropSheetInfo
* psInfo
);
133 static BOOL
PROPSHEET_CreatePage(HWND hwndParent
, int index
,
134 const PropSheetInfo
* psInfo
,
135 LPCPROPSHEETPAGEW ppshpage
);
136 static BOOL
PROPSHEET_ShowPage(HWND hwndDlg
, int index
, PropSheetInfo
* psInfo
);
137 static PADDING_INFO
PROPSHEET_GetPaddingInfo(HWND hwndDlg
);
138 static BOOL
PROPSHEET_Back(HWND hwndDlg
);
139 static BOOL
PROPSHEET_Next(HWND hwndDlg
);
140 static BOOL
PROPSHEET_Finish(HWND hwndDlg
);
141 static BOOL
PROPSHEET_Apply(HWND hwndDlg
, LPARAM lParam
);
142 static void PROPSHEET_Cancel(HWND hwndDlg
, LPARAM lParam
);
143 static void PROPSHEET_Help(HWND hwndDlg
);
144 static void PROPSHEET_Changed(HWND hwndDlg
, HWND hwndDirtyPage
);
145 static void PROPSHEET_UnChanged(HWND hwndDlg
, HWND hwndCleanPage
);
146 static void PROPSHEET_PressButton(HWND hwndDlg
, int buttonID
);
147 static void PROPSHEET_SetFinishTextA(HWND hwndDlg
, LPCSTR lpszText
);
148 static void PROPSHEET_SetFinishTextW(HWND hwndDlg
, LPCWSTR lpszText
);
149 static void PROPSHEET_SetTitleA(HWND hwndDlg
, DWORD dwStyle
, LPCSTR lpszText
);
150 static void PROPSHEET_SetTitleW(HWND hwndDlg
, DWORD dwStyle
, LPCWSTR lpszText
);
151 static BOOL
PROPSHEET_CanSetCurSel(HWND hwndDlg
);
152 static BOOL
PROPSHEET_SetCurSel(HWND hwndDlg
,
155 HPROPSHEETPAGE hpage
);
156 static void PROPSHEET_SetCurSelId(HWND hwndDlg
, int id
);
157 static LRESULT
PROPSHEET_QuerySiblings(HWND hwndDlg
,
158 WPARAM wParam
, LPARAM lParam
);
159 static BOOL
PROPSHEET_AddPage(HWND hwndDlg
,
160 HPROPSHEETPAGE hpage
);
162 static BOOL
PROPSHEET_RemovePage(HWND hwndDlg
,
164 HPROPSHEETPAGE hpage
);
165 static void PROPSHEET_CleanUp();
166 static int PROPSHEET_GetPageIndex(HPROPSHEETPAGE hpage
, PropSheetInfo
* psInfo
);
167 static void PROPSHEET_SetWizButtons(HWND hwndDlg
, DWORD dwFlags
);
168 static PADDING_INFO
PROPSHEET_GetPaddingInfoWizard(HWND hwndDlg
, const PropSheetInfo
* psInfo
);
169 static BOOL
PROPSHEET_IsDialogMessage(HWND hwnd
, LPMSG lpMsg
);
170 static BOOL
PROPSHEET_DoCommand(HWND hwnd
, WORD wID
);
173 PROPSHEET_DialogProc(HWND hwnd
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
);
175 WINE_DEFAULT_DEBUG_CHANNEL(propsheet
);
177 #define add_flag(a) if (dwFlags & a) {strcat(string, #a );strcat(string," ");}
178 /******************************************************************************
179 * PROPSHEET_UnImplementedFlags
181 * Document use of flags we don't implement yet.
183 static VOID
PROPSHEET_UnImplementedFlags(DWORD dwFlags
)
190 * unhandled header flags:
191 * PSH_DEFAULT 0x00000000
192 * PSH_WIZARDHASFINISH 0x00000010
193 * PSH_RTLREADING 0x00000800
194 * PSH_WIZARDCONTEXTHELP 0x00001000
195 * PSH_WIZARD97 0x00002000 (pre IE 5)
196 * PSH_WATERMARK 0x00008000
197 * PSH_USEHBMWATERMARK 0x00010000
198 * PSH_USEHPLWATERMARK 0x00020000
199 * PSH_STRETCHWATERMARK 0x00040000
200 * PSH_HEADER 0x00080000
201 * PSH_USEHBMHEADER 0x00100000
202 * PSH_USEPAGELANG 0x00200000
203 * PSH_WIZARD_LITE 0x00400000 also not in .h
204 * PSH_WIZARD97 0x01000000 (IE 5 and above)
205 * PSH_NOCONTEXTHELP 0x02000000 also not in .h
208 add_flag(PSH_WIZARDHASFINISH
);
209 add_flag(PSH_RTLREADING
);
210 add_flag(PSH_WIZARDCONTEXTHELP
);
211 add_flag(PSH_WIZARD97_OLD
);
212 add_flag(PSH_WATERMARK
);
213 add_flag(PSH_USEHBMWATERMARK
);
214 add_flag(PSH_USEHPLWATERMARK
);
215 add_flag(PSH_STRETCHWATERMARK
);
216 add_flag(PSH_HEADER
);
217 add_flag(PSH_USEHBMHEADER
);
218 add_flag(PSH_USEPAGELANG
);
219 add_flag(PSH_WIZARD_LITE
);
220 add_flag(PSH_WIZARD97_NEW
);
221 add_flag(PSH_NOCONTEXTHELP
);
222 if (string
[0] != '\0')
223 FIXME("%s\n", string
);
227 /******************************************************************************
228 * PROPSHEET_GetPageRect
230 * Retrieve rect from tab control and map into the dialog for SetWindowPos
232 static void PROPSHEET_GetPageRect(const PropSheetInfo
* psInfo
, HWND hwndDlg
, RECT
*rc
)
234 HWND hwndTabCtrl
= GetDlgItem(hwndDlg
, IDC_TABCONTROL
);
236 GetClientRect(hwndTabCtrl
, rc
);
237 SendMessageW(hwndTabCtrl
, TCM_ADJUSTRECT
, FALSE
, (LPARAM
)rc
);
238 MapWindowPoints(hwndTabCtrl
, hwndDlg
, (LPPOINT
)rc
, 2);
241 /******************************************************************************
242 * PROPSHEET_FindPageByResId
244 * Find page index corresponding to page resource id.
246 INT
PROPSHEET_FindPageByResId(PropSheetInfo
* psInfo
, LRESULT resId
)
250 for (i
= 0; i
< psInfo
->nPages
; i
++)
252 LPCPROPSHEETPAGEA lppsp
= (LPCPROPSHEETPAGEA
)psInfo
->proppage
[i
].hpage
;
254 /* Fixme: if resource ID is a string shall we use strcmp ??? */
255 if (lppsp
->u
.pszTemplate
== (LPVOID
)resId
)
262 /******************************************************************************
265 * Convert ASCII to Unicode since all data is saved as Unicode.
267 static void PROPSHEET_AtoW(LPCWSTR
*tostr
, LPCSTR frstr
)
271 TRACE("<%s>\n", frstr
);
272 len
= MultiByteToWideChar(CP_ACP
, 0, frstr
, -1, 0, 0);
273 *tostr
= (LPWSTR
)HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
274 MultiByteToWideChar(CP_ACP
, 0, frstr
, -1, (LPWSTR
)*tostr
, len
);
277 /******************************************************************************
278 * PROPSHEET_CollectSheetInfoA
280 * Collect relevant data.
282 static BOOL
PROPSHEET_CollectSheetInfoA(LPCPROPSHEETHEADERA lppsh
,
283 PropSheetInfo
* psInfo
)
285 DWORD dwSize
= min(lppsh
->dwSize
,sizeof(PROPSHEETHEADERA
));
286 DWORD dwFlags
= lppsh
->dwFlags
;
288 psInfo
->hasHelp
= dwFlags
& PSH_HASHELP
;
289 psInfo
->hasApply
= !(dwFlags
& PSH_NOAPPLYNOW
);
290 psInfo
->useCallback
= dwFlags
& PSH_USECALLBACK
;
291 psInfo
->isModeless
= dwFlags
& PSH_MODELESS
;
293 memcpy(&psInfo
->ppshheader
,lppsh
,dwSize
);
294 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",
295 lppsh
->dwSize
, lppsh
->dwFlags
, lppsh
->hwndParent
, lppsh
->hInstance
,
296 debugstr_a(lppsh
->pszCaption
), lppsh
->nPages
, lppsh
->pfnCallback
);
298 PROPSHEET_UnImplementedFlags(lppsh
->dwFlags
);
300 if (HIWORD(lppsh
->pszCaption
))
302 int len
= strlen(lppsh
->pszCaption
);
303 psInfo
->ppshheader
.pszCaption
= HeapAlloc( GetProcessHeap(), 0, (len
+1)*sizeof (WCHAR
) );
304 MultiByteToWideChar(CP_ACP
, 0, lppsh
->pszCaption
, -1, (LPWSTR
) psInfo
->ppshheader
.pszCaption
, len
+1);
305 /* strcpy( (char *)psInfo->ppshheader.pszCaption, lppsh->pszCaption ); */
307 psInfo
->nPages
= lppsh
->nPages
;
309 if (dwFlags
& PSH_USEPSTARTPAGE
)
311 TRACE("PSH_USEPSTARTPAGE is on");
312 psInfo
->active_page
= 0;
315 psInfo
->active_page
= lppsh
->u2
.nStartPage
;
317 if (psInfo
->active_page
< 0 || psInfo
->active_page
>= psInfo
->nPages
)
318 psInfo
->active_page
= 0;
320 psInfo
->restartWindows
= FALSE
;
321 psInfo
->rebootSystem
= FALSE
;
322 psInfo
->hImageList
= 0;
323 psInfo
->activeValid
= FALSE
;
328 /******************************************************************************
329 * PROPSHEET_CollectSheetInfoW
331 * Collect relevant data.
333 static BOOL
PROPSHEET_CollectSheetInfoW(LPCPROPSHEETHEADERW lppsh
,
334 PropSheetInfo
* psInfo
)
336 DWORD dwSize
= min(lppsh
->dwSize
,sizeof(PROPSHEETHEADERW
));
337 DWORD dwFlags
= lppsh
->dwFlags
;
339 psInfo
->hasHelp
= dwFlags
& PSH_HASHELP
;
340 psInfo
->hasApply
= !(dwFlags
& PSH_NOAPPLYNOW
);
341 psInfo
->useCallback
= dwFlags
& PSH_USECALLBACK
;
342 psInfo
->isModeless
= dwFlags
& PSH_MODELESS
;
344 memcpy(&psInfo
->ppshheader
,lppsh
,dwSize
);
345 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",
346 lppsh
->dwSize
, lppsh
->dwFlags
, lppsh
->hwndParent
, lppsh
->hInstance
, debugstr_w(lppsh
->pszCaption
), lppsh
->nPages
, lppsh
->pfnCallback
);
348 PROPSHEET_UnImplementedFlags(lppsh
->dwFlags
);
350 if (HIWORD(lppsh
->pszCaption
))
352 int len
= strlenW(lppsh
->pszCaption
);
353 psInfo
->ppshheader
.pszCaption
= HeapAlloc( GetProcessHeap(), 0, (len
+1)*sizeof(WCHAR
) );
354 strcpyW( (WCHAR
*)psInfo
->ppshheader
.pszCaption
, lppsh
->pszCaption
);
356 psInfo
->nPages
= lppsh
->nPages
;
358 if (dwFlags
& PSH_USEPSTARTPAGE
)
360 TRACE("PSH_USEPSTARTPAGE is on");
361 psInfo
->active_page
= 0;
364 psInfo
->active_page
= lppsh
->u2
.nStartPage
;
366 if (psInfo
->active_page
< 0 || psInfo
->active_page
>= psInfo
->nPages
)
367 psInfo
->active_page
= 0;
369 psInfo
->restartWindows
= FALSE
;
370 psInfo
->rebootSystem
= FALSE
;
371 psInfo
->hImageList
= 0;
372 psInfo
->activeValid
= FALSE
;
377 /******************************************************************************
378 * PROPSHEET_CollectPageInfo
380 * Collect property sheet data.
381 * With code taken from DIALOG_ParseTemplate32.
383 BOOL
PROPSHEET_CollectPageInfo(LPCPROPSHEETPAGEW lppsp
,
384 PropSheetInfo
* psInfo
,
387 DLGTEMPLATE
* pTemplate
;
393 psInfo
->proppage
[index
].hpage
= (HPROPSHEETPAGE
)lppsp
;
394 psInfo
->proppage
[index
].hwndPage
= 0;
395 psInfo
->proppage
[index
].isDirty
= FALSE
;
398 * Process property page flags.
400 dwFlags
= lppsp
->dwFlags
;
401 psInfo
->proppage
[index
].useCallback
= (dwFlags
& PSP_USECALLBACK
) && (lppsp
->pfnCallback
);
402 psInfo
->proppage
[index
].hasHelp
= dwFlags
& PSP_HASHELP
;
403 psInfo
->proppage
[index
].hasIcon
= dwFlags
& (PSP_USEHICON
| PSP_USEICONID
);
405 /* as soon as we have a page with the help flag, set the sheet flag on */
406 if (psInfo
->proppage
[index
].hasHelp
)
407 psInfo
->hasHelp
= TRUE
;
410 * Process page template.
412 if (dwFlags
& PSP_DLGINDIRECT
)
413 pTemplate
= (DLGTEMPLATE
*)lppsp
->u
.pResource
;
416 HRSRC hResource
= FindResourceW(lppsp
->hInstance
,
417 lppsp
->u
.pszTemplate
,
419 HGLOBAL hTemplate
= LoadResource(lppsp
->hInstance
,
421 pTemplate
= (LPDLGTEMPLATEW
)LockResource(hTemplate
);
425 * Extract the size of the page and the caption.
430 p
= (const WORD
*)pTemplate
;
432 if (((MyDLGTEMPLATEEX
*)pTemplate
)->signature
== 0xFFFF)
434 /* DLGTEMPLATEEX (not defined in any std. header file) */
438 p
+= 2; /* help ID */
439 p
+= 2; /* ext style */
447 p
+= 2; /* ext style */
453 width
= (WORD
)*p
; p
++;
454 height
= (WORD
)*p
; p
++;
456 /* remember the largest width and height */
457 if (width
> psInfo
->width
)
458 psInfo
->width
= width
;
460 if (height
> psInfo
->height
)
461 psInfo
->height
= height
;
473 p
+= lstrlenW( (LPCWSTR
)p
) + 1;
487 p
+= lstrlenW( (LPCWSTR
)p
) + 1;
491 /* Extract the caption */
492 psInfo
->proppage
[index
].pszText
= (LPCWSTR
)p
;
493 TRACE("Tab %d %s\n",index
,debugstr_w((LPCWSTR
)p
));
494 p
+= lstrlenW((LPCWSTR
)p
) + 1;
496 if (dwFlags
& PSP_USETITLE
)
500 static WCHAR pszNull
[] = { '(','n','u','l','l',')',0 };
503 if ( !HIWORD( lppsp
->pszTitle
) )
505 if (!LoadStringW( lppsp
->hInstance
, (UINT
)lppsp
->pszTitle
,szTitle
,sizeof szTitle
))
508 FIXME("Could not load resource #%04x?\n",LOWORD(lppsp
->pszTitle
));
514 pTitle
= lppsp
->pszTitle
;
516 len
= strlenW(pTitle
);
517 psInfo
->proppage
[index
].pszText
= COMCTL32_Alloc( (len
+1)*sizeof (WCHAR
) );
518 strcpyW( (LPWSTR
)psInfo
->proppage
[index
].pszText
,pTitle
);
522 * Build the image list for icons
524 if ((dwFlags
& PSP_USEHICON
) || (dwFlags
& PSP_USEICONID
))
527 int icon_cx
= GetSystemMetrics(SM_CXSMICON
);
528 int icon_cy
= GetSystemMetrics(SM_CYSMICON
);
530 if (dwFlags
& PSP_USEICONID
)
531 hIcon
= LoadImageW(lppsp
->hInstance
, lppsp
->u2
.pszIcon
, IMAGE_ICON
,
532 icon_cx
, icon_cy
, LR_DEFAULTCOLOR
);
534 hIcon
= lppsp
->u2
.hIcon
;
538 if (psInfo
->hImageList
== 0 )
539 psInfo
->hImageList
= ImageList_Create(icon_cx
, icon_cy
, ILC_COLOR
, 1, 1);
541 ImageList_AddIcon(psInfo
->hImageList
, hIcon
);
549 /******************************************************************************
550 * PROPSHEET_CreateDialog
552 * Creates the actual property sheet.
554 BOOL
PROPSHEET_CreateDialog(PropSheetInfo
* psInfo
)
561 WORD resID
= IDD_PROPSHEET
;
564 if (psInfo
->ppshheader
.dwFlags
& INTRNL_ANY_WIZARD
)
567 if(!(hRes
= FindResourceW(COMCTL32_hModule
,
568 MAKEINTRESOURCEW(resID
),
572 if(!(template = (LPVOID
)LoadResource(COMCTL32_hModule
, hRes
)))
576 * Make a copy of the dialog template.
578 resSize
= SizeofResource(COMCTL32_hModule
, hRes
);
580 temp
= COMCTL32_Alloc(resSize
);
585 memcpy(temp
, template, resSize
);
587 if (psInfo
->useCallback
)
588 (*(psInfo
->ppshheader
.pfnCallback
))(0, PSCB_PRECREATE
, (LPARAM
)temp
);
590 if (!(psInfo
->ppshheader
.dwFlags
& PSH_MODELESS
))
591 ret
= DialogBoxIndirectParamW(psInfo
->ppshheader
.hInstance
,
592 (LPDLGTEMPLATEW
) temp
,
593 psInfo
->ppshheader
.hwndParent
,
594 PROPSHEET_DialogProc
,
597 ret
= CreateDialogIndirectParamW(psInfo
->ppshheader
.hInstance
,
598 (LPDLGTEMPLATEW
) temp
,
599 psInfo
->ppshheader
.hwndParent
,
600 PROPSHEET_DialogProc
,
601 (LPARAM
)psInfo
) ? TRUE
: FALSE
;
608 /******************************************************************************
609 * PROPSHEET_SizeMismatch
611 * Verify that the tab control and the "largest" property sheet page dlg. template
614 static BOOL
PROPSHEET_SizeMismatch(HWND hwndDlg
, PropSheetInfo
* psInfo
)
616 HWND hwndTabCtrl
= GetDlgItem(hwndDlg
, IDC_TABCONTROL
);
617 RECT rcOrigTab
, rcPage
;
622 GetClientRect(hwndTabCtrl
, &rcOrigTab
);
623 TRACE("orig tab %d %d %d %d\n", rcOrigTab
.left
, rcOrigTab
.top
,
624 rcOrigTab
.right
, rcOrigTab
.bottom
);
629 rcPage
.left
= psInfo
->x
;
630 rcPage
.top
= psInfo
->y
;
631 rcPage
.right
= psInfo
->width
;
632 rcPage
.bottom
= psInfo
->height
;
634 MapDialogRect(hwndDlg
, &rcPage
);
635 TRACE("biggest page %d %d %d %d\n", rcPage
.left
, rcPage
.top
,
636 rcPage
.right
, rcPage
.bottom
);
638 if ( (rcPage
.right
- rcPage
.left
) != (rcOrigTab
.right
- rcOrigTab
.left
) )
640 if ( (rcPage
.bottom
- rcPage
.top
) != (rcOrigTab
.bottom
- rcOrigTab
.top
) )
646 /******************************************************************************
647 * PROPSHEET_IsTooSmallWizard
649 * Verify that the default property sheet is big enough.
651 static BOOL
PROPSHEET_IsTooSmallWizard(HWND hwndDlg
, PropSheetInfo
* psInfo
)
653 RECT rcSheetRect
, rcPage
, rcLine
, rcSheetClient
;
654 HWND hwndLine
= GetDlgItem(hwndDlg
, IDC_SUNKEN_LINE
);
655 PADDING_INFO padding
= PROPSHEET_GetPaddingInfoWizard(hwndDlg
, psInfo
);
657 GetClientRect(hwndDlg
, &rcSheetClient
);
658 GetWindowRect(hwndDlg
, &rcSheetRect
);
659 GetWindowRect(hwndLine
, &rcLine
);
661 /* Remove the space below the sunken line */
662 rcSheetClient
.bottom
-= (rcSheetRect
.bottom
- rcLine
.top
);
664 /* Remove the buffer zone all around the edge */
665 rcSheetClient
.bottom
-= (padding
.y
* 2);
666 rcSheetClient
.right
-= (padding
.x
* 2);
671 rcPage
.left
= psInfo
->x
;
672 rcPage
.top
= psInfo
->y
;
673 rcPage
.right
= psInfo
->width
;
674 rcPage
.bottom
= psInfo
->height
;
676 MapDialogRect(hwndDlg
, &rcPage
);
677 TRACE("biggest page %d %d %d %d\n", rcPage
.left
, rcPage
.top
,
678 rcPage
.right
, rcPage
.bottom
);
680 if (rcPage
.right
> rcSheetClient
.right
)
683 if (rcPage
.bottom
> rcSheetClient
.bottom
)
689 /******************************************************************************
690 * PROPSHEET_AdjustSize
692 * Resizes the property sheet and the tab control to fit the largest page.
694 static BOOL
PROPSHEET_AdjustSize(HWND hwndDlg
, PropSheetInfo
* psInfo
)
696 HWND hwndTabCtrl
= GetDlgItem(hwndDlg
, IDC_TABCONTROL
);
697 HWND hwndButton
= GetDlgItem(hwndDlg
, IDOK
);
699 int tabOffsetX
, tabOffsetY
, buttonHeight
;
700 PADDING_INFO padding
= PROPSHEET_GetPaddingInfo(hwndDlg
);
703 /* Get the height of buttons */
704 GetClientRect(hwndButton
, &rc
);
705 buttonHeight
= rc
.bottom
;
712 rc
.right
= psInfo
->width
;
713 rc
.bottom
= psInfo
->height
;
715 MapDialogRect(hwndDlg
, &rc
);
717 /* retrieve the dialog units */
718 units
.left
= units
.right
= 4;
719 units
.top
= units
.bottom
= 8;
720 MapDialogRect(hwndDlg
, &units
);
723 * Resize the tab control.
725 GetClientRect(hwndTabCtrl
,&tabRect
);
727 SendMessageW(hwndTabCtrl
, TCM_ADJUSTRECT
, FALSE
, (LPARAM
)&tabRect
);
729 if ((rc
.bottom
- rc
.top
) < (tabRect
.bottom
- tabRect
.top
))
731 rc
.bottom
= rc
.top
+ tabRect
.bottom
- tabRect
.top
;
732 psInfo
->height
= MulDiv((rc
.bottom
- rc
.top
),8,units
.top
);
735 if ((rc
.right
- rc
.left
) < (tabRect
.right
- tabRect
.left
))
737 rc
.right
= rc
.left
+ tabRect
.right
- tabRect
.left
;
738 psInfo
->width
= MulDiv((rc
.right
- rc
.left
),4,units
.left
);
741 SendMessageW(hwndTabCtrl
, TCM_ADJUSTRECT
, TRUE
, (LPARAM
)&rc
);
743 tabOffsetX
= -(rc
.left
);
744 tabOffsetY
= -(rc
.top
);
748 TRACE("setting tab %08lx, rc (0,0)-(%d,%d)\n",
749 (DWORD
)hwndTabCtrl
, rc
.right
, rc
.bottom
);
750 SetWindowPos(hwndTabCtrl
, 0, 0, 0, rc
.right
, rc
.bottom
,
751 SWP_NOMOVE
| SWP_NOZORDER
| SWP_NOACTIVATE
);
753 GetClientRect(hwndTabCtrl
, &rc
);
755 TRACE("tab client rc %d %d %d %d\n",
756 rc
.left
, rc
.top
, rc
.right
, rc
.bottom
);
758 rc
.right
+= ((padding
.x
* 2) + tabOffsetX
);
759 rc
.bottom
+= (buttonHeight
+ (3 * padding
.y
) + tabOffsetY
);
762 * Resize the property sheet.
764 TRACE("setting dialog %08lx, rc (0,0)-(%d,%d)\n",
765 (DWORD
)hwndDlg
, rc
.right
, rc
.bottom
);
766 SetWindowPos(hwndDlg
, 0, 0, 0, rc
.right
, rc
.bottom
,
767 SWP_NOMOVE
| SWP_NOZORDER
| SWP_NOACTIVATE
);
771 /******************************************************************************
772 * PROPSHEET_AdjustSizeWizard
774 * Resizes the property sheet to fit the largest page.
776 static BOOL
PROPSHEET_AdjustSizeWizard(HWND hwndDlg
, PropSheetInfo
* psInfo
)
778 HWND hwndButton
= GetDlgItem(hwndDlg
, IDCANCEL
);
779 HWND hwndLine
= GetDlgItem(hwndDlg
, IDC_SUNKEN_LINE
);
780 HWND hwndTabCtrl
= GetDlgItem(hwndDlg
, IDC_TABCONTROL
);
782 int buttonHeight
, lineHeight
;
783 PADDING_INFO padding
= PROPSHEET_GetPaddingInfoWizard(hwndDlg
, psInfo
);
786 /* Get the height of buttons */
787 GetClientRect(hwndButton
, &rc
);
788 buttonHeight
= rc
.bottom
;
790 GetClientRect(hwndLine
, &rc
);
791 lineHeight
= rc
.bottom
;
793 /* retrieve the dialog units */
794 units
.left
= units
.right
= 4;
795 units
.top
= units
.bottom
= 8;
796 MapDialogRect(hwndDlg
, &units
);
803 rc
.right
= psInfo
->width
;
804 rc
.bottom
= psInfo
->height
;
806 MapDialogRect(hwndDlg
, &rc
);
808 GetClientRect(hwndTabCtrl
,&tabRect
);
810 if ((rc
.bottom
- rc
.top
) < (tabRect
.bottom
- tabRect
.top
))
812 rc
.bottom
= rc
.top
+ tabRect
.bottom
- tabRect
.top
;
813 psInfo
->height
= MulDiv((rc
.bottom
- rc
.top
), 8, units
.top
);
816 if ((rc
.right
- rc
.left
) < (tabRect
.right
- tabRect
.left
))
818 rc
.right
= rc
.left
+ tabRect
.right
- tabRect
.left
;
819 psInfo
->width
= MulDiv((rc
.right
- rc
.left
), 4, units
.left
);
822 TRACE("Biggest page %d %d %d %d\n", rc
.left
, rc
.top
, rc
.right
, rc
.bottom
);
823 TRACE(" constants padx=%d, pady=%d, butH=%d, lH=%d\n",
824 padding
.x
, padding
.y
, buttonHeight
, lineHeight
);
827 rc
.right
+= (padding
.x
* 2);
828 rc
.bottom
+= (buttonHeight
+ (5 * padding
.y
) + lineHeight
);
831 * Resize the property sheet.
833 TRACE("setting dialog %08lx, rc (0,0)-(%d,%d)\n",
834 (DWORD
)hwndDlg
, rc
.right
, rc
.bottom
);
835 SetWindowPos(hwndDlg
, 0, 0, 0, rc
.right
, rc
.bottom
,
836 SWP_NOMOVE
| SWP_NOZORDER
| SWP_NOACTIVATE
);
840 /******************************************************************************
841 * PROPSHEET_AdjustButtons
843 * Adjusts the buttons' positions.
845 static BOOL
PROPSHEET_AdjustButtons(HWND hwndParent
, PropSheetInfo
* psInfo
)
847 HWND hwndButton
= GetDlgItem(hwndParent
, IDOK
);
851 int buttonWidth
, buttonHeight
;
852 PADDING_INFO padding
= PROPSHEET_GetPaddingInfo(hwndParent
);
854 if (psInfo
->hasApply
)
861 * Obtain the size of the buttons.
863 GetClientRect(hwndButton
, &rcSheet
);
864 buttonWidth
= rcSheet
.right
;
865 buttonHeight
= rcSheet
.bottom
;
868 * Get the size of the property sheet.
870 GetClientRect(hwndParent
, &rcSheet
);
873 * All buttons will be at this y coordinate.
875 y
= rcSheet
.bottom
- (padding
.y
+ buttonHeight
);
878 * Position OK button.
880 hwndButton
= GetDlgItem(hwndParent
, IDOK
);
882 x
= rcSheet
.right
- ((padding
.x
+ buttonWidth
) * num_buttons
);
884 SetWindowPos(hwndButton
, 0, x
, y
, 0, 0,
885 SWP_NOSIZE
| SWP_NOZORDER
| SWP_NOACTIVATE
);
888 * Position Cancel button.
890 hwndButton
= GetDlgItem(hwndParent
, IDCANCEL
);
892 x
= rcSheet
.right
- ((padding
.x
+ buttonWidth
) * (num_buttons
- 1));
894 SetWindowPos(hwndButton
, 0, x
, y
, 0, 0,
895 SWP_NOSIZE
| SWP_NOZORDER
| SWP_NOACTIVATE
);
898 * Position Apply button.
900 hwndButton
= GetDlgItem(hwndParent
, IDC_APPLY_BUTTON
);
902 if (psInfo
->hasApply
)
905 x
= rcSheet
.right
- ((padding
.x
+ buttonWidth
) * 2);
907 x
= rcSheet
.right
- (padding
.x
+ buttonWidth
);
909 SetWindowPos(hwndButton
, 0, x
, y
, 0, 0,
910 SWP_NOSIZE
| SWP_NOZORDER
| SWP_NOACTIVATE
);
912 EnableWindow(hwndButton
, FALSE
);
915 ShowWindow(hwndButton
, SW_HIDE
);
918 * Position Help button.
920 hwndButton
= GetDlgItem(hwndParent
, IDHELP
);
924 x
= rcSheet
.right
- (padding
.x
+ buttonWidth
);
926 SetWindowPos(hwndButton
, 0, x
, y
, 0, 0,
927 SWP_NOSIZE
| SWP_NOZORDER
| SWP_NOACTIVATE
);
930 ShowWindow(hwndButton
, SW_HIDE
);
935 /******************************************************************************
936 * PROPSHEET_AdjustButtonsWizard
938 * Adjusts the buttons' positions.
940 static BOOL
PROPSHEET_AdjustButtonsWizard(HWND hwndParent
,
941 PropSheetInfo
* psInfo
)
943 HWND hwndButton
= GetDlgItem(hwndParent
, IDCANCEL
);
944 HWND hwndLine
= GetDlgItem(hwndParent
, IDC_SUNKEN_LINE
);
948 int buttonWidth
, buttonHeight
, lineHeight
, lineWidth
;
949 PADDING_INFO padding
= PROPSHEET_GetPaddingInfoWizard(hwndParent
, psInfo
);
955 * Obtain the size of the buttons.
957 GetClientRect(hwndButton
, &rcSheet
);
958 buttonWidth
= rcSheet
.right
;
959 buttonHeight
= rcSheet
.bottom
;
961 GetClientRect(hwndLine
, &rcSheet
);
962 lineHeight
= rcSheet
.bottom
;
965 * Get the size of the property sheet.
967 GetClientRect(hwndParent
, &rcSheet
);
970 * All buttons will be at this y coordinate.
972 y
= rcSheet
.bottom
- (padding
.y
+ buttonHeight
);
975 * Position the Next and the Finish buttons.
977 hwndButton
= GetDlgItem(hwndParent
, IDC_NEXT_BUTTON
);
979 x
= rcSheet
.right
- ((padding
.x
+ buttonWidth
) * (num_buttons
- 1));
981 SetWindowPos(hwndButton
, 0, x
, y
, 0, 0,
982 SWP_NOSIZE
| SWP_NOZORDER
| SWP_NOACTIVATE
);
984 hwndButton
= GetDlgItem(hwndParent
, IDC_FINISH_BUTTON
);
986 SetWindowPos(hwndButton
, 0, x
, y
, 0, 0,
987 SWP_NOSIZE
| SWP_NOZORDER
| SWP_NOACTIVATE
);
989 ShowWindow(hwndButton
, SW_HIDE
);
992 * Position the Back button.
994 hwndButton
= GetDlgItem(hwndParent
, IDC_BACK_BUTTON
);
998 SetWindowPos(hwndButton
, 0, x
, y
, 0, 0,
999 SWP_NOSIZE
| SWP_NOZORDER
| SWP_NOACTIVATE
);
1002 * Position the Cancel button.
1004 hwndButton
= GetDlgItem(hwndParent
, IDCANCEL
);
1006 x
= rcSheet
.right
- ((padding
.x
+ buttonWidth
) * (num_buttons
- 2));
1008 SetWindowPos(hwndButton
, 0, x
, y
, 0, 0,
1009 SWP_NOSIZE
| SWP_NOZORDER
| SWP_NOACTIVATE
);
1012 * Position Help button.
1014 hwndButton
= GetDlgItem(hwndParent
, IDHELP
);
1016 if (psInfo
->hasHelp
)
1018 x
= rcSheet
.right
- (padding
.x
+ buttonWidth
);
1020 SetWindowPos(hwndButton
, 0, x
, y
, 0, 0,
1021 SWP_NOSIZE
| SWP_NOZORDER
| SWP_NOACTIVATE
);
1024 ShowWindow(hwndButton
, SW_HIDE
);
1027 * Position and resize the sunken line.
1030 y
= rcSheet
.bottom
- ((padding
.y
* 2) + buttonHeight
+ lineHeight
);
1032 GetClientRect(hwndParent
, &rcSheet
);
1033 lineWidth
= rcSheet
.right
- (padding
.x
* 2);
1035 SetWindowPos(hwndLine
, 0, x
, y
, lineWidth
, 2,
1036 SWP_NOZORDER
| SWP_NOACTIVATE
);
1041 /******************************************************************************
1042 * PROPSHEET_GetPaddingInfo
1044 * Returns the layout information.
1046 static PADDING_INFO
PROPSHEET_GetPaddingInfo(HWND hwndDlg
)
1048 HWND hwndTab
= GetDlgItem(hwndDlg
, IDC_TABCONTROL
);
1051 PADDING_INFO padding
;
1053 GetWindowRect(hwndTab
, &rcTab
);
1058 ScreenToClient(hwndDlg
, &tl
);
1066 /******************************************************************************
1067 * PROPSHEET_GetPaddingInfoWizard
1069 * Returns the layout information.
1070 * Vertical spacing is the distance between the line and the buttons.
1071 * Do NOT use the Help button to gather padding information when it isn't mapped
1072 * (PSH_HASHELP), as app writers aren't forced to supply correct coordinates
1073 * for it in this case !
1074 * FIXME: I'm not sure about any other coordinate problems with these evil
1075 * buttons. Fix it in case additional problems appear or maybe calculate
1076 * a padding in a completely different way, as this is somewhat messy.
1078 static PADDING_INFO
PROPSHEET_GetPaddingInfoWizard(HWND hwndDlg
, const PropSheetInfo
*
1081 PADDING_INFO padding
;
1085 POINT ptButton
, ptLine
;
1088 if (psInfo
->hasHelp
)
1094 if (psInfo
->ppshheader
.dwFlags
& INTRNL_ANY_WIZARD
)
1096 idButton
= IDC_NEXT_BUTTON
;
1100 /* hopefully this is ok */
1101 idButton
= IDCANCEL
;
1105 hwndControl
= GetDlgItem(hwndDlg
, idButton
);
1106 GetWindowRect(hwndControl
, &rc
);
1108 ptButton
.x
= rc
.left
;
1109 ptButton
.y
= rc
.top
;
1111 ScreenToClient(hwndDlg
, &ptButton
);
1114 hwndControl
= GetDlgItem(hwndDlg
, IDC_SUNKEN_LINE
);
1115 GetWindowRect(hwndControl
, &rc
);
1118 ptLine
.y
= rc
.bottom
;
1120 ScreenToClient(hwndDlg
, &ptLine
);
1122 padding
.y
= ptButton
.y
- ptLine
.y
;
1125 ERR("padding negative ! Please report this !\n");
1127 /* this is most probably not correct, but the best we have now */
1128 padding
.x
= padding
.y
;
1132 /******************************************************************************
1133 * PROPSHEET_CreateTabControl
1135 * Insert the tabs in the tab control.
1137 static BOOL
PROPSHEET_CreateTabControl(HWND hwndParent
,
1138 PropSheetInfo
* psInfo
)
1140 HWND hwndTabCtrl
= GetDlgItem(hwndParent
, IDC_TABCONTROL
);
1146 item
.mask
= TCIF_TEXT
;
1147 item
.cchTextMax
= MAX_TABTEXT_LENGTH
;
1149 nTabs
= psInfo
->nPages
;
1152 * Set the image list for icons.
1154 if (psInfo
->hImageList
)
1156 SendMessageW(hwndTabCtrl
, TCM_SETIMAGELIST
, 0, (LPARAM
)psInfo
->hImageList
);
1159 for (i
= 0; i
< nTabs
; i
++)
1161 if ( psInfo
->proppage
[i
].hasIcon
)
1163 item
.mask
|= TCIF_IMAGE
;
1164 item
.iImage
= iImage
++;
1168 item
.mask
&= ~TCIF_IMAGE
;
1171 item
.pszText
= (LPWSTR
) psInfo
->proppage
[i
].pszText
;
1172 SendMessageW(hwndTabCtrl
, TCM_INSERTITEMW
, (WPARAM
)i
, (LPARAM
)&item
);
1178 * Get the size of an in-memory Template
1180 *( Based on the code of PROPSHEET_CollectPageInfo)
1181 * See also dialog.c/DIALOG_ParseTemplate32().
1184 static UINT
GetTemplateSize(DLGTEMPLATE
* pTemplate
)
1187 const WORD
* p
= (const WORD
*)pTemplate
;
1188 BOOL istemplateex
= (((MyDLGTEMPLATEEX
*)pTemplate
)->signature
== 0xFFFF);
1193 /* DLGTEMPLATEEX (not defined in any std. header file) */
1195 TRACE("is DLGTEMPLATEEX\n");
1197 p
++; /* signature */
1198 p
+= 2; /* help ID */
1199 p
+= 2; /* ext style */
1206 TRACE("is DLGTEMPLATE\n");
1208 p
+= 2; /* ext style */
1211 nrofitems
= (WORD
)*p
; p
++; /* nb items */
1227 TRACE("menu %s\n",debugstr_w((LPCWSTR
)p
));
1228 p
+= lstrlenW( (LPCWSTR
)p
) + 1;
1239 p
+= 2; /* 0xffff plus predefined window class ordinal value */
1242 TRACE("class %s\n",debugstr_w((LPCWSTR
)p
));
1243 p
+= lstrlenW( (LPCWSTR
)p
) + 1;
1248 TRACE("title %s\n",debugstr_w((LPCWSTR
)p
));
1249 p
+= lstrlenW((LPCWSTR
)p
) + 1;
1251 /* font, if DS_SETFONT set */
1252 if ((DS_SETFONT
& ((istemplateex
)? ((MyDLGTEMPLATEEX
*)pTemplate
)->style
:
1255 p
+=(istemplateex
)?3:1;
1256 TRACE("font %s\n",debugstr_w((LPCWSTR
)p
));
1257 p
+= lstrlenW( (LPCWSTR
)p
) + 1; /* the font name */
1260 /* now process the DLGITEMTEMPLATE(EX) structs (plus custom data)
1261 * that are following the DLGTEMPLATE(EX) data */
1262 TRACE("%d items\n",nrofitems
);
1263 while (nrofitems
> 0)
1265 p
= (WORD
*)(((DWORD
)p
+ 3) & ~3); /* DWORD align */
1268 p
+= (istemplateex
? sizeof(MyDLGITEMTEMPLATEEX
) : sizeof(DLGITEMTEMPLATE
))/sizeof(WORD
);
1277 TRACE("class ordinal 0x%08lx\n",*(DWORD
*)p
);
1281 TRACE("class %s\n",debugstr_w((LPCWSTR
)p
));
1282 p
+= lstrlenW( (LPCWSTR
)p
) + 1;
1286 /* check title text */
1293 TRACE("text ordinal 0x%08lx\n",*(DWORD
*)p
);
1297 TRACE("text %s\n",debugstr_w((LPCWSTR
)p
));
1298 p
+= lstrlenW( (LPCWSTR
)p
) + 1;
1301 p
+= *p
+ 1; /* Skip extra data */
1305 TRACE("%p %p size 0x%08x\n",p
, (WORD
*)pTemplate
,sizeof(WORD
)*(p
- (WORD
*)pTemplate
));
1306 return (p
- (WORD
*)pTemplate
)*sizeof(WORD
);
1310 /******************************************************************************
1311 * PROPSHEET_CreatePage
1315 static BOOL
PROPSHEET_CreatePage(HWND hwndParent
,
1317 const PropSheetInfo
* psInfo
,
1318 LPCPROPSHEETPAGEW ppshpage
)
1320 DLGTEMPLATE
* pTemplate
;
1323 PropPageInfo
* ppInfo
= psInfo
->proppage
;
1324 PADDING_INFO padding
;
1325 UINT pageWidth
,pageHeight
;
1329 TRACE("index %d\n", index
);
1331 if (ppshpage
== NULL
)
1336 if (ppshpage
->dwFlags
& PSP_DLGINDIRECT
)
1338 pTemplate
= (DLGTEMPLATE
*)ppshpage
->u
.pResource
;
1339 resSize
= GetTemplateSize(pTemplate
);
1346 hResource
= FindResourceW(ppshpage
->hInstance
,
1347 ppshpage
->u
.pszTemplate
,
1352 resSize
= SizeofResource(ppshpage
->hInstance
, hResource
);
1354 hTemplate
= LoadResource(ppshpage
->hInstance
, hResource
);
1358 pTemplate
= (LPDLGTEMPLATEW
)LockResource(hTemplate
);
1360 * Make a copy of the dialog template to make it writable
1363 temp
= COMCTL32_Alloc(resSize
);
1367 TRACE("copying pTemplate %p into temp %p (%ld)\n", pTemplate
, temp
, resSize
);
1368 memcpy(temp
, pTemplate
, resSize
);
1371 if (((MyDLGTEMPLATEEX
*)pTemplate
)->signature
== 0xFFFF)
1373 ((MyDLGTEMPLATEEX
*)pTemplate
)->style
|= WS_CHILD
| DS_CONTROL
;
1374 ((MyDLGTEMPLATEEX
*)pTemplate
)->style
&= ~DS_MODALFRAME
;
1375 ((MyDLGTEMPLATEEX
*)pTemplate
)->style
&= ~WS_CAPTION
;
1376 ((MyDLGTEMPLATEEX
*)pTemplate
)->style
&= ~WS_SYSMENU
;
1377 ((MyDLGTEMPLATEEX
*)pTemplate
)->style
&= ~WS_POPUP
;
1378 ((MyDLGTEMPLATEEX
*)pTemplate
)->style
&= ~WS_DISABLED
;
1379 ((MyDLGTEMPLATEEX
*)pTemplate
)->style
&= ~WS_VISIBLE
;
1380 ((MyDLGTEMPLATEEX
*)pTemplate
)->style
&= ~WS_THICKFRAME
;
1384 pTemplate
->style
|= WS_CHILD
| DS_CONTROL
;
1385 pTemplate
->style
&= ~DS_MODALFRAME
;
1386 pTemplate
->style
&= ~WS_CAPTION
;
1387 pTemplate
->style
&= ~WS_SYSMENU
;
1388 pTemplate
->style
&= ~WS_POPUP
;
1389 pTemplate
->style
&= ~WS_DISABLED
;
1390 pTemplate
->style
&= ~WS_VISIBLE
;
1391 pTemplate
->style
&= ~WS_THICKFRAME
;
1394 if (psInfo
->proppage
[index
].useCallback
)
1395 (*(ppshpage
->pfnCallback
))(hwndParent
,
1397 (LPPROPSHEETPAGEW
)ppshpage
);
1399 hwndPage
= CreateDialogIndirectParamW(ppshpage
->hInstance
,
1402 ppshpage
->pfnDlgProc
,
1404 /* Free a no more needed copy */
1406 COMCTL32_Free(temp
);
1408 ppInfo
[index
].hwndPage
= hwndPage
;
1410 if (psInfo
->ppshheader
.dwFlags
& INTRNL_ANY_WIZARD
) {
1411 /* FIXME: This code may no longer be correct.
1412 * It was not for the non-wizard path. (GLA 6/02)
1414 rc
.left
= psInfo
->x
;
1416 rc
.right
= psInfo
->width
;
1417 rc
.bottom
= psInfo
->height
;
1419 MapDialogRect(hwndParent
, &rc
);
1421 pageWidth
= rc
.right
- rc
.left
;
1422 pageHeight
= rc
.bottom
- rc
.top
;
1424 padding
= PROPSHEET_GetPaddingInfoWizard(hwndParent
, psInfo
);
1425 TRACE("setting page %08lx, rc (%d,%d)-(%d,%d) w=%d, h=%d, padx=%d, pady=%d\n",
1426 (DWORD
)hwndPage
, rc
.left
, rc
.top
, rc
.right
, rc
.bottom
,
1427 pageWidth
, pageHeight
, padding
.x
, padding
.y
);
1428 SetWindowPos(hwndPage
, HWND_TOP
,
1429 rc
.left
+ padding
.x
/2,
1430 rc
.top
+ padding
.y
/2,
1431 pageWidth
, pageHeight
, 0);
1435 * Ask the Tab control to reduce the client rectangle to that
1438 PROPSHEET_GetPageRect(psInfo
, hwndParent
, &rc
);
1439 pageWidth
= rc
.right
- rc
.left
;
1440 pageHeight
= rc
.bottom
- rc
.top
;
1441 TRACE("setting page %08lx, rc (%d,%d)-(%d,%d) w=%d, h=%d\n",
1442 (DWORD
)hwndPage
, rc
.left
, rc
.top
, rc
.right
, rc
.bottom
,
1443 pageWidth
, pageHeight
);
1444 SetWindowPos(hwndPage
, HWND_TOP
,
1446 pageWidth
, pageHeight
, 0);
1452 /******************************************************************************
1453 * PROPSHEET_ShowPage
1455 * Displays or creates the specified page.
1457 static BOOL
PROPSHEET_ShowPage(HWND hwndDlg
, int index
, PropSheetInfo
* psInfo
)
1461 TRACE("active_page %d, index %d\n", psInfo
->active_page
, index
);
1462 if (index
== psInfo
->active_page
)
1464 if (GetTopWindow(hwndDlg
) != psInfo
->proppage
[index
].hwndPage
)
1465 SetWindowPos(psInfo
->proppage
[index
].hwndPage
, HWND_TOP
, 0, 0, 0, 0, SWP_NOSIZE
| SWP_NOMOVE
);
1469 if (psInfo
->proppage
[index
].hwndPage
== 0)
1471 LPCPROPSHEETPAGEW ppshpage
;
1473 ppshpage
= (LPCPROPSHEETPAGEW
)psInfo
->proppage
[index
].hpage
;
1474 PROPSHEET_CreatePage(hwndDlg
, index
, psInfo
, ppshpage
);
1477 if (psInfo
->active_page
!= -1)
1478 ShowWindow(psInfo
->proppage
[psInfo
->active_page
].hwndPage
, SW_HIDE
);
1480 ShowWindow(psInfo
->proppage
[index
].hwndPage
, SW_SHOW
);
1482 /* Synchronize current selection with tab control
1483 * It seems to be needed even in case of PSH_WIZARD (no tab controls there) */
1484 hwndTabCtrl
= GetDlgItem(hwndDlg
, IDC_TABCONTROL
);
1485 SendMessageW(hwndTabCtrl
, TCM_SETCURSEL
, index
, 0);
1487 psInfo
->active_page
= index
;
1488 psInfo
->activeValid
= TRUE
;
1493 /******************************************************************************
1496 static BOOL
PROPSHEET_Back(HWND hwndDlg
)
1500 PropSheetInfo
* psInfo
= (PropSheetInfo
*) GetPropW(hwndDlg
,
1505 TRACE("active_page %d\n", psInfo
->active_page
);
1506 if (psInfo
->active_page
< 0)
1509 psn
.hdr
.code
= PSN_WIZBACK
;
1510 psn
.hdr
.hwndFrom
= hwndDlg
;
1514 hwndPage
= psInfo
->proppage
[psInfo
->active_page
].hwndPage
;
1516 result
= SendMessageW(hwndPage
, WM_NOTIFY
, 0, (LPARAM
) &psn
);
1519 else if (result
== 0)
1520 idx
= psInfo
->active_page
- 1;
1522 idx
= PROPSHEET_FindPageByResId(psInfo
, result
);
1524 if (idx
>= 0 && idx
< psInfo
->nPages
)
1526 if (PROPSHEET_CanSetCurSel(hwndDlg
))
1527 PROPSHEET_SetCurSel(hwndDlg
, idx
, -1, 0);
1532 /******************************************************************************
1535 static BOOL
PROPSHEET_Next(HWND hwndDlg
)
1539 LRESULT msgResult
= 0;
1540 PropSheetInfo
* psInfo
= (PropSheetInfo
*) GetPropW(hwndDlg
,
1544 TRACE("active_page %d\n", psInfo
->active_page
);
1545 if (psInfo
->active_page
< 0)
1548 psn
.hdr
.code
= PSN_WIZNEXT
;
1549 psn
.hdr
.hwndFrom
= hwndDlg
;
1553 hwndPage
= psInfo
->proppage
[psInfo
->active_page
].hwndPage
;
1555 msgResult
= SendMessageA(hwndPage
, WM_NOTIFY
, 0, (LPARAM
) &psn
);
1556 if (msgResult
== -1)
1558 else if (msgResult
== 0)
1559 idx
= psInfo
->active_page
+ 1;
1561 idx
= PROPSHEET_FindPageByResId(psInfo
, msgResult
);
1563 if (idx
< psInfo
->nPages
)
1565 if (PROPSHEET_CanSetCurSel(hwndDlg
) != FALSE
)
1566 PROPSHEET_SetCurSel(hwndDlg
, idx
, 1, 0);
1572 /******************************************************************************
1575 static BOOL
PROPSHEET_Finish(HWND hwndDlg
)
1579 LRESULT msgResult
= 0;
1580 PropSheetInfo
* psInfo
= (PropSheetInfo
*) GetPropW(hwndDlg
,
1583 TRACE("active_page %d\n", psInfo
->active_page
);
1584 if (psInfo
->active_page
< 0)
1587 psn
.hdr
.code
= PSN_WIZFINISH
;
1588 psn
.hdr
.hwndFrom
= hwndDlg
;
1592 hwndPage
= psInfo
->proppage
[psInfo
->active_page
].hwndPage
;
1594 msgResult
= SendMessageW(hwndPage
, WM_NOTIFY
, 0, (LPARAM
) &psn
);
1596 TRACE("msg result %ld\n", msgResult
);
1601 if (psInfo
->isModeless
)
1602 psInfo
->activeValid
= FALSE
;
1604 EndDialog(hwndDlg
, TRUE
);
1609 /******************************************************************************
1612 static BOOL
PROPSHEET_Apply(HWND hwndDlg
, LPARAM lParam
)
1618 PropSheetInfo
* psInfo
= (PropSheetInfo
*) GetPropW(hwndDlg
,
1621 TRACE("active_page %d\n", psInfo
->active_page
);
1622 if (psInfo
->active_page
< 0)
1625 psn
.hdr
.hwndFrom
= hwndDlg
;
1631 * Send PSN_KILLACTIVE to the current page.
1633 psn
.hdr
.code
= PSN_KILLACTIVE
;
1635 hwndPage
= psInfo
->proppage
[psInfo
->active_page
].hwndPage
;
1637 if (SendMessageA(hwndPage
, WM_NOTIFY
, 0, (LPARAM
) &psn
) != FALSE
)
1641 * Send PSN_APPLY to all pages.
1643 psn
.hdr
.code
= PSN_APPLY
;
1644 psn
.lParam
= lParam
;
1646 for (i
= 0; i
< psInfo
->nPages
; i
++)
1648 hwndPage
= psInfo
->proppage
[i
].hwndPage
;
1651 msgResult
= SendMessageA(hwndPage
, WM_NOTIFY
, 0, (LPARAM
) &psn
);
1652 if (msgResult
== PSNRET_INVALID_NOCHANGEPAGE
)
1659 psInfo
->activeValid
= FALSE
;
1661 else if(psInfo
->active_page
>= 0)
1663 psn
.hdr
.code
= PSN_SETACTIVE
;
1665 hwndPage
= psInfo
->proppage
[psInfo
->active_page
].hwndPage
;
1666 SendMessageA(hwndPage
, WM_NOTIFY
, 0, (LPARAM
) &psn
);
1672 /******************************************************************************
1675 static void PROPSHEET_Cancel(HWND hwndDlg
, LPARAM lParam
)
1677 PropSheetInfo
* psInfo
= (PropSheetInfo
*) GetPropW(hwndDlg
,
1683 TRACE("active_page %d\n", psInfo
->active_page
);
1684 if (psInfo
->active_page
< 0)
1687 hwndPage
= psInfo
->proppage
[psInfo
->active_page
].hwndPage
;
1688 psn
.hdr
.code
= PSN_QUERYCANCEL
;
1689 psn
.hdr
.hwndFrom
= hwndDlg
;
1693 if (SendMessageA(hwndPage
, WM_NOTIFY
, 0, (LPARAM
) &psn
))
1696 psn
.hdr
.code
= PSN_RESET
;
1697 psn
.lParam
= lParam
;
1699 for (i
= 0; i
< psInfo
->nPages
; i
++)
1701 hwndPage
= psInfo
->proppage
[i
].hwndPage
;
1704 SendMessageA(hwndPage
, WM_NOTIFY
, 0, (LPARAM
) &psn
);
1707 if (psInfo
->isModeless
)
1709 /* makes PSM_GETCURRENTPAGEHWND return NULL */
1710 psInfo
->activeValid
= FALSE
;
1713 EndDialog(hwndDlg
, FALSE
);
1716 /******************************************************************************
1719 static void PROPSHEET_Help(HWND hwndDlg
)
1721 PropSheetInfo
* psInfo
= (PropSheetInfo
*) GetPropW(hwndDlg
,
1726 TRACE("active_page %d\n", psInfo
->active_page
);
1727 if (psInfo
->active_page
< 0)
1730 hwndPage
= psInfo
->proppage
[psInfo
->active_page
].hwndPage
;
1731 psn
.hdr
.code
= PSN_HELP
;
1732 psn
.hdr
.hwndFrom
= hwndDlg
;
1736 SendMessageA(hwndPage
, WM_NOTIFY
, 0, (LPARAM
) &psn
);
1739 /******************************************************************************
1742 static void PROPSHEET_Changed(HWND hwndDlg
, HWND hwndDirtyPage
)
1745 PropSheetInfo
* psInfo
= (PropSheetInfo
*) GetPropW(hwndDlg
,
1749 if (!psInfo
) return;
1751 * Set the dirty flag of this page.
1753 for (i
= 0; i
< psInfo
->nPages
; i
++)
1755 if (psInfo
->proppage
[i
].hwndPage
== hwndDirtyPage
)
1756 psInfo
->proppage
[i
].isDirty
= TRUE
;
1760 * Enable the Apply button.
1762 if (psInfo
->hasApply
)
1764 HWND hwndApplyBtn
= GetDlgItem(hwndDlg
, IDC_APPLY_BUTTON
);
1766 EnableWindow(hwndApplyBtn
, TRUE
);
1770 /******************************************************************************
1771 * PROPSHEET_UnChanged
1773 static void PROPSHEET_UnChanged(HWND hwndDlg
, HWND hwndCleanPage
)
1776 BOOL noPageDirty
= TRUE
;
1777 HWND hwndApplyBtn
= GetDlgItem(hwndDlg
, IDC_APPLY_BUTTON
);
1778 PropSheetInfo
* psInfo
= (PropSheetInfo
*) GetPropW(hwndDlg
,
1782 if ( !psInfo
) return;
1783 for (i
= 0; i
< psInfo
->nPages
; i
++)
1785 /* set the specified page as clean */
1786 if (psInfo
->proppage
[i
].hwndPage
== hwndCleanPage
)
1787 psInfo
->proppage
[i
].isDirty
= FALSE
;
1789 /* look to see if there's any dirty pages */
1790 if (psInfo
->proppage
[i
].isDirty
)
1791 noPageDirty
= FALSE
;
1795 * Disable Apply button.
1798 EnableWindow(hwndApplyBtn
, FALSE
);
1801 /******************************************************************************
1802 * PROPSHEET_PressButton
1804 static void PROPSHEET_PressButton(HWND hwndDlg
, int buttonID
)
1806 TRACE("buttonID %d\n", buttonID
);
1809 case PSBTN_APPLYNOW
:
1810 PROPSHEET_DoCommand(hwndDlg
, IDC_APPLY_BUTTON
);
1813 PROPSHEET_Back(hwndDlg
);
1816 PROPSHEET_DoCommand(hwndDlg
, IDCANCEL
);
1819 PROPSHEET_Finish(hwndDlg
);
1822 PROPSHEET_DoCommand(hwndDlg
, IDHELP
);
1825 PROPSHEET_Next(hwndDlg
);
1828 PROPSHEET_DoCommand(hwndDlg
, IDOK
);
1831 FIXME("Invalid button index %d\n", buttonID
);
1836 /*************************************************************************
1837 * BOOL PROPSHEET_CanSetCurSel [Internal]
1839 * Test whether the current page can be changed by sending a PSN_KILLACTIVE
1842 * hwndDlg [I] handle to a Dialog hWnd
1845 * TRUE if Current Selection can change
1849 static BOOL
PROPSHEET_CanSetCurSel(HWND hwndDlg
)
1851 PropSheetInfo
* psInfo
= (PropSheetInfo
*) GetPropW(hwndDlg
,
1857 TRACE("active_page %d\n", psInfo
->active_page
);
1864 if (psInfo
->active_page
< 0)
1871 * Notify the current page.
1873 hwndPage
= psInfo
->proppage
[psInfo
->active_page
].hwndPage
;
1874 psn
.hdr
.code
= PSN_KILLACTIVE
;
1875 psn
.hdr
.hwndFrom
= hwndDlg
;
1879 res
= !SendMessageA(hwndPage
, WM_NOTIFY
, 0, (LPARAM
) &psn
);
1882 TRACE("<-- %d\n", res
);
1886 /******************************************************************************
1887 * PROPSHEET_SetCurSel
1889 static BOOL
PROPSHEET_SetCurSel(HWND hwndDlg
,
1892 HPROPSHEETPAGE hpage
1895 PropSheetInfo
* psInfo
= (PropSheetInfo
*) GetPropW(hwndDlg
, PropSheetInfoStr
);
1896 HWND hwndHelp
= GetDlgItem(hwndDlg
, IDHELP
);
1897 HWND hwndTabControl
= GetDlgItem(hwndDlg
, IDC_TABCONTROL
);
1899 TRACE("index %d, skipdir %d, hpage %p\n", index
, skipdir
, hpage
);
1900 /* hpage takes precedence over index */
1902 index
= PROPSHEET_GetPageIndex(hpage
, psInfo
);
1904 if (index
< 0 || index
>= psInfo
->nPages
)
1906 TRACE("Could not find page to select!\n");
1915 SendMessageW(hwndTabControl
, TCM_SETCURSEL
, index
, 0);
1917 psn
.hdr
.code
= PSN_SETACTIVE
;
1918 psn
.hdr
.hwndFrom
= hwndDlg
;
1922 if (!psInfo
->proppage
[index
].hwndPage
) {
1923 LPCPROPSHEETPAGEW ppshpage
= (LPCPROPSHEETPAGEW
)psInfo
->proppage
[index
].hpage
;
1924 PROPSHEET_CreatePage(hwndDlg
, index
, psInfo
, ppshpage
);
1927 result
= SendMessageW(psInfo
->proppage
[index
].hwndPage
, WM_NOTIFY
, 0, (LPARAM
) &psn
);
1934 FIXME("Tried to skip before first property sheet page!\n");
1937 if (index
>= psInfo
->nPages
) {
1938 FIXME("Tried to skip after last property sheet page!\n");
1939 index
= psInfo
->nPages
-1;
1943 else if (result
!= 0)
1945 index
= PROPSHEET_FindPageByResId(psInfo
, result
);
1950 * Display the new page.
1952 PROPSHEET_ShowPage(hwndDlg
, index
, psInfo
);
1954 if (psInfo
->proppage
[index
].hasHelp
)
1955 EnableWindow(hwndHelp
, TRUE
);
1957 EnableWindow(hwndHelp
, FALSE
);
1962 /******************************************************************************
1963 * PROPSHEET_SetCurSelId
1965 * Selects the page, specified by resource id.
1967 static void PROPSHEET_SetCurSelId(HWND hwndDlg
, int id
)
1970 PropSheetInfo
* psInfo
=
1971 (PropSheetInfo
*) GetPropW(hwndDlg
, PropSheetInfoStr
);
1973 idx
= PROPSHEET_FindPageByResId(psInfo
, id
);
1974 if (idx
< psInfo
->nPages
)
1976 if (PROPSHEET_CanSetCurSel(hwndDlg
) != FALSE
)
1977 PROPSHEET_SetCurSel(hwndDlg
, idx
, 1, 0);
1981 /******************************************************************************
1982 * PROPSHEET_SetTitleA
1984 static void PROPSHEET_SetTitleA(HWND hwndDlg
, DWORD dwStyle
, LPCSTR lpszText
)
1986 if(HIWORD(lpszText
))
1989 MultiByteToWideChar(CP_ACP
, 0, lpszText
, -1,
1990 szTitle
, sizeof szTitle
);
1991 PROPSHEET_SetTitleW(hwndDlg
, dwStyle
, szTitle
);
1995 PROPSHEET_SetTitleW(hwndDlg
, dwStyle
, (LPCWSTR
)lpszText
);
1999 /******************************************************************************
2000 * PROPSHEET_SetTitleW
2002 static void PROPSHEET_SetTitleW(HWND hwndDlg
, DWORD dwStyle
, LPCWSTR lpszText
)
2004 PropSheetInfo
* psInfo
= (PropSheetInfo
*) GetPropW(hwndDlg
, PropSheetInfoStr
);
2007 TRACE("'%s' (style %08lx)\n", debugstr_w(lpszText
), dwStyle
);
2008 if (HIWORD(lpszText
) == 0) {
2009 if (!LoadStringW(psInfo
->ppshheader
.hInstance
,
2010 LOWORD(lpszText
), szTitle
, sizeof(szTitle
)-sizeof(WCHAR
)))
2014 if (dwStyle
& PSH_PROPTITLE
)
2017 int lentitle
= strlenW(lpszText
);
2018 int lenprop
= strlenW(psInfo
->strPropertiesFor
);
2020 dest
= COMCTL32_Alloc( (lentitle
+ lenprop
+ 1)*sizeof (WCHAR
));
2021 strcpyW(dest
, psInfo
->strPropertiesFor
);
2022 strcatW(dest
, lpszText
);
2024 SetWindowTextW(hwndDlg
, dest
);
2025 COMCTL32_Free(dest
);
2028 SetWindowTextW(hwndDlg
, lpszText
);
2031 /******************************************************************************
2032 * PROPSHEET_SetFinishTextA
2034 static void PROPSHEET_SetFinishTextA(HWND hwndDlg
, LPCSTR lpszText
)
2036 HWND hwndButton
= GetDlgItem(hwndDlg
, IDC_FINISH_BUTTON
);
2038 TRACE("'%s'\n", lpszText
);
2039 /* Set text, show and enable the Finish button */
2040 SetWindowTextA(hwndButton
, lpszText
);
2041 ShowWindow(hwndButton
, SW_SHOW
);
2042 EnableWindow(hwndButton
, TRUE
);
2044 /* Make it default pushbutton */
2045 SendMessageA(hwndDlg
, DM_SETDEFID
, IDC_FINISH_BUTTON
, 0);
2047 /* Hide Back button */
2048 hwndButton
= GetDlgItem(hwndDlg
, IDC_BACK_BUTTON
);
2049 ShowWindow(hwndButton
, SW_HIDE
);
2051 /* Hide Next button */
2052 hwndButton
= GetDlgItem(hwndDlg
, IDC_NEXT_BUTTON
);
2053 ShowWindow(hwndButton
, SW_HIDE
);
2056 /******************************************************************************
2057 * PROPSHEET_SetFinishTextW
2059 static void PROPSHEET_SetFinishTextW(HWND hwndDlg
, LPCWSTR lpszText
)
2061 HWND hwndButton
= GetDlgItem(hwndDlg
, IDC_FINISH_BUTTON
);
2063 TRACE("'%s'\n", debugstr_w(lpszText
));
2064 /* Set text, show and enable the Finish button */
2065 SetWindowTextW(hwndButton
, lpszText
);
2066 ShowWindow(hwndButton
, SW_SHOW
);
2067 EnableWindow(hwndButton
, TRUE
);
2069 /* Make it default pushbutton */
2070 SendMessageW(hwndDlg
, DM_SETDEFID
, IDC_FINISH_BUTTON
, 0);
2072 /* Hide Back button */
2073 hwndButton
= GetDlgItem(hwndDlg
, IDC_BACK_BUTTON
);
2074 ShowWindow(hwndButton
, SW_HIDE
);
2076 /* Hide Next button */
2077 hwndButton
= GetDlgItem(hwndDlg
, IDC_NEXT_BUTTON
);
2078 ShowWindow(hwndButton
, SW_HIDE
);
2081 /******************************************************************************
2082 * PROPSHEET_QuerySiblings
2084 static LRESULT
PROPSHEET_QuerySiblings(HWND hwndDlg
,
2085 WPARAM wParam
, LPARAM lParam
)
2089 LRESULT msgResult
= 0;
2090 PropSheetInfo
* psInfo
= (PropSheetInfo
*) GetPropW(hwndDlg
,
2093 while ((i
< psInfo
->nPages
) && (msgResult
== 0))
2095 hwndPage
= psInfo
->proppage
[i
].hwndPage
;
2096 msgResult
= SendMessageA(hwndPage
, PSM_QUERYSIBLINGS
, wParam
, lParam
);
2104 /******************************************************************************
2107 static BOOL
PROPSHEET_AddPage(HWND hwndDlg
,
2108 HPROPSHEETPAGE hpage
)
2110 PropSheetInfo
* psInfo
= (PropSheetInfo
*) GetPropW(hwndDlg
,
2112 HWND hwndTabControl
= GetDlgItem(hwndDlg
, IDC_TABCONTROL
);
2114 LPCPROPSHEETPAGEW ppsp
= (LPCPROPSHEETPAGEW
)hpage
;
2116 TRACE("hpage %p\n", hpage
);
2118 * Allocate and fill in a new PropPageInfo entry.
2120 psInfo
->proppage
= (PropPageInfo
*) COMCTL32_ReAlloc(psInfo
->proppage
,
2121 sizeof(PropPageInfo
) *
2122 (psInfo
->nPages
+ 1));
2123 if (!PROPSHEET_CollectPageInfo(ppsp
, psInfo
, psInfo
->nPages
))
2126 psInfo
->proppage
[psInfo
->nPages
].hpage
= hpage
;
2128 if (ppsp
->dwFlags
& PSP_PREMATURE
)
2130 /* Create the page but don't show it */
2131 PROPSHEET_CreatePage(hwndDlg
, psInfo
->nPages
, psInfo
, ppsp
);
2135 * Add a new tab to the tab control.
2137 item
.mask
= TCIF_TEXT
;
2138 item
.pszText
= (LPWSTR
) psInfo
->proppage
[psInfo
->nPages
].pszText
;
2139 item
.cchTextMax
= MAX_TABTEXT_LENGTH
;
2141 if (psInfo
->hImageList
)
2143 SendMessageW(hwndTabControl
, TCM_SETIMAGELIST
, 0, (LPARAM
)psInfo
->hImageList
);
2146 if ( psInfo
->proppage
[psInfo
->nPages
].hasIcon
)
2148 item
.mask
|= TCIF_IMAGE
;
2149 item
.iImage
= psInfo
->nPages
;
2152 SendMessageW(hwndTabControl
, TCM_INSERTITEMW
, psInfo
->nPages
+ 1,
2157 /* If it is the only page - show it */
2158 if(psInfo
->nPages
== 1)
2159 PROPSHEET_SetCurSel(hwndDlg
, 0, 1, 0);
2163 /******************************************************************************
2164 * PROPSHEET_RemovePage
2166 static BOOL
PROPSHEET_RemovePage(HWND hwndDlg
,
2168 HPROPSHEETPAGE hpage
)
2170 PropSheetInfo
* psInfo
= (PropSheetInfo
*) GetPropW(hwndDlg
,
2172 HWND hwndTabControl
= GetDlgItem(hwndDlg
, IDC_TABCONTROL
);
2173 PropPageInfo
* oldPages
;
2175 TRACE("index %d, hpage %p\n", index
, hpage
);
2179 oldPages
= psInfo
->proppage
;
2181 * hpage takes precedence over index.
2185 index
= PROPSHEET_GetPageIndex(hpage
, psInfo
);
2188 /* Make sure that index is within range */
2189 if (index
< 0 || index
>= psInfo
->nPages
)
2191 TRACE("Could not find page to remove!\n");
2195 TRACE("total pages %d removing page %d active page %d\n",
2196 psInfo
->nPages
, index
, psInfo
->active_page
);
2198 * Check if we're removing the active page.
2200 if (index
== psInfo
->active_page
)
2202 if (psInfo
->nPages
> 1)
2206 /* activate previous page */
2207 PROPSHEET_SetCurSel(hwndDlg
, index
- 1, -1, 0);
2211 /* activate the next page */
2212 PROPSHEET_SetCurSel(hwndDlg
, index
+ 1, 1, 0);
2213 psInfo
->active_page
= index
;
2218 psInfo
->active_page
= -1;
2219 if (!psInfo
->isModeless
)
2221 EndDialog(hwndDlg
, FALSE
);
2226 else if (index
< psInfo
->active_page
)
2227 psInfo
->active_page
--;
2229 /* Destroy page dialog window */
2230 DestroyWindow(psInfo
->proppage
[index
].hwndPage
);
2232 /* Free page resources */
2233 if(psInfo
->proppage
[index
].hpage
)
2235 PROPSHEETPAGEW
* psp
= (PROPSHEETPAGEW
*)psInfo
->proppage
[index
].hpage
;
2237 if ((psp
->dwFlags
& PSP_USETITLE
) && psInfo
->proppage
[index
].pszText
)
2238 HeapFree(GetProcessHeap(), 0, (LPVOID
)psInfo
->proppage
[index
].pszText
);
2240 DestroyPropertySheetPage(psInfo
->proppage
[index
].hpage
);
2243 /* Remove the tab */
2244 SendMessageW(hwndTabControl
, TCM_DELETEITEM
, index
, 0);
2247 psInfo
->proppage
= COMCTL32_Alloc(sizeof(PropPageInfo
) * psInfo
->nPages
);
2250 memcpy(&psInfo
->proppage
[0], &oldPages
[0], index
* sizeof(PropPageInfo
));
2252 if (index
< psInfo
->nPages
)
2253 memcpy(&psInfo
->proppage
[index
], &oldPages
[index
+ 1],
2254 (psInfo
->nPages
- index
) * sizeof(PropPageInfo
));
2256 COMCTL32_Free(oldPages
);
2261 /******************************************************************************
2262 * PROPSHEET_SetWizButtons
2264 * This code will work if (and assumes that) the Next button is on top of the
2265 * Finish button. ie. Finish comes after Next in the Z order.
2266 * This means make sure the dialog template reflects this.
2269 static void PROPSHEET_SetWizButtons(HWND hwndDlg
, DWORD dwFlags
)
2271 HWND hwndBack
= GetDlgItem(hwndDlg
, IDC_BACK_BUTTON
);
2272 HWND hwndNext
= GetDlgItem(hwndDlg
, IDC_NEXT_BUTTON
);
2273 HWND hwndFinish
= GetDlgItem(hwndDlg
, IDC_FINISH_BUTTON
);
2275 TRACE("%ld\n", dwFlags
);
2277 EnableWindow(hwndBack
, FALSE
);
2278 EnableWindow(hwndNext
, FALSE
);
2279 EnableWindow(hwndFinish
, FALSE
);
2281 if (dwFlags
& PSWIZB_BACK
)
2282 EnableWindow(hwndBack
, TRUE
);
2284 if (dwFlags
& PSWIZB_NEXT
)
2286 /* Hide the Finish button */
2287 ShowWindow(hwndFinish
, SW_HIDE
);
2289 /* Show and enable the Next button */
2290 ShowWindow(hwndNext
, SW_SHOW
);
2291 EnableWindow(hwndNext
, TRUE
);
2293 /* Set the Next button as the default pushbutton */
2294 SendMessageA(hwndDlg
, DM_SETDEFID
, IDC_NEXT_BUTTON
, 0);
2297 if ((dwFlags
& PSWIZB_FINISH
) || (dwFlags
& PSWIZB_DISABLEDFINISH
))
2299 /* Hide the Next button */
2300 ShowWindow(hwndNext
, SW_HIDE
);
2302 /* Show the Finish button */
2303 ShowWindow(hwndFinish
, SW_SHOW
);
2305 if (dwFlags
& PSWIZB_FINISH
)
2306 EnableWindow(hwndFinish
, TRUE
);
2308 /* Set the Finish button as the default pushbutton */
2309 SendMessageA(hwndDlg
, DM_SETDEFID
, IDC_FINISH_BUTTON
, 0);
2313 /******************************************************************************
2314 * PROPSHEET_GetPageIndex
2316 * Given a HPROPSHEETPAGE, returns the index of the corresponding page from
2317 * the array of PropPageInfo.
2319 static int PROPSHEET_GetPageIndex(HPROPSHEETPAGE hpage
, PropSheetInfo
* psInfo
)
2324 TRACE("hpage %p\n", hpage
);
2325 while ((index
< psInfo
->nPages
) && (found
== FALSE
))
2327 if (psInfo
->proppage
[index
].hpage
== hpage
)
2339 /******************************************************************************
2342 static void PROPSHEET_CleanUp(HWND hwndDlg
)
2345 PropSheetInfo
* psInfo
= (PropSheetInfo
*) RemovePropW(hwndDlg
,
2349 if (!psInfo
) return;
2350 if (HIWORD(psInfo
->ppshheader
.pszCaption
))
2351 HeapFree(GetProcessHeap(), 0, (LPVOID
)psInfo
->ppshheader
.pszCaption
);
2353 for (i
= 0; i
< psInfo
->nPages
; i
++)
2355 PROPSHEETPAGEA
* psp
= (PROPSHEETPAGEA
*)psInfo
->proppage
[i
].hpage
;
2357 if(psInfo
->proppage
[i
].hwndPage
)
2358 DestroyWindow(psInfo
->proppage
[i
].hwndPage
);
2362 if ((psp
->dwFlags
& PSP_USETITLE
) && psInfo
->proppage
[i
].pszText
)
2363 HeapFree(GetProcessHeap(), 0, (LPVOID
)psInfo
->proppage
[i
].pszText
);
2365 DestroyPropertySheetPage(psInfo
->proppage
[i
].hpage
);
2369 COMCTL32_Free(psInfo
->proppage
);
2370 COMCTL32_Free(psInfo
->strPropertiesFor
);
2371 ImageList_Destroy(psInfo
->hImageList
);
2373 GlobalFree((HGLOBAL
)psInfo
);
2376 /******************************************************************************
2377 * PropertySheet (COMCTL32.@)
2378 * PropertySheetA (COMCTL32.@)
2380 INT WINAPI
PropertySheetA(LPCPROPSHEETHEADERA lppsh
)
2383 PropSheetInfo
* psInfo
= (PropSheetInfo
*) GlobalAlloc(GPTR
,
2384 sizeof(PropSheetInfo
));
2388 TRACE("(%p)\n", lppsh
);
2390 PROPSHEET_CollectSheetInfoA(lppsh
, psInfo
);
2392 psInfo
->proppage
= (PropPageInfo
*) COMCTL32_Alloc(sizeof(PropPageInfo
) *
2394 pByte
= (BYTE
*) psInfo
->ppshheader
.u3
.ppsp
;
2396 for (n
= i
= 0; i
< lppsh
->nPages
; i
++, n
++)
2398 if (!(lppsh
->dwFlags
& PSH_PROPSHEETPAGE
))
2399 psInfo
->proppage
[n
].hpage
= psInfo
->ppshheader
.u3
.phpage
[i
];
2402 psInfo
->proppage
[n
].hpage
= CreatePropertySheetPageA((LPCPROPSHEETPAGEA
)pByte
);
2403 pByte
+= ((LPPROPSHEETPAGEA
)pByte
)->dwSize
;
2406 if (!PROPSHEET_CollectPageInfo((LPCPROPSHEETPAGEW
)psInfo
->proppage
[n
].hpage
,
2409 if (lppsh
->dwFlags
& PSH_PROPSHEETPAGE
)
2410 DestroyPropertySheetPage(psInfo
->proppage
[n
].hpage
);
2416 bRet
= PROPSHEET_CreateDialog(psInfo
);
2421 /******************************************************************************
2422 * PropertySheetW (COMCTL32.@)
2424 INT WINAPI
PropertySheetW(LPCPROPSHEETHEADERW lppsh
)
2427 PropSheetInfo
* psInfo
= (PropSheetInfo
*) GlobalAlloc(GPTR
,
2428 sizeof(PropSheetInfo
));
2432 TRACE("(%p)\n", lppsh
);
2434 PROPSHEET_CollectSheetInfoW(lppsh
, psInfo
);
2436 psInfo
->proppage
= (PropPageInfo
*) COMCTL32_Alloc(sizeof(PropPageInfo
) *
2438 pByte
= (BYTE
*) psInfo
->ppshheader
.u3
.ppsp
;
2440 for (n
= i
= 0; i
< lppsh
->nPages
; i
++, n
++)
2442 if (!(lppsh
->dwFlags
& PSH_PROPSHEETPAGE
))
2443 psInfo
->proppage
[n
].hpage
= psInfo
->ppshheader
.u3
.phpage
[i
];
2446 psInfo
->proppage
[n
].hpage
= CreatePropertySheetPageW((LPCPROPSHEETPAGEW
)pByte
);
2447 pByte
+= ((LPPROPSHEETPAGEW
)pByte
)->dwSize
;
2450 if (!PROPSHEET_CollectPageInfo((LPCPROPSHEETPAGEW
)psInfo
->proppage
[n
].hpage
,
2453 if (lppsh
->dwFlags
& PSH_PROPSHEETPAGE
)
2454 DestroyPropertySheetPage(psInfo
->proppage
[n
].hpage
);
2460 bRet
= PROPSHEET_CreateDialog(psInfo
);
2465 /******************************************************************************
2466 * CreatePropertySheetPage (COMCTL32.@)
2467 * CreatePropertySheetPageA (COMCTL32.@)
2469 HPROPSHEETPAGE WINAPI
CreatePropertySheetPageA(
2470 LPCPROPSHEETPAGEA lpPropSheetPage
)
2472 PROPSHEETPAGEW
* ppsp
= COMCTL32_Alloc(sizeof(PROPSHEETPAGEW
));
2474 memcpy(ppsp
,lpPropSheetPage
,min(lpPropSheetPage
->dwSize
,sizeof(PROPSHEETPAGEA
)));
2476 if ( !(ppsp
->dwFlags
& PSP_DLGINDIRECT
) && HIWORD( ppsp
->u
.pszTemplate
) )
2478 PROPSHEET_AtoW(&ppsp
->u
.pszTemplate
, lpPropSheetPage
->u
.pszTemplate
);
2480 if ( (ppsp
->dwFlags
& PSP_USEICONID
) && HIWORD( ppsp
->u2
.pszIcon
) )
2482 PROPSHEET_AtoW(&ppsp
->u2
.pszIcon
, lpPropSheetPage
->u2
.pszIcon
);
2485 if ((ppsp
->dwFlags
& PSP_USETITLE
) && HIWORD( ppsp
->pszTitle
))
2487 PROPSHEET_AtoW(&ppsp
->pszTitle
, lpPropSheetPage
->pszTitle
);
2489 else if ( !(ppsp
->dwFlags
& PSP_USETITLE
) )
2490 ppsp
->pszTitle
= NULL
;
2492 return (HPROPSHEETPAGE
)ppsp
;
2495 /******************************************************************************
2496 * CreatePropertySheetPageW (COMCTL32.@)
2498 HPROPSHEETPAGE WINAPI
CreatePropertySheetPageW(LPCPROPSHEETPAGEW lpPropSheetPage
)
2500 PROPSHEETPAGEW
* ppsp
= COMCTL32_Alloc(sizeof(PROPSHEETPAGEW
));
2502 memcpy(ppsp
,lpPropSheetPage
,min(lpPropSheetPage
->dwSize
,sizeof(PROPSHEETPAGEW
)));
2504 if ( !(ppsp
->dwFlags
& PSP_DLGINDIRECT
) && HIWORD( ppsp
->u
.pszTemplate
) )
2506 int len
= strlenW(lpPropSheetPage
->u
.pszTemplate
);
2508 ppsp
->u
.pszTemplate
= HeapAlloc( GetProcessHeap(),0,(len
+1)*sizeof (WCHAR
) );
2509 strcpyW( (WCHAR
*)ppsp
->u
.pszTemplate
, lpPropSheetPage
->u
.pszTemplate
);
2511 if ( (ppsp
->dwFlags
& PSP_USEICONID
) && HIWORD( ppsp
->u2
.pszIcon
) )
2513 int len
= strlenW(lpPropSheetPage
->u2
.pszIcon
);
2514 ppsp
->u2
.pszIcon
= HeapAlloc( GetProcessHeap(), 0, (len
+1)*sizeof (WCHAR
) );
2515 strcpyW( (WCHAR
*)ppsp
->u2
.pszIcon
, lpPropSheetPage
->u2
.pszIcon
);
2518 if ((ppsp
->dwFlags
& PSP_USETITLE
) && HIWORD( ppsp
->pszTitle
))
2520 int len
= strlenW(lpPropSheetPage
->pszTitle
);
2521 ppsp
->pszTitle
= HeapAlloc( GetProcessHeap(), 0, (len
+1)*sizeof (WCHAR
) );
2522 strcpyW( (WCHAR
*)ppsp
->pszTitle
, lpPropSheetPage
->pszTitle
);
2524 else if ( !(ppsp
->dwFlags
& PSP_USETITLE
) )
2525 ppsp
->pszTitle
= NULL
;
2527 return (HPROPSHEETPAGE
)ppsp
;
2530 /******************************************************************************
2531 * DestroyPropertySheetPage (COMCTL32.@)
2533 BOOL WINAPI
DestroyPropertySheetPage(HPROPSHEETPAGE hPropPage
)
2535 PROPSHEETPAGEW
*psp
= (PROPSHEETPAGEW
*)hPropPage
;
2540 if ( !(psp
->dwFlags
& PSP_DLGINDIRECT
) && HIWORD( psp
->u
.pszTemplate
) )
2541 HeapFree(GetProcessHeap(), 0, (LPVOID
)psp
->u
.pszTemplate
);
2543 if ( (psp
->dwFlags
& PSP_USEICONID
) && HIWORD( psp
->u2
.pszIcon
) )
2544 HeapFree(GetProcessHeap(), 0, (LPVOID
)psp
->u2
.pszIcon
);
2546 if ((psp
->dwFlags
& PSP_USETITLE
) && HIWORD( psp
->pszTitle
))
2547 HeapFree(GetProcessHeap(), 0, (LPVOID
)psp
->pszTitle
);
2549 COMCTL32_Free(hPropPage
);
2554 /******************************************************************************
2555 * PROPSHEET_IsDialogMessage
2557 static BOOL
PROPSHEET_IsDialogMessage(HWND hwnd
, LPMSG lpMsg
)
2559 PropSheetInfo
* psInfo
= (PropSheetInfo
*) GetPropW(hwnd
, PropSheetInfoStr
);
2562 if (!psInfo
|| (hwnd
!= lpMsg
->hwnd
&& !IsChild(hwnd
, lpMsg
->hwnd
)))
2565 if (lpMsg
->message
== WM_KEYDOWN
&& (GetKeyState(VK_CONTROL
) & 0x8000))
2568 INT dlgCode
= SendMessageA(lpMsg
->hwnd
, WM_GETDLGCODE
, 0, (LPARAM
)lpMsg
);
2570 if (!(dlgCode
& DLGC_WANTMESSAGE
))
2572 switch (lpMsg
->wParam
)
2575 if (GetKeyState(VK_SHIFT
) & 0x8000)
2581 case VK_NEXT
: new_page
= 1; break;
2582 case VK_PRIOR
: new_page
= -1; break;
2588 if (PROPSHEET_CanSetCurSel(hwnd
) != FALSE
)
2590 new_page
+= psInfo
->active_page
;
2593 new_page
= psInfo
->nPages
- 1;
2594 else if (new_page
>= psInfo
->nPages
)
2597 PROPSHEET_SetCurSel(hwnd
, new_page
, 1, 0);
2604 return IsDialogMessageA(hwnd
, lpMsg
);
2607 /******************************************************************************
2608 * PROPSHEET_DoCommand
2610 static BOOL
PROPSHEET_DoCommand(HWND hwnd
, WORD wID
)
2616 case IDC_APPLY_BUTTON
:
2618 HWND hwndApplyBtn
= GetDlgItem(hwnd
, IDC_APPLY_BUTTON
);
2620 if (PROPSHEET_Apply(hwnd
, wID
== IDOK
? 1: 0) == FALSE
)
2625 PropSheetInfo
* psInfo
= (PropSheetInfo
*) GetPropW(hwnd
,
2629 if (psInfo
->restartWindows
)
2630 result
= ID_PSRESTARTWINDOWS
;
2632 /* reboot system takes precedence over restart windows */
2633 if (psInfo
->rebootSystem
)
2634 result
= ID_PSREBOOTSYSTEM
;
2636 if (psInfo
->isModeless
)
2637 psInfo
->activeValid
= FALSE
;
2639 EndDialog(hwnd
, result
);
2642 EnableWindow(hwndApplyBtn
, FALSE
);
2647 case IDC_BACK_BUTTON
:
2648 PROPSHEET_Back(hwnd
);
2651 case IDC_NEXT_BUTTON
:
2652 PROPSHEET_Next(hwnd
);
2655 case IDC_FINISH_BUTTON
:
2656 PROPSHEET_Finish(hwnd
);
2660 PROPSHEET_Cancel(hwnd
, 0);
2664 PROPSHEET_Help(hwnd
);
2671 /******************************************************************************
2672 * PROPSHEET_DialogProc
2675 PROPSHEET_DialogProc(HWND hwnd
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
)
2677 TRACE("hwnd=%p msg=0x%04x wparam=%x lparam=%lx\n",
2678 hwnd
, uMsg
, wParam
, lParam
);
2684 PropSheetInfo
* psInfo
= (PropSheetInfo
*) lParam
;
2685 WCHAR
* strCaption
= (WCHAR
*)COMCTL32_Alloc(MAX_CAPTION_LENGTH
*sizeof(WCHAR
));
2686 HWND hwndTabCtrl
= GetDlgItem(hwnd
, IDC_TABCONTROL
);
2687 LPCPROPSHEETPAGEW ppshpage
;
2690 SetPropW(hwnd
, PropSheetInfoStr
, (HANDLE
)psInfo
);
2693 * psInfo->hwnd is not being used by WINE code - it exists
2694 * for compatibility with "real" Windoze. The same about
2695 * SetWindowLong - WINE is only using the PropSheetInfoStr
2698 psInfo
->hwnd
= hwnd
;
2699 SetWindowLongW(hwnd
,DWL_USER
,(LONG
)psInfo
);
2702 * Small icon in the title bar.
2704 if ((psInfo
->ppshheader
.dwFlags
& PSH_USEICONID
) ||
2705 (psInfo
->ppshheader
.dwFlags
& PSH_USEHICON
))
2708 int icon_cx
= GetSystemMetrics(SM_CXSMICON
);
2709 int icon_cy
= GetSystemMetrics(SM_CYSMICON
);
2711 if (psInfo
->ppshheader
.dwFlags
& PSH_USEICONID
)
2712 hIcon
= LoadImageW(psInfo
->ppshheader
.hInstance
,
2713 psInfo
->ppshheader
.u
.pszIcon
,
2718 hIcon
= psInfo
->ppshheader
.u
.hIcon
;
2720 SendMessageW(hwnd
, WM_SETICON
, 0, (LPARAM
)hIcon
);
2723 if (psInfo
->ppshheader
.dwFlags
& PSH_USEHICON
)
2724 SendMessageW(hwnd
, WM_SETICON
, 0, (LPARAM
)psInfo
->ppshheader
.u
.hIcon
);
2726 psInfo
->strPropertiesFor
= strCaption
;
2728 GetWindowTextW(hwnd
, psInfo
->strPropertiesFor
, MAX_CAPTION_LENGTH
);
2730 PROPSHEET_CreateTabControl(hwnd
, psInfo
);
2732 if (psInfo
->ppshheader
.dwFlags
& INTRNL_ANY_WIZARD
)
2734 if (PROPSHEET_IsTooSmallWizard(hwnd
, psInfo
))
2736 PROPSHEET_AdjustSizeWizard(hwnd
, psInfo
);
2737 PROPSHEET_AdjustButtonsWizard(hwnd
, psInfo
);
2742 if (PROPSHEET_SizeMismatch(hwnd
, psInfo
))
2744 PROPSHEET_AdjustSize(hwnd
, psInfo
);
2745 PROPSHEET_AdjustButtons(hwnd
, psInfo
);
2749 if (psInfo
->useCallback
)
2750 (*(psInfo
->ppshheader
.pfnCallback
))(hwnd
,
2751 PSCB_INITIALIZED
, (LPARAM
)0);
2753 idx
= psInfo
->active_page
;
2754 ppshpage
= (LPCPROPSHEETPAGEW
)psInfo
->proppage
[idx
].hpage
;
2755 psInfo
->active_page
= -1;
2757 PROPSHEET_SetCurSel(hwnd
, idx
, 1, psInfo
->proppage
[idx
].hpage
);
2759 /* doing TCM_SETCURSEL seems to be needed even in case of PSH_WIZARD,
2760 * as some programs call TCM_GETCURSEL to get the current selection
2761 * from which to switch to the next page */
2762 SendMessageW(hwndTabCtrl
, TCM_SETCURSEL
, psInfo
->active_page
, 0);
2764 if (!HIWORD(psInfo
->ppshheader
.pszCaption
) &&
2765 psInfo
->ppshheader
.hInstance
)
2769 if (LoadStringW(psInfo
->ppshheader
.hInstance
,
2770 (UINT
)psInfo
->ppshheader
.pszCaption
, szText
, 255))
2771 PROPSHEET_SetTitleW(hwnd
, psInfo
->ppshheader
.dwFlags
, szText
);
2775 PROPSHEET_SetTitleW(hwnd
, psInfo
->ppshheader
.dwFlags
,
2776 psInfo
->ppshheader
.pszCaption
);
2783 PROPSHEET_CleanUp(hwnd
);
2787 PROPSHEET_Cancel(hwnd
, 1);
2791 return PROPSHEET_DoCommand(hwnd
, LOWORD(wParam
));
2795 NMHDR
* pnmh
= (LPNMHDR
) lParam
;
2797 if (pnmh
->code
== TCN_SELCHANGE
)
2799 int index
= SendMessageW(pnmh
->hwndFrom
, TCM_GETCURSEL
, 0, 0);
2800 PROPSHEET_SetCurSel(hwnd
, index
, 1, 0);
2803 if(pnmh
->code
== TCN_SELCHANGING
)
2805 BOOL bRet
= PROPSHEET_CanSetCurSel(hwnd
);
2806 SetWindowLongW(hwnd
, DWL_MSGRESULT
, !bRet
);
2813 case PSM_GETCURRENTPAGEHWND
:
2815 PropSheetInfo
* psInfo
= (PropSheetInfo
*) GetPropW(hwnd
,
2819 if (psInfo
->activeValid
&& psInfo
->active_page
!= -1)
2820 hwndPage
= psInfo
->proppage
[psInfo
->active_page
].hwndPage
;
2822 SetWindowLongW(hwnd
, DWL_MSGRESULT
, (LONG
)hwndPage
);
2828 PROPSHEET_Changed(hwnd
, (HWND
)wParam
);
2832 PROPSHEET_UnChanged(hwnd
, (HWND
)wParam
);
2835 case PSM_GETTABCONTROL
:
2837 HWND hwndTabCtrl
= GetDlgItem(hwnd
, IDC_TABCONTROL
);
2839 SetWindowLongW(hwnd
, DWL_MSGRESULT
, (LONG
)hwndTabCtrl
);
2848 msgResult
= PROPSHEET_CanSetCurSel(hwnd
);
2849 if(msgResult
!= FALSE
)
2851 msgResult
= PROPSHEET_SetCurSel(hwnd
,
2854 (HPROPSHEETPAGE
)lParam
);
2857 SetWindowLongW(hwnd
, DWL_MSGRESULT
, msgResult
);
2862 case PSM_CANCELTOCLOSE
:
2864 WCHAR buf
[MAX_BUTTONTEXT_LENGTH
];
2865 HWND hwndOK
= GetDlgItem(hwnd
, IDOK
);
2866 HWND hwndCancel
= GetDlgItem(hwnd
, IDCANCEL
);
2868 EnableWindow(hwndCancel
, FALSE
);
2869 if (LoadStringW(COMCTL32_hModule
, IDS_CLOSE
, buf
, sizeof(buf
)))
2870 SetWindowTextW(hwndOK
, buf
);
2875 case PSM_RESTARTWINDOWS
:
2877 PropSheetInfo
* psInfo
= (PropSheetInfo
*) GetPropW(hwnd
,
2880 psInfo
->restartWindows
= TRUE
;
2884 case PSM_REBOOTSYSTEM
:
2886 PropSheetInfo
* psInfo
= (PropSheetInfo
*) GetPropW(hwnd
,
2889 psInfo
->rebootSystem
= TRUE
;
2894 PROPSHEET_SetTitleA(hwnd
, (DWORD
) wParam
, (LPCSTR
) lParam
);
2898 PROPSHEET_SetTitleW(hwnd
, (DWORD
) wParam
, (LPCWSTR
) lParam
);
2903 BOOL msgResult
= PROPSHEET_Apply(hwnd
, 0);
2905 SetWindowLongW(hwnd
, DWL_MSGRESULT
, msgResult
);
2910 case PSM_QUERYSIBLINGS
:
2912 LRESULT msgResult
= PROPSHEET_QuerySiblings(hwnd
, wParam
, lParam
);
2914 SetWindowLongW(hwnd
, DWL_MSGRESULT
, msgResult
);
2922 * Note: MSVC++ 6.0 documentation says that PSM_ADDPAGE does not have
2923 * a return value. This is not true. PSM_ADDPAGE returns TRUE
2924 * on success or FALSE otherwise, as specified on MSDN Online.
2925 * Also see the MFC code for
2926 * CPropertySheet::AddPage(CPropertyPage* pPage).
2929 BOOL msgResult
= PROPSHEET_AddPage(hwnd
, (HPROPSHEETPAGE
)lParam
);
2931 SetWindowLongW(hwnd
, DWL_MSGRESULT
, msgResult
);
2936 case PSM_REMOVEPAGE
:
2937 PROPSHEET_RemovePage(hwnd
, (int)wParam
, (HPROPSHEETPAGE
)lParam
);
2940 case PSM_ISDIALOGMESSAGE
:
2942 BOOL msgResult
= PROPSHEET_IsDialogMessage(hwnd
, (LPMSG
)lParam
);
2943 SetWindowLongA(hwnd
, DWL_MSGRESULT
, msgResult
);
2947 case PSM_PRESSBUTTON
:
2948 PROPSHEET_PressButton(hwnd
, (int)wParam
);
2951 case PSM_SETFINISHTEXTA
:
2952 PROPSHEET_SetFinishTextA(hwnd
, (LPCSTR
) lParam
);
2955 case PSM_SETWIZBUTTONS
:
2956 PROPSHEET_SetWizButtons(hwnd
, (DWORD
)lParam
);
2959 case PSM_SETCURSELID
:
2960 PROPSHEET_SetCurSelId(hwnd
, (int)lParam
);
2963 case PSM_SETFINISHTEXTW
:
2964 PROPSHEET_SetFinishTextW(hwnd
, (LPCWSTR
) lParam
);