4 * Copyright 1998 Francis Beaudet
5 * Copyright 1999 Thuy Nguyen
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 * - Unicode property sheets
28 #define NONAMELESSUNION
29 #define NONAMELESSSTRUCT
36 #include "wine/debug.h"
37 #include "wine/unicode.h"
39 /******************************************************************************
63 } MyDLGITEMTEMPLATEEX
;
66 typedef struct tagPropPageInfo
68 HPROPSHEETPAGE hpage
; /* to keep track of pages not passed to PropertySheet */
77 typedef struct tagPropSheetInfo
80 PROPSHEETHEADERW ppshheader
;
82 LPWSTR strPropertiesFor
;
92 PropPageInfo
* proppage
;
97 HIMAGELIST hImageList
;
106 /******************************************************************************
107 * Defines and global variables
110 const WCHAR PropSheetInfoStr
[] =
111 {'P','r','o','p','e','r','t','y','S','h','e','e','t','I','n','f','o',0 };
113 #define PSP_INTERNAL_UNICODE 0x80000000
115 #define MAX_CAPTION_LENGTH 255
116 #define MAX_TABTEXT_LENGTH 255
117 #define MAX_BUTTONTEXT_LENGTH 64
119 #define INTRNL_ANY_WIZARD (PSH_WIZARD | PSH_WIZARD97_OLD | PSH_WIZARD97_NEW | PSH_WIZARD_LITE)
121 /******************************************************************************
124 static int PROPSHEET_CreateDialog(PropSheetInfo
* psInfo
);
125 static BOOL
PROPSHEET_SizeMismatch(HWND hwndDlg
, PropSheetInfo
* psInfo
);
126 static BOOL
PROPSHEET_AdjustSize(HWND hwndDlg
, PropSheetInfo
* psInfo
);
127 static BOOL
PROPSHEET_AdjustButtons(HWND hwndParent
, PropSheetInfo
* psInfo
);
128 static BOOL
PROPSHEET_CollectSheetInfoA(LPCPROPSHEETHEADERA lppsh
,
129 PropSheetInfo
* psInfo
);
130 static BOOL
PROPSHEET_CollectSheetInfoW(LPCPROPSHEETHEADERW lppsh
,
131 PropSheetInfo
* psInfo
);
132 static BOOL
PROPSHEET_CollectPageInfo(LPCPROPSHEETPAGEW lppsp
,
133 PropSheetInfo
* psInfo
,
135 static BOOL
PROPSHEET_CreateTabControl(HWND hwndParent
,
136 PropSheetInfo
* psInfo
);
137 static BOOL
PROPSHEET_CreatePage(HWND hwndParent
, int index
,
138 const PropSheetInfo
* psInfo
,
139 LPCPROPSHEETPAGEW ppshpage
);
140 static BOOL
PROPSHEET_ShowPage(HWND hwndDlg
, int index
, PropSheetInfo
* psInfo
);
141 static PADDING_INFO
PROPSHEET_GetPaddingInfo(HWND hwndDlg
);
142 static BOOL
PROPSHEET_Back(HWND hwndDlg
);
143 static BOOL
PROPSHEET_Next(HWND hwndDlg
);
144 static BOOL
PROPSHEET_Finish(HWND hwndDlg
);
145 static BOOL
PROPSHEET_Apply(HWND hwndDlg
, LPARAM lParam
);
146 static void PROPSHEET_Cancel(HWND hwndDlg
, LPARAM lParam
);
147 static void PROPSHEET_Help(HWND hwndDlg
);
148 static void PROPSHEET_Changed(HWND hwndDlg
, HWND hwndDirtyPage
);
149 static void PROPSHEET_UnChanged(HWND hwndDlg
, HWND hwndCleanPage
);
150 static void PROPSHEET_PressButton(HWND hwndDlg
, int buttonID
);
151 static void PROPSHEET_SetFinishTextA(HWND hwndDlg
, LPCSTR lpszText
);
152 static void PROPSHEET_SetFinishTextW(HWND hwndDlg
, LPCWSTR lpszText
);
153 static void PROPSHEET_SetTitleA(HWND hwndDlg
, DWORD dwStyle
, LPCSTR lpszText
);
154 static void PROPSHEET_SetTitleW(HWND hwndDlg
, DWORD dwStyle
, LPCWSTR lpszText
);
155 static BOOL
PROPSHEET_CanSetCurSel(HWND hwndDlg
);
156 static BOOL
PROPSHEET_SetCurSel(HWND hwndDlg
,
159 HPROPSHEETPAGE hpage
);
160 static void PROPSHEET_SetCurSelId(HWND hwndDlg
, int id
);
161 static LRESULT
PROPSHEET_QuerySiblings(HWND hwndDlg
,
162 WPARAM wParam
, LPARAM lParam
);
163 static BOOL
PROPSHEET_AddPage(HWND hwndDlg
,
164 HPROPSHEETPAGE hpage
);
166 static BOOL
PROPSHEET_RemovePage(HWND hwndDlg
,
168 HPROPSHEETPAGE hpage
);
169 static void PROPSHEET_CleanUp();
170 static int PROPSHEET_GetPageIndex(HPROPSHEETPAGE hpage
, PropSheetInfo
* psInfo
);
171 static void PROPSHEET_SetWizButtons(HWND hwndDlg
, DWORD dwFlags
);
172 static PADDING_INFO
PROPSHEET_GetPaddingInfoWizard(HWND hwndDlg
, const PropSheetInfo
* psInfo
);
173 static BOOL
PROPSHEET_IsDialogMessage(HWND hwnd
, LPMSG lpMsg
);
174 static BOOL
PROPSHEET_DoCommand(HWND hwnd
, WORD wID
);
177 PROPSHEET_DialogProc(HWND hwnd
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
);
179 WINE_DEFAULT_DEBUG_CHANNEL(propsheet
);
181 #define add_flag(a) if (dwFlags & a) {strcat(string, #a );strcat(string," ");}
182 /******************************************************************************
183 * PROPSHEET_UnImplementedFlags
185 * Document use of flags we don't implement yet.
187 static VOID
PROPSHEET_UnImplementedFlags(DWORD dwFlags
)
194 * unhandled header flags:
195 * PSH_DEFAULT 0x00000000
196 * PSH_WIZARDHASFINISH 0x00000010
197 * PSH_RTLREADING 0x00000800
198 * PSH_WIZARDCONTEXTHELP 0x00001000
199 * PSH_WIZARD97 0x00002000 (pre IE 5)
200 * PSH_WATERMARK 0x00008000
201 * PSH_USEHBMWATERMARK 0x00010000
202 * PSH_USEHPLWATERMARK 0x00020000
203 * PSH_STRETCHWATERMARK 0x00040000
204 * PSH_HEADER 0x00080000
205 * PSH_USEHBMHEADER 0x00100000
206 * PSH_USEPAGELANG 0x00200000
207 * PSH_WIZARD_LITE 0x00400000 also not in .h
208 * PSH_WIZARD97 0x01000000 (IE 5 and above)
209 * PSH_NOCONTEXTHELP 0x02000000 also not in .h
212 add_flag(PSH_WIZARDHASFINISH
);
213 add_flag(PSH_RTLREADING
);
214 add_flag(PSH_WIZARDCONTEXTHELP
);
215 add_flag(PSH_WIZARD97_OLD
);
216 add_flag(PSH_WATERMARK
);
217 add_flag(PSH_USEHBMWATERMARK
);
218 add_flag(PSH_USEHPLWATERMARK
);
219 add_flag(PSH_STRETCHWATERMARK
);
220 add_flag(PSH_HEADER
);
221 add_flag(PSH_USEHBMHEADER
);
222 add_flag(PSH_USEPAGELANG
);
223 add_flag(PSH_WIZARD_LITE
);
224 add_flag(PSH_WIZARD97_NEW
);
225 add_flag(PSH_NOCONTEXTHELP
);
226 if (string
[0] != '\0')
227 FIXME("%s\n", string
);
231 /******************************************************************************
232 * PROPSHEET_GetPageRect
234 * Retrieve rect from tab control and map into the dialog for SetWindowPos
236 static void PROPSHEET_GetPageRect(const PropSheetInfo
* psInfo
, HWND hwndDlg
, RECT
*rc
)
238 HWND hwndTabCtrl
= GetDlgItem(hwndDlg
, IDC_TABCONTROL
);
240 GetClientRect(hwndTabCtrl
, rc
);
241 SendMessageW(hwndTabCtrl
, TCM_ADJUSTRECT
, FALSE
, (LPARAM
)rc
);
242 MapWindowPoints(hwndTabCtrl
, hwndDlg
, (LPPOINT
)rc
, 2);
245 /******************************************************************************
246 * PROPSHEET_FindPageByResId
248 * Find page index corresponding to page resource id.
250 INT
PROPSHEET_FindPageByResId(PropSheetInfo
* psInfo
, LRESULT resId
)
254 for (i
= 0; i
< psInfo
->nPages
; i
++)
256 LPCPROPSHEETPAGEA lppsp
= (LPCPROPSHEETPAGEA
)psInfo
->proppage
[i
].hpage
;
258 /* Fixme: if resource ID is a string shall we use strcmp ??? */
259 if (lppsp
->u
.pszTemplate
== (LPVOID
)resId
)
266 /******************************************************************************
269 * Convert ASCII to Unicode since all data is saved as Unicode.
271 static void PROPSHEET_AtoW(LPCWSTR
*tostr
, LPCSTR frstr
)
275 TRACE("<%s>\n", frstr
);
276 len
= MultiByteToWideChar(CP_ACP
, 0, frstr
, -1, 0, 0);
277 *tostr
= (LPWSTR
)HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
278 MultiByteToWideChar(CP_ACP
, 0, frstr
, -1, (LPWSTR
)*tostr
, len
);
281 /******************************************************************************
282 * PROPSHEET_CollectSheetInfoA
284 * Collect relevant data.
286 static BOOL
PROPSHEET_CollectSheetInfoA(LPCPROPSHEETHEADERA lppsh
,
287 PropSheetInfo
* psInfo
)
289 DWORD dwSize
= min(lppsh
->dwSize
,sizeof(PROPSHEETHEADERA
));
290 DWORD dwFlags
= lppsh
->dwFlags
;
292 psInfo
->hasHelp
= dwFlags
& PSH_HASHELP
;
293 psInfo
->hasApply
= !(dwFlags
& PSH_NOAPPLYNOW
);
294 psInfo
->useCallback
= (dwFlags
& PSH_USECALLBACK
)&& (lppsh
->pfnCallback
);
295 psInfo
->isModeless
= dwFlags
& PSH_MODELESS
;
297 memcpy(&psInfo
->ppshheader
,lppsh
,dwSize
);
298 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",
299 lppsh
->dwSize
, lppsh
->dwFlags
, lppsh
->hwndParent
, lppsh
->hInstance
,
300 debugstr_a(lppsh
->pszCaption
), lppsh
->nPages
, lppsh
->pfnCallback
);
302 PROPSHEET_UnImplementedFlags(lppsh
->dwFlags
);
304 if (HIWORD(lppsh
->pszCaption
))
306 int len
= strlen(lppsh
->pszCaption
);
307 psInfo
->ppshheader
.pszCaption
= HeapAlloc( GetProcessHeap(), 0, (len
+1)*sizeof (WCHAR
) );
308 MultiByteToWideChar(CP_ACP
, 0, lppsh
->pszCaption
, -1, (LPWSTR
) psInfo
->ppshheader
.pszCaption
, len
+1);
309 /* strcpy( (char *)psInfo->ppshheader.pszCaption, lppsh->pszCaption ); */
311 psInfo
->nPages
= lppsh
->nPages
;
313 if (dwFlags
& PSH_USEPSTARTPAGE
)
315 TRACE("PSH_USEPSTARTPAGE is on");
316 psInfo
->active_page
= 0;
319 psInfo
->active_page
= lppsh
->u2
.nStartPage
;
321 if (psInfo
->active_page
< 0 || psInfo
->active_page
>= psInfo
->nPages
)
322 psInfo
->active_page
= 0;
324 psInfo
->restartWindows
= FALSE
;
325 psInfo
->rebootSystem
= FALSE
;
326 psInfo
->hImageList
= 0;
327 psInfo
->activeValid
= FALSE
;
332 /******************************************************************************
333 * PROPSHEET_CollectSheetInfoW
335 * Collect relevant data.
337 static BOOL
PROPSHEET_CollectSheetInfoW(LPCPROPSHEETHEADERW lppsh
,
338 PropSheetInfo
* psInfo
)
340 DWORD dwSize
= min(lppsh
->dwSize
,sizeof(PROPSHEETHEADERW
));
341 DWORD dwFlags
= lppsh
->dwFlags
;
343 psInfo
->hasHelp
= dwFlags
& PSH_HASHELP
;
344 psInfo
->hasApply
= !(dwFlags
& PSH_NOAPPLYNOW
);
345 psInfo
->useCallback
= (dwFlags
& PSH_USECALLBACK
) && (lppsh
->pfnCallback
);
346 psInfo
->isModeless
= dwFlags
& PSH_MODELESS
;
348 memcpy(&psInfo
->ppshheader
,lppsh
,dwSize
);
349 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",
350 lppsh
->dwSize
, lppsh
->dwFlags
, lppsh
->hwndParent
, lppsh
->hInstance
, debugstr_w(lppsh
->pszCaption
), lppsh
->nPages
, lppsh
->pfnCallback
);
352 PROPSHEET_UnImplementedFlags(lppsh
->dwFlags
);
354 if (HIWORD(lppsh
->pszCaption
))
356 int len
= strlenW(lppsh
->pszCaption
);
357 psInfo
->ppshheader
.pszCaption
= HeapAlloc( GetProcessHeap(), 0, (len
+1)*sizeof(WCHAR
) );
358 strcpyW( (WCHAR
*)psInfo
->ppshheader
.pszCaption
, lppsh
->pszCaption
);
360 psInfo
->nPages
= lppsh
->nPages
;
362 if (dwFlags
& PSH_USEPSTARTPAGE
)
364 TRACE("PSH_USEPSTARTPAGE is on");
365 psInfo
->active_page
= 0;
368 psInfo
->active_page
= lppsh
->u2
.nStartPage
;
370 if (psInfo
->active_page
< 0 || psInfo
->active_page
>= psInfo
->nPages
)
371 psInfo
->active_page
= 0;
373 psInfo
->restartWindows
= FALSE
;
374 psInfo
->rebootSystem
= FALSE
;
375 psInfo
->hImageList
= 0;
376 psInfo
->activeValid
= FALSE
;
381 /******************************************************************************
382 * PROPSHEET_CollectPageInfo
384 * Collect property sheet data.
385 * With code taken from DIALOG_ParseTemplate32.
387 BOOL
PROPSHEET_CollectPageInfo(LPCPROPSHEETPAGEW lppsp
,
388 PropSheetInfo
* psInfo
,
391 DLGTEMPLATE
* pTemplate
;
397 psInfo
->proppage
[index
].hpage
= (HPROPSHEETPAGE
)lppsp
;
398 psInfo
->proppage
[index
].hwndPage
= 0;
399 psInfo
->proppage
[index
].isDirty
= FALSE
;
402 * Process property page flags.
404 dwFlags
= lppsp
->dwFlags
;
405 psInfo
->proppage
[index
].useCallback
= (dwFlags
& PSP_USECALLBACK
) && (lppsp
->pfnCallback
);
406 psInfo
->proppage
[index
].hasHelp
= dwFlags
& PSP_HASHELP
;
407 psInfo
->proppage
[index
].hasIcon
= dwFlags
& (PSP_USEHICON
| PSP_USEICONID
);
409 /* as soon as we have a page with the help flag, set the sheet flag on */
410 if (psInfo
->proppage
[index
].hasHelp
)
411 psInfo
->hasHelp
= TRUE
;
414 * Process page template.
416 if (dwFlags
& PSP_DLGINDIRECT
)
417 pTemplate
= (DLGTEMPLATE
*)lppsp
->u
.pResource
;
418 else if(dwFlags
& PSP_INTERNAL_UNICODE
)
420 HRSRC hResource
= FindResourceW(lppsp
->hInstance
,
421 lppsp
->u
.pszTemplate
,
423 HGLOBAL hTemplate
= LoadResource(lppsp
->hInstance
,
425 pTemplate
= (LPDLGTEMPLATEW
)LockResource(hTemplate
);
429 HRSRC hResource
= FindResourceA(lppsp
->hInstance
,
430 (LPSTR
)lppsp
->u
.pszTemplate
,
432 HGLOBAL hTemplate
= LoadResource(lppsp
->hInstance
,
434 pTemplate
= (LPDLGTEMPLATEA
)LockResource(hTemplate
);
438 * Extract the size of the page and the caption.
443 p
= (const WORD
*)pTemplate
;
445 if (((MyDLGTEMPLATEEX
*)pTemplate
)->signature
== 0xFFFF)
447 /* DLGTEMPLATEEX (not defined in any std. header file) */
451 p
+= 2; /* help ID */
452 p
+= 2; /* ext style */
460 p
+= 2; /* ext style */
466 width
= (WORD
)*p
; p
++;
467 height
= (WORD
)*p
; p
++;
469 /* remember the largest width and height */
470 if (width
> psInfo
->width
)
471 psInfo
->width
= width
;
473 if (height
> psInfo
->height
)
474 psInfo
->height
= height
;
486 p
+= lstrlenW( (LPCWSTR
)p
) + 1;
500 p
+= lstrlenW( (LPCWSTR
)p
) + 1;
504 /* Extract the caption */
505 psInfo
->proppage
[index
].pszText
= (LPCWSTR
)p
;
506 TRACE("Tab %d %s\n",index
,debugstr_w((LPCWSTR
)p
));
507 p
+= lstrlenW((LPCWSTR
)p
) + 1;
509 if (dwFlags
& PSP_USETITLE
)
513 static WCHAR pszNull
[] = { '(','n','u','l','l',')',0 };
516 if ( !HIWORD( lppsp
->pszTitle
) )
518 if (!LoadStringW( lppsp
->hInstance
, (UINT
)lppsp
->pszTitle
,szTitle
,sizeof(szTitle
) ))
521 FIXME("Could not load resource #%04x?\n",LOWORD(lppsp
->pszTitle
));
527 pTitle
= lppsp
->pszTitle
;
529 len
= strlenW(pTitle
);
530 psInfo
->proppage
[index
].pszText
= COMCTL32_Alloc( (len
+1)*sizeof (WCHAR
) );
531 strcpyW( (LPWSTR
)psInfo
->proppage
[index
].pszText
,pTitle
);
535 * Build the image list for icons
537 if ((dwFlags
& PSP_USEHICON
) || (dwFlags
& PSP_USEICONID
))
540 int icon_cx
= GetSystemMetrics(SM_CXSMICON
);
541 int icon_cy
= GetSystemMetrics(SM_CYSMICON
);
543 if (dwFlags
& PSP_USEICONID
)
544 hIcon
= LoadImageW(lppsp
->hInstance
, lppsp
->u2
.pszIcon
, IMAGE_ICON
,
545 icon_cx
, icon_cy
, LR_DEFAULTCOLOR
);
547 hIcon
= lppsp
->u2
.hIcon
;
551 if (psInfo
->hImageList
== 0 )
552 psInfo
->hImageList
= ImageList_Create(icon_cx
, icon_cy
, ILC_COLOR
, 1, 1);
554 ImageList_AddIcon(psInfo
->hImageList
, hIcon
);
562 /******************************************************************************
563 * PROPSHEET_CreateDialog
565 * Creates the actual property sheet.
567 int PROPSHEET_CreateDialog(PropSheetInfo
* psInfo
)
574 WORD resID
= IDD_PROPSHEET
;
577 if (psInfo
->ppshheader
.dwFlags
& INTRNL_ANY_WIZARD
)
580 if( psInfo
->unicode
)
582 if(!(hRes
= FindResourceW(COMCTL32_hModule
,
583 MAKEINTRESOURCEW(resID
),
589 if(!(hRes
= FindResourceA(COMCTL32_hModule
,
590 MAKEINTRESOURCEA(resID
),
595 if(!(template = (LPVOID
)LoadResource(COMCTL32_hModule
, hRes
)))
599 * Make a copy of the dialog template.
601 resSize
= SizeofResource(COMCTL32_hModule
, hRes
);
603 temp
= COMCTL32_Alloc(resSize
);
608 memcpy(temp
, template, resSize
);
610 if (psInfo
->useCallback
)
611 (*(psInfo
->ppshheader
.pfnCallback
))(0, PSCB_PRECREATE
, (LPARAM
)temp
);
613 if( psInfo
->unicode
)
615 if (!(psInfo
->ppshheader
.dwFlags
& PSH_MODELESS
))
616 ret
= DialogBoxIndirectParamW(psInfo
->ppshheader
.hInstance
,
617 (LPDLGTEMPLATEW
) temp
,
618 psInfo
->ppshheader
.hwndParent
,
619 PROPSHEET_DialogProc
,
623 ret
= (int)CreateDialogIndirectParamW(psInfo
->ppshheader
.hInstance
,
624 (LPDLGTEMPLATEW
) temp
,
625 psInfo
->ppshheader
.hwndParent
,
626 PROPSHEET_DialogProc
,
628 if ( !ret
) ret
= -1;
633 if (!(psInfo
->ppshheader
.dwFlags
& PSH_MODELESS
))
634 ret
= DialogBoxIndirectParamA(psInfo
->ppshheader
.hInstance
,
635 (LPDLGTEMPLATEA
) temp
,
636 psInfo
->ppshheader
.hwndParent
,
637 PROPSHEET_DialogProc
,
641 ret
= (int)CreateDialogIndirectParamA(psInfo
->ppshheader
.hInstance
,
642 (LPDLGTEMPLATEA
) temp
,
643 psInfo
->ppshheader
.hwndParent
,
644 PROPSHEET_DialogProc
,
646 if ( !ret
) ret
= -1;
655 /******************************************************************************
656 * PROPSHEET_SizeMismatch
658 * Verify that the tab control and the "largest" property sheet page dlg. template
661 static BOOL
PROPSHEET_SizeMismatch(HWND hwndDlg
, PropSheetInfo
* psInfo
)
663 HWND hwndTabCtrl
= GetDlgItem(hwndDlg
, IDC_TABCONTROL
);
664 RECT rcOrigTab
, rcPage
;
669 GetClientRect(hwndTabCtrl
, &rcOrigTab
);
670 TRACE("orig tab %ld %ld %ld %ld\n", rcOrigTab
.left
, rcOrigTab
.top
,
671 rcOrigTab
.right
, rcOrigTab
.bottom
);
676 rcPage
.left
= psInfo
->x
;
677 rcPage
.top
= psInfo
->y
;
678 rcPage
.right
= psInfo
->width
;
679 rcPage
.bottom
= psInfo
->height
;
681 MapDialogRect(hwndDlg
, &rcPage
);
682 TRACE("biggest page %ld %ld %ld %ld\n", rcPage
.left
, rcPage
.top
,
683 rcPage
.right
, rcPage
.bottom
);
685 if ( (rcPage
.right
- rcPage
.left
) != (rcOrigTab
.right
- rcOrigTab
.left
) )
687 if ( (rcPage
.bottom
- rcPage
.top
) != (rcOrigTab
.bottom
- rcOrigTab
.top
) )
693 /******************************************************************************
694 * PROPSHEET_IsTooSmallWizard
696 * Verify that the default property sheet is big enough.
698 static BOOL
PROPSHEET_IsTooSmallWizard(HWND hwndDlg
, PropSheetInfo
* psInfo
)
700 RECT rcSheetRect
, rcPage
, rcLine
, rcSheetClient
;
701 HWND hwndLine
= GetDlgItem(hwndDlg
, IDC_SUNKEN_LINE
);
702 PADDING_INFO padding
= PROPSHEET_GetPaddingInfoWizard(hwndDlg
, psInfo
);
704 GetClientRect(hwndDlg
, &rcSheetClient
);
705 GetWindowRect(hwndDlg
, &rcSheetRect
);
706 GetWindowRect(hwndLine
, &rcLine
);
708 /* Remove the space below the sunken line */
709 rcSheetClient
.bottom
-= (rcSheetRect
.bottom
- rcLine
.top
);
711 /* Remove the buffer zone all around the edge */
712 rcSheetClient
.bottom
-= (padding
.y
* 2);
713 rcSheetClient
.right
-= (padding
.x
* 2);
718 rcPage
.left
= psInfo
->x
;
719 rcPage
.top
= psInfo
->y
;
720 rcPage
.right
= psInfo
->width
;
721 rcPage
.bottom
= psInfo
->height
;
723 MapDialogRect(hwndDlg
, &rcPage
);
724 TRACE("biggest page %ld %ld %ld %ld\n", rcPage
.left
, rcPage
.top
,
725 rcPage
.right
, rcPage
.bottom
);
727 if (rcPage
.right
> rcSheetClient
.right
)
730 if (rcPage
.bottom
> rcSheetClient
.bottom
)
736 /******************************************************************************
737 * PROPSHEET_AdjustSize
739 * Resizes the property sheet and the tab control to fit the largest page.
741 static BOOL
PROPSHEET_AdjustSize(HWND hwndDlg
, PropSheetInfo
* psInfo
)
743 HWND hwndTabCtrl
= GetDlgItem(hwndDlg
, IDC_TABCONTROL
);
744 HWND hwndButton
= GetDlgItem(hwndDlg
, IDOK
);
746 int tabOffsetX
, tabOffsetY
, buttonHeight
;
747 PADDING_INFO padding
= PROPSHEET_GetPaddingInfo(hwndDlg
);
750 /* Get the height of buttons */
751 GetClientRect(hwndButton
, &rc
);
752 buttonHeight
= rc
.bottom
;
759 rc
.right
= psInfo
->width
;
760 rc
.bottom
= psInfo
->height
;
762 MapDialogRect(hwndDlg
, &rc
);
764 /* retrieve the dialog units */
765 units
.left
= units
.right
= 4;
766 units
.top
= units
.bottom
= 8;
767 MapDialogRect(hwndDlg
, &units
);
770 * Resize the tab control.
772 GetClientRect(hwndTabCtrl
,&tabRect
);
774 SendMessageW(hwndTabCtrl
, TCM_ADJUSTRECT
, FALSE
, (LPARAM
)&tabRect
);
776 if ((rc
.bottom
- rc
.top
) < (tabRect
.bottom
- tabRect
.top
))
778 rc
.bottom
= rc
.top
+ tabRect
.bottom
- tabRect
.top
;
779 psInfo
->height
= MulDiv((rc
.bottom
- rc
.top
),8,units
.top
);
782 if ((rc
.right
- rc
.left
) < (tabRect
.right
- tabRect
.left
))
784 rc
.right
= rc
.left
+ tabRect
.right
- tabRect
.left
;
785 psInfo
->width
= MulDiv((rc
.right
- rc
.left
),4,units
.left
);
788 SendMessageW(hwndTabCtrl
, TCM_ADJUSTRECT
, TRUE
, (LPARAM
)&rc
);
790 tabOffsetX
= -(rc
.left
);
791 tabOffsetY
= -(rc
.top
);
795 TRACE("setting tab %08lx, rc (0,0)-(%ld,%ld)\n",
796 (DWORD
)hwndTabCtrl
, rc
.right
, rc
.bottom
);
797 SetWindowPos(hwndTabCtrl
, 0, 0, 0, rc
.right
, rc
.bottom
,
798 SWP_NOMOVE
| SWP_NOZORDER
| SWP_NOACTIVATE
);
800 GetClientRect(hwndTabCtrl
, &rc
);
802 TRACE("tab client rc %ld %ld %ld %ld\n",
803 rc
.left
, rc
.top
, rc
.right
, rc
.bottom
);
805 rc
.right
+= ((padding
.x
* 2) + tabOffsetX
);
806 rc
.bottom
+= (buttonHeight
+ (3 * padding
.y
) + tabOffsetY
);
809 * Resize the property sheet.
811 TRACE("setting dialog %08lx, rc (0,0)-(%ld,%ld)\n",
812 (DWORD
)hwndDlg
, rc
.right
, rc
.bottom
);
813 SetWindowPos(hwndDlg
, 0, 0, 0, rc
.right
, rc
.bottom
,
814 SWP_NOMOVE
| SWP_NOZORDER
| SWP_NOACTIVATE
);
818 /******************************************************************************
819 * PROPSHEET_AdjustSizeWizard
821 * Resizes the property sheet to fit the largest page.
823 static BOOL
PROPSHEET_AdjustSizeWizard(HWND hwndDlg
, PropSheetInfo
* psInfo
)
825 HWND hwndButton
= GetDlgItem(hwndDlg
, IDCANCEL
);
826 HWND hwndLine
= GetDlgItem(hwndDlg
, IDC_SUNKEN_LINE
);
827 HWND hwndTabCtrl
= GetDlgItem(hwndDlg
, IDC_TABCONTROL
);
829 int buttonHeight
, lineHeight
;
830 PADDING_INFO padding
= PROPSHEET_GetPaddingInfoWizard(hwndDlg
, psInfo
);
833 /* Get the height of buttons */
834 GetClientRect(hwndButton
, &rc
);
835 buttonHeight
= rc
.bottom
;
837 GetClientRect(hwndLine
, &rc
);
838 lineHeight
= rc
.bottom
;
840 /* retrieve the dialog units */
841 units
.left
= units
.right
= 4;
842 units
.top
= units
.bottom
= 8;
843 MapDialogRect(hwndDlg
, &units
);
850 rc
.right
= psInfo
->width
;
851 rc
.bottom
= psInfo
->height
;
853 MapDialogRect(hwndDlg
, &rc
);
855 GetClientRect(hwndTabCtrl
,&tabRect
);
857 if ((rc
.bottom
- rc
.top
) < (tabRect
.bottom
- tabRect
.top
))
859 rc
.bottom
= rc
.top
+ tabRect
.bottom
- tabRect
.top
;
860 psInfo
->height
= MulDiv((rc
.bottom
- rc
.top
), 8, units
.top
);
863 if ((rc
.right
- rc
.left
) < (tabRect
.right
- tabRect
.left
))
865 rc
.right
= rc
.left
+ tabRect
.right
- tabRect
.left
;
866 psInfo
->width
= MulDiv((rc
.right
- rc
.left
), 4, units
.left
);
869 TRACE("Biggest page %ld %ld %ld %ld\n", rc
.left
, rc
.top
, rc
.right
, rc
.bottom
);
870 TRACE(" constants padx=%d, pady=%d, butH=%d, lH=%d\n",
871 padding
.x
, padding
.y
, buttonHeight
, lineHeight
);
874 rc
.right
+= (padding
.x
* 2);
875 rc
.bottom
+= (buttonHeight
+ (5 * padding
.y
) + lineHeight
);
878 * Resize the property sheet.
880 TRACE("setting dialog %08lx, rc (0,0)-(%ld,%ld)\n",
881 (DWORD
)hwndDlg
, rc
.right
, rc
.bottom
);
882 SetWindowPos(hwndDlg
, 0, 0, 0, rc
.right
, rc
.bottom
,
883 SWP_NOMOVE
| SWP_NOZORDER
| SWP_NOACTIVATE
);
887 /******************************************************************************
888 * PROPSHEET_AdjustButtons
890 * Adjusts the buttons' positions.
892 static BOOL
PROPSHEET_AdjustButtons(HWND hwndParent
, PropSheetInfo
* psInfo
)
894 HWND hwndButton
= GetDlgItem(hwndParent
, IDOK
);
898 int buttonWidth
, buttonHeight
;
899 PADDING_INFO padding
= PROPSHEET_GetPaddingInfo(hwndParent
);
901 if (psInfo
->hasApply
)
908 * Obtain the size of the buttons.
910 GetClientRect(hwndButton
, &rcSheet
);
911 buttonWidth
= rcSheet
.right
;
912 buttonHeight
= rcSheet
.bottom
;
915 * Get the size of the property sheet.
917 GetClientRect(hwndParent
, &rcSheet
);
920 * All buttons will be at this y coordinate.
922 y
= rcSheet
.bottom
- (padding
.y
+ buttonHeight
);
925 * Position OK button.
927 hwndButton
= GetDlgItem(hwndParent
, IDOK
);
929 x
= rcSheet
.right
- ((padding
.x
+ buttonWidth
) * num_buttons
);
931 SetWindowPos(hwndButton
, 0, x
, y
, 0, 0,
932 SWP_NOSIZE
| SWP_NOZORDER
| SWP_NOACTIVATE
);
935 * Position Cancel button.
937 hwndButton
= GetDlgItem(hwndParent
, IDCANCEL
);
939 x
= rcSheet
.right
- ((padding
.x
+ buttonWidth
) * (num_buttons
- 1));
941 SetWindowPos(hwndButton
, 0, x
, y
, 0, 0,
942 SWP_NOSIZE
| SWP_NOZORDER
| SWP_NOACTIVATE
);
945 * Position Apply button.
947 hwndButton
= GetDlgItem(hwndParent
, IDC_APPLY_BUTTON
);
949 if (psInfo
->hasApply
)
952 x
= rcSheet
.right
- ((padding
.x
+ buttonWidth
) * 2);
954 x
= rcSheet
.right
- (padding
.x
+ buttonWidth
);
956 SetWindowPos(hwndButton
, 0, x
, y
, 0, 0,
957 SWP_NOSIZE
| SWP_NOZORDER
| SWP_NOACTIVATE
);
959 EnableWindow(hwndButton
, FALSE
);
962 ShowWindow(hwndButton
, SW_HIDE
);
965 * Position Help button.
967 hwndButton
= GetDlgItem(hwndParent
, IDHELP
);
971 x
= rcSheet
.right
- (padding
.x
+ buttonWidth
);
973 SetWindowPos(hwndButton
, 0, x
, y
, 0, 0,
974 SWP_NOSIZE
| SWP_NOZORDER
| SWP_NOACTIVATE
);
977 ShowWindow(hwndButton
, SW_HIDE
);
982 /******************************************************************************
983 * PROPSHEET_AdjustButtonsWizard
985 * Adjusts the buttons' positions.
987 static BOOL
PROPSHEET_AdjustButtonsWizard(HWND hwndParent
,
988 PropSheetInfo
* psInfo
)
990 HWND hwndButton
= GetDlgItem(hwndParent
, IDCANCEL
);
991 HWND hwndLine
= GetDlgItem(hwndParent
, IDC_SUNKEN_LINE
);
995 int buttonWidth
, buttonHeight
, lineHeight
, lineWidth
;
996 PADDING_INFO padding
= PROPSHEET_GetPaddingInfoWizard(hwndParent
, psInfo
);
1002 * Obtain the size of the buttons.
1004 GetClientRect(hwndButton
, &rcSheet
);
1005 buttonWidth
= rcSheet
.right
;
1006 buttonHeight
= rcSheet
.bottom
;
1008 GetClientRect(hwndLine
, &rcSheet
);
1009 lineHeight
= rcSheet
.bottom
;
1012 * Get the size of the property sheet.
1014 GetClientRect(hwndParent
, &rcSheet
);
1017 * All buttons will be at this y coordinate.
1019 y
= rcSheet
.bottom
- (padding
.y
+ buttonHeight
);
1022 * Position the Next and the Finish buttons.
1024 hwndButton
= GetDlgItem(hwndParent
, IDC_NEXT_BUTTON
);
1026 x
= rcSheet
.right
- ((padding
.x
+ buttonWidth
) * (num_buttons
- 1));
1028 SetWindowPos(hwndButton
, 0, x
, y
, 0, 0,
1029 SWP_NOSIZE
| SWP_NOZORDER
| SWP_NOACTIVATE
);
1031 hwndButton
= GetDlgItem(hwndParent
, IDC_FINISH_BUTTON
);
1033 SetWindowPos(hwndButton
, 0, x
, y
, 0, 0,
1034 SWP_NOSIZE
| SWP_NOZORDER
| SWP_NOACTIVATE
);
1036 ShowWindow(hwndButton
, SW_HIDE
);
1039 * Position the Back button.
1041 hwndButton
= GetDlgItem(hwndParent
, IDC_BACK_BUTTON
);
1045 SetWindowPos(hwndButton
, 0, x
, y
, 0, 0,
1046 SWP_NOSIZE
| SWP_NOZORDER
| SWP_NOACTIVATE
);
1049 * Position the Cancel button.
1051 hwndButton
= GetDlgItem(hwndParent
, IDCANCEL
);
1053 x
= rcSheet
.right
- ((padding
.x
+ buttonWidth
) * (num_buttons
- 2));
1055 SetWindowPos(hwndButton
, 0, x
, y
, 0, 0,
1056 SWP_NOSIZE
| SWP_NOZORDER
| SWP_NOACTIVATE
);
1059 * Position Help button.
1061 hwndButton
= GetDlgItem(hwndParent
, IDHELP
);
1063 if (psInfo
->hasHelp
)
1065 x
= rcSheet
.right
- (padding
.x
+ buttonWidth
);
1067 SetWindowPos(hwndButton
, 0, x
, y
, 0, 0,
1068 SWP_NOSIZE
| SWP_NOZORDER
| SWP_NOACTIVATE
);
1071 ShowWindow(hwndButton
, SW_HIDE
);
1074 * Position and resize the sunken line.
1077 y
= rcSheet
.bottom
- ((padding
.y
* 2) + buttonHeight
+ lineHeight
);
1079 GetClientRect(hwndParent
, &rcSheet
);
1080 lineWidth
= rcSheet
.right
- (padding
.x
* 2);
1082 SetWindowPos(hwndLine
, 0, x
, y
, lineWidth
, 2,
1083 SWP_NOZORDER
| SWP_NOACTIVATE
);
1088 /******************************************************************************
1089 * PROPSHEET_GetPaddingInfo
1091 * Returns the layout information.
1093 static PADDING_INFO
PROPSHEET_GetPaddingInfo(HWND hwndDlg
)
1095 HWND hwndTab
= GetDlgItem(hwndDlg
, IDC_TABCONTROL
);
1098 PADDING_INFO padding
;
1100 GetWindowRect(hwndTab
, &rcTab
);
1105 ScreenToClient(hwndDlg
, &tl
);
1113 /******************************************************************************
1114 * PROPSHEET_GetPaddingInfoWizard
1116 * Returns the layout information.
1117 * Vertical spacing is the distance between the line and the buttons.
1118 * Do NOT use the Help button to gather padding information when it isn't mapped
1119 * (PSH_HASHELP), as app writers aren't forced to supply correct coordinates
1120 * for it in this case !
1121 * FIXME: I'm not sure about any other coordinate problems with these evil
1122 * buttons. Fix it in case additional problems appear or maybe calculate
1123 * a padding in a completely different way, as this is somewhat messy.
1125 static PADDING_INFO
PROPSHEET_GetPaddingInfoWizard(HWND hwndDlg
, const PropSheetInfo
*
1128 PADDING_INFO padding
;
1132 POINT ptButton
, ptLine
;
1135 if (psInfo
->hasHelp
)
1141 if (psInfo
->ppshheader
.dwFlags
& INTRNL_ANY_WIZARD
)
1143 idButton
= IDC_NEXT_BUTTON
;
1147 /* hopefully this is ok */
1148 idButton
= IDCANCEL
;
1152 hwndControl
= GetDlgItem(hwndDlg
, idButton
);
1153 GetWindowRect(hwndControl
, &rc
);
1155 ptButton
.x
= rc
.left
;
1156 ptButton
.y
= rc
.top
;
1158 ScreenToClient(hwndDlg
, &ptButton
);
1161 hwndControl
= GetDlgItem(hwndDlg
, IDC_SUNKEN_LINE
);
1162 GetWindowRect(hwndControl
, &rc
);
1165 ptLine
.y
= rc
.bottom
;
1167 ScreenToClient(hwndDlg
, &ptLine
);
1169 padding
.y
= ptButton
.y
- ptLine
.y
;
1172 ERR("padding negative ! Please report this !\n");
1174 /* this is most probably not correct, but the best we have now */
1175 padding
.x
= padding
.y
;
1179 /******************************************************************************
1180 * PROPSHEET_CreateTabControl
1182 * Insert the tabs in the tab control.
1184 static BOOL
PROPSHEET_CreateTabControl(HWND hwndParent
,
1185 PropSheetInfo
* psInfo
)
1187 HWND hwndTabCtrl
= GetDlgItem(hwndParent
, IDC_TABCONTROL
);
1193 item
.mask
= TCIF_TEXT
;
1194 item
.cchTextMax
= MAX_TABTEXT_LENGTH
;
1196 nTabs
= psInfo
->nPages
;
1199 * Set the image list for icons.
1201 if (psInfo
->hImageList
)
1203 SendMessageW(hwndTabCtrl
, TCM_SETIMAGELIST
, 0, (LPARAM
)psInfo
->hImageList
);
1206 for (i
= 0; i
< nTabs
; i
++)
1208 if ( psInfo
->proppage
[i
].hasIcon
)
1210 item
.mask
|= TCIF_IMAGE
;
1211 item
.iImage
= iImage
++;
1215 item
.mask
&= ~TCIF_IMAGE
;
1218 item
.pszText
= (LPWSTR
) psInfo
->proppage
[i
].pszText
;
1219 SendMessageW(hwndTabCtrl
, TCM_INSERTITEMW
, (WPARAM
)i
, (LPARAM
)&item
);
1225 * Get the size of an in-memory Template
1227 *( Based on the code of PROPSHEET_CollectPageInfo)
1228 * See also dialog.c/DIALOG_ParseTemplate32().
1231 static UINT
GetTemplateSize(DLGTEMPLATE
* pTemplate
)
1234 const WORD
* p
= (const WORD
*)pTemplate
;
1235 BOOL istemplateex
= (((MyDLGTEMPLATEEX
*)pTemplate
)->signature
== 0xFFFF);
1240 /* DLGTEMPLATEEX (not defined in any std. header file) */
1242 TRACE("is DLGTEMPLATEEX\n");
1244 p
++; /* signature */
1245 p
+= 2; /* help ID */
1246 p
+= 2; /* ext style */
1253 TRACE("is DLGTEMPLATE\n");
1255 p
+= 2; /* ext style */
1258 nrofitems
= (WORD
)*p
; p
++; /* nb items */
1274 TRACE("menu %s\n",debugstr_w((LPCWSTR
)p
));
1275 p
+= lstrlenW( (LPCWSTR
)p
) + 1;
1286 p
+= 2; /* 0xffff plus predefined window class ordinal value */
1289 TRACE("class %s\n",debugstr_w((LPCWSTR
)p
));
1290 p
+= lstrlenW( (LPCWSTR
)p
) + 1;
1295 TRACE("title %s\n",debugstr_w((LPCWSTR
)p
));
1296 p
+= lstrlenW((LPCWSTR
)p
) + 1;
1298 /* font, if DS_SETFONT set */
1299 if ((DS_SETFONT
& ((istemplateex
)? ((MyDLGTEMPLATEEX
*)pTemplate
)->style
:
1302 p
+=(istemplateex
)?3:1;
1303 TRACE("font %s\n",debugstr_w((LPCWSTR
)p
));
1304 p
+= lstrlenW( (LPCWSTR
)p
) + 1; /* the font name */
1307 /* now process the DLGITEMTEMPLATE(EX) structs (plus custom data)
1308 * that are following the DLGTEMPLATE(EX) data */
1309 TRACE("%d items\n",nrofitems
);
1310 while (nrofitems
> 0)
1312 p
= (WORD
*)(((DWORD
)p
+ 3) & ~3); /* DWORD align */
1315 p
+= (istemplateex
? sizeof(MyDLGITEMTEMPLATEEX
) : sizeof(DLGITEMTEMPLATE
))/sizeof(WORD
);
1324 TRACE("class ordinal 0x%08lx\n",*(DWORD
*)p
);
1328 TRACE("class %s\n",debugstr_w((LPCWSTR
)p
));
1329 p
+= lstrlenW( (LPCWSTR
)p
) + 1;
1333 /* check title text */
1340 TRACE("text ordinal 0x%08lx\n",*(DWORD
*)p
);
1344 TRACE("text %s\n",debugstr_w((LPCWSTR
)p
));
1345 p
+= lstrlenW( (LPCWSTR
)p
) + 1;
1348 p
+= *p
+ 1; /* Skip extra data */
1352 TRACE("%p %p size 0x%08x\n",p
, (WORD
*)pTemplate
,sizeof(WORD
)*(p
- (WORD
*)pTemplate
));
1353 return (p
- (WORD
*)pTemplate
)*sizeof(WORD
);
1357 /******************************************************************************
1358 * PROPSHEET_CreatePage
1362 static BOOL
PROPSHEET_CreatePage(HWND hwndParent
,
1364 const PropSheetInfo
* psInfo
,
1365 LPCPROPSHEETPAGEW ppshpage
)
1367 DLGTEMPLATE
* pTemplate
;
1370 PropPageInfo
* ppInfo
= psInfo
->proppage
;
1371 PADDING_INFO padding
;
1372 UINT pageWidth
,pageHeight
;
1376 TRACE("index %d\n", index
);
1378 if (ppshpage
== NULL
)
1383 if (ppshpage
->dwFlags
& PSP_DLGINDIRECT
)
1385 pTemplate
= (DLGTEMPLATE
*)ppshpage
->u
.pResource
;
1386 resSize
= GetTemplateSize(pTemplate
);
1388 else if(ppshpage
->dwFlags
& PSP_INTERNAL_UNICODE
)
1393 hResource
= FindResourceW(ppshpage
->hInstance
,
1394 ppshpage
->u
.pszTemplate
,
1399 resSize
= SizeofResource(ppshpage
->hInstance
, hResource
);
1401 hTemplate
= LoadResource(ppshpage
->hInstance
, hResource
);
1405 pTemplate
= (LPDLGTEMPLATEW
)LockResource(hTemplate
);
1407 * Make a copy of the dialog template to make it writable
1415 hResource
= FindResourceA(ppshpage
->hInstance
,
1416 (LPSTR
)ppshpage
->u
.pszTemplate
,
1421 resSize
= SizeofResource(ppshpage
->hInstance
, hResource
);
1423 hTemplate
= LoadResource(ppshpage
->hInstance
, hResource
);
1427 pTemplate
= (LPDLGTEMPLATEA
)LockResource(hTemplate
);
1429 * Make a copy of the dialog template to make it writable
1432 temp
= COMCTL32_Alloc(resSize
);
1436 TRACE("copying pTemplate %p into temp %p (%ld)\n", pTemplate
, temp
, resSize
);
1437 memcpy(temp
, pTemplate
, resSize
);
1440 if (((MyDLGTEMPLATEEX
*)pTemplate
)->signature
== 0xFFFF)
1442 ((MyDLGTEMPLATEEX
*)pTemplate
)->style
|= WS_CHILD
| DS_CONTROL
;
1443 ((MyDLGTEMPLATEEX
*)pTemplate
)->style
&= ~DS_MODALFRAME
;
1444 ((MyDLGTEMPLATEEX
*)pTemplate
)->style
&= ~WS_CAPTION
;
1445 ((MyDLGTEMPLATEEX
*)pTemplate
)->style
&= ~WS_SYSMENU
;
1446 ((MyDLGTEMPLATEEX
*)pTemplate
)->style
&= ~WS_POPUP
;
1447 ((MyDLGTEMPLATEEX
*)pTemplate
)->style
&= ~WS_DISABLED
;
1448 ((MyDLGTEMPLATEEX
*)pTemplate
)->style
&= ~WS_VISIBLE
;
1449 ((MyDLGTEMPLATEEX
*)pTemplate
)->style
&= ~WS_THICKFRAME
;
1453 pTemplate
->style
|= WS_CHILD
| DS_CONTROL
;
1454 pTemplate
->style
&= ~DS_MODALFRAME
;
1455 pTemplate
->style
&= ~WS_CAPTION
;
1456 pTemplate
->style
&= ~WS_SYSMENU
;
1457 pTemplate
->style
&= ~WS_POPUP
;
1458 pTemplate
->style
&= ~WS_DISABLED
;
1459 pTemplate
->style
&= ~WS_VISIBLE
;
1460 pTemplate
->style
&= ~WS_THICKFRAME
;
1463 if (psInfo
->proppage
[index
].useCallback
)
1464 (*(ppshpage
->pfnCallback
))(hwndParent
,
1466 (LPPROPSHEETPAGEW
)ppshpage
);
1468 if(ppshpage
->dwFlags
& PSP_INTERNAL_UNICODE
)
1469 hwndPage
= CreateDialogIndirectParamW(ppshpage
->hInstance
,
1472 ppshpage
->pfnDlgProc
,
1475 hwndPage
= CreateDialogIndirectParamA(ppshpage
->hInstance
,
1478 ppshpage
->pfnDlgProc
,
1480 /* Free a no more needed copy */
1482 COMCTL32_Free(temp
);
1484 ppInfo
[index
].hwndPage
= hwndPage
;
1486 if (psInfo
->ppshheader
.dwFlags
& INTRNL_ANY_WIZARD
) {
1487 /* FIXME: This code may no longer be correct.
1488 * It was not for the non-wizard path. (GLA 6/02)
1490 rc
.left
= psInfo
->x
;
1492 rc
.right
= psInfo
->width
;
1493 rc
.bottom
= psInfo
->height
;
1495 MapDialogRect(hwndParent
, &rc
);
1497 pageWidth
= rc
.right
- rc
.left
;
1498 pageHeight
= rc
.bottom
- rc
.top
;
1500 padding
= PROPSHEET_GetPaddingInfoWizard(hwndParent
, psInfo
);
1501 TRACE("setting page %08lx, rc (%ld,%ld)-(%ld,%ld) w=%d, h=%d, padx=%d, pady=%d\n",
1502 (DWORD
)hwndPage
, rc
.left
, rc
.top
, rc
.right
, rc
.bottom
,
1503 pageWidth
, pageHeight
, padding
.x
, padding
.y
);
1504 SetWindowPos(hwndPage
, HWND_TOP
,
1505 rc
.left
+ padding
.x
/2,
1506 rc
.top
+ padding
.y
/2,
1507 pageWidth
, pageHeight
, 0);
1511 * Ask the Tab control to reduce the client rectangle to that
1514 PROPSHEET_GetPageRect(psInfo
, hwndParent
, &rc
);
1515 pageWidth
= rc
.right
- rc
.left
;
1516 pageHeight
= rc
.bottom
- rc
.top
;
1517 TRACE("setting page %08lx, rc (%ld,%ld)-(%ld,%ld) w=%d, h=%d\n",
1518 (DWORD
)hwndPage
, rc
.left
, rc
.top
, rc
.right
, rc
.bottom
,
1519 pageWidth
, pageHeight
);
1520 SetWindowPos(hwndPage
, HWND_TOP
,
1522 pageWidth
, pageHeight
, 0);
1528 /******************************************************************************
1529 * PROPSHEET_ShowPage
1531 * Displays or creates the specified page.
1533 static BOOL
PROPSHEET_ShowPage(HWND hwndDlg
, int index
, PropSheetInfo
* psInfo
)
1537 TRACE("active_page %d, index %d\n", psInfo
->active_page
, index
);
1538 if (index
== psInfo
->active_page
)
1540 if (GetTopWindow(hwndDlg
) != psInfo
->proppage
[index
].hwndPage
)
1541 SetWindowPos(psInfo
->proppage
[index
].hwndPage
, HWND_TOP
, 0, 0, 0, 0, SWP_NOSIZE
| SWP_NOMOVE
);
1545 if (psInfo
->proppage
[index
].hwndPage
== 0)
1547 LPCPROPSHEETPAGEW ppshpage
;
1549 ppshpage
= (LPCPROPSHEETPAGEW
)psInfo
->proppage
[index
].hpage
;
1550 PROPSHEET_CreatePage(hwndDlg
, index
, psInfo
, ppshpage
);
1553 if (psInfo
->active_page
!= -1)
1554 ShowWindow(psInfo
->proppage
[psInfo
->active_page
].hwndPage
, SW_HIDE
);
1556 ShowWindow(psInfo
->proppage
[index
].hwndPage
, SW_SHOW
);
1558 /* Synchronize current selection with tab control
1559 * It seems to be needed even in case of PSH_WIZARD (no tab controls there) */
1560 hwndTabCtrl
= GetDlgItem(hwndDlg
, IDC_TABCONTROL
);
1561 SendMessageW(hwndTabCtrl
, TCM_SETCURSEL
, index
, 0);
1563 psInfo
->active_page
= index
;
1564 psInfo
->activeValid
= TRUE
;
1569 /******************************************************************************
1572 static BOOL
PROPSHEET_Back(HWND hwndDlg
)
1576 PropSheetInfo
* psInfo
= (PropSheetInfo
*) GetPropW(hwndDlg
,
1581 TRACE("active_page %d\n", psInfo
->active_page
);
1582 if (psInfo
->active_page
< 0)
1585 psn
.hdr
.code
= PSN_WIZBACK
;
1586 psn
.hdr
.hwndFrom
= hwndDlg
;
1590 hwndPage
= psInfo
->proppage
[psInfo
->active_page
].hwndPage
;
1592 result
= SendMessageW(hwndPage
, WM_NOTIFY
, 0, (LPARAM
) &psn
);
1595 else if (result
== 0)
1596 idx
= psInfo
->active_page
- 1;
1598 idx
= PROPSHEET_FindPageByResId(psInfo
, result
);
1600 if (idx
>= 0 && idx
< psInfo
->nPages
)
1602 if (PROPSHEET_CanSetCurSel(hwndDlg
))
1603 PROPSHEET_SetCurSel(hwndDlg
, idx
, -1, 0);
1608 /******************************************************************************
1611 static BOOL
PROPSHEET_Next(HWND hwndDlg
)
1615 LRESULT msgResult
= 0;
1616 PropSheetInfo
* psInfo
= (PropSheetInfo
*) GetPropW(hwndDlg
,
1620 TRACE("active_page %d\n", psInfo
->active_page
);
1621 if (psInfo
->active_page
< 0)
1624 psn
.hdr
.code
= PSN_WIZNEXT
;
1625 psn
.hdr
.hwndFrom
= hwndDlg
;
1629 hwndPage
= psInfo
->proppage
[psInfo
->active_page
].hwndPage
;
1631 msgResult
= SendMessageA(hwndPage
, WM_NOTIFY
, 0, (LPARAM
) &psn
);
1632 if (msgResult
== -1)
1634 else if (msgResult
== 0)
1635 idx
= psInfo
->active_page
+ 1;
1637 idx
= PROPSHEET_FindPageByResId(psInfo
, msgResult
);
1639 if (idx
< psInfo
->nPages
)
1641 if (PROPSHEET_CanSetCurSel(hwndDlg
) != FALSE
)
1642 PROPSHEET_SetCurSel(hwndDlg
, idx
, 1, 0);
1648 /******************************************************************************
1651 static BOOL
PROPSHEET_Finish(HWND hwndDlg
)
1655 LRESULT msgResult
= 0;
1656 PropSheetInfo
* psInfo
= (PropSheetInfo
*) GetPropW(hwndDlg
,
1659 TRACE("active_page %d\n", psInfo
->active_page
);
1660 if (psInfo
->active_page
< 0)
1663 psn
.hdr
.code
= PSN_WIZFINISH
;
1664 psn
.hdr
.hwndFrom
= hwndDlg
;
1668 hwndPage
= psInfo
->proppage
[psInfo
->active_page
].hwndPage
;
1670 msgResult
= SendMessageW(hwndPage
, WM_NOTIFY
, 0, (LPARAM
) &psn
);
1672 TRACE("msg result %ld\n", msgResult
);
1677 if (psInfo
->isModeless
)
1678 psInfo
->activeValid
= FALSE
;
1680 EndDialog(hwndDlg
, TRUE
);
1685 /******************************************************************************
1688 static BOOL
PROPSHEET_Apply(HWND hwndDlg
, LPARAM lParam
)
1693 PropSheetInfo
* psInfo
= (PropSheetInfo
*) GetPropW(hwndDlg
,
1696 TRACE("active_page %d\n", psInfo
->active_page
);
1697 if (psInfo
->active_page
< 0)
1700 psn
.hdr
.hwndFrom
= hwndDlg
;
1706 * Send PSN_KILLACTIVE to the current page.
1708 psn
.hdr
.code
= PSN_KILLACTIVE
;
1710 hwndPage
= psInfo
->proppage
[psInfo
->active_page
].hwndPage
;
1712 if (SendMessageA(hwndPage
, WM_NOTIFY
, 0, (LPARAM
) &psn
) != FALSE
)
1716 * Send PSN_APPLY to all pages.
1718 psn
.hdr
.code
= PSN_APPLY
;
1719 psn
.lParam
= lParam
;
1721 for (i
= 0; i
< psInfo
->nPages
; i
++)
1723 hwndPage
= psInfo
->proppage
[i
].hwndPage
;
1726 switch (SendMessageA(hwndPage
, WM_NOTIFY
, 0, (LPARAM
) &psn
))
1728 case PSNRET_INVALID
:
1729 PROPSHEET_ShowPage(hwndDlg
, i
, psInfo
);
1731 case PSNRET_INVALID_NOCHANGEPAGE
:
1739 psInfo
->activeValid
= FALSE
;
1741 else if(psInfo
->active_page
>= 0)
1743 psn
.hdr
.code
= PSN_SETACTIVE
;
1745 hwndPage
= psInfo
->proppage
[psInfo
->active_page
].hwndPage
;
1746 SendMessageA(hwndPage
, WM_NOTIFY
, 0, (LPARAM
) &psn
);
1752 /******************************************************************************
1755 static void PROPSHEET_Cancel(HWND hwndDlg
, LPARAM lParam
)
1757 PropSheetInfo
* psInfo
= (PropSheetInfo
*) GetPropW(hwndDlg
,
1763 TRACE("active_page %d\n", psInfo
->active_page
);
1764 if (psInfo
->active_page
< 0)
1767 hwndPage
= psInfo
->proppage
[psInfo
->active_page
].hwndPage
;
1768 psn
.hdr
.code
= PSN_QUERYCANCEL
;
1769 psn
.hdr
.hwndFrom
= hwndDlg
;
1773 if (SendMessageA(hwndPage
, WM_NOTIFY
, 0, (LPARAM
) &psn
))
1776 psn
.hdr
.code
= PSN_RESET
;
1777 psn
.lParam
= lParam
;
1779 for (i
= 0; i
< psInfo
->nPages
; i
++)
1781 hwndPage
= psInfo
->proppage
[i
].hwndPage
;
1784 SendMessageA(hwndPage
, WM_NOTIFY
, 0, (LPARAM
) &psn
);
1787 if (psInfo
->isModeless
)
1789 /* makes PSM_GETCURRENTPAGEHWND return NULL */
1790 psInfo
->activeValid
= FALSE
;
1793 EndDialog(hwndDlg
, FALSE
);
1796 /******************************************************************************
1799 static void PROPSHEET_Help(HWND hwndDlg
)
1801 PropSheetInfo
* psInfo
= (PropSheetInfo
*) GetPropW(hwndDlg
,
1806 TRACE("active_page %d\n", psInfo
->active_page
);
1807 if (psInfo
->active_page
< 0)
1810 hwndPage
= psInfo
->proppage
[psInfo
->active_page
].hwndPage
;
1811 psn
.hdr
.code
= PSN_HELP
;
1812 psn
.hdr
.hwndFrom
= hwndDlg
;
1816 SendMessageA(hwndPage
, WM_NOTIFY
, 0, (LPARAM
) &psn
);
1819 /******************************************************************************
1822 static void PROPSHEET_Changed(HWND hwndDlg
, HWND hwndDirtyPage
)
1825 PropSheetInfo
* psInfo
= (PropSheetInfo
*) GetPropW(hwndDlg
,
1829 if (!psInfo
) return;
1831 * Set the dirty flag of this page.
1833 for (i
= 0; i
< psInfo
->nPages
; i
++)
1835 if (psInfo
->proppage
[i
].hwndPage
== hwndDirtyPage
)
1836 psInfo
->proppage
[i
].isDirty
= TRUE
;
1840 * Enable the Apply button.
1842 if (psInfo
->hasApply
)
1844 HWND hwndApplyBtn
= GetDlgItem(hwndDlg
, IDC_APPLY_BUTTON
);
1846 EnableWindow(hwndApplyBtn
, TRUE
);
1850 /******************************************************************************
1851 * PROPSHEET_UnChanged
1853 static void PROPSHEET_UnChanged(HWND hwndDlg
, HWND hwndCleanPage
)
1856 BOOL noPageDirty
= TRUE
;
1857 HWND hwndApplyBtn
= GetDlgItem(hwndDlg
, IDC_APPLY_BUTTON
);
1858 PropSheetInfo
* psInfo
= (PropSheetInfo
*) GetPropW(hwndDlg
,
1862 if ( !psInfo
) return;
1863 for (i
= 0; i
< psInfo
->nPages
; i
++)
1865 /* set the specified page as clean */
1866 if (psInfo
->proppage
[i
].hwndPage
== hwndCleanPage
)
1867 psInfo
->proppage
[i
].isDirty
= FALSE
;
1869 /* look to see if there's any dirty pages */
1870 if (psInfo
->proppage
[i
].isDirty
)
1871 noPageDirty
= FALSE
;
1875 * Disable Apply button.
1878 EnableWindow(hwndApplyBtn
, FALSE
);
1881 /******************************************************************************
1882 * PROPSHEET_PressButton
1884 static void PROPSHEET_PressButton(HWND hwndDlg
, int buttonID
)
1886 TRACE("buttonID %d\n", buttonID
);
1889 case PSBTN_APPLYNOW
:
1890 PROPSHEET_DoCommand(hwndDlg
, IDC_APPLY_BUTTON
);
1893 PROPSHEET_Back(hwndDlg
);
1896 PROPSHEET_DoCommand(hwndDlg
, IDCANCEL
);
1899 PROPSHEET_Finish(hwndDlg
);
1902 PROPSHEET_DoCommand(hwndDlg
, IDHELP
);
1905 PROPSHEET_Next(hwndDlg
);
1908 PROPSHEET_DoCommand(hwndDlg
, IDOK
);
1911 FIXME("Invalid button index %d\n", buttonID
);
1916 /*************************************************************************
1917 * BOOL PROPSHEET_CanSetCurSel [Internal]
1919 * Test whether the current page can be changed by sending a PSN_KILLACTIVE
1922 * hwndDlg [I] handle to a Dialog hWnd
1925 * TRUE if Current Selection can change
1929 static BOOL
PROPSHEET_CanSetCurSel(HWND hwndDlg
)
1931 PropSheetInfo
* psInfo
= (PropSheetInfo
*) GetPropW(hwndDlg
,
1937 TRACE("active_page %d\n", psInfo
->active_page
);
1944 if (psInfo
->active_page
< 0)
1951 * Notify the current page.
1953 hwndPage
= psInfo
->proppage
[psInfo
->active_page
].hwndPage
;
1954 psn
.hdr
.code
= PSN_KILLACTIVE
;
1955 psn
.hdr
.hwndFrom
= hwndDlg
;
1959 res
= !SendMessageA(hwndPage
, WM_NOTIFY
, 0, (LPARAM
) &psn
);
1962 TRACE("<-- %d\n", res
);
1966 /******************************************************************************
1967 * PROPSHEET_SetCurSel
1969 static BOOL
PROPSHEET_SetCurSel(HWND hwndDlg
,
1972 HPROPSHEETPAGE hpage
1975 PropSheetInfo
* psInfo
= (PropSheetInfo
*) GetPropW(hwndDlg
, PropSheetInfoStr
);
1976 HWND hwndHelp
= GetDlgItem(hwndDlg
, IDHELP
);
1977 HWND hwndTabControl
= GetDlgItem(hwndDlg
, IDC_TABCONTROL
);
1979 TRACE("index %d, skipdir %d, hpage %p\n", index
, skipdir
, hpage
);
1980 /* hpage takes precedence over index */
1982 index
= PROPSHEET_GetPageIndex(hpage
, psInfo
);
1984 if (index
< 0 || index
>= psInfo
->nPages
)
1986 TRACE("Could not find page to select!\n");
1995 SendMessageW(hwndTabControl
, TCM_SETCURSEL
, index
, 0);
1997 psn
.hdr
.code
= PSN_SETACTIVE
;
1998 psn
.hdr
.hwndFrom
= hwndDlg
;
2002 if (!psInfo
->proppage
[index
].hwndPage
) {
2003 LPCPROPSHEETPAGEW ppshpage
= (LPCPROPSHEETPAGEW
)psInfo
->proppage
[index
].hpage
;
2004 PROPSHEET_CreatePage(hwndDlg
, index
, psInfo
, ppshpage
);
2007 result
= SendMessageW(psInfo
->proppage
[index
].hwndPage
, WM_NOTIFY
, 0, (LPARAM
) &psn
);
2014 FIXME("Tried to skip before first property sheet page!\n");
2017 if (index
>= psInfo
->nPages
) {
2018 FIXME("Tried to skip after last property sheet page!\n");
2019 index
= psInfo
->nPages
-1;
2023 else if (result
!= 0)
2025 index
= PROPSHEET_FindPageByResId(psInfo
, result
);
2030 * Display the new page.
2032 PROPSHEET_ShowPage(hwndDlg
, index
, psInfo
);
2034 if (psInfo
->proppage
[index
].hasHelp
)
2035 EnableWindow(hwndHelp
, TRUE
);
2037 EnableWindow(hwndHelp
, FALSE
);
2042 /******************************************************************************
2043 * PROPSHEET_SetCurSelId
2045 * Selects the page, specified by resource id.
2047 static void PROPSHEET_SetCurSelId(HWND hwndDlg
, int id
)
2050 PropSheetInfo
* psInfo
=
2051 (PropSheetInfo
*) GetPropW(hwndDlg
, PropSheetInfoStr
);
2053 idx
= PROPSHEET_FindPageByResId(psInfo
, id
);
2054 if (idx
< psInfo
->nPages
)
2056 if (PROPSHEET_CanSetCurSel(hwndDlg
) != FALSE
)
2057 PROPSHEET_SetCurSel(hwndDlg
, idx
, 1, 0);
2061 /******************************************************************************
2062 * PROPSHEET_SetTitleA
2064 static void PROPSHEET_SetTitleA(HWND hwndDlg
, DWORD dwStyle
, LPCSTR lpszText
)
2066 if(HIWORD(lpszText
))
2069 MultiByteToWideChar(CP_ACP
, 0, lpszText
, -1,
2070 szTitle
, sizeof(szTitle
));
2071 PROPSHEET_SetTitleW(hwndDlg
, dwStyle
, szTitle
);
2075 PROPSHEET_SetTitleW(hwndDlg
, dwStyle
, (LPCWSTR
)lpszText
);
2079 /******************************************************************************
2080 * PROPSHEET_SetTitleW
2082 static void PROPSHEET_SetTitleW(HWND hwndDlg
, DWORD dwStyle
, LPCWSTR lpszText
)
2084 PropSheetInfo
* psInfo
= (PropSheetInfo
*) GetPropW(hwndDlg
, PropSheetInfoStr
);
2087 TRACE("'%s' (style %08lx)\n", debugstr_w(lpszText
), dwStyle
);
2088 if (HIWORD(lpszText
) == 0) {
2089 if (!LoadStringW(psInfo
->ppshheader
.hInstance
,
2090 LOWORD(lpszText
), szTitle
, sizeof(szTitle
)-sizeof(WCHAR
)))
2094 if (dwStyle
& PSH_PROPTITLE
)
2097 int lentitle
= strlenW(lpszText
);
2098 int lenprop
= strlenW(psInfo
->strPropertiesFor
);
2100 dest
= COMCTL32_Alloc( (lentitle
+ lenprop
+ 1)*sizeof (WCHAR
));
2101 strcpyW(dest
, psInfo
->strPropertiesFor
);
2102 strcatW(dest
, lpszText
);
2104 SetWindowTextW(hwndDlg
, dest
);
2105 COMCTL32_Free(dest
);
2108 SetWindowTextW(hwndDlg
, lpszText
);
2111 /******************************************************************************
2112 * PROPSHEET_SetFinishTextA
2114 static void PROPSHEET_SetFinishTextA(HWND hwndDlg
, LPCSTR lpszText
)
2116 HWND hwndButton
= GetDlgItem(hwndDlg
, IDC_FINISH_BUTTON
);
2118 TRACE("'%s'\n", lpszText
);
2119 /* Set text, show and enable the Finish button */
2120 SetWindowTextA(hwndButton
, lpszText
);
2121 ShowWindow(hwndButton
, SW_SHOW
);
2122 EnableWindow(hwndButton
, TRUE
);
2124 /* Make it default pushbutton */
2125 SendMessageA(hwndDlg
, DM_SETDEFID
, IDC_FINISH_BUTTON
, 0);
2127 /* Hide Back button */
2128 hwndButton
= GetDlgItem(hwndDlg
, IDC_BACK_BUTTON
);
2129 ShowWindow(hwndButton
, SW_HIDE
);
2131 /* Hide Next button */
2132 hwndButton
= GetDlgItem(hwndDlg
, IDC_NEXT_BUTTON
);
2133 ShowWindow(hwndButton
, SW_HIDE
);
2136 /******************************************************************************
2137 * PROPSHEET_SetFinishTextW
2139 static void PROPSHEET_SetFinishTextW(HWND hwndDlg
, LPCWSTR lpszText
)
2141 HWND hwndButton
= GetDlgItem(hwndDlg
, IDC_FINISH_BUTTON
);
2143 TRACE("'%s'\n", debugstr_w(lpszText
));
2144 /* Set text, show and enable the Finish button */
2145 SetWindowTextW(hwndButton
, lpszText
);
2146 ShowWindow(hwndButton
, SW_SHOW
);
2147 EnableWindow(hwndButton
, TRUE
);
2149 /* Make it default pushbutton */
2150 SendMessageW(hwndDlg
, DM_SETDEFID
, IDC_FINISH_BUTTON
, 0);
2152 /* Hide Back button */
2153 hwndButton
= GetDlgItem(hwndDlg
, IDC_BACK_BUTTON
);
2154 ShowWindow(hwndButton
, SW_HIDE
);
2156 /* Hide Next button */
2157 hwndButton
= GetDlgItem(hwndDlg
, IDC_NEXT_BUTTON
);
2158 ShowWindow(hwndButton
, SW_HIDE
);
2161 /******************************************************************************
2162 * PROPSHEET_QuerySiblings
2164 static LRESULT
PROPSHEET_QuerySiblings(HWND hwndDlg
,
2165 WPARAM wParam
, LPARAM lParam
)
2169 LRESULT msgResult
= 0;
2170 PropSheetInfo
* psInfo
= (PropSheetInfo
*) GetPropW(hwndDlg
,
2173 while ((i
< psInfo
->nPages
) && (msgResult
== 0))
2175 hwndPage
= psInfo
->proppage
[i
].hwndPage
;
2176 msgResult
= SendMessageA(hwndPage
, PSM_QUERYSIBLINGS
, wParam
, lParam
);
2184 /******************************************************************************
2187 static BOOL
PROPSHEET_AddPage(HWND hwndDlg
,
2188 HPROPSHEETPAGE hpage
)
2190 PropSheetInfo
* psInfo
= (PropSheetInfo
*) GetPropW(hwndDlg
,
2192 HWND hwndTabControl
= GetDlgItem(hwndDlg
, IDC_TABCONTROL
);
2194 LPCPROPSHEETPAGEW ppsp
= (LPCPROPSHEETPAGEW
)hpage
;
2196 TRACE("hpage %p\n", hpage
);
2198 * Allocate and fill in a new PropPageInfo entry.
2200 psInfo
->proppage
= (PropPageInfo
*) COMCTL32_ReAlloc(psInfo
->proppage
,
2201 sizeof(PropPageInfo
) *
2202 (psInfo
->nPages
+ 1));
2203 if (!PROPSHEET_CollectPageInfo(ppsp
, psInfo
, psInfo
->nPages
))
2206 psInfo
->proppage
[psInfo
->nPages
].hpage
= hpage
;
2208 if (ppsp
->dwFlags
& PSP_PREMATURE
)
2210 /* Create the page but don't show it */
2211 PROPSHEET_CreatePage(hwndDlg
, psInfo
->nPages
, psInfo
, ppsp
);
2215 * Add a new tab to the tab control.
2217 item
.mask
= TCIF_TEXT
;
2218 item
.pszText
= (LPWSTR
) psInfo
->proppage
[psInfo
->nPages
].pszText
;
2219 item
.cchTextMax
= MAX_TABTEXT_LENGTH
;
2221 if (psInfo
->hImageList
)
2223 SendMessageW(hwndTabControl
, TCM_SETIMAGELIST
, 0, (LPARAM
)psInfo
->hImageList
);
2226 if ( psInfo
->proppage
[psInfo
->nPages
].hasIcon
)
2228 item
.mask
|= TCIF_IMAGE
;
2229 item
.iImage
= psInfo
->nPages
;
2232 SendMessageW(hwndTabControl
, TCM_INSERTITEMW
, psInfo
->nPages
+ 1,
2237 /* If it is the only page - show it */
2238 if(psInfo
->nPages
== 1)
2239 PROPSHEET_SetCurSel(hwndDlg
, 0, 1, 0);
2243 /******************************************************************************
2244 * PROPSHEET_RemovePage
2246 static BOOL
PROPSHEET_RemovePage(HWND hwndDlg
,
2248 HPROPSHEETPAGE hpage
)
2250 PropSheetInfo
* psInfo
= (PropSheetInfo
*) GetPropW(hwndDlg
,
2252 HWND hwndTabControl
= GetDlgItem(hwndDlg
, IDC_TABCONTROL
);
2253 PropPageInfo
* oldPages
;
2255 TRACE("index %d, hpage %p\n", index
, hpage
);
2259 oldPages
= psInfo
->proppage
;
2261 * hpage takes precedence over index.
2265 index
= PROPSHEET_GetPageIndex(hpage
, psInfo
);
2268 /* Make sure that index is within range */
2269 if (index
< 0 || index
>= psInfo
->nPages
)
2271 TRACE("Could not find page to remove!\n");
2275 TRACE("total pages %d removing page %d active page %d\n",
2276 psInfo
->nPages
, index
, psInfo
->active_page
);
2278 * Check if we're removing the active page.
2280 if (index
== psInfo
->active_page
)
2282 if (psInfo
->nPages
> 1)
2286 /* activate previous page */
2287 PROPSHEET_SetCurSel(hwndDlg
, index
- 1, -1, 0);
2291 /* activate the next page */
2292 PROPSHEET_SetCurSel(hwndDlg
, index
+ 1, 1, 0);
2293 psInfo
->active_page
= index
;
2298 psInfo
->active_page
= -1;
2299 if (!psInfo
->isModeless
)
2301 EndDialog(hwndDlg
, FALSE
);
2306 else if (index
< psInfo
->active_page
)
2307 psInfo
->active_page
--;
2309 /* Destroy page dialog window */
2310 DestroyWindow(psInfo
->proppage
[index
].hwndPage
);
2312 /* Free page resources */
2313 if(psInfo
->proppage
[index
].hpage
)
2315 PROPSHEETPAGEW
* psp
= (PROPSHEETPAGEW
*)psInfo
->proppage
[index
].hpage
;
2317 if ((psp
->dwFlags
& PSP_USETITLE
) && psInfo
->proppage
[index
].pszText
)
2318 HeapFree(GetProcessHeap(), 0, (LPVOID
)psInfo
->proppage
[index
].pszText
);
2320 DestroyPropertySheetPage(psInfo
->proppage
[index
].hpage
);
2323 /* Remove the tab */
2324 SendMessageW(hwndTabControl
, TCM_DELETEITEM
, index
, 0);
2327 psInfo
->proppage
= COMCTL32_Alloc(sizeof(PropPageInfo
) * psInfo
->nPages
);
2330 memcpy(&psInfo
->proppage
[0], &oldPages
[0], index
* sizeof(PropPageInfo
));
2332 if (index
< psInfo
->nPages
)
2333 memcpy(&psInfo
->proppage
[index
], &oldPages
[index
+ 1],
2334 (psInfo
->nPages
- index
) * sizeof(PropPageInfo
));
2336 COMCTL32_Free(oldPages
);
2341 /******************************************************************************
2342 * PROPSHEET_SetWizButtons
2344 * This code will work if (and assumes that) the Next button is on top of the
2345 * Finish button. ie. Finish comes after Next in the Z order.
2346 * This means make sure the dialog template reflects this.
2349 static void PROPSHEET_SetWizButtons(HWND hwndDlg
, DWORD dwFlags
)
2351 HWND hwndBack
= GetDlgItem(hwndDlg
, IDC_BACK_BUTTON
);
2352 HWND hwndNext
= GetDlgItem(hwndDlg
, IDC_NEXT_BUTTON
);
2353 HWND hwndFinish
= GetDlgItem(hwndDlg
, IDC_FINISH_BUTTON
);
2355 TRACE("%ld\n", dwFlags
);
2357 EnableWindow(hwndBack
, FALSE
);
2358 EnableWindow(hwndNext
, FALSE
);
2359 EnableWindow(hwndFinish
, FALSE
);
2361 if (dwFlags
& PSWIZB_BACK
)
2362 EnableWindow(hwndBack
, TRUE
);
2364 if (dwFlags
& PSWIZB_NEXT
)
2366 /* Hide the Finish button */
2367 ShowWindow(hwndFinish
, SW_HIDE
);
2369 /* Show and enable the Next button */
2370 ShowWindow(hwndNext
, SW_SHOW
);
2371 EnableWindow(hwndNext
, TRUE
);
2373 /* Set the Next button as the default pushbutton */
2374 SendMessageA(hwndDlg
, DM_SETDEFID
, IDC_NEXT_BUTTON
, 0);
2377 if ((dwFlags
& PSWIZB_FINISH
) || (dwFlags
& PSWIZB_DISABLEDFINISH
))
2379 /* Hide the Next button */
2380 ShowWindow(hwndNext
, SW_HIDE
);
2382 /* Show the Finish button */
2383 ShowWindow(hwndFinish
, SW_SHOW
);
2385 if (dwFlags
& PSWIZB_FINISH
)
2386 EnableWindow(hwndFinish
, TRUE
);
2388 /* Set the Finish button as the default pushbutton */
2389 SendMessageA(hwndDlg
, DM_SETDEFID
, IDC_FINISH_BUTTON
, 0);
2393 /******************************************************************************
2394 * PROPSHEET_GetPageIndex
2396 * Given a HPROPSHEETPAGE, returns the index of the corresponding page from
2397 * the array of PropPageInfo.
2399 static int PROPSHEET_GetPageIndex(HPROPSHEETPAGE hpage
, PropSheetInfo
* psInfo
)
2404 TRACE("hpage %p\n", hpage
);
2405 while ((index
< psInfo
->nPages
) && (found
== FALSE
))
2407 if (psInfo
->proppage
[index
].hpage
== hpage
)
2419 /******************************************************************************
2422 static void PROPSHEET_CleanUp(HWND hwndDlg
)
2425 PropSheetInfo
* psInfo
= (PropSheetInfo
*) RemovePropW(hwndDlg
,
2429 if (!psInfo
) return;
2430 if (HIWORD(psInfo
->ppshheader
.pszCaption
))
2431 HeapFree(GetProcessHeap(), 0, (LPVOID
)psInfo
->ppshheader
.pszCaption
);
2433 for (i
= 0; i
< psInfo
->nPages
; i
++)
2435 PROPSHEETPAGEA
* psp
= (PROPSHEETPAGEA
*)psInfo
->proppage
[i
].hpage
;
2437 if(psInfo
->proppage
[i
].hwndPage
)
2438 DestroyWindow(psInfo
->proppage
[i
].hwndPage
);
2442 if ((psp
->dwFlags
& PSP_USETITLE
) && psInfo
->proppage
[i
].pszText
)
2443 HeapFree(GetProcessHeap(), 0, (LPVOID
)psInfo
->proppage
[i
].pszText
);
2445 DestroyPropertySheetPage(psInfo
->proppage
[i
].hpage
);
2449 COMCTL32_Free(psInfo
->proppage
);
2450 COMCTL32_Free(psInfo
->strPropertiesFor
);
2451 ImageList_Destroy(psInfo
->hImageList
);
2453 GlobalFree((HGLOBAL
)psInfo
);
2456 /******************************************************************************
2457 * PropertySheet (COMCTL32.@)
2458 * PropertySheetA (COMCTL32.@)
2460 INT WINAPI
PropertySheetA(LPCPROPSHEETHEADERA lppsh
)
2463 PropSheetInfo
* psInfo
= (PropSheetInfo
*) GlobalAlloc(GPTR
,
2464 sizeof(PropSheetInfo
));
2468 TRACE("(%p)\n", lppsh
);
2470 PROPSHEET_CollectSheetInfoA(lppsh
, psInfo
);
2472 psInfo
->proppage
= (PropPageInfo
*) COMCTL32_Alloc(sizeof(PropPageInfo
) *
2474 pByte
= (BYTE
*) psInfo
->ppshheader
.u3
.ppsp
;
2476 for (n
= i
= 0; i
< lppsh
->nPages
; i
++, n
++)
2478 if (!(lppsh
->dwFlags
& PSH_PROPSHEETPAGE
))
2479 psInfo
->proppage
[n
].hpage
= psInfo
->ppshheader
.u3
.phpage
[i
];
2482 psInfo
->proppage
[n
].hpage
= CreatePropertySheetPageA((LPCPROPSHEETPAGEA
)pByte
);
2483 pByte
+= ((LPPROPSHEETPAGEA
)pByte
)->dwSize
;
2486 if (!PROPSHEET_CollectPageInfo((LPCPROPSHEETPAGEW
)psInfo
->proppage
[n
].hpage
,
2489 if (lppsh
->dwFlags
& PSH_PROPSHEETPAGE
)
2490 DestroyPropertySheetPage(psInfo
->proppage
[n
].hpage
);
2496 psInfo
->unicode
= FALSE
;
2497 bRet
= PROPSHEET_CreateDialog(psInfo
);
2502 /******************************************************************************
2503 * PropertySheetW (COMCTL32.@)
2505 INT WINAPI
PropertySheetW(LPCPROPSHEETHEADERW lppsh
)
2508 PropSheetInfo
* psInfo
= (PropSheetInfo
*) GlobalAlloc(GPTR
,
2509 sizeof(PropSheetInfo
));
2513 TRACE("(%p)\n", lppsh
);
2515 PROPSHEET_CollectSheetInfoW(lppsh
, psInfo
);
2517 psInfo
->proppage
= (PropPageInfo
*) COMCTL32_Alloc(sizeof(PropPageInfo
) *
2519 pByte
= (BYTE
*) psInfo
->ppshheader
.u3
.ppsp
;
2521 for (n
= i
= 0; i
< lppsh
->nPages
; i
++, n
++)
2523 if (!(lppsh
->dwFlags
& PSH_PROPSHEETPAGE
))
2524 psInfo
->proppage
[n
].hpage
= psInfo
->ppshheader
.u3
.phpage
[i
];
2527 psInfo
->proppage
[n
].hpage
= CreatePropertySheetPageW((LPCPROPSHEETPAGEW
)pByte
);
2528 pByte
+= ((LPPROPSHEETPAGEW
)pByte
)->dwSize
;
2531 if (!PROPSHEET_CollectPageInfo((LPCPROPSHEETPAGEW
)psInfo
->proppage
[n
].hpage
,
2534 if (lppsh
->dwFlags
& PSH_PROPSHEETPAGE
)
2535 DestroyPropertySheetPage(psInfo
->proppage
[n
].hpage
);
2541 psInfo
->unicode
= TRUE
;
2542 bRet
= PROPSHEET_CreateDialog(psInfo
);
2547 /******************************************************************************
2548 * CreatePropertySheetPage (COMCTL32.@)
2549 * CreatePropertySheetPageA (COMCTL32.@)
2551 HPROPSHEETPAGE WINAPI
CreatePropertySheetPageA(
2552 LPCPROPSHEETPAGEA lpPropSheetPage
)
2554 PROPSHEETPAGEW
* ppsp
= COMCTL32_Alloc(sizeof(PROPSHEETPAGEW
));
2556 memcpy(ppsp
,lpPropSheetPage
,min(lpPropSheetPage
->dwSize
,sizeof(PROPSHEETPAGEA
)));
2558 ppsp
->dwFlags
&= ~ PSP_INTERNAL_UNICODE
;
2559 if ( !(ppsp
->dwFlags
& PSP_DLGINDIRECT
) && HIWORD( ppsp
->u
.pszTemplate
) )
2561 int len
= strlen(lpPropSheetPage
->u
.pszTemplate
);
2563 ppsp
->u
.pszTemplate
= HeapAlloc( GetProcessHeap(),0,len
+1 );
2564 strcpy( (LPSTR
)ppsp
->u
.pszTemplate
, lpPropSheetPage
->u
.pszTemplate
);
2566 if ( (ppsp
->dwFlags
& PSP_USEICONID
) && HIWORD( ppsp
->u2
.pszIcon
) )
2568 PROPSHEET_AtoW(&ppsp
->u2
.pszIcon
, lpPropSheetPage
->u2
.pszIcon
);
2571 if ((ppsp
->dwFlags
& PSP_USETITLE
) && HIWORD( ppsp
->pszTitle
))
2573 PROPSHEET_AtoW(&ppsp
->pszTitle
, lpPropSheetPage
->pszTitle
);
2575 else if ( !(ppsp
->dwFlags
& PSP_USETITLE
) )
2576 ppsp
->pszTitle
= NULL
;
2578 return (HPROPSHEETPAGE
)ppsp
;
2581 /******************************************************************************
2582 * CreatePropertySheetPageW (COMCTL32.@)
2584 HPROPSHEETPAGE WINAPI
CreatePropertySheetPageW(LPCPROPSHEETPAGEW lpPropSheetPage
)
2586 PROPSHEETPAGEW
* ppsp
= COMCTL32_Alloc(sizeof(PROPSHEETPAGEW
));
2588 memcpy(ppsp
,lpPropSheetPage
,min(lpPropSheetPage
->dwSize
,sizeof(PROPSHEETPAGEW
)));
2590 ppsp
->dwFlags
|= PSP_INTERNAL_UNICODE
;
2592 if ( !(ppsp
->dwFlags
& PSP_DLGINDIRECT
) && HIWORD( ppsp
->u
.pszTemplate
) )
2594 int len
= strlenW(lpPropSheetPage
->u
.pszTemplate
);
2596 ppsp
->u
.pszTemplate
= HeapAlloc( GetProcessHeap(),0,(len
+1)*sizeof (WCHAR
) );
2597 strcpyW( (WCHAR
*)ppsp
->u
.pszTemplate
, lpPropSheetPage
->u
.pszTemplate
);
2599 if ( (ppsp
->dwFlags
& PSP_USEICONID
) && HIWORD( ppsp
->u2
.pszIcon
) )
2601 int len
= strlenW(lpPropSheetPage
->u2
.pszIcon
);
2602 ppsp
->u2
.pszIcon
= HeapAlloc( GetProcessHeap(), 0, (len
+1)*sizeof (WCHAR
) );
2603 strcpyW( (WCHAR
*)ppsp
->u2
.pszIcon
, lpPropSheetPage
->u2
.pszIcon
);
2606 if ((ppsp
->dwFlags
& PSP_USETITLE
) && HIWORD( ppsp
->pszTitle
))
2608 int len
= strlenW(lpPropSheetPage
->pszTitle
);
2609 ppsp
->pszTitle
= HeapAlloc( GetProcessHeap(), 0, (len
+1)*sizeof (WCHAR
) );
2610 strcpyW( (WCHAR
*)ppsp
->pszTitle
, lpPropSheetPage
->pszTitle
);
2612 else if ( !(ppsp
->dwFlags
& PSP_USETITLE
) )
2613 ppsp
->pszTitle
= NULL
;
2615 return (HPROPSHEETPAGE
)ppsp
;
2618 /******************************************************************************
2619 * DestroyPropertySheetPage (COMCTL32.@)
2621 BOOL WINAPI
DestroyPropertySheetPage(HPROPSHEETPAGE hPropPage
)
2623 PROPSHEETPAGEW
*psp
= (PROPSHEETPAGEW
*)hPropPage
;
2628 if ( !(psp
->dwFlags
& PSP_DLGINDIRECT
) && HIWORD( psp
->u
.pszTemplate
) )
2629 HeapFree(GetProcessHeap(), 0, (LPVOID
)psp
->u
.pszTemplate
);
2631 if ( (psp
->dwFlags
& PSP_USEICONID
) && HIWORD( psp
->u2
.pszIcon
) )
2632 HeapFree(GetProcessHeap(), 0, (LPVOID
)psp
->u2
.pszIcon
);
2634 if ((psp
->dwFlags
& PSP_USETITLE
) && HIWORD( psp
->pszTitle
))
2635 HeapFree(GetProcessHeap(), 0, (LPVOID
)psp
->pszTitle
);
2637 COMCTL32_Free(hPropPage
);
2642 /******************************************************************************
2643 * PROPSHEET_IsDialogMessage
2645 static BOOL
PROPSHEET_IsDialogMessage(HWND hwnd
, LPMSG lpMsg
)
2647 PropSheetInfo
* psInfo
= (PropSheetInfo
*) GetPropW(hwnd
, PropSheetInfoStr
);
2650 if (!psInfo
|| (hwnd
!= lpMsg
->hwnd
&& !IsChild(hwnd
, lpMsg
->hwnd
)))
2653 if (lpMsg
->message
== WM_KEYDOWN
&& (GetKeyState(VK_CONTROL
) & 0x8000))
2656 INT dlgCode
= SendMessageA(lpMsg
->hwnd
, WM_GETDLGCODE
, 0, (LPARAM
)lpMsg
);
2658 if (!(dlgCode
& DLGC_WANTMESSAGE
))
2660 switch (lpMsg
->wParam
)
2663 if (GetKeyState(VK_SHIFT
) & 0x8000)
2669 case VK_NEXT
: new_page
= 1; break;
2670 case VK_PRIOR
: new_page
= -1; break;
2676 if (PROPSHEET_CanSetCurSel(hwnd
) != FALSE
)
2678 new_page
+= psInfo
->active_page
;
2681 new_page
= psInfo
->nPages
- 1;
2682 else if (new_page
>= psInfo
->nPages
)
2685 PROPSHEET_SetCurSel(hwnd
, new_page
, 1, 0);
2692 return IsDialogMessageA(hwnd
, lpMsg
);
2695 /******************************************************************************
2696 * PROPSHEET_DoCommand
2698 static BOOL
PROPSHEET_DoCommand(HWND hwnd
, WORD wID
)
2704 case IDC_APPLY_BUTTON
:
2706 HWND hwndApplyBtn
= GetDlgItem(hwnd
, IDC_APPLY_BUTTON
);
2708 if (PROPSHEET_Apply(hwnd
, wID
== IDOK
? 1: 0) == FALSE
)
2713 PropSheetInfo
* psInfo
= (PropSheetInfo
*) GetPropW(hwnd
,
2717 if (psInfo
->restartWindows
)
2718 result
= ID_PSRESTARTWINDOWS
;
2720 /* reboot system takes precedence over restart windows */
2721 if (psInfo
->rebootSystem
)
2722 result
= ID_PSREBOOTSYSTEM
;
2724 if (psInfo
->isModeless
)
2725 psInfo
->activeValid
= FALSE
;
2727 EndDialog(hwnd
, result
);
2730 EnableWindow(hwndApplyBtn
, FALSE
);
2735 case IDC_BACK_BUTTON
:
2736 PROPSHEET_Back(hwnd
);
2739 case IDC_NEXT_BUTTON
:
2740 PROPSHEET_Next(hwnd
);
2743 case IDC_FINISH_BUTTON
:
2744 PROPSHEET_Finish(hwnd
);
2748 PROPSHEET_Cancel(hwnd
, 0);
2752 PROPSHEET_Help(hwnd
);
2759 /******************************************************************************
2760 * PROPSHEET_DialogProc
2763 PROPSHEET_DialogProc(HWND hwnd
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
)
2765 TRACE("hwnd=%p msg=0x%04x wparam=%x lparam=%lx\n",
2766 hwnd
, uMsg
, wParam
, lParam
);
2772 PropSheetInfo
* psInfo
= (PropSheetInfo
*) lParam
;
2773 WCHAR
* strCaption
= (WCHAR
*)COMCTL32_Alloc(MAX_CAPTION_LENGTH
*sizeof(WCHAR
));
2774 HWND hwndTabCtrl
= GetDlgItem(hwnd
, IDC_TABCONTROL
);
2775 LPCPROPSHEETPAGEW ppshpage
;
2778 SetPropW(hwnd
, PropSheetInfoStr
, (HANDLE
)psInfo
);
2781 * psInfo->hwnd is not being used by WINE code - it exists
2782 * for compatibility with "real" Windoze. The same about
2783 * SetWindowLong - WINE is only using the PropSheetInfoStr
2786 psInfo
->hwnd
= hwnd
;
2787 SetWindowLongW(hwnd
,DWL_USER
,(LONG
)psInfo
);
2790 * Small icon in the title bar.
2792 if ((psInfo
->ppshheader
.dwFlags
& PSH_USEICONID
) ||
2793 (psInfo
->ppshheader
.dwFlags
& PSH_USEHICON
))
2796 int icon_cx
= GetSystemMetrics(SM_CXSMICON
);
2797 int icon_cy
= GetSystemMetrics(SM_CYSMICON
);
2799 if (psInfo
->ppshheader
.dwFlags
& PSH_USEICONID
)
2800 hIcon
= LoadImageW(psInfo
->ppshheader
.hInstance
,
2801 psInfo
->ppshheader
.u
.pszIcon
,
2806 hIcon
= psInfo
->ppshheader
.u
.hIcon
;
2808 SendMessageW(hwnd
, WM_SETICON
, 0, (LPARAM
)hIcon
);
2811 if (psInfo
->ppshheader
.dwFlags
& PSH_USEHICON
)
2812 SendMessageW(hwnd
, WM_SETICON
, 0, (LPARAM
)psInfo
->ppshheader
.u
.hIcon
);
2814 psInfo
->strPropertiesFor
= strCaption
;
2816 GetWindowTextW(hwnd
, psInfo
->strPropertiesFor
, MAX_CAPTION_LENGTH
);
2818 PROPSHEET_CreateTabControl(hwnd
, psInfo
);
2820 if (psInfo
->ppshheader
.dwFlags
& INTRNL_ANY_WIZARD
)
2822 if (PROPSHEET_IsTooSmallWizard(hwnd
, psInfo
))
2824 PROPSHEET_AdjustSizeWizard(hwnd
, psInfo
);
2825 PROPSHEET_AdjustButtonsWizard(hwnd
, psInfo
);
2830 if (PROPSHEET_SizeMismatch(hwnd
, psInfo
))
2832 PROPSHEET_AdjustSize(hwnd
, psInfo
);
2833 PROPSHEET_AdjustButtons(hwnd
, psInfo
);
2837 if (psInfo
->useCallback
)
2838 (*(psInfo
->ppshheader
.pfnCallback
))(hwnd
,
2839 PSCB_INITIALIZED
, (LPARAM
)0);
2841 idx
= psInfo
->active_page
;
2842 ppshpage
= (LPCPROPSHEETPAGEW
)psInfo
->proppage
[idx
].hpage
;
2843 psInfo
->active_page
= -1;
2845 PROPSHEET_SetCurSel(hwnd
, idx
, 1, psInfo
->proppage
[idx
].hpage
);
2847 /* doing TCM_SETCURSEL seems to be needed even in case of PSH_WIZARD,
2848 * as some programs call TCM_GETCURSEL to get the current selection
2849 * from which to switch to the next page */
2850 SendMessageW(hwndTabCtrl
, TCM_SETCURSEL
, psInfo
->active_page
, 0);
2852 if (!HIWORD(psInfo
->ppshheader
.pszCaption
) &&
2853 psInfo
->ppshheader
.hInstance
)
2857 if (LoadStringW(psInfo
->ppshheader
.hInstance
,
2858 (UINT
)psInfo
->ppshheader
.pszCaption
, szText
, 255))
2859 PROPSHEET_SetTitleW(hwnd
, psInfo
->ppshheader
.dwFlags
, szText
);
2863 PROPSHEET_SetTitleW(hwnd
, psInfo
->ppshheader
.dwFlags
,
2864 psInfo
->ppshheader
.pszCaption
);
2871 PROPSHEET_CleanUp(hwnd
);
2875 PROPSHEET_Cancel(hwnd
, 1);
2879 return PROPSHEET_DoCommand(hwnd
, LOWORD(wParam
));
2883 NMHDR
* pnmh
= (LPNMHDR
) lParam
;
2885 if (pnmh
->code
== TCN_SELCHANGE
)
2887 int index
= SendMessageW(pnmh
->hwndFrom
, TCM_GETCURSEL
, 0, 0);
2888 PROPSHEET_SetCurSel(hwnd
, index
, 1, 0);
2891 if(pnmh
->code
== TCN_SELCHANGING
)
2893 BOOL bRet
= PROPSHEET_CanSetCurSel(hwnd
);
2894 SetWindowLongW(hwnd
, DWL_MSGRESULT
, !bRet
);
2901 case PSM_GETCURRENTPAGEHWND
:
2903 PropSheetInfo
* psInfo
= (PropSheetInfo
*) GetPropW(hwnd
,
2907 if (psInfo
->activeValid
&& psInfo
->active_page
!= -1)
2908 hwndPage
= psInfo
->proppage
[psInfo
->active_page
].hwndPage
;
2910 SetWindowLongW(hwnd
, DWL_MSGRESULT
, (LONG
)hwndPage
);
2916 PROPSHEET_Changed(hwnd
, (HWND
)wParam
);
2920 PROPSHEET_UnChanged(hwnd
, (HWND
)wParam
);
2923 case PSM_GETTABCONTROL
:
2925 HWND hwndTabCtrl
= GetDlgItem(hwnd
, IDC_TABCONTROL
);
2927 SetWindowLongW(hwnd
, DWL_MSGRESULT
, (LONG
)hwndTabCtrl
);
2936 msgResult
= PROPSHEET_CanSetCurSel(hwnd
);
2937 if(msgResult
!= FALSE
)
2939 msgResult
= PROPSHEET_SetCurSel(hwnd
,
2942 (HPROPSHEETPAGE
)lParam
);
2945 SetWindowLongW(hwnd
, DWL_MSGRESULT
, msgResult
);
2950 case PSM_CANCELTOCLOSE
:
2952 WCHAR buf
[MAX_BUTTONTEXT_LENGTH
];
2953 HWND hwndOK
= GetDlgItem(hwnd
, IDOK
);
2954 HWND hwndCancel
= GetDlgItem(hwnd
, IDCANCEL
);
2956 EnableWindow(hwndCancel
, FALSE
);
2957 if (LoadStringW(COMCTL32_hModule
, IDS_CLOSE
, buf
, sizeof(buf
)))
2958 SetWindowTextW(hwndOK
, buf
);
2963 case PSM_RESTARTWINDOWS
:
2965 PropSheetInfo
* psInfo
= (PropSheetInfo
*) GetPropW(hwnd
,
2968 psInfo
->restartWindows
= TRUE
;
2972 case PSM_REBOOTSYSTEM
:
2974 PropSheetInfo
* psInfo
= (PropSheetInfo
*) GetPropW(hwnd
,
2977 psInfo
->rebootSystem
= TRUE
;
2982 PROPSHEET_SetTitleA(hwnd
, (DWORD
) wParam
, (LPCSTR
) lParam
);
2986 PROPSHEET_SetTitleW(hwnd
, (DWORD
) wParam
, (LPCWSTR
) lParam
);
2991 BOOL msgResult
= PROPSHEET_Apply(hwnd
, 0);
2993 SetWindowLongW(hwnd
, DWL_MSGRESULT
, msgResult
);
2998 case PSM_QUERYSIBLINGS
:
3000 LRESULT msgResult
= PROPSHEET_QuerySiblings(hwnd
, wParam
, lParam
);
3002 SetWindowLongW(hwnd
, DWL_MSGRESULT
, msgResult
);
3010 * Note: MSVC++ 6.0 documentation says that PSM_ADDPAGE does not have
3011 * a return value. This is not true. PSM_ADDPAGE returns TRUE
3012 * on success or FALSE otherwise, as specified on MSDN Online.
3013 * Also see the MFC code for
3014 * CPropertySheet::AddPage(CPropertyPage* pPage).
3017 BOOL msgResult
= PROPSHEET_AddPage(hwnd
, (HPROPSHEETPAGE
)lParam
);
3019 SetWindowLongW(hwnd
, DWL_MSGRESULT
, msgResult
);
3024 case PSM_REMOVEPAGE
:
3025 PROPSHEET_RemovePage(hwnd
, (int)wParam
, (HPROPSHEETPAGE
)lParam
);
3028 case PSM_ISDIALOGMESSAGE
:
3030 BOOL msgResult
= PROPSHEET_IsDialogMessage(hwnd
, (LPMSG
)lParam
);
3031 SetWindowLongA(hwnd
, DWL_MSGRESULT
, msgResult
);
3035 case PSM_PRESSBUTTON
:
3036 PROPSHEET_PressButton(hwnd
, (int)wParam
);
3039 case PSM_SETFINISHTEXTA
:
3040 PROPSHEET_SetFinishTextA(hwnd
, (LPCSTR
) lParam
);
3043 case PSM_SETWIZBUTTONS
:
3044 PROPSHEET_SetWizButtons(hwnd
, (DWORD
)lParam
);
3047 case PSM_SETCURSELID
:
3048 PROPSHEET_SetCurSelId(hwnd
, (int)lParam
);
3051 case PSM_SETFINISHTEXTW
:
3052 PROPSHEET_SetFinishTextW(hwnd
, (LPCWSTR
) lParam
);