Win32 アプリケーションの作成 (C++)
更新 : 2007 年 11 月
Win32 API (Windows API とも呼ばれます) は、Windows アプリケーションを作成するための C ベースのフレームワークであり、Windows のバージョンが 1.0 のときから使用されています。この API の詳細については、「Windows API」を参照してください。
この手順では、ウィンドウに "Hello, World!" を表示する単純な Win32 アプリケーションを作成します。手順はすべての Win32 アプリケーションで同じです。この手順を完了した後、ここで作成したコードをスケルトンとして使用して、他の Win32 アプリケーションを作成できます。
前提条件
このトピックは、C++ 言語の基本を理解していることを前提としています。C++ の学習を始めたばかりのユーザーには、『C++ Beginner's Guide』(Herb Schildt 著) をお勧めします。このガイドはオンラインで入手できます (https://go.microsoft.com/fwlink/?LinkId=115303)。
ビデオ デモについては、「Video How to: Creating Win32 Applications (C++)」を参照してください。
新しい Win32 プロジェクトを作成するには
[ファイル] メニューの [新規作成] をポイントし、[プロジェクト] をクリックします。
[プロジェクトの種類] ペインの [Visual C++] ノードの [Win32] を選択し、[テンプレート] ペインの [Win32 プロジェクト] を選択します。
プロジェクトに「win32app」などの名前を付けて入力します。プロジェクトを保存する場所は、既定の場所をそのまま使用するか、新しい場所を入力するか、ディレクトリを検索します。
Win32 アプリケーション ウィザードで、[次へ] をクリックします。
Win32 アプリケーション ウィザードで、[アプリケーションの種類] の [Windows アプリケーション] を選択します。[追加のオプション] の [空のプロジェクト] を選択します。残りのオプションはそのままにします。[完了] をクリックして、プロジェクトを作成します。
C++ ファイルをプロジェクトに追加するには、[プロジェクト] メニューの [新しい項目の追加] をクリックします。[新しい項目の追加] ダイアログ ボックスで、[C++ ファイル (.cpp)] をクリックします。「GT_HelloWorldWin32.cpp」などファイルの名前を入力し、[追加] をクリックします。
Win32 アプリケーションを起動するには
C および C++ アプリケーションにはすべて main 関数が必要です。この関数は、アプリケーションの開始点です。同様に、Win32 アプリケーションもすべて WinMain 関数を必要とします。WinMain の構文は次のとおりです。
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow);
この関数のパラメータと戻り値については、「WinMain 関数」を参照してください。
WinMain に加えて、各 Win32 アプリケーションには、通常 WndProc と呼ばれるもう 1 つの関数が必要です。この名前はウィンドウ プロシージャを表しています。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 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; }
この関数は 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 関数を実装していないからです。
WinMain の最後の手順は、メッセージ ループです。このループの目的は、オペレーティング システムが送信するメッセージを待機することです。アプリケーションがメッセージを受け取ると、メッセージは処理のために WndProc 関数にディスパッチされます。メッセージ ループは次のようになります。
MSG msg; while (GetMessage(&msg, NULL, 0, 0)) { TranslateMessage(&msg); DispatchMessage(&msg); } return (int) msg.wParam;
メッセージ ループで使用される構造体と関数の詳細については、「MSG」、「GetMessage」、「TranslateMessage」、および「DispatchMessage」を参照してください。
ここで完了した手順は、ほとんどの Win32 アプリケーションに共通しています。この時点で、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 を呼び出す必要があります。これら 2 つの関数呼び出しの間に、ウィンドウのテキスト、ボタン、およびその他コントロールをレイアウトするためのすべてのロジックが処理されます。このアプリケーションでは、ウィンドウ内に "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; }
例
説明
すべての手順を完了した後、コードは次のようになります。アプリケーションをビルドするには、[ビルド] メニューの [ソリューションのビルド] をクリックします。エラーなしでアプリケーションをコンパイルできた場合は、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 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;
}
//
// 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;
}
次の手順
前へ :Windows アプリケーションの作成 (C++) | 次へ :.NET Framework を使った Windows フォーム アプリケーションの作成 (C++)