Пошаговое руководство. Создание традиционного классического приложения Windows (C++)

В этом пошаговом руководстве объясняется, как создать традиционное классическое приложение Windows в Visual Studio. Приложение, которое вы создаете, использует API Windows для отображения Hello, Windows desktop! в окне. Код, который вы разрабатываете в этом пошаговом руководстве, можно использовать в качестве шаблона для создания классических приложений Windows.

Windows API (также известный как Win32 API, API рабочего стола Windows и классический API Windows) — это среда, основанная на языке C, для создания приложений Windows. Он использовался для создания приложений Windows на протяжении десятилетий. Более сложные и простые платформы для программ были созданы на основе API Windows, например MFC, ATL и платформ .NET. Даже самый современный код для среда выполнения Windows в приложениях UWP и Магазина Windows, написанных на C++/WinRT, в своей основе использует Windows API. Дополнительные сведения об API Windows см. в разделе "Индекс API Windows".

Внимание

Блоки кода в разделе The code — это пояснительные фрагменты, а не команды, которые нужно вставлять по ходу работы. Они опускают вспомогательный код, чтобы каждую концепцию было легче понять. После того как вы создадите пустой проект, используйте полный исходный код, готовый к сборке, из раздела Сборка кода.

Предварительные требования

  • Microsoft Windows 7 или более поздних версий. Мы рекомендуем Windows 11 или более поздней версии для оптимальной разработки.

  • Visual Studio. Сведения о скачивании и установке Visual Studio см. в этой статье. При запуске установщика убедитесь, что установлен флажок Разработка классических приложений на C++. Не беспокойтесь, если вы не установили эту рабочую нагрузку при установке Visual Studio. Вы можете снова запустить установщик и установить ее сейчас.

    Снимок экрана с нагрузкой разработки настольных приложений с использованием C плюс плюс в установщике Visual Studio.

  • Базовое понимание использования интегрированной среды разработки Visual Studio. Если вы раньше пользовались настольными приложениями Windows, вам, вероятно, будет нетрудно разобраться. Общие сведения см. в обзоре возможностей интегрированной среды разработки Visual Studio.

  • Некоторые знания о языке C++. Не волнуйтесь, мы не будем делать ничего сложного.

Создание проекта классического приложения Windows

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

Чтобы просмотреть шаги для предпочтительной версии Visual Studio, используйте селектор версий , расположенный в верхней части оглавлений на этой странице.

Создание проекта классического приложения Windows в Visual Studio

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

  2. В верхней части диалогового окна задайте для Язык значение C++, для Платформа — значение Windows, а для Тип проекта — значение Desktop.

  3. Из отфильтрованного списка типов проектов выберите мастер рабочего стола Windows и нажмите кнопку "Далее". На следующей странице введите имя проекта, например DesktopApp.

  4. Нажмите кнопку Создать, чтобы создать проект.

  5. Откроется диалоговое окно "Проект рабочего стола Windows". В раскрывающемся списке "Тип приложения" выберите классическое приложение (.exe). Так как мы делаем приложение Windows, выбор консольного приложения приводит к созданию проекта, который не будет строиться с учетом кода, который мы будем использовать. Затем в разделе "Дополнительные параметры" выберите "Пустой проект". Нажмите кнопку ОК, чтобы создать проект.

  6. В Обозреватель решений щелкните правой кнопкой мыши проект DesktopApp, выберите "Добавить" и выберите "Создать элемент".

    Анимация, показывающая добавление нового элемента в Project DesktopApp в Visual Studio 2019.

    Анимация показывает, как щелкнуть правой кнопкой мыши по имени проекта в обозревателе решений, выбрать в появившемся меню пункт «Добавить», а затем — «Создать элемент».

  7. В диалоговом окне Добавление нового элемента выберите Файл C++ (.cpp). В поле "Имя" введите имя файла, например HelloWindowsDesktop.cpp. Нажмите кнопку Добавить.

    Снимок экрана: диалоговое окно

Теперь проект создается, и исходный файл открывается в редакторе.

Создать проект классического приложения Windows в Visual Studio 2017

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

  2. В диалоговом окне Создать проект на левой панели разверните Установленные>Visual C++, а затем выберите Рабочий стол Windows. В средней области выберите мастер рабочего стола Windows.

    В поле "Имя" введите имя проекта, например DesktopApp. Выберите OK.

    Снимок экрана диалогового окна

  3. В диалоговом окне "Классический проект Windows" в разделе "Тип приложения" выберите приложение Windows (.exe). В поле Дополнительные параметрывыберите Пустой проект. Убедитесь, что предварительно скомпилированные заголовки не выбраны. Нажмите кнопку ОК, чтобы создать проект.

  4. В Обозреватель решений щелкните правой кнопкой мыши проект DesktopApp, выберите "Добавить" и выберите "Создать элемент".

    Анимация, показывающая добавление нового элемента в Project DesktopApp в Visual Studio 2017.

    Анимация показывает щелчок правой кнопкой мыши по имени проекта в обозревателе решений, выбор команды "Добавить" в появившемся меню, а затем команды "Создать элемент".

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

    Снимок экрана диалогового окна

Теперь проект создается, и исходный файл открывается в редакторе.

Создание классического проекта Windows в Visual Studio 2015

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

  2. В диалоговом окне «Создать проект» в левой области разверните узел Установленные>Шаблоны>Visual C++, а затем выберите Win32. На средней панели выберите проект Win32.

    В поле "Имя" введите имя проекта, например DesktopApp. Выберите OK.

    Снимок экрана: диалоговое окно

  3. На странице "Обзор"мастера приложений Win32 нажмите кнопку "Далее".

    Снимок экрана: диалоговое окно в Visual Studio 2015, на котором показана страница обзора мастера приложений Win32.

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

  5. В Обозреватель решений щелкните правой кнопкой мыши проект DesktopApp, выберите "Добавить" и выберите "Создать элемент".

    Анимация, показывающая добавление нового элемента в Проект DesktopApp в Visual Studio 2015.

    Анимация показывает, как в обозревателе решений щелкают правой кнопкой мыши по имени проекта, в появившемся меню выбирают «Добавить», а затем — «Создать элемент».

  6. В диалоговом окне Добавление нового элемента выберите Файл C++ (.cpp). В поле "Имя" введите имя файла, например HelloWindowsDesktop.cpp. Нажмите кнопку Добавить.

    Снимок экрана: диалоговое окно

Теперь проект создается, и исходный файл открывается в редакторе.

Код

Далее вы узнаете, как создать код для классического приложения Windows в Visual Studio.

Как устроена программа

Традиционное классическое приложение Windows использует несколько фрагментов кода установки, прежде чем он сможет отобразить окно:

Компонент программы Purpose
Заголовки и общие объявления Укажите Windows типы и объявляйте значения, используемые несколькими функциями.
WinMain Регистрирует класс окна, создает и отображает окно и запускает цикл сообщений.
WndProc Обрабатывает сообщения из Windows, например запросы на краску или закрытие окна.

Следующие фрагменты сосредоточены на одной части программы одновременно. Полный источник объединяет части в правильном порядке.

Где код начинает выполняться в классическом приложении Windows

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

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

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

    Примечание.

    Что такое все эти дополнительные слова, например WINAPI, или , или CALLBACK, или HINSTANCE_In_? Традиционный API Windows широко использует псевдонимы типов typedef и макросы препроцессора, чтобы скрыть некоторые детали типов и платформозависимого кода, такие как соглашения о вызовах, объявления __declspec и директивы pragma компилятора. В среде Visual Studio вы можете использовать функцию IntelliSense Quick Info, чтобы посмотреть, как определены эти typedef’ы и макросы. Наведите указатель мыши на нужное слово или выделите его и нажмите Ctrl+K, CtrlI, чтобы открыть небольшое всплывающее окно с определением. Дополнительные сведения см. в разделе Using IntelliSense. Параметры и типы возвращаемых значений часто используют аннотации SAL, чтобы помочь выявлять ошибки в программировании. Дополнительные сведения см. в статье "Использование заметок SAL для уменьшения дефектов кода C/C++".

  2. Классические программы Windows требуют <windows.h>. Вы также часто видите #include <tchar.h>. Это упрощает написание приложения, которое может работать либо с char, либо с wchar_t. Таким образом, вы вместо этого используете TCHAR макрос в коде. TCHAR преобразуется в wchar_t, если в проекте определён символ UNICODE; в противном случае — в char. Если вы всегда выполняете сборку с включённой поддержкой Unicode, TCHAR вам не нужен, и можно просто использовать wchar_t напрямую. Дополнительные сведения см. в разделе "Использование универсальных текстовых сопоставлений". В следующем коде показаны эти две #include инструкции в верхней части файла.

    #include <windows.h>
    #include <tchar.h>
    
  3. Наряду с функцией WinMain, каждое настольное приложение Windows также должно иметь функцию процедуры окна. В этом пошаговом руководстве показано имя функции WndProc, но вы можете присвоить ему любое имя, как вы хотите в коде. WndProc имеет следующий синтаксис:

    LRESULT CALLBACK WndProc(
       _In_ HWND   hWnd,
       _In_ UINT   message,
       _In_ WPARAM wParam,
       _In_ LPARAM lParam
    );
    

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

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

Добавление функций в функцию WinMain

Перед WinMain объявите значения и оконную процедуру, которые используют другие части программы. Эти объявления расположены перед WinMain в полном исходном коде:

// The main window class name.
static TCHAR szWindowClass[] = _T("DesktopApp");

// The string that appears in the application's title bar.
static TCHAR szTitle[] = _T("Windows Desktop Guided Tour Application");

// Stored instance handle for use in Win32 API calls such as FindResource.
HINSTANCE hInst;

LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
  1. WinMain В функции необходимо записать некоторые основные сведения о главном окне. Это можно сделать, заполнив структуру типа WNDCLASSEX. Структура содержит сведения о окне, например значок приложения, цвет фона окна, имя, отображаемое в строке заголовка, помимо прочего. Важно отметить, что он содержит указатель функции на процедуру окна, которая обрабатывает сообщения, которые Windows отправляет в приложение. В следующем примере показана типичная 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(wcex.hInstance, 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, IDI_APPLICATION);
    

    Сведения о полях этой структуры см. в разделе WNDCLASSEX.

  2. После заполнения WNDCLASSEX структуры зарегистрируйте ее в Windows, чтобы она знала о окне и о том, как отправлять сообщения в него. RegisterClassEx Используйте функцию и передайте структуру класса окна в качестве аргумента. Макрос _T делает строковый литерал соответствующим типу символов, выбранному с помощью TCHAR, как описано выше в обсуждении Unicode. В следующем коде показано, как зарегистрировать класс окна.

    if (!RegisterClassEx(&wcex))
    {
       MessageBox(NULL,
          _T("Call to RegisterClassEx failed!"),
          _T("Windows Desktop Guided Tour"),
          NULL);
    
       return 1;
    }
    
  3. Создайте окно с помощью CreateWindowEx функции.

    // The parameters to CreateWindowEx explained:
    // WS_EX_OVERLAPPEDWINDOW : An optional extended window style.
    // 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, height)
    // NULL: the parent of this window
    // NULL: this application doesn't have a menu bar
    // hInstance: the first parameter from WinMain
    // NULL: not used in this application
    HWND hWnd = CreateWindowEx(
    WS_EX_OVERLAPPEDWINDOW,
       szWindowClass,
       szTitle,
       WS_OVERLAPPEDWINDOW,
       CW_USEDEFAULT, CW_USEDEFAULT,
       500, 100,
       NULL,
       NULL,
       hInstance,
       NULL
    );
    if (!hWnd)
    {
       MessageBox(NULL,
          _T("Call to CreateWindowEx failed!"),
          _T("Windows Desktop Guided Tour"),
          NULL);
    
       return 1;
    }
    

    Эта функция возвращает HWND, который является дескриптором окна. Дескриптор в некотором смысле похож на указатель. Windows использует его для отслеживания создаваемых окон. Дополнительные сведения см. в разделе Типы данных Windows.

  4. К этому моменту окно уже создано, но нам всё ещё нужно указать Windows, что его следует отобразить. Вот что делает этот код:

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

    Отображаемое окно является просто пустым прямоугольником, так как вы еще не реализовали функцию WndProc . Приложение пока не обрабатывает сообщения, которые Windows отправляет в него.

  5. Чтобы обрабатывать сообщения, сначала мы добавим цикл сообщений для прослушивания сообщений, отправляемых Windows. Когда приложение получает сообщение, этот цикл отправляет его в WndProc функцию для обработки. Цикл сообщений похож на следующий код:

    MSG msg;
    while (GetMessage(&msg, NULL, 0, 0))
    {
       TranslateMessage(&msg);
       DispatchMessage(&msg);
    }
    
    return (int) msg.wParam;
    

    Дополнительные сведения о структурах и функциях в цикле сообщений см. в разделе MSG, GetMessageTranslateMessage и DispatchMessage.

    Базовая WinMain функция, которая создаёт главное окно приложения и обрабатывает сообщения, отправляемые Windows приложению, будет выглядеть примерно так:

    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(wcex.hInstance, 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, IDI_APPLICATION);
    
       if (!RegisterClassEx(&wcex))
       {
          MessageBox(NULL,
             _T("Call to RegisterClassEx failed!"),
             _T("Windows Desktop Guided Tour"),
             NULL);
    
          return 1;
       }
    
       // Store instance handle in our global variable
       hInst = hInstance;
    
       // The parameters to CreateWindowEx explained:
       // WS_EX_OVERLAPPEDWINDOW : An optional extended window style.
       // 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, height)
       // NULL: the parent of this window
       // NULL: this application doesn't have a menu bar
       // hInstance: the first parameter from WinMain
       // NULL: not used in this application
       HWND hWnd = CreateWindowEx(
          WS_EX_OVERLAPPEDWINDOW,
          szWindowClass,
          szTitle,
          WS_OVERLAPPEDWINDOW,
          CW_USEDEFAULT, CW_USEDEFAULT,
          500, 100,
          NULL,
          NULL,
          hInstance,
          NULL
       );
    
       if (!hWnd)
       {
          MessageBox(NULL,
             _T("Call to CreateWindowEx failed!"),
             _T("Windows Desktop Guided Tour"),
             NULL);
    
          return 1;
       }
    
       // The parameters to ShowWindow explained:
       // hWnd: the value returned from CreateWindowEx
       // 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. Для обработки сообщений, получаемых приложением, вы реализуете инструкцию switch в WndProc функции.

    Важное сообщение, которое нужно обработать, — WM_PAINT. Приложение получает WM_PAINT сообщение, когда необходимо обновить часть отображаемого окна. Событие может произойти, когда пользователь перемещает другое окно так, что оно оказывается перед вашим окном, а затем снова убирает его. Оно получает это сообщение при первом отображении окна, что дает возможность отображать пользовательский интерфейс приложения. Приложение узнает об этих событиях, когда Windows отправляет их. При первом отображении окна всё оно должно быть обновлено.

    Чтобы обработать сообщение WM_PAINT, сначала вызовите BeginPaint, затем реализуйте всю логику размещения текста, кнопок и других элементов управления в окне. Затем вызовите EndPaint. Для этого приложения код между BeginPaint() и EndPaint() отображает Hello, Windows desktop! в окне, которое вы создали в WinMain(). В следующем коде TextOut функция отображает текст в указанном расположении в окне.

    PAINTSTRUCT ps;
    HDC hdc;
    TCHAR greeting[] = _T("Hello, Windows desktop!");
    
    switch (message)
    {
    case WM_PAINT:
       hdc = BeginPaint(hWnd, &ps);
    
       // Here your application is laid out.
       // For this introduction, we just print out "Hello, Windows desktop!"
       // in the top left corner.
       TextOut(hdc,
          5, 5,
          greeting, static_cast<int>(_tcslen(greeting))); // TextOut expects an int here but _tcslen returns a size_t. Thus the cast.
       // End application-specific layout section.
    
       EndPaint(hWnd, &ps);
       break;
    }
    

    В приведенном выше коде HDC — это дескриптор контекста устройства, связанного с клиентской областью окна. При рисовании в окне используйте этот дескриптор для ссылки на клиентную область. Используйте функции BeginPaint и EndPaint для подготовки к рисованию и его завершения в клиентской области. BeginPaint возвращает дескриптор контекста устройства отображения, используемого для рисования в клиентской области; EndPaint завершает запрос на краску и освобождает контекст устройства.

  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, Windows desktop!");
    
       switch (message)
       {
       case WM_PAINT:
          hdc = BeginPaint(hWnd, &ps);
    
          // Here your application is laid out.
          // For this introduction, we just print out "Hello, Windows desktop!"
          // in the top left corner.
          TextOut(hdc,
             5, 5,
             greeting, static_cast<int>(_tcslen(greeting))); // TextOut expects an int here but _tcslen returns a size_t. Thus the cast.
          // 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. Удалите весь код в HelloWindowsDesktop.cpp редакторе. Скопируйте этот пример кода и вставьте его в HelloWindowsDesktop.cpp:

    // HelloWindowsDesktop.cpp
    // compile with: /D_UNICODE /DUNICODE /DWIN32 /D_WINDOWS /c
    
    #include <windows.h>
    #include <tchar.h>
    
    // Global variables
    
    // The main window class name.
    static TCHAR szWindowClass[] = _T("DesktopApp");
    
    // The string that appears in the application's title bar.
    static TCHAR szTitle[] = _T("Windows Desktop Guided Tour Application");
    
    // Stored instance handle for use in Win32 API calls such as FindResource.
    HINSTANCE hInst;
    
    // Forward declarations of functions included in this code module:
    LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
    
    int WINAPI WinMain(
       _In_ HINSTANCE hInstance,
       _In_opt_ HINSTANCE hPrevInstance,
       _In_ LPSTR     lpCmdLine,
       _In_ 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(wcex.hInstance, 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, IDI_APPLICATION);
    
       if (!RegisterClassEx(&wcex))
       {
          MessageBox(NULL,
             _T("Call to RegisterClassEx failed!"),
             _T("Windows Desktop Guided Tour"),
             NULL);
    
          return 1;
       }
    
       // Store instance handle in our global variable
       hInst = hInstance;
    
       // The parameters to CreateWindowEx explained:
       // WS_EX_OVERLAPPEDWINDOW : An optional extended window style.
       // 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, height)
       // NULL: the parent of this window
       // NULL: this application doesn't have a menu bar
       // hInstance: the first parameter from WinMain
       // NULL: not used in this application
       HWND hWnd = CreateWindowEx(
          WS_EX_OVERLAPPEDWINDOW,
          szWindowClass,
          szTitle,
          WS_OVERLAPPEDWINDOW,
          CW_USEDEFAULT, CW_USEDEFAULT,
          500, 100,
          NULL,
          NULL,
          hInstance,
          NULL
       );
    
       if (!hWnd)
       {
          MessageBox(NULL,
             _T("Call to CreateWindowEx failed!"),
             _T("Windows Desktop Guided Tour"),
             NULL);
    
          return 1;
       }
    
       // The parameters to ShowWindow explained:
       // hWnd: the value returned from CreateWindowEx
       // 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, Windows desktop!");
    
       switch (message)
       {
       case WM_PAINT:
          hdc = BeginPaint(hWnd, &ps);
    
          // Here your application is laid out.
          // For this introduction, we just print out "Hello, Windows desktop!"
          // in the top left corner.
          TextOut(hdc,
             5, 5,
             greeting, static_cast<int>(_tcslen(greeting))); // TextOut expects an int here but _tcslen returns a size_t. Thus the cast.
          // 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;
    }
    
  2. В меню Построение выберите Построить решение. Результаты компиляции отображаются в окне вывода в Visual Studio.

    Анимация, показывающая шаги по созданию проекта DesktopApp.

    Анимация показывает нажатие кнопки «Сохранить все», а затем выбор команды «Сборка > Построить решение» в главном меню.

  3. Чтобы запустить приложение, нажмите клавишу F5. Должно появиться окно с текстом Hello, Windows desktop! .

    Снимок экрана окна с заголовком

Поздравляем! Вы создали традиционное классическое приложение Windows.

См. также