ReactOS  0.4.15-dev-1636-gf634010
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  {
1473 #ifdef __REACTOS__
1474  if (psInfo->ppshheader.u4.hbmWatermark)
1475 #endif
1477  (DWORD_PTR)ppshpage);
1478  }
1479  if (!(psInfo->ppshheader.dwFlags & INTRNL_ANY_WIZARD))
1481 
1482 #ifdef __REACTOS__
1483  PROPSHEET_UnChanged(hwndParent, hwndPage);
1484 #endif
1485  return TRUE;
1486 }
1487 
1488 /******************************************************************************
1489  * PROPSHEET_LoadWizardBitmaps
1490  *
1491  * Loads the watermark and header bitmaps for a wizard.
1492  */
1494 {
1495  if (psInfo->ppshheader.dwFlags & (PSH_WIZARD97_NEW | PSH_WIZARD97_OLD))
1496  {
1497  /* if PSH_USEHBMWATERMARK is not set, load the resource from pszbmWatermark
1498  and put the HBITMAP in hbmWatermark. Thus all the rest of the code always
1499  considers hbmWatermark as valid. */
1500  if ((psInfo->ppshheader.dwFlags & PSH_WATERMARK) &&
1501  !(psInfo->ppshheader.dwFlags & PSH_USEHBMWATERMARK))
1502  {
1503  psInfo->ppshheader.u4.hbmWatermark =
1504  CreateMappedBitmap(psInfo->ppshheader.hInstance, (INT_PTR)psInfo->ppshheader.u4.pszbmWatermark, 0, NULL, 0);
1505  }
1506 
1507  /* Same behavior as for watermarks */
1508  if ((psInfo->ppshheader.dwFlags & PSH_HEADER) &&
1509  !(psInfo->ppshheader.dwFlags & PSH_USEHBMHEADER))
1510  {
1511  psInfo->ppshheader.u5.hbmHeader =
1512  CreateMappedBitmap(psInfo->ppshheader.hInstance, (INT_PTR)psInfo->ppshheader.u5.pszbmHeader, 0, NULL, 0);
1513  }
1514  }
1515 }
1516 
1517 
1518 /******************************************************************************
1519  * PROPSHEET_ShowPage
1520  *
1521  * Displays or creates the specified page.
1522  */
1523 static BOOL PROPSHEET_ShowPage(HWND hwndDlg, int index, PropSheetInfo * psInfo)
1524 {
1525  HWND hwndTabCtrl;
1526  HWND hwndLineHeader;
1527  HWND control;
1528  LPCPROPSHEETPAGEW ppshpage;
1529 
1530  TRACE("active_page %d, index %d\n", psInfo->active_page, index);
1531  if (index == psInfo->active_page)
1532  {
1533  if (GetTopWindow(hwndDlg) != psInfo->proppage[index].hwndPage)
1534  SetWindowPos(psInfo->proppage[index].hwndPage, HWND_TOP, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE);
1535  return TRUE;
1536  }
1537 
1538  ppshpage = (LPCPROPSHEETPAGEW)psInfo->proppage[index].hpage;
1539  if (psInfo->proppage[index].hwndPage == 0)
1540  {
1541  PROPSHEET_CreatePage(hwndDlg, index, psInfo, ppshpage);
1542  }
1543 
1544  if (psInfo->ppshheader.dwFlags & INTRNL_ANY_WIZARD)
1545  {
1546  PROPSHEET_SetTitleW(hwndDlg, psInfo->ppshheader.dwFlags,
1547  psInfo->proppage[index].pszText);
1548 
1549  control = GetNextDlgTabItem(psInfo->proppage[index].hwndPage, NULL, FALSE);
1550  if(control != NULL)
1551  SetFocus(control);
1552  }
1553 
1554  if (psInfo->active_page != -1)
1555  ShowWindow(psInfo->proppage[psInfo->active_page].hwndPage, SW_HIDE);
1556 
1558 
1559  /* Synchronize current selection with tab control
1560  * It seems to be needed even in case of PSH_WIZARD (no tab controls there) */
1561  hwndTabCtrl = GetDlgItem(hwndDlg, IDC_TABCONTROL);
1562  SendMessageW(hwndTabCtrl, TCM_SETCURSEL, index, 0);
1563 
1564  psInfo->active_page = index;
1565  psInfo->activeValid = TRUE;
1566 
1567  if (psInfo->ppshheader.dwFlags & (PSH_WIZARD97_OLD | PSH_WIZARD97_NEW) )
1568  {
1569  hwndLineHeader = GetDlgItem(hwndDlg, IDC_SUNKEN_LINEHEADER);
1570  ppshpage = (LPCPROPSHEETPAGEW)psInfo->proppage[index].hpage;
1571 
1572  if ((ppshpage->dwFlags & PSP_HIDEHEADER) || (!(psInfo->ppshheader.dwFlags & PSH_HEADER)) )
1573  ShowWindow(hwndLineHeader, SW_HIDE);
1574  else
1575  ShowWindow(hwndLineHeader, SW_SHOW);
1576  }
1577 
1578  return TRUE;
1579 }
1580 
1581 /******************************************************************************
1582  * PROPSHEET_Back
1583  */
1584 static BOOL PROPSHEET_Back(HWND hwndDlg)
1585 {
1586  PSHNOTIFY psn;
1587  HWND hwndPage;
1588  PropSheetInfo* psInfo = GetPropW(hwndDlg, PropSheetInfoStr);
1589  LRESULT result;
1590  int idx;
1591 
1592  TRACE("active_page %d\n", psInfo->active_page);
1593  if (psInfo->active_page < 0)
1594  return FALSE;
1595 
1596  psn.hdr.code = PSN_WIZBACK;
1597  psn.hdr.hwndFrom = hwndDlg;
1598  psn.hdr.idFrom = 0;
1599  psn.lParam = 0;
1600 
1601  hwndPage = psInfo->proppage[psInfo->active_page].hwndPage;
1602 
1603  result = SendMessageW(hwndPage, WM_NOTIFY, 0, (LPARAM) &psn);
1604  if (result == -1)
1605  return FALSE;
1606  else if (result == 0)
1607  idx = psInfo->active_page - 1;
1608  else
1610 
1611  if (idx >= 0 && idx < psInfo->nPages)
1612  {
1613  if (PROPSHEET_CanSetCurSel(hwndDlg))
1614  {
1615  SetFocus(GetDlgItem(hwndDlg, IDC_BACK_BUTTON));
1617  PROPSHEET_SetCurSel(hwndDlg, idx, -1, 0);
1618  }
1619  }
1620  return TRUE;
1621 }
1622 
1623 /******************************************************************************
1624  * PROPSHEET_Next
1625  */
1626 static BOOL PROPSHEET_Next(HWND hwndDlg)
1627 {
1628  PSHNOTIFY psn;
1629  HWND hwndPage;
1630  LRESULT msgResult = 0;
1631  PropSheetInfo* psInfo = GetPropW(hwndDlg, PropSheetInfoStr);
1632  int idx;
1633 
1634  TRACE("active_page %d\n", psInfo->active_page);
1635  if (psInfo->active_page < 0)
1636  return FALSE;
1637 
1638  psn.hdr.code = PSN_WIZNEXT;
1639  psn.hdr.hwndFrom = hwndDlg;
1640  psn.hdr.idFrom = 0;
1641  psn.lParam = 0;
1642 
1643  hwndPage = psInfo->proppage[psInfo->active_page].hwndPage;
1644 
1645  msgResult = SendMessageW(hwndPage, WM_NOTIFY, 0, (LPARAM) &psn);
1646  if (msgResult == -1)
1647  return FALSE;
1648  else if (msgResult == 0)
1649  idx = psInfo->active_page + 1;
1650  else
1651  idx = PROPSHEET_FindPageByResId(psInfo, msgResult);
1652 
1653  if (idx < psInfo->nPages )
1654  {
1655  if (PROPSHEET_CanSetCurSel(hwndDlg) != FALSE)
1656  {
1657  SetFocus(GetDlgItem(hwndDlg, IDC_NEXT_BUTTON));
1659  PROPSHEET_SetCurSel(hwndDlg, idx, 1, 0);
1660  }
1661  }
1662 
1663  return TRUE;
1664 }
1665 
1666 /******************************************************************************
1667  * PROPSHEET_Finish
1668  */
1669 static BOOL PROPSHEET_Finish(HWND hwndDlg)
1670 {
1671  PSHNOTIFY psn;
1672  HWND hwndPage;
1673  LRESULT msgResult = 0;
1674  PropSheetInfo* psInfo = GetPropW(hwndDlg, PropSheetInfoStr);
1675 
1676  TRACE("active_page %d\n", psInfo->active_page);
1677  if (psInfo->active_page < 0)
1678  return FALSE;
1679 
1680  psn.hdr.code = PSN_WIZFINISH;
1681  psn.hdr.hwndFrom = hwndDlg;
1682  psn.hdr.idFrom = 0;
1683  psn.lParam = 0;
1684 
1685  hwndPage = psInfo->proppage[psInfo->active_page].hwndPage;
1686 
1687  msgResult = SendMessageW(hwndPage, WM_NOTIFY, 0, (LPARAM) &psn);
1688 
1689  TRACE("msg result %ld\n", msgResult);
1690 
1691  if (msgResult != 0)
1692  return FALSE;
1693 
1694  if (psInfo->result == 0)
1695  psInfo->result = IDOK;
1696  if (psInfo->isModeless)
1697  psInfo->activeValid = FALSE;
1698  else
1699  psInfo->ended = TRUE;
1700 
1701  return TRUE;
1702 }
1703 
1704 /******************************************************************************
1705  * PROPSHEET_Apply
1706  */
1708 {
1709  int i;
1710  HWND hwndPage;
1711  PSHNOTIFY psn;
1712  PropSheetInfo* psInfo = GetPropW(hwndDlg, PropSheetInfoStr);
1713 
1714  TRACE("active_page %d\n", psInfo->active_page);
1715  if (psInfo->active_page < 0)
1716  return FALSE;
1717 
1718  psn.hdr.hwndFrom = hwndDlg;
1719  psn.hdr.idFrom = 0;
1720  psn.lParam = 0;
1721 
1722 
1723  /*
1724  * Send PSN_KILLACTIVE to the current page.
1725  */
1726  psn.hdr.code = PSN_KILLACTIVE;
1727 
1728  hwndPage = psInfo->proppage[psInfo->active_page].hwndPage;
1729 
1730  if (SendMessageW(hwndPage, WM_NOTIFY, 0, (LPARAM) &psn) != FALSE)
1731  return FALSE;
1732 
1733  /*
1734  * Send PSN_APPLY to all pages.
1735  */
1736  psn.hdr.code = PSN_APPLY;
1737  psn.lParam = lParam;
1738 
1739  for (i = 0; i < psInfo->nPages; i++)
1740  {
1741  hwndPage = psInfo->proppage[i].hwndPage;
1742  if (hwndPage)
1743  {
1744  switch (SendMessageW(hwndPage, WM_NOTIFY, 0, (LPARAM) &psn))
1745  {
1746  case PSNRET_INVALID:
1747  PROPSHEET_ShowPage(hwndDlg, i, psInfo);
1748  /* fall through */
1750  return FALSE;
1751  }
1752  }
1753  }
1754 
1755  if(lParam)
1756  {
1757  psInfo->activeValid = FALSE;
1758  }
1759  else if(psInfo->active_page >= 0)
1760  {
1761  psn.hdr.code = PSN_SETACTIVE;
1762  psn.lParam = 0;
1763  hwndPage = psInfo->proppage[psInfo->active_page].hwndPage;
1764  SendMessageW(hwndPage, WM_NOTIFY, 0, (LPARAM) &psn);
1765  }
1766 
1767  return TRUE;
1768 }
1769 
1770 /******************************************************************************
1771  * PROPSHEET_Cancel
1772  */
1773 static void PROPSHEET_Cancel(HWND hwndDlg, LPARAM lParam)
1774 {
1775  PropSheetInfo* psInfo = GetPropW(hwndDlg, PropSheetInfoStr);
1776  HWND hwndPage;
1777  PSHNOTIFY psn;
1778  int i;
1779 
1780  TRACE("active_page %d\n", psInfo->active_page);
1781  if (psInfo->active_page < 0)
1782  return;
1783 
1784  hwndPage = psInfo->proppage[psInfo->active_page].hwndPage;
1785  psn.hdr.code = PSN_QUERYCANCEL;
1786  psn.hdr.hwndFrom = hwndDlg;
1787  psn.hdr.idFrom = 0;
1788  psn.lParam = 0;
1789 
1790  if (SendMessageW(hwndPage, WM_NOTIFY, 0, (LPARAM) &psn))
1791  return;
1792 
1793  psn.hdr.code = PSN_RESET;
1794  psn.lParam = lParam;
1795 
1796  for (i = 0; i < psInfo->nPages; i++)
1797  {
1798  hwndPage = psInfo->proppage[i].hwndPage;
1799 
1800  if (hwndPage)
1801  SendMessageW(hwndPage, WM_NOTIFY, 0, (LPARAM) &psn);
1802  }
1803 
1804  if (psInfo->isModeless)
1805  {
1806  /* makes PSM_GETCURRENTPAGEHWND return NULL */
1807  psInfo->activeValid = FALSE;
1808  }
1809  else
1810  psInfo->ended = TRUE;
1811 }
1812 
1813 /******************************************************************************
1814  * PROPSHEET_Help
1815  */
1816 static void PROPSHEET_Help(HWND hwndDlg)
1817 {
1818  PropSheetInfo* psInfo = GetPropW(hwndDlg, PropSheetInfoStr);
1819  HWND hwndPage;
1820  PSHNOTIFY psn;
1821 
1822  TRACE("active_page %d\n", psInfo->active_page);
1823  if (psInfo->active_page < 0)
1824  return;
1825 
1826  hwndPage = psInfo->proppage[psInfo->active_page].hwndPage;
1827  psn.hdr.code = PSN_HELP;
1828  psn.hdr.hwndFrom = hwndDlg;
1829  psn.hdr.idFrom = 0;
1830  psn.lParam = 0;
1831 
1832  SendMessageW(hwndPage, WM_NOTIFY, 0, (LPARAM) &psn);
1833 }
1834 
1835 /******************************************************************************
1836  * PROPSHEET_Changed
1837  */
1838 static void PROPSHEET_Changed(HWND hwndDlg, HWND hwndDirtyPage)
1839 {
1840  int i;
1841  PropSheetInfo* psInfo = GetPropW(hwndDlg, PropSheetInfoStr);
1842 
1843  TRACE("\n");
1844  if (!psInfo) return;
1845  /*
1846  * Set the dirty flag of this page.
1847  */
1848  for (i = 0; i < psInfo->nPages; i++)
1849  {
1850  if (psInfo->proppage[i].hwndPage == hwndDirtyPage)
1851  psInfo->proppage[i].isDirty = TRUE;
1852  }
1853 
1854  /*
1855  * Enable the Apply button.
1856  */
1857  if (psInfo->hasApply)
1858  {
1859  HWND hwndApplyBtn = GetDlgItem(hwndDlg, IDC_APPLY_BUTTON);
1860 
1861  EnableWindow(hwndApplyBtn, TRUE);
1862  }
1863 }
1864 
1865 /******************************************************************************
1866  * PROPSHEET_UnChanged
1867  */
1868 static void PROPSHEET_UnChanged(HWND hwndDlg, HWND hwndCleanPage)
1869 {
1870  int i;
1871  BOOL noPageDirty = TRUE;
1872  HWND hwndApplyBtn = GetDlgItem(hwndDlg, IDC_APPLY_BUTTON);
1873  PropSheetInfo* psInfo = GetPropW(hwndDlg, PropSheetInfoStr);
1874 
1875  TRACE("\n");
1876  if ( !psInfo ) return;
1877  for (i = 0; i < psInfo->nPages; i++)
1878  {
1879  /* set the specified page as clean */
1880  if (psInfo->proppage[i].hwndPage == hwndCleanPage)
1881  psInfo->proppage[i].isDirty = FALSE;
1882 
1883  /* look to see if there are any dirty pages */
1884  if (psInfo->proppage[i].isDirty)
1885  noPageDirty = FALSE;
1886  }
1887 
1888  /*
1889  * Disable Apply button.
1890  */
1891  if (noPageDirty)
1892  EnableWindow(hwndApplyBtn, FALSE);
1893 }
1894 
1895 /******************************************************************************
1896  * PROPSHEET_PressButton
1897  */
1898 static void PROPSHEET_PressButton(HWND hwndDlg, int buttonID)
1899 {
1900  TRACE("buttonID %d\n", buttonID);
1901  switch (buttonID)
1902  {
1903  case PSBTN_APPLYNOW:
1905  break;
1906  case PSBTN_BACK:
1907  PROPSHEET_Back(hwndDlg);
1908  break;
1909  case PSBTN_CANCEL:
1910  PROPSHEET_DoCommand(hwndDlg, IDCANCEL);
1911  break;
1912  case PSBTN_FINISH:
1913  PROPSHEET_Finish(hwndDlg);
1914  break;
1915  case PSBTN_HELP:
1916  PROPSHEET_DoCommand(hwndDlg, IDHELP);
1917  break;
1918  case PSBTN_NEXT:
1919  PROPSHEET_Next(hwndDlg);
1920  break;
1921  case PSBTN_OK:
1922  PROPSHEET_DoCommand(hwndDlg, IDOK);
1923  break;
1924  default:
1925  FIXME("Invalid button index %d\n", buttonID);
1926  }
1927 }
1928 
1929 
1930 /*************************************************************************
1931  * BOOL PROPSHEET_CanSetCurSel [Internal]
1932  *
1933  * Test whether the current page can be changed by sending a PSN_KILLACTIVE
1934  *
1935  * PARAMS
1936  * hwndDlg [I] handle to a Dialog hWnd
1937  *
1938  * RETURNS
1939  * TRUE if Current Selection can change
1940  *
1941  * NOTES
1942  */
1944 {
1945  PropSheetInfo* psInfo = GetPropW(hwndDlg, PropSheetInfoStr);
1946  HWND hwndPage;
1947  PSHNOTIFY psn;
1948  BOOL res = FALSE;
1949 
1950  if (!psInfo)
1951  {
1952  res = FALSE;
1953  goto end;
1954  }
1955 
1956  TRACE("active_page %d\n", psInfo->active_page);
1957  if (psInfo->active_page < 0)
1958  {
1959  res = TRUE;
1960  goto end;
1961  }
1962 
1963  /*
1964  * Notify the current page.
1965  */
1966  hwndPage = psInfo->proppage[psInfo->active_page].hwndPage;
1967  psn.hdr.code = PSN_KILLACTIVE;
1968  psn.hdr.hwndFrom = hwndDlg;
1969  psn.hdr.idFrom = 0;
1970  psn.lParam = 0;
1971 
1972  res = !SendMessageW(hwndPage, WM_NOTIFY, 0, (LPARAM) &psn);
1973 
1974 end:
1975  TRACE("<-- %d\n", res);
1976  return res;
1977 }
1978 
1979 /******************************************************************************
1980  * PROPSHEET_SetCurSel
1981  */
1983  int index,
1984  int skipdir,
1985  HPROPSHEETPAGE hpage
1986  )
1987 {
1988  PropSheetInfo* psInfo = GetPropW(hwndDlg, PropSheetInfoStr);
1989  HWND hwndHelp = GetDlgItem(hwndDlg, IDHELP);
1990  HWND hwndTabControl = GetDlgItem(hwndDlg, IDC_TABCONTROL);
1991 
1992  TRACE("index %d, skipdir %d, hpage %p\n", index, skipdir, hpage);
1993 
1994  index = PROPSHEET_GetPageIndex(hpage, psInfo, index);
1995 
1996  if (index < 0 || index >= psInfo->nPages)
1997  {
1998  TRACE("Could not find page to select!\n");
1999  return FALSE;
2000  }
2001 
2002  /* unset active page while doing this transition. */
2003  if (psInfo->active_page != -1)
2004  ShowWindow(psInfo->proppage[psInfo->active_page].hwndPage, SW_HIDE);
2005  psInfo->active_page = -1;
2006 
2007  while (1) {
2008  int result;
2009  PSHNOTIFY psn;
2010  RECT rc;
2012 
2013  if (hwndTabControl)
2014  SendMessageW(hwndTabControl, TCM_SETCURSEL, index, 0);
2015 
2016  psn.hdr.code = PSN_SETACTIVE;
2017  psn.hdr.hwndFrom = hwndDlg;
2018  psn.hdr.idFrom = 0;
2019  psn.lParam = 0;
2020 
2021  if (!psInfo->proppage[index].hwndPage) {
2022  if(!PROPSHEET_CreatePage(hwndDlg, index, psInfo, ppshpage)) {
2023  PROPSHEET_RemovePage(hwndDlg, index, NULL);
2024  if(index >= psInfo->nPages)
2025  index--;
2026  if(index < 0)
2027  return FALSE;
2028  continue;
2029  }
2030  }
2031 
2032  /* Resize the property sheet page to the fit in the Tab control
2033  * (for regular property sheets) or to fit in the client area (for
2034  * wizards).
2035  * NOTE: The resizing happens every time the page is selected and
2036  * not only when it's created (some applications depend on it). */
2037  PROPSHEET_GetPageRect(psInfo, hwndDlg, &rc, ppshpage);
2038  TRACE("setting page %p, rc (%s) w=%d, h=%d\n",
2039  psInfo->proppage[index].hwndPage, wine_dbgstr_rect(&rc),
2040  rc.right - rc.left, rc.bottom - rc.top);
2042  rc.left, rc.top,
2043  rc.right - rc.left, rc.bottom - rc.top, 0);
2044 
2045  result = SendMessageW(psInfo->proppage[index].hwndPage, WM_NOTIFY, 0, (LPARAM) &psn);
2046  if (!result)
2047  break;
2048  if (result == -1) {
2049  index+=skipdir;
2050  if (index < 0) {
2051  index = 0;
2052  WARN("Tried to skip before first property sheet page!\n");
2053  break;
2054  }
2055  if (index >= psInfo->nPages) {
2056  WARN("Tried to skip after last property sheet page!\n");
2057  index = psInfo->nPages-1;
2058  break;
2059  }
2060  }
2061  else if (result != 0)
2062  {
2063  int old_index = index;
2065  if(index >= psInfo->nPages) {
2066  index = old_index;
2067  WARN("Tried to skip to nonexistent page by res id\n");
2068  break;
2069  }
2070  continue;
2071  }
2072  }
2073 
2074  /* Invalidate the header area */
2075  if ( (psInfo->ppshheader.dwFlags & (PSH_WIZARD97_OLD | PSH_WIZARD97_NEW)) &&
2076  (psInfo->ppshheader.dwFlags & PSH_HEADER) )
2077  {
2078  HWND hwndLineHeader = GetDlgItem(hwndDlg, IDC_SUNKEN_LINEHEADER);
2079  RECT r;
2080 
2081  GetClientRect(hwndLineHeader, &r);
2082  MapWindowPoints(hwndLineHeader, hwndDlg, (LPPOINT) &r, 2);
2083  SetRect(&r, 0, 0, r.right + 1, r.top - 1);
2084 
2085  InvalidateRect(hwndDlg, &r, TRUE);
2086  }
2087 
2088  /*
2089  * Display the new page.
2090  */
2091  PROPSHEET_ShowPage(hwndDlg, index, psInfo);
2092 
2093  if (psInfo->proppage[index].hasHelp)
2094  EnableWindow(hwndHelp, TRUE);
2095  else
2096  EnableWindow(hwndHelp, FALSE);
2097 
2098  return TRUE;
2099 }
2100 
2101 /******************************************************************************
2102  * PROPSHEET_SetCurSelId
2103  *
2104  * Selects the page, specified by resource id.
2105  */
2106 static void PROPSHEET_SetCurSelId(HWND hwndDlg, int id)
2107 {
2108  int idx;
2109  PropSheetInfo* psInfo = GetPropW(hwndDlg, PropSheetInfoStr);
2110 
2111  idx = PROPSHEET_FindPageByResId(psInfo, id);
2112  if (idx < psInfo->nPages )
2113  {
2114  if (PROPSHEET_CanSetCurSel(hwndDlg) != FALSE)
2115  PROPSHEET_SetCurSel(hwndDlg, idx, 1, 0);
2116  }
2117 }
2118 
2119 /******************************************************************************
2120  * PROPSHEET_SetTitleA
2121  */
2122 static void PROPSHEET_SetTitleA(HWND hwndDlg, DWORD dwStyle, LPCSTR lpszText)
2123 {
2124  if(!IS_INTRESOURCE(lpszText))
2125  {
2126  WCHAR szTitle[256];
2127  MultiByteToWideChar(CP_ACP, 0, lpszText, -1, szTitle, ARRAY_SIZE(szTitle));
2128  PROPSHEET_SetTitleW(hwndDlg, dwStyle, szTitle);
2129  }
2130  else
2131  {
2132  PROPSHEET_SetTitleW(hwndDlg, dwStyle, (LPCWSTR)lpszText);
2133  }
2134 }
2135 
2136 /******************************************************************************
2137  * PROPSHEET_SetTitleW
2138  */
2139 static void PROPSHEET_SetTitleW(HWND hwndDlg, DWORD dwStyle, LPCWSTR lpszText)
2140 {
2141  PropSheetInfo* psInfo = GetPropW(hwndDlg, PropSheetInfoStr);
2142  WCHAR szTitle[256];
2143 
2144  TRACE("%s (style %08x)\n", debugstr_w(lpszText), dwStyle);
2145  if (IS_INTRESOURCE(lpszText)) {
2146  if (!LoadStringW(psInfo->ppshheader.hInstance, LOWORD(lpszText), szTitle, ARRAY_SIZE(szTitle)))
2147  return;
2148  lpszText = szTitle;
2149  }
2150  if (dwStyle & PSH_PROPTITLE)
2151  {
2152  WCHAR* dest;
2153  int lentitle = strlenW(lpszText);
2154  int lenprop = strlenW(psInfo->strPropertiesFor);
2155 
2156  dest = Alloc( (lentitle + lenprop + 1)*sizeof (WCHAR));
2157  wsprintfW(dest, psInfo->strPropertiesFor, lpszText);
2158 
2159  SetWindowTextW(hwndDlg, dest);
2160  Free(dest);
2161  }
2162  else
2163  SetWindowTextW(hwndDlg, lpszText);
2164 }
2165 
2166 /******************************************************************************
2167  * PROPSHEET_SetFinishTextA
2168  */
2169 static void PROPSHEET_SetFinishTextA(HWND hwndDlg, LPCSTR lpszText)
2170 {
2171  PropSheetInfo* psInfo = GetPropW(hwndDlg, PropSheetInfoStr);
2172  HWND hwndButton = GetDlgItem(hwndDlg, IDC_FINISH_BUTTON);
2173 
2174  TRACE("'%s'\n", lpszText);
2175  /* Set text, show and enable the Finish button */
2176  SetWindowTextA(hwndButton, lpszText);
2177  ShowWindow(hwndButton, SW_SHOW);
2178  EnableWindow(hwndButton, TRUE);
2179 
2180  /* Make it default pushbutton */
2182 
2183  /* Hide Back button */
2184  hwndButton = GetDlgItem(hwndDlg, IDC_BACK_BUTTON);
2185  ShowWindow(hwndButton, SW_HIDE);
2186 
2187  if (!psInfo->hasFinish)
2188  {
2189  /* Hide Next button */
2190  hwndButton = GetDlgItem(hwndDlg, IDC_NEXT_BUTTON);
2191  ShowWindow(hwndButton, SW_HIDE);
2192  }
2193 }
2194 
2195 /******************************************************************************
2196  * PROPSHEET_SetFinishTextW
2197  */
2198 static void PROPSHEET_SetFinishTextW(HWND hwndDlg, LPCWSTR lpszText)
2199 {
2200  PropSheetInfo* psInfo = GetPropW(hwndDlg, PropSheetInfoStr);
2201  HWND hwndButton = GetDlgItem(hwndDlg, IDC_FINISH_BUTTON);
2202 
2203  TRACE("%s\n", debugstr_w(lpszText));
2204  /* Set text, show and enable the Finish button */
2205  SetWindowTextW(hwndButton, lpszText);
2206  ShowWindow(hwndButton, SW_SHOW);
2207  EnableWindow(hwndButton, TRUE);
2208 
2209  /* Make it default pushbutton */
2211 
2212  /* Hide Back button */
2213  hwndButton = GetDlgItem(hwndDlg, IDC_BACK_BUTTON);
2214  ShowWindow(hwndButton, SW_HIDE);
2215 
2216  if (!psInfo->hasFinish)
2217  {
2218  /* Hide Next button */
2219  hwndButton = GetDlgItem(hwndDlg, IDC_NEXT_BUTTON);
2220  ShowWindow(hwndButton, SW_HIDE);
2221  }
2222 }
2223 
2224 /******************************************************************************
2225  * PROPSHEET_QuerySiblings
2226  */
2229 {
2230  int i = 0;
2231  HWND hwndPage;
2232  LRESULT msgResult = 0;
2233  PropSheetInfo* psInfo = GetPropW(hwndDlg, PropSheetInfoStr);
2234 
2235  while ((i < psInfo->nPages) && (msgResult == 0))
2236  {
2237  hwndPage = psInfo->proppage[i].hwndPage;
2238  msgResult = SendMessageW(hwndPage, PSM_QUERYSIBLINGS, wParam, lParam);
2239  i++;
2240  }
2241 
2242  return msgResult;
2243 }
2244 
2245 /******************************************************************************
2246  * PROPSHEET_InsertPage
2247  */
2248 static BOOL PROPSHEET_InsertPage(HWND hwndDlg, HPROPSHEETPAGE hpageInsertAfter, HPROPSHEETPAGE hpage)
2249 {
2250  PropSheetInfo *psInfo = GetPropW(hwndDlg, PropSheetInfoStr);
2251  PropPageInfo *ppi, *prev_ppi = psInfo->proppage;
2252  HWND hwndTabControl = GetDlgItem(hwndDlg, IDC_TABCONTROL);
2253  LPCPROPSHEETPAGEW ppsp = (LPCPROPSHEETPAGEW)hpage;
2254  TCITEMW item;
2255  int index;
2256 
2257  TRACE("hwndDlg %p, hpageInsertAfter %p, hpage %p\n", hwndDlg, hpageInsertAfter, hpage);
2258 
2259  if (IS_INTRESOURCE(hpageInsertAfter))
2260  index = LOWORD(hpageInsertAfter);
2261  else
2262  {
2263  index = PROPSHEET_GetPageIndex(hpageInsertAfter, psInfo, -1);
2264  if (index < 0)
2265  {
2266  TRACE("Could not find page to insert after!\n");
2267  return FALSE;
2268  }
2269  index++;
2270  }
2271 
2272  if (index > psInfo->nPages)
2273  index = psInfo->nPages;
2274 
2275  ppi = Alloc(sizeof(PropPageInfo) * (psInfo->nPages + 1));
2276  if (!ppi)
2277  return FALSE;
2278 
2279  /*
2280  * Fill in a new PropPageInfo entry.
2281  */
2282  if (index > 0)
2283  memcpy(ppi, prev_ppi, index * sizeof(PropPageInfo));
2284  memset(&ppi[index], 0, sizeof(PropPageInfo));
2285  if (index < psInfo->nPages)
2286  memcpy(&ppi[index + 1], &prev_ppi[index], (psInfo->nPages - index) * sizeof(PropPageInfo));
2287  psInfo->proppage = ppi;
2288 
2289  if (!PROPSHEET_CollectPageInfo(ppsp, psInfo, index, FALSE))
2290  {
2291  psInfo->proppage = prev_ppi;
2292  Free(ppi);
2293  return FALSE;
2294  }
2295 
2296  psInfo->proppage[index].hpage = hpage;
2297 
2298  if (ppsp->dwFlags & PSP_PREMATURE)
2299  {
2300  /* Create the page but don't show it */
2301  if (!PROPSHEET_CreatePage(hwndDlg, index, psInfo, ppsp))
2302  {
2303  psInfo->proppage = prev_ppi;
2304  Free(ppi);
2305  return FALSE;
2306  }
2307  }
2308 
2309  Free(prev_ppi);
2310  psInfo->nPages++;
2312  psInfo->active_page++;
2313 
2314  /*
2315  * Add a new tab to the tab control.
2316  */
2317  item.mask = TCIF_TEXT;
2318  item.pszText = (LPWSTR) psInfo->proppage[index].pszText;
2319  item.cchTextMax = MAX_TABTEXT_LENGTH;
2320 
2321  if (psInfo->hImageList)
2322  SendMessageW(hwndTabControl, TCM_SETIMAGELIST, 0, (LPARAM)psInfo->hImageList);
2323 
2324  if (psInfo->proppage[index].hasIcon)
2325  {
2326  item.mask |= TCIF_IMAGE;
2327  item.iImage = index;
2328  }
2329 
2330  SendMessageW(hwndTabControl, TCM_INSERTITEMW, index, (LPARAM)&item);
2331 
2332  /* If it is the only page - show it */
2333  if (psInfo->nPages == 1)
2334  PROPSHEET_SetCurSel(hwndDlg, 0, 1, 0);
2335 
2336  return TRUE;
2337 }
2338 
2339 /******************************************************************************
2340  * PROPSHEET_AddPage
2341  */
2343 {
2344  PropSheetInfo * psInfo = GetPropW(hwndDlg, PropSheetInfoStr);
2345  TRACE("hwndDlg %p, hpage %p\n", hwndDlg, hpage);
2346  return PROPSHEET_InsertPage(hwndDlg, UlongToPtr(psInfo->nPages), hpage);
2347 }
2348 
2349 /******************************************************************************
2350  * PROPSHEET_RemovePage
2351  */
2353  int index,
2354  HPROPSHEETPAGE hpage)
2355 {
2356  PropSheetInfo * psInfo = GetPropW(hwndDlg, PropSheetInfoStr);
2357  HWND hwndTabControl = GetDlgItem(hwndDlg, IDC_TABCONTROL);
2358  PropPageInfo* oldPages;
2359 
2360  TRACE("index %d, hpage %p\n", index, hpage);
2361  if (!psInfo) {
2362  return FALSE;
2363  }
2364 
2365  index = PROPSHEET_GetPageIndex(hpage, psInfo, index);
2366 
2367  /* Make sure that index is within range */
2368  if (index < 0 || index >= psInfo->nPages)
2369  {
2370  TRACE("Could not find page to remove!\n");
2371  return FALSE;
2372  }
2373 
2374  TRACE("total pages %d removing page %d active page %d\n",
2375  psInfo->nPages, index, psInfo->active_page);
2376  /*
2377  * Check if we're removing the active page.
2378  */
2379  if (index == psInfo->active_page)
2380  {
2381  if (psInfo->nPages > 1)
2382  {
2383  if (index > 0)
2384  {
2385  /* activate previous page */
2386  PROPSHEET_SetCurSel(hwndDlg, index - 1, -1, 0);
2387  }
2388  else
2389  {
2390  /* activate the next page */
2391  PROPSHEET_SetCurSel(hwndDlg, index + 1, 1, 0);
2392  psInfo->active_page = index;
2393  }
2394  }
2395  else
2396  {
2397  psInfo->active_page = -1;
2398  if (!psInfo->isModeless)
2399  {
2400  psInfo->ended = TRUE;
2401  return TRUE;
2402  }
2403  }
2404  }
2405  else if (index < psInfo->active_page)
2406  psInfo->active_page--;
2407 
2408  /* Unsubclass the page dialog window */
2409  if((psInfo->ppshheader.dwFlags & (PSH_WIZARD97_NEW | PSH_WIZARD97_OLD) &&
2410  (psInfo->ppshheader.dwFlags & PSH_WATERMARK) &&
2411  ((PROPSHEETPAGEW*)psInfo->proppage[index].hpage)->dwFlags & PSP_HIDEHEADER))
2412  {
2415  }
2416 
2417  /* Destroy page dialog window */
2419 
2420  /* Free page resources */
2421  if(psInfo->proppage[index].hpage)
2422  {
2423  PROPSHEETPAGEW* psp = (PROPSHEETPAGEW*)psInfo->proppage[index].hpage;
2424 
2425  if (psp->dwFlags & PSP_USETITLE)
2426  Free ((LPVOID)psInfo->proppage[index].pszText);
2427 
2429  }
2430 
2431  /* Remove the tab */
2432  SendMessageW(hwndTabControl, TCM_DELETEITEM, index, 0);
2433 
2434  oldPages = psInfo->proppage;
2435  psInfo->nPages--;
2436  psInfo->proppage = Alloc(sizeof(PropPageInfo) * psInfo->nPages);
2437 
2438  if (index > 0)
2439  memcpy(&psInfo->proppage[0], &oldPages[0], index * sizeof(PropPageInfo));
2440 
2441  if (index < psInfo->nPages)
2442  memcpy(&psInfo->proppage[index], &oldPages[index + 1],
2443  (psInfo->nPages - index) * sizeof(PropPageInfo));
2444 
2445  Free(oldPages);
2446 
2447  return FALSE;
2448 }
2449 
2450 /******************************************************************************
2451  * PROPSHEET_SetWizButtons
2452  *
2453  * This code will work if (and assumes that) the Next button is on top of the
2454  * Finish button. ie. Finish comes after Next in the Z order.
2455  * This means make sure the dialog template reflects this.
2456  *
2457  */
2459 {
2460  PropSheetInfo* psInfo = GetPropW(hwndDlg, PropSheetInfoStr);
2461  HWND hwndBack = GetDlgItem(hwndDlg, IDC_BACK_BUTTON);
2462  HWND hwndNext = GetDlgItem(hwndDlg, IDC_NEXT_BUTTON);
2463  HWND hwndFinish = GetDlgItem(hwndDlg, IDC_FINISH_BUTTON);
2464  BOOL enable_finish = ((dwFlags & PSWIZB_FINISH) || psInfo->hasFinish) && !(dwFlags & PSWIZB_DISABLEDFINISH);
2465 
2466 #ifdef __REACTOS__
2467  HWND hwndCancel = GetDlgItem(hwndDlg, IDCANCEL);
2468  INT iDefItem = 0;
2469  HWND hwndFocus;
2470 #endif
2471 
2472  TRACE("%d\n", dwFlags);
2473 
2474  EnableWindow(hwndBack, dwFlags & PSWIZB_BACK);
2475  EnableWindow(hwndNext, dwFlags & PSWIZB_NEXT);
2476  EnableWindow(hwndFinish, enable_finish);
2477 
2478 #ifndef __REACTOS__
2479  /* set the default pushbutton to an enabled button */
2480  if (enable_finish)
2482  else if (dwFlags & PSWIZB_NEXT)
2484  else if (dwFlags & PSWIZB_BACK)
2486  else
2487  SendMessageW(hwndDlg, DM_SETDEFID, IDCANCEL, 0);
2488 #endif
2489 
2490  if (!psInfo->hasFinish)
2491  {
2493  {
2494  /* Hide the Next button */
2495  ShowWindow(hwndNext, SW_HIDE);
2496 
2497  /* Show the Finish button */
2498  ShowWindow(hwndFinish, SW_SHOW);
2499  }
2500  else
2501  {
2502  /* Hide the Finish button */
2503  ShowWindow(hwndFinish, SW_HIDE);
2504  /* Show the Next button */
2505  ShowWindow(hwndNext, SW_SHOW);
2506  }
2507  }
2508 
2509 #ifdef __REACTOS__
2510  /* set the default pushbutton to an enabled button */
2511  if (((dwFlags & PSWIZB_FINISH) || psInfo->hasFinish) && !(dwFlags & PSWIZB_DISABLEDFINISH))
2512  iDefItem = IDC_FINISH_BUTTON;
2513  else if (dwFlags & PSWIZB_NEXT)
2514  iDefItem = IDC_NEXT_BUTTON;
2515  else if (dwFlags & PSWIZB_BACK)
2516  iDefItem = IDC_BACK_BUTTON;
2517  else
2518  iDefItem = IDCANCEL;
2519  SendMessageW(hwndDlg, DM_SETDEFID, iDefItem, 0);
2520 
2521  /* Set focus if no control has it */
2522  hwndFocus = GetFocus();
2523  if (!hwndFocus || hwndFocus == hwndCancel)
2524  SetFocus(GetDlgItem(hwndDlg, iDefItem));
2525 #endif
2526 
2527 }
2528 
2529 /******************************************************************************
2530  * PROPSHEET_SetHeaderTitleW
2531  */
2532 static void PROPSHEET_SetHeaderTitleW(HWND hwndDlg, UINT page_index, const WCHAR *title)
2533 {
2534  PropSheetInfo *psInfo = GetPropW(hwndDlg, PropSheetInfoStr);
2536 
2537  TRACE("(%p, %u, %s)\n", hwndDlg, page_index, debugstr_w(title));
2538 
2539  if (page_index >= psInfo->nPages)
2540  return;
2541 
2542  page = (PROPSHEETPAGEW *)psInfo->proppage[page_index].hpage;
2543 
2544  if (!IS_INTRESOURCE(page->pszHeaderTitle))
2545  Free((void *)page->pszHeaderTitle);
2546 
2547  page->pszHeaderTitle = heap_strdupW(title);
2548  page->dwFlags |= PSP_USEHEADERTITLE;
2549 }
2550 
2551 /******************************************************************************
2552  * PROPSHEET_SetHeaderTitleA
2553  */
2554 static void PROPSHEET_SetHeaderTitleA(HWND hwndDlg, UINT page_index, const char *title)
2555 {
2556  WCHAR *titleW;
2557 
2558  TRACE("(%p, %u, %s)\n", hwndDlg, page_index, debugstr_a(title));
2559 
2561  PROPSHEET_SetHeaderTitleW(hwndDlg, page_index, titleW);
2562  Free(titleW);
2563 }
2564 
2565 /******************************************************************************
2566  * PROPSHEET_SetHeaderSubTitleW
2567  */
2568 static void PROPSHEET_SetHeaderSubTitleW(HWND hwndDlg, UINT page_index, const WCHAR *subtitle)
2569 {
2570  PropSheetInfo *psInfo = GetPropW(hwndDlg, PropSheetInfoStr);
2572 
2573  TRACE("(%p, %u, %s)\n", hwndDlg, page_index, debugstr_w(subtitle));
2574 
2575  if (page_index >= psInfo->nPages)
2576  return;
2577 
2578  page = (PROPSHEETPAGEW *)psInfo->proppage[page_index].hpage;
2579 
2580  if (!IS_INTRESOURCE(page->pszHeaderSubTitle))
2581  Free((void *)page->pszHeaderSubTitle);
2582 
2583  page->pszHeaderSubTitle = heap_strdupW(subtitle);
2584  page->dwFlags |= PSP_USEHEADERSUBTITLE;
2585 }
2586 
2587 /******************************************************************************
2588  * PROPSHEET_SetHeaderSubTitleA
2589  */
2590 static void PROPSHEET_SetHeaderSubTitleA(HWND hwndDlg, UINT page_index, const char *subtitle)
2591 {
2592  WCHAR *subtitleW;
2593 
2594  TRACE("(%p, %u, %s)\n", hwndDlg, page_index, debugstr_a(subtitle));
2595 
2596  subtitleW = heap_strdupAtoW(subtitle);
2597  PROPSHEET_SetHeaderSubTitleW(hwndDlg, page_index, subtitleW);
2598  Free(subtitleW);
2599 }
2600 
2601 /******************************************************************************
2602  * PROPSHEET_HwndToIndex
2603  */
2604 static LRESULT PROPSHEET_HwndToIndex(HWND hwndDlg, HWND hPageDlg)
2605 {
2606  int index;
2607  PropSheetInfo * psInfo = GetPropW(hwndDlg, PropSheetInfoStr);
2608 
2609  TRACE("(%p, %p)\n", hwndDlg, hPageDlg);
2610 
2611  for (index = 0; index < psInfo->nPages; index++)
2612  if (psInfo->proppage[index].hwndPage == hPageDlg)
2613  return index;
2614  WARN("%p not found\n", hPageDlg);
2615  return -1;
2616 }
2617 
2618 /******************************************************************************
2619  * PROPSHEET_IndexToHwnd
2620  */
2621 static LRESULT PROPSHEET_IndexToHwnd(HWND hwndDlg, int iPageIndex)
2622 {
2623  PropSheetInfo * psInfo = GetPropW(hwndDlg, PropSheetInfoStr);
2624  TRACE("(%p, %d)\n", hwndDlg, iPageIndex);
2625  if (!psInfo)
2626  return 0;
2627  if (iPageIndex<0 || iPageIndex>=psInfo->nPages) {
2628  WARN("%d out of range.\n", iPageIndex);
2629  return 0;
2630  }
2631  return (LRESULT)psInfo->proppage[iPageIndex].hwndPage;
2632 }
2633 
2634 /******************************************************************************
2635  * PROPSHEET_PageToIndex
2636  */
2638 {
2639  PropSheetInfo * psInfo = GetPropW(hwndDlg, PropSheetInfoStr);
2640 
2641  TRACE("(%p, %p)\n", hwndDlg, hPage);
2642 
2643  return PROPSHEET_GetPageIndex(hPage, psInfo, -1);
2644 }
2645 
2646 /******************************************************************************
2647  * PROPSHEET_IndexToPage
2648  */
2649 static LRESULT PROPSHEET_IndexToPage(HWND hwndDlg, int iPageIndex)
2650 {
2651  PropSheetInfo * psInfo = GetPropW(hwndDlg, PropSheetInfoStr);
2652  TRACE("(%p, %d)\n", hwndDlg, iPageIndex);
2653  if (iPageIndex<0 || iPageIndex>=psInfo->nPages) {
2654  WARN("%d out of range.\n", iPageIndex);
2655  return 0;
2656  }
2657  return (LRESULT)psInfo->proppage[iPageIndex].hpage;
2658 }
2659 
2660 /******************************************************************************
2661  * PROPSHEET_IdToIndex
2662  */
2663 static LRESULT PROPSHEET_IdToIndex(HWND hwndDlg, int iPageId)
2664 {
2665  int index;
2666  LPCPROPSHEETPAGEW psp;
2667  PropSheetInfo * psInfo = GetPropW(hwndDlg, PropSheetInfoStr);
2668  TRACE("(%p, %d)\n", hwndDlg, iPageId);
2669  for (index = 0; index < psInfo->nPages; index++) {
2670  psp = (LPCPROPSHEETPAGEW)psInfo->proppage[index].hpage;
2671  if (psp->u.pszTemplate == MAKEINTRESOURCEW(iPageId))
2672  return index;
2673  }
2674 
2675  return -1;
2676 }
2677 
2678 /******************************************************************************
2679  * PROPSHEET_IndexToId
2680  */
2681 static LRESULT PROPSHEET_IndexToId(HWND hwndDlg, int iPageIndex)
2682 {
2683  PropSheetInfo * psInfo = GetPropW(hwndDlg, PropSheetInfoStr);
2684  LPCPROPSHEETPAGEW psp;
2685  TRACE("(%p, %d)\n", hwndDlg, iPageIndex);
2686  if (iPageIndex<0 || iPageIndex>=psInfo->nPages) {
2687  WARN("%d out of range.\n", iPageIndex);
2688  return 0;
2689  }
2690  psp = (LPCPROPSHEETPAGEW)psInfo->proppage[iPageIndex].hpage;
2691  if (psp->dwFlags & PSP_DLGINDIRECT || !IS_INTRESOURCE(psp->u.pszTemplate)) {
2692  return 0;
2693  }
2694  return (LRESULT)psp->u.pszTemplate;
2695 }
2696 
2697 /******************************************************************************
2698  * PROPSHEET_GetResult
2699  */
2701 {
2702  PropSheetInfo * psInfo = GetPropW(hwndDlg, PropSheetInfoStr);
2703  return psInfo->result;
2704 }
2705 
2706 /******************************************************************************
2707  * PROPSHEET_RecalcPageSizes
2708  */
2710 {
2711  FIXME("(%p): stub\n", hwndDlg);
2712  return FALSE;
2713 }
2714 
2715 /******************************************************************************
2716  * PROPSHEET_GetPageIndex
2717  *
2718  * Given a HPROPSHEETPAGE, returns the index of the corresponding page from
2719  * the array of PropPageInfo. If page is not found original index is used
2720  * (page takes precedence over index).
2721  */
2722 static int PROPSHEET_GetPageIndex(HPROPSHEETPAGE page, const PropSheetInfo* psInfo, int original_index)
2723 {
2724  int index;
2725 
2726  TRACE("page %p index %d\n", page, original_index);
2727 
2728  for (index = 0; index < psInfo->nPages; index++)
2729  if (psInfo->proppage[index].hpage == page)
2730  return index;
2731 
2732  return original_index;
2733 }
2734 
2735 /******************************************************************************
2736  * PROPSHEET_CleanUp
2737  */
2738 static void PROPSHEET_CleanUp(HWND hwndDlg)
2739 {
2740  int i;
2741  PropSheetInfo* psInfo = RemovePropW(hwndDlg, PropSheetInfoStr);
2742 
2743  TRACE("\n");
2744  if (!psInfo) return;
2745  if (!IS_INTRESOURCE(psInfo->ppshheader.pszCaption))
2746  Free ((LPVOID)psInfo->ppshheader.pszCaption);
2747 
2748  for (i = 0; i < psInfo->nPages; i++)
2749  {
2750  PROPSHEETPAGEA* psp = (PROPSHEETPAGEA*)psInfo->proppage[i].hpage;
2751 
2752  /* Unsubclass the page dialog window */
2753  if((psInfo->ppshheader.dwFlags & (PSH_WIZARD97_NEW | PSH_WIZARD97_OLD)) &&
2754  (psInfo->ppshheader.dwFlags & PSH_WATERMARK) &&
2755  (psp->dwFlags & PSP_HIDEHEADER))
2756  {
2759  }
2760 
2761  if(psInfo->proppage[i].hwndPage)
2762  DestroyWindow(psInfo->proppage[i].hwndPage);
2763 
2764  if(psp)
2765  {
2766  if (psp->dwFlags & PSP_USETITLE)
2767  Free ((LPVOID)psInfo->proppage[i].pszText);
2768 
2770  }
2771  }
2772 
2773  DeleteObject(psInfo->hFont);
2774  DeleteObject(psInfo->hFontBold);
2775  /* If we created the bitmaps, destroy them */
2776  if ((psInfo->ppshheader.dwFlags & PSH_WATERMARK) &&
2777  (!(psInfo->ppshheader.dwFlags & PSH_USEHBMWATERMARK)) )
2778  DeleteObject(psInfo->ppshheader.u4.hbmWatermark);
2779  if ((psInfo->ppshheader.dwFlags & PSH_HEADER) &&
2780  (!(psInfo->ppshheader.dwFlags & PSH_USEHBMHEADER)) )
2781  DeleteObject(psInfo->ppshheader.u5.hbmHeader);
2782 
2783  Free(psInfo->proppage);
2784  Free(psInfo->strPropertiesFor);
2785  ImageList_Destroy(psInfo->hImageList);
2786 
2787  GlobalFree(psInfo);
2788 }
2789 
2790 static INT do_loop(const PropSheetInfo *psInfo)
2791 {
2792  MSG msg;
2793  INT ret = -1;
2794  HWND hwnd = psInfo->hwnd;
2795  HWND parent = psInfo->ppshheader.hwndParent;
2796 
2797  while(IsWindow(hwnd) && !psInfo->ended && (ret = GetMessageW(&msg, NULL, 0, 0)))
2798  {
2799  if(ret == -1)
2800  break;
2801 
2802  if(!IsDialogMessageW(hwnd, &msg))
2803  {
2806  }
2807  }
2808 
2809  if(ret == 0)
2810  {
2811  PostQuitMessage(msg.wParam);
2812  ret = -1;
2813  }
2814 
2815  if(ret != -1)
2816  ret = psInfo->result;
2817 
2818  if(parent)
2820 
2822  return ret;
2823 }
2824 
2825 /******************************************************************************
2826  * PROPSHEET_PropertySheet
2827  *
2828  * Common code between PropertySheetA/W
2829  */
2831 {
2832  INT_PTR bRet = 0;
2833  HWND parent = NULL;
2834  if (psInfo->active_page >= psInfo->nPages) psInfo->active_page = 0;
2835  TRACE("startpage: %d of %d pages\n", psInfo->active_page, psInfo->nPages);
2836 
2837  psInfo->unicode = unicode;
2838  psInfo->ended = FALSE;
2839 
2840  if(!psInfo->isModeless)
2841  {
2842  parent = psInfo->ppshheader.hwndParent;
2844  }
2845  bRet = PROPSHEET_CreateDialog(psInfo);
2846  if(!psInfo->isModeless)
2847  bRet = do_loop(psInfo);
2848  return bRet;
2849 }
2850 
2851 /******************************************************************************
2852  * PropertySheet (COMCTL32.@)
2853  * PropertySheetA (COMCTL32.@)
2854  *
2855  * Creates a property sheet in the specified property sheet header.
2856  *
2857  * RETURNS
2858  * Modal property sheets: Positive if successful or -1 otherwise.
2859  * Modeless property sheets: Property sheet handle.
2860  * Or:
2861  *| ID_PSREBOOTSYSTEM - The user must reboot the computer for the changes to take effect.
2862  *| ID_PSRESTARTWINDOWS - The user must restart Windows for the changes to take effect.
2863  */
2865 {
2866  PropSheetInfo* psInfo = GlobalAlloc(GPTR, sizeof(PropSheetInfo));
2867  UINT i, n;
2868  const BYTE* pByte;
2869 
2870  TRACE("(%p)\n", lppsh);
2871 
2872  PROPSHEET_CollectSheetInfoA(lppsh, psInfo);
2873 
2874  psInfo->proppage = Alloc(sizeof(PropPageInfo) * lppsh->nPages);
2875  pByte = (const BYTE*) psInfo->ppshheader.u3.ppsp;
2876 
2877  for (n = i = 0; i < lppsh->nPages; i++, n++)
2878  {
2879  if (!psInfo->usePropPage)
2880  psInfo->proppage[n].hpage = psInfo->ppshheader.u3.phpage[i];
2881  else
2882  {
2884  pByte += ((LPCPROPSHEETPAGEA)pByte)->dwSize;
2885  }
2886 
2888  psInfo, n, TRUE))
2889  {
2890  if (psInfo->usePropPage)
2892  n--;
2893  psInfo->nPages--;
2894  }
2895  }
2896 
2897  return PROPSHEET_PropertySheet(psInfo, FALSE);
2898 }
2899 
2900 /******************************************************************************
2901  * PropertySheetW (COMCTL32.@)
2902  *
2903  * See PropertySheetA.
2904  */
2906 {
2907  PropSheetInfo* psInfo = GlobalAlloc(GPTR, sizeof(PropSheetInfo));
2908  UINT i, n;
2909  const BYTE* pByte;
2910 
2911  TRACE("(%p)\n", lppsh);
2912 
2913  PROPSHEET_CollectSheetInfoW(lppsh, psInfo);
2914 
2915  psInfo->proppage = Alloc(sizeof(PropPageInfo) * lppsh->nPages);
2916  pByte = (const BYTE*) psInfo->ppshheader.u3.ppsp;
2917 
2918  for (n = i = 0; i < lppsh->nPages; i++, n++)
2919  {
2920  if (!psInfo->usePropPage)
2921  psInfo->proppage[n].hpage = psInfo->ppshheader.u3.phpage[i];
2922  else
2923  {
2925  pByte += ((LPCPROPSHEETPAGEW)pByte)->dwSize;
2926  }
2927 
2929  psInfo, n, TRUE))
2930  {
2931  if (psInfo->usePropPage)
2933  n--;
2934  psInfo->nPages--;
2935  }
2936  }
2937 
2938  return PROPSHEET_PropertySheet(psInfo, TRUE);
2939 }
2940 
2942 {
2943  LPWSTR ret;
2944 
2945  if (IS_INTRESOURCE(str))
2946  {
2947  HRSRC hrsrc;
2948  HGLOBAL hmem;
2949  WCHAR *ptr;
2950  WORD i, id = LOWORD(str);
2951  UINT len;
2952 
2953  if (!(hrsrc = FindResourceW( instance, MAKEINTRESOURCEW((id >> 4) + 1), (LPWSTR)RT_STRING )))
2954  return NULL;
2955  if (!(hmem = LoadResource( instance, hrsrc ))) return NULL;
2956  if (!(ptr = LockResource( hmem ))) return NULL;
2957  for (i = id & 0x0f; i > 0; i--) ptr += *ptr + 1;
2958  len = *ptr;
2959  if (!len) return NULL;
2960  ret = Alloc( (len + 1) * sizeof(WCHAR) );
2961  if (ret)
2962  {
2963  memcpy( ret, ptr + 1, len * sizeof(WCHAR) );
2964  ret[len] = 0;
2965  }
2966  }
2967  else
2968  {
2969  int len = (strlenW(str) + 1) * sizeof(WCHAR);
2970  ret = Alloc( len );
2971  if (ret) memcpy( ret, str, len );
2972  }
2973  return ret;
2974 }
2975 
2976 
2977 /******************************************************************************
2978  * CreatePropertySheetPage (COMCTL32.@)
2979  * CreatePropertySheetPageA (COMCTL32.@)
2980  *
2981  * Creates a new property sheet page.
2982  *
2983  * RETURNS
2984  * Success: Handle to new property sheet page.
2985  * Failure: NULL.
2986  *
2987  * NOTES
2988  * An application must use the PSM_ADDPAGE message to add the new page to
2989  * an existing property sheet.
2990  */
2992  LPCPROPSHEETPAGEA lpPropSheetPage)
2993 {
2994  PROPSHEETPAGEW *ppsp;
2995 
2996  if (lpPropSheetPage->dwSize < PROPSHEETPAGEA_V1_SIZE)
2997  return NULL;
2998 
2999  /* original data is used for callback notifications */
3000  if ((lpPropSheetPage->dwFlags & PSP_USECALLBACK) && lpPropSheetPage->pfnCallback)
3001  {
3002  ppsp = Alloc(2 * sizeof(*ppsp));
3003  memcpy(ppsp, lpPropSheetPage, min(lpPropSheetPage->dwSize, sizeof(PROPSHEETPAGEA)));
3004  memcpy(ppsp + 1, lpPropSheetPage, min(lpPropSheetPage->dwSize, sizeof(PROPSHEETPAGEA)));
3005  }
3006  else
3007  {
3008  ppsp = Alloc(sizeof(*ppsp));
3009  memcpy(ppsp, lpPropSheetPage, min(lpPropSheetPage->dwSize, sizeof(PROPSHEETPAGEA)));
3010  }
3011 
3012  ppsp->dwFlags &= ~PSP_INTERNAL_UNICODE;
3013 
3014  if ( !(ppsp->dwFlags & PSP_DLGINDIRECT) )
3015  {
3016  if (!IS_INTRESOURCE( ppsp->u.pszTemplate ))
3017  {
3018  int len = strlen(lpPropSheetPage->u.pszTemplate) + 1;
3019  char *template = Alloc( len );
3020 
3021  ppsp->u.pszTemplate = (LPWSTR)strcpy( template, lpPropSheetPage->u.pszTemplate );
3022  }
3023  }
3024 
3025  if (ppsp->dwFlags & PSP_USEICONID)
3026  {
3027  if (!IS_INTRESOURCE( ppsp->u2.pszIcon ))
3028  ppsp->u2.pszIcon = heap_strdupAtoW( lpPropSheetPage->u2.pszIcon );
3029  }
3030 
3031  if (ppsp->dwFlags & PSP_USETITLE)
3032  {
3033  if (IS_INTRESOURCE( ppsp->pszTitle ))
3034  ppsp->pszTitle = load_string( ppsp->hInstance, ppsp->pszTitle );
3035  else
3036  ppsp->pszTitle = heap_strdupAtoW( lpPropSheetPage->pszTitle );
3037  }
3038  else
3039  ppsp->pszTitle = NULL;
3040 
3041  if (ppsp->dwFlags & PSP_HIDEHEADER)
3042  ppsp->dwFlags &= ~(PSP_USEHEADERTITLE | PSP_USEHEADERSUBTITLE);
3043 
3044  if (ppsp->dwFlags & PSP_USEHEADERTITLE)
3045  {
3046  if (IS_INTRESOURCE( ppsp->pszHeaderTitle ))
3047  ppsp->pszHeaderTitle = load_string( ppsp->hInstance, ppsp->pszHeaderTitle );
3048  else
3049  ppsp->pszHeaderTitle = heap_strdupAtoW( lpPropSheetPage->pszHeaderTitle );
3050  }
3051  else
3052  ppsp->pszHeaderTitle = NULL;
3053 
3054  if (ppsp->dwFlags & PSP_USEHEADERSUBTITLE)
3055  {
3056  if (IS_INTRESOURCE( ppsp->pszHeaderSubTitle ))
3057  ppsp->pszHeaderSubTitle = load_string( ppsp->hInstance, ppsp->pszHeaderSubTitle );
3058  else
3059  ppsp->pszHeaderSubTitle = heap_strdupAtoW( lpPropSheetPage->pszHeaderSubTitle );
3060  }
3061  else
3062  ppsp->pszHeaderSubTitle = NULL;
3063 
3064  if ((ppsp->dwFlags & PSP_USECALLBACK) && ppsp->dwSize > PROPSHEETPAGEA_V1_SIZE && ppsp->pfnCallback)
3065  ppsp->pfnCallback(0, PSPCB_ADDREF, ppsp + 1);
3066 
3067  return (HPROPSHEETPAGE)ppsp;
3068 }
3069 
3070 /******************************************************************************
3071  * CreatePropertySheetPageW (COMCTL32.@)
3072  *
3073  * See CreatePropertySheetA.
3074  */
3076 {
3077  PROPSHEETPAGEW *ppsp;
3078 
3079  if (lpPropSheetPage->dwSize < PROPSHEETPAGEW_V1_SIZE)
3080  return NULL;
3081 
3082  /* original data is used for callback notifications */
3083  if ((lpPropSheetPage->dwFlags & PSP_USECALLBACK) && lpPropSheetPage->pfnCallback)
3084  {
3085  ppsp = Alloc(2 * sizeof(*ppsp));
3086  memcpy(ppsp, lpPropSheetPage, min(lpPropSheetPage->dwSize, sizeof(PROPSHEETPAGEW)));
3087  memcpy(ppsp + 1, lpPropSheetPage, min(lpPropSheetPage->dwSize, sizeof(PROPSHEETPAGEW)));
3088  }
3089  else
3090  {
3091  ppsp = Alloc(sizeof(*ppsp));
3092  memcpy(ppsp, lpPropSheetPage, min(lpPropSheetPage->dwSize, sizeof(PROPSHEETPAGEW)));
3093  }
3094 
3095  ppsp->dwFlags |= PSP_INTERNAL_UNICODE;
3096 
3097  if ( !(ppsp->dwFlags & PSP_DLGINDIRECT) )
3098  {
3099  if (!IS_INTRESOURCE( ppsp->u.pszTemplate ))
3100  ppsp->u.pszTemplate = heap_strdupW( lpPropSheetPage->u.pszTemplate );
3101  }
3102 
3103  if ( ppsp->dwFlags & PSP_USEICONID )
3104  {
3105  if (!IS_INTRESOURCE( ppsp->u2.pszIcon ))
3106  ppsp->u2.pszIcon = heap_strdupW( lpPropSheetPage->u2.pszIcon );
3107  }
3108 
3109  if (ppsp->dwFlags & PSP_USETITLE)
3110  ppsp->pszTitle = load_string( ppsp->hInstance, ppsp->pszTitle );
3111  else
3112  ppsp->pszTitle = NULL;
3113 
3114  if (ppsp->dwFlags & PSP_HIDEHEADER)
3115  ppsp->dwFlags &= ~(PSP_USEHEADERTITLE | PSP_USEHEADERSUBTITLE);
3116 
3117  if (ppsp->dwFlags & PSP_USEHEADERTITLE)
3118  ppsp->pszHeaderTitle = load_string( ppsp->hInstance, ppsp->pszHeaderTitle );
3119  else
3120  ppsp->pszHeaderTitle = NULL;
3121 
3122  if (ppsp->dwFlags & PSP_USEHEADERSUBTITLE)
3123  ppsp->pszHeaderSubTitle = load_string( ppsp->hInstance, ppsp->pszHeaderSubTitle );
3124  else
3125  ppsp->pszHeaderSubTitle = NULL;
3126 
3127  if ((ppsp->dwFlags & PSP_USECALLBACK) && ppsp->dwSize > PROPSHEETPAGEW_V1_SIZE && ppsp->pfnCallback)
3128  ppsp->pfnCallback(0, PSPCB_ADDREF, ppsp + 1);
3129 
3130  return (HPROPSHEETPAGE)ppsp;
3131 }
3132 
3133 /******************************************************************************
3134  * DestroyPropertySheetPage (COMCTL32.@)
3135  *
3136  * Destroys a property sheet page previously created with
3137  * CreatePropertySheetA() or CreatePropertySheetW() and frees the associated
3138  * memory.
3139  *
3140  * RETURNS
3141  * Success: TRUE
3142  * Failure: FALSE
3143  */
3145 {
3146  PROPSHEETPAGEW *psp = (PROPSHEETPAGEW *)hPropPage;
3147 
3148  if (!psp)
3149  return FALSE;
3150 
3151  if ((psp->dwFlags & PSP_USECALLBACK) && psp->pfnCallback)
3152  psp->pfnCallback(0, PSPCB_RELEASE, psp + 1);
3153 
3154  if (!(psp->dwFlags & PSP_DLGINDIRECT) && !IS_INTRESOURCE( psp->u.pszTemplate ))
3155  Free ((LPVOID)psp->u.pszTemplate);
3156 
3157  if ((psp->dwFlags & PSP_USEICONID) && !IS_INTRESOURCE( psp->u2.pszIcon ))
3158  Free ((LPVOID)psp->u2.pszIcon);
3159 
3160  if ((psp->dwFlags & PSP_USETITLE) && !IS_INTRESOURCE( psp->pszTitle ))
3161  Free ((LPVOID)psp->pszTitle);
3162 
3163  if ((psp->dwFlags & PSP_USEHEADERTITLE) && !IS_INTRESOURCE( psp->pszHeaderTitle ))
3164  Free ((LPVOID)psp->pszHeaderTitle);
3165 
3166  if ((psp->dwFlags & PSP_USEHEADERSUBTITLE) && !IS_INTRESOURCE( psp->pszHeaderSubTitle ))
3167  Free ((LPVOID)psp->pszHeaderSubTitle);
3168 
3169  Free(hPropPage);
3170 
3171  return TRUE;
3172 }
3173 
3174 /******************************************************************************
3175  * PROPSHEET_IsDialogMessage
3176  */
3178 {
3180 
3181  TRACE("\n");
3182  if (!psInfo || (hwnd != lpMsg->hwnd && !IsChild(hwnd, lpMsg->hwnd)))
3183  return FALSE;
3184 
3185  if (lpMsg->message == WM_KEYDOWN && (GetKeyState(VK_CONTROL) & 0x8000))
3186  {
3187  int new_page = 0;
3188  INT dlgCode = SendMessageW(lpMsg->hwnd, WM_GETDLGCODE, 0, (LPARAM)lpMsg);
3189 
3190  if (!(dlgCode & DLGC_WANTMESSAGE))
3191  {
3192  switch (lpMsg->wParam)
3193  {
3194  case VK_TAB:
3195  if (GetKeyState(VK_SHIFT) & 0x8000)
3196  new_page = -1;
3197  else
3198  new_page = 1;
3199  break;
3200 
3201  case VK_NEXT: new_page = 1; break;
3202  case VK_PRIOR: new_page = -1; break;
3203  }
3204  }
3205 
3206  if (new_page)
3207  {
3209  {
3210  new_page += psInfo->active_page;
3211 
3212  if (new_page < 0)
3213  new_page = psInfo->nPages - 1;
3214  else if (new_page >= psInfo->nPages)
3215  new_page = 0;
3216 
3217  PROPSHEET_SetCurSel(hwnd, new_page, 1, 0);
3218  }
3219 
3220  return TRUE;
3221  }
3222  }
3223 
3224  return IsDialogMessageW(hwnd, lpMsg);
3225 }
3226 
3227 /******************************************************************************
3228  * PROPSHEET_DoCommand
3229  */
3231 {
3232 
3233  switch (wID) {
3234 
3235  case IDOK:
3236  case IDC_APPLY_BUTTON:
3237  {
3238  HWND hwndApplyBtn = GetDlgItem(hwnd, IDC_APPLY_BUTTON);
3239 
3240  if (PROPSHEET_Apply(hwnd, wID == IDOK ? 1: 0) == FALSE)
3241  break;
3242 
3243  if (wID == IDOK)
3244  {
3246 
3247  /* don't overwrite ID_PSRESTARTWINDOWS or ID_PSREBOOTSYSTEM */
3248  if (psInfo->result == 0)
3249  psInfo->result = IDOK;
3250 
3251  if (psInfo->isModeless)
3252  psInfo->activeValid = FALSE;
3253  else
3254  psInfo->ended = TRUE;
3255  }
3256  else
3257  EnableWindow(hwndApplyBtn, FALSE);
3258 
3259  break;
3260  }
3261 
3262  case IDC_BACK_BUTTON:
3264  break;
3265 
3266  case IDC_NEXT_BUTTON:
3268  break;
3269 
3270  case IDC_FINISH_BUTTON:
3272  break;
3273 
3274  case IDCANCEL:
3275  PROPSHEET_Cancel(hwnd, 0);
3276  break;
3277 
3278  case IDHELP:
3280  break;
3281 
3282  default:
3283  return FALSE;
3284  }
3285 
3286  return TRUE;
3287 }
3288 
3289 /******************************************************************************
3290  * PROPSHEET_Paint
3291  */
3293 {
3295  PAINTSTRUCT ps;
3296  HDC hdc, hdcSrc;
3297  BITMAP bm;
3298  HBITMAP hbmp;
3299  HPALETTE hOldPal = 0;
3300  int offsety = 0;
3301  HBRUSH hbr;
3302  RECT r, rzone;
3303  LPCPROPSHEETPAGEW ppshpage;
3304  WCHAR szBuffer[256];
3305  int nLength;
3306 
3307  hdc = hdcParam ? hdcParam : BeginPaint(hwnd, &ps);
3308  if (!hdc) return 1;
3309 
3311 
3312  if (psInfo->ppshheader.dwFlags & PSH_USEHPLWATERMARK)
3313  hOldPal = SelectPalette(hdc, psInfo->ppshheader.hplWatermark, FALSE);
3314 
3315  if (psInfo->active_page < 0)
3316  ppshpage = NULL;
3317  else
3318  ppshpage = (LPCPROPSHEETPAGEW)psInfo->proppage[psInfo->active_page].hpage;
3319 
3320  if ( (ppshpage && !(ppshpage->dwFlags & PSP_HIDEHEADER)) &&
3321  (psInfo->ppshheader.dwFlags & (PSH_WIZARD97_OLD | PSH_WIZARD97_NEW)) &&
3322  (psInfo->ppshheader.dwFlags & PSH_HEADER) )
3323  {
3324  HWND hwndLineHeader = GetDlgItem(hwnd, IDC_SUNKEN_LINEHEADER);
3325  HFONT hOldFont;
3326  COLORREF clrOld = 0;
3327  int oldBkMode = 0;
3328 
3329  GetClientRect(hwndLineHeader, &r);
3330  MapWindowPoints(hwndLineHeader, hwnd, (LPPOINT) &r, 2);
3331  SetRect(&rzone, 0, 0, r.right + 1, r.top - 1);
3332 
3333  hOldFont = SelectObject(hdc, psInfo->hFontBold);
3334 
3335 #ifdef __REACTOS__
3336  if (psInfo->ppshheader.u5.hbmHeader)
3337 #else
3338  if (psInfo->ppshheader.dwFlags & PSH_USEHBMHEADER)
3339 #endif
3340  {
3341  hbmp = SelectObject(hdcSrc, psInfo->ppshheader.u5.hbmHeader);
3342 
3343  GetObjectW(psInfo->ppshheader.u5.hbmHeader, sizeof(BITMAP), &bm);
3344  if (psInfo->ppshheader.dwFlags & PSH_WIZARD97_OLD)
3345  {
3346  /* Fill the unoccupied part of the header with color of the
3347  * left-top pixel, but do it only when needed.
3348  */
3349  if (bm.bmWidth < r.right || bm.bmHeight < r.bottom)
3350  {
3351  hbr = CreateSolidBrush(GetPixel(hdcSrc, 0, 0));
3352  r = rzone;
3353  if (bm.bmWidth < r.right)
3354  {
3355  r.left = bm.bmWidth;
3356  FillRect(hdc, &r, hbr);
3357  }
3358  if (bm.bmHeight < r.bottom)
3359  {
3360  r.left = 0;
3361  r.top = bm.bmHeight;
3362  FillRect(hdc, &r, hbr);
3363  }
3364  DeleteObject(hbr);
3365  }
3366 
3367  /* Draw the header itself. */
3368  BitBlt(hdc, 0, 0, bm.bmWidth, min(bm.bmHeight, rzone.bottom),
3369  hdcSrc, 0, 0, SRCCOPY);
3370  }
3371  else
3372  {
3373  int margin;
3375  FillRect(hdc, &rzone, hbr);
3376 
3377  /* Draw the header bitmap. It's always centered like a
3378  * common 49 x 49 bitmap. */
3379  margin = (rzone.bottom - 49) / 2;
3380  BitBlt(hdc, rzone.right - 49 - margin, margin,
3381  min(bm.bmWidth, 49), min(bm.bmHeight, 49),
3382  hdcSrc, 0, 0, SRCCOPY);
3383 
3384  /* NOTE: Native COMCTL32 draws a white stripe over the bitmap
3385  * if its height is smaller than 49 pixels. Because the reason
3386  * for this bug is unknown the current code doesn't try to
3387  * replicate it. */
3388  }
3389 
3391  }
3392 
3393  clrOld = SetTextColor (hdc, 0x00000000);
3394  oldBkMode = SetBkMode (hdc, TRANSPARENT);
3395 
3396  if (ppshpage->dwFlags & PSP_USEHEADERTITLE) {
3397  SetRect(&r, 20, 10, 0, 0);
3398  if (!IS_INTRESOURCE(ppshpage->pszHeaderTitle))
3399  DrawTextW(hdc, ppshpage->pszHeaderTitle, -1, &r, DT_LEFT | DT_SINGLELINE | DT_NOCLIP);
3400  else
3401  {
3402  nLength = LoadStringW(ppshpage->hInstance, (UINT_PTR)ppshpage->pszHeaderTitle,
3403  szBuffer, 256);
3404  if (nLength != 0)
3405  {
3406  DrawTextW(hdc, szBuffer, nLength, &r, DT_LEFT | DT_SINGLELINE | DT_NOCLIP);
3407  }
3408  }
3409  }
3410 
3411  if (ppshpage->dwFlags & PSP_USEHEADERSUBTITLE) {
3412  SelectObject(hdc, psInfo->hFont);
3413  SetRect(&r, 40, 25, rzone.right - 69, rzone.bottom);
3414 #ifdef __REACTOS__
3415  if (!IS_INTRESOURCE(ppshpage->pszHeaderSubTitle))
3416 #else
3417  if (!IS_INTRESOURCE(ppshpage->pszHeaderTitle))
3418 #endif
3419  DrawTextW(hdc, ppshpage->pszHeaderSubTitle, -1, &r, DT_LEFT | DT_WORDBREAK);
3420  else
3421  {
3422  nLength = LoadStringW(ppshpage->hInstance, (UINT_PTR)ppshpage->pszHeaderSubTitle,
3423  szBuffer, 256);
3424  if (nLength != 0)
3425  {
3426  DrawTextW(hdc, szBuffer, nLength, &r, DT_LEFT | DT_WORDBREAK);
3427  }
3428  }
3429  }
3430 
3431  offsety = rzone.bottom + 2;
3432 
3433  SetTextColor(hdc, clrOld);
3434  SetBkMode(hdc, oldBkMode);
3435  SelectObject(hdc, hOldFont);
3436  }
3437 
3438  if ( (ppshpage && (ppshpage->dwFlags & PSP_HIDEHEADER)) &&
3439  (psInfo->ppshheader.dwFlags & (PSH_WIZARD97_OLD | PSH_WIZARD97_NEW)) &&
3440 #ifdef __REACTOS__
3441  (psInfo->ppshheader.dwFlags & PSH_WATERMARK) &&
3442  (psInfo->ppshheader.u4.hbmWatermark) )
3443 #else
3444  (psInfo->ppshheader.dwFlags & PSH_WATERMARK) )
3445 #endif
3446  {
3447  HWND hwndLine = GetDlgItem(hwnd, IDC_SUNKEN_LINE);
3448 
3449  GetClientRect(hwndLine, &r);
3450  MapWindowPoints(hwndLine, hwnd, (LPPOINT) &r, 2);
3451  SetRect(&rzone, 0, 0, r.right, r.top - 1);
3452 
3454  FillRect(hdc, &rzone, hbr);
3455 
3456  GetObjectW(psInfo->ppshheader.u4.hbmWatermark, sizeof(BITMAP), &bm);
3457  hbmp = SelectObject(hdcSrc, psInfo->ppshheader.u4.hbmWatermark);
3458 
3459  /* The watermark is truncated to a width of 164 pixels */
3460  r.right = min(r.right, 164);
3461  BitBlt(hdc, 0, offsety, min(bm.bmWidth, r.right),
3462  min(bm.bmHeight, r.bottom), hdcSrc, 0, 0, SRCCOPY);
3463 
3464  /* If the bitmap is not big enough, fill the remaining area
3465  with the color of pixel (0,0) of bitmap - see MSDN */
3466  if (r.top > bm.bmHeight) {
3467  r.bottom = r.top - 1;
3468  r.top = bm.bmHeight;
3469  r.left = 0;
3470  r.right = bm.bmWidth;
3471  hbr = CreateSolidBrush(GetPixel(hdcSrc, 0, 0));
3472  FillRect(hdc, &r, hbr);
3473  DeleteObject(hbr);
3474  }
3475 
3477  }
3478 
3479  if (psInfo->ppshheader.dwFlags & PSH_USEHPLWATERMARK)
3480  SelectPalette(hdc, hOldPal, FALSE);
3481 
3482  DeleteDC(hdcSrc);
3483 
3484  if (!hdcParam) EndPaint(hwnd, &ps);
3485 
3486  return 0;
3487 }
3488 
3489 /******************************************************************************
3490  * PROPSHEET_DialogProc
3491  */
3492 static INT_PTR CALLBACK
3494 {
3495  TRACE("hwnd=%p msg=0x%04x wparam=%lx lparam=%lx\n",
3496  hwnd, uMsg, wParam, lParam);
3497 
3498  switch (uMsg)
3499  {
3500  case WM_INITDIALOG:
3501  {
3502  PropSheetInfo* psInfo = (PropSheetInfo*) lParam;
3503  WCHAR* strCaption = Alloc(MAX_CAPTION_LENGTH*sizeof(WCHAR));
3504  HWND hwndTabCtrl = GetDlgItem(hwnd, IDC_TABCONTROL);
3505  int idx;
3506  LOGFONTW logFont;
3507 
3508  /* Using PropSheetInfoStr to store extra data doesn't match the native
3509  * common control: native uses TCM_[GS]ETITEM
3510  */
3511  SetPropW(hwnd, PropSheetInfoStr, psInfo);
3512 
3513  /*
3514  * psInfo->hwnd is not being used by WINE code - it exists
3515  * for compatibility with "real" Windoze. The same about
3516  * SetWindowLongPtr - WINE is only using the PropSheetInfoStr
3517  * property.
3518  */
3519  psInfo->hwnd = hwnd;
3521 
3522  if (psInfo->ppshheader.dwFlags & INTRNL_ANY_WIZARD)
3523  {
3524  /* set up the Next and Back buttons by default */
3526  }
3527 
3528  /* Set up fonts */
3530  psInfo->hFont = CreateFontIndirectW (&logFont);
3531  logFont.lfWeight = FW_BOLD;
3532  psInfo->hFontBold = CreateFontIndirectW (&logFont);
3533 
3534  /*
3535  * Small icon in the title bar.
3536  */
3537  if ((psInfo->ppshheader.dwFlags & PSH_USEICONID) ||
3538  (psInfo->ppshheader.dwFlags & PSH_USEHICON))
3539  {
3540  HICON hIcon;
3541  int icon_cx = GetSystemMetrics(SM_CXSMICON);
3542  int icon_cy = GetSystemMetrics(SM_CYSMICON);
3543 
3544  if (psInfo->ppshheader.dwFlags & PSH_USEICONID)
3545  hIcon = LoadImageW(psInfo->ppshheader.hInstance,
3546  psInfo->ppshheader.u.pszIcon,
3547  IMAGE_ICON,
3548  icon_cx, icon_cy,
3549  LR_DEFAULTCOLOR);
3550  else
3551  hIcon = psInfo->ppshheader.u.hIcon;
3552 
3553  SendMessageW(hwnd, WM_SETICON, 0, (LPARAM)hIcon);
3554  }
3555 
3556  if (psInfo->ppshheader.dwFlags & PSH_USEHICON)
3557  SendMessageW(hwnd, WM_SETICON, 0, (LPARAM)psInfo->ppshheader.u.hIcon);
3558 
3559  psInfo->strPropertiesFor = strCaption;
3560 
3561  GetWindowTextW(hwnd, psInfo->strPropertiesFor, MAX_CAPTION_LENGTH);
3562 
3564 
3566 
3567  if (psInfo->ppshheader.dwFlags & INTRNL_ANY_WIZARD)
3568  {
3569  ShowWindow(hwndTabCtrl, SW_HIDE);
3573  }
3574  else
3575  {
3576  if (PROPSHEET_SizeMismatch(hwnd, psInfo))
3577  {
3578  PROPSHEET_AdjustSize(hwnd, psInfo);
3579  PROPSHEET_AdjustButtons(hwnd, psInfo);
3580  }
3582  }
3583 #ifdef __REACTOS__
3584  { /*
3585  try to fit it into the desktop
3586  user32 positions the dialog based on the IDD_PROPSHEET template,
3587  but we've since made it larger by adding controls
3588  */
3589  RECT rcWork;
3590  RECT rcDlg;
3591  int dx, dy;
3592 
3593  if (GetWindowRect(hwnd, &rcDlg) && SystemParametersInfo(SPI_GETWORKAREA, 0, &rcWork, 0))
3594  {
3595  dx = rcDlg.right - rcWork.right;
3596  dy = rcDlg.bottom - rcWork.bottom;
3597 
3598  if (rcDlg.right > rcWork.right)
3599  rcDlg.left -= dx;
3600  if (rcDlg.bottom > rcWork.bottom)
3601  rcDlg.top -= dy;
3602 
3604  }
3605  }
3606 #endif
3607 
3608  if (IS_INTRESOURCE(psInfo->ppshheader.pszCaption) &&
3609  psInfo->ppshheader.hInstance)
3610  {
3611  WCHAR szText[256];
3612 
3613  if (LoadStringW(psInfo->ppshheader.hInstance,
3614  (UINT_PTR)psInfo->ppshheader.pszCaption, szText, 255))
3615  PROPSHEET_SetTitleW(hwnd, psInfo->ppshheader.dwFlags, szText);
3616  }
3617  else
3618  {
3619  PROPSHEET_SetTitleW(hwnd, psInfo->ppshheader.dwFlags,
3620  psInfo->ppshheader.pszCaption);
3621  }
3622 
3623 
3624  if (psInfo->useCallback)
3625  (*(psInfo->ppshheader.pfnCallback))(hwnd, PSCB_INITIALIZED, 0);
3626 
3627  idx = psInfo->active_page;
3628  psInfo->active_page = -1;
3629 
3630  PROPSHEET_SetCurSel(hwnd, idx, 1, psInfo->proppage[idx].hpage);
3631 
3632  /* doing TCM_SETCURSEL seems to be needed even in case of PSH_WIZARD,
3633  * as some programs call TCM_GETCURSEL to get the current selection
3634  * from which to switch to the next page */
3635  SendMessageW(hwndTabCtrl, TCM_SETCURSEL, psInfo->active_page, 0);
3636 
3638 
3639  /* wizards set their focus during init */
3640  if (psInfo->ppshheader.dwFlags & INTRNL_ANY_WIZARD)
3641  return FALSE;
3642 
3643  return TRUE;
3644  }
3645 
3646  case WM_PRINTCLIENT:
3647  case WM_PAINT:
3649  return TRUE;
3650 
3651  case WM_DESTROY:
3653  return TRUE;
3654 
3655  case WM_CLOSE:
3656  PROPSHEET_Cancel(hwnd, 1);
3657  return FALSE; /* let DefDlgProc post us WM_COMMAND/IDCANCEL */
3658 
3659  case WM_COMMAND:
3661  {
3663 
3664  if (!psInfo)
3665  return FALSE;
3666 
3667  /* No default handler, forward notification to active page */
3668  if (psInfo->activeValid && psInfo->active_page != -1)
3669  {
3670  HWND hwndPage = psInfo->proppage[psInfo->active_page].hwndPage;
3671  SendMessageW(hwndPage, WM_COMMAND, wParam, lParam);
3672  }
3673  }
3674  return TRUE;
3675 
3676  case WM_NOTIFY:
3677  {
3678  NMHDR* pnmh = (LPNMHDR) lParam;
3679 
3680  if (pnmh->code == TCN_SELCHANGE)
3681  {
3682  int index = SendMessageW(pnmh->hwndFrom, TCM_GETCURSEL, 0, 0);
3683  PROPSHEET_SetCurSel(hwnd, index, 1, 0);
3684  }
3685 
3686  if(pnmh->code == TCN_SELCHANGING)
3687  {
3690  return TRUE;
3691  }
3692 
3693  return FALSE;
3694  }
3695 
3696  case WM_SYSCOLORCHANGE:
3698  return FALSE;
3699 
3701  {
3703  HWND hwndPage = 0;
3704 
3705  if (!psInfo)
3706  return FALSE;
3707 
3708  if (psInfo->activeValid && psInfo->active_page != -1)
3709  hwndPage = psInfo->proppage[psInfo->active_page].hwndPage;
3710 
3712 
3713  return TRUE;
3714  }
3715 
3716  case PSM_CHANGED:
3718  return TRUE;
3719 
3720  case PSM_UNCHANGED:
3722  return TRUE;
3723 
3724  case PSM_GETTABCONTROL:
3725  {
3726  HWND hwndTabCtrl = GetDlgItem(hwnd, IDC_TABCONTROL);
3727 
3729 
3730  return TRUE;
3731  }
3732 
3733  case PSM_SETCURSEL:
3734  {
3735  BOOL msgResult;
3736 
3737  msgResult = PROPSHEET_CanSetCurSel(hwnd);
3738  if(msgResult != FALSE)
3739  {
3740  msgResult = PROPSHEET_SetCurSel(hwnd,
3741  (int)wParam,
3742  1,
3744  }
3745 
3746  SetWindowLongPtrW(hwnd, DWLP_MSGRESULT, msgResult);
3747 
3748  return TRUE;
3749  }
3750 
3751  case PSM_CANCELTOCLOSE:
3752  {
3754  HWND hwndOK = GetDlgItem(hwnd, IDOK);
3755  HWND hwndCancel = GetDlgItem(hwnd, IDCANCEL);
3756 
3757  EnableWindow(hwndCancel, FALSE);
3759  SetWindowTextW(hwndOK, buf);
3760 
3761  return FALSE;
3762  }
3763 
3764  case PSM_RESTARTWINDOWS:
3765  {
3767 
3768  if (!psInfo)
3769  return FALSE;
3770 
3771  /* reboot system takes precedence over restart windows */
3772  if (psInfo->result != ID_PSREBOOTSYSTEM)
3773  psInfo->result = ID_PSRESTARTWINDOWS;
3774 
3775  return TRUE;
3776  }
3777 
3778  case PSM_REBOOTSYSTEM:
3779  {
3781 
3782  if (!psInfo)
3783  return FALSE;
3784 
3785  psInfo->result = ID_PSREBOOTSYSTEM;
3786 
3787  return TRUE;
3788  }
3789 
3790  case PSM_SETTITLEA:
3792  return TRUE;
3793 
3794  case PSM_SETTITLEW:
3796  return TRUE;
3797 
3798  case PSM_APPLY:
3799  {
3800  BOOL msgResult = PROPSHEET_Apply(hwnd, 0);
3801 
3802  SetWindowLongPtrW(hwnd, DWLP_MSGRESULT, msgResult);
3803 
3804  return TRUE;
3805  }
3806 
3807  case PSM_QUERYSIBLINGS:
3808  {
3810 
3811  SetWindowLongPtrW(hwnd, DWLP_MSGRESULT, msgResult);
3812 
3813  return TRUE;
3814  }
3815 
3816  case PSM_ADDPAGE:
3817  {
3818  /*
3819  * Note: MSVC++ 6.0 documentation says that PSM_ADDPAGE does not have
3820  * a return value. This is not true. PSM_ADDPAGE returns TRUE
3821  * on success or FALSE otherwise, as specified on MSDN Online.
3822  * Also see the MFC code for
3823  * CPropertySheet::AddPage(CPropertyPage* pPage).
3824  */
3825 
3827 
3828  SetWindowLongPtrW(hwnd, DWLP_MSGRESULT, msgResult);
3829 
3830  return TRUE;
3831  }
3832 
3833  case PSM_REMOVEPAGE:
3835  return TRUE;
3836 
3837  case PSM_ISDIALOGMESSAGE:
3838  {
3840  SetWindowLongPtrW(hwnd, DWLP_MSGRESULT, msgResult);
3841  return TRUE;
3842  }
3843 
3844  case PSM_PRESSBUTTON:
3846  return TRUE;
3847 
3848  case PSM_SETFINISHTEXTA:
3850  return TRUE;
3851 
3852  case PSM_SETWIZBUTTONS:
3854  return TRUE;
3855 
3856  case PSM_SETCURSELID:
3858  return TRUE;
3859 
3860  case PSM_SETFINISHTEXTW:
3862  return FALSE;
3863 
3864  case PSM_INSERTPAGE:
3865  {
3867  SetWindowLongPtrW(hwnd, DWLP_MSGRESULT, msgResult);
3868  return TRUE;
3869  }
3870 
3871  case PSM_SETHEADERTITLEW:
3873  return TRUE;
3874 
3875  case PSM_SETHEADERTITLEA:
3877  return TRUE;
3878 
3879  case PSM_SETHEADERSUBTITLEW:
3881  return TRUE;
3882 
3883  case PSM_SETHEADERSUBTITLEA:
3885  return TRUE;
3886 
3887  case PSM_HWNDTOINDEX:
3888  {
3889  LRESULT msgResult = PROPSHEET_HwndToIndex(hwnd, (HWND)wParam);
3890  SetWindowLongPtrW(hwnd, DWLP_MSGRESULT, msgResult);
3891  return TRUE;
3892  }
3893 
3894  case PSM_INDEXTOHWND:
3895  {
3896  LRESULT msgResult = PROPSHEET_IndexToHwnd(hwnd, (int)wParam);
3897  SetWindowLongPtrW(hwnd, DWLP_MSGRESULT, msgResult);
3898  return TRUE;
3899  }
3900 
3901  case PSM_PAGETOINDEX:
3902  {
3904  SetWindowLongPtrW(hwnd, DWLP_MSGRESULT, msgResult);
3905  return TRUE;
3906  }
3907 
3908  case PSM_INDEXTOPAGE:
3909  {
3910  LRESULT msgResult = PROPSHEET_IndexToPage(hwnd, (int)wParam);
3911  SetWindowLongPtrW(hwnd, DWLP_MSGRESULT, msgResult);
3912  return TRUE;
3913  }
3914 
3915  case PSM_IDTOINDEX:
3916  {
3917  LRESULT msgResult = PROPSHEET_IdToIndex(hwnd, (int)lParam);
3918  SetWindowLongPtrW(hwnd, DWLP_MSGRESULT, msgResult);
3919  return TRUE;
3920  }
3921 
3922  case PSM_INDEXTOID:
3923  {
3924  LRESULT msgResult = PROPSHEET_IndexToId(hwnd, (int)wParam);
3925  SetWindowLongPtrW(hwnd, DWLP_MSGRESULT, msgResult);
3926  return TRUE;
3927  }
3928 
3929  case PSM_GETRESULT:
3930  {
3931  LRESULT msgResult = PROPSHEET_GetResult(hwnd);
3932  SetWindowLongPtrW(hwnd, DWLP_MSGRESULT, msgResult);
3933  return TRUE;
3934  }
3935 
3936  case PSM_RECALCPAGESIZES:
3937  {
3938  LRESULT msgResult = PROPSHEET_RecalcPageSizes(hwnd);
3939  SetWindowLongPtrW(hwnd, DWLP_MSGRESULT, msgResult);
3940  return TRUE;
3941  }
3942 
3943  default:
3944  return FALSE;
3945  }
3946 }
int WINAPIV wsprintfW(_Out_ LPWSTR, _In_ _Printf_format_string_ LPCWSTR,...)
static LRESULT PROPSHEET_HwndToIndex(HWND hwndDlg, HWND hPageDlg)
Definition: propsheet.c:2604
#define PSH_WIZARDHASFINISH
Definition: prsht.h:44
static LRESULT PROPSHEET_Paint(HWND hwnd, HDC hdcParam)
Definition: propsheet.c:3292
#define TCM_GETCURSEL
Definition: commctrl.h:4058
#define WS_DISABLED
Definition: pedump.c:621
HWND hwndParent
Definition: prsht.h:295
#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 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:1816
LPCPROPSHEETPAGEW ppsp
Definition: prsht.h:308
#define PSH_NOAPPLYNOW
Definition: prsht.h:47
static void PROPSHEET_SetFinishTextA(HWND hwndDlg, LPCSTR lpszText)
Definition: propsheet.c:2169
WINE_UNICODE_INLINE unsigned int strlenW(const WCHAR *str)
Definition: unicode.h:212
#define IDC_APPLY_BUTTON
Definition: propsheet.c:14
LPCWSTR pszTemplate
Definition: prsht.h:218
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)
GLuint64EXT * result
Definition: glext.h:11304
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:58
#define TCM_ADJUSTRECT
Definition: commctrl.h:4081
ACPI_SIZE strlen(const char *String)
Definition: utclib.c:269
#define PSM_GETTABCONTROL
Definition: prsht.h:80
struct tagPropPageInfo PropPageInfo
#define TRUE
Definition: types.h:120
#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:3144
GLdouble GLdouble GLdouble r
Definition: gl.h:2055
#define CP_ACP
Definition: compat.h:109
PROPSHEETHEADERW ppshheader
Definition: propsheet.c:111
GLint dy
Definition: linetemp.h:97
#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:57
#define WARN(fmt,...)
Definition: debug.h:112
HRSRC WINAPI FindResourceA(HMODULE hModule, LPCSTR name, LPCSTR type)
Definition: res.c:155
LPCDLGTEMPLATE pResource
Definition: prsht.h:219
LPCSTR pszCaption
Definition: prsht.h:266
static HDC
Definition: imagelist.c:92
#define CALLBACK
Definition: compat.h:35
_In_ DWORD nLength
Definition: wincon.h:476
#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
#define SystemParametersInfo
Definition: winuser.h:5833
GLdouble n
Definition: glext.h:7729
LONG top
Definition: windef.h:307
#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:2342
HGDIOBJ WINAPI SelectObject(_In_ HDC, _In_ HGDIOBJ)
Definition: dc.c:1499
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_TOPMOST
Definition: winuser.h:1194
#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:4061
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:2709
UINT_PTR WPARAM
Definition: windef.h:207
struct tagPropSheetInfo PropSheetInfo
#define VK_TAB
Definition: winuser.h:2174
#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:3967
#define PSH_WIZARD
Definition: prsht.h:45
#define PSN_APPLY
Definition: prsht.h:117
LONG left
Definition: windef.h:306
#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:64
#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:308
HWND WINAPI GetNextDlgTabItem(_In_ HWND, _In_opt_ HWND, _In_ BOOL)
#define lstrlenW
Definition: compat.h:609
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:2554
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:58
#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:3177
UINT nStartPage
Definition: prsht.h:269
#define VK_NEXT
Definition: winuser.h:2196
_In_opt_ PALLOCATE_FUNCTION _In_opt_ PFREE_FUNCTION Free
Definition: exfuncs.h:814
#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:3134
static void PROPSHEET_Changed(HWND hwndDlg, HWND hwndDirtyPage)
Definition: propsheet.c:1838
COLORREF WINAPI SetBkColor(_In_ HDC, _In_ COLORREF)
Definition: dc.c:977
#define DS_MODALFRAME
Definition: winuser.h:375
GLenum GLuint GLenum GLsizei const GLchar * buf
Definition: glext.h:7751
NMHDR hdr
Definition: prsht.h:330
static void PROPSHEET_SetHeaderTitleW(HWND hwndDlg, UINT page_index, const WCHAR *title)
Definition: propsheet.c:2532
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:1943
int WINAPI SetBkMode(_In_ HDC, _In_ int)
Definition: dc.c:1034
#define IDD_PROPSHEET
Definition: comctl32.h:50
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:214
#define PSH_USEICONID
Definition: prsht.h:42
static LONG active_page
Definition: propsheet.c:37
#define FALSE
Definition: types.h:117
#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:301
static void PROPSHEET_Cancel(HWND hwndDlg, LPARAM lParam)
Definition: propsheet.c:1773
HWND hwndParent
Definition: prsht.h:260
unsigned int BOOL
Definition: ntddk_ex.h:94
DLGPROC pfnDlgProc
Definition: prsht.h:226
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:3133
static BOOL PROPSHEET_Next(HWND hwndDlg)
Definition: propsheet.c:1626
#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:111
#define ILC_COLOR
Definition: commctrl.h:348
#define PSM_SETWIZBUTTONS
Definition: prsht.h:157
#define TCM_DELETEITEM
Definition: commctrl.h:4049
static PVOID ptr
Definition: dispmode.c:27
PFNPROPSHEETCALLBACK pfnCallback
Definition: prsht.h:311
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:2106
#define VK_SHIFT
Definition: winuser.h:2177
#define PSCB_PRECREATE
Definition: prsht.h:76
PFNPROPSHEETCALLBACK pfnCallback
Definition: prsht.h:276
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:4043
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
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:2663
INT_PTR WINAPI PropertySheetW(LPCPROPSHEETHEADERW lppsh)
Definition: propsheet.c:2905
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:225
#define SW_SHOW
Definition: winuser.h:769
INT_PTR WINAPI PropertySheetA(LPCPROPSHEETHEADERA lppsh)
Definition: propsheet.c:2864
#define PSPCB_RELEASE
Definition: prsht.h:37
static BOOL PROPSHEET_Back(HWND hwndDlg)
Definition: propsheet.c:1584
#define UlongToPtr(u)
Definition: config.h:106
#define WM_DESTROY
Definition: winuser.h:1591
#define IDS_CLOSE
Definition: comctl32.h:61
#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:3075
#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:4128
#define PSM_APPLY
Definition: prsht.h:158
static void PROPSHEET_SetWizButtons(HWND hwndDlg, DWORD dwFlags)
Definition: propsheet.c:2458
static void PROPSHEET_SetFinishTextW(HWND hwndDlg, LPCWSTR lpszText)
Definition: propsheet.c:2198
static VOID PROPSHEET_UnImplementedFlags(DWORD dwFlags)
Definition: propsheet.c:204
static VOID PROPSHEET_LoadWizardBitmaps(PropSheetInfo *psInfo)
Definition: propsheet.c:1493
#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:59
BOOL WINAPI SetPropW(_In_ HWND, _In_ LPCWSTR, _In_opt_ HANDLE)
r parent
Definition: btrfs.c:2944
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:300
HINSTANCE hInstance
Definition: prsht.h:296
HRESULT WINAPI EnableThemeDialogTexture(_In_ HWND hwnd, _In_ DWORD dwFlags)
Definition: uxthemesupp.c:55
DWORD dwSize
Definition: prsht.h:258
#define PROPSHEETPAGEA_V1_SIZE
Definition: prsht.h:209
#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:6
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:208
#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:293
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:294
TCHAR szTitle[MAX_LOADSTRING]
Definition: magnifier.c:35
static BOOL PROPSHEET_SetCurSel(HWND hwndDlg, int index, int skipdir, HPROPSHEETPAGE hpage)
Definition: propsheet.c:1982
#define WM_PAINT
Definition: winuser.h:1602
#define SM_CXSMICON
Definition: winuser.h:1002
GLuint GLuint end
Definition: gl.h:1545
static BOOL PROPSHEET_InsertPage(HWND hwndDlg, HPROPSHEETPAGE hpageInsertAfter, HPROPSHEETPAGE hpage)
Definition: propsheet.c:2248
DWORD dwFlags
Definition: prsht.h:259
#define IDD_WIZARD
Definition: comctl32.h:51
#define IDC_BACK_BUTTON
Definition: comctl32.h:55
int ret
static WCHAR * heap_strdupAtoW(const char *str)
Definition: propsheet.c:186
static LRESULT PROPSHEET_IndexToHwnd(HWND hwndDlg, int iPageIndex)
Definition: propsheet.c:2621
#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:216
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
GLenum GLsizei len
Definition: glext.h:6722
#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:2790
HWND hwndFrom
Definition: winuser.h:3132
uint32_t DWORD_PTR
Definition: typedefs.h:65
#define PSP_USETITLE
Definition: prsht.h:26
#define PSBTN_NEXT
Definition: prsht.h:147
unsigned char BYTE
Definition: xxhash.c:193
GLint GLint GLsizei GLsizei height
Definition: gl.h:1546
static void PROPSHEET_SetHeaderSubTitleA(HWND hwndDlg, UINT page_index, const char *subtitle)
Definition: propsheet.c:2590
HICON hIcon
Definition: prsht.h:222
BOOL WINAPI EnableWindow(_In_ HWND, _In_ BOOL)
HPROPSHEETPAGE * phpage
Definition: prsht.h:309
const PROPSHEETPAGEW * LPCPROPSHEETPAGEW
Definition: prsht.h:245
#define SWP_NOSIZE
Definition: winuser.h:1230
#define ERR(fmt,...)
Definition: debug.h:110
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: