MFC控件使用自己本地的字体文件
MFC作为一套古老的框架,加载使用本地字体流程也很复杂,网上的资料大多也都不能直接运行。在参考了一些github上现有代码和古代代码之后,实现了加载本地字体文件并显示在指定控件的功能。
首先要把字体文件加载到资源文件里,资源视图
下右键-添加资源, 点击自定义
,输入"OTF"
, "TTF"
等需要加载的字体文件类型,记得要加双引号。
资源导入完成后开始加代码:
CFontHelper.h
#pragma once
#include <GdiPlus.h>
using namespace Gdiplus;
class CFontHelper
{
public:
CFontHelper();
~CFontHelper();
public:
// 加载字体
BOOL LoadFont(UINT lpszResource, LPCTSTR lpszType = _T("ttf"));
Gdiplus::Font* SetFontStyle(Gdiplus::FontStyle fontstyle = FontStyleRegular, REAL nFontSize = 14.0F);
Gdiplus::FontFamily* FontFamily();
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;
DWORD m_nFontIndex;
// GDI+
PrivateFontCollection* m_pFontCollection;
Gdiplus::FontFamily* m_pFontFamily;
Gdiplus::Font* m_Font;
// GDI
CString m_strFontFile;
HANDLE m_hFontRes;
};
CFontHelper.cpp
#include "pch.h"
#include "CFontHelper.h"
CFontHelper::CFontHelper() :
m_Font(NULL),
m_pData(NULL), m_nSize(0),
m_nFontIndex(0), m_hFontRes(NULL)
{
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_hFontRes != NULL)
{
RemoveFontMemResourceEx(m_hFontRes);
m_hFontRes = NULL;
}
if (!m_strFontFile.IsEmpty())
RemoveFontResourceEx(m_strFontFile, FR_PRIVATE, NULL);
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 FALSE;
m_nSize = SizeofResource(hInst, hResrc);
m_pData = LoadResource(hInst, hResrc);
if (m_pData == NULL)
return FALSE;
// GDI
m_nFontIndex = 0;
m_hFontRes = 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_hFontRes == 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;
}
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 NULL;
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)
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::SetFontStyle(Gdiplus::FontStyle fontstyle/* = FontStyleRegular*/, REAL nFontSize/* = 14.0F*/)
{
int nNumFound = 0;
m_pFontCollection->GetFamilies(1, m_pFontFamily, &nNumFound);
if (nNumFound <= 0)
return NULL;
if (m_Font != NULL)
{
delete m_Font;
m_Font = NULL;
}
m_Font = new Gdiplus::Font(m_pFontFamily, nFontSize, fontstyle, UnitPixel);
return m_Font;
}
// GDI
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)GetSafeHFONT(hWnd), TRUE);
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南