如何在Windows中获取所有等宽字体?

时间:2012-09-14 02:39:57

标签: c# windows fonts

我见过How do I get all installed fixed-width fonts?,但我无法让它发挥作用:

internal class NativeMethods
{
    public const Int32 LF_FACESIZE = 32;
    public const Int32 FIXED_PITCH = 1;

    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
    public class LOGFONT
    {
        public Int32 lfHeight = 0;
        public Int32 lfWidth = 0;
        public Int32 lfEscapement = 0;
        public Int32 lfOrientation = 0;
        public Int32 lfWeight = 0;
        public Byte lfItalic = 0;
        public Byte lfUnderline = 0;
        public Byte lfStrikeOut = 0;
        public Byte lfCharSet = 0;
        public Byte lfOutPrecision = 0;
        public Byte lfClipPrecision = 0;
        public Byte lfQuality = 0;
        public Byte lfPitchAndFamily = 0;

        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = LF_FACESIZE)]
        public String lfFaceName = string.Empty;
    }
}


public partial class MainForm : Form
{
    private string font_names = null;

    public MainForm()
    {
        InitializeComponent();

        StringBuilder sb = new StringBuilder();
        foreach (var font_family in FontFamily.Families)
        {
            if (font_family.IsStyleAvailable(FontStyle.Regular))
            {
                var lf = new NativeMethods.LOGFONT();
                Font font = new Font(font_family, 9.0f);
                font.ToLogFont(lf);
                if ((lf.lfPitchAndFamily & 0x3) == NativeMethods.FIXED_PITCH)
                {
                    sb.AppendLine(font_family.Name);
                }
            }
        }
        font_names = sb.ToString();
    }

    private void MainForm_Paint(object sender, PaintEventArgs e)
    {
        e.Graphics.DrawString(font_names, SystemFonts.MessageBoxFont, SystemBrushes.WindowText, 10.0f, 10.0f);
    }
}

无论它是什么字体,lfPitchAndFamily始终为零。

那么如何获得所有等宽字体?

1 个答案:

答案 0 :(得分:4)

我想我会用P / Invoke来做这件事:

internal class NativeMethods
{
    public const Int32 LF_FACESIZE = 32;
    public const Int32 LF_FULLFACESIZE = 64;
    public const Int32 DEFAULT_CHARSET = 1;
    public const Int32 FIXED_PITCH = 1;
    public const Int32 TRUETYPE_FONTTYPE = 0x0004;

    public delegate Int32 FONTENUMPROC(ref ENUMLOGFONT lpelf, ref NEWTEXTMETRIC lpntm, UInt32 FontType, IntPtr lParam);

    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
    public struct LOGFONT
    {
        public Int32 lfHeight;
        public Int32 lfWidth;
        public Int32 lfEscapement;
        public Int32 lfOrientation;
        public Int32 lfWeight;
        public Byte lfItalic;
        public Byte lfUnderline;
        public Byte lfStrikeOut;
        public Byte lfCharSet;
        public Byte lfOutPrecision;
        public Byte lfClipPrecision;
        public Byte lfQuality;
        public Byte lfPitchAndFamily;

        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = LF_FACESIZE)]
        public String lfFaceName;
    }

    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
    public struct TEXTMETRIC
    {
        public Int32 tmHeight;
        public Int32 tmAscent;
        public Int32 tmDescent;
        public Int32 tmInternalLeading;
        public Int32 tmExternalLeading;
        public Int32 tmAveCharWidth;
        public Int32 tmMaxCharWidth;
        public Int32 tmWeight;
        public Int32 tmOverhang;
        public Int32 tmDigitizedAspectX;
        public Int32 tmDigitizedAspectY;
        public Char tmFirstChar;
        public Char tmLastChar;
        public Char tmDefaultChar;
        public Char tmBreakChar;
        public Byte tmItalic;
        public Byte tmUnderlined;
        public Byte tmStruckOut;
        public Byte tmPitchAndFamily;
        public Byte tmCharSet;
    }

    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
    public struct ENUMLOGFONT
    {
        public LOGFONT elfLogFont;

        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = LF_FULLFACESIZE)]
        public String elfFullName;

        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = LF_FACESIZE)]
        public String elfStyle;
    }

    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
    public struct NEWTEXTMETRIC
    {
        public Int32 tmHeight;
        public Int32 tmAscent;
        public Int32 tmDescent;
        public Int32 tmInternalLeading;
        public Int32 tmExternalLeading;
        public Int32 tmAveCharWidth;
        public Int32 tmMaxCharWidth;
        public Int32 tmWeight;
        public Int32 tmOverhang;
        public Int32 tmDigitizedAspectX;
        public Int32 tmDigitizedAspectY;
        public Char tmFirstChar;
        public Char tmLastChar;
        public Char tmDefaultChar;
        public Char tmBreakChar;
        public Byte tmItalic;
        public Byte tmUnderlined;
        public Byte tmStruckOut;
        public Byte tmPitchAndFamily;
        public Byte tmCharSet;
        public UInt32 ntmFlags;
        public UInt32 ntmSizeEM;
        public UInt32 ntmCellHeight;
        public UInt32 ntmAvgWidth;
    }

    [DllImport("gdi32.dll", CharSet = CharSet.Auto)]
    public extern static Int32 EnumFontFamiliesEx(IntPtr hdc, ref LOGFONT lpLogfont, FONTENUMPROC lpEnumFontFamExProc, IntPtr lParam, UInt32 dwFlags);
}

internal static class Program
{
    private static void Main()
    {
        Graphics graphics = Graphics.FromHwnd(IntPtr.Zero);
        IntPtr hdc = graphics.GetHdc();
        var logfont = new NativeMethods.LOGFONT() { lfCharSet = NativeMethods.DEFAULT_CHARSET };
        NativeMethods.EnumFontFamiliesEx(hdc, ref logfont, new NativeMethods.FONTENUMPROC(EnumFontFamExProc), IntPtr.Zero, 0);
        graphics.ReleaseHdc();
    }

    private static int EnumFontFamExProc(ref NativeMethods.ENUMLOGFONT lpelf, ref NativeMethods.NEWTEXTMETRIC lpntm, uint FontType, IntPtr lParam)
    {
        if ((lpelf.elfLogFont.lfPitchAndFamily & 0x3) == NativeMethods.FIXED_PITCH)
        {
            Console.WriteLine(lpelf.elfLogFont.lfFaceName);
        }
        return 1;
    }
}