質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.31%
C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

Visual Studio

Microsoft Visual StudioはMicrosoftによる統合開発環境(IDE)です。多種多様なプログラミング言語に対応しています。

Windows Forms

Windows Forms(WinForms)はMicrosoft .NET フレームワークに含まれる視覚的なアプリケーションのプログラミングインターフェイス(API)です。WinFormsは管理されているコードの既存のWindowsのAPIをラップすることで元のMicrosoft Windowsのインターフェイスのエレメントにアクセスすることができます。

Q&A

解決済

2回答

1049閲覧

インストール先にないフォントをアプリ内に設定したい

kjkjmk

総合スコア7

C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

Visual Studio

Microsoft Visual StudioはMicrosoftによる統合開発環境(IDE)です。多種多様なプログラミング言語に対応しています。

Windows Forms

Windows Forms(WinForms)はMicrosoft .NET フレームワークに含まれる視覚的なアプリケーションのプログラミングインターフェイス(API)です。WinFormsは管理されているコードの既存のWindowsのAPIをラップすることで元のMicrosoft Windowsのインターフェイスのエレメントにアクセスすることができます。

1グッド

0クリップ

投稿2023/12/10 00:24

実現したいこと

言語:C#
環境:visualstudio 
Windowsフォームで作成したアプリでインストール先に存在しないフォントを表示させたい。

前提

アプリ内のテキストボックスやラベルのフォントを標準フォント以外のフォントに設定していましたが
アプリ完成後、インストーラーを作り別PCにインストールしてみたところ、インストール先のPCには標準のフォントしかないため
アプリ内のフォントがすべて標準のものにさし変わっていました。

こちらを解決する方法をご教示いただきたいです。
こちらは以前質問していましたが、実装できずに、断念していました。
しかし、やはり実装したいと思い、再度質問させていただいています。

以前回答でいただいた、下記URLを参考にして、いろいろ試しましたが
以下のことが起こっています。

▼参考サイト
https://dobon.net/vb/dotnet/graphics/privatefontcollection.html

試したこと

参考サイトをもとに以下を実施
1.アンセーフコードの許可にチェックを入れる
2.リソースにフォントを追加
※追加方法はこちらを参照
https://dobon.net/vb/dotnet/programing/vsresource.html
3.参考サイトの下記コードを追加

起こったこと

表示自体は成功しているが、立ち上げてすぐに以下の例外が発生して、強制終了してしまう。

発生している問題・エラーメッセージ

エラーメッセージ System.AccessViolationException HResult=0x80004003 Message=保護されているメモリに読み取りまたは書き込み操作を行おうとしました。他のメモリが壊れていることが考えられます。 Source=<例外のソースを評価できません> スタック トレース: <例外のスタック トレースを評価できません>

該当のソースコード

//PrivateFontCollectionオブジェクトを作成する System.Drawing.Text.PrivateFontCollection pfc = new System.Drawing.Text.PrivateFontCollection(); //リソース(wlmaru2004p4u)をバイト配列に読み込む byte[] fontBuf = Properties.Resources.CP_Font; //バイト配列のポインターを取得する //アンセーフコードが許可されている必要がある unsafe { fixed (byte* pFontBuf = fontBuf) { //PrivateFontCollectionにフォントを追加する pfc.AddMemoryFont((IntPtr)pFontBuf, fontBuf.Length); } } foreach (Label label in this.Controls.OfType<Label>()) { label.UseCompatibleTextRendering = true; label.Font = new Font(pfc.Families[0], label.Font.Size); }

    pfc.Dispose();

補足情報(FW/ツールのバージョンなど)

デバッグモードで処理を見る限り、表示を行う処理段階ではエラーは発生しておらず、
以下の場所で例外が発生していました。

static class Program { /// <summary> /// アプリケーションのメイン エントリ ポイントです。 /// </summary> [STAThread] static void Main() { Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault(false); Application.Run(new Form1());//ここで例外が発生している。 } }

フォントは2種類、ttfとotfそれぞれで試しました。
・チェックポイントフォント
・ふぉんとうは怖い明朝体

また、参考サイト内のリソース埋め込みの方法以外にもフォントファイルを読み込む方法でも同じ個所で同じエラーが発生します。
リソース埋め込みの方法では、参考サイト記載の2パターンとも試しています。(※または、次のようにして~の箇所)

該当のソースコードを削除すれば、例外は発生しないので、該当のソースコードに原因があるとは思います。

どなたかご教授お願いいたします。

TN8001👍を押しています

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

TN8001

2023/12/11 02:45

> 参考サイト内のリソース埋め込みの方法以外にもフォントファイルを読み込む方法でも同じ個所で同じエラーが発生します。 1. 開発PCで通常のexeを実行時に(未インストールの)ローカルのフォントファイルを読めるのか 2. 開発PCで通常のexeを実行時に(未インストールの)リソースに埋め込んだフォントを読めるのか 3. 開発PCでインストーラーでインストールしたアプリを実行時に(未インストールの)リソースに埋め込んだフォントを読めるのか 4. 別PCでインストーラーでインストールしたアプリを実行時に(未インストールの)リソースに埋め込んだフォントを読めるのか のような段階で順にチェックし、どこまでは正常に動くのでしょう? Shunlyさんは1を試しておられるようです。 わたしは手元で1・2まで試しました .NET FW4.8 Windows11(エラーなく表示されました) .NETのバージョンやインストーラを何で作ったか・それぞれのPCのOSのバージョン等も必要でしょう。 --- インストーラーを作ったのであれば、フォントを埋め込む必要ありますか? ライセンス的な問題?(簡単に取り出せてしまうとまずい的な) (フォントのライセンスが許すなら)フォントも一緒にインストールしちゃえば簡単な話になりますね。 [Installing font using C# setup project « JG Vimalan's Blog](https://jgvimalan.wordpress.com/2011/02/22/installing-font-using-c-setup-project/)
kjkjmk

2023/12/12 00:40

バージョン等の記載は失念してました、気を付けます! //インストーラーを作ったのであれば、フォントを埋め込む必要ありますか? インストール時に一緒にフォントをインストールさせる方法も考えましたが、調べるとより複雑?な感じがしたので、断念してました・・・ リンクを張っていただきありがとうございます! なにやらシンプルな方法もありそうですね、どちらも今後できるように参考にしてみます!ありがとうございました!
kjkjmk

2023/12/12 00:44

ただこのリンクのやり方だと、再配布になりそうですね・・・
TN8001

2023/12/12 03:44 編集

> //インストーラーを作ったのであれば、フォントを埋め込む必要ありますか? > インストール時に一緒にフォントをインストールさせる方法も考えましたが、調べるとより複雑?な感じがしたので、断念してました・・・ これは「(未インストールの)ローカルのフォントファイルを読み込む」という話のつもりでした。 exeのフォルダにフォントファイルも一緒に出力するということです。 まあこれも「再配布」にあたるでしょうが^^; > なにやらシンプルな方法もありそうですね、どちらも今後できるように参考にしてみます! フォントのインストールは難しいのかなと思ったのですが、すごい簡単でびっくりしました。 記事はすごい古いですが拡張機能とほぼ同じ構成で記事そのままでできました。 [Microsoft Visual Studio Installer Projects 2022 - Visual Studio Marketplace](https://marketplace.visualstudio.com/items?itemName=VisualStudioClient.MicrosoftVisualStudio2022InstallerProjects) > ただこのリンクのやり方だと、再配布になりそうですね・・・ そうですね。確実に「再配布」でしょう。 ただ禁止としているものはそうない気がします。 「ライセンス文書を含めなければならない」という条件が多いですね(各自確認してください) 埋め込みの場合はそれを省略できる場合がありますが、個人的には著作権を(自分のも含め)明示したいですし、インストーラならファイルの1つや2つ増えても気にならないので(わたしなら)含めちゃいますかねぇ。 だったら「再配布でもいいんじゃない?」ということになります。 なんにせよ解決されたようで何よりです^^
kjkjmk

2023/12/12 18:50 編集

>「(未インストールの)ローカルのフォントファイルを読み込む」 そんなこともできるんですね、勉強になります。 >「ライセンス文書を含めなければならない」 使用時にはlicense元の名前とリンク張ってください的なことでしょうか? それでしたら、どちらにせよ、記載はするつもりでした! 自身の周りにプログラムとかこういったものを制作している方がいないので 自分だったらこういう風にするという情報はとてもありがたいですし、参考になります。本当にありがとうございます!
TN8001

2023/12/12 21:56

>>「(未インストールの)ローカルのフォントファイルを読み込む」 > そんなこともできるんですね、勉強になります。 え?↓のような話ってだけですが。。。(ファイルパスは当然変わります) pfc.AddFontFile(@"C:\test\wlmaru2004p4u.ttf"); >>「ライセンス文書を含めなければならない」 > 使用時にはlicense元の名前とリンク張ってください的なことでしょうか? はい。多いは言い過ぎでしたね^^; Apacheは「ライセンス文書を含めなければならない」ようですが、OFLなんかはリンクでいいようです。 [フォントのライセンスについて | 自家製フォント工房](http://jikasei.me/info/license.html) わたしなんかは法律的なことも疎いですしあまり考えたくもないので、安全側(文書があったら一応含めときましょ)に振りがちですね。
kjkjmk

2023/12/14 19:28

あ、なるほど、勘違いしてました! >わたしなんかは法律的なことも疎いですしあまり考えたくもないので、安全側(文書があったら一応含めときましょ)に振りがちですね 確かにそうですよね。なんでもやっておいて損はないですしね! ありがとうございます!
guest

回答2

0

PrivateFontCollection の Dispose をやめてみてください。
どの時点か忘れてしまいましたが、PrivateFontCollection を Dispose すると要素である Font も Dispose されるよう仕様変更されたと思います。

投稿2023/12/11 05:06

KOZ6.0

総合スコア2721

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

kjkjmk

2023/12/12 00:35

ありがとうございます。 まさしく、Disposeが原因でした。 メンバー変数で維持することにより、エラーが発生せず、正常にできました。 ベストアンサーに関しては、他に早い方がいらしたのでそちらにさせていただきました、すいません。ありがとうございました!
guest

0

ベストアンサー

以下で試してみましたが特に問題なかったです。(.NET Core8 / .NET Framework4.8、メモリから読み込んでも問題無し)

ネイティブデバッグを有効にしてスタックトレースが取れるなら詳細がわかるかもしれません。

C#

1public partial class Form1 : Form 2{ 3 public Form1() 4 { 5 InitializeComponent(); 6 LoadFont(); 7 } 8 9 private void LoadFont() 10 { 11 var path = @".\07ReallyScaryMinchotai.ttf"; 12 13 using (var pfc = new PrivateFontCollection()) 14 { 15 pfc.AddFontFile(path); 16 17 foreach (var label in Controls.OfType<Label>()) 18 { 19 label.UseCompatibleTextRendering = true; 20 label.Font = new Font(pfc.Families[0], label.Font.Size); 21 } 22 } 23 } 24}

投稿2023/12/10 06:44

Shunly

総合スコア152

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

kjkjmk

2023/12/10 10:41

//ネイティブデバッグを有効にしてスタックトレース すいません、いろいろ調べて実行してみようとしましたが、これがいまいちよくわかりませんでした。 現状、他にはこのようなエラーが出ています。 型 'System.AccessViolationException' のハンドルされていない例外が System.Drawing.dll で発生しました 保護されているメモリに読み取りまたは書き込み操作を行おうとしました。他のメモリが壊れていることが考えられます。 もう少し他の方法を検索してみます。
Shunly

2023/12/10 14:49

メニューの"デバッグ" > ~のデバッグプロパティ > ネイティブコードのデバッグを有効にする、をチェックしておいたら、.NETがエラーを捕まえるよりも早い、問題の発生した位置で止まるはずなので、そこからスタックを追えるかも、と思ったのですが。ネイティブのデバッグに慣れてないと難しいかもしれません、、、 手元で問題が発生しないのでお試しになりますが、サンプルコードの通りに作成されているなら、今はLabelにフォントを設定したらすぐにPrivateFontCollectionをDisposeしてますよね?これをPFCをメンバー変数にして、Formを表示している間ずっと保持して置いたらどうでしょう?(FormのDispose時に一緒に破棄する) フォントはPFCが保持するはずなので、PFCの解放時にフォントのメモリも解放されるため、それより後の描画時にAccess Violationになるのかな、と思ました。(最初そう思って手元で試したらエラーにならなかったのですが、、、)
kjkjmk

2023/12/11 23:32

//フォントはPFCが保持するはずなので、PFCの解放時にフォントのメモリも解放されるため、それより後の描画時にAccess Violationになるのかな、と思ました まさにこれでした。ありがとうございます。 最初のほうにDisposeが原因かと思い、Disposeせずに実行したのですが、その時はなぜかメンバー変数にするのを失念していました・・・ メンバー変数にしたところ、維持したまま実行できましたし、インストール後も指定したフォントが使用できました!本当にありがとうございます!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.31%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問