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

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

comctl32 wine 991114 merge

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