使用对EnumFontFamiliesEx的DLL调用枚举C#中的活动字体使我感到非常困惑
我的最终目标是列出windows计算机上的所有活动字体。例如,如果您启动写字板或Word,您将看到它们。其中一些字体来自windows\fonts文件夹,但不是全部。有些是使用gdi32.dll调用AddFontResource(…)动态注册的。现在,你可能认为C#支持检索整个列表,如果是,请告诉我 然而,在花了很多时间在这上面之后,为了安装系统字体而进行的常规C#调用只会检索到所有实际活动的字体中的一部分。例如,InstalledFontCollection.Families找不到随AddFontResource添加的任何字体(它找到写字板中列出的字体的25%) 虽然我想在C#中执行此操作,但似乎我必须使用更多的gdi32.dll调用。我的EnumFontFamiliesEx问题就这样开始了 我已经成功地使下面的代码工作到了一个地步,我得到了一堆带有字体的回调。但是,结构ENUMLOGFONTEX似乎已损坏,例如lpelfe.elfFullName通常包含两个方形字符,而不是实名。也许我在编组或结构定义方面犯了错误,我不太确定。我尝试了多次迭代和无休止的谷歌搜索,但都没有用 任何帮助都将不胜感激使用对EnumFontFamiliesEx的DLL调用枚举C#中的活动字体使我感到非常困惑,c#,dll,fonts,callback,gdi,C#,Dll,Fonts,Callback,Gdi,我的最终目标是列出windows计算机上的所有活动字体。例如,如果您启动写字板或Word,您将看到它们。其中一些字体来自windows\fonts文件夹,但不是全部。有些是使用gdi32.dll调用AddFontResource(…)动态注册的。现在,你可能认为C#支持检索整个列表,如果是,请告诉我 然而,在花了很多时间在这上面之后,为了安装系统字体而进行的常规C#调用只会检索到所有实际活动的字体中的一部分。例如,InstalledFontCollection.Families找不到随AddFo
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Windows.Media;
using System.Runtime.InteropServices;
using Microsoft.Win32;
namespace FontRetriever
{
public partial class TestForm : Form
{
[DllImport("gdi32.dll")]
static extern int EnumFontFamiliesEx(IntPtr hdc,
[In] IntPtr pLogfont,
EnumFontExDelegate lpEnumFontFamExProc,
IntPtr lParam,
uint dwFlags);
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
public class LOGFONT
{
public int lfHeight;
public int lfWidth;
public int lfEscapement;
public int lfOrientation;
public FontWeight lfWeight;
[MarshalAs(UnmanagedType.U1)]
public bool lfItalic;
[MarshalAs(UnmanagedType.U1)]
public bool lfUnderline;
[MarshalAs(UnmanagedType.U1)]
public bool lfStrikeOut;
public FontCharSet lfCharSet;
public FontPrecision lfOutPrecision;
public FontClipPrecision lfClipPrecision;
public FontQuality lfQuality;
public FontPitchAndFamily lfPitchAndFamily;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)]
public string lfFaceName;
}
public enum FontWeight : int
{
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 FontCharSet : byte
{
ANSI_CHARSET = 0,
DEFAULT_CHARSET = 1,
SYMBOL_CHARSET = 2,
SHIFTJIS_CHARSET = 128,
HANGEUL_CHARSET = 129,
HANGUL_CHARSET = 129,
GB2312_CHARSET = 134,
CHINESEBIG5_CHARSET = 136,
OEM_CHARSET = 255,
JOHAB_CHARSET = 130,
HEBREW_CHARSET = 177,
ARABIC_CHARSET = 178,
GREEK_CHARSET = 161,
TURKISH_CHARSET = 162,
VIETNAMESE_CHARSET = 163,
THAI_CHARSET = 222,
EASTEUROPE_CHARSET = 238,
RUSSIAN_CHARSET = 204,
MAC_CHARSET = 77,
BALTIC_CHARSET = 186,
}
public enum FontPrecision : byte
{
OUT_DEFAULT_PRECIS = 0,
OUT_STRING_PRECIS = 1,
OUT_CHARACTER_PRECIS = 2,
OUT_STROKE_PRECIS = 3,
OUT_TT_PRECIS = 4,
OUT_DEVICE_PRECIS = 5,
OUT_RASTER_PRECIS = 6,
OUT_TT_ONLY_PRECIS = 7,
OUT_OUTLINE_PRECIS = 8,
OUT_SCREEN_OUTLINE_PRECIS = 9,
OUT_PS_ONLY_PRECIS = 10,
}
public enum FontClipPrecision : byte
{
CLIP_DEFAULT_PRECIS = 0,
CLIP_CHARACTER_PRECIS = 1,
CLIP_STROKE_PRECIS = 2,
CLIP_MASK = 0xf,
CLIP_LH_ANGLES = (1 << 4),
CLIP_TT_ALWAYS = (2 << 4),
CLIP_DFA_DISABLE = (4 << 4),
CLIP_EMBEDDED = (8 << 4),
}
public enum FontQuality : byte
{
DEFAULT_QUALITY = 0,
DRAFT_QUALITY = 1,
PROOF_QUALITY = 2,
NONANTIALIASED_QUALITY = 3,
ANTIALIASED_QUALITY = 4,
CLEARTYPE_QUALITY = 5,
CLEARTYPE_NATURAL_QUALITY = 6,
}
[Flags]
public enum FontPitchAndFamily : byte
{
DEFAULT_PITCH = 0,
FIXED_PITCH = 1,
VARIABLE_PITCH = 2,
FF_DONTCARE = (0 << 4),
FF_ROMAN = (1 << 4),
FF_SWISS = (2 << 4),
FF_MODERN = (3 << 4),
FF_SCRIPT = (4 << 4),
FF_DECORATIVE = (5 << 4),
}
[StructLayout(LayoutKind.Sequential)]
public class NEWTEXTMETRICEX
{
//public const int LF_FACESIZE = 32;
public int tmHeight;
public int tmAscent;
public int tmDescent;
public int tmInternalLeading;
public int tmExternalLeading;
public int tmAveCharWidth;
public int tmMaxCharWidth;
public int tmWeight;
public int tmOverhang;
public int tmDigitizedAspectX;
public int 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;
}
private const byte DEFAULT_CHARSET = 1;
private const byte SHIFTJIS_CHARSET = 128;
private const byte JOHAB_CHARSET = 130;
private const byte EASTEUROPE_CHARSET = 238;
private const byte DEFAULT_PITCH = 0;
private const byte FIXED_PITCH = 1;
private const byte VARIABLE_PITCH = 2;
private const byte FF_DONTCARE = (0 << 4);
private const byte FF_ROMAN = (1 << 4);
private const byte FF_SWISS = (2 << 4);
private const byte FF_MODERN = (3 << 4);
private const byte FF_SCRIPT = (4 << 4);
private const byte FF_DECORATIVE = (5 << 4);
public TestForm()
{
InitializeComponent();
}
private int cnt = 0;
private void TestForm_Load(object sender, EventArgs e)
{
LOGFONT lf = CreateLogFont("");
IntPtr plogFont = Marshal.AllocHGlobal(Marshal.SizeOf(lf));
Marshal.StructureToPtr(lf, plogFont, true);
int ret = 0;
try
{
Graphics G = pictureBox1.CreateGraphics();
IntPtr P = G.GetHdc();
del1 = new EnumFontExDelegate(callback1);
ret = EnumFontFamiliesEx(P, plogFont, del1, IntPtr.Zero, 0);
System.Diagnostics.Trace.WriteLine("EnumFontFamiliesEx = " + ret.ToString());
}
catch
{
System.Diagnostics.Trace.WriteLine("Exception");
}
}
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
public struct ENUMLOGFONTEX
{
public LOGFONT elfLogFont;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 64)]
public string elfFullName;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)]
public string elfStyle;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)]
public string elfScript;
}
public delegate int EnumFontExDelegate(ref ENUMLOGFONTEX lpelfe, IntPtr lpntme, int FontType, int lParam);
public EnumFontExDelegate del1;
public int callback1(ref ENUMLOGFONTEX lpelfe, IntPtr lpntme, int FontType, int lParam)
{
try
{
++cnt;
Font F = Font.FromLogFont(lpelfe.elfLogFont);
Console.WriteLine(F.Name + " " + lpelfe.elfFullName);
}
catch
{
System.Diagnostics.Trace.WriteLine("What happened?");
}
return cnt;
}
public static LOGFONT CreateLogFont(string fontname)
{
LOGFONT lf = new LOGFONT();
lf.lfHeight = 0;
lf.lfWidth = 0;
lf.lfEscapement = 0;
lf.lfOrientation = 0;
lf.lfWeight = 0;
lf.lfItalic = false;
lf.lfUnderline = false;
lf.lfStrikeOut = false;
lf.lfCharSet = FontCharSet.DEFAULT_CHARSET;
lf.lfOutPrecision = 0;
lf.lfClipPrecision = 0;
lf.lfQuality = 0;
lf.lfPitchAndFamily = FontPitchAndFamily.FF_DONTCARE;
lf.lfFaceName = "";
return lf;
}
}
使用系统;
使用System.Collections.Generic;
使用系统组件模型;
使用系统数据;
使用系统图;
使用System.Linq;
使用系统文本;
使用System.Windows.Forms;
使用System.Windows.Media;
使用System.Runtime.InteropServices;
使用Microsoft.Win32;
名称空间检索器
{
公共部分类TestForm:Form
{
[DllImport(“gdi32.dll”)]
静态外部int ENUMFONTFAMILESEX(IntPtr hdc,
[In]IntPtr pLogfont,
EnumFontExDelegate lpEnumFontFamExProc,
IntPtr LPRAM,
uint(dwFlags);
[StructLayout(LayoutKind.Sequential,CharSet=CharSet.Auto)]
公共类LOGFONT
{
公众身高;
公共宽度;
公共擒纵机构;
公众导向;
公众体重;
[Marshallas(UnmanagedType.U1)]
公共图书馆;
[Marshallas(UnmanagedType.U1)]
公共图书馆;
[Marshallas(UnmanagedType.U1)]
公众罢工;
公共fontscharset-lfCharSet;
公共输出精度;
公共fontclipprection lfclipprection;
公共质量;
公共FontPitchAndFamily lfPitchAndFamily;
[Marshallas(UnmanagedType.ByValTStr,SizeConst=32)]
公共字符串名称;
}
公共枚举字体权重:int
{
FW_DONTCARE=0,
FW_THIN=100,
FW_超轻=200,
FW_灯=300,
FW_正常值=400,
FW_中等=500,
FW_半黑体=600,
FW_黑体=700,
FW_EXTRABOLD=800,
FW_重型=900,
}
公共枚举FontCharSet:字节
{
ANSI_字符集=0,
默认字符集=1,
符号_字符集=2,
SHIFTJIS_字符集=128,
Hangul_字符集=129,
韩国语字符集=129,
GB2312_字符集=134,
CHINESEBIG5_字符集=136,
OEM_字符集=255,
JOHAB_CHARSET=130,
希伯来语字符集=177,
阿拉伯文字符集=178,
希腊文字符集=161,
土耳其语字符集=162,
越南语字符集=163,
泰文字符集=222,
东欧字符集=238,
俄语字符集=204,
MAC_CHARSET=77,
波罗的海字符集=186,
}
公共枚举精度:字节
{
OUT\u DEFAULT\u PRECIS=0,
OUT\u STRING\u PRECIS=1,
OUT\u CHARACTER\u PRECIS=2,
输出冲程精度=3,
OUT_TT_PRECIS=4,
输出设备精度=5,
输出光栅精度=6,
OUT_TT_ONLY_PRECIS=7,
OUT\u OUTLINE\u PRECIS=8,
屏幕外轮廓精度=9,
OUT\u PS\u ONLY\u PRECIS=10,
}
公共枚举fontclipprection:字节
{
CLIP\u DEFAULT\u PRECIS=0,
CLIP\u CHARACTER\u PRECIS=1,
卡扣_行程_精度=2,
CLIP_MASK=0xf,
CLIP_LH_ANGLES=(1将CharSet=CharSet.Auto添加到EnumFontFamiliesEx上的DllImport属性应该会解决这个问题。就像Merlyn的提示一样,这是一个ANSI/Unicode不匹配的问题
别忘了释放Marshal.AllocHGlobal分配的内存。谢谢Mattias的回答。结果我遇到了一些问题,我从其他论坛得到了一些帮助解决这些问题的答案。下面是最后的代码供大家欣赏
[DllImport("gdi32.dll", CharSet = CharSet.Auto)]
static extern int EnumFontFamiliesEx(IntPtr hdc,
[In] IntPtr pLogfont,
EnumFontExDelegate lpEnumFontFamExProc,
IntPtr lParam,
uint dwFlags);
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
public class LOGFONT
{
public int lfHeight;
public int lfWidth;
public int lfEscapement;
public int lfOrientation;
public FontWeight lfWeight;
[MarshalAs(UnmanagedType.U1)]
public bool lfItalic;
[MarshalAs(UnmanagedType.U1)]
public bool lfUnderline;
[MarshalAs(UnmanagedType.U1)]
public bool lfStrikeOut;
public FontCharSet lfCharSet;
public FontPrecision lfOutPrecision;
public FontClipPrecision lfClipPrecision;
public FontQuality lfQuality;
public FontPitchAndFamily lfPitchAndFamily;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)]
public string lfFaceName;
}
public enum FontWeight : int
{
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 FontCharSet : byte
{
ANSI_CHARSET = 0,
DEFAULT_CHARSET = 1,
SYMBOL_CHARSET = 2,
SHIFTJIS_CHARSET = 128,
HANGEUL_CHARSET = 129,
HANGUL_CHARSET = 129,
GB2312_CHARSET = 134,
CHINESEBIG5_CHARSET = 136,
OEM_CHARSET = 255,
JOHAB_CHARSET = 130,
HEBREW_CHARSET = 177,
ARABIC_CHARSET = 178,
GREEK_CHARSET = 161,
TURKISH_CHARSET = 162,
VIETNAMESE_CHARSET = 163,
THAI_CHARSET = 222,
EASTEUROPE_CHARSET = 238,
RUSSIAN_CHARSET = 204,
MAC_CHARSET = 77,
BALTIC_CHARSET = 186,
}
public enum FontPrecision : byte
{
OUT_DEFAULT_PRECIS = 0,
OUT_STRING_PRECIS = 1,
OUT_CHARACTER_PRECIS = 2,
OUT_STROKE_PRECIS = 3,
OUT_TT_PRECIS = 4,
OUT_DEVICE_PRECIS = 5,
OUT_RASTER_PRECIS = 6,
OUT_TT_ONLY_PRECIS = 7,
OUT_OUTLINE_PRECIS = 8,
OUT_SCREEN_OUTLINE_PRECIS = 9,
OUT_PS_ONLY_PRECIS = 10,
}
public enum FontClipPrecision : byte
{
CLIP_DEFAULT_PRECIS = 0,
CLIP_CHARACTER_PRECIS = 1,
CLIP_STROKE_PRECIS = 2,
CLIP_MASK = 0xf,
CLIP_LH_ANGLES = (1 << 4),
CLIP_TT_ALWAYS = (2 << 4),
CLIP_DFA_DISABLE = (4 << 4),
CLIP_EMBEDDED = (8 << 4),
}
public enum FontQuality : byte
{
DEFAULT_QUALITY = 0,
DRAFT_QUALITY = 1,
PROOF_QUALITY = 2,
NONANTIALIASED_QUALITY = 3,
ANTIALIASED_QUALITY = 4,
CLEARTYPE_QUALITY = 5,
CLEARTYPE_NATURAL_QUALITY = 6,
}
[Flags]
public enum FontPitchAndFamily : byte
{
DEFAULT_PITCH = 0,
FIXED_PITCH = 1,
VARIABLE_PITCH = 2,
FF_DONTCARE = (0 << 4),
FF_ROMAN = (1 << 4),
FF_SWISS = (2 << 4),
FF_MODERN = (3 << 4),
FF_SCRIPT = (4 << 4),
FF_DECORATIVE = (5 << 4),
}
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
public struct NEWTEXTMETRIC
{
public int tmHeight;
public int tmAscent;
public int tmDescent;
public int tmInternalLeading;
public int tmExternalLeading;
public int tmAveCharWidth;
public int tmMaxCharWidth;
public int tmWeight;
public int tmOverhang;
public int tmDigitizedAspectX;
public int 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;
int ntmFlags;
int ntmSizeEM;
int ntmCellHeight;
int ntmAvgWidth;
}
public struct FONTSIGNATURE
{
[MarshalAs(UnmanagedType.ByValArray)]
int[] fsUsb;
[MarshalAs(UnmanagedType.ByValArray)]
int[] fsCsb;
}
public struct NEWTEXTMETRICEX
{
NEWTEXTMETRIC ntmTm;
FONTSIGNATURE ntmFontSig;
}
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
public struct ENUMLOGFONTEX
{
public LOGFONT elfLogFont;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 64)]
public string elfFullName;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)]
public string elfStyle;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)]
public string elfScript;
}
private const byte DEFAULT_CHARSET = 1;
private const byte SHIFTJIS_CHARSET = 128;
private const byte JOHAB_CHARSET = 130;
private const byte EASTEUROPE_CHARSET = 238;
private const byte DEFAULT_PITCH = 0;
private const byte FIXED_PITCH = 1;
private const byte VARIABLE_PITCH = 2;
private const byte FF_DONTCARE = (0 << 4);
private const byte FF_ROMAN = (1 << 4);
private const byte FF_SWISS = (2 << 4);
private const byte FF_MODERN = (3 << 4);
private const byte FF_SCRIPT = (4 << 4);
private const byte FF_DECORATIVE = (5 << 4);
…
private void TestForm_Load(object sender, EventArgs e)
{
LOGFONT lf = CreateLogFont("");
IntPtr plogFont = Marshal.AllocHGlobal(Marshal.SizeOf(lf));
Marshal.StructureToPtr(lf, plogFont, true);
int ret = 0;
try
{
Graphics G = pictureBox1.CreateGraphics();
IntPtr P = G.GetHdc();
del1 = new EnumFontExDelegate(callback1);
ret = EnumFontFamiliesEx(P, plogFont, del1, IntPtr.Zero, 0);
System.Diagnostics.Trace.WriteLine("EnumFontFamiliesEx = " + ret.ToString());
G.ReleaseHdc(P);
}
catch
{
System.Diagnostics.Trace.WriteLine("Error!");
}
finally
{
Marshal.DestroyStructure(plogFont, typeof(LOGFONT));
}
}
public delegate int EnumFontExDelegate(ref ENUMLOGFONTEX lpelfe, ref NEWTEXTMETRICEX lpntme, int FontType, int lParam);
public EnumFontExDelegate del1;
public int callback1(ref ENUMLOGFONTEX lpelfe, ref NEWTEXTMETRICEX lpntme, int FontType, int lParam)
{
try
{
// Do something cool
}
catch (Exception e)
{
System.Diagnostics.Trace.WriteLine(e.ToString());
}
return cnt;
}
public static LOGFONT CreateLogFont(string fontname)
{
LOGFONT lf = new LOGFONT();
lf.lfHeight = 0;
lf.lfWidth = 0;
lf.lfEscapement = 0;
lf.lfOrientation = 0;
lf.lfWeight = 0;
lf.lfItalic = false;
lf.lfUnderline = false;
lf.lfStrikeOut = false;
lf.lfCharSet = FontCharSet.DEFAULT_CHARSET;
lf.lfOutPrecision = 0;
lf.lfClipPrecision = 0;
lf.lfQuality = 0;
lf.lfPitchAndFamily = FontPitchAndFamily.FF_DONTCARE;
lf.lfFaceName = "";
return lf;
}
[DllImport(“gdi32.dll”,CharSet=CharSet.Auto)]
静态外部int ENUMFONTFAMILESEX(IntPtr hdc,
[In]IntPtr pLogfont,
EnumFontExDelegate lpEnumFontFamExProc,
IntPtr LPRAM,
uint(dwFlags);
[StructLayout(LayoutKind.Sequential,CharSet=CharSet.Auto)]
公共类LOGFONT
{
公众身高;
公共宽度;
公共擒纵机构;
公众导向;
公众体重;
[Marshallas(UnmanagedType.U1)]
公共图书馆;
[Marshallas(UnmanagedType.U1)]
公共图书馆;
[Marshallas(UnmanagedType.U1)]
公众罢工;
公共fontscharset-lfCharSet;
公共输出精度;
公共fontclipprection lfclipprection;
公共质量;
公共FontPitchAndFamily lfPitchAndFamily;
[Marshallas(UnmanagedType.ByValTStr,SizeConst=32)]
公共字符串名称;
}
公共枚举字体权重:int
{
FW_DONTCARE=0,
FW_THIN=100,
FW_超轻=200,
FW_灯=300,