686 lines
15 KiB
C
686 lines
15 KiB
C
/*++
|
|
|
|
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 <pshpack2.h>
|
|
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 <poppack.h>
|
|
|
|
//
|
|
// 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; i<ItemCount; i++) {
|
|
|
|
//
|
|
// Align to next DWORD boundary
|
|
//
|
|
p = (PVOID)(((DWORD)p + sizeof(DWORD) - 1) & (~(sizeof(DWORD) - 1)));
|
|
pItem = p;
|
|
|
|
if(pItem->id == (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<PagesInSet); i++) {
|
|
|
|
PageOrdinal = PageList[i];
|
|
|
|
SetupWizardPages[PageOrdinal].Page.hInstance = hInstance;
|
|
SetupWizardPages[PageOrdinal].Page.dwFlags |= PSP_USETITLE;
|
|
SetupWizardPages[PageOrdinal].Page.lParam = (LPARAM) &SetupWizardPages[PageOrdinal];
|
|
SetupWizardPages[PageOrdinal].Page.dwSize = sizeof(PROPSHEETPAGE);
|
|
|
|
if (PointPrintSetup) {
|
|
SetupWizardPages[PageOrdinal].Page.pszTitle = GetString( IDS_TITLE_PP );
|
|
}
|
|
|
|
WizardPageHandles[*PageCount] = CreatePropertySheetPage(
|
|
&SetupWizardPages[PageOrdinal].Page
|
|
);
|
|
|
|
if(WizardPageHandles[*PageCount]) {
|
|
(*PageCount)++;
|
|
} else {
|
|
b = FALSE;
|
|
}
|
|
|
|
}
|
|
|
|
if (!b) {
|
|
MemFree( WizardPageHandles );
|
|
return NULL;
|
|
}
|
|
|
|
return WizardPageHandles;
|
|
}
|