スケルトンプログラムにDirectDrawを組み込み、
ウィンドウを640×480ピクセルのフルスクリーンに設定する。
プログラムの流れは次のようになる。![]()
1.DirectDrawラッパー関数の準備
Microsoftが無料公開しているDirectDrawのラッパー関数「
ddutil.cpp」を利用すると、DirectDraw系の処理が簡単に作成できるので、これを利用する。
プロジェクトのフォルダにMicrtosoftのDirectDrawラッパー関数「ddutil.cpp」「ddutil.h」をコピーし、コピーしたファイルをプロジェクトに追加(「プロジェクト」→「プロジェクトへ追加」→「ファイル」)する。2.DirectDraw関係のヘッダ・ファイルをインクルード
DirectDrawを利用するには、「
ddraw.h」をインクルードする必要がある。また、DirectDrawのラッパー関数「ddutil.cpp」を利用するには、「ddutil.h」をインクルードしなければならない。
#include <ddraw.h>
#include "ddutil.h"
- ddraw.hはC:\mssdk\include\libにあるため、<>で囲む
- ddutil.hはプロジェクトのフォルダ内にあるため、””で囲む
- プロトタイプ宣言に、以下の行を追加する
HRESULT InitializeDraw(HWND); - グローバル変数にDirectDrawオブジェクトを宣言する
LPDIRECTDRAW7 g_pDD = NULL; // DirectDraw オブジェクト
LPDIRECTDRAWSURFACE7 g_pDDSPrimary = NULL; // プライマリ・サーフェイス
LPDIRECTDRAWSURFACE7 g_pDDSBack = NULL; // バック・サーフェース- DirectDrawオブジェクトの生成・初期化を行う関数をInitApp関数の下に作成する
//----------------------------------------------------------------------------- // 関数名 : InitializeDraw() // 機能概要: Direct Draw オブジェクトの生成 // 戻り値 : 正常終了のとき:DD_OK、異常終了のとき:エラーコード //----------------------------------------------------------------------------- HRESULT InitializeDraw(HWND hWnd) { DDSURFACEDESC2 ddsd; DDSCAPS2 ddscaps; HRESULT hRet; /////////////////////////////////////////////////////////////////////////// // DirectDraw メインオブジェクトの作成 /////////////////////////////////////////////////////////////////////////// hRet = DirectDrawCreateEx(NULL, (VOID**)&g_pDD, IID_IDirectDraw7, NULL); if (hRet != DD_OK) return InitFail(hWnd, hRet, "DirectDrawCreateEx FAILED"); // 協調レベルの設定 hRet = g_pDD->SetCooperativeLevel(hWnd, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN | DDSCL_ALLOWREBOOT); if (hRet != DD_OK) return InitFail(hWnd, hRet, "SetCooperativeLevel FAILED"); // ビデオモードの設定 640x480x8 hRet = g_pDD->SetDisplayMode(640, 480, 8, 0, 0); if (hRet != DD_OK) return InitFail(hWnd, hRet, "SetDisplayMode FAILED"); // プライマリ・サーフェイスの生成 ZeroMemory(&ddsd, sizeof(ddsd)); ddsd.dwSize = sizeof(ddsd); ddsd.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT; ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_FLIP | DDSCAPS_COMPLEX; ddsd.dwBackBufferCount = 1; hRet = g_pDD->CreateSurface(&ddsd, &g_pDDSPrimary, NULL); if (hRet != DD_OK) return InitFail(hWnd, hRet, "CreateSurface FAILED"); // バック・サーフェイスの生成 ZeroMemory(&ddscaps, sizeof(ddscaps)); ddscaps.dwCaps = DDSCAPS_BACKBUFFER; hRet = g_pDDSPrimary->GetAttachedSurface(&ddscaps, &g_pDDSBack); if (hRet != DD_OK) return InitFail(hWnd, hRet, "GetAttachedSurface FAILED"); return DD_OK; }DirectDrawの各オブジェクトの生成に失敗したときに実行する
InitFail関数を作成していないため、ここでビルドしてもエラーになる。
DirectDrawオブジェクトの生成に失敗したとき、以下の処理を行わせる関数を作成する。
- エラーメッセージをダイアログボックスで表示する
- DirectDrawオブジェクトを開放する関数
ReleaseDrawを実行する
(ReleaseDraw関数はまだ作成していない)プログラム作成手順は次のとおり。
- プロトタイプ宣言に、以下の行を追加する
HRESULT InitFail(HWND hWnd, HRESULT hRet, LPCTSTR szError,...); - エラー処理を行う関数をInitializeDraw関数の下に作成する
//----------------------------------------------------------------------------- // 関数名 : InitFail() // 機能概要: 初期化に失敗したときのメッセージ表示関数 // 引数例 : InitFail(hWnd,hRet,"Err String"); 文字列の表示 // InitFail(hWnd,hRet,"Err Code %d %d", code, err); 書式指定の表示 // 戻り値 : hRetの値(エラーコード) //----------------------------------------------------------------------------- HRESULT InitFail(HWND hWnd, HRESULT hRet, LPCTSTR szError,...) { char szBuff[128]; va_list vl; va_start(vl, szError); vsprintf(szBuff, szError, vl); ReleaseDraw(); MessageBox(hWnd, szBuff, "ERROR", MB_OK); DestroyWindow(hWnd); va_end(vl); return hRet; }- この関数では、vsprintf関数を使用しているが、この関数を利用するにはstdio.hをインクルードしなければならない。
#include <stdio.h> DirectDrawの各オブジェクトを開放する
ReleaseDraw関数を作成していないため、ここでビルドしてもエラーになる。
ウィンドウを閉じるとき(ゲームが終了するとき)に、生成済みのDirectDrawオブジェクトを開放する関数を作成する。
プログラム作成手順は次のとおり。
- プロトタイプ宣言に、以下の行を追加する
void ReleaseDraw(void); - 生成済みのDirectDrawオブジェクトを開放する関数をInitFail関数の下に作成する
//----------------------------------------------------------------------------- // 関数名 : ReleaseDraw() // 機能概要: Direct Draw オブジェクトの削除 //----------------------------------------------------------------------------- void ReleaseDraw(void) { if (g_pDD != NULL) { if (g_pDDSPrimary != NULL) // プライマリ・サーフェイス { g_pDDSPrimary->Release(); g_pDDSPrimary = NULL; } g_pDD->Release(); // DirectDrawオブジェクト g_pDD = NULL; } }ここまでで、DirectDrawオブジェクトの生成、開放を行う関数が作成できた。しかし、これらの関数を使う処理はまだ組み込んでいない。
関数を作っただけでは実行されないので、各関数を適切な場所で実行するようプロうグラムをさらに修正する。
- ウィンドウの生成後にInitializeDraw関数を実行するようWinMain関数を修正する。InitApp関数を実行している場所の下に、以下のプログラムを追加する。
/* Direct Draw Object の初期化 */
if (InitializeDraw(hWnd) != DD_OK) return FALSE;- ウィンドウを終了するときにDirectDrawオブジェクトを開放するようWinProc関数を修正する。
case WM_DESTROY: // 閉じるボタンをクリックした時ReleaseDraw();PostQuitMessage(0); // WM_QUITメッセージを発行 break;ここまでで、DirectDrawオブジェクトの生成、開放を行うようになった。
また、フルスクリーンでゲームをする場合、Windows標準のマウスカーソルを消す必要があるため、WinProc関数に以下のプログラムを追加する。
case WM_SETCURSOR: // カーソルの設定 SetCursor(NULL); break;
ついにビルド&実行するときが来ました。しかし、ビルドの前に
DirectDraw関係のライブラリを使用できるよう、プロジェクトの設定を変更しなければならないので、次のように設定する。
- 「プロジェクト」→「設定」を選択
- 「リンク」タブをクリックし、「オブジェクト/ライブラリ モジュール」に以下のライブラリを追加
- ddraw.lib
- dxguid.lib
- winmm.lib
- 追加したら「OK」ボタンをクリック
この状態でビルド、実行を行うと画面が消える。(真っ黒なウインドウが表示される)
※プライマリ・サーフェイスに何も画像を送ってなく、またフリップ処理を行っていないため、ウィンドウは何も変化しない
※ウィンドウを終了させるにはESCキーまたはF12キーを押す