落書きノート

ふと自分が気になった事を書いてます

C/C++ WinAPI DirectX9 クライアント領域の計算

DirectXの積み本を消化しようと思って読んでいます。バージョンが9のため、少々古い情報となりますが、このバージョンも未だに現役で使われています。

まずはサンプルコードでビルド出来るかどうかを確認していました。ちょっと端折って書きます。

今回検証したのはVisual Studio 2015 Community Edition(Visual C++)とDirectX9 SDK(June 2010)の組み合わせです。とりあえず2つともインストールしてIDEで設定していきます。プロジェクトのプロパティで設定していきます。VC++ディレクトリにDirectX SDKのインクルードパスとライブラリパスを追加していきます。インクルードパスは分かると思いますが、ライブラリパスはx64版とx86版に分かれていると思います。ここではx86版を試しましたのでx86のライブラリパスを追加します。続いてリンカの設定です。以下のライブラリファイルを追加します。

  • dsound.lib
  • dinput8.lib
  • DxErr.lib
  • d3dx9.lib
  • d3d9.lib
  • d3dxof.lib
  • dxguid.lib

個人的に注意したことは、dxerr9.libがJune 2010には含まれていません。代わりにDxErr.libがあるのでこれを使いました。後設定することは、文字セットを「マルチバイト文字セットを利用する」に変更します。後はサンプルコードをビルドして成功すれば設定ができています。

まだ本は最初の方ぐらいしか読んでいないので、クライアント領域の計算から書いていきます。

#define CLIENT_WIDTH    640
#define    CLIENT_HEIGHT   480

[...]

RECT rect;
int ww, wh;
int cw, ch;

GetClientRect(hWnd, &rect);     
cw = rect.right - rect.left;    
ch = rect.bottom - rect.top;    

GetWindowRect(hWnd, &rect);     
ww = rect.right - rect.left;    
wh = rect.bottom - rect.top;    
ww = ww - cw;                   
wh = wh - ch;                   

ww = CLIENT_WIDTH + ww;
wh = CLIENT_HEIGHT + wh;

SetWindowPos(hWnd, HWND_TOP, 0, 0, ww, wh, SWP_NOMOVE);

[...]

とりあえずはCreateWindow関数でウィンドウを生成します。最初のサイズはデタラメです。クライアントサイズは640x480を指定したいとします。これだけでは目的のウィンドウサイズが得られません。タイトルバーやウィンドウ枠の分も計算しないと目的のサイズにならないからです。

Rect構造体と適当なint型の変数を用意します。そして、GetClientRect関数で、クライアント部分のサイズを取得します。hWndというウィンドウハンドルを指定し、rectにそれぞれの座標を格納しています。rect.right - rect.leftで、クライアント領域の横幅を算出します。rect.bottom - rect.topでクライアント領域の縦幅を算出します。

ここでふと思いましたが、クライアント領域というのは今回で言う、DirectXを使ってグラフィックを描画するための領域を言います。ここがわからない人もいるかもしれませんね。迂闊でした。

GetWindowRect関数でウィンドウ全体のサイズを取得します。rect.right - rect.leftでウィンドウ全体の横幅を計算します。rect.bottom - rect.topでウインドウ全体の縦幅を計算します。ww = ww - cwで、ウィンドウ全体の横幅からクライアント領域の横幅を引きます。同様にwh - chでウィンドウ全体の縦幅からクライアント領域の縦幅を引きます。そして指定したサイズ640x480にそれぞれの差を足し算します。SetWindowPos関数で計算したサイズを指定し、ShowWindow関数でウィンドウを表示しています。ちなみに、WM_PAINTが呼ばれないようにするためにValidateRect関数も使います。

裏ではどういう数値でやり取りされているのかが気になりますね。デバッグ用のコードが必要ですね。printf関数が使えれば簡単ですが、使えないので、sprintf_s関数とSetWindowText関数を使います。以下のようにコードを挿入します。

char buffer[1000];

GetClientRect(hWnd, &rect);     
sprintf_s(buffer, "left:%d right:%d top:%d bottom:%d", rect.left, rect.right, rect.top, rect.bottom);
SetWindowText(hWnd, buffer);
cw = rect.right - rect.left;    
ch = rect.bottom - rect.top;

20160416212127

タイトルバーに値が表示されてますね。ここで値が確認出来ます。クライアント部分のサイズを取得している時の値は、rect.leftが0,rect.rightが1424,rect.topが0,rect.bottomが720。ウィンドウ全体のサイズを取得している時の値は、rect.leftが26,rect.rightが1466,rect.topが26,rect.bottomが785。

これで大体お分かりになると思います。さて、休憩して続きをやるなり違う本を読むなりするとします。

*盛大に誤ったことを書いたので修正しておきました。ついでに分かりやすく書いたつもりです。