Win32 アプリケーションの作成 (C++)
このチュートリアルでは、ウィンドウに "Hello, World!" を表示する基本的な Win32 ベースのアプリケーションを作成する方法について説明します。 このチュートリアルで開発したコードは、他の Win32 ベースのアプリケーションを作成するためのパターンとして使用できます。
Win32 API (Windows API とも呼ばれます) は、Windows アプリケーションを作成するための C ベースのフレームワークです。 Win32 API の詳細については、「Windows API (Windows API)」を参照してください。
重要
このドキュメントでは、手順のコードの特定のセグメントについてさらに明確に説明するために、実際に動作するアプリケーションでは必要な一部のコード ステートメントを省略しているところがあります。たとえば、include ディレクティブや、グローバル変数宣言などです。このドキュメントの最後の「例」のセクションに、コード全体を示します。
必須コンポーネント
このチュートリアルを完了するには、C++ 言語の基本を理解している必要があります。
ビデオ デモについては、Visual Studio 2008 ドキュメントの「Video How to: Creating Win32 Applications (C++) (ビデオ デモ: Win32 アプリケーション (C++) の作成)」を参照してください。
Win32 ベースのプロジェクトを作成するには
[ファイル] メニューの [新規作成] をポイントし、[プロジェクト] をクリックします。
[新しいプロジェクト] ダイアログ ボックスで、左ペインの [インストールされたテンプレート] をクリックし、[Visual C++] をクリックして、[Win32] を選択します。 中央のペインで、[Win32 プロジェクト] を選択します。
[名前] ボックスにプロジェクトの名前を入力します。たとえば、「win32app」などです。 [OK] をクリックします。
Win32 アプリケーション ウィザードの [ようこそ] ページで、[次へ] をクリックします。
[アプリケーションの種類] の [アプリケーションの設定] ページで、[Windows アプリケーション] を選択します。 [追加のオプション] の [空のプロジェクト] を選択します。 [完了] をクリックして、プロジェクトを作成します。
ソリューション エクスプローラーで、Win32app プロジェクトを右クリックし、[追加] をクリックして、[新しい項目] をクリックします。 [新しい項目の追加] ダイアログ ボックスで、[C++ ファイル (.cpp)] をクリックします。 [名前] ボックスに、「GT_HelloWorldWin32.cpp」などファイルの名前を入力します。 [追加] をクリックします。
Win32 ベースのアプリケーションを起動するには
すべての C アプリケーションおよび C++ アプリケーションに開始点として main 関数が必要なように、すべての Win32 ベースのアプリケーションにも WinMain 関数が必要です。 WinMain の構文は、次のとおりです。
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow);
この関数のパラメーターと戻り値については、「WinMain 関数」を参照してください。
アプリケーション コードは既存の定義を使用する必要があるので、include ステートメントをファイルに追加します。
#include <windows.h> #include <stdlib.h> #include <string.h> #include <tchar.h>
WinMain 関数のほかに、すべてのWin32 ベースのアプリケーションには ウィンドウ プロシージャ関数が必要です。 この関数は通常、WndProc と呼ばれます。 WndProc の構文は、次のとおりです。
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
この関数は、アプリケーションがオペレーティング システムから受け取る多数のメッセージを処理します。 たとえば、アプリケーションに [OK] ボタンがあるダイアログ ボックスがあるとき、ユーザーがそのボタンをクリックすると、オペレーティング システムからアプリケーションに、ボタンがクリックされたというメッセージが送信されます。 WndProc は、そのイベントに対する応答を担当します。 この例では、適切な応答はダイアログ ボックスを閉じることです。
詳細については、「ウィンドウ プロシージャ」を参照してください。
WinMain 関数に機能を追加するには
WinMain 関数の中に WNDCLASSEX 型のウィンドウ クラス構造体を作成します。 この構造体には、ウィンドウに関する情報が格納されます。たとえば、アプリケーションのアイコン、ウィンドウの背景色、タイトル バーに表示する名前、ウィンドウ プロシージャ関数の名前などです。 一般的な WNDCLASSEX 構造体の例を次に示します。
WNDCLASSEX wcex; wcex.cbSize = sizeof(WNDCLASSEX); wcex.style = CS_HREDRAW | CS_VREDRAW; wcex.lpfnWndProc = WndProc; wcex.cbClsExtra = 0; wcex.cbWndExtra = 0; wcex.hInstance = hInstance; wcex.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_APPLICATION)); wcex.hCursor = LoadCursor(NULL, IDC_ARROW); wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1); wcex.lpszMenuName = NULL; wcex.lpszClassName = szWindowClass; wcex.hIconSm = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_APPLICATION));
この構造体のフィールドについては、「WNDCLASSEX」を参照してください。
これでウィンドウ クラスが作成されました。次に、登録を行う必要があります。 RegisterClassEx 関数を使用して、ウィンドウ クラス構造体を引数として渡します。
if (!RegisterClassEx(&wcex)) { MessageBox(NULL, _T("Call to RegisterClassEx failed!"), _T("Win32 Guided Tour"), NULL); return 1; }
これで、ウィンドウを作成できます。 CreateWindow 関数を使用します。
static TCHAR szWindowClass[] = _T("win32app"); static TCHAR szTitle[] = _T("Win32 Guided Tour Application"); // The parameters to CreateWindow explained: // szWindowClass: the name of the application // szTitle: the text that appears in the title bar // WS_OVERLAPPEDWINDOW: the type of window to create // CW_USEDEFAULT, CW_USEDEFAULT: initial position (x, y) // 500, 100: initial size (width, length) // NULL: the parent of this window // NULL: this application does not have a menu bar // hInstance: the first parameter from WinMain // NULL: not used in this application HWND hWnd = CreateWindow( szWindowClass, szTitle, WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, 500, 100, NULL, NULL, hInstance, NULL ); if (!hWnd) { MessageBox(NULL, _T("Call to CreateWindow failed!"), _T("Win32 Guided Tour"), NULL); return 1; }
この関数は HWND を返します。これはウィンドウのハンドルです。 詳細については、「Windows Data Types」を参照してください。
今度は、次のコードを使用してウィンドウを表示します。
// The parameters to ShowWindow explained: // hWnd: the value returned from CreateWindow // nCmdShow: the fourth parameter from WinMain ShowWindow(hWnd, nCmdShow); UpdateWindow(hWnd);
この段階では、表示されたウィンドウには多くのコンテンツがありません。まだ WndProc 関数を実装していないからです。
次に、メッセージ ループを追加して、オペレーティング システムが送信するメッセージを待機します。 アプリケーションがメッセージを受け取ると、このループはそのメッセージを処理するために WndProc 関数にディスパッチします。 メッセージ ループのコードは、次のようになります。
MSG msg; while (GetMessage(&msg, NULL, 0, 0)) { TranslateMessage(&msg); DispatchMessage(&msg); } return (int) msg.wParam;
メッセージ ループ内の構造体と関数の詳細については、「MSG」、「GetMessage」、「TranslateMessage」、および「DispatchMessage」を参照してください。
この段階では、WinMain 関数のコードは次のようになります。
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) { WNDCLASSEX wcex; wcex.cbSize = sizeof(WNDCLASSEX); wcex.style = CS_HREDRAW | CS_VREDRAW; wcex.lpfnWndProc = WndProc; wcex.cbClsExtra = 0; wcex.cbWndExtra = 0; wcex.hInstance = hInstance; wcex.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_APPLICATION)); wcex.hCursor = LoadCursor(NULL, IDC_ARROW); wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1); wcex.lpszMenuName = NULL; wcex.lpszClassName = szWindowClass; wcex.hIconSm = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_APPLICATION)); if (!RegisterClassEx(&wcex)) { MessageBox(NULL, _T("Call to RegisterClassEx failed!"), _T("Win32 Guided Tour"), NULL); return 1; } hInst = hInstance; // Store instance handle in our global variable // The parameters to CreateWindow explained: // szWindowClass: the name of the application // szTitle: the text that appears in the title bar // WS_OVERLAPPEDWINDOW: the type of window to create // CW_USEDEFAULT, CW_USEDEFAULT: initial position (x, y) // 500, 100: initial size (width, length) // NULL: the parent of this window // NULL: this application dows not have a menu bar // hInstance: the first parameter from WinMain // NULL: not used in this application HWND hWnd = CreateWindow( szWindowClass, szTitle, WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, 500, 100, NULL, NULL, hInstance, NULL ); if (!hWnd) { MessageBox(NULL, _T("Call to CreateWindow failed!"), _T("Win32 Guided Tour"), NULL); return 1; } // The parameters to ShowWindow explained: // hWnd: the value returned from CreateWindow // nCmdShow: the fourth parameter from WinMain ShowWindow(hWnd, nCmdShow); UpdateWindow(hWnd); // Main message loop: MSG msg; while (GetMessage(&msg, NULL, 0, 0)) { TranslateMessage(&msg); DispatchMessage(&msg); } return (int) msg.wParam; }
WndProc 関数に機能を追加するには
WndProc 関数を有効にしてアプリケーションが受け取るメッセージを処理するために、switch ステートメントを実装します。
最初に処理するメッセージは、WM_PAINT メッセージです。 アプリケーションは、表示しているウィンドウの一部の更新が必要になったときにこのメッセージを受け取ります (ウィンドウが初めて表示されるときには、その全体を更新する必要があります)。
WM_PAINT メッセージを処理するには、まず BeginPaint を呼び出して、ウィンドウのテキスト、ボタン、およびその他コントロールをレイアウトするためのすべてのロジックを処理し、次に EndPaint を呼び出します。 このアプリケーションの場合、最初の呼び出しと最後の呼び出しの間のロジックは、ウィンドウに "Hello, World!" という文字列を表示することです。 次のコードでは、文字列を表示するために TextOut 関数が使用されていることに注意してください。
PAINTSTRUCT ps; HDC hdc; TCHAR greeting[] = _T("Hello, World!"); switch (message) { case WM_PAINT: hdc = BeginPaint(hWnd, &ps); // Here your application is laid out. // For this introduction, we just print out "Hello, World!" // in the top left corner. TextOut(hdc, 5, 5, greeting, _tcslen(greeting)); // End application-specific layout section. EndPaint(hWnd, &ps); break; }
通常、アプリケーションは WM_CREATE、WM_DESTROY など、他にも多くのメッセージを処理します。 単純でも完成した WndProc 関数のコードを次に示します。
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { PAINTSTRUCT ps; HDC hdc; TCHAR greeting[] = _T("Hello, World!"); switch (message) { case WM_PAINT: hdc = BeginPaint(hWnd, &ps); // Here your application is laid out. // For this introduction, we just print out "Hello, World!" // in the top left corner. TextOut(hdc, 5, 5, greeting, _tcslen(greeting)); // End application specific layout section. EndPaint(hWnd, &ps); break; case WM_DESTROY: PostQuitMessage(0); break; default: return DefWindowProc(hWnd, message, wParam, lParam); break; } return 0; }
例
この例をビルドするには
このチュートリアルの前半の「Win32 ベースのプロジェクトを作成するには」で示した Win32 ベースのプロジェクトを作成します。
この説明の次に示すコードをコピーして、GT_HelloWorldWin32.cpp ソース ファイルに貼り付けます。
[ビルド] メニューの [ソリューションのビルド] をクリックします。
アプリケーションを実行するには、F5 キーを押します。 画面の左上隅にウィンドウが表示され、そこに "Hello, World!" というテキストが表示されるはずです。
コード
// GT_HelloWorldWin32.cpp
// compile with: /D_UNICODE /DUNICODE /DWIN32 /D_WINDOWS /c
#include <windows.h>
#include <stdlib.h>
#include <string.h>
#include <tchar.h>
// Global variables
// The main window class name.
static TCHAR szWindowClass[] = _T("win32app");
// The string that appears in the application's title bar.
static TCHAR szTitle[] = _T("Win32 Guided Tour Application");
HINSTANCE hInst;
// Forward declarations of functions included in this code module:
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
int WINAPI WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow)
{
WNDCLASSEX wcex;
wcex.cbSize = sizeof(WNDCLASSEX);
wcex.style = CS_HREDRAW | CS_VREDRAW;
wcex.lpfnWndProc = WndProc;
wcex.cbClsExtra = 0;
wcex.cbWndExtra = 0;
wcex.hInstance = hInstance;
wcex.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_APPLICATION));
wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
wcex.lpszMenuName = NULL;
wcex.lpszClassName = szWindowClass;
wcex.hIconSm = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_APPLICATION));
if (!RegisterClassEx(&wcex))
{
MessageBox(NULL,
_T("Call to RegisterClassEx failed!"),
_T("Win32 Guided Tour"),
NULL);
return 1;
}
hInst = hInstance; // Store instance handle in our global variable
// The parameters to CreateWindow explained:
// szWindowClass: the name of the application
// szTitle: the text that appears in the title bar
// WS_OVERLAPPEDWINDOW: the type of window to create
// CW_USEDEFAULT, CW_USEDEFAULT: initial position (x, y)
// 500, 100: initial size (width, length)
// NULL: the parent of this window
// NULL: this application does not have a menu bar
// hInstance: the first parameter from WinMain
// NULL: not used in this application
HWND hWnd = CreateWindow(
szWindowClass,
szTitle,
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT,
500, 100,
NULL,
NULL,
hInstance,
NULL
);
if (!hWnd)
{
MessageBox(NULL,
_T("Call to CreateWindow failed!"),
_T("Win32 Guided Tour"),
NULL);
return 1;
}
// The parameters to ShowWindow explained:
// hWnd: the value returned from CreateWindow
// nCmdShow: the fourth parameter from WinMain
ShowWindow(hWnd,
nCmdShow);
UpdateWindow(hWnd);
// Main message loop:
MSG msg;
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return (int) msg.wParam;
}
//
// FUNCTION: WndProc(HWND, UINT, WPARAM, LPARAM)
//
// PURPOSE: Processes messages for the main window.
//
// WM_PAINT - Paint the main window
// WM_DESTROY - post a quit message and return
//
//
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
PAINTSTRUCT ps;
HDC hdc;
TCHAR greeting[] = _T("Hello, World!");
switch (message)
{
case WM_PAINT:
hdc = BeginPaint(hWnd, &ps);
// Here your application is laid out.
// For this introduction, we just print out "Hello, World!"
// in the top left corner.
TextOut(hdc,
5, 5,
greeting, _tcslen(greeting));
// End application-specific layout section.
EndPaint(hWnd, &ps);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
break;
}
return 0;
}