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

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

merged latest WINE 990923 changes

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