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
29 #define NONAMELESSUNION
30 #define NONAMELESSSTRUCT
40 #include "wine/debug.h"
41 #include "wine/unicode.h"
43 /******************************************************************************
67 } MyDLGITEMTEMPLATEEX
;
70 typedef struct tagPropPageInfo
72 HPROPSHEETPAGE hpage
; /* to keep track of pages not passed to PropertySheet */
81 typedef struct tagPropSheetInfo
84 PROPSHEETHEADERW ppshheader
;
86 LPWSTR strPropertiesFor
;
96 PropPageInfo
* proppage
;
101 HIMAGELIST hImageList
;
110 /******************************************************************************
111 * Defines and global variables
114 const WCHAR PropSheetInfoStr
[] =
115 {'P','r','o','p','e','r','t','y','S','h','e','e','t','I','n','f','o',0 };
117 #define PSP_INTERNAL_UNICODE 0x80000000
119 #define MAX_CAPTION_LENGTH 255
120 #define MAX_TABTEXT_LENGTH 255
121 #define MAX_BUTTONTEXT_LENGTH 64
123 #define INTRNL_ANY_WIZARD (PSH_WIZARD | PSH_WIZARD97_OLD | PSH_WIZARD97_NEW | PSH_WIZARD_LITE)
125 /******************************************************************************
128 static int PROPSHEET_CreateDialog(PropSheetInfo
* psInfo
);
129 static BOOL
PROPSHEET_SizeMismatch(HWND hwndDlg
, PropSheetInfo
* psInfo
);
130 static BOOL
PROPSHEET_AdjustSize(HWND hwndDlg
, PropSheetInfo
* psInfo
);
131 static BOOL
PROPSHEET_AdjustButtons(HWND hwndParent
, PropSheetInfo
* psInfo
);
132 static BOOL
PROPSHEET_CollectSheetInfoA(LPCPROPSHEETHEADERA lppsh
,
133 PropSheetInfo
* psInfo
);
134 static BOOL
PROPSHEET_CollectSheetInfoW(LPCPROPSHEETHEADERW lppsh
,
135 PropSheetInfo
* psInfo
);
136 static BOOL
PROPSHEET_CollectPageInfo(LPCPROPSHEETPAGEW lppsp
,
137 PropSheetInfo
* psInfo
,
139 static BOOL
PROPSHEET_CreateTabControl(HWND hwndParent
,
140 PropSheetInfo
* psInfo
);
141 static BOOL
PROPSHEET_CreatePage(HWND hwndParent
, int index
,
142 const PropSheetInfo
* psInfo
,
143 LPCPROPSHEETPAGEW ppshpage
);
144 static BOOL
PROPSHEET_ShowPage(HWND hwndDlg
, int index
, PropSheetInfo
* psInfo
);
145 static PADDING_INFO
PROPSHEET_GetPaddingInfo(HWND hwndDlg
);
146 static BOOL
PROPSHEET_Back(HWND hwndDlg
);
147 static BOOL
PROPSHEET_Next(HWND hwndDlg
);
148 static BOOL
PROPSHEET_Finish(HWND hwndDlg
);
149 static BOOL
PROPSHEET_Apply(HWND hwndDlg
, LPARAM lParam
);
150 static void PROPSHEET_Cancel(HWND hwndDlg
, LPARAM lParam
);
151 static void PROPSHEET_Help(HWND hwndDlg
);
152 static void PROPSHEET_Changed(HWND hwndDlg
, HWND hwndDirtyPage
);
153 static void PROPSHEET_UnChanged(HWND hwndDlg
, HWND hwndCleanPage
);
154 static void PROPSHEET_PressButton(HWND hwndDlg
, int buttonID
);
155 static void PROPSHEET_SetFinishTextA(HWND hwndDlg
, LPCSTR lpszText
);
156 static void PROPSHEET_SetFinishTextW(HWND hwndDlg
, LPCWSTR lpszText
);
157 static void PROPSHEET_SetTitleA(HWND hwndDlg
, DWORD dwStyle
, LPCSTR lpszText
);
158 static void PROPSHEET_SetTitleW(HWND hwndDlg
, DWORD dwStyle
, LPCWSTR lpszText
);
159 static BOOL
PROPSHEET_CanSetCurSel(HWND hwndDlg
);
160 static BOOL
PROPSHEET_SetCurSel(HWND hwndDlg
,
163 HPROPSHEETPAGE hpage
);
164 static void PROPSHEET_SetCurSelId(HWND hwndDlg
, int id
);
165 static LRESULT
PROPSHEET_QuerySiblings(HWND hwndDlg
,
166 WPARAM wParam
, LPARAM lParam
);
167 static BOOL
PROPSHEET_AddPage(HWND hwndDlg
,
168 HPROPSHEETPAGE hpage
);
170 static BOOL
PROPSHEET_RemovePage(HWND hwndDlg
,
172 HPROPSHEETPAGE hpage
);
173 static void PROPSHEET_CleanUp();
174 static int PROPSHEET_GetPageIndex(HPROPSHEETPAGE hpage
, PropSheetInfo
* psInfo
);
175 static void PROPSHEET_SetWizButtons(HWND hwndDlg
, DWORD dwFlags
);
176 static PADDING_INFO
PROPSHEET_GetPaddingInfoWizard(HWND hwndDlg
, const PropSheetInfo
* psInfo
);
177 static BOOL
PROPSHEET_IsDialogMessage(HWND hwnd
, LPMSG lpMsg
);
178 static BOOL
PROPSHEET_DoCommand(HWND hwnd
, WORD wID
);
181 PROPSHEET_DialogProc(HWND hwnd
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
);
183 WINE_DEFAULT_DEBUG_CHANNEL(propsheet
);
185 #define add_flag(a) if (dwFlags & a) {strcat(string, #a );strcat(string," ");}
186 /******************************************************************************
187 * PROPSHEET_UnImplementedFlags
189 * Document use of flags we don't implement yet.
191 static VOID
PROPSHEET_UnImplementedFlags(DWORD dwFlags
)
198 * unhandled header flags:
199 * PSH_DEFAULT 0x00000000
200 * PSH_WIZARDHASFINISH 0x00000010
201 * PSH_RTLREADING 0x00000800
202 * PSH_WIZARDCONTEXTHELP 0x00001000
203 * PSH_WIZARD97 0x00002000 (pre IE 5)
204 * PSH_WATERMARK 0x00008000
205 * PSH_USEHBMWATERMARK 0x00010000
206 * PSH_USEHPLWATERMARK 0x00020000
207 * PSH_STRETCHWATERMARK 0x00040000
208 * PSH_HEADER 0x00080000
209 * PSH_USEHBMHEADER 0x00100000
210 * PSH_USEPAGELANG 0x00200000
211 * PSH_WIZARD_LITE 0x00400000 also not in .h
212 * PSH_WIZARD97 0x01000000 (IE 5 and above)
213 * PSH_NOCONTEXTHELP 0x02000000 also not in .h
216 add_flag(PSH_WIZARDHASFINISH
);
217 add_flag(PSH_RTLREADING
);
218 add_flag(PSH_WIZARDCONTEXTHELP
);
219 add_flag(PSH_WIZARD97_OLD
);
220 add_flag(PSH_WATERMARK
);
221 add_flag(PSH_USEHBMWATERMARK
);
222 add_flag(PSH_USEHPLWATERMARK
);
223 add_flag(PSH_STRETCHWATERMARK
);
224 add_flag(PSH_HEADER
);
225 add_flag(PSH_USEHBMHEADER
);
226 add_flag(PSH_USEPAGELANG
);
227 add_flag(PSH_WIZARD_LITE
);
228 add_flag(PSH_WIZARD97_NEW
);
229 add_flag(PSH_NOCONTEXTHELP
);
230 if (string
[0] != '\0')
231 FIXME("%s\n", string
);
235 /******************************************************************************
236 * PROPSHEET_GetPageRect
238 * Retrieve rect from tab control and map into the dialog for SetWindowPos
240 static void PROPSHEET_GetPageRect(const PropSheetInfo
* psInfo
, HWND hwndDlg
, RECT
*rc
)
242 HWND hwndTabCtrl
= GetDlgItem(hwndDlg
, IDC_TABCONTROL
);
244 GetClientRect(hwndTabCtrl
, rc
);
245 SendMessageW(hwndTabCtrl
, TCM_ADJUSTRECT
, FALSE
, (LPARAM
)rc
);
246 MapWindowPoints(hwndTabCtrl
, hwndDlg
, (LPPOINT
)rc
, 2);
249 /******************************************************************************
250 * PROPSHEET_FindPageByResId
252 * Find page index corresponding to page resource id.
254 INT
PROPSHEET_FindPageByResId(PropSheetInfo
* psInfo
, LRESULT resId
)
258 for (i
= 0; i
< psInfo
->nPages
; i
++)
260 LPCPROPSHEETPAGEA lppsp
= (LPCPROPSHEETPAGEA
)psInfo
->proppage
[i
].hpage
;
262 /* Fixme: if resource ID is a string shall we use strcmp ??? */
263 if (lppsp
->u
.pszTemplate
== (LPVOID
)resId
)
270 /******************************************************************************
273 * Convert ASCII to Unicode since all data is saved as Unicode.
275 static void PROPSHEET_AtoW(LPCWSTR
*tostr
, LPCSTR frstr
)
279 TRACE("<%s>\n", frstr
);
280 len
= MultiByteToWideChar(CP_ACP
, 0, frstr
, -1, 0, 0);
281 *tostr
= (LPWSTR
)HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
282 MultiByteToWideChar(CP_ACP
, 0, frstr
, -1, (LPWSTR
)*tostr
, len
);
285 /******************************************************************************
286 * PROPSHEET_CollectSheetInfoA
288 * Collect relevant data.
290 static BOOL
PROPSHEET_CollectSheetInfoA(LPCPROPSHEETHEADERA lppsh
,
291 PropSheetInfo
* psInfo
)
293 DWORD dwSize
= min(lppsh
->dwSize
,sizeof(PROPSHEETHEADERA
));
294 DWORD dwFlags
= lppsh
->dwFlags
;
296 psInfo
->hasHelp
= dwFlags
& PSH_HASHELP
;
297 psInfo
->hasApply
= !(dwFlags
& PSH_NOAPPLYNOW
);
298 psInfo
->useCallback
= (dwFlags
& PSH_USECALLBACK
)&& (lppsh
->pfnCallback
);
299 psInfo
->isModeless
= dwFlags
& PSH_MODELESS
;
301 memcpy(&psInfo
->ppshheader
,lppsh
,dwSize
);
302 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",
303 lppsh
->dwSize
, lppsh
->dwFlags
, lppsh
->hwndParent
, lppsh
->hInstance
,
304 debugstr_a(lppsh
->pszCaption
), lppsh
->nPages
, lppsh
->pfnCallback
);
306 PROPSHEET_UnImplementedFlags(lppsh
->dwFlags
);
308 if (lppsh
->dwFlags
& INTRNL_ANY_WIZARD
)
309 psInfo
->ppshheader
.pszCaption
= NULL
;
312 if (HIWORD(lppsh
->pszCaption
))
314 int len
= strlen(lppsh
->pszCaption
);
315 psInfo
->ppshheader
.pszCaption
= HeapAlloc( GetProcessHeap(), 0, (len
+1)*sizeof (WCHAR
) );
316 MultiByteToWideChar(CP_ACP
, 0, lppsh
->pszCaption
, -1, (LPWSTR
) psInfo
->ppshheader
.pszCaption
, len
+1);
317 /* strcpy( (char *)psInfo->ppshheader.pszCaption, lppsh->pszCaption ); */
320 psInfo
->nPages
= lppsh
->nPages
;
322 if (dwFlags
& PSH_USEPSTARTPAGE
)
324 TRACE("PSH_USEPSTARTPAGE is on\n");
325 psInfo
->active_page
= 0;
328 psInfo
->active_page
= lppsh
->u2
.nStartPage
;
330 if (psInfo
->active_page
< 0 || psInfo
->active_page
>= psInfo
->nPages
)
331 psInfo
->active_page
= 0;
333 psInfo
->restartWindows
= FALSE
;
334 psInfo
->rebootSystem
= FALSE
;
335 psInfo
->hImageList
= 0;
336 psInfo
->activeValid
= FALSE
;
341 /******************************************************************************
342 * PROPSHEET_CollectSheetInfoW
344 * Collect relevant data.
346 static BOOL
PROPSHEET_CollectSheetInfoW(LPCPROPSHEETHEADERW lppsh
,
347 PropSheetInfo
* psInfo
)
349 DWORD dwSize
= min(lppsh
->dwSize
,sizeof(PROPSHEETHEADERW
));
350 DWORD dwFlags
= lppsh
->dwFlags
;
352 psInfo
->hasHelp
= dwFlags
& PSH_HASHELP
;
353 psInfo
->hasApply
= !(dwFlags
& PSH_NOAPPLYNOW
);
354 psInfo
->useCallback
= (dwFlags
& PSH_USECALLBACK
) && (lppsh
->pfnCallback
);
355 psInfo
->isModeless
= dwFlags
& PSH_MODELESS
;
357 memcpy(&psInfo
->ppshheader
,lppsh
,dwSize
);
358 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",
359 lppsh
->dwSize
, lppsh
->dwFlags
, lppsh
->hwndParent
, lppsh
->hInstance
, debugstr_w(lppsh
->pszCaption
), lppsh
->nPages
, lppsh
->pfnCallback
);
361 PROPSHEET_UnImplementedFlags(lppsh
->dwFlags
);
363 if (lppsh
->dwFlags
& INTRNL_ANY_WIZARD
)
364 psInfo
->ppshheader
.pszCaption
= NULL
;
367 if (!(lppsh
->dwFlags
& INTRNL_ANY_WIZARD
) && HIWORD(lppsh
->pszCaption
))
369 int len
= strlenW(lppsh
->pszCaption
);
370 psInfo
->ppshheader
.pszCaption
= HeapAlloc( GetProcessHeap(), 0, (len
+1)*sizeof(WCHAR
) );
371 strcpyW( (WCHAR
*)psInfo
->ppshheader
.pszCaption
, lppsh
->pszCaption
);
374 psInfo
->nPages
= lppsh
->nPages
;
376 if (dwFlags
& PSH_USEPSTARTPAGE
)
378 TRACE("PSH_USEPSTARTPAGE is on\n");
379 psInfo
->active_page
= 0;
382 psInfo
->active_page
= lppsh
->u2
.nStartPage
;
384 if (psInfo
->active_page
< 0 || psInfo
->active_page
>= psInfo
->nPages
)
385 psInfo
->active_page
= 0;
387 psInfo
->restartWindows
= FALSE
;
388 psInfo
->rebootSystem
= FALSE
;
389 psInfo
->hImageList
= 0;
390 psInfo
->activeValid
= FALSE
;
395 /******************************************************************************
396 * PROPSHEET_CollectPageInfo
398 * Collect property sheet data.
399 * With code taken from DIALOG_ParseTemplate32.
401 BOOL
PROPSHEET_CollectPageInfo(LPCPROPSHEETPAGEW lppsp
,
402 PropSheetInfo
* psInfo
,
405 DLGTEMPLATE
* pTemplate
;
411 psInfo
->proppage
[index
].hpage
= (HPROPSHEETPAGE
)lppsp
;
412 psInfo
->proppage
[index
].hwndPage
= 0;
413 psInfo
->proppage
[index
].isDirty
= FALSE
;
416 * Process property page flags.
418 dwFlags
= lppsp
->dwFlags
;
419 psInfo
->proppage
[index
].useCallback
= (dwFlags
& PSP_USECALLBACK
) && (lppsp
->pfnCallback
);
420 psInfo
->proppage
[index
].hasHelp
= dwFlags
& PSP_HASHELP
;
421 psInfo
->proppage
[index
].hasIcon
= dwFlags
& (PSP_USEHICON
| PSP_USEICONID
);
423 /* as soon as we have a page with the help flag, set the sheet flag on */
424 if (psInfo
->proppage
[index
].hasHelp
)
425 psInfo
->hasHelp
= TRUE
;
428 * Process page template.
430 if (dwFlags
& PSP_DLGINDIRECT
)
431 pTemplate
= (DLGTEMPLATE
*)lppsp
->u
.pResource
;
432 else if(dwFlags
& PSP_INTERNAL_UNICODE
)
434 HRSRC hResource
= FindResourceW(lppsp
->hInstance
,
435 lppsp
->u
.pszTemplate
,
437 HGLOBAL hTemplate
= LoadResource(lppsp
->hInstance
,
439 pTemplate
= (LPDLGTEMPLATEW
)LockResource(hTemplate
);
443 HRSRC hResource
= FindResourceA(lppsp
->hInstance
,
444 (LPSTR
)lppsp
->u
.pszTemplate
,
446 HGLOBAL hTemplate
= LoadResource(lppsp
->hInstance
,
448 pTemplate
= (LPDLGTEMPLATEA
)LockResource(hTemplate
);
452 * Extract the size of the page and the caption.
457 p
= (const WORD
*)pTemplate
;
459 if (((MyDLGTEMPLATEEX
*)pTemplate
)->signature
== 0xFFFF)
461 /* DLGTEMPLATEEX (not defined in any std. header file) */
465 p
+= 2; /* help ID */
466 p
+= 2; /* ext style */
474 p
+= 2; /* ext style */
480 width
= (WORD
)*p
; p
++;
481 height
= (WORD
)*p
; p
++;
483 /* remember the largest width and height */
484 if (width
> psInfo
->width
)
485 psInfo
->width
= width
;
487 if (height
> psInfo
->height
)
488 psInfo
->height
= height
;
500 p
+= lstrlenW( (LPCWSTR
)p
) + 1;
514 p
+= lstrlenW( (LPCWSTR
)p
) + 1;
518 /* Extract the caption */
519 psInfo
->proppage
[index
].pszText
= (LPCWSTR
)p
;
520 TRACE("Tab %d %s\n",index
,debugstr_w((LPCWSTR
)p
));
521 p
+= lstrlenW((LPCWSTR
)p
) + 1;
523 if (dwFlags
& PSP_USETITLE
)
527 static WCHAR pszNull
[] = { '(','n','u','l','l',')',0 };
530 if ( !HIWORD( lppsp
->pszTitle
) )
532 if (!LoadStringW( lppsp
->hInstance
, (UINT
)lppsp
->pszTitle
,szTitle
,sizeof(szTitle
) ))
535 FIXME("Could not load resource #%04x?\n",LOWORD(lppsp
->pszTitle
));
541 pTitle
= lppsp
->pszTitle
;
543 len
= strlenW(pTitle
);
544 psInfo
->proppage
[index
].pszText
= Alloc( (len
+1)*sizeof (WCHAR
) );
545 strcpyW( (LPWSTR
)psInfo
->proppage
[index
].pszText
,pTitle
);
549 * Build the image list for icons
551 if ((dwFlags
& PSP_USEHICON
) || (dwFlags
& PSP_USEICONID
))
554 int icon_cx
= GetSystemMetrics(SM_CXSMICON
);
555 int icon_cy
= GetSystemMetrics(SM_CYSMICON
);
557 if (dwFlags
& PSP_USEICONID
)
558 hIcon
= LoadImageW(lppsp
->hInstance
, lppsp
->u2
.pszIcon
, IMAGE_ICON
,
559 icon_cx
, icon_cy
, LR_DEFAULTCOLOR
);
561 hIcon
= lppsp
->u2
.hIcon
;
565 if (psInfo
->hImageList
== 0 )
566 psInfo
->hImageList
= ImageList_Create(icon_cx
, icon_cy
, ILC_COLOR
, 1, 1);
568 ImageList_AddIcon(psInfo
->hImageList
, hIcon
);
576 /******************************************************************************
577 * PROPSHEET_CreateDialog
579 * Creates the actual property sheet.
581 int PROPSHEET_CreateDialog(PropSheetInfo
* psInfo
)
588 WORD resID
= IDD_PROPSHEET
;
591 if (psInfo
->ppshheader
.dwFlags
& INTRNL_ANY_WIZARD
)
594 if( psInfo
->unicode
)
596 if(!(hRes
= FindResourceW(COMCTL32_hModule
,
597 MAKEINTRESOURCEW(resID
),
603 if(!(hRes
= FindResourceA(COMCTL32_hModule
,
604 MAKEINTRESOURCEA(resID
),
609 if(!(template = (LPVOID
)LoadResource(COMCTL32_hModule
, hRes
)))
613 * Make a copy of the dialog template.
615 resSize
= SizeofResource(COMCTL32_hModule
, hRes
);
617 temp
= Alloc(resSize
);
622 memcpy(temp
, template, resSize
);
624 if (psInfo
->useCallback
)
625 (*(psInfo
->ppshheader
.pfnCallback
))(0, PSCB_PRECREATE
, (LPARAM
)temp
);
627 if( psInfo
->unicode
)
629 if (!(psInfo
->ppshheader
.dwFlags
& PSH_MODELESS
))
630 ret
= DialogBoxIndirectParamW(psInfo
->ppshheader
.hInstance
,
631 (LPDLGTEMPLATEW
) temp
,
632 psInfo
->ppshheader
.hwndParent
,
633 PROPSHEET_DialogProc
,
637 ret
= (int)CreateDialogIndirectParamW(psInfo
->ppshheader
.hInstance
,
638 (LPDLGTEMPLATEW
) temp
,
639 psInfo
->ppshheader
.hwndParent
,
640 PROPSHEET_DialogProc
,
642 if ( !ret
) ret
= -1;
647 if (!(psInfo
->ppshheader
.dwFlags
& PSH_MODELESS
))
648 ret
= DialogBoxIndirectParamA(psInfo
->ppshheader
.hInstance
,
649 (LPDLGTEMPLATEA
) temp
,
650 psInfo
->ppshheader
.hwndParent
,
651 PROPSHEET_DialogProc
,
655 ret
= (int)CreateDialogIndirectParamA(psInfo
->ppshheader
.hInstance
,
656 (LPDLGTEMPLATEA
) temp
,
657 psInfo
->ppshheader
.hwndParent
,
658 PROPSHEET_DialogProc
,
660 if ( !ret
) ret
= -1;
669 /******************************************************************************
670 * PROPSHEET_SizeMismatch
672 * Verify that the tab control and the "largest" property sheet page dlg. template
675 static BOOL
PROPSHEET_SizeMismatch(HWND hwndDlg
, PropSheetInfo
* psInfo
)
677 HWND hwndTabCtrl
= GetDlgItem(hwndDlg
, IDC_TABCONTROL
);
678 RECT rcOrigTab
, rcPage
;
683 GetClientRect(hwndTabCtrl
, &rcOrigTab
);
684 TRACE("orig tab %ld %ld %ld %ld\n", rcOrigTab
.left
, rcOrigTab
.top
,
685 rcOrigTab
.right
, rcOrigTab
.bottom
);
690 rcPage
.left
= psInfo
->x
;
691 rcPage
.top
= psInfo
->y
;
692 rcPage
.right
= psInfo
->width
;
693 rcPage
.bottom
= psInfo
->height
;
695 MapDialogRect(hwndDlg
, &rcPage
);
696 TRACE("biggest page %ld %ld %ld %ld\n", rcPage
.left
, rcPage
.top
,
697 rcPage
.right
, rcPage
.bottom
);
699 if ( (rcPage
.right
- rcPage
.left
) != (rcOrigTab
.right
- rcOrigTab
.left
) )
701 if ( (rcPage
.bottom
- rcPage
.top
) != (rcOrigTab
.bottom
- rcOrigTab
.top
) )
707 /******************************************************************************
708 * PROPSHEET_IsTooSmallWizard
710 * Verify that the default property sheet is big enough.
712 static BOOL
PROPSHEET_IsTooSmallWizard(HWND hwndDlg
, PropSheetInfo
* psInfo
)
714 RECT rcSheetRect
, rcPage
, rcLine
, rcSheetClient
;
715 HWND hwndLine
= GetDlgItem(hwndDlg
, IDC_SUNKEN_LINE
);
716 PADDING_INFO padding
= PROPSHEET_GetPaddingInfoWizard(hwndDlg
, psInfo
);
718 GetClientRect(hwndDlg
, &rcSheetClient
);
719 GetWindowRect(hwndDlg
, &rcSheetRect
);
720 GetWindowRect(hwndLine
, &rcLine
);
722 /* Remove the space below the sunken line */
723 rcSheetClient
.bottom
-= (rcSheetRect
.bottom
- rcLine
.top
);
725 /* Remove the buffer zone all around the edge */
726 rcSheetClient
.bottom
-= (padding
.y
* 2);
727 rcSheetClient
.right
-= (padding
.x
* 2);
732 rcPage
.left
= psInfo
->x
;
733 rcPage
.top
= psInfo
->y
;
734 rcPage
.right
= psInfo
->width
;
735 rcPage
.bottom
= psInfo
->height
;
737 MapDialogRect(hwndDlg
, &rcPage
);
738 TRACE("biggest page %ld %ld %ld %ld\n", rcPage
.left
, rcPage
.top
,
739 rcPage
.right
, rcPage
.bottom
);
741 if (rcPage
.right
> rcSheetClient
.right
)
744 if (rcPage
.bottom
> rcSheetClient
.bottom
)
750 /******************************************************************************
751 * PROPSHEET_AdjustSize
753 * Resizes the property sheet and the tab control to fit the largest page.
755 static BOOL
PROPSHEET_AdjustSize(HWND hwndDlg
, PropSheetInfo
* psInfo
)
757 HWND hwndTabCtrl
= GetDlgItem(hwndDlg
, IDC_TABCONTROL
);
758 HWND hwndButton
= GetDlgItem(hwndDlg
, IDOK
);
760 int tabOffsetX
, tabOffsetY
, buttonHeight
;
761 PADDING_INFO padding
= PROPSHEET_GetPaddingInfo(hwndDlg
);
764 /* Get the height of buttons */
765 GetClientRect(hwndButton
, &rc
);
766 buttonHeight
= rc
.bottom
;
773 rc
.right
= psInfo
->width
;
774 rc
.bottom
= psInfo
->height
;
776 MapDialogRect(hwndDlg
, &rc
);
778 /* retrieve the dialog units */
779 units
.left
= units
.right
= 4;
780 units
.top
= units
.bottom
= 8;
781 MapDialogRect(hwndDlg
, &units
);
784 * Resize the tab control.
786 GetClientRect(hwndTabCtrl
,&tabRect
);
788 SendMessageW(hwndTabCtrl
, TCM_ADJUSTRECT
, FALSE
, (LPARAM
)&tabRect
);
790 if ((rc
.bottom
- rc
.top
) < (tabRect
.bottom
- tabRect
.top
))
792 rc
.bottom
= rc
.top
+ tabRect
.bottom
- tabRect
.top
;
793 psInfo
->height
= MulDiv((rc
.bottom
- rc
.top
),8,units
.top
);
796 if ((rc
.right
- rc
.left
) < (tabRect
.right
- tabRect
.left
))
798 rc
.right
= rc
.left
+ tabRect
.right
- tabRect
.left
;
799 psInfo
->width
= MulDiv((rc
.right
- rc
.left
),4,units
.left
);
802 SendMessageW(hwndTabCtrl
, TCM_ADJUSTRECT
, TRUE
, (LPARAM
)&rc
);
804 tabOffsetX
= -(rc
.left
);
805 tabOffsetY
= -(rc
.top
);
809 TRACE("setting tab %08lx, rc (0,0)-(%ld,%ld)\n",
810 (DWORD
)hwndTabCtrl
, rc
.right
, rc
.bottom
);
811 SetWindowPos(hwndTabCtrl
, 0, 0, 0, rc
.right
, rc
.bottom
,
812 SWP_NOMOVE
| SWP_NOZORDER
| SWP_NOACTIVATE
);
814 GetClientRect(hwndTabCtrl
, &rc
);
816 TRACE("tab client rc %ld %ld %ld %ld\n",
817 rc
.left
, rc
.top
, rc
.right
, rc
.bottom
);
819 rc
.right
+= ((padding
.x
* 2) + tabOffsetX
);
820 rc
.bottom
+= (buttonHeight
+ (3 * padding
.y
) + tabOffsetY
);
823 * Resize the property sheet.
825 TRACE("setting dialog %08lx, rc (0,0)-(%ld,%ld)\n",
826 (DWORD
)hwndDlg
, rc
.right
, rc
.bottom
);
827 SetWindowPos(hwndDlg
, 0, 0, 0, rc
.right
, rc
.bottom
,
828 SWP_NOMOVE
| SWP_NOZORDER
| SWP_NOACTIVATE
);
832 /******************************************************************************
833 * PROPSHEET_AdjustSizeWizard
835 * Resizes the property sheet to fit the largest page.
837 static BOOL
PROPSHEET_AdjustSizeWizard(HWND hwndDlg
, PropSheetInfo
* psInfo
)
839 HWND hwndButton
= GetDlgItem(hwndDlg
, IDCANCEL
);
840 HWND hwndLine
= GetDlgItem(hwndDlg
, IDC_SUNKEN_LINE
);
841 HWND hwndTabCtrl
= GetDlgItem(hwndDlg
, IDC_TABCONTROL
);
843 int buttonHeight
, lineHeight
;
844 PADDING_INFO padding
= PROPSHEET_GetPaddingInfoWizard(hwndDlg
, psInfo
);
847 /* Get the height of buttons */
848 GetClientRect(hwndButton
, &rc
);
849 buttonHeight
= rc
.bottom
;
851 GetClientRect(hwndLine
, &rc
);
852 lineHeight
= rc
.bottom
;
854 /* retrieve the dialog units */
855 units
.left
= units
.right
= 4;
856 units
.top
= units
.bottom
= 8;
857 MapDialogRect(hwndDlg
, &units
);
864 rc
.right
= psInfo
->width
;
865 rc
.bottom
= psInfo
->height
;
867 MapDialogRect(hwndDlg
, &rc
);
869 GetClientRect(hwndTabCtrl
,&tabRect
);
871 if ((rc
.bottom
- rc
.top
) < (tabRect
.bottom
- tabRect
.top
))
873 rc
.bottom
= rc
.top
+ tabRect
.bottom
- tabRect
.top
;
874 psInfo
->height
= MulDiv((rc
.bottom
- rc
.top
), 8, units
.top
);
877 if ((rc
.right
- rc
.left
) < (tabRect
.right
- tabRect
.left
))
879 rc
.right
= rc
.left
+ tabRect
.right
- tabRect
.left
;
880 psInfo
->width
= MulDiv((rc
.right
- rc
.left
), 4, units
.left
);
883 TRACE("Biggest page %ld %ld %ld %ld\n", rc
.left
, rc
.top
, rc
.right
, rc
.bottom
);
884 TRACE(" constants padx=%d, pady=%d, butH=%d, lH=%d\n",
885 padding
.x
, padding
.y
, buttonHeight
, lineHeight
);
888 rc
.right
+= (padding
.x
* 2);
889 rc
.bottom
+= (buttonHeight
+ (5 * padding
.y
) + lineHeight
);
892 * Resize the property sheet.
894 TRACE("setting dialog %08lx, rc (0,0)-(%ld,%ld)\n",
895 (DWORD
)hwndDlg
, rc
.right
, rc
.bottom
);
896 SetWindowPos(hwndDlg
, 0, 0, 0, rc
.right
, rc
.bottom
,
897 SWP_NOMOVE
| SWP_NOZORDER
| SWP_NOACTIVATE
);
901 /******************************************************************************
902 * PROPSHEET_AdjustButtons
904 * Adjusts the buttons' positions.
906 static BOOL
PROPSHEET_AdjustButtons(HWND hwndParent
, PropSheetInfo
* psInfo
)
908 HWND hwndButton
= GetDlgItem(hwndParent
, IDOK
);
912 int buttonWidth
, buttonHeight
;
913 PADDING_INFO padding
= PROPSHEET_GetPaddingInfo(hwndParent
);
915 if (psInfo
->hasApply
)
922 * Obtain the size of the buttons.
924 GetClientRect(hwndButton
, &rcSheet
);
925 buttonWidth
= rcSheet
.right
;
926 buttonHeight
= rcSheet
.bottom
;
929 * Get the size of the property sheet.
931 GetClientRect(hwndParent
, &rcSheet
);
934 * All buttons will be at this y coordinate.
936 y
= rcSheet
.bottom
- (padding
.y
+ buttonHeight
);
939 * Position OK button.
941 hwndButton
= GetDlgItem(hwndParent
, IDOK
);
943 x
= rcSheet
.right
- ((padding
.x
+ buttonWidth
) * num_buttons
);
945 SetWindowPos(hwndButton
, 0, x
, y
, 0, 0,
946 SWP_NOSIZE
| SWP_NOZORDER
| SWP_NOACTIVATE
);
949 * Position Cancel button.
951 hwndButton
= GetDlgItem(hwndParent
, IDCANCEL
);
953 x
= rcSheet
.right
- ((padding
.x
+ buttonWidth
) * (num_buttons
- 1));
955 SetWindowPos(hwndButton
, 0, x
, y
, 0, 0,
956 SWP_NOSIZE
| SWP_NOZORDER
| SWP_NOACTIVATE
);
959 * Position Apply button.
961 hwndButton
= GetDlgItem(hwndParent
, IDC_APPLY_BUTTON
);
963 if (psInfo
->hasApply
)
966 x
= rcSheet
.right
- ((padding
.x
+ buttonWidth
) * 2);
968 x
= rcSheet
.right
- (padding
.x
+ buttonWidth
);
970 SetWindowPos(hwndButton
, 0, x
, y
, 0, 0,
971 SWP_NOSIZE
| SWP_NOZORDER
| SWP_NOACTIVATE
);
973 EnableWindow(hwndButton
, FALSE
);
976 ShowWindow(hwndButton
, SW_HIDE
);
979 * Position Help button.
981 hwndButton
= GetDlgItem(hwndParent
, IDHELP
);
985 x
= rcSheet
.right
- (padding
.x
+ buttonWidth
);
987 SetWindowPos(hwndButton
, 0, x
, y
, 0, 0,
988 SWP_NOSIZE
| SWP_NOZORDER
| SWP_NOACTIVATE
);
991 ShowWindow(hwndButton
, SW_HIDE
);
996 /******************************************************************************
997 * PROPSHEET_AdjustButtonsWizard
999 * Adjusts the buttons' positions.
1001 static BOOL
PROPSHEET_AdjustButtonsWizard(HWND hwndParent
,
1002 PropSheetInfo
* psInfo
)
1004 HWND hwndButton
= GetDlgItem(hwndParent
, IDCANCEL
);
1005 HWND hwndLine
= GetDlgItem(hwndParent
, IDC_SUNKEN_LINE
);
1008 int num_buttons
= 3;
1009 int buttonWidth
, buttonHeight
, lineHeight
, lineWidth
;
1010 PADDING_INFO padding
= PROPSHEET_GetPaddingInfoWizard(hwndParent
, psInfo
);
1012 if (psInfo
->hasHelp
)
1016 * Obtain the size of the buttons.
1018 GetClientRect(hwndButton
, &rcSheet
);
1019 buttonWidth
= rcSheet
.right
;
1020 buttonHeight
= rcSheet
.bottom
;
1022 GetClientRect(hwndLine
, &rcSheet
);
1023 lineHeight
= rcSheet
.bottom
;
1026 * Get the size of the property sheet.
1028 GetClientRect(hwndParent
, &rcSheet
);
1031 * All buttons will be at this y coordinate.
1033 y
= rcSheet
.bottom
- (padding
.y
+ buttonHeight
);
1036 * Position the Next and the Finish buttons.
1038 hwndButton
= GetDlgItem(hwndParent
, IDC_NEXT_BUTTON
);
1040 x
= rcSheet
.right
- ((padding
.x
+ buttonWidth
) * (num_buttons
- 1));
1042 SetWindowPos(hwndButton
, 0, x
, y
, 0, 0,
1043 SWP_NOSIZE
| SWP_NOZORDER
| SWP_NOACTIVATE
);
1045 hwndButton
= GetDlgItem(hwndParent
, IDC_FINISH_BUTTON
);
1047 SetWindowPos(hwndButton
, 0, x
, y
, 0, 0,
1048 SWP_NOSIZE
| SWP_NOZORDER
| SWP_NOACTIVATE
);
1050 ShowWindow(hwndButton
, SW_HIDE
);
1053 * Position the Back button.
1055 hwndButton
= GetDlgItem(hwndParent
, IDC_BACK_BUTTON
);
1059 SetWindowPos(hwndButton
, 0, x
, y
, 0, 0,
1060 SWP_NOSIZE
| SWP_NOZORDER
| SWP_NOACTIVATE
);
1063 * Position the Cancel button.
1065 hwndButton
= GetDlgItem(hwndParent
, IDCANCEL
);
1067 x
= rcSheet
.right
- ((padding
.x
+ buttonWidth
) * (num_buttons
- 2));
1069 SetWindowPos(hwndButton
, 0, x
, y
, 0, 0,
1070 SWP_NOSIZE
| SWP_NOZORDER
| SWP_NOACTIVATE
);
1073 * Position Help button.
1075 hwndButton
= GetDlgItem(hwndParent
, IDHELP
);
1077 if (psInfo
->hasHelp
)
1079 x
= rcSheet
.right
- (padding
.x
+ buttonWidth
);
1081 SetWindowPos(hwndButton
, 0, x
, y
, 0, 0,
1082 SWP_NOSIZE
| SWP_NOZORDER
| SWP_NOACTIVATE
);
1085 ShowWindow(hwndButton
, SW_HIDE
);
1088 * Position and resize the sunken line.
1091 y
= rcSheet
.bottom
- ((padding
.y
* 2) + buttonHeight
+ lineHeight
);
1093 GetClientRect(hwndParent
, &rcSheet
);
1094 lineWidth
= rcSheet
.right
- (padding
.x
* 2);
1096 SetWindowPos(hwndLine
, 0, x
, y
, lineWidth
, 2,
1097 SWP_NOZORDER
| SWP_NOACTIVATE
);
1102 /******************************************************************************
1103 * PROPSHEET_GetPaddingInfo
1105 * Returns the layout information.
1107 static PADDING_INFO
PROPSHEET_GetPaddingInfo(HWND hwndDlg
)
1109 HWND hwndTab
= GetDlgItem(hwndDlg
, IDC_TABCONTROL
);
1112 PADDING_INFO padding
;
1114 GetWindowRect(hwndTab
, &rcTab
);
1119 ScreenToClient(hwndDlg
, &tl
);
1127 /******************************************************************************
1128 * PROPSHEET_GetPaddingInfoWizard
1130 * Returns the layout information.
1131 * Vertical spacing is the distance between the line and the buttons.
1132 * Do NOT use the Help button to gather padding information when it isn't mapped
1133 * (PSH_HASHELP), as app writers aren't forced to supply correct coordinates
1134 * for it in this case !
1135 * FIXME: I'm not sure about any other coordinate problems with these evil
1136 * buttons. Fix it in case additional problems appear or maybe calculate
1137 * a padding in a completely different way, as this is somewhat messy.
1139 static PADDING_INFO
PROPSHEET_GetPaddingInfoWizard(HWND hwndDlg
, const PropSheetInfo
*
1142 PADDING_INFO padding
;
1146 POINT ptButton
, ptLine
;
1149 if (psInfo
->hasHelp
)
1155 if (psInfo
->ppshheader
.dwFlags
& INTRNL_ANY_WIZARD
)
1157 idButton
= IDC_NEXT_BUTTON
;
1161 /* hopefully this is ok */
1162 idButton
= IDCANCEL
;
1166 hwndControl
= GetDlgItem(hwndDlg
, idButton
);
1167 GetWindowRect(hwndControl
, &rc
);
1169 ptButton
.x
= rc
.left
;
1170 ptButton
.y
= rc
.top
;
1172 ScreenToClient(hwndDlg
, &ptButton
);
1175 hwndControl
= GetDlgItem(hwndDlg
, IDC_SUNKEN_LINE
);
1176 GetWindowRect(hwndControl
, &rc
);
1179 ptLine
.y
= rc
.bottom
;
1181 ScreenToClient(hwndDlg
, &ptLine
);
1183 padding
.y
= ptButton
.y
- ptLine
.y
;
1186 ERR("padding negative ! Please report this !\n");
1188 /* this is most probably not correct, but the best we have now */
1189 padding
.x
= padding
.y
;
1193 /******************************************************************************
1194 * PROPSHEET_CreateTabControl
1196 * Insert the tabs in the tab control.
1198 static BOOL
PROPSHEET_CreateTabControl(HWND hwndParent
,
1199 PropSheetInfo
* psInfo
)
1201 HWND hwndTabCtrl
= GetDlgItem(hwndParent
, IDC_TABCONTROL
);
1207 item
.mask
= TCIF_TEXT
;
1208 item
.cchTextMax
= MAX_TABTEXT_LENGTH
;
1210 nTabs
= psInfo
->nPages
;
1213 * Set the image list for icons.
1215 if (psInfo
->hImageList
)
1217 SendMessageW(hwndTabCtrl
, TCM_SETIMAGELIST
, 0, (LPARAM
)psInfo
->hImageList
);
1220 SendMessageW(GetDlgItem(hwndTabCtrl
, IDC_TABCONTROL
), WM_SETREDRAW
, 0, 0);
1221 for (i
= 0; i
< nTabs
; i
++)
1223 if ( psInfo
->proppage
[i
].hasIcon
)
1225 item
.mask
|= TCIF_IMAGE
;
1226 item
.iImage
= iImage
++;
1230 item
.mask
&= ~TCIF_IMAGE
;
1233 item
.pszText
= (LPWSTR
) psInfo
->proppage
[i
].pszText
;
1234 SendMessageW(hwndTabCtrl
, TCM_INSERTITEMW
, (WPARAM
)i
, (LPARAM
)&item
);
1236 SendMessageW(GetDlgItem(hwndTabCtrl
, IDC_TABCONTROL
), WM_SETREDRAW
, 1, 0);
1241 * Get the size of an in-memory Template
1243 *( Based on the code of PROPSHEET_CollectPageInfo)
1244 * See also dialog.c/DIALOG_ParseTemplate32().
1247 static UINT
GetTemplateSize(DLGTEMPLATE
* pTemplate
)
1250 const WORD
* p
= (const WORD
*)pTemplate
;
1251 BOOL istemplateex
= (((MyDLGTEMPLATEEX
*)pTemplate
)->signature
== 0xFFFF);
1256 /* DLGTEMPLATEEX (not defined in any std. header file) */
1258 TRACE("is DLGTEMPLATEEX\n");
1260 p
++; /* signature */
1261 p
+= 2; /* help ID */
1262 p
+= 2; /* ext style */
1269 TRACE("is DLGTEMPLATE\n");
1271 p
+= 2; /* ext style */
1274 nrofitems
= (WORD
)*p
; p
++; /* nb items */
1290 TRACE("menu %s\n",debugstr_w((LPCWSTR
)p
));
1291 p
+= lstrlenW( (LPCWSTR
)p
) + 1;
1302 p
+= 2; /* 0xffff plus predefined window class ordinal value */
1305 TRACE("class %s\n",debugstr_w((LPCWSTR
)p
));
1306 p
+= lstrlenW( (LPCWSTR
)p
) + 1;
1311 TRACE("title %s\n",debugstr_w((LPCWSTR
)p
));
1312 p
+= lstrlenW((LPCWSTR
)p
) + 1;
1314 /* font, if DS_SETFONT set */
1315 if ((DS_SETFONT
& ((istemplateex
)? ((MyDLGTEMPLATEEX
*)pTemplate
)->style
:
1318 p
+=(istemplateex
)?3:1;
1319 TRACE("font %s\n",debugstr_w((LPCWSTR
)p
));
1320 p
+= lstrlenW( (LPCWSTR
)p
) + 1; /* the font name */
1323 /* now process the DLGITEMTEMPLATE(EX) structs (plus custom data)
1324 * that are following the DLGTEMPLATE(EX) data */
1325 TRACE("%d items\n",nrofitems
);
1326 while (nrofitems
> 0)
1328 p
= (WORD
*)(((DWORD
)p
+ 3) & ~3); /* DWORD align */
1331 p
+= (istemplateex
? sizeof(MyDLGITEMTEMPLATEEX
) : sizeof(DLGITEMTEMPLATE
))/sizeof(WORD
);
1340 TRACE("class ordinal 0x%08lx\n",*(DWORD
*)p
);
1344 TRACE("class %s\n",debugstr_w((LPCWSTR
)p
));
1345 p
+= lstrlenW( (LPCWSTR
)p
) + 1;
1349 /* check title text */
1356 TRACE("text ordinal 0x%08lx\n",*(DWORD
*)p
);
1360 TRACE("text %s\n",debugstr_w((LPCWSTR
)p
));
1361 p
+= lstrlenW( (LPCWSTR
)p
) + 1;
1364 p
+= *p
+ 1; /* Skip extra data */
1368 TRACE("%p %p size 0x%08x\n",p
, (WORD
*)pTemplate
,sizeof(WORD
)*(p
- (WORD
*)pTemplate
));
1369 return (p
- (WORD
*)pTemplate
)*sizeof(WORD
);
1373 /******************************************************************************
1374 * PROPSHEET_CreatePage
1378 static BOOL
PROPSHEET_CreatePage(HWND hwndParent
,
1380 const PropSheetInfo
* psInfo
,
1381 LPCPROPSHEETPAGEW ppshpage
)
1383 DLGTEMPLATE
* pTemplate
;
1386 PADDING_INFO padding
;
1387 UINT pageWidth
,pageHeight
;
1391 TRACE("index %d\n", index
);
1393 if (ppshpage
== NULL
)
1398 if (ppshpage
->dwFlags
& PSP_DLGINDIRECT
)
1400 pTemplate
= (DLGTEMPLATE
*)ppshpage
->u
.pResource
;
1401 resSize
= GetTemplateSize(pTemplate
);
1403 else if(ppshpage
->dwFlags
& PSP_INTERNAL_UNICODE
)
1408 hResource
= FindResourceW(ppshpage
->hInstance
,
1409 ppshpage
->u
.pszTemplate
,
1414 resSize
= SizeofResource(ppshpage
->hInstance
, hResource
);
1416 hTemplate
= LoadResource(ppshpage
->hInstance
, hResource
);
1420 pTemplate
= (LPDLGTEMPLATEW
)LockResource(hTemplate
);
1422 * Make a copy of the dialog template to make it writable
1430 hResource
= FindResourceA(ppshpage
->hInstance
,
1431 (LPSTR
)ppshpage
->u
.pszTemplate
,
1436 resSize
= SizeofResource(ppshpage
->hInstance
, hResource
);
1438 hTemplate
= LoadResource(ppshpage
->hInstance
, hResource
);
1442 pTemplate
= (LPDLGTEMPLATEA
)LockResource(hTemplate
);
1444 * Make a copy of the dialog template to make it writable
1447 temp
= Alloc(resSize
);
1451 TRACE("copying pTemplate %p into temp %p (%ld)\n", pTemplate
, temp
, resSize
);
1452 memcpy(temp
, pTemplate
, resSize
);
1455 if (((MyDLGTEMPLATEEX
*)pTemplate
)->signature
== 0xFFFF)
1457 ((MyDLGTEMPLATEEX
*)pTemplate
)->style
|= WS_CHILD
| DS_CONTROL
;
1458 ((MyDLGTEMPLATEEX
*)pTemplate
)->style
&= ~DS_MODALFRAME
;
1459 ((MyDLGTEMPLATEEX
*)pTemplate
)->style
&= ~WS_CAPTION
;
1460 ((MyDLGTEMPLATEEX
*)pTemplate
)->style
&= ~WS_SYSMENU
;
1461 ((MyDLGTEMPLATEEX
*)pTemplate
)->style
&= ~WS_POPUP
;
1462 ((MyDLGTEMPLATEEX
*)pTemplate
)->style
&= ~WS_DISABLED
;
1463 ((MyDLGTEMPLATEEX
*)pTemplate
)->style
&= ~WS_VISIBLE
;
1464 ((MyDLGTEMPLATEEX
*)pTemplate
)->style
&= ~WS_THICKFRAME
;
1468 pTemplate
->style
|= WS_CHILD
| DS_CONTROL
;
1469 pTemplate
->style
&= ~DS_MODALFRAME
;
1470 pTemplate
->style
&= ~WS_CAPTION
;
1471 pTemplate
->style
&= ~WS_SYSMENU
;
1472 pTemplate
->style
&= ~WS_POPUP
;
1473 pTemplate
->style
&= ~WS_DISABLED
;
1474 pTemplate
->style
&= ~WS_VISIBLE
;
1475 pTemplate
->style
&= ~WS_THICKFRAME
;
1478 if (psInfo
->proppage
[index
].useCallback
)
1479 (*(ppshpage
->pfnCallback
))(0, PSPCB_CREATE
,
1480 (LPPROPSHEETPAGEW
)ppshpage
);
1482 if(ppshpage
->dwFlags
& PSP_INTERNAL_UNICODE
)
1483 hwndPage
= CreateDialogIndirectParamW(ppshpage
->hInstance
,
1486 ppshpage
->pfnDlgProc
,
1489 hwndPage
= CreateDialogIndirectParamA(ppshpage
->hInstance
,
1492 ppshpage
->pfnDlgProc
,
1494 /* Free a no more needed copy */
1498 psInfo
->proppage
[index
].hwndPage
= hwndPage
;
1500 if (psInfo
->ppshheader
.dwFlags
& INTRNL_ANY_WIZARD
) {
1501 /* FIXME: This code may no longer be correct.
1502 * It was not for the non-wizard path. (GLA 6/02)
1504 rc
.left
= psInfo
->x
;
1506 rc
.right
= psInfo
->width
;
1507 rc
.bottom
= psInfo
->height
;
1509 MapDialogRect(hwndParent
, &rc
);
1511 pageWidth
= rc
.right
- rc
.left
;
1512 pageHeight
= rc
.bottom
- rc
.top
;
1514 padding
= PROPSHEET_GetPaddingInfoWizard(hwndParent
, psInfo
);
1515 TRACE("setting page %08lx, rc (%ld,%ld)-(%ld,%ld) w=%d, h=%d, padx=%d, pady=%d\n",
1516 (DWORD
)hwndPage
, rc
.left
, rc
.top
, rc
.right
, rc
.bottom
,
1517 pageWidth
, pageHeight
, padding
.x
, padding
.y
);
1518 SetWindowPos(hwndPage
, HWND_TOP
,
1519 rc
.left
+ padding
.x
/2,
1520 rc
.top
+ padding
.y
/2,
1521 pageWidth
, pageHeight
, 0);
1525 * Ask the Tab control to reduce the client rectangle to that
1528 PROPSHEET_GetPageRect(psInfo
, hwndParent
, &rc
);
1529 pageWidth
= rc
.right
- rc
.left
;
1530 pageHeight
= rc
.bottom
- rc
.top
;
1531 TRACE("setting page %08lx, rc (%ld,%ld)-(%ld,%ld) w=%d, h=%d\n",
1532 (DWORD
)hwndPage
, rc
.left
, rc
.top
, rc
.right
, rc
.bottom
,
1533 pageWidth
, pageHeight
);
1534 SetWindowPos(hwndPage
, HWND_TOP
,
1536 pageWidth
, pageHeight
, 0);
1542 /******************************************************************************
1543 * PROPSHEET_ShowPage
1545 * Displays or creates the specified page.
1547 static BOOL
PROPSHEET_ShowPage(HWND hwndDlg
, int index
, PropSheetInfo
* psInfo
)
1551 TRACE("active_page %d, index %d\n", psInfo
->active_page
, index
);
1552 if (index
== psInfo
->active_page
)
1554 if (GetTopWindow(hwndDlg
) != psInfo
->proppage
[index
].hwndPage
)
1555 SetWindowPos(psInfo
->proppage
[index
].hwndPage
, HWND_TOP
, 0, 0, 0, 0, SWP_NOSIZE
| SWP_NOMOVE
);
1559 if (psInfo
->proppage
[index
].hwndPage
== 0)
1561 LPCPROPSHEETPAGEW ppshpage
;
1563 ppshpage
= (LPCPROPSHEETPAGEW
)psInfo
->proppage
[index
].hpage
;
1564 PROPSHEET_CreatePage(hwndDlg
, index
, psInfo
, ppshpage
);
1567 PROPSHEET_SetTitleW(hwndDlg
, psInfo
->ppshheader
.dwFlags
,
1568 psInfo
->proppage
[index
].pszText
);
1570 if (psInfo
->active_page
!= -1)
1571 ShowWindow(psInfo
->proppage
[psInfo
->active_page
].hwndPage
, SW_HIDE
);
1573 ShowWindow(psInfo
->proppage
[index
].hwndPage
, SW_SHOW
);
1575 /* Synchronize current selection with tab control
1576 * It seems to be needed even in case of PSH_WIZARD (no tab controls there) */
1577 hwndTabCtrl
= GetDlgItem(hwndDlg
, IDC_TABCONTROL
);
1578 SendMessageW(hwndTabCtrl
, TCM_SETCURSEL
, index
, 0);
1580 psInfo
->active_page
= index
;
1581 psInfo
->activeValid
= TRUE
;
1586 /******************************************************************************
1589 static BOOL
PROPSHEET_Back(HWND hwndDlg
)
1593 PropSheetInfo
* psInfo
= (PropSheetInfo
*) GetPropW(hwndDlg
,
1598 TRACE("active_page %d\n", psInfo
->active_page
);
1599 if (psInfo
->active_page
< 0)
1602 psn
.hdr
.code
= PSN_WIZBACK
;
1603 psn
.hdr
.hwndFrom
= hwndDlg
;
1607 hwndPage
= psInfo
->proppage
[psInfo
->active_page
].hwndPage
;
1609 result
= SendMessageW(hwndPage
, WM_NOTIFY
, 0, (LPARAM
) &psn
);
1612 else if (result
== 0)
1613 idx
= psInfo
->active_page
- 1;
1615 idx
= PROPSHEET_FindPageByResId(psInfo
, result
);
1617 if (idx
>= 0 && idx
< psInfo
->nPages
)
1619 if (PROPSHEET_CanSetCurSel(hwndDlg
))
1620 PROPSHEET_SetCurSel(hwndDlg
, idx
, -1, 0);
1625 /******************************************************************************
1628 static BOOL
PROPSHEET_Next(HWND hwndDlg
)
1632 LRESULT msgResult
= 0;
1633 PropSheetInfo
* psInfo
= (PropSheetInfo
*) GetPropW(hwndDlg
,
1637 TRACE("active_page %d\n", psInfo
->active_page
);
1638 if (psInfo
->active_page
< 0)
1641 psn
.hdr
.code
= PSN_WIZNEXT
;
1642 psn
.hdr
.hwndFrom
= hwndDlg
;
1646 hwndPage
= psInfo
->proppage
[psInfo
->active_page
].hwndPage
;
1648 msgResult
= SendMessageA(hwndPage
, WM_NOTIFY
, 0, (LPARAM
) &psn
);
1649 if (msgResult
== -1)
1651 else if (msgResult
== 0)
1652 idx
= psInfo
->active_page
+ 1;
1654 idx
= PROPSHEET_FindPageByResId(psInfo
, msgResult
);
1656 if (idx
< psInfo
->nPages
)
1658 if (PROPSHEET_CanSetCurSel(hwndDlg
) != FALSE
)
1659 PROPSHEET_SetCurSel(hwndDlg
, idx
, 1, 0);
1665 /******************************************************************************
1668 static BOOL
PROPSHEET_Finish(HWND hwndDlg
)
1672 LRESULT msgResult
= 0;
1673 PropSheetInfo
* psInfo
= (PropSheetInfo
*) GetPropW(hwndDlg
,
1676 TRACE("active_page %d\n", psInfo
->active_page
);
1677 if (psInfo
->active_page
< 0)
1680 psn
.hdr
.code
= PSN_WIZFINISH
;
1681 psn
.hdr
.hwndFrom
= hwndDlg
;
1685 hwndPage
= psInfo
->proppage
[psInfo
->active_page
].hwndPage
;
1687 msgResult
= SendMessageW(hwndPage
, WM_NOTIFY
, 0, (LPARAM
) &psn
);
1689 TRACE("msg result %ld\n", msgResult
);
1694 if (psInfo
->isModeless
)
1695 psInfo
->activeValid
= FALSE
;
1697 EndDialog(hwndDlg
, TRUE
);
1702 /******************************************************************************
1705 static BOOL
PROPSHEET_Apply(HWND hwndDlg
, LPARAM lParam
)
1710 PropSheetInfo
* psInfo
= (PropSheetInfo
*) GetPropW(hwndDlg
,
1713 TRACE("active_page %d\n", psInfo
->active_page
);
1714 if (psInfo
->active_page
< 0)
1717 psn
.hdr
.hwndFrom
= hwndDlg
;
1723 * Send PSN_KILLACTIVE to the current page.
1725 psn
.hdr
.code
= PSN_KILLACTIVE
;
1727 hwndPage
= psInfo
->proppage
[psInfo
->active_page
].hwndPage
;
1729 if (SendMessageA(hwndPage
, WM_NOTIFY
, 0, (LPARAM
) &psn
) != FALSE
)
1733 * Send PSN_APPLY to all pages.
1735 psn
.hdr
.code
= PSN_APPLY
;
1736 psn
.lParam
= lParam
;
1738 for (i
= 0; i
< psInfo
->nPages
; i
++)
1740 hwndPage
= psInfo
->proppage
[i
].hwndPage
;
1743 switch (SendMessageA(hwndPage
, WM_NOTIFY
, 0, (LPARAM
) &psn
))
1745 case PSNRET_INVALID
:
1746 PROPSHEET_ShowPage(hwndDlg
, i
, psInfo
);
1748 case PSNRET_INVALID_NOCHANGEPAGE
:
1756 psInfo
->activeValid
= FALSE
;
1758 else if(psInfo
->active_page
>= 0)
1760 psn
.hdr
.code
= PSN_SETACTIVE
;
1762 hwndPage
= psInfo
->proppage
[psInfo
->active_page
].hwndPage
;
1763 SendMessageA(hwndPage
, WM_NOTIFY
, 0, (LPARAM
) &psn
);
1769 /******************************************************************************
1772 static void PROPSHEET_Cancel(HWND hwndDlg
, LPARAM lParam
)
1774 PropSheetInfo
* psInfo
= (PropSheetInfo
*) GetPropW(hwndDlg
,
1780 TRACE("active_page %d\n", psInfo
->active_page
);
1781 if (psInfo
->active_page
< 0)
1784 hwndPage
= psInfo
->proppage
[psInfo
->active_page
].hwndPage
;
1785 psn
.hdr
.code
= PSN_QUERYCANCEL
;
1786 psn
.hdr
.hwndFrom
= hwndDlg
;
1790 if (SendMessageA(hwndPage
, WM_NOTIFY
, 0, (LPARAM
) &psn
))
1793 psn
.hdr
.code
= PSN_RESET
;
1794 psn
.lParam
= lParam
;
1796 for (i
= 0; i
< psInfo
->nPages
; i
++)
1798 hwndPage
= psInfo
->proppage
[i
].hwndPage
;
1801 SendMessageA(hwndPage
, WM_NOTIFY
, 0, (LPARAM
) &psn
);
1804 if (psInfo
->isModeless
)
1806 /* makes PSM_GETCURRENTPAGEHWND return NULL */
1807 psInfo
->activeValid
= FALSE
;
1810 EndDialog(hwndDlg
, FALSE
);
1813 /******************************************************************************
1816 static void PROPSHEET_Help(HWND hwndDlg
)
1818 PropSheetInfo
* psInfo
= (PropSheetInfo
*) GetPropW(hwndDlg
,
1823 TRACE("active_page %d\n", psInfo
->active_page
);
1824 if (psInfo
->active_page
< 0)
1827 hwndPage
= psInfo
->proppage
[psInfo
->active_page
].hwndPage
;
1828 psn
.hdr
.code
= PSN_HELP
;
1829 psn
.hdr
.hwndFrom
= hwndDlg
;
1833 SendMessageA(hwndPage
, WM_NOTIFY
, 0, (LPARAM
) &psn
);
1836 /******************************************************************************
1839 static void PROPSHEET_Changed(HWND hwndDlg
, HWND hwndDirtyPage
)
1842 PropSheetInfo
* psInfo
= (PropSheetInfo
*) GetPropW(hwndDlg
,
1846 if (!psInfo
) return;
1848 * Set the dirty flag of this page.
1850 for (i
= 0; i
< psInfo
->nPages
; i
++)
1852 if (psInfo
->proppage
[i
].hwndPage
== hwndDirtyPage
)
1853 psInfo
->proppage
[i
].isDirty
= TRUE
;
1857 * Enable the Apply button.
1859 if (psInfo
->hasApply
)
1861 HWND hwndApplyBtn
= GetDlgItem(hwndDlg
, IDC_APPLY_BUTTON
);
1863 EnableWindow(hwndApplyBtn
, TRUE
);
1867 /******************************************************************************
1868 * PROPSHEET_UnChanged
1870 static void PROPSHEET_UnChanged(HWND hwndDlg
, HWND hwndCleanPage
)
1873 BOOL noPageDirty
= TRUE
;
1874 HWND hwndApplyBtn
= GetDlgItem(hwndDlg
, IDC_APPLY_BUTTON
);
1875 PropSheetInfo
* psInfo
= (PropSheetInfo
*) GetPropW(hwndDlg
,
1879 if ( !psInfo
) return;
1880 for (i
= 0; i
< psInfo
->nPages
; i
++)
1882 /* set the specified page as clean */
1883 if (psInfo
->proppage
[i
].hwndPage
== hwndCleanPage
)
1884 psInfo
->proppage
[i
].isDirty
= FALSE
;
1886 /* look to see if there's any dirty pages */
1887 if (psInfo
->proppage
[i
].isDirty
)
1888 noPageDirty
= FALSE
;
1892 * Disable Apply button.
1895 EnableWindow(hwndApplyBtn
, FALSE
);
1898 /******************************************************************************
1899 * PROPSHEET_PressButton
1901 static void PROPSHEET_PressButton(HWND hwndDlg
, int buttonID
)
1903 TRACE("buttonID %d\n", buttonID
);
1906 case PSBTN_APPLYNOW
:
1907 PROPSHEET_DoCommand(hwndDlg
, IDC_APPLY_BUTTON
);
1910 PROPSHEET_Back(hwndDlg
);
1913 PROPSHEET_DoCommand(hwndDlg
, IDCANCEL
);
1916 PROPSHEET_Finish(hwndDlg
);
1919 PROPSHEET_DoCommand(hwndDlg
, IDHELP
);
1922 PROPSHEET_Next(hwndDlg
);
1925 PROPSHEET_DoCommand(hwndDlg
, IDOK
);
1928 FIXME("Invalid button index %d\n", buttonID
);
1933 /*************************************************************************
1934 * BOOL PROPSHEET_CanSetCurSel [Internal]
1936 * Test whether the current page can be changed by sending a PSN_KILLACTIVE
1939 * hwndDlg [I] handle to a Dialog hWnd
1942 * TRUE if Current Selection can change
1946 static BOOL
PROPSHEET_CanSetCurSel(HWND hwndDlg
)
1948 PropSheetInfo
* psInfo
= (PropSheetInfo
*) GetPropW(hwndDlg
,
1954 TRACE("active_page %d\n", psInfo
->active_page
);
1961 if (psInfo
->active_page
< 0)
1968 * Notify the current page.
1970 hwndPage
= psInfo
->proppage
[psInfo
->active_page
].hwndPage
;
1971 psn
.hdr
.code
= PSN_KILLACTIVE
;
1972 psn
.hdr
.hwndFrom
= hwndDlg
;
1976 res
= !SendMessageA(hwndPage
, WM_NOTIFY
, 0, (LPARAM
) &psn
);
1979 TRACE("<-- %d\n", res
);
1983 /******************************************************************************
1984 * PROPSHEET_SetCurSel
1986 static BOOL
PROPSHEET_SetCurSel(HWND hwndDlg
,
1989 HPROPSHEETPAGE hpage
1992 PropSheetInfo
* psInfo
= (PropSheetInfo
*) GetPropW(hwndDlg
, PropSheetInfoStr
);
1993 HWND hwndHelp
= GetDlgItem(hwndDlg
, IDHELP
);
1994 HWND hwndTabControl
= GetDlgItem(hwndDlg
, IDC_TABCONTROL
);
1996 TRACE("index %d, skipdir %d, hpage %p\n", index
, skipdir
, hpage
);
1997 /* hpage takes precedence over index */
1999 index
= PROPSHEET_GetPageIndex(hpage
, psInfo
);
2001 if (index
< 0 || index
>= psInfo
->nPages
)
2003 TRACE("Could not find page to select!\n");
2012 SendMessageW(hwndTabControl
, TCM_SETCURSEL
, index
, 0);
2014 psn
.hdr
.code
= PSN_SETACTIVE
;
2015 psn
.hdr
.hwndFrom
= hwndDlg
;
2019 if (!psInfo
->proppage
[index
].hwndPage
) {
2020 LPCPROPSHEETPAGEW ppshpage
= (LPCPROPSHEETPAGEW
)psInfo
->proppage
[index
].hpage
;
2021 PROPSHEET_CreatePage(hwndDlg
, index
, psInfo
, ppshpage
);
2024 result
= SendMessageW(psInfo
->proppage
[index
].hwndPage
, WM_NOTIFY
, 0, (LPARAM
) &psn
);
2031 WARN("Tried to skip before first property sheet page!\n");
2034 if (index
>= psInfo
->nPages
) {
2035 WARN("Tried to skip after last property sheet page!\n");
2036 index
= psInfo
->nPages
-1;
2040 else if (result
!= 0)
2042 int old_index
= index
;
2043 index
= PROPSHEET_FindPageByResId(psInfo
, result
);
2044 if(index
>= psInfo
->nPages
) {
2046 WARN("Tried to skip to nonexistant page by res id\n");
2053 * Display the new page.
2055 PROPSHEET_ShowPage(hwndDlg
, index
, psInfo
);
2057 if (psInfo
->proppage
[index
].hasHelp
)
2058 EnableWindow(hwndHelp
, TRUE
);
2060 EnableWindow(hwndHelp
, FALSE
);
2065 /******************************************************************************
2066 * PROPSHEET_SetCurSelId
2068 * Selects the page, specified by resource id.
2070 static void PROPSHEET_SetCurSelId(HWND hwndDlg
, int id
)
2073 PropSheetInfo
* psInfo
=
2074 (PropSheetInfo
*) GetPropW(hwndDlg
, PropSheetInfoStr
);
2076 idx
= PROPSHEET_FindPageByResId(psInfo
, id
);
2077 if (idx
< psInfo
->nPages
)
2079 if (PROPSHEET_CanSetCurSel(hwndDlg
) != FALSE
)
2080 PROPSHEET_SetCurSel(hwndDlg
, idx
, 1, 0);
2084 /******************************************************************************
2085 * PROPSHEET_SetTitleA
2087 static void PROPSHEET_SetTitleA(HWND hwndDlg
, DWORD dwStyle
, LPCSTR lpszText
)
2089 if(HIWORD(lpszText
))
2092 MultiByteToWideChar(CP_ACP
, 0, lpszText
, -1,
2093 szTitle
, sizeof(szTitle
));
2094 PROPSHEET_SetTitleW(hwndDlg
, dwStyle
, szTitle
);
2098 PROPSHEET_SetTitleW(hwndDlg
, dwStyle
, (LPCWSTR
)lpszText
);
2102 /******************************************************************************
2103 * PROPSHEET_SetTitleW
2105 static void PROPSHEET_SetTitleW(HWND hwndDlg
, DWORD dwStyle
, LPCWSTR lpszText
)
2107 PropSheetInfo
* psInfo
= (PropSheetInfo
*) GetPropW(hwndDlg
, PropSheetInfoStr
);
2110 TRACE("'%s' (style %08lx)\n", debugstr_w(lpszText
), dwStyle
);
2111 if (HIWORD(lpszText
) == 0) {
2112 if (!LoadStringW(psInfo
->ppshheader
.hInstance
,
2113 LOWORD(lpszText
), szTitle
, sizeof(szTitle
)-sizeof(WCHAR
)))
2117 if (dwStyle
& PSH_PROPTITLE
)
2120 int lentitle
= strlenW(lpszText
);
2121 int lenprop
= strlenW(psInfo
->strPropertiesFor
);
2123 dest
= Alloc( (lentitle
+ lenprop
+ 1)*sizeof (WCHAR
));
2124 strcpyW(dest
, psInfo
->strPropertiesFor
);
2125 strcatW(dest
, lpszText
);
2127 SetWindowTextW(hwndDlg
, dest
);
2131 SetWindowTextW(hwndDlg
, lpszText
);
2134 /******************************************************************************
2135 * PROPSHEET_SetFinishTextA
2137 static void PROPSHEET_SetFinishTextA(HWND hwndDlg
, LPCSTR lpszText
)
2139 HWND hwndButton
= GetDlgItem(hwndDlg
, IDC_FINISH_BUTTON
);
2141 TRACE("'%s'\n", lpszText
);
2142 /* Set text, show and enable the Finish button */
2143 SetWindowTextA(hwndButton
, lpszText
);
2144 ShowWindow(hwndButton
, SW_SHOW
);
2145 EnableWindow(hwndButton
, TRUE
);
2147 /* Make it default pushbutton */
2148 SendMessageA(hwndDlg
, DM_SETDEFID
, IDC_FINISH_BUTTON
, 0);
2150 /* Hide Back button */
2151 hwndButton
= GetDlgItem(hwndDlg
, IDC_BACK_BUTTON
);
2152 ShowWindow(hwndButton
, SW_HIDE
);
2154 /* Hide Next button */
2155 hwndButton
= GetDlgItem(hwndDlg
, IDC_NEXT_BUTTON
);
2156 ShowWindow(hwndButton
, SW_HIDE
);
2159 /******************************************************************************
2160 * PROPSHEET_SetFinishTextW
2162 static void PROPSHEET_SetFinishTextW(HWND hwndDlg
, LPCWSTR lpszText
)
2164 HWND hwndButton
= GetDlgItem(hwndDlg
, IDC_FINISH_BUTTON
);
2166 TRACE("'%s'\n", debugstr_w(lpszText
));
2167 /* Set text, show and enable the Finish button */
2168 SetWindowTextW(hwndButton
, lpszText
);
2169 ShowWindow(hwndButton
, SW_SHOW
);
2170 EnableWindow(hwndButton
, TRUE
);
2172 /* Make it default pushbutton */
2173 SendMessageW(hwndDlg
, DM_SETDEFID
, IDC_FINISH_BUTTON
, 0);
2175 /* Hide Back button */
2176 hwndButton
= GetDlgItem(hwndDlg
, IDC_BACK_BUTTON
);
2177 ShowWindow(hwndButton
, SW_HIDE
);
2179 /* Hide Next button */
2180 hwndButton
= GetDlgItem(hwndDlg
, IDC_NEXT_BUTTON
);
2181 ShowWindow(hwndButton
, SW_HIDE
);
2184 /******************************************************************************
2185 * PROPSHEET_QuerySiblings
2187 static LRESULT
PROPSHEET_QuerySiblings(HWND hwndDlg
,
2188 WPARAM wParam
, LPARAM lParam
)
2192 LRESULT msgResult
= 0;
2193 PropSheetInfo
* psInfo
= (PropSheetInfo
*) GetPropW(hwndDlg
,
2196 while ((i
< psInfo
->nPages
) && (msgResult
== 0))
2198 hwndPage
= psInfo
->proppage
[i
].hwndPage
;
2199 msgResult
= SendMessageA(hwndPage
, PSM_QUERYSIBLINGS
, wParam
, lParam
);
2207 /******************************************************************************
2210 static BOOL
PROPSHEET_AddPage(HWND hwndDlg
,
2211 HPROPSHEETPAGE hpage
)
2213 PropSheetInfo
* psInfo
= (PropSheetInfo
*) GetPropW(hwndDlg
,
2215 HWND hwndTabControl
= GetDlgItem(hwndDlg
, IDC_TABCONTROL
);
2217 LPCPROPSHEETPAGEW ppsp
= (LPCPROPSHEETPAGEW
)hpage
;
2219 TRACE("hpage %p\n", hpage
);
2221 * Allocate and fill in a new PropPageInfo entry.
2223 psInfo
->proppage
= (PropPageInfo
*) ReAlloc(psInfo
->proppage
,
2224 sizeof(PropPageInfo
) *
2225 (psInfo
->nPages
+ 1));
2226 if (!PROPSHEET_CollectPageInfo(ppsp
, psInfo
, psInfo
->nPages
))
2229 psInfo
->proppage
[psInfo
->nPages
].hpage
= hpage
;
2231 if (ppsp
->dwFlags
& PSP_PREMATURE
)
2233 /* Create the page but don't show it */
2234 PROPSHEET_CreatePage(hwndDlg
, psInfo
->nPages
, psInfo
, ppsp
);
2238 * Add a new tab to the tab control.
2240 item
.mask
= TCIF_TEXT
;
2241 item
.pszText
= (LPWSTR
) psInfo
->proppage
[psInfo
->nPages
].pszText
;
2242 item
.cchTextMax
= MAX_TABTEXT_LENGTH
;
2244 if (psInfo
->hImageList
)
2246 SendMessageW(hwndTabControl
, TCM_SETIMAGELIST
, 0, (LPARAM
)psInfo
->hImageList
);
2249 if ( psInfo
->proppage
[psInfo
->nPages
].hasIcon
)
2251 item
.mask
|= TCIF_IMAGE
;
2252 item
.iImage
= psInfo
->nPages
;
2255 SendMessageW(hwndTabControl
, TCM_INSERTITEMW
, psInfo
->nPages
+ 1,
2260 /* If it is the only page - show it */
2261 if(psInfo
->nPages
== 1)
2262 PROPSHEET_SetCurSel(hwndDlg
, 0, 1, 0);
2266 /******************************************************************************
2267 * PROPSHEET_RemovePage
2269 static BOOL
PROPSHEET_RemovePage(HWND hwndDlg
,
2271 HPROPSHEETPAGE hpage
)
2273 PropSheetInfo
* psInfo
= (PropSheetInfo
*) GetPropW(hwndDlg
,
2275 HWND hwndTabControl
= GetDlgItem(hwndDlg
, IDC_TABCONTROL
);
2276 PropPageInfo
* oldPages
;
2278 TRACE("index %d, hpage %p\n", index
, hpage
);
2283 * hpage takes precedence over index.
2287 index
= PROPSHEET_GetPageIndex(hpage
, psInfo
);
2290 /* Make sure that index is within range */
2291 if (index
< 0 || index
>= psInfo
->nPages
)
2293 TRACE("Could not find page to remove!\n");
2297 TRACE("total pages %d removing page %d active page %d\n",
2298 psInfo
->nPages
, index
, psInfo
->active_page
);
2300 * Check if we're removing the active page.
2302 if (index
== psInfo
->active_page
)
2304 if (psInfo
->nPages
> 1)
2308 /* activate previous page */
2309 PROPSHEET_SetCurSel(hwndDlg
, index
- 1, -1, 0);
2313 /* activate the next page */
2314 PROPSHEET_SetCurSel(hwndDlg
, index
+ 1, 1, 0);
2315 psInfo
->active_page
= index
;
2320 psInfo
->active_page
= -1;
2321 if (!psInfo
->isModeless
)
2323 EndDialog(hwndDlg
, FALSE
);
2328 else if (index
< psInfo
->active_page
)
2329 psInfo
->active_page
--;
2331 /* Destroy page dialog window */
2332 DestroyWindow(psInfo
->proppage
[index
].hwndPage
);
2334 /* Free page resources */
2335 if(psInfo
->proppage
[index
].hpage
)
2337 PROPSHEETPAGEW
* psp
= (PROPSHEETPAGEW
*)psInfo
->proppage
[index
].hpage
;
2339 if ((psp
->dwFlags
& PSP_USETITLE
) && psInfo
->proppage
[index
].pszText
)
2340 HeapFree(GetProcessHeap(), 0, (LPVOID
)psInfo
->proppage
[index
].pszText
);
2342 DestroyPropertySheetPage(psInfo
->proppage
[index
].hpage
);
2345 /* Remove the tab */
2346 SendMessageW(hwndTabControl
, TCM_DELETEITEM
, index
, 0);
2348 oldPages
= psInfo
->proppage
;
2350 psInfo
->proppage
= Alloc(sizeof(PropPageInfo
) * psInfo
->nPages
);
2353 memcpy(&psInfo
->proppage
[0], &oldPages
[0], index
* sizeof(PropPageInfo
));
2355 if (index
< psInfo
->nPages
)
2356 memcpy(&psInfo
->proppage
[index
], &oldPages
[index
+ 1],
2357 (psInfo
->nPages
- index
) * sizeof(PropPageInfo
));
2364 /******************************************************************************
2365 * PROPSHEET_SetWizButtons
2367 * This code will work if (and assumes that) the Next button is on top of the
2368 * Finish button. ie. Finish comes after Next in the Z order.
2369 * This means make sure the dialog template reflects this.
2372 static void PROPSHEET_SetWizButtons(HWND hwndDlg
, DWORD dwFlags
)
2374 HWND hwndBack
= GetDlgItem(hwndDlg
, IDC_BACK_BUTTON
);
2375 HWND hwndNext
= GetDlgItem(hwndDlg
, IDC_NEXT_BUTTON
);
2376 HWND hwndFinish
= GetDlgItem(hwndDlg
, IDC_FINISH_BUTTON
);
2378 TRACE("%ld\n", dwFlags
);
2380 EnableWindow(hwndBack
, FALSE
);
2381 EnableWindow(hwndNext
, FALSE
);
2382 EnableWindow(hwndFinish
, FALSE
);
2384 if (dwFlags
& PSWIZB_BACK
)
2385 EnableWindow(hwndBack
, TRUE
);
2387 if (dwFlags
& PSWIZB_NEXT
)
2389 /* Hide the Finish button */
2390 ShowWindow(hwndFinish
, SW_HIDE
);
2392 /* Show and enable the Next button */
2393 ShowWindow(hwndNext
, SW_SHOW
);
2394 EnableWindow(hwndNext
, TRUE
);
2396 /* Set the Next button as the default pushbutton */
2397 SendMessageA(hwndDlg
, DM_SETDEFID
, IDC_NEXT_BUTTON
, 0);
2400 if ((dwFlags
& PSWIZB_FINISH
) || (dwFlags
& PSWIZB_DISABLEDFINISH
))
2402 /* Hide the Next button */
2403 ShowWindow(hwndNext
, SW_HIDE
);
2405 /* Show the Finish button */
2406 ShowWindow(hwndFinish
, SW_SHOW
);
2408 if (dwFlags
& PSWIZB_FINISH
)
2409 EnableWindow(hwndFinish
, TRUE
);
2411 /* Set the Finish button as the default pushbutton */
2412 SendMessageA(hwndDlg
, DM_SETDEFID
, IDC_FINISH_BUTTON
, 0);
2416 /******************************************************************************
2417 * PROPSHEET_GetPageIndex
2419 * Given a HPROPSHEETPAGE, returns the index of the corresponding page from
2420 * the array of PropPageInfo.
2422 static int PROPSHEET_GetPageIndex(HPROPSHEETPAGE hpage
, PropSheetInfo
* psInfo
)
2427 TRACE("hpage %p\n", hpage
);
2428 while ((index
< psInfo
->nPages
) && (found
== FALSE
))
2430 if (psInfo
->proppage
[index
].hpage
== hpage
)
2442 /******************************************************************************
2445 static void PROPSHEET_CleanUp(HWND hwndDlg
)
2448 PropSheetInfo
* psInfo
= (PropSheetInfo
*) RemovePropW(hwndDlg
,
2452 if (!psInfo
) return;
2453 if (HIWORD(psInfo
->ppshheader
.pszCaption
))
2454 HeapFree(GetProcessHeap(), 0, (LPVOID
)psInfo
->ppshheader
.pszCaption
);
2456 for (i
= 0; i
< psInfo
->nPages
; i
++)
2458 PROPSHEETPAGEA
* psp
= (PROPSHEETPAGEA
*)psInfo
->proppage
[i
].hpage
;
2460 if(psInfo
->proppage
[i
].hwndPage
)
2461 DestroyWindow(psInfo
->proppage
[i
].hwndPage
);
2465 if ((psp
->dwFlags
& PSP_USETITLE
) && psInfo
->proppage
[i
].pszText
)
2466 HeapFree(GetProcessHeap(), 0, (LPVOID
)psInfo
->proppage
[i
].pszText
);
2468 DestroyPropertySheetPage(psInfo
->proppage
[i
].hpage
);
2472 Free(psInfo
->proppage
);
2473 Free(psInfo
->strPropertiesFor
);
2474 ImageList_Destroy(psInfo
->hImageList
);
2476 GlobalFree((HGLOBAL
)psInfo
);
2479 /******************************************************************************
2480 * PropertySheet (COMCTL32.@)
2481 * PropertySheetA (COMCTL32.@)
2483 * Creates a property sheet in the specified property sheet header.
2486 * Modal property sheets: Positive if successful or -1 otherwise.
2487 * Modeless property sheets: Property sheet handle.
2489 *| ID_PSREBOOTSYSTEM - The user must reboot the computer for the changes to take effect.
2490 *| ID_PSRESTARTWINDOWS - The user must restart Windows for the changes to take effect.
2492 INT WINAPI
PropertySheetA(LPCPROPSHEETHEADERA lppsh
)
2495 PropSheetInfo
* psInfo
= (PropSheetInfo
*) GlobalAlloc(GPTR
,
2496 sizeof(PropSheetInfo
));
2500 TRACE("(%p)\n", lppsh
);
2502 PROPSHEET_CollectSheetInfoA(lppsh
, psInfo
);
2504 psInfo
->proppage
= (PropPageInfo
*) Alloc(sizeof(PropPageInfo
) *
2506 pByte
= (BYTE
*) psInfo
->ppshheader
.u3
.ppsp
;
2508 for (n
= i
= 0; i
< lppsh
->nPages
; i
++, n
++)
2510 if (!(lppsh
->dwFlags
& PSH_PROPSHEETPAGE
))
2511 psInfo
->proppage
[n
].hpage
= psInfo
->ppshheader
.u3
.phpage
[i
];
2514 psInfo
->proppage
[n
].hpage
= CreatePropertySheetPageA((LPCPROPSHEETPAGEA
)pByte
);
2515 pByte
+= ((LPPROPSHEETPAGEA
)pByte
)->dwSize
;
2518 if (!PROPSHEET_CollectPageInfo((LPCPROPSHEETPAGEW
)psInfo
->proppage
[n
].hpage
,
2521 if (lppsh
->dwFlags
& PSH_PROPSHEETPAGE
)
2522 DestroyPropertySheetPage(psInfo
->proppage
[n
].hpage
);
2528 psInfo
->unicode
= FALSE
;
2529 bRet
= PROPSHEET_CreateDialog(psInfo
);
2534 /******************************************************************************
2535 * PropertySheetW (COMCTL32.@)
2537 * See PropertySheetA.
2539 INT WINAPI
PropertySheetW(LPCPROPSHEETHEADERW lppsh
)
2542 PropSheetInfo
* psInfo
= (PropSheetInfo
*) GlobalAlloc(GPTR
,
2543 sizeof(PropSheetInfo
));
2547 TRACE("(%p)\n", lppsh
);
2549 PROPSHEET_CollectSheetInfoW(lppsh
, psInfo
);
2551 psInfo
->proppage
= (PropPageInfo
*) Alloc(sizeof(PropPageInfo
) *
2553 pByte
= (BYTE
*) psInfo
->ppshheader
.u3
.ppsp
;
2555 for (n
= i
= 0; i
< lppsh
->nPages
; i
++, n
++)
2557 if (!(lppsh
->dwFlags
& PSH_PROPSHEETPAGE
))
2558 psInfo
->proppage
[n
].hpage
= psInfo
->ppshheader
.u3
.phpage
[i
];
2561 psInfo
->proppage
[n
].hpage
= CreatePropertySheetPageW((LPCPROPSHEETPAGEW
)pByte
);
2562 pByte
+= ((LPPROPSHEETPAGEW
)pByte
)->dwSize
;
2565 if (!PROPSHEET_CollectPageInfo((LPCPROPSHEETPAGEW
)psInfo
->proppage
[n
].hpage
,
2568 if (lppsh
->dwFlags
& PSH_PROPSHEETPAGE
)
2569 DestroyPropertySheetPage(psInfo
->proppage
[n
].hpage
);
2575 psInfo
->unicode
= TRUE
;
2576 bRet
= PROPSHEET_CreateDialog(psInfo
);
2581 /******************************************************************************
2582 * CreatePropertySheetPage (COMCTL32.@)
2583 * CreatePropertySheetPageA (COMCTL32.@)
2585 * Creates a new property sheet page.
2588 * Success: Handle to new property sheet page.
2592 * An application must use the PSM_ADDPAGE message to add the new page to
2593 * an existing property sheet.
2595 HPROPSHEETPAGE WINAPI
CreatePropertySheetPageA(
2596 LPCPROPSHEETPAGEA lpPropSheetPage
)
2598 PROPSHEETPAGEW
* ppsp
= Alloc(sizeof(PROPSHEETPAGEW
));
2600 memcpy(ppsp
,lpPropSheetPage
,min(lpPropSheetPage
->dwSize
,sizeof(PROPSHEETPAGEA
)));
2602 ppsp
->dwFlags
&= ~ PSP_INTERNAL_UNICODE
;
2603 if ( !(ppsp
->dwFlags
& PSP_DLGINDIRECT
) && HIWORD( ppsp
->u
.pszTemplate
) )
2605 int len
= strlen(lpPropSheetPage
->u
.pszTemplate
);
2607 ppsp
->u
.pszTemplate
= HeapAlloc( GetProcessHeap(),0,len
+1 );
2608 strcpy( (LPSTR
)ppsp
->u
.pszTemplate
, lpPropSheetPage
->u
.pszTemplate
);
2610 if ( (ppsp
->dwFlags
& PSP_USEICONID
) && HIWORD( ppsp
->u2
.pszIcon
) )
2612 PROPSHEET_AtoW(&ppsp
->u2
.pszIcon
, lpPropSheetPage
->u2
.pszIcon
);
2615 if ((ppsp
->dwFlags
& PSP_USETITLE
) && HIWORD( ppsp
->pszTitle
))
2617 PROPSHEET_AtoW(&ppsp
->pszTitle
, lpPropSheetPage
->pszTitle
);
2619 else if ( !(ppsp
->dwFlags
& PSP_USETITLE
) )
2620 ppsp
->pszTitle
= NULL
;
2622 return (HPROPSHEETPAGE
)ppsp
;
2625 /******************************************************************************
2626 * CreatePropertySheetPageW (COMCTL32.@)
2628 * See CreatePropertySheetA.
2630 HPROPSHEETPAGE WINAPI
CreatePropertySheetPageW(LPCPROPSHEETPAGEW lpPropSheetPage
)
2632 PROPSHEETPAGEW
* ppsp
= Alloc(sizeof(PROPSHEETPAGEW
));
2634 memcpy(ppsp
,lpPropSheetPage
,min(lpPropSheetPage
->dwSize
,sizeof(PROPSHEETPAGEW
)));
2636 ppsp
->dwFlags
|= PSP_INTERNAL_UNICODE
;
2638 if ( !(ppsp
->dwFlags
& PSP_DLGINDIRECT
) && HIWORD( ppsp
->u
.pszTemplate
) )
2640 int len
= strlenW(lpPropSheetPage
->u
.pszTemplate
);
2642 ppsp
->u
.pszTemplate
= HeapAlloc( GetProcessHeap(),0,(len
+1)*sizeof (WCHAR
) );
2643 strcpyW( (WCHAR
*)ppsp
->u
.pszTemplate
, lpPropSheetPage
->u
.pszTemplate
);
2645 if ( (ppsp
->dwFlags
& PSP_USEICONID
) && HIWORD( ppsp
->u2
.pszIcon
) )
2647 int len
= strlenW(lpPropSheetPage
->u2
.pszIcon
);
2648 ppsp
->u2
.pszIcon
= HeapAlloc( GetProcessHeap(), 0, (len
+1)*sizeof (WCHAR
) );
2649 strcpyW( (WCHAR
*)ppsp
->u2
.pszIcon
, lpPropSheetPage
->u2
.pszIcon
);
2652 if ((ppsp
->dwFlags
& PSP_USETITLE
) && HIWORD( ppsp
->pszTitle
))
2654 int len
= strlenW(lpPropSheetPage
->pszTitle
);
2655 ppsp
->pszTitle
= HeapAlloc( GetProcessHeap(), 0, (len
+1)*sizeof (WCHAR
) );
2656 strcpyW( (WCHAR
*)ppsp
->pszTitle
, lpPropSheetPage
->pszTitle
);
2658 else if ( !(ppsp
->dwFlags
& PSP_USETITLE
) )
2659 ppsp
->pszTitle
= NULL
;
2661 return (HPROPSHEETPAGE
)ppsp
;
2664 /******************************************************************************
2665 * DestroyPropertySheetPage (COMCTL32.@)
2667 * Destroys a property sheet page previously created with
2668 * CreatePropertySheetA() or CreatePropertySheetW() and frees the associated
2675 BOOL WINAPI
DestroyPropertySheetPage(HPROPSHEETPAGE hPropPage
)
2677 PROPSHEETPAGEW
*psp
= (PROPSHEETPAGEW
*)hPropPage
;
2682 if ( !(psp
->dwFlags
& PSP_DLGINDIRECT
) && HIWORD( psp
->u
.pszTemplate
) )
2683 HeapFree(GetProcessHeap(), 0, (LPVOID
)psp
->u
.pszTemplate
);
2685 if ( (psp
->dwFlags
& PSP_USEICONID
) && HIWORD( psp
->u2
.pszIcon
) )
2686 HeapFree(GetProcessHeap(), 0, (LPVOID
)psp
->u2
.pszIcon
);
2688 if ((psp
->dwFlags
& PSP_USETITLE
) && HIWORD( psp
->pszTitle
))
2689 HeapFree(GetProcessHeap(), 0, (LPVOID
)psp
->pszTitle
);
2696 /******************************************************************************
2697 * PROPSHEET_IsDialogMessage
2699 static BOOL
PROPSHEET_IsDialogMessage(HWND hwnd
, LPMSG lpMsg
)
2701 PropSheetInfo
* psInfo
= (PropSheetInfo
*) GetPropW(hwnd
, PropSheetInfoStr
);
2704 if (!psInfo
|| (hwnd
!= lpMsg
->hwnd
&& !IsChild(hwnd
, lpMsg
->hwnd
)))
2707 if (lpMsg
->message
== WM_KEYDOWN
&& (GetKeyState(VK_CONTROL
) & 0x8000))
2710 INT dlgCode
= SendMessageA(lpMsg
->hwnd
, WM_GETDLGCODE
, 0, (LPARAM
)lpMsg
);
2712 if (!(dlgCode
& DLGC_WANTMESSAGE
))
2714 switch (lpMsg
->wParam
)
2717 if (GetKeyState(VK_SHIFT
) & 0x8000)
2723 case VK_NEXT
: new_page
= 1; break;
2724 case VK_PRIOR
: new_page
= -1; break;
2730 if (PROPSHEET_CanSetCurSel(hwnd
) != FALSE
)
2732 new_page
+= psInfo
->active_page
;
2735 new_page
= psInfo
->nPages
- 1;
2736 else if (new_page
>= psInfo
->nPages
)
2739 PROPSHEET_SetCurSel(hwnd
, new_page
, 1, 0);
2746 return IsDialogMessageA(hwnd
, lpMsg
);
2749 /******************************************************************************
2750 * PROPSHEET_DoCommand
2752 static BOOL
PROPSHEET_DoCommand(HWND hwnd
, WORD wID
)
2758 case IDC_APPLY_BUTTON
:
2760 HWND hwndApplyBtn
= GetDlgItem(hwnd
, IDC_APPLY_BUTTON
);
2762 if (PROPSHEET_Apply(hwnd
, wID
== IDOK
? 1: 0) == FALSE
)
2767 PropSheetInfo
* psInfo
= (PropSheetInfo
*) GetPropW(hwnd
,
2771 if (psInfo
->restartWindows
)
2772 result
= ID_PSRESTARTWINDOWS
;
2774 /* reboot system takes precedence over restart windows */
2775 if (psInfo
->rebootSystem
)
2776 result
= ID_PSREBOOTSYSTEM
;
2778 if (psInfo
->isModeless
)
2779 psInfo
->activeValid
= FALSE
;
2781 EndDialog(hwnd
, result
);
2784 EnableWindow(hwndApplyBtn
, FALSE
);
2789 case IDC_BACK_BUTTON
:
2790 PROPSHEET_Back(hwnd
);
2793 case IDC_NEXT_BUTTON
:
2794 PROPSHEET_Next(hwnd
);
2797 case IDC_FINISH_BUTTON
:
2798 PROPSHEET_Finish(hwnd
);
2802 PROPSHEET_Cancel(hwnd
, 0);
2806 PROPSHEET_Help(hwnd
);
2816 /******************************************************************************
2817 * PROPSHEET_DialogProc
2820 PROPSHEET_DialogProc(HWND hwnd
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
)
2822 TRACE("hwnd=%p msg=0x%04x wparam=%x lparam=%lx\n",
2823 hwnd
, uMsg
, wParam
, lParam
);
2829 PropSheetInfo
* psInfo
= (PropSheetInfo
*) lParam
;
2830 WCHAR
* strCaption
= (WCHAR
*)Alloc(MAX_CAPTION_LENGTH
*sizeof(WCHAR
));
2831 HWND hwndTabCtrl
= GetDlgItem(hwnd
, IDC_TABCONTROL
);
2832 LPCPROPSHEETPAGEW ppshpage
;
2835 /* Using PropSheetInfoStr to store extra data doesn't match the native
2836 * common control: native uses TCM_[GS]ETITEM
2838 SetPropW(hwnd
, PropSheetInfoStr
, (HANDLE
)psInfo
);
2841 * psInfo->hwnd is not being used by WINE code - it exists
2842 * for compatibility with "real" Windoze. The same about
2843 * SetWindowLong - WINE is only using the PropSheetInfoStr
2846 psInfo
->hwnd
= hwnd
;
2847 SetWindowLongW(hwnd
,DWL_USER
,(LONG
)psInfo
);
2849 /* set up the Next and Back buttons by default */
2850 PROPSHEET_SetWizButtons(hwnd
, PSWIZB_BACK
|PSWIZB_NEXT
);
2853 * Small icon in the title bar.
2855 if ((psInfo
->ppshheader
.dwFlags
& PSH_USEICONID
) ||
2856 (psInfo
->ppshheader
.dwFlags
& PSH_USEHICON
))
2859 int icon_cx
= GetSystemMetrics(SM_CXSMICON
);
2860 int icon_cy
= GetSystemMetrics(SM_CYSMICON
);
2862 if (psInfo
->ppshheader
.dwFlags
& PSH_USEICONID
)
2863 hIcon
= LoadImageW(psInfo
->ppshheader
.hInstance
,
2864 psInfo
->ppshheader
.u
.pszIcon
,
2869 hIcon
= psInfo
->ppshheader
.u
.hIcon
;
2871 SendMessageW(hwnd
, WM_SETICON
, 0, (LPARAM
)hIcon
);
2874 if (psInfo
->ppshheader
.dwFlags
& PSH_USEHICON
)
2875 SendMessageW(hwnd
, WM_SETICON
, 0, (LPARAM
)psInfo
->ppshheader
.u
.hIcon
);
2877 psInfo
->strPropertiesFor
= strCaption
;
2879 GetWindowTextW(hwnd
, psInfo
->strPropertiesFor
, MAX_CAPTION_LENGTH
);
2881 PROPSHEET_CreateTabControl(hwnd
, psInfo
);
2883 if (psInfo
->ppshheader
.dwFlags
& INTRNL_ANY_WIZARD
)
2885 if (PROPSHEET_IsTooSmallWizard(hwnd
, psInfo
))
2887 PROPSHEET_AdjustSizeWizard(hwnd
, psInfo
);
2888 PROPSHEET_AdjustButtonsWizard(hwnd
, psInfo
);
2893 if (PROPSHEET_SizeMismatch(hwnd
, psInfo
))
2895 PROPSHEET_AdjustSize(hwnd
, psInfo
);
2896 PROPSHEET_AdjustButtons(hwnd
, psInfo
);
2900 if (psInfo
->useCallback
)
2901 (*(psInfo
->ppshheader
.pfnCallback
))(hwnd
,
2902 PSCB_INITIALIZED
, (LPARAM
)0);
2904 idx
= psInfo
->active_page
;
2905 ppshpage
= (LPCPROPSHEETPAGEW
)psInfo
->proppage
[idx
].hpage
;
2906 psInfo
->active_page
= -1;
2908 PROPSHEET_SetCurSel(hwnd
, idx
, 1, psInfo
->proppage
[idx
].hpage
);
2910 /* doing TCM_SETCURSEL seems to be needed even in case of PSH_WIZARD,
2911 * as some programs call TCM_GETCURSEL to get the current selection
2912 * from which to switch to the next page */
2913 SendMessageW(hwndTabCtrl
, TCM_SETCURSEL
, psInfo
->active_page
, 0);
2915 if (!HIWORD(psInfo
->ppshheader
.pszCaption
) &&
2916 psInfo
->ppshheader
.hInstance
)
2920 if (LoadStringW(psInfo
->ppshheader
.hInstance
,
2921 (UINT
)psInfo
->ppshheader
.pszCaption
, szText
, 255))
2922 PROPSHEET_SetTitleW(hwnd
, psInfo
->ppshheader
.dwFlags
, szText
);
2926 PROPSHEET_SetTitleW(hwnd
, psInfo
->ppshheader
.dwFlags
,
2927 psInfo
->ppshheader
.pszCaption
);
2934 PROPSHEET_CleanUp(hwnd
);
2938 PROPSHEET_Cancel(hwnd
, 1);
2942 if (!PROPSHEET_DoCommand(hwnd
, LOWORD(wParam
)))
2944 PropSheetInfo
* psInfo
= (PropSheetInfo
*) GetPropW(hwnd
, PropSheetInfoStr
);
2946 /* No default handler, forward notification to active page */
2947 if (psInfo
->activeValid
&& psInfo
->active_page
!= -1)
2949 HWND hwndPage
= psInfo
->proppage
[psInfo
->active_page
].hwndPage
;
2950 SendMessageW(hwndPage
, WM_COMMAND
, wParam
, lParam
);
2957 NMHDR
* pnmh
= (LPNMHDR
) lParam
;
2959 if (pnmh
->code
== TCN_SELCHANGE
)
2961 int index
= SendMessageW(pnmh
->hwndFrom
, TCM_GETCURSEL
, 0, 0);
2962 PROPSHEET_SetCurSel(hwnd
, index
, 1, 0);
2965 if(pnmh
->code
== TCN_SELCHANGING
)
2967 BOOL bRet
= PROPSHEET_CanSetCurSel(hwnd
);
2968 SetWindowLongW(hwnd
, DWL_MSGRESULT
, !bRet
);
2975 case PSM_GETCURRENTPAGEHWND
:
2977 PropSheetInfo
* psInfo
= (PropSheetInfo
*) GetPropW(hwnd
,
2981 if (psInfo
->activeValid
&& psInfo
->active_page
!= -1)
2982 hwndPage
= psInfo
->proppage
[psInfo
->active_page
].hwndPage
;
2984 SetWindowLongW(hwnd
, DWL_MSGRESULT
, (LONG
)hwndPage
);
2990 PROPSHEET_Changed(hwnd
, (HWND
)wParam
);
2994 PROPSHEET_UnChanged(hwnd
, (HWND
)wParam
);
2997 case PSM_GETTABCONTROL
:
2999 HWND hwndTabCtrl
= GetDlgItem(hwnd
, IDC_TABCONTROL
);
3001 SetWindowLongW(hwnd
, DWL_MSGRESULT
, (LONG
)hwndTabCtrl
);
3010 msgResult
= PROPSHEET_CanSetCurSel(hwnd
);
3011 if(msgResult
!= FALSE
)
3013 msgResult
= PROPSHEET_SetCurSel(hwnd
,
3016 (HPROPSHEETPAGE
)lParam
);
3019 SetWindowLongW(hwnd
, DWL_MSGRESULT
, msgResult
);
3024 case PSM_CANCELTOCLOSE
:
3026 WCHAR buf
[MAX_BUTTONTEXT_LENGTH
];
3027 HWND hwndOK
= GetDlgItem(hwnd
, IDOK
);
3028 HWND hwndCancel
= GetDlgItem(hwnd
, IDCANCEL
);
3030 EnableWindow(hwndCancel
, FALSE
);
3031 if (LoadStringW(COMCTL32_hModule
, IDS_CLOSE
, buf
, sizeof(buf
)))
3032 SetWindowTextW(hwndOK
, buf
);
3037 case PSM_RESTARTWINDOWS
:
3039 PropSheetInfo
* psInfo
= (PropSheetInfo
*) GetPropW(hwnd
,
3042 psInfo
->restartWindows
= TRUE
;
3046 case PSM_REBOOTSYSTEM
:
3048 PropSheetInfo
* psInfo
= (PropSheetInfo
*) GetPropW(hwnd
,
3051 psInfo
->rebootSystem
= TRUE
;
3056 PROPSHEET_SetTitleA(hwnd
, (DWORD
) wParam
, (LPCSTR
) lParam
);
3060 PROPSHEET_SetTitleW(hwnd
, (DWORD
) wParam
, (LPCWSTR
) lParam
);
3065 BOOL msgResult
= PROPSHEET_Apply(hwnd
, 0);
3067 SetWindowLongW(hwnd
, DWL_MSGRESULT
, msgResult
);
3072 case PSM_QUERYSIBLINGS
:
3074 LRESULT msgResult
= PROPSHEET_QuerySiblings(hwnd
, wParam
, lParam
);
3076 SetWindowLongW(hwnd
, DWL_MSGRESULT
, msgResult
);
3084 * Note: MSVC++ 6.0 documentation says that PSM_ADDPAGE does not have
3085 * a return value. This is not true. PSM_ADDPAGE returns TRUE
3086 * on success or FALSE otherwise, as specified on MSDN Online.
3087 * Also see the MFC code for
3088 * CPropertySheet::AddPage(CPropertyPage* pPage).
3091 BOOL msgResult
= PROPSHEET_AddPage(hwnd
, (HPROPSHEETPAGE
)lParam
);
3093 SetWindowLongW(hwnd
, DWL_MSGRESULT
, msgResult
);
3098 case PSM_REMOVEPAGE
:
3099 PROPSHEET_RemovePage(hwnd
, (int)wParam
, (HPROPSHEETPAGE
)lParam
);
3102 case PSM_ISDIALOGMESSAGE
:
3104 BOOL msgResult
= PROPSHEET_IsDialogMessage(hwnd
, (LPMSG
)lParam
);
3105 SetWindowLongA(hwnd
, DWL_MSGRESULT
, msgResult
);
3109 case PSM_PRESSBUTTON
:
3110 PROPSHEET_PressButton(hwnd
, (int)wParam
);
3113 case PSM_SETFINISHTEXTA
:
3114 PROPSHEET_SetFinishTextA(hwnd
, (LPCSTR
) lParam
);
3117 case PSM_SETWIZBUTTONS
:
3118 PROPSHEET_SetWizButtons(hwnd
, (DWORD
)lParam
);
3121 case PSM_SETCURSELID
:
3122 PROPSHEET_SetCurSelId(hwnd
, (int)lParam
);
3125 case PSM_SETFINISHTEXTW
:
3126 PROPSHEET_SetFinishTextW(hwnd
, (LPCWSTR
) lParam
);