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

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

added HEAP_strdupAtoW/WtoA calls that were commented out

File size: 54.8 KB
Line 
1/* $Id: propsheet.c,v 1.13 1999-11-14 10:58:38 achimha Exp $ */
2/*
3 * Property Sheets
4 *
5 * Copyright 1998 Francis Beaudet
6 * Copyright 1999 Thuy Nguyen
7 * Copyright 1999 Achim Hasenmueller
8 * Copyright 1999 Christoph Bratschi
9 *
10 * TODO:
11 * - Tab order
12 * - Unicode property sheets
13 */
14
15/* WINE 991031 level */
16
17/* CB: Odin problems:
18 - trap in PROPSHEET_DialogProc (tab control creation)
19*/
20
21#include <string.h>
22#include "winbase.h"
23#include "commctrl.h"
24#include "prsht.h"
25#include "winnls.h"
26#include "comctl32.h"
27
28
29/******************************************************************************
30 * Data structures
31 */
32typedef struct
33{
34 WORD dlgVer;
35 WORD signature;
36 DWORD helpID;
37 DWORD exStyle;
38 DWORD style;
39} MyDLGTEMPLATEEX;
40
41typedef struct tagPropPageInfo
42{
43 int index; /* corresponds to the index in ppshheader->ppsp */
44 HPROPSHEETPAGE hpage; /* to keep track of pages not passed to PropertySheet */
45 HWND hwndPage;
46 BOOL isDirty;
47 LPCWSTR pszText;
48 BOOL hasHelp;
49 BOOL useCallback;
50} PropPageInfo;
51
52typedef struct tagPropSheetInfo
53{
54 LPSTR strPropertiesFor;
55 int nPages;
56 int active_page;
57 LPCPROPSHEETHEADERA ppshheader;
58 BOOL isModeless;
59 BOOL hasHelp;
60 BOOL hasApply;
61 BOOL useCallback;
62 BOOL restartWindows;
63 BOOL rebootSystem;
64 PropPageInfo* proppage;
65 int x;
66 int y;
67 int width;
68 int height;
69 HIMAGELIST hImageList;
70} PropSheetInfo;
71
72typedef struct
73{
74 int x;
75 int y;
76} PADDING_INFO;
77
78/******************************************************************************
79 * Defines and global variables
80 */
81
82const char * PropSheetInfoStr = "PropertySheetInfo";
83
84#define MAX_CAPTION_LENGTH 255
85#define MAX_TABTEXT_LENGTH 255
86
87
88/******************************************************************************
89 * Prototypes
90 */
91static BOOL PROPSHEET_CreateDialog(PropSheetInfo* psInfo);
92static BOOL PROPSHEET_IsTooSmall(HWND hwndDlg, PropSheetInfo* psInfo);
93static BOOL PROPSHEET_AdjustSize(HWND hwndDlg, PropSheetInfo* psInfo);
94static BOOL PROPSHEET_AdjustButtons(HWND hwndParent, PropSheetInfo* psInfo);
95static BOOL PROPSHEET_CollectSheetInfo(LPCPROPSHEETHEADERA lppsh,
96 PropSheetInfo * psInfo);
97static BOOL PROPSHEET_CollectPageInfo(LPCPROPSHEETPAGEA lppsp,
98 PropSheetInfo * psInfo,
99 int index);
100static BOOL PROPSHEET_CreateTabControl(HWND hwndParent,
101 PropSheetInfo * psInfo);
102static int PROPSHEET_CreatePage(HWND hwndParent, int index,
103 const PropSheetInfo * psInfo,
104 LPCPROPSHEETPAGEA ppshpage,
105 BOOL showPage);
106static BOOL PROPSHEET_ShowPage(HWND hwndDlg, int index, PropSheetInfo * psInfo);
107static PADDING_INFO PROPSHEET_GetPaddingInfo(HWND hwndDlg);
108static BOOL PROPSHEET_Back(HWND hwndDlg);
109static BOOL PROPSHEET_Next(HWND hwndDlg);
110static BOOL PROPSHEET_Finish(HWND hwndDlg);
111static BOOL PROPSHEET_Apply(HWND hwndDlg);
112static void PROPSHEET_Cancel(HWND hwndDlg);
113static void PROPSHEET_Help(HWND hwndDlg);
114static void PROPSHEET_Changed(HWND hwndDlg, HWND hwndDirtyPage);
115static void PROPSHEET_UnChanged(HWND hwndDlg, HWND hwndCleanPage);
116static void PROPSHEET_PressButton(HWND hwndDlg, int buttonID);
117static void PROPSHEET_SetFinishTextA(HWND hwndDlg, LPCSTR lpszText);
118static void PROPSHEET_SetTitleA(HWND hwndDlg, DWORD dwStyle, LPCSTR lpszText);
119static BOOL PROPSHEET_CanSetCurSel(HWND hwndDlg);
120static BOOL PROPSHEET_SetCurSel(HWND hwndDlg,
121 int index,
122 HPROPSHEETPAGE hpage);
123static LRESULT PROPSHEET_QuerySiblings(HWND hwndDlg,
124 WPARAM wParam, LPARAM lParam);
125static LPCPROPSHEETPAGEA PROPSHEET_GetPSPPage(const PropSheetInfo * psInfo,
126 int index);
127static BOOL PROPSHEET_AddPage(HWND hwndDlg,
128 HPROPSHEETPAGE hpage);
129
130static BOOL PROPSHEET_RemovePage(HWND hwndDlg,
131 int index,
132 HPROPSHEETPAGE hpage);
133static void PROPSHEET_CleanUp();
134static int PROPSHEET_GetPageIndex(HPROPSHEETPAGE hpage, PropSheetInfo* psInfo);
135static void PROPSHEET_SetWizButtons(HWND hwndDlg, DWORD dwFlags);
136static PADDING_INFO PROPSHEET_GetPaddingInfoWizard(HWND hwndDlg);
137
138BOOL WINAPI
139PROPSHEET_DialogProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
140
141
142/******************************************************************************
143 * PROPSHEET_CollectSheetInfo
144 *
145 * Collect relevant data.
146 */
147static BOOL PROPSHEET_CollectSheetInfo(LPCPROPSHEETHEADERA lppsh,
148 PropSheetInfo * psInfo)
149{
150 DWORD dwFlags = lppsh->dwFlags;
151
152 psInfo->hasHelp = dwFlags & PSH_HASHELP;
153 psInfo->hasApply = !(dwFlags & PSH_NOAPPLYNOW);
154 psInfo->useCallback = dwFlags & PSH_USECALLBACK;
155 psInfo->isModeless = dwFlags & PSH_MODELESS;
156 psInfo->ppshheader = lppsh;
157 psInfo->nPages = lppsh->nPages;
158
159 if (dwFlags & PSH_USEPSTARTPAGE)
160 {
161// TRACE(propsheet, "PSH_USEPSTARTPAGE is on");
162 psInfo->active_page = 0;
163 }
164 else
165 psInfo->active_page = lppsh->u2.nStartPage;
166
167 psInfo->restartWindows = FALSE;
168 psInfo->rebootSystem = FALSE;
169 psInfo->hImageList = 0;
170
171 return TRUE;
172}
173
174/******************************************************************************
175 * PROPSHEET_CollectPageInfo
176 *
177 * Collect property sheet data.
178 * With code taken from DIALOG_ParseTemplate32.
179 */
180BOOL PROPSHEET_CollectPageInfo(LPCPROPSHEETPAGEA lppsp,
181 PropSheetInfo * psInfo,
182 int index)
183{
184 DLGTEMPLATE* pTemplate;
185 const WORD* p;
186 DWORD dwFlags;
187 int width, height;
188
189 if (psInfo->ppshheader->dwFlags & PSH_PROPSHEETPAGE)
190 psInfo->proppage[index].hpage = 0;
191 psInfo->proppage[index].hwndPage = 0;
192 psInfo->proppage[index].isDirty = FALSE;
193
194 /*
195 * Process property page flags.
196 */
197 dwFlags = lppsp->dwFlags;
198 psInfo->proppage[index].useCallback = dwFlags & PSP_USECALLBACK;
199 psInfo->proppage[index].hasHelp = dwFlags & PSP_HASHELP;
200
201 /* as soon as we have a page with the help flag, set the sheet flag on */
202 if (psInfo->proppage[index].hasHelp)
203 psInfo->hasHelp = TRUE;
204
205 /*
206 * Process page template.
207 */
208 if (dwFlags & PSP_DLGINDIRECT)
209 pTemplate = (DLGTEMPLATE*)lppsp->u1.pResource;
210 else
211 {
212 HRSRC hResource = FindResourceA(lppsp->hInstance,
213 lppsp->u1.pszTemplate,
214 RT_DIALOGA);
215 HGLOBAL hTemplate = LoadResource(lppsp->hInstance,
216 hResource);
217 pTemplate = (LPDLGTEMPLATEA)LockResource(hTemplate);
218 }
219
220 /*
221 * Extract the size of the page and the caption.
222 */
223 p = (const WORD *)pTemplate;
224
225 if (((MyDLGTEMPLATEEX*)pTemplate)->signature == 0xFFFF)
226 {
227 /* DIALOGEX template */
228
229 p++; /* dlgVer */
230 p++; /* signature */
231 p += 2; /* help ID */
232 p += 2; /* ext style */
233 p += 2; /* style */
234 }
235 else
236 {
237 /* DIALOG template */
238
239 p += 2; /* style */
240 p += 2; /* ext style */
241 }
242
243 p++; /* nb items */
244 p++; /* x */
245 p++; /* y */
246 width = (WORD)*p; p++;
247 height = (WORD)*p; p++;
248
249 /* remember the largest width and height */
250 if (width > psInfo->width)
251 psInfo->width = width;
252
253 if (height > psInfo->height)
254 psInfo->height = height;
255
256 /* menu */
257 switch ((WORD)*p)
258 {
259 case 0x0000:
260 p++;
261 break;
262 case 0xffff:
263 p += 2;
264 break;
265 default:
266 p += lstrlenW( (LPCWSTR)p ) + 1;
267 break;
268 }
269
270 /* class */
271 switch ((WORD)*p)
272 {
273 case 0x0000:
274 p++;
275 break;
276 case 0xffff:
277 p += 2;
278 break;
279 default:
280 p += lstrlenW( (LPCWSTR)p ) + 1;
281 break;
282 }
283
284 /* Extract the caption */
285 psInfo->proppage[index].pszText = (LPCWSTR)p;
286// TRACE("Tab %d %s\n",index,debugstr_w((LPCWSTR)p));
287 p += lstrlenW((LPCWSTR)p) + 1;
288
289 if (dwFlags & PSP_USETITLE)
290 {
291 if ( !HIWORD( lppsp->pszTitle ) )
292 {
293 char szTitle[256];
294
295 if ( !LoadStringA( lppsp->hInstance, (UINT) lppsp->pszTitle, szTitle, 256 ) )
296 return FALSE;
297
298 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.code = PSN_SETACTIVE;
966
967 /*
968 * Send the notification before showing the page.
969 */
970 SendMessageA(hwndPage, WM_NOTIFY, 0, (LPARAM) &hdr);
971
972 ShowWindow(hwndPage, SW_SHOW);
973 }
974 else
975 ShowWindow(hwndPage, SW_HIDE);
976
977 return TRUE;
978}
979
980/******************************************************************************
981 * PROPSHEET_ShowPage
982 *
983 * Displays or creates the specified page.
984 */
985static BOOL PROPSHEET_ShowPage(HWND hwndDlg, int index, PropSheetInfo * psInfo)
986{
987 if (index == psInfo->active_page)
988 return TRUE;
989
990 ShowWindow(psInfo->proppage[psInfo->active_page].hwndPage, SW_HIDE);
991
992 if (psInfo->proppage[index].hwndPage != 0)
993 ShowWindow(psInfo->proppage[index].hwndPage, SW_SHOW);
994 else
995 {
996 LPCPROPSHEETPAGEA ppshpage = PROPSHEET_GetPSPPage(psInfo, index);
997 PROPSHEET_CreatePage(hwndDlg, index, psInfo, ppshpage, TRUE);
998 }
999
1000 psInfo->active_page = index;
1001
1002 return TRUE;
1003}
1004
1005/******************************************************************************
1006 * PROPSHEET_Back
1007 */
1008static BOOL PROPSHEET_Back(HWND hwndDlg)
1009{
1010 BOOL res;
1011 NMHDR hdr;
1012 HWND hwndPage;
1013 HWND hwndBack = GetDlgItem(hwndDlg, IDC_BACK_BUTTON);
1014 PropSheetInfo* psInfo = (PropSheetInfo*) GetPropA(hwndDlg,
1015 PropSheetInfoStr);
1016
1017 hdr.code = PSN_WIZBACK;
1018
1019 hwndPage = psInfo->proppage[psInfo->active_page].hwndPage;
1020
1021 if (SendMessageA(hwndPage, WM_NOTIFY, 0, (LPARAM) &hdr) == -1)
1022 return FALSE;
1023
1024 res = PROPSHEET_SetCurSel(hwndDlg, psInfo->active_page - 1, 0);
1025
1026 /* if we went to page 0, disable Back button */
1027 if (res && (psInfo->active_page == 0))
1028 EnableWindow(hwndBack, FALSE);
1029
1030 return TRUE;
1031}
1032
1033/******************************************************************************
1034 * PROPSHEET_Next
1035 */
1036static BOOL PROPSHEET_Next(HWND hwndDlg)
1037{
1038 NMHDR hdr;
1039 HWND hwndPage;
1040 LRESULT msgResult = 0;
1041 PropSheetInfo* psInfo = (PropSheetInfo*) GetPropA(hwndDlg,
1042 PropSheetInfoStr);
1043
1044 hdr.hwndFrom = hwndDlg;
1045 hdr.code = PSN_WIZNEXT;
1046
1047 hwndPage = psInfo->proppage[psInfo->active_page].hwndPage;
1048
1049 msgResult = SendMessageA(hwndPage, WM_NOTIFY, 0, (LPARAM) &hdr);
1050
1051// TRACE("msg result %ld\n", msgResult);
1052
1053 if (msgResult == -1)
1054 return FALSE;
1055
1056 if(PROPSHEET_CanSetCurSel(hwndDlg) != FALSE)
1057 {
1058 PROPSHEET_SetCurSel(hwndDlg, psInfo->active_page + 1, 0);
1059 }
1060
1061 return TRUE;
1062}
1063
1064/******************************************************************************
1065 * PROPSHEET_Finish
1066 */
1067static BOOL PROPSHEET_Finish(HWND hwndDlg)
1068{
1069 NMHDR hdr;
1070 HWND hwndPage;
1071 LRESULT msgResult = 0;
1072 PropSheetInfo* psInfo = (PropSheetInfo*) GetPropA(hwndDlg,
1073 PropSheetInfoStr);
1074
1075 hdr.hwndFrom = hwndDlg;
1076 hdr.code = PSN_WIZFINISH;
1077
1078 hwndPage = psInfo->proppage[psInfo->active_page].hwndPage;
1079
1080 msgResult = SendMessageA(hwndPage, WM_NOTIFY, 0, (LPARAM) &hdr);
1081
1082// TRACE("msg result %ld\n", msgResult);
1083
1084 if (msgResult != 0)
1085 return FALSE;
1086
1087 if (psInfo->isModeless)
1088 psInfo->active_page = -1;
1089 else
1090 EndDialog(hwndDlg, TRUE);
1091
1092 return TRUE;
1093}
1094
1095/******************************************************************************
1096 * PROPSHEET_Apply
1097 */
1098static BOOL PROPSHEET_Apply(HWND hwndDlg)
1099{
1100 int i;
1101 NMHDR hdr;
1102 HWND hwndPage;
1103 LRESULT msgResult;
1104 PropSheetInfo* psInfo = (PropSheetInfo*) GetPropA(hwndDlg,
1105 PropSheetInfoStr);
1106
1107 hdr.hwndFrom = hwndDlg;
1108
1109 /*
1110 * Send PSN_KILLACTIVE to the current page.
1111 */
1112 hdr.code = PSN_KILLACTIVE;
1113
1114 hwndPage = psInfo->proppage[psInfo->active_page].hwndPage;
1115
1116 if (SendMessageA(hwndPage, WM_NOTIFY, 0, (LPARAM) &hdr) != FALSE)
1117 return FALSE;
1118
1119 /*
1120 * Send PSN_APPLY to all pages.
1121 */
1122 hdr.code = PSN_APPLY;
1123
1124 for (i = 0; i < psInfo->nPages; i++)
1125 {
1126 hwndPage = psInfo->proppage[i].hwndPage;
1127 msgResult = SendMessageA(hwndPage, WM_NOTIFY, 0, (LPARAM) &hdr);
1128
1129 if (msgResult == PSNRET_INVALID_NOCHANGEPAGE)
1130 return FALSE;
1131 }
1132
1133 return TRUE;
1134}
1135
1136/******************************************************************************
1137 * PROPSHEET_Cancel
1138 */
1139static void PROPSHEET_Cancel(HWND hwndDlg)
1140{
1141 PropSheetInfo* psInfo = (PropSheetInfo*) GetPropA(hwndDlg,
1142 PropSheetInfoStr);
1143 HWND hwndPage = psInfo->proppage[psInfo->active_page].hwndPage;
1144 NMHDR hdr;
1145
1146 hdr.hwndFrom = hwndDlg;
1147 hdr.code = PSN_QUERYCANCEL;
1148
1149 if (SendMessageA(hwndPage, WM_NOTIFY, 0, (LPARAM) &hdr))
1150 return;
1151
1152 hdr.code = PSN_RESET;
1153
1154 SendMessageA(hwndPage, WM_NOTIFY, 0, (LPARAM) &hdr);
1155
1156 if (psInfo->isModeless)
1157 psInfo->active_page = -1; /* makes PSM_GETCURRENTPAGEHWND return NULL */
1158 else
1159 EndDialog(hwndDlg, FALSE);
1160}
1161
1162/******************************************************************************
1163 * PROPSHEET_Help
1164 */
1165static void PROPSHEET_Help(HWND hwndDlg)
1166{
1167 PropSheetInfo* psInfo = (PropSheetInfo*) GetPropA(hwndDlg,
1168 PropSheetInfoStr);
1169 HWND hwndPage = psInfo->proppage[psInfo->active_page].hwndPage;
1170 NMHDR hdr;
1171
1172 hdr.hwndFrom = hwndDlg;
1173 hdr.code = PSN_HELP;
1174
1175 SendMessageA(hwndPage, WM_NOTIFY, 0, (LPARAM) &hdr);
1176}
1177
1178/******************************************************************************
1179 * PROPSHEET_Changed
1180 */
1181static void PROPSHEET_Changed(HWND hwndDlg, HWND hwndDirtyPage)
1182{
1183 int i;
1184 PropSheetInfo* psInfo = (PropSheetInfo*) GetPropA(hwndDlg,
1185 PropSheetInfoStr);
1186 if (!psInfo) return;
1187 /*
1188 * Set the dirty flag of this page.
1189 */
1190 for (i = 0; i < psInfo->nPages; i++)
1191 {
1192 if (psInfo->proppage[i].hwndPage == hwndDirtyPage)
1193 psInfo->proppage[i].isDirty = TRUE;
1194 }
1195
1196 /*
1197 * Enable the Apply button.
1198 */
1199 if (psInfo->hasApply)
1200 {
1201 HWND hwndApplyBtn = GetDlgItem(hwndDlg, IDC_APPLY_BUTTON);
1202
1203 EnableWindow(hwndApplyBtn, TRUE);
1204 }
1205}
1206
1207/******************************************************************************
1208 * PROPSHEET_UnChanged
1209 */
1210static void PROPSHEET_UnChanged(HWND hwndDlg, HWND hwndCleanPage)
1211{
1212 int i;
1213 BOOL noPageDirty = TRUE;
1214 HWND hwndApplyBtn = GetDlgItem(hwndDlg, IDC_APPLY_BUTTON);
1215 PropSheetInfo* psInfo = (PropSheetInfo*) GetPropA(hwndDlg,
1216 PropSheetInfoStr);
1217 if ( !psInfo ) return;
1218 for (i = 0; i < psInfo->nPages; i++)
1219 {
1220 /* set the specified page as clean */
1221 if (psInfo->proppage[i].hwndPage == hwndCleanPage)
1222 psInfo->proppage[i].isDirty = FALSE;
1223
1224 /* look to see if there's any dirty pages */
1225 if (psInfo->proppage[i].isDirty)
1226 noPageDirty = FALSE;
1227 }
1228
1229 /*
1230 * Disable Apply button.
1231 */
1232 if (noPageDirty)
1233 EnableWindow(hwndApplyBtn, FALSE);
1234}
1235
1236/******************************************************************************
1237 * PROPSHEET_PressButton
1238 */
1239static void PROPSHEET_PressButton(HWND hwndDlg, int buttonID)
1240{
1241 switch (buttonID)
1242 {
1243 case PSBTN_APPLYNOW:
1244 SendMessageA(hwndDlg, WM_COMMAND, IDC_APPLY_BUTTON, 0);
1245 break;
1246 case PSBTN_BACK:
1247 PROPSHEET_Back(hwndDlg);
1248 break;
1249 case PSBTN_CANCEL:
1250 SendMessageA(hwndDlg, WM_COMMAND, IDCANCEL, 0);
1251 break;
1252 case PSBTN_FINISH:
1253 PROPSHEET_Finish(hwndDlg);
1254 break;
1255 case PSBTN_HELP:
1256 SendMessageA(hwndDlg, WM_COMMAND, IDHELP, 0);
1257 break;
1258 case PSBTN_NEXT:
1259 PROPSHEET_Next(hwndDlg);
1260 break;
1261 case PSBTN_OK:
1262 SendMessageA(hwndDlg, WM_COMMAND, IDOK, 0);
1263 break;
1264 default:
1265// FIXME(propsheet, "Invalid button index %d\n", buttonID);
1266 break;
1267 }
1268}
1269
1270/*************************************************************************
1271 * BOOL PROPSHEET_CanSetCurSel [Internal]
1272 *
1273 * Test weither the current page can be changed by sending a PSN_KILLACTIVE
1274 *
1275 * PARAMS
1276 * hwndDlg [I] handle to a Dialog hWnd
1277 *
1278 * RETURNS
1279 * TRUE if Current Selection can change
1280 *
1281 * NOTES
1282 */
1283static BOOL PROPSHEET_CanSetCurSel(HWND hwndDlg)
1284{
1285 PropSheetInfo* psInfo = (PropSheetInfo*) GetPropA(hwndDlg,
1286 PropSheetInfoStr);
1287 HWND hwndPage;
1288 NMHDR hdr;
1289
1290 if (!psInfo)
1291 return FALSE;
1292
1293 /*
1294 * Notify the current page.
1295 */
1296 hwndPage = psInfo->proppage[psInfo->active_page].hwndPage;
1297
1298 hdr.hwndFrom = hwndDlg;
1299 hdr.code = PSN_KILLACTIVE;
1300
1301 return !SendMessageA(hwndPage, WM_NOTIFY, 0, (LPARAM) &hdr);
1302}
1303
1304/******************************************************************************
1305 * PROPSHEET_SetCurSel
1306 */
1307static BOOL PROPSHEET_SetCurSel(HWND hwndDlg,
1308 int index,
1309 HPROPSHEETPAGE hpage)
1310{
1311 PropSheetInfo* psInfo = (PropSheetInfo*) GetPropA(hwndDlg,
1312 PropSheetInfoStr);
1313 HWND hwndPage;
1314 HWND hwndHelp = GetDlgItem(hwndDlg, IDHELP);
1315 NMHDR hdr;
1316
1317 hwndPage = psInfo->proppage[psInfo->active_page].hwndPage;
1318
1319 hdr.hwndFrom = hwndDlg;
1320 /*
1321 * hpage takes precedence over index.
1322 */
1323 if (hpage != NULL)
1324 {
1325 index = PROPSHEET_GetPageIndex(hpage, psInfo);
1326
1327 if (index == -1)
1328 {
1329 TRACE("Could not find page to remove!\n");
1330 return FALSE;
1331 }
1332 }
1333
1334 hwndPage = psInfo->proppage[index].hwndPage;
1335
1336 /*
1337 * Notify the new page if it's already created.
1338 * If not it will get created and notified in PROPSHEET_ShowPage.
1339 */
1340 if (hwndPage)
1341 {
1342 int result;
1343 hdr.code = PSN_SETACTIVE;
1344
1345 result = SendMessageA(hwndPage, WM_NOTIFY, 0, (LPARAM) &hdr);
1346 /*
1347 * TODO: check return value.
1348 */
1349 }
1350
1351 /*
1352 * Display the new page.
1353 */
1354 PROPSHEET_ShowPage(hwndDlg, index, psInfo);
1355
1356 if (psInfo->proppage[index].hasHelp)
1357 EnableWindow(hwndHelp, TRUE);
1358 else
1359 EnableWindow(hwndHelp, FALSE);
1360
1361 return TRUE;
1362}
1363
1364/******************************************************************************
1365 * PROPSHEET_SetTitleA
1366 */
1367static void PROPSHEET_SetTitleA(HWND hwndDlg, DWORD dwStyle, LPCSTR lpszText)
1368{
1369 if (dwStyle & PSH_PROPTITLE)
1370 {
1371 PropSheetInfo* psInfo = (PropSheetInfo*) GetPropA(hwndDlg,
1372 PropSheetInfoStr);
1373 char* dest;
1374 int lentitle = strlen(lpszText);
1375 int lenprop = strlen(psInfo->strPropertiesFor);
1376
1377 dest = COMCTL32_Alloc(lentitle + lenprop + 1);
1378 strcpy(dest, psInfo->strPropertiesFor);
1379 strcat(dest, lpszText);
1380
1381 SetWindowTextA(hwndDlg, dest);
1382 COMCTL32_Free(dest);
1383 }
1384 else
1385 SetWindowTextA(hwndDlg, lpszText);
1386}
1387
1388/******************************************************************************
1389 * PROPSHEET_SetFinishTextA
1390 */
1391static void PROPSHEET_SetFinishTextA(HWND hwndDlg, LPCSTR lpszText)
1392{
1393 HWND hwndButton = GetDlgItem(hwndDlg, IDC_FINISH_BUTTON);
1394
1395 /* Set text, show and enable the Finish button */
1396 SetWindowTextA(hwndButton, lpszText);
1397 ShowWindow(hwndButton, SW_SHOW);
1398 EnableWindow(hwndButton, TRUE);
1399
1400 /* Make it default pushbutton */
1401 SendMessageA(hwndDlg, DM_SETDEFID, IDC_FINISH_BUTTON, 0);
1402
1403 /* Hide Back button */
1404 hwndButton = GetDlgItem(hwndDlg, IDC_BACK_BUTTON);
1405 ShowWindow(hwndButton, SW_HIDE);
1406
1407 /* Hide Next button */
1408 hwndButton = GetDlgItem(hwndDlg, IDC_NEXT_BUTTON);
1409 ShowWindow(hwndButton, SW_HIDE);
1410}
1411
1412/******************************************************************************
1413 * PROPSHEET_QuerySiblings
1414 */
1415static LRESULT PROPSHEET_QuerySiblings(HWND hwndDlg,
1416 WPARAM wParam, LPARAM lParam)
1417{
1418 int i = 0;
1419 HWND hwndPage;
1420 LRESULT msgResult = 0;
1421 PropSheetInfo* psInfo = (PropSheetInfo*) GetPropA(hwndDlg,
1422 PropSheetInfoStr);
1423
1424 while ((i < psInfo->nPages) && (msgResult == 0))
1425 {
1426 hwndPage = psInfo->proppage[i].hwndPage;
1427 msgResult = SendMessageA(hwndPage, PSM_QUERYSIBLINGS, wParam, lParam);
1428 i++;
1429 }
1430
1431 return msgResult;
1432}
1433
1434/******************************************************************************
1435 * PROPSHEET_GetPSPPage
1436 */
1437static LPCPROPSHEETPAGEA PROPSHEET_GetPSPPage(const PropSheetInfo * psInfo,
1438 int index)
1439{
1440 BOOL usePSP = psInfo->ppshheader->dwFlags & PSH_PROPSHEETPAGE;
1441 LPCPROPSHEETPAGEA lppsp;
1442 int realIndex = psInfo->proppage[index].index;
1443
1444 if (usePSP)
1445 {
1446 BYTE* pByte;
1447
1448 lppsp = psInfo->ppshheader->u3.ppsp;
1449
1450 pByte = (BYTE*) lppsp;
1451
1452 pByte += (lppsp->dwSize * realIndex);
1453 lppsp = (LPCPROPSHEETPAGEA)pByte;
1454 }
1455 else
1456 lppsp = (LPCPROPSHEETPAGEA) psInfo->ppshheader->u3.phpage[realIndex];
1457
1458 return lppsp;
1459}
1460
1461/******************************************************************************
1462 * PROPSHEET_AddPage
1463 */
1464static BOOL PROPSHEET_AddPage(HWND hwndDlg,
1465 HPROPSHEETPAGE hpage)
1466{
1467 PropSheetInfo * psInfo = (PropSheetInfo*) GetPropA(hwndDlg,
1468 PropSheetInfoStr);
1469 HWND hwndTabControl = GetDlgItem(hwndDlg, IDC_TABCONTROL);
1470 TCITEMA item;
1471 char tabtext[MAX_TABTEXT_LENGTH] = "Tab text";
1472 LPCPROPSHEETPAGEA ppsp = (LPCPROPSHEETPAGEA)hpage;
1473
1474 /*
1475 * Allocate and fill in a new PropPageInfo entry.
1476 */
1477 psInfo->proppage = (PropPageInfo*) COMCTL32_ReAlloc(psInfo->proppage,
1478 sizeof(PropPageInfo) *
1479 (psInfo->nPages + 1));
1480
1481 PROPSHEET_CollectPageInfo(ppsp, psInfo, psInfo->nPages);
1482 psInfo->proppage[psInfo->nPages].index = -1;
1483 psInfo->proppage[psInfo->nPages].hpage = hpage;
1484
1485 /*
1486 * Create the page but don't show it.
1487 */
1488 PROPSHEET_CreatePage(hwndDlg, psInfo->nPages, psInfo, ppsp, FALSE);
1489
1490 /*
1491 * Add a new tab to the tab control.
1492 */
1493 item.mask = TCIF_TEXT;
1494 item.pszText = tabtext;
1495 item.cchTextMax = MAX_TABTEXT_LENGTH;
1496
1497 WideCharToMultiByte(CP_ACP, 0,
1498 (LPCWSTR)psInfo->proppage[psInfo->nPages].pszText,
1499 -1, tabtext, MAX_TABTEXT_LENGTH, NULL, NULL);
1500
1501 SendMessageA(hwndTabControl, TCM_INSERTITEMA, psInfo->nPages + 1,
1502 (LPARAM)&item);
1503
1504 psInfo->nPages++;
1505
1506 return TRUE;
1507}
1508
1509/******************************************************************************
1510 * PROPSHEET_RemovePage
1511 */
1512static BOOL PROPSHEET_RemovePage(HWND hwndDlg,
1513 int index,
1514 HPROPSHEETPAGE hpage)
1515{
1516 PropSheetInfo * psInfo = (PropSheetInfo*) GetPropA(hwndDlg,
1517 PropSheetInfoStr);
1518 HWND hwndTabControl = GetDlgItem(hwndDlg, IDC_TABCONTROL);
1519 PropPageInfo* oldPages;
1520
1521 if (!psInfo) {
1522// FIXME("No psInfo for propertysheet at windows 0x%04x, returning FALSE...\n", hwndDlg);
1523 return FALSE;
1524 }
1525 oldPages = psInfo->proppage;
1526 /*
1527 * hpage takes precedence over index.
1528 */
1529 if (hpage != 0)
1530 {
1531 index = PROPSHEET_GetPageIndex(hpage, psInfo);
1532 }
1533
1534 /* Make shure that index is within range */
1535 if (index < 0 || index >= psInfo->nPages)
1536 {
1537// TRACE("Could not find page to remove!\n");
1538 return FALSE;
1539 }
1540
1541// TRACE("total pages %d removing page %d active page %d\n",
1542// psInfo->nPages, index, psInfo->active_page);
1543 /*
1544 * Check if we're removing the active page.
1545 */
1546 if (index == psInfo->active_page)
1547 {
1548 if (psInfo->nPages > 1)
1549 {
1550 if (index > 0)
1551 {
1552 /* activate previous page */
1553 PROPSHEET_ShowPage(hwndDlg, index - 1, psInfo);
1554 }
1555 else
1556 {
1557 /* activate the next page */
1558 PROPSHEET_ShowPage(hwndDlg, index + 1, psInfo);
1559 }
1560 }
1561 else
1562 {
1563// TRACE("Removing the only page, close the dialog!\n");
1564
1565 if (psInfo->isModeless)
1566 psInfo->active_page = -1;
1567 else
1568 EndDialog(hwndDlg, FALSE);
1569
1570 return TRUE;
1571 }
1572 }
1573
1574 if (index < psInfo->active_page)
1575 psInfo->active_page--;
1576
1577 /* Destroy page dialog window.
1578 * If it's last page in modal dialog, it has been destroyed by EndDialog
1579 */
1580 if (psInfo->isModeless || psInfo->nPages > 1)
1581 DestroyWindow(psInfo->proppage[index].hwndPage);
1582
1583 /* Remove the tab */
1584 SendMessageA(hwndTabControl, TCM_DELETEITEM, index, 0);
1585
1586 psInfo->nPages--;
1587 psInfo->proppage = COMCTL32_Alloc(sizeof(PropPageInfo) * psInfo->nPages);
1588
1589 if (index > 0)
1590 memcpy(&psInfo->proppage[0], &oldPages[0], index * sizeof(PropPageInfo));
1591
1592 if (index < psInfo->nPages)
1593 memcpy(&psInfo->proppage[index], &oldPages[index + 1],
1594 (psInfo->nPages - index) * sizeof(PropPageInfo));
1595
1596 COMCTL32_Free(oldPages);
1597
1598 return FALSE;
1599}
1600
1601/******************************************************************************
1602 * PROPSHEET_SetWizButtons
1603 *
1604 * This code will work if (and assumes that) the Next button is on top of the
1605 * Finish button. ie. Finish comes after Next in the Z order.
1606 * This means make sure the dialog template reflects this.
1607 *
1608 */
1609static void PROPSHEET_SetWizButtons(HWND hwndDlg, DWORD dwFlags)
1610{
1611 HWND hwndButton;
1612
1613// TRACE("%ld\n", dwFlags);
1614
1615 if (dwFlags & PSWIZB_BACK)
1616 {
1617 hwndButton = GetDlgItem(hwndDlg, IDC_BACK_BUTTON);
1618 EnableWindow(hwndButton, TRUE);
1619 }
1620
1621 if (dwFlags & PSWIZB_NEXT)
1622 {
1623 /* Hide the Finish button */
1624 hwndButton = GetDlgItem(hwndDlg, IDC_FINISH_BUTTON);
1625 ShowWindow(hwndButton, SW_HIDE);
1626
1627 /* Show and enable the Next button */
1628 hwndButton = GetDlgItem(hwndDlg, IDC_NEXT_BUTTON);
1629
1630 ShowWindow(hwndButton, SW_SHOW);
1631 EnableWindow(hwndButton, TRUE);
1632
1633 /* Set the Next button as the default pushbutton */
1634 SendMessageA(hwndDlg, DM_SETDEFID, IDC_NEXT_BUTTON, 0);
1635 }
1636
1637 if ((dwFlags & PSWIZB_FINISH) || (dwFlags & PSWIZB_DISABLEDFINISH))
1638 {
1639 /* Hide the Next button */
1640 hwndButton = GetDlgItem(hwndDlg, IDC_NEXT_BUTTON);
1641 ShowWindow(hwndButton, SW_HIDE);
1642
1643 /* Show the Finish button */
1644 hwndButton = GetDlgItem(hwndDlg, IDC_FINISH_BUTTON);
1645 ShowWindow(hwndButton, SW_SHOW);
1646
1647 if (dwFlags & PSWIZB_FINISH)
1648 EnableWindow(hwndButton, TRUE);
1649 else
1650 EnableWindow(hwndButton, FALSE);
1651
1652 /* Set the Finish button as the default pushbutton */
1653 SendMessageA(hwndDlg, DM_SETDEFID, IDC_FINISH_BUTTON, 0);
1654 }
1655}
1656
1657/******************************************************************************
1658 * PROPSHEET_GetPageIndex
1659 *
1660 * Given a HPROPSHEETPAGE, returns the index of the corresponding page from
1661 * the array of PropPageInfo.
1662 */
1663static int PROPSHEET_GetPageIndex(HPROPSHEETPAGE hpage, PropSheetInfo* psInfo)
1664{
1665 BOOL found = FALSE;
1666 int index = 0;
1667
1668 while ((index < psInfo->nPages) && (found == FALSE))
1669 {
1670 if (psInfo->proppage[index].hpage == hpage)
1671 found = TRUE;
1672 else
1673 index++;
1674 }
1675
1676 if (found == FALSE)
1677 index = -1;
1678
1679 return index;
1680}
1681
1682/******************************************************************************
1683 * PROPSHEET_CleanUp
1684 */
1685static void PROPSHEET_CleanUp(HWND hwndDlg)
1686{
1687 PropSheetInfo* psInfo = (PropSheetInfo*) RemovePropA(hwndDlg,
1688 PropSheetInfoStr);
1689 COMCTL32_Free(psInfo->proppage);
1690 COMCTL32_Free(psInfo->strPropertiesFor);
1691 ImageList_Destroy(psInfo->hImageList);
1692
1693 GlobalFree((HGLOBAL)psInfo);
1694}
1695
1696/******************************************************************************
1697 * PropertySheetA (COMCTL32.84)(COMCTL32.83)
1698 */
1699INT WINAPI PropertySheetA(LPCPROPSHEETHEADERA lppsh)
1700{
1701 int bRet = 0;
1702 PropSheetInfo* psInfo = (PropSheetInfo*) GlobalAlloc(GPTR,
1703 sizeof(PropSheetInfo));
1704 LPCPROPSHEETPAGEA lppsp;
1705 int i;
1706
1707 PROPSHEET_CollectSheetInfo(lppsh, psInfo);
1708
1709 psInfo->proppage = (PropPageInfo*) COMCTL32_Alloc(sizeof(PropPageInfo) *
1710 lppsh->nPages);
1711
1712 for (i = 0; i < lppsh->nPages; i++)
1713 {
1714 psInfo->proppage[i].index = i;
1715 if (!(lppsh->dwFlags & PSH_PROPSHEETPAGE))
1716 psInfo->proppage[i].hpage = psInfo->ppshheader->u3.phpage[i];
1717 lppsp = PROPSHEET_GetPSPPage(psInfo, i);
1718 PROPSHEET_CollectPageInfo(lppsp, psInfo, i);
1719 }
1720
1721 bRet = PROPSHEET_CreateDialog(psInfo);
1722
1723 return bRet;
1724}
1725
1726/******************************************************************************
1727 * PropertySheet32W (COMCTL32.85)
1728 */
1729INT WINAPI PropertySheetW(LPCPROPSHEETHEADERW propertySheetHeader)
1730{
1731// FIXME(propsheet, "(%p): stub\n", propertySheetHeader);
1732
1733 return -1;
1734}
1735
1736/******************************************************************************
1737 * CreatePropertySheetPageA (COMCTL32.19)(COMCTL32.18)
1738 */
1739HPROPSHEETPAGE WINAPI CreatePropertySheetPageA(
1740 LPCPROPSHEETPAGEA lpPropSheetPage)
1741{
1742 PROPSHEETPAGEA* ppsp = COMCTL32_Alloc(sizeof(PROPSHEETPAGEA));
1743
1744 *ppsp = *lpPropSheetPage;
1745
1746 return (HPROPSHEETPAGE)ppsp;
1747}
1748
1749/******************************************************************************
1750 * CreatePropertySheetPageW (COMCTL32.20)
1751 */
1752HPROPSHEETPAGE WINAPI CreatePropertySheetPageW(LPCPROPSHEETPAGEW lpPropSheetPage)
1753{
1754// FIXME(propsheet, "(%p): stub\n", lpPropSheetPage);
1755
1756 return 0;
1757}
1758
1759/******************************************************************************
1760 * DestroyPropertySheetPage (COMCTL32.24)
1761 */
1762BOOL WINAPI DestroyPropertySheetPage(HPROPSHEETPAGE hPropPage)
1763{
1764 COMCTL32_Free(hPropPage);
1765
1766 return TRUE;
1767}
1768
1769/******************************************************************************
1770 * PROPSHEET_DialogProc
1771 */
1772BOOL WINAPI
1773PROPSHEET_DialogProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
1774{
1775 switch (uMsg)
1776 {
1777 case WM_INITDIALOG:
1778 {
1779 PropSheetInfo* psInfo = (PropSheetInfo*) lParam;
1780 char* strCaption = (char*)COMCTL32_Alloc(MAX_CAPTION_LENGTH);
1781 HWND hwndTabCtrl = GetDlgItem(hwnd, IDC_TABCONTROL);
1782 LPCPROPSHEETPAGEA ppshpage;
1783
1784 /*
1785 * Small icon in the title bar.
1786 */
1787 if ((psInfo->ppshheader->dwFlags & PSH_USEICONID) ||
1788 (psInfo->ppshheader->dwFlags & PSH_USEHICON))
1789 {
1790 HICON hIcon;
1791 int icon_cx = GetSystemMetrics(SM_CXSMICON);
1792 int icon_cy = GetSystemMetrics(SM_CYSMICON);
1793
1794 if (psInfo->ppshheader->dwFlags & PSH_USEICONID)
1795 hIcon = LoadImageA(psInfo->ppshheader->hInstance,
1796 psInfo->ppshheader->u1.pszIcon,
1797 IMAGE_ICON,
1798 icon_cx, icon_cy,
1799 LR_DEFAULTCOLOR);
1800 else
1801 hIcon = psInfo->ppshheader->u1.hIcon;
1802
1803 SendMessageA(hwnd, WM_SETICON, 0, hIcon);
1804 }
1805
1806 if (psInfo->ppshheader->dwFlags & PSH_USEHICON)
1807 SendMessageA(hwnd, WM_SETICON, 0, psInfo->ppshheader->u1.hIcon);
1808
1809 psInfo->strPropertiesFor = strCaption;
1810
1811 GetWindowTextA(hwnd, psInfo->strPropertiesFor, MAX_CAPTION_LENGTH);
1812
1813 PROPSHEET_CreateTabControl(hwnd, psInfo);
1814
1815 if (psInfo->ppshheader->dwFlags & PSH_WIZARD)
1816 {
1817 HWND hwndBack = GetDlgItem(hwnd, IDC_BACK_BUTTON);
1818
1819 if (PROPSHEET_IsTooSmallWizard(hwnd, psInfo))
1820 {
1821 PROPSHEET_AdjustSizeWizard(hwnd, psInfo);
1822 PROPSHEET_AdjustButtonsWizard(hwnd, psInfo);
1823 }
1824
1825 /* Disable Back button if we start at page 0 */
1826 if (psInfo->active_page == 0)
1827 EnableWindow(hwndBack, FALSE);
1828 }
1829 else
1830 {
1831 if (PROPSHEET_IsTooSmall(hwnd, psInfo))
1832 {
1833 PROPSHEET_AdjustSize(hwnd, psInfo);
1834 PROPSHEET_AdjustButtons(hwnd, psInfo);
1835 }
1836 }
1837
1838 if (psInfo->useCallback)
1839 (*(psInfo->ppshheader->pfnCallback))(hwnd,
1840 PSCB_INITIALIZED, (LPARAM)0);
1841
1842 ppshpage = PROPSHEET_GetPSPPage(psInfo, psInfo->active_page);
1843 PROPSHEET_CreatePage(hwnd, psInfo->active_page, psInfo, ppshpage, TRUE);
1844
1845 if (!(psInfo->ppshheader->dwFlags & PSH_WIZARD))
1846 SendMessageA(hwndTabCtrl, TCM_SETCURSEL, psInfo->active_page, 0);
1847
1848 SetPropA(hwnd, PropSheetInfoStr, (HANDLE)psInfo);
1849
1850
1851 if (!HIWORD(psInfo->ppshheader->pszCaption) &&
1852 psInfo->ppshheader->hInstance)
1853 {
1854 char szText[256];
1855
1856 if (LoadStringA(psInfo->ppshheader->hInstance,
1857 (UINT)psInfo->ppshheader->pszCaption, szText, 255))
1858 PROPSHEET_SetTitleA(hwnd, psInfo->ppshheader->dwFlags, szText);
1859 }
1860 else
1861 {
1862 PROPSHEET_SetTitleA(hwnd, psInfo->ppshheader->dwFlags,
1863 psInfo->ppshheader->pszCaption);
1864 }
1865
1866 return TRUE;
1867 }
1868
1869 case WM_DESTROY:
1870 PROPSHEET_CleanUp(hwnd);
1871 return TRUE;
1872
1873 case WM_CLOSE:
1874 PROPSHEET_Cancel(hwnd);
1875 return TRUE;
1876
1877 case WM_COMMAND:
1878 {
1879 WORD wID = LOWORD(wParam);
1880
1881 switch (wID)
1882 {
1883 case IDOK:
1884 case IDC_APPLY_BUTTON:
1885 {
1886 HWND hwndApplyBtn = GetDlgItem(hwnd, IDC_APPLY_BUTTON);
1887
1888 if (PROPSHEET_Apply(hwnd) == FALSE)
1889 break;
1890
1891 EnableWindow(hwndApplyBtn, FALSE);
1892
1893 if (wID == IDOK)
1894 {
1895 PropSheetInfo* psInfo = (PropSheetInfo*) GetPropA(hwnd,
1896 PropSheetInfoStr);
1897 int result = TRUE;
1898
1899 if (psInfo->restartWindows)
1900 result = ID_PSRESTARTWINDOWS;
1901
1902 /* reboot system takes precedence over restart windows */
1903 if (psInfo->rebootSystem)
1904 result = ID_PSREBOOTSYSTEM;
1905
1906 if (psInfo->isModeless)
1907 psInfo->active_page = -1;
1908 else
1909 EndDialog(hwnd, result);
1910 }
1911
1912 break;
1913 }
1914
1915 case IDC_BACK_BUTTON:
1916 PROPSHEET_Back(hwnd);
1917 break;
1918
1919 case IDC_NEXT_BUTTON:
1920 PROPSHEET_Next(hwnd);
1921 break;
1922
1923 case IDC_FINISH_BUTTON:
1924 PROPSHEET_Finish(hwnd);
1925 break;
1926
1927 case IDCANCEL:
1928 PROPSHEET_Cancel(hwnd);
1929 break;
1930
1931 case IDHELP:
1932 PROPSHEET_Help(hwnd);
1933 break;
1934 }
1935
1936 return TRUE;
1937 }
1938
1939 case WM_NOTIFY:
1940 {
1941 NMHDR* pnmh = (LPNMHDR) lParam;
1942
1943 if (pnmh->code == TCN_SELCHANGE)
1944 {
1945 int index = SendMessageA(pnmh->hwndFrom, TCM_GETCURSEL, 0, 0);
1946 PROPSHEET_SetCurSel(hwnd, index, 0);
1947 }
1948
1949 if(pnmh->code == TCN_SELCHANGING)
1950 {
1951 BOOL bRet = PROPSHEET_CanSetCurSel(hwnd);
1952 SetWindowLongA(hwnd, DWL_MSGRESULT, !bRet);
1953 return TRUE;
1954 }
1955
1956
1957 return 0;
1958 }
1959
1960 case PSM_GETCURRENTPAGEHWND:
1961 {
1962 PropSheetInfo* psInfo = (PropSheetInfo*) GetPropA(hwnd,
1963 PropSheetInfoStr);
1964 HWND hwndPage = 0;
1965
1966 if (psInfo->active_page != -1)
1967 hwndPage = psInfo->proppage[psInfo->active_page].hwndPage;
1968
1969 SetWindowLongA(hwnd, DWL_MSGRESULT, hwndPage);
1970
1971 return TRUE;
1972 }
1973
1974 case PSM_CHANGED:
1975 PROPSHEET_Changed(hwnd, (HWND)wParam);
1976 return TRUE;
1977
1978 case PSM_UNCHANGED:
1979 PROPSHEET_UnChanged(hwnd, (HWND)wParam);
1980 return TRUE;
1981
1982 case PSM_GETTABCONTROL:
1983 {
1984 HWND hwndTabCtrl = GetDlgItem(hwnd, IDC_TABCONTROL);
1985
1986 SetWindowLongA(hwnd, DWL_MSGRESULT, hwndTabCtrl);
1987
1988 return TRUE;
1989 }
1990
1991 case PSM_SETCURSEL:
1992 {
1993 BOOL msgResult;
1994
1995 msgResult = PROPSHEET_CanSetCurSel(hwnd);
1996 if(msgResult != FALSE)
1997 {
1998 msgResult = PROPSHEET_SetCurSel(hwnd,
1999 (int)wParam,
2000 (HPROPSHEETPAGE)lParam);
2001 }
2002
2003 SetWindowLongA(hwnd, DWL_MSGRESULT, msgResult);
2004
2005 return TRUE;
2006 }
2007
2008 case PSM_CANCELTOCLOSE:
2009 {
2010 HWND hwndOK = GetDlgItem(hwnd, IDOK);
2011 HWND hwndCancel = GetDlgItem(hwnd, IDCANCEL);
2012
2013 EnableWindow(hwndCancel, FALSE);
2014 SetWindowTextA(hwndOK, "Close"); /* FIXME: hardcoded string */
2015
2016 return TRUE;
2017 }
2018
2019 case PSM_RESTARTWINDOWS:
2020 {
2021 PropSheetInfo* psInfo = (PropSheetInfo*) GetPropA(hwnd,
2022 PropSheetInfoStr);
2023
2024 psInfo->restartWindows = TRUE;
2025 return TRUE;
2026 }
2027
2028 case PSM_REBOOTSYSTEM:
2029 {
2030 PropSheetInfo* psInfo = (PropSheetInfo*) GetPropA(hwnd,
2031 PropSheetInfoStr);
2032
2033 psInfo->rebootSystem = TRUE;
2034 return TRUE;
2035 }
2036
2037 case PSM_SETTITLEA:
2038 PROPSHEET_SetTitleA(hwnd, (DWORD) wParam, (LPCSTR) lParam);
2039 return TRUE;
2040
2041 case PSM_APPLY:
2042 {
2043 BOOL msgResult = PROPSHEET_Apply(hwnd);
2044
2045 SetWindowLongA(hwnd, DWL_MSGRESULT, msgResult);
2046
2047 return TRUE;
2048 }
2049
2050 case PSM_QUERYSIBLINGS:
2051 {
2052 LRESULT msgResult = PROPSHEET_QuerySiblings(hwnd, wParam, lParam);
2053
2054 SetWindowLongA(hwnd, DWL_MSGRESULT, msgResult);
2055
2056 return TRUE;
2057 }
2058
2059 case PSM_ADDPAGE:
2060 {
2061 /*
2062 * Note: MSVC++ 6.0 documentation says that PSM_ADDPAGE does not have
2063 * a return value. This is not true. PSM_ADDPAGE returns TRUE
2064 * on success or FALSE otherwise, as specified on MSDN Online.
2065 * Also see the MFC code for
2066 * CPropertySheet::AddPage(CPropertyPage* pPage).
2067 */
2068
2069 BOOL msgResult = PROPSHEET_AddPage(hwnd, (HPROPSHEETPAGE)lParam);
2070
2071 SetWindowLongA(hwnd, DWL_MSGRESULT, msgResult);
2072
2073 return TRUE;
2074 }
2075
2076 case PSM_REMOVEPAGE:
2077 PROPSHEET_RemovePage(hwnd, (int)wParam, (HPROPSHEETPAGE)lParam);
2078 return TRUE;
2079
2080 case PSM_ISDIALOGMESSAGE:
2081 {
2082 FIXME("Unimplemented msg PSM_ISDIALOGMESSAGE\n");
2083 return 0;
2084 }
2085
2086 case PSM_PRESSBUTTON:
2087 PROPSHEET_PressButton(hwnd, (int)wParam);
2088 return TRUE;
2089
2090 case PSM_SETFINISHTEXTA:
2091 PROPSHEET_SetFinishTextA(hwnd, (LPCSTR) lParam);
2092 return TRUE;
2093
2094 case PSM_SETWIZBUTTONS:
2095 PROPSHEET_SetWizButtons(hwnd, (DWORD)lParam);
2096 return TRUE;
2097
2098 case PSM_SETTITLEW:
2099 FIXME("Unimplemented msg PSM_SETTITLE32W\n");
2100 return 0;
2101 case PSM_SETCURSELID:
2102 FIXME("Unimplemented msg PSM_SETCURSELID\n");
2103 return 0;
2104 case PSM_SETFINISHTEXTW:
2105 FIXME("Unimplemented msg PSM_SETFINISHTEXT32W\n");
2106 return 0;
2107
2108 default:
2109 return FALSE;
2110 }
2111}
2112
Note: See TracBrowser for help on using the repository browser.