[HMC]年間5250円で独自ドメイン付属、ウィルスチェックありのレンタルサーバ!
Last update : 1999/08/16
DirectDraw基礎 第7回
ビットマップをサーフェイス上に読み込む
サンプルコードのダウンロード
  では、まずサンプルコードをダウンロードし、解凍して下さい。 私はVisual C++6.0でコンパイルしているので、をお持ちの方は Visual C++でプロジェクトファイルを開いて下さい(「ddraw_07.dsw」をダブルクリックすれば開けます)。 圧縮ファイルに含まれる「ddraw_07.exe」をダブルクリックし、実行してみて下さい。どうでしょう?画面が切り替わり、フルスクリーン化し、 がフロントバッファに読み込まれると思います。
  というわけで、今回は256色のビットマップ形式(*.bmp)をサーフェイスを読み込みたいと思います。
パレット設定
  さて、256色のビットマップを正確に表示するためには、まずビットマップファイルが持つパレットを読み込む必要があります。 これをサボると、ビットマップの色がバケてしまいますからね。
  ちなみに、256色の場合は、パレットが256個あり、サーフェイスの1ドット1ドットは表示しているパレット番号(色)を記憶しているだけです。これはビットマップ画像(*.bmp)も同じ構造です。

であ、よく解らない解説いってみよう!
  では、解説・・・って言っても見てわかりませんかねぇ?(爆)。私が解析したトコロ、BMP形式はパレット情報が0x36番地から格納されているので fseekで読み込む位置をずらし、順番に青、緑、赤と読み込んでいます。256個読み込んだらlpPalette->SetEntries(0,0,256,peEntry);を実行して DirectDrawのパレットを全て変更します(と言っても0、255番は変更できませんが・・・)。ちなみにlpPalette->SetEntries(0,1,254,&peEntry[1]);でも良いでしょう(未確認)。

  それと言っておきたい事は、これらの方法は1例にしか過ぎないという事です。私もGDIはよく解らないので(というかよく解らない関数が多いので) 適当にプログラムを組んでいます。GDIに詳しい方ならもっと良い方法を知っているでしょう。そういう場合は私にメール下さい(爆。
ビットマップ読み込み
  ちうわけで、パレットの設定が終わったら、画像データ(?)を読み込みます。パレットと同じようにデータを解析して適当に表示しても良いのですが 、便利そうなシステムサービス関数を見つけたので今回はこれを使用してみました。
  んー、面倒ですが仕方ない(謎)のでちゃちゃっと説明しちゃいますね。

まず、最初のLoadImage関数、ここではビットマップファイルをメモリ内に読み込むといった処理をしています。

書式HANDLE LoadImage( HINSTANCE hinst, LPCTSTR lpszName , UINT uType , int cxDesired , int cyDesired , UINT fuLoad );
hinstイメージが格納されているアプリケーションのインスタンスを認識するハンドル。
そもそもこの関数はリソースと呼ばれる実行ファイル(*.EXE)に含まれるデータから読み込むものなので、関係ないからNULLぢゃ。
lpszNameファイル名
uTypeロードするイメージのタイプを指定するのですが、ビットマップを読み込むのでIMAGE_BITMAPを指定。
cxDesired横幅
cyDesired縦幅
fuLoadロード用のフラグ。今回は外部ファイルからビットマップを読み込むという事でLR_CREATEDIBSECTION | LR_LOADFROMFILEを指定。
戻り値 ロードされたイメージのハンドル

  そうしたら、次にhdcs=CreateCompatibleDC(NULL);を実行し、適当なデバイスコンテキストを作成します(戻り値:デバイスコンテキストのハンドル)。 次に、hbmpold=SelectObject(hdcs,hbmp);を実行し、デバイスコンテキストに先ほど読み込んだビットマップを選択させます(戻り値:選択前のオブジェクト)。これでビットマップが読み込まれているデバイスコンテキストへのハンドルが取得できた事になります。よくわかりませんが、GDIはこういうものです(爆)。 まぁ、細かい事は気にせず、こうすれば良いという事を覚えてしまえばいいでしょう。

  で、第4回で記述したように、サーフェイスへのデバイスコンテキストハンドルを取得し、BitBltというGDI関数を使用してビットマップをサーフェイスに転送します。
書式BOOL BitBlt( HDC hdcDest, int nXDest , int nYDest , int nWidth, int nHeight, HDC hdcSrc, int nXSrc, int nYSrc, DWORD dwRop );
hdcDest転送先のデバイスコンテキストのハンドル
nXDest転送先の左上X座標
nYDest転送先の左上Y座標
nWidth画像の横幅
nHeight画像の縦幅
hdcSrc転送元のデバイスコンテキストのハンドル
nXSrc転送元の左上X座標
nYSrc転送元の左上Y座標
dwRop転送時のオプションのようなものだが、ここは「そっくりそのまま転送」を意味するSRCCOPYを指定。
戻り値成功するとTRUEが返ってくるらしい。

  最後に、後始末です。最初にSelectObject(hdcs,hbmpold);としていますが、これはhdcsに変更前のオブジェクトを選択していると言う事です(謎)。そうしたら DeleteDCで適当に作成したデバイスコンテキストを消去し、DeleteObjectで、メモリ内に読み込んであるビットマップを消去しています。

  だー、もうGDIはよーわからん(^^;こんなんだからMS-DOSからWindowsになかなか移行できんプログラマが多いのだよ・・・。今回は(も?)カット&ペーストでそのまま使用して下さい(逝)。