WisdomSoft - for your serial experiences.

アプリケーションの起動

Windows デスクトップアプリケーションの起動ポイントである WinMain() 関数の概要を解説し、何も実行しない空のプログラムを作成します。

WinMain() 関数

標準 C に準拠した関数だけを用いたコンソールアプリケーションを開発する場合は、必ず main() 関数からプログラムが始まり、main() 関数の終了がプログラムの終了を表しました。このようなプログラムの開始位置のことをアプリケーションエントリポイントと呼びます。アプリケーションエントリポイントを呼び出すのはオペレーティングシステムである Windows の役割となります。

ところが、Windows アプリケーションの場合は main() 関数を使いません。Windows は main() 関数の代わりに WinMain() 関数をアプリケーションエントリポイントとして定めています。この関数は、次のように宣言されなければなりません。

WinMain() 関数
int WINAPI WinMain(
  HINSTANCE hInstance,      // 現在のインスタンスのハンドル
  HINSTANCE hPrevInstance,  // 以前のインスタンスのハンドル
  LPSTR lpCmdLine,          // コマンドライン
  int nCmdShow              // 表示状態
);

WINAPI、HINSTANCE、LPSTR と、見慣れない識別子が存在します。最初は戸惑うかもしれませんが、Windows プログラムにはこのような新しい型やマクロが大量に定義されています。

WINAPI は関数の呼び出し規約を定める Microsoft 固有の仕様です。通常は __stdcall キーワードを表すマクロとして割り当てられています。__stdcall キーワードは関数の呼び出し規約を表します。呼び出し規約とは、関数を呼び出すときに引数をどのように渡すかなどの決まりごとのことです。具体的にはマシンコードの話になるため、引数の引き渡して順などについて知る必要はありません。Win32 API の呼び出し規約は WINAPI として定められているため、システムからコールバックされる関数などを宣言する場合は WINAPI を指定しなければならないということを知っておけばよいでしょう。WinMain() 関数もまた、システムから呼び出される関数なので WINAPI を必ず指定します。

次に WinMain() 関数の仮パラメータを見てみましょう。hInstance パラメータと hPrevInstance パラメータは HINSTANCE という型です。HINSTANCE はインスタンスハンドルと呼ばれる情報で、アプリケーションそのものを表すユニークな値を表しています。この値は Windows API の一部の関数を利用するために必要な情報となります。

hInstance パラメータには、WinMain() 関数を実行している、このアプリケーションそのものを表すインスタンスハンドルが格納されています。この値は、ウィンドウを生成したりするときに必要です。hPrevInstance パラメータは常に NULL が格納されます。このパラメータは 16 ビット Windows 時代に使われていたもので、Win32 API では利用することはありません。

LPSTR 型は、文字列へのポインタを表します。lpCmdLine パラメータには、コマンドライン引数として渡された NULL で終わる文字列へのポインタが格納されています。

最後の nCmdShow パラメータにはウィンドウをどのように表示するべきかを指定した値が格納されています。ただし、アプリケーションが必ずしもこの値に従う必要はありません。ウィンドウをどのように表示するかを指定する値は SW_ から始まる定数として定義されています。まだ、ウィンドウを作成する方法を解説していないので、このパラメータの詳細は口述します。

では、さっそく WinMain() 関数を記述した何もしない Windows アプリケーションを作ってみましょう。Windows API を呼び出したり、Windows 用のマクロなどを用いる場合は、必ずプログラムの前に windows.h ヘッダファイルをインクルードします。windows.h ヘッダファイルは、基本的な Win32 API を参照するヘッダファイルをインクルードしています。

コード1
#include <windows.h>

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
	return 0;
}

コード1は何もしないで終了する最も単純なプログラムです。この状態ではウィンドウを作成する作業を何も行っていないため、プログラムを実行してもすぐに return 文で終了してしまいます。このコードをコンパイルして main() 関数が存在しないことによるエラーが発生した場合、Windows 用の設定なっていない可能性があります。前述した「プロジェクトの作成」に従ってプロジェクトを用意してください。