DIALOGS.C


/******************************************************************************\
* This is a part of the Microsoft Source Code Samples.
* Copyright 1993 - 1998 Microsoft Corporation.
* All rights reserved.
* This source code is only intended as a supplement to
* Microsoft Development Tools and/or WinHelp documentation.
* See these sources for detailed information regarding the
* Microsoft samples programs.
\******************************************************************************/

#define NOMINMAX
#include <windows.h>
#include "FontView.h"

#include <stdlib.h>

#if !defined (APIENTRY)
#define APIENTRY FAR PASCAL
#endif

BOOL CenterWindow (HWND, HWND);


typedef struct FONTENUM {
short ft;
TEXTMETRIC tm;
LOGFONT lf;
} FONTSTRUCT;
typedef FONTSTRUCT *PFONTSTRUCT;
typedef FONTSTRUCT NEAR *NPFONTSTRUCT;
typedef FONTSTRUCT FAR *LPFONTSTRUCT;

typedef struct FONTLIST {
int count;
HANDLE hList;
} FONTLIST;
typedef FONTLIST *PFONTLIST;
typedef FONTLIST NEAR *NPFONTLIST;
typedef FONTLIST FAR *LPFONTLIST;


void SetDlgItemValue (HWND hDlg, int nIDDlgItem, int wValue, BOOL bSigned, int nBase)
{
char szValue[20];

switch (nBase) {
case 8:
wsprintf (szValue, "0o%o", wValue);
SetDlgItemText (hDlg, nIDDlgItem, szValue);
break;
case 16:
wsprintf (szValue, "0x%x", wValue);
SetDlgItemText (hDlg, nIDDlgItem, szValue);
break;
default:
SetDlgItemInt (hDlg, nIDDlgItem, wValue, bSigned);
break;
}
}

int FAR PASCAL DlgEnumFontSizes (lpLogFont, lpTextMetric, nFontType, lpData)
LPLOGFONT lpLogFont;
LPTEXTMETRIC lpTextMetric;
short nFontType;
LPHANDLE lpData;
{
HANDLE hFonts;
LPFONTSTRUCT pFS;
LPFONTLIST pFL;

/*
This function will lock down the incoming handle, properly alloc, and realloc the
handle within it to hold the data of the fonts enumerated, then unlock the handle.
*/
hFonts = *lpData;
pFL = (LPFONTLIST)GlobalLock (hFonts);
if (!pFL) {
return FALSE;
} else if (pFL->count == 0) {
pFL->hList = GlobalAlloc (GHND, sizeof(FONTSTRUCT));
} else {
pFL->hList = GlobalReAlloc (pFL->hList, sizeof(FONTSTRUCT)*(1+pFL->count), GMEM_MOVEABLE);
}

if (pFL->hList) {
pFS = (LPFONTSTRUCT)GlobalLock (pFL->hList);
if (pFS) {
pFS[pFL->count].ft = nFontType;
pFS[pFL->count].tm = *lpTextMetric;
pFS[pFL->count].lf = *lpLogFont;
GlobalUnlock (pFL->hList);
pFL->count++;
}
GlobalUnlock (hFonts);

} else {
GlobalUnlock (hFonts);
return FALSE;
}

return TRUE;
}

int FAR PASCAL DlgEnumFontNames (lpLogFont, lpTextMetric, nFontType, lpData)
LPLOGFONT lpLogFont;
LPTEXTMETRIC lpTextMetric;
short nFontType;
LPHANDLE lpData;
{
HDC hdc;
HWND hwnd;
HANDLE hInst;
FARPROC lpFontEnumProc;

/*
This function is just a pass through. For each face encountered, it will in turn enumerate all
sizes available. the lpData, which is a FAR * to a FONTSTRUCT structure will simply be passed
on to the second enumeration procedure which will fill it in.
*/
hwnd = GetFocus();
#if defined (WIN32)
hInst = (HANDLE)GetWindowLong (hwnd, GWL_HINSTANCE);
#elif defined (WIN16)
hInst = (HANDLE)GetWindowWord (hwnd, GWW_HINSTANCE);
#endif

lpFontEnumProc = MakeProcInstance((FARPROC)DlgEnumFontSizes, hInst);
if (lpFontEnumProc) {
hdc = GetDC(hwnd);
EnumFonts (hdc, lpLogFont->lfFaceName, (FONTENUMPROC)lpFontEnumProc, (LPARAM)lpData);
ReleaseDC(hwnd, hdc);
FreeProcInstance (lpFontEnumProc);
} else {
MessageBox (GetFocus(), "Couldn't create a proc instance", "FontView", MB_OK);
return FALSE;
}
return TRUE;

lpTextMetric; // unreferenced formal parameter
nFontType; // unreferenced formal parameter
}



BOOL APIENTRY SimpleDlgProc(HWND hwnd, UINT msg, UINT wParam, LONG lParam)
{
int wmId;
static HBITMAP hbmFontView;
static BITMAP bmFontView;
RECT rect;
HDC hdc, hdcSrc;
HBITMAP hbmOld;
PAINTSTRUCT ps;
HANDLE hInst;

#if defined (WIN32)
hInst = (HANDLE)GetWindowLong (hwnd, GWL_HINSTANCE);
#elif defined (WIN16)
hInst = (HANDLE)GetWindowWord (hwnd, GWW_HINSTANCE);
#endif

switch (msg) {
case WM_INITDIALOG:
CenterWindow (hwnd, GetWindow (hwnd, GW_OWNER));
hbmFontView = LoadBitmap (hInst, "FONTVIEW");
GetObject (hbmFontView,sizeof(BITMAP), &bmFontView);
if (!hbmFontView) MessageBeep(0);
return (TRUE);

case WM_DESTROY:
DeleteObject (hbmFontView);
break;

case WM_PAINT:
hdc = BeginPaint (hwnd, &ps);
GetWindowRect (hwnd, &rect);
ScreenToClient (hwnd, (LPPOINT)&rect.left);
ScreenToClient (hwnd, (LPPOINT)&rect.right);
hdc = GetDC (hwnd);
hdcSrc = CreateCompatibleDC (hdc);
hbmOld = SelectObject (hdcSrc, hbmFontView);
if (!BitBlt (hdc, 0, 0, bmFontView.bmWidth, bmFontView.bmHeight, hdcSrc, 0, 0, SRCCOPY)) {
MessageBeep(0);
}
SelectObject (hdcSrc, hbmOld);
DeleteDC (hdcSrc);
EndPaint (hwnd, &ps);
break;

case WM_COMMAND:
#if defined (WIN32)
wmId = LOWORD(wParam);
#elif defined (WIN16)
wmId = wParam;
#endif
switch (wmId) {

case IDOK:
EndDialog(hwnd, TRUE);
return (TRUE);

case IDCANCEL:
EndDialog(hwnd, TRUE);
return (TRUE);
}
break;
}
return (FALSE);

lParam; // unreferenced formal parameter
}


/*
This dialog will present edit controls for all the parameters of a CreateFont call.
The user can put any value in any of the fields, no validation is done. These parameters
are then used to create a font with, and that will be the font that will be displayed.
*/
BOOL APIENTRY CreateDlgProc(HWND hwnd, UINT msg, UINT wParam, LONG lParam)
{
int wmId, i;
BOOL bDone;
static LOGFONT lfDlg;
static LPLOGFONT lplf;

switch (msg) {
case WM_INITDIALOG:
CenterWindow (hwnd, GetWindow (hwnd, GW_OWNER));
lplf = (LOGFONT *)lParam;
lfDlg = *lplf;
SetDlgItemInt (hwnd, CFD_HEIGHT, (int)lfDlg.lfHeight, TRUE);
SetDlgItemInt (hwnd, CFD_WIDTH, (int)lfDlg.lfWidth, TRUE);
SetDlgItemInt (hwnd, CFD_ESCAPEMENT, (int)lfDlg.lfEscapement, TRUE);
SetDlgItemInt (hwnd, CFD_ORIENTATION, (int)lfDlg.lfOrientation, TRUE);
SetDlgItemInt (hwnd, CFD_WEIGHT, (int)lfDlg.lfWeight, FALSE);
SetDlgItemInt (hwnd, CFD_ITALIC, (int)lfDlg.lfItalic, FALSE);
SetDlgItemInt (hwnd, CFD_UNDERLINE, (int)lfDlg.lfUnderline, FALSE);
SetDlgItemInt (hwnd, CFD_STRIKEOUT, (int)lfDlg.lfStrikeOut, FALSE);
SetDlgItemInt (hwnd, CFD_CHARSET, (int)lfDlg.lfCharSet, FALSE);
SetDlgItemInt (hwnd, CFD_OUTPUTPRECISION, (int)lfDlg.lfOutPrecision, FALSE);
SetDlgItemInt (hwnd, CFD_CLIPPRECISION, (int)lfDlg.lfClipPrecision, FALSE);
SetDlgItemInt (hwnd, CFD_QUALITY, (int)lfDlg.lfQuality, FALSE);
SetDlgItemInt (hwnd, CFD_PITCHANDFAMILY, (int)lfDlg.lfPitchAndFamily, FALSE);
SetDlgItemText(hwnd, CFD_FACENAME, lfDlg.lfFaceName);

return (TRUE);

case WM_COMMAND:
#if defined (WIN32)
wmId = LOWORD(wParam);
#elif defined (WIN16)
wmId = wParam;
#endif
switch (wmId) {
case CFD_DEFAULT:
// Set all elements to ZERO. This will give us a 'default' font
for (i=CFD_BASE; i<=CFD_PITCHANDFAMILY; i++) {
SetDlgItemInt (hwnd, i, 0, FALSE);
}
SetDlgItemText (hwnd, CFD_FACENAME, "");
break;

case IDOK:
// Get the data from the edit control, we will then use this for a 'CreatFont' call
lfDlg.lfHeight = GetDlgItemInt (hwnd, CFD_HEIGHT, &bDone, TRUE);
lfDlg.lfWidth = GetDlgItemInt (hwnd, CFD_WIDTH, &bDone, TRUE);
lfDlg.lfEscapement = GetDlgItemInt (hwnd, CFD_ESCAPEMENT, &bDone, TRUE);
lfDlg.lfOrientation = GetDlgItemInt (hwnd, CFD_ORIENTATION, &bDone, TRUE);
lfDlg.lfWeight = GetDlgItemInt (hwnd, CFD_WEIGHT, &bDone, FALSE);
lfDlg.lfItalic = (BYTE)GetDlgItemInt (hwnd, CFD_ITALIC, &bDone, FALSE);
lfDlg.lfUnderline = (BYTE)GetDlgItemInt (hwnd, CFD_UNDERLINE, &bDone, FALSE);
lfDlg.lfStrikeOut = (BYTE)GetDlgItemInt (hwnd, CFD_STRIKEOUT, &bDone, FALSE);
lfDlg.lfCharSet = (BYTE)GetDlgItemInt (hwnd, CFD_CHARSET, &bDone, FALSE);
lfDlg.lfOutPrecision = (BYTE)GetDlgItemInt (hwnd, CFD_OUTPUTPRECISION, &bDone, FALSE);
lfDlg.lfClipPrecision = (BYTE)GetDlgItemInt (hwnd, CFD_CLIPPRECISION, &bDone, FALSE);
lfDlg.lfQuality = (BYTE)GetDlgItemInt (hwnd, CFD_QUALITY, &bDone, FALSE);
lfDlg.lfPitchAndFamily = (BYTE)GetDlgItemInt (hwnd, CFD_PITCHANDFAMILY, &bDone, FALSE);
GetDlgItemText(hwnd, CFD_FACENAME, lfDlg.lfFaceName,20);
// and copy the data into our external structure
*lplf = lfDlg;
EndDialog(hwnd, TRUE);
return (TRUE);

case IDCANCEL:
// Exit without changing anything
EndDialog(hwnd, TRUE);
return (TRUE);

}
break;
}
return (FALSE);

lParam; //unreferenced formal paramter
}

/*
This dialog will display the TEXTMETRIC data that is retrieved from a 'GetTextMetric' call.
If the 'Select' button is clicked, then the current CreateFont data will be replaced with
as much data from TEXTMETRIC as possible.
*/
BOOL APIENTRY MetricsDlgProc(HWND hwnd, UINT msg, UINT wParam, LONG lParam)
{
static LOGFONT lfDlg;
static LPLOGFONT lplf;
static TEXTMETRIC tm;
static char szFacename[LF_FACESIZE];
int wmId;
BOOL bDone;
TEXTMETRIC tmTmp;
HFONT hfont, hfontPrev;
HDC hdc;
char szBuffer[LF_FACESIZE+15];


switch (msg) {
case WM_INITDIALOG:
CenterWindow (hwnd, GetWindow (hwnd, GW_OWNER));
lplf = (LOGFONT *)lParam;
lfDlg = *lplf;

hfont = CreateFontIndirect (&lfDlg);
hdc = GetDC (hwnd);
hfontPrev = SelectObject (hdc, hfont);
GetTextMetrics (hdc, &tm);
GetTextFace (hdc, sizeof(szFacename), szFacename);
SelectObject (hdc, hfontPrev);
DeleteObject (hfont);
ReleaseDC (hwnd, hdc);

wsprintf (szBuffer, "TextMetrics: %s", (LPSTR)szFacename);
SetWindowText (hwnd, szBuffer);

SetDlgItemInt (hwnd, TMD_HEIGHT, (int)tm.tmHeight, TRUE);
SetDlgItemInt (hwnd, TMD_ASCENT, (int)tm.tmAscent, TRUE);
SetDlgItemInt (hwnd, TMD_DESCENT, (int)tm.tmDescent, TRUE);
SetDlgItemInt (hwnd, TMD_INTERNAL, (int)tm.tmInternalLeading, TRUE);
SetDlgItemInt (hwnd, TMD_EXTERNAL, (int)tm.tmExternalLeading, TRUE);
SetDlgItemInt (hwnd, TMD_AVEWIDTH, (int)tm.tmAveCharWidth, TRUE);
SetDlgItemInt (hwnd, TMD_MAXWIDTH, (int)tm.tmMaxCharWidth, TRUE);
SetDlgItemInt (hwnd, TMD_WEIGHT, (int)tm.tmWeight, TRUE);
SetDlgItemInt (hwnd, TMD_ITALIC, (int)tm.tmItalic, FALSE);
SetDlgItemInt (hwnd, TMD_UNDERLINE, (int)tm.tmUnderlined, FALSE);
SetDlgItemInt (hwnd, TMD_STRUCKOUT, (int)tm.tmStruckOut, FALSE);
SetDlgItemInt (hwnd, TMD_FIRSTCHAR, (int)tm.tmFirstChar, FALSE);
SetDlgItemInt (hwnd, TMD_LASTCHAR, (int)tm.tmLastChar, FALSE);
SetDlgItemInt (hwnd, TMD_DEFAULTCHAR, (int)tm.tmDefaultChar, FALSE);
SetDlgItemInt (hwnd, TMD_BREAKCHAR, (int)tm.tmBreakChar, FALSE);
SetDlgItemInt (hwnd, TMD_PITCHANDFAMILY, (int)tm.tmPitchAndFamily, FALSE);
SetDlgItemInt (hwnd, TMD_CHARSET, (int)tm.tmCharSet, FALSE);
SetDlgItemInt (hwnd, TMD_OVERHANG, (int)tm.tmOverhang, TRUE);
SetDlgItemInt (hwnd, TMD_DIGITIZEDASPECTX, (int)tm.tmDigitizedAspectX, TRUE);
SetDlgItemInt (hwnd, TMD_DIGITIZEDASPECTY, (int)tm.tmDigitizedAspectY, TRUE);

return (TRUE);

case WM_COMMAND:
#if defined (WIN32)
wmId = LOWORD(wParam);
#elif defined (WIN16)
wmId = wParam;
#endif
switch (wmId) {
case IDOK:
// Lets pull in as much data from the TEXTMETRIC structure as possible...
lfDlg.lfHeight = tm.tmHeight;
lfDlg.lfWidth = tm.tmAveCharWidth;
//lfDlg.lfEscapement - No Use
//lfDlg.lfOrientation - No Use
lfDlg.lfWeight = tm.tmWeight;
lfDlg.lfItalic = tm.tmItalic;
lfDlg.lfUnderline = tm.tmUnderlined;
lfDlg.lfStrikeOut = tm.tmStruckOut;
lfDlg.lfCharSet = tm.tmCharSet;
//lfDlg.lfOutPrecision - No Use
//lfDlg.lfClipPrecision - No Use
//lfDlg.lfQuality - No Use
lfDlg.lfPitchAndFamily = tm.tmPitchAndFamily;
lstrcpy(lfDlg.lfFaceName, szFacename);

// Lets create a font with this new data
hfont = CreateFontIndirect (&lfDlg);
hdc = GetDC (hwnd);
hfontPrev = SelectObject (hdc, hfont);
GetTextMetrics (hdc, &tmTmp);
// Get the face name
GetTextFace (hdc, sizeof(szBuffer), szBuffer);
SelectObject (hdc, hfontPrev);
DeleteObject (hfont);
ReleaseDC (hwnd, hdc);

// And verify that we did indeed get the same font.
bDone = TRUE;
bDone = bDone && (tm.tmHeight==tmTmp.tmHeight);
bDone = bDone && (tm.tmAscent==tmTmp.tmAscent);
bDone = bDone && (tm.tmDescent==tmTmp.tmDescent);
bDone = bDone && (tm.tmInternalLeading==tmTmp.tmInternalLeading);
bDone = bDone && (tm.tmExternalLeading==tmTmp.tmExternalLeading);
bDone = bDone && (tm.tmAveCharWidth==tmTmp.tmAveCharWidth);
bDone = bDone && (tm.tmMaxCharWidth==tmTmp.tmMaxCharWidth);
bDone = bDone && (tm.tmWeight==tmTmp.tmWeight);
bDone = bDone && (tm.tmItalic==tmTmp.tmItalic);
bDone = bDone && (tm.tmUnderlined==tmTmp.tmUnderlined);
bDone = bDone && (tm.tmStruckOut==tmTmp.tmStruckOut);
bDone = bDone && (tm.tmFirstChar==tmTmp.tmFirstChar);
bDone = bDone && (tm.tmLastChar==tmTmp.tmLastChar);
bDone = bDone && (tm.tmDefaultChar==tmTmp.tmDefaultChar);
bDone = bDone && (tm.tmBreakChar==tmTmp.tmBreakChar);
bDone = bDone && (tm.tmPitchAndFamily==tmTmp.tmPitchAndFamily);
bDone = bDone && (tm.tmCharSet==tmTmp.tmCharSet);
// Did it work?
if (bDone) {
*lplf = lfDlg;
EndDialog(hwnd, TRUE);
return (TRUE);
} else {
// We need to take a close look at the font verification
// code. Currently, it sometimes will report that the
// font didn't get properly selected, even if it did.
*lplf = lfDlg;
EndDialog(hwnd, TRUE);
return (TRUE);

// This is what we want to do once we beef up the font
// verification code:
lfDlg = *lplf;
MessageBox (GetFocus(),
"Unable to re-create font from TextMetrics",
"FontView", MB_OK);
}
break;

case IDCANCEL:
EndDialog(hwnd, TRUE);
return (TRUE);

}
break;
}
return (FALSE);

/* Just For Reference */
lParam;
}


BOOL FillEnumFields (HWND hwnd, int iType, LPTEXTMETRIC ptm, LPLOGFONT plf, int nBase)
{
SetDlgItemValue (hwnd, TMD_HEIGHT, (int)ptm->tmHeight, TRUE, nBase);
SetDlgItemValue (hwnd, TMD_ASCENT, (int)ptm->tmAscent, TRUE, nBase);
SetDlgItemValue (hwnd, TMD_DESCENT, (int)ptm->tmDescent, TRUE, nBase);
SetDlgItemValue (hwnd, TMD_INTERNAL, (int)ptm->tmInternalLeading, TRUE, nBase);
SetDlgItemValue (hwnd, TMD_EXTERNAL, (int)ptm->tmExternalLeading, TRUE, nBase);
SetDlgItemValue (hwnd, TMD_AVEWIDTH, (int)ptm->tmAveCharWidth, TRUE, nBase);
SetDlgItemValue (hwnd, TMD_MAXWIDTH, (int)ptm->tmMaxCharWidth, TRUE, nBase);
SetDlgItemValue (hwnd, TMD_WEIGHT, (int)ptm->tmWeight, TRUE, nBase);
SetDlgItemValue (hwnd, TMD_ITALIC, (int)ptm->tmItalic, FALSE, nBase);
SetDlgItemValue (hwnd, TMD_UNDERLINE, (int)ptm->tmUnderlined, FALSE, nBase);
SetDlgItemValue (hwnd, TMD_STRUCKOUT, (int)ptm->tmStruckOut, FALSE, nBase);
SetDlgItemValue (hwnd, TMD_FIRSTCHAR, (int)ptm->tmFirstChar, FALSE, nBase);
SetDlgItemValue (hwnd, TMD_LASTCHAR, (int)ptm->tmLastChar, FALSE, nBase);
SetDlgItemValue (hwnd, TMD_DEFAULTCHAR, (int)ptm->tmDefaultChar, FALSE, nBase);
SetDlgItemValue (hwnd, TMD_BREAKCHAR, (int)ptm->tmBreakChar, FALSE, nBase);
SetDlgItemValue (hwnd, TMD_PITCHANDFAMILY, (int)ptm->tmPitchAndFamily, FALSE, nBase);
SetDlgItemValue (hwnd, TMD_CHARSET, (int)ptm->tmCharSet, FALSE, nBase);
SetDlgItemValue (hwnd, TMD_OVERHANG, (int)ptm->tmOverhang, TRUE, nBase);
SetDlgItemValue (hwnd, TMD_DIGITIZEDASPECTX, (int)ptm->tmDigitizedAspectX, TRUE, nBase);
SetDlgItemValue (hwnd, TMD_DIGITIZEDASPECTY, (int)ptm->tmDigitizedAspectY, TRUE, nBase);

SetDlgItemValue (hwnd, CFD_HEIGHT, (int)plf->lfHeight, TRUE, nBase);
SetDlgItemValue (hwnd, CFD_WIDTH, (int)plf->lfWidth, TRUE, nBase);
SetDlgItemValue (hwnd, CFD_ESCAPEMENT, (int)plf->lfEscapement, TRUE, nBase);
SetDlgItemValue (hwnd, CFD_ORIENTATION, (int)plf->lfOrientation, TRUE, nBase);
SetDlgItemValue (hwnd, CFD_WEIGHT, (int)plf->lfWeight, FALSE, nBase);
SetDlgItemValue (hwnd, CFD_ITALIC, (int)plf->lfItalic, FALSE, nBase);
SetDlgItemValue (hwnd, CFD_UNDERLINE, (int)plf->lfUnderline, FALSE, nBase);
SetDlgItemValue (hwnd, CFD_STRIKEOUT, (int)plf->lfStrikeOut, FALSE, nBase);
SetDlgItemValue (hwnd, CFD_CHARSET, (int)plf->lfCharSet, FALSE, nBase);
SetDlgItemValue (hwnd, CFD_OUTPUTPRECISION, (int)plf->lfOutPrecision, FALSE, nBase);
SetDlgItemValue (hwnd, CFD_CLIPPRECISION, (int)plf->lfClipPrecision, FALSE, nBase);
SetDlgItemValue (hwnd, CFD_QUALITY, (int)plf->lfQuality, FALSE, nBase);
SetDlgItemValue (hwnd, CFD_PITCHANDFAMILY, (int)plf->lfPitchAndFamily, FALSE, nBase);
SetDlgItemText(hwnd, CFD_FACENAME, plf->lfFaceName);

SetDlgItemValue (hwnd, ED_TYPE, (int)iType, FALSE, nBase);

return TRUE;
}


BOOL DrawSample (HWND hwnd, LPLOGFONT plf)
{
HFONT hfont, hfontPrev;
HDC hdc;
RECT r;

hfont = CreateFontIndirect (plf);
hdc = GetDC (hwnd);
hfontPrev = SelectObject (hdc, hfont);
GetWindowRect (hwnd, &r);
ScreenToClient (hwnd, (LPPOINT)&r.left);
ScreenToClient (hwnd, (LPPOINT)&r.right);

Rectangle (hdc, r.left, r.top, r.right, r.bottom);

InflateRect (&r, -1, -1);
SetTextAlign (hdc, TA_BOTTOM | TA_CENTER);
ExtTextOut (hdc, r.left + ((r.right-r.left)/2), r.bottom, ETO_CLIPPED, &r,"AaBbCcDdEe 012345", 17, NULL);

SelectObject (hdc, hfontPrev);
DeleteObject (hfont);
ReleaseDC (hwnd, hdc);
return TRUE;
}


/*
Display a dialog that the user can use to enumerate through all of the fonts in the system.
Show him not only all of the metrics for the font, but a sample of the font as well.
If the user picks the 'Select' button, then the Metrics of this font will be used for
the CreateFont call.
*/
BOOL APIENTRY EnumDlgProc(HWND hwnd, UINT msg, UINT wParam, LONG lParam)
{
static HANDLE /*TO FONTLIST*/ hFonts;
static int iLoc=0;
static int count=0;
static BOOL bHex = FALSE;
static LOGFONT *lplf;
static LOGFONT lfDlg;
int wmId, i, j;
HANDLE hInst;
HWND hwndItem;
HDC hdc;
FARPROC lpEnumFonts;
LPFONTLIST pFL;
LPFONTSTRUCT pFS;
char szTmp[80];
HFONT hfont, hfontPrev;
BOOL bDone;
TEXTMETRIC tmTmp;


switch (msg) {
case WM_INITDIALOG:
lplf = (LOGFONT *)lParam;
lfDlg = *lplf;
iLoc = 0;
count = 0;
bHex = FALSE;
/* First, lets enumerate ALL fonts, and store them in our list */
hFonts = GlobalAlloc (GHND, sizeof(FONTLIST));
if (hFonts) {

#if defined (WIN32)
hInst = (HANDLE)GetWindowLong (hwnd, GWL_HINSTANCE);
#elif defined (WIN16)
hInst = (HANDLE)GetWindowWord (hwnd, GWW_HINSTANCE);
#endif

lpEnumFonts = MakeProcInstance((FARPROC)DlgEnumFontNames, hInst);
if (lpEnumFonts) {
hdc = GetDC(hwnd);
// The enumeration function will lock down the handle
EnumFonts (hdc, NULL, (FONTENUMPROC)lpEnumFonts, (LPARAM)&hFonts);
// The handle will come back to us properly unlocked
ReleaseDC(hwnd, hdc);
FreeProcInstance (lpEnumFonts);

}
}
pFL = (LPFONTLIST)GlobalLock (hFonts);
if (pFL) {
pFS = (LPFONTSTRUCT)GlobalLock (pFL->hList);
if (pFS) {
iLoc = 0;
j = 100;
for (i=0; i<pFL->count; i++) {
if (lstrcmp(lfDlg.lfFaceName, pFS[i].lf.lfFaceName) == 0) {
if (abs(lfDlg.lfHeight-pFS[i].lf.lfHeight) < j) {
j = abs(lfDlg.lfHeight-pFS[i].lf.lfHeight);
iLoc = i;
}
}
}
FillEnumFields (hwnd, pFS[iLoc].ft, &pFS[iLoc].tm, &pFS[iLoc].lf, (bHex?16:10));
hwndItem = GetDlgItem (hwnd, ED_SAMPLE);
DrawSample (hwndItem, &pFS[iLoc].lf);
GlobalUnlock (pFL->hList);

}
count = pFL->count;
GlobalUnlock (hFonts);

}
/* now fill in the dialog values */
wsprintf (szTmp, "EnumFonts %d of %d", iLoc+1, count);
SetWindowText (hwnd, szTmp);
CenterWindow (hwnd, GetWindow (hwnd, GW_OWNER));

return TRUE;

case WM_PAINT:
pFL = (LPFONTLIST)GlobalLock (hFonts);
if (pFL) {
pFS = (LPFONTSTRUCT)GlobalLock (pFL->hList);
if (pFS) {
FillEnumFields (hwnd, pFS[iLoc].ft, &pFS[iLoc].tm, &pFS[iLoc].lf, (bHex?16:10));
hwndItem = GetDlgItem (hwnd, ED_SAMPLE);
DrawSample (hwndItem, &pFS[iLoc].lf);
GlobalUnlock (pFL->hList);
}
GlobalUnlock (hFonts);
}
return 0;

case WM_COMMAND:
#if defined (WIN32)
wmId = LOWORD(wParam);
#elif defined (WIN16)
wmId = wParam;
#endif
switch (wmId) {

case ED_HEX:
// Display the data in either Hex mode or Dec mode.
bHex = !bHex;
CheckDlgButton (hwnd, wmId, bHex);
pFL = (LPFONTLIST)GlobalLock (hFonts);
if (pFL) {
pFS = (LPFONTSTRUCT)GlobalLock (pFL->hList);
if (pFS) {
FillEnumFields (hwnd, pFS[iLoc].ft, &pFS[iLoc].tm, &pFS[iLoc].lf, (bHex?16:10));
if (GlobalUnlock (pFL->hList)) {
MessageBox (GetFocus(), "In HEX", "Unlock pFL->hList", MB_OK);
}
}
if (GlobalUnlock (hFonts)) {
MessageBox (GetFocus(), "In HEX", "Unlock hFonts", MB_OK);
}

}
break;

case ED_PREV:
pFL = (LPFONTLIST)GlobalLock (hFonts);
if (pFL) {
if (iLoc > 0) {
iLoc--;
pFS = (LPFONTSTRUCT)GlobalLock (pFL->hList);
if (pFS) {
FillEnumFields (hwnd, pFS[iLoc].ft, &pFS[iLoc].tm, &pFS[iLoc].lf, (bHex?16:10));
hwndItem = GetDlgItem (hwnd, ED_SAMPLE);
DrawSample (hwndItem, &pFS[iLoc].lf);
GlobalUnlock (pFL->hList);
}
}
GlobalUnlock (hFonts);
}
wsprintf (szTmp, "EnumFonts %d of %d", iLoc+1, count);
SetWindowText (hwnd, szTmp);
break;

case ED_NEXT:
pFL = (LPFONTLIST)GlobalLock (hFonts);
if (pFL) {
if ((pFL->count-1) > iLoc) {
iLoc++;
pFS = (LPFONTSTRUCT)GlobalLock (pFL->hList);
if (pFS) {
FillEnumFields (hwnd, pFS[iLoc].ft, &pFS[iLoc].tm, &pFS[iLoc].lf, (bHex?16:10));
hwndItem = GetDlgItem (hwnd, ED_SAMPLE);
DrawSample (hwndItem, &pFS[iLoc].lf);
GlobalUnlock (pFL->hList);
}

}
GlobalUnlock (hFonts);
}
wsprintf (szTmp, "EnumFonts %d of %d", iLoc+1, count);
SetWindowText (hwnd, szTmp);
break;

case IDOK:
// Copy the LOGFONT structure from the enumeration list, into our private LF
pFL = (LPFONTLIST)GlobalLock (hFonts);
bDone = FALSE;
if (pFL) {
if ((pFL->count-1) >= iLoc) {
pFS = (LPFONTSTRUCT)GlobalLock (pFL->hList);
if (pFS) {
lfDlg = pFS[iLoc].lf;

// Lets create a font with this new data
hfont = CreateFontIndirect (&lfDlg);
hdc = GetDC (hwnd);
hfontPrev = SelectObject (hdc, hfont);
GetTextMetrics (hdc, &tmTmp);
// Get the face name
GetTextFace (hdc, sizeof(szTmp), szTmp);
SelectObject (hdc, hfontPrev);
DeleteObject (hfont);
ReleaseDC (hwnd, hdc);

// And verify that we did indeed get the same font.
bDone = TRUE;
bDone = bDone && (pFS[iLoc].tm.tmHeight==tmTmp.tmHeight);
bDone = bDone && (pFS[iLoc].tm.tmAscent==tmTmp.tmAscent);
bDone = bDone && (pFS[iLoc].tm.tmDescent==tmTmp.tmDescent);
bDone = bDone && (pFS[iLoc].tm.tmInternalLeading==tmTmp.tmInternalLeading);
bDone = bDone && (pFS[iLoc].tm.tmExternalLeading==tmTmp.tmExternalLeading);
bDone = bDone && (pFS[iLoc].tm.tmAveCharWidth==tmTmp.tmAveCharWidth);

bDone = bDone && (pFS[iLoc].tm.tmMaxCharWidth==tmTmp.tmMaxCharWidth); 
bDone = bDone && (pFS[iLoc].tm.tmWeight==tmTmp.tmWeight);
bDone = bDone && (pFS[iLoc].tm.tmItalic==tmTmp.tmItalic);
bDone = bDone && (pFS[iLoc].tm.tmUnderlined==tmTmp.tmUnderlined);
bDone = bDone && (pFS[iLoc].tm.tmStruckOut==tmTmp.tmStruckOut);
bDone = bDone && (pFS[iLoc].tm.tmFirstChar==tmTmp.tmFirstChar);
bDone = bDone && (pFS[iLoc].tm.tmLastChar==tmTmp.tmLastChar);
bDone = bDone && (pFS[iLoc].tm.tmDefaultChar==tmTmp.tmDefaultChar);
bDone = bDone && (pFS[iLoc].tm.tmBreakChar==tmTmp.tmBreakChar);
bDone = bDone && (pFS[iLoc].tm.tmPitchAndFamily==tmTmp.tmPitchAndFamily);
bDone = bDone && (pFS[iLoc].tm.tmCharSet==tmTmp.tmCharSet);
// Did it work?
if (bDone) {
*lplf = lfDlg;
//EndDialog(hwnd, TRUE);
//return (TRUE);
} else {
// Again, font verification code is'nt quite up to
// snuff yet, so just Select the font anyway:
*lplf = lfDlg;

// ...and this is what we want to do once we fix the
// font verification code:
//lfDlg = *lplf;
//MessageBox (GetFocus(),
// "Unable to re-create font from TextMetrics",
// "FontView", MB_OK);
}


GlobalUnlock (pFL->hList);
}
}
GlobalUnlock (hFonts);
}


// Now set our master lf to this value. This way, we 'could' verify that the
// LOGFONT structure will in fact select this particular font, we just aren't yet
// *lplf = lfDlg;

pFL = (LPFONTLIST)GlobalLock (hFonts);
if (pFL) {
if (GlobalFree (pFL->hList)) {
MessageBox (GetFocus(), "Failed To Free", "pFL->hList", MB_OK);
} else {
GlobalUnlock (hFonts);
if (GlobalFree (hFonts)) {
MessageBox (GetFocus(), "Failed To Free", "hFonts", MB_OK);
}
}
}
EndDialog(hwnd, TRUE);
return (bDone);

case IDCANCEL:
pFL = (LPFONTLIST)GlobalLock (hFonts);
if (pFL) {
if (GlobalFree (pFL->hList)) {
MessageBox (GetFocus(), "Failed To Free", "pFL->hList", MB_OK);
} else {
GlobalUnlock (hFonts);
if (GlobalFree (hFonts)) {
MessageBox (GetFocus(), "Failed To Free", "hFonts", MB_OK);
}
}
}
EndDialog(hwnd, TRUE);
return (TRUE);
}
break;
}
return (FALSE);

lParam; // unreferenced formal parameter
}