さて、いよいよボタンの位置変更処理を行なうことにしますが、最初の位置を決めるだけならそれほど難しいことはありません。
先ほど修正していただいた部分の b_width の前にある 0, 0, という部分を適当な値に変更していただくだけでボタンの位置は変わります。
問題なのはウインドウサイズが変更された場合ですので、今回はそちらの処理を中心に見ていこうと思います。
とりあえず以下のような処理を追加してください(最初の方の1行と case WM_SIZE から break; までの青色の部分です)。
LRESULT CALLBACK WindowProcedure(...)
{
static HWND hwndButton = 0;
static int b_width, b_height;
RECT rc;
switch (message)
{
case WM_CREATE:
b_width = 200;
b_height = 50;
hwndButton = CreateWindow("button", "Click Here",
WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON,
0, 0, b_width, b_height, hwnd, (HMENU)1,
((LPCREATESTRUCT)lParam)->hInstance, NULL);
return 0;
break;
case WM_SIZE:
if (hwndButton &&
(wParam == SIZEFULLSCREEN ||
wParam == SIZENORMAL)
) {
rc.left = (LOWORD(lParam) - b_width) / 2;
rc.top = (HIWORD(lParam) - b_height) / 2;
MoveWindow(hwndButton, rc.left, rc.top,
b_width, b_height, TRUE);
}
break;
case WM_COMMAND:
if (LOWORD(wParam) == 1 &&
:
}
return 0;
}
|
変更できたらコンパイル( Execute -> Compile )をして、タイプミスなどによるエラーがなければ実行( >> Execute << ボタンをクリック)してみてください。
今までと違ってボタンがウインドウの真ん中に表示されていませんか?さらにウインドウの縁をつかんでサイズを変更してみてください。サイズの変更に合わせてボタンの位置が変わると思います。
【起動直後、ボタンが真ん中にあります。】
【ウインドウサイズを変更しても、ボタンは真ん中にいます。】
と言うことで、期待通りの動きをするようになりました(嬉)。
さて、一体何がどうなっているのかを見ていくことにしましょうか。
まず、ウインドウサイズが変更された場合に発生するイベントです。これはもう見ていただければ分かると思いますが、WM_SIZE というものが発生しています。
よって、WM_SIZE が発生した時に必要な処理を行なえばいいわけです。
重要なのは rc.left から始まる3行(画面上では3行目が折り返しているために4行となってますが)です。
まず最初の2行でボタンの位置をウインドウの真ん中になるように決定しています。 ボタンの位置というのはボタンの左上の場所を指定することで決定されます。
例えば、幅が 100 のウインドウの真ん中に幅が 60 のボタンを置きたい場合、ボタンの左上の位置はどこになるでしょう?
全体の幅が 100 あって、そのうちボタンで使用されるのが 60 ですから、余白の部分は 100 - 60 で 40 となりますね。ボタンを真ん中に置くためには、この余白を半分に分けた場所、すなわち 40 / 2 で 20 の場所にすれば良いということになります。
もちろん、高さの場合でも考え方は同じですね。全体の長さから自分が使う分を引いて、残った長さを半分にすれば真ん中に配置できるというわけです。
LOWORD(lParam) がウインドウの幅、b_width がボタンの幅、HIWORD(lParam) がウインドウの高さ、b_height がボタンの高さを示しますので、追加していただいたような計算式となります。
この辺りは第5回でも軽く説明しましたが、実のところ私もまだ完全に理解できてなかったりします(汗)。
そして表示すべきボタンの座標が決まったところで、ボタンを移動させます。
移動させるために使用するのが MoveWindow() という関数で、第1引数が移動させたいウインドウ、第2、3引数が座標(X座標、Y座標)、第3、4引数がサイズ(幅、高さ)となっています。最後は現状では TRUE にするものだと思ってください。
こうして無事にボタンが真ん中に表示されるようになりました。
でも1つだけ気になることがあります。まだウインドウサイズを変更していない起動直後でもボタンがちゃんと真ん中にいますね( CreateWindow() の引数は 0, 0, のままなのに)。これはなぜでしょう?
理由は簡単で、ウインドウが作成された瞬間に設定された大きさにウインドウが自動的にサイズ変更されているのです。
ですので、起動直後にも WM_SIZE が発行されて、ボタンの位置が調整されるというわけです。
と言うことで、3回に分けてウインドウの上にボタンをつけるという処理について見てきました。ウインドウ操作の本当に基本的な部分は押さえられたかなと思っています。
しかしながら、お世辞にも使えるアプリケーションとは思えないのも事実です(笑)。
ですので、次回からはもう少しは役に立つ(?)アプリケーションを考えてみたいと思っています(しかも、できるだけ難しいことをせずに済むもので)。
しばらくネタを考えますので、おそらく来月はお休みすることになると思いま〜す。ごめんなさいね。
|