Search code examples
c#wpffontsdriverprinters

How to get the printer device font list in WPF


Is there a way to get the printer device fonts list and not the ones installed on Windows using WPF?


Solution

  • Using PInovke you can access printer device context and enumerate its specific font, as explained in this.

    using System.Collections.Generic;
    using System.Drawing;
    using System.Runtime.InteropServices;
    
    public static class GdiFonts
    {    
        #region gdi32
        
        public enum FontMask
        {
            RASTER_FONTTYPE = 0x0001,
            DEVICE_FONTTYPE = 0x0002,
            TRUETYPE_FONTTYPE = 0x0004
        }
        
        public enum FontWeight
        {
            FW_DONTCARE = 0,
            FW_THIN = 100,
            FW_EXTRALIGHT = 200,
            FW_LIGHT = 300,
            FW_NORMAL = 400,
            FW_MEDIUM = 500,
            FW_SEMIBOLD = 600,
            FW_BOLD = 700,
            FW_EXTRABOLD = 800,
            FW_HEAVY = 900
        }
        
        public enum FontPitch : int
        {
            DEFAULT_PITCH = 0,
            FIXED_PITCH = 1,
            VARIABLE_PITCH = 2,
            MONO_FONT = 8
        }
        
        public enum FontFamily
        {
            FF_DONTCARE = 0 << 4,
            FF_ROMAN = 1 << 4,
            FF_SWISS = 2 << 4,
            FF_MODERN = 3 << 4,
            FF_SCRIPT = 4 << 4,
            FF_DECORATIVE = 5 << 4
        }
        
        public enum FontMappingMode
        {
            MM_TEXT = 1,
            MM_LOMETRIC = 2,
            MM_HIMETRIC = 3,
            MM_LOENGLISH = 4,
            MM_HIENGLISH = 5,
            MM_TWIPS = 6,
            MM_ISOTROPIC = 7,
            MM_ANISOTROPIC = 8
        }
        
        public enum FontLanguageCharSet
        {
            ANSI_CHARSET = 0x00000000,
            DEFAULT_CHARSET = 0x00000001,
            SYMBOL_CHARSET = 0x00000002,
            MAC_CHARSET = 0x0000004D,
            SHIFTJIS_CHARSET = 0x00000080,
            HANGUL_CHARSET = 0x00000081,
            JOHAB_CHARSET = 0x00000082,
            GB2312_CHARSET = 0x00000086,
            CHINESEBIG5_CHARSET = 0x00000088,
            GREEK_CHARSET = 0x000000A1,
            TURKISH_CHARSET = 0x000000A2,
            VIETNAMESE_CHARSET = 0x000000A3,
            HEBREW_CHARSET = 0x000000B1,
            ARABIC_CHARSET = 0x000000B2,
            BALTIC_CHARSET = 0x000000BA,
            RUSSIAN_CHARSET = 0x000000CC,
            THAI_CHARSET = 0x000000DE,
            EASTEUROPE_CHARSET = 0x000000EE,
            OEM_CHARSET = 0x000000FF
        }
        
        public const Int32 LF_FACESIZE = 32; // ref WinGDI.h
        public const Int32 LF_FULLFACESIZE = 64; // ref WinGDI.h
        
        [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;
        }
        
        public struct FontData
        {
            public ENUMLOGFONT LogFont;
            public NEWTEXTMETRIC TextMetric;
            public uint FontType;
        }
        
        [DllImport("gdi32.dll", CharSet = CharSet.Auto)]
        public extern static Int32 EnumFontFamiliesEx(IntPtr hdc, ref LOGFONT lpLogfont, FONTENUMPROC lpEnumFontFamExProc, IntPtr lParam, UInt32 dwFlags);
        
        
        public delegate Int32 FONTENUMPROC(ref ENUMLOGFONT lpelf, ref NEWTEXTMETRIC lpntm, UInt32 FontType, IntPtr lParam);
        public static int EnumFontFamExProc(ref ENUMLOGFONT lpelf, ref NEWTEXTMETRIC lpntm, uint FontType, IntPtr lParam)
        {
            allFontData.Add(new FontData() { LogFont = lpelf, TextMetric = lpntm, FontType = FontType });
            return 1;
        }
        
        #endregion
    
        private static List<FontData> allFontData;
        public static List<FontData> GetAllFonts(IntPtr hdc) 
        {
            allFontData = new List<FontData>();
            Graphics graphics = Graphics.FromHwnd(IntPtr.Zero);
            try
            {           
                var logfont = new LOGFONT() { lfCharSet = (byte)FontLanguageCharSet.DEFAULT_CHARSET };
                EnumFontFamiliesEx(hdc, ref logfont, new FONTENUMPROC(EnumFontFamExProc), IntPtr.Zero, 0);
            }
            catch (Exception)
            {
            }
            finally
            {
                //graphics.ReleaseHdc();
            }
            
            return allFontData;
        }
    }
    

    The hdc passed to GetAllFonts(IntPtr hdc) is obtained throught the folowing code:

    [DllImport("gdi32.dll")]
    public static extern IntPtr CreateDC(string strDriver, string strDevice, string strOutput, IntPtr pData);
    
    ...
    IntPtr hdc = CreateDC("", yourPrinterName, "", System.IntPtr.Zero);
    ...