Как запустить приложение winapi
Что такое FASM? - Это компилятор ассемблера (flat assembler).
Что такое ассемблер? - это машинные инструкции, то есть команды что делать процессору.
Что такое Windows API/WinAPI? - Это функции Windows, без них нельзя работать с Windows.
Что дают WinAPI функции? - Очень много чего:
Работа с файлами.
Работа с окнами, отрисовка картинок, OpenGL, DirectX, GDI, и все в таком духе.
Взаимодействие с другими процессами.
Работа с портами.
Работа с консолью Windows
И еще очень много интересных функций.
Зачем нужен ассемблер?
На нем можно сделать все что угодно, от ОС до 3D игр.
Вот плюсы ассемблера:
Он очень быстрый.
На нем можно сделать любую программу.
А вот минусы ассемблера:
Долго делать программу. (относительно)
Сложен в освоении.
Что нужно для программирования на ассемблере (FASM)?
Это все мероприятие весит всего лишь 8.5MB.
Установка компонентов (если можно так назвать)
Архив FASM-а распаковуем в C:\\FASM\ или любой другой, но потом не забудьте настроить FASMEditor.
Архив FASMEdit-a распаковуем куда-то, в моем случае C:\\FASM Editor 2.0\
Архив OlyDbg распаковуем тоже куда-то, в моем случае C:\\Users\****\Documents\FasmEditorProjects\
Настройка FASM Editor-a
Для этого его нужно запустить.
Сразу вас приветствует FASM Editor соей заставкой.
Теперь вам нужно зайти в вкладку "Сервис" (на картинке выделил синим) -> "Настройки. "
Жмем на кнопку с названием ". " и выбираем путь к файлам или папкам.
Теперь мы полностью готовы. К началу.
Пишем "Hello world!" на FASM
В Fasm Editor нужно нажать на кнопку слева сверху или "файл" -> "новый". Выбираем любое, но можно выбрать "Console"
По началу вас это может напугать, но не боимся и разбираемся.
На самом деле из всей этой каши текста, команд всего 3: на 16, 18, 21 строках. (и то это не команды, а макросы. Мы к командам даже не подобрались)
Все остальное это просто подготовка программы к запуску.
Программа при запуске должна выглядеть так:
Самое интересное то что программа весит 2КБ. (Можно сократить и до 1КБ, но для упрощения и так пойдет)
Разбор: что значат этот весь текст?
На 1 строчке: "format PE Console" - это строчка говорит FASM-у какой файл скомпилировать, точнее 1 слово, все остальные слова это аргументы (можно так сказать).
PE - EXE файл, программа.
Console - говорим что это у нас консольная программа, но вам некто не мешает сделать из консольной программы оконную и наоборот.
Но есть кроме это остальные:
format MZ - EXE-файл НО под MS-DOS
format PE - EXE-файл под Windows, аналогично format PE GUI 4.0
format PE64 - EXE-файл под Windows, 64 битное приложение.
format PE GUI 4.0 - EXE-файл под Windows, графическое приложение.
format PE Console - EXE-файл под Windows, консольная программа. (просто подключается заранее консоль)
format PE Native - драйвер
format PE DLL - DLL-файл Windows, поясню позднее.
format COFF - OBJ-файл Linux
format MS COFF - аналогично предыдущему
format ELF - OBJ-файл для gcc (Linux)
format ELF64 - OBJ-файл для gcc (Linux), 64-bit
Сразу за командой (для компилятора) format PE Console идет ; это значит комментарий. К сожалению он есть только однострочный.
3 строка: entry start
Говорим windows-у где\в каком месте стартовать. "start" это метка, но о метках чуть позже.
5 строка: include 'win32a.inc'
Подключает к проекту файл, в данном случае "win32a.inc" он находиться в папке INCLUDE (в папке с FASM). этот файл создает константы и создает макросы для облегчения программирования.
8 строка: section '.data' data readable writeable
Секция данных, то есть программа делиться на секции (части), к этим секциям мы можем дать разрешение, имя.
Флаг "data" (Флаг это бит\байт\аргумент хранившей в себе какую-то информацию) говорит то что эта секция данных.
Флаги "readable writeable" говорят то что эта секция может читаться кем-то и записываться кем-то.
Текст '.data' - имя секции
10 строка: hello db 'hello world!',0
hello - это метка, она может быть любого имени (почти, есть некоторые зарезервированные имена), эта метка хранит в себе адрес строки, это не переменная, а просто адрес, но чтобы не запоминать адреса в ручную, помогает FASM он запоминает адрес и потом когда видит эту метку снова, то он заменяет слово на адрес.
db - говорит то что под каждый символ резервируем 1 байт. То есть 1 символ храниться в одном байте.
'hello world!' - наша строка в кодировке ASCII
Что значит ",0" в конце строки? - это символ с номером 0 (или просто ноль), у вас на клавиатуре нет клавиши которая имела символ с номером 0, по этому этот символ используют как показатель конца строки. То есть это значит конец строки. Просто ноль записываем в байт после строки.
12 строка: section '.code' code readable writeable executable
Флаг "code" - говорит то что это секция кода.
Флаг "executable" - говорит то что эта секция исполняема, то есть в этой секции может выполняться код.
Все остальное уже разобрали.
14 строка: start:
Это второй вид меток. Просто эта метка указывает на следующую команду. Обратите внимание на то что в 3 строке мы указали start как метку входа в программу, это она и есть. Может иметь эта метка любое имя, главное не забудьте ваше новое имя метки вписать в entry
15 строка: invoke printf, hello
Функция printf - выводит текст\число в консоль. В данном случае текст по адресу "hello"
Это штото на подобие команды, но это и близко не команда ассемблера, а просто макрос.
Макрос - Это макро команда для компилятора, то есть вместо имени макроса подставляется что-то другое.
Например, макро команда invoke делиться на такие команды: (взят в пример команда с 15 строки)
Не переживайте если нечего не поняли.
17 строка: invoke getch
getch - функция получения нажатой кнопки, то есть просто ждет нажатия кнопки и потом возвращает нажатую кнопку.
20 строка: invoke ExitProcess, 0
ExitProcess - WinAPI функция, она завершает программу. Она принимает значение, с которым завершиться, то есть код ошибки, ноль это нет ошибок.
23 строка: section '.idata' data import readable
Флаг "import" - говорит то что это секция импорта библиотек.
24-25 строки:
Макро команда "library" загружает DLL библиотеки в виртуальную память (не в ОЗУ, вам ОЗУ не хватит чтоб хранить всю виртуальную память).
Что такое DLL объясню позже.
kernel - имя которое привязывается к библиотеке, оно может быть любым.
Следующий текст после запятой: 'kernel32.dll' - это имя DLL библиотеки который вы хотите подключить.
Дальше есть знак \ это значит что текст на следующей строке нужно подставить в эту строку.
Это нужно потому что у ассемблера 1 строка это 1 команда.
27-28 строка:
import - Макро команда, которая загружает функции из DLL.
kernel - Имя к которой привязана DLL, может быть любым.
ExitProcess - Как будет называться функция в программе, это имя будет только в вашей программе, и по этому имени вы будете вызывать функцию. (WinAPI функция)
'ExitProcess' - Это имя функции которое будет загружено из DLL, то есть это имя функции которое прописано в DLL.
Дальше думаю не стоит объяснять, вроде все понятно.
Что такое DLL библиотека?
Это файл с расширением DLL. В этом файле прописаны функции (какие ни будь). Это обычная программа, но которая не запускается по двойному щелчку, а загружается к программе в виртуальную память, и потом вызываются функции находящиеся в этой DLL.
Подводим итог
На ассемблере писать можно не зная самого языка, а используя всего лишь макро команды компилятора. За всю статью я упомянул всего 2 команды ассемблера это push hello и call [printf] . Что это значит расскажу в следующей статье.
в этом пошаговом руководстве показано, как создать традиционное Windows классическое приложение в Visual Studio. в примере приложения, которое вы создадите, будет использоваться Windows API для вывода "Hello, Windows desktop!". "Hello, World!". Код, созданный в этом пошаговом руководстве, можно использовать в качестве шаблона для создания других классических приложений Windows.
Для краткости в тексте пропущены некоторые операторы кода. В разделе Построение кода в конце документа показан полный код.
Предварительные требования
Компьютер под управлением Microsoft Windows 7 или более поздних версий. Для обеспечения оптимальной среды разработки рекомендуется использовать Windows 10.
Копия Visual Studio. Сведения о скачивании и установке Visual Studio см. в этой статье. Когда вы запускаете установщик, убедитесь, что установлена рабочая нагрузка Разработка классических приложений на C++ . Не беспокойтесь, если вы не установили эту рабочую нагрузку при установке Visual Studio. Вы можете снова запустить установщик и установить ее сейчас.
Базовые значения об использовании интегрированной среды разработки Visual Studio. Если вы уже использовали классические приложения для Windows, вы, вероятно, справитесь. Общие сведения см. в обзоре возможностей интегрированной среды разработки Visual Studio.
Основные навыки владения языком C++. Не волнуйтесь, мы не будем делать ничего сложного.
создание проекта Windows классических приложений
чтобы создать первый проект Windows desktop, выполните следующие действия. в процессе работы вы вводите код рабочего Windows приложения. Чтобы ознакомиться с документацией по предпочтительной версии Visual Studio, используйте селектор Версия. Он находится в верхней части оглавления на этой странице.
создание проекта Windows desktop в Visual Studio 2019
В главном меню выберите Файл > Создать > Проект, чтобы открыть диалоговое окно Создание проекта.
в верхней части диалогового окна задайте для параметра язык значение C++, задайте для параметра платформа значение Windows и задайте для параметра Project тип значение рабочий стол.
в отфильтрованном списке типов проектов выберите мастер рабочего стола Windows , а затем нажмите кнопку далее. На следующей странице введите имя проекта, например десктопапп.
В Обозреватель решений щелкните правой кнопкой мыши проект Десктопапп , выберите Добавить, а затем выберите новый элемент.
Теперь проект создан и исходный файл открыт в редакторе. Чтобы продолжить, перейдите к созданию кода.
создание проекта Windows desktop в Visual Studio 2017
В меню Файл выберите команду Создать, а затем пункт Проект.
в левой области диалогового окна создание Project разверните узел установленные > Visual C++ и выберите пункт Windows рабочий стол. в средней области выберите мастер рабочего стола Windows.
В Обозреватель решений щелкните правой кнопкой мыши проект Десктопапп , выберите Добавить, а затем выберите новый элемент.
Теперь проект создан и исходный файл открыт в редакторе. Чтобы продолжить, перейдите к созданию кода.
создание проекта Windows desktop в Visual Studio 2015
В меню Файл выберите команду Создать, а затем пункт Проект.
в левой области диалогового окна создание Project разверните узел установленные > шаблоны > Visual C++, а затем выберите пункт Win32. В средней области выберите шаблон Проект Win32.
На странице Обзор мастера приложений Win32 нажмите кнопку Далее.
на странице Параметры приложений в разделе тип приложения выберите Windows приложение. В разделе Дополнительные параметры снимите флажок предкомпилированный заголовок, а затем выберите пустой проект. Чтобы создать проект, нажмите кнопку Готово.
В Обозреватель решений щелкните правой кнопкой мыши проект десктопапп, выберите Добавить, а затем выберите новый элемент.
Теперь проект создан и исходный файл открыт в редакторе.
Создание кода
далее вы узнаете, как создать код для Windows классического приложения в Visual Studio.
Запуск классического приложения Windows
точно так же, как у каждого приложения C и C++ должна быть main функция в качестве начальной точки, каждое Windows классическое приложение должно иметь WinMain функцию. WinMain имеет следующий синтаксис:
Сведения о параметрах и возвращаемом значении этой функции см. в разделе WinMain Entry Point.
Что такое дополнительные слова, такие как, или, или WINAPI CALLBACK HINSTANCE _In_ ? традиционный API Windows использует определения типов и макросов препроцессора, чтобы изменялись некоторые сведения о типах и коде, зависящем от платформы, такие как соглашения о вызовах, __declspec объявления и директивы pragma компилятора. в Visual Studio можно использовать функцию " быстрые сведения " IntelliSense, чтобы увидеть, что определяются этими определениями и макросами. Наведите указатель мыши на интересующую слово или выберите его и нажмите клавиши CTRL + K, CTRL + I для небольшого всплывающего окна, содержащего определение. Дополнительные сведения см. в разделе Using IntelliSense. Параметры и возвращаемые типы часто используют аннотации SAL , чтобы помочь в перехвате ошибок программирования. Дополнительные сведения см. в разделе Использование аннотаций SAL для сокращения числа дефектов кода C/C++.
для Windows настольных приложений требуется <> Windows. h. <в файле Tchar. h> определен TCHAR макрос, который в конечном итоге разрешается в, wchar_t Если в проекте ОПРЕДЕЛЕН символ Юникода, в противном случае — значение char . Если вы всегда создаете Юникод с включенным параметром UNICODE, то не нужно использовать TCHAR и может быть просто использоваться wchar_t напрямую.
наряду с WinMain функцией, каждое Windows классическое приложение также должно иметь функцию window-procedure. Эта функция обычно называется WndProc , но вы можете назвать ее по своему усмотрению. WndProc имеет следующий синтаксис:
Дополнительные сведения см. в разделе Процедуры окна.
Добавление функциональных возможностей в функцию WinMain
В WinMain функции вы заполняете структуру типа вндклассекс. Структура содержит сведения о окне: значок приложения, цвет фона окна, имя, отображаемое в строке заголовка, помимо прочего. Важно, что он содержит указатель на функцию окна. В приведенном ниже примере показана типичная структура WNDCLASSEX .
Дополнительные сведения о полях приведенной выше структуры см. в разделе вндклассекс.
Теперь можно создать окно. Используйте функцию CreateWindowEx .
Эта функция возвращает объект HWND , который является обработчиком окна. маркер похож на указатель, который Windows использует для наблюдения за открытыми окнами. Дополнительные сведения см. в разделе Типы данных Windows.
на этом этапе окно было создано, но нам по-прежнему нужно сообщить Windows, чтобы сделать его видимым. Вот что делает этот код:
На этом этапе функция WinMain должна напоминать приведенный ниже код.
Добавление функциональных возможностей в функцию WndProc
HDC в коде — это обработчик контекста устройства, который используется для рисования в клиентской области окна. Используйте BeginPaint функции и EndPaint для подготовки и завершения рисования в клиентской области. BeginPaint Возвращает маркер контекста устройства отображения, используемый для рисования в клиентской области. EndPaint завершает запрос на рисование и освобождает контекст устройства.
Сборка кода
Как обещано, вот полный код для рабочего приложения.
Сборка примера
Удалите код, введенный в хелловиндовсдесктоп. cpp в редакторе. Скопируйте этот пример кода и вставьте его в хелловиндовсдесктоп. cpp:
В меню Построение выберите Построить решение. Результаты компиляции должны появиться в окне вывод в Visual Studio.
Чтобы запустить приложение, нажмите клавишу F5. окно, содержащее текст "Hello, Windows desktop!" должно отображаться в левом верхнем углу экрана.
Поздравляем! вы выполнили это пошаговое руководство и создали традиционное Windows классическое приложение.
КАК подготовить и запустить проект Win API?
Итак, маленькая предыстория. Когда мы работали в Borland C++ 3.1 достаточно было создать новый файл, настучать в него текст программы и запустить. Компилятор принимал имя файла и создавал выполнимый EXE-файл. С тех пор концепция программирования несколько изменилась. Программисты для Windows обычно работают с очень большим количеством файлов, которые объединены в проект. Проект включает в себя не только исходные тексты, но и библиотеки и внешние текстовые файлы, используемые для записи промежуточных и конечных результатов, файлы типа Excell, базы данных XML, иконки, курсоры, картинки, аудиои видеофайлы и многое другое. Поэтому ошибкой было бы писать текст в редакторе типа "Блокнот", а потом пытаться открыть его с помощью VC++ да ещё и скомпиллировать. Visual С изначально понимает только проекты, причём созданные в нём самом.
Подчиняясь суровой необходимости, открываем Visual C++. На экране то, что обычно. Ничего. В лучших традициях Microsoft - никакого намёка на то, что делать дальше.
Сейчас вам предстоит определиться с тем, какая версия Visual Studio стоит на вашем компьютере. Если их несколько, имеет смыл использовать самую новую. Программисты - это люди завтрашнего дня.
Итак, если у вас стоит Visual Studio, то вам сюда. Сейчас я научу вас создавать программы на API. Эти рекомендации пригодятся вам в дальнейшем, когда вы будете создавать проекты для последующих, более сложных примеров.
Запустите программу Visual C++ через меню пуск. На экране появится пустое окно программы, впрочем, готовое к сотрудничеству. Беглый осмотр говорит нам о том, что в программе есть свойственная всем продуктам Microsoft панель управления для удобного редактирования текстов, а также меню. Назначение многих элементов меню и кнопок из панели управления мы будем разбирать по ходу пьессы.
В Visual Studio можно создавать удивительно много полезных штук. Создание Win API - программ - не единственное, что в ней можно делать. Чаще всего она используется для создания программ на основе библиотеки классов MFC. Но и это не обязательно. Поэтому, при создании нового проекта, надо его как следует настроить.
Выберите пункты меню File->New->Project. У вас появятся аналогичные окна New или New Project. Для версий 6.0 и 7.0 соответственно.
| |
В списке перечислены основные типы проектов, которые можно создавать в Visual C++. Освоим пока только один из них.
В окне New (New Project) выберите тип "Win 32 Application" ("Win32 Project"). Win 32 Application - это и есть программа на API. Сейчас от нас требуется дать имя нашему проекту - заметьте, не файлу, не будущей программе, а проекту. В большинстве случаев это имя может быть любым, но мой вам совет - давайте говорящие имена, чтобы потом не гадать, чем Project4 отличается от Project111. Пусть имя первого проекта будет First. В поле Location будет указан путь, по которому будет создана одноимённая папка для проекта First, в которой будет размещён весь наш проект. Нажмите Ok.
| |
Это ещё не всё. Появится следующее окно, которое будет просить определить содержание проекта. В Visual C++ есть некоторые шаблоны, которые позволяют избавить разработчика от многих рутинных операций - они сами создают исходные файлы и даже прописывают в них какой-то минимальный код. Так, например, чтобы не перетруждаться, мы можем создать готовое окно с меню и строкой состояния. К шаблонам мы ещё вернёмся, а пока изучим всё с азов. В Visual C++ 6.0 надо поставить галочку на An Empty Project ("Пустой проект"), так как мы будем создавать всё вручную, и нажать кнопку Finish. В 7-й версии надо перейти на закладку Application Settings ("Настройки приложения") и поставить галочку Application Type - Windows Application, Application options: Empty рroject. И тоже нажать Finish ("Завершить") .
У вас появился готовый проект, правда в нём пока ещё нет ровным счётом ничего. У нас есть проект, но пока нет программы. Остаётся набрать исходный текст и добавить его в проект. Вообще особенность пустых проектов - то, что надо добавлять в него все файлы вручную, несмотря на то, исходники это, библиотеки или ресурсы.
Вот такой вид будут иметь пустые проекты:
| |
Теперь познакомимся поближе с редактором. Как и в любой программе Windows, в верхней части окна расположены меню и панель инструментов. Она стандартная для всех приложений Microsoft, и я думаю, со многими кнопками (такими, как Сохранить, Копировать, Вырезать, Вставить) вы уже знакомы.
В нижней части программы, как и в Borland C++ окно комментариев компилятора. В нём будет вестись журнал компиляции, компоновки и построения, отображаться статус проекта, выдаваться предупреждения (warnings), ошибки (errors) и комменатрии. Чтобы оно не мешало, его можно закрывать, когда вы работаете с кодом.
В левой части окно навигатора, в котором есть три вкладки: Files (Файлы), ClassView (Вид классов) и Resource (Ресурсы).
Вкладка FileView - файлы, которые входят в проект. Они условно разделены на три папочки: Source (исходники), Headers (Библиотеки, заголовочные файлы), Resources (ресурсы - картинки, иконки, курсоры). В больших проектах количество файлов и папок может доходить до тысячи, поэтому очень удобно иметь весь список файлов перед собой, чтобы быстро получить доступ к нужному.
ClassView - диаграмма классов, используемых в программе. Поскольку язык API процедурный, нам она пока не понадобится.
ResourceView - содержит наши ресурсы. Они описаны в файле ресурсов. Этот файл носит вспомогательный характер, но он очень важен. В нём описаны все ресурсы приложения - диалоговые окна, панели инстрментов, меню, картинки, иконки, курсоры и многое другое. В MFC этот файл генерируется автоматически, нам придётся создавать его вручную. Для этого придётся овладеть нехитрым языком описания ресурсов. Обычно файл ресурсов имеет расширение: *.RC
Пока что проект пуст и не содержит никаких файлов. Чтобы вы могли набирать исходные тексты из моей книги и других книг, вы должны освоить процедуру создания пустого проекта и включения в него файлов, описанные в этой главе. Рассмотрим методику включения файла исходника для обоих версий.
Вот теперь всё готово для ввода программы. Если вы выберите в навигаторе вкладку Files и раскроете папочку Source, то увидите, что в ней появился наш первый исходный файл First.cpp!
Примечание. Следите, чтобы все исходные файлы хранились в папке проекта. При большом количестве файлов удобно сортировать их по каталогам. Но всё равно, все каталоги должны храниться в одной общей папке - папке проекта.
Вот теперь в файл можно ввести какой-то текст. Итак, первая программа!
Самая первая программка будет такой:
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpszCmdLine, int nCmdShow)
MessageBox(0, "Привет, Win32 API", "Первое окно. ", MB_ICONINFORMATION|MB_OK);
Не бойтесь, если вы ещё не знаете языка API. мы здесь и собрались для его изучения. Пока мы просто учимся работать с компилятором. Введите этот текст в файл First.cpp и сохранить его. Запустить программу на выполнение можно кнопкой F5. Компилятор переидёт в режим отладки нашего проекта. Вас спросят, хотите ли вы построить выполнимый файл. Вы ответите Yes, и через какое-то время, если всё правильно набрали, увидите свою программу. Так будут запускаться на исполнение все наши программы. После запуска build в папке проекта появится вложенная папка Debug, в которую будет помещён созданный нами файл First.exe.
Эта программка не содержит главного окна, которое в большинстве своём считается обязательным элементов для всех Windows-программ, если конечно они не консольные, однако это уже полноценная программа для Windows, о чём мы заявили, когда включили библиотеку windows.h. Далее идёт тело функции WinMain().
WinMain() - главная функция любой API программы - точка входа в неё. Нечто подобное представляла собой и функция main(), когда мы работали в DOS.
Как вы уже поняли, программа выводит на экран информационное окно, с которым вы конечно уже нераз сталкивались, когда работали в Windows в качестве пользователя.
Число кнопок также может варьироваться:
- только кнопка "ОК" (MB_OK)
- "Отмена" (MB_CANCEL)
- "Пропустить" (MB_IGNORE)
- "ОК и Отмена" (MB_OKCANCEL)
Окно, создаваемое MessageBox - стандартное окно Windows. Также к стандартным окнам относятся такие известные вам диалоги, как: окно выбора папки, окно открытия и сохранения файлов, окно выбора цвета, шрифта и окно настройки принтера. Они нам очень помогают, но к сожалению никогда не заменят главного окна программы, которое мы будем создавать сами.
Это была разминка с целью научить вас создавать проекты для Win32 API. С каждой новой главой, мы будем исследовать всё более сложные и всё более интересные вещи.
Задание:
Измените информационную иконку на вопросительную и придумайте вопрос, который задаёт программа (например "Вы действительно хотите удалить файл?"). В строке заголовка окна введите имя программы (в данном случае "First"). Пусть в новом окне теперь будут две кнопки: "ОК и Отмена". Запустите программу на выполнение.
Что будет дальше?
Вы наверное уже достаточно хорошо освоили работу с функцией MesaageBox и хотите двигаться дальше. Спешу вас обрадовать, что в следующей главе вы уже создадим своё первое окно!
WinAPI или Windows API (Application Programming Interface) - это библиотека для создания классических приложений Windows. Сама библиотека WinAPI написана на языке C и представляет собой коллекцию функций, структур и констант. Она объявлена в определённых заголовочных файлах и реализована в статических (.lib) и динамических (.dll) библиотеках.
В данном уроке мы создадим нашу первую программу на WinAPI. Для начала создайте проект. Выберите меню File -> New -> Project:
В открытом окне в левой панели выберите Other, затем Empty Project (пустой проект). Там же доступен шаблон Windows Desktop Application, но мы напишем программу с нуля, так как шаблон по умолчанию пока слишком сложен для нас. В нижней части выберите имя проекта, его местоположение и хотите ли вы создать решение для него. Местоположение может быть любым, для меня это C:\prog\cpp\
В обозревателе решений щёлкните правой кнопкой мышки и выберите Add -> New Item.
В открывшемся окне выберите C++ File (.cpp) и введите имя файла в нижней части - main.cpp.
Перед тем как мы начнём рассматривать код, давайте поговорим о типах данных в WinAPI и соглашениях вызова (calling conventions).
Типы данных в WinAPI
WinAPI переопределяет множество стандартных типов языка C. Некоторые переопределения зависят от платформы для которой создаётся программа. Например, тип LRESULT, если его скомпилировать для x86, будет типом long. Но если скомпилировать программу для x64, то LRESULT будет типом __int64. Вот так LRESULT определяется на самом деле (он зависит от LONG_PTR, а LONG_PTR может уже быть или __int64, или long):
Соглашения по вызову (Calling Conventions) - __stdcall
В коде ниже перед именами функций вы встретите __stdcall. Это одно из соглашений по вызову функций. Соглашение по вызову функций определяет каким образом аргументы будут добавляться в стек. Для __stdcall аргументы помещаются в стек в обратном порядке - справа налево. Также, __stdcall говорит, что после того как функция завершится, она сама (а не вызывающая функция) удалит свои аргументы из стека. Все функции WinAPI используют __stdcall соглашение.
WinAPI переопределяет __stdcall в WINAPI, CALLBACK или APIENTRY, которые используются в разных ситуациях. Поэтому в примерах из MSDN вы не увидите __stdcall, но нужно помнить что именно оно будет использоваться.
Типы WinAPI пишутся в верхнем регистре.
Описатели/дескрипторы (Handles) в WinAPI
Handle на русский язык сложно перевести однозначно. Наверное, наиболее частое употребление в русском имеет слово дескриптор. По сути это ссылка на ресурс в памяти. Например, вы создаёте окно. Это окно хранится в памяти и оно имеет запись в таблице, которая хранит указатели на все созданные системные ресурсы: окна, шрифты, файлы, картинки. Указатель на ваше окно в данной таблице называется дескриптором окна (handle of the window).
Любой указатель это просто переопределение типа void*. Примеры дескрипторных типов в WinAPI: HWND, HINSTANCE, HBITMAP, HCURSOR, HFILE, HMENU.
Подытожим: дескрипторы используются для получения доступа к каким-либо системным ресурсам.
WinAPI окна
Давайте посмотрим на код самой простой WinAPI программы:
Вначале нужно добавить WinAPI: статичную библиотеку, которая содержит определения различных функций и включить заголовочный файл с объявлениями этих функций, структур и констант. user32.lib содержит основные возможности Windows - всё, что касается окон и обработки событий.
Функция WinMain
WinMain - точка входа в программу, а как мы помним такая функция вызывается операционной системой.
Главная функция приложений под Windows отличается от консольной версии. Она возвращает целое число и это всегда ноль. __sdtcall говорит, что аргументы добавляются в стек в обратном порядке и WinMain сама удаляет их из стека по завершении. WinMain принимает 4 аргумента:
int __stdcall WinMain(HINSTANCE hInstance, HINSTANCE, LPSTR, int nCmdShow)hInstance - дескриптор экземпляра приложения. Можете думать о нём, как о представлении вашего приложения в памяти. Он используется для создания окон.
Второй аргумент - наследие шестнадцатибитных версий Windows. Уже давно не используется.
Третий аргумент представляет аргументы командной строки. Пока мы не будем им пользоваться.
nCmdShow - специальный флаг, который можно использовать при создании окон. Он говорит о состоянии окна: должно ли оно показываться нормально, на полный экран или быть свёрнутым.
Теперь давайте посмотрим как создаются окна.
Классы окон (Window Classes)
Сначала нужно заполнить структуру WNDCLASS. Пусть вас не смущает название WNDCLASS - это не C++ класс. В данном случае, класс - всего лишь термин используемый в WinAPI:
WNDCLASS windowClass = < 0 >; windowClass.lpfnWndProc = WindowProc; windowClass.hInstance = hInstance; windowClass.lpszClassName = "HELLO_WORLD"; RegisterClass(&windowClass);Здесь мы инициализируем структуру WNDCLASS нулями, определяем обязательные поля и регистрируем класс.
lpfnWndProc имеет тип WNDPROC. Как говорилось выше, это указатель на функцию WindowProc, которую мы объявили в самом начале. У каждого оконного класса должна быть своя оконная процедура.
hInstance - дескриптор экземпляра приложения. Все оконные классы должны сообщать, какое приложение их зарегистрировало. Мы используем первый параметр функции WinMain.
lpszClassName - имя класса, задаётся пользователем. В Windows все классы называются в верхнем регистре (примеры: BUTTON, EDIT, LISTBOX), мы будем делать также в наших уроках.
WNDCLASS содержит больше полей: стиль, иконка, имя меню, но мы можем пропустить их. Некоторые из них мы рассмотрим в следующих уроках. Вы можете посмотреть полный список в документации к WinAPI на MSDN (официальном сайте Microsoft с документацией).
В конце мы регистрируем наш класс с помощью функции RegisterClass. Мы передаём адрес структуры WNDCLASS. Теперь мы можем создать окно.
Первая WinAPI программа - Пустое окно
В WinAPI есть функция для создания окон - CreateWindow:
HWND hwnd = CreateWindow( windowClass.lpszClassName, "Пустое WinAPI окно - Привет Мир!", WS_OVERLAPPEDWINDOW, 100, 50, 1280, 720, nullptr, nullptr, hInstance, nullptr);Первый параметр - имя класса. В данном случае он совпадает с именем класса, который мы зарегистрировали. Второй - имя окна, это та строка, которую пользователи программы будут видеть в заголовке. Следующий - стиль. WS_OVERLAPPEDWINDOW говорит, что WinAPI окно имеет заголовок (caption), кнопки сворачивания и разворачивания, системное меню и рамку.
Четыре числа определяют позицию левого верхнего угла окна и ширину/высоту.
Затем идут два указателя nullptr. Первый - дескриптор родительского окна, второй - меню. У нашего окна нет ни того, ни другого.
hInstance - дескриптор на экземпляр приложения, с которым связано окно.
В последний аргумент мы передаём nullptr. Он используется для специальных случаев - MDI (Multiple Document Interface ) - окно в окне.
CreateWindow возвращает дескриптор окна. Мы можем использовать его для обращения к окну в коде. Теперь мы можем показать и обновить окно.:
ShowWindow (показать окно) использует параметр nCmdShow функции WinMain для контроля начального состояния (развёрнуто на весь экран, минимизировано, обычный размер). UpdateWindow (обновить окно) мы обсудим в следующих уроках.
Главный цикл WinAPI
Далее идёт бесконечный цикл. В этом цикле мы будем реагировать на разные события, возникающие при взаимодействии пользователя с нашей программой.
Оконная процедура (Window Procedure) WindowProc
LRESULT __stdcall WindowProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) < switch (message) < case WM_DESTROY: PostQuitMessage(0); return 0; >return DefWindowProc(hWnd, message, wParam, lParam); >Обратите внимание, что мы сами нигде не вызываем WindowProc. Оконная процедура привязана к классу окна. И когда мы вызываем DispatchMessage, система сама вызывает оконную процедуру, связанную с окном. Такие функции называются функциями обратного вызова (callback functions) - они не вызываются напрямую. Также обратите внимание, что данная функция получает только часть свойств MSG структуры.
Заключение
В данном уроке мы создали пустое но полностью функциональное стандартное окно операционной системы Windows. В следующих уроках мы обсудим разные части WinAPI, а шаблон из данного урока станет основой для наших программ на DirectX и OpenGL.
Читайте также: