エントリーポイントとは
C言語またはC++言語では、ユーザープログラムの開始を必ず「main」という関数を用意しなければならない。 それをエントリーポイントと呼ぶようだ。
これは、Visual C++ においても、ほぼ同じである。 しかし、「main」はコンソールアプリ向けではある。 Widnowsのグラフィカルユーザーインターフェイスにおいては、「WinMain」がエントリーポイントになる。 ただ、Windows2000以後はOS自体が文字をUnicodeという文字対応機能で作成されており、「wWinMain」「wmain」 というエントリーポイント名で作成することになっている。 自動生成したソースコードも先頭に「w」が付く「wWinMain」となっている。 「(プロジェクト名).cpp」を開くと「wWinMain」があるはずだ。
例1 サンプルコード(抜粋)
// Win32Project3.cpp : アプリケーションのエントリ ポイントを定義します。 // #include "stdafx.h" #include "Win32Project3.h" #define MAX_LOADSTRING 100 // グローバル変数: HINSTANCE hInst; // 現在のインターフェイス WCHAR szTitle[MAX_LOADSTRING]; // タイトル バーのテキスト WCHAR szWindowClass[MAX_LOADSTRING]; // メイン ウィンドウ クラス名 // このコード モジュールに含まれる関数の宣言を転送します: ATOM MyRegisterClass(HINSTANCE hInstance); BOOL InitInstance(HINSTANCE, int); LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); INT_PTR CALLBACK About(HWND, UINT, WPARAM, LPARAM); int APIENTRY wWinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance, _In_ LPWSTR lpCmdLine, _In_ int nCmdShow) { UNREFERENCED_PARAMETER(hPrevInstance); UNREFERENCED_PARAMETER(lpCmdLine); // TODO: ここにコードを挿入してください。 ※以下略
wWinMainの引数の意味だが、OSからアプリに引き渡される情報で以下の通りとなる。
引数 | 型 | 意味 |
---|---|---|
hInstance | HINSTANCE | OSが割り当てた番号 |
hPrevInstance | HINSTANCE | 0固定。 16ビット時代の互換のため残っている。 重複起動チェックに用いられてた。 |
lpCmdLine | LPWSTR | コマンドラインやショートカットなどで、指定されたオプション文字列。 コンパイルの設定によって文字コードが変わる。 |
nCmdShow | int |
起動時のウィンドウ表示形式。
通常は、そのまま「ShowWindow」APIの第二引数に使用する。 |
いよいよプログラムの中身を見ていく。
例2 サンプルコード(抜粋)
int APIENTRY wWinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance, _In_ LPWSTR lpCmdLine, _In_ int nCmdShow) { UNREFERENCED_PARAMETER(hPrevInstance); UNREFERENCED_PARAMETER(lpCmdLine); // TODO: ここにコードを挿入してください。 // グローバル文字列を初期化しています。 LoadStringW(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING); LoadStringW(hInstance, IDC_WIN32PROJECT3, szWindowClass, MAX_LOADSTRING); MyRegisterClass(hInstance); // アプリケーションの初期化を実行します: if (!InitInstance (hInstance, nCmdShow)) { return FALSE; } HACCEL hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_WIN32PROJECT3)); MSG msg; // メイン メッセージ ループ: while (GetMessage(&msg, nullptr, 0, 0)) { if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg)) { TranslateMessage(&msg); DispatchMessage(&msg); } } return (int) msg.wParam; }
wWinMain関数は、上記「例2」の内容となる。 コードを上から見ていく。
- UNREFERENCED_PARAMETER(...);
- 行の先頭にこの記述がある。 引数は、wWinMain関数の中で使用していない引数である。 必ず書かなければならないものでもないが、コンパイルするとワーニング(警告)に扱われる。
- LoadStringW(...);
- リソースから文字列を読み込む機能である。 タイトルバーにアプリケーションの文字列を設定するために使用したり 後で出てくるクラスの文字列に使用する。 わざわざリソースに持つ必要が感じられないが、 例えば、作成したアプリを英語化する場合、リソースを書き換えるだけで、ソースコードに あまり手を入れず対応できるなどに利用されると思う。
- MyRegisterClass(hInstance);
- 後に出てくるユーザー関数。 主にOSに対しての登録を行うと思われる。
- InitInstance (hInstance, nCmdShow);
- 後に出てくるユーザー関数。 ここで、アプリの外観のウィンドウが生成と表示をおこなう。
- LoadAccelerators(...);
- おそらく、キーボード操作におけるショートカットキーの設定をリソースから読み込むものと思われる。 このアプリの場合、「alt」+「/」、「alt」+「?」の操作でバージョン情報のダイアログが表示できる。 後で説明するTranslateAccelerator関数で使用される。
- GetMessage(&msg, nullptr, 0, 0)
- メッセージを受け取る関数。 WindowsではマルチタスクとGUIを実現するためにOSからメッセージというものを各アプリに 送ることによって実現している。 OSから自アプリに必要なメッセージが送られてくるまでここで止まる格好になる。
- TranslateAccelerator(msg.hwnd, hAccelTable, &msg)
- ショートカットキーをメニューに対応させる処理を行う。
- TranslateMessage(&msg);
- 仮想キーメッセージを文字メッセージに変換する。
- DispatchMessage(&msg);
- おそらく、後で説明するユーザー関数「WndProc」にGetMessageで取得したメッセージを引き渡す。
- return (int) msg.wParam;
- OSに処理結果を返す。 返しても何も意味はないが、バッチファイルのErrorLevel、子プロセスの戻り値に使えると思われる。