⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 choosefont.cpp

📁 Windows 图形编程 书籍
💻 CPP
字号:
//-----------------------------------------------------------------------------------//
//              Windows Graphics Programming: Win32 GDI and DirectDraw               //
//                             ISBN  0-13-086985-6                                   //
//                                                                                   //
//  Written            by  Yuan, Feng                             www.fengyuan.com   //
//  Copyright (c) 2000 by  Hewlett-Packard Company                www.hp.com         //
//  Published          by  Prentice Hall PTR, Prentice-Hall, Inc. www.phptr.com      //
//                                                                                   //
//  FileName   : choosefont.cpp					                                     //
//  Description: Customized font selection dialog box                                //
//  Version    : 1.00.000, May 31, 2000                                              //
//-----------------------------------------------------------------------------------//

// ChooseFont.cpp Customized Font Selection Dialog Box
#define STRICT
#define NOCRYPT

#pragma pack(push, 4)
#include <windows.h>
#pragma pack(pop)

#include <assert.h>
#include <tchar.h>
#include <math.h>
#include <commctrl.h>
#include <stdio.h>

#include "..\..\include\fonttext.h"
#include "..\..\include\treeview.h"
#include "..\..\include\OutlineMetric.h"

#include "ChooseFont.h"

// add a single string to a tree view

// { <tag> <format> }
// <tag>::= g |   // dword, dword, dword, dword
//          8 |   // dword, dword
//          4 |   // dword
//          2 |   // unsigned short
//          1 |   // unsigned char
//          &     // address of input data

const TCHAR Format_LOGFONT [] =
    "4lfHeight: %d\0"
	"4lfWidth:  %d\0"
	"4lfEscapement: %d\0"
	"4lfOrientation: %d\0"
	"4lfWeight: %d\0"
    "1lfItalic: %d\0"
	"1lfUnderline: %d\0"
	"1lfStrikeOut: %d\0"
	"1lfCharSet: %d\0"
	"1lfOutPrecision: %d\0"
	"1lfClipPrecision: %d\0"
	"1lfQuality: %d\0"
	"1lfPitchAndFamily: 0x%x\0"
	"&lfFaceName: %s\0";


const TCHAR Format_TEXTMETRIC [] =
	"4tmHeight: %d\0"
    "4tmAscent: %d\0"
    "4tmDescent: %d\0"
    "4tmInternalLeading: %d\0"
    "4tmExternalLeading: %d\0"
    "4tmAveCharWidth: %d\0"
    "4tmMaxCharWidth: %d\0"
    "4tmWeight: %d\0"
    "4tmOverhang: %d\0"
    "4tmDigitizedAspectX: %d\0"
    "4tmDigitizedAspectY: %d\0"
    "1tmFirstChar: %d\0"
    "1tmLastChar: %d\0"
    "1tmDefaultChar: %d\0"
    "1tmBreakChar: %d\0"
    "1tmItalic: %d\0"
    "1tmUnderlined: %d\0"
    "1tmStruckOut: %d\0"
    "1tmPitchAndFamily: 0x%x\0"
    "1tmCharSet: %d\0";

const TCHAR Format_PANOSE [] = 
	"1bFamilyType: %d\0"
	"1bSerifStyle: %d\0"
	"1bWeight: %d\0"
	"1bProportion: %d\0"
	"1bContrast: %d\0"
    "1bStrokeVariation: %d\0"
    "1bArmStyle: %d\0"
    "1bLetterform: %d\0"
    "1bMidline: %d\0"
    "1bXHeight: %d\0";

// partial
const TCHAR Format_OUTLINETEXTMETRIC1 [] =
    "4otmSize: %d\n";

const TCHAR Format_OUTLINETEXTMETRIC4 [] =
    "4otmfsSelection: 0x%x\0"
    "4otmfsType: %d\0"
	"4otmsCharSlopeRise: %d\0"
	"4otmsCharSlopeRun: %d\0"
	"4otmItalicAngle: %d\0"
	"4otmEMSquare: %d\0"
	"4otmAscent: %d\0"
	"4otmDescent: %d\0"
	"4otmLineGap: %d\0"
	"4otmsCapEmHeight: %d\0"
	"4otmsXHeight: %d\0"
	"gotmrcFontBox: {%d,%d,%d,%d}\0"
	"4otmMacAscent: %d\0"
	"4otmMacDescent: %d\0"
    "4otmMacLineGap: %d\0"
    "4otmusMinimumPPEM: %d\0"
    "8otmptSubscriptSize: {%d,%d}\0"
    "8otmptSubscriptOffset: {%d,%d}\0"
    "8otmptSuperscriptSize: (%d,%d}\0"
    "8otmptSuperscriptOffset: (%d,%d}\0"
    "4otmsStrikeoutSize: %d\0"
	"4otmsStrikeoutPosition: %d\0"
	"4otmsUnderscoreSize: %d\0"
	"4otmsUnderscorePosition: %d\0";
 
const TCHAR Format_FONTSIGNATURE [] =
	"4fsUsb[0]: 0x%08X\0"
	"4fsUsb[1]: 0x%08X\0"
	"4fsUsb[2]: 0x%08X\0"
	"4fsUsb[3]: 0x%08X\0"
	"4fsCsb[0]: 0x%08X\0"
	"4fsCsb[1]: 0x%08X\0";


HTREEITEM AddCharWidth(KTreeView & Tree, HDC hDC, const TCHAR * name, HTREEITEM hLast, int typ)
{
	hLast = Tree.InsertItem(hLast, TVI_ROOT, name);

	INT       intWidth[256];
	FLOAT     fltWidth[256];
	ABC       abcWidth[256];
	ABCFLOAT abcfWidth[256];

	UINT uFirst = ' ';
	UINT uLast  = 0x80;

	switch ( typ )
	{
		case 0:         GetCharWidth32(hDC, uFirst, uLast, intWidth);  break;
		case 1:      GetCharWidthFloat(hDC, uFirst, uLast, fltWidth);  break;
		case 2:       GetCharABCWidths(hDC, uFirst, uLast, abcWidth);  break;
		case 3:  GetCharABCWidthsFloat(hDC, uFirst, uLast, abcfWidth); break;
	}

	for (UINT ch=uFirst; ch<=uLast; ch++)
	{
		TCHAR mess[MAX_PATH];

		sprintf(mess, "%d '%c': ", ch, ch);

		TCHAR * num = mess + _tcslen(mess);

		switch ( typ )
		{
			case 0: sprintf(num, "%d",    intWidth[ch-uFirst]); break;
			case 1: sprintf(num, "%7.3f", fltWidth[ch-uFirst]); break;
			case 2: sprintf(num, "%d %d %d", abcWidth[ch-uFirst].abcA, abcWidth[ch-uFirst].abcB, abcWidth[ch-uFirst].abcC); break;
			case 3: sprintf(num, "%7.3f %7.3f %7.3f", abcfWidth[ch-uFirst].abcfA, abcfWidth[ch-uFirst].abcfB, abcfWidth[ch-uFirst].abcfC); break;
		}

		Tree.InsertItem(TVI_LAST, hLast, mess);
	}

	return hLast;
}


const term Dic_GCP [] =
{
	{	GCP_DBCS,		"GCP_DBCS"			},
	{	GCP_REORDER,	"GCP_REORDER"		},
	{	GCP_USEKERNING, "GCP_USEKERNING"	},
	{	GCP_GLYPHSHAPE, "GCP_GLYPHSHARE"	},
	{	GCP_LIGATE,		"GCP_LIGATE"		},
	{	GCP_DIACRITIC,	"GCP_DIACRITIC"		},
	{	GCP_KASHIDA,	"GCP_KASHIDA"		},
	{	GCP_ERROR,		"GCP_ERROR"			},
	{	GCP_JUSTIFY,	"GCP_JUSTIFY"		},
	{	FLI_GLYPHS,		"FLI_GLYPHS"		},
	{	0,				NULL				}
};


// Base on LOGFONT, create font, select font, decode font information in a TreeView
void DecodeFont(KTreeView & Tree, LOGFONT * pLf, int dpi)
{
	TCHAR t1[MAX_PATH], t2[MAX_PATH];

	HDC hDC     = GetDC(NULL);

	HFONT hFont = CreateFontIndirect(pLf);

	HTREEITEM hLast, h1;

	// LOGFONT
	hLast = Tree.InsertTree(TVI_LAST, TVI_ROOT, "LOGFONT", Format_LOGFONT, pLf);

	SelectObject(hDC, hFont);

	GetTextFace(hDC, MAX_PATH, t1);
	wsprintf(t2, "GetTextFace: %s", t1);

	// GetTextFace
    hLast = Tree.InsertItem(hLast,    TVI_ROOT, t2);

	// GetFontLangageInfo
	DWORD langinfo = GetFontLanguageInfo(hDC);

	wsprintf(t1, "GetFontLanguageInfo: 0x%x", langinfo);
	hLast = Tree.InsertItem(hLast, TVI_ROOT, t1);
	Tree.AddFlags(hLast, langinfo, Dic_GCP);

	// GetTextCharset
	wsprintf(t1, "GetTextCharset: 0x%x", GetTextCharset(hDC));
	hLast = Tree.InsertItem(hLast, TVI_ROOT, t1);

	{
		FONTSIGNATURE fs;
		GetTextCharsetInfo(hDC, & fs, 0);

		hLast = Tree.InsertTree(hLast, TVI_ROOT, "FONTSIGNATURE", Format_FONTSIGNATURE, & fs);
	}
	
	// TEXTMETRIC
	{
		TEXTMETRIC tm;
		GetTextMetrics(hDC, & tm);
		hLast = Tree.InsertTree(hLast, TVI_ROOT, "TEXTMETRIC", Format_TEXTMETRIC, & tm);
	}

	// OUTLINETEXTMETIRC
	{
		KOutlineTextMetric otm(hDC);

		if ( otm.m_pOtm )
		{
			// first field of OUTLINTTEXTMETRIC
			hLast = Tree.InsertTree(hLast, TVI_ROOT, "OUTLINETEXTMETRIC", Format_OUTLINETEXTMETRIC1, otm.m_pOtm);
	
			// otmTextMetrics
			h1    =	Tree.InsertTree(TVI_LAST, hLast, "otmTextMetrics: TEXTMETRIC", Format_TEXTMETRIC, & otm.m_pOtm->otmTextMetrics);

			// otmPanseNumber
			h1    =	Tree.InsertTree(h1,       hLast, "otmPanoseNumber: PANOSE",    Format_PANOSE,     & otm.m_pOtm->otmPanoseNumber);

			// main fields after PANOSE
			h1    = Tree.InsertTree(h1,       hLast, NULL,                         Format_OUTLINETEXTMETRIC4, & otm.m_pOtm->otmfsSelection);
	
			wsprintf(t1, "otmpFamilyName: %s", otm.GetName(otm.m_pOtm->otmpFamilyName));
			h1 = Tree.InsertItem(h1, hLast, t1);

			wsprintf(t1, "otmpFaceName: %s", otm.GetName(otm.m_pOtm->otmpFaceName));
			h1 = Tree.InsertItem(h1, hLast, t1);

			wsprintf(t1, "otmpStyleName: %s", otm.GetName(otm.m_pOtm->otmpStyleName));
			h1 = Tree.InsertItem(h1, hLast, t1);

			wsprintf(t1, "otmpFullName: %s", otm.GetName(otm.m_pOtm->otmpFullName));
			h1 = Tree.InsertItem(h1, hLast, t1);
		}
	}

	hLast = AddCharWidth(Tree, hDC, "GetCharWidth32",        hLast, 0);
	hLast = AddCharWidth(Tree, hDC, "GetCharWidthFloat",     hLast, 1);
	hLast = AddCharWidth(Tree, hDC, "GetCharABCWidths",      hLast, 2);
	hLast = AddCharWidth(Tree, hDC, "GetCharABCWidthsFloat", hLast, 3);

	// Kerning pairs
	{
		KKerningPair kerning(hDC);

		wsprintf(t1, "GetKerningPairs: %d pairs", kerning.m_nPairs);

		hLast = Tree.InsertItem(hLast, TVI_ROOT, t1);

		for (int i=0; i<kerning.m_nPairs; i++)
		{
			wsprintf(t1, "'%c' (%02x) '%c' (%02x) -> %d", 
				kerning.m_pKerningPairs[i].wFirst,  kerning.m_pKerningPairs[i].wFirst, 
				kerning.m_pKerningPairs[i].wSecond, kerning.m_pKerningPairs[i].wSecond, 
				kerning.m_pKerningPairs[i].iKernAmount);

			Tree.InsertItem(TVI_LAST, hLast, t1);
		}
	}

	// Cleanup
	SelectObject(hDC, GetStockObject(ANSI_FIXED_FONT));
	DeleteObject(hDC);
	DeleteObject(hFont);
}


void GenerateTree(HWND hDlg, KTreeView & Tree, int dpi)
{
	LOGFONT lf;

	SendMessage(hDlg, WM_CHOOSEFONT_GETLOGFONT, 0, (LPARAM) & lf);

	Tree.DeleteAllItems();
	DecodeFont(Tree, & lf, dpi);
}

/*
// Resolution setup dialog box: not used
class KSetup : public KDialog
{
	virtual BOOL OnInitDialog(HWND hWnd, WPARAM wParam, LPARAM lParam)
	{
		m_hWnd = hWnd;
	
		SendDlgItemMessage(hWnd, IDC_SCREEN, BM_SETCHECK, BST_CHECKED, 0);
		return TRUE;
	}
	
	virtual BOOL OnCommand(HWND hWnd, WPARAM wParam, LPARAM lParam)
	{
		switch ( LOWORD(wParam) )
		{
			case IDOK:
				{
					int rslt = 1;

					if ( SendDlgItemMessage(hWnd, IDC_120, BM_GETCHECK, 0, 0)==BST_CHECKED )
						rslt = 120;
					else if ( SendDlgItemMessage(hWnd, IDC_180, BM_GETCHECK, 0, 0)==BST_CHECKED )
						rslt = 180;
					else if ( SendDlgItemMessage(hWnd, IDC_300, BM_GETCHECK, 0, 0)==BST_CHECKED )
						rslt = 300;
					else if ( SendDlgItemMessage(hWnd, IDC_1800, BM_GETCHECK, 0, 0)==BST_CHECKED )
						rslt = 1800;

					EndDialog(hWnd, rslt);
					return TRUE;
				}
			
			case IDCANCEL:
				EndDialog(hWnd, 0);
				return TRUE;
		}

		return FALSE;
	}

};
*/

// Customized Font Selection Dialog Box
class KChooseFont
{
	typedef enum { MAX_DPINO= 5 };

	KTreeView m_Tree;
	HWND	  m_hButton[MAX_DPINO];
	int		  m_nDPI   [MAX_DPINO];

	// member hook function
	UINT HookProc(HWND hDlg, UINT uiMsg, WPARAM wParam, LPARAM lParam)
	{
		switch ( uiMsg )
		{
			case WM_INITDIALOG:
				{
					RECT rect;
					GetWindowRect(hDlg, & rect);
					// enlarge the window by 260 pixels on the right
					MoveWindow(hDlg, rect.left, rect.top, rect.right - rect.left + 260, 
						rect.bottom - rect.top, TRUE);

					// get new client area dimension
					GetClientRect(hDlg, & rect);

					// add a treeview child window on the right
					m_Tree.Create(hDlg, 1, rect.right - 270, 2, 266, rect.bottom - 4,
								(HINSTANCE) GetWindowLong(hDlg, GWL_HINSTANCE));

					GetWindowRect(GetDlgItem(hDlg, 0x402), & rect);
					MapWindowPoints(NULL, hDlg, (POINT *) & rect, 2);
					
					HDC hDC = GetDC(NULL);
					m_nDPI[0] = GetDeviceCaps(hDC, LOGPIXELSX);
					DeleteObject(hDC);

					m_nDPI[1] =  120;
					m_nDPI[2] =  180;
					m_nDPI[3] =  300;
					m_nDPI[4] = 1800;

					ReleaseDC(NULL, hDC);

/*					for (int i=0; i<MAX_DPINO; i++)
					{
						rect.top    += 30;
						rect.bottom += 30;
					
						TCHAR temp[32];
						wsprintf(temp, "%d dpi", m_nDPI[i]);
						
						m_hButton[i] = CreateWindow("BUTTON", temp,
							WS_CHILD | WS_VISIBLE | BS_AUTORADIOBUTTON,
							rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top,
							hDlg, (HMENU) (1234+i), (HINSTANCE) GetWindowLong(hDlg, GWL_HINSTANCE), NULL);

						SendMessage(m_hButton[i], WM_SETFONT, SendDlgItemMessage(hDlg, 0x402, WM_GETFONT, 0, 0), TRUE);
					}
*/
				}
				return 1;

			case WM_COMMAND:
				if ( LOWORD(wParam)==0x402 ) // APPLY button
				{
					int dpi = m_nDPI[0];

/*					for (int i=0; i<MAX_DPINO; i++)
						if ( SendMessage(m_hButton[i], BM_GETCHECK, 0, 0)==BST_CHECKED )
						{
							dpi = m_nDPI[i];
							break;
						}
*/
					GenerateTree(hDlg, m_Tree, dpi);
					return 1;
				}
		}

		return 0;
	}

	// static hook function
	static UINT CALLBACK CFHookProc(HWND hdlg, UINT uiMsg, WPARAM wParam, LPARAM lParam)
	{
		if ( uiMsg == WM_INITDIALOG )
		{
			CHOOSEFONT * p = (CHOOSEFONT *) lParam;

			if ( IsBadWritePtr(p, sizeof(CHOOSEFONT)) )
				return 0;
		
			SetWindowLong(hdlg, GWL_USERDATA, p->lCustData);
		}

		KChooseFont * p = (KChooseFont *) GetWindowLong(hdlg, GWL_USERDATA);

		if ( IsBadWritePtr(p, sizeof(KChooseFont)) )
			return 0;
		else
			return p->HookProc(hdlg, uiMsg, wParam, lParam);
	}

public:
    CHOOSEFONT m_cf; 
    LOGFONT	   m_lf; 

	HFONT ChooseFont(HINSTANCE hInstance)
	{
	    // Initialize members of the CHOOSEFONT structure. 
		memset(& m_cf, 0, sizeof(m_cf));

		m_cf.lStructSize = sizeof(CHOOSEFONT); 
		m_cf.lpLogFont   = & m_lf; 
		m_cf.Flags	     = CF_APPLY | CF_BOTH | CF_EFFECTS | CF_ENABLEHOOK; 
		m_cf.lpfnHook    = CFHookProc;
		m_cf.rgbColors   = RGB(0,0,0); 
		m_cf.nFontType   = SCREEN_FONTTYPE; 
		m_cf.lCustData   = (LPARAM) this; // pass to hook function

//		KSetup setup;

//		int rslt = setup.Dialogbox(hInstance, MAKEINTRESOURCE(IDD_SETUP));

		if ( ::ChooseFont(&m_cf) ) 
			return CreateFontIndirect(& m_lf);
		else
			return NULL;
	}
};    


void FontSelection(HINSTANCE hInst)
{
	KChooseFont cf;

	HFONT hFont = cf.ChooseFont(hInst);

	DeleteObject(hFont);
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -