引言:有时候UI设计的时候,界面显示要求显示特殊字体,而这种字体在字体库中又并没有安装,那么在程序中该如何调用该字体文件呢?下面将给你讲解实现思路:
方法一、从资源文件中加载字体资源文件
方法二、从本地硬盘加载字体文件
为此,我们将所需功能封装成类库文件,方便直接调用:
类头文件定义:
#pragma once
#include <GdiPlus.h>
using namespace Gdiplus;
class CFontHelper : public Singleton<CFontHelper>
{
public:
CFontHelper();
~CFontHelper();
public:
// 加载字体
BOOL LoadFont(UINT lpszResource, LPCTSTR lpszType = _T("ttf"));
BOOL LoadFont(char* lpszFile, LPCTSTR lpszType = _T("ttf"));
Gdiplus::Font* Font(Gdiplus::FontStyle fontstyle = FontStyleRegular, REAL nFontSize = 14.0F);
Gdiplus::FontFamily* FontFamily();
operator HFONT() const;
HFONT FontToHFONTA(HWND hWnd);
HFONT FontToHFONTW(HWND hWnd);
HFONT GetSafeHFONT(HWND hWnd);
void SetFont(HWND hWnd);
private:
ULONG_PTR gdiplusToken;
void* m_pData;
int m_nSize;
BYTE* m_lpResrc;
DWORD m_nFontIndex;
// GDI+
PrivateFontCollection *m_pFontCollection;
Gdiplus::FontFamily *m_pFontFamily;
Gdiplus::Font* m_Font;
// GDI
HFONT m_hFont;
CString m_strFontFile;
CFont* m_pFont;
};
类源码实现:
#include "stdafx.h"
#include "CFontHelper.h"
_MACRO_SINGLETON_(CFontHelper)
CFontHelper::CFontHelper() :
m_Font(NULL), m_hFont(NULL),
m_pData(NULL), m_nSize(0)
{
GdiplusStartupInput gdiplusStartupInput;
GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);
m_pFontCollection = new PrivateFontCollection;
m_pFontFamily = new Gdiplus::FontFamily;
}
CFontHelper::~CFontHelper()
{
if (m_Font != NULL)
{
delete m_Font;
m_Font = NULL;
}
if (m_pFontCollection != NULL)
{
delete m_pFontCollection;
m_pFontCollection = NULL;
}
if (m_pFontFamily != NULL)
{
delete m_pFontFamily;
m_pFontFamily = NULL;
}
if (m_hFont != NULL)
{
RemoveFontMemResourceEx(m_hFont);
m_hFont = NULL;
}
if (!m_strFontFile.IsEmpty())
RemoveFontResourceEx(m_strFontFile, FR_PRIVATE, NULL);
FreeResource(m_lpResrc);
GdiplusShutdown(gdiplusToken);
}
BOOL CFontHelper::LoadFont(UINT lpszResource, LPCTSTR lpszType/* = _T("ttf")*/)
{
HINSTANCE hInst = AfxGetResourceHandle();
HRSRC hResrc = ::FindResource(hInst, MAKEINTRESOURCE(lpszResource), lpszType);
if (hResrc == NULL)
return NULL;
m_nSize = SizeofResource(hInst, hResrc);
m_lpResrc = (BYTE*)LoadResource(hInst, hResrc);
if (m_lpResrc == NULL)
return FALSE;
m_pData = (BYTE*)LockResource(m_lpResrc);
// GDI
m_nFontIndex = 0;
HANDLE m_hFont = AddFontMemResourceEx(
m_pData, // font resource
m_nSize, // number of bytes in font resource
NULL, // Reserved. Must be 0.
&m_nFontIndex); // number of fonts installed
if (m_hFont == NULL)
return FALSE;
// GDI+
Gdiplus::Status nResults = m_pFontCollection->AddMemoryFont(m_pData, m_nSize);
if (nResults != Gdiplus::Ok)
return FALSE;
int nNumFound = 0;
m_pFontCollection->GetFamilies(1, m_pFontFamily, &nNumFound);
if (nNumFound <= 0)
return FALSE;
return TRUE;
}
BOOL CFontHelper::LoadFont(wchar_t* lpszFile, LPCTSTR lpszType/* = _T("ttf")*/)
{
// GDI+
Gdiplus::Status nResults = m_pFontCollection->AddFontFile(lpszFile);
if (nResults != Gdiplus::Ok)
return FALSE;
int nNumFound = 0;
m_pFontCollection->GetFamilies(1, m_pFontFamily, &nNumFound);
if (nNumFound <= 0)
return FALSE;
// GDI
if (lpszFile == NULL || lpszType == NULL)
return FALSE;
m_strFontFile = lpszFile;
m_nFontIndex = AddFontResourceExA(lpszFile, FR_PRIVATE, NULL);// 返回私有字体个数
if (m_nFontIndex <= 0)
return FALSE;
wchar_t wszFontName[32] = { 0 };
m_pFontFamily->GetFamilyName(wszFontName);
char* szFontName = Unicode2Ansi(wszFontName);
LOGFONT logFont;
memset(&logFont, 0x0, sizeof(logFont));
logFont.lfHeight = 9;
logFont.lfWeight = FW_NORMAL;// FW_NORMAL; FW_BOLD
logFont.lfCharSet = GB2312_CHARSET;
_tcscpy_s(logFont.lfFaceName, LF_FACESIZE, szFontName);
logFont.lfQuality = CLEARTYPE_QUALITY;
logFont.lfOutPrecision = OUT_TT_ONLY_PRECIS;
logFont.lfClipPrecision = CLIP_CHARACTER_PRECIS;
logFont.lfCharSet = DEFAULT_CHARSET;
logFont.lfPitchAndFamily = DEFAULT_PITCH;
m_hFont = ::CreateFontIndirectA(&logFont);
delete szFontName;
return TRUE;
}
HFONT CFontHelper::FontToHFONTA(HWND hWnd)
{
if (m_Font == NULL || hWnd == NULL)
return NULL;
int nNumFound = 0;
m_pFontCollection->GetFamilies(1, m_pFontFamily, &nNumFound);
if (nNumFound <= 0)
return FALSE;
Graphics g(hWnd);
LOGFONTA logFont;
m_Font->GetLogFontA(&g, &logFont);
logFont.lfQuality = CLEARTYPE_QUALITY;
logFont.lfOutPrecision = OUT_TT_ONLY_PRECIS;
logFont.lfClipPrecision = CLIP_CHARACTER_PRECIS;
logFont.lfCharSet = DEFAULT_CHARSET;
logFont.lfPitchAndFamily = DEFAULT_PITCH;
return ::CreateFontIndirectA(&logFont);
}
// GDI+ -> GDI
HFONT CFontHelper::FontToHFONTW(HWND hWnd)
{
if (m_Font == NULL || hWnd == NULL)
{
ATLASSERT(FALSE);
return NULL;
}
Graphics g(hWnd);
LOGFONTW logFont;
m_Font->GetLogFontW(&g, &logFont);
logFont.lfQuality = CLEARTYPE_QUALITY;
logFont.lfOutPrecision = OUT_TT_ONLY_PRECIS;
logFont.lfClipPrecision = CLIP_CHARACTER_PRECIS;
logFont.lfCharSet = DEFAULT_CHARSET;
logFont.lfPitchAndFamily = DEFAULT_PITCH;
return ::CreateFontIndirectW(&logFont);
}
// GDI+ -> GDI
HFONT CFontHelper::GetSafeHFONT(HWND hWnd)
{
#ifdef _UNICODE
return FontToHFONTW(hWnd);
#else
return FontToHFONTA(hWnd);
#endif // _UNICODE
}
// GDI+
Gdiplus::Font* CFontHelper::Font(Gdiplus::FontStyle fontstyle/* = FontStyleRegular*/, REAL nFontSize/* = 14.0F*/)
{
int nNumFound = 0;
m_pFontCollection->GetFamilies(1, m_pFontFamily, &nNumFound);
if (nNumFound <= 0)
return FALSE;
if (m_Font != NULL)
{
delete m_Font;
m_Font = NULL;
}
m_Font = new Gdiplus::Font(m_pFontFamily, nFontSize, fontstyle, UnitPixel);
return m_Font;
}
// GDI
CFontHelper::operator HFONT() const
{
return m_hFont;
}
Gdiplus::FontFamily* CFontHelper::FontFamily()
{
int nNumFound = 0;
m_pFontCollection->GetFamilies(1, m_pFontFamily, &nNumFound);
if (nNumFound <= 0)
return NULL;
return m_pFontFamily;
}
BOOL CALLBACK EnumChildProc(HWND hwndChild, LPARAM lParam)
{
CFont* pFont = (CFont*)lParam;
CWnd* pWnd = CWnd::FromHandle(hwndChild);
pWnd->SetFont(pFont);
return TRUE;
}
void CFontHelper::SetFont(HWND hWnd)
{
CFont* pFont = CFont::FromHandle(GetSafeHFONT(hWnd));
::EnumChildWindows(hWnd, EnumChildProc, (LPARAM)&pFont);
::SendMessage(hWnd, WM_SETFONT, (WPARAM)CFontHelper::getSingletonPtr()->GetSafeHFONT(hWnd), TRUE);
}
这里用到了一个安全指针类型单实例模板-Singleton<class T>,不需要的可以直接删除。