Что такое дескриптор экземпляра приложения

Что такое дескриптор экземпляра приложения

Давайте исследуем приведенный код сверху донизу, уделяя внимание каждому встретившемуся вызову функции. Читая следующие подразделы, смотрите на приведенный выше код программы Hello World.

Включение файлов, глобальные переменные и прототипы

Вторая инструкция — это объявление глобальной переменной с типом HWND. Это сокращение обозначает «дескриптор окна» (handle to a window). Программируя для Windows вы часто будете пользоваться дескрипторами для ссылок на внутренние объекты Windows. В данном примере мы используем HWND чтобы ссылаться на главное окно приложения, управление которым осуществляют внутренние механизмы Windows. Мы должны сохранить дескриптор нашего окна потому что многие вызовы API требуют, чтобы им был передан дескриптор того окна, над которым они должны произвести действия. Например, функция UpdateWindow получает один параметр типа HWND, используемый для того, чтобы сообщить ей, какое окно должно быть обновлено. Если мы не передадим дескриптор, функция не будет знать какое окно ей обновлять.

В следующих трех строках находятся объявления функций. Говоря кратко, InitWindowsApp создает и инициализирует главное окно приложения, Run является оберткой для цикла обработки сообщений нашего приложения, а WndProc — это оконная процедура главного окна нашей программы. Мы подробно исследуем эти функции, когда дойдем до того места кода, где они вызываются.

WinMain

WinMain в мире Windows является аналогом функции main в обычном программировании на C++. Прототип WinMain выглядит так:

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

hPrevInstance — В 32-разрядных системах не используется и равно 0.

lpCmdLine — Строка с аргументами командной строки, указанными при запуске программы.

nCmdShow — Вариант отображения окна приложения. Наиболее часто используются варианты SW_SHOW (отображение окна указанных размеров в заданной позиции), SW_SHOWMAXIMIZED (отображение окна, развернутого на весь экран) и SW_SHOWMINIMIZED (отображение свернутого окна). Полный список вариантов отображения и соответствующих констант приведен в библиотеке MSDN.

Если работа функции WinMain завершается успешно, она должна вернуть член wParam сообщения WM_QUIT. Если работа функции завершена до входа в цикл обработки сообщений, она должна вернуть 0. Идентификатор WINAPI определен следующим образом:

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

В прототипе функции WinMain в примере Hello World, для третьего параметра мы указали тип PSTR, а не LPSTR. Это объясняется тем, что в 32-разрядных системах Windows больше нет «дальних указателей». PSTR — это просто указатель на строку символов (т.е., char*).

WNDCLASS и регистрация

Из WinMain мы обращаемся к функции InitWindowsApp. Как уже сообщалось, эта функция выполняет действия, необходимые для инициализации программы. Давайте перейдем к ее коду и исследуем его. InitWindowsApp возвращает true или falsetrue, если инициализация успешно завершена, false если что-то не получилось. Как видно из кода WinMain, мы передаем функции InitWindowsApp копию дескриптора экземпляра нашего приложения и переменную, задающую режим отображения окна. Сама функция WinMain получает эти два значения в своих параметрах.

Первая задача, с которой мы сталкиваемся при инициализации окна, — описать параметры окна и зарегистрировать его в Windows. Параметры окна задаются с помощью структуры данных WNDCLASS. Вот ее определение:

style — Задает стиль окна. В нашем примере мы используем комбинацию флагов CS_HREDRAW и CS_VREDRAW. Она означает, что окно будет перерисовываться при изменении его размеров по горизонтали или по вертикали. Полный список стилей с их описанием приведен в библиотеке MSDN.

lpfnWndProc — Указатель на оконную процедуру. Именно здесь устанавливается связь оконной процедуры с окном. Таким образом окна, созданные на основе одного и того же экземпляра структуры WNDCLASS будут совместно использовать одну и ту же оконную процедуру. Сама оконная процедура будет рассмотрена чуть позже в разделе «Оконная процедура».

cbClsExtra и cbWndExtra — Это дополнительные области памяти, которые вы можете использовать в своих собственных целях. В рассматриваемой программе дополнительные области памяти не нужны и поэтому обоим параметрам присваивается 0.

hInstance — Поле для дескриптора экземпляра нашего приложения. Вспомните, что этот дескриптор был передан нам через функцию WinMain.

hIcon — Дескриптор значка, используемого для окон, создаваемых на основе данного класса. Существует несколько стандартных значков операционной системы и вы можете выбрать один из них. Более подробно этот вопрос рассматривается в MSDN.

hCursor — Тут, аналогично полю hIcon, вы задаете дескриптор курсора приложения, определяющий как будет выглядеть указатель мыши, когда он находится в клиентской области окна. Здесь также есть несколько встроенных типов курсоров. За дополнительной информацией обращайтесь к MSDN.

hbrBackground — Это поле определяет цвет фона клиентской области окна. В нашем примере мы вызываем функцию GetStockObject, которая возвращает дескриптор кисти указанного нами цвета. Описание других встроенных кистей можно найти в MSDN.

lpszMenuName — Задает меню окна. В нашем приложении нет меню, поэтому значение данного поля равно 0.

lpszClassName — Определяет имя создаваемого класса окна. Вы можете выбрать любое имя. В нашем приложении класс называется «Hello». Имя используется для идентификации структуры данных класса, чтобы мы могли обращаться к ней в дальнейшем.

После того, как мы описали параметры класса нашего окна, нам надо зарегистрировать его в Windows. Это выполняется с помощью функции RegisterClass, которая получает указатель на структуру WNDCLASS. В случае успешного завершения функция возвращает 0.

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

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

lpClassName — Имя класса (завершающаяся нулем строка), которое было указано в зарегистрированной структуре WNDCLASS, описывающей параметры окна, которое мы хотим создать. Передавайте имя класса, указанное в той структуре WNDCLASS, которую вы хотите использовать при создании окна.

lpWindowName — Имя (завершающаяся нулем строка), которое мы присваиваем нашему окну; это имя будет также отображаться в заголовке окна.

dwStyle — Описывает стиль создаваемого окна. Используемое в примере Hello World значение WS_OVERLAPPEDWINDOW является комбинацией флагов WS_OVERLAPPED, WS_CAPTION, WS_SYSMENU, WS_THICKFRAME, WS_MINIMIZEBOX и WS_MAXIMIZEBOX. Имена флагов описывают соответствующие характеристики окна. Полный список стилей приведен в MSDN.

x — Позиция по горизонтали верхнего левого угла окна в экранной системе координат.

y — Позиция по вертикали верхнего левого угла окна в экранной системе координат.

nWidth — Ширина окна в пикселях.

nHeight — Высота окна в пикселях.

hWndParent — Дескриптор окна, которое является родителем данного. Создаваемое в примере окно не имеет взаимоотношений с другими окнами, поэтому данному параметру присваивается 0.

hMenu — Дескриптор меню. В приложении Hello World нет меню, поэтому данному параметру присваивается 0.

hInstance — Дескриптор экземпляра приложения с которым связано данное окно.

lpParam — указатель на определяемые пользователем данные.

Когда мы указываем координаты окна (x, y), они отсчитываются относительно верхнего левого угла экрана. При этом положительные значения по оси X отсчитываются, как обычно, вправо, а вот положительные значения по оси Y отсчитываются вниз. Эта система координат, называемая экранными координатами (screen coordinates) или экранным пространством (screen space), показана на рис. 4.

Когда наше окно должно быть уничтожено, мы отправляем сообщение о выходе из приложения (которое прерывает работу цикла сообщений).

В самом конце оконной процедуры мы вызываем функцию DefWindowProc. Это стандартная оконная процедура. В приложении Hello World мы обрабатываем только три сообщения; стандартная оконная процедура определяет поведение при получении всех остальных сообщений, которые мы получаем, но решили не обрабатывать самостоятельно. Например, окно приложения Hello World может быть свернуто, развернуто на весь экран, закрыто, может быть изменен его размер. Вся эта функциональность предоставляется нам стандартной оконной процедурой, и нам не надо писать свои обработчики сообщений, реализующие эти функции. Обратите внимание, что функция DefWindowProc является частью Win32 API.

Функция MessageBox

Последняя функция API, которую мы сейчас рассмотрим — это функция MessageBox. Она очень полезна в тех случаях, когда надо показать какую-то информацию пользователю и получить от него ответ. Прототип функции MessageBox выглядит так:

Значение, возвращаемое функцией MessageBox зависит от типа окна сообщения. Стили окон сообщений и соответствующие им возвращаемые значения перечислены в MSDN.

Источник

Общие сведения о дескрипторах

Дескрипторы создаются вызовами API и определяют ресурсы.

Данные дескриптора

Дескриптор — это относительно небольшой блок данных, который полностью описывает объект для GPU в непрозрачном формате, характерном для GPU. Существует несколько различных типов дескрипторов — отрисовки целевых представлений (RTVs), представлений трафаретов глубины (DSV), представлений ресурсов шейдера (СРВС), неупорядоченных представлений доступа (уавс), представлений постоянного буфера (КБВС) и проб.

Дескрипторы имеют разный размер в зависимости от оборудования GPU. Можно запросить размер SRV, UAV или CBV, вызвав ID3D12Device:: жетдескрипторхандлеинкрементсизе. Дескрипторы показаны в этой документации как неделимые единицы. Ниже приведен пример.

Что такое дескриптор экземпляра приложения. single descriptor. Что такое дескриптор экземпляра приложения фото. Что такое дескриптор экземпляра приложения-single descriptor. картинка Что такое дескриптор экземпляра приложения. картинка single descriptor.

Дескрипторы создаются вызовами API и будут включать такие сведения, как ресурс и MIP-карты, которые должен содержать дескриптор.

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

Дескрипторы объектов не обязательно должны освобождаться или освобождаться. Драйверы не присоединяют выделения для создания дескриптора. Дескриптор, однако, может кодировать ссылки на другие выделения, для которых приложение владеет временем существования. Например, дескриптор для SRV должен содержать виртуальный адрес ресурса D3D (например, текстуру), на который ссылается SRV. Это обязанность приложения, чтобы убедиться, что он не использует дескриптор SRV, когда базовый ресурс D3D, от которого он зависит, был уничтожен или изменен (например, объявлен как нерезидентный).

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

Дескрипторы дескрипторов

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

Дескрипторы ЦП предназначены для немедленного использования, например для копирования, где должны быть идентифицированы источник и назначение. Сразу после использования (например, вызов ID3D12GraphicsCommandList:: омсетрендертаржетс) они могут быть использованы повторно, или их базовая куча может быть удалена.

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

Эти методы возвращают следующие структуры:

Поскольку размер дескрипторов зависит от оборудования, для получения инкремента между каждым дескриптором в куче используется:

Для копирования дескрипторов и передачи дескрипторов в вызовы API можно легко смещать начальное расположение с числом инкрементов. Разыменование маркера необязательно, как если бы он был допустимым указателем ЦП, а также для анализа битов в пределах маркера.

Некоторые вспомогательные структуры были добавлены с элементами инициализации, чтобы упростить управление дескрипторами.

Дескрипторы null

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

Оставшаяся часть дескриптора должна быть заполнена как можно больше. Например, в случае с представлениями ресурсов шейдера (СРВС) дескриптор можно использовать для различения типа представления (Texture1D, Texture2D и т. д.). Числовые параметры в дескрипторе представления, например число MIP-карты, должны быть заданы для значений, допустимых для ресурса.

Во многих случаях существует определенное поведение для доступа к несвязанному ресурсу, например СРВС, возвращающего значения по умолчанию. Они будут учитываться при доступе к дескриптору NULL, если тип доступа шейдера совместим с типом дескриптора. Например, если шейдер ожидает Texture2D SRV и обращается к NULL SRV, определенному как Texture1D, поведение не определено и может привести к сбросу устройства.

В сводке, чтобы создать дескриптор null, передайте null параметр предварительного источника при создании представления с такими методами, как креатешадерресаурцевиев. В параметре описания представления пдеск Задайте конфигурацию, которая будет работать, если ресурс не равен null (в противном случае может произойти сбой на определенном оборудовании).

Однако корневые дескрипторы не должны иметь значение null.

На 1 класса оборудовании (см. раздел уровни оборудования), все дескрипторы, которые привязаны (посредством таблиц дескрипторов), должны быть инициализированы либо как реальные дескрипторы, либо как дескрипторы null, даже если нет доступа к оборудованию, в противном случае поведение не определено.

На партнеров оборудовании это относится к привязанным дескрипторам CBV и UAV, но не к дескрипторам SRV.

На Tier3 оборудовании нет ограничений на это, при условии, что неинициализированные дескрипторы никогда не обращаются.

Дескрипторы по умолчанию

Дескрипторы по умолчанию нельзя использовать с представлением структуры ускорения райтраЦинг, так как предоставленный параметр предварительного источника должен иметь значение NULL, а расположение должно передаваться через [D3D12_RAYTRACING_ACCELERATION_STRUCTURE_SRV]/Windows/Win32/API/d3d12/NS-d3d12-d3d12_raytracing_acceleration_structure_srv).

Источник

Основы программирования для Win32 API

Материал рассматривается на примере пакета Borland C++ 5.5 command line tools

Многие компиляторы для Windows «понимают» такую стартовую функцию. Однако при этом они создают хотя и 32-битное, но консольное приложение. Пример 1 (example1.cpp): Компилируем: Запускаем:
Что такое дескриптор экземпляра приложения. . Что такое дескриптор экземпляра приложения фото. Что такое дескриптор экземпляра приложения-. картинка Что такое дескриптор экземпляра приложения. картинка .

Кроме того, компилятору и компоновщику нужно сообщить о том, что вы делаете графическое приложение. Для bcc32 это опция -tW: Что такое дескриптор экземпляра приложения. . Что такое дескриптор экземпляра приложения фото. Что такое дескриптор экземпляра приложения-. картинка Что такое дескриптор экземпляра приложения. картинка .

Если же вы соскучитесь по черному консольному окошку, его можно в любой момент создать при помощи вызова Win32 API

Окно приложения может содержать строку заголовка title bar (1), строку меню menu bar (2), системное меню system menu (3), кнопку сворачивания окна minimize box (4), кнопку разворачивания окна maximize box (5), рамку изменения размеров sizing border (6), клиентскую область client area (7), горизонтальную и вертикальную полосы прокрутки scroll bars (8):
Что такое дескриптор экземпляра приложения. appwnd. Что такое дескриптор экземпляра приложения фото. Что такое дескриптор экземпляра приложения-appwnd. картинка Что такое дескриптор экземпляра приложения. картинка appwnd.

Меню, строка заголовка с системными кнопками, системное меню, рамка изменения размеров и полосы прокрутки относятся к области окна, называемой неклиентской областью (non-client area). С неклиентской областью Windows справляется сама, а вот за содержимое и обслуживание клиентской области отвечает приложение.

Программа для Win32 обычно состоит из следующих блоков:

Класс регистрируется при помощи функции: При успешном завершении функция возвращает целочисленный код, соответствующий строке-имени класса в общесистемной таблице строк (такой код называется атомом). При ошибке возвращается 0.

Для создания окна вызывается функция:

Процедура обработки событий должна вернуть определенное 32-битное значение, интерпретация которого также зависит от типа сообщения. В большинстве случаев, если сообщение успешно обработано, процедура возвращает значение 0.

Процедура обработки событий не должна игнорировать сообщения. Если процедура не обрабатывает какое-то сообщение, она должна вернуть его системе для обработки по умолчанию. Для этого вызывается функция:

Все описанное в данном параграфе суммируется в примере 4 (example4.cpp):

Приведенный пример создает окно с кнопкой «My button», при нажатии на которую вылезает окно-сообщение:
Что такое дескриптор экземпляра приложения. . Что такое дескриптор экземпляра приложения фото. Что такое дескриптор экземпляра приложения-. картинка Что такое дескриптор экземпляра приложения. картинка .

Эти ресурсы можно внедрить в виде шестнадцатеричных кодов непосредственно в файл ресурсов:

Следует отметить, что первая иконка в ресурсах будет использоваться «Проводником» как иконка исполняемого файла.

Для закрепления полученных сведений, давайте добавим к примеру 4 какую-нибудь иконку и такое меню:
Что такое дескриптор экземпляра приложения. menus. Что такое дескриптор экземпляра приложения фото. Что такое дескриптор экземпляра приложения-menus. картинка Что такое дескриптор экземпляра приложения. картинка menus.

Для этого создаем файл ресурсов (example4a.rc):

Для перевода файла описания ресурсов в бинарный вид используется компилятор ресурсов Borland Resource Compiler: В результате получается файл example4a.res, который потребуется в процессе компоновки.

В примере 4 надо изменить строки на

Чтобы программа не была такой скучной, изменим обработчик сообщения WM_COMMAND : В результате при выборе того или иного пункта меню выводится окно-сообщение с кодом команды.

Теперь компоновка программы будет более сложной, поэтому bcc32 с этой задачей не справится. В этом примере компилятор будет использоваться только для компилирования (запускаем с ключом ): В результате получаем объектный файл example4a.obj.

Итак, компонуем модифицированный пример 4:

Эта же иконка отображается в строке заголовка главного окна программы. Под строкой заголовка отображается созданное нами меню. При выборе любой команды меню появляется окно-сообщение с кодом команды. При выборе команды «Exit» программа завершается.
Что такое дескриптор экземпляра приложения. . Что такое дескриптор экземпляра приложения фото. Что такое дескриптор экземпляра приложения-. картинка Что такое дескриптор экземпляра приложения. картинка .

Если написать подходящий сценарий компиляции, то для компиляции вашего проекта придется набирать лишь команду:

Большинство приложений использует диалоговые окна для запроса у пользователя дополнительной информации для выполнения каких-либо команд. Например, команда открытия файла требует указания имени файла, так что приложение создает диалоговое окно, чтобы запросить у пользователя имя файла. Пока пользователь не укажет имя файла, команда не будет выполнена. После этого программа уничтожает это диалоговое окно. В этом случае используется модальное диалоговое окно. Другой пример: текстовый редактор может использовать немодальное диалоговое окно, для команды поиска. Пока редактор ищет введенную фразу, диалоговое окно остается на экране. Более того, пользователь может вернуться к редактированию текста, не закрывая диалог поиска. Либо пользователь может ввести другую фразу для поиска. Такое диалоговое окно остается открытым, пока приложение не завершится или пользователь непосредственно не выберет команду закрытия этого диалога.

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

Немодальное диалоговое окно появляется поверх указанного в качестве родительского окна, но не блокирует его. Диалоговое окно остается поверх родительского окна, даже если оно неактивно. Программа сама отвечает за отображение/сокрытие окна (с помощью стиля WS_VISIBLE и функции ShowWindow ). Сообщения для немодального диалогового окна оказываются в основной очереди сообщений программы. Чтобы эти сообщения были корректно обработаны, следует включить в цикл обработки сообщений вызов функции:

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

Шаблон диалогового окна в ресурсах задается следующим образом:

После заголовка блока идет ряд необязательных операторов-параметров диалога (property-statements) в любом порядке:

Вот пример диалога, содержащего простое статическое текстовое поле и кнопку «OK»:

Добавим этот диалог к ресурсам примера 4. В текст программы добавим две глобальных переменных:

Изменим обработчик сообщения WM_COMMAND следующим образом:

Теперь в текст программы необходимо добавить диалоговую процедуру:

Для многих управляющих элементов определены специальные сообщения, которые управляют видом или поведением таких элементов или позволяют получить параметры их состояния. Как и для любого другого окна эти сообщения можно отправить с помощью функции:

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

Для функции отсылки сообщений есть специальный вариант, предназначенный для более удобной работы с управляющими элементами:

Кроме предопределенных управляющих элементов, Windows предоставляет еще набор стандартных управляющих элементов посредством библиотеки Common Controls Library (COMCTL32.DLL). Чтобы воспользоваться ей, в тест программы надо включить заголовочный файл commctrl.h и добавить в блок инициализации программы вызов функции:

Ресурсы значительно облегчают работу программиста по созданию интерфейса программы, поэтому весьма привлекательно использовать ресурсы для описания главного окна. Это возможно в случае, если главное окно реализовано в виде немодального диалога.

Пример 5 демонстрирует использование немодального диалога в приложении типа «блокнот».

Файл example5.h содержит константы-идентификаторы команд меню и элементов диалога.

Файл example5.rc описывает ресурсы программы: иконку, меню и шаблон диалога.

Источник

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *

Что такое дескриптор экземпляра приложения. fa1 04. Что такое дескриптор экземпляра приложения фото. Что такое дескриптор экземпляра приложения-fa1 04. картинка Что такое дескриптор экземпляра приложения. картинка fa1 04.

Рис. 4. Экранное пространство

Функция CreateWindow возвращает дескриптор созданного ею окна (значение типа HWND). Если создать окно не удалось, значение дескриптора равно нулю. Помните, что дескриптор — это способ сослаться на конкретное окно, управляемое Windows. Многие вызовы API требуют указания HWND, чтобы знать с каким окном производятся действия.

Последние два обращения к функциям API из функции InitWindowsApp предназначены для отображения окна. Сперва мы вызываем функцию ShowWindow и передаем ей дескриптор только что созданного окна, чтобы Windows знала, какое окно должно быть показано. Мы также передаем число, определяющее в каком виде будет показано окно (обычным, свернутым, развернутым на весь экран и т.д.). Здесь лучше всего указать значение nShowCmd, которое было передано нам в одном из аргументов WinMain. Конечно, вы можете жестко задать значение в коде, но это не рекомендуется. После отображения окна мы должны обновить его. Это делает функция UpdateWindow; она получает один аргумент, являющийся дескриптором обновляемого окна.

Если в функции InitWindowsApp были выполнены все описанные выше действия, значит инициализация завершена; мы возвращаем true, чтобы сообщить об успешном завершении функции.

Цикл сообщений

Успешно завершив инициализацию, мы переходим к сердцу программы — циклу обработки сообщений. В программе Hello World, мы заключили цикл обработки сообщений в функцию с именем Run.

Начинается функция Run с объявления переменной msg типа MSG, являющейся структурой данных, представляющей сообщения Windows. Ее определение выглядит следующим образом:

hwnd — Идентифицирует окно, которому предназначено сообщение.

message — Одна из предопределенных констант, идентифицирующих сообщение (например, WM_QUIT).

wParam — Дополнительная информация о сообщении. Зависит от конкретного сообщения.

lParam — Дополнительная информация о сообщении. Зависит от конкретного сообщения.

time — Время, когда сообщение было помещено в очередь.

pt — Координаты указателя мыши (x, y) в экранном пространстве в тот момент, когда сообщение было помещено в очередь.

Затем мы входим в цикл обработки сообщений. Функция GetMessage будет возвращать true до тех пор, пока из очереди не будет извлечено сообщение WM_QUIT; следовательно цикл будет выполняться, пока не будет получено сообщение WM_QUIT. Функция GetMessage извлекает сообщение из очереди и заполняет члены нашей структуры MSG. Если GetMessage возвращает true, будут вызваны еще две функции: TranslateMessage и DispatchMessage. TranslateMessage выполняет трансляцию сообщений Windows, в частности преобразование виртуальных кодов клавиш в коды символов. DispatchMessage направляет сообщение соответствующей оконной процедуре.

Оконная процедура

Мы уже упоминали ранее, что оконная процедура — это то место, где мы указываем код, который должен выполняться при получении окном приложения каких-либо сообщений. В программе Hello World оконная процедура называется WndProc. Ее прототип выглядит так:

Функция возвращает значение типа LRESULT (в действительности это целое число типа long), сообщающее успешно или нет завершена работа функции. Идентификатор CALLBACK сообщает, что это функция обратного вызова (callback function). Это означает, что вызов данной функции осуществляют внутренние механизмы Windows. Посмотрите на исходный код приложения Hello World: вы нигде не найдете явно указанного нами вызова оконной процедуры; Windows вызывает ее за нас, когда окну требуется обработать поступившее сообщение.

В сигнатуре оконной процедуры указано четыре параметра:

hwnd — Идентифицирует окно, которому предназначено сообщение.

uMsg — Предопределенная константа, идентифицирующая конкретное сообщение. Например, сообщению о выходе из приложения соответствует константа WM_QUIT. Префикс WM означает «оконное сообщение» (Window Message). Существуют сотни предопределенных оконных сообщений, описание которых можно найти в MSDN.

wParam — Дополнительная информация о сообщении. Зависит от конкретного сообщения.

lParam — Дополнительная информация о сообщении. Зависит от конкретного сообщения.

Наша оконная процедура обрабатывает три сообщения: WM_LBUTTONDOWN, WM_KEYDOWN и WM_DESTROY. Сообщение WM_LBUTTONDOWN посылается когда пользователь нажимает левую кнопку мыши и при этом указатель мыши находится внутри клиентской области окна. Сообщение WM_KEYDOWN отправляется если нажата какая-нибудь клавиша на клавиатуре. Сообщение WM_DESTROY будет получено в том случае, если окно должно быть уничтожено. Наш код очень простой; получив сообщение WM_LBUTTONDOWN мы выводим окно сообщений с текстом «Hello, World»:

Когда окно получает сообщение WM_KEYDOWN мы проверяем какая именно клавиша была нажата. Параметр wParam, передаваемый в оконную процедуру, содержит виртуальный код клавиши (virtual key kode), указывающий какая клавиша нажата. Вы можете думать о виртуальном коде клавиши как об идентификаторе конкретной клавиши на клавиатуре. В заголовочном файле Windows содержится список виртуальных кодов клавиш, которые мы можем использовать при проверке того, какая именно клавиша была нажата (например, чтобы проверить была ли нажата клавиша Esc, мы используем константу виртуального кода клавиши VK_ESCAPE).

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