VC字体安装相关方法总结

//

在程序中添加安装字体文件的功能,要求如下:
1.不复制到Fonts文件夹,可以安装的任意分区,以减少系统分区负担。
2.不改变Fonts文件夹位置,尽量不改变系统设置。

网上得来的资料,用ADDFontResource,根据这一思路我遇到如下问题:
1.必须复制字体文件到Fonts文件夹才能永久安装,否则重启后字体无效
2.看MSDN要永久安装需要registry(不知是不是注册表,所以没敢翻译),不知该如何registry.
3.查看注册表HLM\Software\Microsoft\Windows NT\CurrentVersion\Fonts,键值是字体名称,该如何获得字体文件的名称呢(好像每种字体文件中都存储有不同于文件名的名称)?

曾经尝试字体文件的快捷方式:
1.复制字体文件快捷方式成功,但Fonts文件夹并不显示.
2.没有尝试用IShellLink在Fonts文件夹创建字体文件快捷方式。

另一思路:Shell编程,调出Fonts文件夹,发消息控制菜单-文件-安装新字体-不复制...,不过这太那什么了。

//

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

网上广泛流传的使用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 (不然编译器会提示这些函数未定义)

//

    

安装字体私有字体资源遵循以下步骤:

1)TrueType字体文件复制到一个临时文件中有一个独特的文件名,如“ttfont01.ttf”,可以属于应用程序的实例。

2)调用CreateScalableFontResource()函数来创建一个惟一命名的临时隐藏的字体的资源文件,也可以属于应用程序的实例。

3)调用AddFontResource()函数来安装这个惟一命名的字体资源文件的这个实例的应用程序。

4)在所需要使用的应用程序中使用这个字体。

5)当应用程序终止的实例或者其他方式完成字体文件,它应该卸载字体资源通过调用RemoveFontResource()函数,直到它失败。

6)最后,应用程序应该删除临时字体资源文件和临时TrueType字体文件。

代码如下:

CString sSourceDir =defaultFullDirPath+_T("\\");                                  
	CString sFontFileName=_T("YPFONT.TTF");                              
	//字体名称(将显示在字体对话框中).      
	CString sFontName=_T("YPFont (TrueType)");      
	TCHAR sWinDir[MAX_PATH];      
	GetWindowsDirectory(sWinDir,MAX_PATH);      
	CString sFontDir(sWinDir);      
	sFontDir += _T("\\Fonts\\");      
	CString sFOTFile  = sFontDir;      
	sFOTFile += (sFontFileName.Left(sFontFileName.GetLength()-4) + _T(".FOT "));      
	CopyFile((sSourceDir + sFontFileName),(sFontDir  + sFontFileName),FALSE);      
	BOOL Result;      
	Result =  CreateScalableFontResource(0, sFOTFile, sFontFileName, sFontDir);      
	Result =  AddFontResource(sFOTFile);      
	HKEY   phkResult;      
	DWORD  RegResult;          
	LONG   Rlt=RegCreateKeyEx(
		HKEY_LOCAL_MACHINE,      
		_T("SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Fonts"),
		0,_T("REG_SZ"),      
		0,
		KEY_WRITE,
		0,
		&phkResult,
		&RegResult
		);      
	if(Rlt !=ERROR_SUCCESS)      
	{ 
		MessageBox(NULL,_T("失败!"),_T("提示"),MB_OK);      
	}      
	int sFontFileNameLength=(sFontFileName.GetLength())*2;
	const BYTE* you=(CONST BYTE*)((LPCTSTR)sFontFileName);
	RegSetValueEx(
		phkResult,
		sFontName,
		0,
		REG_SZ,
		you,
		sFontFileNameLength
		);      
	RegCloseKey(phkResult);      
	SendMessage(HWND_BROADCAST,WM_FONTCHANGE,0,0);      
	//DeleteFile((sFontDir + sFontFileName));

 

//
永久安装字体使用,类似下面的代码:   

CString sSourceDir =defaultFullDirPath+_T("\\");                                  
	CString sFontFileName=_T("YPFONT.TTF");                              
	//字体名称(将显示在字体对话框中).      
	CString sFontName=_T("YPFont (TrueType)");      
	TCHAR sWinDir[MAX_PATH];      
	GetWindowsDirectory(sWinDir,MAX_PATH);      
	CString sFontDir(sWinDir);      
	sFontDir += _T("\\Fonts\\");      
	CopyFile((sSourceDir + sFontFileName),(sFontDir  + sFontFileName),FALSE);      
	BOOL Result;         
	Result =  AddFontResource(sFontDir  + sFontFileName);      
	HKEY   phkResult;      
	DWORD  RegResult;          
	LONG   Rlt=RegCreateKeyEx(
		HKEY_LOCAL_MACHINE,      
		_T("SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Fonts"),
		0,_T("REG_SZ"),      
		0,
		KEY_WRITE,
		0,
		&phkResult,
		&RegResult
		);      
	if(Rlt !=ERROR_SUCCESS)      
	{ 
		MessageBox(NULL,_T("失败!"),_T("提示"),MB_OK);      
	}      
	int sFontFileNameLength=(sFontFileName.GetLength())*2;
	const BYTE* you=(CONST BYTE*)((LPCTSTR)sFontFileName);
	RegSetValueEx(
		phkResult,
		sFontName,
		0,
		REG_SZ,
		you,
		sFontFileNameLength
		);      
	RegCloseKey(phkResult);      
	SendMessage(HWND_BROADCAST,WM_FONTCHANGE,0,0);      
	//DeleteFile((sFontDir + sFontFileName));

注:从WIN7系统下发现如下问题: 最后一次安装的字体 在记事本中打开 字体设置 中的  字形  默认只有   常规。需要多点一次 才能出现如粗体 斜体等的字形。


转载于:https://my.oschina.net/ypimgt/blog/66955

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值