D3DXCreateFontとID3DXFont::DrawTextによる文字列の縦書き描画

このQ&Aのポイント
  • D3DXCreateFontとID3DXFont::DrawTextを使用して文字列を縦書き描画する方法
  • コードの記述方法と引数の設定により、文字列が表示されない場合の解決策
  • 開発環境と言語:Visual Studio 2005 C++、C/C++(Win32API)+DirectX9.0b
回答を見る
  • ベストアンサー

D3DXCreateFontとID3DXFont::DrawTextによる文字列の縦書き描画

お世話になっています。 D3DXCreateFontとID3DXFont::DrawTextによって文字列を左上(0,0)右下(20,100)の四角形内に縦書き描画しようと、以下のようにコードを書きました。 CreateFontの第3引数cEscapementを2700にし、 CreateFontの第4引数cOrientationも2700にしてCreateFont、D3DXCreateFontによって作成したフォントで、 SetRect(0,0,20,100); DrawText(Str,-1,&rc,DT_SINGLELINE | DT_WORD_ELLIPSIS | DT_NOCLIP, D3DCOLOR_XRGB(0,0,0)); 上のようにして実行すると、何も表示されません。 SetRectの引数を変えてみたりはしたのですが、それでもやはり上手くいきませんでした。 もちろん、フォントは縦書きフォントを指定しています。 さっぱり原因がわからないので、どなたがご存知の方がいらっしゃれば、ご教授よろしくお願いします。 開発環境:Visual Studio 2005 C++ 開発言語:C/C++(Win32API)+DirectX9.0b

noname#75566
noname#75566

質問者が選んだベストアンサー

  • ベストアンサー
  • koedame
  • ベストアンサー率33% (10/30)
回答No.3

そうですか・・・。 横書きが OK なら少しずつ値(角度等)を変更していくと何かがわかる場合が あります。変更できるところがあるならとことん変更していくと 覚えられるし、応用方法が増えていくのでいいと思います。 (まあ、時間が空いているならですが。^^) ただ、ダイレクト X と WinAPI を組み合わせる動作は 私にはよくわかりませんのでご自分でしらべてください。 でも、少し突っ込みを入れると >ただ、D3DXFontを使うためにDrawTextがいいんですよね。 >(DirectXでTextOutは重すぎるので・・) DirectX で TextOut() 関数は別に重いわけではないです。(多分) DirectX で TextOut() 関数を使うにはサーフェイスからデバイスコンテキストハンドルを 取得してやる・・・というめんどくさい作業が入るけど出来ます。 それに DrawText() も実は重いです(うわさ)。 下記のサイトから DirectX技術編→高速フォント表示 ではテクスチャにフォント文字を書き込んで そのテクスチャを貼り付けるという高速文字の描画方法 が記述されています。それにテクスチャなので回転等が 使えるので縦書きにも工夫次第で出来ます。 サンプルソースが記述されているのでわかりやすいサイトです。 DirectX をやっているならこのサイトはそれなりに役に立つと思います。

参考URL:
http://www.h6.dion.ne.jp/~game296o/GameMain.html
noname#75566
質問者

補足

アドバイス有難うございます。 そうですね、素直にテクスチャ生成を試してみた方がいいですね。 頻繁に描画する文字が変わるため、テクスチャ生成の時間がネックになりそうで躊躇していたのですが、やってみることにします。 DrawTextは普通に重いですが、TextOutよりは軽いと思います。 一応Win32APIではなくID3DXFontのメソッドですので。 内部でWin32APIのDrawTextを呼び出しているだとかいう話があったような気もするため確信が持てなくなってきましたが・・。 では、やはり初心に帰ってテクスチャ生成を試してみます。 上手くできたらご報告します。

その他の回答 (3)

  • koedame
  • ベストアンサー率33% (10/30)
回答No.4

色々と手間がかかりますけど頑張ってください。 DrawText については私も WinAPI の途中からDirectX に移ったので微妙なうる覚えだったかもしれません。 >内部でWin32APIのDrawTextを呼び出しているだとかいう話があったよ>うな気もするため確信が持てなくなってきましたが・・。 こんなこと知りませんでしたよ。ありがとうございます。^^ ずいぶんお詳しいようですから、すぐ出来ますよ。 頑張ってください。 ちなみに私はDirectX 始めて5ヶ月くらいなので そんなに詳しくはお答えできなかったと思います。 本当に参考程度にしてください。

noname#75566
質問者

お礼

お返事遅れてすみません。 動的にテクスチャを生成する方法で大丈夫のようでした。 手間はかなり増えましたが、速度も速く上々です。 ありがとうございました。

  • koedame
  • ベストアンサー率33% (10/30)
回答No.2

とりあえず、もう一度・・・ここからはアドバイスというより 余計なおせっかいになるかもしれませんデス。^^ エラーチェックをしてOKなら、 (備考 g_pD3DDevice はLPDIRECT3DDEVICE9です (デバイス)) g_pD3DDevice->BeginScene();  //シーンの開始 /*この部分*/ g_pD3DDevice->EndScene(); g_pD3DDevice->Present( NULL, NULL, NULL, NULL ); 「/*この部分*/」 という場所にDrawText() メソッドを使っているか・・・ そういう単純なミスのチェックが結構あるのでそこなど 最後に補足なんですけど、縦書きをやろうとしていらっしゃるようですが、横書きは出来ているのでしょうか? もし、出来ていないなら、そちらからやったほうが・・ね・・ orz 俺は何が言いたいんだろう・・。 これでもまだ駄目ならまた返事をお願いします。 少し調べてみます。

noname#75566
質問者

補足

アドバイスありがとうございます。 CreateFontの角度指定で0を指定した場合は、普通に横書きで表示されています。 ですので、DrawTextメソッドの位置はあっているはずだと思います。 HDCを使って、TextOutで描画したときはきちんと縦書きに表示されるんです。 ただ、D3DXFontを使うためにDrawTextがいいんですよね。 (DirectXでTextOutは重すぎるので・・)

  • koedame
  • ベストアンサー率33% (10/30)
回答No.1

アドバイス程度に聞いてください。 そちらの開発環境ではデバッガがあるのでブレークポイント等を挿入したりしてプログラムを止めてみて様子を見るのも一つの手です。 LPD3DXFONT p_D3DXFont; //フォントオブジェクト HRESULT hr; hr = p_D3DXFont->DrawText(     NULL,     /*文字列*/,     -1,     /*RECT 構造体*/,     FW_NORMAL, //仮の値なので・・・     D3DCOLOR_XRGB(0,0,0) ); if( FAILED(hr) ) {     MessageBox( NULL, "失敗", "エラー", MB_OK ); } hr には成功するとD3D_OK,失敗すると、うーん・・・変な値が入っています。 -214341ぐらいの数字です。 ただ、上のif文のやり方だとメッセージボックスがたくさん出る のでお勧めしません。 他にも背景の色と文字の色が同じなんていう落ちもあるので、 色々試してください。

noname#75566
質問者

お礼

アドバイスありがとうございます。 DrawTextの返り値を調べてみたのですが、エラーが返されることはありませんでした。 背景の色と文字の色が同じ、という落ちもなかったみたいです。 いまいちDrawTextメソッドの仕様を詳細に把握してなく、Rectの座標指定ミスかな、とは踏んでいるのですが。 どうしましょうか・・・。

関連するQ&A

  • DrawTextでの描画

    お世話になります。 現在開発中のアプリケーションにて行き詰ってしまった箇所が あったためご質問させていただきました。 Visual Studio2005にてダイアログベースのアプリケーションを作成しており、オリジナルのCStatic派生のクラスCSampleStaticクラスを作成します。 このCSampleStaticクラスはメインダイアログでのサブクラスにした際に PreSubclassWindow() ないでタイマーイベントを発生させます。タイマーイベントの内容は1秒ごとにタイマーを呼び、ランダムの値をそのCStaticの値に代入し、ダイアログ上に表示させる動作をします。 その際の処理のプログラムは以下のように作成しています CString str;//メンバー変数 //メインダイアログにてサブクラス化した際に呼ばれる CSampleStatic::PreSubclassWindow() { SetTimer(1,1000,NULL);//1秒毎に } CSampleStatic::OnTimer(UINT_PTR nIDEvent) { str.Format(_T("%d"),rand()%200); //1~199の乱数をstrに代入  Invalidate();           //OnPaint()を呼ぶ  CStatic::OnTimer(nIDEvent); } CSampleStatic::OnPaint() { CPaintDC dc(this); CFont MyFont; MyFont.CreateFont(-----); //フォント設定 CDC* myDC = GetDC(); CRect Myrect; GetClientRect(&Myrect); myDC->SelectObject(&Myrect); myDC->DrawText(str,-1,&Myrect,DT_CENTER); //strを表示 ReleaseDC(myDC); MyFont.DeleteObject(); } というプログラムを作成しているのですが、この方法でのダイアログへの文字の表示では、たとえば90が表示され、次に100が表示されるのであればいいのですが、100のあとに90が表示された時に100の上にそのまま90が表示されてしまい、うまく表示できません。 再描画のときに、上書きではなく、前回の数値を消去してから新たな数値を表示できればいいとは思うのですが、やり方がわからず、ご意見をいただければと思い質問させていただきました。 どうか宜しくお願いいたします。 開発環境は Windows CE 6.0 Visual Studio 2005 です。

  • リッチエディットの独自描画で文字の位置をそろえたい

    リッチエディットのWM_PAINT命令をフックすることで、改行文字を視覚化するプログラムを組んでいるのですが、GetCharPos命令で取得した文字位置の座標は左上隅のものなので、一般のテキスト文字と描画した文字がうまく横並びになりません。また、GetTextExtentでフォントの高さを取得することで、水平位置を調整しようと思ったのですが、フォントの高さとリッチエディットの一行単位の高さが異なるためか、以下のコード例(MFCにて作成)でもやはりきれいに揃いません(文字数制限のため、一部コードを省いています)。 void CRichEditEx::OnDrawFormatChar() { CString strText; GetWindowText(strText); CPoint ptCharL; CClientDC dc(this); //m_foFormatCharは //SetDefaultCharFormat()で登録したフォントと //サイズ・フォント名ともに同一 CFont* pfoOld = dc.SelectObject(&m_foFormatChar); CSize sizChar = dc.GetTextExtent(_T("W")); CRect rectClient; GetRect(&rectClient); int i, iPos = 0; while(iPos != -1){ iPos = strText.Find(_T('\n'), iPos); if(iPos != -1){ ptCharL = GetCharPos(iPos); if(ptCharL.y > rectClient.bottom) break; if(rectClient.PtInRect(ptCharL)){ dc.DrawText(_T("N"), CRect(ptCharL, ptCharL + sizChar), DT_SINGLELINE | DT_VCENTER); } } } フォントの上下余白を含めた高さ、あるいは、リッチテキストの1行単位の高さが取得できれば何とかなると思うのですが、よい方法はございますでしょうか。

  • PGPLOTでの文字描画

    VB6やVS.Netを使わずWindows上でグラフを書くよう依頼があり、 PGPLOTを使い始めました。 グラフ描画に関しては何の問題もなく動作しているのですが、 なぜか文字が描画されません。 解決の糸口が全く掴めないのでご教示願います。 ■ソース #include "cpgplot.h" int main(void){ cpgopen("/GW"); cpgpap(5.0, 0.75); cpgenv(0, 50, 0, 50, 0, 0); cpgscf(1); //文字フォント cpgsch(2.0); //文字の大きさ cpgtext(10, 10, "TEST"); return; } ■開発環境 (1)OS Windows XP SP3 (2)MinGW Ver. 5.1.6 (3)コンパイラ Borland C++ Compiler 5.5 (4)GrWin グラフィックス・ライブラリ lGrWn0999b.exe (5)開発時の使用ソフト BCC Developer プロジェクト設定のリンクは以下を追加しています C:\borland\bcc55\Lib\cpgplot.lib C:\borland\bcc55\Lib\pgplot.lib C:\borland\bcc55\Lib\f2c.lib C:\borland\bcc55\Lib\GrWin.lib

  • ウィンドウのフレームの色変更

    <環境> Win98 VC++6.0 MFC よろしくお願いします。 ダイアログのボタン押し下げにて、新規にウィンドウを作成しています。 新規に作成したウィンドウのクライアント領域の色は、 CPaintDC dc(this); // 描画用のデバイス コンテキスト CRect cr; GetClientRect( &cr); dc.FillSolidRect( cr, RGB( 250, 250, 0)); dc.DrawText( moji,cr, DT_SINGLELINE | DT_VCENTER | DT_CENTER); にて変更することが出来ました。 クライアント領域の外側にあるフレームの色も変更したいのですが、 どのようにすれば実現可能でしょうか? ご存知の方、教えてください。お願いします。

  • fgetws関数で読み込んだUNICODE文字列の文字化け

    お世話になります。 UNICODE文字列について上手くいかない部分があったので質問します。 (1)ANSI文字コードのテキストファイルをfgetws関数で読み込む (2)読み込んだ文字列をID3DXFont::DrawTextWメソッドで描画 以上のことを行うと、1バイト文字(半角文字)はきちんと表示されるのに対し、2バイト文字は化けてしまいます。 きちんと表示されるようにするにはどうすれば良いでしょうか? 開発環境:Visual Studio 2005 C++ 開発言語:C/C++(Win32API)+DirectX9.0b ご存知の方がいましたら、よろしくお願いします。

  • ローディング画面をマルチスレッドで動かせません。

    ローディング画面をマルチスレッドで動かせません。 DirectXとC++をVisualStudio2010でゲームを制作しています。 ローディング画面を動かせるようにマルチスレッドにしているんですが、パソコンによってはローディング画面から動かなくなってしまいます。(開発環境では、問題なく動きます) スレッドの呼び出し部分は以下のようになっています。 HANDLE thread; CScene gamen; //タイトル画面やメインゲーム画面などのシーンを管理 void Loading() { SetDrawLoading( true ); delete gamen; gamen = new CTitleGamen(); thread = (HANDLE)_beginthreadex(NULL,0,DrawLoading,NULL,0,NULL); gamen->LoadData(); //クラス内の画像や音楽データを読み込み effect->SetDrawLoading(false); WaitForSingleObject( thread, INFINITE ); CloseHandle(thread); } マルチスレッド部分は以下のように、 drawLoading変数がtrueの間、ローディング画面を描画するようにしています。 D3DXMATRIX m_world; unsigned __stdcall DrawLoading(void *p){ LPDIRECT3DTEXTURE9 pTexture; D3DXCreateTextureFromFileEx(m_pD3DDevice, TEXT("texture.png"),16, 16, 0, 0, D3DFMT_UNKNOWN, D3DPOOL_MANAGED, D3DX_FILTER_NONE, D3DX_DEFAULT, D3DCOLOR_XRGB(255,255,0), NULL, NULL, &pTexture)) do{ m_pD3DDevice->Clear(0,NULL,D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, D3DCOLOR_XRGB(0,0,0), 1.0f, 0); if( SUCCEEDED( m_pD3DDevice->BeginScene() ) ) { D3DXMatrixIdentity( &m_world ); m_pD3DDevice->SetTransform( D3DTS_WORLD, &m_world ); m_pSprite->Begin( D3DXSPRITE_ALPHABLEND ); m_pSprite->Draw( pTexture, NULL, NULL, &D3DXVECTOR3( timeGetTime()%800), 550, 0 ), 0xffffffff ); m_pSprite->End(); m_pD3DDevice->EndScene(); } m_pD3DDevice->Present( 0, 0, 0, 0 ); }while( effect->GetDrawLoading() ); pTexture->Release(); _endthreadex(0); return 0; } どなたか、ご教授お願い致します。

  • C言語のvoid型ポインタ変数について。

    C言語のvoid型ポインタ変数について。 C言語のvoid型ポインタ変数について質問があります。 組み込み系の開発を行っているのですが、現在使用しているシステムで、 提供されている "API" を介してアプリケーション部のソフト作成を行っています。 この "API" ですが、引数の多くはvoid型ポインタとなっています。 ある人がこの引数がvoid型となっているのを見て、 『なんでvoid型なんや??、C言語でアセンブラと違うんやから、void型なんかにしない方が良い』 とおっしゃいました。 この意味がよくわからなかったのですが、なぜ void型はよろしくないんでしょうか? -- 僕が思うに、APIなんやから引数を void型ポインタ にすることでどんな型にも対応できる 汎用的であると感じ、逆にこの方が良いのではと感じたのですが。。 -API例---- int _exApiKannsuu( char in_data, void* out_data ) "in_data" をもとに "out_data" を取得する。 どーやらこの "out_data" が void型 であるのががよくないらしい・・

  • 文字を縦書きで描画する

    drawStringメソッドを使用すると、横書きで 引数の文字列を描画しますが、これを縦書きで描画したい 場合はどのようにすればよろしいのでしょうか?

    • ベストアンサー
    • Java
  • 5^3をAPIで表示するために

    HDC hD; PAINTSTRUCT ps; TEXTMETRIC tm; HDROP hDrop; HFONT hPF,hF; string str; int i_w,i_h; ................................................................ case WM_PAINT: hD=BeginPaint(hW,&ps); SelectObject(hD,GetStockObject(OEM_FIXED_FONT)); GetTextMetrics(hD,&tm); i_w=tm.tmAveCharWidth; i_h=tm.tmHeight; SetTextAlign(hD,TA_LEFT|TA_TOP); ///////////////////////////////////////////////// str="5"; TextOut(hD,0,0,str.c_str(),str.size()); ///////////////////////////////////////////////// hF=CreateFont (i_h/2,i_w/2,0,0,FW_NORMAL,FALSE,FALSE,FALSE,SHIFTJIS_CHARSET,OUT_DEFAULT_PRECIS ,CLIP_DEFAULT_PRECIS,DEFAULT_QUALITY,FIXED_PITCH|FF_MODERN,"System"); hPF=(HFONT)SelectObject(hD,hF); ///////////////////////////////////////////////// str="3"; TextOut(hD,i_w,0,str.c_str(),str.size()); ///////////////////////////////////////////////// SelectObject(hD,hPF); DeleteObject(hF); EndPaint(hW,&ps); return 0; とすればできますがCreateFontによる文字サイズは思うようなサイズにならないことが多くてやってみないとサイズが半分になっているかどうかわかりません 酷い場合には半分のサイズを指定しても全くサイズが変わらない場合もあります 上の例では i_h=18でありi_w=8でありCreateFont後 キャラクタの高さはi_h/2=9となりキャラクタの幅はi_w/2=4になってくれました しかしこの場合はたまたまうまくいったので通常はこうはなりません 確実にもとのサイズの半分(面積比1/4)のキャラクタサイズにする方法を教えてください

  • テキストエディタならばCreateWindow

    を使って hEdit = CreateWindow("EDIT",NULL,WS_CHILD| WS_VISIBLE|ES_WANTRETURN|ES_MULTILINE| ES_AUTOVSCROLL|WS_VSCROLL|ES_AUTOHSCROLL| WS_HSCROLL, 0,0,rc.right,rc.bottom,hWnd,(HMENU)ID_EDIT, hInst,NULL); として char Str[1048576]にテキストをおさめ SetWindowText(hEdit,Str); とすればスクロール関数も使う必要なくカレットもでて文字を簡単に編集できるのですが テキストビューワならば文字を変更する必要が無くカレットもでると困るのでこれが使えません また↓や↑で1行スクロールしないといけません (エディタの場合はカレットが上下端にきたときにスクロールだからちょっと違う) DrawTextだとスクロール関数を使わないといけないような気がするし・・・ 見るだけのテキストビューワを作るのに適した方法やC言語SDK関数を教えてください

専門家に質問してみよう