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

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

source code cleanup, remove warnings

File size: 54.9 KB
Line 
1/* $Id: propsheet.c,v 1.12 1999-11-05 13:01:33 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 * - Tab order
12 * - Unicode property sheets
13 */
14
15/* WINE 991031 level */
16
17/* CB: Odin problems:
18 - trap in PROPSHEET_DialogProc (tab control creation)
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 HIMAGELIST hImageList;
70} PropSheetInfo;
71
72typedef struct
73{
74 int x;
75 int y;
76} PADDING_INFO;
77
78/******************************************************************************
79 * Defines and global variables
80 */
81
82const char * PropSheetInfoStr = "PropertySheetInfo";
83
84#define MAX_CAPTION_LENGTH 255
85#define MAX_TABTEXT_LENGTH 255
86
87
88/******************************************************************************
89 * Prototypes
90 */
91static BOOL PROPSHEET_CreateDialog(PropSheetInfo* psInfo);
92static BOOL PROPSHEET_IsTooSmall(HWND hwndDlg, PropSheetInfo* psInfo);
93static BOOL PROPSHEET_AdjustSize(HWND hwndDlg, PropSheetInfo* psInfo);
94static BOOL PROPSHEET_AdjustButtons(HWND hwndParent, PropSheetInfo* psInfo);
95static BOOL PROPSHEET_CollectSheetInfo(LPCPROPSHEETHEADERA lppsh,
96 PropSheetInfo * psInfo);
97static BOOL PROPSHEET_CollectPageInfo(LPCPROPSHEETPAGEA lppsp,
98 PropSheetInfo * psInfo,
99 int index);
100static BOOL PROPSHEET_CreateTabControl(HWND hwndParent,
101 PropSheetInfo * psInfo);
102static int PROPSHEET_CreatePage(HWND hwndParent, int index,
103 const PropSheetInfo * psInfo,
104 LPCPROPSHEETPAGEA ppshpage,
105 BOOL showPage);
106static BOOL PROPSHEET_ShowPage(HWND hwndDlg, int index, PropSheetInfo * psInfo);
107static PADDING_INFO PROPSHEET_GetPaddingInfo(HWND hwndDlg);
108static BOOL PROPSHEET_Back(HWND hwndDlg);
109static BOOL PROPSHEET_Next(HWND hwndDlg);
110static BOOL PROPSHEET_Finish(HWND hwndDlg);
111static BOOL PROPSHEET_Apply(HWND hwndDlg);
112static void PROPSHEET_Cancel(HWND hwndDlg);
113static void PROPSHEET_Help(HWND hwndDlg);
114static void PROPSHEET_Changed(HWND hwndDlg, HWND hwndDirtyPage);
115static void PROPSHEET_UnChanged(HWND hwndDlg, HWND hwndCleanPage);
116static void PROPSHEET_PressButton(HWND hwndDlg, int buttonID);
117static void PROPSHEET_SetFinishTextA(HWND hwndDlg, LPCSTR lpszText);
118static void PROPSHEET_SetTitleA(HWND hwndDlg, DWORD dwStyle, LPCSTR lpszText);
119static BOOL PROPSHEET_CanSetCurSel(HWND hwndDlg);
120static BOOL PROPSHEET_SetCurSel(HWND hwndDlg,
121 int index,
122 HPROPSHEETPAGE hpage);
123static LRESULT PROPSHEET_QuerySiblings(HWND hwndDlg,
124 WPARAM wParam, LPARAM lParam);
125static LPCPROPSHEETPAGEA PROPSHEET_GetPSPPage(const PropSheetInfo * psInfo,
126 int index);
127static BOOL PROPSHEET_AddPage(HWND hwndDlg,
128 HPROPSHEETPAGE hpage);
129
130static BOOL PROPSHEET_RemovePage(HWND hwndDlg,
131 int index,
132 HPROPSHEETPAGE hpage);
133static void PROPSHEET_CleanUp();
134static int PROPSHEET_GetPageIndex(HPROPSHEETPAGE hpage, PropSheetInfo* psInfo);
135static void PROPSHEET_SetWizButtons(HWND hwndDlg, DWORD dwFlags);
136static PADDING_INFO PROPSHEET_GetPaddingInfoWizard(HWND hwndDlg);
137
138BOOL WINAPI
139PROPSHEET_DialogProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
140
141
142/******************************************************************************
143 * PROPSHEET_CollectSheetInfo
144 *
145 * Collect relevant data.
146 */
147static BOOL PROPSHEET_CollectSheetInfo(LPCPROPSHEETHEADERA lppsh,
148 PropSheetInfo * psInfo)
149{
150 DWORD dwFlags = lppsh->dwFlags;
151
152 psInfo->hasHelp = dwFlags & PSH_HASHELP;
153 psInfo->hasApply = !(dwFlags & PSH_NOAPPLYNOW);
154 psInfo->useCallback = dwFlags & PSH_USECALLBACK;
155 psInfo->isModeless = dwFlags & PSH_MODELESS;
156 psInfo->ppshheader = lppsh;
157 psInfo->nPages = lppsh->nPages;
158
159 if (dwFlags & PSH_USEPSTARTPAGE)
160 {
161// TRACE(propsheet, "PSH_USEPSTARTPAGE is on");
162 psInfo->active_page = 0;
163 }
164 else
165 psInfo->active_page = lppsh->u2.nStartPage;
166
167 psInfo->restartWindows = FALSE;
168 psInfo->rebootSystem = FALSE;
169 psInfo->hImageList = 0;
170
171 return TRUE;
172}
173
174/******************************************************************************
175 * PROPSHEET_CollectPageInfo
176 *
177 * Collect property sheet data.
178 * With code taken from DIALOG_ParseTemplate32.
179 */
180BOOL PROPSHEET_CollectPageInfo(LPCPROPSHEETPAGEA lppsp,
181 PropSheetInfo * psInfo,
182 int index)
183{
184 DLGTEMPLATE* pTemplate;
185 const WORD* p;
186 DWORD dwFlags;
187 int width, height;
188
189 if (psInfo->ppshheader->dwFlags & PSH_PROPSHEETPAGE)
190 psInfo->proppage[index].hpage = 0;
191 psInfo->proppage[index].hwndPage = 0;
192 psInfo->proppage[index].isDirty = FALSE;
193
194 /*
195 * Process property page flags.
196 */
197 dwFlags = lppsp->dwFlags;
198 psInfo->proppage[index].useCallback = dwFlags & PSP_USECALLBACK;
199 psInfo->proppage[index].hasHelp = dwFlags & PSP_HASHELP;
200
201 /* as soon as we have a page with the help flag, set the sheet flag on */
202 if (psInfo->proppage[index].hasHelp)
203 psInfo->hasHelp = TRUE;
204
205 /*
206 * Process page template.
207 */
208 if (dwFlags & PSP_DLGINDIRECT)
209 pTemplate = (DLGTEMPLATE*)lppsp->u1.pResource;
210 else
211 {
212 HRSRC hResource = FindResourceA(lppsp->hInstance,
213 lppsp->u1.pszTemplate,
214 RT_DIALOGA);
215 HGLOBAL hTemplate = LoadResource(lppsp->hInstance,
216 hResource);
217 pTemplate = (LPDLGTEMPLATEA)LockResource(hTemplate);
218 }
219
220 /*
221 * Extract the size of the page and the caption.
222 */
223 p = (const WORD *)pTemplate;
224
225 if (((MyDLGTEMPLATEEX*)pTemplate)->signature == 0xFFFF)
226 {
227 /* DIALOGEX template */
228
229 p++; /* dlgVer */
230 p++; /* signature */
231 p += 2; /* help ID */
232 p += 2; /* ext style */
233 p += 2; /* style */
234 }
235 else
236 {
237 /* DIALOG template */
238
239 p += 2; /* style */
240 p += 2; /* ext style */
241 }
242
243 p++; /* nb items */
244 p++; /* x */
245 p++; /* y */
246 width = (WORD)*p; p++;
247 height = (WORD)*p; p++;
248
249 /* remember the largest width and height */
250 if (width > psInfo->width)
251 psInfo->width = width;
252
253 if (height > psInfo->height)
254 psInfo->height = height;
255
256 /* menu */
257 switch ((WORD)*p)
258 {
259 case 0x0000:
260 p++;
261 break;
262 case 0xffff:
263 p += 2;
264 break;
265 default:
266 p += lstrlenW( (LPCWSTR)p ) + 1;
267 break;
268 }
269
270 /* class */
271 switch ((WORD)*p)
272 {
273 case 0x0000:
274 p++;
275 break;
276 case 0xffff:
277 p += 2;
278 break;
279 default:
280 p += lstrlenW( (LPCWSTR)p ) + 1;
281 break;
282 }
283
284 /* Extract the caption */
285 psInfo->proppage[index].pszText = (LPCWSTR)p;
286// TRACE("Tab %d %s\n",index,debugstr_w((LPCWSTR)p));
287 p += lstrlenW((LPCWSTR)p) + 1;
288
289 if (dwFlags & PSP_USETITLE)
290 {
291 if ( !HIWORD( lppsp->pszTitle ) )
292 {
293 char szTitle[256];
294
295 if ( !LoadStringA( lppsp->hInstance, (UINT) lppsp->pszTitle, szTitle, 256 ) )
296 return FALSE;
297
298//AH: TODO
299// psInfo->proppage[index].pszText = HEAP_strdupAtoW( GetProcessHeap(),
300// 0, szTitle );
301 }
302//AH: TODO
303// else
304// psInfo->proppage[index].pszText = HEAP_strdupAtoW(GetProcessHeap(),
305// 0,
306// lppsp->pszTitle);
307 }
308
309 /*
310 * Build the image list for icons
311 */
312 if ((dwFlags & PSP_USEHICON) || (dwFlags & PSP_USEICONID))
313 {
314 HICON hIcon;
315 int icon_cx = GetSystemMetrics(SM_CXSMICON);
316 int icon_cy = GetSystemMetrics(SM_CYSMICON);
317
318 if (dwFlags & PSP_USEICONID)
319 hIcon = LoadImageA(lppsp->hInstance, lppsp->u2.pszIcon, IMAGE_ICON,
320 icon_cx, icon_cy, LR_DEFAULTCOLOR);
321 else
322 hIcon = lppsp->u2.hIcon;
323
324 if (psInfo->hImageList == 0)
325 psInfo->hImageList = ImageList_Create(icon_cx, icon_cy, ILC_COLOR, 1, 1);
326
327 ImageList_AddIcon(psInfo->hImageList, hIcon);
328 }
329
330 return TRUE;
331}
332
333/******************************************************************************
334 * PROPSHEET_CreateDialog
335 *
336 * Creates the actual property sheet.
337 */
338
339//AH: WINE 990923 not merged due to changes from CB
340
341BOOL PROPSHEET_CreateDialog(PropSheetInfo* psInfo)
342{
343 LRESULT ret;
344 LPCVOID template;
345 HRSRC hRes;
346
347 if (psInfo->useCallback)
348 (*(psInfo->ppshheader->pfnCallback))(0, PSCB_PRECREATE, (LPARAM)template);
349
350 if (!(hRes = FindResourceA(COMCTL32_hModule,
351 MAKEINTRESOURCEA(IDD_PROPSHEET),
352 RT_DIALOGA)))
353 return FALSE;
354
355 if (!(template = (LPVOID)LoadResource(COMCTL32_hModule, hRes)))
356 return FALSE;
357
358 if (psInfo->useCallback)
359 (*(psInfo->ppshheader->pfnCallback))(0, PSCB_PRECREATE, (LPARAM)template);
360
361 if (psInfo->ppshheader->dwFlags & PSH_MODELESS)
362 ret = CreateDialogIndirectParamA(psInfo->ppshheader->hInstance,
363 (LPDLGTEMPLATEA) template,
364 psInfo->ppshheader->hwndParent,
365 (DLGPROC) PROPSHEET_DialogProc,
366 (LPARAM)psInfo);
367 else
368 ret = DialogBoxIndirectParamA(psInfo->ppshheader->hInstance,
369 (LPDLGTEMPLATEA) template,
370 psInfo->ppshheader->hwndParent,
371 (DLGPROC) PROPSHEET_DialogProc,
372 (LPARAM)psInfo);
373
374 return ret;
375}
376
377/******************************************************************************
378 * PROPSHEET_IsTooSmall
379 *
380 * Verify that the resource property sheet is big enough.
381 */
382static BOOL PROPSHEET_IsTooSmall(HWND hwndDlg, PropSheetInfo* psInfo)
383{
384 HWND hwndTabCtrl = GetDlgItem(hwndDlg, IDC_TABCONTROL);
385 RECT rcOrigTab, rcPage;
386
387 /*
388 * Original tab size.
389 */
390 GetClientRect(hwndTabCtrl, &rcOrigTab);
391// TRACE(propsheet, "orig tab %d %d %d %d\n", rcOrigTab.left, rcOrigTab.top,
392// rcOrigTab.right, rcOrigTab.bottom);
393
394 /*
395 * Biggest page size.
396 */
397 rcPage.left = psInfo->x;
398 rcPage.top = psInfo->y;
399 rcPage.right = psInfo->width;
400 rcPage.bottom = psInfo->height;
401
402 MapDialogRect(hwndDlg, &rcPage);
403// TRACE(propsheet, "biggest page %d %d %d %d\n", rcPage.left, rcPage.top,
404// rcPage.right, rcPage.bottom);
405
406 if (rcPage.right > rcOrigTab.right)
407 return TRUE;
408
409 if (rcPage.bottom > rcOrigTab.bottom)
410 return TRUE;
411
412 return FALSE;
413}
414
415/******************************************************************************
416 * PROPSHEET_IsTooSmallWizard
417 *
418 * Verify that the default property sheet is big enough.
419 */
420static BOOL PROPSHEET_IsTooSmallWizard(HWND hwndDlg, PropSheetInfo* psInfo)
421{
422 RECT rcSheetRect, rcPage, rcLine, rcSheetClient;
423 HWND hwndLine = GetDlgItem(hwndDlg, IDC_SUNKEN_LINE);
424 PADDING_INFO padding = PROPSHEET_GetPaddingInfoWizard(hwndDlg);
425
426 GetClientRect(hwndDlg, &rcSheetClient);
427 GetWindowRect(hwndDlg, &rcSheetRect);
428 GetWindowRect(hwndLine, &rcLine);
429
430 /* Remove the space below the sunken line */
431 rcSheetClient.bottom -= (rcSheetRect.bottom - rcLine.top);
432
433 /* Remove the buffer zone all around the edge */
434 rcSheetClient.bottom -= (padding.y * 2);
435 rcSheetClient.right -= (padding.x * 2);
436
437 /*
438 * Biggest page size.
439 */
440 rcPage.left = psInfo->x;
441 rcPage.top = psInfo->y;
442 rcPage.right = psInfo->width;
443 rcPage.bottom = psInfo->height;
444
445 MapDialogRect(hwndDlg, &rcPage);
446// TRACE("biggest page %d %d %d %d\n", rcPage.left, rcPage.top,
447// rcPage.right, rcPage.bottom);
448
449 if (rcPage.right > rcSheetClient.right)
450 return TRUE;
451
452 if (rcPage.bottom > rcSheetClient.bottom)
453 return TRUE;
454
455 return FALSE;
456}
457
458/******************************************************************************
459 * PROPSHEET_AdjustSize
460 *
461 * Resizes the property sheet and the tab control to fit the largest page.
462 */
463static BOOL PROPSHEET_AdjustSize(HWND hwndDlg, PropSheetInfo* psInfo)
464{
465 HWND hwndTabCtrl = GetDlgItem(hwndDlg, IDC_TABCONTROL);
466 HWND hwndButton = GetDlgItem(hwndDlg, IDOK);
467 RECT rc;
468 int tabOffsetX, tabOffsetY, buttonHeight;
469 PADDING_INFO padding = PROPSHEET_GetPaddingInfo(hwndDlg);
470
471 /* Get the height of buttons */
472 GetClientRect(hwndButton, &rc);
473 buttonHeight = rc.bottom;
474
475 /*
476 * Biggest page size.
477 */
478 rc.left = psInfo->x;
479 rc.top = psInfo->y;
480 rc.right = psInfo->width;
481 rc.bottom = psInfo->height;
482
483 MapDialogRect(hwndDlg, &rc);
484
485 /*
486 * Resize the tab control.
487 */
488 SendMessageA(hwndTabCtrl, TCM_ADJUSTRECT, TRUE, (LPARAM)&rc);
489
490 tabOffsetX = -(rc.left);
491 tabOffsetY = -(rc.top);
492
493 rc.right -= rc.left;
494 rc.bottom -= rc.top;
495 SetWindowPos(hwndTabCtrl, 0, 0, 0, rc.right, rc.bottom,
496 SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE);
497
498 GetClientRect(hwndTabCtrl, &rc);
499
500// TRACE(propsheet, "tab client rc %d %d %d %d\n",
501// rc.left, rc.top, rc.right, rc.bottom);
502
503 rc.right += ((padding.x * 2) + tabOffsetX);
504 rc.bottom += (buttonHeight + (3 * padding.y) + tabOffsetY);
505
506 /*
507 * Resize the property sheet.
508 */
509 SetWindowPos(hwndDlg, 0, 0, 0, rc.right, rc.bottom,
510 SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE);
511
512 return TRUE;
513}
514
515/******************************************************************************
516 * PROPSHEET_AdjustSizeWizard
517 *
518 * Resizes the property sheet to fit the largest page.
519 */
520static BOOL PROPSHEET_AdjustSizeWizard(HWND hwndDlg, PropSheetInfo* psInfo)
521{
522 HWND hwndButton = GetDlgItem(hwndDlg, IDCANCEL);
523 HWND hwndLine = GetDlgItem(hwndDlg, IDC_SUNKEN_LINE);
524 RECT rc;
525 int buttonHeight, lineHeight;
526 PADDING_INFO padding = PROPSHEET_GetPaddingInfoWizard(hwndDlg);
527
528 /* Get the height of buttons */
529 GetClientRect(hwndButton, &rc);
530 buttonHeight = rc.bottom;
531
532 GetClientRect(hwndLine, &rc);
533 lineHeight = rc.bottom;
534
535 /*
536 * Biggest page size.
537 */
538 rc.left = psInfo->x;
539 rc.top = psInfo->y;
540 rc.right = psInfo->width;
541 rc.bottom = psInfo->height;
542
543 MapDialogRect(hwndDlg, &rc);
544
545// TRACE("Biggest page %d %d %d %d\n", rc.left, rc.top, rc.right, rc.bottom);
546
547 /* Make room */
548 rc.right += (padding.x * 2);
549 rc.bottom += (buttonHeight + (5 * padding.y) + lineHeight);
550
551 /*
552 * Resize the property sheet.
553 */
554 SetWindowPos(hwndDlg, 0, 0, 0, rc.right, rc.bottom,
555 SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE);
556
557 return TRUE;
558}
559
560/******************************************************************************
561 * PROPSHEET_AdjustButtons
562 *
563 * Adjusts the buttons' positions.
564 */
565static BOOL PROPSHEET_AdjustButtons(HWND hwndParent, PropSheetInfo* psInfo)
566{
567 HWND hwndButton = GetDlgItem(hwndParent, IDOK);
568 RECT rcSheet;
569 int x, y;
570 int num_buttons = 2;
571 int buttonWidth, buttonHeight;
572 PADDING_INFO padding = PROPSHEET_GetPaddingInfo(hwndParent);
573
574 if (psInfo->hasApply)
575 num_buttons++;
576
577 if (psInfo->hasHelp)
578 num_buttons++;
579
580 /*
581 * Obtain the size of the buttons.
582 */
583 GetClientRect(hwndButton, &rcSheet);
584 buttonWidth = rcSheet.right;
585 buttonHeight = rcSheet.bottom;
586
587 /*
588 * Get the size of the property sheet.
589 */
590 GetClientRect(hwndParent, &rcSheet);
591
592 /*
593 * All buttons will be at this y coordinate.
594 */
595 y = rcSheet.bottom - (padding.y + buttonHeight);
596
597 /*
598 * Position OK button.
599 */
600 hwndButton = GetDlgItem(hwndParent, IDOK);
601
602 x = rcSheet.right - ((padding.x + buttonWidth) * num_buttons);
603
604 SetWindowPos(hwndButton, 0, x, y, 0, 0,
605 SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE);
606
607 /*
608 * Position Cancel button.
609 */
610 hwndButton = GetDlgItem(hwndParent, IDCANCEL);
611
612 x = rcSheet.right - ((padding.x + buttonWidth) * (num_buttons - 1));
613
614 SetWindowPos(hwndButton, 0, x, y, 0, 0,
615 SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE);
616
617 /*
618 * Position Apply button.
619 */
620 hwndButton = GetDlgItem(hwndParent, IDC_APPLY_BUTTON);
621
622 if (psInfo->hasApply)
623 {
624 if (psInfo->hasHelp)
625 x = rcSheet.right - ((padding.x + buttonWidth) * 2);
626 else
627 x = rcSheet.right - (padding.x + buttonWidth);
628
629 SetWindowPos(hwndButton, 0, x, y, 0, 0,
630 SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE);
631
632 EnableWindow(hwndButton, FALSE);
633 }
634 else
635 ShowWindow(hwndButton, SW_HIDE);
636
637 /*
638 * Position Help button.
639 */
640 hwndButton = GetDlgItem(hwndParent, IDHELP);
641
642 if (psInfo->hasHelp)
643 {
644 x = rcSheet.right - (padding.x + buttonWidth);
645
646 SetWindowPos(hwndButton, 0, x, y, 0, 0,
647 SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE);
648 }
649 else
650 ShowWindow(hwndButton, SW_HIDE);
651
652 return TRUE;
653}
654
655/******************************************************************************
656 * PROPSHEET_AdjustButtonsWizard
657 *
658 * Adjusts the buttons' positions.
659 */
660static BOOL PROPSHEET_AdjustButtonsWizard(HWND hwndParent,
661 PropSheetInfo* psInfo)
662{
663 HWND hwndButton = GetDlgItem(hwndParent, IDCANCEL);
664 HWND hwndLine = GetDlgItem(hwndParent, IDC_SUNKEN_LINE);
665 RECT rcSheet;
666 int x, y;
667 int num_buttons = 3;
668 int buttonWidth, buttonHeight, lineHeight, lineWidth;
669 PADDING_INFO padding = PROPSHEET_GetPaddingInfoWizard(hwndParent);
670
671 if (psInfo->hasHelp)
672 num_buttons++;
673
674 /*
675 * Obtain the size of the buttons.
676 */
677 GetClientRect(hwndButton, &rcSheet);
678 buttonWidth = rcSheet.right;
679 buttonHeight = rcSheet.bottom;
680
681 GetClientRect(hwndLine, &rcSheet);
682 lineHeight = rcSheet.bottom;
683
684 /*
685 * Get the size of the property sheet.
686 */
687 GetClientRect(hwndParent, &rcSheet);
688
689 /*
690 * All buttons will be at this y coordinate.
691 */
692 y = rcSheet.bottom - (padding.y + buttonHeight);
693
694 /*
695 * Position the Next and the Finish buttons.
696 */
697 hwndButton = GetDlgItem(hwndParent, IDC_NEXT_BUTTON);
698
699 x = rcSheet.right - ((padding.x + buttonWidth) * (num_buttons - 1));
700
701 SetWindowPos(hwndButton, 0, x, y, 0, 0,
702 SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE);
703
704 hwndButton = GetDlgItem(hwndParent, IDC_FINISH_BUTTON);
705
706 SetWindowPos(hwndButton, 0, x, y, 0, 0,
707 SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE);
708
709 ShowWindow(hwndButton, SW_HIDE);
710
711 /*
712 * Position the Back button.
713 */
714 hwndButton = GetDlgItem(hwndParent, IDC_BACK_BUTTON);
715
716 x -= buttonWidth;
717
718 SetWindowPos(hwndButton, 0, x, y, 0, 0,
719 SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE);
720
721 /*
722 * Position the Cancel button.
723 */
724 hwndButton = GetDlgItem(hwndParent, IDCANCEL);
725
726 x = rcSheet.right - ((padding.x + buttonWidth) * (num_buttons - 2));
727
728 SetWindowPos(hwndButton, 0, x, y, 0, 0,
729 SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE);
730
731 /*
732 * Position Help button.
733 */
734 hwndButton = GetDlgItem(hwndParent, IDHELP);
735
736 if (psInfo->hasHelp)
737 {
738 x = rcSheet.right - (padding.x + buttonWidth);
739
740 SetWindowPos(hwndButton, 0, x, y, 0, 0,
741 SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE);
742 }
743 else
744 ShowWindow(hwndButton, SW_HIDE);
745
746 /*
747 * Position and resize the sunken line.
748 */
749 x = padding.x;
750 y = rcSheet.bottom - ((padding.y * 2) + buttonHeight + lineHeight);
751
752 GetClientRect(hwndParent, &rcSheet);
753 lineWidth = rcSheet.right - (padding.x * 2);
754
755 SetWindowPos(hwndLine, 0, x, y, lineWidth, 2,
756 SWP_NOZORDER | SWP_NOACTIVATE);
757
758 return TRUE;
759}
760
761/******************************************************************************
762 * PROPSHEET_GetPaddingInfo
763 *
764 * Returns the layout information.
765 */
766static PADDING_INFO PROPSHEET_GetPaddingInfo(HWND hwndDlg)
767{
768 HWND hwndTab = GetDlgItem(hwndDlg, IDC_TABCONTROL);
769 RECT rcTab;
770 POINT tl;
771 PADDING_INFO padding;
772
773 GetWindowRect(hwndTab, &rcTab);
774
775 tl.x = rcTab.left;
776 tl.y = rcTab.top;
777
778 ScreenToClient(hwndDlg, &tl);
779
780 padding.x = tl.x;
781 padding.y = tl.y;
782
783 return padding;
784}
785
786/******************************************************************************
787 * PROPSHEET_GetPaddingInfoWizard
788 *
789 * Returns the layout information.
790 * Horizontal spacing is the distance between the Cancel and Help buttons.
791 * Vertical spacing is the distance between the line and the buttons.
792 */
793static PADDING_INFO PROPSHEET_GetPaddingInfoWizard(HWND hwndDlg)
794{
795 PADDING_INFO padding;
796 RECT rc;
797 HWND hwndControl;
798 POINT ptHelp, ptCancel, ptLine;
799
800 /* Help button */
801 hwndControl = GetDlgItem(hwndDlg, IDHELP);
802 GetWindowRect(hwndControl, &rc);
803
804 ptHelp.x = rc.left;
805 ptHelp.y = rc.top;
806
807 ScreenToClient(hwndDlg, &ptHelp);
808
809 /* Cancel button */
810 hwndControl = GetDlgItem(hwndDlg, IDCANCEL);
811 GetWindowRect(hwndControl, &rc);
812
813 ptCancel.x = rc.right;
814 ptCancel.y = rc.top;
815
816 ScreenToClient(hwndDlg, &ptCancel);
817
818 /* Line */
819 hwndControl = GetDlgItem(hwndDlg, IDC_SUNKEN_LINE);
820 GetWindowRect(hwndControl, &rc);
821
822 ptLine.x = 0;
823 ptLine.y = rc.bottom;
824
825 ScreenToClient(hwndDlg, &ptLine);
826
827 padding.x = ptHelp.x - ptCancel.x;
828 padding.y = ptHelp.y - ptLine.y;
829
830 return padding;
831}
832
833/******************************************************************************
834 * PROPSHEET_CreateTabControl
835 *
836 * Insert the tabs in the tab control.
837 */
838static BOOL PROPSHEET_CreateTabControl(HWND hwndParent,
839 PropSheetInfo * psInfo)
840{
841 HWND hwndTabCtrl = GetDlgItem(hwndParent, IDC_TABCONTROL);
842 TCITEMA item;
843 int i, nTabs;
844 char tabtext[MAX_TABTEXT_LENGTH] = "Tab text";
845
846 item.mask = TCIF_TEXT;
847 item.pszText = tabtext;
848 item.cchTextMax = MAX_TABTEXT_LENGTH;
849
850 nTabs = psInfo->ppshheader->nPages;
851
852 /*
853 * Set the image list for icons.
854 */
855 if (psInfo->hImageList)
856 {
857 item.mask |= TCIF_IMAGE;
858 SendMessageA(hwndTabCtrl, TCM_SETIMAGELIST, 0, (LPARAM)psInfo->hImageList);
859 }
860
861 for (i = 0; i < nTabs; i++)
862 {
863 item.iImage = i;
864
865 WideCharToMultiByte(CP_ACP, 0,
866 (LPCWSTR)psInfo->proppage[i].pszText,
867 -1, tabtext, MAX_TABTEXT_LENGTH, NULL, NULL);
868
869 SendMessageA(hwndTabCtrl, TCM_INSERTITEMA, (WPARAM)i, (LPARAM)&item);
870 }
871
872 return TRUE;
873}
874
875/******************************************************************************
876 * PROPSHEET_CreatePage
877 *
878 * Creates a page.
879 */
880static int PROPSHEET_CreatePage(HWND hwndParent,
881 int index,
882 const PropSheetInfo * psInfo,
883 LPCPROPSHEETPAGEA ppshpage,
884 BOOL showPage)
885{
886 DLGTEMPLATE* pTemplate;
887 HWND hwndPage;
888 RECT rc;
889 PropPageInfo* ppInfo = psInfo->proppage;
890 PADDING_INFO padding;
891
892// TRACE("index %d\n", index);
893
894 if (ppshpage->dwFlags & PSP_DLGINDIRECT)
895 pTemplate = (DLGTEMPLATE*)ppshpage->u1.pResource;
896 else
897 {
898 HRSRC hResource = FindResourceA(ppshpage->hInstance,
899 ppshpage->u1.pszTemplate,
900 RT_DIALOGA);
901 HGLOBAL hTemplate = LoadResource(ppshpage->hInstance, hResource);
902 pTemplate = (LPDLGTEMPLATEA)LockResource(hTemplate);
903 }
904
905 if (((MyDLGTEMPLATEEX*)pTemplate)->signature == 0xFFFF)
906 {
907 ((MyDLGTEMPLATEEX*)pTemplate)->style |= WS_CHILD;
908 ((MyDLGTEMPLATEEX*)pTemplate)->style &= ~DS_MODALFRAME;
909 ((MyDLGTEMPLATEEX*)pTemplate)->style &= ~WS_CAPTION;
910 ((MyDLGTEMPLATEEX*)pTemplate)->style &= ~WS_SYSMENU;
911 ((MyDLGTEMPLATEEX*)pTemplate)->style &= ~WS_POPUP;
912 ((MyDLGTEMPLATEEX*)pTemplate)->style &= ~WS_DISABLED;
913 }
914 else
915 {
916 pTemplate->style |= WS_CHILD;
917 pTemplate->style &= ~DS_MODALFRAME;
918 pTemplate->style &= ~WS_CAPTION;
919 pTemplate->style &= ~WS_SYSMENU;
920 pTemplate->style &= ~WS_POPUP;
921 pTemplate->style &= ~WS_DISABLED;
922 }
923
924 if (psInfo->proppage[index].useCallback)
925 (*(ppshpage->pfnCallback))(hwndParent,
926 PSPCB_CREATE,
927 (LPPROPSHEETPAGEA)ppshpage);
928
929 hwndPage = CreateDialogIndirectParamA(ppshpage->hInstance,
930 pTemplate,
931 hwndParent,
932 ppshpage->pfnDlgProc,
933 (LPARAM)ppshpage);
934
935 ppInfo[index].hwndPage = hwndPage;
936
937 rc.left = psInfo->x;
938 rc.top = psInfo->y;
939 rc.right = psInfo->width;
940 rc.bottom = psInfo->height;
941
942 MapDialogRect(hwndParent, &rc);
943
944 if (psInfo->ppshheader->dwFlags & PSH_WIZARD)
945 padding = PROPSHEET_GetPaddingInfoWizard(hwndParent);
946 else
947 {
948 /*
949 * Ask the Tab control to fit this page in.
950 */
951
952 HWND hwndTabCtrl = GetDlgItem(hwndParent, IDC_TABCONTROL);
953 SendMessageA(hwndTabCtrl, TCM_ADJUSTRECT, FALSE, (LPARAM)&rc);
954 padding = PROPSHEET_GetPaddingInfo(hwndParent);
955 }
956
957 SetWindowPos(hwndPage, HWND_TOP,
958 rc.left + padding.x,
959 rc.top + padding.y,
960 0, 0, SWP_NOSIZE);
961
962 if (showPage)
963 {
964 NMHDR hdr;
965
966 hdr.hwndFrom = hwndParent;
967 hdr.code = PSN_SETACTIVE;
968
969 /*
970 * Send the notification before showing the page.
971 */
972 SendMessageA(hwndPage, WM_NOTIFY, 0, (LPARAM) &hdr);
973
974 ShowWindow(hwndPage, SW_SHOW);
975 }
976 else
977 ShowWindow(hwndPage, SW_HIDE);
978
979 return TRUE;
980}
981
982/******************************************************************************
983 * PROPSHEET_ShowPage
984 *
985 * Displays or creates the specified page.
986 */
987static BOOL PROPSHEET_ShowPage(HWND hwndDlg, int index, PropSheetInfo * psInfo)
988{
989 if (index == psInfo->active_page)
990 return TRUE;
991
992 ShowWindow(psInfo->proppage[psInfo->active_page].hwndPage, SW_HIDE);
993
994 if (psInfo->proppage[index].hwndPage != 0)
995 ShowWindow(psInfo->proppage[index].hwndPage, SW_SHOW);
996 else
997 {
998 LPCPROPSHEETPAGEA ppshpage = PROPSHEET_GetPSPPage(psInfo, index);
999 PROPSHEET_CreatePage(hwndDlg, index, psInfo, ppshpage, TRUE);
1000 }
1001
1002 psInfo->active_page = index;
1003
1004 return TRUE;
1005}
1006
1007/******************************************************************************
1008 * PROPSHEET_Back
1009 */
1010static BOOL PROPSHEET_Back(HWND hwndDlg)
1011{
1012 BOOL res;
1013 NMHDR hdr;
1014 HWND hwndPage;
1015 HWND hwndBack = GetDlgItem(hwndDlg, IDC_BACK_BUTTON);
1016 PropSheetInfo* psInfo = (PropSheetInfo*) GetPropA(hwndDlg,
1017 PropSheetInfoStr);
1018
1019 hdr.code = PSN_WIZBACK;
1020
1021 hwndPage = psInfo->proppage[psInfo->active_page].hwndPage;
1022
1023 if (SendMessageA(hwndPage, WM_NOTIFY, 0, (LPARAM) &hdr) == -1)
1024 return FALSE;
1025
1026 res = PROPSHEET_SetCurSel(hwndDlg, psInfo->active_page - 1, 0);
1027
1028 /* if we went to page 0, disable Back button */
1029 if (res && (psInfo->active_page == 0))
1030 EnableWindow(hwndBack, FALSE);
1031
1032 return TRUE;
1033}
1034
1035/******************************************************************************
1036 * PROPSHEET_Next
1037 */
1038static BOOL PROPSHEET_Next(HWND hwndDlg)
1039{
1040 NMHDR hdr;
1041 HWND hwndPage;
1042 LRESULT msgResult = 0;
1043 PropSheetInfo* psInfo = (PropSheetInfo*) GetPropA(hwndDlg,
1044 PropSheetInfoStr);
1045
1046 hdr.hwndFrom = hwndDlg;
1047 hdr.code = PSN_WIZNEXT;
1048
1049 hwndPage = psInfo->proppage[psInfo->active_page].hwndPage;
1050
1051 msgResult = SendMessageA(hwndPage, WM_NOTIFY, 0, (LPARAM) &hdr);
1052
1053// TRACE("msg result %ld\n", msgResult);
1054
1055 if (msgResult == -1)
1056 return FALSE;
1057
1058 if(PROPSHEET_CanSetCurSel(hwndDlg) != FALSE)
1059 {
1060 PROPSHEET_SetCurSel(hwndDlg, psInfo->active_page + 1, 0);
1061 }
1062
1063 return TRUE;
1064}
1065
1066/******************************************************************************
1067 * PROPSHEET_Finish
1068 */
1069static BOOL PROPSHEET_Finish(HWND hwndDlg)
1070{
1071 NMHDR hdr;
1072 HWND hwndPage;
1073 LRESULT msgResult = 0;
1074 PropSheetInfo* psInfo = (PropSheetInfo*) GetPropA(hwndDlg,
1075 PropSheetInfoStr);
1076
1077 hdr.hwndFrom = hwndDlg;
1078 hdr.code = PSN_WIZFINISH;
1079
1080 hwndPage = psInfo->proppage[psInfo->active_page].hwndPage;
1081
1082 msgResult = SendMessageA(hwndPage, WM_NOTIFY, 0, (LPARAM) &hdr);
1083
1084// TRACE("msg result %ld\n", msgResult);
1085
1086 if (msgResult != 0)
1087 return FALSE;
1088
1089 if (psInfo->isModeless)
1090 psInfo->active_page = -1;
1091 else
1092 EndDialog(hwndDlg, TRUE);
1093
1094 return TRUE;
1095}
1096
1097/******************************************************************************
1098 * PROPSHEET_Apply
1099 */
1100static BOOL PROPSHEET_Apply(HWND hwndDlg)
1101{
1102 int i;
1103 NMHDR hdr;
1104 HWND hwndPage;
1105 LRESULT msgResult;
1106 PropSheetInfo* psInfo = (PropSheetInfo*) GetPropA(hwndDlg,
1107 PropSheetInfoStr);
1108
1109 hdr.hwndFrom = hwndDlg;
1110
1111 /*
1112 * Send PSN_KILLACTIVE to the current page.
1113 */
1114 hdr.code = PSN_KILLACTIVE;
1115
1116 hwndPage = psInfo->proppage[psInfo->active_page].hwndPage;
1117
1118 if (SendMessageA(hwndPage, WM_NOTIFY, 0, (LPARAM) &hdr) != FALSE)
1119 return FALSE;
1120
1121 /*
1122 * Send PSN_APPLY to all pages.
1123 */
1124 hdr.code = PSN_APPLY;
1125
1126 for (i = 0; i < psInfo->nPages; i++)
1127 {
1128 hwndPage = psInfo->proppage[i].hwndPage;
1129 msgResult = SendMessageA(hwndPage, WM_NOTIFY, 0, (LPARAM) &hdr);
1130
1131 if (msgResult == PSNRET_INVALID_NOCHANGEPAGE)
1132 return FALSE;
1133 }
1134
1135 return TRUE;
1136}
1137
1138/******************************************************************************
1139 * PROPSHEET_Cancel
1140 */
1141static void PROPSHEET_Cancel(HWND hwndDlg)
1142{
1143 PropSheetInfo* psInfo = (PropSheetInfo*) GetPropA(hwndDlg,
1144 PropSheetInfoStr);
1145 HWND hwndPage = psInfo->proppage[psInfo->active_page].hwndPage;
1146 NMHDR hdr;
1147
1148 hdr.hwndFrom = hwndDlg;
1149 hdr.code = PSN_QUERYCANCEL;
1150
1151 if (SendMessageA(hwndPage, WM_NOTIFY, 0, (LPARAM) &hdr))
1152 return;
1153
1154 hdr.code = PSN_RESET;
1155
1156 SendMessageA(hwndPage, WM_NOTIFY, 0, (LPARAM) &hdr);
1157
1158 if (psInfo->isModeless)
1159 psInfo->active_page = -1; /* makes PSM_GETCURRENTPAGEHWND return NULL */
1160 else
1161 EndDialog(hwndDlg, FALSE);
1162}
1163
1164/******************************************************************************
1165 * PROPSHEET_Help
1166 */
1167static void PROPSHEET_Help(HWND hwndDlg)
1168{
1169 PropSheetInfo* psInfo = (PropSheetInfo*) GetPropA(hwndDlg,
1170 PropSheetInfoStr);
1171 HWND hwndPage = psInfo->proppage[psInfo->active_page].hwndPage;
1172 NMHDR hdr;
1173
1174 hdr.hwndFrom = hwndDlg;
1175 hdr.code = PSN_HELP;
1176
1177 SendMessageA(hwndPage, WM_NOTIFY, 0, (LPARAM) &hdr);
1178}
1179
1180/******************************************************************************
1181 * PROPSHEET_Changed
1182 */
1183static void PROPSHEET_Changed(HWND hwndDlg, HWND hwndDirtyPage)
1184{
1185 int i;
1186 PropSheetInfo* psInfo = (PropSheetInfo*) GetPropA(hwndDlg,
1187 PropSheetInfoStr);
1188 if (!psInfo) return;
1189 /*
1190 * Set the dirty flag of this page.
1191 */
1192 for (i = 0; i < psInfo->nPages; i++)
1193 {
1194 if (psInfo->proppage[i].hwndPage == hwndDirtyPage)
1195 psInfo->proppage[i].isDirty = TRUE;
1196 }
1197
1198 /*
1199 * Enable the Apply button.
1200 */
1201 if (psInfo->hasApply)
1202 {
1203 HWND hwndApplyBtn = GetDlgItem(hwndDlg, IDC_APPLY_BUTTON);
1204
1205 EnableWindow(hwndApplyBtn, TRUE);
1206 }
1207}
1208
1209/******************************************************************************
1210 * PROPSHEET_UnChanged
1211 */
1212static void PROPSHEET_UnChanged(HWND hwndDlg, HWND hwndCleanPage)
1213{
1214 int i;
1215 BOOL noPageDirty = TRUE;
1216 HWND hwndApplyBtn = GetDlgItem(hwndDlg, IDC_APPLY_BUTTON);
1217 PropSheetInfo* psInfo = (PropSheetInfo*) GetPropA(hwndDlg,
1218 PropSheetInfoStr);
1219 if ( !psInfo ) return;
1220 for (i = 0; i < psInfo->nPages; i++)
1221 {
1222 /* set the specified page as clean */
1223 if (psInfo->proppage[i].hwndPage == hwndCleanPage)
1224 psInfo->proppage[i].isDirty = FALSE;
1225
1226 /* look to see if there's any dirty pages */
1227 if (psInfo->proppage[i].isDirty)
1228 noPageDirty = FALSE;
1229 }
1230
1231 /*
1232 * Disable Apply button.
1233 */
1234 if (noPageDirty)
1235 EnableWindow(hwndApplyBtn, FALSE);
1236}
1237
1238/******************************************************************************
1239 * PROPSHEET_PressButton
1240 */
1241static void PROPSHEET_PressButton(HWND hwndDlg, int buttonID)
1242{
1243 switch (buttonID)
1244 {
1245 case PSBTN_APPLYNOW:
1246 SendMessageA(hwndDlg, WM_COMMAND, IDC_APPLY_BUTTON, 0);
1247 break;
1248 case PSBTN_BACK:
1249 PROPSHEET_Back(hwndDlg);
1250 break;
1251 case PSBTN_CANCEL:
1252 SendMessageA(hwndDlg, WM_COMMAND, IDCANCEL, 0);
1253 break;
1254 case PSBTN_FINISH:
1255 PROPSHEET_Finish(hwndDlg);
1256 break;
1257 case PSBTN_HELP:
1258 SendMessageA(hwndDlg, WM_COMMAND, IDHELP, 0);
1259 break;
1260 case PSBTN_NEXT:
1261 PROPSHEET_Next(hwndDlg);
1262 break;
1263 case PSBTN_OK:
1264 SendMessageA(hwndDlg, WM_COMMAND, IDOK, 0);
1265 break;
1266 default:
1267// FIXME(propsheet, "Invalid button index %d\n", buttonID);
1268 break;
1269 }
1270}
1271
1272/*************************************************************************
1273 * BOOL PROPSHEET_CanSetCurSel [Internal]
1274 *
1275 * Test weither the current page can be changed by sending a PSN_KILLACTIVE
1276 *
1277 * PARAMS
1278 * hwndDlg [I] handle to a Dialog hWnd
1279 *
1280 * RETURNS
1281 * TRUE if Current Selection can change
1282 *
1283 * NOTES
1284 */
1285static BOOL PROPSHEET_CanSetCurSel(HWND hwndDlg)
1286{
1287 PropSheetInfo* psInfo = (PropSheetInfo*) GetPropA(hwndDlg,
1288 PropSheetInfoStr);
1289 HWND hwndPage;
1290 NMHDR hdr;
1291
1292 if (!psInfo)
1293 return FALSE;
1294
1295 /*
1296 * Notify the current page.
1297 */
1298 hwndPage = psInfo->proppage[psInfo->active_page].hwndPage;
1299
1300 hdr.hwndFrom = hwndDlg;
1301 hdr.code = PSN_KILLACTIVE;
1302
1303 return !SendMessageA(hwndPage, WM_NOTIFY, 0, (LPARAM) &hdr);
1304}
1305
1306/******************************************************************************
1307 * PROPSHEET_SetCurSel
1308 */
1309static BOOL PROPSHEET_SetCurSel(HWND hwndDlg,
1310 int index,
1311 HPROPSHEETPAGE hpage)
1312{
1313 PropSheetInfo* psInfo = (PropSheetInfo*) GetPropA(hwndDlg,
1314 PropSheetInfoStr);
1315 HWND hwndPage;
1316 HWND hwndHelp = GetDlgItem(hwndDlg, IDHELP);
1317 NMHDR hdr;
1318
1319 hwndPage = psInfo->proppage[psInfo->active_page].hwndPage;
1320
1321 hdr.hwndFrom = hwndDlg;
1322 /*
1323 * hpage takes precedence over index.
1324 */
1325 if (hpage != NULL)
1326 {
1327 index = PROPSHEET_GetPageIndex(hpage, psInfo);
1328
1329 if (index == -1)
1330 {
1331 TRACE("Could not find page to remove!\n");
1332 return FALSE;
1333 }
1334 }
1335
1336 hwndPage = psInfo->proppage[index].hwndPage;
1337
1338 /*
1339 * Notify the new page if it's already created.
1340 * If not it will get created and notified in PROPSHEET_ShowPage.
1341 */
1342 if (hwndPage)
1343 {
1344 int result;
1345 hdr.code = PSN_SETACTIVE;
1346
1347 result = SendMessageA(hwndPage, WM_NOTIFY, 0, (LPARAM) &hdr);
1348 /*
1349 * TODO: check return value.
1350 */
1351 }
1352
1353 /*
1354 * Display the new page.
1355 */
1356 PROPSHEET_ShowPage(hwndDlg, index, psInfo);
1357
1358 if (psInfo->proppage[index].hasHelp)
1359 EnableWindow(hwndHelp, TRUE);
1360 else
1361 EnableWindow(hwndHelp, FALSE);
1362
1363 return TRUE;
1364}
1365
1366/******************************************************************************
1367 * PROPSHEET_SetTitleA
1368 */
1369static void PROPSHEET_SetTitleA(HWND hwndDlg, DWORD dwStyle, LPCSTR lpszText)
1370{
1371 if (dwStyle & PSH_PROPTITLE)
1372 {
1373 PropSheetInfo* psInfo = (PropSheetInfo*) GetPropA(hwndDlg,
1374 PropSheetInfoStr);
1375 char* dest;
1376 int lentitle = strlen(lpszText);
1377 int lenprop = strlen(psInfo->strPropertiesFor);
1378
1379 dest = COMCTL32_Alloc(lentitle + lenprop + 1);
1380 strcpy(dest, psInfo->strPropertiesFor);
1381 strcat(dest, lpszText);
1382
1383 SetWindowTextA(hwndDlg, dest);
1384 COMCTL32_Free(dest);
1385 }
1386 else
1387 SetWindowTextA(hwndDlg, lpszText);
1388}
1389
1390/******************************************************************************
1391 * PROPSHEET_SetFinishTextA
1392 */
1393static void PROPSHEET_SetFinishTextA(HWND hwndDlg, LPCSTR lpszText)
1394{
1395 HWND hwndButton = GetDlgItem(hwndDlg, IDC_FINISH_BUTTON);
1396
1397 /* Set text, show and enable the Finish button */
1398 SetWindowTextA(hwndButton, lpszText);
1399 ShowWindow(hwndButton, SW_SHOW);
1400 EnableWindow(hwndButton, TRUE);
1401
1402 /* Make it default pushbutton */
1403 SendMessageA(hwndDlg, DM_SETDEFID, IDC_FINISH_BUTTON, 0);
1404
1405 /* Hide Back button */
1406 hwndButton = GetDlgItem(hwndDlg, IDC_BACK_BUTTON);
1407 ShowWindow(hwndButton, SW_HIDE);
1408
1409 /* Hide Next button */
1410 hwndButton = GetDlgItem(hwndDlg, IDC_NEXT_BUTTON);
1411 ShowWindow(hwndButton, SW_HIDE);
1412}
1413
1414/******************************************************************************
1415 * PROPSHEET_QuerySiblings
1416 */
1417static LRESULT PROPSHEET_QuerySiblings(HWND hwndDlg,
1418 WPARAM wParam, LPARAM lParam)
1419{
1420 int i = 0;
1421 HWND hwndPage;
1422 LRESULT msgResult = 0;
1423 PropSheetInfo* psInfo = (PropSheetInfo*) GetPropA(hwndDlg,
1424 PropSheetInfoStr);
1425
1426 while ((i < psInfo->nPages) && (msgResult == 0))
1427 {
1428 hwndPage = psInfo->proppage[i].hwndPage;
1429 msgResult = SendMessageA(hwndPage, PSM_QUERYSIBLINGS, wParam, lParam);
1430 i++;
1431 }
1432
1433 return msgResult;
1434}
1435
1436/******************************************************************************
1437 * PROPSHEET_GetPSPPage
1438 */
1439static LPCPROPSHEETPAGEA PROPSHEET_GetPSPPage(const PropSheetInfo * psInfo,
1440 int index)
1441{
1442 BOOL usePSP = psInfo->ppshheader->dwFlags & PSH_PROPSHEETPAGE;
1443 LPCPROPSHEETPAGEA lppsp;
1444 int realIndex = psInfo->proppage[index].index;
1445
1446 if (usePSP)
1447 {
1448 BYTE* pByte;
1449
1450 lppsp = psInfo->ppshheader->u3.ppsp;
1451
1452 pByte = (BYTE*) lppsp;
1453
1454 pByte += (lppsp->dwSize * realIndex);
1455 lppsp = (LPCPROPSHEETPAGEA)pByte;
1456 }
1457 else
1458 lppsp = (LPCPROPSHEETPAGEA) psInfo->ppshheader->u3.phpage[realIndex];
1459
1460 return lppsp;
1461}
1462
1463/******************************************************************************
1464 * PROPSHEET_AddPage
1465 */
1466static BOOL PROPSHEET_AddPage(HWND hwndDlg,
1467 HPROPSHEETPAGE hpage)
1468{
1469 PropSheetInfo * psInfo = (PropSheetInfo*) GetPropA(hwndDlg,
1470 PropSheetInfoStr);
1471 HWND hwndTabControl = GetDlgItem(hwndDlg, IDC_TABCONTROL);
1472 TCITEMA item;
1473 char tabtext[MAX_TABTEXT_LENGTH] = "Tab text";
1474 LPCPROPSHEETPAGEA ppsp = (LPCPROPSHEETPAGEA)hpage;
1475
1476 /*
1477 * Allocate and fill in a new PropPageInfo entry.
1478 */
1479 psInfo->proppage = (PropPageInfo*) COMCTL32_ReAlloc(psInfo->proppage,
1480 sizeof(PropPageInfo) *
1481 (psInfo->nPages + 1));
1482
1483 PROPSHEET_CollectPageInfo(ppsp, psInfo, psInfo->nPages);
1484 psInfo->proppage[psInfo->nPages].index = -1;
1485 psInfo->proppage[psInfo->nPages].hpage = hpage;
1486
1487 /*
1488 * Create the page but don't show it.
1489 */
1490 PROPSHEET_CreatePage(hwndDlg, psInfo->nPages, psInfo, ppsp, FALSE);
1491
1492 /*
1493 * Add a new tab to the tab control.
1494 */
1495 item.mask = TCIF_TEXT;
1496 item.pszText = tabtext;
1497 item.cchTextMax = MAX_TABTEXT_LENGTH;
1498
1499 WideCharToMultiByte(CP_ACP, 0,
1500 (LPCWSTR)psInfo->proppage[psInfo->nPages].pszText,
1501 -1, tabtext, MAX_TABTEXT_LENGTH, NULL, NULL);
1502
1503 SendMessageA(hwndTabControl, TCM_INSERTITEMA, psInfo->nPages + 1,
1504 (LPARAM)&item);
1505
1506 psInfo->nPages++;
1507
1508 return TRUE;
1509}
1510
1511/******************************************************************************
1512 * PROPSHEET_RemovePage
1513 */
1514static BOOL PROPSHEET_RemovePage(HWND hwndDlg,
1515 int index,
1516 HPROPSHEETPAGE hpage)
1517{
1518 PropSheetInfo * psInfo = (PropSheetInfo*) GetPropA(hwndDlg,
1519 PropSheetInfoStr);
1520 HWND hwndTabControl = GetDlgItem(hwndDlg, IDC_TABCONTROL);
1521 PropPageInfo* oldPages;
1522
1523 if (!psInfo) {
1524// FIXME("No psInfo for propertysheet at windows 0x%04x, returning FALSE...\n", hwndDlg);
1525 return FALSE;
1526 }
1527 oldPages = psInfo->proppage;
1528 /*
1529 * hpage takes precedence over index.
1530 */
1531 if (hpage != 0)
1532 {
1533 index = PROPSHEET_GetPageIndex(hpage, psInfo);
1534 }
1535
1536 /* Make shure that index is within range */
1537 if (index < 0 || index >= psInfo->nPages)
1538 {
1539// TRACE("Could not find page to remove!\n");
1540 return FALSE;
1541 }
1542
1543// TRACE("total pages %d removing page %d active page %d\n",
1544// psInfo->nPages, index, psInfo->active_page);
1545 /*
1546 * Check if we're removing the active page.
1547 */
1548 if (index == psInfo->active_page)
1549 {
1550 if (psInfo->nPages > 1)
1551 {
1552 if (index > 0)
1553 {
1554 /* activate previous page */
1555 PROPSHEET_ShowPage(hwndDlg, index - 1, psInfo);
1556 }
1557 else
1558 {
1559 /* activate the next page */
1560 PROPSHEET_ShowPage(hwndDlg, index + 1, psInfo);
1561 }
1562 }
1563 else
1564 {
1565// TRACE("Removing the only page, close the dialog!\n");
1566
1567 if (psInfo->isModeless)
1568 psInfo->active_page = -1;
1569 else
1570 EndDialog(hwndDlg, FALSE);
1571
1572 return TRUE;
1573 }
1574 }
1575
1576 if (index < psInfo->active_page)
1577 psInfo->active_page--;
1578
1579 /* Destroy page dialog window.
1580 * If it's last page in modal dialog, it has been destroyed by EndDialog
1581 */
1582 if (psInfo->isModeless || psInfo->nPages > 1)
1583 DestroyWindow(psInfo->proppage[index].hwndPage);
1584
1585 /* Remove the tab */
1586 SendMessageA(hwndTabControl, TCM_DELETEITEM, index, 0);
1587
1588 psInfo->nPages--;
1589 psInfo->proppage = COMCTL32_Alloc(sizeof(PropPageInfo) * psInfo->nPages);
1590
1591 if (index > 0)
1592 memcpy(&psInfo->proppage[0], &oldPages[0], index * sizeof(PropPageInfo));
1593
1594 if (index < psInfo->nPages)
1595 memcpy(&psInfo->proppage[index], &oldPages[index + 1],
1596 (psInfo->nPages - index) * sizeof(PropPageInfo));
1597
1598 COMCTL32_Free(oldPages);
1599
1600 return FALSE;
1601}
1602
1603/******************************************************************************
1604 * PROPSHEET_SetWizButtons
1605 *
1606 * This code will work if (and assumes that) the Next button is on top of the
1607 * Finish button. ie. Finish comes after Next in the Z order.
1608 * This means make sure the dialog template reflects this.
1609 *
1610 */
1611static void PROPSHEET_SetWizButtons(HWND hwndDlg, DWORD dwFlags)
1612{
1613 HWND hwndButton;
1614
1615// TRACE("%ld\n", dwFlags);
1616
1617 if (dwFlags & PSWIZB_BACK)
1618 {
1619 hwndButton = GetDlgItem(hwndDlg, IDC_BACK_BUTTON);
1620 EnableWindow(hwndButton, TRUE);
1621 }
1622
1623 if (dwFlags & PSWIZB_NEXT)
1624 {
1625 /* Hide the Finish button */
1626 hwndButton = GetDlgItem(hwndDlg, IDC_FINISH_BUTTON);
1627 ShowWindow(hwndButton, SW_HIDE);
1628
1629 /* Show and enable the Next button */
1630 hwndButton = GetDlgItem(hwndDlg, IDC_NEXT_BUTTON);
1631
1632 ShowWindow(hwndButton, SW_SHOW);
1633 EnableWindow(hwndButton, TRUE);
1634
1635 /* Set the Next button as the default pushbutton */
1636 SendMessageA(hwndDlg, DM_SETDEFID, IDC_NEXT_BUTTON, 0);
1637 }
1638
1639 if ((dwFlags & PSWIZB_FINISH) || (dwFlags & PSWIZB_DISABLEDFINISH))
1640 {
1641 /* Hide the Next button */
1642 hwndButton = GetDlgItem(hwndDlg, IDC_NEXT_BUTTON);
1643 ShowWindow(hwndButton, SW_HIDE);
1644
1645 /* Show the Finish button */
1646 hwndButton = GetDlgItem(hwndDlg, IDC_FINISH_BUTTON);
1647 ShowWindow(hwndButton, SW_SHOW);
1648
1649 if (dwFlags & PSWIZB_FINISH)
1650 EnableWindow(hwndButton, TRUE);
1651 else
1652 EnableWindow(hwndButton, FALSE);
1653
1654 /* Set the Finish button as the default pushbutton */
1655 SendMessageA(hwndDlg, DM_SETDEFID, IDC_FINISH_BUTTON, 0);
1656 }
1657}
1658
1659/******************************************************************************
1660 * PROPSHEET_GetPageIndex
1661 *
1662 * Given a HPROPSHEETPAGE, returns the index of the corresponding page from
1663 * the array of PropPageInfo.
1664 */
1665static int PROPSHEET_GetPageIndex(HPROPSHEETPAGE hpage, PropSheetInfo* psInfo)
1666{
1667 BOOL found = FALSE;
1668 int index = 0;
1669
1670 while ((index < psInfo->nPages) && (found == FALSE))
1671 {
1672 if (psInfo->proppage[index].hpage == hpage)
1673 found = TRUE;
1674 else
1675 index++;
1676 }
1677
1678 if (found == FALSE)
1679 index = -1;
1680
1681 return index;
1682}
1683
1684/******************************************************************************
1685 * PROPSHEET_CleanUp
1686 */
1687static void PROPSHEET_CleanUp(HWND hwndDlg)
1688{
1689 PropSheetInfo* psInfo = (PropSheetInfo*) RemovePropA(hwndDlg,
1690 PropSheetInfoStr);
1691 COMCTL32_Free(psInfo->proppage);
1692 COMCTL32_Free(psInfo->strPropertiesFor);
1693 ImageList_Destroy(psInfo->hImageList);
1694
1695 GlobalFree((HGLOBAL)psInfo);
1696}
1697
1698/******************************************************************************
1699 * PropertySheetA (COMCTL32.84)(COMCTL32.83)
1700 */
1701INT WINAPI PropertySheetA(LPCPROPSHEETHEADERA lppsh)
1702{
1703 int bRet = 0;
1704 PropSheetInfo* psInfo = (PropSheetInfo*) GlobalAlloc(GPTR,
1705 sizeof(PropSheetInfo));
1706 LPCPROPSHEETPAGEA lppsp;
1707 int i;
1708
1709 PROPSHEET_CollectSheetInfo(lppsh, psInfo);
1710
1711 psInfo->proppage = (PropPageInfo*) COMCTL32_Alloc(sizeof(PropPageInfo) *
1712 lppsh->nPages);
1713
1714 for (i = 0; i < lppsh->nPages; i++)
1715 {
1716 psInfo->proppage[i].index = i;
1717 if (!(lppsh->dwFlags & PSH_PROPSHEETPAGE))
1718 psInfo->proppage[i].hpage = psInfo->ppshheader->u3.phpage[i];
1719 lppsp = PROPSHEET_GetPSPPage(psInfo, i);
1720 PROPSHEET_CollectPageInfo(lppsp, psInfo, i);
1721 }
1722
1723 bRet = PROPSHEET_CreateDialog(psInfo);
1724
1725 return bRet;
1726}
1727
1728/******************************************************************************
1729 * PropertySheet32W (COMCTL32.85)
1730 */
1731INT WINAPI PropertySheetW(LPCPROPSHEETHEADERW propertySheetHeader)
1732{
1733// FIXME(propsheet, "(%p): stub\n", propertySheetHeader);
1734
1735 return -1;
1736}
1737
1738/******************************************************************************
1739 * CreatePropertySheetPageA (COMCTL32.19)(COMCTL32.18)
1740 */
1741HPROPSHEETPAGE WINAPI CreatePropertySheetPageA(
1742 LPCPROPSHEETPAGEA lpPropSheetPage)
1743{
1744 PROPSHEETPAGEA* ppsp = COMCTL32_Alloc(sizeof(PROPSHEETPAGEA));
1745
1746 *ppsp = *lpPropSheetPage;
1747
1748 return (HPROPSHEETPAGE)ppsp;
1749}
1750
1751/******************************************************************************
1752 * CreatePropertySheetPageW (COMCTL32.20)
1753 */
1754HPROPSHEETPAGE WINAPI CreatePropertySheetPageW(LPCPROPSHEETPAGEW lpPropSheetPage)
1755{
1756// FIXME(propsheet, "(%p): stub\n", lpPropSheetPage);
1757
1758 return 0;
1759}
1760
1761/******************************************************************************
1762 * DestroyPropertySheetPage (COMCTL32.24)
1763 */
1764BOOL WINAPI DestroyPropertySheetPage(HPROPSHEETPAGE hPropPage)
1765{
1766 COMCTL32_Free(hPropPage);
1767
1768 return TRUE;
1769}
1770
1771/******************************************************************************
1772 * PROPSHEET_DialogProc
1773 */
1774BOOL WINAPI
1775PROPSHEET_DialogProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
1776{
1777 switch (uMsg)
1778 {
1779 case WM_INITDIALOG:
1780 {
1781 PropSheetInfo* psInfo = (PropSheetInfo*) lParam;
1782 char* strCaption = (char*)COMCTL32_Alloc(MAX_CAPTION_LENGTH);
1783 HWND hwndTabCtrl = GetDlgItem(hwnd, IDC_TABCONTROL);
1784 LPCPROPSHEETPAGEA ppshpage;
1785
1786 /*
1787 * Small icon in the title bar.
1788 */
1789 if ((psInfo->ppshheader->dwFlags & PSH_USEICONID) ||
1790 (psInfo->ppshheader->dwFlags & PSH_USEHICON))
1791 {
1792 HICON hIcon;
1793 int icon_cx = GetSystemMetrics(SM_CXSMICON);
1794 int icon_cy = GetSystemMetrics(SM_CYSMICON);
1795
1796 if (psInfo->ppshheader->dwFlags & PSH_USEICONID)
1797 hIcon = LoadImageA(psInfo->ppshheader->hInstance,
1798 psInfo->ppshheader->u1.pszIcon,
1799 IMAGE_ICON,
1800 icon_cx, icon_cy,
1801 LR_DEFAULTCOLOR);
1802 else
1803 hIcon = psInfo->ppshheader->u1.hIcon;
1804
1805 SendMessageA(hwnd, WM_SETICON, 0, hIcon);
1806 }
1807
1808 if (psInfo->ppshheader->dwFlags & PSH_USEHICON)
1809 SendMessageA(hwnd, WM_SETICON, 0, psInfo->ppshheader->u1.hIcon);
1810
1811 psInfo->strPropertiesFor = strCaption;
1812
1813 GetWindowTextA(hwnd, psInfo->strPropertiesFor, MAX_CAPTION_LENGTH);
1814
1815 PROPSHEET_CreateTabControl(hwnd, psInfo);
1816
1817 if (psInfo->ppshheader->dwFlags & PSH_WIZARD)
1818 {
1819 HWND hwndBack = GetDlgItem(hwnd, IDC_BACK_BUTTON);
1820
1821 if (PROPSHEET_IsTooSmallWizard(hwnd, psInfo))
1822 {
1823 PROPSHEET_AdjustSizeWizard(hwnd, psInfo);
1824 PROPSHEET_AdjustButtonsWizard(hwnd, psInfo);
1825 }
1826
1827 /* Disable Back button if we start at page 0 */
1828 if (psInfo->active_page == 0)
1829 EnableWindow(hwndBack, FALSE);
1830 }
1831 else
1832 {
1833 if (PROPSHEET_IsTooSmall(hwnd, psInfo))
1834 {
1835 PROPSHEET_AdjustSize(hwnd, psInfo);
1836 PROPSHEET_AdjustButtons(hwnd, psInfo);
1837 }
1838 }
1839
1840 if (psInfo->useCallback)
1841 (*(psInfo->ppshheader->pfnCallback))(hwnd,
1842 PSCB_INITIALIZED, (LPARAM)0);
1843
1844 ppshpage = PROPSHEET_GetPSPPage(psInfo, psInfo->active_page);
1845 PROPSHEET_CreatePage(hwnd, psInfo->active_page, psInfo, ppshpage, TRUE);
1846
1847 if (!(psInfo->ppshheader->dwFlags & PSH_WIZARD))
1848 SendMessageA(hwndTabCtrl, TCM_SETCURSEL, psInfo->active_page, 0);
1849
1850 SetPropA(hwnd, PropSheetInfoStr, (HANDLE)psInfo);
1851
1852
1853 if (!HIWORD(psInfo->ppshheader->pszCaption) &&
1854 psInfo->ppshheader->hInstance)
1855 {
1856 char szText[256];
1857
1858 if (LoadStringA(psInfo->ppshheader->hInstance,
1859 (UINT)psInfo->ppshheader->pszCaption, szText, 255))
1860 PROPSHEET_SetTitleA(hwnd, psInfo->ppshheader->dwFlags, szText);
1861 }
1862 else
1863 {
1864 PROPSHEET_SetTitleA(hwnd, psInfo->ppshheader->dwFlags,
1865 psInfo->ppshheader->pszCaption);
1866 }
1867
1868 return TRUE;
1869 }
1870
1871 case WM_DESTROY:
1872 PROPSHEET_CleanUp(hwnd);
1873 return TRUE;
1874
1875 case WM_CLOSE:
1876 PROPSHEET_Cancel(hwnd);
1877 return TRUE;
1878
1879 case WM_COMMAND:
1880 {
1881 WORD wID = LOWORD(wParam);
1882
1883 switch (wID)
1884 {
1885 case IDOK:
1886 case IDC_APPLY_BUTTON:
1887 {
1888 HWND hwndApplyBtn = GetDlgItem(hwnd, IDC_APPLY_BUTTON);
1889
1890 if (PROPSHEET_Apply(hwnd) == FALSE)
1891 break;
1892
1893 EnableWindow(hwndApplyBtn, FALSE);
1894
1895 if (wID == IDOK)
1896 {
1897 PropSheetInfo* psInfo = (PropSheetInfo*) GetPropA(hwnd,
1898 PropSheetInfoStr);
1899 int result = TRUE;
1900
1901 if (psInfo->restartWindows)
1902 result = ID_PSRESTARTWINDOWS;
1903
1904 /* reboot system takes precedence over restart windows */
1905 if (psInfo->rebootSystem)
1906 result = ID_PSREBOOTSYSTEM;
1907
1908 if (psInfo->isModeless)
1909 psInfo->active_page = -1;
1910 else
1911 EndDialog(hwnd, result);
1912 }
1913
1914 break;
1915 }
1916
1917 case IDC_BACK_BUTTON:
1918 PROPSHEET_Back(hwnd);
1919 break;
1920
1921 case IDC_NEXT_BUTTON:
1922 PROPSHEET_Next(hwnd);
1923 break;
1924
1925 case IDC_FINISH_BUTTON:
1926 PROPSHEET_Finish(hwnd);
1927 break;
1928
1929 case IDCANCEL:
1930 PROPSHEET_Cancel(hwnd);
1931 break;
1932
1933 case IDHELP:
1934 PROPSHEET_Help(hwnd);
1935 break;
1936 }
1937
1938 return TRUE;
1939 }
1940
1941 case WM_NOTIFY:
1942 {
1943 NMHDR* pnmh = (LPNMHDR) lParam;
1944
1945 if (pnmh->code == TCN_SELCHANGE)
1946 {
1947 int index = SendMessageA(pnmh->hwndFrom, TCM_GETCURSEL, 0, 0);
1948 PROPSHEET_SetCurSel(hwnd, index, 0);
1949 }
1950
1951 if(pnmh->code == TCN_SELCHANGING)
1952 {
1953 BOOL bRet = PROPSHEET_CanSetCurSel(hwnd);
1954 SetWindowLongA(hwnd, DWL_MSGRESULT, !bRet);
1955 return TRUE;
1956 }
1957
1958
1959 return 0;
1960 }
1961
1962 case PSM_GETCURRENTPAGEHWND:
1963 {
1964 PropSheetInfo* psInfo = (PropSheetInfo*) GetPropA(hwnd,
1965 PropSheetInfoStr);
1966 HWND hwndPage = 0;
1967
1968 if (psInfo->active_page != -1)
1969 hwndPage = psInfo->proppage[psInfo->active_page].hwndPage;
1970
1971 SetWindowLongA(hwnd, DWL_MSGRESULT, hwndPage);
1972
1973 return TRUE;
1974 }
1975
1976 case PSM_CHANGED:
1977 PROPSHEET_Changed(hwnd, (HWND)wParam);
1978 return TRUE;
1979
1980 case PSM_UNCHANGED:
1981 PROPSHEET_UnChanged(hwnd, (HWND)wParam);
1982 return TRUE;
1983
1984 case PSM_GETTABCONTROL:
1985 {
1986 HWND hwndTabCtrl = GetDlgItem(hwnd, IDC_TABCONTROL);
1987
1988 SetWindowLongA(hwnd, DWL_MSGRESULT, hwndTabCtrl);
1989
1990 return TRUE;
1991 }
1992
1993 case PSM_SETCURSEL:
1994 {
1995 BOOL msgResult;
1996
1997 msgResult = PROPSHEET_CanSetCurSel(hwnd);
1998 if(msgResult != FALSE)
1999 {
2000 msgResult = PROPSHEET_SetCurSel(hwnd,
2001 (int)wParam,
2002 (HPROPSHEETPAGE)lParam);
2003 }
2004
2005 SetWindowLongA(hwnd, DWL_MSGRESULT, msgResult);
2006
2007 return TRUE;
2008 }
2009
2010 case PSM_CANCELTOCLOSE:
2011 {
2012 HWND hwndOK = GetDlgItem(hwnd, IDOK);
2013 HWND hwndCancel = GetDlgItem(hwnd, IDCANCEL);
2014
2015 EnableWindow(hwndCancel, FALSE);
2016 SetWindowTextA(hwndOK, "Close"); /* FIXME: hardcoded string */
2017
2018 return TRUE;
2019 }
2020
2021 case PSM_RESTARTWINDOWS:
2022 {
2023 PropSheetInfo* psInfo = (PropSheetInfo*) GetPropA(hwnd,
2024 PropSheetInfoStr);
2025
2026 psInfo->restartWindows = TRUE;
2027 return TRUE;
2028 }
2029
2030 case PSM_REBOOTSYSTEM:
2031 {
2032 PropSheetInfo* psInfo = (PropSheetInfo*) GetPropA(hwnd,
2033 PropSheetInfoStr);
2034
2035 psInfo->rebootSystem = TRUE;
2036 return TRUE;
2037 }
2038
2039 case PSM_SETTITLEA:
2040 PROPSHEET_SetTitleA(hwnd, (DWORD) wParam, (LPCSTR) lParam);
2041 return TRUE;
2042
2043 case PSM_APPLY:
2044 {
2045 BOOL msgResult = PROPSHEET_Apply(hwnd);
2046
2047 SetWindowLongA(hwnd, DWL_MSGRESULT, msgResult);
2048
2049 return TRUE;
2050 }
2051
2052 case PSM_QUERYSIBLINGS:
2053 {
2054 LRESULT msgResult = PROPSHEET_QuerySiblings(hwnd, wParam, lParam);
2055
2056 SetWindowLongA(hwnd, DWL_MSGRESULT, msgResult);
2057
2058 return TRUE;
2059 }
2060
2061 case PSM_ADDPAGE:
2062 {
2063 /*
2064 * Note: MSVC++ 6.0 documentation says that PSM_ADDPAGE does not have
2065 * a return value. This is not true. PSM_ADDPAGE returns TRUE
2066 * on success or FALSE otherwise, as specified on MSDN Online.
2067 * Also see the MFC code for
2068 * CPropertySheet::AddPage(CPropertyPage* pPage).
2069 */
2070
2071 BOOL msgResult = PROPSHEET_AddPage(hwnd, (HPROPSHEETPAGE)lParam);
2072
2073 SetWindowLongA(hwnd, DWL_MSGRESULT, msgResult);
2074
2075 return TRUE;
2076 }
2077
2078 case PSM_REMOVEPAGE:
2079 PROPSHEET_RemovePage(hwnd, (int)wParam, (HPROPSHEETPAGE)lParam);
2080 return TRUE;
2081
2082 case PSM_ISDIALOGMESSAGE:
2083 {
2084 FIXME("Unimplemented msg PSM_ISDIALOGMESSAGE\n");
2085 return 0;
2086 }
2087
2088 case PSM_PRESSBUTTON:
2089 PROPSHEET_PressButton(hwnd, (int)wParam);
2090 return TRUE;
2091
2092 case PSM_SETFINISHTEXTA:
2093 PROPSHEET_SetFinishTextA(hwnd, (LPCSTR) lParam);
2094 return TRUE;
2095
2096 case PSM_SETWIZBUTTONS:
2097 PROPSHEET_SetWizButtons(hwnd, (DWORD)lParam);
2098 return TRUE;
2099
2100 case PSM_SETTITLEW:
2101 FIXME("Unimplemented msg PSM_SETTITLE32W\n");
2102 return 0;
2103 case PSM_SETCURSELID:
2104 FIXME("Unimplemented msg PSM_SETCURSELID\n");
2105 return 0;
2106 case PSM_SETFINISHTEXTW:
2107 FIXME("Unimplemented msg PSM_SETFINISHTEXT32W\n");
2108 return 0;
2109
2110 default:
2111 return FALSE;
2112 }
2113}
2114
Note: See TracBrowser for help on using the repository browser.