ページ 1 / 1
.ttfフォントデータをCreateFontToHandleで使用する
Posted: 2014年8月13日(水) 19:51
by amehirune
こんばんは、アメヒルネです。
今回は息抜きプログラム? 兼、追加したい部分として、使用フォントを追加しようと思い、勉強していました。
その結果、AddFontResource関数またはAddFontResourceEx関数を用いれば使用できるようになる、
というお話をどこかのサイトから聞いたので、実際に描いてみました。
コード:
AddFontResourceEx( "dat/font/DS-DIGI.TTF", FR_PRIVATE, NULL );
font[7] = CreateFontToHandle( "DS-Digital" ,20 , 4 , DX_FONTTYPE_ANTIALIASING_EDGE);
デバッグしてもエラーは検出されなかったため、実行してみたところ、
なぜかデフォルトのフォントでしか描写されていませんでした。
考えられる要因として、
・パスの位置が間違っている
・正常に読み込み操作ができていない
・使用不可能文字を描写しようとしている
・フォント名が間違っている
の4つが考えられていたのですが、いろいろ確認したところ、
・パスの位置が間違っている
・使用不可能文字を描写しようとしている
・フォント名が間違っている
の3つは考えられないことがわかりました。
パスの位置は間違っておらず、
描写しようとしているのは描写可能文字である数字だけ、
フォント名は.ttfファイルを開いて確認しました。
念のため、.ttfファイルを添付しておきます。
関数の使い方が間違っているのでしょうか?
ご指摘、よろしくお願いします。
オフトピック
開発環境とかを言い忘れてました。
VC2008++、DXライブラリを使用しています。
Re: .ttfフォントデータをCreateFontToHandleで使用する
Posted: 2014年8月13日(水) 20:08
by うずら
載せていただいたフォントデータで成功しました。
クラスでまとめてたコードですが、長いしあまり人に見せたくないのでコードの一部を張ります。
コード:
// Resource.rc
# include <windows.h>
# include "resource.h"
USERFONT FONT "DS-DIGI.TTF"
// main.cpp
// リソース読み込み部分
/* ============ */
HRSRC hFontResource = FindResource(NULL, MAKEINTRESOURCE(KYD02_FONT), RT_FONT);
HGLOBAL LoadRes = LoadResource(NULL, hFontResource);
LPVOID lpFontImage = LockResource(LoadRes);
DWORD dwFontImageSize = SizeofResource(NULL, hFontResource);
DWORD dwFontCount = 0;
HANDLE hFontResourceHandle = AddFontMemResourceEx(lpFontImage, dwFontImageSize, NULL, &dwFontCount);
/* ============ */
// Image.cpp (クラスになっていますが、必要なコードだけ掲載)
void Image::SetFont(const char *pFontName, unsigned int pID, int pFontSize, int pFontThick, int pFontEdge, double pSpaceCor)
{
char str[256];
if (pID < 0)
{
AppLogAdd("UserMes: Image::SetFont Illegal Index Number\n");
sprintf_s(str, "フォントの作成に失敗。インデックス番号が不正です。 ID:%d", pID);
MessageBox(NULL, str, ("エラー"), MB_OK | MB_ICONERROR);
return;
}
while ( FontID.size() <= pID ) // FontIDはvectorです。std::vector<int> でフォントを保持しています
{
FontID.push_back(-1);
FontWidth.push_back(-1);
// これは強制固定幅設定のためのものですがバグがあるので・・・(´・ω・`)。std::vector<double>型になっています
}
if (pFontEdge)
{
FontID[pID] = CreateFontToHandle(pFontName, pFontSize, pFontThick, DX_FONTTYPE_ANTIALIASING_EDGE_8X8, DX_CHARSET_DEFAULT, pFontEdge);
}
else
{
FontID[pID] = CreateFontToHandle(pFontName, pFontSize, pFontThick, DX_FONTTYPE_ANTIALIASING_8X8, DX_CHARSET_DEFAULT, pFontEdge);
}
if (FontID[pID] == -1)
{
AppLogAdd("UserMes: Image::SetFont Font Create Error.\n");
MessageBox(NULL, "フォントの作成に失敗。", ("エラー"), MB_OK | MB_ICONERROR);
return;
}
// ここから疑似等幅用のコードになります
FontWidth[pID] = 0;
for (int i = 0x21; i < 0x80; i++)
{
int i2;
char lcStr[] = {i, '\0'};
if (FontWidth[pID] < (i2 = GetDrawStringWidthToHandle(lcStr, strlen(lcStr), FontID[pID])) )
{
FontWidth[pID] = (i2 * pSpaceCor);
}
}
}
不足してる説明とかあったら言ってください。
Re: .ttfフォントデータをCreateFontToHandleで使用する
Posted: 2014年8月13日(水) 20:13
by みけCAT
・フォントのファイルはDXアーカイブではなく、普通のファイルとして存在しますか?
・パスに含まれる/を全て\(ソースコード中では\\)に変えてもダメですか?
・きちんと読み込んだフォントを使用する設定で描画していますか?
・AddFontResourceEx()の戻り値で失敗していないことは確認しましたか?
・CreateFontToHandle()でエラーが返ってきていないことは確認しましたか?
Re: .ttfフォントデータをCreateFontToHandleで使用する
Posted: 2014年8月13日(水) 20:29
by amehirune
うずらさん≫
申し訳ございませんが、(私が勉強不足なもので)まったく意味が理解できませんorz
みけCATさん≫
みけCAT さんが書きました:・フォントのファイルはDXアーカイブではなく、普通のファイルとして存在しますか?
・パスに含まれる/を全て\(ソースコード中では\\)に変えてもダメですか?
・きちんと読み込んだフォントを使用する設定で描画していますか?
・AddFontResourceEx()の戻り値で失敗していないことは確認しましたか?
・CreateFontToHandle()でエラーが返ってきていないことは確認しましたか?
上から順に回答いたします。
まず、ファイルですが、アーカイブで圧縮とかはしていません。よって普通のファイルです。
/を\\に変更…ですが、やってみました。しかし、結果は変わりませんでした。
描写するフォントですが、読み込ませたのがfont[7]に対し、
コード:
for(i=0;i<2;i++){
DrawFormatStringToHandle(400-12*i,23,color[0],font[7],"%d",time%10);
time/=10;
}
となっていたため、間違いはないと思います。
AddFontResourceExの戻り値は、失敗した場合0で返ってくるため、戻り値が0ならばメッセージを出すようにしましたが、
メッセージは表示されなかったため、問題はなかったと思われます。
CreateFontToHandleの失敗時の戻り値は-1であったため、同じような操作をしましたが、メッセージは見られませんでした。
Re: .ttfフォントデータをCreateFontToHandleで使用する
Posted: 2014年8月13日(水) 20:33
by みけCAT
まだttfファイルを詳しく調べていませんが、
CreateFontToHandleを呼ぶときに、文字セットをDX_CHARSET_DEFAULTに指定した方がいいかもしれません。
Re: .ttfフォントデータをCreateFontToHandleで使用する
Posted: 2014年8月13日(水) 20:38
by amehirune
みけCAT さんが書きました:まだttfファイルを詳しく調べていませんが、
CreateFontToHandleを呼ぶときに、文字セットをDX_CHARSET_DEFAULTに指定した方がいいかもしれません。
回答ありがとうございます。
試してみましたが、変化はあまり見られませんでした。
オフトピック
まさかとは思いながらも、名前の半角だったのを全角にして試してみましたが、案の定違いました。
Re: .ttfフォントデータをCreateFontToHandleで使用する
Posted: 2014年8月13日(水) 21:11
by うずら
クラスから完全に切り離して作り直してみました。
コード:
// main.cpp
# include <vector>
# include "DxLib.h"
# include "resource.h"
int FontHandle;
int FontColor;
int EdgeColor;
void SetFont(const char *pFontName, int pFontSize, int pFontThick, int pFontEdge)
// 引数はそのまま<CreateFontToHandle>に渡すだけ
{
if (pFontEdge) // 縁つきのフォントにするかどうか
{
FontHandle = CreateFontToHandle(pFontName, pFontSize, pFontThick, DX_FONTTYPE_ANTIALIASING_EDGE_8X8, DX_CHARSET_DEFAULT, pFontEdge);
}
else
{
FontHandle = CreateFontToHandle(pFontName, pFontSize, pFontThick, DX_FONTTYPE_ANTIALIASING_8X8, DX_CHARSET_DEFAULT);
}
if (FontHandle == -1) // 読み込み失敗検出
{
AppLogAdd("UserMes: Image::SetFont Font Create Error.\n");
MessageBox(NULL, "フォントの作成に失敗。", ("エラー"), MB_OK | MB_ICONERROR);
return;
}
}
void SetFontColor(int pR, int pG, int pB)
{
FontColor = GetColor(pR, pG, pB);
}
void SetEdgeColor(int pR, int pG, int pB)
{
EdgeColor = GetColor(pR, pG, pB);
}
// 描画
void DrawStr(int pX, int pY, const char *pStr, int pID)
{
SetDrawBlendMode(DX_BLENDMODE_NOBLEND, 255);
DrawStringToHandle(pX, pY, pStr, FontColor, FontHandle, EdgeColor);
}
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
HRSRC hFontResource = FindResource(NULL, MAKEINTRESOURCE(USERFONT), RT_FONT);
HGLOBAL LoadRes = LoadResource(NULL, hFontResource);
LPVOID lpFontImage = LockResource(LoadRes);
DWORD dwFontImageSize = SizeofResource(NULL, hFontResource);
DWORD dwFontCount = 0;
HANDLE hFontResourceHandle = AddFontMemResourceEx(lpFontImage, dwFontImageSize, NULL, &dwFontCount);
// ここまでで実行ファイルに埋め込んだリソースを、フォントとして認識できるようにします。
// ウィンドウ登録と同じくらい定型文コードです
ChangeWindowMode(1); // ウィンドウ
DxLib_Init(); // 初期化
SetDrawScreen(DX_SCREEN_BACK); // 裏画面化
// フォント追加関数です。(インストール済み、またはリソースからすでに読み込んでいるものからDXライブラリのハンドルを生成します)
SetFont("DS-Digital", 64, 5, 1); // 元はクラス内で管理してたので、返り値はないです。
SetFontColor(255, 255, 255); // 文字色
SetEdgeColor(100, 100, 100); // 縁色
while(1) // ループ突入。グッドラック!
{
ClearDrawScreen();
DrawStr(0, 0, "]-[|/34<#!", 0); // 記号
DrawStr(0, 90, "0123456789", 0); // 数字
DrawStr(0, 180, "ABCDEFGHIJKLM", 0); // アルファベット
DrawStr(0, 270, "NOPQRSTUVWXYZ", 0);
DrawStr(0, 360, "死ぬがよい", 0); // 描画できない文字の例
ScreenFlip();
// 以下終了判定
if (CheckHitKey(KEY_INPUT_ESCAPE))
{
break;
}
if (ProcessMessage() == -1)
{
break; // エラーが発生したらループを抜ける
}
}
DxLib_End();
}
// ***********************************************************************************************************************************
// resource.h
# define USERFONT 101
// ***********************************************************************************************************************************
// resource.rc
# include <windows.h>
# include "resource.h"
USERFONT FONT "DS-DIGI.TTF"
Re: .ttfフォントデータをCreateFontToHandleで使用する
Posted: 2014年8月13日(水) 23:50
by ookami
DxLibで似たようなプログラムを組んでいるので、添付されていたttfファイルを試したところ、ちゃんと表示されましたー
ロード部分は以下のような感じです。
(独自クラスの部分がありますが... char配列にぶち込むだけのクラスです)
コード:
char *font_path="(パス)";
DWORD font_num=0;
file f; // 独自クラス。f.load()でファイル全体をchar配列にバイナリロード。f.begin()で先頭のポインタを返す。f.getSize()でファイルサイズを返す。
f.load(font_path,false);
if(!AddFontMemResourceEx(f.begin(),f.getSize(),NULL,&font_num)){
// エラー処理
}
しかし、
AddFontResourceExは試されたんですよね?
AddFontMemResourceExで違いが出るようにも思えないので、ロード以外の問題な気もしてきましたね...
Re: .ttfフォントデータをCreateFontToHandleで使用する
Posted: 2014年8月14日(木) 00:20
by みけCAT
試してみましたが、きちんと反映されました。
DXライブラリを最新版にしてみてください。
コード:
#include <DxLib.h>
char Key[256];
int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine,int nCmdShow) {
if(ChangeWindowMode(TRUE)!=DX_CHANGESCREEN_OK || DxLib_Init()==-1) return -1;
SetDrawScreen(DX_SCREEN_BACK);
if(AddFontResourceEx("dat/font/DS-DIGI.TTF",FR_PRIVATE,NULL)==0) {
printfDx("AddFontResourceEx失敗\n");
}
int hFont=CreateFontToHandle("DS-Digital", 20,-1,DX_FONTTYPE_ANTIALIASING_8X8);
if(hFont==0) {
printfDx("CreateFontToHandle失敗\n");
}
while(!ProcessMessage() && !ClearDrawScreen() && !GetHitKeyStateAll(Key) && !Key[KEY_INPUT_ESCAPE]) {
DrawString(100,100,"123456789011",GetColor(255,0,0));
DrawStringToHandle(100,200,"123456789011",GetColor(0,255,0),hFont);
ScreenFlip();
}
DxLib_End();
return 0;
}
Re: .ttfフォントデータをCreateFontToHandleで使用する
Posted: 2014年8月14日(木) 00:24
by みけCAT
CreateFontToHandleの引数をNo: 1と同じにしても成功しました。
コード:
#include <DxLib.h>
char Key[256];
int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine,int nCmdShow) {
if(ChangeWindowMode(TRUE)!=DX_CHANGESCREEN_OK || DxLib_Init()==-1) return -1;
SetDrawScreen(DX_SCREEN_BACK);
if(AddFontResourceEx("dat/font/DS-DIGI.TTF",FR_PRIVATE,NULL)==0) {
printfDx("AddFontResourceEx失敗\n");
}
#if 0
int hFont=CreateFontToHandle("DS-Digital", 20,-1,DX_FONTTYPE_ANTIALIASING_8X8);
#else
int hFont=CreateFontToHandle("DS-Digital", 20 , 4 , DX_FONTTYPE_ANTIALIASING_EDGE);
#endif
if(hFont==0) {
printfDx("CreateFontToHandle失敗\n");
}
while(!ProcessMessage() && !ClearDrawScreen() && !GetHitKeyStateAll(Key) && !Key[KEY_INPUT_ESCAPE]) {
DrawString(100,100,"123456789011",GetColor(255,0,0));
DrawStringToHandle(100,200,"123456789011",GetColor(0,255,0),hFont);
ScreenFlip();
}
DxLib_End();
return 0;
}
Re: .ttfフォントデータをCreateFontToHandleで使用する
Posted: 2014年8月14日(木) 00:25
by みけCAT
ごめんなさい。
上記2件のソースコードで、CreateFontToHandleのエラーチェックを0と比較することで行っていますが、
正しくは-1と比較しないといけません。
本質的ではないので、訂正は省略します。
Re: .ttfフォントデータをCreateFontToHandleで使用する
Posted: 2014年8月14日(木) 13:34
by amehirune
別のプロジェクトを作ってみたところ、そちらではうまくいったのですが、
肝心のゲームプロジェクトでは、フォントが変更されていません。
コンパイラやライブラリに問題がないとするならば、どこに不備があるのでしょうか。
Re: .ttfフォントデータをCreateFontToHandleで使用する
Posted: 2014年8月14日(木) 14:06
by amehirune
ゲームのプロジェクトの方で、さらに問題点が発見されました。
DX_FONTTYPE_ANTIALIASING_EDGEはライブラリの方で#defineで定義されているのが確認されましたが、
DX_FONTTYPE_ANTIALIASING_8×8は定義が確認されておらず、
これを使用したらコンパイル時にエラーが検出されてしまいます。
Re: .ttfフォントデータをCreateFontToHandleで使用する
Posted: 2014年8月14日(木) 14:19
by うずら
古いバージョンのものを使用してるから定義が古いまま・・・
とかそんなことだと思います。
追加のライブラリディレクトリ、追加のインクルードディレクトリの設定が古いままで古いバージョンを参照している・・・
ってところじゃないですかね。
私が上げたサンプルは3.12c(軽量パッケージ)での動作を確認しています
Re: .ttfフォントデータをCreateFontToHandleで使用する
Posted: 2014年8月14日(木) 14:40
by softya(ソフト屋)
バージョン確認は、実行ログのLog.txtで行えますので確認してみてください。
Re: .ttfフォントデータをCreateFontToHandleで使用する
Posted: 2014年8月14日(木) 14:52
by amehirune
バージョン確認しました。
3.04dでした。
DXライブラリの更新は、例の手順に新たにフォルダパスを指定してあげるだけでよいのでしょうか?
Re: .ttfフォントデータをCreateFontToHandleで使用する
Posted: 2014年8月14日(木) 14:59
by うずら
それは古すぎます・・・(*´ω`*)
DXライブラリのページに書いてあるようにやれば問題ないです。
VS2008用のページ
私は、" プロジェクトに追加すべきファイル_VC用 "の場所を固定して、今までのを消してからコピーしてます。設定が面倒なんで
Re: .ttfフォントデータをCreateFontToHandleで使用する
Posted: 2014年8月14日(木) 15:07
by うずら
必要なのはここの部分だけです
2.VisualStudio2008 でDXライブラリを使うための設定を行う
必要なアイテムが揃ったところで、今度は VisualStudio2008 の設定を少し変更して、DXライブラリのファイルにPC上の何処にあるプロジェクトからもアクセスできるようにします。
① VisualStudio2008 のメニューの『ツール』→『オプション』を選びます。
② オプションウインドウの左側から『プロジェクトおよびソリューション』→
『VC++ ディレクトリ』を選びます。
③ 右側の『ディレクトリを表示するプロジェクト』から『インクルードファイル』を選びます。
④ ディレクトリリストにDXライブラリのパッケージ内に入っている
『プロジェクトに追加すべきファイル_VC用』フォルダのパスを追加します。
⑤ 『ディレクトリを表示するプロジェクト』を今度は『ライブラリファイル』にします。
⑥ ディレクトリリストに④と同じく
『プロジェクトに追加すべきファイル_VC用』フォルダのパスを追加します。
⑦ 『OK』ボタンを押して設定完了です。
Re: .ttfフォントデータをCreateFontToHandleで使用する
Posted: 2014年8月14日(木) 15:15
by amehirune
更新したところ、
コード:
1>load.obj : error LNK2019: 未解決の外部シンボル "int __cdecl DxLib::CreateFontToHandle(char const *,int,int,int,int,int,int,int,int)" (?CreateFontToHandle@DxLib@@YAHPBDHHHHHHHH@Z) が関数 "void __cdecl load(void)" (?load@@YAXXZ) で参照されました。
1>main.obj : error LNK2019: 未解決の外部シンボル "int __cdecl DxLib::ClearDrawScreen(struct tagRECT *)" (?ClearDrawScreen@DxLib@@YAHPAUtagRECT@@@Z) が関数 "int __cdecl ProcessLoop(void)" (?ProcessLoop@@YAHXZ) で参照されました。
1>C:\Users\..\Debug\???.exe : fatal error LNK1120: 外部参照 2 が未解決です。
というエラー文が出てしまいました。
(こういう系のエラーは、私には全く原因がわかりません…)
Re: .ttfフォントデータをCreateFontToHandleで使用する
Posted: 2014年8月14日(木) 15:23
by うずら
このエラーは関数宣言があって、関数定義がなかった時のものだったはずです。
さっき上げたものの⑤以降の設定を見直してみてください
Re: .ttfフォントデータをCreateFontToHandleで使用する
Posted: 2014年8月14日(木) 15:33
by amehirune
確認しましたが、エラーメッセージに変化はありませんでした。。。orz
Re: .ttfフォントデータをCreateFontToHandleで使用する
Posted: 2014年8月14日(木) 15:39
by うずら
プロジェクトに追加すべきファイル_VC用
の中身を更新してみるくらいしか対策思いつかないです(´・ω・`)
あとは、画像一枚描画するだけのプログラムがコンパイル&正常動作するか確かめたり。
Re: .ttfフォントデータをCreateFontToHandleで使用する
Posted: 2014年8月14日(木) 19:38
by へにっくす
ライブラリを更新したなら、リビルドしないとだめですよ。
またライブラリへのパスに全角が含まれるのは個人的にはよくなかったと思いますが・・・
Re: .ttfフォントデータをCreateFontToHandleで使用する
Posted: 2014年8月15日(金) 08:24
by amehirune
VC++2008でDXライブラリを使う方法を、すべて見直して登録しなおしてみたところ、
バグが消え、フォントも使えるようになりました!
皆様、ありがとうございました!