Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

685 lines
15 KiB

  1. /*++
  2. Copyright (c) 1996 Microsoft Corporation
  3. Module Name:
  4. wizard.c
  5. Abstract:
  6. This file implements wizard functions.
  7. Environment:
  8. WIN32 User Mode
  9. Author:
  10. Wesley Witt (wesw) 17-Feb-1996
  11. --*/
  12. #include "wizard.h"
  13. #pragma hdrstop
  14. //
  15. // the following is not in the SDK
  16. //
  17. #include <pshpack2.h>
  18. typedef struct _DLGTEMPLATE2 {
  19. WORD DlgVersion;
  20. WORD Signature;
  21. DWORD HelpId;
  22. DWORD StyleEx;
  23. DWORD Style;
  24. WORD cDlgItems;
  25. short x;
  26. short y;
  27. short cx;
  28. short cy;
  29. } DLGTEMPLATE2;
  30. #include <poppack.h>
  31. //
  32. // Enum for SetDialogFont().
  33. //
  34. typedef enum {
  35. DlgFontTitle,
  36. DlgFontSupertitle,
  37. DlgFontSubtitle
  38. } MyDlgFont;
  39. CONST BITMAPINFOHEADER *WatermarkBitmapInfoHeader;
  40. HPALETTE WatermarkPalette;
  41. UINT WatermarkPaletteColorCount;
  42. UINT WatermarkHeaderHeight;
  43. VOID
  44. SetDialogFont(
  45. IN HWND hdlg,
  46. IN UINT ControlId,
  47. IN MyDlgFont WhichFont
  48. )
  49. {
  50. static HFONT BigBoldFont = NULL;
  51. static HFONT BoldFont = NULL;
  52. HFONT Font;
  53. LOGFONT LogFont;
  54. int FontSize;
  55. HDC hdc;
  56. switch(WhichFont) {
  57. case DlgFontTitle:
  58. if(!BigBoldFont) {
  59. if(Font = (HFONT)SendDlgItemMessage(hdlg,ControlId,WM_GETFONT,0,0)) {
  60. if(GetObject(Font,sizeof(LOGFONT),&LogFont)) {
  61. LogFont.lfWeight = FW_BOLD;
  62. //
  63. // Load size and name from resources, since these may change
  64. // from locale to locale based on the size of the system font, etc.
  65. //
  66. lstrcpy(LogFont.lfFaceName,GetString(IDS_LARGEFONTNAME));
  67. FontSize = _tcstoul(GetString(IDS_LARGEFONTSIZE),NULL,10);
  68. if(hdc = GetDC(hdlg)) {
  69. LogFont.lfHeight = 0 - (GetDeviceCaps(hdc,LOGPIXELSY) * FontSize / 72);
  70. BigBoldFont = CreateFontIndirect(&LogFont);
  71. ReleaseDC(hdlg,hdc);
  72. }
  73. }
  74. }
  75. }
  76. Font = BigBoldFont;
  77. break;
  78. case DlgFontSupertitle:
  79. if(!BoldFont) {
  80. if(Font = (HFONT)SendDlgItemMessage(hdlg,ControlId,WM_GETFONT,0,0)) {
  81. if(GetObject(Font,sizeof(LOGFONT),&LogFont)) {
  82. LogFont.lfWeight = FW_BOLD;
  83. if(hdc = GetDC(hdlg)) {
  84. BoldFont = CreateFontIndirect(&LogFont);
  85. ReleaseDC(hdlg,hdc);
  86. }
  87. }
  88. }
  89. }
  90. Font = BoldFont;
  91. break;
  92. case DlgFontSubtitle:
  93. default:
  94. //
  95. // Nothing to do here.
  96. //
  97. Font = NULL;
  98. break;
  99. }
  100. if(Font) {
  101. SendDlgItemMessage(hdlg,ControlId,WM_SETFONT,(WPARAM)Font,0);
  102. }
  103. }
  104. BOOL
  105. PaintWatermark(
  106. IN HWND hdlg,
  107. IN HDC DialogDC,
  108. IN UINT XOffset,
  109. IN UINT YOffset,
  110. IN BOOL FullPage
  111. )
  112. {
  113. HPALETTE OldPalette;
  114. RECT rect;
  115. int Height,Width;
  116. //
  117. // The correct palette is already realized in foreground from
  118. // WM_xxxPALETTExxx processing in dialog procs.
  119. //
  120. OldPalette = SelectPalette(DialogDC,WatermarkPalette,TRUE);
  121. SetDIBitsToDevice(
  122. //
  123. // Target the dialog's background.
  124. //
  125. DialogDC,
  126. //
  127. // Destination is upper left of dialog client area.
  128. //
  129. 0,0,
  130. //
  131. // Assume that wizard pages are centered horizontally in the wizard dialog.
  132. //
  133. Width = WatermarkBitmapInfoHeader->biWidth - (2*XOffset),
  134. //
  135. // For full-page watermarks, the height is the height of the bitmap.
  136. // For header watermarks, the height is the header area's height.
  137. // Also account for the y offset within the source bitmap.
  138. //
  139. Height = (FullPage ? WatermarkBitmapInfoHeader->biHeight : WatermarkHeaderHeight) - YOffset,
  140. //
  141. // The x coord of the lower-left corner of the source is the X offset
  142. // within the source bitmap.
  143. //
  144. XOffset,
  145. //
  146. // Now we need the y coord of the lower-left corner of the source.
  147. // The lower-left corner is the origin.
  148. //
  149. FullPage ? 0 : (WatermarkBitmapInfoHeader->biHeight - WatermarkHeaderHeight),
  150. //
  151. // We don't do banding so the start scan line is always 0
  152. // and the scan line count is always the number of lines in the bitmap.
  153. //
  154. 0,WatermarkBitmapInfoHeader->biHeight,
  155. //
  156. // Additional bitmap data.
  157. //
  158. (LPBYTE)WatermarkBitmapInfoHeader + WatermarkBitmapInfoHeader->biSize + (WatermarkPaletteColorCount * sizeof(RGBQUAD)),
  159. (BITMAPINFO *)WatermarkBitmapInfoHeader,
  160. //
  161. // Specify that the bitmap's color info is supplied in RGB and not in
  162. // palette indices.
  163. //
  164. DIB_RGB_COLORS
  165. );
  166. //
  167. // Fill in area below the watermark if needed. We do this by removing the area
  168. // we filled with watermark from the clipping area, and passing a return code
  169. // back from WM_ERASEBKGND indicating that we didn't erase the background.
  170. // The dialog manager will do its default thing, which is to fill the background
  171. // in the correct color, but won't touch what we just painted.
  172. //
  173. GetClientRect(hdlg,&rect);
  174. if((Height < rect.bottom) || (Width+(int)XOffset < rect.right)) {
  175. ExcludeClipRect(DialogDC,0,0,Width+XOffset,Height);
  176. return(FALSE);
  177. }
  178. return(TRUE);
  179. }
  180. HPALETTE
  181. CreateDIBPalette(
  182. IN LPBITMAPINFO BitmapInfo,
  183. OUT int *ColorCount
  184. )
  185. /*++
  186. Routine Description:
  187. Arguments:
  188. Return Value:
  189. --*/
  190. {
  191. LPBITMAPINFOHEADER BitmapInfoHeader;
  192. LPLOGPALETTE LogicalPalette;
  193. HPALETTE Palette;
  194. int i;
  195. DWORD d;
  196. BitmapInfoHeader = (LPBITMAPINFOHEADER)BitmapInfo;
  197. //
  198. // No palette needed for >= 16 bpp
  199. //
  200. *ColorCount = (BitmapInfoHeader->biBitCount <= 8)
  201. ? (1 << BitmapInfoHeader->biBitCount)
  202. : 0;
  203. if(*ColorCount) {
  204. LogicalPalette = MemAlloc(sizeof(LOGPALETTE) + (sizeof(PALETTEENTRY) * (*ColorCount)));
  205. if(!LogicalPalette) {
  206. SetLastError(ERROR_NOT_ENOUGH_MEMORY);
  207. return(NULL);
  208. }
  209. LogicalPalette->palVersion = 0x300;
  210. LogicalPalette->palNumEntries = *ColorCount;
  211. for(i=0; i<*ColorCount; i++) {
  212. LogicalPalette->palPalEntry[i].peRed = BitmapInfo->bmiColors[i].rgbRed;
  213. LogicalPalette->palPalEntry[i].peGreen = BitmapInfo->bmiColors[i].rgbGreen;
  214. LogicalPalette->palPalEntry[i].peBlue = BitmapInfo->bmiColors[i].rgbBlue;
  215. LogicalPalette->palPalEntry[i].peFlags = 0;
  216. }
  217. Palette = CreatePalette(LogicalPalette);
  218. d = GetLastError();
  219. MemFree(LogicalPalette);
  220. SetLastError(d);
  221. } else {
  222. Palette = NULL;
  223. }
  224. return(Palette);
  225. }
  226. BOOL
  227. GetBitmapDataAndPalette(
  228. IN HINSTANCE hInst,
  229. IN LPCTSTR Id,
  230. OUT HPALETTE *Palette,
  231. OUT PUINT ColorCount,
  232. OUT CONST BITMAPINFOHEADER **BitmapData
  233. )
  234. /*++
  235. Routine Description:
  236. Retreives device-independent bitmap data and a color table from a
  237. bitmap in a resource.
  238. Arguments:
  239. hInst - supplies instance handle for module containing the bitmap resource.
  240. Id - supplies the id of the bitmap resource.
  241. Palette - if successful, receives a handle to a palette for the bitmap.
  242. ColorCount - if successful, receives the number of entries in the
  243. palette for the bitmap.
  244. BitmapData - if successful, receives a pointer to the bitmap info
  245. header structure in the resources. This is in read-only memory
  246. so the caller should not try to modify it.
  247. Return Value:
  248. If successful, handle to the loaded bitmap (DIB).
  249. If not, NULL is returned. Check GetLastError().
  250. --*/
  251. {
  252. HRSRC BlockHandle;
  253. HGLOBAL MemoryHandle;
  254. //
  255. // None of FindResource(), LoadResource(), or LockResource()
  256. // need to have cleanup routines called in Win32.
  257. //
  258. BlockHandle = FindResource(hInst,Id,RT_BITMAP);
  259. if(!BlockHandle) {
  260. return(FALSE);
  261. }
  262. MemoryHandle = LoadResource(hInst,BlockHandle);
  263. if(!MemoryHandle) {
  264. return(FALSE);
  265. }
  266. *BitmapData = LockResource(MemoryHandle);
  267. if(*BitmapData == NULL) {
  268. return(FALSE);
  269. }
  270. *Palette = CreateDIBPalette((LPBITMAPINFO)*BitmapData,ColorCount);
  271. return(TRUE);
  272. }
  273. DLGITEMTEMPLATE *
  274. FindControlInDialog(
  275. IN PVOID Template,
  276. IN UINT ControlId
  277. )
  278. {
  279. PVOID p;
  280. DLGTEMPLATE *pTemplate;
  281. DLGTEMPLATE2 *pTemplate2;
  282. DLGITEMTEMPLATE *pItem;
  283. WORD ItemCount;
  284. DWORD Style;
  285. WORD i;
  286. p = Template;
  287. //
  288. // Skip fixed part of template
  289. //
  290. if(((DLGTEMPLATE2 *)p)->Signature == 0xffff) {
  291. pTemplate2 = p;
  292. ItemCount = pTemplate2->cDlgItems;
  293. Style = pTemplate2->Style;
  294. p = pTemplate2 + 1;
  295. } else {
  296. pTemplate = p;
  297. ItemCount = pTemplate->cdit;
  298. Style = pTemplate->style;
  299. p = pTemplate + 1;
  300. }
  301. //
  302. // Skip menu. First word=0 means no menu
  303. // First word=0xffff means one more word follows
  304. // Else it's a nul-terminated string
  305. //
  306. switch(*(WORD *)p) {
  307. case 0xffff:
  308. p = (WORD *)p + 2;
  309. break;
  310. case 0:
  311. p = (WORD *)p + 1;
  312. break;
  313. default:
  314. p = (PWCHAR)p + lstrlenW(p) + 1;
  315. break;
  316. }
  317. //
  318. // Skip class, similar to menu
  319. //
  320. switch(*(WORD *)p) {
  321. case 0xffff:
  322. p = (WORD *)p + 2;
  323. break;
  324. case 0:
  325. p = (WORD *)p + 1;
  326. break;
  327. default:
  328. p = (PWCHAR)p + lstrlenW(p) + 1;
  329. break;
  330. }
  331. //
  332. // Skip title
  333. //
  334. p = (PWCHAR)p + lstrlenW(p) + 1;
  335. if(Style & DS_SETFONT) {
  336. //
  337. // Skip point size and typeface name
  338. //
  339. p = (WORD *)p + 1;
  340. p = (PWCHAR)p + lstrlenW(p) + 1;
  341. }
  342. //
  343. // Now we have a pointer to the first item in the dialog
  344. //
  345. for(i=0; i<ItemCount; i++) {
  346. //
  347. // Align to next DWORD boundary
  348. //
  349. p = (PVOID)(((DWORD)p + sizeof(DWORD) - 1) & (~(sizeof(DWORD) - 1)));
  350. pItem = p;
  351. if(pItem->id == (WORD)ControlId) {
  352. break;
  353. }
  354. //
  355. // Skip to next item in dialog.
  356. // First is class, which is either 0xffff plus one more word,
  357. // or a unicode string. After that is text/title.
  358. //
  359. p = pItem + 1;
  360. if(*(WORD *)p == 0xffff) {
  361. p = (WORD *)p + 2;
  362. } else {
  363. p = (PWCHAR)p + lstrlenW(p) + 1;
  364. }
  365. if(*(WORD *)p == 0xffff) {
  366. p = (WORD *)p + 2;
  367. } else {
  368. p = (PWCHAR)p + lstrlenW(p) + 1;
  369. }
  370. //
  371. // Skip creation data.
  372. //
  373. p = (PUCHAR)p + *(WORD *)p;
  374. p = (WORD *)p + 1;
  375. }
  376. if(i == ItemCount) {
  377. pItem = NULL;
  378. }
  379. return(pItem);
  380. }
  381. UINT
  382. GetYPositionOfDialogItem(
  383. IN LPCTSTR Dialog,
  384. IN UINT ControlId
  385. )
  386. {
  387. HRSRC hRsrc;
  388. PVOID p;
  389. HGLOBAL hGlobal;
  390. DLGITEMTEMPLATE *pItem;
  391. UINT i;
  392. i = 0;
  393. if(hRsrc = FindResource(FaxWizModuleHandle,Dialog,RT_DIALOG)) {
  394. if(hGlobal = LoadResource(FaxWizModuleHandle,hRsrc)) {
  395. if(p = LockResource(hGlobal)) {
  396. if(pItem = FindControlInDialog(p,ControlId)) {
  397. i = pItem->y * HIWORD(GetDialogBaseUnits()) / 8;
  398. }
  399. UnlockResource(hGlobal);
  400. }
  401. FreeResource(hGlobal);
  402. }
  403. }
  404. return(i);
  405. }
  406. int
  407. CALLBACK
  408. WizardCallback(
  409. IN HWND hdlg,
  410. IN UINT code,
  411. IN LPARAM lParam
  412. )
  413. {
  414. DLGTEMPLATE *DlgTemplate;
  415. //
  416. // Get rid of context sensitive help control on title bar
  417. //
  418. if(code == PSCB_PRECREATE) {
  419. DlgTemplate = (DLGTEMPLATE *)lParam;
  420. DlgTemplate->style &= ~DS_CONTEXTHELP;
  421. }
  422. return 0;
  423. }
  424. int
  425. CALLBACK
  426. Winnt32SheetCallback(
  427. IN HWND DialogHandle,
  428. IN UINT Message,
  429. IN LPARAM lParam
  430. )
  431. {
  432. DLGTEMPLATE *DlgTemplate;
  433. HDC hdc;
  434. switch(Message) {
  435. case PSCB_PRECREATE:
  436. //
  437. // Make sure we get into the foreground.
  438. //
  439. DlgTemplate = (DLGTEMPLATE *)lParam;
  440. DlgTemplate->style &= ~DS_CONTEXTHELP;
  441. DlgTemplate->style |= DS_SETFOREGROUND;
  442. //
  443. // Get the height of the page header/watermark area. The first page
  444. // must have a separator control with a known ID. We use that as
  445. // the basis for the header area height.
  446. //
  447. WatermarkHeaderHeight = GetYPositionOfDialogItem(
  448. MAKEINTRESOURCE(IDD_WELCOME),
  449. IDC_HEADER_BOTTOM
  450. );
  451. break;
  452. case PSCB_INITIALIZED:
  453. //
  454. // Load the watermark bitmap and override the dialog procedure for the wizard.
  455. //
  456. hdc = GetDC(NULL);
  457. GetBitmapDataAndPalette(
  458. FaxWizModuleHandle,
  459. (!hdc || (GetDeviceCaps(hdc,BITSPIXEL) < 8))
  460. ? MAKEINTRESOURCE(IDB_WATERMARK16) : MAKEINTRESOURCE(IDB_WATERMARK256),
  461. &WatermarkPalette,
  462. &WatermarkPaletteColorCount,
  463. &WatermarkBitmapInfoHeader
  464. );
  465. if(hdc) {
  466. ReleaseDC(NULL,hdc);
  467. }
  468. //OldWizardProc = (WNDPROC)SetWindowLong(DialogHandle,DWL_DLGPROC,(LONG)WizardDlgProc);
  469. break;
  470. }
  471. return(0);
  472. }
  473. LPHPROPSHEETPAGE
  474. CreateWizardPages(
  475. HINSTANCE hInstance,
  476. PWIZPAGE SetupWizardPages,
  477. LPDWORD RequestedPages,
  478. LPDWORD PageCount
  479. )
  480. {
  481. LPHPROPSHEETPAGE WizardPageHandles;
  482. LPDWORD PageList;
  483. DWORD PagesInSet;
  484. DWORD i;
  485. DWORD PageOrdinal;
  486. BOOL b;
  487. //
  488. // Determine which set of pages to use and how many there are in the set.
  489. //
  490. PageList = RequestedPages;
  491. PagesInSet = 0;
  492. while( PageList[PagesInSet] != (DWORD)-1) {
  493. PagesInSet += 1;
  494. }
  495. //
  496. // allocate the page handle array
  497. //
  498. WizardPageHandles = (HPROPSHEETPAGE*) MemAlloc(
  499. sizeof(HPROPSHEETPAGE) * PagesInSet
  500. );
  501. if (!WizardPageHandles) {
  502. return NULL;
  503. }
  504. //
  505. // Create each page.
  506. //
  507. b = TRUE;
  508. *PageCount = 0;
  509. for(i=0; b && (i<PagesInSet); i++) {
  510. PageOrdinal = PageList[i];
  511. SetupWizardPages[PageOrdinal].Page.hInstance = hInstance;
  512. SetupWizardPages[PageOrdinal].Page.dwFlags |= PSP_USETITLE;
  513. SetupWizardPages[PageOrdinal].Page.lParam = (LPARAM) &SetupWizardPages[PageOrdinal];
  514. SetupWizardPages[PageOrdinal].Page.dwSize = sizeof(PROPSHEETPAGE);
  515. if (PointPrintSetup) {
  516. SetupWizardPages[PageOrdinal].Page.pszTitle = GetString( IDS_TITLE_PP );
  517. }
  518. WizardPageHandles[*PageCount] = CreatePropertySheetPage(
  519. &SetupWizardPages[PageOrdinal].Page
  520. );
  521. if(WizardPageHandles[*PageCount]) {
  522. (*PageCount)++;
  523. } else {
  524. b = FALSE;
  525. }
  526. }
  527. if (!b) {
  528. MemFree( WizardPageHandles );
  529. return NULL;
  530. }
  531. return WizardPageHandles;
  532. }