/*++ Copyright (c) 1996 Microsoft Corporation Module Name: wizard.c Abstract: This file implements wizard functions. Environment: WIN32 User Mode Author: Wesley Witt (wesw) 17-Feb-1996 --*/ #include "wizard.h" #pragma hdrstop // // the following is not in the SDK // #include typedef struct _DLGTEMPLATE2 { WORD DlgVersion; WORD Signature; DWORD HelpId; DWORD StyleEx; DWORD Style; WORD cDlgItems; short x; short y; short cx; short cy; } DLGTEMPLATE2; #include // // Enum for SetDialogFont(). // typedef enum { DlgFontTitle, DlgFontSupertitle, DlgFontSubtitle } MyDlgFont; CONST BITMAPINFOHEADER *WatermarkBitmapInfoHeader; HPALETTE WatermarkPalette; UINT WatermarkPaletteColorCount; UINT WatermarkHeaderHeight; VOID SetDialogFont( IN HWND hdlg, IN UINT ControlId, IN MyDlgFont WhichFont ) { static HFONT BigBoldFont = NULL; static HFONT BoldFont = NULL; HFONT Font; LOGFONT LogFont; int FontSize; HDC hdc; switch(WhichFont) { case DlgFontTitle: if(!BigBoldFont) { if(Font = (HFONT)SendDlgItemMessage(hdlg,ControlId,WM_GETFONT,0,0)) { if(GetObject(Font,sizeof(LOGFONT),&LogFont)) { LogFont.lfWeight = FW_BOLD; // // Load size and name from resources, since these may change // from locale to locale based on the size of the system font, etc. // lstrcpy(LogFont.lfFaceName,GetString(IDS_LARGEFONTNAME)); FontSize = _tcstoul(GetString(IDS_LARGEFONTSIZE),NULL,10); if(hdc = GetDC(hdlg)) { LogFont.lfHeight = 0 - (GetDeviceCaps(hdc,LOGPIXELSY) * FontSize / 72); BigBoldFont = CreateFontIndirect(&LogFont); ReleaseDC(hdlg,hdc); } } } } Font = BigBoldFont; break; case DlgFontSupertitle: if(!BoldFont) { if(Font = (HFONT)SendDlgItemMessage(hdlg,ControlId,WM_GETFONT,0,0)) { if(GetObject(Font,sizeof(LOGFONT),&LogFont)) { LogFont.lfWeight = FW_BOLD; if(hdc = GetDC(hdlg)) { BoldFont = CreateFontIndirect(&LogFont); ReleaseDC(hdlg,hdc); } } } } Font = BoldFont; break; case DlgFontSubtitle: default: // // Nothing to do here. // Font = NULL; break; } if(Font) { SendDlgItemMessage(hdlg,ControlId,WM_SETFONT,(WPARAM)Font,0); } } BOOL PaintWatermark( IN HWND hdlg, IN HDC DialogDC, IN UINT XOffset, IN UINT YOffset, IN BOOL FullPage ) { HPALETTE OldPalette; RECT rect; int Height,Width; // // The correct palette is already realized in foreground from // WM_xxxPALETTExxx processing in dialog procs. // OldPalette = SelectPalette(DialogDC,WatermarkPalette,TRUE); SetDIBitsToDevice( // // Target the dialog's background. // DialogDC, // // Destination is upper left of dialog client area. // 0,0, // // Assume that wizard pages are centered horizontally in the wizard dialog. // Width = WatermarkBitmapInfoHeader->biWidth - (2*XOffset), // // For full-page watermarks, the height is the height of the bitmap. // For header watermarks, the height is the header area's height. // Also account for the y offset within the source bitmap. // Height = (FullPage ? WatermarkBitmapInfoHeader->biHeight : WatermarkHeaderHeight) - YOffset, // // The x coord of the lower-left corner of the source is the X offset // within the source bitmap. // XOffset, // // Now we need the y coord of the lower-left corner of the source. // The lower-left corner is the origin. // FullPage ? 0 : (WatermarkBitmapInfoHeader->biHeight - WatermarkHeaderHeight), // // We don't do banding so the start scan line is always 0 // and the scan line count is always the number of lines in the bitmap. // 0,WatermarkBitmapInfoHeader->biHeight, // // Additional bitmap data. // (LPBYTE)WatermarkBitmapInfoHeader + WatermarkBitmapInfoHeader->biSize + (WatermarkPaletteColorCount * sizeof(RGBQUAD)), (BITMAPINFO *)WatermarkBitmapInfoHeader, // // Specify that the bitmap's color info is supplied in RGB and not in // palette indices. // DIB_RGB_COLORS ); // // Fill in area below the watermark if needed. We do this by removing the area // we filled with watermark from the clipping area, and passing a return code // back from WM_ERASEBKGND indicating that we didn't erase the background. // The dialog manager will do its default thing, which is to fill the background // in the correct color, but won't touch what we just painted. // GetClientRect(hdlg,&rect); if((Height < rect.bottom) || (Width+(int)XOffset < rect.right)) { ExcludeClipRect(DialogDC,0,0,Width+XOffset,Height); return(FALSE); } return(TRUE); } HPALETTE CreateDIBPalette( IN LPBITMAPINFO BitmapInfo, OUT int *ColorCount ) /*++ Routine Description: Arguments: Return Value: --*/ { LPBITMAPINFOHEADER BitmapInfoHeader; LPLOGPALETTE LogicalPalette; HPALETTE Palette; int i; DWORD d; BitmapInfoHeader = (LPBITMAPINFOHEADER)BitmapInfo; // // No palette needed for >= 16 bpp // *ColorCount = (BitmapInfoHeader->biBitCount <= 8) ? (1 << BitmapInfoHeader->biBitCount) : 0; if(*ColorCount) { LogicalPalette = MemAlloc(sizeof(LOGPALETTE) + (sizeof(PALETTEENTRY) * (*ColorCount))); if(!LogicalPalette) { SetLastError(ERROR_NOT_ENOUGH_MEMORY); return(NULL); } LogicalPalette->palVersion = 0x300; LogicalPalette->palNumEntries = *ColorCount; for(i=0; i<*ColorCount; i++) { LogicalPalette->palPalEntry[i].peRed = BitmapInfo->bmiColors[i].rgbRed; LogicalPalette->palPalEntry[i].peGreen = BitmapInfo->bmiColors[i].rgbGreen; LogicalPalette->palPalEntry[i].peBlue = BitmapInfo->bmiColors[i].rgbBlue; LogicalPalette->palPalEntry[i].peFlags = 0; } Palette = CreatePalette(LogicalPalette); d = GetLastError(); MemFree(LogicalPalette); SetLastError(d); } else { Palette = NULL; } return(Palette); } BOOL GetBitmapDataAndPalette( IN HINSTANCE hInst, IN LPCTSTR Id, OUT HPALETTE *Palette, OUT PUINT ColorCount, OUT CONST BITMAPINFOHEADER **BitmapData ) /*++ Routine Description: Retreives device-independent bitmap data and a color table from a bitmap in a resource. Arguments: hInst - supplies instance handle for module containing the bitmap resource. Id - supplies the id of the bitmap resource. Palette - if successful, receives a handle to a palette for the bitmap. ColorCount - if successful, receives the number of entries in the palette for the bitmap. BitmapData - if successful, receives a pointer to the bitmap info header structure in the resources. This is in read-only memory so the caller should not try to modify it. Return Value: If successful, handle to the loaded bitmap (DIB). If not, NULL is returned. Check GetLastError(). --*/ { HRSRC BlockHandle; HGLOBAL MemoryHandle; // // None of FindResource(), LoadResource(), or LockResource() // need to have cleanup routines called in Win32. // BlockHandle = FindResource(hInst,Id,RT_BITMAP); if(!BlockHandle) { return(FALSE); } MemoryHandle = LoadResource(hInst,BlockHandle); if(!MemoryHandle) { return(FALSE); } *BitmapData = LockResource(MemoryHandle); if(*BitmapData == NULL) { return(FALSE); } *Palette = CreateDIBPalette((LPBITMAPINFO)*BitmapData,ColorCount); return(TRUE); } DLGITEMTEMPLATE * FindControlInDialog( IN PVOID Template, IN UINT ControlId ) { PVOID p; DLGTEMPLATE *pTemplate; DLGTEMPLATE2 *pTemplate2; DLGITEMTEMPLATE *pItem; WORD ItemCount; DWORD Style; WORD i; p = Template; // // Skip fixed part of template // if(((DLGTEMPLATE2 *)p)->Signature == 0xffff) { pTemplate2 = p; ItemCount = pTemplate2->cDlgItems; Style = pTemplate2->Style; p = pTemplate2 + 1; } else { pTemplate = p; ItemCount = pTemplate->cdit; Style = pTemplate->style; p = pTemplate + 1; } // // Skip menu. First word=0 means no menu // First word=0xffff means one more word follows // Else it's a nul-terminated string // switch(*(WORD *)p) { case 0xffff: p = (WORD *)p + 2; break; case 0: p = (WORD *)p + 1; break; default: p = (PWCHAR)p + lstrlenW(p) + 1; break; } // // Skip class, similar to menu // switch(*(WORD *)p) { case 0xffff: p = (WORD *)p + 2; break; case 0: p = (WORD *)p + 1; break; default: p = (PWCHAR)p + lstrlenW(p) + 1; break; } // // Skip title // p = (PWCHAR)p + lstrlenW(p) + 1; if(Style & DS_SETFONT) { // // Skip point size and typeface name // p = (WORD *)p + 1; p = (PWCHAR)p + lstrlenW(p) + 1; } // // Now we have a pointer to the first item in the dialog // for(i=0; iid == (WORD)ControlId) { break; } // // Skip to next item in dialog. // First is class, which is either 0xffff plus one more word, // or a unicode string. After that is text/title. // p = pItem + 1; if(*(WORD *)p == 0xffff) { p = (WORD *)p + 2; } else { p = (PWCHAR)p + lstrlenW(p) + 1; } if(*(WORD *)p == 0xffff) { p = (WORD *)p + 2; } else { p = (PWCHAR)p + lstrlenW(p) + 1; } // // Skip creation data. // p = (PUCHAR)p + *(WORD *)p; p = (WORD *)p + 1; } if(i == ItemCount) { pItem = NULL; } return(pItem); } UINT GetYPositionOfDialogItem( IN LPCTSTR Dialog, IN UINT ControlId ) { HRSRC hRsrc; PVOID p; HGLOBAL hGlobal; DLGITEMTEMPLATE *pItem; UINT i; i = 0; if(hRsrc = FindResource(FaxWizModuleHandle,Dialog,RT_DIALOG)) { if(hGlobal = LoadResource(FaxWizModuleHandle,hRsrc)) { if(p = LockResource(hGlobal)) { if(pItem = FindControlInDialog(p,ControlId)) { i = pItem->y * HIWORD(GetDialogBaseUnits()) / 8; } UnlockResource(hGlobal); } FreeResource(hGlobal); } } return(i); } int CALLBACK WizardCallback( IN HWND hdlg, IN UINT code, IN LPARAM lParam ) { DLGTEMPLATE *DlgTemplate; // // Get rid of context sensitive help control on title bar // if(code == PSCB_PRECREATE) { DlgTemplate = (DLGTEMPLATE *)lParam; DlgTemplate->style &= ~DS_CONTEXTHELP; } return 0; } int CALLBACK Winnt32SheetCallback( IN HWND DialogHandle, IN UINT Message, IN LPARAM lParam ) { DLGTEMPLATE *DlgTemplate; HDC hdc; switch(Message) { case PSCB_PRECREATE: // // Make sure we get into the foreground. // DlgTemplate = (DLGTEMPLATE *)lParam; DlgTemplate->style &= ~DS_CONTEXTHELP; DlgTemplate->style |= DS_SETFOREGROUND; // // Get the height of the page header/watermark area. The first page // must have a separator control with a known ID. We use that as // the basis for the header area height. // WatermarkHeaderHeight = GetYPositionOfDialogItem( MAKEINTRESOURCE(IDD_WELCOME), IDC_HEADER_BOTTOM ); break; case PSCB_INITIALIZED: // // Load the watermark bitmap and override the dialog procedure for the wizard. // hdc = GetDC(NULL); GetBitmapDataAndPalette( FaxWizModuleHandle, (!hdc || (GetDeviceCaps(hdc,BITSPIXEL) < 8)) ? MAKEINTRESOURCE(IDB_WATERMARK16) : MAKEINTRESOURCE(IDB_WATERMARK256), &WatermarkPalette, &WatermarkPaletteColorCount, &WatermarkBitmapInfoHeader ); if(hdc) { ReleaseDC(NULL,hdc); } //OldWizardProc = (WNDPROC)SetWindowLong(DialogHandle,DWL_DLGPROC,(LONG)WizardDlgProc); break; } return(0); } LPHPROPSHEETPAGE CreateWizardPages( HINSTANCE hInstance, PWIZPAGE SetupWizardPages, LPDWORD RequestedPages, LPDWORD PageCount ) { LPHPROPSHEETPAGE WizardPageHandles; LPDWORD PageList; DWORD PagesInSet; DWORD i; DWORD PageOrdinal; BOOL b; // // Determine which set of pages to use and how many there are in the set. // PageList = RequestedPages; PagesInSet = 0; while( PageList[PagesInSet] != (DWORD)-1) { PagesInSet += 1; } // // allocate the page handle array // WizardPageHandles = (HPROPSHEETPAGE*) MemAlloc( sizeof(HPROPSHEETPAGE) * PagesInSet ); if (!WizardPageHandles) { return NULL; } // // Create each page. // b = TRUE; *PageCount = 0; for(i=0; b && (i