ホーム < ゲームつくろー! < クラス構築編 < ファイルをメモリのように「メモリマップドファイルクラス」:サンプルプログラム


ファイルをメモリのように「メモリマップドファイルクラス」:サンプルプログラム


 『ファイルをメモリのように「メモリマップドファイルクラス」』で紹介したクラスを踏まえたサンプルプログラムです。実行するとメモリにマップされたファイルポインタを通してD3DXCreateTextureFromFileInMemory関数によりテクスチャを作成します。テクスチャの作成に成功するとメッセージボックスが出現してそれを知らせます。ただそれだけのプログラムなのですが、メモリマップドファイルの有用性がわかると思います。

 以下のクラスをコピペするか、こちらからクラスをダウンロード(MemMapFile.lzh)して下さい。ルートに「Test.bmp」という名前のファイルを用意し(ダウンロードファイル中にありますが、同名のビットマップファイルなら何でも結構です)、一番下に示しましたメイン関数を空のプロジェクトにコピペし、パスの通った場所にMemMapFile.h及びMemMapFile.cppを置き、プロジェクトにそれらを追加する事で完全に動きます。尚、このプログラムはUnicode環境では動きません。マルチバイト環境でお試し下さい。

(注意 : 以下のクラスはテストしておりますが、各自の責任を持ってお試し下さい。うまく動かない場合は掲示板にてご報告頂けますと助かります(^-^;)

CMemMapFileクラス宣言部 (MemMapFile.h)
// メモリマップドファイルクラス宣言部
#pragma once

#include <windows.h>

///////////////////////////////////
// メモリマップドファイルクラス
///////////
class CMemMapFile
{
   protected:
   HANDLE m_hFile;
   HANDLE m_hMap;
   void* m_pPointer;
   DWORD m_dwFileSize;

   public:
   CMemMapFile();
   virtual ~CMemMapFile();

   // ファイルオープン
   virtual bool Open( char* filename, DWORD rwflag=GENERIC_READ | GENERIC_WRITE, DWORD openflag=OPEN_EXISTING);

   // ファイルポインタ取得
   virtual bool GetPtr( void** ptr , char* subfilename=NULL, DWORD *pfilesize=NULL );
};
CMemMapFileクラス実装部 (MemMapFile.cpp)
// MemMapFile.cpp (2006. 10. 13)

#include "MemMapFile.h"


// メモリマップドファイル実装部

CMemMapFile::CMemMapFile()
{
   m_hFile = INVALID_HANDLE_VALUE;
   m_hMap = 0;
   m_pPointer = NULL;
   m_dwFileSize = 0;
}


CMemMapFile::~CMemMapFile()
{
   UnmapViewOfFile( m_pPointer );
   if( m_hMap != 0 )
   CloseHandle( m_hMap );
   if( m_hFile != INVALID_HANDLE_VALUE )
   CloseHandle( m_hFile );
}

// ファイルオープン
bool CMemMapFile::Open( char* filename, DWORD rwflag, DWORD openflag)
{
   // ファイルオープン
   m_hFile = CreateFile( filename, rwflag, 0, 0, openflag, 0, 0 );
   if( m_hFile == INVALID_HANDLE_VALUE )
      return false;

   // ファイルマッピングオブジェクトを作成
   DWORD mapflag = PAGE_READWRITE;
   if( rwflag == GENERIC_READ )
   mapflag = PAGE_READONLY; // 読み込み専用に設定
   m_hMap = CreateFileMapping( m_hFile, 0, mapflag, 0, 0, filename );
   if( m_hMap <= 0 ){
      CloseHandle( m_hFile );
      m_hFile = INVALID_HANDLE_VALUE;
      return false;
   }

   // ポインタを取得
   DWORD mapviewflag = FILE_MAP_WRITE;
   if( mapflag == PAGE_READONLY )
      mapviewflag = FILE_MAP_READ;
   m_pPointer = (char*)MapViewOfFile( m_hMap, mapviewflag, 0, 0, 0);
   if( m_pPointer == NULL){
      CloseHandle( m_hMap );
      CloseHandle( m_hFile );
      m_hMap = 0;
      m_hFile = INVALID_HANDLE_VALUE;
   return false;
   }

   // ファイルサイズを取得
   DWORD high;
   m_dwFileSize = ::GetFileSize( m_hFile, &high );

   return true;
}


// ファイルポインタ取得
bool CMemMapFile::GetPtr( void** ptr, char* subfilename, DWORD *pfilesize )
{
   *ptr = m_pPointer;
   if(pfilesize != NULL)
      *pfilesize = m_dwFileSize; // 全ファイルサイズを返す
   return true;
}

メイン (main.cpp)
/// メモリマップドファイルからテクスチャ取得テスト

#pragma comment(lib, "dxguid.lib")
#pragma comment(lib, "d3d9.lib")
#pragma comment(lib, "d3dx9.lib")

#include <windows.h>
#include <tchar.h>
#include <d3d9.h>
#include <d3dx9.h>
#include "MemMapFile.h"


TCHAR gName[100] = _T("メモリマップドファイルからテクスチャ取得テスト");


LRESULT CALLBACK WndProc(HWND hWnd, UINT mes, WPARAM wParam, LPARAM lParam){
   if(mes == WM_DESTROY) {PostQuitMessage(0); return 0;}
   return DefWindowProc(hWnd, mes, wParam, lParam);
}

int APIENTRY _tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow)
{
   // アプリケーションの初期化
   HWND hWnd;
   WNDCLASSEX wcex ={sizeof(WNDCLASSEX), CS_HREDRAW | CS_VREDRAW, WndProc, 0, 0, hInstance, NULL, NULL,
   (HBRUSH)(COLOR_WINDOW+1), NULL, (TCHAR*)gName, NULL};
   if(!RegisterClassEx(&wcex))
      return 0;

   if(!(hWnd = CreateWindow(gName, gName, WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, 0, CW_USEDEFAULT, 0,
      NULL, NULL, hInstance, NULL)))
      return 0;

   // Direct3Dの初期化
   LPDIRECT3D9 g_pD3D;
   LPDIRECT3DDEVICE9 g_pD3DDev;
   if( !(g_pD3D = Direct3DCreate9( D3D_SDK_VERSION )) ) return 0;

   D3DPRESENT_PARAMETERS d3dpp = {0,0,D3DFMT_UNKNOWN,0,D3DMULTISAMPLE_NONE,0,
            D3DSWAPEFFECT_DISCARD,NULL,TRUE,TRUE,D3DFMT_D24S8,0,D3DPRESENT_RATE_DEFAULT,D3DPRESENT_INTERVAL_DEFAULT};

   if( FAILED( g_pD3D->CreateDevice( D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hWnd, D3DCREATE_HARDWARE_VERTEXPROCESSING, &d3dpp, &g_pD3DDev ) ) )
   if( FAILED( g_pD3D->CreateDevice( D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hWnd, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &g_pD3DDev ) ) )
   {
      g_pD3D->Release();
      return 0;
   }

   // メモリマップドファイルオブジェクトの生成
   CMemMapFile MF;
   char *ptr;
   if(!MF.Open( "Test.bmp" )){
      ::MessageBox(hWnd, "[Test.bmp]がありませんでした。Test.bmpというファイルを用意して下さい。", "ファイルがありません", 0 );
      g_pD3DDev->Release();
      g_pD3D->Release();
      return 0;
   }

   // ファイルポインタを取得
   DWORD size;
   MF.GetPtr( (void**)&ptr, NULL, &size );

   // テクスチャをメモリから作成
   IDirect3DTexture9 *pTex = NULL;
   D3DXCreateTextureFromFileInMemory( g_pD3DDev, ptr, size, &pTex );
   if( pTex == NULL ){
      ::MessageBox(hWnd, "[Test.bmp]の読み込みに何らかの理由で失敗しました。", "読み込み失敗", 0 );
      g_pD3DDev->Release();
      g_pD3D->Release();
      return 0;
   }

   ::MessageBox(hWnd, "テクスチャの読み込みに成功しました。OKを押してプログラムを終了して下さい。", "読み込み成功", 0 );

   pTex->Release();
   g_pD3DDev->Release();
   g_pD3D->Release();

   return 0;
}