文字列の Surface を描画する

DirectX で CDisplay Class を使って、CreateSurfaceFromText で文字列を格納した Surface を生成します。
DirectX9 では2Dグラフィックスのサンプルソースが消えましたが、2Dが使えなくなった訳ではありません。 (^_^;
3Dの Sprite 機能を使えば2D描画も出来るのですが、3Dボードが無いマシンでは非常に重く実用的ではありません。 (/_;)
スペックの低いマシンでも快適に動作できて、これまで築き上げた資産を生かす上からも2Dは捨て難いでしょう。
ここでは2Dのプログラム構築について説明しています。(●^o^●)
最初に CDisplay Object Class を使って FullScreenMode で「Hello DirectX」を表示してみましょう。

前田稔(Maeda Minoru)の超初心者のプログラム入門

プロジェクトの作成

  1. 事前に DirectX9 をインストールしてパスの設定を行って下さい。
    インストールとパスの設定は DirectX9 のインストール を参照して下さい。
  2. [ファイル][新規作成][プロジェクト]を選択すると新しいプロジェクトのウインドウが表示されます。
    [プロジェクトの種類]から[Visual C++ プロジェクト]を、[テンプレート]から[Win32 プロジェクト]を選択します。
    プロジェクト名は Hello にして下さい。
    説明の画像
  3. [アプリケーションの設定]画面を表示して下さい。
    [Windows アプリケーション]と[空のプロジェクト]をチェックして下さい。
    完了ボタンをクリックすると Hello のフォルダーが作成されてプロジェクトが構築されます。
    説明の画像
  4. 次のファイルを Hello のフォルダーに格納して下さい。
    Hello.cpp の全ソースコードを、このページの後に掲載しています。
    [c:\DXSDK\]は DirectX9 がインストールされているフォルダーです。
    ddutil.cpp は DirectX の2D汎用関数が格納されているソースファイルです。
    この中で dxutil.h を include しているので dxutil.cpp を使わなくても dxutil.h は必要です。
    dxutil.h を取り込まないで、ここに記述されている数行を ddutil.cpp に直接記述することもできます。
    プロジェクト/既存項目の追加から格納したファイルをプロジェクトに追加します。
    ☆DirectX9 の新しいバージョンでは、2D関係のソースファイルが無くなっています。 (;_;)
    見つからないときは、ここから Object Class Library から取得して下さい。
    ファイル名 ファイルの説明
    Hello.cpp このページの後部に掲載
    ddutil.cpp c:\DXSDK\Samples\C++\Common\Src
    ddutil.h c:\DXSDK\Samples\C++\Common\Include
    dxutil.h c:\DXSDK\Samples\C++\Common\Include
    説明の画像
  5. ★2014/08/11 次の環境で実行出来ることを確認しました。
    ddutil.h で "d3d.h" にエラーが表示されるときは "d3d9.h" に修正して下さい。
  6. プロジェクト/プロパティを選択して Hello のプロパティページを表示します。
    下記のウインドウが表示されない時は[ソリューション]または[リソース]のタブをクリックして再操作してみて下さい。
    構成プロパティ/リンカ/入力/追加する依存関係で、次のライブラリ名をタイプして OK をクリックします。
    詳細は Windows Guid から「パスの設定」を参照して下さい。
    dxguid.lib
    ddraw.lib
    dxerr9.lib
    説明の画像
  7. ビルドから実行を選ぶと、コンパイルに続いて実行が行われます。

プログラムの説明

プログラムの実行手順は、次のようになります。
  1. ウインドウを生成します。
  2. DirectDraw を初期化します。
  3. Surface を生成して "Hello DirectX" の文字を格納します。
  4. メッセージループに入ります。
  5. ループの中で "Hello DirectX" の描画を繰り返します。
  6. 何かキーが押されたら終了します。


DirectDraw の global 領域です。
Display と文字列を格納する Surface(描画に使用するメモリ領域)です。
g_bActive は DirectDraw の初期化成功のフラグです。
CDisplay*   g_pDisplay    = NULL;
CSurface*   g_pTextSurface= NULL;  
BOOL        g_bActive     = FALSE;

DirectDraw を初期化するコードです。
初期化に失敗したらエラーメッセージを表示してリターンします。
Text を格納する Surface(描画に使用するメモリ領域)を生成して "Hello DirectX" を ドットイメージとして格納します。
「RGB(0,0,0)」「RGB(255,255,0)」は背景色と描画色で、R(赤),G(緑),B(青)の濃さを 0~255 の範囲で指定します。
下記の場合は背景色が黒に、文字の色が黄色に設定されています。
Direct Draw の初期化の詳しい説明は directX7 の「Hello DirectX7 を表示する」を参照して下さい。
HRESULT InitDirectDraw(HWND hWnd)
{   HRESULT             hr;

    g_pDisplay = new CDisplay();
    if (FAILED(hr= g_pDisplay->CreateFullScreenDisplay(hWnd, 640, 480, 16)))
    {   ERMSG("This display card does not support 640x480x16.");
        return hr;
    }

    // Create a surface, and draw text to it.  
    if (FAILED(hr= g_pDisplay->CreateSurfaceFromText(&g_pTextSurface,
               NULL,"Hellow DirectX",RGB(0,0,0),RGB(255,255,0))))
        return hr;

    return S_OK;
}

Message Loop です。
DisplayFrame() で毎回描画を行います。
    while(TRUE)
    {   if (PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE))
        {   if (0 == GetMessage(&msg, NULL, 0, 0))  return (int)msg.wParam;
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }
        else
        {   if (g_bActive)
            {   if (FAILED(DisplayFrame()))
                {   SAFE_DELETE(g_pDisplay);
                    ERMSG("Displaying the next frame failed. The sample will now exit.");
                    return FALSE;
                }
            }
            else    WaitMessage();
        }
    }

描画を行うコードです。
Clear() で DisplaySurface をクリアします。
Blt() でドットイメージになった文字列を描画します。
Present() でフレームを切り替えます。
HRESULT DisplayFrame()
{   HRESULT hr;

    // Fill the back buffer with black, ignoring errors until the flip
    g_pDisplay->Clear(0);
    // Blt all the sprites onto the back buffer using color keying,
    g_pDisplay->Blt(0, 0, g_pTextSurface, NULL);
    // We are in fullscreen mode, so perform a flip and return 
    if (FAILED(hr= g_pDisplay->Present())) return hr;

    return S_OK;
}

変数の頭に「g_p,g_b」などと付けられていますが、これらは変数の種類を識別するプリフィックスで g は Global を p は Pointer を意味します。
このようにプリフィックスを付けた変数名の付け方をハンガリアン記法と呼びます。
変数名が長くなるので嫌われる向きもあるのですが、なるべく尊重したいものです。
代表的なハンガリアン記法を掲載します。
ハンガリアン記法 データ型
b 論理値
by BYTE
c char
dw DWORD
fn 関数
g Global
h ハンドル
i int
l long または farポインタ
n short または nearポインタ
p ポインタ
s 文字列
sz NULL で終了する文字列
w WORD

超初心者の方のために全ソースコードを掲載します。 (^_^;)
全ソースコード

超初心者のプログラム入門(DirectX9 game program)