ReactOS  0.4.14-dev-41-g31d7680
propsheet.c
Go to the documentation of this file.
1 /*
2  * Property Sheets
3  *
4  * Copyright 1998 Francis Beaudet
5  * Copyright 1999 Thuy Nguyen
6  * Copyright 2004 Maxime Bellenge
7  * Copyright 2004 Filip Navara
8  *
9  * This library is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU Lesser General Public
11  * License as published by the Free Software Foundation; either
12  * version 2.1 of the License, or (at your option) any later version.
13  *
14  * This library is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17  * Lesser General Public License for more details.
18  *
19  * You should have received a copy of the GNU Lesser General Public
20  * License along with this library; if not, write to the Free Software
21  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
22  *
23  * This code was audited for completeness against the documented features
24  * of Comctl32.dll version 6.0 on Sep. 12, 2004, by Filip Navara.
25  *
26  * Unless otherwise noted, we believe this code to be complete, as per
27  * the specification mentioned above.
28  * If you discover missing features, or bugs, please note them below.
29  *
30  * TODO:
31  * - Tab order
32  * - Wizard 97 header resizing
33  * - Enforcing of minimal wizard size
34  * - Messages:
35  * o PSM_RECALCPAGESIZES
36  * o WM_HELP
37  * o WM_CONTEXTMENU
38  * - Notifications:
39  * o PSN_GETOBJECT
40  * o PSN_QUERYINITIALFOCUS
41  * o PSN_TRANSLATEACCELERATOR
42  * - Styles:
43  * o PSH_RTLREADING
44  * o PSH_STRETCHWATERMARK
45  * o PSH_USEPAGELANG
46  * o PSH_USEPSTARTPAGE
47  * - Page styles:
48  * o PSP_USEFUSIONCONTEXT
49  * o PSP_USEREFPARENT
50  */
51 
52 #include <stdarg.h>
53 #include <string.h>
54 
55 #define NONAMELESSUNION
56 
57 #include "windef.h"
58 #include "winbase.h"
59 #include "wingdi.h"
60 #include "winuser.h"
61 #include "winnls.h"
62 #include "commctrl.h"
63 #include "prsht.h"
64 #include "comctl32.h"
65 #include "uxtheme.h"
66 
67 #include "wine/debug.h"
68 #include "wine/unicode.h"
69 
70 /******************************************************************************
71  * Data structures
72  */
73 #include "pshpack2.h"
74 
75 typedef struct
76 {
83 
84 typedef struct
85 {
89  short x;
90  short y;
91  short cx;
92  short cy;
95 #include "poppack.h"
96 
97 typedef struct tagPropPageInfo
98 {
99  HPROPSHEETPAGE hpage; /* to keep track of pages not passed to PropertySheet */
106 } PropPageInfo;
107 
108 typedef struct tagPropSheetInfo
109 {
114  int nPages;
126  int width;
127  int height;
131 } PropSheetInfo;
132 
133 typedef struct
134 {
135  int x;
136  int y;
137 } PADDING_INFO;
138 
139 /******************************************************************************
140  * Defines and global variables
141  */
142 
143 static const WCHAR PropSheetInfoStr[] =
144  {'P','r','o','p','e','r','t','y','S','h','e','e','t','I','n','f','o',0 };
145 
146 #define PSP_INTERNAL_UNICODE 0x80000000
147 
148 #define MAX_CAPTION_LENGTH 255
149 #define MAX_TABTEXT_LENGTH 255
150 #define MAX_BUTTONTEXT_LENGTH 64
151 
152 #define INTRNL_ANY_WIZARD (PSH_WIZARD | PSH_WIZARD97_OLD | PSH_WIZARD97_NEW | PSH_WIZARD_LITE)
153 
154 /* Wizard metrics specified in DLUs */
155 #define WIZARD_PADDING 7
156 #define WIZARD_HEADER_HEIGHT 36
157 
158 /******************************************************************************
159  * Prototypes
160  */
162 static void PROPSHEET_SetTitleW(HWND hwndDlg, DWORD dwStyle, LPCWSTR lpszText);
163 static BOOL PROPSHEET_CanSetCurSel(HWND hwndDlg);
164 static BOOL PROPSHEET_SetCurSel(HWND hwndDlg,
165  int index,
166  int skipdir,
167  HPROPSHEETPAGE hpage);
168 static int PROPSHEET_GetPageIndex(HPROPSHEETPAGE hpage, const PropSheetInfo* psInfo, int original_index);
169 static PADDING_INFO PROPSHEET_GetPaddingInfoWizard(HWND hwndDlg, const PropSheetInfo* psInfo);
170 static BOOL PROPSHEET_DoCommand(HWND hwnd, WORD wID);
171 static BOOL PROPSHEET_RemovePage(HWND hwndDlg, int index, HPROPSHEETPAGE hpage);
172 
173 static INT_PTR CALLBACK
175 
176 WINE_DEFAULT_DEBUG_CHANNEL(propsheet);
177 
178 static WCHAR *heap_strdupW(const WCHAR *str)
179 {
180  int len = strlenW(str) + 1;
181  WCHAR *ret = Alloc(len * sizeof(WCHAR));
182  strcpyW(ret, str);
183  return ret;
184 }
185 
186 static WCHAR *heap_strdupAtoW(const char *str)
187 {
188  WCHAR *ret;
189  INT len;
190 
191  len = MultiByteToWideChar(CP_ACP, 0, str, -1, 0, 0);
192  ret = Alloc(len * sizeof(WCHAR));
193  MultiByteToWideChar(CP_ACP, 0, str, -1, ret, len);
194 
195  return ret;
196 }
197 
198 #define add_flag(a) if (dwFlags & a) {strcat(string, #a );strcat(string," ");}
199 /******************************************************************************
200  * PROPSHEET_UnImplementedFlags
201  *
202  * Document use of flags we don't implement yet.
203  */
205 {
206  CHAR string[256];
207 
208  string[0] = '\0';
209 
210  /*
211  * unhandled header flags:
212  * PSH_RTLREADING 0x00000800
213  * PSH_STRETCHWATERMARK 0x00040000
214  * PSH_USEPAGELANG 0x00200000
215  */
216 
218  add_flag(PSH_STRETCHWATERMARK);
219  add_flag(PSH_USEPAGELANG);
220  if (string[0] != '\0')
221  FIXME("%s\n", string);
222 }
223 #undef add_flag
224 
225 /******************************************************************************
226  * PROPSHEET_GetPageRect
227  *
228  * Retrieve rect from tab control and map into the dialog for SetWindowPos
229  */
230 static void PROPSHEET_GetPageRect(const PropSheetInfo * psInfo, HWND hwndDlg,
231  RECT *rc, LPCPROPSHEETPAGEW ppshpage)
232 {
233  if (psInfo->ppshheader.dwFlags & INTRNL_ANY_WIZARD) {
234  HWND hwndChild;
235  RECT r;
236 
237  if (((psInfo->ppshheader.dwFlags & (PSH_WIZARD97_NEW | PSH_WIZARD97_OLD)) &&
238  (psInfo->ppshheader.dwFlags & PSH_HEADER) &&
239  !(ppshpage->dwFlags & PSP_HIDEHEADER)) ||
240  (psInfo->ppshheader.dwFlags & PSH_WIZARD))
241  {
242  rc->left = rc->top = WIZARD_PADDING;
243  }
244  else
245  {
246  rc->left = rc->top = 0;
247  }
248  rc->right = psInfo->width - rc->left;
249  rc->bottom = psInfo->height - rc->top;
250  MapDialogRect(hwndDlg, rc);
251 
252  if ((psInfo->ppshheader.dwFlags & (PSH_WIZARD97_NEW | PSH_WIZARD97_OLD)) &&
253  (psInfo->ppshheader.dwFlags & PSH_HEADER) &&
254  !(ppshpage->dwFlags & PSP_HIDEHEADER))
255  {
256  hwndChild = GetDlgItem(hwndDlg, IDC_SUNKEN_LINEHEADER);
257  GetClientRect(hwndChild, &r);
258  MapWindowPoints(hwndChild, hwndDlg, (LPPOINT) &r, 2);
259  rc->top += r.bottom + 1;
260  }
261  } else {
262  HWND hwndTabCtrl = GetDlgItem(hwndDlg, IDC_TABCONTROL);
263  GetClientRect(hwndTabCtrl, rc);
264  SendMessageW(hwndTabCtrl, TCM_ADJUSTRECT, FALSE, (LPARAM)rc);
265  MapWindowPoints(hwndTabCtrl, hwndDlg, (LPPOINT)rc, 2);
266  }
267 }
268 
269 /******************************************************************************
270  * PROPSHEET_FindPageByResId
271  *
272  * Find page index corresponding to page resource id.
273  */
274 static INT PROPSHEET_FindPageByResId(const PropSheetInfo * psInfo, LRESULT resId)
275 {
276  INT i;
277 
278  for (i = 0; i < psInfo->nPages; i++)
279  {
281 
282  /* Fixme: if resource ID is a string shall we use strcmp ??? */
283  if (lppsp->u.pszTemplate == (LPVOID)resId)
284  break;
285  }
286 
287  return i;
288 }
289 
290 /******************************************************************************
291  * PROPSHEET_CollectSheetInfoCommon
292  *
293  * Common code for PROPSHEET_CollectSheetInfoA/W
294  */
296 {
298 
299  psInfo->hasHelp = dwFlags & PSH_HASHELP;
300  psInfo->hasApply = !(dwFlags & PSH_NOAPPLYNOW);
302  psInfo->isModeless = dwFlags & PSH_MODELESS;
304  if (psInfo->active_page < 0 || psInfo->active_page >= psInfo->nPages)
305  psInfo->active_page = 0;
306 
307  psInfo->result = 0;
308  psInfo->hImageList = 0;
309  psInfo->activeValid = FALSE;
310 }
311 
312 /******************************************************************************
313  * PROPSHEET_CollectSheetInfoA
314  *
315  * Collect relevant data.
316  */
318  PropSheetInfo * psInfo)
319 {
320  DWORD dwSize = min(lppsh->dwSize,sizeof(PROPSHEETHEADERA));
321  DWORD dwFlags = lppsh->dwFlags;
322 
323  psInfo->useCallback = (dwFlags & PSH_USECALLBACK )&& (lppsh->pfnCallback);
324 
325  memcpy(&psInfo->ppshheader,lppsh,dwSize);
326  TRACE("\n** PROPSHEETHEADER **\ndwSize\t\t%d\ndwFlags\t\t%08x\nhwndParent\t%p\nhInstance\t%p\npszCaption\t'%s'\nnPages\t\t%d\npfnCallback\t%p\n",
327  lppsh->dwSize, lppsh->dwFlags, lppsh->hwndParent, lppsh->hInstance,
328  debugstr_a(lppsh->pszCaption), lppsh->nPages, lppsh->pfnCallback);
329 
330  if (lppsh->dwFlags & INTRNL_ANY_WIZARD)
331  psInfo->ppshheader.pszCaption = NULL;
332  else
333  {
334  if (!IS_INTRESOURCE(lppsh->pszCaption))
335  {
336  int len = MultiByteToWideChar(CP_ACP, 0, lppsh->pszCaption, -1, NULL, 0);
337  WCHAR *caption = Alloc( len*sizeof (WCHAR) );
338 
339  MultiByteToWideChar(CP_ACP, 0, lppsh->pszCaption, -1, caption, len);
340  psInfo->ppshheader.pszCaption = caption;
341  }
342  }
343  psInfo->nPages = lppsh->nPages;
344 
346  {
347  TRACE("PSH_USEPSTARTPAGE is on\n");
348  psInfo->active_page = 0;
349  }
350  else
351  psInfo->active_page = lppsh->u2.nStartPage;
352 
354 }
355 
356 /******************************************************************************
357  * PROPSHEET_CollectSheetInfoW
358  *
359  * Collect relevant data.
360  */
362  PropSheetInfo * psInfo)
363 {
364  DWORD dwSize = min(lppsh->dwSize,sizeof(PROPSHEETHEADERW));
365  DWORD dwFlags = lppsh->dwFlags;
366 
367  psInfo->useCallback = (dwFlags & PSH_USECALLBACK) && (lppsh->pfnCallback);
368 
369  memcpy(&psInfo->ppshheader,lppsh,dwSize);
370  TRACE("\n** PROPSHEETHEADER **\ndwSize\t\t%d\ndwFlags\t\t%08x\nhwndParent\t%p\nhInstance\t%p\npszCaption\t%s\nnPages\t\t%d\npfnCallback\t%p\n",
371  lppsh->dwSize, lppsh->dwFlags, lppsh->hwndParent, lppsh->hInstance, debugstr_w(lppsh->pszCaption), lppsh->nPages, lppsh->pfnCallback);
372 
373  if (lppsh->dwFlags & INTRNL_ANY_WIZARD)
374  psInfo->ppshheader.pszCaption = NULL;
375  else
376  {
377  if (!IS_INTRESOURCE(lppsh->pszCaption))
378  psInfo->ppshheader.pszCaption = heap_strdupW( lppsh->pszCaption );
379  }
380  psInfo->nPages = lppsh->nPages;
381 
383  {
384  TRACE("PSH_USEPSTARTPAGE is on\n");
385  psInfo->active_page = 0;
386  }
387  else
388  psInfo->active_page = lppsh->u2.nStartPage;
389 
391 }
392 
393 /******************************************************************************
394  * PROPSHEET_CollectPageInfo
395  *
396  * Collect property sheet data.
397  * With code taken from DIALOG_ParseTemplate32.
398  */
400  PropSheetInfo * psInfo,
401  int index, BOOL resize)
402 {
403  const DLGTEMPLATE* pTemplate;
404  const WORD* p;
405  DWORD dwFlags;
406  int width, height;
407 
408  if (!lppsp)
409  return FALSE;
410 
411  TRACE("\n");
412  psInfo->proppage[index].hpage = (HPROPSHEETPAGE)lppsp;
413  psInfo->proppage[index].hwndPage = 0;
414  psInfo->proppage[index].isDirty = FALSE;
415 
416  /*
417  * Process property page flags.
418  */
419  dwFlags = lppsp->dwFlags;
420  psInfo->proppage[index].useCallback = (dwFlags & PSP_USECALLBACK) && (lppsp->pfnCallback);
423 
424  /* as soon as we have a page with the help flag, set the sheet flag on */
425  if (psInfo->proppage[index].hasHelp)
426  psInfo->hasHelp = TRUE;
427 
428  /*
429  * Process page template.
430  */
431  if (dwFlags & PSP_DLGINDIRECT)
432  pTemplate = lppsp->u.pResource;
433  else if(dwFlags & PSP_INTERNAL_UNICODE )
434  {
435  HRSRC hResource = FindResourceW(lppsp->hInstance,
436  lppsp->u.pszTemplate,
437  (LPWSTR)RT_DIALOG);
438  HGLOBAL hTemplate = LoadResource(lppsp->hInstance,
439  hResource);
440  pTemplate = LockResource(hTemplate);
441  }
442  else
443  {
444  HRSRC hResource = FindResourceA(lppsp->hInstance,
445  (LPCSTR)lppsp->u.pszTemplate,
446  (LPSTR)RT_DIALOG);
447  HGLOBAL hTemplate = LoadResource(lppsp->hInstance,
448  hResource);
449  pTemplate = LockResource(hTemplate);
450  }
451 
452  /*
453  * Extract the size of the page and the caption.
454  */
455  if (!pTemplate)
456  return FALSE;
457 
458  p = (const WORD *)pTemplate;
459 
460  if (((const MyDLGTEMPLATEEX*)pTemplate)->signature == 0xFFFF)
461  {
462  /* DLGTEMPLATEEX (not defined in any std. header file) */
463 
464  p++; /* dlgVer */
465  p++; /* signature */
466  p += 2; /* help ID */
467  p += 2; /* ext style */
468  p += 2; /* style */
469  }
470  else
471  {
472  /* DLGTEMPLATE */
473 
474  p += 2; /* style */
475  p += 2; /* ext style */
476  }
477 
478  p++; /* nb items */
479  p++; /* x */
480  p++; /* y */
481  width = (WORD)*p; p++;
482  height = (WORD)*p; p++;
483 
484  if (lppsp->dwFlags & (PSP_USEHEADERTITLE | PSP_USEHEADERSUBTITLE))
485  psInfo->ppshheader.dwFlags |= PSH_HEADER;
486 
487  /* Special calculation for interior wizard pages so the largest page is
488  * calculated correctly. We need to add all the padding and space occupied
489  * by the header so the width and height sums up to the whole wizard client
490  * area. */
491  if ((psInfo->ppshheader.dwFlags & (PSH_WIZARD97_OLD | PSH_WIZARD97_NEW)) &&
492  (psInfo->ppshheader.dwFlags & PSH_HEADER) &&
493  !(dwFlags & PSP_HIDEHEADER))
494  {
496  width += 2 * WIZARD_PADDING;
497  }
498  if (psInfo->ppshheader.dwFlags & PSH_WIZARD)
499  {
500  height += 2 * WIZARD_PADDING;
501  width += 2 * WIZARD_PADDING;
502  }
503 
504  /* remember the largest width and height */
505  if (resize)
506  {
507  if (width > psInfo->width)
508  psInfo->width = width;
509 
510  if (height > psInfo->height)
511  psInfo->height = height;
512  }
513 
514  /* menu */
515  switch ((WORD)*p)
516  {
517  case 0x0000:
518  p++;
519  break;
520  case 0xffff:
521  p += 2;
522  break;
523  default:
524  p += lstrlenW( p ) + 1;
525  break;
526  }
527 
528  /* class */
529  switch ((WORD)*p)
530  {
531  case 0x0000:
532  p++;
533  break;
534  case 0xffff:
535  p += 2;
536  break;
537  default:
538  p += lstrlenW( p ) + 1;
539  break;
540  }
541 
542  /* Extract the caption */
543  psInfo->proppage[index].pszText = p;
544  TRACE("Tab %d %s\n",index,debugstr_w( p ));
545 
546  if (dwFlags & PSP_USETITLE)
547  {
548  WCHAR szTitle[256];
549  const WCHAR *pTitle;
550  static const WCHAR pszNull[] = { '(','n','u','l','l',')',0 };
551 
552  if (IS_INTRESOURCE( lppsp->pszTitle ))
553  {
555  pTitle = szTitle;
556  else if (*p)
557  pTitle = p;
558  else
559  pTitle = pszNull;
560  }
561  else
562  pTitle = lppsp->pszTitle;
563 
564  psInfo->proppage[index].pszText = heap_strdupW( pTitle );
565  }
566 
567  /*
568  * Build the image list for icons
569  */
570  if ((dwFlags & PSP_USEHICON) || (dwFlags & PSP_USEICONID))
571  {
572  HICON hIcon;
573  int icon_cx = GetSystemMetrics(SM_CXSMICON);
574  int icon_cy = GetSystemMetrics(SM_CYSMICON);
575 
576  if (dwFlags & PSP_USEICONID)
577  hIcon = LoadImageW(lppsp->hInstance, lppsp->u2.pszIcon, IMAGE_ICON,
578  icon_cx, icon_cy, LR_DEFAULTCOLOR);
579  else
580  hIcon = lppsp->u2.hIcon;
581 
582  if ( hIcon )
583  {
584  if (psInfo->hImageList == 0 )
585  psInfo->hImageList = ImageList_Create(icon_cx, icon_cy, ILC_COLOR, 1, 1);
586 
588  }
589 
590  }
591 
592  return TRUE;
593 }
594 
595 /******************************************************************************
596  * PROPSHEET_CreateDialog
597  *
598  * Creates the actual property sheet.
599  */
601 {
602  LRESULT ret;
603  LPCVOID template;
604  LPVOID temp = 0;
605  HRSRC hRes;
606  DWORD resSize;
607  WORD resID = IDD_PROPSHEET;
608 
609  TRACE("(%p)\n", psInfo);
610  if (psInfo->ppshheader.dwFlags & INTRNL_ANY_WIZARD)
611  resID = IDD_WIZARD;
612 
613  if( psInfo->unicode )
614  {
615  if(!(hRes = FindResourceW(COMCTL32_hModule,
616  MAKEINTRESOURCEW(resID),
617  (LPWSTR)RT_DIALOG)))
618  return -1;
619  }
620  else
621  {
622  if(!(hRes = FindResourceA(COMCTL32_hModule,
623  MAKEINTRESOURCEA(resID),
624  (LPSTR)RT_DIALOG)))
625  return -1;
626  }
627 
628  if(!(template = LoadResource(COMCTL32_hModule, hRes)))
629  return -1;
630 
631  /*
632  * Make a copy of the dialog template.
633  */
634  resSize = SizeofResource(COMCTL32_hModule, hRes);
635 
636  temp = Alloc(2 * resSize);
637 
638  if (!temp)
639  return -1;
640 
641  memcpy(temp, template, resSize);
642 
643  if (psInfo->ppshheader.dwFlags & PSH_NOCONTEXTHELP)
644  {
645  if (((MyDLGTEMPLATEEX*)temp)->signature == 0xFFFF)
646  ((MyDLGTEMPLATEEX*)temp)->style &= ~DS_CONTEXTHELP;
647  else
649  }
650  if ((psInfo->ppshheader.dwFlags & INTRNL_ANY_WIZARD) &&
652  {
653  if (((MyDLGTEMPLATEEX*)temp)->signature == 0xFFFF)
654  ((MyDLGTEMPLATEEX*)temp)->style |= DS_CONTEXTHELP;
655  else
657  }
658 
659  if (psInfo->useCallback)
660  (*(psInfo->ppshheader.pfnCallback))(0, PSCB_PRECREATE, (LPARAM)temp);
661 
662  /* NOTE: MSDN states "Returns a positive value if successful, or -1
663  * otherwise for modal property sheets.", but this is wrong. The
664  * actual return value is either TRUE (success), FALSE (cancel) or
665  * -1 (error). */
666  if( psInfo->unicode )
667  {
669  temp, psInfo->ppshheader.hwndParent,
670  PROPSHEET_DialogProc, (LPARAM)psInfo);
671  if ( !ret ) ret = -1;
672  }
673  else
674  {
676  temp, psInfo->ppshheader.hwndParent,
677  PROPSHEET_DialogProc, (LPARAM)psInfo);
678  if ( !ret ) ret = -1;
679  }
680 
681  Free(temp);
682 
683  return ret;
684 }
685 
686 /******************************************************************************
687  * PROPSHEET_SizeMismatch
688  *
689  * Verify that the tab control and the "largest" property sheet page dlg. template
690  * match in size.
691  */
692 static BOOL PROPSHEET_SizeMismatch(HWND hwndDlg, const PropSheetInfo* psInfo)
693 {
694  HWND hwndTabCtrl = GetDlgItem(hwndDlg, IDC_TABCONTROL);
695  RECT rcOrigTab, rcPage;
696 
697  /*
698  * Original tab size.
699  */
700  GetClientRect(hwndTabCtrl, &rcOrigTab);
701  TRACE("orig tab %s\n", wine_dbgstr_rect(&rcOrigTab));
702 
703  /*
704  * Biggest page size.
705  */
706  SetRect(&rcPage, 0, 0, psInfo->width, psInfo->height);
707  MapDialogRect(hwndDlg, &rcPage);
708  TRACE("biggest page %s\n", wine_dbgstr_rect(&rcPage));
709 
710  if ( (rcPage.right - rcPage.left) != (rcOrigTab.right - rcOrigTab.left) )
711  return TRUE;
712  if ( (rcPage.bottom - rcPage.top) != (rcOrigTab.bottom - rcOrigTab.top) )
713  return TRUE;
714 
715  return FALSE;
716 }
717 
718 /******************************************************************************
719  * PROPSHEET_AdjustSize
720  *
721  * Resizes the property sheet and the tab control to fit the largest page.
722  */
723 static BOOL PROPSHEET_AdjustSize(HWND hwndDlg, PropSheetInfo* psInfo)
724 {
725  HWND hwndTabCtrl = GetDlgItem(hwndDlg, IDC_TABCONTROL);
726  HWND hwndButton = GetDlgItem(hwndDlg, IDOK);
727  RECT rc,tabRect;
728  int buttonHeight;
730  RECT units;
731  LONG style;
732 
733  /* Get the height of buttons */
734  GetClientRect(hwndButton, &rc);
735  buttonHeight = rc.bottom;
736 
737  /*
738  * Biggest page size.
739  */
740  SetRect(&rc, 0, 0, psInfo->width, psInfo->height);
741  MapDialogRect(hwndDlg, &rc);
742 
743  /* retrieve the dialog units */
744  units.left = units.right = 4;
745  units.top = units.bottom = 8;
746  MapDialogRect(hwndDlg, &units);
747 
748  /*
749  * Resize the tab control.
750  */
751  GetClientRect(hwndTabCtrl,&tabRect);
752 
753  SendMessageW(hwndTabCtrl, TCM_ADJUSTRECT, FALSE, (LPARAM)&tabRect);
754 
755  if ((rc.bottom - rc.top) < (tabRect.bottom - tabRect.top))
756  {
757  rc.bottom = rc.top + tabRect.bottom - tabRect.top;
758  psInfo->height = MulDiv((rc.bottom - rc.top),8,units.top);
759  }
760 
761  if ((rc.right - rc.left) < (tabRect.right - tabRect.left))
762  {
763  rc.right = rc.left + tabRect.right - tabRect.left;
764  psInfo->width = MulDiv((rc.right - rc.left),4,units.left);
765  }
766 
767  SendMessageW(hwndTabCtrl, TCM_ADJUSTRECT, TRUE, (LPARAM)&rc);
768 
769  rc.right -= rc.left;
770  rc.bottom -= rc.top;
771  TRACE("setting tab %p, rc (0,0)-(%d,%d)\n",
772  hwndTabCtrl, rc.right, rc.bottom);
773  SetWindowPos(hwndTabCtrl, 0, 0, 0, rc.right, rc.bottom,
775 
776  GetClientRect(hwndTabCtrl, &rc);
777 
778  TRACE("tab client rc %s\n", wine_dbgstr_rect(&rc));
779 
780  rc.right += (padding.x * 2);
781  rc.bottom += buttonHeight + (3 * padding.y);
782 
783  style = GetWindowLongW(hwndDlg, GWL_STYLE);
784  if (!(style & WS_CHILD))
786 
787  rc.right -= rc.left;
788  rc.bottom -= rc.top;
789 
790  /*
791  * Resize the property sheet.
792  */
793  TRACE("setting dialog %p, rc (0,0)-(%d,%d)\n",
794  hwndDlg, rc.right, rc.bottom);
795  SetWindowPos(hwndDlg, 0, 0, 0, rc.right, rc.bottom,
797  return TRUE;
798 }
799 
800 /******************************************************************************
801  * PROPSHEET_AdjustSizeWizard
802  *
803  * Resizes the property sheet to fit the largest page.
804  */
805 static BOOL PROPSHEET_AdjustSizeWizard(HWND hwndDlg, const PropSheetInfo* psInfo)
806 {
807  HWND hwndLine = GetDlgItem(hwndDlg, IDC_SUNKEN_LINE);
808  RECT rc, lineRect, dialogRect;
809 
810  /* Biggest page size */
811  SetRect(&rc, 0, 0, psInfo->width, psInfo->height);
812  MapDialogRect(hwndDlg, &rc);
813 
814  TRACE("Biggest page %s\n", wine_dbgstr_rect(&rc));
815 
816  /* Add space for the buttons row */
817  GetWindowRect(hwndLine, &lineRect);
818  MapWindowPoints(NULL, hwndDlg, (LPPOINT)&lineRect, 2);
819  GetClientRect(hwndDlg, &dialogRect);
820  rc.bottom += dialogRect.bottom - lineRect.top - 1;
821 
822  /* Convert the client coordinates to window coordinates */
824 
825  /* Resize the property sheet */
826  TRACE("setting dialog %p, rc (0,0)-(%d,%d)\n",
827  hwndDlg, rc.right, rc.bottom);
828  SetWindowPos(hwndDlg, 0, 0, 0, rc.right - rc.left, rc.bottom - rc.top,
830 
831  return TRUE;
832 }
833 
834 /******************************************************************************
835  * PROPSHEET_AdjustButtons
836  *
837  * Adjusts the buttons' positions.
838  */
840 {
841  HWND hwndButton = GetDlgItem(hwndParent, IDOK);
842  RECT rcSheet;
843  int x, y;
844  int num_buttons = 2;
845  int buttonWidth, buttonHeight;
847 
848  if (psInfo->hasApply)
849  num_buttons++;
850 
851  if (psInfo->hasHelp)
852  num_buttons++;
853 
854  /*
855  * Obtain the size of the buttons.
856  */
857  GetClientRect(hwndButton, &rcSheet);
858  buttonWidth = rcSheet.right;
859  buttonHeight = rcSheet.bottom;
860 
861  /*
862  * Get the size of the property sheet.
863  */
864  GetClientRect(hwndParent, &rcSheet);
865 
866  /*
867  * All buttons will be at this y coordinate.
868  */
869  y = rcSheet.bottom - (padding.y + buttonHeight);
870 
871  /*
872  * Position OK button and make it default.
873  */
874  hwndButton = GetDlgItem(hwndParent, IDOK);
875 
876  x = rcSheet.right - ((padding.x + buttonWidth) * num_buttons);
877 
878  SetWindowPos(hwndButton, 0, x, y, 0, 0,
880 
882 
883 
884  /*
885  * Position Cancel button.
886  */
887  hwndButton = GetDlgItem(hwndParent, IDCANCEL);
888 
889  x += padding.x + buttonWidth;
890 
891  SetWindowPos(hwndButton, 0, x, y, 0, 0,
893 
894  /*
895  * Position Apply button.
896  */
897  hwndButton = GetDlgItem(hwndParent, IDC_APPLY_BUTTON);
898 
899  if(psInfo->hasApply)
900  x += padding.x + buttonWidth;
901  else
902  ShowWindow(hwndButton, SW_HIDE);
903 
904  SetWindowPos(hwndButton, 0, x, y, 0, 0,
906  EnableWindow(hwndButton, FALSE);
907 
908  /*
909  * Position Help button.
910  */
911  hwndButton = GetDlgItem(hwndParent, IDHELP);
912 
913  x += padding.x + buttonWidth;
914  SetWindowPos(hwndButton, 0, x, y, 0, 0,
916 
917  if(!psInfo->hasHelp)
918  ShowWindow(hwndButton, SW_HIDE);
919 
920  return TRUE;
921 }
922 
923 /******************************************************************************
924  * PROPSHEET_AdjustButtonsWizard
925  *
926  * Adjusts the buttons' positions.
927  */
929  const PropSheetInfo* psInfo)
930 {
931  HWND hwndButton = GetDlgItem(hwndParent, IDCANCEL);
933  HWND hwndLineHeader = GetDlgItem(hwndParent, IDC_SUNKEN_LINEHEADER);
934  RECT rcSheet;
935  int x, y;
936  int num_buttons = 3;
937  int buttonWidth, buttonHeight, lineHeight, lineWidth;
939 
940  if (psInfo->hasHelp)
941  num_buttons++;
942  if (psInfo->hasFinish)
943  num_buttons++;
944 
945  /*
946  * Obtain the size of the buttons.
947  */
948  GetClientRect(hwndButton, &rcSheet);
949  buttonWidth = rcSheet.right;
950  buttonHeight = rcSheet.bottom;
951 
952  GetClientRect(hwndLine, &rcSheet);
953  lineHeight = rcSheet.bottom;
954 
955  /*
956  * Get the size of the property sheet.
957  */
958  GetClientRect(hwndParent, &rcSheet);
959 
960  /*
961  * All buttons will be at this y coordinate.
962  */
963  y = rcSheet.bottom - (padding.y + buttonHeight);
964 
965  /*
966  * Position the Back button.
967  */
968  hwndButton = GetDlgItem(hwndParent, IDC_BACK_BUTTON);
969 
970  x = rcSheet.right - ((padding.x + buttonWidth) * (num_buttons - 1)) - buttonWidth;
971 
972  SetWindowPos(hwndButton, 0, x, y, 0, 0,
974 
975  /*
976  * Position the Next button.
977  */
978  hwndButton = GetDlgItem(hwndParent, IDC_NEXT_BUTTON);
979 
980  x += buttonWidth;
981 
982  SetWindowPos(hwndButton, 0, x, y, 0, 0,
984 
985  /*
986  * Position the Finish button.
987  */
988  hwndButton = GetDlgItem(hwndParent, IDC_FINISH_BUTTON);
989 
990  if (psInfo->hasFinish)
991  x += padding.x + buttonWidth;
992 
993  SetWindowPos(hwndButton, 0, x, y, 0, 0,
995 
996  if (!psInfo->hasFinish)
997  ShowWindow(hwndButton, SW_HIDE);
998 
999  /*
1000  * Position the Cancel button.
1001  */
1002  hwndButton = GetDlgItem(hwndParent, IDCANCEL);
1003 
1004  x += padding.x + buttonWidth;
1005 
1006  SetWindowPos(hwndButton, 0, x, y, 0, 0,
1008 
1009  /*
1010  * Position Help button.
1011  */
1012  hwndButton = GetDlgItem(hwndParent, IDHELP);
1013 
1014  if (psInfo->hasHelp)
1015  {
1016  x += padding.x + buttonWidth;
1017 
1018  SetWindowPos(hwndButton, 0, x, y, 0, 0,
1020  }
1021  else
1022  ShowWindow(hwndButton, SW_HIDE);
1023 
1024  if (psInfo->ppshheader.dwFlags &
1025  (PSH_WIZARD97_OLD | PSH_WIZARD97_NEW | PSH_WIZARD_LITE))
1026  padding.x = 0;
1027 
1028  /*
1029  * Position and resize the sunken line.
1030  */
1031  x = padding.x;
1032  y = rcSheet.bottom - ((padding.y * 2) + buttonHeight + lineHeight);
1033 
1034  lineWidth = rcSheet.right - (padding.x * 2);
1035  SetWindowPos(hwndLine, 0, x, y, lineWidth, 2,
1037 
1038  /*
1039  * Position and resize the header sunken line.
1040  */
1041 
1042  SetWindowPos(hwndLineHeader, 0, 0, 0, rcSheet.right, 2,
1044  if (!(psInfo->ppshheader.dwFlags & (PSH_WIZARD97_OLD | PSH_WIZARD97_NEW)))
1045  ShowWindow(hwndLineHeader, SW_HIDE);
1046 
1047  return TRUE;
1048 }
1049 
1050 /******************************************************************************
1051  * PROPSHEET_GetPaddingInfo
1052  *
1053  * Returns the layout information.
1054  */
1056 {
1057  HWND hwndTab = GetDlgItem(hwndDlg, IDC_TABCONTROL);
1058  RECT rcTab;
1060 
1061  GetWindowRect(hwndTab, &rcTab);
1062  MapWindowPoints( 0, hwndDlg, (POINT *)&rcTab, 2 );
1063 
1064  padding.x = rcTab.left;
1065  padding.y = rcTab.top;
1066 
1067  return padding;
1068 }
1069 
1070 /******************************************************************************
1071  * PROPSHEET_GetPaddingInfoWizard
1072  *
1073  * Returns the layout information.
1074  * Vertical spacing is the distance between the line and the buttons.
1075  * Do NOT use the Help button to gather padding information when it isn't mapped
1076  * (PSH_HASHELP), as app writers aren't forced to supply correct coordinates
1077  * for it in this case !
1078  * FIXME: I'm not sure about any other coordinate problems with these evil
1079  * buttons. Fix it in case additional problems appear or maybe calculate
1080  * a padding in a completely different way, as this is somewhat messy.
1081  */
1083  psInfo)
1084 {
1086  RECT rc;
1087  HWND hwndControl;
1088  INT idButton;
1089  POINT ptButton, ptLine;
1090 
1091  TRACE("\n");
1092  if (psInfo->hasHelp)
1093  {
1094  idButton = IDHELP;
1095  }
1096  else
1097  {
1098  if (psInfo->ppshheader.dwFlags & INTRNL_ANY_WIZARD)
1099  {
1100  idButton = IDC_NEXT_BUTTON;
1101  }
1102  else
1103  {
1104  /* hopefully this is ok */
1105  idButton = IDCANCEL;
1106  }
1107  }
1108 
1109  hwndControl = GetDlgItem(hwndDlg, idButton);
1110  GetWindowRect(hwndControl, &rc);
1111  MapWindowPoints( 0, hwndDlg, (POINT *)&rc, 2 );
1112  ptButton.x = rc.left;
1113  ptButton.y = rc.top;
1114 
1115  /* Line */
1116  hwndControl = GetDlgItem(hwndDlg, IDC_SUNKEN_LINE);
1117  GetWindowRect(hwndControl, &rc);
1118  MapWindowPoints( 0, hwndDlg, (POINT *)&rc, 2 );
1119  ptLine.x = rc.left;
1120  ptLine.y = rc.bottom;
1121 
1122  padding.y = ptButton.y - ptLine.y;
1123 
1124  if (padding.y < 0)
1125  ERR("padding negative ! Please report this !\n");
1126 
1127  /* this is most probably not correct, but the best we have now */
1128  padding.x = padding.y;
1129  return padding;
1130 }
1131 
1132 /******************************************************************************
1133  * PROPSHEET_CreateTabControl
1134  *
1135  * Insert the tabs in the tab control.
1136  */
1138  const PropSheetInfo * psInfo)
1139 {
1140  HWND hwndTabCtrl = GetDlgItem(hwndParent, IDC_TABCONTROL);
1141  TCITEMW item;
1142  int i, nTabs;
1143  int iImage = 0;
1144 
1145  TRACE("\n");
1146  item.mask = TCIF_TEXT;
1147  item.cchTextMax = MAX_TABTEXT_LENGTH;
1148 
1149  nTabs = psInfo->nPages;
1150 
1151  /*
1152  * Set the image list for icons.
1153  */
1154  if (psInfo->hImageList)
1155  {
1156  SendMessageW(hwndTabCtrl, TCM_SETIMAGELIST, 0, (LPARAM)psInfo->hImageList);
1157  }
1158 
1159  SendMessageW(hwndTabCtrl, WM_SETREDRAW, 0, 0);
1160  for (i = 0; i < nTabs; i++)
1161  {
1162  if ( psInfo->proppage[i].hasIcon )
1163  {
1164  item.mask |= TCIF_IMAGE;
1165  item.iImage = iImage++;
1166  }
1167  else
1168  {
1169  item.mask &= ~TCIF_IMAGE;
1170  }
1171 
1172  item.pszText = (LPWSTR) psInfo->proppage[i].pszText;
1173  SendMessageW(hwndTabCtrl, TCM_INSERTITEMW, i, (LPARAM)&item);
1174  }
1175  SendMessageW(hwndTabCtrl, WM_SETREDRAW, 1, 0);
1176 
1177  return TRUE;
1178 }
1179 
1180 /******************************************************************************
1181  * PROPSHEET_WizardSubclassProc
1182  *
1183  * Subclassing window procedure for wizard exterior pages to prevent drawing
1184  * background and so drawing above the watermark.
1185  */
1186 static LRESULT CALLBACK
1188 {
1189  switch (uMsg)
1190  {
1191  case WM_ERASEBKGND:
1192  return TRUE;
1193 
1194  case WM_CTLCOLORSTATIC:
1197  }
1198 
1199  return DefSubclassProc(hwnd, uMsg, wParam, lParam);
1200 }
1201 
1202 /*
1203  * Get the size of an in-memory Template
1204  *
1205  *( Based on the code of PROPSHEET_CollectPageInfo)
1206  * See also dialog.c/DIALOG_ParseTemplate32().
1207  */
1208 
1209 static UINT GetTemplateSize(const DLGTEMPLATE* pTemplate)
1210 
1211 {
1212  const WORD* p = (const WORD *)pTemplate;
1213  BOOL istemplateex = (((const MyDLGTEMPLATEEX*)pTemplate)->signature == 0xFFFF);
1214  WORD nrofitems;
1215  UINT ret;
1216 
1217  if (istemplateex)
1218  {
1219  /* DLGTEMPLATEEX (not defined in any std. header file) */
1220 
1221  TRACE("is DLGTEMPLATEEX\n");
1222  p++; /* dlgVer */
1223  p++; /* signature */
1224  p += 2; /* help ID */
1225  p += 2; /* ext style */
1226  p += 2; /* style */
1227  }
1228  else
1229  {
1230  /* DLGTEMPLATE */
1231 
1232  TRACE("is DLGTEMPLATE\n");
1233  p += 2; /* style */
1234  p += 2; /* ext style */
1235  }
1236 
1237  nrofitems = (WORD)*p; p++; /* nb items */
1238  p++; /* x */
1239  p++; /* y */
1240  p++; /* width */
1241  p++; /* height */
1242 
1243  /* menu */
1244  switch ((WORD)*p)
1245  {
1246  case 0x0000:
1247  p++;
1248  break;
1249  case 0xffff:
1250  p += 2;
1251  break;
1252  default:
1253  TRACE("menu %s\n",debugstr_w( p ));
1254  p += lstrlenW( p ) + 1;
1255  break;
1256  }
1257 
1258  /* class */
1259  switch ((WORD)*p)
1260  {
1261  case 0x0000:
1262  p++;
1263  break;
1264  case 0xffff:
1265  p += 2; /* 0xffff plus predefined window class ordinal value */
1266  break;
1267  default:
1268  TRACE("class %s\n",debugstr_w( p ));
1269  p += lstrlenW( p ) + 1;
1270  break;
1271  }
1272 
1273  /* title */
1274  TRACE("title %s\n",debugstr_w( p ));
1275  p += lstrlenW( p ) + 1;
1276 
1277  /* font, if DS_SETFONT set */
1278  if ((DS_SETFONT & ((istemplateex)? ((const MyDLGTEMPLATEEX*)pTemplate)->style :
1279  pTemplate->style)))
1280  {
1281  p+=(istemplateex)?3:1;
1282  TRACE("font %s\n",debugstr_w( p ));
1283  p += lstrlenW( p ) + 1; /* the font name */
1284  }
1285 
1286  /* now process the DLGITEMTEMPLATE(EX) structs (plus custom data)
1287  * that are following the DLGTEMPLATE(EX) data */
1288  TRACE("%d items\n",nrofitems);
1289  while (nrofitems > 0)
1290  {
1291  p = (WORD*)(((DWORD_PTR)p + 3) & ~3); /* DWORD align */
1292 
1293  /* skip header */
1294  p += (istemplateex ? sizeof(MyDLGITEMTEMPLATEEX) : sizeof(DLGITEMTEMPLATE))/sizeof(WORD);
1295 
1296  /* check class */
1297  switch ((WORD)*p)
1298  {
1299  case 0x0000:
1300  p++;
1301  break;
1302  case 0xffff:
1303  TRACE("class ordinal 0x%08x\n",*(const DWORD*)p);
1304  p += 2;
1305  break;
1306  default:
1307  TRACE("class %s\n",debugstr_w( p ));
1308  p += lstrlenW( p ) + 1;
1309  break;
1310  }
1311 
1312  /* check title text */
1313  switch ((WORD)*p)
1314  {
1315  case 0x0000:
1316  p++;
1317  break;
1318  case 0xffff:
1319  TRACE("text ordinal 0x%08x\n",*(const DWORD*)p);
1320  p += 2;
1321  break;
1322  default:
1323  TRACE("text %s\n",debugstr_w( p ));
1324  p += lstrlenW( p ) + 1;
1325  break;
1326  }
1327  p += *p / sizeof(WORD) + 1; /* Skip extra data */
1328  --nrofitems;
1329  }
1330 
1331  ret = (p - (const WORD*)pTemplate) * sizeof(WORD);
1332  TRACE("%p %p size 0x%08x\n", p, pTemplate, ret);
1333  return ret;
1334 }
1335 
1336 #ifdef __REACTOS__
1337 static void PROPSHEET_UnChanged(HWND hwndDlg, HWND hwndCleanPage);
1338 #endif
1339 /******************************************************************************
1340  * PROPSHEET_CreatePage
1341  *
1342  * Creates a page.
1343  */
1345  int index,
1346  const PropSheetInfo * psInfo,
1347  LPCPROPSHEETPAGEW ppshpage)
1348 {
1349  const DLGTEMPLATE* pTemplate;
1350  HWND hwndPage;
1351  DWORD resSize;
1352  DLGTEMPLATE* pTemplateCopy = NULL;
1353 
1354  TRACE("index %d\n", index);
1355 
1356  if (ppshpage == NULL)
1357  {
1358  return FALSE;
1359  }
1360 
1361  if (ppshpage->dwFlags & PSP_DLGINDIRECT)
1362  {
1363  pTemplate = ppshpage->u.pResource;
1364  resSize = GetTemplateSize(pTemplate);
1365  }
1366  else if(ppshpage->dwFlags & PSP_INTERNAL_UNICODE)
1367  {
1368  HRSRC hResource;
1369  HANDLE hTemplate;
1370 
1371  hResource = FindResourceW(ppshpage->hInstance,
1372  ppshpage->u.pszTemplate,
1373  (LPWSTR)RT_DIALOG);
1374  if(!hResource)
1375  return FALSE;
1376 
1377  resSize = SizeofResource(ppshpage->hInstance, hResource);
1378 
1379  hTemplate = LoadResource(ppshpage->hInstance, hResource);
1380  if(!hTemplate)
1381  return FALSE;
1382 
1383  pTemplate = LockResource(hTemplate);
1384  /*
1385  * Make a copy of the dialog template to make it writable
1386  */
1387  }
1388  else
1389  {
1390  HRSRC hResource;
1391  HANDLE hTemplate;
1392 
1393  hResource = FindResourceA(ppshpage->hInstance,
1394  (LPCSTR)ppshpage->u.pszTemplate,
1395  (LPSTR)RT_DIALOG);
1396  if(!hResource)
1397  return FALSE;
1398 
1399  resSize = SizeofResource(ppshpage->hInstance, hResource);
1400 
1401  hTemplate = LoadResource(ppshpage->hInstance, hResource);
1402  if(!hTemplate)
1403  return FALSE;
1404 
1405  pTemplate = LockResource(hTemplate);
1406  /*
1407  * Make a copy of the dialog template to make it writable
1408  */
1409  }
1410  pTemplateCopy = Alloc(resSize);
1411  if (!pTemplateCopy)
1412  return FALSE;
1413 
1414  TRACE("copying pTemplate %p into pTemplateCopy %p (%d)\n", pTemplate, pTemplateCopy, resSize);
1415  memcpy(pTemplateCopy, pTemplate, resSize);
1416 
1417  if (((MyDLGTEMPLATEEX*)pTemplateCopy)->signature == 0xFFFF)
1418  {
1419  ((MyDLGTEMPLATEEX*)pTemplateCopy)->style |= WS_CHILD | WS_TABSTOP | DS_CONTROL;
1420  ((MyDLGTEMPLATEEX*)pTemplateCopy)->style &= ~DS_MODALFRAME;
1421  ((MyDLGTEMPLATEEX*)pTemplateCopy)->style &= ~WS_CAPTION;
1422  ((MyDLGTEMPLATEEX*)pTemplateCopy)->style &= ~WS_SYSMENU;
1423  ((MyDLGTEMPLATEEX*)pTemplateCopy)->style &= ~WS_POPUP;
1424  ((MyDLGTEMPLATEEX*)pTemplateCopy)->style &= ~WS_DISABLED;
1425  ((MyDLGTEMPLATEEX*)pTemplateCopy)->style &= ~WS_VISIBLE;
1426  ((MyDLGTEMPLATEEX*)pTemplateCopy)->style &= ~WS_THICKFRAME;
1427 
1428  ((MyDLGTEMPLATEEX*)pTemplateCopy)->exStyle |= WS_EX_CONTROLPARENT;
1429  }
1430  else
1431  {
1432  pTemplateCopy->style |= WS_CHILD | WS_TABSTOP | DS_CONTROL;
1433  pTemplateCopy->style &= ~DS_MODALFRAME;
1434  pTemplateCopy->style &= ~WS_CAPTION;
1435  pTemplateCopy->style &= ~WS_SYSMENU;
1436  pTemplateCopy->style &= ~WS_POPUP;
1437  pTemplateCopy->style &= ~WS_DISABLED;
1438  pTemplateCopy->style &= ~WS_VISIBLE;
1439  pTemplateCopy->style &= ~WS_THICKFRAME;
1440 
1441  pTemplateCopy->dwExtendedStyle |= WS_EX_CONTROLPARENT;
1442  }
1443 
1444  if (psInfo->proppage[index].useCallback)
1445  (*(ppshpage->pfnCallback))(0, PSPCB_CREATE,
1446  (LPPROPSHEETPAGEW)ppshpage);
1447 
1448  if(ppshpage->dwFlags & PSP_INTERNAL_UNICODE)
1449  hwndPage = CreateDialogIndirectParamW(ppshpage->hInstance,
1450  pTemplateCopy,
1451  hwndParent,
1452  ppshpage->pfnDlgProc,
1453  (LPARAM)ppshpage);
1454  else
1455  hwndPage = CreateDialogIndirectParamA(ppshpage->hInstance,
1456  pTemplateCopy,
1457  hwndParent,
1458  ppshpage->pfnDlgProc,
1459  (LPARAM)ppshpage);
1460  /* Free a no more needed copy */
1461  Free(pTemplateCopy);
1462 
1463  if(!hwndPage)
1464  return FALSE;
1465 
1466  psInfo->proppage[index].hwndPage = hwndPage;
1467 
1468  /* Subclass exterior wizard pages */
1469  if((psInfo->ppshheader.dwFlags & (PSH_WIZARD97_NEW | PSH_WIZARD97_OLD)) &&
1470  (psInfo->ppshheader.dwFlags & PSH_WATERMARK) &&
1471  (ppshpage->dwFlags & PSP_HIDEHEADER))
1472  {
1474  (DWORD_PTR)ppshpage);
1475  }
1476  if (!(psInfo->ppshheader.dwFlags & INTRNL_ANY_WIZARD))
1478 
1479 #ifdef __REACTOS__
1480  PROPSHEET_UnChanged(hwndParent, hwndPage);
1481 #endif
1482  return TRUE;
1483 }
1484 
1485 /******************************************************************************
1486  * PROPSHEET_LoadWizardBitmaps
1487  *
1488  * Loads the watermark and header bitmaps for a wizard.
1489  */
1491 {
1492  if (psInfo->ppshheader.dwFlags & (PSH_WIZARD97_NEW | PSH_WIZARD97_OLD))
1493  {
1494  /* if PSH_USEHBMWATERMARK is not set, load the resource from pszbmWatermark
1495  and put the HBITMAP in hbmWatermark. Thus all the rest of the code always
1496  considers hbmWatermark as valid. */
1497  if ((psInfo->ppshheader.dwFlags & PSH_WATERMARK) &&
1498  !(psInfo->ppshheader.dwFlags & PSH_USEHBMWATERMARK))
1499  {
1500  psInfo->ppshheader.u4.hbmWatermark =
1501  CreateMappedBitmap(psInfo->ppshheader.hInstance, (INT_PTR)psInfo->ppshheader.u4.pszbmWatermark, 0, NULL, 0);
1502  }
1503 
1504  /* Same behavior as for watermarks */
1505  if ((psInfo->ppshheader.dwFlags & PSH_HEADER) &&
1506  !(psInfo->ppshheader.dwFlags & PSH_USEHBMHEADER))
1507  {
1508  psInfo->ppshheader.u5.hbmHeader =
1509  CreateMappedBitmap(psInfo->ppshheader.hInstance, (INT_PTR)psInfo->ppshheader.u5.pszbmHeader, 0, NULL, 0);
1510  }
1511  }
1512 }
1513 
1514 
1515 /******************************************************************************
1516  * PROPSHEET_ShowPage
1517  *
1518  * Displays or creates the specified page.
1519  */
1520 static BOOL PROPSHEET_ShowPage(HWND hwndDlg, int index, PropSheetInfo * psInfo)
1521 {
1522  HWND hwndTabCtrl;
1523  HWND hwndLineHeader;
1524  HWND control;
1525  LPCPROPSHEETPAGEW ppshpage;
1526 
1527  TRACE("active_page %d, index %d\n", psInfo->active_page, index);
1528  if (index == psInfo->active_page)
1529  {
1530  if (GetTopWindow(hwndDlg) != psInfo->proppage[index].hwndPage)
1531  SetWindowPos(psInfo->proppage[index].hwndPage, HWND_TOP, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE);
1532  return TRUE;
1533  }
1534 
1535  ppshpage = (LPCPROPSHEETPAGEW)psInfo->proppage[index].hpage;
1536  if (psInfo->proppage[index].hwndPage == 0)
1537  {
1538  PROPSHEET_CreatePage(hwndDlg, index, psInfo, ppshpage);
1539  }
1540 
1541  if (psInfo->ppshheader.dwFlags & INTRNL_ANY_WIZARD)
1542  {
1543  PROPSHEET_SetTitleW(hwndDlg, psInfo->ppshheader.dwFlags,
1544  psInfo->proppage[index].pszText);
1545 
1546  control = GetNextDlgTabItem(psInfo->proppage[index].hwndPage, NULL, FALSE);
1547  if(control != NULL)
1548  SetFocus(control);
1549  }
1550 
1551  if (psInfo->active_page != -1)
1552  ShowWindow(psInfo->proppage[psInfo->active_page].hwndPage, SW_HIDE);
1553 
1555 
1556  /* Synchronize current selection with tab control
1557  * It seems to be needed even in case of PSH_WIZARD (no tab controls there) */
1558  hwndTabCtrl = GetDlgItem(hwndDlg, IDC_TABCONTROL);
1559  SendMessageW(hwndTabCtrl, TCM_SETCURSEL, index, 0);
1560 
1561  psInfo->active_page = index;
1562  psInfo->activeValid = TRUE;
1563 
1564  if (psInfo->ppshheader.dwFlags & (PSH_WIZARD97_OLD | PSH_WIZARD97_NEW) )
1565  {
1566  hwndLineHeader = GetDlgItem(hwndDlg, IDC_SUNKEN_LINEHEADER);
1567  ppshpage = (LPCPROPSHEETPAGEW)psInfo->proppage[index].hpage;
1568 
1569  if ((ppshpage->dwFlags & PSP_HIDEHEADER) || (!(psInfo->ppshheader.dwFlags & PSH_HEADER)) )
1570  ShowWindow(hwndLineHeader, SW_HIDE);
1571  else
1572  ShowWindow(hwndLineHeader, SW_SHOW);
1573  }
1574 
1575  return TRUE;
1576 }
1577 
1578 /******************************************************************************
1579  * PROPSHEET_Back
1580  */
1581 static BOOL PROPSHEET_Back(HWND hwndDlg)
1582 {
1583  PSHNOTIFY psn;
1584  HWND hwndPage;
1585  PropSheetInfo* psInfo = GetPropW(hwndDlg, PropSheetInfoStr);
1586  LRESULT result;
1587  int idx;
1588 
1589  TRACE("active_page %d\n", psInfo->active_page);
1590  if (psInfo->active_page < 0)
1591  return FALSE;
1592 
1593  psn.hdr.code = PSN_WIZBACK;
1594  psn.hdr.hwndFrom = hwndDlg;
1595  psn.hdr.idFrom = 0;
1596  psn.lParam = 0;
1597 
1598  hwndPage = psInfo->proppage[psInfo->active_page].hwndPage;
1599 
1600  result = SendMessageW(hwndPage, WM_NOTIFY, 0, (LPARAM) &psn);
1601  if (result == -1)
1602  return FALSE;
1603  else if (result == 0)
1604  idx = psInfo->active_page - 1;
1605  else
1607 
1608  if (idx >= 0 && idx < psInfo->nPages)
1609  {
1610  if (PROPSHEET_CanSetCurSel(hwndDlg))
1611  {
1612  SetFocus(GetDlgItem(hwndDlg, IDC_BACK_BUTTON));
1614  PROPSHEET_SetCurSel(hwndDlg, idx, -1, 0);
1615  }
1616  }
1617  return TRUE;
1618 }
1619 
1620 /******************************************************************************
1621  * PROPSHEET_Next
1622  */
1623 static BOOL PROPSHEET_Next(HWND hwndDlg)
1624 {
1625  PSHNOTIFY psn;
1626  HWND hwndPage;
1627  LRESULT msgResult = 0;
1628  PropSheetInfo* psInfo = GetPropW(hwndDlg, PropSheetInfoStr);
1629  int idx;
1630 
1631  TRACE("active_page %d\n", psInfo->active_page);
1632  if (psInfo->active_page < 0)
1633  return FALSE;
1634 
1635  psn.hdr.code = PSN_WIZNEXT;
1636  psn.hdr.hwndFrom = hwndDlg;
1637  psn.hdr.idFrom = 0;
1638  psn.lParam = 0;
1639 
1640  hwndPage = psInfo->proppage[psInfo->active_page].hwndPage;
1641 
1642  msgResult = SendMessageW(hwndPage, WM_NOTIFY, 0, (LPARAM) &psn);
1643  if (msgResult == -1)
1644  return FALSE;
1645  else if (msgResult == 0)
1646  idx = psInfo->active_page + 1;
1647  else
1648  idx = PROPSHEET_FindPageByResId(psInfo, msgResult);
1649 
1650  if (idx < psInfo->nPages )
1651  {
1652  if (PROPSHEET_CanSetCurSel(hwndDlg) != FALSE)
1653  {
1654  SetFocus(GetDlgItem(hwndDlg, IDC_NEXT_BUTTON));
1656  PROPSHEET_SetCurSel(hwndDlg, idx, 1, 0);
1657  }
1658  }
1659 
1660  return TRUE;
1661 }
1662 
1663 /******************************************************************************
1664  * PROPSHEET_Finish
1665  */
1666 static BOOL PROPSHEET_Finish(HWND hwndDlg)
1667 {
1668  PSHNOTIFY psn;
1669  HWND hwndPage;
1670  LRESULT msgResult = 0;
1671  PropSheetInfo* psInfo = GetPropW(hwndDlg, PropSheetInfoStr);
1672 
1673  TRACE("active_page %d\n", psInfo->active_page);
1674  if (psInfo->active_page < 0)
1675  return FALSE;
1676 
1677  psn.hdr.code = PSN_WIZFINISH;
1678  psn.hdr.hwndFrom = hwndDlg;
1679  psn.hdr.idFrom = 0;
1680  psn.lParam = 0;
1681 
1682  hwndPage = psInfo->proppage[psInfo->active_page].hwndPage;
1683 
1684  msgResult = SendMessageW(hwndPage, WM_NOTIFY, 0, (LPARAM) &psn);
1685 
1686  TRACE("msg result %ld\n", msgResult);
1687 
1688  if (msgResult != 0)
1689  return FALSE;
1690 
1691  if (psInfo->result == 0)
1692  psInfo->result = IDOK;
1693  if (psInfo->isModeless)
1694  psInfo->activeValid = FALSE;
1695  else
1696  psInfo->ended = TRUE;
1697 
1698  return TRUE;
1699 }
1700 
1701 /******************************************************************************
1702  * PROPSHEET_Apply
1703  */
1705 {
1706  int i;
1707  HWND hwndPage;
1708  PSHNOTIFY psn;
1709  PropSheetInfo* psInfo = GetPropW(hwndDlg, PropSheetInfoStr);
1710 
1711  TRACE("active_page %d\n", psInfo->active_page);
1712  if (psInfo->active_page < 0)
1713  return FALSE;
1714 
1715  psn.hdr.hwndFrom = hwndDlg;
1716  psn.hdr.idFrom = 0;
1717  psn.lParam = 0;
1718 
1719 
1720  /*
1721  * Send PSN_KILLACTIVE to the current page.
1722  */
1723  psn.hdr.code = PSN_KILLACTIVE;
1724 
1725  hwndPage = psInfo->proppage[psInfo->active_page].hwndPage;
1726 
1727  if (SendMessageW(hwndPage, WM_NOTIFY, 0, (LPARAM) &psn) != FALSE)
1728  return FALSE;
1729 
1730  /*
1731  * Send PSN_APPLY to all pages.
1732  */
1733  psn.hdr.code = PSN_APPLY;
1734  psn.lParam = lParam;
1735 
1736  for (i = 0; i < psInfo->nPages; i++)
1737  {
1738  hwndPage = psInfo->proppage[i].hwndPage;
1739  if (hwndPage)
1740  {
1741  switch (SendMessageW(hwndPage, WM_NOTIFY, 0, (LPARAM) &psn))
1742  {
1743  case PSNRET_INVALID:
1744  PROPSHEET_ShowPage(hwndDlg, i, psInfo);
1745  /* fall through */
1747  return FALSE;
1748  }
1749  }
1750  }
1751 
1752  if(lParam)
1753  {
1754  psInfo->activeValid = FALSE;
1755  }
1756  else if(psInfo->active_page >= 0)
1757  {
1758  psn.hdr.code = PSN_SETACTIVE;
1759  psn.lParam = 0;
1760  hwndPage = psInfo->proppage[psInfo->active_page].hwndPage;
1761  SendMessageW(hwndPage, WM_NOTIFY, 0, (LPARAM) &psn);
1762  }
1763 
1764  return TRUE;
1765 }
1766 
1767 /******************************************************************************
1768  * PROPSHEET_Cancel
1769  */
1770 static void PROPSHEET_Cancel(HWND hwndDlg, LPARAM lParam)
1771 {
1772  PropSheetInfo* psInfo = GetPropW(hwndDlg, PropSheetInfoStr);
1773  HWND hwndPage;
1774  PSHNOTIFY psn;
1775  int i;
1776 
1777  TRACE("active_page %d\n", psInfo->active_page);
1778  if (psInfo->active_page < 0)
1779  return;
1780 
1781  hwndPage = psInfo->proppage[psInfo->active_page].hwndPage;
1782  psn.hdr.code = PSN_QUERYCANCEL;
1783  psn.hdr.hwndFrom = hwndDlg;
1784  psn.hdr.idFrom = 0;
1785  psn.lParam = 0;
1786 
1787  if (SendMessageW(hwndPage, WM_NOTIFY, 0, (LPARAM) &psn))
1788  return;
1789 
1790  psn.hdr.code = PSN_RESET;
1791  psn.lParam = lParam;
1792 
1793  for (i = 0; i < psInfo->nPages; i++)
1794  {
1795  hwndPage = psInfo->proppage[i].hwndPage;
1796 
1797  if (hwndPage)
1798  SendMessageW(hwndPage, WM_NOTIFY, 0, (LPARAM) &psn);
1799  }
1800 
1801  if (psInfo->isModeless)
1802  {
1803  /* makes PSM_GETCURRENTPAGEHWND return NULL */
1804  psInfo->activeValid = FALSE;
1805  }
1806  else
1807  psInfo->ended = TRUE;
1808 }
1809 
1810 /******************************************************************************
1811  * PROPSHEET_Help
1812  */
1813 static void PROPSHEET_Help(HWND hwndDlg)
1814 {
1815  PropSheetInfo* psInfo = GetPropW(hwndDlg, PropSheetInfoStr);
1816  HWND hwndPage;
1817  PSHNOTIFY psn;
1818 
1819  TRACE("active_page %d\n", psInfo->active_page);
1820  if (psInfo->active_page < 0)
1821  return;
1822 
1823  hwndPage = psInfo->proppage[psInfo->active_page].hwndPage;
1824  psn.hdr.code = PSN_HELP;
1825  psn.hdr.hwndFrom = hwndDlg;
1826  psn.hdr.idFrom = 0;
1827  psn.lParam = 0;
1828 
1829  SendMessageW(hwndPage, WM_NOTIFY, 0, (LPARAM) &psn);
1830 }
1831 
1832 /******************************************************************************
1833  * PROPSHEET_Changed
1834  */
1835 static void PROPSHEET_Changed(HWND hwndDlg, HWND hwndDirtyPage)
1836 {
1837  int i;
1838  PropSheetInfo* psInfo = GetPropW(hwndDlg, PropSheetInfoStr);
1839 
1840  TRACE("\n");
1841  if (!psInfo) return;
1842  /*
1843  * Set the dirty flag of this page.
1844  */
1845  for (i = 0; i < psInfo->nPages; i++)
1846  {
1847  if (psInfo->proppage[i].hwndPage == hwndDirtyPage)
1848  psInfo->proppage[i].isDirty = TRUE;
1849  }
1850 
1851  /*
1852  * Enable the Apply button.
1853  */
1854  if (psInfo->hasApply)
1855  {
1856  HWND hwndApplyBtn = GetDlgItem(hwndDlg, IDC_APPLY_BUTTON);
1857 
1858  EnableWindow(hwndApplyBtn, TRUE);
1859  }
1860 }
1861 
1862 /******************************************************************************
1863  * PROPSHEET_UnChanged
1864  */
1865 static void PROPSHEET_UnChanged(HWND hwndDlg, HWND hwndCleanPage)
1866 {
1867  int i;
1868  BOOL noPageDirty = TRUE;
1869  HWND hwndApplyBtn = GetDlgItem(hwndDlg, IDC_APPLY_BUTTON);
1870  PropSheetInfo* psInfo = GetPropW(hwndDlg, PropSheetInfoStr);
1871 
1872  TRACE("\n");
1873  if ( !psInfo ) return;
1874  for (i = 0; i < psInfo->nPages; i++)
1875  {
1876  /* set the specified page as clean */
1877  if (psInfo->proppage[i].hwndPage == hwndCleanPage)
1878  psInfo->proppage[i].isDirty = FALSE;
1879 
1880  /* look to see if there are any dirty pages */
1881  if (psInfo->proppage[i].isDirty)
1882  noPageDirty = FALSE;
1883  }
1884 
1885  /*
1886  * Disable Apply button.
1887  */
1888  if (noPageDirty)
1889  EnableWindow(hwndApplyBtn, FALSE);
1890 }
1891 
1892 /******************************************************************************
1893  * PROPSHEET_PressButton
1894  */
1895 static void PROPSHEET_PressButton(HWND hwndDlg, int buttonID)
1896 {
1897  TRACE("buttonID %d\n", buttonID);
1898  switch (buttonID)
1899  {
1900  case PSBTN_APPLYNOW:
1902  break;
1903  case PSBTN_BACK:
1904  PROPSHEET_Back(hwndDlg);
1905  break;
1906  case PSBTN_CANCEL:
1907  PROPSHEET_DoCommand(hwndDlg, IDCANCEL);
1908  break;
1909  case PSBTN_FINISH:
1910  PROPSHEET_Finish(hwndDlg);
1911  break;
1912  case PSBTN_HELP:
1913  PROPSHEET_DoCommand(hwndDlg, IDHELP);
1914  break;
1915  case PSBTN_NEXT:
1916  PROPSHEET_Next(hwndDlg);
1917  break;
1918  case PSBTN_OK:
1919  PROPSHEET_DoCommand(hwndDlg, IDOK);
1920  break;
1921  default:
1922  FIXME("Invalid button index %d\n", buttonID);
1923  }
1924 }
1925 
1926 
1927 /*************************************************************************
1928  * BOOL PROPSHEET_CanSetCurSel [Internal]
1929  *
1930  * Test whether the current page can be changed by sending a PSN_KILLACTIVE
1931  *
1932  * PARAMS
1933  * hwndDlg [I] handle to a Dialog hWnd
1934  *
1935  * RETURNS
1936  * TRUE if Current Selection can change
1937  *
1938  * NOTES
1939  */
1941 {
1942  PropSheetInfo* psInfo = GetPropW(hwndDlg, PropSheetInfoStr);
1943  HWND hwndPage;
1944  PSHNOTIFY psn;
1945  BOOL res = FALSE;
1946 
1947  if (!psInfo)
1948  {
1949  res = FALSE;
1950  goto end;
1951  }
1952 
1953  TRACE("active_page %d\n", psInfo->active_page);
1954  if (psInfo->active_page < 0)
1955  {
1956  res = TRUE;
1957  goto end;
1958  }
1959 
1960  /*
1961  * Notify the current page.
1962  */
1963  hwndPage = psInfo->proppage[psInfo->active_page].hwndPage;
1964  psn.hdr.code = PSN_KILLACTIVE;
1965  psn.hdr.hwndFrom = hwndDlg;
1966  psn.hdr.idFrom = 0;
1967  psn.lParam = 0;
1968 
1969  res = !SendMessageW(hwndPage, WM_NOTIFY, 0, (LPARAM) &psn);
1970 
1971 end:
1972  TRACE("<-- %d\n", res);
1973  return res;
1974 }
1975 
1976 /******************************************************************************
1977  * PROPSHEET_SetCurSel
1978  */
1980  int index,
1981  int skipdir,
1982  HPROPSHEETPAGE hpage
1983  )
1984 {
1985  PropSheetInfo* psInfo = GetPropW(hwndDlg, PropSheetInfoStr);
1986  HWND hwndHelp = GetDlgItem(hwndDlg, IDHELP);
1987  HWND hwndTabControl = GetDlgItem(hwndDlg, IDC_TABCONTROL);
1988 
1989  TRACE("index %d, skipdir %d, hpage %p\n", index, skipdir, hpage);
1990 
1991  index = PROPSHEET_GetPageIndex(hpage, psInfo, index);
1992 
1993  if (index < 0 || index >= psInfo->nPages)
1994  {
1995  TRACE("Could not find page to select!\n");
1996  return FALSE;
1997  }
1998 
1999  /* unset active page while doing this transition. */
2000  if (psInfo->active_page != -1)
2001  ShowWindow(psInfo->proppage[psInfo->active_page].hwndPage, SW_HIDE);
2002  psInfo->active_page = -1;
2003 
2004  while (1) {
2005  int result;
2006  PSHNOTIFY psn;
2007  RECT rc;
2009 
2010  if (hwndTabControl)
2011  SendMessageW(hwndTabControl, TCM_SETCURSEL, index, 0);
2012 
2013  psn.hdr.code = PSN_SETACTIVE;
2014  psn.hdr.hwndFrom = hwndDlg;
2015  psn.hdr.idFrom = 0;
2016  psn.lParam = 0;
2017 
2018  if (!psInfo->proppage[index].hwndPage) {
2019  if(!PROPSHEET_CreatePage(hwndDlg, index, psInfo, ppshpage)) {
2020  PROPSHEET_RemovePage(hwndDlg, index, NULL);
2021  if(index >= psInfo->nPages)
2022  index--;
2023  if(index < 0)
2024  return FALSE;
2025  continue;
2026  }
2027  }
2028 
2029  /* Resize the property sheet page to the fit in the Tab control
2030  * (for regular property sheets) or to fit in the client area (for
2031  * wizards).
2032  * NOTE: The resizing happens every time the page is selected and
2033  * not only when it's created (some applications depend on it). */
2034  PROPSHEET_GetPageRect(psInfo, hwndDlg, &rc, ppshpage);
2035  TRACE("setting page %p, rc (%s) w=%d, h=%d\n",
2036  psInfo->proppage[index].hwndPage, wine_dbgstr_rect(&rc),
2037  rc.right - rc.left, rc.bottom - rc.top);
2039  rc.left, rc.top,
2040  rc.right - rc.left, rc.bottom - rc.top, 0);
2041 
2042  result = SendMessageW(psInfo->proppage[index].hwndPage, WM_NOTIFY, 0, (LPARAM) &psn);
2043  if (!result)
2044  break;
2045  if (result == -1) {
2046  index+=skipdir;
2047  if (index < 0) {
2048  index = 0;
2049  WARN("Tried to skip before first property sheet page!\n");
2050  break;
2051  }
2052  if (index >= psInfo->nPages) {
2053  WARN("Tried to skip after last property sheet page!\n");
2054  index = psInfo->nPages-1;
2055  break;
2056  }
2057  }
2058  else if (result != 0)
2059  {
2060  int old_index = index;
2062  if(index >= psInfo->nPages) {
2063  index = old_index;
2064  WARN("Tried to skip to nonexistent page by res id\n");
2065  break;
2066  }
2067  continue;
2068  }
2069  }
2070 
2071  /* Invalidate the header area */
2072  if ( (psInfo->ppshheader.dwFlags & (PSH_WIZARD97_OLD | PSH_WIZARD97_NEW)) &&
2073  (psInfo->ppshheader.dwFlags & PSH_HEADER) )
2074  {
2075  HWND hwndLineHeader = GetDlgItem(hwndDlg, IDC_SUNKEN_LINEHEADER);
2076  RECT r;
2077 
2078  GetClientRect(hwndLineHeader, &r);
2079  MapWindowPoints(hwndLineHeader, hwndDlg, (LPPOINT) &r, 2);
2080  SetRect(&r, 0, 0, r.right + 1, r.top - 1);
2081 
2082  InvalidateRect(hwndDlg, &r, TRUE);
2083  }
2084 
2085  /*
2086  * Display the new page.
2087  */
2088  PROPSHEET_ShowPage(hwndDlg, index, psInfo);
2089 
2090  if (psInfo->proppage[index].hasHelp)
2091  EnableWindow(hwndHelp, TRUE);
2092  else
2093  EnableWindow(hwndHelp, FALSE);
2094 
2095  return TRUE;
2096 }
2097 
2098 /******************************************************************************
2099  * PROPSHEET_SetCurSelId
2100  *
2101  * Selects the page, specified by resource id.
2102  */
2103 static void PROPSHEET_SetCurSelId(HWND hwndDlg, int id)
2104 {
2105  int idx;
2106  PropSheetInfo* psInfo = GetPropW(hwndDlg, PropSheetInfoStr);
2107 
2108  idx = PROPSHEET_FindPageByResId(psInfo, id);
2109  if (idx < psInfo->nPages )
2110  {
2111  if (PROPSHEET_CanSetCurSel(hwndDlg) != FALSE)
2112  PROPSHEET_SetCurSel(hwndDlg, idx, 1, 0);
2113  }
2114 }
2115 
2116 /******************************************************************************
2117  * PROPSHEET_SetTitleA
2118  */
2119 static void PROPSHEET_SetTitleA(HWND hwndDlg, DWORD dwStyle, LPCSTR lpszText)
2120 {
2121  if(!IS_INTRESOURCE(lpszText))
2122  {
2123  WCHAR szTitle[256];
2124  MultiByteToWideChar(CP_ACP, 0, lpszText, -1, szTitle, ARRAY_SIZE(szTitle));
2125  PROPSHEET_SetTitleW(hwndDlg, dwStyle, szTitle);
2126  }
2127  else
2128  {
2129  PROPSHEET_SetTitleW(hwndDlg, dwStyle, (LPCWSTR)lpszText);
2130  }
2131 }
2132 
2133 /******************************************************************************
2134  * PROPSHEET_SetTitleW
2135  */
2136 static void PROPSHEET_SetTitleW(HWND hwndDlg, DWORD dwStyle, LPCWSTR lpszText)
2137 {
2138  PropSheetInfo* psInfo = GetPropW(hwndDlg, PropSheetInfoStr);
2139  WCHAR szTitle[256];
2140 
2141  TRACE("%s (style %08x)\n", debugstr_w(lpszText), dwStyle);
2142  if (IS_INTRESOURCE(lpszText)) {
2143  if (!LoadStringW(psInfo->ppshheader.hInstance, LOWORD(lpszText), szTitle, ARRAY_SIZE(szTitle)))
2144  return;
2145  lpszText = szTitle;
2146  }
2147  if (dwStyle & PSH_PROPTITLE)
2148  {
2149  WCHAR* dest;
2150  int lentitle = strlenW(lpszText);
2151  int lenprop = strlenW(psInfo->strPropertiesFor);
2152 
2153  dest = Alloc( (lentitle + lenprop + 1)*sizeof (WCHAR));
2154  wsprintfW(dest, psInfo->strPropertiesFor, lpszText);
2155 
2156  SetWindowTextW(hwndDlg, dest);
2157  Free(dest);
2158  }
2159  else
2160  SetWindowTextW(hwndDlg, lpszText);
2161 }
2162 
2163 /******************************************************************************
2164  * PROPSHEET_SetFinishTextA
2165  */
2166 static void PROPSHEET_SetFinishTextA(HWND hwndDlg, LPCSTR lpszText)
2167 {
2168  PropSheetInfo* psInfo = GetPropW(hwndDlg, PropSheetInfoStr);
2169  HWND hwndButton = GetDlgItem(hwndDlg, IDC_FINISH_BUTTON);
2170 
2171  TRACE("'%s'\n", lpszText);
2172  /* Set text, show and enable the Finish button */
2173  SetWindowTextA(hwndButton, lpszText);
2174  ShowWindow(hwndButton, SW_SHOW);
2175  EnableWindow(hwndButton, TRUE);
2176 
2177  /* Make it default pushbutton */
2179 
2180  /* Hide Back button */
2181  hwndButton = GetDlgItem(hwndDlg, IDC_BACK_BUTTON);
2182  ShowWindow(hwndButton, SW_HIDE);
2183 
2184  if (!psInfo->hasFinish)
2185  {
2186  /* Hide Next button */
2187  hwndButton = GetDlgItem(hwndDlg, IDC_NEXT_BUTTON);
2188  ShowWindow(hwndButton, SW_HIDE);
2189  }
2190 }
2191 
2192 /******************************************************************************
2193  * PROPSHEET_SetFinishTextW
2194  */
2195 static void PROPSHEET_SetFinishTextW(HWND hwndDlg, LPCWSTR lpszText)
2196 {
2197  PropSheetInfo* psInfo = GetPropW(hwndDlg, PropSheetInfoStr);
2198  HWND hwndButton = GetDlgItem(hwndDlg, IDC_FINISH_BUTTON);
2199 
2200  TRACE("%s\n", debugstr_w(lpszText));
2201  /* Set text, show and enable the Finish button */
2202  SetWindowTextW(hwndButton, lpszText);
2203  ShowWindow(hwndButton, SW_SHOW);
2204  EnableWindow(hwndButton, TRUE);
2205 
2206  /* Make it default pushbutton */
2208 
2209  /* Hide Back button */
2210  hwndButton = GetDlgItem(hwndDlg, IDC_BACK_BUTTON);
2211  ShowWindow(hwndButton, SW_HIDE);
2212 
2213  if (!psInfo->hasFinish)
2214  {
2215  /* Hide Next button */
2216  hwndButton = GetDlgItem(hwndDlg, IDC_NEXT_BUTTON);
2217  ShowWindow(hwndButton, SW_HIDE);
2218  }
2219 }
2220 
2221 /******************************************************************************
2222  * PROPSHEET_QuerySiblings
2223  */
2226 {
2227  int i = 0;
2228  HWND hwndPage;
2229  LRESULT msgResult = 0;
2230  PropSheetInfo* psInfo = GetPropW(hwndDlg, PropSheetInfoStr);
2231 
2232  while ((i < psInfo->nPages) && (msgResult == 0))
2233  {
2234  hwndPage = psInfo->proppage[i].hwndPage;
2235  msgResult = SendMessageW(hwndPage, PSM_QUERYSIBLINGS, wParam, lParam);
2236  i++;
2237  }
2238 
2239  return msgResult;
2240 }
2241 
2242 /******************************************************************************
2243  * PROPSHEET_InsertPage
2244  */
2245 static BOOL PROPSHEET_InsertPage(HWND hwndDlg, HPROPSHEETPAGE hpageInsertAfter, HPROPSHEETPAGE hpage)
2246 {
2247  PropSheetInfo *psInfo = GetPropW(hwndDlg, PropSheetInfoStr);
2248  PropPageInfo *ppi, *prev_ppi = psInfo->proppage;
2249  HWND hwndTabControl = GetDlgItem(hwndDlg, IDC_TABCONTROL);
2250  LPCPROPSHEETPAGEW ppsp = (LPCPROPSHEETPAGEW)hpage;
2251  TCITEMW item;
2252  int index;
2253 
2254  TRACE("hwndDlg %p, hpageInsertAfter %p, hpage %p\n", hwndDlg, hpageInsertAfter, hpage);
2255 
2256  if (IS_INTRESOURCE(hpageInsertAfter))
2257  index = LOWORD(hpageInsertAfter);
2258  else
2259  {
2260  index = PROPSHEET_GetPageIndex(hpageInsertAfter, psInfo, -1);
2261  if (index < 0)
2262  {
2263  TRACE("Could not find page to insert after!\n");
2264  return FALSE;
2265  }
2266  index++;
2267  }
2268 
2269  if (index > psInfo->nPages)
2270  index = psInfo->nPages;
2271 
2272  ppi = Alloc(sizeof(PropPageInfo) * (psInfo->nPages + 1));
2273  if (!ppi)
2274  return FALSE;
2275 
2276  /*
2277  * Fill in a new PropPageInfo entry.
2278  */
2279  if (index > 0)
2280  memcpy(ppi, prev_ppi, index * sizeof(PropPageInfo));
2281  memset(&ppi[index], 0, sizeof(PropPageInfo));
2282  if (index < psInfo->nPages)
2283  memcpy(&ppi[index + 1], &prev_ppi[index], (psInfo->nPages - index) * sizeof(PropPageInfo));
2284  psInfo->proppage = ppi;
2285 
2286  if (!PROPSHEET_CollectPageInfo(ppsp, psInfo, index, FALSE))
2287  {
2288  psInfo->proppage = prev_ppi;
2289  Free(ppi);
2290  return FALSE;
2291  }
2292 
2293  psInfo->proppage[index].hpage = hpage;
2294 
2295  if (ppsp->dwFlags & PSP_PREMATURE)
2296  {
2297  /* Create the page but don't show it */
2298  if (!PROPSHEET_CreatePage(hwndDlg, index, psInfo, ppsp))
2299  {
2300  psInfo->proppage = prev_ppi;
2301  Free(ppi);
2302  return FALSE;
2303  }
2304  }
2305 
2306  Free(prev_ppi);
2307  psInfo->nPages++;
2309  psInfo->active_page++;
2310 
2311  /*
2312  * Add a new tab to the tab control.
2313  */
2314  item.mask = TCIF_TEXT;
2315  item.pszText = (LPWSTR) psInfo->proppage[index].pszText;
2316  item.cchTextMax = MAX_TABTEXT_LENGTH;
2317 
2318  if (psInfo->hImageList)
2319  SendMessageW(hwndTabControl, TCM_SETIMAGELIST, 0, (LPARAM)psInfo->hImageList);
2320 
2321  if (psInfo->proppage[index].hasIcon)
2322  {
2323  item.mask |= TCIF_IMAGE;
2324  item.iImage = index;
2325  }
2326 
2327  SendMessageW(hwndTabControl, TCM_INSERTITEMW, index, (LPARAM)&item);
2328 
2329  /* If it is the only page - show it */
2330  if (psInfo->nPages == 1)
2331  PROPSHEET_SetCurSel(hwndDlg, 0, 1, 0);
2332 
2333  return TRUE;
2334 }
2335 
2336 /******************************************************************************
2337  * PROPSHEET_AddPage
2338  */
2340 {
2341  PropSheetInfo * psInfo = GetPropW(hwndDlg, PropSheetInfoStr);
2342  TRACE("hwndDlg %p, hpage %p\n", hwndDlg, hpage);
2343  return PROPSHEET_InsertPage(hwndDlg, UlongToPtr(psInfo->nPages), hpage);
2344 }
2345 
2346 /******************************************************************************
2347  * PROPSHEET_RemovePage
2348  */
2350  int index,
2351  HPROPSHEETPAGE hpage)
2352 {
2353  PropSheetInfo * psInfo = GetPropW(hwndDlg, PropSheetInfoStr);
2354  HWND hwndTabControl = GetDlgItem(hwndDlg, IDC_TABCONTROL);
2355  PropPageInfo* oldPages;
2356 
2357  TRACE("index %d, hpage %p\n", index, hpage);
2358  if (!psInfo) {
2359  return FALSE;
2360  }
2361 
2362  index = PROPSHEET_GetPageIndex(hpage, psInfo, index);
2363 
2364  /* Make sure that index is within range */
2365  if (index < 0 || index >= psInfo->nPages)
2366  {
2367  TRACE("Could not find page to remove!\n");
2368  return FALSE;
2369  }
2370 
2371  TRACE("total pages %d removing page %d active page %d\n",
2372  psInfo->nPages, index, psInfo->active_page);
2373  /*
2374  * Check if we're removing the active page.
2375  */
2376  if (index == psInfo->active_page)
2377  {
2378  if (psInfo->nPages > 1)
2379  {
2380  if (index > 0)
2381  {
2382  /* activate previous page */
2383  PROPSHEET_SetCurSel(hwndDlg, index - 1, -1, 0);
2384  }
2385  else
2386  {
2387  /* activate the next page */
2388  PROPSHEET_SetCurSel(hwndDlg, index + 1, 1, 0);
2389  psInfo->active_page = index;
2390  }
2391  }
2392  else
2393  {
2394  psInfo->active_page = -1;
2395  if (!psInfo->isModeless)
2396  {
2397  psInfo->ended = TRUE;
2398  return TRUE;
2399  }
2400  }
2401  }
2402  else if (index < psInfo->active_page)
2403  psInfo->active_page--;
2404 
2405  /* Unsubclass the page dialog window */
2406  if((psInfo->ppshheader.dwFlags & (PSH_WIZARD97_NEW | PSH_WIZARD97_OLD) &&
2407  (psInfo->ppshheader.dwFlags & PSH_WATERMARK) &&
2408  ((PROPSHEETPAGEW*)psInfo->proppage[index].hpage)->dwFlags & PSP_HIDEHEADER))
2409  {
2412  }
2413 
2414  /* Destroy page dialog window */
2416 
2417  /* Free page resources */
2418  if(psInfo->proppage[index].hpage)
2419  {
2420  PROPSHEETPAGEW* psp = (PROPSHEETPAGEW*)psInfo->proppage[index].hpage;
2421 
2422  if (psp->dwFlags & PSP_USETITLE)
2423  Free ((LPVOID)psInfo->proppage[index].pszText);
2424 
2426  }
2427 
2428  /* Remove the tab */
2429  SendMessageW(hwndTabControl, TCM_DELETEITEM, index, 0);
2430 
2431  oldPages = psInfo->proppage;
2432  psInfo->nPages--;
2433  psInfo->proppage = Alloc(sizeof(PropPageInfo) * psInfo->nPages);
2434 
2435  if (index > 0)
2436  memcpy(&psInfo->proppage[0], &oldPages[0], index * sizeof(PropPageInfo));
2437 
2438  if (index < psInfo->nPages)
2439  memcpy(&psInfo->proppage[index], &oldPages[index + 1],
2440  (psInfo->nPages - index) * sizeof(PropPageInfo));
2441 
2442  Free(oldPages);
2443 
2444  return FALSE;
2445 }
2446 
2447 /******************************************************************************
2448  * PROPSHEET_SetWizButtons
2449  *
2450  * This code will work if (and assumes that) the Next button is on top of the
2451  * Finish button. ie. Finish comes after Next in the Z order.
2452  * This means make sure the dialog template reflects this.
2453  *
2454  */
2456 {
2457  PropSheetInfo* psInfo = GetPropW(hwndDlg, PropSheetInfoStr);
2458  HWND hwndBack = GetDlgItem(hwndDlg, IDC_BACK_BUTTON);
2459  HWND hwndNext = GetDlgItem(hwndDlg, IDC_NEXT_BUTTON);
2460  HWND hwndFinish = GetDlgItem(hwndDlg, IDC_FINISH_BUTTON);
2461  BOOL enable_finish = ((dwFlags & PSWIZB_FINISH) || psInfo->hasFinish) && !(dwFlags & PSWIZB_DISABLEDFINISH);
2462 
2463 #ifdef __REACTOS__
2464  HWND hwndCancel = GetDlgItem(hwndDlg, IDCANCEL);
2465  INT iDefItem = 0;
2466  HWND hwndFocus;
2467 #endif
2468 
2469  TRACE("%d\n", dwFlags);
2470 
2471  EnableWindow(hwndBack, dwFlags & PSWIZB_BACK);
2472  EnableWindow(hwndNext, dwFlags & PSWIZB_NEXT);
2473  EnableWindow(hwndFinish, enable_finish);
2474 
2475 #ifndef __REACTOS__
2476  /* set the default pushbutton to an enabled button */
2477  if (enable_finish)
2479  else if (dwFlags & PSWIZB_NEXT)
2481  else if (dwFlags & PSWIZB_BACK)
2483  else
2484  SendMessageW(hwndDlg, DM_SETDEFID, IDCANCEL, 0);
2485 #endif
2486 
2487  if (!psInfo->hasFinish)
2488  {
2490  {
2491  /* Hide the Next button */
2492  ShowWindow(hwndNext, SW_HIDE);
2493 
2494  /* Show the Finish button */
2495  ShowWindow(hwndFinish, SW_SHOW);
2496  }
2497  else
2498  {
2499  /* Hide the Finish button */
2500  ShowWindow(hwndFinish, SW_HIDE);
2501  /* Show the Next button */
2502  ShowWindow(hwndNext, SW_SHOW);
2503  }
2504  }
2505 
2506 #ifdef __REACTOS__
2507  /* set the default pushbutton to an enabled button */
2508  if (((dwFlags & PSWIZB_FINISH) || psInfo->hasFinish) && !(dwFlags & PSWIZB_DISABLEDFINISH))
2509  iDefItem = IDC_FINISH_BUTTON;
2510  else if (dwFlags & PSWIZB_NEXT)
2511  iDefItem = IDC_NEXT_BUTTON;
2512  else if (dwFlags & PSWIZB_BACK)
2513  iDefItem = IDC_BACK_BUTTON;
2514  else
2515  iDefItem = IDCANCEL;
2516  SendMessageW(hwndDlg, DM_SETDEFID, iDefItem, 0);
2517 
2518  /* Set focus if no control has it */
2519  hwndFocus = GetFocus();
2520  if (!hwndFocus || hwndFocus == hwndCancel)
2521  SetFocus(GetDlgItem(hwndDlg, iDefItem));
2522 #endif
2523 
2524 }
2525 
2526 /******************************************************************************
2527  * PROPSHEET_SetHeaderTitleW
2528  */
2529 static void PROPSHEET_SetHeaderTitleW(HWND hwndDlg, UINT page_index, const WCHAR *title)
2530 {
2531  PropSheetInfo *psInfo = GetPropW(hwndDlg, PropSheetInfoStr);
2533 
2534  TRACE("(%p, %u, %s)\n", hwndDlg, page_index, debugstr_w(title));
2535 
2536  if (page_index >= psInfo->nPages)
2537  return;
2538 
2539  page = (PROPSHEETPAGEW *)psInfo->proppage[page_index].hpage;
2540 
2541  if (!IS_INTRESOURCE(page->pszHeaderTitle))
2542  Free((void *)page->pszHeaderTitle);
2543 
2544  page->pszHeaderTitle = heap_strdupW(title);
2545  page->dwFlags |= PSP_USEHEADERTITLE;
2546 }
2547 
2548 /******************************************************************************
2549  * PROPSHEET_SetHeaderTitleA
2550  */
2551 static void PROPSHEET_SetHeaderTitleA(HWND hwndDlg, UINT page_index, const char *title)
2552 {
2553  WCHAR *titleW;
2554 
2555  TRACE("(%p, %u, %s)\n", hwndDlg, page_index, debugstr_a(title));
2556 
2558  PROPSHEET_SetHeaderTitleW(hwndDlg, page_index, titleW);
2559  Free(titleW);
2560 }
2561 
2562 /******************************************************************************
2563  * PROPSHEET_SetHeaderSubTitleW
2564  */
2565 static void PROPSHEET_SetHeaderSubTitleW(HWND hwndDlg, UINT page_index, const WCHAR *subtitle)
2566 {
2567  PropSheetInfo *psInfo = GetPropW(hwndDlg, PropSheetInfoStr);
2569 
2570  TRACE("(%p, %u, %s)\n", hwndDlg, page_index, debugstr_w(subtitle));
2571 
2572  if (page_index >= psInfo->nPages)
2573  return;
2574 
2575  page = (PROPSHEETPAGEW *)psInfo->proppage[page_index].hpage;
2576 
2577  if (!IS_INTRESOURCE(page->pszHeaderSubTitle))
2578  Free((void *)page->pszHeaderSubTitle);
2579 
2580  page->pszHeaderSubTitle = heap_strdupW(subtitle);
2581  page->dwFlags |= PSP_USEHEADERSUBTITLE;
2582 }
2583 
2584 /******************************************************************************
2585  * PROPSHEET_SetHeaderSubTitleA
2586  */
2587 static void PROPSHEET_SetHeaderSubTitleA(HWND hwndDlg, UINT page_index, const char *subtitle)
2588 {
2589  WCHAR *subtitleW;
2590 
2591  TRACE("(%p, %u, %s)\n", hwndDlg, page_index, debugstr_a(subtitle));
2592 
2593  subtitleW = heap_strdupAtoW(subtitle);
2594  PROPSHEET_SetHeaderSubTitleW(hwndDlg, page_index, subtitleW);
2595  Free(subtitleW);
2596 }
2597 
2598 /******************************************************************************
2599  * PROPSHEET_HwndToIndex
2600  */
2601 static LRESULT PROPSHEET_HwndToIndex(HWND hwndDlg, HWND hPageDlg)
2602 {
2603  int index;
2604  PropSheetInfo * psInfo = GetPropW(hwndDlg, PropSheetInfoStr);
2605 
2606  TRACE("(%p, %p)\n", hwndDlg, hPageDlg);
2607 
2608  for (index = 0; index < psInfo->nPages; index++)
2609  if (psInfo->proppage[index].hwndPage == hPageDlg)
2610  return index;
2611  WARN("%p not found\n", hPageDlg);
2612  return -1;
2613 }
2614 
2615 /******************************************************************************
2616  * PROPSHEET_IndexToHwnd
2617  */
2618 static LRESULT PROPSHEET_IndexToHwnd(HWND hwndDlg, int iPageIndex)
2619 {
2620  PropSheetInfo * psInfo = GetPropW(hwndDlg, PropSheetInfoStr);
2621  TRACE("(%p, %d)\n", hwndDlg, iPageIndex);
2622  if (!psInfo)
2623  return 0;
2624  if (iPageIndex<0 || iPageIndex>=psInfo->nPages) {
2625  WARN("%d out of range.\n", iPageIndex);
2626  return 0;
2627  }
2628  return (LRESULT)psInfo->proppage[iPageIndex].hwndPage;
2629 }
2630 
2631 /******************************************************************************
2632  * PROPSHEET_PageToIndex
2633  */
2635 {
2636  PropSheetInfo * psInfo = GetPropW(hwndDlg, PropSheetInfoStr);
2637 
2638  TRACE("(%p, %p)\n", hwndDlg, hPage);
2639 
2640  return PROPSHEET_GetPageIndex(hPage, psInfo, -1);
2641 }
2642 
2643 /******************************************************************************
2644  * PROPSHEET_IndexToPage
2645  */
2646 static LRESULT PROPSHEET_IndexToPage(HWND hwndDlg, int iPageIndex)
2647 {
2648  PropSheetInfo * psInfo = GetPropW(hwndDlg, PropSheetInfoStr);
2649  TRACE("(%p, %d)\n", hwndDlg, iPageIndex);
2650  if (iPageIndex<0 || iPageIndex>=psInfo->nPages) {
2651  WARN("%d out of range.\n", iPageIndex);
2652  return 0;
2653  }
2654  return (LRESULT)psInfo->proppage[iPageIndex].hpage;
2655 }
2656 
2657 /******************************************************************************
2658  * PROPSHEET_IdToIndex
2659  */
2660 static LRESULT PROPSHEET_IdToIndex(HWND hwndDlg, int iPageId)
2661 {
2662  int index;
2663  LPCPROPSHEETPAGEW psp;
2664  PropSheetInfo * psInfo = GetPropW(hwndDlg, PropSheetInfoStr);
2665  TRACE("(%p, %d)\n", hwndDlg, iPageId);
2666  for (index = 0; index < psInfo->nPages; index++) {
2667  psp = (LPCPROPSHEETPAGEW)psInfo->proppage[index].hpage;
2668  if (psp->u.pszTemplate == MAKEINTRESOURCEW(iPageId))
2669  return index;
2670  }
2671 
2672  return -1;
2673 }
2674 
2675 /******************************************************************************
2676  * PROPSHEET_IndexToId
2677  */
2678 static LRESULT PROPSHEET_IndexToId(HWND hwndDlg, int iPageIndex)
2679 {
2680  PropSheetInfo * psInfo = GetPropW(hwndDlg, PropSheetInfoStr);
2681  LPCPROPSHEETPAGEW psp;
2682  TRACE("(%p, %d)\n", hwndDlg, iPageIndex);
2683  if (iPageIndex<0 || iPageIndex>=psInfo->nPages) {
2684  WARN("%d out of range.\n", iPageIndex);
2685  return 0;
2686  }
2687  psp = (LPCPROPSHEETPAGEW)psInfo->proppage[iPageIndex].hpage;
2688  if (psp->dwFlags & PSP_DLGINDIRECT || !IS_INTRESOURCE(psp->u.pszTemplate)) {
2689  return 0;
2690  }
2691  return (LRESULT)psp->u.pszTemplate;
2692 }
2693 
2694 /******************************************************************************
2695  * PROPSHEET_GetResult
2696  */
2698 {
2699  PropSheetInfo * psInfo = GetPropW(hwndDlg, PropSheetInfoStr);
2700  return psInfo->result;
2701 }
2702 
2703 /******************************************************************************
2704  * PROPSHEET_RecalcPageSizes
2705  */
2707 {
2708  FIXME("(%p): stub\n", hwndDlg);
2709  return FALSE;
2710 }
2711 
2712 /******************************************************************************
2713  * PROPSHEET_GetPageIndex
2714  *
2715  * Given a HPROPSHEETPAGE, returns the index of the corresponding page from
2716  * the array of PropPageInfo. If page is not found original index is used
2717  * (page takes precedence over index).
2718  */
2719 static int PROPSHEET_GetPageIndex(HPROPSHEETPAGE page, const PropSheetInfo* psInfo, int original_index)
2720 {
2721  int index;
2722 
2723  TRACE("page %p index %d\n", page, original_index);
2724 
2725  for (index = 0; index < psInfo->nPages; index++)
2726  if (psInfo->proppage[index].hpage == page)
2727  return index;
2728 
2729  return original_index;
2730 }
2731 
2732 /******************************************************************************
2733  * PROPSHEET_CleanUp
2734  */
2735 static void PROPSHEET_CleanUp(HWND hwndDlg)
2736 {
2737  int i;
2738  PropSheetInfo* psInfo = RemovePropW(hwndDlg, PropSheetInfoStr);
2739 
2740  TRACE("\n");
2741  if (!psInfo) return;
2742  if (!IS_INTRESOURCE(psInfo->ppshheader.pszCaption))
2743  Free ((LPVOID)psInfo->ppshheader.pszCaption);
2744 
2745  for (i = 0; i < psInfo->nPages; i++)
2746  {
2747  PROPSHEETPAGEA* psp = (PROPSHEETPAGEA*)psInfo->proppage[i].hpage;
2748 
2749  /* Unsubclass the page dialog window */
2750  if((psInfo->ppshheader.dwFlags & (PSH_WIZARD97_NEW | PSH_WIZARD97_OLD)) &&
2751  (psInfo->ppshheader.dwFlags & PSH_WATERMARK) &&
2752  (psp->dwFlags & PSP_HIDEHEADER))
2753  {
2756  }
2757 
2758  if(psInfo->proppage[i].hwndPage)
2759  DestroyWindow(psInfo->proppage[i].hwndPage);
2760 
2761  if(psp)
2762  {
2763  if (psp->dwFlags & PSP_USETITLE)
2764  Free ((LPVOID)psInfo->proppage[i].pszText);
2765 
2767  }
2768  }
2769 
2770  DeleteObject(psInfo->hFont);
2771  DeleteObject(psInfo->hFontBold);
2772  /* If we created the bitmaps, destroy them */
2773  if ((psInfo->ppshheader.dwFlags & PSH_WATERMARK) &&
2774  (!(psInfo->ppshheader.dwFlags & PSH_USEHBMWATERMARK)) )
2775  DeleteObject(psInfo->ppshheader.u4.hbmWatermark);
2776  if ((psInfo->ppshheader.dwFlags & PSH_HEADER) &&
2777  (!(psInfo->ppshheader.dwFlags & PSH_USEHBMHEADER)) )
2778  DeleteObject(psInfo->ppshheader.u5.hbmHeader);
2779 
2780  Free(psInfo->proppage);
2781  Free(psInfo->strPropertiesFor);
2782  ImageList_Destroy(psInfo->hImageList);
2783 
2784  GlobalFree(psInfo);
2785 }
2786 
2787 static INT do_loop(const PropSheetInfo *psInfo)
2788 {
2789  MSG msg;
2790  INT ret = -1;
2791  HWND hwnd = psInfo->hwnd;
2792  HWND parent = psInfo->ppshheader.hwndParent;
2793 
2794  while(IsWindow(hwnd) && !psInfo->ended && (ret = GetMessageW(&msg, NULL, 0, 0)))
2795  {
2796  if(ret == -1)
2797  break;
2798 
2799  if(!IsDialogMessageW(hwnd, &msg))
2800  {
2803  }
2804  }
2805 
2806  if(ret == 0)
2807  {
2808  PostQuitMessage(msg.wParam);
2809  ret = -1;
2810  }
2811 
2812  if(ret != -1)
2813  ret = psInfo->result;
2814 
2815  if(parent)
2817 
2819  return ret;
2820 }
2821 
2822 /******************************************************************************
2823  * PROPSHEET_PropertySheet
2824  *
2825  * Common code between PropertySheetA/W
2826  */
2828 {
2829  INT_PTR bRet = 0;
2830  HWND parent = NULL;
2831  if (psInfo->active_page >= psInfo->nPages) psInfo->active_page = 0;
2832  TRACE("startpage: %d of %d pages\n", psInfo->active_page, psInfo->nPages);
2833 
2834  psInfo->unicode = unicode;
2835  psInfo->ended = FALSE;
2836 
2837  if(!psInfo->isModeless)
2838  {
2839  parent = psInfo->ppshheader.hwndParent;
2841  }
2842  bRet = PROPSHEET_CreateDialog(psInfo);
2843  if(!psInfo->isModeless)
2844  bRet = do_loop(psInfo);
2845  return bRet;
2846 }
2847 
2848 /******************************************************************************
2849  * PropertySheet (COMCTL32.@)
2850  * PropertySheetA (COMCTL32.@)
2851  *
2852  * Creates a property sheet in the specified property sheet header.
2853  *
2854  * RETURNS
2855  * Modal property sheets: Positive if successful or -1 otherwise.
2856  * Modeless property sheets: Property sheet handle.
2857  * Or:
2858  *| ID_PSREBOOTSYSTEM - The user must reboot the computer for the changes to take effect.
2859  *| ID_PSRESTARTWINDOWS - The user must restart Windows for the changes to take effect.
2860  */
2862 {
2863  PropSheetInfo* psInfo = GlobalAlloc(GPTR, sizeof(PropSheetInfo));
2864  UINT i, n;
2865  const BYTE* pByte;
2866 
2867  TRACE("(%p)\n", lppsh);
2868 
2869  PROPSHEET_CollectSheetInfoA(lppsh, psInfo);
2870 
2871  psInfo->proppage = Alloc(sizeof(PropPageInfo) * lppsh->nPages);
2872  pByte = (const BYTE*) psInfo->ppshheader.u3.ppsp;
2873 
2874  for (n = i = 0; i < lppsh->nPages; i++, n++)
2875  {
2876  if (!psInfo->usePropPage)
2877  psInfo->proppage[n].hpage = psInfo->ppshheader.u3.phpage[i];
2878  else
2879  {
2881  pByte += ((LPCPROPSHEETPAGEA)pByte)->dwSize;
2882  }
2883 
2885  psInfo, n, TRUE))
2886  {
2887  if (psInfo->usePropPage)
2889  n--;
2890  psInfo->nPages--;
2891  }
2892  }
2893 
2894  return PROPSHEET_PropertySheet(psInfo, FALSE);
2895 }
2896 
2897 /******************************************************************************
2898  * PropertySheetW (COMCTL32.@)
2899  *
2900  * See PropertySheetA.
2901  */
2903 {
2904  PropSheetInfo* psInfo = GlobalAlloc(GPTR, sizeof(PropSheetInfo));
2905  UINT i, n;
2906  const BYTE* pByte;
2907 
2908  TRACE("(%p)\n", lppsh);
2909 
2910  PROPSHEET_CollectSheetInfoW(lppsh, psInfo);
2911 
2912  psInfo->proppage = Alloc(sizeof(PropPageInfo) * lppsh->nPages);
2913  pByte = (const BYTE*) psInfo->ppshheader.u3.ppsp;
2914 
2915  for (n = i = 0; i < lppsh->nPages; i++, n++)
2916  {
2917  if (!psInfo->usePropPage)
2918  psInfo->proppage[n].hpage = psInfo->ppshheader.u3.phpage[i];
2919  else
2920  {
2922  pByte += ((LPCPROPSHEETPAGEW)pByte)->dwSize;
2923  }
2924 
2926  psInfo, n, TRUE))
2927  {
2928  if (psInfo->usePropPage)
2930  n--;
2931  psInfo->nPages--;
2932  }
2933  }
2934 
2935  return PROPSHEET_PropertySheet(psInfo, TRUE);
2936 }
2937 
2939 {
2940  LPWSTR ret;
2941 
2942  if (IS_INTRESOURCE(str))
2943  {
2944  HRSRC hrsrc;
2945  HGLOBAL hmem;
2946  WCHAR *ptr;
2947  WORD i, id = LOWORD(str);
2948  UINT len;
2949 
2950  if (!(hrsrc = FindResourceW( instance, MAKEINTRESOURCEW((id >> 4) + 1), (LPWSTR)RT_STRING )))
2951  return NULL;
2952  if (!(hmem = LoadResource( instance, hrsrc ))) return NULL;
2953  if (!(ptr = LockResource( hmem ))) return NULL;
2954  for (i = id & 0x0f; i > 0; i--) ptr += *ptr + 1;
2955  len = *ptr;
2956  if (!len) return NULL;
2957  ret = Alloc( (len + 1) * sizeof(WCHAR) );
2958  if (ret)
2959  {
2960  memcpy( ret, ptr + 1, len * sizeof(WCHAR) );
2961  ret[len] = 0;
2962  }
2963  }
2964  else
2965  {
2966  int len = (strlenW(str) + 1) * sizeof(WCHAR);
2967  ret = Alloc( len );
2968  if (ret) memcpy( ret, str, len );
2969  }
2970  return ret;
2971 }
2972 
2973 
2974 /******************************************************************************
2975  * CreatePropertySheetPage (COMCTL32.@)
2976  * CreatePropertySheetPageA (COMCTL32.@)
2977  *
2978  * Creates a new property sheet page.
2979  *
2980  * RETURNS
2981  * Success: Handle to new property sheet page.
2982  * Failure: NULL.
2983  *
2984  * NOTES
2985  * An application must use the PSM_ADDPAGE message to add the new page to
2986  * an existing property sheet.
2987  */
2989  LPCPROPSHEETPAGEA lpPropSheetPage)
2990 {
2991  PROPSHEETPAGEW *ppsp;
2992 
2993  if (lpPropSheetPage->dwSize < PROPSHEETPAGEA_V1_SIZE)
2994  return NULL;
2995 
2996  /* original data is used for callback notifications */
2997  if ((lpPropSheetPage->dwFlags & PSP_USECALLBACK) && lpPropSheetPage->pfnCallback)
2998  {
2999  ppsp = Alloc(2 * sizeof(*ppsp));
3000  memcpy(ppsp, lpPropSheetPage, min(lpPropSheetPage->dwSize, sizeof(PROPSHEETPAGEA)));
3001  memcpy(ppsp + 1, lpPropSheetPage, min(lpPropSheetPage->dwSize, sizeof(PROPSHEETPAGEA)));
3002  }
3003  else
3004  {
3005  ppsp = Alloc(sizeof(*ppsp));
3006  memcpy(ppsp, lpPropSheetPage, min(lpPropSheetPage->dwSize, sizeof(PROPSHEETPAGEA)));
3007  }
3008 
3009  ppsp->dwFlags &= ~PSP_INTERNAL_UNICODE;
3010 
3011  if ( !(ppsp->dwFlags & PSP_DLGINDIRECT) )
3012  {
3013  if (!IS_INTRESOURCE( ppsp->u.pszTemplate ))
3014  {
3015  int len = strlen(lpPropSheetPage->u.pszTemplate) + 1;
3016  char *template = Alloc( len );
3017 
3018  ppsp->u.pszTemplate = (LPWSTR)strcpy( template, lpPropSheetPage->u.pszTemplate );
3019  }
3020  }
3021 
3022  if (ppsp->dwFlags & PSP_USEICONID)
3023  {
3024  if (!IS_INTRESOURCE( ppsp->u2.pszIcon ))
3025  ppsp->u2.pszIcon = heap_strdupAtoW( lpPropSheetPage->u2.pszIcon );
3026  }
3027 
3028  if (ppsp->dwFlags & PSP_USETITLE)
3029  {
3030  if (IS_INTRESOURCE( ppsp->pszTitle ))
3031  ppsp->pszTitle = load_string( ppsp->hInstance, ppsp->pszTitle );
3032  else
3033  ppsp->pszTitle = heap_strdupAtoW( lpPropSheetPage->pszTitle );
3034  }
3035  else
3036  ppsp->pszTitle = NULL;
3037 
3038  if (ppsp->dwFlags & PSP_HIDEHEADER)
3039  ppsp->dwFlags &= ~(PSP_USEHEADERTITLE | PSP_USEHEADERSUBTITLE);
3040 
3041  if (ppsp->dwFlags & PSP_USEHEADERTITLE)
3042  {
3043  if (IS_INTRESOURCE( ppsp->pszHeaderTitle ))
3044  ppsp->pszHeaderTitle = load_string( ppsp->hInstance, ppsp->pszHeaderTitle );
3045  else
3046  ppsp->pszHeaderTitle = heap_strdupAtoW( lpPropSheetPage->pszHeaderTitle );
3047  }
3048  else
3049  ppsp->pszHeaderTitle = NULL;
3050 
3051  if (ppsp->dwFlags & PSP_USEHEADERSUBTITLE)
3052  {
3053  if (IS_INTRESOURCE( ppsp->pszHeaderSubTitle ))
3054  ppsp->pszHeaderSubTitle = load_string( ppsp->hInstance, ppsp->pszHeaderSubTitle );
3055  else
3056  ppsp->pszHeaderSubTitle = heap_strdupAtoW( lpPropSheetPage->pszHeaderSubTitle );
3057  }
3058  else
3059  ppsp->pszHeaderSubTitle = NULL;
3060 
3061  if ((ppsp->dwFlags & PSP_USECALLBACK) && ppsp->dwSize > PROPSHEETPAGEA_V1_SIZE && ppsp->pfnCallback)
3062  ppsp->pfnCallback(0, PSPCB_ADDREF, ppsp + 1);
3063 
3064  return (HPROPSHEETPAGE)ppsp;
3065 }
3066 
3067 /******************************************************************************
3068  * CreatePropertySheetPageW (COMCTL32.@)
3069  *
3070  * See CreatePropertySheetA.
3071  */
3073 {
3074  PROPSHEETPAGEW *ppsp;
3075 
3076  if (lpPropSheetPage->dwSize < PROPSHEETPAGEW_V1_SIZE)
3077  return NULL;
3078 
3079  /* original data is used for callback notifications */
3080  if ((lpPropSheetPage->dwFlags & PSP_USECALLBACK) && lpPropSheetPage->pfnCallback)
3081  {
3082  ppsp = Alloc(2 * sizeof(*ppsp));
3083  memcpy(ppsp, lpPropSheetPage, min(lpPropSheetPage->dwSize, sizeof(PROPSHEETPAGEW)));
3084  memcpy(ppsp + 1, lpPropSheetPage, min(lpPropSheetPage->dwSize, sizeof(PROPSHEETPAGEW)));
3085  }
3086  else
3087  {
3088  ppsp = Alloc(sizeof(*ppsp));
3089  memcpy(ppsp, lpPropSheetPage, min(lpPropSheetPage->dwSize, sizeof(PROPSHEETPAGEW)));
3090  }
3091 
3092  ppsp->dwFlags |= PSP_INTERNAL_UNICODE;
3093 
3094  if ( !(ppsp->dwFlags & PSP_DLGINDIRECT) )
3095  {
3096  if (!IS_INTRESOURCE( ppsp->u.pszTemplate ))
3097  ppsp->u.pszTemplate = heap_strdupW( lpPropSheetPage->u.pszTemplate );
3098  }
3099 
3100  if ( ppsp->dwFlags & PSP_USEICONID )
3101  {
3102  if (!IS_INTRESOURCE( ppsp->u2.pszIcon ))
3103  ppsp->u2.pszIcon = heap_strdupW( lpPropSheetPage->u2.pszIcon );
3104  }
3105 
3106  if (ppsp->dwFlags & PSP_USETITLE)
3107  ppsp->pszTitle = load_string( ppsp->hInstance, ppsp->pszTitle );
3108  else
3109  ppsp->pszTitle = NULL;
3110 
3111  if (ppsp->dwFlags & PSP_HIDEHEADER)
3112  ppsp->dwFlags &= ~(PSP_USEHEADERTITLE | PSP_USEHEADERSUBTITLE);
3113 
3114  if (ppsp->dwFlags & PSP_USEHEADERTITLE)
3115  ppsp->pszHeaderTitle = load_string( ppsp->hInstance, ppsp->pszHeaderTitle );
3116  else
3117  ppsp->pszHeaderTitle = NULL;
3118 
3119  if (ppsp->dwFlags & PSP_USEHEADERSUBTITLE)
3120  ppsp->pszHeaderSubTitle = load_string( ppsp->hInstance, ppsp->pszHeaderSubTitle );
3121  else
3122  ppsp->pszHeaderSubTitle = NULL;
3123 
3124  if ((ppsp->dwFlags & PSP_USECALLBACK) && ppsp->dwSize > PROPSHEETPAGEW_V1_SIZE && ppsp->pfnCallback)
3125  ppsp->pfnCallback(0, PSPCB_ADDREF, ppsp + 1);
3126 
3127  return (HPROPSHEETPAGE)ppsp;
3128 }
3129 
3130 /******************************************************************************
3131  * DestroyPropertySheetPage (COMCTL32.@)
3132  *
3133  * Destroys a property sheet page previously created with
3134  * CreatePropertySheetA() or CreatePropertySheetW() and frees the associated
3135  * memory.
3136  *
3137  * RETURNS
3138  * Success: TRUE
3139  * Failure: FALSE
3140  */
3142 {
3143  PROPSHEETPAGEW *psp = (PROPSHEETPAGEW *)hPropPage;
3144 
3145  if (!psp)
3146  return FALSE;
3147 
3148  if ((psp->dwFlags & PSP_USECALLBACK) && psp->pfnCallback)
3149  psp->pfnCallback(0, PSPCB_RELEASE, psp + 1);
3150 
3151  if (!(psp->dwFlags & PSP_DLGINDIRECT) && !IS_INTRESOURCE( psp->u.pszTemplate ))
3152  Free ((LPVOID)psp->u.pszTemplate);
3153 
3154  if ((psp->dwFlags & PSP_USEICONID) && !IS_INTRESOURCE( psp->u2.pszIcon ))
3155  Free ((LPVOID)psp->u2.pszIcon);
3156 
3157  if ((psp->dwFlags & PSP_USETITLE) && !IS_INTRESOURCE( psp->pszTitle ))
3158  Free ((LPVOID)psp->pszTitle);
3159 
3160  if ((psp->dwFlags & PSP_USEHEADERTITLE) && !IS_INTRESOURCE( psp->pszHeaderTitle ))
3161  Free ((LPVOID)psp->pszHeaderTitle);
3162 
3163  if ((psp->dwFlags & PSP_USEHEADERSUBTITLE) && !IS_INTRESOURCE( psp->pszHeaderSubTitle ))
3164  Free ((LPVOID)psp->pszHeaderSubTitle);
3165 
3166  Free(hPropPage);
3167 
3168  return TRUE;
3169 }
3170 
3171 /******************************************************************************
3172  * PROPSHEET_IsDialogMessage
3173  */
3175 {
3177 
3178  TRACE("\n");
3179  if (!psInfo || (hwnd != lpMsg->hwnd && !IsChild(hwnd, lpMsg->hwnd)))
3180  return FALSE;
3181 
3182  if (lpMsg->message == WM_KEYDOWN && (GetKeyState(VK_CONTROL) & 0x8000))
3183  {
3184  int new_page = 0;
3185  INT dlgCode = SendMessageW(lpMsg->hwnd, WM_GETDLGCODE, 0, (LPARAM)lpMsg);
3186 
3187  if (!(dlgCode & DLGC_WANTMESSAGE))
3188  {
3189  switch (lpMsg->wParam)
3190  {
3191  case VK_TAB:
3192  if (GetKeyState(VK_SHIFT) & 0x8000)
3193  new_page = -1;
3194  else
3195  new_page = 1;
3196  break;
3197 
3198  case VK_NEXT: new_page = 1; break;
3199  case VK_PRIOR: new_page = -1; break;
3200  }
3201  }
3202 
3203  if (new_page)
3204  {
3206  {
3207  new_page += psInfo->active_page;
3208 
3209  if (new_page < 0)
3210  new_page = psInfo->nPages - 1;
3211  else if (new_page >= psInfo->nPages)
3212  new_page = 0;
3213 
3214  PROPSHEET_SetCurSel(hwnd, new_page, 1, 0);
3215  }
3216 
3217  return TRUE;
3218  }
3219  }
3220 
3221  return IsDialogMessageW(hwnd, lpMsg);
3222 }
3223 
3224 /******************************************************************************
3225  * PROPSHEET_DoCommand
3226  */
3228 {
3229 
3230  switch (wID) {
3231 
3232  case IDOK:
3233  case IDC_APPLY_BUTTON:
3234  {
3235  HWND hwndApplyBtn = GetDlgItem(hwnd, IDC_APPLY_BUTTON);
3236 
3237  if (PROPSHEET_Apply(hwnd, wID == IDOK ? 1: 0) == FALSE)
3238  break;
3239 
3240  if (wID == IDOK)
3241  {
3243 
3244  /* don't overwrite ID_PSRESTARTWINDOWS or ID_PSREBOOTSYSTEM */
3245  if (psInfo->result == 0)
3246  psInfo->result = IDOK;
3247 
3248  if (psInfo->isModeless)
3249  psInfo->activeValid = FALSE;
3250  else
3251  psInfo->ended = TRUE;
3252  }
3253  else
3254  EnableWindow(hwndApplyBtn, FALSE);
3255 
3256  break;
3257  }
3258 
3259  case IDC_BACK_BUTTON:
3261  break;
3262 
3263  case IDC_NEXT_BUTTON:
3265  break;
3266 
3267  case IDC_FINISH_BUTTON:
3269  break;
3270 
3271  case IDCANCEL:
3272  PROPSHEET_Cancel(hwnd, 0);
3273  break;
3274 
3275  case IDHELP:
3277  break;
3278 
3279  default:
3280  return FALSE;
3281  }
3282 
3283  return TRUE;
3284 }
3285 
3286 /******************************************************************************
3287  * PROPSHEET_Paint
3288  */
3290 {
3292  PAINTSTRUCT ps;
3293  HDC hdc, hdcSrc;
3294  BITMAP bm;
3295  HBITMAP hbmp;
3296  HPALETTE hOldPal = 0;
3297  int offsety = 0;
3298  HBRUSH hbr;
3299  RECT r, rzone;
3300  LPCPROPSHEETPAGEW ppshpage;
3301  WCHAR szBuffer[256];
3302  int nLength;
3303 
3304  hdc = hdcParam ? hdcParam : BeginPaint(hwnd, &ps);
3305  if (!hdc) return 1;
3306 
3308 
3309  if (psInfo->ppshheader.dwFlags & PSH_USEHPLWATERMARK)
3310  hOldPal = SelectPalette(hdc, psInfo->ppshheader.hplWatermark, FALSE);
3311 
3312  if (psInfo->active_page < 0)
3313  ppshpage = NULL;
3314  else
3315  ppshpage = (LPCPROPSHEETPAGEW)psInfo->proppage[psInfo->active_page].hpage;
3316 
3317  if ( (ppshpage && !(ppshpage->dwFlags & PSP_HIDEHEADER)) &&
3318  (psInfo->ppshheader.dwFlags & (PSH_WIZARD97_OLD | PSH_WIZARD97_NEW)) &&
3319  (psInfo->ppshheader.dwFlags & PSH_HEADER) )
3320  {
3321  HWND hwndLineHeader = GetDlgItem(hwnd, IDC_SUNKEN_LINEHEADER);
3322  HFONT hOldFont;
3323  COLORREF clrOld = 0;
3324  int oldBkMode = 0;
3325 
3326  GetClientRect(hwndLineHeader, &r);
3327  MapWindowPoints(hwndLineHeader, hwnd, (LPPOINT) &r, 2);
3328  SetRect(&rzone, 0, 0, r.right + 1, r.top - 1);
3329 
3330  hOldFont = SelectObject(hdc, psInfo->hFontBold);
3331 
3332 #ifdef __REACTOS__
3333  if (psInfo->ppshheader.u5.hbmHeader)
3334 #else
3335  if (psInfo->ppshheader.dwFlags & PSH_USEHBMHEADER)
3336 #endif
3337  {
3338  hbmp = SelectObject(hdcSrc, psInfo->ppshheader.u5.hbmHeader);
3339 
3340  GetObjectW(psInfo->ppshheader.u5.hbmHeader, sizeof(BITMAP), &bm);
3341  if (psInfo->ppshheader.dwFlags & PSH_WIZARD97_OLD)
3342  {
3343  /* Fill the unoccupied part of the header with color of the
3344  * left-top pixel, but do it only when needed.
3345  */
3346  if (bm.bmWidth < r.right || bm.bmHeight < r.bottom)
3347  {
3348  hbr = CreateSolidBrush(GetPixel(hdcSrc, 0, 0));
3349  r = rzone;
3350  if (bm.bmWidth < r.right)
3351  {
3352  r.left = bm.bmWidth;
3353  FillRect(hdc, &r, hbr);
3354  }
3355  if (bm.bmHeight < r.bottom)
3356  {
3357  r.left = 0;
3358  r.top = bm.bmHeight;
3359  FillRect(hdc, &r, hbr);
3360  }
3361  DeleteObject(hbr);
3362  }
3363 
3364  /* Draw the header itself. */
3365  BitBlt(hdc, 0, 0, bm.bmWidth, min(bm.bmHeight, rzone.bottom),
3366  hdcSrc, 0, 0, SRCCOPY);
3367  }
3368  else
3369  {
3370  int margin;
3372  FillRect(hdc, &rzone, hbr);
3373 
3374  /* Draw the header bitmap. It's always centered like a
3375  * common 49 x 49 bitmap. */
3376  margin = (rzone.bottom - 49) / 2;
3377  BitBlt(hdc, rzone.right - 49 - margin, margin,
3378  min(bm.bmWidth, 49), min(bm.bmHeight, 49),
3379  hdcSrc, 0, 0, SRCCOPY);
3380 
3381  /* NOTE: Native COMCTL32 draws a white stripe over the bitmap
3382  * if its height is smaller than 49 pixels. Because the reason
3383  * for this bug is unknown the current code doesn't try to
3384  * replicate it. */
3385  }
3386 
3388  }
3389 
3390  clrOld = SetTextColor (hdc, 0x00000000);
3391  oldBkMode = SetBkMode (hdc, TRANSPARENT);
3392 
3393  if (ppshpage->dwFlags & PSP_USEHEADERTITLE) {
3394  SetRect(&r, 20, 10, 0, 0);
3395  if (!IS_INTRESOURCE(ppshpage->pszHeaderTitle))
3396  DrawTextW(hdc, ppshpage->pszHeaderTitle, -1, &r, DT_LEFT | DT_SINGLELINE | DT_NOCLIP);
3397  else
3398  {
3399  nLength = LoadStringW(ppshpage->hInstance, (UINT_PTR)ppshpage->pszHeaderTitle,
3400  szBuffer, 256);
3401  if (nLength != 0)
3402  {
3403  DrawTextW(hdc, szBuffer, nLength, &r, DT_LEFT | DT_SINGLELINE | DT_NOCLIP);
3404  }
3405  }
3406  }
3407 
3408  if (ppshpage->dwFlags & PSP_USEHEADERSUBTITLE) {
3409  SelectObject(hdc, psInfo->hFont);
3410  SetRect(&r, 40, 25, rzone.right - 69, rzone.bottom);
3411 #ifdef __REACTOS__
3412  if (!IS_INTRESOURCE(ppshpage->pszHeaderSubTitle))
3413 #else
3414  if (!IS_INTRESOURCE(ppshpage->pszHeaderTitle))
3415 #endif
3416  DrawTextW(hdc, ppshpage->pszHeaderSubTitle, -1, &r, DT_LEFT | DT_WORDBREAK);
3417  else
3418  {
3419  nLength = LoadStringW(ppshpage->hInstance, (UINT_PTR)ppshpage->pszHeaderSubTitle,
3420  szBuffer, 256);
3421  if (nLength != 0)
3422  {
3423  DrawTextW(hdc, szBuffer, nLength, &r, DT_LEFT | DT_WORDBREAK);
3424  }
3425  }
3426  }
3427 
3428  offsety = rzone.bottom + 2;
3429 
3430  SetTextColor(hdc, clrOld);
3431  SetBkMode(hdc, oldBkMode);
3432  SelectObject(hdc, hOldFont);
3433  }
3434 
3435  if ( (ppshpage && (ppshpage->dwFlags & PSP_HIDEHEADER)) &&
3436  (psInfo->ppshheader.dwFlags & (PSH_WIZARD97_OLD | PSH_WIZARD97_NEW)) &&
3437 #ifdef __REACTOS__
3438  (psInfo->ppshheader.dwFlags & PSH_WATERMARK) &&
3439  (psInfo->ppshheader.u4.hbmWatermark) )
3440 #else
3441  (psInfo->ppshheader.dwFlags & PSH_WATERMARK) )
3442 #endif
3443  {
3444  HWND hwndLine = GetDlgItem(hwnd, IDC_SUNKEN_LINE);
3445 
3446  GetClientRect(hwndLine, &r);
3447  MapWindowPoints(hwndLine, hwnd, (LPPOINT) &r, 2);
3448  SetRect(&rzone, 0, 0, r.right, r.top - 1);
3449 
3451  FillRect(hdc, &rzone, hbr);
3452 
3453  GetObjectW(psInfo->ppshheader.u4.hbmWatermark, sizeof(BITMAP), &bm);
3454  hbmp = SelectObject(hdcSrc, psInfo->ppshheader.u4.hbmWatermark);
3455 
3456  /* The watermark is truncated to a width of 164 pixels */
3457  r.right = min(r.right, 164);
3458  BitBlt(hdc, 0, offsety, min(bm.bmWidth, r.right),
3459  min(bm.bmHeight, r.bottom), hdcSrc, 0, 0, SRCCOPY);
3460 
3461  /* If the bitmap is not big enough, fill the remaining area
3462  with the color of pixel (0,0) of bitmap - see MSDN */
3463  if (r.top > bm.bmHeight) {
3464  r.bottom = r.top - 1;
3465  r.top = bm.bmHeight;
3466  r.left = 0;
3467  r.right = bm.bmWidth;
3468  hbr = CreateSolidBrush(GetPixel(hdcSrc, 0, 0));
3469  FillRect(hdc, &r, hbr);
3470  DeleteObject(hbr);
3471  }
3472 
3474  }
3475 
3476  if (psInfo->ppshheader.dwFlags & PSH_USEHPLWATERMARK)
3477  SelectPalette(hdc, hOldPal, FALSE);
3478 
3479  DeleteDC(hdcSrc);
3480 
3481  if (!hdcParam) EndPaint(hwnd, &ps);
3482 
3483  return 0;
3484 }
3485 
3486 /******************************************************************************
3487  * PROPSHEET_DialogProc
3488  */
3489 static INT_PTR CALLBACK
3491 {
3492  TRACE("hwnd=%p msg=0x%04x wparam=%lx lparam=%lx\n",
3493  hwnd, uMsg, wParam, lParam);
3494 
3495  switch (uMsg)
3496  {
3497  case WM_INITDIALOG:
3498  {
3499  PropSheetInfo* psInfo = (PropSheetInfo*) lParam;
3500  WCHAR* strCaption = Alloc(MAX_CAPTION_LENGTH*sizeof(WCHAR));
3501  HWND hwndTabCtrl = GetDlgItem(hwnd, IDC_TABCONTROL);
3502  int idx;
3503  LOGFONTW logFont;
3504 
3505  /* Using PropSheetInfoStr to store extra data doesn't match the native
3506  * common control: native uses TCM_[GS]ETITEM
3507  */
3508  SetPropW(hwnd, PropSheetInfoStr, psInfo);
3509 
3510  /*
3511  * psInfo->hwnd is not being used by WINE code - it exists
3512  * for compatibility with "real" Windoze. The same about
3513  * SetWindowLongPtr - WINE is only using the PropSheetInfoStr
3514  * property.
3515  */
3516  psInfo->hwnd = hwnd;
3518 
3519  if (psInfo->ppshheader.dwFlags & INTRNL_ANY_WIZARD)
3520  {
3521  /* set up the Next and Back buttons by default */
3523  }
3524 
3525  /* Set up fonts */
3527  psInfo->hFont = CreateFontIndirectW (&logFont);
3528  logFont.lfWeight = FW_BOLD;
3529  psInfo->hFontBold = CreateFontIndirectW (&logFont);
3530 
3531  /*
3532  * Small icon in the title bar.
3533  */
3534  if ((psInfo->ppshheader.dwFlags & PSH_USEICONID) ||
3535  (psInfo->ppshheader.dwFlags & PSH_USEHICON))
3536  {
3537  HICON hIcon;
3538  int icon_cx = GetSystemMetrics(SM_CXSMICON);
3539  int icon_cy = GetSystemMetrics(SM_CYSMICON);
3540 
3541  if (psInfo->ppshheader.dwFlags & PSH_USEICONID)
3542  hIcon = LoadImageW(psInfo->ppshheader.hInstance,
3543  psInfo->ppshheader.u.pszIcon,
3544  IMAGE_ICON,
3545  icon_cx, icon_cy,
3546  LR_DEFAULTCOLOR);
3547  else
3548  hIcon = psInfo->ppshheader.u.hIcon;
3549 
3550  SendMessageW(hwnd, WM_SETICON, 0, (LPARAM)hIcon);
3551  }
3552 
3553  if (psInfo->ppshheader.dwFlags & PSH_USEHICON)
3554  SendMessageW(hwnd, WM_SETICON, 0, (LPARAM)psInfo->ppshheader.u.hIcon);
3555 
3556  psInfo->strPropertiesFor = strCaption;
3557 
3558  GetWindowTextW(hwnd, psInfo->strPropertiesFor, MAX_CAPTION_LENGTH);
3559 
3561 
3563 
3564  if (psInfo->ppshheader.dwFlags & INTRNL_ANY_WIZARD)
3565  {
3566  ShowWindow(hwndTabCtrl, SW_HIDE);
3570  }
3571  else
3572  {
3573  if (PROPSHEET_SizeMismatch(hwnd, psInfo))
3574  {
3575  PROPSHEET_AdjustSize(hwnd, psInfo);
3576  PROPSHEET_AdjustButtons(hwnd, psInfo);
3577  }
3579  }
3580 
3581  if (IS_INTRESOURCE(psInfo->ppshheader.pszCaption) &&
3582  psInfo->ppshheader.hInstance)
3583  {
3584  WCHAR szText[256];
3585 
3586  if (LoadStringW(psInfo->ppshheader.hInstance,
3587  (UINT_PTR)psInfo->ppshheader.pszCaption, szText, 255))
3588  PROPSHEET_SetTitleW(hwnd, psInfo->ppshheader.dwFlags, szText);
3589  }
3590  else
3591  {
3592  PROPSHEET_SetTitleW(hwnd, psInfo->ppshheader.dwFlags,
3593  psInfo->ppshheader.pszCaption);
3594  }
3595 
3596 
3597  if (psInfo->useCallback)
3598  (*(psInfo->ppshheader.pfnCallback))(hwnd, PSCB_INITIALIZED, 0);
3599 
3600  idx = psInfo->active_page;
3601  psInfo->active_page = -1;
3602 
3603  PROPSHEET_SetCurSel(hwnd, idx, 1, psInfo->proppage[idx].hpage);
3604 
3605  /* doing TCM_SETCURSEL seems to be needed even in case of PSH_WIZARD,
3606  * as some programs call TCM_GETCURSEL to get the current selection
3607  * from which to switch to the next page */
3608  SendMessageW(hwndTabCtrl, TCM_SETCURSEL, psInfo->active_page, 0);
3609 
3611 
3612  /* wizards set their focus during init */
3613  if (psInfo->ppshheader.dwFlags & INTRNL_ANY_WIZARD)
3614  return FALSE;
3615 
3616  return TRUE;
3617  }
3618 
3619  case WM_PRINTCLIENT:
3620  case WM_PAINT:
3622  return TRUE;
3623 
3624  case WM_DESTROY:
3626  return TRUE;
3627 
3628  case WM_CLOSE:
3629  PROPSHEET_Cancel(hwnd, 1);
3630  return FALSE; /* let DefDlgProc post us WM_COMMAND/IDCANCEL */
3631 
3632  case WM_COMMAND:
3634  {
3636 
3637  if (!psInfo)
3638  return FALSE;
3639 
3640  /* No default handler, forward notification to active page */
3641  if (psInfo->activeValid && psInfo->active_page != -1)
3642  {
3643  HWND hwndPage = psInfo->proppage[psInfo->active_page].hwndPage;
3644  SendMessageW(hwndPage, WM_COMMAND, wParam, lParam);
3645  }
3646  }
3647  return TRUE;
3648 
3649  case WM_NOTIFY:
3650  {
3651  NMHDR* pnmh = (LPNMHDR) lParam;
3652 
3653  if (pnmh->code == TCN_SELCHANGE)
3654  {
3655  int index = SendMessageW(pnmh->hwndFrom, TCM_GETCURSEL, 0, 0);
3656  PROPSHEET_SetCurSel(hwnd, index, 1, 0);
3657  }
3658 
3659  if(pnmh->code == TCN_SELCHANGING)
3660  {
3663  return TRUE;
3664  }
3665 
3666  return FALSE;
3667  }
3668 
3669  case WM_SYSCOLORCHANGE:
3671  return FALSE;
3672 
3674  {
3676  HWND hwndPage = 0;
3677 
3678  if (!psInfo)
3679  return FALSE;
3680 
3681  if (psInfo->activeValid && psInfo->active_page != -1)
3682  hwndPage = psInfo->proppage[psInfo->active_page].hwndPage;
3683 
3685 
3686  return TRUE;
3687  }
3688 
3689  case PSM_CHANGED:
3691  return TRUE;
3692 
3693  case PSM_UNCHANGED:
3695  return TRUE;
3696 
3697  case PSM_GETTABCONTROL:
3698  {
3699  HWND hwndTabCtrl = GetDlgItem(hwnd, IDC_TABCONTROL);
3700 
3702 
3703  return TRUE;
3704  }
3705 
3706  case PSM_SETCURSEL:
3707  {
3708  BOOL msgResult;
3709 
3710  msgResult = PROPSHEET_CanSetCurSel(hwnd);
3711  if(msgResult != FALSE)
3712  {
3713  msgResult = PROPSHEET_SetCurSel(hwnd,
3714  (int)wParam,
3715  1,
3717  }
3718 
3719  SetWindowLongPtrW(hwnd, DWLP_MSGRESULT, msgResult);
3720 
3721  return TRUE;
3722  }
3723 
3724  case PSM_CANCELTOCLOSE:
3725  {
3727  HWND hwndOK = GetDlgItem(hwnd, IDOK);
3728  HWND hwndCancel = GetDlgItem(hwnd, IDCANCEL);
3729 
3730  EnableWindow(hwndCancel, FALSE);
3732  SetWindowTextW(hwndOK, buf);
3733 
3734  return FALSE;
3735  }
3736 
3737  case PSM_RESTARTWINDOWS:
3738  {
3740 
3741  if (!psInfo)
3742  return FALSE;
3743 
3744  /* reboot system takes precedence over restart windows */
3745  if (psInfo->result != ID_PSREBOOTSYSTEM)
3746  psInfo->result = ID_PSRESTARTWINDOWS;
3747 
3748  return TRUE;
3749  }
3750 
3751  case PSM_REBOOTSYSTEM:
3752  {
3754 
3755  if (!psInfo)
3756  return FALSE;
3757 
3758  psInfo->result = ID_PSREBOOTSYSTEM;
3759 
3760  return TRUE;
3761  }
3762 
3763  case PSM_SETTITLEA:
3765  return TRUE;
3766 
3767  case PSM_SETTITLEW:
3769  return TRUE;
3770 
3771  case PSM_APPLY:
3772  {
3773  BOOL msgResult = PROPSHEET_Apply(hwnd, 0);
3774 
3775  SetWindowLongPtrW(hwnd, DWLP_MSGRESULT, msgResult);
3776 
3777  return TRUE;
3778  }
3779 
3780  case PSM_QUERYSIBLINGS:
3781  {
3783 
3784  SetWindowLongPtrW(hwnd, DWLP_MSGRESULT, msgResult);
3785 
3786  return TRUE;
3787  }
3788 
3789  case PSM_ADDPAGE:
3790  {
3791  /*
3792  * Note: MSVC++ 6.0 documentation says that PSM_ADDPAGE does not have
3793  * a return value. This is not true. PSM_ADDPAGE returns TRUE
3794  * on success or FALSE otherwise, as specified on MSDN Online.
3795  * Also see the MFC code for
3796  * CPropertySheet::AddPage(CPropertyPage* pPage).
3797  */
3798 
3800 
3801  SetWindowLongPtrW(hwnd, DWLP_MSGRESULT, msgResult);
3802 
3803  return TRUE;
3804  }
3805 
3806  case PSM_REMOVEPAGE:
3808  return TRUE;
3809 
3810  case PSM_ISDIALOGMESSAGE:
3811  {
3813  SetWindowLongPtrW(hwnd, DWLP_MSGRESULT, msgResult);
3814  return TRUE;
3815  }
3816 
3817  case PSM_PRESSBUTTON:
3819  return TRUE;
3820 
3821  case PSM_SETFINISHTEXTA:
3823  return TRUE;
3824 
3825  case PSM_SETWIZBUTTONS:
3827  return TRUE;
3828 
3829  case PSM_SETCURSELID:
3831  return TRUE;
3832 
3833  case PSM_SETFINISHTEXTW:
3835  return FALSE;
3836 
3837  case PSM_INSERTPAGE:
3838  {
3840  SetWindowLongPtrW(hwnd, DWLP_MSGRESULT, msgResult);
3841  return TRUE;
3842  }
3843 
3844  case PSM_SETHEADERTITLEW:
3846  return TRUE;
3847 
3848  case PSM_SETHEADERTITLEA:
3850  return TRUE;
3851 
3852  case PSM_SETHEADERSUBTITLEW:
3854  return TRUE;
3855 
3856  case PSM_SETHEADERSUBTITLEA:
3858  return TRUE;
3859 
3860  case PSM_HWNDTOINDEX:
3861  {
3862  LRESULT msgResult = PROPSHEET_HwndToIndex(hwnd, (HWND)wParam);
3863  SetWindowLongPtrW(hwnd, DWLP_MSGRESULT, msgResult);
3864  return TRUE;
3865  }
3866 
3867  case PSM_INDEXTOHWND:
3868  {
3869  LRESULT msgResult = PROPSHEET_IndexToHwnd(hwnd, (int)wParam);
3870  SetWindowLongPtrW(hwnd, DWLP_MSGRESULT, msgResult);
3871  return TRUE;
3872  }
3873 
3874  case PSM_PAGETOINDEX:
3875  {
3877  SetWindowLongPtrW(hwnd, DWLP_MSGRESULT, msgResult);
3878  return TRUE;
3879  }
3880 
3881  case PSM_INDEXTOPAGE:
3882  {
3883  LRESULT msgResult = PROPSHEET_IndexToPage(hwnd, (int)wParam);
3884  SetWindowLongPtrW(hwnd, DWLP_MSGRESULT, msgResult);
3885  return TRUE;
3886  }
3887 
3888  case PSM_IDTOINDEX:
3889  {
3890  LRESULT msgResult = PROPSHEET_IdToIndex(hwnd, (int)lParam);
3891  SetWindowLongPtrW(hwnd, DWLP_MSGRESULT, msgResult);
3892  return TRUE;
3893  }
3894 
3895  case PSM_INDEXTOID:
3896  {
3897  LRESULT msgResult = PROPSHEET_IndexToId(hwnd, (int)wParam);
3898  SetWindowLongPtrW(hwnd, DWLP_MSGRESULT, msgResult);
3899  return TRUE;
3900  }
3901 
3902  case PSM_GETRESULT:
3903  {
3904  LRESULT msgResult = PROPSHEET_GetResult(hwnd);
3905  SetWindowLongPtrW(hwnd, DWLP_MSGRESULT, msgResult);
3906  return TRUE;
3907  }
3908 
3909  case PSM_RECALCPAGESIZES:
3910  {
3911  LRESULT msgResult = PROPSHEET_RecalcPageSizes(hwnd);
3912  SetWindowLongPtrW(hwnd, DWLP_MSGRESULT, msgResult);
3913  return TRUE;
3914  }
3915 
3916  default:
3917  return FALSE;
3918  }
3919 }
int WINAPIV wsprintfW(_Out_ LPWSTR, _In_ _Printf_format_string_ LPCWSTR,...)
static LRESULT PROPSHEET_HwndToIndex(HWND hwndDlg, HWND hPageDlg)
Definition: propsheet.c:2601
#define PSH_WIZARDHASFINISH
Definition: prsht.h:44
static LRESULT PROPSHEET_Paint(HWND hwnd, HDC hdcParam)
Definition: propsheet.c:3289
#define TCM_GETCURSEL
Definition: commctrl.h:4034
#define WS_DISABLED
Definition: pedump.c:621
HWND hwndParent
Definition: prsht.h:277
#define WS_THICKFRAME
Definition: pedump.c:630
const DOCKBAR PVOID HWND HWND * hwnd
Definition: tooldock.h:22
#define PSH_USEHICON
Definition: prsht.h:41
GLint GLint GLsizei width
Definition: gl.h:1546
#define WM_SYSCOLORCHANGE
Definition: winuser.h:1608
#define WIZARD_HEADER_HEIGHT
Definition: propsheet.c:156
BOOL WINAPI TranslateMessage(_In_ const MSG *)
static HICON
Definition: imagelist.c:84
#define TRUE
Definition: types.h:120
#define INTRNL_ANY_WIZARD
Definition: propsheet.c:152
HGLOBAL NTAPI GlobalAlloc(UINT uFlags, SIZE_T dwBytes)
Definition: heapmem.c:368
#define IDOK
Definition: winuser.h:824
#define IMAGE_ICON
Definition: winuser.h:212
#define DLGC_WANTMESSAGE
Definition: winuser.h:2588
#define MAX_TABTEXT_LENGTH
Definition: propsheet.c:149
static void PROPSHEET_Help(HWND hwndDlg)
Definition: propsheet.c:1813
LPCPROPSHEETPAGEW ppsp
Definition: prsht.h:290
#define PSH_NOAPPLYNOW
Definition: prsht.h:47
static void PROPSHEET_SetFinishTextA(HWND hwndDlg, LPCSTR lpszText)
Definition: propsheet.c:2166
WINE_UNICODE_INLINE unsigned int strlenW(const WCHAR *str)
Definition: unicode.h:212
#define IDC_APPLY_BUTTON
Definition: propsheet.c:13
LPCWSTR pszTemplate
Definition: prsht.h:209
long y
Definition: polytest.cpp:48
#define WM_GETDLGCODE
Definition: winuser.h:1671
int WINAPI MapWindowPoints(_In_opt_ HWND hWndFrom, _In_opt_ HWND hWndTo, _Inout_updates_(cPoints) LPPOINT lpPoints, _In_ UINT cPoints)
const WCHAR * LPCWSTR
Definition: xmlstorage.h:185
BOOL WINAPI IsWindow(_In_opt_ HWND)
#define GPTR
Definition: winbase.h:293
DWORD dwSize
Definition: prsht.h:177
long x
Definition: polytest.cpp:48
#define PSH_RTLREADING
Definition: prsht.h:51
#define IDC_SUNKEN_LINE
Definition: comctl32.h:50
#define TCM_ADJUSTRECT
Definition: commctrl.h:4057
ACPI_SIZE strlen(const char *String)
Definition: utclib.c:269
#define PSM_GETTABCONTROL
Definition: prsht.h:80
GLenum GLuint GLenum GLsizei const GLchar * buf
Definition: glext.h:7751
struct tagPropPageInfo PropPageInfo
#define PSN_HELP
Definition: prsht.h:119
#define ID_PSREBOOTSYSTEM
Definition: prsht.h:133
#define SW_HIDE
Definition: winuser.h:762
BOOL WINAPI DestroyPropertySheetPage(HPROPSHEETPAGE hPropPage)
Definition: propsheet.c:3141
GLdouble GLdouble GLdouble r
Definition: gl.h:2055
#define CP_ACP
Definition: compat.h:99
PROPSHEETHEADERW ppshheader
Definition: propsheet.c:111
#define WM_CTLCOLORSTATIC
Definition: winuser.h:1754
char CHAR
Definition: xmlstorage.h:175
TW_UINT32 TW_UINT16 TW_UINT16 MSG
Definition: twain.h:1827
#define DT_WORDBREAK
Definition: winuser.h:544
#define IDC_FINISH_BUTTON
Definition: comctl32.h:49
#define WARN(fmt,...)
Definition: debug.h:111
HRSRC WINAPI FindResourceA(HMODULE hModule, LPCSTR name, LPCSTR type)
Definition: res.c:155
LPCDLGTEMPLATE pResource
Definition: prsht.h:210
LPCSTR pszCaption
Definition: prsht.h:248
static HDC
Definition: imagelist.c:92
#define CALLBACK
Definition: compat.h:27
_In_ DWORD nLength
Definition: wincon.h:461
#define WM_SETREDRAW
Definition: winuser.h:1598
#define PSBTN_APPLYNOW
Definition: prsht.h:150
static INT_PTR(WINAPI *pPropertySheetA)(const PROPSHEETHEADERA *header)
LPCSTR pszTitle
Definition: prsht.h:188
GLdouble n
Definition: glext.h:7729
LONG top
Definition: windef.h:292
#define PSWIZB_NEXT
Definition: prsht.h:154
BOOL WINAPI MapDialogRect(_In_ HWND, _Inout_ LPRECT)
#define PSM_REMOVEPAGE
Definition: prsht.h:166
static BOOL PROPSHEET_CollectPageInfo(LPCPROPSHEETPAGEW lppsp, PropSheetInfo *psInfo, int index, BOOL resize)
Definition: propsheet.c:399
static BOOL PROPSHEET_AddPage(HWND hwndDlg, HPROPSHEETPAGE hpage)
Definition: propsheet.c:2339
HGDIOBJ WINAPI SelectObject(_In_ HDC, _In_ HGDIOBJ)
Definition: dc.c:1497
HWND WINAPI CreateDialogIndirectParamW(_In_opt_ HINSTANCE, _In_ LPCDLGTEMPLATE, _In_opt_ HWND, _In_opt_ DLGPROC, _In_ LPARAM)
BOOL WINAPI DeleteObject(_In_ HGDIOBJ)
LPVOID WINAPI LockResource(HGLOBAL handle)
Definition: res.c:550
#define DM_SETDEFID
Definition: winuser.h:2081
LPCSTR pszTemplate
Definition: prsht.h:181
#define HWND_TOP
Definition: winuser.h:1193
#define SM_CYSMICON
Definition: winuser.h:1003
GLint GLint GLint GLint GLint x
Definition: gl.h:1548
#define PSBTN_HELP
Definition: prsht.h:152
#define MAKEINTRESOURCEA(i)
Definition: winuser.h:581
#define TCM_SETCURSEL
Definition: commctrl.h:4037
HWND WINAPI SetFocus(_In_opt_ HWND)
#define PSP_USEICONID
Definition: prsht.h:25
HDC WINAPI CreateCompatibleDC(_In_opt_ HDC hdc)
#define PSWIZB_DISABLEDFINISH
Definition: prsht.h:156
#define PSP_USECALLBACK
Definition: prsht.h:30
BOOL WINAPI SetWindowTextW(_In_ HWND, _In_opt_ LPCWSTR)
static BOOL PROPSHEET_RecalcPageSizes(HWND hwndDlg)
Definition: propsheet.c:2706
UINT_PTR WPARAM
Definition: windef.h:207
struct tagPropSheetInfo PropSheetInfo
#define VK_TAB
Definition: winuser.h:2174
GLuint GLuint end
Definition: gl.h:1545
#define PSBTN_FINISH
Definition: prsht.h:148
#define WS_CHILD
Definition: pedump.c:617
#define VK_PRIOR
Definition: winuser.h:2195
#define TCIF_TEXT
Definition: commctrl.h:3943
#define PSH_WIZARD
Definition: prsht.h:45
#define PSN_APPLY
Definition: prsht.h:117
LONG left
Definition: windef.h:291
#define SWP_NOZORDER
Definition: winuser.h:1232
BOOL WINAPI ShowWindow(_In_ HWND, _In_ int)
static HDC hdcSrc
Definition: xlate.c:32
BOOL WINAPI EndPaint(_In_ HWND, _In_ const PAINTSTRUCT *)
int32_t INT_PTR
Definition: typedefs.h:62
#define PSH_MODELESS
Definition: prsht.h:50
#define PSH_USECALLBACK
Definition: prsht.h:48
char * LPSTR
Definition: xmlstorage.h:182
static const WCHAR PropSheetInfoStr[]
Definition: propsheet.c:143
DWORD GetPixel(LPDIRECTDRAWSURFACE7 Surface, UINT x, UINT y)
Definition: blt.cpp:2
LONG right
Definition: windef.h:293
HWND WINAPI GetNextDlgTabItem(_In_ HWND, _In_opt_ HWND, _In_ BOOL)
#define lstrlenW
Definition: compat.h:407
BOOL WINAPI DestroyWindow(_In_ HWND)
#define PSN_SETACTIVE
Definition: prsht.h:115
static void PROPSHEET_SetHeaderTitleA(HWND hwndDlg, UINT page_index, const char *title)
Definition: propsheet.c:2551
static VOID NTAPI BitBlt(IN ULONG Left, IN ULONG Top, IN ULONG Width, IN ULONG Height, IN PUCHAR Buffer, IN ULONG BitsPerPixel, IN ULONG Delta)
Definition: vga.c:410
int WINAPI LoadStringW(_In_opt_ HINSTANCE hInstance, _In_ UINT uID, _Out_writes_to_(cchBufferMax, return+1) LPWSTR lpBuffer, _In_ int cchBufferMax)
#define COLOR_WINDOW
Definition: winuser.h:908
int32_t INT
Definition: typedefs.h:56
#define PSM_SETFINISHTEXTW
Definition: prsht.h:105
static UINT GetTemplateSize(const DLGTEMPLATE *pTemplate)
Definition: propsheet.c:1209
DWORD WINAPI GetSysColor(_In_ int)
WPARAM wParam
Definition: combotst.c:138
HRSRC WINAPI FindResourceW(HINSTANCE hModule, LPCWSTR name, LPCWSTR type)
Definition: res.c:176
HWND WINAPI GetTopWindow(_In_opt_ HWND)
#define DWLP_MSGRESULT
Definition: winuser.h:864
struct tagNMHDR * LPNMHDR
HANDLE WINAPI RemovePropW(_In_ HWND, _In_ LPCWSTR)
#define MAX_BUTTONTEXT_LENGTH
Definition: propsheet.c:150
#define WM_PRINTCLIENT
Definition: richedit.h:70
static BOOL PROPSHEET_IsDialogMessage(HWND hwnd, LPMSG lpMsg)
Definition: propsheet.c:3174
UINT nStartPage
Definition: prsht.h:251
#define VK_NEXT
Definition: winuser.h:2196
_In_opt_ PALLOCATE_FUNCTION _In_opt_ PFREE_FUNCTION Free
Definition: exfuncs.h:656
#define ID_PSRESTARTWINDOWS
Definition: prsht.h:132
#define PSM_ISDIALOGMESSAGE
Definition: prsht.h:96
BOOL WINAPI ImageList_Destroy(HIMAGELIST himl)
Definition: imagelist.c:928
#define IDHELP
Definition: resource_2.h:8
static BOOL PROPSHEET_AdjustButtonsWizard(HWND hwndParent, const PropSheetInfo *psInfo)
Definition: propsheet.c:928
#define PSM_SETCURSEL
Definition: prsht.h:167
#define PSN_QUERYCANCEL
Definition: prsht.h:123
UINT code
Definition: winuser.h:3133
static void PROPSHEET_Changed(HWND hwndDlg, HWND hwndDirtyPage)
Definition: propsheet.c:1835
COLORREF WINAPI SetBkColor(_In_ HDC, _In_ COLORREF)
Definition: dc.c:975
#define DS_MODALFRAME
Definition: winuser.h:375
NMHDR hdr
Definition: prsht.h:312
static void PROPSHEET_SetHeaderTitleW(HWND hwndDlg, UINT page_index, const WCHAR *title)
Definition: propsheet.c:2529
static INT PROPSHEET_FindPageByResId(const PropSheetInfo *psInfo, LRESULT resId)
Definition: propsheet.c:274
BOOL WINAPI AdjustWindowRect(_Inout_ LPRECT, _In_ DWORD, _In_ BOOL)
LPWSTR strPropertiesFor
Definition: propsheet.c:113
static BOOL PROPSHEET_CanSetCurSel(HWND hwndDlg)
Definition: propsheet.c:1940
int WINAPI SetBkMode(_In_ HDC, _In_ int)
Definition: dc.c:1032
#define IDD_PROPSHEET
Definition: comctl32.h:42
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
static void PROPSHEET_GetPageRect(const PropSheetInfo *psInfo, HWND hwndDlg, RECT *rc, LPCPROPSHEETPAGEW ppshpage)
Definition: propsheet.c:230
#define WS_EX_CONTROLPARENT
Definition: winuser.h:387
HIMAGELIST WINAPI ImageList_Create(INT cx, INT cy, UINT flags, INT cInitial, INT cGrow)
Definition: imagelist.c:804
#define PSN_KILLACTIVE
Definition: prsht.h:116
DWORD dwSize
Definition: prsht.h:205
#define PSH_USEICONID
Definition: prsht.h:42
static LONG active_page
Definition: propsheet.c:37
#define DT_LEFT
Definition: winuser.h:534
#define PSN_WIZFINISH
Definition: prsht.h:122
static const WCHAR szText[]
Definition: dialog.c:139
LRESULT WINAPI DispatchMessageW(_In_ const MSG *)
HIMAGELIST hImageList
Definition: propsheet.c:128
LPCWSTR pszCaption
Definition: prsht.h:283
static void PROPSHEET_Cancel(HWND hwndDlg, LPARAM lParam)
Definition: propsheet.c:1770
HWND hwndParent
Definition: prsht.h:242
unsigned int BOOL
Definition: ntddk_ex.h:94
DLGPROC pfnDlgProc
Definition: prsht.h:217
HANDLE WINAPI LoadImageW(_In_opt_ HINSTANCE, _In_ LPCWSTR, _In_ UINT, _In_ int, _In_ int, _In_ UINT)
Definition: cursoricon.c:2172
long LONG
Definition: pedump.c:60
HDC WINAPI BeginPaint(_In_ HWND, _Out_ LPPAINTSTRUCT)
static WCHAR * heap_strdupW(const WCHAR *str)
Definition: propsheet.c:178
UINT_PTR idFrom
Definition: winuser.h:3132
static BOOL PROPSHEET_Next(HWND hwndDlg)
Definition: propsheet.c:1623
#define debugstr_w
Definition: kernel32.h:32
struct _PSP * HPROPSHEETPAGE
Definition: mstask.idl:90
#define PSH_WIZARDCONTEXTHELP
Definition: prsht.h:52
#define FIXME(fmt,...)
Definition: debug.h:110
#define ILC_COLOR
Definition: commctrl.h:337
#define PSM_SETWIZBUTTONS
Definition: prsht.h:157
#define TCM_DELETEITEM
Definition: commctrl.h:4025
static PVOID ptr
Definition: dispmode.c:27
PFNPROPSHEETCALLBACK pfnCallback
Definition: prsht.h:293
unsigned int idx
Definition: utils.c:41
#define TRANSPARENT
Definition: wingdi.h:949
static BOOL PROPSHEET_CreateTabControl(HWND hwndParent, const PropSheetInfo *psInfo)
Definition: propsheet.c:1137
static void PROPSHEET_SetCurSelId(HWND hwndDlg, int id)
Definition: propsheet.c:2103
#define VK_SHIFT
Definition: winuser.h:2177
#define PSCB_PRECREATE
Definition: prsht.h:76
PFNPROPSHEETCALLBACK pfnCallback
Definition: prsht.h:258
HGLOBAL WINAPI LoadResource(HINSTANCE hModule, HRSRC hRsrc)
Definition: res.c:532
const WCHAR * str
LONG WINAPI GetWindowLongW(_In_ HWND, _In_ int)
#define TCM_INSERTITEMW
Definition: commctrl.h:4019
static void PROPSHEET_CollectSheetInfoW(LPCPROPSHEETHEADERW lppsh, PropSheetInfo *psInfo)
Definition: propsheet.c:361
#define PSNRET_INVALID_NOCHANGEPAGE
Definition: prsht.h:131
HPALETTE WINAPI SelectPalette(_In_ HDC, _In_ HPALETTE, _In_ BOOL)
static INT_PTR PROPSHEET_CreateDialog(PropSheetInfo *psInfo)
Definition: propsheet.c:600
smooth NULL
Definition: ftsmooth.c:416
HFONT WINAPI CreateFontIndirectW(_In_ const LOGFONTW *)
struct _PROPSHEETPAGEW * LPPROPSHEETPAGEW
static HWND hwndParent
Definition: cryptui.c:300
LPCSTR pszIcon
Definition: prsht.h:186
#define PSN_WIZNEXT
Definition: prsht.h:121
#define ETDT_ENABLETAB
Definition: dxdiag.c:30
#define WM_KEYDOWN
Definition: winuser.h:1697
LONG_PTR LPARAM
Definition: windef.h:208
Definition: module.h:566
#define PSM_SETCURSELID
Definition: prsht.h:104
static PADDING_INFO PROPSHEET_GetPaddingInfo(HWND hwndDlg)
Definition: propsheet.c:1055
LPCWSTR pszText
Definition: propsheet.c:102
static LRESULT PROPSHEET_IdToIndex(HWND hwndDlg, int iPageId)
Definition: propsheet.c:2660
INT_PTR WINAPI PropertySheetW(LPCPROPSHEETHEADERW lppsh)
Definition: propsheet.c:2902
LRESULT WINAPI DefSubclassProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
Definition: commctrl.c:1496
GLuint index
Definition: glext.h:6031
HBITMAP WINAPI CreateMappedBitmap(HINSTANCE hInstance, INT_PTR idBitmap, UINT wFlags, LPCOLORMAP lpColorMap, INT iNumMaps)
Definition: commctrl.c:998
static BOOL PROPSHEET_SizeMismatch(HWND hwndDlg, const PropSheetInfo *psInfo)
Definition: propsheet.c:692
const char * LPCSTR
Definition: xmlstorage.h:183
static void PROPSHEET_CollectSheetInfoA(LPCPROPSHEETHEADERA lppsh, PropSheetInfo *psInfo)
Definition: propsheet.c:317
LPCWSTR pszTitle
Definition: prsht.h:216
#define SW_SHOW
Definition: winuser.h:769
INT_PTR WINAPI PropertySheetA(LPCPROPSHEETHEADERA lppsh)
Definition: propsheet.c:2861
#define PSPCB_RELEASE
Definition: prsht.h:37
static BOOL PROPSHEET_Back(HWND hwndDlg)
Definition: propsheet.c:1581
#define UlongToPtr(u)
Definition: config.h:106
#define WM_DESTROY
Definition: winuser.h:1591
#define IDS_CLOSE
Definition: comctl32.h:53
#define PSBTN_CANCEL
Definition: prsht.h:151
#define PSM_REBOOTSYSTEM
Definition: prsht.h:162
#define RT_DIALOG
Definition: pedump.c:367
SHORT WINAPI GetKeyState(_In_ int)
HPROPSHEETPAGE WINAPI CreatePropertySheetPageW(LPCPROPSHEETPAGEW lpPropSheetPage)
Definition: propsheet.c:3072
#define PSWIZB_FINISH
Definition: prsht.h:155
HBITMAP hbmp
BOOL WINAPI SetWindowSubclass(HWND hWnd, SUBCLASSPROC pfnSubclass, UINT_PTR uIDSubclass, DWORD_PTR dwRef)
Definition: commctrl.c:1261
#define WS_CAPTION
Definition: pedump.c:624
BOOL WINAPI SystemParametersInfoW(_In_ UINT, _In_ UINT, _Inout_opt_ PVOID, _In_ UINT)
#define TCN_SELCHANGE
Definition: commctrl.h:4104
#define PSM_APPLY
Definition: prsht.h:158
static void PROPSHEET_SetWizButtons(HWND hwndDlg, DWORD dwFlags)
Definition: propsheet.c:2455
static void PROPSHEET_SetFinishTextW(HWND hwndDlg, LPCWSTR lpszText)
Definition: propsheet.c:2195
static VOID PROPSHEET_UnImplementedFlags(DWORD dwFlags)
Definition: propsheet.c:204
static VOID PROPSHEET_LoadWizardBitmaps(PropSheetInfo *psInfo)
Definition: propsheet.c:1490
#define TRACE(s)
Definition: solgame.cpp:4
unsigned int padding
Definition: isohybrid.c:50
#define IS_INTRESOURCE(i)
Definition: winuser.h:580
#define IDC_SUNKEN_LINEHEADER
Definition: comctl32.h:51
BOOL WINAPI SetPropW(_In_ HWND, _In_ LPCWSTR, _In_opt_ HANDLE)
r parent
Definition: btrfs.c:2897
static BOOL PROPSHEET_AdjustButtons(HWND hwndParent, const PropSheetInfo *psInfo)
Definition: propsheet.c:839
if(!(yy_init))
Definition: macro.lex.yy.c:714
HWND WINAPI GetDlgItem(_In_opt_ HWND, _In_ int)
__wchar_t WCHAR
Definition: xmlstorage.h:180
#define PSWIZB_BACK
Definition: prsht.h:153
#define debugstr_a
Definition: kernel32.h:31
#define PSM_CANCELTOCLOSE
Definition: prsht.h:161
#define PSH_PROPTITLE
Definition: prsht.h:40
BOOL WINAPI SetWindowTextA(_In_ HWND, _In_opt_ LPCSTR)
#define SWP_NOACTIVATE
Definition: winuser.h:1227
DWORD COLORREF
Definition: windef.h:285
HINSTANCE hInstance
Definition: prsht.h:278
HRESULT WINAPI EnableThemeDialogTexture(_In_ HWND hwnd, _In_ DWORD dwFlags)
Definition: uxthemesupp.c:55
DWORD dwSize
Definition: prsht.h:240
#define PROPSHEETPAGEA_V1_SIZE
Definition: prsht.h:200
#define PSH_USEPSTARTPAGE
Definition: prsht.h:46
#define WM_CLOSE
Definition: winuser.h:1603
#define PSH_HASHELP
Definition: prsht.h:49
HWND WINAPI CreateDialogIndirectParamA(_In_opt_ HINSTANCE, _In_ LPCDLGTEMPLATE, _In_opt_ HWND, _In_opt_ DLGPROC, _In_ LPARAM)
#define WINAPI
Definition: msvc.h:8
const char * wine_dbgstr_rect(const RECT *rect)
BOOL WINAPI InvalidateRect(_In_opt_ HWND, _In_opt_ LPCRECT, _In_ BOOL)
PVOID Alloc(IN DWORD dwFlags, IN SIZE_T dwBytes)
Definition: main.c:63
static const WCHAR titleW[]
Definition: htmlelem.c:1067
unsigned short WORD
Definition: ntddk_ex.h:93
int WINAPI GetSystemMetrics(_In_ int)
#define PSM_GETRESULT
Definition: window.cpp:1319
#define for
Definition: utility.h:88
unsigned long DWORD
Definition: ntddk_ex.h:95
static BOOL PROPSHEET_AdjustSizeWizard(HWND hwndDlg, const PropSheetInfo *psInfo)
Definition: propsheet.c:805
const PROPSHEETPAGEA * LPCPROPSHEETPAGEA
Definition: prsht.h:199
#define PSM_GETCURRENTPAGEHWND
Definition: prsht.h:81
HGLOBAL NTAPI GlobalFree(HGLOBAL hMem)
Definition: heapmem.c:611
unsigned __int3264 UINT_PTR
Definition: mstsclib_h.h:274
DWORD dwSize
Definition: prsht.h:275
INT WINAPI ImageList_AddIcon(HIMAGELIST himl, HICON hIcon)
Definition: imagelist.c:540
#define PSM_RESTARTWINDOWS
Definition: prsht.h:163
#define PSBTN_OK
Definition: prsht.h:149
DWORD dwFlags
Definition: prsht.h:276
TCHAR szTitle[MAX_LOADSTRING]
Definition: magnifier.c:35
static BOOL PROPSHEET_SetCurSel(HWND hwndDlg, int index, int skipdir, HPROPSHEETPAGE hpage)
Definition: propsheet.c:1979
#define WM_PAINT
Definition: winuser.h:1602
#define SM_CXSMICON
Definition: winuser.h:1002
static BOOL PROPSHEET_InsertPage(HWND hwndDlg, HPROPSHEETPAGE hpageInsertAfter, HPROPSHEETPAGE hpage)
Definition: propsheet.c:2245
DWORD dwFlags
Definition: prsht.h:241
#define IDD_WIZARD
Definition: comctl32.h:43
#define IDC_BACK_BUTTON
Definition: comctl32.h:47
int ret
static WCHAR * heap_strdupAtoW(const char *str)
Definition: propsheet.c:186
static LRESULT PROPSHEET_IndexToHwnd(HWND hwndDlg, int iPageIndex)
Definition: propsheet.c:2618
#define PSPCB_CREATE
Definition: prsht.h:38
#define index(s, c)
Definition: various.h:29
HDC hdc
Definition: main.c:9
#define DS_SETFONT
Definition: winuser.h:378
static BOOL PROPSHEET_AdjustSize(HWND hwndDlg, PropSheetInfo *psInfo)
Definition: propsheet.c:723
#define DWLP_USER
Definition: winuser.h:866
_In_ PCCERT_CONTEXT _In_ DWORD dwFlags
Definition: wincrypt.h:1175
#define DS_CONTEXTHELP
Definition: winuser.h:371
HINSTANCE hInstance
Definition: prsht.h:207
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
GLenum GLsizei len
Definition: glext.h:6722
unsigned char BYTE
Definition: mem.h:68
#define RT_STRING
Definition: pedump.c:368
#define WS_TABSTOP
Definition: pedump.c:634
#define PSM_ADDPAGE
Definition: prsht.h:165
#define PSM_UNCHANGED
Definition: prsht.h:159
#define WM_COMMAND
Definition: winuser.h:1722
DWORD dwFlags
Definition: prsht.h:178
static INT do_loop(const PropSheetInfo *psInfo)
Definition: propsheet.c:2787
HWND hwndFrom
Definition: winuser.h:3131
uint32_t DWORD_PTR
Definition: typedefs.h:63
#define PSP_USETITLE
Definition: prsht.h:26
#define PSBTN_NEXT
Definition: prsht.h:147
GLint GLint GLsizei GLsizei height
Definition: gl.h:1546
static void PROPSHEET_SetHeaderSubTitleA(HWND hwndDlg, UINT page_index, const char *subtitle)
Definition: propsheet.c:2587
HICON hIcon
Definition: prsht.h:213
BOOL WINAPI EnableWindow(_In_ HWND, _In_ BOOL)
HPROPSHEETPAGE * phpage
Definition: prsht.h:291
const PROPSHEETPAGEW * LPCPROPSHEETPAGEW
Definition: prsht.h:227
#define SWP_NOSIZE
Definition: winuser.h:1230
#define ERR(fmt,...)
Definition: debug.h:109
static BOOL PROPSHEET_CreatePage(HWND hwndParent, int index, const PropSheetInfo *psInfo, LPCPROPSHEETPAGEW ppshpage)
Definition: propsheet.c:1344
#define GWL_STYLE
Definition: winuser.h:846
#define DT_NOCLIP
Definition: winuser.h:536
COLORREF WINAPI SetTextColor(_In_ HDC, _In_ COLORREF)
Definition: text.c:888
int WINAPI GetObjectW(_In_ HANDLE h, _In_ int c, _Out_writes_bytes_opt_(c) LPVOID pv)
#define WIZARD_PADDING
Definition: propsheet.c:155
BOOL WINAPI GetClientRect(_In_ HWND, _Out_ LPRECT)
#define TCM_SETIMAGELIST
Definition: commctrl.h:3937
#define MAX_CAPTION_LENGTH
Definition: propsheet.c:148
#define DT_SINGLELINE
Definition: winuser.h:540
BOOL WINAPI SetRect(_Out_ LPRECT, _In_ int, _In_ int, _In_ int, _In_ int)
WINE_UNICODE_INLINE WCHAR * strcpyW(WCHAR *dst, const WCHAR *src)
Definition: unicode.h:219
#define TCIF_IMAGE
Definition: commctrl.h:3944