我需要从Winforms C#应用程序安装新字体。我发现很多帖子如何在Windows中以编程方式安装新字体,因此结果写了以下代码,它适用于除Win 10以外的任何版本的Windows:
public Form1()
{
InitializeComponent();
//Some ttf file in current folder where app resides
string fontName = Environment.GetCommandLineArgs()[1];
//Name of the font
string name = Environment.GetCommandLineArgs()[2];
var newPath = Path.Combine(WindowsFontsFolder, fontName);
File.Move(fontName, newPath);
var result = AddFontResource(newPath);
var error = Marshal.GetLastWin32Error();
if (error != 0)
{
MessageBox.Show("Failed to AddFontResource");
return;
}
//Add font's record to the registry
Microsoft.Win32.RegistryKey key = Microsoft.Win32.Registry.LocalMachine.
CreateSubKey(@"SOFTWARE\Microsoft\Windows NT\CurrentVersion\Fonts");
key.SetValue(name + " (TrueType)", fontName);
key.Close();
//WM_FONTCHANGE = 0x001D
SendBroadcastMessageTimeout(0x001D, 5000);
}
执行此代码后,例如我从名为“elektra”的文件“4427267.ttf”安装字体,我打开写字板,看到字体添加到写字板但在字体列表中有一个空名称。
如果我在列表中选择我的新字体,则文档中的文本不会更改。但重启后Windows字体工作正常。此外,如果我使用NSIS安装程序安装字体,那么字体安装好并且工作正常:
System::Call 'kernel32::GetSystemWindowsDirectory(t .r0, i ${NSIS_MAX_STRLEN})'
${File} "" ${fontToInstallFile}
${CopyFiles} "$INSTDIR\${fontToInstallFileName}" "$0\Fonts\${fontToInstallFileName}"
System::Call "GDI32::AddFontResourceW(t) i ('$0\Fonts\${fontToInstallFileName}') .s"
WriteRegStr HKLM "${fontkey}" "FontName (TrueType)" "${fontToInstallFileName}"
SendMessage ${HWND_BROADCAST} ${WM_FONTCHANGE} 0 0 /TIMEOUT=5000
但NSIS脚本逻辑与我的winforms C#app代码逻辑之间没有明显区别。 NSIS代码有效,但c#没有。两个代码都以管理员权限执行。