1. 起因:

在界面编程时,我们经常需要用到自定义字体,来使自己的界面更美观。可要是别人电脑上没有你预定义的字体就麻烦了,你的界面字体会被Windows默认字体所取代,然后控件变形、错位等等问题会接踵而至。

2. 解决办法:

遇到这种情况,我们可以把字体放在Visual Studio的自定义资源中,和exe一起打包。还有一种办法是将字体打包在dll中或者放在一个文件夹中,这样可以减少exe的体积。这里为了方便讲解,我将字体放入至自定义资源中,用一个ID值来索引它即可。

首先,将字体加入至resource文件中,因为我的字体文件是ttf格式的,所以给他取名为TTF,如下图:

我这里使用了2个字体,一个是中文篆体,一个是英文android字体。

接下来,我们需要用到Windows的两个API函数,来让Windows安装字体,或者是卸载字体。当你的程序完全退出时,可以将字体卸载。这两个函数分别是:AddFontMemResourceEx和RemoveFontMemResourceEx,他们是为GDI设计的,而GDI+可以直接使用PrivateFontCollection下的AddMemoryFont函数来进行字体的加载即可。

我这里设计了个类,它可以用在GDI和GDI+上面,可能有的看官会觉得多此一举,直接GDI+不就好了么?为什么还要照顾GDI呢?那是因为,我们的控件的设置字体SetFont还是基于GDI的,GDI+中的字体没办法直接用在上面。

GDI+中的字体要想转换为GDI的HFONT,就得用CreateFontIndirect来转换。转换得到的字体,在不用时,需要用DeleteObject删除之。以下是这个类的完整代码:

 class CFontHelper{// Constructor, destructor and operator.public:CFontHelper() : m_Font(NULL), m_hFontRes(NULL), m_pData(NULL), m_nSize(0){}~CFontHelper(){DeleteOldFont();}// Data members.public:Font*   m_Font;private:PrivateFontCollection   m_FontCollection;FontFamily              m_FontFamily;HANDLE                  m_hFontRes;void*                   m_pData;int                     m_nSize;// Operations.public:void DeleteOldFont(){if (m_Font != NULL){delete m_Font;m_Font = NULL;}if (m_hFontRes != NULL){RemoveFontMemResourceEx(m_hFontRes);m_hFontRes = NULL;}}// Load font from resource manager.BOOL LoadFont(ATL::_U_STRINGorID resource, ATL::_U_STRINGorID type = _T("ttf")){CResource res;if( !res.Load(type, resource) ) {ATLASSERT(FALSE);return FALSE;}m_nSize   = (int)res.GetSize();m_pData  = res.Lock();Gdiplus::Status nResults = m_FontCollection.AddMemoryFont(m_pData, m_nSize);if( nResults != Gdiplus::Ok ){ATLASSERT(FALSE);return FALSE;}DWORD dwNum = 1;SetFontStyle();return TRUE;}// Modify font style.BOOL SetFontStyle(Gdiplus::FontStyle fontstyle = FontStyleRegular, REAL nFontSize = 14.0F){int nNumFound = 0;m_FontCollection.GetFamilies(1, &m_FontFamily, &nNumFound);DWORD dwFound = (DWORD)nNumFound;if (nNumFound <= 0){// You need load font first.ATLASSERT(FALSE);return FALSE;}// Delete old font.DeleteOldFont();m_Font      = new Font(&m_FontFamily, nFontSize, fontstyle, UnitPixel);m_hFontRes  = AddFontMemResourceEx(m_pData, (DWORD)m_nSize, NULL, &dwFound);if (m_Font != NULL){return TRUE;}ATLASSERT(FALSE);return FALSE;}// Turn GDI+ Font to HFONT (ANSI).HFONT FontToHFONT_A(HWND m_hWnd){if (m_Font == NULL || m_hWnd == NULL){ATLASSERT(FALSE);return NULL;}Graphics g(m_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);}// Turn GDI+ Font to HFONT (UNICODE).HFONT FontToHFONT_W(HWND m_hWnd){if (m_Font == NULL || m_hWnd == NULL){ATLASSERT(FALSE);return NULL;}Graphics g(m_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);}};

好了,让我们新建个窗口,并创建两个CEdit控件,并用SetFont来设置他们的字体,看看是不是很简单?说真的,我们老祖宗创建的篆体是不是很好看呢?看来编程之余还得多多学习国学方面的知识啊,编程之美,国学之美,嘿嘿

本文代码工程免费下载链接:http://download.csdn.net/detail/renstarone/6022471

VC++界面编程之--动态安装字体(CFont)相关推荐

  1. vc 界面编程常用方法 listctrl toolbar

      vc 界面编程常用方法收藏 新一篇: Building SQLite3 with Visual Studio 2005 | 旧一篇: Visual Studio 2005 IDE 技巧和窍门 &l ...

  2. VC++界面编程之--使用分层窗口实现界面皮肤

    使用分层界面来实现界面皮肤的好处是:可以保证图片边缘处理不失真,且能用于异形窗口上,如一些不规则的窗口,你很难用SetWindowRgn来达到理想效果. 在很多情况下,界面的漂亮与否,取决于PS的制作 ...

  3. Vc 界面编程常用方法

    (http://blog.emuch.net/244485/spacelist-blog-itemtypeid-2708.html) http://blog.csdn.net/guanchanghui ...

  4. VC界面编程skill tips-CListCtrl

    CListCtrl 使用技巧 作者:lixiaosan 时间:04/06/2006 以下未经说明,listctrl默认view 风格为report 相关类及处理函数 MFC:CListCtrl类 SD ...

  5. vc 界面编程常用方法(http://blog.emuch.net/244485/spacelist-blog-itemtypeid-2708.html)

    CListCtrl 使用技巧 2007-09-24 13:53:39 [原]CListCtrl 使用技巧 作者:lixiaosan 时间:04/06/2006 以下未经说明,listctrl默认vie ...

  6. VC++界面编程之--实现一个画板并提供文字输入功能(MsPaint)

    画板的实现非常有趣,首先要新建一张HBITMAP来保存原来的绘制内容,然后需要创建一个可拉伸的输入框,供用户输入文字.必要时还得提供UnDo功能,供用户取消上一次绘制的功能. 利用业余时间,我制作了一 ...

  7. java swing 字体_Java Swing界面编程(4)---获取本地字体

    ubuntu 安装tp-link usb无线网卡 tl-wn821n 全过程 1.   无线网卡识别 在终端中输入   lsusb  ,观察插入USB无线网卡tl-wn821n,是否多显示出Realt ...

  8. VC++界面编程之--自定义CEdit(编辑框)皮肤

    自定义编辑框是登陆界面经常用到的效果,所以我也模仿站酷网的素材做了个. 要想继承CCustomDraw来完全自绘CEdit控件,是不太可行的方案,因为一旦你完全重绘,那么你需要额外做以下几件事: 1. ...

  9. C语言控制台窗口界面编程:printf格式化显示-修改字符字体、颜色和背景

    环境:cygwin-Linux+GCC PS:windows的cmd下不能实现. 在linux终端中一个ls指令得出的显示结果文件夹.文件以及不同操作权限的文件的显示颜色是不同的,那么这个是如何实现的 ...

最新文章

  1. Json-server 创建模拟API服务器
  2. wordpress页面里可不可以写php,如何在WordPress页面中创建不同的可编辑部分?
  3. gzp解压命令 linux_Linux-压缩解压命令(gzip,zip,tar,bzip)
  4. [转]2020年4月github上最热门项目-python
  5. 微程序相关的两个知识点
  6. mysql 图文安装_mysql安装图解mysql图文安装教程(详细说明)
  7. 目标检测的图像特征提取之(一)HOG特征
  8. 学校设备保修维修工单小程序开发制作
  9. 基于vmdk文件创建虚拟机
  10. Docker Swarm 入门一篇文章就够了【转】
  11. 【定义】三角形行列式和对角行列式
  12. r76800h怎么样r7 6800h参数
  13. 严蔚敏数据结构源码及习题解析
  14. twitter视频下载php,Twitter推特红心点赞H5动画按钮特效
  15. 怎么可以修改pr基本图形中的文字_PR教程03 | 如何增加字幕
  16. 有源阻尼抑制LCL滤波器固有谐振
  17. php与mysql结合的数据库编程,php与mysql结合的数据库编程
  18. 计算机领域的诺贝尔奖是图灵奖,计算机界的诺贝尔奖图灵奖.DOC
  19. 小熊派 移植TencentOS-tiny+EC20+MQTT对接腾讯云
  20. 生成随机小数的函数python_哪个选项是random库中用于生成随机小数的函数?

热门文章

  1. fiddler抓取不了PC端微信小程序的包解决方法
  2. 原生开发什么意思_APP原生开发和混合开发的区别你了解多少
  3. mysql的报错日志哪里看_mysql错误日志
  4. 基于CarMaker的C-NCAP主动安全系统试验仿真(三)
  5. 如何远程连接Linux系统服务器
  6. 华为交换机开局Telnet配置
  7. mysql 中abs函数_Mysql常用函数
  8. open_files打开输入输出文件
  9. Java项目:医院电子病历管理系统(java+Servlet+JSP+Easyui+Mysql)
  10. jmeter利用察看结果树查看响应调试取样器(Debug Sampler)(3)