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 psInfo->proppage[index].pszText = HEAP_strdupAtoW(GetProcessHeap(),
290 * Build the image list for icons
292 if ((dwFlags & PSP_USEHICON) || (dwFlags & PSP_USEICONID))
295 int icon_cx = GetSystemMetrics(SM_CXSMICON);
296 int icon_cy = GetSystemMetrics(SM_CYSMICON);
298 if (dwFlags & PSP_USEICONID)
299 hIcon = LoadImageA(lppsp->hInstance, lppsp->u2.pszIcon, IMAGE_ICON,
300 icon_cx, icon_cy, LR_DEFAULTCOLOR);
302 hIcon = lppsp->u2.hIcon;
304 if (psInfo->hImageList == 0)
305 psInfo->hImageList = ImageList_Create(icon_cx, icon_cy, ILC_COLOR, 1, 1);
307 ImageList_AddIcon(psInfo->hImageList, hIcon);
313 /******************************************************************************
314 * PROPSHEET_CreateDialog
316 * Creates the actual property sheet.
318 BOOL PROPSHEET_CreateDialog(PropSheetInfo* psInfo)
325 WORD resID = IDD_PROPSHEET;
327 if (psInfo->ppshheader->dwFlags & PSH_WIZARD)
330 if(!(hRes = FindResourceA(COMCTL32_hModule,
331 MAKEINTRESOURCEA(resID),
335 if(!(template = (LPVOID)LoadResource(COMCTL32_hModule, hRes)))
339 * Make a copy of the dialog template.
341 resSize = SizeofResource(COMCTL32_hModule, hRes);
343 temp = COMCTL32_Alloc(resSize);
348 memcpy(temp, template, resSize);
350 if (psInfo->useCallback)
351 (*(psInfo->ppshheader->pfnCallback))(0, PSCB_PRECREATE, (LPARAM)temp);
353 if (psInfo->ppshheader->dwFlags & PSH_MODELESS)
354 ret = CreateDialogIndirectParamA(psInfo->ppshheader->hInstance,
355 (LPDLGTEMPLATEA) temp,
356 psInfo->ppshheader->hwndParent,
357 (DLGPROC) PROPSHEET_DialogProc,
360 ret = DialogBoxIndirectParamA(psInfo->ppshheader->hInstance,
361 (LPDLGTEMPLATEA) temp,
362 psInfo->ppshheader->hwndParent,
363 (DLGPROC) PROPSHEET_DialogProc,
371 /******************************************************************************
372 * PROPSHEET_IsTooSmall
374 * Verify that the resource property sheet is big enough.
376 static BOOL PROPSHEET_IsTooSmall(HWND hwndDlg, PropSheetInfo* psInfo)
378 HWND hwndTabCtrl = GetDlgItem(hwndDlg, IDC_TABCONTROL);
379 RECT rcOrigTab, rcPage;
384 GetClientRect(hwndTabCtrl, &rcOrigTab);
385 TRACE("orig tab %d %d %d %d\n", rcOrigTab.left, rcOrigTab.top,
386 rcOrigTab.right, rcOrigTab.bottom);
391 rcPage.left = psInfo->x;
392 rcPage.top = psInfo->y;
393 rcPage.right = psInfo->width;
394 rcPage.bottom = psInfo->height;
396 MapDialogRect(hwndDlg, &rcPage);
397 TRACE("biggest page %d %d %d %d\n", rcPage.left, rcPage.top,
398 rcPage.right, rcPage.bottom);
400 if (rcPage.right > rcOrigTab.right)
403 if (rcPage.bottom > rcOrigTab.bottom)
409 /******************************************************************************
410 * PROPSHEET_IsTooSmallWizard
412 * Verify that the default property sheet is big enough.
414 static BOOL PROPSHEET_IsTooSmallWizard(HWND hwndDlg, PropSheetInfo* psInfo)
416 RECT rcSheetRect, rcPage, rcLine, rcSheetClient;
417 HWND hwndLine = GetDlgItem(hwndDlg, IDC_SUNKEN_LINE);
418 PADDING_INFO padding = PROPSHEET_GetPaddingInfoWizard(hwndDlg);
420 GetClientRect(hwndDlg, &rcSheetClient);
421 GetWindowRect(hwndDlg, &rcSheetRect);
422 GetWindowRect(hwndLine, &rcLine);
424 /* Remove the space below the sunken line */
425 rcSheetClient.bottom -= (rcSheetRect.bottom - rcLine.top);
427 /* Remove the buffer zone all around the edge */
428 rcSheetClient.bottom -= (padding.y * 2);
429 rcSheetClient.right -= (padding.x * 2);
434 rcPage.left = psInfo->x;
435 rcPage.top = psInfo->y;
436 rcPage.right = psInfo->width;
437 rcPage.bottom = psInfo->height;
439 MapDialogRect(hwndDlg, &rcPage);
440 TRACE("biggest page %d %d %d %d\n", rcPage.left, rcPage.top,
441 rcPage.right, rcPage.bottom);
443 if (rcPage.right > rcSheetClient.right)
446 if (rcPage.bottom > rcSheetClient.bottom)
452 /******************************************************************************
453 * PROPSHEET_AdjustSize
455 * Resizes the property sheet and the tab control to fit the largest page.
457 static BOOL PROPSHEET_AdjustSize(HWND hwndDlg, PropSheetInfo* psInfo)
459 HWND hwndTabCtrl = GetDlgItem(hwndDlg, IDC_TABCONTROL);
460 HWND hwndButton = GetDlgItem(hwndDlg, IDOK);
462 int tabOffsetX, tabOffsetY, buttonHeight;
463 PADDING_INFO padding = PROPSHEET_GetPaddingInfo(hwndDlg);
465 /* Get the height of buttons */
466 GetClientRect(hwndButton, &rc);
467 buttonHeight = rc.bottom;
474 rc.right = psInfo->width;
475 rc.bottom = psInfo->height;
477 MapDialogRect(hwndDlg, &rc);
480 * Resize the tab control.
482 SendMessageA(hwndTabCtrl, TCM_ADJUSTRECT, TRUE, (LPARAM)&rc);
484 tabOffsetX = -(rc.left);
485 tabOffsetY = -(rc.top);
489 SetWindowPos(hwndTabCtrl, 0, 0, 0, rc.right, rc.bottom,
490 SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE);
492 GetClientRect(hwndTabCtrl, &rc);
494 TRACE("tab client rc %d %d %d %d\n",
495 rc.left, rc.top, rc.right, rc.bottom);
497 rc.right += ((padding.x * 2) + tabOffsetX);
498 rc.bottom += (buttonHeight + (3 * padding.y) + tabOffsetY);
501 * Resize the property sheet.
503 SetWindowPos(hwndDlg, 0, 0, 0, rc.right, rc.bottom,
504 SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE);
509 /******************************************************************************
510 * PROPSHEET_AdjustSizeWizard
512 * Resizes the property sheet to fit the largest page.
514 static BOOL PROPSHEET_AdjustSizeWizard(HWND hwndDlg, PropSheetInfo* psInfo)
516 HWND hwndButton = GetDlgItem(hwndDlg, IDCANCEL);
517 HWND hwndLine = GetDlgItem(hwndDlg, IDC_SUNKEN_LINE);
519 int buttonHeight, lineHeight;
520 PADDING_INFO padding = PROPSHEET_GetPaddingInfoWizard(hwndDlg);
522 /* Get the height of buttons */
523 GetClientRect(hwndButton, &rc);
524 buttonHeight = rc.bottom;
526 GetClientRect(hwndLine, &rc);
527 lineHeight = rc.bottom;
534 rc.right = psInfo->width;
535 rc.bottom = psInfo->height;
537 MapDialogRect(hwndDlg, &rc);
539 TRACE("Biggest page %d %d %d %d\n", rc.left, rc.top, rc.right, rc.bottom);
542 rc.right += (padding.x * 2);
543 rc.bottom += (buttonHeight + (5 * padding.y) + lineHeight);
546 * Resize the property sheet.
548 SetWindowPos(hwndDlg, 0, 0, 0, rc.right, rc.bottom,
549 SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE);
554 /******************************************************************************
555 * PROPSHEET_AdjustButtons
557 * Adjusts the buttons' positions.
559 static BOOL PROPSHEET_AdjustButtons(HWND hwndParent, PropSheetInfo* psInfo)
561 HWND hwndButton = GetDlgItem(hwndParent, IDOK);
565 int buttonWidth, buttonHeight;
566 PADDING_INFO padding = PROPSHEET_GetPaddingInfo(hwndParent);
568 if (psInfo->hasApply)
575 * Obtain the size of the buttons.
577 GetClientRect(hwndButton, &rcSheet);
578 buttonWidth = rcSheet.right;
579 buttonHeight = rcSheet.bottom;
582 * Get the size of the property sheet.
584 GetClientRect(hwndParent, &rcSheet);
587 * All buttons will be at this y coordinate.
589 y = rcSheet.bottom - (padding.y + buttonHeight);
592 * Position OK button.
594 hwndButton = GetDlgItem(hwndParent, IDOK);
596 x = rcSheet.right - ((padding.x + buttonWidth) * num_buttons);
598 SetWindowPos(hwndButton, 0, x, y, 0, 0,
599 SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE);
602 * Position Cancel button.
604 hwndButton = GetDlgItem(hwndParent, IDCANCEL);
606 x = rcSheet.right - ((padding.x + buttonWidth) * (num_buttons - 1));
608 SetWindowPos(hwndButton, 0, x, y, 0, 0,
609 SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE);
612 * Position Apply button.
614 hwndButton = GetDlgItem(hwndParent, IDC_APPLY_BUTTON);
616 if (psInfo->hasApply)
619 x = rcSheet.right - ((padding.x + buttonWidth) * 2);
621 x = rcSheet.right - (padding.x + buttonWidth);
623 SetWindowPos(hwndButton, 0, x, y, 0, 0,
624 SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE);
626 EnableWindow(hwndButton, FALSE);
629 ShowWindow(hwndButton, SW_HIDE);
632 * Position Help button.
634 hwndButton = GetDlgItem(hwndParent, IDHELP);
638 x = rcSheet.right - (padding.x + buttonWidth);
640 SetWindowPos(hwndButton, 0, x, y, 0, 0,
641 SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE);
644 ShowWindow(hwndButton, SW_HIDE);
649 /******************************************************************************
650 * PROPSHEET_AdjustButtonsWizard
652 * Adjusts the buttons' positions.
654 static BOOL PROPSHEET_AdjustButtonsWizard(HWND hwndParent,
655 PropSheetInfo* psInfo)
657 HWND hwndButton = GetDlgItem(hwndParent, IDCANCEL);
658 HWND hwndLine = GetDlgItem(hwndParent, IDC_SUNKEN_LINE);
662 int buttonWidth, buttonHeight, lineHeight, lineWidth;
663 PADDING_INFO padding = PROPSHEET_GetPaddingInfoWizard(hwndParent);
669 * Obtain the size of the buttons.
671 GetClientRect(hwndButton, &rcSheet);
672 buttonWidth = rcSheet.right;
673 buttonHeight = rcSheet.bottom;
675 GetClientRect(hwndLine, &rcSheet);
676 lineHeight = rcSheet.bottom;
679 * Get the size of the property sheet.
681 GetClientRect(hwndParent, &rcSheet);
684 * All buttons will be at this y coordinate.
686 y = rcSheet.bottom - (padding.y + buttonHeight);
689 * Position the Next and the Finish buttons.
691 hwndButton = GetDlgItem(hwndParent, IDC_NEXT_BUTTON);
693 x = rcSheet.right - ((padding.x + buttonWidth) * (num_buttons - 1));
695 SetWindowPos(hwndButton, 0, x, y, 0, 0,
696 SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE);
698 hwndButton = GetDlgItem(hwndParent, IDC_FINISH_BUTTON);
700 SetWindowPos(hwndButton, 0, x, y, 0, 0,
701 SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE);
703 ShowWindow(hwndButton, SW_HIDE);
706 * Position the Back button.
708 hwndButton = GetDlgItem(hwndParent, IDC_BACK_BUTTON);
712 SetWindowPos(hwndButton, 0, x, y, 0, 0,
713 SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE);
716 * Position the Cancel button.
718 hwndButton = GetDlgItem(hwndParent, IDCANCEL);
720 x = rcSheet.right - ((padding.x + buttonWidth) * (num_buttons - 2));
722 SetWindowPos(hwndButton, 0, x, y, 0, 0,
723 SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE);
726 * Position Help button.
728 hwndButton = GetDlgItem(hwndParent, IDHELP);
732 x = rcSheet.right - (padding.x + buttonWidth);
734 SetWindowPos(hwndButton, 0, x, y, 0, 0,
735 SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE);
738 ShowWindow(hwndButton, SW_HIDE);
741 * Position and resize the sunken line.
744 y = rcSheet.bottom - ((padding.y * 2) + buttonHeight + lineHeight);
746 GetClientRect(hwndParent, &rcSheet);
747 lineWidth = rcSheet.right - (padding.x * 2);
749 SetWindowPos(hwndLine, 0, x, y, lineWidth, 2,
750 SWP_NOZORDER | SWP_NOACTIVATE);
755 /******************************************************************************
756 * PROPSHEET_GetPaddingInfo
758 * Returns the layout information.
760 static PADDING_INFO PROPSHEET_GetPaddingInfo(HWND hwndDlg)
762 HWND hwndTab = GetDlgItem(hwndDlg, IDC_TABCONTROL);
765 PADDING_INFO padding;
767 GetWindowRect(hwndTab, &rcTab);
772 ScreenToClient(hwndDlg, &tl);
780 /******************************************************************************
781 * PROPSHEET_GetPaddingInfoWizard
783 * Returns the layout information.
784 * Horizontal spacing is the distance between the Cancel and Help buttons.
785 * Vertical spacing is the distance between the line and the buttons.
787 static PADDING_INFO PROPSHEET_GetPaddingInfoWizard(HWND hwndDlg)
789 PADDING_INFO padding;
792 POINT ptHelp, ptCancel, ptLine;
795 hwndControl = GetDlgItem(hwndDlg, IDHELP);
796 GetWindowRect(hwndControl, &rc);
801 ScreenToClient(hwndDlg, &ptHelp);
804 hwndControl = GetDlgItem(hwndDlg, IDCANCEL);
805 GetWindowRect(hwndControl, &rc);
807 ptCancel.x = rc.right;
810 ScreenToClient(hwndDlg, &ptCancel);
813 hwndControl = GetDlgItem(hwndDlg, IDC_SUNKEN_LINE);
814 GetWindowRect(hwndControl, &rc);
817 ptLine.y = rc.bottom;
819 ScreenToClient(hwndDlg, &ptLine);
821 padding.x = ptHelp.x - ptCancel.x;
822 padding.y = ptHelp.y - ptLine.y;
827 /******************************************************************************
828 * PROPSHEET_CreateTabControl
830 * Insert the tabs in the tab control.
832 static BOOL PROPSHEET_CreateTabControl(HWND hwndParent,
833 PropSheetInfo * psInfo)
835 HWND hwndTabCtrl = GetDlgItem(hwndParent, IDC_TABCONTROL);
838 char tabtext[MAX_TABTEXT_LENGTH] = "Tab text";
840 item.mask = TCIF_TEXT;
841 item.pszText = tabtext;
842 item.cchTextMax = MAX_TABTEXT_LENGTH;
844 nTabs = psInfo->ppshheader->nPages;
847 * Set the image list for icons.
849 if (psInfo->hImageList)
851 item.mask |= TCIF_IMAGE;
852 SendMessageA(hwndTabCtrl, TCM_SETIMAGELIST, 0, (LPARAM)psInfo->hImageList);
855 for (i = 0; i < nTabs; i++)
859 WideCharToMultiByte(CP_ACP, 0,
860 (LPCWSTR)psInfo->proppage[i].pszText,
861 -1, tabtext, MAX_TABTEXT_LENGTH, NULL, NULL);
863 SendMessageA(hwndTabCtrl, TCM_INSERTITEMA, (WPARAM)i, (LPARAM)&item);
869 /******************************************************************************
870 * PROPSHEET_CreatePage
874 static int PROPSHEET_CreatePage(HWND hwndParent,
876 const PropSheetInfo * psInfo,
877 LPCPROPSHEETPAGEA ppshpage,
880 DLGTEMPLATE* pTemplate;
883 PropPageInfo* ppInfo = psInfo->proppage;
884 PADDING_INFO padding;
887 TRACE("index %d\n", index);
889 if (ppshpage->dwFlags & PSP_DLGINDIRECT)
890 pTemplate = (DLGTEMPLATE*)ppshpage->u1.pResource;
893 HRSRC hResource = FindResourceA(ppshpage->hInstance,
894 ppshpage->u1.pszTemplate,
896 HGLOBAL hTemplate = LoadResource(ppshpage->hInstance, hResource);
897 pTemplate = (LPDLGTEMPLATEA)LockResource(hTemplate);
900 if (((MyDLGTEMPLATEEX*)pTemplate)->signature == 0xFFFF)
902 ((MyDLGTEMPLATEEX*)pTemplate)->style |= WS_CHILD;
903 ((MyDLGTEMPLATEEX*)pTemplate)->style &= ~DS_MODALFRAME;
904 ((MyDLGTEMPLATEEX*)pTemplate)->style &= ~WS_CAPTION;
905 ((MyDLGTEMPLATEEX*)pTemplate)->style &= ~WS_SYSMENU;
906 ((MyDLGTEMPLATEEX*)pTemplate)->style &= ~WS_POPUP;
907 ((MyDLGTEMPLATEEX*)pTemplate)->style &= ~WS_DISABLED;
911 pTemplate->style |= WS_CHILD;
912 pTemplate->style &= ~DS_MODALFRAME;
913 pTemplate->style &= ~WS_CAPTION;
914 pTemplate->style &= ~WS_SYSMENU;
915 pTemplate->style &= ~WS_POPUP;
916 pTemplate->style &= ~WS_DISABLED;
919 if (psInfo->proppage[index].useCallback)
920 (*(ppshpage->pfnCallback))(hwndParent,
922 (LPPROPSHEETPAGEA)ppshpage);
924 hwndPage = CreateDialogIndirectParamA(ppshpage->hInstance,
927 ppshpage->pfnDlgProc,
930 ppInfo[index].hwndPage = hwndPage;
934 rc.right = psInfo->width;
935 rc.bottom = psInfo->height;
937 MapDialogRect(hwndParent, &rc);
939 if (psInfo->ppshheader->dwFlags & PSH_WIZARD)
941 GetWindowRect(hwndParent, &rc);
942 padding = PROPSHEET_GetPaddingInfoWizard(hwndParent);
943 hwndAfter = hwndParent;
948 * Ask the Tab control to fit this page in.
951 HWND hwndTabCtrl = GetDlgItem(hwndParent, IDC_TABCONTROL);
952 SendMessageA(hwndTabCtrl, TCM_ADJUSTRECT, FALSE, (LPARAM)&rc);
953 padding = PROPSHEET_GetPaddingInfo(hwndParent);
954 hwndAfter = HWND_TOP;
957 SetWindowPos(hwndPage, hwndAfter,
966 hdr.hwndFrom = hwndParent;
967 hdr.code = PSN_SETACTIVE;
970 * Send the notification before showing the page.
972 SendMessageA(hwndPage, WM_NOTIFY, 0, (LPARAM) &hdr);
974 ShowWindow(hwndPage, SW_SHOW);
977 ShowWindow(hwndPage, SW_HIDE);
982 /******************************************************************************
985 * Displays or creates the specified page.
987 static BOOL PROPSHEET_ShowPage(HWND hwndDlg, int index, PropSheetInfo * psInfo)
989 if (index == psInfo->active_page)
992 ShowWindow(psInfo->proppage[psInfo->active_page].hwndPage, SW_HIDE);
994 if (psInfo->proppage[index].hwndPage != 0)
995 ShowWindow(psInfo->proppage[index].hwndPage, SW_SHOW);
998 LPCPROPSHEETPAGEA ppshpage = PROPSHEET_GetPSPPage(psInfo, index);
999 PROPSHEET_CreatePage(hwndDlg, index, psInfo, ppshpage, TRUE);
1002 psInfo->active_page = index;
1007 /******************************************************************************
1010 static BOOL PROPSHEET_Back(HWND hwndDlg)
1015 HWND hwndBack = GetDlgItem(hwndDlg, IDC_BACK_BUTTON);
1016 PropSheetInfo* psInfo = (PropSheetInfo*) GetPropA(hwndDlg,
1019 hdr.code = PSN_WIZBACK;
1021 hwndPage = psInfo->proppage[psInfo->active_page].hwndPage;
1023 if (SendMessageA(hwndPage, WM_NOTIFY, 0, (LPARAM) &hdr) == -1)
1026 res = PROPSHEET_CanSetCurSel(hwndDlg);
1029 res = PROPSHEET_SetCurSel(hwndDlg, psInfo->active_page - 1, 0);
1032 /* if we went to page 0, disable Back button */
1033 if (res && (psInfo->active_page == 0))
1034 EnableWindow(hwndBack, FALSE);
1039 /******************************************************************************
1042 static BOOL PROPSHEET_Next(HWND hwndDlg)
1046 LRESULT msgResult = 0;
1047 PropSheetInfo* psInfo = (PropSheetInfo*) GetPropA(hwndDlg,
1050 hdr.code = PSN_WIZNEXT;
1052 hwndPage = psInfo->proppage[psInfo->active_page].hwndPage;
1054 msgResult = SendMessageA(hwndPage, WM_NOTIFY, 0, (LPARAM) &hdr);
1056 TRACE("msg result %ld\n", msgResult);
1058 if (msgResult == -1)
1061 if(PROPSHEET_CanSetCurSel(hwndDlg) != FALSE)
1063 PROPSHEET_SetCurSel(hwndDlg, psInfo->active_page + 1, 0);
1069 /******************************************************************************
1072 static BOOL PROPSHEET_Finish(HWND hwndDlg)
1076 LRESULT msgResult = 0;
1077 PropSheetInfo* psInfo = (PropSheetInfo*) GetPropA(hwndDlg,
1080 hdr.code = PSN_WIZFINISH;
1082 hwndPage = psInfo->proppage[psInfo->active_page].hwndPage;
1084 msgResult = SendMessageA(hwndPage, WM_NOTIFY, 0, (LPARAM) &hdr);
1086 TRACE("msg result %ld\n", msgResult);
1091 if (psInfo->isModeless)
1092 psInfo->active_page = -1;
1094 EndDialog(hwndDlg, TRUE);
1099 /******************************************************************************
1102 static BOOL PROPSHEET_Apply(HWND hwndDlg)
1108 PropSheetInfo* psInfo = (PropSheetInfo*) GetPropA(hwndDlg,
1111 hdr.hwndFrom = hwndDlg;
1114 * Send PSN_KILLACTIVE to the current page.
1116 hdr.code = PSN_KILLACTIVE;
1118 hwndPage = psInfo->proppage[psInfo->active_page].hwndPage;
1120 if (SendMessageA(hwndPage, WM_NOTIFY, 0, (LPARAM) &hdr) != FALSE)
1124 * Send PSN_APPLY to all pages.
1126 hdr.code = PSN_APPLY;
1128 for (i = 0; i < psInfo->nPages; i++)
1130 hwndPage = psInfo->proppage[i].hwndPage;
1131 msgResult = SendMessageA(hwndPage, WM_NOTIFY, 0, (LPARAM) &hdr);
1133 if (msgResult == PSNRET_INVALID_NOCHANGEPAGE)
1140 /******************************************************************************
1143 static void PROPSHEET_Cancel(HWND hwndDlg)
1145 PropSheetInfo* psInfo = (PropSheetInfo*) GetPropA(hwndDlg,
1147 HWND hwndPage = psInfo->proppage[psInfo->active_page].hwndPage;
1150 hdr.hwndFrom = hwndDlg;
1151 hdr.code = PSN_QUERYCANCEL;
1153 if (SendMessageA(hwndPage, WM_NOTIFY, 0, (LPARAM) &hdr))
1156 hdr.code = PSN_RESET;
1158 SendMessageA(hwndPage, WM_NOTIFY, 0, (LPARAM) &hdr);
1160 if (psInfo->isModeless)
1161 psInfo->active_page = -1; /* makes PSM_GETCURRENTPAGEHWND return NULL */
1163 EndDialog(hwndDlg, FALSE);
1166 /******************************************************************************
1169 static void PROPSHEET_Help(HWND hwndDlg)
1171 PropSheetInfo* psInfo = (PropSheetInfo*) GetPropA(hwndDlg,
1173 HWND hwndPage = psInfo->proppage[psInfo->active_page].hwndPage;
1176 hdr.hwndFrom = hwndDlg;
1177 hdr.code = PSN_HELP;
1179 SendMessageA(hwndPage, WM_NOTIFY, 0, (LPARAM) &hdr);
1182 /******************************************************************************
1185 static void PROPSHEET_Changed(HWND hwndDlg, HWND hwndDirtyPage)
1188 PropSheetInfo* psInfo = (PropSheetInfo*) GetPropA(hwndDlg,
1191 if (!psInfo) return;
1193 * Set the dirty flag of this page.
1195 for (i = 0; i < psInfo->nPages; i++)
1197 if (psInfo->proppage[i].hwndPage == hwndDirtyPage)
1198 psInfo->proppage[i].isDirty = TRUE;
1202 * Enable the Apply button.
1204 if (psInfo->hasApply)
1206 HWND hwndApplyBtn = GetDlgItem(hwndDlg, IDC_APPLY_BUTTON);
1208 EnableWindow(hwndApplyBtn, TRUE);
1212 /******************************************************************************
1213 * PROPSHEET_UnChanged
1215 static void PROPSHEET_UnChanged(HWND hwndDlg, HWND hwndCleanPage)
1218 BOOL noPageDirty = TRUE;
1219 HWND hwndApplyBtn = GetDlgItem(hwndDlg, IDC_APPLY_BUTTON);
1220 PropSheetInfo* psInfo = (PropSheetInfo*) GetPropA(hwndDlg,
1223 for (i = 0; i < psInfo->nPages; i++)
1225 /* set the specified page as clean */
1226 if (psInfo->proppage[i].hwndPage == hwndCleanPage)
1227 psInfo->proppage[i].isDirty = FALSE;
1229 /* look to see if there's any dirty pages */
1230 if (psInfo->proppage[i].isDirty)
1231 noPageDirty = FALSE;
1235 * Disable Apply button.
1238 EnableWindow(hwndApplyBtn, FALSE);
1241 /******************************************************************************
1242 * PROPSHEET_PressButton
1244 static void PROPSHEET_PressButton(HWND hwndDlg, int buttonID)
1248 case PSBTN_APPLYNOW:
1249 SendMessageA(hwndDlg, WM_COMMAND, IDC_APPLY_BUTTON, 0);
1252 PROPSHEET_Back(hwndDlg);
1255 SendMessageA(hwndDlg, WM_COMMAND, IDCANCEL, 0);
1258 PROPSHEET_Finish(hwndDlg);
1261 SendMessageA(hwndDlg, WM_COMMAND, IDHELP, 0);
1264 PROPSHEET_Next(hwndDlg);
1267 SendMessageA(hwndDlg, WM_COMMAND, IDOK, 0);
1270 FIXME("Invalid button index %d\n", buttonID);
1275 /*************************************************************************
1276 * BOOL PROPSHEET_CanSetCurSel [Internal]
1278 * Test weither the current page can be change by sending a PSN_KILLACTIVE
1281 * hwndDlg [I] handle to a Dialog hWnd
1284 * TRUE if Current Selection can change
1288 static BOOL PROPSHEET_CanSetCurSel(HWND hwndDlg)
1290 PropSheetInfo* psInfo = (PropSheetInfo*) GetPropA(hwndDlg,
1295 * Notify the current page.
1297 hwndPage = psInfo->proppage[psInfo->active_page].hwndPage;
1299 hdr.hwndFrom = hwndDlg;
1300 hdr.code = PSN_KILLACTIVE;
1302 return !SendMessageA(hwndPage, WM_NOTIFY, 0, (LPARAM) &hdr);
1305 /******************************************************************************
1306 * PROPSHEET_SetCurSel
1308 static BOOL PROPSHEET_SetCurSel(HWND hwndDlg,
1310 HPROPSHEETPAGE hpage)
1312 PropSheetInfo* psInfo = (PropSheetInfo*) GetPropA(hwndDlg,
1315 HWND hwndHelp = GetDlgItem(hwndDlg, IDHELP);
1319 * Notify the current page.
1321 hwndPage = psInfo->proppage[psInfo->active_page].hwndPage;
1323 hdr.hwndFrom = hwndDlg;
1324 hdr.code = PSN_KILLACTIVE;
1326 if (SendMessageA(hwndPage, WM_NOTIFY, 0, (LPARAM) &hdr))
1330 * hpage takes precedence over index.
1334 index = PROPSHEET_GetPageIndex(hpage, psInfo);
1338 TRACE("Could not find page to remove!\n");
1343 hwndPage = psInfo->proppage[index].hwndPage;
1346 * Notify the new page if it's already created.
1347 * If not it will get created and notified in PROPSHEET_ShowPage.
1352 hdr.code = PSN_SETACTIVE;
1354 result = SendMessageA(hwndPage, WM_NOTIFY, 0, (LPARAM) &hdr);
1356 * TODO: check return value.
1361 * Display the new page.
1363 PROPSHEET_ShowPage(hwndDlg, index, psInfo);
1365 if (psInfo->proppage[index].hasHelp)
1366 EnableWindow(hwndHelp, TRUE);
1368 EnableWindow(hwndHelp, FALSE);
1373 /******************************************************************************
1374 * PROPSHEET_SetTitleA
1376 static void PROPSHEET_SetTitleA(HWND hwndDlg, DWORD dwStyle, LPCSTR lpszText)
1378 if (dwStyle & PSH_PROPTITLE)
1380 PropSheetInfo* psInfo = (PropSheetInfo*) GetPropA(hwndDlg,
1383 int lentitle = strlen(lpszText);
1384 int lenprop = strlen(psInfo->strPropertiesFor);
1386 dest = COMCTL32_Alloc(lentitle + lenprop + 1);
1387 strcpy(dest, psInfo->strPropertiesFor);
1388 strcat(dest, lpszText);
1390 SetWindowTextA(hwndDlg, dest);
1391 COMCTL32_Free(dest);
1394 SetWindowTextA(hwndDlg, lpszText);
1397 /******************************************************************************
1398 * PROPSHEET_SetFinishTextA
1400 static void PROPSHEET_SetFinishTextA(HWND hwndDlg, LPCSTR lpszText)
1402 HWND hwndButton = GetDlgItem(hwndDlg, IDC_FINISH_BUTTON);
1404 /* Set text, show and enable the Finish button */
1405 SetWindowTextA(hwndButton, lpszText);
1406 ShowWindow(hwndButton, SW_SHOW);
1407 EnableWindow(hwndButton, TRUE);
1409 /* Make it default pushbutton */
1410 SendMessageA(hwndDlg, DM_SETDEFID, IDC_FINISH_BUTTON, 0);
1412 /* Hide Back button */
1413 hwndButton = GetDlgItem(hwndDlg, IDC_BACK_BUTTON);
1414 ShowWindow(hwndButton, SW_HIDE);
1416 /* Hide Next button */
1417 hwndButton = GetDlgItem(hwndDlg, IDC_NEXT_BUTTON);
1418 ShowWindow(hwndButton, SW_HIDE);
1421 /******************************************************************************
1422 * PROPSHEET_QuerySiblings
1424 static LRESULT PROPSHEET_QuerySiblings(HWND hwndDlg,
1425 WPARAM wParam, LPARAM lParam)
1429 LRESULT msgResult = 0;
1430 PropSheetInfo* psInfo = (PropSheetInfo*) GetPropA(hwndDlg,
1433 while ((i < psInfo->nPages) && (msgResult == 0))
1435 hwndPage = psInfo->proppage[i].hwndPage;
1436 msgResult = SendMessageA(hwndPage, PSM_QUERYSIBLINGS, wParam, lParam);
1443 /******************************************************************************
1444 * PROPSHEET_GetPSPPage
1446 static LPCPROPSHEETPAGEA PROPSHEET_GetPSPPage(const PropSheetInfo * psInfo,
1449 BOOL usePSP = psInfo->ppshheader->dwFlags & PSH_PROPSHEETPAGE;
1450 LPCPROPSHEETPAGEA lppsp;
1451 int realIndex = psInfo->proppage[index].index;
1457 lppsp = psInfo->ppshheader->u3.ppsp;
1459 pByte = (BYTE*) lppsp;
1461 pByte += (lppsp->dwSize * realIndex);
1462 lppsp = (LPCPROPSHEETPAGEA)pByte;
1465 lppsp = (LPCPROPSHEETPAGEA) psInfo->ppshheader->u3.phpage[realIndex];
1470 /******************************************************************************
1473 static BOOL PROPSHEET_AddPage(HWND hwndDlg,
1474 HPROPSHEETPAGE hpage)
1476 PropSheetInfo * psInfo = (PropSheetInfo*) GetPropA(hwndDlg,
1478 HWND hwndTabControl = GetDlgItem(hwndDlg, IDC_TABCONTROL);
1480 char tabtext[MAX_TABTEXT_LENGTH] = "Tab text";
1481 LPCPROPSHEETPAGEA ppsp = (LPCPROPSHEETPAGEA)hpage;
1484 * Allocate and fill in a new PropPageInfo entry.
1486 psInfo->proppage = (PropPageInfo*) COMCTL32_ReAlloc(psInfo->proppage,
1487 sizeof(PropPageInfo) *
1488 (psInfo->nPages + 1));
1490 PROPSHEET_CollectPageInfo(ppsp, psInfo, psInfo->nPages);
1491 psInfo->proppage[psInfo->nPages].index = -1;
1492 psInfo->proppage[psInfo->nPages].hpage = hpage;
1495 * Create the page but don't show it.
1497 PROPSHEET_CreatePage(hwndDlg, psInfo->nPages, psInfo, ppsp, FALSE);
1500 * Add a new tab to the tab control.
1502 item.mask = TCIF_TEXT;
1503 item.pszText = tabtext;
1504 item.cchTextMax = MAX_TABTEXT_LENGTH;
1506 WideCharToMultiByte(CP_ACP, 0,
1507 (LPCWSTR)psInfo->proppage[psInfo->nPages].pszText,
1508 -1, tabtext, MAX_TABTEXT_LENGTH, NULL, NULL);
1510 SendMessageA(hwndTabControl, TCM_INSERTITEMA, psInfo->nPages + 1,
1518 /******************************************************************************
1519 * PROPSHEET_RemovePage
1521 static BOOL PROPSHEET_RemovePage(HWND hwndDlg,
1523 HPROPSHEETPAGE hpage)
1525 PropSheetInfo * psInfo = (PropSheetInfo*) GetPropA(hwndDlg,
1527 HWND hwndTabControl = GetDlgItem(hwndDlg, IDC_TABCONTROL);
1528 PropPageInfo* oldPages;
1531 FIXME("No psInfo for propertysheet at windows 0x%04x? returning FALSE...\n");
1534 oldPages = psInfo->proppage;
1536 * hpage takes precedence over index.
1540 index = PROPSHEET_GetPageIndex(hpage, psInfo);
1544 TRACE("Could not find page to remove!\n");
1549 TRACE("total pages %d removing page %d active page %d\n",
1550 psInfo->nPages, index, psInfo->active_page);
1552 * Check if we're removing the active page.
1554 if (index == psInfo->active_page)
1556 if (psInfo->nPages > 1)
1560 /* activate previous page */
1561 PROPSHEET_ShowPage(hwndDlg, index - 1, psInfo);
1565 /* activate the next page */
1566 PROPSHEET_ShowPage(hwndDlg, index + 1, psInfo);
1571 TRACE("Removing the only page, close the dialog!\n");
1573 if (psInfo->isModeless)
1574 psInfo->active_page = -1;
1576 EndDialog(hwndDlg, FALSE);
1582 if (index < psInfo->active_page)
1583 psInfo->active_page--;
1585 /* Remove the tab */
1586 SendMessageA(hwndTabControl, TCM_DELETEITEM, index, 0);
1589 psInfo->proppage = COMCTL32_Alloc(sizeof(PropPageInfo) * psInfo->nPages);
1592 memcpy(&psInfo->proppage[0], &oldPages[0], index * sizeof(PropPageInfo));
1594 if (index < psInfo->nPages)
1595 memcpy(&psInfo->proppage[index], &oldPages[index + 1],
1596 (psInfo->nPages - index) * sizeof(PropPageInfo));
1598 COMCTL32_Free(oldPages);
1603 /******************************************************************************
1604 * PROPSHEET_SetWizButtons
1606 * This code will work if (and assumes that) the Next button is on top of the
1607 * Finish button. ie. Finish comes after Next in the Z order.
1608 * This means make sure the dialog template reflects this.
1611 static void PROPSHEET_SetWizButtons(HWND hwndDlg, DWORD dwFlags)
1615 TRACE("%ld\n", dwFlags);
1617 if (dwFlags & PSWIZB_BACK)
1619 hwndButton = GetDlgItem(hwndDlg, IDC_BACK_BUTTON);
1620 EnableWindow(hwndButton, TRUE);
1623 if (dwFlags & PSWIZB_NEXT)
1625 /* Hide the Finish button */
1626 hwndButton = GetDlgItem(hwndDlg, IDC_FINISH_BUTTON);
1627 ShowWindow(hwndButton, SW_HIDE);
1629 /* Show and enable the Next button */
1630 hwndButton = GetDlgItem(hwndDlg, IDC_NEXT_BUTTON);
1632 ShowWindow(hwndButton, SW_SHOW);
1633 EnableWindow(hwndButton, TRUE);
1635 /* Set the Next button as the default pushbutton */
1636 SendMessageA(hwndDlg, DM_SETDEFID, IDC_NEXT_BUTTON, 0);
1639 if ((dwFlags & PSWIZB_FINISH) || (dwFlags & PSWIZB_DISABLEDFINISH))
1641 /* Hide the Next button */
1642 hwndButton = GetDlgItem(hwndDlg, IDC_NEXT_BUTTON);
1643 ShowWindow(hwndButton, SW_HIDE);
1645 /* Show the Finish button */
1646 hwndButton = GetDlgItem(hwndDlg, IDC_FINISH_BUTTON);
1647 ShowWindow(hwndButton, SW_SHOW);
1649 if (dwFlags & PSWIZB_FINISH)
1650 EnableWindow(hwndButton, TRUE);
1652 EnableWindow(hwndButton, FALSE);
1654 /* Set the Finish button as the default pushbutton */
1655 SendMessageA(hwndDlg, DM_SETDEFID, IDC_FINISH_BUTTON, 0);
1659 /******************************************************************************
1660 * PROPSHEET_GetPageIndex
1662 * Given a HPROPSHEETPAGE, returns the index of the corresponding page from
1663 * the array of PropPageInfo.
1665 static int PROPSHEET_GetPageIndex(HPROPSHEETPAGE hpage, PropSheetInfo* psInfo)
1670 while ((index < psInfo->nPages) && (found == FALSE))
1672 if (psInfo->proppage[index].hpage == hpage)
1684 /******************************************************************************
1687 static void PROPSHEET_CleanUp(HWND hwndDlg)
1689 PropSheetInfo* psInfo = (PropSheetInfo*) RemovePropA(hwndDlg,
1693 COMCTL32_Free(psInfo->proppage);
1694 COMCTL32_Free(psInfo->strPropertiesFor);
1695 ImageList_Destroy(psInfo->hImageList);
1697 GlobalFree((HGLOBAL)psInfo);
1700 /******************************************************************************
1701 * PropertySheetA (COMCTL32.84)(COMCTL32.83)
1703 INT WINAPI PropertySheetA(LPCPROPSHEETHEADERA lppsh)
1706 PropSheetInfo* psInfo = (PropSheetInfo*) GlobalAlloc(GPTR,
1707 sizeof(PropSheetInfo));
1708 LPCPROPSHEETPAGEA lppsp;
1711 PROPSHEET_CollectSheetInfo(lppsh, psInfo);
1713 psInfo->proppage = (PropPageInfo*) COMCTL32_Alloc(sizeof(PropPageInfo) *
1716 for (i = 0; i < lppsh->nPages; i++)
1718 psInfo->proppage[i].index = i;
1719 if (!(lppsh->dwFlags & PSH_PROPSHEETPAGE))
1720 psInfo->proppage[i].hpage = psInfo->ppshheader->u3.phpage[i];
1721 lppsp = PROPSHEET_GetPSPPage(psInfo, i);
1722 PROPSHEET_CollectPageInfo(lppsp, psInfo, i);
1725 bRet = PROPSHEET_CreateDialog(psInfo);
1730 /******************************************************************************
1731 * PropertySheet32W (COMCTL32.85)
1733 INT WINAPI PropertySheetW(LPCPROPSHEETHEADERW propertySheetHeader)
1735 FIXME("(%p): stub\n", propertySheetHeader);
1740 /******************************************************************************
1741 * CreatePropertySheetPageA (COMCTL32.19)(COMCTL32.18)
1743 HPROPSHEETPAGE WINAPI CreatePropertySheetPageA(
1744 LPCPROPSHEETPAGEA lpPropSheetPage)
1746 PROPSHEETPAGEA* ppsp = COMCTL32_Alloc(sizeof(PROPSHEETPAGEA));
1748 *ppsp = *lpPropSheetPage;
1750 return (HPROPSHEETPAGE)ppsp;
1753 /******************************************************************************
1754 * CreatePropertySheetPageW (COMCTL32.20)
1756 HPROPSHEETPAGE WINAPI CreatePropertySheetPageW(LPCPROPSHEETPAGEW lpPropSheetPage)
1758 FIXME("(%p): stub\n", lpPropSheetPage);
1763 /******************************************************************************
1764 * DestroyPropertySheetPage (COMCTL32.24)
1766 BOOL WINAPI DestroyPropertySheetPage(HPROPSHEETPAGE hPropPage)
1768 COMCTL32_Free(hPropPage);
1773 /******************************************************************************
1774 * PROPSHEET_DialogProc
1777 PROPSHEET_DialogProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
1783 PropSheetInfo* psInfo = (PropSheetInfo*) lParam;
1784 char* strCaption = (char*)COMCTL32_Alloc(MAX_CAPTION_LENGTH);
1785 HWND hwndTabCtrl = GetDlgItem(hwnd, IDC_TABCONTROL);
1786 LPCPROPSHEETPAGEA ppshpage;
1789 * Small icon in the title bar.
1791 if ((psInfo->ppshheader->dwFlags & PSH_USEICONID) ||
1792 (psInfo->ppshheader->dwFlags & PSH_USEHICON))
1795 int icon_cx = GetSystemMetrics(SM_CXSMICON);
1796 int icon_cy = GetSystemMetrics(SM_CYSMICON);
1798 if (psInfo->ppshheader->dwFlags & PSH_USEICONID)
1799 hIcon = LoadImageA(psInfo->ppshheader->hInstance,
1800 psInfo->ppshheader->u1.pszIcon,
1805 hIcon = psInfo->ppshheader->u1.hIcon;
1807 SendMessageA(hwnd, WM_SETICON, 0, hIcon);
1810 if (psInfo->ppshheader->dwFlags & PSH_USEHICON)
1811 SendMessageA(hwnd, WM_SETICON, 0, psInfo->ppshheader->u1.hIcon);
1813 psInfo->strPropertiesFor = strCaption;
1815 GetWindowTextA(hwnd, psInfo->strPropertiesFor, MAX_CAPTION_LENGTH);
1817 if (psInfo->ppshheader->dwFlags & PSH_WIZARD)
1819 HWND hwndBack = GetDlgItem(hwnd, IDC_BACK_BUTTON);
1821 if (PROPSHEET_IsTooSmallWizard(hwnd, psInfo))
1823 PROPSHEET_AdjustSizeWizard(hwnd, psInfo);
1824 PROPSHEET_AdjustButtonsWizard(hwnd, psInfo);
1827 /* Disable Back button if we start at page 0 */
1828 if (psInfo->active_page == 0)
1829 EnableWindow(hwndBack, FALSE);
1833 PROPSHEET_CreateTabControl(hwnd, psInfo);
1835 if (PROPSHEET_IsTooSmall(hwnd, psInfo))
1837 PROPSHEET_AdjustSize(hwnd, psInfo);
1838 PROPSHEET_AdjustButtons(hwnd, psInfo);
1842 ppshpage = PROPSHEET_GetPSPPage(psInfo, psInfo->active_page);
1843 PROPSHEET_CreatePage(hwnd, psInfo->active_page, psInfo, ppshpage, TRUE);
1845 if (!(psInfo->ppshheader->dwFlags & PSH_WIZARD))
1846 SendMessageA(hwndTabCtrl, TCM_SETCURSEL, psInfo->active_page, 0);
1848 SetPropA(hwnd, PropSheetInfoStr, (HANDLE)psInfo);
1850 PROPSHEET_SetTitleA(hwnd,
1851 psInfo->ppshheader->dwFlags,
1852 psInfo->ppshheader->pszCaption);
1858 PROPSHEET_CleanUp(hwnd);
1862 PROPSHEET_Cancel(hwnd);
1867 WORD wID = LOWORD(wParam);
1872 case IDC_APPLY_BUTTON:
1874 HWND hwndApplyBtn = GetDlgItem(hwnd, IDC_APPLY_BUTTON);
1876 if (PROPSHEET_Apply(hwnd) == FALSE)
1879 EnableWindow(hwndApplyBtn, FALSE);
1883 PropSheetInfo* psInfo = (PropSheetInfo*) GetPropA(hwnd,
1887 if (psInfo->restartWindows)
1888 result = ID_PSRESTARTWINDOWS;
1890 /* reboot system takes precedence over restart windows */
1891 if (psInfo->rebootSystem)
1892 result = ID_PSREBOOTSYSTEM;
1894 if (psInfo->isModeless)
1895 psInfo->active_page = -1;
1897 EndDialog(hwnd, result);
1903 case IDC_BACK_BUTTON:
1904 PROPSHEET_Back(hwnd);
1907 case IDC_NEXT_BUTTON:
1908 PROPSHEET_Next(hwnd);
1911 case IDC_FINISH_BUTTON:
1912 PROPSHEET_Finish(hwnd);
1916 PROPSHEET_Cancel(hwnd);
1920 PROPSHEET_Help(hwnd);
1929 NMHDR* pnmh = (LPNMHDR) lParam;
1931 if (pnmh->code == TCN_SELCHANGE)
1933 int index = SendMessageA(pnmh->hwndFrom, TCM_GETCURSEL, 0, 0);
1934 PROPSHEET_SetCurSel(hwnd, index, 0);
1937 if(pnmh->code == TCN_SELCHANGING)
1939 BOOL bRet = PROPSHEET_CanSetCurSel(hwnd);
1940 SetWindowLongA(hwnd, DWL_MSGRESULT, !bRet);
1948 case PSM_GETCURRENTPAGEHWND:
1950 PropSheetInfo* psInfo = (PropSheetInfo*) GetPropA(hwnd,
1954 if (psInfo->active_page != -1)
1955 hwndPage = psInfo->proppage[psInfo->active_page].hwndPage;
1957 SetWindowLongA(hwnd, DWL_MSGRESULT, hwndPage);
1963 PROPSHEET_Changed(hwnd, (HWND)wParam);
1967 PROPSHEET_UnChanged(hwnd, (HWND)wParam);
1970 case PSM_GETTABCONTROL:
1972 HWND hwndTabCtrl = GetDlgItem(hwnd, IDC_TABCONTROL);
1974 SetWindowLongA(hwnd, DWL_MSGRESULT, hwndTabCtrl);
1983 msgResult = PROPSHEET_CanSetCurSel(hwnd);
1984 if(msgResult != FALSE)
1986 msgResult = PROPSHEET_SetCurSel(hwnd,
1988 (HPROPSHEETPAGE)lParam);
1991 SetWindowLongA(hwnd, DWL_MSGRESULT, msgResult);
1996 case PSM_CANCELTOCLOSE:
1998 HWND hwndOK = GetDlgItem(hwnd, IDOK);
1999 HWND hwndCancel = GetDlgItem(hwnd, IDCANCEL);
2001 EnableWindow(hwndCancel, FALSE);
2002 SetWindowTextA(hwndOK, "Close"); /* FIXME: hardcoded string */
2007 case PSM_RESTARTWINDOWS:
2009 PropSheetInfo* psInfo = (PropSheetInfo*) GetPropA(hwnd,
2012 psInfo->restartWindows = TRUE;
2016 case PSM_REBOOTSYSTEM:
2018 PropSheetInfo* psInfo = (PropSheetInfo*) GetPropA(hwnd,
2021 psInfo->rebootSystem = TRUE;
2026 PROPSHEET_SetTitleA(hwnd, (DWORD) wParam, (LPCSTR) lParam);
2031 BOOL msgResult = PROPSHEET_Apply(hwnd);
2033 SetWindowLongA(hwnd, DWL_MSGRESULT, msgResult);
2038 case PSM_QUERYSIBLINGS:
2040 LRESULT msgResult = PROPSHEET_QuerySiblings(hwnd, wParam, lParam);
2042 SetWindowLongA(hwnd, DWL_MSGRESULT, msgResult);
2048 PROPSHEET_AddPage(hwnd, (HPROPSHEETPAGE)lParam);
2051 case PSM_REMOVEPAGE:
2052 PROPSHEET_RemovePage(hwnd, (int)wParam, (HPROPSHEETPAGE)lParam);
2055 case PSM_ISDIALOGMESSAGE:
2057 FIXME("Unimplemented msg PSM_ISDIALOGMESSAGE\n");
2061 case PSM_PRESSBUTTON:
2062 PROPSHEET_PressButton(hwnd, (int)wParam);
2065 case PSM_SETFINISHTEXTA:
2066 PROPSHEET_SetFinishTextA(hwnd, (LPCSTR) lParam);
2069 case PSM_SETWIZBUTTONS:
2070 PROPSHEET_SetWizButtons(hwnd, (DWORD)lParam);
2074 FIXME("Unimplemented msg PSM_SETTITLE32W\n");
2076 case PSM_SETCURSELID:
2077 FIXME("Unimplemented msg PSM_SETCURSELID\n");
2079 case PSM_SETFINISHTEXTW:
2080 FIXME("Unimplemented msg PSM_SETFINISHTEXT32W\n");