检索字体的文件名

时间:2014-02-03 10:52:35

标签: c# .net winforms fonts

我想获取字体的文件名。这不是那么难......我知道,已经存在一个非常类似的问题,但问题的答案不可能是它。

我想要做的是通过TCP / IP将Font文件发送给其他客户端,如果他请求的话。我在FontDialog上选择了所需的字体,我可以从框架中获取FontName。我无法找到可以说大部分时间都可以使用的字体文件。

.NET在哪里知道系统上安装了哪些字体?它不能是框架依赖于一直无法运行的解决方案,例如CodeProject上的解决方案和Stackoverflow中的建议。必须有一种安全的方法来检索字体文件。 FontDialog可以将它们全部列在一个框中,并且安装的字体必须具有其文件的路径。

有兴趣帮助我吗?

enter image description here

3 个答案:

答案 0 :(得分:7)

using System;
using System.Drawing;
using System.Text.RegularExpressions;
using Microsoft.Win32

public static string GetSystemFontFileName(Font font)
{
    RegistryKey fonts = null;
    try{
        fonts = Registry.LocalMachine.OpenSubKey(@"Software\Microsoft\Windows NT\CurrentVersion\Fonts", false);
        if(fonts == null)
        {
            fonts = Registry.LocalMachine.OpenSubKey(@"Software\Microsoft\Windows\CurrentVersion\Fonts", false);
            if(fonts == null)
            {
                throw new Exception("Can't find font registry database.");
            }
        }

        string suffix = "";
        if(font.Bold)
            suffix += "(?: Bold)?";
        if(font.Italic)
            suffix += "(?: Italic)?";

        var regex = new Regex(@"^(?:.+ & )?"+Regex.Escape(font.Name)+@"(?: & .+)?(?<suffix>"+suffix+@") \(TrueType\)$", RegexOptions.Compiled);

        string[] names = fonts.GetValueNames();

        string name = names.Select(n => regex.Match(n)).Where(m => m.Success).OrderByDescending(m => m.Groups["suffix"].Length).Select(m => m.Value).FirstOrDefault();

        if(name != null)
        {
            return fonts.GetValue(name).ToString();
        }else{
            return null;
        }
    }finally{
        if(fonts != null)
        {
            fonts.Dispose();
        }
    }
}

答案 1 :(得分:2)

首先,您的问题描述了Windows操作系统的问题。因此,您的解决方案需要是Windows特定的解决方案。在您的评论中,您提到该解决方案可能无法在其他操作系统上运行。

肯定不行。

每个操作系统都需要单独处理。此外,您不能假设在客户端的操作系统上以相同的方式安装字体。

关于获取字体文件名的问题。 CP上提供的解决方案没有任何问题。在许多情况下,在Windows中获取内容的唯一方法是进行API调用。 .Net根本不支持我们可能需要做的一些事情。因此,依赖API并不会使其自动错误或不受欢迎。

修改

在.NET 4.0中,字体是一个可以像这样访问的特殊文件夹

var fontsFolderPath = Environment.GetFolderPath(Environment.SpecialFolder.Fonts);

答案 2 :(得分:0)

    Dictionary<string, List<string>> _fontNameToFiles; 
    /// <summary>
    /// This is a brute force way of finding the files that represent a particular
    /// font family.
    /// The first call may be quite slow.
    /// Only finds font files that are installed in the standard directory.
    /// Will not discover font files installed after the first call.
    /// </summary>
    /// <returns>enumeration of file paths (possibly none) that contain data
    /// for the specified font name</returns>
    private IEnumerable<string> GetFilesForFont(string fontName)
    {
        if (_fontNameToFiles == null)
        {
            _fontNameToFiles = new Dictionary<string, List<string>>();
            foreach (var fontFile in Directory.GetFiles(Environment.GetFolderPath(Environment.SpecialFolder.Fonts)))
            {
                var fc = new PrivateFontCollection();
                try
                {
                    fc.AddFontFile(fontFile);
                }
                catch (FileNotFoundException)
                {
                    continue; // not sure how this can happen but I've seen it.
                }
                var name = fc.Families[0].Name;
                // If you care about bold, italic, etc, you can filter here.
                List<string> files;
                if (!_fontNameToFiles.TryGetValue(name, out files))
                {
                    files = new List<string>();
                    _fontNameToFiles[name] = files;
                }
                files.Add(fontFile);
            }
        }
        List<string> result;
        if (!_fontNameToFiles.TryGetValue(fontName,  out result))
            return new string[0];
        return result;
    }