4 * Copyright 1998 Francis Beaudet
5 * Copyright 1999 Thuy Nguyen
10 * - Adding and removing pages dynamically (PSM_ADDPAGE,etc)
11 * - CreatePropertySheetPage
12 * - DestroyPropertySheetPage
24 /******************************************************************************
36 typedef struct tagPropPageInfo
45 typedef struct tagPropSheetInfo
47 LPSTR strPropertiesFor;
49 LPCPROPSHEETHEADERA ppshheader;
56 PropPageInfo* proppage;
69 /******************************************************************************
70 * Defines and global variables
72 const char * PropSheetInfoStr = "PropertySheetInfo";
74 #define MAX_CAPTION_LENGTH 255
76 #define IDC_TABCONTROL 12320
77 #define IDC_APPLY_BUTTON 12321
79 /******************************************************************************
82 static BOOL PROPSHEET_CreateDialog(PropSheetInfo* psInfo);
83 static BOOL PROPSHEET_IsTooSmall(HWND hwndDlg, PropSheetInfo* psInfo);
84 static BOOL PROPSHEET_AdjustSize(HWND hwndDlg, PropSheetInfo* psInfo);
85 static BOOL PROPSHEET_AdjustButtons(HWND hwndParent, PropSheetInfo* psInfo);
86 static BOOL PROPSHEET_CollectSheetInfo(LPCPROPSHEETHEADERA lppsh,
87 PropSheetInfo * psInfo);
88 static BOOL PROPSHEET_CollectPageInfo(LPCPROPSHEETHEADERA lppsh,
89 PropSheetInfo * psInfo);
90 static BOOL PROPSHEET_CreateTabControl(HWND hwndParent,
91 PropSheetInfo * psInfo);
92 static int PROPSHEET_CreatePage(HWND hwndParent, int index,
93 const PropSheetInfo * psInfo);
94 static BOOL PROPSHEET_ShowPage(HWND hwndDlg, int index, PropSheetInfo * psInfo);
95 static PADDING_INFO PROPSHEET_GetPaddingInfo(HWND hwndDlg);
96 static BOOL PROPSHEET_Apply(HWND hwndDlg);
97 static void PROPSHEET_Cancel(HWND hwndDlg);
98 static void PROPSHEET_Changed(HWND hwndDlg, HWND hwndDirtyPage);
99 static void PROPSHEET_UnChanged(HWND hwndDlg, HWND hwndCleanPage);
100 static void PROPSHEET_PressButton(HWND hwndDlg, int buttonID);
101 static void PROPSHEET_SetTitleA(HWND hwndDlg, DWORD dwStyle, LPCSTR lpszText);
102 static BOOL PROPSHEET_SetCurSel(HWND hwndDlg,
104 HPROPSHEETPAGE hpage);
105 static LRESULT PROPSHEET_QuerySiblings(HWND hwndDlg,
106 WPARAM wParam, LPARAM lParam);
107 static LPCPROPSHEETPAGEA PROPSHEET_GetPage(const PropSheetInfo * psInfo,
109 static BOOL PROPSHEET_AddPage(HWND hwndDlg,
110 HPROPSHEETPAGE hpage);
112 static BOOL PROPSHEET_RemovePage(HWND hwndDlg,
114 HPROPSHEETPAGE hpage);
115 static void PROPSHEET_CleanUp();
118 PROPSHEET_DialogProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
120 DEFAULT_DEBUG_CHANNEL(propsheet)
122 /******************************************************************************
123 * PROPSHEET_CollectSheetInfo
125 * Collect relevant data.
127 static BOOL PROPSHEET_CollectSheetInfo(LPCPROPSHEETHEADERA lppsh,
128 PropSheetInfo * psInfo)
130 DWORD dwFlags = lppsh->dwFlags;
132 psInfo->hasHelp = dwFlags & PSH_HASHELP;
133 psInfo->hasApply = !(dwFlags & PSH_NOAPPLYNOW);
134 psInfo->useCallback = dwFlags & PSH_USECALLBACK;
135 psInfo->isModeless = dwFlags & PSH_MODELESS;
136 psInfo->ppshheader = lppsh;
138 if (dwFlags & PSH_USEPSTARTPAGE)
140 TRACE(propsheet, "PSH_USEPSTARTPAGE is on");
141 psInfo->active_page = 0;
144 psInfo->active_page = lppsh->u2.nStartPage;
146 psInfo->restartWindows = FALSE;
147 psInfo->rebootSystem = FALSE;
152 /******************************************************************************
153 * PROPSHEET_CollectPageInfo
155 * Collect property sheet data.
156 * With code taken from DIALOG_ParseTemplate32.
158 BOOL PROPSHEET_CollectPageInfo(LPCPROPSHEETHEADERA lppsh,
159 PropSheetInfo * psInfo)
161 DLGTEMPLATE* pTemplate;
165 LPCPROPSHEETPAGEA lppsp;
168 psInfo->proppage = (PropPageInfo*) COMCTL32_Alloc(sizeof(PropPageInfo) *
171 for (i = 0; i < lppsh->nPages; i++)
173 lppsp = PROPSHEET_GetPage(psInfo, i);
175 psInfo->proppage[i].hwndPage = 0;
176 psInfo->proppage[i].isDirty = FALSE;
179 * Process property page flags.
181 dwFlags = lppsp->dwFlags;
182 psInfo->proppage[i].useCallback = dwFlags & PSP_USECALLBACK;
183 psInfo->proppage[i].hasHelp = dwFlags & PSP_HASHELP;
185 /* as soon as we have a page with the help flag, set the sheet flag on */
186 if (psInfo->proppage[i].hasHelp)
187 psInfo->hasHelp = TRUE;
190 * Process page template.
192 if (dwFlags & PSP_DLGINDIRECT)
193 pTemplate = (DLGTEMPLATE*)lppsp->u1.pResource;
196 HRSRC hResource = FindResourceA(lppsp->hInstance,
197 lppsp->u1.pszTemplate,
199 HGLOBAL hTemplate = LoadResource(lppsp->hInstance,
201 pTemplate = (LPDLGTEMPLATEA)LockResource(hTemplate);
205 * Extract the size of the page and the caption.
207 p = (const WORD *)pTemplate;
209 if (((MyDLGTEMPLATEEX*)pTemplate)->signature == 0xFFFF)
211 /* DIALOGEX template */
215 p += 2; /* help ID */
216 p += 2; /* ext style */
221 /* DIALOG template */
224 p += 2; /* ext style */
230 width = (WORD)*p; p++;
231 height = (WORD)*p; p++;
233 /* remember the largest width and height */
234 if (width > psInfo->width)
235 psInfo->width = width;
237 if (height > psInfo->height)
238 psInfo->height = height;
250 p += lstrlenW( (LPCWSTR)p ) + 1;
264 p += lstrlenW( (LPCWSTR)p ) + 1;
268 /* Extract the caption */
269 psInfo->proppage[i].pszText = (LPCWSTR)p;
270 TRACE(propsheet, "Tab %d %s\n",i,debugstr_w((LPCWSTR)p));
271 p += lstrlenW((LPCWSTR)p) + 1;
277 /******************************************************************************
278 * PROPSHEET_CreateDialog
280 * Creates the actual property sheet.
282 BOOL PROPSHEET_CreateDialog(PropSheetInfo* psInfo)
287 template = SYSRES_GetResPtr(SYSRES_DIALOG_PROPSHEET);
289 if (psInfo->useCallback)
290 (*(psInfo->ppshheader->pfnCallback))(0, PSCB_PRECREATE, (LPARAM)template);
292 if (psInfo->ppshheader->dwFlags & PSH_MODELESS)
293 ret = CreateDialogIndirectParamA(psInfo->ppshheader->hInstance,
294 (LPDLGTEMPLATEA) template,
295 psInfo->ppshheader->hwndParent,
296 (DLGPROC) PROPSHEET_DialogProc,
299 ret = DialogBoxIndirectParamA(psInfo->ppshheader->hInstance,
300 (LPDLGTEMPLATEA) template,
301 psInfo->ppshheader->hwndParent,
302 (DLGPROC) PROPSHEET_DialogProc,
308 /******************************************************************************
309 * PROPSHEET_IsTooSmall
311 * Verify that the resource property sheet is big enough.
313 static BOOL PROPSHEET_IsTooSmall(HWND hwndDlg, PropSheetInfo* psInfo)
315 HWND hwndTabCtrl = GetDlgItem(hwndDlg, IDC_TABCONTROL);
316 RECT rcOrigTab, rcPage;
321 GetClientRect(hwndTabCtrl, &rcOrigTab);
322 TRACE(propsheet, "orig tab %d %d %d %d\n", rcOrigTab.left, rcOrigTab.top,
323 rcOrigTab.right, rcOrigTab.bottom);
328 rcPage.left = psInfo->x;
329 rcPage.top = psInfo->y;
330 rcPage.right = psInfo->width;
331 rcPage.bottom = psInfo->height;
333 MapDialogRect(hwndDlg, &rcPage);
334 TRACE(propsheet, "biggest page %d %d %d %d\n", rcPage.left, rcPage.top,
335 rcPage.right, rcPage.bottom);
337 if (rcPage.right > rcOrigTab.right)
340 if (rcPage.bottom > rcOrigTab.bottom)
346 /******************************************************************************
347 * PROPSHEET_AdjustSize
349 * Resizes the property sheet and the tab control to fit the largest page.
351 static BOOL PROPSHEET_AdjustSize(HWND hwndDlg, PropSheetInfo* psInfo)
353 HWND hwndTabCtrl = GetDlgItem(hwndDlg, IDC_TABCONTROL);
354 HWND hwndButton = GetDlgItem(hwndDlg, IDOK);
356 int tabOffsetX, tabOffsetY, buttonHeight;
357 PADDING_INFO padding = PROPSHEET_GetPaddingInfo(hwndDlg);
359 /* Get the height of buttons */
360 GetClientRect(hwndButton, &rc);
361 buttonHeight = rc.bottom;
368 rc.right = psInfo->width;
369 rc.bottom = psInfo->height;
371 MapDialogRect(hwndDlg, &rc);
374 * Resize the tab control.
376 SendMessageA(hwndTabCtrl, TCM_ADJUSTRECT, TRUE, (LPARAM)&rc);
378 tabOffsetX = -(rc.left);
379 tabOffsetY = -(rc.top);
383 SetWindowPos(hwndTabCtrl, 0, 0, 0, rc.right, rc.bottom,
384 SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE);
386 GetClientRect(hwndTabCtrl, &rc);
388 TRACE(propsheet, "tab client rc %d %d %d %d\n",
389 rc.left, rc.top, rc.right, rc.bottom);
391 rc.right += ((padding.x * 2) + tabOffsetX);
392 rc.bottom += (buttonHeight + (3 * padding.y) + tabOffsetY);
395 * Resize the property sheet.
397 SetWindowPos(hwndDlg, 0, 0, 0, rc.right, rc.bottom,
398 SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE);
403 /******************************************************************************
404 * PROPSHEET_AdjustButtons
406 * Adjusts the buttons' positions.
408 static BOOL PROPSHEET_AdjustButtons(HWND hwndParent, PropSheetInfo* psInfo)
410 HWND hwndButton = GetDlgItem(hwndParent, IDOK);
414 int buttonWidth, buttonHeight;
415 PADDING_INFO padding = PROPSHEET_GetPaddingInfo(hwndParent);
417 if (psInfo->hasApply)
424 * Obtain the size of the buttons.
426 GetClientRect(hwndButton, &rcSheet);
427 buttonWidth = rcSheet.right;
428 buttonHeight = rcSheet.bottom;
431 * Get the size of the property sheet.
433 GetClientRect(hwndParent, &rcSheet);
436 * All buttons will be at this y coordinate.
438 y = rcSheet.bottom - (padding.y + buttonHeight);
441 * Position OK button.
443 hwndButton = GetDlgItem(hwndParent, IDOK);
445 x = rcSheet.right - ((padding.x + buttonWidth) * num_buttons);
447 SetWindowPos(hwndButton, 0, x, y, 0, 0,
448 SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE);
451 * Position Cancel button.
453 hwndButton = GetDlgItem(hwndParent, IDCANCEL);
455 x = rcSheet.right - ((padding.x + buttonWidth) * (num_buttons - 1));
457 SetWindowPos(hwndButton, 0, x, y, 0, 0,
458 SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE);
461 * Position Apply button.
463 hwndButton = GetDlgItem(hwndParent, IDC_APPLY_BUTTON);
465 if (psInfo->hasApply)
468 x = rcSheet.right - ((padding.x + buttonWidth) * 2);
470 x = rcSheet.right - (padding.x + buttonWidth);
472 SetWindowPos(hwndButton, 0, x, y, 0, 0,
473 SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE);
475 EnableWindow(hwndButton, FALSE);
478 ShowWindow(hwndButton, SW_HIDE);
481 * Position Help button.
483 hwndButton = GetDlgItem(hwndParent, IDHELP);
487 x = rcSheet.right - (padding.x + buttonWidth);
489 SetWindowPos(hwndButton, 0, x, y, 0, 0,
490 SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE);
493 ShowWindow(hwndButton, SW_HIDE);
498 /******************************************************************************
499 * PROPSHEET_GetPaddingInfo
501 * Returns the layout information.
503 static PADDING_INFO PROPSHEET_GetPaddingInfo(HWND hwndDlg)
505 HWND hwndTab = GetDlgItem(hwndDlg, IDC_TABCONTROL);
508 PADDING_INFO padding;
510 GetWindowRect(hwndTab, &rcTab);
515 ScreenToClient(hwndDlg, &tl);
523 /******************************************************************************
524 * PROPSHEET_CreateTabControl
526 * Insert the tabs in the tab control.
528 static BOOL PROPSHEET_CreateTabControl(HWND hwndParent,
529 PropSheetInfo * psInfo)
531 HWND hwndTabCtrl = GetDlgItem(hwndParent, IDC_TABCONTROL);
534 char tabtext[255] = "Tab text";
536 item.mask = TCIF_TEXT;
537 item.pszText = tabtext;
538 item.cchTextMax = 255;
540 nTabs = psInfo->ppshheader->nPages;
542 for (i = 0; i < nTabs; i++)
544 WideCharToMultiByte(CP_ACP, 0,
545 (LPCWSTR)psInfo->proppage[i].pszText,
546 -1, tabtext, 255, NULL, NULL);
548 SendMessageA(hwndTabCtrl, TCM_INSERTITEMA, (WPARAM)i, (LPARAM)&item);
554 /******************************************************************************
555 * PROPSHEET_CreatePage
559 static int PROPSHEET_CreatePage(HWND hwndParent,
561 const PropSheetInfo * psInfo)
563 DLGTEMPLATE* pTemplate;
566 PropPageInfo* ppInfo = psInfo->proppage;
567 LPCPROPSHEETPAGEA ppshpage = PROPSHEET_GetPage(psInfo, index);
568 PADDING_INFO padding = PROPSHEET_GetPaddingInfo(hwndParent);
569 HWND hwndTabCtrl = GetDlgItem(hwndParent, IDC_TABCONTROL);
571 TRACE(propsheet, "index %d\n", index);
573 if (ppshpage->dwFlags & PSP_DLGINDIRECT)
574 pTemplate = (DLGTEMPLATE*)ppshpage->u1.pResource;
577 HRSRC hResource = FindResourceA(ppshpage->hInstance,
578 ppshpage->u1.pszTemplate,
580 HGLOBAL hTemplate = LoadResource(ppshpage->hInstance, hResource);
581 pTemplate = (LPDLGTEMPLATEA)LockResource(hTemplate);
584 if (((MyDLGTEMPLATEEX*)pTemplate)->signature == 0xFFFF)
586 ((MyDLGTEMPLATEEX*)pTemplate)->style |= WS_CHILD;
587 ((MyDLGTEMPLATEEX*)pTemplate)->style &= ~DS_MODALFRAME;
588 ((MyDLGTEMPLATEEX*)pTemplate)->style &= ~WS_CAPTION;
589 ((MyDLGTEMPLATEEX*)pTemplate)->style &= ~WS_SYSMENU;
590 ((MyDLGTEMPLATEEX*)pTemplate)->style &= ~WS_POPUP;
594 pTemplate->style |= WS_CHILD;
595 pTemplate->style &= ~DS_MODALFRAME;
596 pTemplate->style &= ~WS_CAPTION;
597 pTemplate->style &= ~WS_SYSMENU;
598 pTemplate->style &= ~WS_POPUP;
601 if (psInfo->proppage[index].useCallback)
602 (*(ppshpage->pfnCallback))(hwndParent,
604 (LPPROPSHEETPAGEA)ppshpage);
606 hwndPage = CreateDialogIndirectA(ppshpage->hInstance,
609 ppshpage->pfnDlgProc);
611 ppInfo[index].hwndPage = hwndPage;
615 rc.right = psInfo->width;
616 rc.bottom = psInfo->height;
618 MapDialogRect(hwndParent, &rc);
621 * Ask the Tab control to fit this page in.
623 SendMessageA(hwndTabCtrl, TCM_ADJUSTRECT, FALSE, (LPARAM)&rc);
625 SetWindowPos(hwndPage, HWND_TOP,
630 ShowWindow(hwndPage, SW_SHOW);
635 /******************************************************************************
638 * Displays or creates the specified page.
640 static BOOL PROPSHEET_ShowPage(HWND hwndDlg, int index, PropSheetInfo * psInfo)
642 if (index == psInfo->active_page)
645 ShowWindow(psInfo->proppage[psInfo->active_page].hwndPage, SW_HIDE);
647 if (psInfo->proppage[index].hwndPage != 0)
648 ShowWindow(psInfo->proppage[index].hwndPage, SW_SHOW);
650 PROPSHEET_CreatePage(hwndDlg, index, psInfo);
652 psInfo->active_page = index;
657 /******************************************************************************
660 static BOOL PROPSHEET_Apply(HWND hwndDlg)
666 PropSheetInfo* psInfo = (PropSheetInfo*) GetPropA(hwndDlg,
669 hdr.hwndFrom = hwndDlg;
672 * Send PSN_KILLACTIVE to the current page.
674 hdr.code = PSN_KILLACTIVE;
676 hwndPage = psInfo->proppage[psInfo->active_page].hwndPage;
678 if (SendMessageA(hwndPage, WM_NOTIFY, 0, (LPARAM) &hdr) != FALSE)
682 * Send PSN_APPLY to all pages.
684 hdr.code = PSN_APPLY;
686 for (i = 0; i < psInfo->ppshheader->nPages; i++)
688 hwndPage = psInfo->proppage[i].hwndPage;
689 msgResult = SendMessageA(hwndPage, WM_NOTIFY, 0, (LPARAM) &hdr);
691 if (msgResult == PSNRET_INVALID_NOCHANGEPAGE)
698 /******************************************************************************
701 static void PROPSHEET_Cancel(HWND hwndDlg)
703 PropSheetInfo* psInfo = (PropSheetInfo*) GetPropA(hwndDlg,
705 HWND hwndPage = psInfo->proppage[psInfo->active_page].hwndPage;
708 hdr.hwndFrom = hwndDlg;
709 hdr.code = PSN_QUERYCANCEL;
711 if (SendMessageA(hwndPage, WM_NOTIFY, 0, (LPARAM) &hdr))
714 hdr.code = PSN_RESET;
716 SendMessageA(hwndPage, WM_NOTIFY, 0, (LPARAM) &hdr);
718 if (psInfo->isModeless)
719 psInfo->active_page = -1; /* makes PSM_GETCURRENTPAGEHWND return NULL */
721 EndDialog(hwndDlg, FALSE);
724 /******************************************************************************
727 static void PROPSHEET_Changed(HWND hwndDlg, HWND hwndDirtyPage)
730 PropSheetInfo* psInfo = (PropSheetInfo*) GetPropA(hwndDlg,
734 * Set the dirty flag of this page.
736 for (i = 0; i < psInfo->ppshheader->nPages; i++)
738 if (psInfo->proppage[i].hwndPage == hwndDirtyPage)
739 psInfo->proppage[i].isDirty = TRUE;
743 * Enable the Apply button.
745 if (psInfo->hasApply)
747 HWND hwndApplyBtn = GetDlgItem(hwndDlg, IDC_APPLY_BUTTON);
749 EnableWindow(hwndApplyBtn, TRUE);
753 /******************************************************************************
754 * PROPSHEET_UnChanged
756 static void PROPSHEET_UnChanged(HWND hwndDlg, HWND hwndCleanPage)
759 BOOL noPageDirty = TRUE;
760 HWND hwndApplyBtn = GetDlgItem(hwndDlg, IDC_APPLY_BUTTON);
761 PropSheetInfo* psInfo = (PropSheetInfo*) GetPropA(hwndDlg,
764 for (i = 0; i < psInfo->ppshheader->nPages; i++)
766 /* set the specified page as clean */
767 if (psInfo->proppage[i].hwndPage == hwndCleanPage)
768 psInfo->proppage[i].isDirty = FALSE;
770 /* look to see if there's any dirty pages */
771 if (psInfo->proppage[i].isDirty)
776 * Disable Apply button.
779 EnableWindow(hwndApplyBtn, FALSE);
782 /******************************************************************************
783 * PROPSHEET_PressButton
785 static void PROPSHEET_PressButton(HWND hwndDlg, int buttonID)
790 SendMessageA(hwndDlg, WM_COMMAND, IDC_APPLY_BUTTON, 0);
793 FIXME(propsheet, "Wizard mode not implemented.\n");
796 SendMessageA(hwndDlg, WM_COMMAND, IDCANCEL, 0);
799 FIXME(propsheet, "Wizard mode not implemented.\n");
802 SendMessageA(hwndDlg, WM_COMMAND, IDHELP, 0);
805 FIXME(propsheet, "Wizard mode not implemented.\n");
808 SendMessageA(hwndDlg, WM_COMMAND, IDOK, 0);
811 FIXME(propsheet, "Invalid button index %d\n", buttonID);
815 /******************************************************************************
816 * PROPSHEET_SetCurSel
818 static BOOL PROPSHEET_SetCurSel(HWND hwndDlg,
820 HPROPSHEETPAGE hpage)
822 PropSheetInfo* psInfo = (PropSheetInfo*) GetPropA(hwndDlg,
825 HWND hwndHelp = GetDlgItem(hwndDlg, IDHELP);
829 * Notify the current page.
831 hwndPage = psInfo->proppage[psInfo->active_page].hwndPage;
833 hdr.hwndFrom = hwndDlg;
834 hdr.code = PSN_KILLACTIVE;
836 if (SendMessageA(hwndPage, WM_NOTIFY, 0, (LPARAM) &hdr))
840 FIXME(propsheet, "Implement HPROPSHEETPAGE!\n");
842 hwndPage = psInfo->proppage[index].hwndPage;
845 * Notify the new page.
847 hdr.code = PSN_SETACTIVE;
849 SendMessageA(hwndPage, WM_NOTIFY, 0, (LPARAM) &hdr);
852 * Display the new page.
854 PROPSHEET_ShowPage(hwndDlg, index, psInfo);
856 if (psInfo->proppage[index].hasHelp)
857 EnableWindow(hwndHelp, TRUE);
859 EnableWindow(hwndHelp, FALSE);
864 /******************************************************************************
865 * PROPSHEET_SetTitleA
867 static void PROPSHEET_SetTitleA(HWND hwndDlg, DWORD dwStyle, LPCSTR lpszText)
869 if (dwStyle & PSH_PROPTITLE)
871 PropSheetInfo* psInfo = (PropSheetInfo*) GetPropA(hwndDlg,
874 int lentitle = strlen(lpszText);
875 int lenprop = strlen(psInfo->strPropertiesFor);
877 dest = COMCTL32_Alloc(lentitle + lenprop + 1);
878 strcpy(dest, psInfo->strPropertiesFor);
879 strcat(dest, lpszText);
881 SetWindowTextA(hwndDlg, dest);
885 SetWindowTextA(hwndDlg, lpszText);
888 /******************************************************************************
889 * PROPSHEET_QuerySiblings
891 static LRESULT PROPSHEET_QuerySiblings(HWND hwndDlg,
892 WPARAM wParam, LPARAM lParam)
896 LRESULT msgResult = 0;
897 PropSheetInfo* psInfo = (PropSheetInfo*) GetPropA(hwndDlg,
900 while ((i < psInfo->ppshheader->nPages) && (msgResult == 0))
902 hwndPage = psInfo->proppage[i].hwndPage;
903 msgResult = SendMessageA(hwndPage, PSM_QUERYSIBLINGS, wParam, lParam);
910 /******************************************************************************
913 static LPCPROPSHEETPAGEA PROPSHEET_GetPage(const PropSheetInfo * psInfo,
916 LPCPROPSHEETPAGEA lppsp = psInfo->ppshheader->u3.ppsp;
917 BYTE* pByte = (BYTE*) lppsp;
919 pByte += (lppsp->dwSize * index);
920 lppsp = (LPCPROPSHEETPAGEA)pByte;
925 /******************************************************************************
928 static BOOL PROPSHEET_AddPage(HWND hwndDlg,
929 HPROPSHEETPAGE hpage)
931 /* PropSheetInfo * psInfo = (PropSheetInfo*) GetPropA(hwndDlg,
933 HWND hwndTabControl = GetDlgItem(hwndDlg, IDC_TABCONTROL);
935 psInfo->proppage = (PropPageInfo*) COMCTL32_ReAlloc(psInfo->proppage,
936 sizeof(PropPageInfo) *
937 (psInfo->nPages + 1));
944 /******************************************************************************
945 * PROPSHEET_RemovePage
947 static BOOL PROPSHEET_RemovePage(HWND hwndDlg,
949 HPROPSHEETPAGE hpage)
952 PropSheetInfo * psInfo = (PropSheetInfo*) GetPropA(hwndDlg,
955 HWND hwndTabControl = GetDlgItem(hwndDlg, IDC_TABCONTROL);
960 /******************************************************************************
963 static void PROPSHEET_CleanUp(HWND hwndDlg)
965 PropSheetInfo* psInfo = (PropSheetInfo*) RemovePropA(hwndDlg,
967 COMCTL32_Free(psInfo->proppage);
968 COMCTL32_Free(psInfo->strPropertiesFor);
970 GlobalFree((HGLOBAL)psInfo);
973 /******************************************************************************
974 * PropertySheetA (COMCTL32.84)(COMCTL32.83)
976 INT WINAPI PropertySheetA(LPCPROPSHEETHEADERA lppsh)
979 PropSheetInfo* psInfo = (PropSheetInfo*) GlobalAlloc(GPTR,
980 sizeof(PropSheetInfo));
982 PROPSHEET_CollectSheetInfo(lppsh, psInfo);
983 PROPSHEET_CollectPageInfo(lppsh, psInfo);
985 bRet = PROPSHEET_CreateDialog(psInfo);
990 /******************************************************************************
991 * PropertySheet32W (COMCTL32.85)
993 INT WINAPI PropertySheetW(LPCPROPSHEETHEADERW propertySheetHeader)
995 FIXME(propsheet, "(%p): stub\n", propertySheetHeader);
1000 /******************************************************************************
1001 * CreatePropertySheetPage32A (COMCTL32.19)(COMCTL32.18)
1003 HPROPSHEETPAGE WINAPI CreatePropertySheetPageA(LPCPROPSHEETPAGEA lpPropSheetPage)
1005 FIXME(propsheet, "(%p): stub\n", lpPropSheetPage);
1010 /******************************************************************************
1011 * CreatePropertySheetPage32W (COMCTL32.20)
1013 HPROPSHEETPAGE WINAPI CreatePropertySheetPageW(LPCPROPSHEETPAGEW lpPropSheetPage)
1015 FIXME(propsheet, "(%p): stub\n", lpPropSheetPage);
1020 /******************************************************************************
1021 * DestroyPropertySheetPage32 (COMCTL32.24)
1023 BOOL WINAPI DestroyPropertySheetPage(HPROPSHEETPAGE hPropPage)
1025 FIXME(propsheet, "(0x%08lx): stub\n", (DWORD)hPropPage);
1029 /******************************************************************************
1030 * PROPSHEET_DialogProc
1033 PROPSHEET_DialogProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
1039 PropSheetInfo* psInfo = (PropSheetInfo*) lParam;
1040 char* strCaption = (char*)COMCTL32_Alloc(MAX_CAPTION_LENGTH);
1041 HWND hwndTabCtrl = GetDlgItem(hwnd, IDC_TABCONTROL);
1043 psInfo->strPropertiesFor = strCaption;
1045 GetWindowTextA(hwnd, psInfo->strPropertiesFor, MAX_CAPTION_LENGTH);
1047 PROPSHEET_CreateTabControl(hwnd, psInfo);
1049 if (PROPSHEET_IsTooSmall(hwnd, psInfo))
1051 PROPSHEET_AdjustSize(hwnd, psInfo);
1052 PROPSHEET_AdjustButtons(hwnd, psInfo);
1055 PROPSHEET_CreatePage(hwnd, psInfo->active_page, psInfo);
1056 SendMessageA(hwndTabCtrl, TCM_SETCURSEL, psInfo->active_page, 0);
1058 SetPropA(hwnd, PropSheetInfoStr, (HANDLE)psInfo);
1060 PROPSHEET_SetTitleA(hwnd,
1061 psInfo->ppshheader->dwFlags,
1062 psInfo->ppshheader->pszCaption);
1068 PROPSHEET_CleanUp(hwnd);
1072 PROPSHEET_Cancel(hwnd);
1077 WORD wID = LOWORD(wParam);
1082 case IDC_APPLY_BUTTON:
1084 HWND hwndApplyBtn = GetDlgItem(hwnd, IDC_APPLY_BUTTON);
1086 if (PROPSHEET_Apply(hwnd) == FALSE)
1089 EnableWindow(hwndApplyBtn, FALSE);
1093 PropSheetInfo* psInfo = (PropSheetInfo*) GetPropA(hwnd,
1097 if (psInfo->restartWindows)
1098 result = ID_PSRESTARTWINDOWS;
1100 /* reboot system takes precedence over restart windows */
1101 if (psInfo->rebootSystem)
1102 result = ID_PSREBOOTSYSTEM;
1104 if (psInfo->isModeless)
1105 psInfo->active_page = -1;
1107 EndDialog(hwnd, result);
1114 PROPSHEET_Cancel(hwnd);
1119 PROPSHEET_RemovePage(hwnd, 1, 0);
1120 FIXME(propsheet, "Help!\n");
1130 NMHDR* pnmh = (LPNMHDR) lParam;
1132 if (pnmh->code == TCN_SELCHANGE)
1134 PropSheetInfo* psInfo = (PropSheetInfo*) GetPropA(hwnd,
1136 int index = SendMessageA(pnmh->hwndFrom, TCM_GETCURSEL, 0, 0);
1137 HWND hwndHelp = GetDlgItem(hwnd, IDHELP);
1139 PROPSHEET_ShowPage(hwnd, index, psInfo);
1141 if (psInfo->proppage[index].hasHelp)
1142 EnableWindow(hwndHelp, TRUE);
1144 EnableWindow(hwndHelp, FALSE);
1150 case PSM_GETCURRENTPAGEHWND:
1152 PropSheetInfo* psInfo = (PropSheetInfo*) GetPropA(hwnd,
1156 if (psInfo->active_page != -1)
1157 hwndPage = psInfo->proppage[psInfo->active_page].hwndPage;
1159 SetWindowLongA(hwnd, DWL_MSGRESULT, hwndPage);
1165 PROPSHEET_Changed(hwnd, (HWND)wParam);
1169 PROPSHEET_UnChanged(hwnd, (HWND)wParam);
1172 case PSM_GETTABCONTROL:
1174 HWND hwndTabCtrl = GetDlgItem(hwnd, IDC_TABCONTROL);
1176 SetWindowLongA(hwnd, DWL_MSGRESULT, hwndTabCtrl);
1185 msgResult = PROPSHEET_SetCurSel(hwnd,
1187 (HPROPSHEETPAGE)lParam);
1189 SetWindowLongA(hwnd, DWL_MSGRESULT, msgResult);
1194 case PSM_CANCELTOCLOSE:
1196 HWND hwndOK = GetDlgItem(hwnd, IDOK);
1197 HWND hwndCancel = GetDlgItem(hwnd, IDCANCEL);
1199 EnableWindow(hwndCancel, FALSE);
1200 SetWindowTextA(hwndOK, "Close"); /* FIXME: hardcoded string */
1205 case PSM_RESTARTWINDOWS:
1207 PropSheetInfo* psInfo = (PropSheetInfo*) GetPropA(hwnd,
1210 psInfo->restartWindows = TRUE;
1214 case PSM_REBOOTSYSTEM:
1216 PropSheetInfo* psInfo = (PropSheetInfo*) GetPropA(hwnd,
1219 psInfo->rebootSystem = TRUE;
1224 PROPSHEET_SetTitleA(hwnd, (DWORD) wParam, (LPCSTR) lParam);
1229 BOOL msgResult = PROPSHEET_Apply(hwnd);
1231 SetWindowLongA(hwnd, DWL_MSGRESULT, msgResult);
1236 case PSM_QUERYSIBLINGS:
1238 LRESULT msgResult = PROPSHEET_QuerySiblings(hwnd, wParam, lParam);
1240 SetWindowLongA(hwnd, DWL_MSGRESULT, msgResult);
1245 case PSM_ISDIALOGMESSAGE:
1247 FIXME (propsheet, "Unimplemented msg PSM_REMOVEPAGE\n");
1251 case PSM_PRESSBUTTON:
1252 PROPSHEET_PressButton(hwnd, (int)wParam);
1255 case PSM_REMOVEPAGE:
1256 FIXME (propsheet, "Unimplemented msg PSM_REMOVEPAGE\n");
1257 PROPSHEET_RemovePage(hwnd, (int)wParam, (HPROPSHEETPAGE)lParam);
1260 FIXME (propsheet, "Unimplemented msg PSM_ADDPAGE\n");
1261 PROPSHEET_AddPage(hwnd, (HPROPSHEETPAGE)lParam);
1264 FIXME (propsheet, "Unimplemented msg PSM_SETTITLE32W\n");
1266 case PSM_SETWIZBUTTONS:
1267 FIXME (propsheet, "Unimplemented msg PSM_SETWIZBUTTONS\n");
1269 case PSM_SETCURSELID:
1270 FIXME (propsheet, "Unimplemented msg PSM_SETCURSELID\n");
1272 case PSM_SETFINISHTEXTA:
1273 FIXME (propsheet, "Unimplemented msg PSM_SETFINISHTEXT32A\n");
1275 case PSM_SETFINISHTEXTW:
1276 FIXME (propsheet, "Unimplemented msg PSM_SETFINISHTEXT32W\n");