web-dev-qa-db-ja.com

C#のwinformsアプリにフォントをすばやく簡単に埋め込む方法

これはおそらくnoobの領域ですが、一体何を意味します:

フォントがマシンにインストールされることを心配する必要がないように、winformsアプリケーションにフォントを埋め込みたいです。 MSDNサイトで少し検索したところ、ネイティブのWindows API呼び出しの使用に関するヒントがいくつか見つかりました。たとえば、Scott HanselmanによってリンクされているMichael Caplans(sp?)チュートリアルなどです。今、私は本当にそのすべてのトラブルを経験しなければなりませんか?アプリのリソース部分だけを使用することはできませんか?

そうでない場合は、おそらくインストールのルートに行きます。その場合、プログラムでそれを行うことができますか?フォントファイルをWindows\Fontsフォルダにコピーするだけですか?

編集:私はライセンスの問題を認識していますが、心配はありません。

30
Niklas Winde

これは、安全でないブロックを使用する必要なく、VS 2013で私にとってうまくいきました。

リソースを埋め込む

  1. Resources.resxをダブルクリックし、デザイナーのツールバーで[リソースの追加]/[既存のファイルの追加]をクリックして、.ttfファイルを選択します
  2. ソリューションエクスプローラーで、.ttfファイル(現在はResourcesフォルダー内)を右クリックし、[プロパティ]に移動します。ビルドアクションを「組み込みリソース」に設定します

フォントをメモリにロード

  1. 追加 using System.Drawing.Text;をForm1.csファイルに

  2. 上記およびデフォルトのコンストラクター内にコードを追加して、メモリ内にフォントを作成します(他の例が示すように「unsafe」を使用しません)。以下は私のForm1.cs全体です。

    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Drawing;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    using System.Windows.Forms;
    using System.Reflection;
    
    using System.Drawing.Text;
    
    namespace WindowsFormsApplication1
    {
        public partial class Form1 : Form
        {
            [System.Runtime.InteropServices.DllImport("gdi32.dll")]
            private static extern IntPtr AddFontMemResourceEx(IntPtr pbFont, uint cbFont,
                IntPtr pdv, [System.Runtime.InteropServices.In] ref uint pcFonts);
    
            private PrivateFontCollection fonts = new PrivateFontCollection();
    
            Font myFont;
    
            public Form1()
            {
                InitializeComponent();
    
                byte[] fontData = Properties.Resources.MyFontName;
                IntPtr fontPtr = System.Runtime.InteropServices.Marshal.AllocCoTaskMem(fontData.Length);
                System.Runtime.InteropServices.Marshal.Copy(fontData, 0, fontPtr, fontData.Length);
                uint dummy = 0;
                fonts.AddMemoryFont(fontPtr, Properties.Resources.MyFontName.Length);
                AddFontMemResourceEx(fontPtr, (uint)Properties.Resources.MyFontName.Length, IntPtr.Zero, ref dummy);
                System.Runtime.InteropServices.Marshal.FreeCoTaskMem(fontPtr);
    
                myFont = new Font(fonts.Families[0], 16.0F);
            }
        }
    }
    

フォントを使用

  1. メインフォームにラベルを追加し、ロードイベントを追加して、Form1.csにフォントを設定します。

    private void Form1_Load(object sender, EventArgs e)
    {
        label1.Font = myFont;
    }
    
46
knighter
// specify embedded resource name
string resource = "embedded_font.PAGAP___.TTF";

// receive resource stream
Stream fontStream = Assembly.GetExecutingAssembly().GetManifestResourceStream(resource);

// 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);

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

// close the resource stream
fontStream.Close();

// free up the unsafe memory
Marshal.FreeCoTaskMem(data);
6
David Maron

ランダムにダウンロードされたフォント をリソースにドラッグアンドドロップすると、これが機能しました。ただし、ファイルを使用します。これもフォントのインストールに使用できると思いますか?

public Form1()
{
    string filename = @"C:\lady.gaga";
    File.WriteAllBytes(filename, Resources.KBREINDEERGAMES);
    PrivateFontCollection pfc = new PrivateFontCollection();
    pfc.AddFontFile(filename);

    Label label = new Label();
    label.AutoSize = true;
    label.Font = new Font(pfc.Families[0], 16);
    label.Text = "hello world";
    Controls.Add(label);
}
3
Bitterblue

アプリのリソース部分だけを使用することはできませんか?

はい。ただし、.NETリソースではなくネイティブリソースである必要があります(つまり、rc.exe、ネイティブリソースコンパイラを使用)。

1
Richard