ここでは、システムにインストールされていないフォントをファイルやリソースから読み込んで、Fontオブジェクトを作成する方法を紹介します。
なおシステムにインストールされているフォントを取得する方法については、「インストールされているフォントを取得する」をご覧ください。
システムにインストールされていないフォントを使用するには、PrivateFontCollectionクラス(System.Drawing.Text名前空間)を使用します。
.ttfファイルのようなフォントファイルからフォントをPrivateFontCollectionに追加するには、AddFontFileメソッドを使います。
MSDNによると、AddFontFileメソッドはTrueTypeをサポートしていますが、OpenTypeフォントは制限付きでしかサポートしていません。また、Windows 2000より古いOSでは使用できません。
以下に、和田研細丸ゴシックの「wlmaru2004p4u.ttf」というフォントファイルを使用する例を示します。
'PrivateFontCollectionオブジェクトを作成する Dim pfc As New System.Drawing.Text.PrivateFontCollection() 'PrivateFontCollectionにフォントを追加する pfc.AddFontFile("C:\test\wlmaru2004p4u.ttf") '同様にして、複数のフォントを追加できる 'pfc.AddFontFile("C:\test\wlmaru20044u.ttf") 'PrivateFontCollectionに追加されているフォントの名前を列挙する For Each ff As System.Drawing.FontFamily In pfc.Families Console.WriteLine(ff.Name) Next 'PrivateFontCollectionの先頭のフォントのFontオブジェクトを作成する Dim f As New System.Drawing.Font(pfc.Families(0), 12) 'Labelコントロールのフォントに設定する Label1.Font = f '後始末 pfc.Dispose()
//PrivateFontCollectionオブジェクトを作成する System.Drawing.Text.PrivateFontCollection pfc = new System.Drawing.Text.PrivateFontCollection(); //PrivateFontCollectionにフォントを追加する pfc.AddFontFile(@"C:\test\wlmaru2004p4u.ttf"); //同様にして、複数のフォントを追加できる //pfc.AddFontFile(@"C:\test\wlmaru20044u.ttf"); //PrivateFontCollectionに追加されているフォントの名前を列挙する foreach (System.Drawing.FontFamily ff in pfc.Families) { Console.WriteLine(ff.Name); } //PrivateFontCollectionの先頭のフォントのFontオブジェクトを作成する System.Drawing.Font f = new System.Drawing.Font(pfc.Families[0], 12); //Labelコントロールのフォントに設定する Label1.Font = f; //後始末 pfc.Dispose();
フォントをリソースに埋め込んだ時は、埋め込んだフォントをバイト配列で読み込み、そのメモリのポインターをAddMemoryFontメソッドに渡します。
MSDNによると、メモリフォントを使用する場合はGDI+で描画する必要があります。
リソースにデータを埋め込む方法については、「Visual Studioでリソースを管理する」や「画像やテキストファイルを実行ファイルに埋め込む」をご覧ください。
以下に、和田研細丸ゴシック(wlmaru2004p4u.ttf)がリソースに埋め込まれている時、これを使用する例を示します。
この例では、リソースは「Visual Studioでリソースを管理する」の方法で埋め込まれているものとします。「画像やテキストファイルを実行ファイルに埋め込む」の方法でリソースを埋め込んだ時は、コメントの「または、次のようにしてリソースを読み込む」以下を参考にして下さい。
また、C#では、アンセーフコードが許可されている(プロジェクトのプロパティで、「ビルド」タブの「アンセーフコードの許可」が有効になっている)ものとします。許可しない場合は、コメントの「または、次のようにしてポインターを取得する」以下を参考にして下さい。
'PrivateFontCollectionオブジェクトを作成する Dim pfc As New System.Drawing.Text.PrivateFontCollection() 'リソース(wlmaru2004p4u)をバイト配列に読み込む Dim fontBuf As Byte() = My.Resources.wlmaru2004p4u 'または、次のようにしてリソースを読み込む 'Dim asm As System.Reflection.Assembly = _ ' System.Reflection.Assembly.GetExecutingAssembly() 'Dim strm As System.IO.Stream = _ ' asm.GetManifestResourceStream("Project1.wlmaru2004p4u.ttf") 'Dim fontBuf As Byte() = New Byte(strm.Length - 1) {} 'strm.Read(fontBuf, 0, fontBuf.Length) 'strm.Close() 'バイト配列のポインターを取得する Dim fontBufPtr As IntPtr = System.Runtime.InteropServices. _ Marshal.AllocCoTaskMem(fontBuf.Length) System.Runtime.InteropServices. _ Marshal.Copy(fontBuf, 0, fontBufPtr, fontBuf.Length) 'PrivateFontCollectionにフォントを追加する pfc.AddMemoryFont(fontBufPtr, fontBuf.Length) System.Runtime.InteropServices. _ Marshal.FreeCoTaskMem(fontBufPtr) 'PrivateFontCollectionの先頭のフォントのFontオブジェクトを作成する Dim f As New System.Drawing.Font(pfc.Families(0), 12) 'Labelコントロールのフォントに設定する 'GDI+で描画されるようにする Label1.UseCompatibleTextRendering = True Label1.Font = f '後始末 pfc.Dispose()
//PrivateFontCollectionオブジェクトを作成する System.Drawing.Text.PrivateFontCollection pfc = new System.Drawing.Text.PrivateFontCollection(); //リソース(wlmaru2004p4u)をバイト配列に読み込む byte[] fontBuf = Properties.Resources.wlmaru2004p4u; //または、次のようにしてリソースを読み込む //System.Reflection.Assembly asm = // System.Reflection.Assembly.GetExecutingAssembly(); //System.IO.Stream strm = // asm.GetManifestResourceStream("Project1.wlmaru2004p4u.ttf"); //byte[] fontBuf = new byte[strm.Length]; //strm.Read(fontBuf, 0, fontBuf.Length); //strm.Close(); //バイト配列のポインターを取得する //アンセーフコードが許可されている必要がある unsafe { fixed (byte* pFontBuf = fontBuf) { //PrivateFontCollectionにフォントを追加する pfc.AddMemoryFont((IntPtr)pFontBuf, fontBuf.Length); } } //または、次のようにしてポインターを取得する //IntPtr fontBufPtr = System.Runtime.InteropServices. // Marshal.AllocCoTaskMem(fontBuf.Length); //System.Runtime.InteropServices. // Marshal.Copy(fontBuf, 0, fontBufPtr, fontBuf.Length); ////PrivateFontCollectionにフォントを追加する //pfc.AddMemoryFont(fontBufPtr, fontBuf.Length); //System.Runtime.InteropServices. // Marshal.FreeCoTaskMem(fontBufPtr); //PrivateFontCollectionの先頭のフォントのFontオブジェクトを作成する System.Drawing.Font f = new System.Drawing.Font(pfc.Families[0], 12); //Labelコントロールのフォントに設定する //GDI+で描画されるようにする Label1.UseCompatibleTextRendering = true; Label1.Font = f; //後始末 pfc.Dispose();
先に説明した通り、AddMemoryFontメソッドを使用する場合は、GDI+で描画する必要があります。そのため、TextBoxなどのコントロールでは、通常この方法が使えません。しかし、「Using an embedded font on a textbox」によると、AddMemoryFontメソッドを呼び出す前にAddFontMemResourceEx functionを呼び出しておけば、うまく行くということです。
つまり、例えば以下のようにします。
<System.Runtime.InteropServices.DllImport("gdi32.dll", _ ExactSpelling:=True)> Private Shared Function AddFontMemResourceEx(pbFont As Byte(), _ cbFont As Integer, pdv As IntPtr, ByRef pcFonts As UInteger _ ) As IntPtr End Function Private Sub Button1_Click(sender As Object, e As EventArgs _ ) Handles Button1.Click Dim pfc As New System.Drawing.Text.PrivateFontCollection() Dim fontBuf As Byte() = My.Resources.wlcmaru2004p4u Dim fontBufPtr As IntPtr = System.Runtime.InteropServices. _ Marshal.AllocCoTaskMem(fontBuf.Length) System.Runtime.InteropServices. _ Marshal.Copy(fontBuf, 0, fontBufPtr, fontBuf.Length) 'AddFontMemResourceExを呼び出す Dim cFonts As UInteger AddFontMemResourceEx(fontBuf, fontBuf.Length, IntPtr.Zero, cFonts) pfc.AddMemoryFont(fontBufPtr, fontBuf.Length) System.Runtime.InteropServices. _ Marshal.FreeCoTaskMem(fontBufPtr) Dim f As New System.Drawing.Font(pfc.Families(0), 12) 'TextBoxコントロールのフォントに設定する TextBox1.Font = f pfc.Dispose() End Sub
[System.Runtime.InteropServices.DllImport("gdi32.dll", ExactSpelling = true)] private static extern IntPtr AddFontMemResourceEx( byte[] pbFont, int cbFont, IntPtr pdv, out uint pcFonts); private void Button1_Click(object sender, EventArgs e) { System.Drawing.Text.PrivateFontCollection pfc = new System.Drawing.Text.PrivateFontCollection(); byte[] fontBuf = Properties.Resources.wlcmaru2004p4u; IntPtr fontBufPtr = System.Runtime.InteropServices. Marshal.AllocCoTaskMem(fontBuf.Length); System.Runtime.InteropServices. Marshal.Copy(fontBuf, 0, fontBufPtr, fontBuf.Length); //AddFontMemResourceExを呼び出す uint cFonts; AddFontMemResourceEx(fontBuf, fontBuf.Length, IntPtr.Zero, out cFonts); pfc.AddMemoryFont(fontBufPtr, fontBuf.Length); System.Runtime.InteropServices. Marshal.FreeCoTaskMem(fontBufPtr); System.Drawing.Font f = new System.Drawing.Font(pfc.Families[0], 12); //TextBoxコントロールのフォントに設定する TextBox1.Font = f; pfc.Dispose(); }