カウンタ

  文字の表示

Google
▲探し物はこちら

 本来はポリゴンの作成などからはじめるのが普通なのですが、情報を知るのに文字が表示されたほうが都合がいいので、Direct3D 上で文字を表示させたいと思います。

文字の表示

 下のリンクから今回のプロジェクトをまるごとダウンロードできます。

ファイル名 言語 サイズ バージョン
drawtext_cs_1_1.zip C# 21KB 1.1
drawtext_vb_1_1.zip VB.NET 26KB 1.1
drawtext_cpp_1_1.zip C++/CLI 12KB 1.1

 今回のメインコードファイルを載せます。重要なコードを赤色で表示させています

MainSample.cs

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using Microsoft.DirectX;
using Microsoft.DirectX.Direct3D;

namespace MDXSample
{
    /// <summary>
    /// メインサンプルクラス
    /// </summary>
    public partial class MainSample : IDisposable
    {
        /// <summary>
        /// Direct3D 用フォント
        /// </summary>
        private Microsoft.DirectX.Direct3D.Font _font = null;


        /// <summary>
        /// アプリケーションの初期化
        /// </summary>
        /// <param name="topLevelForm">トップレベルウインドウ</param>
        /// <returns>全ての初期化がOKなら true, ひとつでも失敗したら false を返すようにする</returns>
        /// <remarks>
        /// false を返した場合は、自動的にアプリケーションが終了するようになっている
        /// </remarks>
        public bool InitializeApplication(MainForm topLevelForm)
        {
            // フォームの参照を保持
            this._form = topLevelForm;

            try
            {
                // Direct3D デバイス作成
                this.CreateDevice(topLevelForm);


                // フォントデータの構造体を作成
                FontDescription fd = new FontDescription();

                // 構造体に必要なデータをセット
                fd.Height = 24;
                fd.FaceName = "MS ゴシック";

                // フォントを作成
                this._font = new Microsoft.DirectX.Direct3D.Font(this._device, fd);
            }
            catch (DirectXException ex)
            {
                // 例外発生
                MessageBox.Show(ex.ToString(), "エラー", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return false;
            }

            return true;
        }

        /// <summary>
        /// メインループ処理
        /// </summary>
        public void MainLoop()
        {
            // 描画内容を単色でクリア
            this._device.Clear(ClearFlags.Target, Color.DarkBlue, 1.0f, 0);

            // 「BeginScene」と「EndScene」の間に描画内容を記述する
            this._device.BeginScene();


            // 座標 x=0 y=0 の位置に白色で描画
            this._font.DrawText(null, "DirectX Tips サンプル", 0, 0, Color.White);

            // Point 構造体を使用して位置を設定
            this._font.DrawText(null, "Point 構造体を使用しています。",
                new Point(250, 40), Color.Yellow);

            // Rectangle 構造体とテキストフォーマットを使用して描画
            this._font.DrawText(null, "Rectangle 構造体とテキストフォーマット",
                new Rectangle(100, 260, 500, 400),
                DrawTextFormat.Left | DrawTextFormat.Top, Color.LightPink);

            // 複数行も可能
            this._font.DrawText(null, "複数行も" + Environment.NewLine + "可能",
                new Rectangle(400, 320, 500, 400),
                DrawTextFormat.Left | DrawTextFormat.Top, Color.LightGreen);


            // 描画はここまで
            this._device.EndScene();

            // 実際のディスプレイに描画
            this._device.Present();
        }

        /// <summary>
        /// リソースの破棄をするために呼ばれる
        /// </summary>
        public void Dispose()
        {
            // フォントのリソースを解放
            if (this._font != null)
            {
                this._font.Dispose();
            }

            // Direct3D デバイスのリソース解放
            if (this._device != null)
            {
                this._device.Dispose();
            }
        }
    }
}

 では、赤文字の部分を説明していきます。MainSamplePartial.cs ファイルのコードはこちらです。


public partial class MainClass : IDisposable

 class の前に「partial」というキーワードを付けました。C# が分かる人なら意味は分かると思いますが後ほど説明します。


/// <summary>
/// Direct3D 用フォント
/// </summary>
private Microsoft.DirectX.Direct3D.Font _font = null;

 フィールドで Direct3D 用フォントを宣言しています。描画する文字列の数に関係なくフォントはひとつでいいです。実行速度を考える場合や文字の大きさが異なる場合は、あらかじめ複数作成しておいて描画時に切り替える方法もありますが、今回は文字が描画できればいいのでひとつにします。

 今回、フォントを宣言するのに「Microsoft.DirectX.Direct3D.Font」とネームスペースをすべて記述していますが、これは「System.Drawing」の「Font」と「Microsoft.DirectX.Direct3D」の「Font」を区別するため、このように明確に識別しています。


try
{
    // Direct3D デバイス作成
    this.CreateDevice(topLevelForm);
        ;
        // (省略)
        ;
}
catch (DirectXException ex)
{
    // 例外発生
    MessageBox.Show(ex.ToString(), "エラー", MessageBoxButtons.OK, MessageBoxIcon.Error);
    return false;
}

 前回まであった Direct3D デバイス作成コードがなくなっています。実は、それらのコードを「CreateDevice」メソッドにまとめてしまいました。
 理由はデバイス作成処理は毎回ほとんど同じなので、いちいちメインの Tips に入れると見るときの邪魔になってくるからです。
 では、そのメソッドはどこに書いてあるかというと、「MainSamplePartial.cs」にあります。このファイルを見るとなぜか同じ「MainSample」クラスがあり、普通にクラス内にメソッドとフィールドが記述されています。「C# 2.0」では「partial」修飾子によってクラスを複数のファイルに分割できる機能があります。そのため、別なファイルにコードをまとめる場合でも、わざわざ新しいクラスを作成する必要がなくなります。
 もし、「C# 2.0」以前のバージョンを使用している場合は、分けているコードを一つのファイルにまとめれば大丈夫です。

 「MainSamplePartial.cs」ファイルを追加するには下の図のようにファイルを追加してください。ファイル名は基本的に何でもいいですが一応サンプルでは「MainSamplePartial.cs」とします。ただし、クラス名は必ず一緒(この場合「MainSample」)にしてください。

クラス追加

 ファイルを作成したら下のように書き換え、フィールドやメソッドなどを追加していきます。

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using Microsoft.DirectX;
using Microsoft.DirectX.Direct3D;

namespace MDXSample
{
    public partial class MainSample
    {
    }
}

 この Tips 以降でも、同じようなコードが出てきた場合は、このように「MainSamplePartial.cs」ファイルに移していくようにしたいと思います。これによって Tips を見ている方が重要な部分のみを見れるようになるかと思います。
 後、Tips では別途、クラスを作成する予定はありません。もちろんクラスが必須な Tips もあるので、その場合は作ります。もし必要であれば各自クラスを作ってみるのもいいかもしれません。

 さて、上記コードですが、Direct3D デバイスを作成し、失敗した場合はメソッド内で例外を飛ばすようにしていますので、例外が発生した場合はメッセージボックスを表示して false を返すようにしています。false を返した場合はそのままアプリケーションが終了するようになっています。


// フォントデータの構造体を作成
FontDescription fd = new FontDescription();

// 構造体に必要なデータをセット
fd.Height = 24;
fd.FaceName = "MS ゴシック";

// フォントを作成
this._font = new Microsoft.DirectX.Direct3D.Font(this._device, fd);

 ここでフォントを作成しています。本来は、1行で済ませることもできるのですが、その場合、「Font」コンストラクタですべてのパラメータを設定しなければいけないので、今回は「FontDescription」構造体にデータを設定してそれを渡すようにしています。

 FontDescription 構造体には文字の大きさ、フォント名、太さなど様々な項目があるのでヘルプなどで調べてみてください。

 とりあえず「文字の高さ」と「フォント名」を指定すれば十分なので、それを指定して「Font」コンストラクタに渡します。必要であれば「文字の太さ」や「イタリック」なども設定できます。

Font コンストラクタ
Font クラスのインスタンスを作成します。
device Direct3D デバイスを渡します。
description 設定済みの FontDescription 構造体を渡します。

// 座標 x=0 y=0 の位置に白色で描画
this._font.DrawText(null, "DirectX Tips サンプル", 0, 0, Color.White);

// Point 構造体を使用して位置を設定
this._font.DrawText(null, "Point 構造体を使用しています。",
    new Point(250, 40), Color.Yellow);

// Rectangle 構造体とテキストフォーマットを使用して描画
this._font.DrawText(null, "Rectangle 構造体とテキストフォーマット",
    new Rectangle(100, 260, 500, 400),
    DrawTextFormat.Left | DrawTextFormat.Top, Color.LightPink);

// 複数行も可能
this._font.DrawText(null, "複数行も" + Environment.NewLine + "可能",
    new Rectangle(400, 320, 500, 400),
    DrawTextFormat.Left | DrawTextFormat.Top, Color.LightGreen);

 これが文字を描画するコードになります。本来は1行でいいのですが、いろんなパターンで描画してみることにしました。

 1行目は文字列を描画する位置を X、Y 別々に指定して描画しています。位置は文字列の左上が基準になります。色は描画するときに指定できるので、わざわざ別のフォントを用意する必要はありません。

 2行目は位置を「Point」構造体を使用して指定しています。

 3行目は矩形を使用して描画範囲を設定します。矩形内でどのように描画するかを「DrawTextFormat」で指定します。ここでは矩形の「左上」に描画するように指定しています。もちろん真ん中や右下などの位置を指定することができます。
 また、テキストフォーマットに「DrawTextFormat.NoClip」を指定しない限りは、矩形外にはみ出た文字は描画されません。

 4行目は文字列に改行を入れています。改行コードは「\r\n」ですが、「Environment.NewLine」を使用することが推奨されています。理由は環境によって改行コードが違う場合に対処できるからです。テキストフォーマットで「DrawTextFormat.SingleLine」を指定した場合は、改行コードが入っていても改行できないようにできます。

 Font.DrawText メソッドの第1引数は null を指定していますが、ここには「Sprite」を指定できます。これを指定すると描画速度を若干向上させることができますが、今回は文字を描画できればいいので省略しています。

Font.DrawText メソッド
テキストを描画します
sprite Sprite クラスを使用して描画効率を上げます。使用しない場合は null を指定
text 描画する文字列
rect 描画する範囲
format 書式設定。DrawTextFormat 列挙型の組み合わせを指定
color 文字の色

// フォントのリソースを解放
if (this._font != null)
{
    this._font.Dispose();
}

 フォントも使用し終わったらリソースを解放します。

その他の関連情報です▼