MFC控件使用自己本地的字体文件

MFC控件使用自己本地的字体文件

MFC作为一套古老的框架,加载使用本地字体流程也很复杂,网上的资料大多也都不能直接运行。在参考了一些github上现有代码和古代代码之后,实现了加载本地字体文件并显示在指定控件的功能。

首先要把字体文件加载到资源文件里,资源视图下右键-添加资源, 点击自定义,输入"OTF", "TTF"等需要加载的字体文件类型,记得要加双引号。

然后点击导入,将需要加载的字体文件导入到相应的资源里:

资源导入完成后开始加代码:

CFontHelper.h

#pragma once

#include

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。 看下效果: