//
在程序中添加安装字体文件的功能,要求如下:
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系统下发现如下问题: 最后一次安装的字体 在记事本中打开 字体设置 中的 字形 默认只有 常规。需要多点一次 才能出现如粗体 斜体等的字形。