4 * Copyright 1998 Francis Beaudet
5 * Copyright 1999 Thuy Nguyen
9 * - Unicode property sheets
18 #include "debugtools.h"
22 /******************************************************************************
34 typedef struct tagPropPageInfo
36 int index; /* corresponds to the index in ppshheader->ppsp */
37 HPROPSHEETPAGE hpage; /* to keep track of pages not passed to PropertySheet */
45 typedef struct tagPropSheetInfo
47 LPSTR strPropertiesFor;
50 LPCPROPSHEETHEADERA ppshheader;
57 PropPageInfo* proppage;
62 HIMAGELIST hImageList;
71 /******************************************************************************
72 * Defines and global variables
75 const char * PropSheetInfoStr = "PropertySheetInfo";
77 #define MAX_CAPTION_LENGTH 255
78 #define MAX_TABTEXT_LENGTH 255
80 /******************************************************************************
83 static BOOL PROPSHEET_CreateDialog(PropSheetInfo* psInfo);
84 static BOOL PROPSHEET_IsTooSmall(HWND hwndDlg, PropSheetInfo* psInfo);
85 static BOOL PROPSHEET_AdjustSize(HWND hwndDlg, PropSheetInfo* psInfo);
86 static BOOL PROPSHEET_AdjustButtons(HWND hwndParent, PropSheetInfo* psInfo);
87 static BOOL PROPSHEET_CollectSheetInfo(LPCPROPSHEETHEADERA lppsh,
88 PropSheetInfo * psInfo);
89 static BOOL PROPSHEET_CollectPageInfo(LPCPROPSHEETPAGEA lppsp,
90 PropSheetInfo * psInfo,
92 static BOOL PROPSHEET_CreateTabControl(HWND hwndParent,
93 PropSheetInfo * psInfo);
94 static int PROPSHEET_CreatePage(HWND hwndParent, int index,
95 const PropSheetInfo * psInfo,
96 LPCPROPSHEETPAGEA ppshpage,
98 static BOOL PROPSHEET_ShowPage(HWND hwndDlg, int index, PropSheetInfo * psInfo);
99 static PADDING_INFO PROPSHEET_GetPaddingInfo(HWND hwndDlg);
100 static BOOL PROPSHEET_Back(HWND hwndDlg);
101 static BOOL PROPSHEET_Next(HWND hwndDlg);
102 static BOOL PROPSHEET_Finish(HWND hwndDlg);
103 static BOOL PROPSHEET_Apply(HWND hwndDlg);
104 static void PROPSHEET_Cancel(HWND hwndDlg);
105 static void PROPSHEET_Help(HWND hwndDlg);
106 static void PROPSHEET_Changed(HWND hwndDlg, HWND hwndDirtyPage);
107 static void PROPSHEET_UnChanged(HWND hwndDlg, HWND hwndCleanPage);
108 static void PROPSHEET_PressButton(HWND hwndDlg, int buttonID);
109 static void PROPSHEET_SetFinishTextA(HWND hwndDlg, LPCSTR lpszText);
110 static void PROPSHEET_SetTitleA(HWND hwndDlg, DWORD dwStyle, LPCSTR lpszText);
111 static BOOL PROPSHEET_CanSetCurSel(HWND hwndDlg);
112 static BOOL PROPSHEET_SetCurSel(HWND hwndDlg,
114 HPROPSHEETPAGE hpage);
115 static LRESULT PROPSHEET_QuerySiblings(HWND hwndDlg,
116 WPARAM wParam, LPARAM lParam);
117 static LPCPROPSHEETPAGEA PROPSHEET_GetPSPPage(const PropSheetInfo * psInfo,
119 static BOOL PROPSHEET_AddPage(HWND hwndDlg,
120 HPROPSHEETPAGE hpage);
122 static BOOL PROPSHEET_RemovePage(HWND hwndDlg,
124 HPROPSHEETPAGE hpage);
125 static void PROPSHEET_CleanUp();
126 static int PROPSHEET_GetPageIndex(HPROPSHEETPAGE hpage, PropSheetInfo* psInfo);
127 static void PROPSHEET_SetWizButtons(HWND hwndDlg, DWORD dwFlags);
128 static PADDING_INFO PROPSHEET_GetPaddingInfoWizard(HWND hwndDlg);
131 PROPSHEET_DialogProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
133 DEFAULT_DEBUG_CHANNEL(propsheet)
135 /******************************************************************************
136 * PROPSHEET_CollectSheetInfo
138 * Collect relevant data.
140 static BOOL PROPSHEET_CollectSheetInfo(LPCPROPSHEETHEADERA lppsh,
141 PropSheetInfo * psInfo)
143 DWORD dwFlags = lppsh->dwFlags;
145 psInfo->hasHelp = dwFlags & PSH_HASHELP;
146 psInfo->hasApply = !(dwFlags & PSH_NOAPPLYNOW);
147 psInfo->useCallback = dwFlags & PSH_USECALLBACK;
148 psInfo->isModeless = dwFlags & PSH_MODELESS;
149 psInfo->ppshheader = lppsh;
150 psInfo->nPages = lppsh->nPages;
152 if (dwFlags & PSH_USEPSTARTPAGE)
154 TRACE("PSH_USEPSTARTPAGE is on");
155 psInfo->active_page = 0;
158 psInfo->active_page = lppsh->u2.nStartPage;
160 psInfo->restartWindows = FALSE;
161 psInfo->rebootSystem = FALSE;
162 psInfo->hImageList = 0;
167 /******************************************************************************
168 * PROPSHEET_CollectPageInfo
170 * Collect property sheet data.
171 * With code taken from DIALOG_ParseTemplate32.
173 BOOL PROPSHEET_CollectPageInfo(LPCPROPSHEETPAGEA lppsp,
174 PropSheetInfo * psInfo,
177 DLGTEMPLATE* pTemplate;
182 if (psInfo->ppshheader->dwFlags & PSH_PROPSHEETPAGE)
183 psInfo->proppage[index].hpage = 0;
184 psInfo->proppage[index].hwndPage = 0;
185 psInfo->proppage[index].isDirty = FALSE;
188 * Process property page flags.
190 dwFlags = lppsp->dwFlags;
191 psInfo->proppage[index].useCallback = dwFlags & PSP_USECALLBACK;
192 psInfo->proppage[index].hasHelp = dwFlags & PSP_HASHELP;
194 /* as soon as we have a page with the help flag, set the sheet flag on */
195 if (psInfo->proppage[index].hasHelp)
196 psInfo->hasHelp = TRUE;
199 * Process page template.
201 if (dwFlags & PSP_DLGINDIRECT)
202 pTemplate = (DLGTEMPLATE*)lppsp->u1.pResource;
205 HRSRC hResource = FindResourceA(lppsp->hInstance,
206 lppsp->u1.pszTemplate,
208 HGLOBAL hTemplate = LoadResource(lppsp->hInstance,
210 pTemplate = (LPDLGTEMPLATEA)LockResource(hTemplate);
214 * Extract the size of the page and the caption.
216 p = (const WORD *)pTemplate;
218 if (((MyDLGTEMPLATEEX*)pTemplate)->signature == 0xFFFF)
220 /* DIALOGEX template */
224 p += 2; /* help ID */
225 p += 2; /* ext style */
230 /* DIALOG template */
233 p += 2; /* ext style */
239 width = (WORD)*p; p++;
240 height = (WORD)*p; p++;
242 /* remember the largest width and height */
243 if (width > psInfo->width)
244 psInfo->width = width;
246 if (height > psInfo->height)
247 psInfo->height = height;
259 p += lstrlenW( (LPCWSTR)p ) + 1;
273 p += lstrlenW( (LPCWSTR)p ) + 1;
277 /* Extract the caption */
278 psInfo->proppage[index].pszText = (LPCWSTR)p;
279 TRACE("Tab %d %s\n",index,debugstr_w((LPCWSTR)p));
280 p += lstrlenW((LPCWSTR)p) + 1;
282 if (dwFlags & PSP_USETITLE)
284 if ( !HIWORD( lppsp->pszTitle ) )
288 if ( !LoadStringA( lppsp->hInstance, (UINT) lppsp->pszTitle, szTitle, 256 ) )
291 psInfo->proppage[index].pszText = HEAP_strdupAtoW( GetProcessHeap(),
295 psInfo->proppage[index].pszText = HEAP_strdupAtoW(GetProcessHeap(),
301 * Build the image list for icons
303 if ((dwFlags & PSP_USEHICON) || (dwFlags & PSP_USEICONID))
306 int icon_cx = GetSystemMetrics(SM_CXSMICON);
307 int icon_cy = GetSystemMetrics(SM_CYSMICON);
309 if (dwFlags & PSP_USEICONID)
310 hIcon = LoadImageA(lppsp->hInstance, lppsp->u2.pszIcon, IMAGE_ICON,
311 icon_cx, icon_cy, LR_DEFAULTCOLOR);
313 hIcon = lppsp->u2.hIcon;
315 if (psInfo->hImageList == 0)
316 psInfo->hImageList = ImageList_Create(icon_cx, icon_cy, ILC_COLOR, 1, 1);
318 ImageList_AddIcon(psInfo->hImageList, hIcon);
324 /******************************************************************************
325 * PROPSHEET_CreateDialog
327 * Creates the actual property sheet.
329 BOOL PROPSHEET_CreateDialog(PropSheetInfo* psInfo)
336 WORD resID = IDD_PROPSHEET;
338 if (psInfo->ppshheader->dwFlags & PSH_WIZARD)
341 if(!(hRes = FindResourceA(COMCTL32_hModule,
342 MAKEINTRESOURCEA(resID),
346 if(!(template = (LPVOID)LoadResource(COMCTL32_hModule, hRes)))
350 * Make a copy of the dialog template.
352 resSize = SizeofResource(COMCTL32_hModule, hRes);
354 temp = COMCTL32_Alloc(resSize);
359 memcpy(temp, template, resSize);
361 if (psInfo->useCallback)
362 (*(psInfo->ppshheader->pfnCallback))(0, PSCB_PRECREATE, (LPARAM)temp);
364 if (psInfo->ppshheader->dwFlags & PSH_MODELESS)
365 ret = CreateDialogIndirectParamA(psInfo->ppshheader->hInstance,
366 (LPDLGTEMPLATEA) temp,
367 psInfo->ppshheader->hwndParent,
368 (DLGPROC) PROPSHEET_DialogProc,
371 ret = DialogBoxIndirectParamA(psInfo->ppshheader->hInstance,
372 (LPDLGTEMPLATEA) temp,
373 psInfo->ppshheader->hwndParent,
374 (DLGPROC) PROPSHEET_DialogProc,
382 /******************************************************************************
383 * PROPSHEET_IsTooSmall
385 * Verify that the resource property sheet is big enough.
387 static BOOL PROPSHEET_IsTooSmall(HWND hwndDlg, PropSheetInfo* psInfo)
389 HWND hwndTabCtrl = GetDlgItem(hwndDlg, IDC_TABCONTROL);
390 RECT rcOrigTab, rcPage;
395 GetClientRect(hwndTabCtrl, &rcOrigTab);
396 TRACE("orig tab %d %d %d %d\n", rcOrigTab.left, rcOrigTab.top,
397 rcOrigTab.right, rcOrigTab.bottom);
402 rcPage.left = psInfo->x;
403 rcPage.top = psInfo->y;
404 rcPage.right = psInfo->width;
405 rcPage.bottom = psInfo->height;
407 MapDialogRect(hwndDlg, &rcPage);
408 TRACE("biggest page %d %d %d %d\n", rcPage.left, rcPage.top,
409 rcPage.right, rcPage.bottom);
411 if (rcPage.right > rcOrigTab.right)
414 if (rcPage.bottom > rcOrigTab.bottom)
420 /******************************************************************************
421 * PROPSHEET_IsTooSmallWizard
423 * Verify that the default property sheet is big enough.
425 static BOOL PROPSHEET_IsTooSmallWizard(HWND hwndDlg, PropSheetInfo* psInfo)
427 RECT rcSheetRect, rcPage, rcLine, rcSheetClient;
428 HWND hwndLine = GetDlgItem(hwndDlg, IDC_SUNKEN_LINE);
429 PADDING_INFO padding = PROPSHEET_GetPaddingInfoWizard(hwndDlg);
431 GetClientRect(hwndDlg, &rcSheetClient);
432 GetWindowRect(hwndDlg, &rcSheetRect);
433 GetWindowRect(hwndLine, &rcLine);
435 /* Remove the space below the sunken line */
436 rcSheetClient.bottom -= (rcSheetRect.bottom - rcLine.top);
438 /* Remove the buffer zone all around the edge */
439 rcSheetClient.bottom -= (padding.y * 2);
440 rcSheetClient.right -= (padding.x * 2);
445 rcPage.left = psInfo->x;
446 rcPage.top = psInfo->y;
447 rcPage.right = psInfo->width;
448 rcPage.bottom = psInfo->height;
450 MapDialogRect(hwndDlg, &rcPage);
451 TRACE("biggest page %d %d %d %d\n", rcPage.left, rcPage.top,
452 rcPage.right, rcPage.bottom);
454 if (rcPage.right > rcSheetClient.right)
457 if (rcPage.bottom > rcSheetClient.bottom)
463 /******************************************************************************
464 * PROPSHEET_AdjustSize
466 * Resizes the property sheet and the tab control to fit the largest page.
468 static BOOL PROPSHEET_AdjustSize(HWND hwndDlg, PropSheetInfo* psInfo)
470 HWND hwndTabCtrl = GetDlgItem(hwndDlg, IDC_TABCONTROL);
471 HWND hwndButton = GetDlgItem(hwndDlg, IDOK);
473 int tabOffsetX, tabOffsetY, buttonHeight;
474 PADDING_INFO padding = PROPSHEET_GetPaddingInfo(hwndDlg);
476 /* Get the height of buttons */
477 GetClientRect(hwndButton, &rc);
478 buttonHeight = rc.bottom;
485 rc.right = psInfo->width;
486 rc.bottom = psInfo->height;
488 MapDialogRect(hwndDlg, &rc);
491 * Resize the tab control.
493 SendMessageA(hwndTabCtrl, TCM_ADJUSTRECT, TRUE, (LPARAM)&rc);
495 tabOffsetX = -(rc.left);
496 tabOffsetY = -(rc.top);
500 SetWindowPos(hwndTabCtrl, 0, 0, 0, rc.right, rc.bottom,
501 SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE);
503 GetClientRect(hwndTabCtrl, &rc);
505 TRACE("tab client rc %d %d %d %d\n",
506 rc.left, rc.top, rc.right, rc.bottom);
508 rc.right += ((padding.x * 2) + tabOffsetX);
509 rc.bottom += (buttonHeight + (3 * padding.y) + tabOffsetY);
512 * Resize the property sheet.
514 SetWindowPos(hwndDlg, 0, 0, 0, rc.right, rc.bottom,
515 SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE);
520 /******************************************************************************
521 * PROPSHEET_AdjustSizeWizard
523 * Resizes the property sheet to fit the largest page.
525 static BOOL PROPSHEET_AdjustSizeWizard(HWND hwndDlg, PropSheetInfo* psInfo)
527 HWND hwndButton = GetDlgItem(hwndDlg, IDCANCEL);
528 HWND hwndLine = GetDlgItem(hwndDlg, IDC_SUNKEN_LINE);
530 int buttonHeight, lineHeight;
531 PADDING_INFO padding = PROPSHEET_GetPaddingInfoWizard(hwndDlg);
533 /* Get the height of buttons */
534 GetClientRect(hwndButton, &rc);
535 buttonHeight = rc.bottom;
537 GetClientRect(hwndLine, &rc);
538 lineHeight = rc.bottom;
545 rc.right = psInfo->width;
546 rc.bottom = psInfo->height;
548 MapDialogRect(hwndDlg, &rc);
550 TRACE("Biggest page %d %d %d %d\n", rc.left, rc.top, rc.right, rc.bottom);
553 rc.right += (padding.x * 2);
554 rc.bottom += (buttonHeight + (5 * padding.y) + lineHeight);
557 * Resize the property sheet.
559 SetWindowPos(hwndDlg, 0, 0, 0, rc.right, rc.bottom,
560 SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE);
565 /******************************************************************************
566 * PROPSHEET_AdjustButtons
568 * Adjusts the buttons' positions.
570 static BOOL PROPSHEET_AdjustButtons(HWND hwndParent, PropSheetInfo* psInfo)
572 HWND hwndButton = GetDlgItem(hwndParent, IDOK);
576 int buttonWidth, buttonHeight;
577 PADDING_INFO padding = PROPSHEET_GetPaddingInfo(hwndParent);
579 if (psInfo->hasApply)
586 * Obtain the size of the buttons.
588 GetClientRect(hwndButton, &rcSheet);
589 buttonWidth = rcSheet.right;
590 buttonHeight = rcSheet.bottom;
593 * Get the size of the property sheet.
595 GetClientRect(hwndParent, &rcSheet);
598 * All buttons will be at this y coordinate.
600 y = rcSheet.bottom - (padding.y + buttonHeight);
603 * Position OK button.
605 hwndButton = GetDlgItem(hwndParent, IDOK);
607 x = rcSheet.right - ((padding.x + buttonWidth) * num_buttons);
609 SetWindowPos(hwndButton, 0, x, y, 0, 0,
610 SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE);
613 * Position Cancel button.
615 hwndButton = GetDlgItem(hwndParent, IDCANCEL);
617 x = rcSheet.right - ((padding.x + buttonWidth) * (num_buttons - 1));
619 SetWindowPos(hwndButton, 0, x, y, 0, 0,
620 SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE);
623 * Position Apply button.
625 hwndButton = GetDlgItem(hwndParent, IDC_APPLY_BUTTON);
627 if (psInfo->hasApply)
630 x = rcSheet.right - ((padding.x + buttonWidth) * 2);
632 x = rcSheet.right - (padding.x + buttonWidth);
634 SetWindowPos(hwndButton, 0, x, y, 0, 0,
635 SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE);
637 EnableWindow(hwndButton, FALSE);
640 ShowWindow(hwndButton, SW_HIDE);
643 * Position Help button.
645 hwndButton = GetDlgItem(hwndParent, IDHELP);
649 x = rcSheet.right - (padding.x + buttonWidth);
651 SetWindowPos(hwndButton, 0, x, y, 0, 0,
652 SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE);
655 ShowWindow(hwndButton, SW_HIDE);
660 /******************************************************************************
661 * PROPSHEET_AdjustButtonsWizard
663 * Adjusts the buttons' positions.
665 static BOOL PROPSHEET_AdjustButtonsWizard(HWND hwndParent,
666 PropSheetInfo* psInfo)
668 HWND hwndButton = GetDlgItem(hwndParent, IDCANCEL);
669 HWND hwndLine = GetDlgItem(hwndParent, IDC_SUNKEN_LINE);
673 int buttonWidth, buttonHeight, lineHeight, lineWidth;
674 PADDING_INFO padding = PROPSHEET_GetPaddingInfoWizard(hwndParent);
680 * Obtain the size of the buttons.
682 GetClientRect(hwndButton, &rcSheet);
683 buttonWidth = rcSheet.right;
684 buttonHeight = rcSheet.bottom;
686 GetClientRect(hwndLine, &rcSheet);
687 lineHeight = rcSheet.bottom;
690 * Get the size of the property sheet.
692 GetClientRect(hwndParent, &rcSheet);
695 * All buttons will be at this y coordinate.
697 y = rcSheet.bottom - (padding.y + buttonHeight);
700 * Position the Next and the Finish buttons.
702 hwndButton = GetDlgItem(hwndParent, IDC_NEXT_BUTTON);
704 x = rcSheet.right - ((padding.x + buttonWidth) * (num_buttons - 1));
706 SetWindowPos(hwndButton, 0, x, y, 0, 0,
707 SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE);
709 hwndButton = GetDlgItem(hwndParent, IDC_FINISH_BUTTON);
711 SetWindowPos(hwndButton, 0, x, y, 0, 0,
712 SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE);
714 ShowWindow(hwndButton, SW_HIDE);
717 * Position the Back button.
719 hwndButton = GetDlgItem(hwndParent, IDC_BACK_BUTTON);
723 SetWindowPos(hwndButton, 0, x, y, 0, 0,
724 SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE);
727 * Position the Cancel button.
729 hwndButton = GetDlgItem(hwndParent, IDCANCEL);
731 x = rcSheet.right - ((padding.x + buttonWidth) * (num_buttons - 2));
733 SetWindowPos(hwndButton, 0, x, y, 0, 0,
734 SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE);
737 * Position Help button.
739 hwndButton = GetDlgItem(hwndParent, IDHELP);
743 x = rcSheet.right - (padding.x + buttonWidth);
745 SetWindowPos(hwndButton, 0, x, y, 0, 0,
746 SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE);
749 ShowWindow(hwndButton, SW_HIDE);
752 * Position and resize the sunken line.
755 y = rcSheet.bottom - ((padding.y * 2) + buttonHeight + lineHeight);
757 GetClientRect(hwndParent, &rcSheet);
758 lineWidth = rcSheet.right - (padding.x * 2);
760 SetWindowPos(hwndLine, 0, x, y, lineWidth, 2,
761 SWP_NOZORDER | SWP_NOACTIVATE);
766 /******************************************************************************
767 * PROPSHEET_GetPaddingInfo
769 * Returns the layout information.
771 static PADDING_INFO PROPSHEET_GetPaddingInfo(HWND hwndDlg)
773 HWND hwndTab = GetDlgItem(hwndDlg, IDC_TABCONTROL);
776 PADDING_INFO padding;
778 GetWindowRect(hwndTab, &rcTab);
783 ScreenToClient(hwndDlg, &tl);
791 /******************************************************************************
792 * PROPSHEET_GetPaddingInfoWizard
794 * Returns the layout information.
795 * Horizontal spacing is the distance between the Cancel and Help buttons.
796 * Vertical spacing is the distance between the line and the buttons.
798 static PADDING_INFO PROPSHEET_GetPaddingInfoWizard(HWND hwndDlg)
800 PADDING_INFO padding;
803 POINT ptHelp, ptCancel, ptLine;
806 hwndControl = GetDlgItem(hwndDlg, IDHELP);
807 GetWindowRect(hwndControl, &rc);
812 ScreenToClient(hwndDlg, &ptHelp);
815 hwndControl = GetDlgItem(hwndDlg, IDCANCEL);
816 GetWindowRect(hwndControl, &rc);
818 ptCancel.x = rc.right;
821 ScreenToClient(hwndDlg, &ptCancel);
824 hwndControl = GetDlgItem(hwndDlg, IDC_SUNKEN_LINE);
825 GetWindowRect(hwndControl, &rc);
828 ptLine.y = rc.bottom;
830 ScreenToClient(hwndDlg, &ptLine);
832 padding.x = ptHelp.x - ptCancel.x;
833 padding.y = ptHelp.y - ptLine.y;
838 /******************************************************************************
839 * PROPSHEET_CreateTabControl
841 * Insert the tabs in the tab control.
843 static BOOL PROPSHEET_CreateTabControl(HWND hwndParent,
844 PropSheetInfo * psInfo)
846 HWND hwndTabCtrl = GetDlgItem(hwndParent, IDC_TABCONTROL);
849 char tabtext[MAX_TABTEXT_LENGTH] = "Tab text";
851 item.mask = TCIF_TEXT;
852 item.pszText = tabtext;
853 item.cchTextMax = MAX_TABTEXT_LENGTH;
855 nTabs = psInfo->ppshheader->nPages;
858 * Set the image list for icons.
860 if (psInfo->hImageList)
862 item.mask |= TCIF_IMAGE;
863 SendMessageA(hwndTabCtrl, TCM_SETIMAGELIST, 0, (LPARAM)psInfo->hImageList);
866 for (i = 0; i < nTabs; i++)
870 WideCharToMultiByte(CP_ACP, 0,
871 (LPCWSTR)psInfo->proppage[i].pszText,
872 -1, tabtext, MAX_TABTEXT_LENGTH, NULL, NULL);
874 SendMessageA(hwndTabCtrl, TCM_INSERTITEMA, (WPARAM)i, (LPARAM)&item);
880 /******************************************************************************
881 * PROPSHEET_CreatePage
885 static int PROPSHEET_CreatePage(HWND hwndParent,
887 const PropSheetInfo * psInfo,
888 LPCPROPSHEETPAGEA ppshpage,
891 DLGTEMPLATE* pTemplate;
894 PropPageInfo* ppInfo = psInfo->proppage;
895 PADDING_INFO padding;
897 TRACE("index %d\n", index);
899 if (ppshpage->dwFlags & PSP_DLGINDIRECT)
900 pTemplate = (DLGTEMPLATE*)ppshpage->u1.pResource;
903 HRSRC hResource = FindResourceA(ppshpage->hInstance,
904 ppshpage->u1.pszTemplate,
906 HGLOBAL hTemplate = LoadResource(ppshpage->hInstance, hResource);
907 pTemplate = (LPDLGTEMPLATEA)LockResource(hTemplate);
910 if (((MyDLGTEMPLATEEX*)pTemplate)->signature == 0xFFFF)
912 ((MyDLGTEMPLATEEX*)pTemplate)->style |= WS_CHILD;
913 ((MyDLGTEMPLATEEX*)pTemplate)->style &= ~DS_MODALFRAME;
914 ((MyDLGTEMPLATEEX*)pTemplate)->style &= ~WS_CAPTION;
915 ((MyDLGTEMPLATEEX*)pTemplate)->style &= ~WS_SYSMENU;
916 ((MyDLGTEMPLATEEX*)pTemplate)->style &= ~WS_POPUP;
917 ((MyDLGTEMPLATEEX*)pTemplate)->style &= ~WS_DISABLED;
921 pTemplate->style |= WS_CHILD;
922 pTemplate->style &= ~DS_MODALFRAME;
923 pTemplate->style &= ~WS_CAPTION;
924 pTemplate->style &= ~WS_SYSMENU;
925 pTemplate->style &= ~WS_POPUP;
926 pTemplate->style &= ~WS_DISABLED;
929 if (psInfo->proppage[index].useCallback)
930 (*(ppshpage->pfnCallback))(hwndParent,
932 (LPPROPSHEETPAGEA)ppshpage);
934 hwndPage = CreateDialogIndirectParamA(ppshpage->hInstance,
937 ppshpage->pfnDlgProc,
940 ppInfo[index].hwndPage = hwndPage;
944 rc.right = psInfo->width;
945 rc.bottom = psInfo->height;
947 MapDialogRect(hwndParent, &rc);
949 if (psInfo->ppshheader->dwFlags & PSH_WIZARD)
950 padding = PROPSHEET_GetPaddingInfoWizard(hwndParent);
954 * Ask the Tab control to fit this page in.
957 HWND hwndTabCtrl = GetDlgItem(hwndParent, IDC_TABCONTROL);
958 SendMessageA(hwndTabCtrl, TCM_ADJUSTRECT, FALSE, (LPARAM)&rc);
959 padding = PROPSHEET_GetPaddingInfo(hwndParent);
962 SetWindowPos(hwndPage, HWND_TOP,
971 hdr.hwndFrom = hwndParent;
972 hdr.code = PSN_SETACTIVE;
975 * Send the notification before showing the page.
977 SendMessageA(hwndPage, WM_NOTIFY, 0, (LPARAM) &hdr);
979 ShowWindow(hwndPage, SW_SHOW);
982 ShowWindow(hwndPage, SW_HIDE);
987 /******************************************************************************
990 * Displays or creates the specified page.
992 static BOOL PROPSHEET_ShowPage(HWND hwndDlg, int index, PropSheetInfo * psInfo)
994 if (index == psInfo->active_page)
997 ShowWindow(psInfo->proppage[psInfo->active_page].hwndPage, SW_HIDE);
999 if (psInfo->proppage[index].hwndPage != 0)
1000 ShowWindow(psInfo->proppage[index].hwndPage, SW_SHOW);
1003 LPCPROPSHEETPAGEA ppshpage = PROPSHEET_GetPSPPage(psInfo, index);
1004 PROPSHEET_CreatePage(hwndDlg, index, psInfo, ppshpage, TRUE);
1007 psInfo->active_page = index;
1012 /******************************************************************************
1015 static BOOL PROPSHEET_Back(HWND hwndDlg)
1020 HWND hwndBack = GetDlgItem(hwndDlg, IDC_BACK_BUTTON);
1021 PropSheetInfo* psInfo = (PropSheetInfo*) GetPropA(hwndDlg,
1024 hdr.hwndFrom = hwndDlg;
1025 hdr.code = PSN_WIZBACK;
1027 hwndPage = psInfo->proppage[psInfo->active_page].hwndPage;
1029 if (SendMessageA(hwndPage, WM_NOTIFY, 0, (LPARAM) &hdr) == -1)
1032 res = PROPSHEET_CanSetCurSel(hwndDlg);
1035 res = PROPSHEET_SetCurSel(hwndDlg, psInfo->active_page - 1, 0);
1038 /* if we went to page 0, disable Back button */
1039 if (res && (psInfo->active_page == 0))
1040 EnableWindow(hwndBack, FALSE);
1045 /******************************************************************************
1048 static BOOL PROPSHEET_Next(HWND hwndDlg)
1052 LRESULT msgResult = 0;
1053 PropSheetInfo* psInfo = (PropSheetInfo*) GetPropA(hwndDlg,
1056 hdr.hwndFrom = hwndDlg;
1057 hdr.code = PSN_WIZNEXT;
1059 hwndPage = psInfo->proppage[psInfo->active_page].hwndPage;
1061 msgResult = SendMessageA(hwndPage, WM_NOTIFY, 0, (LPARAM) &hdr);
1063 TRACE("msg result %ld\n", msgResult);
1065 if (msgResult == -1)
1068 if(PROPSHEET_CanSetCurSel(hwndDlg) != FALSE)
1070 PROPSHEET_SetCurSel(hwndDlg, psInfo->active_page + 1, 0);
1076 /******************************************************************************
1079 static BOOL PROPSHEET_Finish(HWND hwndDlg)
1083 LRESULT msgResult = 0;
1084 PropSheetInfo* psInfo = (PropSheetInfo*) GetPropA(hwndDlg,
1087 hdr.hwndFrom = hwndDlg;
1088 hdr.code = PSN_WIZFINISH;
1090 hwndPage = psInfo->proppage[psInfo->active_page].hwndPage;
1092 msgResult = SendMessageA(hwndPage, WM_NOTIFY, 0, (LPARAM) &hdr);
1094 TRACE("msg result %ld\n", msgResult);
1099 if (psInfo->isModeless)
1100 psInfo->active_page = -1;
1102 EndDialog(hwndDlg, TRUE);
1107 /******************************************************************************
1110 static BOOL PROPSHEET_Apply(HWND hwndDlg)
1116 PropSheetInfo* psInfo = (PropSheetInfo*) GetPropA(hwndDlg,
1119 hdr.hwndFrom = hwndDlg;
1122 * Send PSN_KILLACTIVE to the current page.
1124 hdr.code = PSN_KILLACTIVE;
1126 hwndPage = psInfo->proppage[psInfo->active_page].hwndPage;
1128 if (SendMessageA(hwndPage, WM_NOTIFY, 0, (LPARAM) &hdr) != FALSE)
1132 * Send PSN_APPLY to all pages.
1134 hdr.code = PSN_APPLY;
1136 for (i = 0; i < psInfo->nPages; i++)
1138 hwndPage = psInfo->proppage[i].hwndPage;
1139 msgResult = SendMessageA(hwndPage, WM_NOTIFY, 0, (LPARAM) &hdr);
1141 if (msgResult == PSNRET_INVALID_NOCHANGEPAGE)
1148 /******************************************************************************
1151 static void PROPSHEET_Cancel(HWND hwndDlg)
1153 PropSheetInfo* psInfo = (PropSheetInfo*) GetPropA(hwndDlg,
1155 HWND hwndPage = psInfo->proppage[psInfo->active_page].hwndPage;
1158 hdr.hwndFrom = hwndDlg;
1159 hdr.code = PSN_QUERYCANCEL;
1161 if (SendMessageA(hwndPage, WM_NOTIFY, 0, (LPARAM) &hdr))
1164 hdr.code = PSN_RESET;
1166 SendMessageA(hwndPage, WM_NOTIFY, 0, (LPARAM) &hdr);
1168 if (psInfo->isModeless)
1169 psInfo->active_page = -1; /* makes PSM_GETCURRENTPAGEHWND return NULL */
1171 EndDialog(hwndDlg, FALSE);
1174 /******************************************************************************
1177 static void PROPSHEET_Help(HWND hwndDlg)
1179 PropSheetInfo* psInfo = (PropSheetInfo*) GetPropA(hwndDlg,
1181 HWND hwndPage = psInfo->proppage[psInfo->active_page].hwndPage;
1184 hdr.hwndFrom = hwndDlg;
1185 hdr.code = PSN_HELP;
1187 SendMessageA(hwndPage, WM_NOTIFY, 0, (LPARAM) &hdr);
1190 /******************************************************************************
1193 static void PROPSHEET_Changed(HWND hwndDlg, HWND hwndDirtyPage)
1196 PropSheetInfo* psInfo = (PropSheetInfo*) GetPropA(hwndDlg,
1199 if (!psInfo) return;
1201 * Set the dirty flag of this page.
1203 for (i = 0; i < psInfo->nPages; i++)
1205 if (psInfo->proppage[i].hwndPage == hwndDirtyPage)
1206 psInfo->proppage[i].isDirty = TRUE;
1210 * Enable the Apply button.
1212 if (psInfo->hasApply)
1214 HWND hwndApplyBtn = GetDlgItem(hwndDlg, IDC_APPLY_BUTTON);
1216 EnableWindow(hwndApplyBtn, TRUE);
1220 /******************************************************************************
1221 * PROPSHEET_UnChanged
1223 static void PROPSHEET_UnChanged(HWND hwndDlg, HWND hwndCleanPage)
1226 BOOL noPageDirty = TRUE;
1227 HWND hwndApplyBtn = GetDlgItem(hwndDlg, IDC_APPLY_BUTTON);
1228 PropSheetInfo* psInfo = (PropSheetInfo*) GetPropA(hwndDlg,
1231 if ( !psInfo ) return;
1232 for (i = 0; i < psInfo->nPages; i++)
1234 /* set the specified page as clean */
1235 if (psInfo->proppage[i].hwndPage == hwndCleanPage)
1236 psInfo->proppage[i].isDirty = FALSE;
1238 /* look to see if there's any dirty pages */
1239 if (psInfo->proppage[i].isDirty)
1240 noPageDirty = FALSE;
1244 * Disable Apply button.
1247 EnableWindow(hwndApplyBtn, FALSE);
1250 /******************************************************************************
1251 * PROPSHEET_PressButton
1253 static void PROPSHEET_PressButton(HWND hwndDlg, int buttonID)
1257 case PSBTN_APPLYNOW:
1258 SendMessageA(hwndDlg, WM_COMMAND, IDC_APPLY_BUTTON, 0);
1261 PROPSHEET_Back(hwndDlg);
1264 SendMessageA(hwndDlg, WM_COMMAND, IDCANCEL, 0);
1267 PROPSHEET_Finish(hwndDlg);
1270 SendMessageA(hwndDlg, WM_COMMAND, IDHELP, 0);
1273 PROPSHEET_Next(hwndDlg);
1276 SendMessageA(hwndDlg, WM_COMMAND, IDOK, 0);
1279 FIXME("Invalid button index %d\n", buttonID);
1284 /*************************************************************************
1285 * BOOL PROPSHEET_CanSetCurSel [Internal]
1287 * Test weither the current page can be changed by sending a PSN_KILLACTIVE
1290 * hwndDlg [I] handle to a Dialog hWnd
1293 * TRUE if Current Selection can change
1297 static BOOL PROPSHEET_CanSetCurSel(HWND hwndDlg)
1299 PropSheetInfo* psInfo = (PropSheetInfo*) GetPropA(hwndDlg,
1308 * Notify the current page.
1310 hwndPage = psInfo->proppage[psInfo->active_page].hwndPage;
1312 hdr.hwndFrom = hwndDlg;
1313 hdr.code = PSN_KILLACTIVE;
1315 return !SendMessageA(hwndPage, WM_NOTIFY, 0, (LPARAM) &hdr);
1318 /******************************************************************************
1319 * PROPSHEET_SetCurSel
1321 static BOOL PROPSHEET_SetCurSel(HWND hwndDlg,
1323 HPROPSHEETPAGE hpage)
1325 PropSheetInfo* psInfo = (PropSheetInfo*) GetPropA(hwndDlg,
1328 HWND hwndHelp = GetDlgItem(hwndDlg, IDHELP);
1331 hwndPage = psInfo->proppage[psInfo->active_page].hwndPage;
1333 hdr.hwndFrom = hwndDlg;
1335 * hpage takes precedence over index.
1339 index = PROPSHEET_GetPageIndex(hpage, psInfo);
1343 TRACE("Could not find page to remove!\n");
1348 hwndPage = psInfo->proppage[index].hwndPage;
1351 * Notify the new page if it's already created.
1352 * If not it will get created and notified in PROPSHEET_ShowPage.
1357 hdr.code = PSN_SETACTIVE;
1359 result = SendMessageA(hwndPage, WM_NOTIFY, 0, (LPARAM) &hdr);
1361 * TODO: check return value.
1366 * Display the new page.
1368 PROPSHEET_ShowPage(hwndDlg, index, psInfo);
1370 if (psInfo->proppage[index].hasHelp)
1371 EnableWindow(hwndHelp, TRUE);
1373 EnableWindow(hwndHelp, FALSE);
1378 /******************************************************************************
1379 * PROPSHEET_SetTitleA
1381 static void PROPSHEET_SetTitleA(HWND hwndDlg, DWORD dwStyle, LPCSTR lpszText)
1383 if (dwStyle & PSH_PROPTITLE)
1385 PropSheetInfo* psInfo = (PropSheetInfo*) GetPropA(hwndDlg,
1388 int lentitle = strlen(lpszText);
1389 int lenprop = strlen(psInfo->strPropertiesFor);
1391 dest = COMCTL32_Alloc(lentitle + lenprop + 1);
1392 strcpy(dest, psInfo->strPropertiesFor);
1393 strcat(dest, lpszText);
1395 SetWindowTextA(hwndDlg, dest);
1396 COMCTL32_Free(dest);
1399 SetWindowTextA(hwndDlg, lpszText);
1402 /******************************************************************************
1403 * PROPSHEET_SetFinishTextA
1405 static void PROPSHEET_SetFinishTextA(HWND hwndDlg, LPCSTR lpszText)
1407 HWND hwndButton = GetDlgItem(hwndDlg, IDC_FINISH_BUTTON);
1409 /* Set text, show and enable the Finish button */
1410 SetWindowTextA(hwndButton, lpszText);
1411 ShowWindow(hwndButton, SW_SHOW);
1412 EnableWindow(hwndButton, TRUE);
1414 /* Make it default pushbutton */
1415 SendMessageA(hwndDlg, DM_SETDEFID, IDC_FINISH_BUTTON, 0);
1417 /* Hide Back button */
1418 hwndButton = GetDlgItem(hwndDlg, IDC_BACK_BUTTON);
1419 ShowWindow(hwndButton, SW_HIDE);
1421 /* Hide Next button */
1422 hwndButton = GetDlgItem(hwndDlg, IDC_NEXT_BUTTON);
1423 ShowWindow(hwndButton, SW_HIDE);
1426 /******************************************************************************
1427 * PROPSHEET_QuerySiblings
1429 static LRESULT PROPSHEET_QuerySiblings(HWND hwndDlg,
1430 WPARAM wParam, LPARAM lParam)
1434 LRESULT msgResult = 0;
1435 PropSheetInfo* psInfo = (PropSheetInfo*) GetPropA(hwndDlg,
1438 while ((i < psInfo->nPages) && (msgResult == 0))
1440 hwndPage = psInfo->proppage[i].hwndPage;
1441 msgResult = SendMessageA(hwndPage, PSM_QUERYSIBLINGS, wParam, lParam);
1448 /******************************************************************************
1449 * PROPSHEET_GetPSPPage
1451 static LPCPROPSHEETPAGEA PROPSHEET_GetPSPPage(const PropSheetInfo * psInfo,
1454 BOOL usePSP = psInfo->ppshheader->dwFlags & PSH_PROPSHEETPAGE;
1455 LPCPROPSHEETPAGEA lppsp;
1456 int realIndex = psInfo->proppage[index].index;
1462 lppsp = psInfo->ppshheader->u3.ppsp;
1464 pByte = (BYTE*) lppsp;
1466 pByte += (lppsp->dwSize * realIndex);
1467 lppsp = (LPCPROPSHEETPAGEA)pByte;
1470 lppsp = (LPCPROPSHEETPAGEA) psInfo->ppshheader->u3.phpage[realIndex];
1475 /******************************************************************************
1478 static BOOL PROPSHEET_AddPage(HWND hwndDlg,
1479 HPROPSHEETPAGE hpage)
1481 PropSheetInfo * psInfo = (PropSheetInfo*) GetPropA(hwndDlg,
1483 HWND hwndTabControl = GetDlgItem(hwndDlg, IDC_TABCONTROL);
1485 char tabtext[MAX_TABTEXT_LENGTH] = "Tab text";
1486 LPCPROPSHEETPAGEA ppsp = (LPCPROPSHEETPAGEA)hpage;
1489 * Allocate and fill in a new PropPageInfo entry.
1491 psInfo->proppage = (PropPageInfo*) COMCTL32_ReAlloc(psInfo->proppage,
1492 sizeof(PropPageInfo) *
1493 (psInfo->nPages + 1));
1495 PROPSHEET_CollectPageInfo(ppsp, psInfo, psInfo->nPages);
1496 psInfo->proppage[psInfo->nPages].index = -1;
1497 psInfo->proppage[psInfo->nPages].hpage = hpage;
1500 * Create the page but don't show it.
1502 PROPSHEET_CreatePage(hwndDlg, psInfo->nPages, psInfo, ppsp, FALSE);
1505 * Add a new tab to the tab control.
1507 item.mask = TCIF_TEXT;
1508 item.pszText = tabtext;
1509 item.cchTextMax = MAX_TABTEXT_LENGTH;
1511 WideCharToMultiByte(CP_ACP, 0,
1512 (LPCWSTR)psInfo->proppage[psInfo->nPages].pszText,
1513 -1, tabtext, MAX_TABTEXT_LENGTH, NULL, NULL);
1515 SendMessageA(hwndTabControl, TCM_INSERTITEMA, psInfo->nPages + 1,
1523 /******************************************************************************
1524 * PROPSHEET_RemovePage
1526 static BOOL PROPSHEET_RemovePage(HWND hwndDlg,
1528 HPROPSHEETPAGE hpage)
1530 PropSheetInfo * psInfo = (PropSheetInfo*) GetPropA(hwndDlg,
1532 HWND hwndTabControl = GetDlgItem(hwndDlg, IDC_TABCONTROL);
1533 PropPageInfo* oldPages;
1536 FIXME("No psInfo for propertysheet at windows 0x%04x, returning FALSE...\n", hwndDlg);
1539 oldPages = psInfo->proppage;
1541 * hpage takes precedence over index.
1545 index = PROPSHEET_GetPageIndex(hpage, psInfo);
1548 /* Make shure that index is within range */
1549 if (index < 0 || index >= psInfo->nPages)
1551 TRACE("Could not find page to remove!\n");
1555 TRACE("total pages %d removing page %d active page %d\n",
1556 psInfo->nPages, index, psInfo->active_page);
1558 * Check if we're removing the active page.
1560 if (index == psInfo->active_page)
1562 if (psInfo->nPages > 1)
1566 /* activate previous page */
1567 PROPSHEET_ShowPage(hwndDlg, index - 1, psInfo);
1571 /* activate the next page */
1572 PROPSHEET_ShowPage(hwndDlg, index + 1, psInfo);
1577 TRACE("Removing the only page, close the dialog!\n");
1579 if (psInfo->isModeless)
1580 psInfo->active_page = -1;
1582 EndDialog(hwndDlg, FALSE);
1588 if (index < psInfo->active_page)
1589 psInfo->active_page--;
1591 /* Destroy page dialog window.
1592 * If it's last page in modal dialog, it has been destroyed by EndDialog
1594 if (psInfo->isModeless || psInfo->nPages > 1)
1595 DestroyWindow(psInfo->proppage[index].hwndPage);
1597 /* Remove the tab */
1598 SendMessageA(hwndTabControl, TCM_DELETEITEM, index, 0);
1601 psInfo->proppage = COMCTL32_Alloc(sizeof(PropPageInfo) * psInfo->nPages);
1604 memcpy(&psInfo->proppage[0], &oldPages[0], index * sizeof(PropPageInfo));
1606 if (index < psInfo->nPages)
1607 memcpy(&psInfo->proppage[index], &oldPages[index + 1],
1608 (psInfo->nPages - index) * sizeof(PropPageInfo));
1610 COMCTL32_Free(oldPages);
1615 /******************************************************************************
1616 * PROPSHEET_SetWizButtons
1618 * This code will work if (and assumes that) the Next button is on top of the
1619 * Finish button. ie. Finish comes after Next in the Z order.
1620 * This means make sure the dialog template reflects this.
1623 static void PROPSHEET_SetWizButtons(HWND hwndDlg, DWORD dwFlags)
1627 TRACE("%ld\n", dwFlags);
1629 if (dwFlags & PSWIZB_BACK)
1631 hwndButton = GetDlgItem(hwndDlg, IDC_BACK_BUTTON);
1632 EnableWindow(hwndButton, TRUE);
1635 if (dwFlags & PSWIZB_NEXT)
1637 /* Hide the Finish button */
1638 hwndButton = GetDlgItem(hwndDlg, IDC_FINISH_BUTTON);
1639 ShowWindow(hwndButton, SW_HIDE);
1641 /* Show and enable the Next button */
1642 hwndButton = GetDlgItem(hwndDlg, IDC_NEXT_BUTTON);
1644 ShowWindow(hwndButton, SW_SHOW);
1645 EnableWindow(hwndButton, TRUE);
1647 /* Set the Next button as the default pushbutton */
1648 SendMessageA(hwndDlg, DM_SETDEFID, IDC_NEXT_BUTTON, 0);
1651 if ((dwFlags & PSWIZB_FINISH) || (dwFlags & PSWIZB_DISABLEDFINISH))
1653 /* Hide the Next button */
1654 hwndButton = GetDlgItem(hwndDlg, IDC_NEXT_BUTTON);
1655 ShowWindow(hwndButton, SW_HIDE);
1657 /* Show the Finish button */
1658 hwndButton = GetDlgItem(hwndDlg, IDC_FINISH_BUTTON);
1659 ShowWindow(hwndButton, SW_SHOW);
1661 if (dwFlags & PSWIZB_FINISH)
1662 EnableWindow(hwndButton, TRUE);
1664 EnableWindow(hwndButton, FALSE);
1666 /* Set the Finish button as the default pushbutton */
1667 SendMessageA(hwndDlg, DM_SETDEFID, IDC_FINISH_BUTTON, 0);
1671 /******************************************************************************
1672 * PROPSHEET_GetPageIndex
1674 * Given a HPROPSHEETPAGE, returns the index of the corresponding page from
1675 * the array of PropPageInfo.
1677 static int PROPSHEET_GetPageIndex(HPROPSHEETPAGE hpage, PropSheetInfo* psInfo)
1682 while ((index < psInfo->nPages) && (found == FALSE))
1684 if (psInfo->proppage[index].hpage == hpage)
1696 /******************************************************************************
1699 static void PROPSHEET_CleanUp(HWND hwndDlg)
1701 PropSheetInfo* psInfo = (PropSheetInfo*) RemovePropA(hwndDlg,
1705 COMCTL32_Free(psInfo->proppage);
1706 COMCTL32_Free(psInfo->strPropertiesFor);
1707 ImageList_Destroy(psInfo->hImageList);
1709 GlobalFree((HGLOBAL)psInfo);
1712 /******************************************************************************
1713 * PropertySheetA (COMCTL32.84)(COMCTL32.83)
1715 INT WINAPI PropertySheetA(LPCPROPSHEETHEADERA lppsh)
1718 PropSheetInfo* psInfo = (PropSheetInfo*) GlobalAlloc(GPTR,
1719 sizeof(PropSheetInfo));
1720 LPCPROPSHEETPAGEA lppsp;
1723 PROPSHEET_CollectSheetInfo(lppsh, psInfo);
1725 psInfo->proppage = (PropPageInfo*) COMCTL32_Alloc(sizeof(PropPageInfo) *
1728 for (i = 0; i < lppsh->nPages; i++)
1730 psInfo->proppage[i].index = i;
1731 if (!(lppsh->dwFlags & PSH_PROPSHEETPAGE))
1732 psInfo->proppage[i].hpage = psInfo->ppshheader->u3.phpage[i];
1733 lppsp = PROPSHEET_GetPSPPage(psInfo, i);
1734 PROPSHEET_CollectPageInfo(lppsp, psInfo, i);
1737 bRet = PROPSHEET_CreateDialog(psInfo);
1742 /******************************************************************************
1743 * PropertySheet32W (COMCTL32.85)
1745 INT WINAPI PropertySheetW(LPCPROPSHEETHEADERW propertySheetHeader)
1747 FIXME("(%p): stub\n", propertySheetHeader);
1752 /******************************************************************************
1753 * CreatePropertySheetPageA (COMCTL32.19)(COMCTL32.18)
1755 HPROPSHEETPAGE WINAPI CreatePropertySheetPageA(
1756 LPCPROPSHEETPAGEA lpPropSheetPage)
1758 PROPSHEETPAGEA* ppsp = COMCTL32_Alloc(sizeof(PROPSHEETPAGEA));
1760 *ppsp = *lpPropSheetPage;
1762 return (HPROPSHEETPAGE)ppsp;
1765 /******************************************************************************
1766 * CreatePropertySheetPageW (COMCTL32.20)
1768 HPROPSHEETPAGE WINAPI CreatePropertySheetPageW(LPCPROPSHEETPAGEW lpPropSheetPage)
1770 FIXME("(%p): stub\n", lpPropSheetPage);
1775 /******************************************************************************
1776 * DestroyPropertySheetPage (COMCTL32.24)
1778 BOOL WINAPI DestroyPropertySheetPage(HPROPSHEETPAGE hPropPage)
1780 COMCTL32_Free(hPropPage);
1785 /******************************************************************************
1786 * PROPSHEET_DialogProc
1789 PROPSHEET_DialogProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
1795 PropSheetInfo* psInfo = (PropSheetInfo*) lParam;
1796 char* strCaption = (char*)COMCTL32_Alloc(MAX_CAPTION_LENGTH);
1797 HWND hwndTabCtrl = GetDlgItem(hwnd, IDC_TABCONTROL);
1798 LPCPROPSHEETPAGEA ppshpage;
1801 * Small icon in the title bar.
1803 if ((psInfo->ppshheader->dwFlags & PSH_USEICONID) ||
1804 (psInfo->ppshheader->dwFlags & PSH_USEHICON))
1807 int icon_cx = GetSystemMetrics(SM_CXSMICON);
1808 int icon_cy = GetSystemMetrics(SM_CYSMICON);
1810 if (psInfo->ppshheader->dwFlags & PSH_USEICONID)
1811 hIcon = LoadImageA(psInfo->ppshheader->hInstance,
1812 psInfo->ppshheader->u1.pszIcon,
1817 hIcon = psInfo->ppshheader->u1.hIcon;
1819 SendMessageA(hwnd, WM_SETICON, 0, hIcon);
1822 if (psInfo->ppshheader->dwFlags & PSH_USEHICON)
1823 SendMessageA(hwnd, WM_SETICON, 0, psInfo->ppshheader->u1.hIcon);
1825 psInfo->strPropertiesFor = strCaption;
1827 GetWindowTextA(hwnd, psInfo->strPropertiesFor, MAX_CAPTION_LENGTH);
1829 PROPSHEET_CreateTabControl(hwnd, psInfo);
1831 if (psInfo->ppshheader->dwFlags & PSH_WIZARD)
1833 HWND hwndBack = GetDlgItem(hwnd, IDC_BACK_BUTTON);
1835 if (PROPSHEET_IsTooSmallWizard(hwnd, psInfo))
1837 PROPSHEET_AdjustSizeWizard(hwnd, psInfo);
1838 PROPSHEET_AdjustButtonsWizard(hwnd, psInfo);
1841 /* Disable Back button if we start at page 0 */
1842 if (psInfo->active_page == 0)
1843 EnableWindow(hwndBack, FALSE);
1847 if (PROPSHEET_IsTooSmall(hwnd, psInfo))
1849 PROPSHEET_AdjustSize(hwnd, psInfo);
1850 PROPSHEET_AdjustButtons(hwnd, psInfo);
1854 if (psInfo->useCallback)
1855 (*(psInfo->ppshheader->pfnCallback))(hwnd,
1856 PSCB_INITIALIZED, (LPARAM)0);
1858 ppshpage = PROPSHEET_GetPSPPage(psInfo, psInfo->active_page);
1859 PROPSHEET_CreatePage(hwnd, psInfo->active_page, psInfo, ppshpage, TRUE);
1861 if (!(psInfo->ppshheader->dwFlags & PSH_WIZARD))
1862 SendMessageA(hwndTabCtrl, TCM_SETCURSEL, psInfo->active_page, 0);
1864 SetPropA(hwnd, PropSheetInfoStr, (HANDLE)psInfo);
1867 if (!HIWORD(psInfo->ppshheader->pszCaption) &&
1868 psInfo->ppshheader->hInstance)
1872 if (LoadStringA(psInfo->ppshheader->hInstance,
1873 (UINT)psInfo->ppshheader->pszCaption, szText, 255))
1874 PROPSHEET_SetTitleA(hwnd, psInfo->ppshheader->dwFlags, szText);
1878 PROPSHEET_SetTitleA(hwnd, psInfo->ppshheader->dwFlags,
1879 psInfo->ppshheader->pszCaption);
1886 PROPSHEET_CleanUp(hwnd);
1890 PROPSHEET_Cancel(hwnd);
1895 WORD wID = LOWORD(wParam);
1900 case IDC_APPLY_BUTTON:
1902 HWND hwndApplyBtn = GetDlgItem(hwnd, IDC_APPLY_BUTTON);
1904 if (PROPSHEET_Apply(hwnd) == FALSE)
1907 EnableWindow(hwndApplyBtn, FALSE);
1911 PropSheetInfo* psInfo = (PropSheetInfo*) GetPropA(hwnd,
1915 if (psInfo->restartWindows)
1916 result = ID_PSRESTARTWINDOWS;
1918 /* reboot system takes precedence over restart windows */
1919 if (psInfo->rebootSystem)
1920 result = ID_PSREBOOTSYSTEM;
1922 if (psInfo->isModeless)
1923 psInfo->active_page = -1;
1925 EndDialog(hwnd, result);
1931 case IDC_BACK_BUTTON:
1932 PROPSHEET_Back(hwnd);
1935 case IDC_NEXT_BUTTON:
1936 PROPSHEET_Next(hwnd);
1939 case IDC_FINISH_BUTTON:
1940 PROPSHEET_Finish(hwnd);
1944 PROPSHEET_Cancel(hwnd);
1948 PROPSHEET_Help(hwnd);
1957 NMHDR* pnmh = (LPNMHDR) lParam;
1959 if (pnmh->code == TCN_SELCHANGE)
1961 int index = SendMessageA(pnmh->hwndFrom, TCM_GETCURSEL, 0, 0);
1962 PROPSHEET_SetCurSel(hwnd, index, 0);
1965 if(pnmh->code == TCN_SELCHANGING)
1967 BOOL bRet = PROPSHEET_CanSetCurSel(hwnd);
1968 SetWindowLongA(hwnd, DWL_MSGRESULT, !bRet);
1976 case PSM_GETCURRENTPAGEHWND:
1978 PropSheetInfo* psInfo = (PropSheetInfo*) GetPropA(hwnd,
1982 if (psInfo->active_page != -1)
1983 hwndPage = psInfo->proppage[psInfo->active_page].hwndPage;
1985 SetWindowLongA(hwnd, DWL_MSGRESULT, hwndPage);
1991 PROPSHEET_Changed(hwnd, (HWND)wParam);
1995 PROPSHEET_UnChanged(hwnd, (HWND)wParam);
1998 case PSM_GETTABCONTROL:
2000 HWND hwndTabCtrl = GetDlgItem(hwnd, IDC_TABCONTROL);
2002 SetWindowLongA(hwnd, DWL_MSGRESULT, hwndTabCtrl);
2011 msgResult = PROPSHEET_CanSetCurSel(hwnd);
2012 if(msgResult != FALSE)
2014 msgResult = PROPSHEET_SetCurSel(hwnd,
2016 (HPROPSHEETPAGE)lParam);
2019 SetWindowLongA(hwnd, DWL_MSGRESULT, msgResult);
2024 case PSM_CANCELTOCLOSE:
2026 HWND hwndOK = GetDlgItem(hwnd, IDOK);
2027 HWND hwndCancel = GetDlgItem(hwnd, IDCANCEL);
2029 EnableWindow(hwndCancel, FALSE);
2030 SetWindowTextA(hwndOK, "Close"); /* FIXME: hardcoded string */
2035 case PSM_RESTARTWINDOWS:
2037 PropSheetInfo* psInfo = (PropSheetInfo*) GetPropA(hwnd,
2040 psInfo->restartWindows = TRUE;
2044 case PSM_REBOOTSYSTEM:
2046 PropSheetInfo* psInfo = (PropSheetInfo*) GetPropA(hwnd,
2049 psInfo->rebootSystem = TRUE;
2054 PROPSHEET_SetTitleA(hwnd, (DWORD) wParam, (LPCSTR) lParam);
2059 BOOL msgResult = PROPSHEET_Apply(hwnd);
2061 SetWindowLongA(hwnd, DWL_MSGRESULT, msgResult);
2066 case PSM_QUERYSIBLINGS:
2068 LRESULT msgResult = PROPSHEET_QuerySiblings(hwnd, wParam, lParam);
2070 SetWindowLongA(hwnd, DWL_MSGRESULT, msgResult);
2076 PROPSHEET_AddPage(hwnd, (HPROPSHEETPAGE)lParam);
2079 case PSM_REMOVEPAGE:
2080 PROPSHEET_RemovePage(hwnd, (int)wParam, (HPROPSHEETPAGE)lParam);
2083 case PSM_ISDIALOGMESSAGE:
2085 FIXME("Unimplemented msg PSM_ISDIALOGMESSAGE\n");
2089 case PSM_PRESSBUTTON:
2090 PROPSHEET_PressButton(hwnd, (int)wParam);
2093 case PSM_SETFINISHTEXTA:
2094 PROPSHEET_SetFinishTextA(hwnd, (LPCSTR) lParam);
2097 case PSM_SETWIZBUTTONS:
2098 PROPSHEET_SetWizButtons(hwnd, (DWORD)lParam);
2102 FIXME("Unimplemented msg PSM_SETTITLE32W\n");
2104 case PSM_SETCURSELID:
2105 FIXME("Unimplemented msg PSM_SETCURSELID\n");
2107 case PSM_SETFINISHTEXTW:
2108 FIXME("Unimplemented msg PSM_SETFINISHTEXT32W\n");