我正在使用 Panose.FontFamily 型別過濾字體,我使用的是:
[System.Runtime.InteropServices.DllImport("gdi32.dll", CharSet = System.Runtime.InteropServices.CharSet.Ansi)]
private static extern int GetOutlineTextMetricsA(IntPtr hdc, int cbData, IntPtr lpOtm);
但是,我從 System.Windows.Media.FontFamily 開始。來自串列:System.Windows.Media.Fonts.SystemFontFamilies
我還沒有找到獲取 Media.FontFamily 的 hDC 的方法。因此,我需要將它與 System.Drawing.FontFamily 相匹配。來自串列:System.Drawing.FontFamily.Families
我發現將 Media.FontFamily 映射到 Drawing.FontFamily 的唯一方法是將 Media.FontFamily.Source 與 Drawing.FontFamily.Name 進行比較。這并不完美,因為它們各自的名稱通常不完全匹配。我認為我至少可以匹配 90% 的字體。
使用 Drawing.FontFamily 確實有辦法獲取字體的 hDC。
一個體面的解決方案將是一種更好的方式(除了名稱)將 Media.FontFamily 映射到 Drawing.FontFamily。一個理想的解決方案是直接從 Media.FontFamily 獲取 hDC。另一個理想的解決方案是在不需要匯入基本方法的情況下獲取 OUTLINETEXTMETRICS 結構。一個完美的解決方案是通過涉及 Drawing.FontFamily 或匯入方法從 Media.FontFamily 獲取 panose 系列型別。
首先,我得到 Media.FontFamily 的串列,如下所示:
foreach (Media.FontFamily font in Media.Fonts.SystemFontFamilies.OrderBy(_ => _.Source))
然后我得到 Drawing.FontFamily 的串列,如下所示:
System.Collections.IEnumerator fontIter = Draw.FontFamily.Families.OrderBy(_ => _.Name).GetEnumerator();
然后我將 Media.FontFamily.Source 與 Drawing.FontFamily.Name 進行比較。我發現 Drawing.FontFamily.Name 經常包含 Media.FontFamily.Source。獲得 Drawing.FontFamily 后,很容易將其轉換為 Drawing.Font:
Draw.Font drawFont = new Draw.Font(drawFamily, 9.0F);
從中我得到了 Panose 家族型別:
enum PanoseFontFamilyTypes
{
PAN_ANY = 0, PAN_NO_FIT = 1, PAN_FAMILY_TEXT_DISPLAY = 2, PAN_FAMILY_SCRIPT = 3,
PAN_FAMILY_DECORATIVE = 4, PAN_FAMILY_PICTORIAL = 5
}
public PanoseFontFamilyTypes PanoseFontFamilyType(Draw.Font font)
{
byte bFamilyType = 0;
IntPtr hdc = (IntPtr)0;
IntPtr hFontOld;
try
{
hdc = GraphTool.GetHdc();
hFontOld = SelectObject(hdc, font.ToHfont());
int bufSize = GetOutlineTextMetricsA(hdc, 0, (IntPtr)0);
IntPtr lpOtm = System.Runtime.InteropServices.Marshal.AllocCoTaskMem(bufSize);
System.Runtime.InteropServices.Marshal.WriteInt32(lpOtm, bufSize);
int success = GetOutlineTextMetricsA(hdc, bufSize, lpOtm);
if (success != 0)
{
int offset = 61;
bFamilyType = System.Runtime.InteropServices.Marshal.ReadByte(lpOtm, offset);
}
System.Runtime.InteropServices.Marshal.FreeCoTaskMem(lpOtm);
SelectObject(hdc, hFontOld);
}
catch (Exception ex)
{
MessageBox.Show($"Message: {ex.Message}\r\nStackTrace:\r\n{ex.StackTrace}", "Exception", MessageBoxButton.OK, MessageBoxImage.Error);
}
finally
{
GraphTool.ReleaseHdc(hdc);
}
return (PanoseFontFamilyTypes)bFamilyType;
}
尋找一個不太復雜的解決方案。
uj5u.com熱心網友回復:
我從來沒有找到一種方法來將 Media.FontFamily 映射到不涉及字串比較的 Drawing.FontFamily。但是,我確實找到了一種更可靠的映射方法。問題是 Media.FontFamily.Source(字體名稱)通常不完全對應于 Drawing.FontFamily.Name。
Media.FontFamily font=<your font>;
Typeface face = new Typeface(font, FontStyles.Normal, FontWeights.Normal, FontStretches.Normal);
if (face.TryGetGlyphTypeface(out GlyphTypeface typeFace))
{
Drawing.FontFamily drawFont = Drawing.FontFamily.Families.FirstOrDefault(_o => typeFace.Win32FamilyNames.Any(_i => _i.Value.Equals(_o.Name, StringComparison.OrdinalIgnoreCase)));
return new Tuple<FontUtility.OutlineTextMetric, bool>(GetOutlineTextMetric(drawFont, fontData), typeFace.Symbol);
}
GetOutlineTextMetric 方法使用此處找到的代碼獲取 OUTLINETEXTMETRIC:http: //pinvoke.net/default.aspx/gdi32/GetOutlineTextMetrics.html
Win32FamilyNames 中的名稱確實映射到 Drawing.FontFamily.Name。我能夠擺脫我正在使用的包含字串演算法。
這還有獲得 Symbol 布林值的額外好處,至少對于我安裝的每種字體來說,它都能 100% 準確地識別符號字體。(例如翼飾)
轉載請註明出處,本文鏈接:https://www.uj5u.com/net/535142.html
標籤:C#wpf字体
上一篇:如何在第二個ObservableCollection<T>更改時更新一個ObservableCollection<T>
