バイナリリソースの追加

Windowsの実行ファイルやDLLには、プログラムのコードの他に任意のデータを「リソース」として追加することができます。リソースを使うと各種アイコンやビットマップ、メニュー、文字列などさまざまなデータを一つの実行ファイルにまとめられるので、配布やプログラムのコピーが楽になるという利点があります。
Visual C++など最近のビジュアルなプログラミング環境では、アイコンやメニューのリソースを作る場合もちょっとした設定で自動的に作ってくれるのですが、今回は独自形式のバイナリイメージをリソースとして実行ファイルに統合し、プログラムからそのリソースを読み込んでみましょう。この方法を使うと、画像やサウンド、あるいはゲームのマップやイベントデータなどどんなデータでもリソースとして扱えることになります(画像に関しては、ビットマップリソースを扱うAPIもあります。ただ、24ビットのBMPから32ビットのDIBを作る、といった場面では自分で読み込んだ方がよいでしょう)。

実行ファイルへのリソース追加

実行ファイルにリソースを入れるのは簡単で、リソース化するデータを収めたデータファイルとそのデータに名前を付けて実行ファイルにリンクするための設定ファイル(リソーススクリプト/RCファイル)を用意し、コンパイル・リンクするだけです。今回は、test.wavというサウンドファイルの内容をTESTDATAという名前でリソースにすることにしました。この場合、test.wavのバイナリイメージをリソースTESTDATAとして実行ファイルに追加するためのリソーススクリプトは、以下のようになります。

TESTDATA                 WAV_DAT DISCARDABLE     "test.wav"

なお、WAV_DATというのは、リソースのデータ形式です。ここにデータの形式をあらわす文字列を設定しておくと、VC++などのリソースエディタでその文字列をもとにデータをグループ化できるので、管理が楽になるでしょう。

リソーススクリプトができたら、コンパイル後実行ファイルにリンクします。BC++の場合は、リソースコンパイラbcr32を使って

bcr32 リソーススクリプトファイル名 実行ファイル名

とするとリソースが作成され、実行ファイルにリンクされます。VC++の場合は、プロジェクトにリソーススクリプトファイルを追加してビルドすると、実行ファイルにリソースが追加されます。いずれも、リソーススクリプトとリソースとして読み込むデータファイルを同じディレクトリに入れておいてください。

実行ファイル内リソースからのデータ読み込み

このようにして実行ファイルに追加したリソースのデータは、プログラムから簡単に読み込むことができます。具体的な手順は、

  1. FindResource()でリソースの名前を指定し、リソースのハンドルを取得
  2. LoadResource()でリソースのハンドルをもとにリソースをロードし、そのメモリのハンドルを取得
  3. LockResource()で、メモリのハンドルからポインタを取得

という流れになります。今回は、サウンドファイルをリソースにしたので、以下のようにそのデータをメモリ上に読み込んで再生する処理を書いてみました。

  /* リソースからサウンドデータを読み込む */
  hTest = LoadResource(NULL, FindResource(NULL, "TESTDATA", "WAV_DAT"));

  /* 読み込んだデータのポインタ取得 */
  lpTest = (LPTSTR)LockResource(hTest);

  /* サウンドデータを再生 */
  sndPlaySound(lpTest, SND_SYNC | SND_MEMORY);

 これで、リソースTESTDATAをメモリlpTestに読み込んで、そのサウンドイメージを再生することができます。

プログラム

以下のrctest.c/rctest.rc、それに適当なwavファイルをtest.wavというファイル名で同じディレクトリに置いてください。VC++の場合は、そのディレクトリにWin32コンソールアプリケーションのプロジェクトを作成し、rctest.c/rctest.rcをプロジェクトに追加してビルドします。

BC++5.5.1では、まずrctest.cをコンパイルしてrctest.exeを作成し、次にリソースコンパイラbrc32rctest.exeとリソースをリンクします。

BC++のコマンドライン例

bcc32 rctest.c
brc32 rctest.rc rctest.exe

 実行すると、test.exeに追加したtest.wavのサウンドが再生されます。test.wavを削除したり、実行ファイルを他の場所に移すなどして実際にデータが実行ファイルに取り込まれていることを確認してみましょう。

======================= rctest.c ==============================
#include <windows.h>

/* VC++では、このコメントをはずす
#pragma comment(lib, "winmm.lib")
*/

int main() {

	HANDLE hTest;
	LPBYTE lpTest;

	/* リソースからサウンドデータを読み込む */
	hTest = LoadResource(NULL, FindResource(NULL, "TESTDATA", "WAV_DAT"));

	/* 読み込んだデータのポインタ取得 */
	lpTest = (LPTSTR)LockResource(hTest);

	/* サウンドデータを再生 */
	sndPlaySound(lpTest, SND_SYNC | SND_MEMORY);

	return 0;

}
===============================================================

======================= rctest.rc =============================
TESTDATA                 WAV_DAT DISCARDABLE     "test.wav"
===============================================================

Windowsプログラミング実験室 > プログラミング資料庫