建立 Win32 架構的應用程式 (C++)
更新:2010 年 12 月
本逐步解說會示範如何建立於視窗中顯示 "Hello, World!" 的 Win32 應用程式。 您可以使用在這個逐步解說中開發的程式碼做為模板,以建立其他 Win32 應用程式。
Win32 API (又稱為 Windows API) 是建立 Windows 應用程式的 C 架構。 如需 Win32 API 的詳細資訊,請參閱 Windows API。
![]() |
---|
在本文件的各步驟中,為了更清楚解釋特定的程式碼區段,我們可能會省略一般正常的應用程式需要的某些程式碼陳述式,例如 Include 指示詞和全域變數宣告。 本文件最後的範例一節會顯示完整程式碼。 |
必要條件
若要完成此逐步解說,您必須了解 C++ 語言的基礎。 如果您才剛開始學習 C++,建議您參考 Herb Schildt 所著的《C++ Beginner's Guide》。您可以在 MSDN 網站的初學者開發人員學習中心 (英文) 找到這份文件。
如需觀看示範影片,請參閱 Visual Studio 2008 文件中的影片 HOW TO:建立 Win32 應用程式 (C++) (英文)。
若要建立 Win32 專案
按一下 [檔案] 功能表上的 [新增],然後按一下 [專案]。
按一下 [新增專案] 對話方塊左窗格中的 [已安裝的範本],然後按一下 [Visual C++],再選取 [Win32]。 在中間窗格中選取 [Win32 專案]。
在 [名稱] 方塊中輸入專案的名稱,例如 win32app。 按一下 [確定]。
在 [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);
這個函式可以處理應用程從作業系統所接收的許多「訊息」(Message)。 例如,假設應用程式有個對話方塊具有 [確定] 按鈕,當使用者按一下這個按鈕時,作業系統會將按鈕已按下的訊息傳送給應用程式。 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 資料型別。
現在,使用下列程式碼來顯示視窗。
// 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;
}
後續步驟
上一個主題:建立 Windows 應用程式 (C++) |下一個主題:使用 .NET Framework 建立 Windows Form 應用程式 (C++)
請參閱
工作
變更記錄
日期 |
記錄 |
原因 |
---|---|---|
2010 年 12 月 |
說明我們可能已省略一般正常情況下會需要的某些程式碼陳述式,以更清楚解釋程式碼的其他部分。 |
客戶回函。 |