有时候需要用到一些特殊的字体,而用户的机器上可能没有。把它永久安装到用户机器上,总会让人有点不爽,因为这些可能是很特殊的字体,比如是音标,或者液晶数字等用户平时根本就用不着的东东。这时候,程序运行的时候,把它们动态加载为临时字体,就是很好的选择了。

网上广泛流传的使用AddFontResource的方法,缺点比较多。一是,临时加载之后,除了自己的程序可以使用刚加载的字体之外,其它程序,比如记事本,在字体列表中也会发现这个字体也被加了进来,这种私有性,就不是很好了。二,就是,这种办法,最大的弊病就是,当非正常退出(比如用任务管理器杀掉)时,可能会调用不到RemoveFontResource,字体就保留下来了,但是之后就会发现再次AddFontResource时会失败,而且其它程序,也无法使用这种字体了(但是还可以在字体列表中见到)。(ps.重启计算机才可让此字体消失)

回到主题上来,最有效的办法是什么呢?方法之一,用AddFontMemResourceEx从资源加载字体

MSDN上面说了,This function allows an application to get a font that is embedded in a document or a Web page. A font that is added by AddFontMemResourceEx is always private to the process that made the call and is not enumerable.

也就是加载的字体为进程私有,在系统字体列表中不可枚举

这种情况下,如果不调用与之配对的RemoveFontMemResourceEx,临时字体也会被销毁,第二次使用时也完全不会出问题

附代码:

void InstallFont()
{
    HINSTANCE hResInstance = AfxGetResourceHandle( );
    HRSRC res = FindResource(hResInstance,
        MAKEINTRESOURCE(IDR_FONT_PHONETIC),
        _T(“BINARY”));
    if(res)
    {
        HGLOBAL mem = LoadResource(hResInstance, res);
        void *data = LockResource(mem);
        DWORD len = SizeofResource(hResInstance, res);
        DWORD nFonts;
        m_hFont = AddFontMemResourceEx(
                    data,          // font resource
                    len,          // number of bytes in font resource
                    NULL,         // Reserved. Must be 0.
                    &nFonts);      // number of fonts installed
        if(!m_hFont)
            AfxMessageBox(_T(“字体加载失败!”));
    }
}

当然,还有方法之二,就是使用AddFontResourceEx从文件加载字体

参数指定FR_PRIVATE就是私有的了

特别提示

以上提到的函数都是win2k以上系统才支持的,所以尤其是在用VC6的时候,要在stdAfx.h的所有#include 的上方,加上#define _WIN32_WINNT 0×0500 (不然编译器会提示这些函数未定义)