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

Last change on this file since 1844 was 1803, checked in by cbratschi, 26 years ago

fixed id for WM_NOTIFY

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