FONT.C

/************************************************************************ 

File: font.c

Purpose:

Contains all functions pertinent to CDTEST's Font dialog.

Functions:

DoFontDlg() -- Creates CDTEST's font dialog.

FontProc() -- Callback for CDTEST's font dialog.

InitFontStruct() -- Fills a CHOOSEFONT structure with some defaults.

FillFontDlg() -- Fills CDTEST's font dialog with the contents
of a CHOOSEFONT structure.

GetFontDlg() -- Retrieves the contents of CDTEST's font dialog
and fills a CHOOSEFONT structure with them.

GetHdc() -- Creates and returns an HDC

LogFontProc() -- Callback function for the logfont dlg.

InitLogFontStruct() -- Fills a LOGFONT structure with some defaults.

FillLogFontDlg() -- Fills the LOGFONT dlg with the values in
a LOGFONT structure.

GetLogFontDlg() -- Retrieves the user's edits in the LogFont dlg
and puts them in a LOGFONT structure.

FontHookProc() -- Callback function for CHOOSEFONT->lpfnHook

GetFontDlgHandle() -- Creates a handle to the custom template and
returns a handle to it.

EnumFontsProc() -- Callback function for EnumFontFamilies()

FillFontsBox() -- Fills CDTEST's font list box with requested fonts

ResetCheckBoxes() -- handles the font choices check box manipulations

HandleFontCheckBox() -- Handles the WM_COMMAND messages from the font
choices check boxes.

DoChooseFontStuff() -- Calls the ChooseFont() function.

FontThreadProc1() -- Starting address for the first thread.

FontThreadProc2() -- Starting address for the second thread.

MultiThreadFontDlg() -- Creates two threads which each create a
ChooseFont() dialog.

FontEnableButtons() -- Enables or disables CDTEST's font dialog buttons.
Necessary for multithreading part of this app.

************************************************************************/


#include <windows.h>
#include <commdlg.h>
#include <stdlib.h>
#include <winnls.h>
#include "cdtest.h"
#include "font.h"
#include "logfont.h"



/* some definitions that will help us tell the difference between
screen and printer fonts */

#define FONT_TYPE_WYSIWYG 1
BOOL bScreen ;



/* function prototypes and general variables */

void InitFontStruct(HWND, LPCHOOSEFONT) ;
void FillFontDlg(HWND, LPCHOOSEFONT) ;
void GetFontDlg(HWND, LPCHOOSEFONT) ;
HDC GetHdc(HWND, int) ;
void InitLogFontStruct(HWND, LPLOGFONT) ;
void FillLogFontDlg(HWND, LPLOGFONT) ;
void GetLogFontDlg(HWND, LPLOGFONT) ;
BOOL APIENTRY LogFontProc(HWND, UINT, UINT, LONG) ;
UINT APIENTRY FontHookProc(HWND, UINT, UINT, LONG) ;
int CALLBACK EnumFontsProc(LPLOGFONT, LPTEXTMETRIC, DWORD, LONG) ;
void FillFontsBox(HWND, DWORD) ;
void ResetCheckBoxes(HWND) ;
void HandleFontCheckBox(HWND, int) ;
void DoChooseFontStuff(HWND, LPCHOOSEFONT) ;



/* Global variables and some external variables and functions */

DWORD dwFontFlag ;
PRINTDLG pfd ;
BOOL bLogFontParam ;
LOGFONT lfWM_CF_LF ; //for the WM_CHOOSEFONT_GETLOGFONT message
extern UINT uMode ;
extern LONG MyAtol(LPTSTR, BOOL, LPBOOL) ;
HANDLE hResFont, hDialogFont ;
HANDLE GetFontDlgHandle(void) ;
CHOOSEFONT cf ;
LOGFONT lf ;
HDC hdc ;
TCHAR szFaceName[50] ;
TCHAR szFontTemplate[50] ;
TCHAR szFontStyle[50] ;
#define HDCSCREEN 1
#define HDCPRINTER 2
#define HDCNULL 3
#define HDCINVALID 4
INT nHdcType ;



/* Multithreading stuff */

HANDLE hFontThread1 ;
HANDLE hFontThread2 ;
DWORD dwFontThreadID1 ;
DWORD dwFontThreadID2 ;
DWORD dwFontThreadParm1 ;
DWORD dwFontThreadParm2 ;
DWORD FontThreadProc1(LPDWORD) ;
DWORD FontThreadProc2(LPDWORD) ;
HANDLE hwndMainFont ;
int nOpenFontDialogCount ;
CHOOSEFONT cfThread1 ;
CHOOSEFONT cfThread2 ;
void MultiThreadFontDlg(void) ;
void EnableFontButtons(HWND, BOOL) ;




/************************************************************************

Function: DoFontDlg(HWND)

Purpose:

To create the CDTEST's font dialog

Returns: Nothing.

Comments:


************************************************************************/

void DoFontDialog(HWND hwnd)
{


DialogBox(hInst, MAKEINTRESOURCE(ID_FONTDIALOG),
hwnd, FontProc) ;

}







/************************************************************************

Function: FontProc(HWND, UINT, UINT, LONG)

Purpose:

Callback function for CDTEST's font dialog.

Returns: TRUE or FALSE depending on the situation.

Comments:


************************************************************************/


BOOL APIENTRY FontProc(HWND hwnd, UINT msg, UINT wParam, LONG lParam)
{
BOOL b ;
TCHAR szNum[30] ;

switch (msg)
{
case WM_INITDIALOG:

InitLogFontStruct(hwnd, &lf) ; //fill (struct lf) so the choosefont
InitFontStruct(hwnd, &cf) ; //struct can use it
FillFontDlg(hwnd, &cf) ;

CheckRadioButton(hwnd, ID_HDCSCREEN, ID_HDCPRINTER, ID_HDCSCREEN) ;
nHdcType = HDCSCREEN ;

dwFontFlag = cf.Flags ;

FillFontsBox(hwnd, dwFontFlag) ;

ResetCheckBoxes(hwnd) ;

*(&cfThread1) = *(&cfThread2) = *(&cf) ;

hwndMainFont = hwnd ;
nOpenFontDialogCount = 0 ;

SetFocus(GetDlgItem(hwnd, ID_STRUCTSIZEF)) ;

break ;


case UMSG_DECREMENTDLGCOUNT: // user defined message. This is send by
// the functions that are executing when
// a new thread is created. When these
// Thread functions end, they should send
// this message.

nOpenFontDialogCount-- ;

if (nOpenFontDialogCount == 0)
EnableFontButtons(hwnd, TRUE) ;

break ;


case WM_CF_LF:

/* If this message comes in, we know that the user clicked the
button that tells the ChooseFont() dialog to tell the parent
to send the WM_CHOOSEFONT_GETLOGFONT message. So what we will
do is send the message and then show the user what was in the
logfont by calling creating the Logfont dialog box */


SendMessage((HWND) lParam, WM_CHOOSEFONT_GETLOGFONT,
0, (LPARAM) &lfWM_CF_LF) ;

bLogFontParam = TRUE ; //tells us if we are doing normal logfont
//processing or answering the WM_CF_LF message.

DialogBoxParam(hInst, MAKEINTRESOURCE(ID_LOGFONTDIALOG),
(HWND) lParam, LogFontProc, (LPARAM) &lf) ;

bLogFontParam = FALSE ;

break ;


case WM_COMMAND:
{
switch (LOWORD(wParam))
{
case IDOK:
DoChooseFontStuff(hwnd, &cf) ; //create the dialog.
break ;

case IDCANCEL:
EndDialog(hwnd, FALSE) ;
break ;

case ID_RESETFONT:

InitLogFontStruct(hwnd, &lf) ; //reset all the structures.
InitFontStruct(hwnd, &cf) ;
FillFontDlg(hwnd, &cf) ; //refill the dialog.

CheckRadioButton(hwnd, ID_HDCSCREEN, ID_HDCPRINTER, ID_HDCSCREEN) ;
nHdcType = HDCSCREEN ;

SendDlgItemMessage(hwnd, ID_NULLSTRUCTFONT, BM_SETCHECK, (WPARAM) 0, (LPARAM)0) ;
SendDlgItemMessage(hwnd, ID_PRELOADEDFONT, BM_SETCHECK, (WPARAM) 0, (LPARAM)0) ;

dwFontFlag = cf.Flags ;
FillFontsBox(hwnd, dwFontFlag) ;
ResetCheckBoxes(hwnd) ;

SetFocus(GetDlgItem(hwnd, ID_STRUCTSIZEF)) ;

break ;


case ID_HDCSCREEN:
nHdcType = HDCSCREEN ;
break ;

case ID_HDCPRINTER:
nHdcType = HDCPRINTER ;
break ;

case ID_HDCNULL:
nHdcType = HDCNULL ;
break ;

case ID_HDCINVALID:
nHdcType = HDCINVALID ;
break ;

case ID_EDITLOGFONT:

/* Get the address of the logfont and then show the user what
is in it with the Logfont dialog box */

GetDlgItemText(hwnd, ID_LOGFONTF, szNum, 30) ;
cf.lpLogFont = (LPLOGFONT) MyAtol(szNum, uMode==IDM_HEXMODE, &b) ;

DialogBox(hInst, MAKEINTRESOURCE(ID_LOGFONTDIALOG),
hwnd, LogFontProc) ;
break ;


case F_TTONLY:
case F_ANSIONLY:
case F_PRINTERFONTS:
case F_SCREENFONTS:
case F_FIXEDPITCHONLY:
case F_NOOEMFONTS:
case F_NOVECTORFONTS:
case F_SCALABLEONLY:
case F_WYSIWYG:
HandleFontCheckBox(hwnd, LOWORD(wParam)) ;
break ;


case ID_MULTITHREADFONT:

/* Set the dialog count to 2, disable the buttons in CDTEST's font
dialog so the user can't do anything until last dialog has
been terminated */

nOpenFontDialogCount = 2 ;

EnableFontButtons(hwndMainFont, FALSE) ;

/* And then do the multithreading */

MultiThreadFontDlg() ;

break ;


default: break ;
}
}

default:

/*
If the help button is pressed in the ChooseFont()
dialog, it will send a message Registered with RegisterWindowMessage()
to the parent window. The message nHelpMessage was registered
at application startup

It must be detected with an IF statement because the value
returned by RegisterWindowMessage() is not a constant
*/

if (msg == nHelpMessage)
MessageBox(GetForegroundWindow(), TEXT("Hello from the help button"),
TEXT("Font Help Button"), MB_OK | MB_APPLMODAL) ;
break ;
}

return FALSE ;
}








/************************************************************************

Function: InitFontStruct(HWND, LPCHOOSEFONT)

Purpose:

Fill the CHOOSEFONT structure passed as the second parameter with
some default values.

Returns: Nothing.

Comments:


************************************************************************/

void InitFontStruct(HWND hwnd, LPCHOOSEFONT pcf)
{
pcf->lStructSize = sizeof(CHOOSEFONT) ;
pcf->hwndOwner = hwnd ;
pcf->hDC = (HDC) 0 ;
pcf->lpLogFont = &lf ;
pcf->iPointSize = 24 ;
pcf->Flags = CF_EFFECTS | CF_SCREENFONTS | CF_INITTOLOGFONTSTRUCT | CF_SHOWHELP | CF_APPLY ;
pcf->rgbColors = RGB(0, 255, 0) ;
pcf->lCustData = 0L ;
pcf->lpfnHook = FontHookProc ;

lstrcpy(szFontTemplate, TEXT("fonttemp")) ;
pcf->lpTemplateName = szFontTemplate ;

pcf->hInstance = (HANDLE) hInst ;

lstrcpy(szFontStyle, TEXT("Bold")) ;
pcf->lpszStyle = szFontStyle ;

pcf->nFontType = SCREEN_FONTTYPE ;

pcf->nSizeMin = 8 ;
pcf->nSizeMax = 50 ;
}










/************************************************************************

Function: FillFontDlg(HWND, LPCHOOSEFONT)

Purpose:

Fill CDTEST's font dialog with the values in the CHOOSEFONT structure
passed via the second parameter.

Returns: Nothing.

Comments:


************************************************************************/

void FillFontDlg(HWND hwnd, LPCHOOSEFONT pcf)
{
wsprintf(szTemp, szLongFilter, pcf->lStructSize) ;
SetDlgItemText(hwnd, ID_STRUCTSIZEF, szTemp) ;

wsprintf(szTemp, szLongFilter, (DWORD) pcf->hwndOwner) ;
SetDlgItemText(hwnd, ID_HWNDOWNERF, szTemp) ;

wsprintf(szTemp, szLongFilter, (DWORD) pcf->hDC) ;
SetDlgItemText(hwnd, ID_HDCF, szTemp) ;

wsprintf(szTemp, szLongFilter, (DWORD) pcf->hDC) ;
SetDlgItemText(hwnd, ID_HDCF, szTemp) ;

wsprintf(szTemp, szLongFilter, (DWORD) pcf->lpLogFont) ;
SetDlgItemText(hwnd, ID_LOGFONTF, szTemp) ;

wsprintf(szTemp, szLongFilter, (DWORD) pcf->iPointSize) ;
SetDlgItemText(hwnd, ID_POINTSIZEF, szTemp) ;

wsprintf(szTemp, szLongFilter, pcf->Flags) ;
SetDlgItemText(hwnd, ID_FLAGSF, szTemp) ;

wsprintf(szTemp, szLongFilter, pcf->rgbColors) ;
SetDlgItemText(hwnd, ID_RGBCOLORSF, szTemp) ;

wsprintf(szTemp, szLongFilter, pcf->lCustData) ;
SetDlgItemText(hwnd, ID_CUSTDATAF, szTemp) ;

wsprintf(szTemp, szLongFilter, (DWORD) pcf->lpfnHook) ;
SetDlgItemText(hwnd, ID_HOOKF, szTemp) ;

SetDlgItemText(hwnd, ID_TEMPLATEF, pcf->lpTemplateName) ;

wsprintf(szTemp, szLongFilter, (DWORD) pcf->hInstance) ;
SetDlgItemText(hwnd, ID_HINSTANCEF, szTemp) ;

SetDlgItemText(hwnd, ID_STYLEF, pcf->lpszStyle) ;

wsprintf(szTemp, szLongFilter, (int) pcf->nFontType) ;
SetDlgItemText(hwnd, ID_FONTTYPEF, szTemp) ;

wsprintf(szTemp, szLongFilter, (int) pcf->nSizeMin) ;
SetDlgItemText(hwnd, ID_SIZEMINF, szTemp) ;

wsprintf(szTemp, szLongFilter, (int) pcf->nSizeMax) ;
SetDlgItemText(hwnd, ID_SIZEMAXF, szTemp) ;

}







/************************************************************************

Function: GetFontDlg(HWND, LPCHOOSEFONT)

Purpose:

Retrieve the users edits from CDTEST's font dialog and put them
in the CHOOSEFONT structure passed in as the second parameter

Returns: Nothing.

Comments:


************************************************************************/

void GetFontDlg(HWND hwnd, LPCHOOSEFONT pcf)
{
BOOL b ;
TCHAR szNum[30] ;

#define WSIZEFO 30

GetDlgItemText(hwnd, ID_STRUCTSIZEF, szNum, WSIZEFO) ;
pcf->lStructSize = MyAtol(szNum, uMode == IDM_HEXMODE, &b) ;

GetDlgItemText(hwnd, ID_HWNDOWNERF, szNum, WSIZEFO) ;
pcf->hwndOwner = (HWND) MyAtol(szNum, uMode == IDM_HEXMODE, &b) ;

GetDlgItemText(hwnd, ID_LOGFONTF, szNum, WSIZEFO) ;
pcf->lpLogFont = (LPLOGFONT) MyAtol(szNum, uMode == IDM_HEXMODE, &b) ;

GetDlgItemText(hwnd, ID_POINTSIZEF, szNum, WSIZEFO) ;
pcf->iPointSize = (int) MyAtol(szNum, uMode == IDM_HEXMODE, &b) ;

GetDlgItemText(hwnd, ID_FLAGSF, szNum, WSIZEFO) ;
pcf->Flags = MyAtol(szNum, uMode == IDM_HEXMODE, &b) ;

GetDlgItemText(hwnd, ID_RGBCOLORSF, szNum, WSIZEFO) ;
pcf->rgbColors = MyAtol(szNum, uMode == IDM_HEXMODE, &b) ;

GetDlgItemText(hwnd, ID_CUSTDATAF, szNum, WSIZEFO) ;
pcf->lCustData = MyAtol(szNum, uMode == IDM_HEXMODE, &b) ;

GetDlgItemText(hwnd, ID_HOOKF, szNum, WSIZEFO) ;
pcf->lpfnHook = (LPCFHOOKPROC) MyAtol(szNum, uMode == IDM_HEXMODE, &b) ;

GetDlgItemText(hwnd, ID_TEMPLATEF, szFontTemplate, 50) ;

GetDlgItemText(hwnd, ID_HINSTANCEF, szNum, WSIZEFO) ;
pcf->hInstance = (HANDLE) MyAtol(szNum, uMode == IDM_HEXMODE, &b) ;

GetDlgItemText(hwnd, ID_STYLEF, szFontStyle, 50) ;

GetDlgItemText(hwnd, ID_FONTTYPEF, szNum, WSIZEFO) ;
pcf->nFontType = (int) MyAtol(szNum, uMode == IDM_HEXMODE, &b) ;

GetDlgItemText(hwnd, ID_SIZEMINF, szNum, WSIZEFO) ;
pcf->nSizeMin = (int) MyAtol(szNum, uMode == IDM_HEXMODE, &b) ;

GetDlgItemText(hwnd, ID_SIZEMAXF, szNum, WSIZEFO) ;
pcf->nSizeMax = (int) MyAtol(szNum, uMode == IDM_HEXMODE, &b) ;
}







/************************************************************************

Function: GetHdc(HWND, int)

Purpose:

Creates and returns an HDC of the type specified.


Returns: The HDC that it creates.


Comments:

The NULL and INVALID HDCs are only useful to test if the common dialogs
handle an HDC that is not useful, but this function is also necessary
in that the HDC must be a printer HDC if ChooseFont() is called
with the CF_PRINTERFONTS flag bit set.

To tell ChooseFont() to list only printer fonts:

1. Set the HDC in CDTEST's font dialog to "Printer"

2. Set the "Flags" edit box CF_PRINTERFONTS


************************************************************************/



HDC GetHdc(HWND hwnd, int nType)
{
switch (nType)
{
case HDCSCREEN:
return GetDC(hwnd) ;
break ;

case HDCNULL:
return (HDC) 0 ;
break ;

case HDCINVALID:
return (HDC) 999 ;
break ;

case HDCPRINTER:

/* To get the HDC of the current printer, fill out a PRINTDLG
structure, and set it's flags to (PD_RETURNDC | PD_RETURNDEFAULT).
This will tell PrintDlg() to create you an HDC but not show
the Print dialog box. */

pfd.lStructSize = sizeof(PRINTDLG) ;
pfd.hwndOwner = hwnd ;
pfd.hDevMode = (HANDLE) 0 ;
pfd.hDevNames = (HANDLE) 0 ;
pfd.Flags = PD_RETURNDC | PD_RETURNDEFAULT ; //just get default printer
pfd.nFromPage = 0 ;
pfd.nToPage = 0 ;
pfd.nMinPage = 0 ;
pfd.nMaxPage = 0 ;
pfd.nCopies = 0 ;
pfd.hInstance = (HANDLE) hInst ;

if (PrintDlg(&pfd) == 0)
MessageBox(hwnd, TEXT("Error: Could not create a printer DC!"),
(LPTSTR) NULL, MB_OK | MB_ICONEXCLAMATION | MB_APPLMODAL) ;
else
return pfd.hDC ;

break ;

default:
break ;
}
return (HDC) 0 ;
}









/************************************************************************

Function: LogFontProc(HWND, int)

Purpose:

The callback proc for the LogFont dialog box


Returns: BOOL -- depending on the situation.


Comments:

************************************************************************/


BOOL APIENTRY LogFontProc(HWND hwnd, UINT msg, UINT wParam, LONG lParam)
{
switch (msg)
{
case WM_INITDIALOG:
FillLogFontDlg(hwnd, cf.lpLogFont) ; //start off with the one that
//is returned from ChooseFont()
break ;

case WM_COMMAND:
switch(LOWORD(wParam))
{
case IDOK:

GetLogFontDlg(hwnd, &lf) ;

cf.lpLogFont = &lf ;

EndDialog(hwnd, TRUE) ;

break ;



case ID_RESETLF:

SetFocus(GetDlgItem(hwnd, ID_LFHEIGHT)) ;

InitLogFontStruct(hwnd, &lf) ;

FillLogFontDlg(hwnd, &lf) ;

break ;


case IDCANCEL:

EndDialog(hwnd, FALSE) ;

break ;


default:
break ;
}

default: break ;
}


return FALSE ;
}







/************************************************************************

Function: InitLogFontStruct(HWND, LPLOGFONT)

Purpose:

Fills the LOGFONT structure passed in as the second parameter with
some default values.

Returns: Nothing.

Comments:

************************************************************************/

void InitLogFontStruct(HWND hwnd, LPLOGFONT plf)
{
plf->lfHeight = 24 ;
plf->lfWidth = 20 ;
plf->lfEscapement = 0 ;
plf->lfOrientation = 10 ;
plf->lfWeight = 400 ;
plf->lfItalic = FALSE ;
plf->lfUnderline = FALSE ;
plf->lfStrikeOut = FALSE ;
plf->lfCharSet = ANSI_CHARSET ;
plf->lfOutPrecision = OUT_DEFAULT_PRECIS ;
plf->lfClipPrecision = CLIP_DEFAULT_PRECIS ;
plf->lfQuality = DEFAULT_QUALITY ;
plf->lfPitchAndFamily = DEFAULT_PITCH | FF_DONTCARE ;

szFaceName[0] = (TCHAR) 0 ;
lstrcpy(plf->lfFaceName, szFaceName) ;
}






/************************************************************************

Function: FillLogFontDlg(HWND, LPLOGFONT)

Purpose:

Fills CDTEST's logfont dialog with the values in the logfont that
is passed in as the second parameter.

Returns: Nothing.

Comments:

************************************************************************/

void FillLogFontDlg(HWND hwnd, LPLOGFONT plf)
{
TCHAR szTemp[50] ;

LPLOGFONT pl = plf ;

if (bLogFontParam) //Are creating this dialog in response to the
pl = &lfWM_CF_LF ; //WM_CHOOSEFONT_GETLOGFONT message ?

if (!pl) //Avert a ghastly exception error
return ;

wsprintf(szTemp, szLongFilter, pl->lfHeight) ;
SetDlgItemText(hwnd, ID_LFHEIGHT, szTemp) ;

wsprintf(szTemp, szLongFilter, pl->lfWidth) ;
SetDlgItemText(hwnd, ID_LFWIDTH, szTemp) ;

wsprintf(szTemp, szLongFilter, pl->lfEscapement) ;
SetDlgItemText(hwnd, ID_LFESCAPEMENT, szTemp) ;

wsprintf(szTemp, szLongFilter, pl->lfOrientation) ;
SetDlgItemText(hwnd, ID_LFORIENTATION, szTemp) ;

wsprintf(szTemp, szLongFilter, pl->lfWeight) ;
SetDlgItemText(hwnd, ID_LFWEIGHT, szTemp) ;

wsprintf(szTemp, szShortFilter, pl->lfItalic) ;
SetDlgItemText(hwnd, ID_LFITALIC, szTemp) ;

wsprintf(szTemp, szShortFilter, pl->lfUnderline) ;
SetDlgItemText(hwnd, ID_LFUNDERLINE, szTemp) ;

wsprintf(szTemp, szShortFilter, pl->lfStrikeOut) ;
SetDlgItemText(hwnd, ID_LFSTRIKEOUT, szTemp) ;

wsprintf(szTemp, szShortFilter, pl->lfCharSet) ;
SetDlgItemText(hwnd, ID_LFCHARSET, szTemp) ;

wsprintf(szTemp, szShortFilter, pl->lfOutPrecision) ;
SetDlgItemText(hwnd, ID_LFOUTP, szTemp) ;

wsprintf(szTemp, szShortFilter, pl->lfClipPrecision) ;
SetDlgItemText(hwnd, ID_LFCLIPP, szTemp) ;

wsprintf(szTemp, szShortFilter, pl->lfQuality) ;
SetDlgItemText(hwnd, ID_LFQUALITY, szTemp) ;

wsprintf(szTemp, szShortFilter, pl->lfPitchAndFamily) ;
SetDlgItemText(hwnd, ID_LFPITCHANDFAM, szTemp) ;

SetDlgItemText(hwnd, ID_LFFACENAME, (LPTSTR) pl->lfFaceName) ;
}






/************************************************************************

Function: GetLogFontDlg(HWND, LPLOGFONT)

Purpose:

Retrieves the users edits in CDTEST's Logfont dialog and puts them
into the LOGFONT struct that is passed as the second parameter.

Returns: Nothing.

Comments:

************************************************************************/

void GetLogFontDlg(HWND hwnd, LPLOGFONT plf)
{
BOOL b ;
TCHAR szNum[30] ;

if (bLogFontParam) //if we are just viewing the logfont because we sent a
return ; //WM_CHOOSEFONT_GETLOGFONT message, don't change the Logfont Struct
//that ChooseFont() gives us...

#define LFSIZE 30

GetDlgItemText(hwnd, ID_LFHEIGHT, szNum, LFSIZE) ;
plf->lfHeight = MyAtol(szNum, uMode == IDM_HEXMODE, &b) ;

GetDlgItemText(hwnd, ID_LFWIDTH, szNum, LFSIZE) ;
plf->lfWidth = MyAtol(szNum, uMode == IDM_HEXMODE, &b) ;

GetDlgItemText(hwnd, ID_LFESCAPEMENT, szNum, LFSIZE) ;
plf->lfEscapement = MyAtol(szNum, uMode == IDM_HEXMODE, &b) ;

GetDlgItemText(hwnd, ID_LFORIENTATION, szNum, LFSIZE) ;
plf->lfOrientation = MyAtol(szNum, uMode == IDM_HEXMODE, &b) ;

GetDlgItemText(hwnd, ID_LFWEIGHT, szNum, LFSIZE) ;
plf->lfWeight = MyAtol(szNum, uMode == IDM_HEXMODE, &b) ;

GetDlgItemText(hwnd, ID_LFITALIC, szNum, LFSIZE) ;
plf->lfItalic = (BYTE) MyAtol(szNum, uMode == IDM_HEXMODE, &b) ;

GetDlgItemText(hwnd, ID_LFUNDERLINE, szNum, LFSIZE) ;
plf->lfUnderline = (BYTE) MyAtol(szNum, uMode == IDM_HEXMODE, &b) ;

GetDlgItemText(hwnd, ID_LFSTRIKEOUT, szNum, LFSIZE) ;
plf->lfStrikeOut = (BYTE) MyAtol(szNum, uMode == IDM_HEXMODE, &b) ;

GetDlgItemText(hwnd, ID_LFCHARSET, szNum, LFSIZE) ;
plf->lfCharSet = (BYTE) MyAtol(szNum, uMode == IDM_HEXMODE, &b) ;

GetDlgItemText(hwnd, ID_LFOUTP, szNum, LFSIZE) ;
plf->lfOutPrecision = (BYTE) MyAtol(szNum, uMode == IDM_HEXMODE, &b) ;

GetDlgItemText(hwnd, ID_LFCLIPP, szNum, LFSIZE) ;
plf->lfClipPrecision = (BYTE) MyAtol(szNum, uMode == IDM_HEXMODE, &b) ;

GetDlgItemText(hwnd, ID_LFQUALITY, szNum, LFSIZE) ;
plf->lfQuality = (BYTE) MyAtol(szNum, uMode == IDM_HEXMODE, &b) ;

GetDlgItemText(hwnd, ID_LFPITCHANDFAM, szNum, LFSIZE) ;
plf->lfPitchAndFamily = (BYTE) MyAtol(szNum, uMode == IDM_HEXMODE, &b) ;

GetDlgItemText(hwnd, ID_LFFACENAME, (LPTSTR) plf->lfFaceName, 32) ;
}








/************************************************************************

Function: FontHookProc(HWND, UINT, UINT, LONG)

Purpose: The callback function that acts as the hook proc for
the ChooseFont() dialog.


Returns: TRUE to discard the message. FALSE to send the message on
to the normal dialog processing done by the ChooseFont()
function.

Comments:

************************************************************************/

UINT APIENTRY FontHookProc(HWND hwnd, UINT msg, UINT wParam, LONG lParam)
{
LPCHOOSEFONT pCf ;
TCHAR szMsg[50] ;

switch(msg)
{
case WM_INITDIALOG:

pCf = (LPCHOOSEFONT) lParam ;

if (pCf->lCustData != 0L)
{
wsprintf(szMsg, TEXT("CHOOSEFONT->lCustData is: %ld"), pCf->lCustData) ;
MessageBox(hwnd, szMsg, TEXT("lCustData Sent!"), MB_OK) ;
}

SetWindowText(hwnd, TEXT("Font Hook Proc Dialog")) ;

break ;

case WM_COMMAND:

/* NOTE: This button will only be available if the user creates the
ChooseFont() dialog with the CF_ENABLETEMPLATE or CF_ENABLETEMPLATEHANDLE
flag.

This button will only work if the ChooseFont() dialog is created
with the CF_ENABLEHOOK flag. So, to get full functionality from
this button:

1. Enter (CF_ENABLEHOOK | CF_ENABLETEMPLATE | CF_SCREENFONTS)
in the "Flags" edit box of CDTEST'S Font dialog.

2. Click OK
*/



/* The parent will send the WM_CHOOSEFONT_GETLOGFONT message and
display it's findings in a LogFont dialog if it gets this message */

if (LOWORD(wParam) == ID_SEND_WM_CF_LF_MSG)
SendMessage(GetParent(hwnd), WM_CF_LF, 0, (LPARAM) hwnd) ;

break ;


default:
break ;
}

return FALSE ; //send msg to the common dialog code
}









/************************************************************************

Function: GetFontDlgHandle(void)

Purpose: Finds and loads the custom template resource and returns a
handle to it.


Returns: A handle to the custom template resource.

Comments:

************************************************************************/

HANDLE GetFontDlgHandle(void)
{

hResFont = FindResource(hInst, TEXT("fonttemp"), RT_DIALOG) ;

hDialogFont = LoadResource(hInst, hResFont) ;


return hDialogFont ;
}








/************************************************************************

Function: EnumFontsProc(LPLOGFONT, LPTEXTMETRIC, DWORD, LONG)

Purpose: Acts as a callback function for the EnumFontFamilies()
function.

Returns: 0 if the font enumeration should stop. 1 to ask for the
next font.

Comments:

EnumFontFamilies will find the fonts on the system and call this
function each time it finds a font. Pointers to the LOGFONT and
TEXTMETRIC structures the describe the font are passed as the first
and second arguments, so we can determine if the fonts we get
meet the specs we want. If they do, we can add them to the font
list box in CDTEST's Font dialog.

NOTE:

None of this affects the performance of ChooseFont(). This serves
only to illustrate how ChooseFont() finds the fonts you request based
on the flags you pass to the ChooseFont() function.

The fonts found with this function should be the same as the ones
found by ChooseFont() for any flag combination.


************************************************************************/


int CALLBACK EnumFontsProc(LPLOGFONT lplf, LPTEXTMETRIC lptm,
DWORD dwStyle, LONG lParam)
{
UINT i ;

/* check to see if the font is already there right off the bat
and just continue the enumeration if it is... */


i = SendDlgItemMessage((HWND) lParam, ID_FONTLIST, LB_FINDSTRINGEXACT, (WPARAM) 0,
(LONG) (LPTSTR) lplf->lfFaceName) ;

if (i != LB_ERR)
{
if (bScreen) //if we are adding it for the first time
return 1 ;

//else, we are adding printer fonts, so if we find one that is already there

//it must be available for both the printer and the screen... 

else
{
SendDlgItemMessage((HWND) lParam, ID_FONTLIST, LB_SETITEMDATA, i,
FONT_TYPE_WYSIWYG) ;
return 1 ;
}
}


//Get rid of any fonts that we don't want...

if ((dwFontFlag & CF_TTONLY) && (!(dwStyle & TRUETYPE_FONTTYPE)))
return 1 ;

if ((dwFontFlag & CF_SCALABLEONLY) && (dwStyle & RASTER_FONTTYPE))
return 1 ;

if ((dwFontFlag & CF_ANSIONLY) && (lplf->lfCharSet != ANSI_CHARSET))
return 1 ;

if ((dwFontFlag & CF_FIXEDPITCHONLY) && (lplf->lfPitchAndFamily & VARIABLE_PITCH))
return 1 ;

if ((dwFontFlag & CF_NOVECTORFONTS) && (lplf->lfCharSet == OEM_CHARSET))
return 1 ;


//if there is a font to be added, add it.

if (*(lplf->lfFaceName))
SendDlgItemMessage((HWND) lParam, ID_FONTLIST, LB_ADDSTRING,
(WPARAM) 0, (LONG) (LPTSTR) lplf->lfFaceName) ;

return 1 ;
}








/************************************************************************

Function: FillFontsBox(HWND, DWORD)

Purpose: Enumerates all fonts on the system and sends the ones that
meet the criteria of the dwFlags parameter (CF_SCREENFONTS,
CF_SCALABLEONLY, etc).

Returns: Nothing.

Comments:


************************************************************************/

void FillFontsBox(HWND hwnd, DWORD dwFlags)
{
HDC hdc ;
HWND hwndControl ;
DWORD dwData ;
int nItemCount ;


/* Empty the list box, and turn of the redraw because we may need
to remove some fonts after they are added if the user calls this
function with the CF_WYSIWYG flag bit set. */

SendDlgItemMessage(hwnd, ID_FONTLIST, LB_RESETCONTENT, (WPARAM)0, (LPARAM) 0) ;

hwndControl = GetDlgItem(hwnd, ID_FONTLIST) ;

SendMessage(hwndControl, WM_SETREDRAW, FALSE, 0L) ;


/* Now call EnumFontFamilies() for each type of HDC requested */

if (dwFlags & CF_SCREENFONTS)
{
bScreen = TRUE ;
hdc = GetHdc(hwnd, HDCSCREEN) ;
EnumFontFamilies(hdc, (LPTSTR) NULL, (FONTENUMPROC) EnumFontsProc, (LONG) hwnd) ;
ReleaseDC(hwnd, hdc) ;
}

if (dwFlags & CF_PRINTERFONTS)
{
bScreen = FALSE ;
hdc = GetHdc(hwnd, HDCPRINTER) ;
EnumFontFamilies(hdc, (LPTSTR) NULL, (FONTENUMPROC) EnumFontsProc, (LONG) hwnd) ;
ReleaseDC(hwnd, hdc) ;
}


/* Special case: If the CF_WYSIWYG flag is used, we have to enumerate
the fonts in both HDCs and then remove all the ones that are not
both printer fonts and screen fonts. */

if (dwFontFlag & CF_WYSIWYG)
{
nItemCount = SendDlgItemMessage(hwnd, ID_FONTLIST, LB_GETCOUNT, 0, 0L) ;

nItemCount-- ; //the list is zero based

while (nItemCount >= 0)
{
dwData = SendDlgItemMessage(hwnd, ID_FONTLIST, LB_GETITEMDATA, nItemCount, 0L) ;

if (dwData != FONT_TYPE_WYSIWYG)
{
SendDlgItemMessage(hwnd, ID_FONTLIST, LB_DELETESTRING, nItemCount, 0L) ;
}

nItemCount-- ;
}
}


/* Now redraw the font list */

SendMessage(hwndControl, WM_SETREDRAW, TRUE, 0L) ;
InvalidateRect(hwndControl, NULL, FALSE) ;

return ;
}






/************************************************************************

Function: ResetCheckBoxes(HWND)

Purpose: Checks the checkboxes that control what fonts are listed in
CDTEST's font list box.

Returns: Nothing.

Comments:


************************************************************************/

void ResetCheckBoxes(HWND hwnd)
{

SendDlgItemMessage(hwnd, F_TTONLY, BM_SETCHECK, dwFontFlag & CF_TTONLY ? 1 : 0, (LPARAM)0) ;
SendDlgItemMessage(hwnd, F_ANSIONLY, BM_SETCHECK, dwFontFlag & CF_ANSIONLY ? 1 : 0, (LPARAM)0) ;
SendDlgItemMessage(hwnd, F_SCREENFONTS, BM_SETCHECK, dwFontFlag & CF_SCREENFONTS ? 1 : 0, (LPARAM)0) ;
SendDlgItemMessage(hwnd, F_PRINTERFONTS, BM_SETCHECK, dwFontFlag & CF_PRINTERFONTS ? 1 : 0, (LPARAM)0) ;
SendDlgItemMessage(hwnd, F_NOOEMFONTS, BM_SETCHECK, dwFontFlag & CF_NOOEMFONTS ? 1 : 0, (LPARAM)0) ;
SendDlgItemMessage(hwnd, F_NOVECTORFONTS, BM_SETCHECK, dwFontFlag & CF_NOVECTORFONTS ? 1 : 0, (LPARAM)0) ;
SendDlgItemMessage(hwnd, F_SCALABLEONLY, BM_SETCHECK, dwFontFlag & CF_SCALABLEONLY ? 1 : 0, (LPARAM)0) ;
SendDlgItemMessage(hwnd, F_WYSIWYG, BM_SETCHECK, dwFontFlag & CF_WYSIWYG ? 1 : 0, (LPARAM)0) ;
SendDlgItemMessage(hwnd, F_FIXEDPITCHONLY, BM_SETCHECK, dwFontFlag & CF_FIXEDPITCHONLY ? 1 : 0, (LPARAM)0) ;

}






/************************************************************************

Function: HandleFontCheckBox(HWND)

Purpose: If the user clicks one of the fonts in the CDTEST's list of
valid font types, this function will check the correct boxes
and set the correct values in the flag which keeps track of
which fonts are to be enumerated and added to CDTEST's font
list box.


Returns: Nothing.

Comments:

CF_NOOEMFONTS and CF_NOVECTORFONTS are identical.


************************************************************************/

void HandleFontCheckBox(HWND hwnd, int nID)
{
DWORD dwTemp ;

dwTemp = dwFontFlag ;

switch (nID)
{
case F_TTONLY:

/* TTONLY is a special case. If we only want Truetype fonts,
turn off irrelevant flags */

if (!(dwFontFlag & CF_TTONLY)) //if we're turning this flag on...
{
dwFontFlag = 0L ; //turn everyone off but the following:

dwFontFlag |= CF_TTONLY ;

if (dwTemp & CF_ANSIONLY)
dwFontFlag |= CF_ANSIONLY ;

if (dwTemp & CF_FIXEDPITCHONLY)
dwFontFlag |= CF_FIXEDPITCHONLY ;

if (dwTemp & CF_SCREENFONTS)
dwFontFlag |= CF_SCREENFONTS ;

if (dwTemp & CF_PRINTERFONTS)
dwFontFlag |= CF_PRINTERFONTS ;
}
else
{
dwFontFlag ^= CF_TTONLY ;
}


break ;

case F_ANSIONLY:
dwFontFlag ^= CF_ANSIONLY ; //otherwise toggle the bit.
dwFontFlag &= ~CF_WYSIWYG ;

break ;

case F_PRINTERFONTS:
dwFontFlag ^= CF_PRINTERFONTS ;

break ;

case F_SCREENFONTS:
dwFontFlag ^= CF_SCREENFONTS ;

break ;

case F_FIXEDPITCHONLY:
dwFontFlag ^= CF_FIXEDPITCHONLY ;

break ;

case F_NOOEMFONTS:
dwFontFlag ^= CF_NOOEMFONTS ;

break ;

case F_NOVECTORFONTS:
dwFontFlag ^= CF_NOVECTORFONTS ;

break ;

case F_SCALABLEONLY:
dwFontFlag ^= CF_SCALABLEONLY ;

break ;

case F_WYSIWYG: //We want fonts for both the
//screen and the printer...
dwFontFlag ^= CF_WYSIWYG ;

if (dwFontFlag & CF_WYSIWYG)
dwFontFlag |= (CF_SCREENFONTS | CF_PRINTERFONTS | CF_SCALABLEONLY) ;

break ;

default: break ;
}

ResetCheckBoxes(hwnd) ;
FillFontsBox(hwnd, dwFontFlag) ;
}







/************************************************************************

Function: DoChooseFontStuff(HWND, LPCHOOSEFONT)

Purpose:

Calls the ChooseFont() function.

Returns: Nothing.

Comments:


************************************************************************/


void DoChooseFontStuff(HWND hwnd, LPCHOOSEFONT pcf)
{
BOOL bRet = FALSE ;

if (IsDlgButtonChecked(hwnd, ID_PRELOADEDFONT) == 1)
{
pcf->hInstance = GetFontDlgHandle() ;
wsprintf(szTemp, szLongFilter, pcf->hInstance) ;
SetDlgItemText(hwnd, ID_HINSTANCEF, szTemp) ;
}

pcf->hDC = GetHdc(hwnd, nHdcType) ;

wsprintf(szTemp, szLongFilter, pcf->hDC) ;
SetDlgItemText(hwnd, ID_HDCF, szTemp) ;


GetFontDlg(hwnd, pcf) ;


if (IsDlgButtonChecked(hwnd, ID_NULLSTRUCTFONT) == 1)
bRet = ChooseFont((LPCHOOSEFONT)NULL) ;
else
bRet = ChooseFont(pcf) ;

wsprintf(szTemp, szLongFilter, CommDlgExtendedError()) ;
SetDlgItemText(hwnd, ID_ERRORF, szTemp) ;

if (pcf->hDC)
{
ReleaseDC(hwnd, pcf->hDC) ; //free the HDC that we used if we called
pcf->hDC = (HDC) 0 ; //the function with a valid HDC.
}

if (hDialogFont)
{
FreeResource(hDialogFont) ;
hDialogFont = (HANDLE) 0 ;
hResFont = (HANDLE) 0 ;
}

wsprintf(szTemp, szShortFilter, bRet) ; //fill results into the Font dlg
SetDlgItemText(hwnd, ID_RETURNF, szTemp) ;

FillFontDlg(hwnd, pcf) ;
}






/************************************************************************

Function: FontThreadProc1(LPDWORD)

Purpose:

Acts as the starting address for thread 1

Returns: Any DWORD value.

Comments:


************************************************************************/

DWORD FontThreadProc1(LPDWORD pdw)
{
DoChooseFontStuff(hwndMainFont, &cfThread1) ;

PostMessage(hwndMainFont, UMSG_DECREMENTDLGCOUNT, 0, 0L ) ;

return 0L ;
}







/************************************************************************

Function: FontThreadProc2(LPDWORD)

Purpose:

Acts as the starting address for thread 2

Returns: Any DWORD value.

Comments:


************************************************************************/


DWORD FontThreadProc2(LPDWORD pdw)
{
DoChooseFontStuff(hwndMainFont, &cfThread2) ;

PostMessage(hwndMainFont, UMSG_DECREMENTDLGCOUNT, 0, 0L ) ;

return 0L ;
}







/************************************************************************

Function: MultiThreadFontDlg(void)

Purpose:

Create the two threads that will in turn create two ChooseFont()
dialogs.

Returns: Nothing.

Comments:

Multithreading note:

This function will return before the common dialog functions return.
Therefore, do not pass any parameters to this function that will be
referenced by the common dialogs because as soon as this function
ends those parameters will be gone.

************************************************************************/

void MultiThreadFontDlg(void)
{

dwFontThreadParm1 = dwFontThreadParm2 = 0L ;

if (!(hFontThread1 = CreateThread((LPSECURITY_ATTRIBUTES) NULL, 0,
(LPTHREAD_START_ROUTINE) FontThreadProc1,
&dwFontThreadParm1, CREATE_SUSPENDED, &dwFontThreadID1)))

{
MessageBox(GetForegroundWindow(), TEXT("Error creating thread 1"), NULL,
MB_OK | MB_ICONEXCLAMATION | MB_APPLMODAL) ;

nOpenFontDialogCount = 0 ;

EnableFontButtons(hwndMainFont, TRUE) ;

return ;
}


if (!(hFontThread2 = CreateThread((LPSECURITY_ATTRIBUTES) NULL, 0,
(LPTHREAD_START_ROUTINE) FontThreadProc2,
&dwFontThreadParm2, CREATE_SUSPENDED, &dwFontThreadID2)))
{
MessageBox(GetForegroundWindow(), TEXT("Error creating thread 2"), NULL,
MB_OK | MB_ICONEXCLAMATION | MB_APPLMODAL) ;

nOpenFontDialogCount = 0 ;

EnableFontButtons(hwndMainFont, TRUE) ;

return ;
}

ResumeThread(hFontThread1) ;
ResumeThread(hFontThread2) ;

return ;
}






/************************************************************************

Function: EnableFontButtons(HWND, BOOL)

Purpose:

Enables or disables CDTEST's font dialogs buttons based on the
status of the second parameter.


Returns: Nothing.

Comments:

This is necessary when multithreading in the case of this application.

************************************************************************/

void EnableFontButtons(HWND hwnd, BOOL bEnable)
{
EnableWindow(GetDlgItem(hwnd, IDOK), bEnable) ;
EnableWindow(GetDlgItem(hwnd, IDCANCEL), bEnable) ;
EnableWindow(GetDlgItem(hwnd, ID_RESETFONT), bEnable) ;
EnableWindow(GetDlgItem(hwnd, ID_MULTITHREADFONT), bEnable) ;
EnableWindow(GetDlgItem(hwnd, ID_EDITLOGFONT), bEnable) ;
}