source: trunk/src/comctl32/propsheet.c@ 722

Last change on this file since 722 was 722, checked in by achimha, 26 years ago

merged with latest WINE changes

File size: 40.5 KB
Line 
1/* $Id: propsheet.c,v 1.8 1999-08-28 09:25:56 achimha Exp $ */
2/*
3 * Property Sheets
4 *
5 * Copyright 1998 Francis Beaudet
6 * Copyright 1999 Thuy Nguyen
7 * Copyright 1999 Achim Hasenmueller
8 * Copyright 1999 Christoph Bratschi
9 *
10 * TODO:
11 * - Modeless mode
12 * - Wizard mode
13 * - Unicode property sheets
14 */
15
16/* WINE 990815 level */
17
18/* CB: Odin problems:
19 - trap in PROPSHEET_DialogProc (tab control creation)
20 - LockResource traps
21*/
22
23#include <string.h>
24#include "winbase.h"
25#include "commctrl.h"
26#include "prsht.h"
27#include "winnls.h"
28#include "comctl32.h"
29
30
31/******************************************************************************
32 * Data structures
33 */
34typedef struct
35{
36 WORD dlgVer;
37 WORD signature;
38 DWORD helpID;
39 DWORD exStyle;
40 DWORD style;
41} MyDLGTEMPLATEEX;
42
43typedef struct tagPropPageInfo
44{
45 int index; /* corresponds to the index in ppshheader->ppsp */
46 HPROPSHEETPAGE hpage; /* to keep track of pages not passed to PropertySheet */
47 HWND hwndPage;
48 BOOL isDirty;
49 LPCWSTR pszText;
50 BOOL hasHelp;
51 BOOL useCallback;
52} PropPageInfo;
53
54typedef struct tagPropSheetInfo
55{
56 LPSTR strPropertiesFor;
57 int nPages;
58 int active_page;
59 LPCPROPSHEETHEADERA ppshheader;
60 BOOL isModeless;
61 BOOL hasHelp;
62 BOOL hasApply;
63 BOOL useCallback;
64 BOOL restartWindows;
65 BOOL rebootSystem;
66 PropPageInfo* proppage;
67 int x;
68 int y;
69 int width;
70 int height;
71 HIMAGELIST hImageList;
72} PropSheetInfo;
73
74typedef struct
75{
76 int x;
77 int y;
78} PADDING_INFO;
79
80/******************************************************************************
81 * Defines and global variables
82 */
83
84const char * PropSheetInfoStr = "PropertySheetInfo";
85
86#define MAX_CAPTION_LENGTH 255
87#define MAX_TABTEXT_LENGTH 255
88
89
90/******************************************************************************
91 * Prototypes
92 */
93static BOOL PROPSHEET_CreateDialog(PropSheetInfo* psInfo);
94static BOOL PROPSHEET_IsTooSmall(HWND hwndDlg, PropSheetInfo* psInfo);
95static BOOL PROPSHEET_AdjustSize(HWND hwndDlg, PropSheetInfo* psInfo);
96static BOOL PROPSHEET_AdjustButtons(HWND hwndParent, PropSheetInfo* psInfo);
97static BOOL PROPSHEET_CollectSheetInfo(LPCPROPSHEETHEADERA lppsh,
98 PropSheetInfo * psInfo);
99static BOOL PROPSHEET_CollectPageInfo(LPCPROPSHEETPAGEA lppsp,
100 PropSheetInfo * psInfo,
101 int index);
102static BOOL PROPSHEET_CreateTabControl(HWND hwndParent,
103 PropSheetInfo * psInfo);
104static int PROPSHEET_CreatePage(HWND hwndParent, int index,
105 const PropSheetInfo * psInfo,
106 LPCPROPSHEETPAGEA ppshpage,
107 BOOL showPage);
108static BOOL PROPSHEET_ShowPage(HWND hwndDlg, int index, PropSheetInfo * psInfo);
109static PADDING_INFO PROPSHEET_GetPaddingInfo(HWND hwndDlg);
110static BOOL PROPSHEET_Apply(HWND hwndDlg);
111static void PROPSHEET_Cancel(HWND hwndDlg);
112static void PROPSHEET_Help(HWND hwndDlg);
113static void PROPSHEET_Changed(HWND hwndDlg, HWND hwndDirtyPage);
114static void PROPSHEET_UnChanged(HWND hwndDlg, HWND hwndCleanPage);
115static void PROPSHEET_PressButton(HWND hwndDlg, int buttonID);
116static void PROPSHEET_SetTitleA(HWND hwndDlg, DWORD dwStyle, LPCSTR lpszText);
117static BOOL PROPSHEET_SetCurSel(HWND hwndDlg,
118 int index,
119 HPROPSHEETPAGE hpage);
120static LRESULT PROPSHEET_QuerySiblings(HWND hwndDlg,
121 WPARAM wParam, LPARAM lParam);
122static LPCPROPSHEETPAGEA PROPSHEET_GetPSPPage(const PropSheetInfo * psInfo,
123 int index);
124static BOOL PROPSHEET_AddPage(HWND hwndDlg,
125 HPROPSHEETPAGE hpage);
126
127static BOOL PROPSHEET_RemovePage(HWND hwndDlg,
128 int index,
129 HPROPSHEETPAGE hpage);
130static void PROPSHEET_CleanUp();
131static int PROPSHEET_GetPageIndex(HPROPSHEETPAGE hpage, PropSheetInfo* psInfo);
132
133BOOL WINAPI
134PROPSHEET_DialogProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
135
136
137/******************************************************************************
138 * PROPSHEET_CollectSheetInfo
139 *
140 * Collect relevant data.
141 */
142static BOOL PROPSHEET_CollectSheetInfo(LPCPROPSHEETHEADERA lppsh,
143 PropSheetInfo * psInfo)
144{
145 DWORD dwFlags = lppsh->dwFlags;
146
147 psInfo->hasHelp = dwFlags & PSH_HASHELP;
148 psInfo->hasApply = !(dwFlags & PSH_NOAPPLYNOW);
149 psInfo->useCallback = dwFlags & PSH_USECALLBACK;
150 psInfo->isModeless = dwFlags & PSH_MODELESS;
151 psInfo->ppshheader = lppsh;
152 psInfo->nPages = lppsh->nPages;
153
154 if (dwFlags & PSH_USEPSTARTPAGE)
155 {
156// TRACE(propsheet, "PSH_USEPSTARTPAGE is on");
157 psInfo->active_page = 0;
158 }
159 else
160 psInfo->active_page = lppsh->u2.nStartPage;
161
162 psInfo->restartWindows = FALSE;
163 psInfo->rebootSystem = FALSE;
164 psInfo->hImageList = 0;
165
166 return TRUE;
167}
168
169/******************************************************************************
170 * PROPSHEET_CollectPageInfo
171 *
172 * Collect property sheet data.
173 * With code taken from DIALOG_ParseTemplate32.
174 */
175BOOL PROPSHEET_CollectPageInfo(LPCPROPSHEETPAGEA lppsp,
176 PropSheetInfo * psInfo,
177 int index)
178{
179 DLGTEMPLATE* pTemplate;
180 const WORD* p;
181 DWORD dwFlags;
182 int width, height;
183
184 if (psInfo->ppshheader->dwFlags & PSH_PROPSHEETPAGE)
185 psInfo->proppage[index].hpage = 0;
186 psInfo->proppage[index].hwndPage = 0;
187 psInfo->proppage[index].isDirty = FALSE;
188
189 /*
190 * Process property page flags.
191 */
192 dwFlags = lppsp->dwFlags;
193 psInfo->proppage[index].useCallback = dwFlags & PSP_USECALLBACK;
194 psInfo->proppage[index].hasHelp = dwFlags & PSP_HASHELP;
195
196 /* as soon as we have a page with the help flag, set the sheet flag on */
197 if (psInfo->proppage[index].hasHelp)
198 psInfo->hasHelp = TRUE;
199
200 /*
201 * Process page template.
202 */
203 if (dwFlags & PSP_DLGINDIRECT)
204 pTemplate = (DLGTEMPLATE*)lppsp->u1.pResource;
205 else
206 {
207 HRSRC hResource = FindResourceA(lppsp->hInstance,
208 lppsp->u1.pszTemplate,
209 RT_DIALOGA);
210 HGLOBAL hTemplate = LoadResource(lppsp->hInstance,
211 hResource);
212 //pTemplate = (LPDLGTEMPLATEA)LockResource(hTemplate); //CB: trap, fix it
213 }
214
215 /*
216 * Extract the size of the page and the caption.
217 */
218 p = (const WORD *)pTemplate;
219
220 if (((MyDLGTEMPLATEEX*)pTemplate)->signature == 0xFFFF)
221 {
222 /* DIALOGEX template */
223
224 p++; /* dlgVer */
225 p++; /* signature */
226 p += 2; /* help ID */
227 p += 2; /* ext style */
228 p += 2; /* style */
229 }
230 else
231 {
232 /* DIALOG template */
233
234 p += 2; /* style */
235 p += 2; /* ext style */
236 }
237
238 p++; /* nb items */
239 p++; /* x */
240 p++; /* y */
241 width = (WORD)*p; p++;
242 height = (WORD)*p; p++;
243
244 /* remember the largest width and height */
245 if (width > psInfo->width)
246 psInfo->width = width;
247
248 if (height > psInfo->height)
249 psInfo->height = height;
250
251 /* menu */
252 switch ((WORD)*p)
253 {
254 case 0x0000:
255 p++;
256 break;
257 case 0xffff:
258 p += 2;
259 break;
260 default:
261 p += lstrlenW( (LPCWSTR)p ) + 1;
262 break;
263 }
264
265 /* class */
266 switch ((WORD)*p)
267 {
268 case 0x0000:
269 p++;
270 break;
271 case 0xffff:
272 p += 2;
273 break;
274 default:
275 p += lstrlenW( (LPCWSTR)p ) + 1;
276 break;
277 }
278
279 /* Extract the caption */
280 psInfo->proppage[index].pszText = (LPCWSTR)p;
281// TRACE(propsheet, "Tab %d %s\n",index,debugstr_w((LPCWSTR)p));
282 p += lstrlenW((LPCWSTR)p) + 1;
283
284 /*
285 * Build the image list for icons
286 */
287 if ((dwFlags & PSP_USEHICON) || (dwFlags & PSP_USEICONID))
288 {
289 HICON hIcon;
290 int icon_cx = GetSystemMetrics(SM_CXSMICON);
291 int icon_cy = GetSystemMetrics(SM_CYSMICON);
292
293 if (dwFlags & PSP_USEICONID)
294 hIcon = LoadImageA(lppsp->hInstance, lppsp->u2.pszIcon, IMAGE_ICON,
295 icon_cx, icon_cy, LR_DEFAULTCOLOR);
296 else
297 hIcon = lppsp->u2.hIcon;
298
299 if (psInfo->hImageList == 0)
300 psInfo->hImageList = ImageList_Create(icon_cx, icon_cy, ILC_COLOR, 1, 1);
301
302 ImageList_AddIcon(psInfo->hImageList, hIcon);
303 }
304
305 return TRUE;
306}
307
308/******************************************************************************
309 * PROPSHEET_CreateDialog
310 *
311 * Creates the actual property sheet.
312 */
313BOOL PROPSHEET_CreateDialog(PropSheetInfo* psInfo)
314{
315 LRESULT ret;
316 LPCVOID template;
317 HRSRC hRes;
318
319 if (psInfo->useCallback)
320 (*(psInfo->ppshheader->pfnCallback))(0, PSCB_PRECREATE, (LPARAM)template);
321
322 //load OS/2 dialog
323
324 if (psInfo->ppshheader->dwFlags & PSH_MODELESS)
325 ret = NativeCreateDlgIP(COMCTL32_hModule,
326 psInfo->ppshheader->hInstance,
327 MAKEINTRESOURCEA(IDD_PROPSHEET),
328 psInfo->ppshheader->hwndParent,
329 (DLGPROC)PROPSHEET_DialogProc,
330 (LPARAM)psInfo);
331 else
332 ret = NativeDlgBoxIP(COMCTL32_hModule,
333 psInfo->ppshheader->hInstance,
334 MAKEINTRESOURCEA(IDD_PROPSHEET),
335 psInfo->ppshheader->hwndParent,
336 (DLGPROC)PROPSHEET_DialogProc,
337 (LPARAM)psInfo);
338
339 if (ret == (INT)-1) return FALSE;
340
341/* //CB: original WINE code
342 if (!(hRes = FindResourceA(COMCTL32_hModule,
343 MAKEINTRESOURCEA(IDD_PROPSHEET),
344 RT_DIALOGA)))
345 return FALSE;
346
347 if (!(template = (LPVOID)LoadResource(COMCTL32_hModule, hRes)))
348 return FALSE;
349
350 if (psInfo->useCallback)
351 (*(psInfo->ppshheader->pfnCallback))(0, PSCB_PRECREATE, (LPARAM)template);
352
353 if (psInfo->ppshheader->dwFlags & PSH_MODELESS)
354 ret = CreateDialogIndirectParamA(psInfo->ppshheader->hInstance,
355 (LPDLGTEMPLATEA) template,
356 psInfo->ppshheader->hwndParent,
357 (DLGPROC) PROPSHEET_DialogProc,
358 (LPARAM)psInfo);
359 else
360 ret = DialogBoxIndirectParamA(psInfo->ppshheader->hInstance,
361 (LPDLGTEMPLATEA) template,
362 psInfo->ppshheader->hwndParent,
363 (DLGPROC) PROPSHEET_DialogProc,
364 (LPARAM)psInfo);
365*/
366
367 return ret;
368}
369
370/******************************************************************************
371 * PROPSHEET_IsTooSmall
372 *
373 * Verify that the resource property sheet is big enough.
374 */
375static BOOL PROPSHEET_IsTooSmall(HWND hwndDlg, PropSheetInfo* psInfo)
376{
377 HWND hwndTabCtrl = GetDlgItem(hwndDlg, IDC_TABCONTROL);
378 RECT rcOrigTab, rcPage;
379
380 /*
381 * Original tab size.
382 */
383 GetClientRect(hwndTabCtrl, &rcOrigTab);
384// TRACE(propsheet, "orig tab %d %d %d %d\n", rcOrigTab.left, rcOrigTab.top,
385// rcOrigTab.right, rcOrigTab.bottom);
386
387 /*
388 * Biggest page size.
389 */
390 rcPage.left = psInfo->x;
391 rcPage.top = psInfo->y;
392 rcPage.right = psInfo->width;
393 rcPage.bottom = psInfo->height;
394
395 MapDialogRect(hwndDlg, &rcPage);
396// TRACE(propsheet, "biggest page %d %d %d %d\n", rcPage.left, rcPage.top,
397// rcPage.right, rcPage.bottom);
398
399 if (rcPage.right > rcOrigTab.right)
400 return TRUE;
401
402 if (rcPage.bottom > rcOrigTab.bottom)
403 return TRUE;
404
405 return FALSE;
406}
407
408/******************************************************************************
409 * PROPSHEET_AdjustSize
410 *
411 * Resizes the property sheet and the tab control to fit the largest page.
412 */
413static BOOL PROPSHEET_AdjustSize(HWND hwndDlg, PropSheetInfo* psInfo)
414{
415 HWND hwndTabCtrl = GetDlgItem(hwndDlg, IDC_TABCONTROL);
416 HWND hwndButton = GetDlgItem(hwndDlg, IDOK);
417 RECT rc;
418 int tabOffsetX, tabOffsetY, buttonHeight;
419 PADDING_INFO padding = PROPSHEET_GetPaddingInfo(hwndDlg);
420
421 /* Get the height of buttons */
422 GetClientRect(hwndButton, &rc);
423 buttonHeight = rc.bottom;
424
425 /*
426 * Biggest page size.
427 */
428 rc.left = psInfo->x;
429 rc.top = psInfo->y;
430 rc.right = psInfo->width;
431 rc.bottom = psInfo->height;
432
433 MapDialogRect(hwndDlg, &rc);
434
435 /*
436 * Resize the tab control.
437 */
438 SendMessageA(hwndTabCtrl, TCM_ADJUSTRECT, TRUE, (LPARAM)&rc);
439
440 tabOffsetX = -(rc.left);
441 tabOffsetY = -(rc.top);
442
443 rc.right -= rc.left;
444 rc.bottom -= rc.top;
445 SetWindowPos(hwndTabCtrl, 0, 0, 0, rc.right, rc.bottom,
446 SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE);
447
448 GetClientRect(hwndTabCtrl, &rc);
449
450// TRACE(propsheet, "tab client rc %d %d %d %d\n",
451// rc.left, rc.top, rc.right, rc.bottom);
452
453 rc.right += ((padding.x * 2) + tabOffsetX);
454 rc.bottom += (buttonHeight + (3 * padding.y) + tabOffsetY);
455
456 /*
457 * Resize the property sheet.
458 */
459 SetWindowPos(hwndDlg, 0, 0, 0, rc.right, rc.bottom,
460 SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE);
461
462 return TRUE;
463}
464
465/******************************************************************************
466 * PROPSHEET_AdjustButtons
467 *
468 * Adjusts the buttons' positions.
469 */
470static BOOL PROPSHEET_AdjustButtons(HWND hwndParent, PropSheetInfo* psInfo)
471{
472 HWND hwndButton = GetDlgItem(hwndParent, IDOK);
473 RECT rcSheet;
474 int x, y;
475 int num_buttons = 2;
476 int buttonWidth, buttonHeight;
477 PADDING_INFO padding = PROPSHEET_GetPaddingInfo(hwndParent);
478
479 if (psInfo->hasApply)
480 num_buttons++;
481
482 if (psInfo->hasHelp)
483 num_buttons++;
484
485 /*
486 * Obtain the size of the buttons.
487 */
488 GetClientRect(hwndButton, &rcSheet);
489 buttonWidth = rcSheet.right;
490 buttonHeight = rcSheet.bottom;
491
492 /*
493 * Get the size of the property sheet.
494 */
495 GetClientRect(hwndParent, &rcSheet);
496
497 /*
498 * All buttons will be at this y coordinate.
499 */
500 y = rcSheet.bottom - (padding.y + buttonHeight);
501
502 /*
503 * Position OK button.
504 */
505 hwndButton = GetDlgItem(hwndParent, IDOK);
506
507 x = rcSheet.right - ((padding.x + buttonWidth) * num_buttons);
508
509 SetWindowPos(hwndButton, 0, x, y, 0, 0,
510 SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE);
511
512 /*
513 * Position Cancel button.
514 */
515 hwndButton = GetDlgItem(hwndParent, IDCANCEL);
516
517 x = rcSheet.right - ((padding.x + buttonWidth) * (num_buttons - 1));
518
519 SetWindowPos(hwndButton, 0, x, y, 0, 0,
520 SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE);
521
522 /*
523 * Position Apply button.
524 */
525 hwndButton = GetDlgItem(hwndParent, IDC_APPLY_BUTTON);
526
527 if (psInfo->hasApply)
528 {
529 if (psInfo->hasHelp)
530 x = rcSheet.right - ((padding.x + buttonWidth) * 2);
531 else
532 x = rcSheet.right - (padding.x + buttonWidth);
533
534 SetWindowPos(hwndButton, 0, x, y, 0, 0,
535 SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE);
536
537 EnableWindow(hwndButton, FALSE);
538 }
539 else
540 ShowWindow(hwndButton, SW_HIDE);
541
542 /*
543 * Position Help button.
544 */
545 hwndButton = GetDlgItem(hwndParent, IDHELP);
546
547 if (psInfo->hasHelp)
548 {
549 x = rcSheet.right - (padding.x + buttonWidth);
550
551 SetWindowPos(hwndButton, 0, x, y, 0, 0,
552 SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE);
553 }
554 else
555 ShowWindow(hwndButton, SW_HIDE);
556
557 return TRUE;
558}
559
560/******************************************************************************
561 * PROPSHEET_GetPaddingInfo
562 *
563 * Returns the layout information.
564 */
565static PADDING_INFO PROPSHEET_GetPaddingInfo(HWND hwndDlg)
566{
567 HWND hwndTab = GetDlgItem(hwndDlg, IDC_TABCONTROL);
568 RECT rcTab;
569 POINT tl;
570 PADDING_INFO padding;
571
572 GetWindowRect(hwndTab, &rcTab);
573
574 tl.x = rcTab.left;
575 tl.y = rcTab.top;
576
577 ScreenToClient(hwndDlg, &tl);
578
579 padding.x = tl.x;
580 padding.y = tl.y;
581
582 return padding;
583}
584
585/******************************************************************************
586 * PROPSHEET_CreateTabControl
587 *
588 * Insert the tabs in the tab control.
589 */
590static BOOL PROPSHEET_CreateTabControl(HWND hwndParent,
591 PropSheetInfo * psInfo)
592{
593 HWND hwndTabCtrl = GetDlgItem(hwndParent, IDC_TABCONTROL);
594 TCITEMA item;
595 int i, nTabs;
596 char tabtext[MAX_TABTEXT_LENGTH] = "Tab text";
597
598 item.mask = TCIF_TEXT;
599 item.pszText = tabtext;
600 item.cchTextMax = MAX_TABTEXT_LENGTH;
601
602 nTabs = psInfo->ppshheader->nPages;
603
604 /*
605 * Set the image list for icons.
606 */
607 if (psInfo->hImageList)
608 {
609 item.mask |= TCIF_IMAGE;
610 SendMessageA(hwndTabCtrl, TCM_SETIMAGELIST, 0, (LPARAM)psInfo->hImageList);
611 }
612
613 for (i = 0; i < nTabs; i++)
614 {
615 item.iImage = i;
616
617 WideCharToMultiByte(CP_ACP, 0,
618 (LPCWSTR)psInfo->proppage[i].pszText,
619 -1, tabtext, MAX_TABTEXT_LENGTH, NULL, NULL);
620
621 SendMessageA(hwndTabCtrl, TCM_INSERTITEMA, (WPARAM)i, (LPARAM)&item);
622 }
623
624 return TRUE;
625}
626
627/******************************************************************************
628 * PROPSHEET_CreatePage
629 *
630 * Creates a page.
631 */
632static int PROPSHEET_CreatePage(HWND hwndParent,
633 int index,
634 const PropSheetInfo * psInfo,
635 LPCPROPSHEETPAGEA ppshpage,
636 BOOL showPage)
637{
638 DLGTEMPLATE* pTemplate;
639 HWND hwndPage;
640 RECT rc;
641 PropPageInfo* ppInfo = psInfo->proppage;
642 PADDING_INFO padding = PROPSHEET_GetPaddingInfo(hwndParent);
643 HWND hwndTabCtrl = GetDlgItem(hwndParent, IDC_TABCONTROL);
644
645// TRACE(propsheet, "index %d\n", index);
646
647 if (ppshpage->dwFlags & PSP_DLGINDIRECT)
648 pTemplate = (DLGTEMPLATE*)ppshpage->u1.pResource;
649 else
650 {
651 HRSRC hResource = FindResourceA(ppshpage->hInstance,
652 ppshpage->u1.pszTemplate,
653 RT_DIALOGA);
654 HGLOBAL hTemplate = LoadResource(ppshpage->hInstance, hResource);
655 pTemplate = (LPDLGTEMPLATEA)LockResource(hTemplate);
656 }
657
658 if (((MyDLGTEMPLATEEX*)pTemplate)->signature == 0xFFFF)
659 {
660 ((MyDLGTEMPLATEEX*)pTemplate)->style |= WS_CHILD;
661 ((MyDLGTEMPLATEEX*)pTemplate)->style &= ~DS_MODALFRAME;
662 ((MyDLGTEMPLATEEX*)pTemplate)->style &= ~WS_CAPTION;
663 ((MyDLGTEMPLATEEX*)pTemplate)->style &= ~WS_SYSMENU;
664 ((MyDLGTEMPLATEEX*)pTemplate)->style &= ~WS_POPUP;
665 ((MyDLGTEMPLATEEX*)pTemplate)->style &= ~WS_DISABLED;
666 }
667 else
668 {
669 pTemplate->style |= WS_CHILD;
670 pTemplate->style &= ~DS_MODALFRAME;
671 pTemplate->style &= ~WS_CAPTION;
672 pTemplate->style &= ~WS_SYSMENU;
673 pTemplate->style &= ~WS_POPUP;
674 pTemplate->style &= ~WS_DISABLED;
675
676 }
677
678 if (psInfo->proppage[index].useCallback)
679 (*(ppshpage->pfnCallback))(hwndParent,
680 PSPCB_CREATE,
681 (LPPROPSHEETPAGEA)ppshpage);
682
683 hwndPage = CreateDialogIndirectParamA(ppshpage->hInstance,
684 pTemplate,
685 hwndParent,
686 ppshpage->pfnDlgProc,
687 (LPARAM)ppshpage);
688
689 ppInfo[index].hwndPage = hwndPage;
690
691 rc.left = psInfo->x;
692 rc.top = psInfo->y;
693 rc.right = psInfo->width;
694 rc.bottom = psInfo->height;
695
696 MapDialogRect(hwndParent, &rc);
697
698 /*
699 * Ask the Tab control to fit this page in.
700 */
701 SendMessageA(hwndTabCtrl, TCM_ADJUSTRECT, FALSE, (LPARAM)&rc);
702
703 SetWindowPos(hwndPage, HWND_TOP,
704 rc.left + padding.x,
705 rc.top + padding.y,
706 0, 0, SWP_NOSIZE);
707
708 if (showPage)
709 {
710 NMHDR hdr;
711
712 hdr.hwndFrom = hwndParent;
713 hdr.code = PSN_SETACTIVE;
714
715 /*
716 * Send the notification before showing the page.
717 */
718 SendMessageA(hwndPage, WM_NOTIFY, 0, (LPARAM) &hdr);
719
720 ShowWindow(hwndPage, SW_SHOW);
721 }
722 else
723 ShowWindow(hwndPage, SW_HIDE);
724
725 return TRUE;
726}
727
728/******************************************************************************
729 * PROPSHEET_ShowPage
730 *
731 * Displays or creates the specified page.
732 */
733static BOOL PROPSHEET_ShowPage(HWND hwndDlg, int index, PropSheetInfo * psInfo)
734{
735 if (index == psInfo->active_page)
736 return TRUE;
737
738 ShowWindow(psInfo->proppage[psInfo->active_page].hwndPage, SW_HIDE);
739
740 if (psInfo->proppage[index].hwndPage != 0)
741 ShowWindow(psInfo->proppage[index].hwndPage, SW_SHOW);
742 else
743 {
744 LPCPROPSHEETPAGEA ppshpage = PROPSHEET_GetPSPPage(psInfo, index);
745 PROPSHEET_CreatePage(hwndDlg, index, psInfo, ppshpage, TRUE);
746 }
747
748 psInfo->active_page = index;
749
750 return TRUE;
751}
752
753/******************************************************************************
754 * PROPSHEET_Apply
755 */
756static BOOL PROPSHEET_Apply(HWND hwndDlg)
757{
758 int i;
759 NMHDR hdr;
760 HWND hwndPage;
761 LRESULT msgResult;
762 PropSheetInfo* psInfo = (PropSheetInfo*) GetPropA(hwndDlg,
763 PropSheetInfoStr);
764
765 hdr.hwndFrom = hwndDlg;
766
767 /*
768 * Send PSN_KILLACTIVE to the current page.
769 */
770 hdr.code = PSN_KILLACTIVE;
771
772 hwndPage = psInfo->proppage[psInfo->active_page].hwndPage;
773
774 if (SendMessageA(hwndPage, WM_NOTIFY, 0, (LPARAM) &hdr) != FALSE)
775 return FALSE;
776
777 /*
778 * Send PSN_APPLY to all pages.
779 */
780 hdr.code = PSN_APPLY;
781
782 for (i = 0; i < psInfo->nPages; i++)
783 {
784 hwndPage = psInfo->proppage[i].hwndPage;
785 msgResult = SendMessageA(hwndPage, WM_NOTIFY, 0, (LPARAM) &hdr);
786
787 if (msgResult == PSNRET_INVALID_NOCHANGEPAGE)
788 return FALSE;
789 }
790
791 return TRUE;
792}
793
794/******************************************************************************
795 * PROPSHEET_Cancel
796 */
797static void PROPSHEET_Cancel(HWND hwndDlg)
798{
799 PropSheetInfo* psInfo = (PropSheetInfo*) GetPropA(hwndDlg,
800 PropSheetInfoStr);
801 HWND hwndPage = psInfo->proppage[psInfo->active_page].hwndPage;
802 NMHDR hdr;
803
804 hdr.hwndFrom = hwndDlg;
805 hdr.code = PSN_QUERYCANCEL;
806
807 if (SendMessageA(hwndPage, WM_NOTIFY, 0, (LPARAM) &hdr))
808 return;
809
810 hdr.code = PSN_RESET;
811
812 SendMessageA(hwndPage, WM_NOTIFY, 0, (LPARAM) &hdr);
813
814 if (psInfo->isModeless)
815 psInfo->active_page = -1; /* makes PSM_GETCURRENTPAGEHWND return NULL */
816 else
817 EndDialog(hwndDlg, FALSE);
818}
819
820/******************************************************************************
821 * PROPSHEET_Help
822 */
823static void PROPSHEET_Help(HWND hwndDlg)
824{
825 PropSheetInfo* psInfo = (PropSheetInfo*) GetPropA(hwndDlg,
826 PropSheetInfoStr);
827 HWND hwndPage = psInfo->proppage[psInfo->active_page].hwndPage;
828 NMHDR hdr;
829
830 hdr.hwndFrom = hwndDlg;
831 hdr.code = PSN_HELP;
832
833 SendMessageA(hwndPage, WM_NOTIFY, 0, (LPARAM) &hdr);
834}
835
836/******************************************************************************
837 * PROPSHEET_Changed
838 */
839static void PROPSHEET_Changed(HWND hwndDlg, HWND hwndDirtyPage)
840{
841 int i;
842 PropSheetInfo* psInfo = (PropSheetInfo*) GetPropA(hwndDlg,
843 PropSheetInfoStr);
844 if (!psInfo) return;
845 /*
846 * Set the dirty flag of this page.
847 */
848 for (i = 0; i < psInfo->nPages; i++)
849 {
850 if (psInfo->proppage[i].hwndPage == hwndDirtyPage)
851 psInfo->proppage[i].isDirty = TRUE;
852 }
853
854 /*
855 * Enable the Apply button.
856 */
857 if (psInfo->hasApply)
858 {
859 HWND hwndApplyBtn = GetDlgItem(hwndDlg, IDC_APPLY_BUTTON);
860
861 EnableWindow(hwndApplyBtn, TRUE);
862 }
863}
864
865/******************************************************************************
866 * PROPSHEET_UnChanged
867 */
868static void PROPSHEET_UnChanged(HWND hwndDlg, HWND hwndCleanPage)
869{
870 int i;
871 BOOL noPageDirty = TRUE;
872 HWND hwndApplyBtn = GetDlgItem(hwndDlg, IDC_APPLY_BUTTON);
873 PropSheetInfo* psInfo = (PropSheetInfo*) GetPropA(hwndDlg,
874 PropSheetInfoStr);
875
876 for (i = 0; i < psInfo->nPages; i++)
877 {
878 /* set the specified page as clean */
879 if (psInfo->proppage[i].hwndPage == hwndCleanPage)
880 psInfo->proppage[i].isDirty = FALSE;
881
882 /* look to see if there's any dirty pages */
883 if (psInfo->proppage[i].isDirty)
884 noPageDirty = FALSE;
885 }
886
887 /*
888 * Disable Apply button.
889 */
890 if (noPageDirty)
891 EnableWindow(hwndApplyBtn, FALSE);
892}
893
894/******************************************************************************
895 * PROPSHEET_PressButton
896 */
897static void PROPSHEET_PressButton(HWND hwndDlg, int buttonID)
898{
899 switch (buttonID)
900 {
901 case PSBTN_APPLYNOW:
902 SendMessageA(hwndDlg, WM_COMMAND, IDC_APPLY_BUTTON, 0);
903 break;
904 case PSBTN_BACK:
905// FIXME(propsheet, "Wizard mode not implemented.\n");
906 break;
907 case PSBTN_CANCEL:
908 SendMessageA(hwndDlg, WM_COMMAND, IDCANCEL, 0);
909 break;
910 case PSBTN_FINISH:
911// FIXME(propsheet, "Wizard mode not implemented.\n");
912 break;
913 case PSBTN_HELP:
914 SendMessageA(hwndDlg, WM_COMMAND, IDHELP, 0);
915 break;
916 case PSBTN_NEXT:
917// FIXME(propsheet, "Wizard mode not implemented.\n");
918 break;
919 case PSBTN_OK:
920 SendMessageA(hwndDlg, WM_COMMAND, IDOK, 0);
921 break;
922 default:
923// FIXME(propsheet, "Invalid button index %d\n", buttonID);
924 break;
925 }
926}
927
928/******************************************************************************
929 * PROPSHEET_SetCurSel
930 */
931static BOOL PROPSHEET_SetCurSel(HWND hwndDlg,
932 int index,
933 HPROPSHEETPAGE hpage)
934{
935 PropSheetInfo* psInfo = (PropSheetInfo*) GetPropA(hwndDlg,
936 PropSheetInfoStr);
937 HWND hwndPage;
938 HWND hwndHelp = GetDlgItem(hwndDlg, IDHELP);
939 NMHDR hdr;
940
941 /*
942 * Notify the current page.
943 */
944 hwndPage = psInfo->proppage[psInfo->active_page].hwndPage;
945
946 hdr.hwndFrom = hwndDlg;
947 hdr.code = PSN_KILLACTIVE;
948
949 if (SendMessageA(hwndPage, WM_NOTIFY, 0, (LPARAM) &hdr))
950 return FALSE;
951
952 /*
953 * hpage takes precedence over index.
954 */
955 if (hpage != NULL)
956 {
957 index = PROPSHEET_GetPageIndex(hpage, psInfo);
958
959 if (index == -1)
960 {
961 //TRACE("Could not find page to remove!\n");
962 return FALSE;
963 }
964 }
965
966 hwndPage = psInfo->proppage[index].hwndPage;
967
968 /*
969 * Notify the new page if it's already created.
970 * If not it will get created and notified in PROPSHEET_ShowPage.
971 */
972 if (hwndPage)
973 {
974 int result;
975 hdr.code = PSN_SETACTIVE;
976
977 result = SendMessageA(hwndPage, WM_NOTIFY, 0, (LPARAM) &hdr);
978 /*
979 * TODO: check return value.
980 */
981 }
982
983 /*
984 * Display the new page.
985 */
986 PROPSHEET_ShowPage(hwndDlg, index, psInfo);
987
988 if (psInfo->proppage[index].hasHelp)
989 EnableWindow(hwndHelp, TRUE);
990 else
991 EnableWindow(hwndHelp, FALSE);
992
993 return TRUE;
994}
995
996/******************************************************************************
997 * PROPSHEET_SetTitleA
998 */
999static void PROPSHEET_SetTitleA(HWND hwndDlg, DWORD dwStyle, LPCSTR lpszText)
1000{
1001 if (dwStyle & PSH_PROPTITLE)
1002 {
1003 PropSheetInfo* psInfo = (PropSheetInfo*) GetPropA(hwndDlg,
1004 PropSheetInfoStr);
1005 char* dest;
1006 int lentitle = strlen(lpszText);
1007 int lenprop = strlen(psInfo->strPropertiesFor);
1008
1009 dest = COMCTL32_Alloc(lentitle + lenprop + 1);
1010 strcpy(dest, psInfo->strPropertiesFor);
1011 strcat(dest, lpszText);
1012
1013 SetWindowTextA(hwndDlg, dest);
1014 COMCTL32_Free(dest);
1015 }
1016 else
1017 SetWindowTextA(hwndDlg, lpszText);
1018}
1019
1020/******************************************************************************
1021 * PROPSHEET_QuerySiblings
1022 */
1023static LRESULT PROPSHEET_QuerySiblings(HWND hwndDlg,
1024 WPARAM wParam, LPARAM lParam)
1025{
1026 int i = 0;
1027 HWND hwndPage;
1028 LRESULT msgResult = 0;
1029 PropSheetInfo* psInfo = (PropSheetInfo*) GetPropA(hwndDlg,
1030 PropSheetInfoStr);
1031
1032 while ((i < psInfo->nPages) && (msgResult == 0))
1033 {
1034 hwndPage = psInfo->proppage[i].hwndPage;
1035 msgResult = SendMessageA(hwndPage, PSM_QUERYSIBLINGS, wParam, lParam);
1036 i++;
1037 }
1038
1039 return msgResult;
1040}
1041
1042/******************************************************************************
1043 * PROPSHEET_GetPSPPage
1044 */
1045static LPCPROPSHEETPAGEA PROPSHEET_GetPSPPage(const PropSheetInfo * psInfo,
1046 int index)
1047{
1048 BOOL usePSP = psInfo->ppshheader->dwFlags & PSH_PROPSHEETPAGE;
1049 LPCPROPSHEETPAGEA lppsp;
1050 int realIndex = psInfo->proppage[index].index;
1051
1052 if (usePSP)
1053 {
1054 BYTE* pByte;
1055
1056 lppsp = psInfo->ppshheader->u3.ppsp;
1057
1058 pByte = (BYTE*) lppsp;
1059
1060 pByte += (lppsp->dwSize * realIndex);
1061 lppsp = (LPCPROPSHEETPAGEA)pByte;
1062 }
1063 else
1064 lppsp = (LPCPROPSHEETPAGEA) psInfo->ppshheader->u3.phpage[realIndex];
1065
1066 return lppsp;
1067}
1068
1069/******************************************************************************
1070 * PROPSHEET_AddPage
1071 */
1072static BOOL PROPSHEET_AddPage(HWND hwndDlg,
1073 HPROPSHEETPAGE hpage)
1074{
1075 PropSheetInfo * psInfo = (PropSheetInfo*) GetPropA(hwndDlg,
1076 PropSheetInfoStr);
1077 HWND hwndTabControl = GetDlgItem(hwndDlg, IDC_TABCONTROL);
1078 TCITEMA item;
1079 char tabtext[MAX_TABTEXT_LENGTH] = "Tab text";
1080 LPCPROPSHEETPAGEA ppsp = (LPCPROPSHEETPAGEA)hpage;
1081
1082 /*
1083 * Allocate and fill in a new PropPageInfo entry.
1084 */
1085 psInfo->proppage = (PropPageInfo*) COMCTL32_ReAlloc(psInfo->proppage,
1086 sizeof(PropPageInfo) *
1087 (psInfo->nPages + 1));
1088
1089 PROPSHEET_CollectPageInfo(ppsp, psInfo, psInfo->nPages);
1090 psInfo->proppage[psInfo->nPages].index = -1;
1091 psInfo->proppage[psInfo->nPages].hpage = hpage;
1092
1093 /*
1094 * Create the page but don't show it.
1095 */
1096 PROPSHEET_CreatePage(hwndDlg, psInfo->nPages, psInfo, ppsp, FALSE);
1097
1098 /*
1099 * Add a new tab to the tab control.
1100 */
1101 item.mask = TCIF_TEXT;
1102 item.pszText = tabtext;
1103 item.cchTextMax = MAX_TABTEXT_LENGTH;
1104
1105 WideCharToMultiByte(CP_ACP, 0,
1106 (LPCWSTR)psInfo->proppage[psInfo->nPages].pszText,
1107 -1, tabtext, MAX_TABTEXT_LENGTH, NULL, NULL);
1108
1109 SendMessageA(hwndTabControl, TCM_INSERTITEMA, psInfo->nPages + 1,
1110 (LPARAM)&item);
1111
1112 psInfo->nPages++;
1113
1114 return FALSE;
1115}
1116
1117/******************************************************************************
1118 * PROPSHEET_RemovePage
1119 */
1120static BOOL PROPSHEET_RemovePage(HWND hwndDlg,
1121 int index,
1122 HPROPSHEETPAGE hpage)
1123{
1124 PropSheetInfo * psInfo = (PropSheetInfo*) GetPropA(hwndDlg,
1125 PropSheetInfoStr);
1126 HWND hwndTabControl = GetDlgItem(hwndDlg, IDC_TABCONTROL);
1127 PropPageInfo* oldPages = psInfo->proppage;
1128
1129 /*
1130 * hpage takes precedence over index.
1131 */
1132 if (hpage != 0)
1133 {
1134 index = PROPSHEET_GetPageIndex(hpage, psInfo);
1135
1136 if (index == -1)
1137 {
1138// TRACE(propsheet, "Could not find page to remove!\n");
1139 return FALSE;
1140 }
1141 }
1142
1143// TRACE(propsheet, "total pages %d removing page %d active page %d\n",
1144// psInfo->nPages, index, psInfo->active_page);
1145 /*
1146 * Check if we're removing the active page.
1147 */
1148 if (index == psInfo->active_page)
1149 {
1150 if (psInfo->nPages > 1)
1151 {
1152 if (index > 0)
1153 {
1154 /* activate previous page */
1155 PROPSHEET_ShowPage(hwndDlg, index - 1, psInfo);
1156 }
1157 else
1158 {
1159 /* activate the next page */
1160 PROPSHEET_ShowPage(hwndDlg, index + 1, psInfo);
1161 }
1162 }
1163 else
1164 {
1165// TRACE(propsheet, "Removing the only page, close the dialog!\n");
1166
1167 if (psInfo->isModeless)
1168 psInfo->active_page = -1;
1169 else
1170 EndDialog(hwndDlg, FALSE);
1171
1172 return TRUE;
1173 }
1174 }
1175
1176 if (index < psInfo->active_page)
1177 psInfo->active_page--;
1178
1179 /* Remove the tab */
1180 SendMessageA(hwndTabControl, TCM_DELETEITEM, index, 0);
1181
1182 psInfo->nPages--;
1183 psInfo->proppage = COMCTL32_Alloc(sizeof(PropPageInfo) * psInfo->nPages);
1184
1185 if (index > 0)
1186 memcpy(&psInfo->proppage[0], &oldPages[0], index * sizeof(PropPageInfo));
1187
1188 if (index < psInfo->nPages)
1189 memcpy(&psInfo->proppage[index], &oldPages[index + 1],
1190 (psInfo->nPages - index) * sizeof(PropPageInfo));
1191
1192 COMCTL32_Free(oldPages);
1193
1194 return FALSE;
1195}
1196
1197/******************************************************************************
1198 * PROPSHEET_GetPageIndex
1199 *
1200 * Given a HPROPSHEETPAGE, returns the index of the corresponding page from
1201 * the array of PropPageInfo.
1202 */
1203static int PROPSHEET_GetPageIndex(HPROPSHEETPAGE hpage, PropSheetInfo* psInfo)
1204{
1205 BOOL found = FALSE;
1206 int index = 0;
1207
1208 while ((index < psInfo->nPages) && (found == FALSE))
1209 {
1210 if (psInfo->proppage[index].hpage == hpage)
1211 found = TRUE;
1212 else
1213 index++;
1214 }
1215
1216 if (found == FALSE)
1217 index = -1;
1218
1219 return index;
1220}
1221
1222/******************************************************************************
1223 * PROPSHEET_CleanUp
1224 */
1225static void PROPSHEET_CleanUp(HWND hwndDlg)
1226{
1227 PropSheetInfo* psInfo = (PropSheetInfo*) RemovePropA(hwndDlg,
1228 PropSheetInfoStr);
1229 COMCTL32_Free(psInfo->proppage);
1230 COMCTL32_Free(psInfo->strPropertiesFor);
1231 ImageList_Destroy(psInfo->hImageList);
1232
1233 GlobalFree((HGLOBAL)psInfo);
1234}
1235
1236/******************************************************************************
1237 * PropertySheetA (COMCTL32.84)(COMCTL32.83)
1238 */
1239INT WINAPI PropertySheetA(LPCPROPSHEETHEADERA lppsh)
1240{
1241 int bRet = 0;
1242 PropSheetInfo* psInfo = (PropSheetInfo*) GlobalAlloc(GPTR,
1243 sizeof(PropSheetInfo));
1244 LPCPROPSHEETPAGEA lppsp;
1245 int i;
1246
1247 PROPSHEET_CollectSheetInfo(lppsh, psInfo);
1248
1249 psInfo->proppage = (PropPageInfo*) COMCTL32_Alloc(sizeof(PropPageInfo) *
1250 lppsh->nPages);
1251
1252 for (i = 0; i < lppsh->nPages; i++)
1253 {
1254 psInfo->proppage[i].index = i;
1255 if (!(lppsh->dwFlags & PSH_PROPSHEETPAGE))
1256 psInfo->proppage[i].hpage = psInfo->ppshheader->u3.phpage[i];
1257 lppsp = PROPSHEET_GetPSPPage(psInfo, i);
1258 PROPSHEET_CollectPageInfo(lppsp, psInfo, i);
1259 }
1260
1261 bRet = PROPSHEET_CreateDialog(psInfo);
1262
1263 return bRet;
1264}
1265
1266/******************************************************************************
1267 * PropertySheet32W (COMCTL32.85)
1268 */
1269INT WINAPI PropertySheetW(LPCPROPSHEETHEADERW propertySheetHeader)
1270{
1271// FIXME(propsheet, "(%p): stub\n", propertySheetHeader);
1272
1273 return -1;
1274}
1275
1276/******************************************************************************
1277 * CreatePropertySheetPageA (COMCTL32.19)(COMCTL32.18)
1278 */
1279HPROPSHEETPAGE WINAPI CreatePropertySheetPageA(
1280 LPCPROPSHEETPAGEA lpPropSheetPage)
1281{
1282 PROPSHEETPAGEA* ppsp = COMCTL32_Alloc(sizeof(PROPSHEETPAGEA));
1283
1284 *ppsp = *lpPropSheetPage;
1285
1286 return (HPROPSHEETPAGE)ppsp;
1287}
1288
1289/******************************************************************************
1290 * CreatePropertySheetPageW (COMCTL32.20)
1291 */
1292HPROPSHEETPAGE WINAPI CreatePropertySheetPageW(LPCPROPSHEETPAGEW lpPropSheetPage)
1293{
1294// FIXME(propsheet, "(%p): stub\n", lpPropSheetPage);
1295
1296 return 0;
1297}
1298
1299/******************************************************************************
1300 * DestroyPropertySheetPage (COMCTL32.24)
1301 */
1302BOOL WINAPI DestroyPropertySheetPage(HPROPSHEETPAGE hPropPage)
1303{
1304 COMCTL32_Free(hPropPage);
1305
1306 return TRUE;
1307}
1308
1309/******************************************************************************
1310 * PROPSHEET_DialogProc
1311 */
1312BOOL WINAPI
1313PROPSHEET_DialogProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
1314{
1315 switch (uMsg)
1316 {
1317 case WM_INITDIALOG:
1318 {
1319 PropSheetInfo* psInfo = (PropSheetInfo*) lParam;
1320 char* strCaption = (char*)COMCTL32_Alloc(MAX_CAPTION_LENGTH);
1321 HWND hwndTabCtrl = GetDlgItem(hwnd, IDC_TABCONTROL);
1322 LPCPROPSHEETPAGEA ppshpage;
1323
1324 psInfo->strPropertiesFor = strCaption;
1325
1326 GetWindowTextA(hwnd, psInfo->strPropertiesFor, MAX_CAPTION_LENGTH);
1327
1328 PROPSHEET_CreateTabControl(hwnd, psInfo);
1329
1330 if (PROPSHEET_IsTooSmall(hwnd, psInfo))
1331 {
1332 PROPSHEET_AdjustSize(hwnd, psInfo);
1333 PROPSHEET_AdjustButtons(hwnd, psInfo);
1334 }
1335
1336 ppshpage = PROPSHEET_GetPSPPage(psInfo, psInfo->active_page);
1337 PROPSHEET_CreatePage(hwnd, psInfo->active_page, psInfo, ppshpage, TRUE);
1338 SendMessageA(hwndTabCtrl, TCM_SETCURSEL, psInfo->active_page, 0);
1339
1340 SetPropA(hwnd, PropSheetInfoStr, (HANDLE)psInfo);
1341
1342 PROPSHEET_SetTitleA(hwnd,
1343 psInfo->ppshheader->dwFlags,
1344 psInfo->ppshheader->pszCaption);
1345
1346 return TRUE;
1347 }
1348
1349 case WM_DESTROY:
1350 PROPSHEET_CleanUp(hwnd);
1351 return TRUE;
1352
1353 case WM_CLOSE:
1354 PROPSHEET_Cancel(hwnd);
1355 return TRUE;
1356
1357 case WM_COMMAND:
1358 {
1359 WORD wID = LOWORD(wParam);
1360
1361 switch (wID)
1362 {
1363 case IDOK:
1364 case IDC_APPLY_BUTTON:
1365 {
1366 HWND hwndApplyBtn = GetDlgItem(hwnd, IDC_APPLY_BUTTON);
1367
1368 if (PROPSHEET_Apply(hwnd) == FALSE)
1369 break;
1370
1371 EnableWindow(hwndApplyBtn, FALSE);
1372
1373 if (wID == IDOK)
1374 {
1375 PropSheetInfo* psInfo = (PropSheetInfo*) GetPropA(hwnd,
1376 PropSheetInfoStr);
1377 int result = TRUE;
1378
1379 if (psInfo->restartWindows)
1380 result = ID_PSRESTARTWINDOWS;
1381
1382 /* reboot system takes precedence over restart windows */
1383 if (psInfo->rebootSystem)
1384 result = ID_PSREBOOTSYSTEM;
1385
1386 if (psInfo->isModeless)
1387 psInfo->active_page = -1;
1388 else
1389 EndDialog(hwnd, result);
1390 }
1391
1392 break;
1393 }
1394
1395 case IDCANCEL:
1396 PROPSHEET_Cancel(hwnd);
1397 break;
1398
1399 case IDHELP:
1400 PROPSHEET_Help(hwnd);
1401 break;
1402 }
1403
1404 return TRUE;
1405 }
1406
1407 case WM_NOTIFY:
1408 {
1409 NMHDR* pnmh = (LPNMHDR) lParam;
1410
1411 if (pnmh->code == TCN_SELCHANGE)
1412 {
1413 int index = SendMessageA(pnmh->hwndFrom, TCM_GETCURSEL, 0, 0);
1414 PROPSHEET_SetCurSel(hwnd, index, 0);
1415 }
1416
1417 return 0;
1418 }
1419
1420 case PSM_GETCURRENTPAGEHWND:
1421 {
1422 PropSheetInfo* psInfo = (PropSheetInfo*) GetPropA(hwnd,
1423 PropSheetInfoStr);
1424 HWND hwndPage = 0;
1425
1426 if (psInfo->active_page != -1)
1427 hwndPage = psInfo->proppage[psInfo->active_page].hwndPage;
1428
1429 SetWindowLongA(hwnd, DWL_MSGRESULT, hwndPage);
1430
1431 return TRUE;
1432 }
1433
1434 case PSM_CHANGED:
1435 PROPSHEET_Changed(hwnd, (HWND)wParam);
1436 return TRUE;
1437
1438 case PSM_UNCHANGED:
1439 PROPSHEET_UnChanged(hwnd, (HWND)wParam);
1440 return TRUE;
1441
1442 case PSM_GETTABCONTROL:
1443 {
1444 HWND hwndTabCtrl = GetDlgItem(hwnd, IDC_TABCONTROL);
1445
1446 SetWindowLongA(hwnd, DWL_MSGRESULT, hwndTabCtrl);
1447
1448 return TRUE;
1449 }
1450
1451 case PSM_SETCURSEL:
1452 {
1453 BOOL msgResult;
1454
1455 msgResult = PROPSHEET_SetCurSel(hwnd,
1456 (int)wParam,
1457 (HPROPSHEETPAGE)lParam);
1458
1459 SetWindowLongA(hwnd, DWL_MSGRESULT, msgResult);
1460
1461 return TRUE;
1462 }
1463
1464 case PSM_CANCELTOCLOSE:
1465 {
1466 HWND hwndOK = GetDlgItem(hwnd, IDOK);
1467 HWND hwndCancel = GetDlgItem(hwnd, IDCANCEL);
1468
1469 EnableWindow(hwndCancel, FALSE);
1470 SetWindowTextA(hwndOK, "Close"); /* FIXME: hardcoded string */
1471
1472 return TRUE;
1473 }
1474
1475 case PSM_RESTARTWINDOWS:
1476 {
1477 PropSheetInfo* psInfo = (PropSheetInfo*) GetPropA(hwnd,
1478 PropSheetInfoStr);
1479
1480 psInfo->restartWindows = TRUE;
1481 return TRUE;
1482 }
1483
1484 case PSM_REBOOTSYSTEM:
1485 {
1486 PropSheetInfo* psInfo = (PropSheetInfo*) GetPropA(hwnd,
1487 PropSheetInfoStr);
1488
1489 psInfo->rebootSystem = TRUE;
1490 return TRUE;
1491 }
1492
1493 case PSM_SETTITLEA:
1494 PROPSHEET_SetTitleA(hwnd, (DWORD) wParam, (LPCSTR) lParam);
1495 return TRUE;
1496
1497 case PSM_APPLY:
1498 {
1499 BOOL msgResult = PROPSHEET_Apply(hwnd);
1500
1501 SetWindowLongA(hwnd, DWL_MSGRESULT, msgResult);
1502
1503 return TRUE;
1504 }
1505
1506 case PSM_QUERYSIBLINGS:
1507 {
1508 LRESULT msgResult = PROPSHEET_QuerySiblings(hwnd, wParam, lParam);
1509
1510 SetWindowLongA(hwnd, DWL_MSGRESULT, msgResult);
1511
1512 return TRUE;
1513 }
1514
1515 case PSM_ADDPAGE:
1516 PROPSHEET_AddPage(hwnd, (HPROPSHEETPAGE)lParam);
1517 return TRUE;
1518
1519 case PSM_REMOVEPAGE:
1520 PROPSHEET_RemovePage(hwnd, (int)wParam, (HPROPSHEETPAGE)lParam);
1521 return TRUE;
1522
1523 case PSM_ISDIALOGMESSAGE:
1524 {
1525// FIXME (propsheet, "Unimplemented msg PSM_ISDIALOGMESSAGE\n");
1526 return 0;
1527 }
1528
1529 case PSM_PRESSBUTTON:
1530 PROPSHEET_PressButton(hwnd, (int)wParam);
1531 return TRUE;
1532
1533 case PSM_SETTITLEW:
1534// FIXME (propsheet, "Unimplemented msg PSM_SETTITLE32W\n");
1535 return 0;
1536 case PSM_SETWIZBUTTONS:
1537// FIXME (propsheet, "Unimplemented msg PSM_SETWIZBUTTONS\n");
1538 return 0;
1539 case PSM_SETCURSELID:
1540// FIXME (propsheet, "Unimplemented msg PSM_SETCURSELID\n");
1541 return 0;
1542 case PSM_SETFINISHTEXTA:
1543// FIXME (propsheet, "Unimplemented msg PSM_SETFINISHTEXT32A\n");
1544 return 0;
1545 case PSM_SETFINISHTEXTW:
1546// FIXME (propsheet, "Unimplemented msg PSM_SETFINISHTEXT32W\n");
1547 return 0;
1548
1549 default:
1550 return FALSE;
1551 }
1552}
1553
Note: See TracBrowser for help on using the repository browser.