2012年7月アーカイブ

ウィンドウサイズを設定する

| コメント(0) | トラックバック(0)   このエントリーをはてなブックマークに追加 このエントリーを含むはてなブックマーク

前回作成したウィンドウだが、
ゲームの場合は、背景画像が固定サイズなので、ウィンドウサイズを設定する必要がある。
(小さなチップ画像を組み合わせて背景を作成するなら、その必要はない)

今回は、背景画像のサイズを800×600とする。
スマートフォン向けアプリを作るならもっと小さいサイズを検討せねばなるまいが、
PC用のWindowsアプリを作成するなら、この程度のサイズが要るだろう。

まず、ウィンドウのサイズを800×600にするといっても、
以前作成したプログラムのCreateWindow関数の引数320, 240を変えればよいというわけではない。
800×600というのは、ウィンドウのクライアント領域(内容を表示する領域)のサイズなので、
実際のウィンドウサイズは、これにタイトルバーやウィンドウエッジが含まれたサイズとなる。

clientwindowsize.png

ウィンドウサイズを設定するには、SetWindowPos関数を呼ぶ。
第1引数にウィンドウハンドル、
第2引数にZオーダー(ウィンドウが重なる場合に表示される順)を指定するためのウィンドウハンドル
第3引数にディスプレイの表示位置(左端からのピクセル数)、
第4引数にディスプレイの表示位置(上端からのピクセル数)、
第5引数にウィンドウの幅、
第6引数にウィンドウの高さ、
第7引数にウィンドウ位置のオプションを指定する。

クライアント領域を設定するところがどこにもないじゃないか、
と、途方に暮れる前に、まず現在のウィンドウから、
タイトルバーやウィンドウエッジの部分のサイズを取得することにしよう。
設定するクライアント領域のサイズに、これらのサイズを加えれば、設定したいウィンドウサイズになる。

タイトルバーやウィンドウエッジの部分のサイズを取得する最も楽な方法は、
現在のウィンドウサイズから、現在のクライアント領域のサイズを引けばよい。

現在のウィンドウサイズはGetWindowRect関数、
現在のクライアント領域のサイズはGetClientRect関数で取得できる。
いずれの関数も、第1引数はウィンドウハンドルで、第2引数はRECT構造体だ。

CreateWindow関数の後に、次のようなコードを追加しよう。

RECT rx; //ウィンドウ領域
RECT cx; //クライアント領域
GetWindowRect(hWnd, &rx);
GetClientRect(hWnd, &cx);

これでそれぞれのRECT構造体に左端(left)、上端(top)、右端(right)、下端(bottom)が入る。
それを踏まえて、新しいウィンドウサイズは、次のように指定することになる。

const int new_width = 800 + (rx.right - rx.left) - (cx.right - cx.left);
const int new_height = 600 + (rx.bottom - rx.top) - (cx.bottom - cx.top);

幅new_widthについては、
rx.right - rx.leftはウィンドウの幅を表し、
cx.right - cx.leftはクライアント領域の幅を表す。
上から下を引けば、ウィンドウエッジのサイズとなるから、これに設定したいクライアント領域の幅を足せばよい。

それでは、SetWindowPos関数を呼んでみよう。

SetWindowPos(hWnd, NULL, 0, 0, new_width, new_height, SWP_SHOWWINDOW);

コンパイルして実行したら、クライアントサイズが800×600のウィンドウが表示されたはず。

しかし気になるのは、必ずディスプレイの左上にウィンドウが表示されることだ。
できればディスプレイの中央に表示するようにしたい。

表示位置は、先のSetWindowPos関数の第3,4引数で指定すればよいのだが、
その値はどのように取得すればよいだろうか。

これにはまずディスプレイのサイズを取得する必要がある。
次のように、GetSystemMetrics関数で取得する。
SetWindowPos関数の前に追加しよう。

const int disp_width = GetSystemMetrics(SM_CXSCREEN);
const int disp_height = GetSystemMetrics(SM_CYSCREEN);

横方向は、(ディスプレイの幅-ウィンドウの幅)/2、
縦方向は、(ディスプレイの高さ-ウィンドウの高さ)/2
とすると、ウィンドウが画面の中央に表示される。

では改めてSetWindowPos関数を呼んでみよう。

SetWindowPos(hWnd, NULL, (disp_width - new_width) / 2, (disp_height - new_height) / 2,
             new_width, new_height, SWP_SHOWWINDOW);

今度はディスプレイの中央に表示された。

最後に。
最近のPCのディスプレイは従来のような4:3のサイズ比ではなく、16:9のサイズ比が多いようだ。
もしも実行環境が16:9のサイズ比であっても、ウィンドウそのものは4:3で構わないのだが、
もしフルスクリーン化することを考えるなら、ウィンドウを16:9のサイズで作成し
4:3のサイズからはみ出る両端部分を
黒帯(や見栄えのよい画像)で埋めることも考えなければならないだろう。