サンプルコードのダウンロード

では、まずサンプルコードをダウンロードし、解凍してください。
私はVisual C++6.0でコンパイルしているので、お持ちの方はVisual C++でプロジェクトファイルを開いてください(「ddraw_11.dsw」をダブルクリックすれば開けます)。
圧縮ファイルに含まれる「ddraw_11.exe」をダブルクリックし、実行してみてください。
どうでしょう?画面が切り替わり、フルスクリーン化し、SLIME(?)と書かれた画像がタイル状に敷き詰められ、どんどん小さくなりながら左上へスクロールするのが解ると思います。

というわけで今回は、DirectDraw側で画像転送時にクリッピングしたいと思います。

DirectDrawクリッパー

DirectDrawにクリッピングをさせるには、DirectDrawクリッパーというものを使用します。
クリッパー作成は、自作関数「StartDirectDraw」内に追加してあります。

//グローバル変数宣言
LPDIRECTDRAWCLIPPER lpClipper=NULL;	//クリッパーオブジェクト

略

	//クリッパーの設定
	if(lpDD->CreateClipper(0,&lpClipper,NULL)!=DD_OK)
		return FALSE;
	if(lpClipper->SetHWnd(0,hw)!=DD_OK)
		return FALSE;
	if(lpBack->SetClipper(lpClipper)!=DD_OK)
		return FALSE;

意外とソースは短いですかねぇ(^^;。
では、順番に説明していきたいと思います。
まず、DirectDrawオブジェクト(lpDD)のメンバ関数である「CreateClipper」を呼び出し、DirectDrawクリッパーオブジェクトを作成します。
構文は以下の通りです。

書式 HRESULT CreateClipper( DWORD dwFlags, LPDIRECTDRAWCLIPPER FAR *lplpDDClipper, IUnknown FAR *pUnkOuter );
dwFlags このフラグは使用していないらしく、0を指定する必要があるらしい
*lplpDDClipper 新しいDirectDrawClipperオブジェクトを示すポインタへのポインタ。
例によって、LPDIRECTDRAWCLIPPER型自体がポインタ型になっているので、「ポインタへのポインタ」と言っています(たぶん)。
*pUnkOuter 将来拡張のために使用するらしいので今はNULLを指定。
戻り値 成功した場合はDD_OKが返ってくるらしい。

これで、DirectDrawClipperオブジェクトが出来ました。
で次にこいつのメンバ関数である「SetHWnd」を呼び出します。
これは、クリッピング範囲をウィンドウハンドルを参照して設定するというものです。
つまり、プライマリサーフェイスと同じ範囲に設定されるわけです。

というわけで、構文。

書式 HRESULT SetHWnd( DWORD dwFlags, HWND hWnd );
dwFlags このフラグは使用していないらしく、0を指定する必要があるらしい
hWnd クリッピング情報を含むウィンドウ ハンドル
戻り値 成功した場合はDD_OKが返ってくるらしい。

これで、クリッピング範囲を設定し終えたら、次にサーフェイスのメンバ関数である「SetClipper」を呼び出します。
SetClipperによってサーフェイスへクリッパーを関連付けさせれば、そのサーフェイスに対し、クリッピングが可能となります。
一応構文も載せておきます。

書式 HRESULT SetClipper( LPDIRECTDRAWCLIPPER lpDDClipper );
lpDDClipper 関連づけさせるクリッパー。ここを0にしてやると、今まで関連付けられていたクリッパーが外されるらしい(未確認)。
hWnd クリッピング情報を含むウィンドウ ハンドル
戻り値 成功した場合はDD_OKが返ってくるらしい。

設定は以上です。
このクリッパーは、関連付けさせたサーフェイスへ、サーフェイスのメンバ関数「Blt」(自作関数の方では無いので注意してください)で転送した場合にのみ有効となります。
それと、クリッパーが関連づけさせられているサーフェイスへBltFast(自作関数Blt)による転送は出来ません。

今回は、クリッパーをバックバッファ(lpBack)に関連付けさせていますが、ここへBlt(自作関数BltStretch)による転送をしたときにだけ、クリッピングされます。
まぁ、このクリッパーによるクリッピングは私の環境では速度が遅いので使用していません。
ですから詳しいこたぁ、よくわかりましぇ~ん。

後始末

いつも通り、終了する時にはlpClipper->Release();を実行してやらなければなりません。
マクロ使用ではRELEASE(lpClipper);ですね。

記事検索

アーカイブ