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

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

check for invalid structures and log errors

File size: 56.6 KB
Line 
1/* $Id: propsheet.c,v 1.16 1999-11-27 18:14:37 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 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 //AH: Check if ppshpage is valid
893 if (ppshpage == NULL)
894 {
895 dprintf(("COMCTL32:PROPSHEET_CreatePage: ERROR!!! ppshpage == NULL!!!\n"));
896 return FALSE;
897 }
898
899 if (ppshpage->dwFlags & PSP_DLGINDIRECT)
900 pTemplate = (DLGTEMPLATE*)ppshpage->u1.pResource;
901 else
902 {
903 HRSRC hResource = FindResourceA(ppshpage->hInstance,
904 ppshpage->u1.pszTemplate,
905 RT_DIALOGA);
906 HGLOBAL hTemplate = LoadResource(ppshpage->hInstance, hResource);
907 pTemplate = (LPDLGTEMPLATEA)LockResource(hTemplate);
908 }
909
910 //AH: Check if pTemplate is valid
911 if (pTemplate == NULL)
912 {
913 dprintf(("COMCTL32:PROPSHEET_CreatePage: ERROR!!! Dialog Template == NULL!!!\n"));
914 return FALSE;
915 }
916
917 if (((MyDLGTEMPLATEEX*)pTemplate)->signature == 0xFFFF)
918 {
919 ((MyDLGTEMPLATEEX*)pTemplate)->style |= WS_CHILD;
920 ((MyDLGTEMPLATEEX*)pTemplate)->style &= ~DS_MODALFRAME;
921 ((MyDLGTEMPLATEEX*)pTemplate)->style &= ~WS_CAPTION;
922 ((MyDLGTEMPLATEEX*)pTemplate)->style &= ~WS_SYSMENU;
923 ((MyDLGTEMPLATEEX*)pTemplate)->style &= ~WS_POPUP;
924 ((MyDLGTEMPLATEEX*)pTemplate)->style &= ~WS_DISABLED;
925 }
926 else
927 {
928 pTemplate->style |= WS_CHILD;
929 pTemplate->style &= ~DS_MODALFRAME;
930 pTemplate->style &= ~WS_CAPTION;
931 pTemplate->style &= ~WS_SYSMENU;
932 pTemplate->style &= ~WS_POPUP;
933 pTemplate->style &= ~WS_DISABLED;
934 }
935
936 if (psInfo->proppage[index].useCallback)
937 (*(ppshpage->pfnCallback))(hwndParent,
938 PSPCB_CREATE,
939 (LPPROPSHEETPAGEA)ppshpage);
940
941 hwndPage = CreateDialogIndirectParamA(ppshpage->hInstance,
942 pTemplate,
943 hwndParent,
944 ppshpage->pfnDlgProc,
945 (LPARAM)ppshpage);
946
947 ppInfo[index].hwndPage = hwndPage;
948
949 rc.left = psInfo->x;
950 rc.top = psInfo->y;
951 rc.right = psInfo->width;
952 rc.bottom = psInfo->height;
953
954 MapDialogRect(hwndParent, &rc);
955
956 if (psInfo->ppshheader->dwFlags & PSH_WIZARD)
957 padding = PROPSHEET_GetPaddingInfoWizard(hwndParent);
958 else
959 {
960 /*
961 * Ask the Tab control to fit this page in.
962 */
963
964 HWND hwndTabCtrl = GetDlgItem(hwndParent, IDC_TABCONTROL);
965 SendMessageA(hwndTabCtrl, TCM_ADJUSTRECT, FALSE, (LPARAM)&rc);
966 padding = PROPSHEET_GetPaddingInfo(hwndParent);
967 }
968
969 SetWindowPos(hwndPage, HWND_TOP,
970 rc.left + padding.x,
971 rc.top + padding.y,
972 0, 0, SWP_NOSIZE);
973
974 if (showPage)
975 {
976 NMHDR hdr;
977
978 hdr.hwndFrom = hwndParent;
979 hdr.idFrom = GetWindowLongA(hwndParent,GWL_ID);
980 hdr.code = PSN_SETACTIVE;
981
982 /*
983 * Send the notification before showing the page.
984 */
985 SendMessageA(hwndPage, WM_NOTIFY, 0, (LPARAM) &hdr);
986
987 ShowWindow(hwndPage, SW_SHOW);
988 }
989 else
990 ShowWindow(hwndPage, SW_HIDE);
991
992 return TRUE;
993}
994
995/******************************************************************************
996 * PROPSHEET_ShowPage
997 *
998 * Displays or creates the specified page.
999 */
1000static BOOL PROPSHEET_ShowPage(HWND hwndDlg, int index, PropSheetInfo * psInfo)
1001{
1002 if (index == psInfo->active_page)
1003 return TRUE;
1004
1005 ShowWindow(psInfo->proppage[psInfo->active_page].hwndPage, SW_HIDE);
1006
1007 if (psInfo->proppage[index].hwndPage != 0)
1008 ShowWindow(psInfo->proppage[index].hwndPage, SW_SHOW);
1009 else
1010 {
1011 LPCPROPSHEETPAGEA ppshpage = PROPSHEET_GetPSPPage(psInfo, index);
1012 PROPSHEET_CreatePage(hwndDlg, index, psInfo, ppshpage, TRUE);
1013 }
1014
1015 psInfo->active_page = index;
1016
1017 return TRUE;
1018}
1019
1020/******************************************************************************
1021 * PROPSHEET_Back
1022 */
1023static BOOL PROPSHEET_Back(HWND hwndDlg)
1024{
1025 BOOL res;
1026 NMHDR hdr;
1027 HWND hwndPage;
1028 HWND hwndBack = GetDlgItem(hwndDlg, IDC_BACK_BUTTON);
1029 PropSheetInfo* psInfo = (PropSheetInfo*) GetPropA(hwndDlg,
1030 PropSheetInfoStr);
1031
1032 if (psInfo->active_page <= 0)
1033 return FALSE;
1034
1035 hdr.hwndFrom = hwndDlg;
1036 hdr.idFrom = GetWindowLongA(hwndDlg,GWL_ID);
1037 hdr.code = PSN_WIZBACK;
1038
1039 hwndPage = psInfo->proppage[psInfo->active_page].hwndPage;
1040
1041 if (SendMessageA(hwndPage, WM_NOTIFY, 0, (LPARAM) &hdr) == -1)
1042 return FALSE;
1043
1044 res = PROPSHEET_CanSetCurSel(hwndDlg);
1045 if(res != FALSE)
1046 {
1047 res = PROPSHEET_SetCurSel(hwndDlg, psInfo->active_page - 1, 0);
1048 }
1049
1050 /* if we went to page 0, disable Back button */
1051 if (res && (psInfo->active_page == 0))
1052 EnableWindow(hwndBack, FALSE);
1053
1054 return TRUE;
1055}
1056
1057/******************************************************************************
1058 * PROPSHEET_Next
1059 */
1060static BOOL PROPSHEET_Next(HWND hwndDlg)
1061{
1062 NMHDR hdr;
1063 HWND hwndPage;
1064 LRESULT msgResult = 0;
1065 PropSheetInfo* psInfo = (PropSheetInfo*) GetPropA(hwndDlg,
1066 PropSheetInfoStr);
1067
1068 if (psInfo->active_page < 0 || psInfo->active_page == psInfo->nPages - 1)
1069 return FALSE;
1070
1071 hdr.hwndFrom = hwndDlg;
1072 hdr.idFrom = GetWindowLongA(hwndDlg,GWL_ID);
1073 hdr.code = PSN_WIZNEXT;
1074
1075 hwndPage = psInfo->proppage[psInfo->active_page].hwndPage;
1076
1077 msgResult = SendMessageA(hwndPage, WM_NOTIFY, 0, (LPARAM) &hdr);
1078
1079// TRACE("msg result %ld\n", msgResult);
1080
1081 if (msgResult == -1)
1082 return FALSE;
1083
1084 if(PROPSHEET_CanSetCurSel(hwndDlg) != FALSE)
1085 {
1086 PROPSHEET_SetCurSel(hwndDlg, psInfo->active_page + 1, 0);
1087 }
1088
1089 return TRUE;
1090}
1091
1092/******************************************************************************
1093 * PROPSHEET_Finish
1094 */
1095static BOOL PROPSHEET_Finish(HWND hwndDlg)
1096{
1097 NMHDR hdr;
1098 HWND hwndPage;
1099 LRESULT msgResult = 0;
1100 PropSheetInfo* psInfo = (PropSheetInfo*) GetPropA(hwndDlg,
1101 PropSheetInfoStr);
1102
1103 if (psInfo->active_page < 0)
1104 return FALSE;
1105
1106 hdr.hwndFrom = hwndDlg;
1107 hdr.idFrom = GetWindowLongA(hwndDlg,GWL_ID);
1108 hdr.code = PSN_WIZFINISH;
1109
1110 hwndPage = psInfo->proppage[psInfo->active_page].hwndPage;
1111
1112 msgResult = SendMessageA(hwndPage, WM_NOTIFY, 0, (LPARAM) &hdr);
1113
1114// TRACE("msg result %ld\n", msgResult);
1115
1116 if (msgResult != 0)
1117 return FALSE;
1118
1119 if (psInfo->isModeless)
1120 psInfo->active_page = -1;
1121 else
1122 EndDialog(hwndDlg, TRUE);
1123
1124 return TRUE;
1125}
1126
1127/******************************************************************************
1128 * PROPSHEET_Apply
1129 */
1130static BOOL PROPSHEET_Apply(HWND hwndDlg)
1131{
1132 int i;
1133 NMHDR hdr;
1134 HWND hwndPage;
1135 LRESULT msgResult;
1136 PropSheetInfo* psInfo = (PropSheetInfo*) GetPropA(hwndDlg,
1137 PropSheetInfoStr);
1138
1139 if (psInfo->active_page < 0)
1140 return FALSE;
1141
1142 hdr.hwndFrom = hwndDlg;
1143 hdr.idFrom = GetWindowLongA(hwndDlg,GWL_ID);
1144
1145 /*
1146 * Send PSN_KILLACTIVE to the current page.
1147 */
1148 hdr.code = PSN_KILLACTIVE;
1149
1150 hwndPage = psInfo->proppage[psInfo->active_page].hwndPage;
1151
1152 if (SendMessageA(hwndPage, WM_NOTIFY, 0, (LPARAM) &hdr) != FALSE)
1153 return FALSE;
1154
1155 /*
1156 * Send PSN_APPLY to all pages.
1157 */
1158 hdr.code = PSN_APPLY;
1159
1160 for (i = 0; i < psInfo->nPages; i++)
1161 {
1162 hwndPage = psInfo->proppage[i].hwndPage;
1163 msgResult = SendMessageA(hwndPage, WM_NOTIFY, 0, (LPARAM) &hdr);
1164
1165 if (msgResult == PSNRET_INVALID_NOCHANGEPAGE)
1166 return FALSE;
1167 }
1168
1169 return TRUE;
1170}
1171
1172/******************************************************************************
1173 * PROPSHEET_Cancel
1174 */
1175static void PROPSHEET_Cancel(HWND hwndDlg)
1176{
1177 PropSheetInfo* psInfo = (PropSheetInfo*) GetPropA(hwndDlg,
1178 PropSheetInfoStr);
1179 HWND hwndPage;
1180 NMHDR hdr;
1181
1182 if (psInfo->active_page < 0)
1183 return;
1184
1185 hwndPage = psInfo->proppage[psInfo->active_page].hwndPage;
1186 hdr.hwndFrom = hwndDlg;
1187 hdr.idFrom = GetWindowLongA(hwndDlg,GWL_ID);
1188 hdr.code = PSN_QUERYCANCEL;
1189
1190 if (SendMessageA(hwndPage, WM_NOTIFY, 0, (LPARAM) &hdr))
1191 return;
1192
1193 hdr.code = PSN_RESET;
1194
1195 SendMessageA(hwndPage, WM_NOTIFY, 0, (LPARAM) &hdr);
1196
1197 if (psInfo->isModeless)
1198 psInfo->active_page = -1; /* makes PSM_GETCURRENTPAGEHWND return NULL */
1199 else
1200 EndDialog(hwndDlg, FALSE);
1201}
1202
1203/******************************************************************************
1204 * PROPSHEET_Help
1205 */
1206static void PROPSHEET_Help(HWND hwndDlg)
1207{
1208 PropSheetInfo* psInfo = (PropSheetInfo*) GetPropA(hwndDlg,
1209 PropSheetInfoStr);
1210 HWND hwndPage;
1211 NMHDR hdr;
1212
1213 if (psInfo->active_page < 0)
1214 return;
1215
1216 hwndPage = psInfo->proppage[psInfo->active_page].hwndPage;
1217 hdr.hwndFrom = hwndDlg;
1218 hdr.idFrom = GetWindowLongA(hwndDlg,GWL_ID);
1219 hdr.code = PSN_HELP;
1220
1221 SendMessageA(hwndPage, WM_NOTIFY, 0, (LPARAM) &hdr);
1222}
1223
1224/******************************************************************************
1225 * PROPSHEET_Changed
1226 */
1227static void PROPSHEET_Changed(HWND hwndDlg, HWND hwndDirtyPage)
1228{
1229 int i;
1230 PropSheetInfo* psInfo = (PropSheetInfo*) GetPropA(hwndDlg,
1231 PropSheetInfoStr);
1232 if (!psInfo) return;
1233 /*
1234 * Set the dirty flag of this page.
1235 */
1236 for (i = 0; i < psInfo->nPages; i++)
1237 {
1238 if (psInfo->proppage[i].hwndPage == hwndDirtyPage)
1239 psInfo->proppage[i].isDirty = TRUE;
1240 }
1241
1242 /*
1243 * Enable the Apply button.
1244 */
1245 if (psInfo->hasApply)
1246 {
1247 HWND hwndApplyBtn = GetDlgItem(hwndDlg, IDC_APPLY_BUTTON);
1248
1249 EnableWindow(hwndApplyBtn, TRUE);
1250 }
1251}
1252
1253/******************************************************************************
1254 * PROPSHEET_UnChanged
1255 */
1256static void PROPSHEET_UnChanged(HWND hwndDlg, HWND hwndCleanPage)
1257{
1258 int i;
1259 BOOL noPageDirty = TRUE;
1260 HWND hwndApplyBtn = GetDlgItem(hwndDlg, IDC_APPLY_BUTTON);
1261 PropSheetInfo* psInfo = (PropSheetInfo*) GetPropA(hwndDlg,
1262 PropSheetInfoStr);
1263 if ( !psInfo ) return;
1264 for (i = 0; i < psInfo->nPages; i++)
1265 {
1266 /* set the specified page as clean */
1267 if (psInfo->proppage[i].hwndPage == hwndCleanPage)
1268 psInfo->proppage[i].isDirty = FALSE;
1269
1270 /* look to see if there's any dirty pages */
1271 if (psInfo->proppage[i].isDirty)
1272 noPageDirty = FALSE;
1273 }
1274
1275 /*
1276 * Disable Apply button.
1277 */
1278 if (noPageDirty)
1279 EnableWindow(hwndApplyBtn, FALSE);
1280}
1281
1282/******************************************************************************
1283 * PROPSHEET_PressButton
1284 */
1285static void PROPSHEET_PressButton(HWND hwndDlg, int buttonID)
1286{
1287 switch (buttonID)
1288 {
1289 case PSBTN_APPLYNOW:
1290 SendMessageA(hwndDlg, WM_COMMAND, IDC_APPLY_BUTTON, 0);
1291 break;
1292 case PSBTN_BACK:
1293 PROPSHEET_Back(hwndDlg);
1294 break;
1295 case PSBTN_CANCEL:
1296 SendMessageA(hwndDlg, WM_COMMAND, IDCANCEL, 0);
1297 break;
1298 case PSBTN_FINISH:
1299 PROPSHEET_Finish(hwndDlg);
1300 break;
1301 case PSBTN_HELP:
1302 SendMessageA(hwndDlg, WM_COMMAND, IDHELP, 0);
1303 break;
1304 case PSBTN_NEXT:
1305 PROPSHEET_Next(hwndDlg);
1306 break;
1307 case PSBTN_OK:
1308 SendMessageA(hwndDlg, WM_COMMAND, IDOK, 0);
1309 break;
1310 default:
1311// FIXME(propsheet, "Invalid button index %d\n", buttonID);
1312 break;
1313 }
1314}
1315
1316/*************************************************************************
1317 * BOOL PROPSHEET_CanSetCurSel [Internal]
1318 *
1319 * Test weither the current page can be changed by sending a PSN_KILLACTIVE
1320 *
1321 * PARAMS
1322 * hwndDlg [I] handle to a Dialog hWnd
1323 *
1324 * RETURNS
1325 * TRUE if Current Selection can change
1326 *
1327 * NOTES
1328 */
1329static BOOL PROPSHEET_CanSetCurSel(HWND hwndDlg)
1330{
1331 PropSheetInfo* psInfo = (PropSheetInfo*) GetPropA(hwndDlg,
1332 PropSheetInfoStr);
1333 HWND hwndPage;
1334 NMHDR hdr;
1335
1336 if (!psInfo || psInfo->active_page < 0)
1337 return FALSE;
1338 /*
1339 * Notify the current page.
1340 */
1341 hwndPage = psInfo->proppage[psInfo->active_page].hwndPage;
1342
1343 hdr.hwndFrom = hwndDlg;
1344 hdr.idFrom = GetWindowLongA(hwndDlg,GWL_ID);
1345 hdr.code = PSN_KILLACTIVE;
1346
1347 return !SendMessageA(hwndPage, WM_NOTIFY, 0, (LPARAM) &hdr);
1348}
1349
1350/******************************************************************************
1351 * PROPSHEET_SetCurSel
1352 */
1353static BOOL PROPSHEET_SetCurSel(HWND hwndDlg,
1354 int index,
1355 HPROPSHEETPAGE hpage)
1356{
1357 PropSheetInfo* psInfo = (PropSheetInfo*) GetPropA(hwndDlg,
1358 PropSheetInfoStr);
1359 HWND hwndPage;
1360 HWND hwndHelp = GetDlgItem(hwndDlg, IDHELP);
1361 NMHDR hdr;
1362
1363 if (psInfo->active_page < 0)
1364 return FALSE;
1365
1366 hwndPage = psInfo->proppage[psInfo->active_page].hwndPage;
1367
1368 hdr.hwndFrom = hwndDlg;
1369 hdr.idFrom = GetWindowLongA(hwndDlg,GWL_ID);
1370 /*
1371 * hpage takes precedence over index.
1372 */
1373 if (hpage != NULL)
1374 index = PROPSHEET_GetPageIndex(hpage, psInfo);
1375
1376 if (index < 0 || index >= psInfo->nPages)
1377 {
1378 TRACE("Could not find page to select!\n");
1379 return FALSE;
1380 }
1381
1382 hwndPage = psInfo->proppage[index].hwndPage;
1383
1384 /*
1385 * Notify the new page if it's already created.
1386 * If not it will get created and notified in PROPSHEET_ShowPage.
1387 */
1388 if (hwndPage)
1389 {
1390 int result;
1391 hdr.code = PSN_SETACTIVE;
1392
1393 result = SendMessageA(hwndPage, WM_NOTIFY, 0, (LPARAM) &hdr);
1394 /*
1395 * TODO: check return value.
1396 */
1397 }
1398
1399 /*
1400 * Display the new page.
1401 */
1402 PROPSHEET_ShowPage(hwndDlg, index, psInfo);
1403
1404 if (psInfo->proppage[index].hasHelp)
1405 EnableWindow(hwndHelp, TRUE);
1406 else
1407 EnableWindow(hwndHelp, FALSE);
1408
1409 return TRUE;
1410}
1411
1412/******************************************************************************
1413 * PROPSHEET_SetTitleA
1414 */
1415static void PROPSHEET_SetTitleA(HWND hwndDlg, DWORD dwStyle, LPCSTR lpszText)
1416{
1417 PropSheetInfo* psInfo = (PropSheetInfo*) GetPropA(hwndDlg, PropSheetInfoStr);
1418 char szTitle[256];
1419
1420 if (HIWORD(lpszText) == 0) {
1421 if (!LoadStringA(psInfo->ppshheader->hInstance,
1422 LOWORD(lpszText), szTitle, sizeof(szTitle)-1))
1423 return;
1424 lpszText = szTitle;
1425 }
1426 if (dwStyle & PSH_PROPTITLE)
1427 {
1428 char* dest;
1429 int lentitle = strlen(lpszText);
1430 int lenprop = strlen(psInfo->strPropertiesFor);
1431
1432 dest = COMCTL32_Alloc(lentitle + lenprop + 1);
1433 strcpy(dest, psInfo->strPropertiesFor);
1434 strcat(dest, lpszText);
1435
1436 SetWindowTextA(hwndDlg, dest);
1437 COMCTL32_Free(dest);
1438 }
1439 else
1440 SetWindowTextA(hwndDlg, lpszText);
1441}
1442
1443/******************************************************************************
1444 * PROPSHEET_SetFinishTextA
1445 */
1446static void PROPSHEET_SetFinishTextA(HWND hwndDlg, LPCSTR lpszText)
1447{
1448 HWND hwndButton = GetDlgItem(hwndDlg, IDC_FINISH_BUTTON);
1449
1450 /* Set text, show and enable the Finish button */
1451 SetWindowTextA(hwndButton, lpszText);
1452 ShowWindow(hwndButton, SW_SHOW);
1453 EnableWindow(hwndButton, TRUE);
1454
1455 /* Make it default pushbutton */
1456 SendMessageA(hwndDlg, DM_SETDEFID, IDC_FINISH_BUTTON, 0);
1457
1458 /* Hide Back button */
1459 hwndButton = GetDlgItem(hwndDlg, IDC_BACK_BUTTON);
1460 ShowWindow(hwndButton, SW_HIDE);
1461
1462 /* Hide Next button */
1463 hwndButton = GetDlgItem(hwndDlg, IDC_NEXT_BUTTON);
1464 ShowWindow(hwndButton, SW_HIDE);
1465}
1466
1467/******************************************************************************
1468 * PROPSHEET_QuerySiblings
1469 */
1470static LRESULT PROPSHEET_QuerySiblings(HWND hwndDlg,
1471 WPARAM wParam, LPARAM lParam)
1472{
1473 int i = 0;
1474 HWND hwndPage;
1475 LRESULT msgResult = 0;
1476 PropSheetInfo* psInfo = (PropSheetInfo*) GetPropA(hwndDlg,
1477 PropSheetInfoStr);
1478
1479 while ((i < psInfo->nPages) && (msgResult == 0))
1480 {
1481 hwndPage = psInfo->proppage[i].hwndPage;
1482 msgResult = SendMessageA(hwndPage, PSM_QUERYSIBLINGS, wParam, lParam);
1483 i++;
1484 }
1485
1486 return msgResult;
1487}
1488
1489/******************************************************************************
1490 * PROPSHEET_GetPSPPage
1491 */
1492static LPCPROPSHEETPAGEA PROPSHEET_GetPSPPage(const PropSheetInfo * psInfo,
1493 int index)
1494{
1495 BOOL usePSP = psInfo->ppshheader->dwFlags & PSH_PROPSHEETPAGE;
1496 LPCPROPSHEETPAGEA lppsp;
1497 int realIndex = psInfo->proppage[index].index;
1498
1499 if (usePSP)
1500 {
1501 BYTE* pByte;
1502
1503 lppsp = psInfo->ppshheader->u3.ppsp;
1504
1505 pByte = (BYTE*) lppsp;
1506
1507 pByte += (lppsp->dwSize * realIndex);
1508 lppsp = (LPCPROPSHEETPAGEA)pByte;
1509 }
1510 else
1511 lppsp = (LPCPROPSHEETPAGEA) psInfo->ppshheader->u3.phpage[realIndex];
1512
1513 return lppsp;
1514}
1515
1516/******************************************************************************
1517 * PROPSHEET_AddPage
1518 */
1519static BOOL PROPSHEET_AddPage(HWND hwndDlg,
1520 HPROPSHEETPAGE hpage)
1521{
1522 PropSheetInfo * psInfo = (PropSheetInfo*) GetPropA(hwndDlg,
1523 PropSheetInfoStr);
1524 HWND hwndTabControl = GetDlgItem(hwndDlg, IDC_TABCONTROL);
1525 TCITEMA item;
1526 char tabtext[MAX_TABTEXT_LENGTH] = "Tab text";
1527 LPCPROPSHEETPAGEA ppsp = (LPCPROPSHEETPAGEA)hpage;
1528
1529 /*
1530 * Allocate and fill in a new PropPageInfo entry.
1531 */
1532 psInfo->proppage = (PropPageInfo*) COMCTL32_ReAlloc(psInfo->proppage,
1533 sizeof(PropPageInfo) *
1534 (psInfo->nPages + 1));
1535
1536 PROPSHEET_CollectPageInfo(ppsp, psInfo, psInfo->nPages);
1537 psInfo->proppage[psInfo->nPages].index = -1;
1538 psInfo->proppage[psInfo->nPages].hpage = hpage;
1539
1540 /*
1541 * Create the page but don't show it.
1542 */
1543 PROPSHEET_CreatePage(hwndDlg, psInfo->nPages, psInfo, ppsp, FALSE);
1544
1545 /*
1546 * Add a new tab to the tab control.
1547 */
1548 item.mask = TCIF_TEXT;
1549 item.pszText = tabtext;
1550 item.cchTextMax = MAX_TABTEXT_LENGTH;
1551
1552 WideCharToMultiByte(CP_ACP, 0,
1553 (LPCWSTR)psInfo->proppage[psInfo->nPages].pszText,
1554 -1, tabtext, MAX_TABTEXT_LENGTH, NULL, NULL);
1555
1556 SendMessageA(hwndTabControl, TCM_INSERTITEMA, psInfo->nPages + 1,
1557 (LPARAM)&item);
1558
1559 psInfo->nPages++;
1560
1561 return TRUE;
1562}
1563
1564/******************************************************************************
1565 * PROPSHEET_RemovePage
1566 */
1567static BOOL PROPSHEET_RemovePage(HWND hwndDlg,
1568 int index,
1569 HPROPSHEETPAGE hpage)
1570{
1571 PropSheetInfo * psInfo = (PropSheetInfo*) GetPropA(hwndDlg,
1572 PropSheetInfoStr);
1573 HWND hwndTabControl = GetDlgItem(hwndDlg, IDC_TABCONTROL);
1574 PropPageInfo* oldPages;
1575
1576 if (!psInfo) {
1577// FIXME("No psInfo for propertysheet at windows 0x%04x, returning FALSE...\n", hwndDlg);
1578 return FALSE;
1579 }
1580 oldPages = psInfo->proppage;
1581 /*
1582 * hpage takes precedence over index.
1583 */
1584 if (hpage != 0)
1585 {
1586 index = PROPSHEET_GetPageIndex(hpage, psInfo);
1587 }
1588
1589 /* Make shure that index is within range */
1590 if (index < 0 || index >= psInfo->nPages)
1591 {
1592// TRACE("Could not find page to remove!\n");
1593 return FALSE;
1594 }
1595
1596// TRACE("total pages %d removing page %d active page %d\n",
1597// psInfo->nPages, index, psInfo->active_page);
1598 /*
1599 * Check if we're removing the active page.
1600 */
1601 if (index == psInfo->active_page)
1602 {
1603 if (psInfo->nPages > 1)
1604 {
1605 if (index > 0)
1606 {
1607 /* activate previous page */
1608 PROPSHEET_ShowPage(hwndDlg, index - 1, psInfo);
1609 }
1610 else
1611 {
1612 /* activate the next page */
1613 PROPSHEET_ShowPage(hwndDlg, index + 1, psInfo);
1614 }
1615 }
1616 else
1617 {
1618// TRACE("Removing the only page, close the dialog!\n");
1619
1620 if (psInfo->isModeless)
1621 psInfo->active_page = -1;
1622 else
1623 EndDialog(hwndDlg, FALSE);
1624
1625 return TRUE;
1626 }
1627 }
1628
1629 if (index < psInfo->active_page)
1630 psInfo->active_page--;
1631
1632 /* Destroy page dialog window.
1633 * If it's last page in modal dialog, it has been destroyed by EndDialog
1634 */
1635 if (psInfo->isModeless || psInfo->nPages > 1)
1636 DestroyWindow(psInfo->proppage[index].hwndPage);
1637
1638 /* Remove the tab */
1639 SendMessageA(hwndTabControl, TCM_DELETEITEM, index, 0);
1640
1641 psInfo->nPages--;
1642 psInfo->proppage = COMCTL32_Alloc(sizeof(PropPageInfo) * psInfo->nPages);
1643
1644 if (index > 0)
1645 memcpy(&psInfo->proppage[0], &oldPages[0], index * sizeof(PropPageInfo));
1646
1647 if (index < psInfo->nPages)
1648 memcpy(&psInfo->proppage[index], &oldPages[index + 1],
1649 (psInfo->nPages - index) * sizeof(PropPageInfo));
1650
1651 COMCTL32_Free(oldPages);
1652
1653 return FALSE;
1654}
1655
1656/******************************************************************************
1657 * PROPSHEET_SetWizButtons
1658 *
1659 * This code will work if (and assumes that) the Next button is on top of the
1660 * Finish button. ie. Finish comes after Next in the Z order.
1661 * This means make sure the dialog template reflects this.
1662 *
1663 */
1664static void PROPSHEET_SetWizButtons(HWND hwndDlg, DWORD dwFlags)
1665{
1666 HWND hwndButton;
1667
1668// TRACE("%ld\n", dwFlags);
1669
1670 if (dwFlags & PSWIZB_BACK)
1671 {
1672 hwndButton = GetDlgItem(hwndDlg, IDC_BACK_BUTTON);
1673 EnableWindow(hwndButton, TRUE);
1674 }
1675
1676 if (dwFlags & PSWIZB_NEXT)
1677 {
1678 /* Hide the Finish button */
1679 hwndButton = GetDlgItem(hwndDlg, IDC_FINISH_BUTTON);
1680 ShowWindow(hwndButton, SW_HIDE);
1681
1682 /* Show and enable the Next button */
1683 hwndButton = GetDlgItem(hwndDlg, IDC_NEXT_BUTTON);
1684
1685 ShowWindow(hwndButton, SW_SHOW);
1686 EnableWindow(hwndButton, TRUE);
1687
1688 /* Set the Next button as the default pushbutton */
1689 SendMessageA(hwndDlg, DM_SETDEFID, IDC_NEXT_BUTTON, 0);
1690 }
1691
1692 if ((dwFlags & PSWIZB_FINISH) || (dwFlags & PSWIZB_DISABLEDFINISH))
1693 {
1694 /* Hide the Next button */
1695 hwndButton = GetDlgItem(hwndDlg, IDC_NEXT_BUTTON);
1696 ShowWindow(hwndButton, SW_HIDE);
1697
1698 /* Show the Finish button */
1699 hwndButton = GetDlgItem(hwndDlg, IDC_FINISH_BUTTON);
1700 ShowWindow(hwndButton, SW_SHOW);
1701
1702 if (dwFlags & PSWIZB_FINISH)
1703 EnableWindow(hwndButton, TRUE);
1704 else
1705 EnableWindow(hwndButton, FALSE);
1706
1707 /* Set the Finish button as the default pushbutton */
1708 SendMessageA(hwndDlg, DM_SETDEFID, IDC_FINISH_BUTTON, 0);
1709 }
1710}
1711
1712/******************************************************************************
1713 * PROPSHEET_GetPageIndex
1714 *
1715 * Given a HPROPSHEETPAGE, returns the index of the corresponding page from
1716 * the array of PropPageInfo.
1717 */
1718static int PROPSHEET_GetPageIndex(HPROPSHEETPAGE hpage, PropSheetInfo* psInfo)
1719{
1720 BOOL found = FALSE;
1721 int index = 0;
1722
1723 while ((index < psInfo->nPages) && (found == FALSE))
1724 {
1725 if (psInfo->proppage[index].hpage == hpage)
1726 found = TRUE;
1727 else
1728 index++;
1729 }
1730
1731 if (found == FALSE)
1732 index = -1;
1733
1734 return index;
1735}
1736
1737/******************************************************************************
1738 * PROPSHEET_CleanUp
1739 */
1740static void PROPSHEET_CleanUp(HWND hwndDlg)
1741{
1742 PropSheetInfo* psInfo = (PropSheetInfo*) RemovePropA(hwndDlg,
1743 PropSheetInfoStr);
1744 COMCTL32_Free(psInfo->proppage);
1745 COMCTL32_Free(psInfo->strPropertiesFor);
1746 ImageList_Destroy(psInfo->hImageList);
1747
1748 GlobalFree((HGLOBAL)psInfo);
1749}
1750
1751/******************************************************************************
1752 * PropertySheetA (COMCTL32.84)(COMCTL32.83)
1753 */
1754INT WINAPI PropertySheetA(LPCPROPSHEETHEADERA lppsh)
1755{
1756 int bRet = 0;
1757 PropSheetInfo* psInfo = (PropSheetInfo*) GlobalAlloc(GPTR,
1758 sizeof(PropSheetInfo));
1759 LPCPROPSHEETPAGEA lppsp;
1760 int i;
1761
1762 PROPSHEET_CollectSheetInfo(lppsh, psInfo);
1763
1764 psInfo->proppage = (PropPageInfo*) COMCTL32_Alloc(sizeof(PropPageInfo) *
1765 lppsh->nPages);
1766
1767 for (i = 0; i < lppsh->nPages; i++)
1768 {
1769 psInfo->proppage[i].index = i;
1770 if (!(lppsh->dwFlags & PSH_PROPSHEETPAGE))
1771 psInfo->proppage[i].hpage = psInfo->ppshheader->u3.phpage[i];
1772 lppsp = PROPSHEET_GetPSPPage(psInfo, i);
1773 PROPSHEET_CollectPageInfo(lppsp, psInfo, i);
1774 }
1775
1776 bRet = PROPSHEET_CreateDialog(psInfo);
1777
1778 return bRet;
1779}
1780
1781/******************************************************************************
1782 * PropertySheet32W (COMCTL32.85)
1783 */
1784INT WINAPI PropertySheetW(LPCPROPSHEETHEADERW propertySheetHeader)
1785{
1786// FIXME(propsheet, "(%p): stub\n", propertySheetHeader);
1787
1788 return -1;
1789}
1790
1791/******************************************************************************
1792 * CreatePropertySheetPageA (COMCTL32.19)(COMCTL32.18)
1793 */
1794HPROPSHEETPAGE WINAPI CreatePropertySheetPageA(
1795 LPCPROPSHEETPAGEA lpPropSheetPage)
1796{
1797 PROPSHEETPAGEA* ppsp = COMCTL32_Alloc(sizeof(PROPSHEETPAGEA));
1798
1799 *ppsp = *lpPropSheetPage;
1800
1801 return (HPROPSHEETPAGE)ppsp;
1802}
1803
1804/******************************************************************************
1805 * CreatePropertySheetPageW (COMCTL32.20)
1806 */
1807HPROPSHEETPAGE WINAPI CreatePropertySheetPageW(LPCPROPSHEETPAGEW lpPropSheetPage)
1808{
1809// FIXME(propsheet, "(%p): stub\n", lpPropSheetPage);
1810
1811 return 0;
1812}
1813
1814/******************************************************************************
1815 * DestroyPropertySheetPage (COMCTL32.24)
1816 */
1817BOOL WINAPI DestroyPropertySheetPage(HPROPSHEETPAGE hPropPage)
1818{
1819 COMCTL32_Free(hPropPage);
1820
1821 return TRUE;
1822}
1823
1824/******************************************************************************
1825 * PROPSHEET_DialogProc
1826 */
1827BOOL WINAPI
1828PROPSHEET_DialogProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
1829{
1830 switch (uMsg)
1831 {
1832 case WM_INITDIALOG:
1833 {
1834 PropSheetInfo* psInfo = (PropSheetInfo*) lParam;
1835 char* strCaption = (char*)COMCTL32_Alloc(MAX_CAPTION_LENGTH);
1836 HWND hwndTabCtrl = GetDlgItem(hwnd, IDC_TABCONTROL);
1837 LPCPROPSHEETPAGEA ppshpage;
1838
1839 SetPropA(hwnd, PropSheetInfoStr, (HANDLE)psInfo);
1840
1841 /*
1842 * Small icon in the title bar.
1843 */
1844 if ((psInfo->ppshheader->dwFlags & PSH_USEICONID) ||
1845 (psInfo->ppshheader->dwFlags & PSH_USEHICON))
1846 {
1847 HICON hIcon;
1848 int icon_cx = GetSystemMetrics(SM_CXSMICON);
1849 int icon_cy = GetSystemMetrics(SM_CYSMICON);
1850
1851 if (psInfo->ppshheader->dwFlags & PSH_USEICONID)
1852 hIcon = LoadImageA(psInfo->ppshheader->hInstance,
1853 psInfo->ppshheader->u1.pszIcon,
1854 IMAGE_ICON,
1855 icon_cx, icon_cy,
1856 LR_DEFAULTCOLOR);
1857 else
1858 hIcon = psInfo->ppshheader->u1.hIcon;
1859
1860 SendMessageA(hwnd, WM_SETICON, 0, hIcon);
1861 }
1862
1863 if (psInfo->ppshheader->dwFlags & PSH_USEHICON)
1864 SendMessageA(hwnd, WM_SETICON, 0, psInfo->ppshheader->u1.hIcon);
1865
1866 psInfo->strPropertiesFor = strCaption;
1867
1868 GetWindowTextA(hwnd, psInfo->strPropertiesFor, MAX_CAPTION_LENGTH);
1869
1870 PROPSHEET_CreateTabControl(hwnd, psInfo);
1871
1872 if (psInfo->ppshheader->dwFlags & PSH_WIZARD)
1873 {
1874 HWND hwndBack = GetDlgItem(hwnd, IDC_BACK_BUTTON);
1875
1876 if (PROPSHEET_IsTooSmallWizard(hwnd, psInfo))
1877 {
1878 PROPSHEET_AdjustSizeWizard(hwnd, psInfo);
1879 PROPSHEET_AdjustButtonsWizard(hwnd, psInfo);
1880 }
1881
1882 /* Disable Back button if we start at page 0 */
1883 if (psInfo->active_page == 0)
1884 EnableWindow(hwndBack, FALSE);
1885 }
1886 else
1887 {
1888 if (PROPSHEET_IsTooSmall(hwnd, psInfo))
1889 {
1890 PROPSHEET_AdjustSize(hwnd, psInfo);
1891 PROPSHEET_AdjustButtons(hwnd, psInfo);
1892 }
1893 }
1894
1895 if (psInfo->useCallback)
1896 (*(psInfo->ppshheader->pfnCallback))(hwnd,
1897 PSCB_INITIALIZED, (LPARAM)0);
1898
1899 ppshpage = PROPSHEET_GetPSPPage(psInfo, psInfo->active_page);
1900 PROPSHEET_CreatePage(hwnd, psInfo->active_page, psInfo, ppshpage, TRUE);
1901
1902 if (!(psInfo->ppshheader->dwFlags & PSH_WIZARD))
1903 SendMessageA(hwndTabCtrl, TCM_SETCURSEL, psInfo->active_page, 0);
1904
1905 if (!HIWORD(psInfo->ppshheader->pszCaption) &&
1906 psInfo->ppshheader->hInstance)
1907 {
1908 char szText[256];
1909
1910 if (LoadStringA(psInfo->ppshheader->hInstance,
1911 (UINT)psInfo->ppshheader->pszCaption, szText, 255))
1912 PROPSHEET_SetTitleA(hwnd, psInfo->ppshheader->dwFlags, szText);
1913 }
1914 else
1915 {
1916 PROPSHEET_SetTitleA(hwnd, psInfo->ppshheader->dwFlags,
1917 psInfo->ppshheader->pszCaption);
1918 }
1919
1920 return TRUE;
1921 }
1922
1923 case WM_DESTROY:
1924 PROPSHEET_CleanUp(hwnd);
1925 return TRUE;
1926
1927 case WM_CLOSE:
1928 PROPSHEET_Cancel(hwnd);
1929 return TRUE;
1930
1931 case WM_COMMAND:
1932 {
1933 WORD wID = LOWORD(wParam);
1934
1935 switch (wID)
1936 {
1937 case IDOK:
1938 case IDC_APPLY_BUTTON:
1939 {
1940 HWND hwndApplyBtn = GetDlgItem(hwnd, IDC_APPLY_BUTTON);
1941
1942 if (PROPSHEET_Apply(hwnd) == FALSE)
1943 break;
1944
1945 EnableWindow(hwndApplyBtn, FALSE);
1946
1947 if (wID == IDOK)
1948 {
1949 PropSheetInfo* psInfo = (PropSheetInfo*) GetPropA(hwnd,
1950 PropSheetInfoStr);
1951 int result = TRUE;
1952
1953 if (psInfo->restartWindows)
1954 result = ID_PSRESTARTWINDOWS;
1955
1956 /* reboot system takes precedence over restart windows */
1957 if (psInfo->rebootSystem)
1958 result = ID_PSREBOOTSYSTEM;
1959
1960 if (psInfo->isModeless)
1961 psInfo->active_page = -1;
1962 else
1963 EndDialog(hwnd, result);
1964 }
1965
1966 break;
1967 }
1968
1969 case IDC_BACK_BUTTON:
1970 PROPSHEET_Back(hwnd);
1971 break;
1972
1973 case IDC_NEXT_BUTTON:
1974 PROPSHEET_Next(hwnd);
1975 break;
1976
1977 case IDC_FINISH_BUTTON:
1978 PROPSHEET_Finish(hwnd);
1979 break;
1980
1981 case IDCANCEL:
1982 PROPSHEET_Cancel(hwnd);
1983 break;
1984
1985 case IDHELP:
1986 PROPSHEET_Help(hwnd);
1987 break;
1988 }
1989
1990 return TRUE;
1991 }
1992
1993 case WM_NOTIFY:
1994 {
1995 NMHDR* pnmh = (LPNMHDR) lParam;
1996
1997 if (pnmh->code == TCN_SELCHANGE)
1998 {
1999 int index = SendMessageA(pnmh->hwndFrom, TCM_GETCURSEL, 0, 0);
2000 PROPSHEET_SetCurSel(hwnd, index, 0);
2001 }
2002
2003 if(pnmh->code == TCN_SELCHANGING)
2004 {
2005 BOOL bRet = PROPSHEET_CanSetCurSel(hwnd);
2006 SetWindowLongA(hwnd, DWL_MSGRESULT, !bRet);
2007 return TRUE;
2008 }
2009
2010
2011 return 0;
2012 }
2013
2014 case PSM_GETCURRENTPAGEHWND:
2015 {
2016 PropSheetInfo* psInfo = (PropSheetInfo*) GetPropA(hwnd,
2017 PropSheetInfoStr);
2018 HWND hwndPage = 0;
2019
2020 if (psInfo->active_page != -1)
2021 hwndPage = psInfo->proppage[psInfo->active_page].hwndPage;
2022
2023 SetWindowLongA(hwnd, DWL_MSGRESULT, hwndPage);
2024
2025 return TRUE;
2026 }
2027
2028 case PSM_CHANGED:
2029 PROPSHEET_Changed(hwnd, (HWND)wParam);
2030 return TRUE;
2031
2032 case PSM_UNCHANGED:
2033 PROPSHEET_UnChanged(hwnd, (HWND)wParam);
2034 return TRUE;
2035
2036 case PSM_GETTABCONTROL:
2037 {
2038 HWND hwndTabCtrl = GetDlgItem(hwnd, IDC_TABCONTROL);
2039
2040 SetWindowLongA(hwnd, DWL_MSGRESULT, hwndTabCtrl);
2041
2042 return TRUE;
2043 }
2044
2045 case PSM_SETCURSEL:
2046 {
2047 BOOL msgResult;
2048
2049 msgResult = PROPSHEET_CanSetCurSel(hwnd);
2050 if(msgResult != FALSE)
2051 {
2052 msgResult = PROPSHEET_SetCurSel(hwnd,
2053 (int)wParam,
2054 (HPROPSHEETPAGE)lParam);
2055 }
2056
2057 SetWindowLongA(hwnd, DWL_MSGRESULT, msgResult);
2058
2059 return TRUE;
2060 }
2061
2062 case PSM_CANCELTOCLOSE:
2063 {
2064 HWND hwndOK = GetDlgItem(hwnd, IDOK);
2065 HWND hwndCancel = GetDlgItem(hwnd, IDCANCEL);
2066
2067 EnableWindow(hwndCancel, FALSE);
2068 SetWindowTextA(hwndOK, "Close"); /* FIXME: hardcoded string */
2069
2070 return TRUE;
2071 }
2072
2073 case PSM_RESTARTWINDOWS:
2074 {
2075 PropSheetInfo* psInfo = (PropSheetInfo*) GetPropA(hwnd,
2076 PropSheetInfoStr);
2077
2078 psInfo->restartWindows = TRUE;
2079 return TRUE;
2080 }
2081
2082 case PSM_REBOOTSYSTEM:
2083 {
2084 PropSheetInfo* psInfo = (PropSheetInfo*) GetPropA(hwnd,
2085 PropSheetInfoStr);
2086
2087 psInfo->rebootSystem = TRUE;
2088 return TRUE;
2089 }
2090
2091 case PSM_SETTITLEA:
2092 PROPSHEET_SetTitleA(hwnd, (DWORD) wParam, (LPCSTR) lParam);
2093 return TRUE;
2094
2095 case PSM_APPLY:
2096 {
2097 BOOL msgResult = PROPSHEET_Apply(hwnd);
2098
2099 SetWindowLongA(hwnd, DWL_MSGRESULT, msgResult);
2100
2101 return TRUE;
2102 }
2103
2104 case PSM_QUERYSIBLINGS:
2105 {
2106 LRESULT msgResult = PROPSHEET_QuerySiblings(hwnd, wParam, lParam);
2107
2108 SetWindowLongA(hwnd, DWL_MSGRESULT, msgResult);
2109
2110 return TRUE;
2111 }
2112
2113 case PSM_ADDPAGE:
2114 {
2115 /*
2116 * Note: MSVC++ 6.0 documentation says that PSM_ADDPAGE does not have
2117 * a return value. This is not true. PSM_ADDPAGE returns TRUE
2118 * on success or FALSE otherwise, as specified on MSDN Online.
2119 * Also see the MFC code for
2120 * CPropertySheet::AddPage(CPropertyPage* pPage).
2121 */
2122
2123 BOOL msgResult = PROPSHEET_AddPage(hwnd, (HPROPSHEETPAGE)lParam);
2124
2125 SetWindowLongA(hwnd, DWL_MSGRESULT, msgResult);
2126
2127 return TRUE;
2128 }
2129
2130 case PSM_REMOVEPAGE:
2131 PROPSHEET_RemovePage(hwnd, (int)wParam, (HPROPSHEETPAGE)lParam);
2132 return TRUE;
2133
2134 case PSM_ISDIALOGMESSAGE:
2135 {
2136 FIXME("Unimplemented msg PSM_ISDIALOGMESSAGE\n");
2137 return 0;
2138 }
2139
2140 case PSM_PRESSBUTTON:
2141 PROPSHEET_PressButton(hwnd, (int)wParam);
2142 return TRUE;
2143
2144 case PSM_SETFINISHTEXTA:
2145 PROPSHEET_SetFinishTextA(hwnd, (LPCSTR) lParam);
2146 return TRUE;
2147
2148 case PSM_SETWIZBUTTONS:
2149 PROPSHEET_SetWizButtons(hwnd, (DWORD)lParam);
2150 return TRUE;
2151
2152 case PSM_SETTITLEW:
2153 FIXME("Unimplemented msg PSM_SETTITLE32W\n");
2154 return 0;
2155 case PSM_SETCURSELID:
2156 FIXME("Unimplemented msg PSM_SETCURSELID\n");
2157 return 0;
2158 case PSM_SETFINISHTEXTW:
2159 FIXME("Unimplemented msg PSM_SETFINISHTEXT32W\n");
2160 return 0;
2161
2162 default:
2163 return FALSE;
2164 }
2165}
2166
Note: See TracBrowser for help on using the repository browser.