Tvorba aplikací pro prostředí Win32 (C++)
Tento návod ukazuje, jak vytvořit základní aplikaci založenou na Win32, která v okně zobrazí "Hello, World!".Kód vyvinutý v tomto návodu lze použít jako vzor pro vytvoření dalších aplikací založených na Win32.
Rozhraní Win32 API (označované také jako rozhraní Windows API) je rámec založený na jazyce C pro vytváření aplikací pro operační systém Windows.Další informace o rozhraní API systému Win32 naleznete v části Rozhraní Windows API.
![]() |
---|
Abychom v jednotlivých krocích v tomto dokumentu mohli jasněji vysvětlit konkrétní části kódu, mohou být některé příkazy, které jsou jinak pro fungující aplikaci potřeba, vynechány; například direktivy include nebo deklarace globálních proměnných.Sekce Příklad na konci tohoto dokumentu obsahuje kompletní kód. |
Požadavky
Chcete-li dokončit tento návod, je třeba porozumět základům jazyka C++.
Video ukázku naleznete v tématu Video postupy: Vytvoření aplikace Win32 (C++) v dokumentaci sady Visual Studio 2008.
Vytvoření projektu založeného na Win32
V nabídce Soubor klikněte na příkaz Nový a potom na Projekt.
V dialogovém okně Nový projekt na levé straně klikněte postupně na položky Nainstalované šablony, Visual C++ a Win32.V prostředním podokně vyberte Projekt Win32.
Do pole Název zadejte název projektu, například win32app.Klikněte na tlačítko OK.
Na úvodní stránce Průvodce aplikací Win32 klikněte na tlačítko Další.
Na stránce Nastavení aplikace, v části Typ aplikace klikněte na položku Aplikace Windows.V oddíle Další možnosti vyberte Prázdný projekt.Pro vytvoření projektu klikněte na Dokončit.
V Průzkumníku řešení klikněte pravým tlačítkem myši na projekt Win32app, klikněte na položku Přidat a poté Nová položka.V dialogovém okně Přidat novou položku vyberte Soubor C++ (.CPP).Do textového pole Název zadejte název souboru, například GT_HelloWorldWin32.cpp.Klikněte na tlačítko Přidat.
Spuštění aplikace založené na Win32
Stejně jako každá aplikace napsaná v jazyce C nebo C++ musí mít jako výchozí bod funkci main, každá aplikace založená na Win32 musí mít funkci WinMain.Funkce WinMain má následující syntaxi.
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow);
Informace o parametrech a vrácených hodnotách této funkce viz Funkce WinMain.
Jelikož kód aplikace musí používat existující definice, přidejte do souboru příkazy include.
#include <windows.h> #include <stdlib.h> #include <string.h> #include <tchar.h>
Kromě funkce WinMain musí mít každá aplikace založená na Win32 také funkci procedury okna.Tato funkce je obvykle pojmenována WndProc.Funkce WndProc má následující syntaxi.
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
Tato funkce zpracovává všechny různé zprávy, které aplikace přijímá od operačního systému.Například když v aplikaci, která má dialogové okno obsahující tlačítko OK, uživatel klikne na tlačítko, operační systém pošle aplikaci zprávu, že bylo na tlačítko kliknuto.WndProc je zodpovědná za odpověď na tuto událost.V příkladu může být vhodnou odpovědí zavření dialogového okna.
Další informace naleznete v tématu Procedury okna.
Přidání funkčnosti do funkce WinMain
Ve funkci WinMain vytvořte strukturu třídy okna typu WNDCLASSEX.Tato struktura obsahuje informace o okně aplikace, například ikonu aplikace, barvy pozadí okna, název zobrazený v záhlaví, název funkce procedury okna a podobně.Následující příklad ukazuje typickou strukturu 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));
Informace o polích této struktury viz WNDCLASSEX.
Nyní, po vytvoření třídy okna, je třeba třídu zaregistrovat.Použijte funkci RegisterClassEx a předejte strukturu třídy okna jako argument:
if (!RegisterClassEx(&wcex)) { MessageBox(NULL, _T("Call to RegisterClassEx failed!"), _T("Win32 Guided Tour"), NULL); return 1; }
Nyní lze vytvořit okno.Použijte funkci 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; }
Tato funkce vrací HWND, což je popisovač okna.Další informace naleznete v tématu Datové typy Windows.
Nyní použijte následující kód k zobrazení okna.
// The parameters to ShowWindow explained: // hWnd: the value returned from CreateWindow // nCmdShow: the fourth parameter from WinMain ShowWindow(hWnd, nCmdShow); UpdateWindow(hWnd);
V tomto okamžiku nebude mít zobrazené okno příliš mnoho obsahu, protože dosud nebyla implementována funkce WndProc.
Nyní přidejte smyčku zpráv, která bude přijímat zprávy operačního systému.Když aplikace obdrží zprávu, smyčka ji odešle funkci WndProc, kde bude zpracována.Kód smyčky zpráv by měl být podobný následujícímu kódu.
MSG msg; while (GetMessage(&msg, NULL, 0, 0)) { TranslateMessage(&msg); DispatchMessage(&msg); } return (int) msg.wParam;
Další informace o strukturách a funkcích používaných ve smyčce zpráv naleznete v tématech MSG, GetMessage, TranslateMessage a DispatchMessage.
V tomto okamžiku by měla funkce WinMain vypadat podobně jako následující kód.
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; }
Přidání funkčnosti do funkce WndProc
Aby mohla funkce WndProc zpracovávat zprávy, které aplikace příjme, je nutné implementovat příkaz switch.
První zpracovaná zpráva bude zpráva WM_PAINT.Aplikace obdrží tuto zprávu v případě, že část zobrazeného okna musí být aktualizována. (Při prvním zobrazení okna musí být aktualizováno vše.)
Pro zpracování zprávy WM_PAINT je nutné nejdříve zavolat funkci BeginPaint a následně zpracovat veškerou logiku pro vykreslení textu, tlačítek a dalších ovládacích prvků v okně a následně zavolat funkci EndPaint.V této aplikaci logika mezi zahajovacím a ukončovacím voláním představuje výpis řetězce "Hello, World!" v okně.V následujícím kódu si povšimněte, že funkce TextOut je použita k zobrazení řetězce.
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; }
Aplikace obvykle zpracovává mnoho jiných zpráv, například WM_CREATE nebo WM_DESTROY.Následující kód ukazuje základní, ale úplnou funkci 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; }
Příklad
Sestavení tohoto příkladu
Vytvořte projekt založený na Win32, jak je uvedeno v oddílu "Vytvoření projektu založeného na Win32" dříve v tomto návodu.
Zkopírujte kód, který je vytvořen těmito kroky, a následně jej vložte do zdrojového souboru GT_HelloWorldWin32.cpp.
V nabídce Sestavení klikněte na příkaz Sestavit řešení.
Stisknutím klávesy F5 spustíte aplikaci.Okno, které obsahuje text "Hello World", by se mělo zobrazit v levém horním rohu displeje.
Kód
// 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;
}