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