ウィンドウを作成する

ボタンなどの標準コントロールや、任意の図形やイメージのようなグラフィカルなオブジェクトを画面上に表示するには、何はともあれウィンドウが必要です。一般的な Windows アプリケーションで見られるウィンドウを表示するには、ウィンドウの登録や生成が必要になります。.NET Framework や Java のような近代的なフレームワークでは数行で済む作業ですが、ネイティブの Windows API では、やや煩雑な初期化処理が求められます。

ゼロからはじめるWindows API - WinMain 関数 すべての始まり編
C言語の学習および環境の構築は下記を参考にしてください
1.ゼロからはじめるC言語 - 環境構築編
2.ゼロからはじめるC言語 - 関数編
3.ゼロからはじめるC言語 - 型・定数編
4.ゼロからはじめるC言語 - 変数編
5.ゼロからはじめるC言語 - 選択編
6.ゼロからはじめるC言語 - 繰り返し編
7.ゼロからはじめるC言語 - 配列編
8.ゼロからはじめるC言語 - 構造体編
9.ゼロからはじめるC言語 - 自作関数編
10.ゼロからはじめるC言語 - ポインタ編

新しいウィンドウを作成するには CreateWindowEx() 関数を使います。末尾の Ex から想像できるように、この関数は元となる CreateWindow() 関数を拡張してパラメータを追加したものです。追加されたパラメータを除いて、どちらの関数も使い方は同じです。新しくアプリケーションを開発する場合 CreateWindowEx() 関数を使うべきでしょう。

CreateWindowEx() 関数

HWND CreateWindowEx(
  DWORD dwExStyle,
  LPCTSTR lpClassName,
  LPCTSTR lpWindowName,
  DWORD dwStyle,
  int x,
  int y,
  int nWidth,
  int nHeight,
  HWND hWndParent,
  HMENU hMenu,
  HINSTANCE hInstance,
  LPVOID lpParam
);

パラメータ

dwExStyle WS_EX_ から始まる拡張ウィンドウスタイルを表す定数。
lpClassName ウィンドウクラスの名前、またはウィンドウクラスを表すアトム。
lpWindowName ウィンドウの名前。
dwStyle WS_ から始まるウィンドウのスタイルを表す定数
x スクリーンの左上隅を原点とする X 座標で指定する、ウィンドウを表示する水平方向の初期位置。
y スクリーンの左上隅を原点とする Y 座標で指定する、ウィンドウを表示する垂直方向の初期位置。
nWidth ウィンドウの幅。
nHeight ウィンドウの高さ。
hWndParent 親ウィンドウのハンドル。
hMenu メニューのハンドル、または子ウィンドウの ID。
hInstance ウィンドウに関連付けられるインスタンスのハンドル。
lpParam 生成するウィンドウに渡す任意のパラメータ。

戻り値

作成されたウィンドウのハンドル。失敗すると NULL。

初めてこの関数を使うとき、パラメータの多さに戸惑うかもしれません。いくつかのパラメータは NULL で省略可能なので、まずは重要なパラメータの意味を理解すれば十分です。

dwExStyle パラメータと dwStyle パラメータは、ウィンドウの外観や性質などを決定するスタイルを指定します。ウィンドウのタイトルバーや「最大化」ボタン、「最小化」ボタン、「閉じる」ボタンなどを表示するかどうかは、このスタイルによって設定できます。

lpClassName パラメータは、ウィンドウクラスと呼ばれるウィンドウの動作を定めた設定を指定します。Windows によって提供される定義済みのシステムクラスも用意されていますが、アプリケーションが独自のウィンドウを作成するには、事前にウィンドウクラスを登録する必要があります。

x パラメータと y パラメータは、ウィンドウの初期座標を設定します。x パラメータに CW_USEDEFAULT 定数を指定すると、ウィンドウの初期位置はシステムによって調整される既定の位置に設定されます。

nWidth パラメータと nHeight パラメータは、ウィンドウの幅と高さを設定します。nWidth パラメータに CW_USEDEFAULT 定数を指定すると既定のサイズが適用されます。

生成するウィンドウが子ウィンドウである場合、hWndParent パラメータに親ウィンドウを設定します。生成するウィンドウがトップレベルのウィンドウであるならば NULL を指定してください。

hMenu パラメータは、ウィンドウのスタイルによって設定する値が変化します。通常のウィンドウの場合、このパラメータにウィンドウに表示するメニューを設定できます。作成するウィンドウが子ウィンドウである場合、子ウィンドウを識別するための ID を指定できます。通常のウィンドウでメニューを作成しない場合は NULL を指定してください。

hInstance パラメータには、通常は WinMain() 関数の第 1 パラメータで受けたインスタンスハンドルを指定します。このパラメータは、Windows 9x 系で使われていたもので、NT 系では無視されます。

最後の lpParam パラメータは、生成したウィンドウが受け取る任意の値です。利用しない場合は NULL を渡せばよいでしょう。

CreateWindowEx() 関数は、パラメータに指定した情報から新しいウィンドウを生成します。生成されたウィンドウは、戻り値から得られる HWND 型の値によって識別できます。これをウィンドウのハンドルと呼びます。ウィンドウを制御する関数を使って、ウィンドウの状態を設定または取得するときに HWND 型の値を受け渡ししてウィンドウを識別します。現代のプログラミングで言うオブジェクトに相当するものだと考えてください。

問題は、lpClassName パラメータに指定するウィンドウクラスです。アプリケーションが独自のウィンドウを用意するには CreateWindowEx() 関数を呼び出す前に、ウィンドウクラスを作成しなければなりません。ウィンドウクラスの作成については次回に紹介するので、この場では定義済みのシステムクラスを用いてウィンドウを表示してみましょう。

サンプル 01

#include <Windows.h>

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
    HWND hWnd;

    hWnd = CreateWindowEx(
        WS_EX_LEFT, TEXT("STATIC"), TEXT("なんくるないさー"),
        WS_OVERLAPPEDWINDOW | WS_VISIBLE,
        CW_USEDEFAULT, CW_USEDEFAULT, 400, 300,
        NULL, NULL, hInstance, NULL
    );

    if (hWnd) MessageBox(hWnd, TEXT("ウィンドウが生成されました"), TEXT("確認"), MB_OK);
    else MessageBox(NULL, TEXT("ウィンドウの生成に失敗しました"), NULL, MB_OK);

    return 0;
}

実行結果

サンプル01の実行結果

このプログラムは、システムによって提供されている STATIC という名前のウィンドウクラスを使って新しいウィンドウを生成して表示しています。ウィンドウは、デフォルトで非表示の状態ですが WS_VISIBLE をスタイルに設定することで生成と同時に可視化できます。ウィンドウの初期位置はシステムの既定、幅と高さは整数リテラルで固定しています。

ウィンドウを表示しても、その後、制御が return 文に到達してしまうとプログラムが終了してしまいます。このサンプルでは、プログラムが終了してしまうことを防ぐために、ウィンドウの作成した後にメッセージボックスを表示してプログラムの流れを止めています。ウィンドウは、入力処理に対応していないため、移動やサイズの変更などはできません。

一般的な Windows アプリケーションのようにウィンドウを操作するには、メッセージと呼ばれるウィンドウへの入力や要求を処理するプログラムを書かなければなりません。メッセージについては、次回に解説します。