Поделиться через


Создание приложения Win32 (C++)

В данном пошаговом руководстве демонстрируется создание базового приложения на базе Win32, отображающего в окне надпись "Hello, World!". Можно воспользоваться кодом, созданным в этом пошаговом руководстве, в качестве шаблона для создания других приложений на базе Win32.

API-интерфейс Win32 (также известный как Windows API) — это платформа на основе C для создания приложений Windows. Дополнительные сведения об API-интерфейсе Win32 см. в разделе Windows API.

Важно!

Для того чтобы более понятно объяснить определенные сегменты кода, используемые в данном пошаговом руководстве, некоторые операторы кода, необходимые в реально работающем приложении, опущены, например директивы включения и объявления глобальных переменных.В разделе Пример в конце данного документа показан полный код.

Обязательные компоненты

Для выполнения этого пошагового руководства читатель должен владеть основами языка C++. Пользователям, только приступающим к изучению C++, рекомендуется руководство "C++ Beginner's Guide" (C++ для начинающих, на английском языке, автор Герберт Шилдт), которое доступно в центре начинающего разработчика на веб-сайте MSDN.

Видеодемонстрация доступна по адресу Video How to: Creating Win32 Applications (C++) в разделе документации по Visual Studio 2008.

Создание проекта на базе Win32

  1. В меню Файл последовательно выберите пункты Создать и Проект.

  2. В левой области диалогового окна Новый проект щелкните Установленные шаблоны, выберите Visual C++ и щелкните Win32. В средней области выберите Проект Win32.

    В поле Имя введите имя проекта, например win32app. Нажмите кнопку ОК.

  3. На начальной странице Мастер приложений Win32 нажмите кнопку Далее.

  4. На странице "Параметры приложения" в разделе Тип приложения выберите Приложение Windows. В поле Дополнительные параметры выберите Пустой проект. Чтобы создать проект, нажмите кнопку Готово.

  5. В окне Обозреватель решений щелкните правой кнопкой мыши проект Win32app, выберите команду Добавить и щелкните Новый элемент. В диалоговом окне Добавление нового элемента выберите Файл C++ (.cpp). В поле Имя введите имя файла, например GT_HelloWorldWin32.cpp. Нажмите кнопку Добавить.

Запуск приложения на базе Win32

  1. Точно так же как каждое приложение C и C++ должно иметь в качестве начальной точки функцию main, каждое приложение на базе Win32 должно иметь функцию WinMain. WinMain имеет следующий синтаксис.

    int WINAPI WinMain(HINSTANCE hInstance,
                       HINSTANCE hPrevInstance,
                       LPSTR lpCmdLine,
                       int nCmdShow);
    

    Сведения о параметрах и значениях, возвращаемых этой функцией, см. в разделе Функция WinMain.

  2. Поскольку в коде приложения должны использоваться существующие определения, следует добавить в файл операторы включения.

    #include <windows.h>
    #include <stdlib.h>
    #include <string.h>
    #include <tchar.h>
    
  3. Наряду с функцией WinMain в каждом приложении на базе Win32 также должна быть определена функция оконной процедуры. Обычно эта функция имеет имя WndProc. WndProc имеет следующий синтаксис.

    LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
    

    Эта функция обрабатывает многочисленные сообщения, которые приложение получает от операционной системы. Например, в приложении с диалоговым окном, в котором расположена кнопка ОК, при нажатии этой кнопки пользователем операционная система отправляет в приложение сообщение о том, что эта кнопка была нажата. Функция WndProc отвечает за реагирование на это событие. В этом примере соответствующей реакцией на это событие может быть закрытие диалогового окна.

    Дополнительные сведения см. в разделе Процедуры окна.

Добавление функциональных возможностей в функцию WinMain.

  1. В функции 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.

  2. После того как класс окна будет создан, необходимо зарегистрировать его. Воспользуйтесь функцией RegisterClassEx и передайте структуру класса окна в качестве аргумента.

        if (!RegisterClassEx(&wcex))
        {
            MessageBox(NULL,
                _T("Call to RegisterClassEx failed!"),
                _T("Win32 Guided Tour"),
                NULL);
    
            return 1;
        }
    
  3. Теперь можно создать окно. Воспользуйтесь функцией 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.

  4. Теперь воспользуйтесь следующим кодом, чтобы отобразить окно.

    // The parameters to ShowWindow explained:
    // hWnd: the value returned from CreateWindow
    // nCmdShow: the fourth parameter from WinMain
    ShowWindow(hWnd,
        nCmdShow);
    UpdateWindow(hWnd);
    

    На этом этапе в окне не будет отображаться большое количество содержимого, поскольку функция WndProc еще не реализована.

  5. Теперь добавьте цикл обработки сообщений для прослушивания отправляемых ОС сообщений. Когда приложение получает сообщение, этот цикл пересылает его функции 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.

  1. Чтобы включить обработку получаемых приложением сообщений функцией 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;
    }
    
  2. Обычно приложение обрабатывает много других сообщений, например 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;
    }
    

Пример

Построение этого примера

  1. Создайте проект на базе Win32, как показано в разделе "Создание проекта на базе Win32" ранее в этом пошаговом руководстве.

  2. Копируйте код, позволяющий выполнить эти шаги, и вставьте его в исходный файл GT_HelloWorldWin32.cpp.

  3. В меню Построение выберите команду Построить решение.

  4. Чтобы запустить приложение, нажмите клавишу 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++) | Далее: Создание приложения Windows Forms с помощью .NET Framework (C++)

См. также

Задачи

Создание приложений Windows (C++)

Журнал изменений

Дата

Журнал

Причина

Декабрь 2010

Упомянуто, что некоторые операторы кода, обычно требуемые для работы приложения, были опущены с целью более понятного объяснения других частей кода.

Обратная связь от клиента.