我有一个函数下面将安装一个字体( .ttf
)到Windows通过复制到Windows字体文件夹,然后触发WM_FONTCHANGE
消息。 但是,该字体不能立即在Windows资源pipe理器中显示。
运行后,当我通过控制面板打开字体时,我的字体不显示在那里。 而当我打开C:\Windows\Fonts\
它不显示那里。
但是我可以确认我的.ttf
文件真的在那里。 使用命令提示符在这里导航,我可以看到我的字体文件。 当我打开字符映射实用程序时,我的字体在这里列出。 而且字体在我的应用程序中可用。 我必须重新启动explorer.exe
才能在Windows资源pipe理器视图中显示它。 我甚至尝试以pipe理员身份运行我的应用程序(提升),仍然没有运气。
我以为WM_FONTCHANGE
消息应该照顾这个,但显然这不是伎俩。
我在这个字体安装中错过了什么,以确保Windows知道它?
uses SysUtils, ShlObj, ComObj, ActiveX; function SystemDir(Handle: THandle; Folder: Integer): String; var R: HRESULT; PIDL: PItemIDList; Path: array[0..MAX_PATH] of Char; begin Result:= ''; R:= SHGetSpecialFolderLocation(Handle, Folder, PIDL); if R = S_OK then begin if SHGetPathFromIDList(PIDL, Path) then Result:= StrPas(Path); end; end; function InstallFont(Handle: THandle; const Filename: String): Boolean; var Dir, FN: String; begin Result:= False; FN:= ExtractFileName(Filename); Dir:= IncludeTrailingPathDelimiter(SystemDir(Handle, CSIDL_FONTS)); Result:= FileExists(Filename); if Result then begin Result:= CopyFile(PChar(Filename), PChar(Dir + FN), False); end; SendMessage(HWND_BROADCAST, WM_FONTCHANGE, 0, 0); end;
用法:
Result:= InstallFont(Application.Handle, 'C:\MyTestFont.ttf');
UPDATE
在下面的答案的评论中build议通过shell而不是Windows API来安装字体。 所以,我写了这个函数实质上完成了同样的function:
function InstallFont2(Handle: THandle; const Filename: String): Boolean; var R: HINST; begin Result:= False; R:= ShellExecuteW(Handle, 'install', PWideChar(Filename), nil, nil, SW_HIDE); Result:= R > 32; end;
然而这也是有问题的。 返回值是31
(表示错误),当我调用GetLastError
它告诉我1155
(“没有应用程序与此操作的指定文件关联”)。
我也在下面的答案中尝试了特定的解决scheme,但是无济于事。 我都使用AddFontResource
并写入相应的registry项 – 尝试使用此字体安装卸载/重新启动/重试的组合。
WM_FONTCHANGE
只通知应用程序在系统中的新字体,但实际上并没有告诉系统新的字体是什么。
发送WM_FONTCHANGE
之前,您需要调用AddFontResource
将字体添加到系统字体表。 如果希望字体在重新启动后保留,还需要向注册表项HKEY_LOCAL_MACHINE \ SOFTWARE \ Microsoft \ Windows NT \ CurrentVersion \ Fonts添加一个条目(有关更多信息,请参阅AddFontResource
的文档)。