DXライブラリで任意のフォントを使用する

はじめに

ここではDXライブラリでフォントファイル(.ttfなど)をWindowsにインストールせずそのまま利用する方法を紹介する。この方法では既存のDXライブラリにある文字列描画関数をそのまま利用する事ができる。

目次

背景

バージョン3.00eのDXライブラリでは、文字列描画に使用するフォントを変更する手段として2種類の関数が用意されている。1つはChangeFont関数、もう1つはCreateFontToHandle関数だ。
しかし、通常これらの関数で指定できるフォントはWindowsにインストールされたフォントのみである。そのため、DXライブラリユーザ*1側で用意したフォントを使用するためには一工夫必要だ。

準備

以下の環境で正しく動作するのを確認した。

この環境、このバージョンで話を進める。
動作環境においてWindows2000以降の機能を使うので、Windows 95, 98, NTでは動作しないと思われる。これらに対応する方法については後述する。

方法

まずWin32APIのAddFontResourceExでフォントファイルを読み込んでおく。次にChangeFont関数などで読み込ませたフォントのフォント名を指定して、適当な文字列描画関数で文字列を出力する。最後に、プログラム終了前にRemoveFontResourceExでフォントをアンロード*2する。

日向梓さんのあずきフォントを使用するサンプルを以下に示す。あずきフォントのファイル(azuki.ttf)をプロジェクトのフォルダ*3に置いておくこと。
ChangeFontに指定するフォント名を調べるには、フォントファイルを開いて「書体名」を見ればよい。

サンプルコード

#include "DxLib.h"

int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance,
			 LPSTR lpCmdLine, int nCmdShow )
{
	ChangeWindowMode(TRUE);	// ウィンドウモードで表示
	if (DxLib_Init() == -1)	// DXライブラリ初期化処理
		 return -1;	// エラーが起きたら直ちに終了

	// ********** フォントのロード **********
	LPCSTR font_path = "azuki.ttf"; // 読み込むフォントファイルのパス
	if (AddFontResourceEx(font_path, FR_PRIVATE, NULL) > 0) {
	} else {
		// フォント読込エラー処理
		MessageBox(NULL,"フォント読込失敗","",MB_OK);
	}

	// ********** ここから読み込んだフォントを利用できる **********
	SetFontSize(36);	// 見やすさのため、フォントサイズを大きく

	DrawString(10, 200, "この文字はMS ゴシックです。", GetColor(255, 255, 255));

	ChangeFont( "あずきフォント", DX_CHARSET_DEFAULT ) ;
	DrawString( 10 , 240, "この文字はあずきフォントです。", GetColor( 255 , 255 , 255 ) );

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

	// ********** フォントのアンロード **********
	if (RemoveFontResourceEx(font_path, FR_PRIVATE, NULL)) {
	} else {
		MessageBox(NULL, "remove failure", "", MB_OK);
	}

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

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

実行画面

1行目がMS ゴシック、2行目があずきフォントになっている。

フォントファイルの置き場所

読み込むフォントファイルのパスには普通の相対パス絶対パスも指定できる。もちろんフォルダの区切り記号「\」は2個並べないといけない。

	font_path = "azuki.ttf"; // 一種の相対パス
	font_path = "fonts\\azuki.ttf"; // 相対パス
	font_path = "C:\\Documents and Settings\\user\\My Documents\\Visual Studio 2008\\Projects\\AddFontResource on DxLib\\fonts\\azuki.ttf"; // 絶対パス

絶対パスは使わない方がいいだろう。プログラムにフォントを同梱するならば相対パスを使用するべきだ。なぜなら、プログラムのユーザは、そのフォルダをどこに置くかわからないからだ。

欧文フォントを使うには

ChangeFont関数の第2引数のデフォルトはDX_CHARSET_SHFTJISとなっており、フォントの文字セットをシフトJIS文字セットにする。このため、欧文フォントは正しく適用できない。欧文フォントでも使えるようにするには、DX_CHARSET_DEFAULTを渡してデフォルト文字セットを使う様にすればよいようだ。また、日本語フォントを使用する場合であってもDX_CHARSET_DEFAULTを渡して問題無いようだ。

Windows 95, 98, NTに対応させる
上で使用したAddFontResourceExはWindows 2000以降でしか使えない。Windows 95などでは代わりにAddFontResourceを使用すればよい。
ただしAddFontResourceで読み込んだフォントは、このプログラム以外のプログラムからも使用できてしまう。そのため、フォントのライセンスにより注意しなければいけないだろう。

#include "DxLib.h"

int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance,
			 LPSTR lpCmdLine, int nCmdShow )
{
	ChangeWindowMode(TRUE);	// ウィンドウモードで表示
	if (DxLib_Init() == -1)	// DXライブラリ初期化処理
		 return -1;	// エラーが起きたら直ちに終了

	// ********** フォントのロード **********
	LPCSTR font_path = "azuki.ttf"; // 読み込むフォントファイルのパス
	if (AddFontResource(font_path) > 0) {
		PostMessage(HWND_BROADCAST, WM_FONTCHANGE, 0, 0);
	} else {
		// フォント読込エラー処理
		MessageBox(NULL,"フォント読込失敗","",MB_OK);
	}

	// ********** ここから読み込んだフォントを利用できる **********
	SetFontSize(36);	// 見やすさのため、フォントサイズを大きく

	DrawString(10, 200, "この文字はMS ゴシックです。", GetColor(255, 255, 255));

	ChangeFont( "あずきフォント", DX_CHARSET_DEFAULT ) ;
	DrawString( 10 , 240, "この文字はあずきフォントです。", GetColor( 255 , 255 , 255 ) );

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

	// ********** フォントのアンロード **********
	if (RemoveFontResource(font_path)) {
		PostMessage(HWND_BROADCAST, WM_FONTCHANGE, 0, 0);
	} else {
		MessageBox(NULL, "remove failure", "", MB_OK);
	}

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

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

さらにPostMessageを使ってる事に注意したい。ここではウィンドウメッセージをブロードキャストする。このメッセージを適切なウィンドウプロシジャで処理しなければフォントを有効にできない。メッセージ処理のもっとも簡単な方法は、このサンプルのようにDXライブラリにまかせる事だろう。つまりDxLib_Init()とDxLib_End()の間でPostMessageすればよい。

仕組み

DXライブラリはフォントデータの生成のとき、内部でWin32APIのCreateFontを呼んでいる。そこで、CreateFontで任意のフォントファイルからのフォントを使用できるようにしてやればよい。そのためにはAddFontResourceExでフォントファイルを読み込ませる。これでDXライブラリで任意のフォントを使用できるようになるのである。

まとめ

DXライブラリにおいて、任意のフォントを使用するためにはAddFontResourceExでフォントファイルを読み込ませる。これで、DXライブラリの関数ChangeFontやCreateFontToHandleで読み込ませたフォントを指定できるようになる。

DXライブラリ側でこの機能を用意してくれないかな。

参考

*1:DXライブラリを用いたプログラムをを作る人

*2:読み込んだフォントを無効にする

*3:実行プログラムのカレントディレクト