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

Last change on this file since 521 was 496, checked in by cbratschi, 26 years ago

wine-990731 update

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