C#:在文本框中使用嵌入字体

11

我正在将字体作为嵌入式资源嵌入到我的Windows窗体应用程序中,并希望在TextBox中使用它。

AddMemoryFont()的帮助文档说我必须将兼容的文本呈现设置为true才能使用GDI+,然后就可以使用我的字体。但是它似乎无法显示正确的字体。

在Program.cs中,我明确声明:

Application.SetCompatibleTextRenderingDefault(true);

那么为什么它不起作用?有人知道如何将自定义字体设置给文本框吗?

2个回答

31

好的,我通过互联网和Google找到了解决方法。

供以后参考,如果有人遇到这个问题,解决方法如下: 在获取嵌入式字体流后,在调用AddMemoryFont之前,您必须调用AddFontMemResourceEx! (在C#中不可用,因此您必须导入它:

)
    [DllImport("gdi32.dll")]
    private static extern IntPtr AddFontMemResourceEx(IntPtr pbFont, uint cbFont, IntPtr pdv, [In] ref uint pcFonts);

然后:

            //create an unsafe memory block for the data
        System.IntPtr data = Marshal.AllocCoTaskMem((int)fontStream.Length);
        //create a buffer to read in to
        Byte[] fontData = new Byte[fontStream.Length];
        //fetch the font program from the resource
        fontStream.Read(fontData, 0, (int)fontStream.Length);
        //copy the bytes to the unsafe memory block
        Marshal.Copy(fontData, 0, data, (int)fontStream.Length);

        // We HAVE to do this to register the font to the system (Weird .NET bug !)
        uint cFonts = 0;
        AddFontMemResourceEx(data, (uint)fontData.Length, IntPtr.Zero, ref cFonts);

        //pass the font to the font collection
        mFontCollection.AddMemoryFont(data, (int)fontStream.Length);
        //close the resource stream
        fontStream.Close();
        //free the unsafe memory
        Marshal.FreeCoTaskMem(data);

瞬间,您就能使用该字体了。 没有使用AddFontMemResourceEx,它将无法工作。


这里的“fontStream”是从哪里来的? - Mike Fulton
1
你可以从资源中创建流。你应该将字体添加到项目资源中,然后像这样将其转换为流: Stream fontStream = new MemoryStream(Properties.Resources.Font); - Ege Aydın
这似乎是一个很好的解决方案。我正在创建一个自定义控件,并尝试将2个自定义字体嵌入到我拥有的字体集合中。mFontCollection来自哪里,它如何使用?最终,我希望在我的控件中有一个属性,可以像通常选择字体一样选择字体(除了它有两个新字体)。例如:private Font m_FontFace = UserControl.DefaultFont; public Font FontFace { get { return m_FontFace; } set { m_FontFace = value; } } - Arvo Bowen
那里有一个类似的完整代码(用于缺失部分):https://cboard.cprogramming.com/csharp-programming/147926-font-embedding-textbox.html - Furkan Ekinci
如果您使用FontFamily[0]来创建字体对象,似乎可以正常工作。但是,如果您在字体构造函数中使用FamilyName,我总是会得到Microsoft Sans Serif字体。问题是:是否可能通过FamilyName创建字体? - Saftpresse99
当在应用程序中使用字体作为嵌入式资源时,可以完全跳过FontStream的代码。只需将字体添加到项目的资源中,它就已经可用作byte[],以便您可以在此答案中替换Byte[] fontData变量。只需在WinForms应用程序中键入Resource.<FONTNAME>即可。现在,您只需要像此答案中一样注册byte []字体数据即可。 - sɐunıɔןɐqɐp

2

谢谢,它正在运作。

如何在C# Windows应用程序中嵌入字体:

[DllImport("gdi32.dll")]
private static extern IntPtr AddFontMemResourceEx(IntPtr pbFont, uint cbFont, IntPtr pdv, [In] ref uint pcFonts);

    PrivateFontCollection pFC = new PrivateFontCollection();

        try
        {
            string[] resource = { "newFont-Bold.ttf", "newFont-Regular.ttf" }; // specify embedded resource name

            foreach (var item in resource)
            {
                // receive resource stream
                Stream fontStream = Assembly.GetExecutingAssembly().GetManifestResourceStream(item);

                // create an unsafe memory block for the font data
                System.IntPtr data = Marshal.AllocCoTaskMem((int)fontStream.Length);

                // create a buffer to read in to
                byte[] fontdata = new byte[fontStream.Length];

                // read the font data from the resource
                fontStream.Read(fontdata, 0, (int)fontStream.Length);

                // copy the bytes to the unsafe memory block
                Marshal.Copy(fontdata, 0, data, (int)fontStream.Length);

                ///IMPORTANT line to register font in system
                uint cFonts = 0;
                AddFontMemResourceEx(data, (uint)fontdata.Length, IntPtr.Zero, ref cFonts);

                // pass the font to the font collection
                pFC.AddMemoryFont(data, (int)fontStream.Length);

                // close the resource stream
                fontStream.Close();
                // free up the unsafe memory
                Marshal.FreeCoTaskMem(data);
            }
        }
        catch (Exception exp)
        {
            Log.Error(exp);
        }

        return pFC;

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接