Соглашения о написании кода Windows
Если вы не знакомы с программированием для Windows, это может быть смущает, когда вы впервые увидите программу Windows. Код заполняется странными определениями типов , такими как DWORD_PTR и LPRECT, а переменные имеют такие имена, как hWnd и pwsz (венгерская нотация). Стоит уделить некоторое время изучению некоторых соглашений о кодировании Windows.
Подавляющее большинство API Windows состоит из функций или интерфейсов COM. Очень немногие API Windows предоставляются в виде классов C++. (Заметным исключением является GDI+, один из интерфейсов API двухмерной графики.)
Определения типов
Заголовки Windows содержат много типов. Многие из них определены в файле заголовка WinDef.h. Вот некоторые из них, с которыми вы часто столкнетесь.
Целочисленные типы
Тип данных | Размер | Подписал? |
---|---|---|
BYTE | 8 бит | Без знака |
DWORD | 32 бита | Без знака |
INT32 | 32 бита | Со знаком |
INT64 | 64 бита | Со знаком |
LONG | 32 бита | Со знаком |
LONGLONG | 64 бита | Со знаком |
UINT32 | 32 бита | Без знака |
UINT64 | 64 бита | Без знака |
ULONG | 32 бита | Без знака |
ULONGLONG | 64 бита | Без знака |
WORD | 16 бит | Без знака |
Как видите, в этих типах имеется определенная избыточность. Некоторые из этих перекрытий просто связаны с историей API Windows. Перечисленные здесь типы имеют фиксированный размер, а размеры одинаковы как в 32-разрядных, так и в 64-разрядных приложениях. Например, тип DWORD всегда имеет ширину 32 бита.
Логический тип
BOOL — это псевдоним типа для int, отличный от bool C++, а также от других типов, представляющих логическое значение. Файл заголовка WinDef.h
также определяет два значения для использования с BOOL.
#define FALSE 0
#define TRUE 1
Однако, несмотря на это определение TRUE, большинство функций, возвращающих тип BOOL , могут возвращать любое ненулевое значение, указывающее логическую истину. Поэтому всегда следует писать следующее:
// Right way.
if (SomeFunctionThatReturnsBoolean())
{
...
}
// or
if (SomeFunctionThatReturnsBoolean() != FALSE)
{
...
}
а не это:
if (result == TRUE) // Wrong!
{
...
}
BOOL — это целочисленный тип, который не является взаимозаменяемым с логическим значением C++.
Типы указателей
Windows определяет множество типов данных формы, указывающих на X. Обычно они имеют префикс P- или LP- в имени. Например, LPRECT — это указатель на RECT, где RECT — это структура, описывающая прямоугольник. Следующие объявления переменных эквивалентны.
RECT* rect; // Pointer to a RECT structure.
LPRECT rect; // The same
PRECT rect; // Also the same.
В 16-разрядных архитектурах (16-разрядная версия Windows) существует 2 типа указателей: P — "указатель", а LP — "длинный указатель". Длинные указатели (также называемые дальними указателями) были необходимы для обращения к диапазонам памяти за пределами текущего сегмента. Префикс LP был сохранен, чтобы упростить перенос 16-разрядного кода в 32-разрядную версию Windows. Сегодня различий нет, и все эти типы указателей эквивалентны. Избегайте использования этих префиксов; или, если вы должны использовать один, используйте P.
Типы точности указателя
Следующие типы данных всегда имеют размер указателя, то есть 32 бита в ширину в 32-разрядных приложениях и 64 бита в ширину в 64-разрядных приложениях. Размер определяется во время компиляции. Если 32-разрядное приложение работает в 64-разрядной версии Windows, эти типы данных по-прежнему имеют ширину 4 байта. (64-разрядное приложение не может работать в 32-разрядной версии Windows, поэтому обратная ситуация не возникает.)
- DWORD_PTR
- INT_PTR
- LONG_PTR
- ULONG_PTR
- UINT_PTR
Эти типы используются в ситуациях, когда целое число может быть приведено к указателю. Они также используются для определения переменных для арифметики указателя и для определения счетчиков цикла, которые выполняют итерацию по всему диапазону байтов в буферах памяти. В более общем случае они появляются в местах, где существующее 32-разрядное значение было расширено до 64 бит в 64-разрядной версии Windows.
Венгерская нотация
Венгерская нотация — это практика добавления префиксов к именам переменных для получения дополнительных сведений о переменной. (Изобретатель нотации, Чарльз Simonyi, был венгерским, отсюда и ее название).
В первоначальном виде венгерская нотация предоставляет семантическую информацию о переменной, сообщая о предполагаемом использовании. Например, i означает индекс, cb означает размер в байтах ("количество байтов"), а rw и col — средние номера строк и столбцов. Эти префиксы предназначены для предотвращения случайного использования переменной в неправильном контексте. Например, если бы вы увидели выражение rwPosition + cbTable
, вы бы знали, что номер строки добавляется к размеру, что почти наверняка является ошибкой в коде.
Более распространенная форма венгерской нотации использует префиксы для предоставления сведений о типе , например dw для DWORD и w для WORD.
Примечание
Основные рекомендации C++ не рекомендуют нотацию префикса (например, венгерскую нотацию). См . раздел NL.5. Избегайте сведений о типе кодирования в именах. На внутреннем сервере команда Windows больше не использует его. Но его использование остается в примерах и документации.