Windows NT 4.0 source code leak
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.
 
 
 
 
 
 

3128 lines
84 KiB

/** FILE: font2.c ********** Module Header ********************************
*
* Control panel applet for Font configuration. This file holds code for
* the items concerning fonts.
*
* History:
* 12:30 on Tues 23 Apr 1991 -by- Steve Cathcart [stevecat]
* Took base code from Win 3.1 source
* 10:30 on Tues 04 Feb 1992 -by- Steve Cathcart [stevecat]
* Updated code to latest Win 3.1 sources
* 04 April 1994 -by- Steve Cathcart [stevecat]
* Added support for PostScript Type 1 fonts
*
* Copyright (C) 1990-1994 Microsoft Corporation
*
*************************************************************************/
//==========================================================================
// Include files
//==========================================================================
// C Runtime
#include <stddef.h>
#include <stdlib.h>
#include <string.h>
// Application specific
#include "main.h"
#undef IN
#include "t1instal.h"
#undef COLOR
#define CONST const
//typedef WCHAR *PWCHAR;
// Windows SDK - private
#include <wingdip.h> // For private GDI entry point: GetFontResourceInfo()
//==========================================================================
// Local Definitions
//==========================================================================
#define GWL_PROGRESS 0
#define SET_PROGRESS WM_USER
// Progress Control color indices
#define PROGRESSCOLOR_FACE 0
#define PROGRESSCOLOR_ARROW 1
#define PROGRESSCOLOR_SHADOW 2
#define PROGRESSCOLOR_HIGHLIGHT 3
#define PROGRESSCOLOR_FRAME 4
#define PROGRESSCOLOR_WINDOW 5
#define CCOLORS 6
#define CHAR_BACKSLASH TEXT('\\')
#define CHAR_COLON TEXT(':')
#define CHAR_NULL TEXT('\0')
#define CHAR_TRUE TEXT('T')
#define CHAR_FALSE TEXT('F')
//==========================================================================
// External Declarations
//==========================================================================
extern TCHAR szTTF[];
extern TCHAR szFON[];
extern TCHAR szPFM[];
extern TCHAR szPFB[];
extern TCHAR szPostScript[];
extern HWND hLBoxInstalled;
//==========================================================================
// Local Data Declarations
//==========================================================================
BOOL bYesAll_PS = FALSE; // Use global state for all PS fonts
BOOL bConvertPS = TRUE; // Convert Type1 files to TT
BOOL bInstallPS = TRUE; // Install PS files
BOOL bCopyPS = TRUE; // Copy PS files to Windows dir
BOOL bCancelInstall = FALSE; // Global installation cancel
TCHAR szTrue[] = TEXT("T");
TCHAR szFalse[] = TEXT("F");
TCHAR szHash[] = TEXT("#");
BOOL bProgMsgDisplayed; // Used by Progress to avoid msg flicker
BOOL bProg2MsgDisplayed; // Used by Progress2 to avoid msg flicker
HWND hDlgProgress = NULL;
//
// Used to determine Foreground/Backgnd colors for progress bar control
// Global values are set at RegisterClass time
//
DWORD rgbFG;
DWORD rgbBG;
// Registry location for installing PostScript printer font info
TCHAR szType1Key[] = TEXT("SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Type 1 Installer\\Type 1 Fonts");
//Array of default colors, matching the order of PROGRESSCOLOR_* values.
DWORD rgColorPro[CCOLORS]={
COLOR_BTNFACE, // PROGRESSCOLOR_FACE
COLOR_BTNTEXT, // PROGRESSCOLOR_ARROW
COLOR_BTNSHADOW, // PROGRESSCOLOR_SHADOW
COLOR_BTNHIGHLIGHT, // PROGRESSCOLOR_HIGHLIGHT
COLOR_WINDOWFRAME, // PROGRESSCOLOR_FRAME
COLOR_WINDOW // PROGRESSCOLOR_WINDOW
};
typedef struct _T1_INSTALL_OPTIONS
{
BOOL bMatchingTT;
BOOL bOnlyPSInstalled;
int iFontType;
LPTSTR szDesc;
} T1_INSTALL_OPTIONS, *PT1_INSTALL_OPTIONS;
//
// Linked-list structure used for copyright Vendors
//
typedef struct _psvendor
{
struct _psvendor *pNext;
LPTSTR pszCopyright; // Copyright string
int iResponse; // User's response to YES/NO MsgBox
} PSVENDOR;
PSVENDOR *pFirstVendor = NULL; // ptr to linked list for PS vendors
//==========================================================================
// Local Function Prototypes
//==========================================================================
BOOL CheckT1Install (LPTSTR pszDesc, LPTSTR pszData);
BOOL CheckTTInstall (LPTSTR szDesc);
void Draw3DRect (HDC hDC, HBRUSH hBrushFace, HPEN hPenFrame, HPEN hPenHigh,
HPEN hPenShadow, int x1, int y1, int x2, int y2);
BOOL APIENTRY InstallPSDlg (HWND hDlg, UINT nMsg, DWORD wParam, LONG lParam);
void Progress (short PercentDone, void* UniqueValue);
LRESULT APIENTRY ProgressBarCtlProc(HWND hTest, UINT message, WPARAM wParam, LONG lParam);
BOOL APIENTRY ProgressDlg (HWND hDlg, UINT nMsg, DWORD wParam, LONG lParam);
LONG ProgressPaint (HWND hWnd, DWORD dwProgress);
BOOL WriteType1RegistryEntry (HWND hDlg, LPTSTR szDesc, LPTSTR szPfmName, LPTSTR szPfbName);
//==========================================================================
// Functions
//==========================================================================
/////////////////////////////////////////////////////////////////////////////
//
// InspectFontFile
//
// This routine is called to set up all fonts from the FON file passed.
// The handle returned is a handle to global memory containing LOGFONT
// structures, the number of structures contained is returned in the
// integer pointed to by the second parameter.
//
// in:
// szFontFile font file name
// out:
// pNumFonts
//
// NOTE: there must be matching pairs of InspectFontFile () and
// PassedInspection () on each font so module counts don't
// get out of sync.
//
/////////////////////////////////////////////////////////////////////////////
HANDLE InspectFontFile (LPTSTR szFontFile, int *pNumFonts)
{
HANDLE hlpLOGFONT;
int nFonts;
DWORD dwBufSize;
LPTSTR lpFontBuffer;
BOOL bStatus;
nFonts = 0;
if (MyOpenFile (szFontFile, NULL, OF_EXIST) != INVALID_HANDLE_VALUE)
{
if (nFonts = AddFontResource (szFontFile))
{
dwBufSize = (DWORD) (nFonts * sizeof (LOGFONT));
if (hlpLOGFONT = GlobalAlloc (GMEM_MOVEABLE, dwBufSize))
{
lpFontBuffer = GlobalLock(hlpLOGFONT);
bStatus = GetFontResourceInfoW (szFontFile,
&dwBufSize,
lpFontBuffer,
GFRI_LOGFONTS);
GlobalUnlock(hlpLOGFONT);
if (bStatus == 0)
{
GlobalFree (hlpLOGFONT);
nFonts = 0;
// DbgPrint ("CPanel.Fonts::InspectFontFile - GetFontResourceInfo(LOGFONTS) failed!\n");
}
}
}
}
return ((*pNumFonts = nFonts) ? hlpLOGFONT : 0);
}
/////////////////////////////////////////////////////////////////////////////
//
// PassedInspection
//
// This function takes a handle to memory containing the information
// obtained through a call to InspectFontFile, as well as the filename
// where the information was retrieved. If the handle is null,
// InspectFontFile did not increase the reference count and as such the
// count should not be decreased.
//
/////////////////////////////////////////////////////////////////////////////
HANDLE PassedInspection (HANDLE hLogicalFont, LPTSTR szFileName)
{
if (hLogicalFont)
{
GlobalFree (hLogicalFont);
RemoveFontResource (szFileName);
}
return (hLogicalFont);
}
/////////////////////////////////////////////////////////////////////////////
//
// AddBackslash
//
// Add a Backslash character to the end of a path, if necessary.
//
/////////////////////////////////////////////////////////////////////////////
void AddBackslash (LPTSTR pszFile)
{
LPTSTR psz;
if (*CharPrev(pszFile, psz = pszFile + lstrlen (pszFile)) != TEXT('\\'))
{
*psz = TEXT('\\');
*(psz+1) = TEXT('\0');
}
}
/////////////////////////////////////////////////////////////////////////////
//
// StripFilespec
//
// Remove the filespec portion from a path (including the backslash).
//
/////////////////////////////////////////////////////////////////////////////
VOID StripFilespec (LPTSTR lpszPath)
{
LPTSTR p;
p = lpszPath + lstrlen(lpszPath);
while ((*p != CHAR_BACKSLASH) && (*p != CHAR_COLON) && (p != lpszPath))
p--;
if (*p == CHAR_COLON)
p++;
//
// Don't strip backslash from root directory entry.
//
if (p != lpszPath) {
if ((*p == CHAR_BACKSLASH) && (*(p-1) == CHAR_COLON))
p++;
}
*p = CHAR_NULL;
}
/////////////////////////////////////////////////////////////////////////////
//
// StripPath
//
// Extract only the filespec portion from a path.
//
/////////////////////////////////////////////////////////////////////////////
VOID StripPath (LPTSTR lpszPath)
{
LPTSTR p;
p = lpszPath + lstrlen(lpszPath);
while ((*p != CHAR_BACKSLASH) && (*p != CHAR_COLON) && (p != lpszPath))
p--;
if (p != lpszPath)
p++;
if (p != lpszPath)
lstrcpy(lpszPath, p);
}
/////////////////////////////////////////////////////////////////////////////
//
// AddVendorCopyright
//
// Add a PostScript Vendor's Copyright and User response to "MAYBE" list.
// This linked-list is used to keep track of a user's prior response to
// message about converting this vendor's fonts to TrueType. If a vendor
// is not in the registry, we cannot automatically assume that the font
// can be converted. We must present the User with a message, asking them
// to get permission from the vendor before converting the font to TrueType.
//
// However, we do allow them to continue the installation and convert the
// font to TrueType by selecting the YES button on the Message box. This
// routine keeps track of each vendor and the User's response for that
// vendor. This way we do not continually ask them about the same vendor
// during installation of a large number of fonts.
//
// (Insert item into linked list)
//
//
/////////////////////////////////////////////////////////////////////////////
BOOL AddVendorCopyright (LPTSTR pszCopyright, int iResponse)
{
PSVENDOR *pVendor; // temp pointer to linked list
//
// Make the new PSVENDOR node and add it to the linked list.
//
if (pFirstVendor)
{
pVendor = (PSVENDOR *) AllocMem (sizeof(PSVENDOR));
if (pVendor)
{
pVendor->pNext = pFirstVendor;
pFirstVendor = pVendor;
}
else
return FALSE;
}
else // First time thru
{
pFirstVendor = (PSVENDOR *) AllocMem (sizeof(PSVENDOR));
if (pFirstVendor)
pFirstVendor->pNext = NULL;
else
return FALSE;
}
//
// Save User response and Copyright string
//
pFirstVendor->iResponse = iResponse;
pFirstVendor->pszCopyright = AllocStr (pszCopyright);
//
// Return success.
//
return TRUE;
}
/////////////////////////////////////////////////////////////////////////////
//
// CheckVendorCopyright
//
// Check if a Vendor Copyright is already in the "MAYBE" linked-list and
// and return User response if it is found.
//
// Returns:
// IDYES - User wants to convert typeface anyway
// IDNO - User does not want to convert typeface
// -1 - Entry not found
//
/////////////////////////////////////////////////////////////////////////////
int CheckVendorCopyright (LPTSTR pszCopyright)
{
PSVENDOR *pVendor; // temp pointer to linked list
//
// Traverse the list, testing each node for matching copyright string
//
pVendor = pFirstVendor;
while (pVendor)
{
if (!lstrcmpi (pVendor->pszCopyright, pszCopyright))
return (pVendor->iResponse);
pVendor = pVendor->pNext;
}
//
// "Did not find matching copyright" return
//
return (-1);
}
/////////////////////////////////////////////////////////////////////////////
//
// IsPSFont
//
// Check validity of font file passed in and get paths to .pfm/.pfb
// files, determine if it can be converted to TT.
//
// in:
// lpszPfm .pfm file name to validate
// out:
// lpszDesc on succes Font Name of Type1
// lpszPfm on succes the path to .pfm file
// lpszPfb on succes the path to .pfb file
// pbCreatedPFM on succes whether a PFM file was created or not
// lpiFontType set to a value based on Font type 1 == TT, 2 == Type1
//
// NOTE: Assumes that lpszPfm and lpszPfb are of size PATHMAX & lpszDesc is
// of size DESCMAX
//
// returns:
// TRUE success, FALSE failure
//
/////////////////////////////////////////////////////////////////////////////
BOOL IsPSFont (HWND hDlg, // if NULL, HWND_DESKTOP used
LPTSTR lpszKey,
LPTSTR lpszDesc, // Optional
LPTSTR lpszPfm, // Optional
LPTSTR lpszPfb, // Optional
BOOL *pbCreatedPFM, // Optional
int *lpiFontType)
{
BOOL bRet = FALSE;
TCHAR strbuf[PATHMAX];
TCHAR szCopyright[PATHMAX];
BOOL bPFM;
int iResponse;
HWND hwndParent;
//
// ANSI buffers for use with ANSI only API's
//
char *desc, Descbuf[PATHMAX];
char Keybuf[PATHMAX];
char *pfb, Pfbbuf[PATHMAX];
char *pfm, Pfmbuf[PATHMAX];
char Vendorbuf[PATHMAX];
DWORD iDesc, iPfb, iPfm;
if (!lpiFontType)
return bRet;
if (lpszDesc)
*lpszDesc = (TCHAR) 0;
desc = Descbuf;
iDesc = PATHMAX;
pfb = Pfbbuf;
iPfb = PATHMAX;
if (lpszPfm)
{
pfm = Pfmbuf;
iPfm = PATHMAX;
}
else
{
pfm = NULL;
iPfm = 0;
}
if (pbCreatedPFM)
*pbCreatedPFM = FALSE;
*lpiFontType = NOT_TT_OR_T1;
WideCharToMultiByte (CP_ACP, 0, lpszKey, -1, Keybuf, PATHMAX, NULL, NULL);
//
// The CheckType1A routine accepts either a .INF or .PFM file name as
// the Keybuf (i.e. Key file) input parameter. If the input is a .INF
// file, a .PFM file will be created in the SYSTEM directory if (and
// only if) the .PFM file name parameter is non-NULL. Otherwise, it
// will just check to see if a valid .INF, .AFM and .PFB file exist for
// the font.
//
// The bPFM BOOL value is an output parameter that tells me if the routine
// created a .PFM file from the .INF/.AFM file for this font. If the
// pfm input parameter is non-NULL, it will always receive the proper
// path for the .PFM file.
//
if (CheckType1A (Keybuf, iDesc, desc, iPfm, pfm, iPfb, pfb, &bPFM, szFontsDirA))
{
if (pbCreatedPFM)
*pbCreatedPFM = bPFM;
//
// Check convertability of this font from Type1 to TrueType.
//
// Returns: SUCCESS, FAILURE, MAYBE
//
switch (CheckCopyrightA (Pfbbuf, PATHMAX, Vendorbuf))
{
case FAILURE:
*lpiFontType = TYPE1_FONT_NC;
//
// Put up a message box stating that this Type1 font vendor
// does not allow us to Convert their fonts to TT. This will
// let the user know that it is not Microsoft's fault that the
// font is not converted to TT, but the vendor's fault.
//
// NOTE: This is only done if the User has NOT selected the
// YesToAll_PS install option. Otherwise it will be very
// annoying to see message repeated over and over.
//
// HACK: The lpszPfb arg is used in the conditional to determine
// when the message box should be displayed. If the
// IsPSFont routine is called from ValidFontFile routine,
// this arg will be NULL. If this routine is called from
// InstallPSFont routine it will be non-NULL. It is only
// during actual installation that we want the message
// displayed.
//
if (!bYesAll_PS && lpszPfb)
{
//
// Convert ANSI buffers to UNICODE for our use
//
MultiByteToWideChar (CP_ACP, MB_PRECOMPOSED, Vendorbuf, -1,
szCopyright, PATHMAX);
MultiByteToWideChar (CP_ACP, MB_PRECOMPOSED, Descbuf, -1,
strbuf, PATHMAX);
hwndParent = (hDlg == NULL) ? HWND_DESKTOP : hDlg;
MyMessageBox (hwndParent, MYFONT+14, INITS+1,
MB_OK | MB_ICONEXCLAMATION,
(LPTSTR) szCopyright,
(LPTSTR) strbuf);
}
break;
case SUCCESS:
*lpiFontType = TYPE1_FONT;
break;
case MAYBE:
//
// Check font copyright and ask for user response if necessary
//
//
// Convert ANSI buffers to UNICODE for our use
//
MultiByteToWideChar (CP_ACP, MB_PRECOMPOSED, Vendorbuf, -1, szCopyright, PATHMAX);
MultiByteToWideChar (CP_ACP, MB_PRECOMPOSED, Descbuf, -1, strbuf, PATHMAX);
switch (CheckVendorCopyright (szCopyright))
{
case IDYES:
*lpiFontType = TYPE1_FONT;
break;
case IDNO:
*lpiFontType = TYPE1_FONT_NC;
break;
case -1:
default:
*lpiFontType = TYPE1_FONT;
// HACK: The lpszPfb arg is used in the conditional to determine
// when the message box should be displayed. If the
// IsPSFont routine is called from ValidFontFile routine,
// this arg will be NULL. If this routine is called from
// InstallPSFont routine it will be non-NULL. It is only
// during actual installation that we want the message
// displayed.
//
if (lpszPfb)
{
hwndParent = (hDlg == NULL) ? HWND_DESKTOP : hDlg;
iResponse = MyMessageBox (hwndParent, MYFONT+41, INITS+1,
MB_YESNO | MB_ICONEXCLAMATION
| MB_DEFBUTTON2,
(LPTSTR) strbuf,
(LPTSTR) szCopyright);
AddVendorCopyright (szCopyright, iResponse);
*lpiFontType = (iResponse == IDYES) ? TYPE1_FONT : TYPE1_FONT_NC;
}
break;
}
break;
default:
//
// ERROR! from routine - assume worst case
//
*lpiFontType = TYPE1_FONT_NC;
break;
}
//
// Return Font description
//
if (lpszDesc)
{
// Convert Descbuf to UNICODE since IsType1 is ANSI
MultiByteToWideChar (CP_ACP, MB_PRECOMPOSED, Descbuf, -1, strbuf, PATHMAX);
wsprintf(lpszDesc, TEXT("%s (%s)"), strbuf, szPostScript);
}
//
// Return PFM file name
//
if (lpszPfm)
{
// Return PFM file name - convert to UNICODE since IsType1 is ANSI
MultiByteToWideChar (CP_ACP, MB_PRECOMPOSED, Pfmbuf, -1, lpszPfm, PATHMAX);
}
//
// Return PFB file name
//
if (lpszPfb)
{
// Return PFB file name - convert to UNICODE since IsType1 is ANSI
MultiByteToWideChar (CP_ACP, MB_PRECOMPOSED, Pfbbuf, -1, lpszPfb, PATHMAX);
}
bRet = TRUE;
}
return bRet;
}
/////////////////////////////////////////////////////////////////////////////
//
// InitPSInstall
//
// Initialize PostScript install routine global variables.
//
/////////////////////////////////////////////////////////////////////////////
void InitPSInstall ()
{
//
// Initialize linked list variables for "MAYBE" copyright vendor list
//
pFirstVendor = NULL;
//
// Other installation globals
//
bYesAll_PS = FALSE;
bConvertPS = TRUE;
bInstallPS = TRUE;
bCopyPS = TRUE;
return;
}
/////////////////////////////////////////////////////////////////////////////
//
// TermPSInstall
//
// Initialize PostScript install routine global variables.
//
/////////////////////////////////////////////////////////////////////////////
void TermPSInstall ()
{
PSVENDOR *pVendor;
//
// Traverse the list, freeing list memory and strings.
//
pVendor = pFirstVendor;
while (pVendor)
{
pFirstVendor = pVendor;
pVendor = pVendor->pNext;
if (pFirstVendor->pszCopyright)
FreeStr ((LPVOID) pFirstVendor->pszCopyright);
FreeMem ((LPVOID) pFirstVendor, sizeof(PSVENDOR));
}
//
// Reset global to be safe
//
pFirstVendor = NULL;
return;
}
/////////////////////////////////////////////////////////////////////////////
//
// InstallT1Font
//
// Install PostScript Type1 font, possibly converting the Type1 font to a
// TrueType font in the process. Write registry entries so the PostScript
// printer driver can find these files either in their original source
// directory or locally in the 'shared' or system directory.
//
/////////////////////////////////////////////////////////////////////////////
int InstallT1Font (HWND hDlg,
HWND hListFonts, // Installed fonts listbox
BOOL bCopyTTFile, // Copy TT file?
BOOL bInSharedDir, // Files in Shared Directory?
LPTSTR szKeyName, // IN: PFM/INF Source File name & dir
// OUT: Destination file name
LPTSTR szDesc) // INOUT: Font description
{
int iFontType; // Enumerated Font type
int rc, iRet;
WORD wMsg;
BOOL bCreatedPfm = FALSE;
TCHAR szTemp[PATHMAX];
TCHAR szTemp2[PATHMAX];
TCHAR szPfbName[PATHMAX];
TCHAR szPfmName[PATHMAX];
TCHAR szSrcDir[PATHMAX];
TCHAR szDstName[PATHMAX];
TCHAR szTTFName[PATHMAX];
TCHAR *pszArg1, *pszArg2;
T1_INSTALL_OPTIONS t1ops;
//
// ASCII Buffers for use in ASCII-only api calls
//
char pfb[PATHMAX];
char pfm[PATHMAX];
char ttf[PATHMAX];
if (!IsPSFont (hDlg, szKeyName, NULL, szPfmName, szPfbName,
&bCreatedPfm, &iFontType))
{
MyMessageBox (hDlg, ERRORS+1, INITS+1,
MB_OK | MB_ICONEXCLAMATION,
(LPTSTR) szDesc);
iRet = TYPE1_INSTALL_IDNO;
goto InstallPSFailure;
}
t1ops.szDesc = szDesc;
t1ops.iFontType = iFontType;
//
// Keep a copy of source directory
//
lstrcpy (szSrcDir, szKeyName);
StripFilespec (szSrcDir);
AddBackslash (szSrcDir);
//////////////////////////////////////////////////////////////////////
// Check if font is already loaded on the system
//////////////////////////////////////////////////////////////////////
t1ops.bOnlyPSInstalled = FALSE;
t1ops.bMatchingTT = FALSE;
//
// Check both Type1 & Fonts registry location for prior font installation
//
if (CheckT1Install (szDesc, NULL))
{
if (CheckTTInstall (szDesc))
{
//
// "Font is already loaded"
//
iRet = MyMessageBox (hDlg, MYFONT+21, INITS+1,
MB_OKCANCEL|MB_ICONEXCLAMATION,
(LPTSTR)szDesc);
goto InstallPSFailure;
}
else
t1ops.bOnlyPSInstalled = TRUE;
}
else if (CheckTTInstall (szDesc))
{
t1ops.bMatchingTT = TRUE;
if (!bYesAll_PS)
{
//
// "The TrueType version of this font is already installed."
//
switch (MyMessageBox(hDlg, MYFONT+17, INITS+1,
MB_YESNOCANCEL|MB_ICONEXCLAMATION, (LPTSTR)szDesc))
{
case IDYES:
break;
case IDNO:
iRet = TYPE1_INSTALL_IDNO;
goto InstallPSFailure;
case IDCANCEL:
default:
iRet = TYPE1_INSTALL_IDCANCEL;
goto InstallPSFailure;
}
}
}
//
// The global state of
//
// bConvertPS - Convert Type1 files to TT
// bInstallPS - Install PS files
//
// is only effective for the last time the "Install Type 1 fonts"
// dialog was displayed. Check the state of these globals against
// what we know about the current font to determine if the dialog
// should be redisplayed.
//
// 5/31/94 [stevecat] DO NOT redisplay the dialog after "YesToAll"
// selected once. Instead, display messages about 'exceptions' to
// their initial choices and give user the option to continue
// installation.
//
if (bYesAll_PS)
{
//
// If the PS version of this font is already installed AND the
// global bInstall == TRUE, then the globals are out-of-sync
// with this font. Let user know and continue installation.
//
if (t1ops.bOnlyPSInstalled && bInstallPS)
{
//
// "The Type 1 version of this font is already installed."
//
switch (MyMessageBox(hDlg, MYFONT+15, INITS+1,
MB_YESNOCANCEL|MB_ICONEXCLAMATION, (LPTSTR)szDesc))
{
case IDYES:
break;
case IDNO:
iRet = TYPE1_INSTALL_IDNO;
goto InstallPSFailure;
case IDCANCEL:
default:
iRet = TYPE1_INSTALL_IDCANCEL;
goto InstallPSFailure;
}
}
//
// If the matching TT font is already installed AND the global
// bConvertPS == TRUE, then the globals are out-of-sync with
// this font. Let the user know and continue installation.
//
if (t1ops.bMatchingTT && bConvertPS)
{
//
// "The TrueType version of this font is already installed."
//
switch (MyMessageBox(hDlg, MYFONT+17, INITS+1,
MB_YESNOCANCEL|MB_ICONEXCLAMATION, (LPTSTR)szDesc))
{
case IDYES:
break;
case IDNO:
iRet = TYPE1_INSTALL_IDNO;
goto InstallPSFailure;
case IDCANCEL:
default:
iRet = TYPE1_INSTALL_IDCANCEL;
goto InstallPSFailure;
}
}
}
//
// Get user options for PostScript font installation:
// - TT conversion
// - Type1 installation
// - Copying Type1 files
//
// State returned in globals:
//
// bConvertPS - Convert Type1 files to TT
// bInstallPS - Install PS files
// bCopyPS - Copy PS files to Windows\System dir
if (!bYesAll_PS)
{
HourGlass (FALSE);
switch (DoDialogBoxParam(DLG_INSTALL_PS, hDlg, (DLGPROC)InstallPSDlg,
IDH_DLG_INSTALL_PS, (LPARAM) &t1ops))
{
case IDNO:
//
// Note that we do not do HourGlass (TRUE), but that
// should be harmless, since we are either going to come
// right back here, or we are going to exit
//
return IDNO;
case IDD_YESALL:
bYesAll_PS = TRUE;
//
// Fall thru...
//
case IDYES:
//
// Give a warning here about installing from a non-local
// directory and not copying files, as necessary.
//
if (bInstallPS && !bCopyPS)
{
lstrcpy (szTemp, szPfbName);
StripFilespec (szTemp);
AddBackslash (szTemp);
switch (GetDriveType (szTemp))
{
case DRIVE_REMOTE:
case DRIVE_REMOVABLE:
case DRIVE_CDROM:
case DRIVE_RAMDISK:
if (MyMessageBox (hDlg, ERRORS+6, INITS+1,
MB_YESNO|MB_ICONEXCLAMATION) != IDYES)
{
iRet = TYPE1_INSTALL_IDCANCEL;
goto InstallPSFailure;
}
}
}
break;
default:
// CANCEL and NOMEM (user already warned)
iRet = TYPE1_INSTALL_IDCANCEL;
goto InstallPSFailure;
}
HourGlass (TRUE);
}
//
// szDstName should already have the full source file name
//
// Only convert the Type1 font to TT if:
//
// a) The user asked us to do it;
// b) The font can be converted, AND;
// c) There is not a matching TT font already installed
//
if (bConvertPS && (iFontType != TYPE1_FONT_NC) && !t1ops.bMatchingTT)
{
//////////////////////////////////////////////////////////////////
// Convert Type1 files to TrueType
//
// Copy converted TT file, if necessary, to "fonts" directory
//
// NOTE: We are using the ConvertTypeface api to do the copying
// and it is an ASCII only api.
//////////////////////////////////////////////////////////////////
//
// Create destination name with .ttf
//
lstrcpy (szTemp, szPfmName);
StripPath (szTemp);
ConvertExtension (szTemp, szTTF);
//
// Build destination file pathname based on bCopyTTFile
//
if (bCopyTTFile || bInSharedDir)
{
//
// Copy file to local directory
//
lstrcpy (szDstName, szSharedDir);
}
else
{
//
// Create converted file in source directory
//
lstrcpy (szDstName, szSrcDir);
}
//
// Check new filename for uniqueness
//
if (!(UniqueFilename (szTemp, szTemp, szDstName)))
{
iRet = MyMessageBox (hDlg, MYFONT+19, MYFONT+7,
MB_OKCANCEL | MB_ICONEXCLAMATION,
(LPTSTR)szDesc);
goto InstallPSFailure;
}
lstrcat (szDstName, szTemp);
//
// Save destination filename for return to caller
//
if (bCopyTTFile || bInSharedDir)
lstrcpy (szTTFName, szTemp);
else
lstrcpy (szTTFName, szDstName);
//
// We will convert and copy the Type1 font in the same api
//
WideCharToMultiByte (CP_ACP, 0, szPfbName, -1, pfb,
PATHMAX, NULL, NULL);
WideCharToMultiByte (CP_ACP, 0, szPfmName, -1, pfm,
PATHMAX, NULL, NULL);
WideCharToMultiByte (CP_ACP, 0, szDstName, -1, ttf,
PATHMAX, NULL, NULL);
ResetProgress ();
//
// Remove "PostScript" postfix string from description
//
RemoveDecoration (szDesc, TRUE);
if ((rc = (int) ConvertTypefaceA (pfb, pfm, ttf,
Progress,
(void *) szDesc)) < 0)
{
pszArg1 = szPfmName;
pszArg2 = szPfbName;
switch (rc)
{
case ARGSTACK:
case TTSTACK:
case NOMEM:
wMsg = ERRORS+11;
break;
case NOMETRICS:
case BADMETRICS:
case UNSUPPORTEDFORMAT:
//
// Something is wrong with the .pfm metrics file
//
pszArg1 = szDstName;
pszArg2 = szPfmName;
wMsg = MYFONT+43;
break;
case BADT1HYBRID:
case BADT1HEADER:
case BADCHARSTRING:
case NOCOPYRIGHT:
//
// Bad .pfb input file - format, or corruption
//
pszArg1 = szDstName;
pszArg2 = szPfbName;
wMsg = MYFONT+44;
break;
case BADINPUTFILE:
//
// Bad input file names, or formats or file errors
// or file read errors
//
pszArg1 = szDstName;
pszArg2 = szPfbName;
wMsg = MYFONT+45;
break;
case BADOUTPUTFILE:
//
// No diskspace for copy, read-only share, etc.
//
pszArg1 = szDstName;
wMsg = MYFONT+46;
break;
default:
//
// Cannot convert szDesc to TrueType - general failure
//
pszArg1 = szDstName;
pszArg2 = szDesc;
wMsg = MYFONT + 47;
break;
}
iRet = MyMessageBox (hDlg, wMsg, INITS+1,
MB_OKCANCEL | MB_ICONEXCLAMATION,
pszArg1, pszArg2, szPfmName);
goto InstallPSFailure;
}
//
// Change font description to have "TrueType" now
//
wsprintf(szDesc, TEXT("%s (%s)"), szDesc, szTrueType);
}
iRet = TYPE1_INSTALL_IDNO;
if (bInstallPS && !t1ops.bOnlyPSInstalled)
{
//
// Remove "PostScript" postfix string from description
//
lstrcpy (szTemp2, szDesc);
RemoveDecoration (szTemp2, TRUE);
//
// Now reset per font install progress
//
ResetProgress ();
Progress2 (0, szTemp2);
//
// Only copy the files if the User asked us to AND they are NOT
// already in the Shared directory.
//
if (bCopyPS && !bInSharedDir)
{
//
// Copy file progress
//
Progress2 (10, szTemp2);
/////////////////////////////////////////////////////////////////
// COPY files to "system" directory
/////////////////////////////////////////////////////////////////
//
// For .inf/.afm file install:: Check .pfm pathname to see if
// it is the same as the destination file pathname we built.
// Make this check before we test/create a UniqueFilename.
//
// Build Destination file pathname for .PFM file
lstrcpy (szTemp, szPfmName);
StripPath (szTemp);
lstrcpy (szDstName, szSharedDir);
lstrcat (szDstName, szTemp);
//
// Check to see if the .pfm file already exists in the "system"
// directory. If it does, then just copy the .pfb over.
//
if (!lstrcmpi (szPfmName, szDstName))
goto CopyPfbFile;
if (!(UniqueFilename (szTemp, szTemp, szSharedDir)))
{
iRet = MyMessageBox (hDlg, MYFONT+19, MYFONT+7,
MB_OKCANCEL | MB_ICONEXCLAMATION,
(LPTSTR)szDesc);
goto InstallPSFailure;
}
lstrcpy (szDstName, szSharedDir);
lstrcat (szDstName, szTemp);
if ((rc = Copy (hDlg, szPfmName, szDstName)) <= 0)
{
switch (rc)
{
// On these two return codes, the USER has effectively
// "Cancelled" the copy operation for the fonts
case COPY_CANCEL:
case COPY_DRIVEOPEN:
return IDCANCEL;
case COPY_SELF:
wMsg = ERRORS+10;
break;
case COPY_NOCREATE:
wMsg = ERRORS+13;
break;
case COPY_NODISKSPACE:
wMsg = ERRORS+12;
break;
case COPY_NOMEMORY:
wMsg = ERRORS+11;
break;
default:
wMsg = ERRORS+14;
break;
}
iRet = MyMessageBox (hDlg, wMsg, INITS+1,
MB_OKCANCEL | MB_ICONEXCLAMATION,
szDstName, szPfmName);
goto InstallPSFailure;
}
CopyPfbFile:
//
// Copying pfm file was small portion of install
//
Progress2 (30, szTemp2);
// Build Destination file pathname for .PFB file
lstrcpy (szTemp, szPfbName);
StripPath (szTemp);
if (!(UniqueFilename (szTemp, szTemp, szSharedDir)))
{
iRet = MyMessageBox (hDlg, MYFONT+19, MYFONT+7,
MB_OKCANCEL | MB_ICONEXCLAMATION,
(LPTSTR)szDesc);
goto InstallPSFailure;
}
lstrcpy (szDstName, szSharedDir);
lstrcat (szDstName, szTemp);
if ((rc = Copy (hDlg, szPfbName, szDstName)) <= 0)
{
switch (rc)
{
// On these two return codes, the USER has effectively
// "Cancelled" the copy operation for the fonts
case COPY_CANCEL:
case COPY_DRIVEOPEN:
return IDCANCEL;
case COPY_SELF:
wMsg = ERRORS+10;
break;
case COPY_NOCREATE:
wMsg = ERRORS+13;
break;
case COPY_NODISKSPACE:
wMsg = ERRORS+12;
break;
case COPY_NOMEMORY:
wMsg = ERRORS+11;
break;
default:
wMsg = ERRORS+14;
break;
}
iRet = MyMessageBox (hDlg, wMsg, INITS+1,
MB_OKCANCEL | MB_ICONEXCLAMATION,
szDstName, szPfbName);
goto InstallPSFailure;
}
}
//
// Copying pfb file was large portion of install
//
Progress2 (85, szTemp2);
//
// Write registry entry to "install" font for use by the
// PostScript driver, but only after successfully copying
// files (if copy was necessary).
//
iRet = WriteType1RegistryEntry (hDlg, szDesc, szPfmName, szPfbName);
//
// Final registry write completes install, except for listbox munging.
// Note that TrueType file install is handled separately.
//
Progress2 (100, szTemp2);
}
//
// Determine correct return code based on installation options and
// current installed state of font.
//
if (bConvertPS && (iFontType != TYPE1_FONT_NC))
{
//
// Handle the special case of when the matching TTF font is already
// installed.
//
if (t1ops.bMatchingTT)
goto Type1InstallCheck;
lstrcpy (szKeyName, szTTFName);
if (t1ops.bOnlyPSInstalled)
{
//
// There is already a Lbox entry for the PS version of this font
// that needs to be deleted because the TT installation will
// add a new Lbox entry.
//
iRet = TYPE1_INSTALL_TT_AND_MPS;
//
// Funnel all exits thru 1 point to check for Install Cancellation
//
goto MasterExit;
}
else if (bInstallPS)
{
iRet = (iRet == IDOK) ? TYPE1_INSTALL_TT_AND_PS : TYPE1_INSTALL_TT_ONLY;
//
// Funnel all exits thru 1 point to check for Install Cancellation
//
goto MasterExit;
}
else
{
iRet = TYPE1_INSTALL_TT_ONLY;
goto CheckPfmDeletion;
}
}
Type1InstallCheck:
if (bInstallPS)
{
if (iRet != IDOK)
{
iRet = TYPE1_INSTALL_IDNO;
goto InstallPSFailure;
}
iRet = TYPE1_INSTALL_IDNO;
if (t1ops.bMatchingTT)
{
//
// If we previously found the Matching TT font for this Type1
// font and installed the PostScript font in this session, set
// the font type for the Matching TT font to IF_TYPE1_TT.
//
// Also, do not add a new entry in listbox for the Type1 font.
//
// Find matching "xxxxx (TrueType)" entry and change its
// ItemData to IF_TYPE1_TT
//
// Change font description to have "(TrueType)" now
//
RemoveDecoration (szDesc, TRUE);
wsprintf (szDesc, TEXT("%s (%s)"), szDesc, szTrueType);
rc= SendMessage (hListFonts, LB_FINDSTRINGEXACT, (WPARAM) -1,
(LONG)szDesc);
if (rc != LB_ERR)
{
SendMessage (hListFonts, LB_SETITEMDATA, rc, (LONG) IF_TYPE1_TT);
SendMessage (hListFonts, LB_SETSEL, 1, rc);
UpdateWindow (hListFonts);
iRet = TYPE1_INSTALL_PS_AND_MTT;
}
}
else
{
rc = SendMessage (hListFonts, LB_ADDSTRING, 0, (LONG)(LPTSTR)szDesc);
//
// Attach font type to each listed font
//
if (rc != LB_ERR)
{
SendMessage (hListFonts, LB_SETITEMDATA, rc, IF_TYPE1);
SendMessage (hListFonts, LB_SETSEL, 1, rc);
UpdateWindow (hListFonts);
iRet = TYPE1_INSTALL_PS_ONLY;
}
}
}
if (!bInstallPS)
goto CheckPfmDeletion;
//
// Funnel all exits thru 1 point to check for Install Cancellation
//
goto MasterExit;
/////////////////////////////////////////////////////////////////////////
//
// Install failure exit AND Delete extraneously created PFM file
//
// NOTE: For the installation scenario where we based installation on
// the .INF/.AFM file and the Type1 font was NOT installed, we
// need to delete the .FPM file that was created by the
// CheckType1A routine in the IsPSFont routine.
//
/////////////////////////////////////////////////////////////////////////
InstallPSFailure:
CheckPfmDeletion:
if (bCreatedPfm)
DeleteFile (szPfmName);
MasterExit:
return (bCancelInstall ? IDCANCEL : iRet);
}
/////////////////////////////////////////////////////////////////////////////
//
// InstallPSDlg
//
// This dialog proc manages the Install PostScript font dialog which allows
// the user several options for the installation, including converting the
// file to a TrueType font.
//
// Globals munged:
//
// bConvertPS - Convert Type1 files to TT
// bInstallPS - Install PS files
// bCopyPS - Copy PS files to Windows dir
//
/////////////////////////////////////////////////////////////////////////////
BOOL APIENTRY InstallPSDlg (HWND hDlg, UINT nMsg, DWORD wParam, LONG lParam)
{
TCHAR szFormat[PATHMAX];
TCHAR szTemp[PATHMAX];
TCHAR szTemp2[PATHMAX];
int iButtonChecked;
int wMsg;
static HWND hwndActive = NULL;
T1_INSTALL_OPTIONS *pt1ops;
switch (nMsg)
{
case WM_INITDIALOG:
pt1ops = (PT1_INSTALL_OPTIONS) lParam;
//
// Remove all "PostScript" or "TrueType" postfix to font name
//
lstrcpy (szTemp2, (LPTSTR)pt1ops->szDesc);
RemoveDecoration (szTemp2, FALSE);
LoadString (hModule, MYFONT + 34, szFormat, CharSizeOf(szFormat));
wsprintf (szTemp, szFormat, szTemp2);
SetWindowLong (hDlg, DWL_USER, lParam);
SetDlgItemText (hDlg, FONT_INSTALLMSG, szTemp);
EnableWindow (hDlg, TRUE);
if (pt1ops->bOnlyPSInstalled && pt1ops->bMatchingTT)
{
//
// ERROR! Both of these options should not be set at
// this point. It means that the font is
// already installed. This should have been
// handled before calling this dialog.
//
wMsg = MYFONT+21;
InstallError:
MyMessageBox (hDlg,
wMsg,
INITS+1,
MB_OK | MB_ICONEXCLAMATION,
pt1ops->szDesc);
EndDialog (hDlg, IDNO);
break;
}
if ((pt1ops->iFontType == TYPE1_FONT_NC) && pt1ops->bOnlyPSInstalled)
{
//
// ERROR! This case is when I have detected only the PS
// version of font installed, and the font CANNOT
// be converted to TT for some reason.
//
wMsg = MYFONT+37;
goto InstallError;
}
/////////////////////////////////////////////////////////////////////
//
// Setup user options depending on install state of font and
// convertibility to TT of T1 font and on previous user choices.
//
/////////////////////////////////////////////////////////////////////
if ((pt1ops->iFontType == TYPE1_FONT) && (!pt1ops->bMatchingTT))
{
//
// This one can be converted
//
CheckDlgButton(hDlg, FONT_CONVERT_PS, bConvertPS);
}
else
{
//
// Do not allow conversion to TT because, either the font
// type is TYPE1_FONT_NC (i.e. it cannot be converted) OR
// the TT version of font is already installed.
//
CheckDlgButton(hDlg, FONT_CONVERT_PS, FALSE);
EnableWindow (GetDlgItem (hDlg, FONT_CONVERT_PS), FALSE);
}
if (pt1ops->bOnlyPSInstalled)
{
//
// If the PostScript version of this font is already
// installed, then we gray out the options to re-install
// the PostScript version of font, but continue to allow
// the User to convert it to TT.
//
CheckDlgButton(hDlg, FONT_INSTALL_PS, 0);
EnableWindow (GetDlgItem (hDlg, FONT_INSTALL_PS), FALSE);
CheckDlgButton(hDlg, FONT_COPY_PS, 0);
EnableWindow (GetDlgItem (hDlg, FONT_COPY_PS), FALSE);
}
else
{
//
// PostScript version of font is not installed. Set
// state of "INSTALL" and "COPY" checkboxes based on
// global state of "INSTALL"
//
CheckDlgButton(hDlg, FONT_INSTALL_PS, bInstallPS);
CheckDlgButton(hDlg, FONT_COPY_PS, bCopyPS);
EnableWindow (GetDlgItem (hDlg, FONT_COPY_PS), bInstallPS);
}
//
// Save the modeless dlg window handle for reactivation
//
hwndActive = GetActiveWindow ();
break;
case WM_COMMAND:
switch (LOWORD(wParam))
{
case FONT_INSTALL_PS:
if (HIWORD(wParam) != BN_CLICKED)
break;
//
// Get state of "INSTALL" checkbox
//
iButtonChecked = IsDlgButtonChecked (hDlg, LOWORD(wParam));
//
// A disabled checkbox is same as "No Install" selection
//
if (iButtonChecked != 1)
iButtonChecked = 0;
//
// Enable or disable "COPY" control based on state of
// "INSTALL" checkbox. Also, initialize it.
//
EnableWindow (GetDlgItem (hDlg, FONT_COPY_PS), iButtonChecked);
if (iButtonChecked)
CheckDlgButton(hDlg, FONT_COPY_PS, bCopyPS);
break;
case IDD_HELP:
goto DoHelp;
case IDYES:
case IDD_YESALL:
bConvertPS =
bInstallPS = FALSE;
if (IsDlgButtonChecked (hDlg, FONT_CONVERT_PS) == 1)
bConvertPS = TRUE;
if (IsDlgButtonChecked (hDlg, FONT_INSTALL_PS) == 1)
bInstallPS = TRUE;
//
// This is checked twice because it could be disabled,
// in which case we leave the previous state alone.
//
if (IsDlgButtonChecked (hDlg, FONT_COPY_PS) == 1)
bCopyPS = TRUE;
if (IsDlgButtonChecked (hDlg, FONT_COPY_PS) == 0)
bCopyPS = FALSE;
//
// Fall thru...
//
case IDNO:
case IDCANCEL:
//
// Reset the active window to "Install Font Progress" modeless dlg
//
if (hwndActive)
{
SetActiveWindow (hwndActive);
hwndActive = NULL;
}
EndDialog (hDlg, LOWORD(wParam));
break;
default:
return FALSE;
}
break;
default:
if (nMsg == wHelpMessage)
{
DoHelp:
CPHelp (hDlg);
return TRUE;
}
else
return FALSE;
}
return TRUE;
}
/////////////////////////////////////////////////////////////////////////////
//
// RemoveDecoration
//
// Deletes the "(TrueType)" or "(PostScript)" postfix string from the end
// of a font name. Optionally it will also remove the trailing space.
//
// NOTE: This function modifies the string passed into the function.
//
/////////////////////////////////////////////////////////////////////////////
void RemoveDecoration (LPTSTR pszDesc, BOOL bDeleteTrailingSpace)
{
LPTSTR lpch;
//
// Remove any postfix strings like "(PostScript)" or "(TrueType)"
//
if (lpch = _tcschr (pszDesc, TEXT('(')))
{
//
// End string at <space> before "("
//
if (bDeleteTrailingSpace)
lpch--;
*lpch = CHAR_NULL;
}
return ;
}
/////////////////////////////////////////////////////////////////////////////
//
// CheckT1Install
//
// Checks the Type1 fonts location in registry to see if this font is or
// has been previously installed as a "PostScript" font. Optionally, it
// will return the data for the "szDesc" value if it finds a matching entry.
//
// Assumes "szData" buffer is of least size T1_MAX_DATA.
//
/////////////////////////////////////////////////////////////////////////////
BOOL CheckT1Install (LPTSTR pszDesc, LPTSTR pszData)
{
TCHAR szTemp[PATHMAX];
DWORD dwSize;
DWORD dwType;
HKEY hkey;
BOOL bRet = FALSE;
hkey = NULL;
if (RegOpenKeyEx (HKEY_LOCAL_MACHINE, // Root key
szType1Key, // Subkey to open
0L, // Reserved
KEY_READ, // SAM
&hkey) // return handle
== ERROR_SUCCESS)
{
//
// Remove any postfix strings like "PostScript" or "TrueType"
//
lstrcpy (szTemp, pszDesc);
RemoveDecoration (szTemp, TRUE);
dwSize = pszData ? T1_MAX_DATA * sizeof(TCHAR) : 0;
if (RegQueryValueEx (hkey, szTemp, NULL, &dwType,
(LPBYTE) pszData, &dwSize)
== ERROR_SUCCESS)
{
bRet = (dwType == REG_MULTI_SZ);
}
else
{
bRet = FALSE;
}
RegCloseKey (hkey);
}
return bRet;
}
/////////////////////////////////////////////////////////////////////////////
//
// AddSystemPath
//
// Add "System" path to a naked file name, if no path currently exists
// on the filename. Assumes pszFile buffer is at least PATHMAX chars in
// length.
//
/////////////////////////////////////////////////////////////////////////////
void AddSystemPath (LPTSTR pszFile)
{
TCHAR szPath[PATHMAX];
//
// Add "system" path, if no path present on file
//
lstrcpy (szPath, pszFile);
StripFilespec (szPath);
if (szPath[0] == CHAR_NULL)
{
lstrcpy (szPath, szSharedDir);
AddBackslash (szPath);
lstrcat (szPath, pszFile);
lstrcpy (pszFile, szPath);
}
return ;
}
/////////////////////////////////////////////////////////////////////////////
//
// ExtractT1Files
//
// Extracts file names from a REG_MULTI_SZ (multi-string) array that is
// passed into this routine. The output strings are expected to be at
// least PATHMAX in size. A "" (NULL string) indicates that a filename
// string was not present. This should only happen for the PFB filename
// argument.
//
/////////////////////////////////////////////////////////////////////////////
BOOL ExtractT1Files (LPTSTR pszMulti, LPTSTR pszPfmFile, LPTSTR pszPfbFile)
{
LPTSTR pszPfm;
LPTSTR pszPfb;
if (!pszMulti)
return FALSE;
if ((pszMulti[0] != CHAR_TRUE) && (pszMulti[0] != CHAR_FALSE))
return FALSE;
//
// .Pfm file should always be present
//
pszPfm = pszMulti + lstrlen(pszMulti) + 1;
lstrcpy (pszPfmFile, pszPfm);
//
// Add "system" path, if no path present on files
//
AddSystemPath (pszPfmFile);
//
// Check to see if .pfb filename is present
//
if (pszMulti[0] == CHAR_TRUE)
{
pszPfb = pszPfm + lstrlen(pszPfm) + 1;
lstrcpy (pszPfbFile, pszPfb);
//
// Add "system" path, if no path present on files
//
AddSystemPath (pszPfbFile);
}
else
{
pszPfbFile[0] = CHAR_NULL;
}
return TRUE;
}
/////////////////////////////////////////////////////////////////////////////
//
// DeleteT1Install
//
// Deletes a Type1 entry from the registry and optionally the files pointed
// to in the data strings.
//
/////////////////////////////////////////////////////////////////////////////
BOOL DeleteT1Install (HWND hDlg, LPTSTR pszDesc, BOOL bDeleteFiles)
{
TCHAR szTemp[PATHMAX];
TCHAR szTemp2[T1_MAX_DATA];
TCHAR szPfmFile[PATHMAX];
TCHAR szPfbFile[PATHMAX];
TCHAR szPath[PATHMAX];
DWORD dwSize;
DWORD dwType;
HKEY hkey;
BOOL bRet = FALSE;
hkey = NULL;
if (RegOpenKeyEx (HKEY_LOCAL_MACHINE, // Root key
szType1Key, // Subkey to open
0L, // Reserved
(KEY_READ | KEY_WRITE), // SAM
&hkey) // return handle
== ERROR_SUCCESS)
{
//
// Remove any postfix strings like "PostScript" or "TrueType"
//
lstrcpy (szTemp, pszDesc);
RemoveDecoration (szTemp, TRUE);
if (bDeleteFiles)
{
dwSize = sizeof(szTemp2);
if (RegQueryValueEx (hkey, szTemp, NULL, &dwType,
(LPBYTE) szTemp2, &dwSize)
== ERROR_SUCCESS)
{
if (ExtractT1Files (szTemp2, szPfmFile, szPfbFile))
{
//
// Delete the files
//
if (DelSharedFile (hDlg, szTemp, szPfbFile, szPath, TRUE))
DelSharedFile (hDlg, szTemp, szPfmFile, szPath, FALSE);
}
else
{
// ERROR! Cannot get file names from string
goto RemoveT1Error;
}
}
else
{
RemoveT1Error:
MyMessageBox (hDlg, MYFONT+4, INITS+1,
MB_ICONEXCLAMATION|MB_OKCANCEL, szTemp);
bRet = FALSE;
}
}
if (RegDeleteValue (hkey, szTemp) != ERROR_SUCCESS)
{
//
// ERROR! Put up message box
//
MyMessageBox (hDlg, MYFONT+4, INITS+1,
MB_ICONEXCLAMATION|MB_OKCANCEL, szTemp);
bRet = FALSE;
}
else
{
bRet = TRUE;
}
RegCloseKey (hkey);
}
return bRet;
}
/////////////////////////////////////////////////////////////////////////////
//
// GetT1Install
//
// Gets a Type1 entry information from the registry into the files pointed
// to in the data strings.
//
/////////////////////////////////////////////////////////////////////////////
BOOL GetT1Install (HWND hDlg, LPTSTR pszDesc, LPTSTR pszPfmFile, LPTSTR pszPfbFile)
{
TCHAR szTemp2[T1_MAX_DATA];
BOOL bRet = FALSE;
if (CheckT1Install (pszDesc, szTemp2))
{
bRet = ExtractT1Files (szTemp2, pszPfmFile, pszPfbFile);
}
return bRet;
}
/////////////////////////////////////////////////////////////////////////////
//
// CheckTTInstall
//
// Check FONTS location in registry to see if this font has already
// been installed.
//
/////////////////////////////////////////////////////////////////////////////
BOOL CheckTTInstall (LPTSTR szDesc)
{
TCHAR szTemp[PATHMAX];
TCHAR szTemp2[PATHMAX];
//
// Change description string to have TrueType instead of
// PostScript and then check if it is already installed.
//
lstrcpy (szTemp, szDesc);
RemoveDecoration (szTemp, FALSE);
wsprintf(szTemp, TEXT("%s(%s)"), szTemp, szTrueType);
if (GetProfileString(szFonts, szTemp, szNull, szTemp2, CharSizeOf(szTemp2)))
return TRUE;
return FALSE;
}
/////////////////////////////////////////////////////////////////////////////
//
// WriteType1RegistryEntry
//
// Create registry entry for this PostScript font by writing the path of
// both the .PFM and .PFB files.
//
// NOTE: Checks global "bCopyPS" to determine if files have been copied
// to the local shared directory. In that case, the path info is
// stripped from the file names passed into routine.
//
/////////////////////////////////////////////////////////////////////////////
int WriteType1RegistryEntry (HWND hDlg,
LPTSTR szDesc, // Font name description
LPTSTR szPfmName, // .PFM filename
LPTSTR szPfbName) // .PFB filename
{
TCHAR szTemp[2*PATHMAX+6];
TCHAR szTemp2[PATHMAX];
TCHAR szClass[PATHMAX];
DWORD dwSize;
DWORD dwDisposition;
HKEY hkey = NULL;
//
// Must have a Font description to store information in registry
//
if (!szDesc || !szPfmName)
return TYPE1_INSTALL_IDNO;
//
// Try to create the key if it does not exist or open existing key.
//
if (RegCreateKeyEx (HKEY_LOCAL_MACHINE, // Root key
szType1Key, // Subkey to open/create
0L, // Reserved
szClass, // Class string
0L, // Options
KEY_WRITE, // SAM
NULL, // ptr to Security struct
&hkey, // return handle
&dwDisposition) // return disposition
== ERROR_SUCCESS)
{
//
// Create REG_MULTI_SZ string to save in registry
//
// X <null> [path]zzzz.pfm <null> [path]xxxxx.pfb <null><null>
//
// Where X == T(rue) if .pfb file present
//
lstrcpy (szTemp, szPfbName ? szTrue : szFalse);
lstrcat (szTemp, szHash);
if (bCopyPS)
StripPath (szPfmName);
lstrcat (szTemp, szPfmName);
lstrcat (szTemp, szHash);
if (szPfbName)
{
if (bCopyPS)
StripPath (szPfbName);
lstrcat (szTemp, szPfbName);
lstrcat (szTemp, szHash);
}
lstrcat (szTemp, szHash);
dwSize = ByteCountOf(lstrlen(szTemp));
//
// Now convert string to multi-string
//
FixupNulls (szTemp);
//
// Create Registry Value name to store info under by
// removing any postfix strings like "PostScript" or
// "TrueType" from Font description string.
//
lstrcpy (szTemp2, szDesc);
RemoveDecoration (szTemp2, TRUE);
if (RegSetValueEx (hkey, szTemp2, 0L, REG_MULTI_SZ,
(LPBYTE) szTemp, dwSize)
!= ERROR_SUCCESS)
{
goto WriteRegError;
}
RegCloseKey (hkey);
}
else
{
WriteRegError:
//
// Put up a message box error stating that the USER does
// not have the permission necessary to install type1
// fonts.
//
if (hkey)
RegCloseKey (hkey);
return (MyMessageBox (hDlg, MYFONT+38, INITS+1,
MB_OKCANCEL | MB_ICONEXCLAMATION,
(LPTSTR)szDesc,
(LPTSTR)szType1Key));
}
return TYPE1_INSTALL_IDOK;
}
/////////////////////////////////////////////////////////////////////////////
//
// EnumType1Fonts
//
// List all of the Type 1 fonts installed in the registry, check for
// TrueType installation and put Postscript-only installed fonts in
// the "Installed Fonts" list box.
//
// This routine assumes that the TrueType descriptions are already
// displayed in the "Installed Fonts" listbox.
//
/////////////////////////////////////////////////////////////////////////////
BOOL EnumType1Fonts (HWND hLBox)
{
int i, j;
DWORD dwSize;
DWORD dwPathMax;
DWORD dwType;
HKEY hkey;
LPTSTR pszDesc;
LPTSTR pszFontName;
BOOL bRet = FALSE;
//////////////////////////////////////////////////////////////////////
// Get some storage
//////////////////////////////////////////////////////////////////////
pszFontName =
pszDesc = NULL;
dwPathMax = PATHMAX * sizeof(TCHAR);
pszFontName = (LPTSTR) AllocMem (dwPathMax);
pszDesc = (LPTSTR) AllocMem (dwPathMax);
if (!pszDesc || !pszFontName)
goto EnumType1Exit;
//////////////////////////////////////////////////////////////////////
// Get list of installed Type 1 fonts
//////////////////////////////////////////////////////////////////////
hkey = NULL;
if (RegOpenKeyEx (HKEY_LOCAL_MACHINE, // Root key
szType1Key, // Subkey to open
0L, // Reserved
KEY_READ, // SAM
&hkey) // return handle
== ERROR_SUCCESS)
{
dwSize = dwPathMax;
i = 0;
while (RegEnumValue (hkey, i++, pszFontName, &dwSize, NULL,
&dwType, (LPBYTE) NULL, NULL)
== ERROR_SUCCESS)
{
if (dwType != REG_MULTI_SZ)
continue;
wsprintf(pszDesc, TEXT("%s (%s)"), pszFontName, szPostScript);
//
// Check to see if TrueType version is already installed
//
if (CheckTTInstall (pszDesc))
{
//
// Find matching "xxxxx (TrueType)" entry and change its
// ItemData to IF_TYPE1_TT
//
wsprintf(pszDesc, TEXT("%s (%s)"), pszFontName, szTrueType);
j = SendMessage (hLBox, LB_FINDSTRINGEXACT, (WPARAM) -1,
(LONG)pszDesc);
if (j != LB_ERR)
SendMessage (hLBox, LB_SETITEMDATA, j, (LONG) IF_TYPE1_TT);
// else
// ERROR! We should have found a matching LB entry for this
// font based on TT name.
}
else
{
//
// Put Font name string in ListBox
//
j = SendMessage (hLBox, LB_ADDSTRING, 0, (LONG)pszDesc);
if (j != LB_ERR)
SendMessage (hLBox, LB_SETITEMDATA, j, (LONG) IF_TYPE1);
// else
// ERROR! We found an installed Type1 font but cannot show
// it in listbox because of USER error.
}
dwSize = dwPathMax;
}
bRet = TRUE;
RegCloseKey (hkey);
}
EnumType1Exit:
if (pszDesc)
FreeMem (pszDesc, dwPathMax);
if (pszFontName)
FreeMem (pszFontName, dwPathMax);
return bRet;
}
/////////////////////////////////////////////////////////////////////////////
//
// InitProgress
//
// Create and initialize the Progress dialog. Initial state is visible.
//
/////////////////////////////////////////////////////////////////////////////
BOOL InitProgress (HWND hwnd)
{
if (hDlgProgress)
return TRUE;
hDlgProgress = CreateDialog (hModule, MAKEINTRESOURCE(DLG_PROGRESS),
hwnd, (DLGPROC)ProgressDlg);
return (hDlgProgress != NULL);
}
/////////////////////////////////////////////////////////////////////////////
//
// TermProgress
//
// Remove and cleanup after the Progress dialog.
//
/////////////////////////////////////////////////////////////////////////////
void TermProgress ()
{
if (hDlgProgress)
DestroyWindow (hDlgProgress);
hDlgProgress = NULL;
return;
}
/////////////////////////////////////////////////////////////////////////////
//
// cpProgressYield
//
// Allow other messages including Dialog messages for Modeless dialog to be
// processed while we are converting Type1 files to TrueType.
//
// Since the font conversion is done on a single thread (in order to keep it
// synchronous with installation of all fonts) we need to provide a mechanism
// that will allow a user to Cancel out of the operation and also allow
// window messages, like WM_PAINT, to be processed by other Window Procedures.
//
/////////////////////////////////////////////////////////////////////////////
VOID cpProgressYield()
{
MSG msg;
while (PeekMessage (&msg, NULL, 0, 0, PM_REMOVE))
{
// if (!hDlgProgress || !IsDialogMessage (hDlgProgress, &msg))
if (!IsDialogMessage (hDlgProgress, &msg))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
}
/////////////////////////////////////////////////////////////////////////////
//
// UpdateProgress
//
// Set the overall progress control in Progress Dialog, along with a
// message describing installation progress.
//
/////////////////////////////////////////////////////////////////////////////
void UpdateProgress (int iTotalCount, int iFontInstalling, int iProgress)
{
TCHAR szTemp[120];
wsprintf (szTemp, szGenErr, iFontInstalling, iTotalCount);
SetDlgItemText (hDlgProgress, ID_INSTALLMSG, szTemp);
SendDlgItemMessage (hDlgProgress, ID_OVERALL, SET_PROGRESS,
(int) iProgress, 0L);
//
// Process outstanding messages
//
cpProgressYield();
}
/////////////////////////////////////////////////////////////////////////////
//
// ResetProgress
//
// Clear the progress bar control and reset message to NULL
//
/////////////////////////////////////////////////////////////////////////////
void ResetProgress ()
{
SetDlgItemText (hDlgProgress, ID_PROGRESSMSG, szNull);
SendDlgItemMessage(hDlgProgress, ID_BAR, SET_PROGRESS, (int) 0, 0L);
bProgMsgDisplayed = FALSE;
bProg2MsgDisplayed = FALSE;
//
// Process outstanding messages
//
cpProgressYield();
}
/////////////////////////////////////////////////////////////////////////////
//
// Progress
//
// Progress function for ConvertTypefaceA - Adobe Type1 to TrueType font
// file converter. Put up progress in converting font and message
// describing font being converted.
//
/////////////////////////////////////////////////////////////////////////////
void Progress (short PercentDone, void* UniqueValue)
{
TCHAR szTemp[120];
TCHAR szTemp2[120];
DWORD err = GetLastError(); // save whatever t1instal may have set
//
// UniqueValue is a pointer to the string name of the file being
// converted. Only put this message up if not previously displayed.
//
if (!bProgMsgDisplayed)
{
LoadString (hModule, MYFONT + 32, szTemp2, CharSizeOf(szTemp2));
wsprintf (szTemp, szTemp2, (LPTSTR) UniqueValue);
SetDlgItemText (hDlgProgress, ID_PROGRESSMSG, szTemp);
bProgMsgDisplayed = TRUE;
}
SendDlgItemMessage (hDlgProgress, ID_BAR, SET_PROGRESS,
(int) PercentDone, 0L);
//
// Process outstanding messages
//
cpProgressYield();
//
// reset last error to whatever t1instal set it to:
//
SetLastError(err);
}
/////////////////////////////////////////////////////////////////////////////
//
// Progress2
//
// Progress function for updating progress dialog controls on a per font
// install basis.
//
/////////////////////////////////////////////////////////////////////////////
void Progress2 (int PercentDone, LPTSTR pszDesc)
{
TCHAR szTemp[PATHMAX];
TCHAR szTemp2[240];
//
// szDesc is a pointer to the string name of the file being installed.
// Only put this message up if not previously displayed.
if (!bProg2MsgDisplayed)
{
LoadString (hModule, MYFONT + 40, szTemp2, CharSizeOf(szTemp2));
wsprintf (szTemp, szTemp2, pszDesc);
SetDlgItemText (hDlgProgress, ID_PROGRESSMSG, szTemp);
bProg2MsgDisplayed = TRUE;
}
SendDlgItemMessage (hDlgProgress, ID_BAR, SET_PROGRESS, (int) PercentDone, 0L);
//
// Process outstanding messages
//
cpProgressYield();
}
/////////////////////////////////////////////////////////////////////////////
//
// ProgressDlg
//
// Display progress messages to user based on progress in converting
// font files to TrueType
//
/////////////////////////////////////////////////////////////////////////////
BOOL APIENTRY ProgressDlg (HWND hDlg, UINT nMsg, DWORD wParam, LONG lParam)
{
switch (nMsg)
{
case WM_INITDIALOG:
CentreWindow (hDlg);
//
// Load in Progress messages
//
LoadString (hModule, MYFONT + 39, szGenErr, CharSizeOf(szGenErr));
EnableWindow (hDlg, TRUE);
break;
case WM_COMMAND:
switch (LOWORD(wParam))
{
case IDOK:
case IDCANCEL:
bCancelInstall = (LOWORD(wParam) == IDCANCEL);
EndDialog (hDlg, LOWORD(wParam));
break;
default:
return FALSE;
}
break;
default:
return FALSE;
}
return TRUE;
}
/////////////////////////////////////////////////////////////////////////////
//
// ProgressBarCtlProc
//
// Window Procedure for the Progress Bar custom control. Handles all
// messages like WM_PAINT just as a normal application window would.
//
/////////////////////////////////////////////////////////////////////////////
LRESULT APIENTRY ProgressBarCtlProc(HWND hWnd, UINT message, WPARAM wParam, LONG lParam)
{
DWORD dwProgress;
dwProgress = (DWORD) GetWindowLong (hWnd, GWL_PROGRESS);
switch (message)
{
case WM_CREATE:
dwProgress = 0;
SetWindowLong (hWnd, GWL_PROGRESS, (LONG) dwProgress);
break;
case SET_PROGRESS:
SetWindowLong (hWnd, GWL_PROGRESS, (LONG) wParam);
InvalidateRect(hWnd, NULL, FALSE);
UpdateWindow(hWnd);
break;
case WM_ENABLE:
// Force a repaint since the control will look different.
InvalidateRect (hWnd, NULL, TRUE);
UpdateWindow (hWnd);
break;
case WM_PAINT:
return ProgressPaint (hWnd, dwProgress);
default:
return (DefWindowProc (hWnd, message, wParam, lParam));
break;
}
return(0L);
}
/////////////////////////////////////////////////////////////////////////////
//
// RegisterProgressClass
//
//
/////////////////////////////////////////////////////////////////////////////
BOOL RegisterProgressClass (HANDLE hModule)
{
WNDCLASS wcTest;
wcTest.lpszClassName = TEXT("cpProgress");
wcTest.hInstance = hModule;
wcTest.lpfnWndProc = ProgressBarCtlProc;
wcTest.hCursor = LoadCursor(NULL, IDC_WAIT);
wcTest.hIcon = NULL;
wcTest.lpszMenuName = NULL;
wcTest.hbrBackground = (HBRUSH) (rgColorPro[PROGRESSCOLOR_WINDOW]);
wcTest.style = CS_HREDRAW | CS_VREDRAW;
wcTest.cbClsExtra = 0;
wcTest.cbWndExtra = sizeof(DWORD);
//
// Set Bar color to Blue and text color to white
//
rgbBG = RGB( 0, 0, 255);
rgbFG = RGB(255, 255, 255);
return (RegisterClass((LPWNDCLASS) &wcTest));
}
/////////////////////////////////////////////////////////////////////////////
//
// UnRegisterProgressClass
//
//
/////////////////////////////////////////////////////////////////////////////
VOID UnRegisterProgressClass (HANDLE hModule)
{
UnregisterClass(TEXT("cpProgress"), hModule);
}
/////////////////////////////////////////////////////////////////////////////
//
// ProgressPaint
//
// Description:
//
// Handles all WM_PAINT messages for the control and paints
// the control for the progress state.
//
// Parameters:
// hWnd HWND Handle to the control.
// dwProgress DWORD Progress amount - between 1 and 100
//
// Return Value:
// LONG 0L.
//
//
// This is an alternate way to do the progress bar in the control. Instead
// of drawing a rectangle, it uses ExtTextOut to draw the opagueing rect
// based on the percentage complete. Clever.
//
/////////////////////////////////////////////////////////////////////////////
LONG ProgressPaint (HWND hWnd, DWORD dwProgress)
{
PAINTSTRUCT ps;
HDC hDC;
TCHAR szTemp[20];
int dx, dy, len;
RECT rc1, rc2;
SIZE Size;
hDC = BeginPaint (hWnd, &ps);
GetClientRect (hWnd, &rc1);
FrameRect (hDC, &rc1, GetStockObject(BLACK_BRUSH));
InflateRect (&rc1, -2, -2);
rc2 = rc1;
dx = rc1.right;
dy = rc1.bottom;
rc1.right = rc2.left = (dwProgress * dx / 100) + 1;
//
// Boundary condition testing
//
if (rc2.left > rc2.right)
rc2.left = rc2.right;
len = wsprintf (szTemp, TEXT("%3d%%"), dwProgress);
GetTextExtentPoint32 (hDC, szTemp, len, &Size);
SetBkColor (hDC, rgbBG);
SetTextColor (hDC, rgbFG);
ExtTextOut (hDC, (dx-Size.cx)/2, (dy-Size.cy)/2,
ETO_OPAQUE | ETO_CLIPPED, &rc1, szTemp, len, NULL);
SetBkColor (hDC, rgbFG);
SetTextColor (hDC, rgbBG);
ExtTextOut (hDC, (dx-Size.cx)/2, (dy-Size.cy)/2,
ETO_OPAQUE | ETO_CLIPPED, &rc2, szTemp, len, NULL);
EndPaint (hWnd, &ps);
return 0L;
}
#ifdef LATER
/////////////////////////////////////////////////////////////////////////////
//
// ProgressPaint
//
// Description:
//
// Handles all WM_PAINT messages for the control and paints
// the control for the progress state.
//
// Parameters:
// hWnd HWND Handle to the control.
// dwProgress DWORD Progress amount - between 1 and 100
//
// Return Value:
// LONG 0L.
//
/////////////////////////////////////////////////////////////////////////////
LONG ProgressPaint (HWND hWnd, DWORD dwProgress)
{
PAINTSTRUCT ps;
LPRECT lpRect;
RECT rect;
// RECT rc2;
HDC hDC;
COLORREF rgCr[CCOLORS];
HPEN rgHPen[CCOLORS];
int iColor, len;
TCHAR szTemp[20];
SIZE Size;
HBRUSH hBrushFace;
HBRUSH hBrushCtl;
int x1, x2, y1, y2;
if (dwProgress > 100)
return 0L;
lpRect = &rect;
hDC = BeginPaint (hWnd, &ps);
//
// Get colors that we'll need. We do not want to cache these
// items since we may our top-level parent window may have
// received a WM_WININICHANGE message at which time the control
// is repainted. Since this control never sees that message,
// we cannot assume that colors will remain the same throughout
// the life of the control.
//
for (iColor = 0; iColor < CCOLORS; iColor++)
{
rgCr[iColor] = GetSysColor (rgColorPro[iColor]);
rgHPen[iColor] = CreatePen (PS_SOLID, 1, rgCr[iColor]);
}
//
// Draw outer frame of Control and adjust size
//
GetClientRect (hWnd, lpRect);
FrameRect(hDC, lpRect, GetStockObject (BLACK_BRUSH));
hBrushFace = CreateSolidBrush (rgCr[PROGRESSCOLOR_FACE]);
InflateRect (lpRect, -1, -1);
#ifdef OLD
//
// Draw the face color and the outer frame
//
SelectObject (hDC, hBrushFace);
SelectObject (hDC, rgHPen[PROGRESSCOLOR_FRAME]);
#endif // OLD
//
// Draw 3D Progress bar within the control
//
Draw3DRect (hDC, hBrushFace, rgHPen[PROGRESSCOLOR_FRAME],
rgHPen[PROGRESSCOLOR_HIGHLIGHT],
rgHPen[PROGRESSCOLOR_SHADOW],
lpRect->left, lpRect->top,
lpRect->right * dwProgress / 100, lpRect->bottom);
//
// Now draw the rest of the control rectangle in Window color
// (this will erase any text from last call)
//
x1 = (lpRect->right * dwProgress / 100)+ 1;
if (x1 > lpRect->right)
x1= lpRect->right;
y1 = lpRect->top + 1;
x2 = lpRect->right - 1;
y2 = lpRect->bottom - 1;
hBrushCtl = CreateSolidBrush (rgCr[PROGRESSCOLOR_WINDOW]);
SelectObject (hDC, hBrushCtl);
SelectObject (hDC, rgHPen[PROGRESSCOLOR_WINDOW]);
Rectangle (hDC, x1, y1, x2, y2);
//
// Now draw text % centered with-in the rectangle
//
len = wsprintf (szTemp, TEXT("%3d%%"), dwProgress);
GetTextExtentPoint32 (hDC, szTemp, len, &Size);
#ifdef OLD
rc2.left = (lpRect->right - Size.cx) / 2;
rc2.top = (lpRect->bottom - Size.cy) / 2;
rc2.right = rc2.left + Size.cx;
rc2.bottom = rc2.top + Size.cy;
#endif // OLD
SetBkMode (hDC, TRANSPARENT);
SetTextColor (hDC, GetSysColor(COLOR_BTNTEXT));
ExtTextOut (hDC, (lpRect->right-Size.cx)/2, (lpRect->bottom-Size.cy)/2,
0L, lpRect, szTemp, len, NULL);
//
// Clean up
//
EndPaint(hWnd, &ps);
DeleteObject (hBrushFace);
DeleteObject (hBrushCtl);
for (iColor = 0; iColor < CCOLORS; iColor++)
{
if (rgHPen[iColor])
DeleteObject (rgHPen[iColor]);
}
return 0L;
}
/////////////////////////////////////////////////////////////////////////////
//
// Draw3DRect
//
// Description:
// Draws the 3D button look within a given rectangle. This rectangle
// is assumed to be bounded by a one pixel black border, so everything
// is bumped in by one.
//
// Parameters:
// hDC DC to draw to.
// hBrushFace HBRUSH rectangle fill color brush.
// hPenFrame HPEN rectangle frame color pen.
// hPenHigh HPEN highlight color pen.
// hPenShadow HPEN shadow color pen.
// x1 int Upper left corner x.
// y1 int Upper left corner y.
// x2 int Lower right corner x.
// y2 int Lower right corner y.
//
// NOTE: hBrushFace and hPenFrame are usually the same color, only one
// is a Pen used to draw the rectangle frame and the brush color
// is used to fill the rectangle. Then the highlight and shadow
// pens are used to create the 3D effect.
//
// Return Value:
// void
//
/////////////////////////////////////////////////////////////////////////////
void Draw3DRect (HDC hDC, HBRUSH hBrushFace, HPEN hPenFrame,
HPEN hPenHigh, HPEN hPenShadow,
int x1, int y1, int x2, int y2)
{
HPEN hPenOrg;
RECT rect;
if (x1 < 0)
x1 = 0;
if (x2 < 1)
x2 = 1;
if (y1 < 1)
y1 = 1;
if (y2 < 0)
y2 = 0;
if (!(x1 < x2))
x1 = x2;
if (!(y1 < y2))
y1 = y2;
//
// Draw the face color and the rectangle frame
//
SelectObject (hDC, hBrushFace);
hPenOrg = SelectObject (hDC, hPenFrame);
Rectangle (hDC, x1, y1, x2, y2);
//
// Shrink the rectangle to account for borders.
//
x1+=1;
x2-=1;
y1+=1;
y2-=1;
if (x2 < 1)
x2 = 1;
if (y2 < 1)
y2 = 1;
if (!(x1 < x2))
x1 = x2;
if (!(y1 < y2))
y1 = y2;
SelectObject (hDC, hPenShadow);
//
// Lowest shadow line.
//
MoveToEx (hDC, x1, y2, NULL);
LineTo (hDC, x2, y2);
LineTo (hDC, x2, y1-1);
//
// Upper shadow line.
//
MoveToEx (hDC, x1+1, y2-1, NULL);
LineTo (hDC, x2-1, y2-1);
LineTo (hDC, x2-1, y1);
SelectObject (hDC, hPenHigh);
//
// Upper highlight line.
//
MoveToEx (hDC, x1, y2-1, NULL);
LineTo (hDC, x1, y1);
LineTo (hDC, x2, y1);
if (hPenOrg)
SelectObject (hDC, hPenOrg);
return;
}
// If using the ExtTextOut method for progress ctl, these globals are needed
DWORD rgbFG;
DWORD rgbBG;
/////////////////////////////////////////////////////////////////////////////
//
// ProgressPaint2
//
// Description:
//
// Handles all WM_PAINT messages for the control and paints
// the control for the progress state.
//
// Parameters:
// hWnd HWND Handle to the control.
// dwProgress DWORD Progress amount - between 1 and 100
//
// Return Value:
// LONG 0L.
//
//
// This is an alternate way to do the progress bar in the control. Instead
// of drawing a rectangle, it uses ExtTextOut to draw the opagueing rect
// based on the percentage complete. Clever.
//
/////////////////////////////////////////////////////////////////////////////
LONG ProgressPaint2 (HWND hWnd, DWORD dwProgress)
{
PAINTSTRUCT ps;
HDC hDC;
TCHAR szTemp[20];
int dx, dy, len;
RECT rc1, rc2;
SIZE Size;
DWORD rgbFG;
DWORD rgbBG;
rgbBG = RGB( 0, 0, 255);
rgbFG = RGB(255, 255, 255);
hDC = BeginPaint (hWnd, &ps);
GetClientRect (hWnd, &rc1);
FrameRect (hDC, &rc1, GetStockObject(BLACK_BRUSH));
InflateRect (&rc1, -1, -1);
rc2 = rc1;
dx = rc1.right;
dy = rc1.bottom;
rc1.right = rc2.left = (dwProgress * dx / 100) + 1;
len = wsprintf (szTemp, TEXT("%3d%%"), dwProgress);
GetTextExtentPoint32 (hDC, szTemp, len, &Size);
SetBkColor (hDC, rgbBG);
SetTextColor (hDC, rgbFG);
ExtTextOut (hDC, (dx-Size.cx)/2, (dy-Size.cy)/2,
ETO_OPAQUE | ETO_CLIPPED, &rc1, szTemp, len, NULL);
SetBkColor (hDC, rgbFG);
SetTextColor (hDC, rgbBG);
ExtTextOut (hDC, (dx-Size.cx)/2, (dy-Size.cy)/2,
ETO_OPAQUE | ETO_CLIPPED, &rc2, szTemp, len, NULL);
EndPaint (hWnd, &ps);
return 0L;
}
/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
#endif // LATER