Loading

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);
}

大功告成,使用的时候只要这样:

OK。 看下效果:

posted @ 2022-12-11 23:05  柴承训  阅读(478)  评论(3编辑  收藏  举报