С#: использование встроенного шрифта в текстовом поле

Я встраиваю шрифт в свое приложение Windows Forms в качестве встроенного ресурса и хочу использовать его в файле TextBox.

В справке AddMemoryFont() говорится, что я должен установить для совместимого рендеринга текста значение true, чтобы использовать GDI+, и тогда можно будет использовать мой шрифт. Но почему-то он просто не отображает правильный шрифт.

В Program.cs я прямо указываю:

Application.SetCompatibleTextRenderingDefault(true);

Так почему же это не работает? Кто-нибудь понял, как установить собственный шрифт в TextBox?


person Led    schedule 23.12.2009    source источник


Ответы (2)


Ладно, я разобрался благодаря интернету и гуглю.

Для справки в будущем, если у кого-то возникнет эта проблема, исправление таково: после получения вашего встроенного шрифта в виде потока и перед вызовом 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 это не сработает.

person Led    schedule 24.12.2009
comment
Откуда берется fontStream? - person Mike Fulton; 02.02.2016
comment
вы можете создать свой поток из ресурсов. Вы должны добавить свой шрифт в ресурсы вашего проекта, а затем преобразовать его в поток следующим образом: Stream fontStream = new MemoryStream(Properties.Resources.Font); - person Ege Aydın; 28.07.2016
comment
Кажется, это было бы отличным решением. Я создаю пользовательский элемент управления и пытаюсь встроить 2 пользовательских шрифта в коллекцию шрифтов, которая у меня есть. Откуда взялось mFontCollection и как оно используется? Я надеюсь, что в конце концов у меня будет свойство, из которого я смогу выбрать шрифт, как обычно (за исключением того, что у него есть два новых шрифта). Пример: private Font m_FontFace = UserControl.DefaultFont; public Font FontFace { get { return m_FontFace; } set { m_FontFace = value; } } - person Arvo Bowen; 09.12.2016
comment
Там есть аналогичный и полный код (для недостающих частей): cboard.cprogramming.com/csharp-programming/ - person Furkan Ekinci; 26.08.2017
comment
Кажется, это работает, если вы используете FontFamily[0] для создания Font-Object. Но если вы используете FamilyName в конструкторе шрифтов, я всегда получаю шрифт Microsoft Sans Serif. Вопрос: Можно ли создать шрифт по FamilyName? - person Saftpresse99; 21.02.2019
comment
Можно полностью пропустить код для FontStream при использовании шрифта в качестве встроенного ресурса в приложении. Просто добавьте шрифт в ресурсы проекта, и он уже будет доступен как byte[], чтобы вы могли использовать его вместо этой переменной Byte[] fontData в этом ответе. Просто введите Resource.‹FONTNAME› в своем приложении WinForms. Теперь вам просто нужно зарегистрировать данные шрифта byte [], как в этом ответе. - person sɐunıɔןɐqɐp; 18.05.2021

Спасибо, это работает. Встроить шрифт в приложение С# для 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;
person PPr    schedule 07.01.2020