ユーザー環境にd3dx9_XX.dllがあるかどうかを調べる

http://codezine.jp/article/detail/235?p=3
DirectXには有名な問題点として、d3d9.libとd3dx9.libを静的リンクしてしまうと、該当するDLLが無かった場合アプリケーション起動時に分かりづらいダイアログが出るとともに起動失敗してしまうという問題があります。

d3dx9_27.dllが見つからなかったため、このアプリケーションを開始できませんでした。

このダイアログは、エンドユーザーからしてみると「????」といった感じの文言で、とても不親切です。
これを独自のメッセージに変える方法を紹介します。
といっても、NyaRuRuさんの記事なんですけどね!
http://codezine.jp/article/detail/235?p=3
ここのコラム8を読みましょう。
d3dx9_XX.dllの遅延ロードを行います。
 
いくつか躓きそうなポイントを載せておきますので、お役にたてばと思います。
VS2008前提です。サンプルプロジェクトは2005でした。
 
まず、サンプルソースはページの先頭付近にあります。
サンプルファイルってやつです。
最初見つけられなくて探し回りました。
 
プロジェクトのプロパティ>リンカ>入力>DLLの遅延読み込み
に、d3dx9_XX.dllを書きます。
XXの部分は、自分がリンクしているd3dx9.libに対応したバージョンのものです。
d3dx9core.h の D3DX_SDK_VERSION の数字がそれです。
 
サンプルソースでは

//リンカオプションで /DELAYLOAD:"d3dx9_27.dll" を指定する

と書かれていますが、実際はd3dx9_28.dllをチェックしています。
コメントの27は誤植ですね。
 
サンプルソースでは下記のようになっています。

	__try
	{
		D3DXMATRIX mat;
		D3DXMatrixIdentity(&mat);
		D3DXMatrixInverse(&mat, NULL, &mat);
	}
	__except ( DelayLoadDllExceptionFilter( GetExceptionInformation() ) )
	{
		return false;
	}

D3DXMatrixIdentityがあるから、D3DXMatrixInverseを省いてもいいだろ。
とやったら、期待した動作にならなくなりました。
D3DXMatrixIdentityはDLL内の関数ではなく、ヘッダで定義されてる関数だったためです。
(DLLの遅延読み込みは、DLL内の関数を呼んだ時に初めてロードされます)
そんなアホは私だけですか。そうですか。NyaRuRuさんが無駄なコード書くわけないじゃん!私の馬鹿!
素直にコピペしましょう。
 
例外処理は、それが記述されている関数内でデストラクタが呼ばれていてはならないという制限があります。
呼ばれていると、コンパイルの際に下記のようなエラーが出ます。

オブジェクト アンワインディングが必要な関数内で __try を使用できません。

なので上記のtry〜exceptの処理はbool CheckD3DX();とかそんな関数に閉じ込めてしまうと楽だと思います。
 

さて、D3DXMatrixInverseを読んで読み込みを発生させたなら、それ以降は静的リンクした時と同様になります。
よって、
http://codezine.jp/article/detail/235?p=4
で紹介されているAPIフックなどとも併用できます。

	__try
	{
		D3DXMATRIX mat;
		D3DXMatrixIdentity(&mat);
		D3DXMatrixInverse(&mat, NULL, &mat);
	}
	__except ( DelayLoadDllExceptionFilter( GetExceptionInformation() ) )
	{
		return false;
	}

	//	d3dx9_XX.dllが呼ぶ"RegQueryValueExA"をフックする。
	InitHook();

という順番でやればOK。
すいません。フックとの併用はできないようです。
 
ほんとにNyaRuRuさんはDirectX界の神やでー!