如何在我的 C# 应用程序中嵌入字体? (使用 Visual Studio 2005)

发布于 2024-07-16 02:49:19 字数 236 浏览 3 评论 0原文

在我正在开发的应用程序中嵌入 truetype 字体的最佳方法是什么? 基本上我想确保在另一台机器上安装时我的应用程序可以使用特定的字体。 我有 *.ttf 字体文件,只需要一种嵌入它或在应用程序运行时自动安装它的方法。

我是否需要设置安装程序来在安装过程中安装字体,或者我可以在应用程序运行时动态加载字体吗? 事实上,如果知道的话,我们都会很高兴。

该应用程序是使用 .NET 2.0 用 C# 开发的。

What is the best way to embed a truetype font within the application i'm developing? Basically i want to make sure a particular font is available to my application when installed on another machine. I have the *.ttf font file and just need a way of embedding it or automatically installing it when the application is run.

Do i need to set the installation program to install the font during installation or can i dynamically load the font during runtime of the application? In fact both would be nice to know.

The application is being developed in C# using .NET 2.0.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

凶凌 2024-07-23 02:49:19

这篇博客文章应该对您有帮助。

基本上,您将字体添加为嵌入资源,然后将其加载到 PrivateFontCollection 对象。

This blog post should help you.

Basically you add the font as an embedded resource then load it into a PrivateFontCollection object.

岁月打碎记忆 2024-07-23 02:49:19

这是 Will 的答案,翻译成 C#(未经测试):

PrivateFontCollection pfc = new PrivateFontCollection();

using (Stream fontStream = GetType().Assembly.GetManifestResourceStream("Alphd___.ttf"))
{
    if (null == fontStream)
    {
        return;
    }

    int fontStreamLength = (int) fontStream.Length;

    IntPtr data = Marshal.AllocCoTaskMem(fontStreamLength);

    byte[] fontData = new byte[fontStreamLength];
    fontStream.Read(fontData, 0, fontStreamLength);

    Marshal.Copy(fontData, 0, data, fontStreamLength);

    pfc.AddMemoryFont(data, fontStreamLength);

    Marshal.FreeCoTaskMem(data);
}

以及他们的 Paint() 方法:

protected void Form1_Paint(object sender, PaintEventArgs e)
{
    bool bold = false;
    bool italic = false;

    e.Graphics.PageUnit = GraphicsUnit.Point;

    using (SolidBrush b = new SolidBrush(Color.Black))
    {
        int y = 5;

        foreach (FontFamily fontFamily in pfc.Families)
        {
            if (fontFamily.IsStyleAvailable(FontStyle.Regular))
            {
                using (Font font = new Font(fontFamily, 32, FontStyle.Regular))
                {
                    e.Graphics.DrawString(font.Name, font, b, 5, y, StringFormat.GenericTypographic);
                }
                y += 40;
            }
            if (fontFamily.IsStyleAvailable(FontStyle.Bold))
            {
                bold = true;
                using (Font font = new Font(fontFamily, 32, FontStyle.Bold))
                {
                    e.Graphics.DrawString(font.Name, font, b, 5, y, StringFormat.GenericTypographic);
                }
                y += 40;
            }
            if (fontFamily.IsStyleAvailable(FontStyle.Italic))
            {
                italic = true;
                using (Font font = new Font(fontFamily, 32, FontStyle.Italic))
                {
                    e.Graphics.DrawString(font.Name, font, b, 5, y, StringFormat.GenericTypographic);
                }
                y += 40;
            }

            if(bold && italic)
            {
                using(Font font = new Font(fontFamily, 32, FontStyle.Bold | FontStyle.Italic))
                {
                    e.Graphics.DrawString(font.Name, font, b, 5, y, StringFormat.GenericTypographic);
                }
                y += 40;
            }

            using (Font font = new Font(fontFamily, 32, FontStyle.Underline))
            {
                e.Graphics.DrawString(font.Name, font, b, 5, y, StringFormat.GenericTypographic);
                y += 40;
            }

            using (Font font = new Font(fontFamily, 32, FontStyle.Strikeout))
            {
                e.Graphics.DrawString(font.Name, font, b, 5, y, StringFormat.GenericTypographic);
            }
        }
    }
}

Here's Will's answer, translated to C# (untested):

PrivateFontCollection pfc = new PrivateFontCollection();

using (Stream fontStream = GetType().Assembly.GetManifestResourceStream("Alphd___.ttf"))
{
    if (null == fontStream)
    {
        return;
    }

    int fontStreamLength = (int) fontStream.Length;

    IntPtr data = Marshal.AllocCoTaskMem(fontStreamLength);

    byte[] fontData = new byte[fontStreamLength];
    fontStream.Read(fontData, 0, fontStreamLength);

    Marshal.Copy(fontData, 0, data, fontStreamLength);

    pfc.AddMemoryFont(data, fontStreamLength);

    Marshal.FreeCoTaskMem(data);
}

along with their Paint() method:

protected void Form1_Paint(object sender, PaintEventArgs e)
{
    bool bold = false;
    bool italic = false;

    e.Graphics.PageUnit = GraphicsUnit.Point;

    using (SolidBrush b = new SolidBrush(Color.Black))
    {
        int y = 5;

        foreach (FontFamily fontFamily in pfc.Families)
        {
            if (fontFamily.IsStyleAvailable(FontStyle.Regular))
            {
                using (Font font = new Font(fontFamily, 32, FontStyle.Regular))
                {
                    e.Graphics.DrawString(font.Name, font, b, 5, y, StringFormat.GenericTypographic);
                }
                y += 40;
            }
            if (fontFamily.IsStyleAvailable(FontStyle.Bold))
            {
                bold = true;
                using (Font font = new Font(fontFamily, 32, FontStyle.Bold))
                {
                    e.Graphics.DrawString(font.Name, font, b, 5, y, StringFormat.GenericTypographic);
                }
                y += 40;
            }
            if (fontFamily.IsStyleAvailable(FontStyle.Italic))
            {
                italic = true;
                using (Font font = new Font(fontFamily, 32, FontStyle.Italic))
                {
                    e.Graphics.DrawString(font.Name, font, b, 5, y, StringFormat.GenericTypographic);
                }
                y += 40;
            }

            if(bold && italic)
            {
                using(Font font = new Font(fontFamily, 32, FontStyle.Bold | FontStyle.Italic))
                {
                    e.Graphics.DrawString(font.Name, font, b, 5, y, StringFormat.GenericTypographic);
                }
                y += 40;
            }

            using (Font font = new Font(fontFamily, 32, FontStyle.Underline))
            {
                e.Graphics.DrawString(font.Name, font, b, 5, y, StringFormat.GenericTypographic);
                y += 40;
            }

            using (Font font = new Font(fontFamily, 32, FontStyle.Strikeout))
            {
                e.Graphics.DrawString(font.Name, font, b, 5, y, StringFormat.GenericTypographic);
            }
        }
    }
}
握住我的手 2024-07-23 02:49:19

它比看起来容易; 您可以将字体作为资源嵌入到应用程序中,并在应用程序的 Properties 命名空间中将其作为强类型属性进行访问。 但给定的链接应该是一个很好的起点。


对于禁用 VB 的用户:

将字体添加为应用程序中的资源。 调用资源 MyFontLol。 您可以从 Properties.Resources.MyFontLol 访问此资源(作为字节数组)。

我还没有测试以下内容,但它似乎是可行的:

public void LoadMyFontLolKThx()
{
    // get our font and wrap it in a memory stream
    byte[] myFont = Properties.Resources.MyFontLol;
    using (var ms = new MemoryStream(myFont))
    {
        // used to store our font and make it available in our app
        PrivateFontCollection pfc = new PrivateFontCollection();
        // The next call requires a pointer to our memory font
        // I'm doing it this way; not sure what best practice is
        GCHandle handle = GCHandle.Alloc(ms, GCHandleType.Pinned);
        // If Length > int.MaxValue this will throw
        checked
        {
            pfc.AddMemoryFont(
                handle.AddrOfPinnedObject(), (int)ms.Length); 
        }
        var font = new Font(pfc.Families[0],12);

        // use your font here
    }
}

最后一点。 PFC 将字体存储为 GDI+ 字体。 这些与某些表单控件不兼容。 来自文档:

要使用内存字体,请在
控件必须使用 GDI+ 呈现。
使用
设置CompatibleTextRenderingDefault
方法,传递true,设置GDI+
在应用程序上渲染,或者在
通过设置单独控制
控件的 UseCompatibleTextRendering
属性为真。 有些控件不能
使用 GDI+ 渲染。

Its easier than this seems; you can embed the font as a resource in your app and access it as a strongly-typed property within the Properties namespace of your app. But the given link should be a good starting point.


For the VB-disabled:

Add the font as a resource in your application. Call the resource MyFontLol. You can access this resource (as a byte array) from Properties.Resources.MyFontLol.

I haven't tested the following, but it appears to be workable:

public void LoadMyFontLolKThx()
{
    // get our font and wrap it in a memory stream
    byte[] myFont = Properties.Resources.MyFontLol;
    using (var ms = new MemoryStream(myFont))
    {
        // used to store our font and make it available in our app
        PrivateFontCollection pfc = new PrivateFontCollection();
        // The next call requires a pointer to our memory font
        // I'm doing it this way; not sure what best practice is
        GCHandle handle = GCHandle.Alloc(ms, GCHandleType.Pinned);
        // If Length > int.MaxValue this will throw
        checked
        {
            pfc.AddMemoryFont(
                handle.AddrOfPinnedObject(), (int)ms.Length); 
        }
        var font = new Font(pfc.Families[0],12);

        // use your font here
    }
}

One last note. The PFC stores the font as a GDI+ font. These aren't compatible with some forms controls. From the docs:

To use the memory font, text on a
control must be rendered with GDI+.
Use the
SetCompatibleTextRenderingDefault
method, passing true, to set GDI+
rendering on the application, or on
individual controls by setting the
control's UseCompatibleTextRendering
property to true. Some controls cannot
be rendered with GDI+.

ぺ禁宫浮华殁 2024-07-23 02:49:19

这可能不是最好的方法,但是您不能将字体包含在资源中,然后将其复制到 Windows 目录上的字体文件夹中吗?

it might not be the best way but couldn't you just include the font with your resources and then copy it to the font's folder on the windows dir?

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文