フォント周りの覚書

2024年2月24日更新
公式の質問掲示板で目に留まった投稿が有りました。
プログラムでシステム標準外のフォントを使用しているので、
それを同梱してインストール無しで使わせたいというものです。
具体的にどのように使うのかは書かれていないので分かりません。

以前、システムの起動に10分以上掛かっていた頃が有り、
徹底的にメンテナンスを行った事を思い出しました。
その時の原因はフォントの詰め込み過ぎでした。
搭載メモリを遥かに超えていたので大規模なスワップが起き、
信じられない程の時間が掛かっていたのでした。

システムが1803から1809へ移行する辺りから気になり出して、
実際にメンテナンスをしたのは3年ほど前の事です。
今では22H2なので現在の状況から確認してみました。

質問等は上部ボタンからお気軽に書き込んで下さい。
[ 01 現状の調査 ]
先ず、フォントをダブルクリックしてプレビュー画面を開くだけで、
インストールせずにフォントが使えてしまう超便利な裏技ですが、
何が問題だったのか封印されて使えなくなっていました。

次にショートカットをインストールする技を試しました。
フォントファイルのアイコンを選択して右クリックしてみると、
開いたコンテキストメニューに「すべてのユーザーに対してインストール」や、
「すべてのユーザーに対してショートカットをインストール」が有りません。
それどころか只の「インストール」さえ見当たりません。
これも対策されたのかと思いましたがOTFフォントの場合はできました。
TTFフォントの場合はアイコンが白紙で表示されているので、
そもそもフォントとして認識されていないようです。
[ 02 実現方法の検討 ]
現在の状況が大体分かったところで具体的な方法を検討します。
質問者さんが遣りたい事の詳細は分かりませんが、
予め決まった文字列で良いのか実行時に変化するのかで対応が異なります。
予め決まっているなら画像にしてしまう方法が有ります。
実行時にそのフォントを必要としないので私も良く使います。

実行時に内容が決まる場合にはこの方法は使えません。
PDF文書などではフォントの埋め込みが可能です。
しかし、それはドキュメントでの話です。
埋め込まれたドキュメントを表示する為のプログラムが、
先に起動しているので何らかの処理が可能です。

プログラム自体にその処理が必要な時は、
そのプログラムの起動処理中か起動前に何らかの処理が必要になります。
[ 03 現実的な方法に絞って検討 ]
フォントをインストールしないで使いたいという部分は、
ユーザの手を煩わせたくないという事のようなので、
事前に仮インストールをして事後に削除するという操作を、
自動的に行う事でも良さそうです。
現実的な方法としてそれを検証してみます。

一時的なインストールなのでショートカットをインストールしてみます。
それにはコントロールパネルのフォント設定の変更が必要です。
「ショートカットを使用したフォントのインストールを許可する」を確認し、
チェックされていなければチェックを入れます。
取り合えずこの操作をプログラムから行ってみました。
人が行う操作をプログラムに遣らせただけの実験的なリモコンです。

ShellApplicationというCOM型(「Shell.Application」)を作る
 設定を切り替える
 設定を切り替える時の手順
  「[ウィンドウズフォルダ]Fonts」を開く
  2秒待つ
  「+{Tab 7}」を入力する
  1秒待つ
  「{Enter}」を入力する
  1秒待つ
  「{Tab 2}」を入力する
  1秒待つ
  もし選択プロセスのタイトルが「フォント設定」なら
   「%A」を入力する
   「{Tab 8}」を入力する
   1秒待つ
   「{Enter}」を入力する
   「%{F4}」を入力する
  そうでないなら
   「%{F4}」を入力する
  もし終わり
  パス名は、「[ウィンドウズフォルダ]Fonts」
  ウィンドウを閉じる
 終わり
 ウィンドウを閉じる時の手順
  ShellApplicationからインスタンスを作ってShellAppとする
  コレクションは、ShellApp:Windows()
  [コレクション]のすべてのアイテムについてそれぞれ繰り返す
   補正アドレスは、[アイテム]のLocationURLから「%20」を「 」へ置換したもの
   もし(補正アドレスが「file:///[パス名]」)なら
    [アイテム]:Quit()
    0.05秒待つ
    繰り返しを抜ける
   そうでないなら
    繰り返しを続ける
   もし終わり
  繰り返し終わり
 終わり


これを走らせる事で当該チェックボックスのチェックをトグルします。
実際には必要な時だけこれを走らせるようにした方が良いのですが、
細かい事は後回しにします。
[ 04 インストールの違いを調査 ]
今回はインストール方法を変えると実際に何がどう変わるのかを調査しました。
先ずは普通にインストールした場合です。
普通にインストールするとそれはユーザ専用としてインストールされます。
(「[プロファイルフォルダ]AppData\Local\Microsoft\Windows\Fonts」)
それに対してすべてのユーザーに対してインストールすると、
Windowsフォルダ直下のフォント専用フォルダにインストールされます。
(「[ウィンドウズフォルダ]Fonts」)
実際には上記のどちらのフォルダにもインストールされました。
ファイル容量も全く同じでバイナリ比較しても同一のファイルでした。

次にショートカットをインストールしてみました。
結果はWindowsフォルダ直下の方だけにショートカットがインストールされ、
ユーザ専用の方には何もインストールされませんでした。
ある意味当然の結果でしたが何か特別な事をしているような気もしていました。
これを踏まえて次回はプログラムからインストールしてみます。
[ 05 プログラムから仮インストール ]
ショートカットをインストールする事が可能だと分かりましたが、
直接にフォントフォルダ内にショートカットを作成する事はできません。
また、インストールされたショートカットの移動もできません。
本当はこれができるならこの件はあっさりと解決なのですが、
システムがガッチリと管理しているのでプログラムからもできません。

そこで今回も動作確認用のリモコンソフトを作成します。
プログラムからフォントをショートカットとしてインストールするには、
それを選択状態にしてからコンテキストメニューを表示させます。
そのファイルが有効なフォントなら表示されたメニュー項目の中に、
「すべてのユーザーに対してショートカットをインストール」が有る筈です。
それをプログラムから実行させれば目的を果たせます。

此処で問題なのはそれが有効なフォントで無かった場合の処理です。
何らかの方法で判定してエラー処理をする必要があります。
…なのですが今回も細かい事は後回しにしてテストを優先させます。
フォントファイルはプログラムと同じ階層に置かれている仮定しています。

「explorer.exe /select, [プログラムの位置]フォント名.otf」をコマンド実行する
 2秒待つ
 「+{F10}」を入力する
 1秒待つ
 「S」を入力する
 「{Enter}」を入力する


これだけです。
此処では一行目が重要です。
これが無いと正しくコンテキストメニューが表示されません。
今回はotfフォントを指定していますがttcフォントでも可能です。
次回はエラー処理を入れてみます。
[ 06 どの様にエラーを検知するか ]
真剣にエラー処理を追加しだすと大変な事になるので、
フォントファイルが存在しなかった場合とかの基本的なエラーは除外して、
有効なフォントで無かった場合のエラー処理です。
リモコンソフトを走らせてみると分かりますが、
有効なフォントで無かった場合にはその場にショートカットが作成されます。
これを利用してエラー処理をする事にします。

対象フォント名は、「フォント名」
 拡張子は、対象フォント名の拡張子だけ
 もし(拡張子が「ttf」)なら
  「有効なフォント形式ではありません」を表示する
  終了する
 もし終わり

 対象フォルダというフォルダ情報(「[プログラムの位置]」)を作る
 処理前ファイル一覧は、対象フォルダのファイル一覧
 処理前ファイル数は、処理前ファイル一覧の個数

 「explorer.exe /select, [プログラムの位置][対象フォント名]」をコマンド実行する
 2秒待つ
 「+{F10}」を入力する
 1秒待つ
 「S」を入力する
 「{Enter}」を入力する

 処理後ファイル一覧は、対象フォルダのファイル一覧
 処理後ファイル数は、処理後ファイル一覧の個数

 もし(処理前ファイル数=処理後ファイル数)なら
  「仮インストールしました」を表示する
 そうでないなら
  「[プログラムの位置][対象フォント名].lnk」を削除する
  「インストールできませんでした」を表示する
 もし終わり


冒頭のフォント名のところに実際のフォントファイル名を書きます。
フォントファイルはプログラムと同じ階層に配置します。
フォント設定のオプションはショートカットを許可するに切り替え済とします。
[ 07 オプション切替の自動化 ]
一応、前回で指定のフォントをショートカットとしてインストールできました。
しかし、フォント設定のオプション設定が変更されていないとエラーになります。
今回はそれも含めたエラー処理を追加してみました。

対象フォント名は、「フォント名」
 拡張子は、対象フォント名の拡張子だけ
 もし(拡張子が「ttc」でない)かつ(拡張子が「otf」でない)なら
  「有効なフォント形式ではありません」を表示する
  終了する
 もし終わり

 対象フォルダというフォルダ情報(「[プログラムの位置]」)を作る
 処理前ファイル一覧は、対象フォルダのファイル一覧
 処理前ファイル数は、処理前ファイル一覧の個数

 フォントをショートカットとしてインストールする

 処理後ファイル一覧は、対象フォルダのファイル一覧
 処理後ファイル数は、処理後ファイル一覧の個数

 もし(処理前ファイル数=処理後ファイル数)なら
  「仮インストールしました」を表示する
 そうでないなら
  「[プログラムの位置][対象フォント名].lnk」を削除する
  2秒待つ
  「%{F4}」を入力する
  「インストールできませんでした[改行]オプションを切り替えて再試行します」を表示する
  オプションを切り替える
  フォントをショートカットとしてインストールする
 もし終わり

 フォントをショートカットとしてインストールする時の手順
  「explorer.exe /select, [プログラムの位置][対象フォント名]」をコマンド実行する
  2秒待つ
  「+{F10}」を入力する
  1秒待つ
  「S」を入力する
  「{Enter}」を入力する
 終わり

 オプションを切り替える時の手順
  「explorer shell:::{93412589-74D4-4E4E-AD0E-E0CB621440FD}」を、
   コマンド実行する
  1秒待つ
  「%A」を入力する
  「{Tab 8}」を入力する
  1秒待つ
  「{Enter}」を入力する
 終わり

[ 08 削除も自動化してみた ]
前回で仮インストールまでできるようになりました。
これで必要なフォントを使えるようになったのですが、
使い終わったらフォントを削除しておく必要が有るのかも知れません。
インストールされたのはショートカットなので、
本体がなくなれば使えなくなるのでそのままでも良いのかも知れません。
只、表示されないようにする等の処理が必要かも知れませんが、
取り合えず今回は普通に削除してみます。

「@Powershell ^&{Control Fonts}」をコマンド実行する
 2秒待つ
 「対象フォント名」を入力する
 2秒待つ
 「+{F10}」を入力する
 1秒待つ
 「D」を入力する
 「{Enter}」を入力する


これだけで削除されました。
[ 09 フォントを簡単インストール ]
前回までに仮インストールと削除ができるようになりました。
これで目的は果たせそうですが質問者さん的には不採用だと思われます。
「スマートでは無いから…」というのが一番の理由の様な気がします。
そこでインストールをよりスマートに遣ってみました。
但し仮インストールではなく本インストールです。

作成したのは「AddFont.exe」でコンソールアプリケーションです。
どの様に使うのかは同梱した「AddFont.bat」をご覧ください。
テストプログラムなのでエラー処理は入れていません。
※ダウンロードは こちら から。

質問者さんはフォントファイルから直接読み込んで使ったり、
リソースに埋め込んで使いたいのだと思われるので、
恐らくこれでも不採用になると思われます。
実際にリソースに埋め込んだフォントをインストールしないで使ったり、
フォントファイルから直接に読み込んで使う事ができるようです。

一応、フォントをリソースに埋め込んだり、
それをフォントファイルに書き戻したりはプロデルで可能でした。
しかし、今の私のスキルではその先どうしたらよいのか分かりません。
次回は別のアプローチで挑んでみようと思います。
[ 10 別のアプローチ ]
前回までは使用時に文字列の内容が決定すると仮定していました。
もしそれが決められた文字列で良いのなら別のアプローチが有ります。
質問者さんのPCには当然ながらそのフォントは存在しています。
そのフォントを使用した文字列をウィンドウの何処かに表示させ、
環境が変わっても同じように表示させる確実な方法の第一歩は、
キャンバス文字にして更にそれを画像化してリソースに含める事です。

もし(「[プログラムの位置]_素材\絵文字.png」が存在しない)なら
  メイン画面:文字を画像化する
 もし終わり

 素材として「_素材\絵文字.png」を利用する
 素材リストから「絵文字.png」を画像として取得して文字画像とする

 メイン画面を表示する
 待機する
 メイン画面とは
  ウィンドウを継承する
  はじめの手順
   初期化する
   ーー貼り付けた部品に対する操作をここに書きます
   キャンバス1の背景画像を文字画像に変える
  終わり
  
  初期化する手順
   ーー自動生成された手順です。ここにプログラムを書き加えても消える場合があります
   初期化開始する
   この実質大きさを{483,208}に変える
   この内容を「メイン画面」に変える
   この文字色を「標準の文字」に変える
   キャンバス1というキャンバスを作る
    その位置と大きさを{44,51,392,101}に変える
    その自動調整を○に変える
    その文字色を「標準の文字」に変える
    その背景色を「透明」に変える
   初期化終了する
  終わり

  文字を画像化する時の手順
   キャンバス1へ「Hello Produire」という文字を描く
    その位置は、{10,10}
    そのフォントを「ParkAvenue BT,42」に変える
    その文字色を緑色に変える
   キャンバス1を更新する
   キャンバス1の図形画像を「[プログラムの位置]_素材\絵文字.png」へ保存する
  終わり
 終わり


プログラムの使用時環境には「ParkAvenue BT」が無いと仮定しています。
[ 11 表示対象を変えてみた ]
前回はキャンバス文字を使ってキャンバスに文字を描き、
それを画像化してリソースに含めてみました。
開発環境で画像化されているので使用環境にフォント無くても表示されます。

尚、前回の例ではキャンバス文字をキャンバスに描いていますが、
最終的にはキャンバスの背景画像として表示しています。
キャンバス自体に画像として表示する事もできます。
15行目の「キャンバス1の背景画像を文字画像に変える」という部分を、
キャンバス1へ画像を描くしてタイトル画像とする
 タイトル画像の画像は、文字画像

のように変更するだけです。

また、下記のように変更してウィンドウ自体にも配置が可能です。
この背景画像を文字画像に変える
 この背景画像配置を中央に変える

更にウィンドウ自体に表示するならキャンバスを省いて、
下記のようにして構いません。
これへタイトルというピクチャーを作る
  その位置を{50,0}に変える
  その画像は、文字画像


理想には程遠いですが現在の私のスキルではこの位でしょうか。
[ 12 若しかしたらできるかも… ]
その後、全ユーザ対象インストールやログインユーザ対象インストール等、
思い付く限りありとあらゆるアプローチを試しています。
その多くは成功していますが動作が安定していなかったり、
目標とは懸離れています。

最後の手段として一時インストールを試したらこれも成功したようです。
これは[5]の仮インストールとは異なりショートカットではなく、
フォントをプライベート フォント コレクションに登録して使う方法です。
…なのでファイルは何処にもインストールされない一時インストールです。

断定的で無いのはアンインストールに成功していないし、
他言語なのでプロデルに移植が必要です。
また、実際にそれをプロデルから使う方法が分かりません。

一時インストールはセッション内でしか有効でないので、
アンインストールは必須では無いのですが、
初期化できないと色々と困った事になりそうです。
取り合えず今回はフォントをリソースに含めて実行時に戻す処迄です。

プログラムの冒頭で下記のようにします。
素材として「プログラムの位置\素材\フォントファイル名」を利用する
 素材リストから「フォントファイル名」をバイナリ配列として取得して"呼名"とする
 呼名を「.\フォントファイル名」へ保存する


意外と簡単にできましたが一つ注意が有ります。
パス名として「[プログラムの位置]」等は使えません。
フルパスを使う必要が有るようです。
基本は絶対パスですが「.\」等の相対パスも使えました。
[ 13 フォントの仮インストール ]
通常、フォントのインストールは2タイプです。
一つ目はログインユーザ専用のインストールです。
普通にフォントをインストールする場合は全てこれです。

二つ目はすべてのユーザーに対してインストールです。
フォントファイルを右クリックした時に表示される、
「すべてのユーザーに対してインストール(&A)」がこれにあたります。
実行するには管理者権限が必要です。

昔はフォントをインストールするには管理者権限が必要でした。
当時は全てのユーザに対してインストールされました。
その後、管理者でなくてもインストール可能にして欲しいという要望が有り、
現在のような複雑な状況になったようです。

特殊なインストール方法としてショートカットのインストールも有ります。
これもフォントファイルを右クリックした時に表示されます。
「すべてのユーザーに対してショートカットとしてインストール(&S)」です。
こちらも実行するには管理者権限が必要です。

今回紹介するのは第四のインストール方法と言える一時インストールです。
前3方式とは異なりフォントファイルをインストールしません。
システムが管理しているプライベート フォント コレクションに直接追加します。
従ってそのフォントが使えるのはそのセッションのみです。

昔はちらほら見掛けたのですが今ではレガシーな手法のようです。
今回は取り合えず動作確認用のプログラムを作成しました。
C#(Powershell)で作ったのでプロデルへの移植が必要です。

※こちらに置いておきます。
[ 14 使う為の手続きが必要? ]
フォントの仮インストールは上手く行ったのか確認すると、
ワードパッドやテキストエディタ等で問題無く使えました。
プロデル製のプログラムからもフォント選択ダイアログに表示されます。
しかし、それを選択すると「使用可能なフォントでは無い」とエラーになります。
他のソフトでは使えているので仮インストール自体は問題無いようです。
何か使う為の手続きが必要なのでしょうか。
情報が少なすぎるので調査が必要です。
[ 15 仮インストールしたフォントのアンインストール ]
[13]でフォントを仮インストールするプログラムを作り紹介しました。
今回はそれをアンインストールするプログラムを作りました。
これで開発環境でフォントをリソースに含めて使用環境でそれを復元し、
仮インストールする処迄は確認できました。

後はプロデルでプライベート フォント コレクションに登録されたフォントを、
何らかの方法で取得して使用する事ができたら目的達成です。
もう少しのような気もしますが手強そうです。
今回もC#(Powershell)で作ったのでプロデルへの移植が必要です。

※こちらに置いておきます。
[ 16 上手く行ったようです ]
フォント関係の情報を収集して集中的に検証しているので、
俄かに詳しくなった反面、消化不良を起こしています。
仮インストールには幾つかの方法があるようで、
前[15]、[13]で紹介した方法もその一つでした。
只、混乱したまま使っていたので本来の使い方では無かったです。
そこで一旦、ダウンロードを中止して改めてアップロードする事にします。

今回検証したのはフォントファイルを同梱して、
インストールせずにそのフォントを使用するものです。
公式での質問者さんの要望に一番近いと思われます。
今回もC#(Powershell)で作ったのでプロデルへの移植が必要です。


テストプログラムなので使用フォントは決め打ちしています。
下記のテストプログラムをダウンロードすると共に、
「851tegaki_zatsu_normal_0883.ttf」も別途ダウンロードして下さい。
二つのファイルを同じフォルダに配置したらテストプログラムを実行します。
こちら に置いておきます。
[ 17 仮インストールの方法 ]
フォントを仮インストールするにはファイルから読み込むか、
リソースやメモリから取得する方法が有る事が分かりました。
[13]や[15]ではリソースからの読込方式でファイルを指定していました。
本当はリソースやメモリのポインタを渡す必要が有るようです。
敷居が高そうなので追々チャレンジしてみようと思います。

不思議なのは間違った使い方をしたにも関わらず、
ワードパッド等では使えてしまった事です。
この辺りももう少し検証する必要が有りそうです。

また、リソースから読み込む方法にも更に高度な技が有り、
フォントファイルから必要な部分だけを抽出して軽量化を図り、
それを埋め込むサブセット方式も有るようですが、
取り合えずプロデルで使えるようにする事が先決です。
[ 18 現在のアプローチと状況 ]
一応[16]でフォントをインストールする事なく使用できる事を確認しました。
但しC#(Powershell)で書いたのでプロデルへの移植が必要です。
それには「ドットネット型」を使いこなす必要があります。
現在の私の実力では望むべくも無いので全面的な移植は先送りして、
取り合えず主要な部分は外部プログラムに任せて、
プロデル側はそれを受け取って利用する形態にしました。

これで随分と簡単になるかと思えたのですが、
外部プログラムとオブジェクトの受け渡しが必要になりました。
手順としては下記のようになりそうです。
 1. 同梱のフォントをプライベート フォント コレクションに登録する
 2. プライベートフォントコレクションから当該フォントを取得する
 3. 当該フォントをプロデル側へ渡す
 4. プロデル側でその当該フォントを使用する

状況としては1〜3まではできたようです。
プロデル側で下記の様に確認できました。
 FontFamily     : [FontFamily: Name=851手書き雑フォント]
 Bold        : False
 GdiCharSet     : 1
 GdiVerticalFont   : False
 Italic        : False
 Name        : 851手書き雑フォント
 OriginalFontName  : 
 Strikeout      : False
 Underline      : False
 Style        : Regular
 Size        : 20
 SizeInPoints    : 20
 Unit        : Point
 Height       : 27
 IsSystemFont    : False
 SystemFontName  : 

只、これを適用できていません。
[ 19 遂にプロデルでも成功 ]
前回の[18]では後少しの所迄来ていながらフォントの反映ができませんでした。
使い方が原因の様な気がしていましたがその通りでした。
処理される順番とかリードオンリーの属性などを考慮したら通りました。


後は汎用性を持たせたなら完成です。
[ 20 同一セッション内での処理にも成功 ]
プライベートフォントコレクションを使う時にはセッション内という縛りが在り、
最後までそれがクリアできませんでしたが…。
公式でプロデル開発者のゆうとさんからコメントを頂きました。
それを参考に修正を加えたら通るようになりました。

FontPath=「851tegaki_zatsu_normal_0883.ttf」
 「System.Drawing」をネット型として利用する
 PFCという"System.Drawing.Text.PrivateFontCollection"のネット型()を作る
 PFC:AddFontFile(「[FontPath]」)
 MyFontという"System.Drawing.Font"のネット型(PFCのFamilies(1), 28)を作る
 Window1というウィンドウを作る
  Window1の実質大きさを{473,181}に変える
  Window1のタイトルを「Test」にする
 Window1へ書式付きテキスト1という書式付きテキストを作る
  その位置と大きさを{0,0,473,181}に変える
  その内容を「こんな感じでしょうか?」に変える
  そのフォントをMyFontに変える
  そのドッキング方向を「全体」に変える
 Window1を表示する
 ' 放っておいてもそのうち削除されるので必須では無い
 PFC:Dispose()
 待機する


「FontPath」は実際のフォント名に置き換えてください。


こちら に置いておきます。
[ 21 これ迄を整理してみた ]
フォント関係は実に難解です。
この「フォント周りの覚書」を書き始めてから色々と調べ出して、
俄かに詳しくなりましたが誤解していた部分も少なくありません。
フォントを利用するにはインストールしたりアンインストールする他に、
インストールせずにコレクションに追加する方法が有る事が分かりました。

普通にインストールした場合にはフォントファイルが所定のフォルダに配置され、
フォントテーブルにも追加されてそのフォントが使えるようになります。
フォントファイルが残りレジストリにも記録されるので再起動後にも使えます。

一方、インストールせずに直接プライベートなコレクションに追加する場合も、
フォントテーブルやプライベートなコレクションに追加する方法が有ります。
フォントテーブルの方へ追加した場合には他のソフトからも使えますが、
プライベートの方へ追加した場合にはセッション内でしか使えません。

フォントテーブルの方へ追加するメソッドが「AddFontResource」で、
プライベートの方へ追加メソッドが「AddFontFile」のようです。
何方もフォントファイルを指定して追加します。

また、プライベートな追加はメモリ上のフォントバイナリからも行えます。
その時に使用するメソッドが「AddMemoryFont」のようです。
更にはフォントから必要な部分だけを抽出して「Base64」エンコードして、
ファイルのリソースへ埋め込んで使う方法も有るようです。
実際にその様にした事例を見ましたがどの様に抽出したのかは分かりません。
特別な意図が無いなら「AddFontFile」の使用が一番簡単です。
[ 22 リソースに仕込んだフォントを利用する ]
[20]ではフォントファイルから読み込んで利用する方法を紹介しましたが、
今回はリソースに埋め込んだフォントを利用する方法を紹介します。
公式でプロデル開発者のゆうとさんから教示頂いた方式と同じです。
今回も「851手書き雑フォント」を使用しています。

"System.Drawing"をネット型として利用する
素材として「851tegaki_zatsu_normal_0883.ttf」を利用する
素材リストから「851tegaki_zatsu_normal_0883.ttf」をバイナリ配列として取得してResFntとする
"System.Drawing.Text.PrivateFontCollection"のネット型()を作って、PFCとする
ドットネット型(「System.Runtime.InteropServices.Marshal」)を作って、Marshalとする
Marshalから「AllocCoTaskMem」を{ResFntの長さの整数}で呼び出してfontBufPtrとする
Marshalから「Copy」を{ResFnt,0,fontBufPtr,ResFntの長さの整数}で呼び出す
PFC:AddMemoryFont(fontBufPtr, ResFntの長さの整数)
Marshalから「FreeCoTaskMem」を{fontBufPtr}で呼び出す

例外監視
 フォント名は、PFCのFamilies(1)のName
発生した場合
 「対応していないフォントです」を「エラー」として警告アイコンで表示する
 終了する
監視終わり
"System.Drawing.Font"のネット型(PFCのFamilies(1), 32)を作って、MyFontとする

Window1というウィンドウを作る
 Window1の実質大きさを{473,181}に変える
 Window1のタイトルを「Test」にする
Window1へラベル1というラベルを作る
 ラベル1の元実体のUseCompatibleTextRendering=○
 その位置と大きさを{29,43,369,133}に変える
 そのフォントをMyFontに変える
 その内容を「ラベル1」に変える
 その文字色を「標準の文字」に変える
Window1を表示する
PFC:Dispose()
待機する


こちら に置いておきます。
[ 23 基本に立ち返る ]
フォント関係の検証は予想以上に進んだので下記のような事が可能になりました。
 フォントファイルからプライベートフォントコレクションへ登録
 メモリからプライベートフォントコレクションへ登録
 メモリから登録したフォントをプライベートフォントコレクションから解放
 フォントをリソースへ含める
 リソースからフォントを取り出す

プライベートフォントコレクションへの登録はセッション内限定で有効なので、
明示的に開放しなくても自然に解放されるので便利な反面、
複数のプログラム間で共有できないという制約も有ります。

フォントテーブルへの登録ならば他のソフトからも利用が可能になります。
これに関しては登録と解放の動作確認はできていますが、
プロデルからそのフォントを利用できるまでに至っていません。

今回は基本に立ち返ってプロデルで普通のインストールを実現しました。
[5]〜[8]迄のようなリモコン方式ではなく他言語製でも有りません。
但し、大半がCOM型での実装です。

定数は、0x14
 対象フォントは、「フォントパス」
 ShellApplicationというCOM型(「Shell.Application」)を作る
 ShellApplicationからインスタンスを作ってshellAppとする
 対象フォルダ=shellApp:Namespace([定数])
 対象フォルダ:CopyHere([対象フォント])
 終了する


これだけでインストールされます。
アンインストールも可能です。

定数は、0x14
 フォント名は、「フォントの名前」
 ShellApplicationというCOM型(「Shell.Application」)を作る
 ShellApplicationからインスタンスを作ってshellAppとする
 対象フォルダ=shellApp:Namespace([定数])
 (対象フォルダ:Items())のすべてのアイテムについてそれぞれ繰り返す
  もしアイテムのNameが「[フォント名]」で始まるなら
   アイテム:InvokeVerb(「Delete」)
  もし終わり
 繰り返し終わり
 終了する


ここで注意すべきはインストール時はフォントのフルパス名が必要で、
アンインストール時にはフォント名で指定する必要があるところです。
[24 簡単に使いたいならこれかな? ]
「ドットネット型」での実装と言ってもほんの数行なので、
その都度コーディングしてもそれ程苦には成りません。
しかし、「ドットネット型」と聞いただけでも拒絶反応を起こす方は、
その部分を書いたり見ないで済むならそれに越した事はないかも知れません。
そこで「ドットネット型」の「AddFontFile」をプラグインにしてみました。
フォントファイルのパス名と使用ポイント数を引数にして、
プラグインに投げる事でプライベートフォントコレクションに登録して、
そのフォントオブジェクトを返してくれます。


写真はプラグインに同梱した使用サンプルです。
プラグインの使用方法はサンプルのコメントをご覧ください。

こちら に置いておきます。
[25 フォント名一覧を確認する ]
システム標準のフォントだけでも相当数がインストールされています。
この「フォント周りの覚書」では主に一時的な利用方法を検討して来ました。
インストール時に必要なのはフォントファイルのフルパスですが、
利用時にはフォントのファミリ名で指定する必要があります。
然も名前だけではどのようなフォントなのか分からないので、
できる事ならフォント名をそのフォントで表示するのが望ましいです。
フォントビュアの一覧表示のような物が有ったら便利そうです。
…で作ってみました。


ご覧の様にインストールされているフォントをフォント自体で表示するので、
一目瞭然で確認できますしリッチテキストフォーマットで保存も可能です。

こちら に置いておきます。
[26 普通のインスト・アンインストも簡単に… ]
[23]では一般的なインストールとアンインストールに関して、
実際にプロデルでプログラムを書いてみました。
…と言ってもほゞほゞ中身は「COM型」なのですが…。
「ドットネット型」同様に「COM型」も拒絶反応が懸念されるので、
[23]の内容をプラグインにしてみました。


写真はプラグインに同梱した使用サンプルです。
プラグインの使用方法はサンプルのコメントをご覧ください。

こちら に置いておきます。
[27 プラグインを機能強化しました ]
[24]で作成したプラグインを機能強化して更新しました。
今回追加したのはプライベートフォントコレクションの管理機能です。
旧版でも複数フォントをコレクションに追加して使用する事は可能ですが、
登録後にそれを選択的に使用する事はできませんでした。
今回はその機能を追加してより柔軟に対応可能にしました。
これで当初の目的は十分に達成されたものと思われます。


写真はプラグインに同梱した使用サンプルです。
プラグインの使用方法はサンプルのコメントをご覧ください。

こちら に置いておきます。
[28 プラグインをリソース対応させました ]
個人的にはフォントをリソースに埋め込む利用例を思いつきません。
この様な用途には「AddMemoryFont」の出番なのですが、
コード的には「AddFontFile」よりも複雑になります。
旨い具合に手順に纏める等してカプセル化を図らないと煩雑になりがちです。

一応、手順に纏めて引数で対応する事はできましたが、
欲が出て来てプラグイン化を図りたくなりました。
「AddFontFile」とは異なりプラグインとはオブジェクトの受け渡しになります。
プラグインへリソース内のフォントバイナリを渡して登録させ、
フォントオブジェクトとして取得させる必要があります。

案の定、「AddFontFile」の時より大変でしたが何とかできました。
然も既存の「SetPFC.dll」への機能追加という理想的な形です。
「AddMemoryFont」が「AddFontFile」と異なるのは登録時だけなので、
登録さえしてしまえば「AddFontFile」の時と同じように使えます。


写真はプラグインに同梱した使用サンプルです。
プラグインの使用方法はサンプルのコメントをご覧ください。

こちら に置いておきます。