イネマルのプログラミング備忘録

趣味プログラマーのメモ

DXライブラリでフォントファイルからフォント名を取得して使う

f:id:inemaru:20150628061548p:plain 
【追記】

2017/06/11
ttf, otf 限定で、この記事より高速にフォント名を取得する方法について書きました。
inemaru.hatenablog.com















以下の記事は、GDI+を使用したバグ持ちコードを含むので、
GDI+のPrivateFontCollectionについて知りたい場合以外
需要ないです。(なので、読まなくて良いです。)

【目的】
DXライブラリでインストールされていないフォントを簡単に使う
書体名またはデータ名(*.ttf | *.otf | *.ttc)で使えるようにする


【準備】
動作確認した環境
・動作環境
  Windows 8.1 Pro
・開発環境
  Microsoft Visual Studio 2010 Professional
  DXライブラリ VisualC++用(Ver3.14d)

使用させてもらったもの
・DXライブラリ
 http://homepage2.nifty.com/natupaji/DxLib/
・しねきゃぷしょん
 http://chiphead.jp/
・ペン字版 Y.OzFont TTCパック
 http://yozvox.web.fc2.com/82A882B782B782DF8374834883938367.html

作った物
・ PrivateFontManager
PrivateFontManager.zip(PrivateFontManager.zip) ダウンロード | イネマルの備忘倉庫 | uploader.jp
 GDI+のPrivateFontCollectionを使ってフォント名を取得し、
 インストールしていないフォントを使用可能な状態にしてくれるクラス
 (自動解放機能付き)


【方法】
GDI+でフォント名を取得してそれをプログラム中で使用できるように
管理してくれるクラスを作成
デストラクタで自動解放するようにしてあるので
解放処理を、呼ぶ必要はなし

上記の PrivateFontManager をダウンロードして
プロジェクトに追加した状態で動きます

サンプルコード

#include "DxLib.h"
#include "PrivateFontManager.h"

int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance,
    LPSTR lpCmdLine, int nCmdShow )
{
    // 開発環境のチェック
    static_assert( _MSC_VER >= 1600 , "VC2010(VC10.0)以降のコンパイラが必要です" ) ;

    // DXライブラリの準備
    ChangeWindowMode( TRUE ) ;  // ウィンドウモードで表示
    if( DxLib_Init() == -1 )    // DXライブラリ初期化処理
    {
            return -1;      // エラーが起きたら直ちに終了
    }

    // 見やすくする設定
    ChangeFontType( DX_FONTTYPE_ANTIALIASING_EDGE_8X8 ) ;
    SetFontSize( 36 ) ;

    // 白色の値を取得
    int Cr = GetColor( 255 , 255 , 255 ) ;

    // フォント管理クラスでフォントを使えるようにする
    PrivateFontManager lfm;
    auto ttfh = lfm.InstallPrivateFont( _T("cinecaption2.28.ttf") ) ;
    auto ttch = lfm.InstallPrivateFont( _T("YOzRA.TTC") ) ;

    // フォントのインストールに失敗していたら終了する
    if( ttfh == -1 || ttch == -1  )
    {
        OutputDebugString( _T("フォントのインストールに失敗しました") ) ;
        return 0 ;
    }
    
    // 文字列の描画
    DrawString( 10 ,  30 , _T("   ||| フォントファイルを |||") , Cr ) ;
    DrawString( 10 ,  90 , _T("   ||| DXライブラリで使う |||") , Cr ) ;
    DrawString( 10 , 150 , _T("デフォルトフォント") , Cr ) ;
    ChangeFont( lfm.GetFontNameFromList( ttfh ) , DX_CHARSET_DEFAULT ) ;
    DrawFormatString( 10 , 210 , Cr , _T("%s") , lfm.GetFontNameFromList( ttfh ) ) ;
    DrawFormatString( 10 , 270 , Cr , _T("TTCのフォント数 = %d") , lfm.GetFontListCount( ttch ) ) ;
    ChangeFont( lfm.GetFontNameFromList( ttch , 0 ) , DX_CHARSET_DEFAULT ) ;
    DrawFormatString( 10 , 330 , Cr , _T("%s") , lfm.GetFontNameFromList( ttch , 0 ) ) ;
    ChangeFont( lfm.GetFontNameFromList( ttch , 1 ) , DX_CHARSET_DEFAULT ) ;
    DrawFormatString( 10 , 390 , Cr , _T("%s") , lfm.GetFontNameFromList( ttch , 1 ) ) ;

    WaitKey() ;     // キーの入力待ち(『WaitKey』を使用)

    DxLib_End() ;   // DXライブラリ使用の終了処理

    return 0 ;      // ソフトの終了
}

【短所】
ちょっと、重い
でも、初期化時に呼ばれることを想定してるので許容範囲

環境によっては、動かない場合があるらしいです。
もしかしたら、ロケール回りかも?
原因が分かったら修正するつもりです。

【あとがき】
もちろん、ChangeFontとかCreateFontToHandleでも使えます
フォント名を取得するのにGDI+を使ったのは、複数の形式に対応する為ですが
ttf形式に固定するなら、もっと高速に処理を書けるかもしれません

【参考】
・DXライブラリ置き場
http://homepage2.nifty.com/natupaji/DxLib/
・DXライブラリで任意のフォントを使用する
http://d.hatena.ne.jp/willowlet/20091231/1262231680
・DXライブラリのフォントハンドル
http://dixq.net/g/04_03.html
・GDIのプライベートフォントコレクションについて(英語)
https://msdn.microsoft.com/en-us/library/windows/desktop/ms533820(v=vs.85).aspx