- •Оглавление
- •Глава 1 Введение 7
- •Глава 2 Основные понятия 10
- •Глава 3 Рисование текста 42
- •Глава 4. Главное о графике 65
- •Глава 5 Клавиатура 180
- •Глава 6 Мышь 214
- •Глава 7 Таймер 233
- •Глава 8 Дочерние окна управления 247
- •Глава 1 Введение
- •Основные правила
- •1.2 Краткая история Windows
- •Глава 2 Основные понятия
- •2.1 Отличительная особенность Windows
- •2.1.1 Графический интерфейс пользователя
- •2.1.2 Концепции и обоснование gui
- •2.1.3 Содержимое интерфейса пользователя
- •2.1.4 Преимущество многозадачности
- •2.1.5 Управление памятью
- •2.1.6 Независимость графического интерфейса от оборудования
- •2.1.7 Соглашения операционной системы Windows
- •2.1.8 Вызовы функций
- •2.1.9 Объектно-ориентированное программирование
- •2.1.10 Архитектура, управляемая событиями
- •2.1.11 Оконная процедура
- •2.2 Ваша первая программа для Windows
- •2.2.1 Что в этой программе неправильно?
- •2.2.2 Файлы hellowin
- •2.2.3 Файл исходного текста программы на языке с
- •2.2.4 Вызовы функций Windows
- •2.2.5 Идентификаторы, написанные прописными буквами
- •2.2.6 Новые типы данных
- •2.2.7 Описатели
- •2.2.8 Венгерская нотация
- •2.2.9 Точка входа программы
- •2.2.10 Регистрация класса окна
- •2.2.11 Создание окна
- •2.2.12 Отображение окна
- •2.2.13 Цикл обработки сообщений
- •2.2.14 Оконная процедура
- •2.2.15 Обработка сообщений
- •2.2.15 Воспроизведение звукового файла
- •2.2.16 Сообщение wm_paint
- •2.2.17 Сообщение wm_destroy
- •2.3 Сложности программирования для Windows
- •2.3.1 Функции обратного вызова
- •2.3.2 Синхронные и асинхронные сообщения
- •Глава 3 Рисование текста
- •3.1 Рисование и обновление
- •3.1.1 Сообщение wm_paint
- •3.1.2 Действительные и недействительные прямоугольники
- •3.2 Введение в графический интерфейс устройства (gdi)
- •3.2.1 Контекст устройства
- •3.2.2 Получение описателя контекста устройства. Первый метод
- •3.2.3 Структура информации о рисовании
- •3.2.4 Получение описателя контекста устройства. Второй метод
- •3.2.5 Функция TextOut. Подробности
- •3.2.6 Системный шрифт
- •3.2.7 Размер символа
- •3.2.8 Метрические параметры текста. Подробности
- •3.2.9 Форматирование текста
- •3.2.10 Соединим все вместе
- •3.2.11 Оконная процедура программы sysmets1
- •3.2.12 Не хватает места!
- •3.2.13 Размер рабочей области
- •3.3 Полосы прокрутки
- •3.3.1 Диапазон и положение полос прокрутки
- •3.3.2 Сообщения полос прокрутки
- •3.3.3 Прокрутка в программе sysmets2
- •3.3.4 Структурирование вашей программы для рисования
- •Глава 4. Главное о графике
- •4.1 Концепция gdi
- •4.2 Структура gdi
- •4.2.1 Типы функций
- •4.2.2 Примитивы gdi
- •4.2.3 Другие аспекты
- •4.3 Контекст устройства
- •4.3.1 Получение описателя контекста устройства
- •4.3.3 Получение информации из контекста устройства
- •4.3.4 Размер устройства
- •4.3.5 О цветах
- •4.3.6 Атрибуты контекста устройства
- •4.3.7 Сохранение контекста устройства
- •4.4 Рисование отрезков
- •4.4.1 Ограничивающий прямоугольник
- •4.4.2 Сплайны Безье
- •4.4.3 Использование стандартных перьев
- •4.4.4 Создание, выбор и удаление перьев
- •4.4.5 Закрашивание пустот
- •4.4.6 Режимы рисования
- •4.5 Рисование закрашенных областей
- •4.5.1 Функция Polygon и режим закрашивания многоугольника
- •4.5.2 Закрашивание внутренней области
- •4.6 Режим отображения
- •4.6.1 Координаты устройства (физические координаты) и логические координаты
- •4.6.2 Системы координат устройства
- •4.6.3 Область вывода и окно
- •4.6.4 Работа в режиме mm_text
- •4.6.5 Метрические режимы отображения
- •4.6.6 Ваши собственные режимы отображения
- •Режим отображения mm_isotropic
- •Mm_anisotropic: растягивание изображения
- •4.6.7 Программа whatsize
- •4.7 Прямоугольники, регионы и отсечение
- •4.7.1 Работа с прямоугольниками
- •4.7.2 Случайные прямоугольники
- •4.7.3 Создание и рисование регионов
- •4.7.4 Отсечения: прямоугольники и регионы
- •4.7.5 Программа cover
- •4.8 Пути
- •4.8.1 Создание и воспроизведение путей
- •4.8.2 Расширенные перья
- •4.9 Битовые образы
- •4.9.1 Цвета и битовые образы
- •4.9.2 Битовые образы, не зависящие от устройства (dib)
- •4.9.3 Файл dib
- •4.9.4 Упакованный формат хранения dib
- •4.9.5 Отображение dib
- •4.9.6 Преобразование dib в объекты "битовые образы"
- •4.10 Битовый образ — объект gdi
- •4.10.1 Создание битовых образов в программе
- •4.10.2 Формат монохромного битового образа
- •4.10.3 Формат цветного битового образа
- •4.10.4 Контекст памяти
- •4.10.5 Запись пикселей на устройство отображения
- •Функция PatBlt
- •Координаты Blt
- •4.10.6 Перенос битов с помощью функции BitBlt
- •4.10.7 Функция DrawBitmap
- •4.10.8 Использование других rop кодов
- •4.10.9 Дополнительные сведения о контексте памяти
- •4.10.10 Преобразования цветов
- •4.10.11 Преобразования режимов отображения
- •4.10.12 Растяжение битовых образов с помощью функции StretchBlt
- •4.10.13 Кисти и битовые образы
- •4.11 Метафайлы
- •4.11.1 Простое использование метафайлов памяти
- •4.11.2 Сохранение метафайлов на диске
- •4.12 Расширенные метафайлы
- •4.12.1 Делаем это лучше
- •4.12.2 Базовая процедура
- •4.12.3 Заглянем внутрь
- •4.12.4 Вывод точных изображений
- •4.13 Текст и шрифты
- •4.13.1 Вывод простого текста
- •4.13.2 Атрибуты контекста устройства и текст
- •4.13.3 Использование стандартных шрифтов
- •4.13.4 Типы шрифтов
- •4.13.5 Шрифты TrueType
- •4.13.6 Шрифт ezfont
- •4.13.7 Внутренняя работа
- •4.13.8 Форматирование простого текста
- •4.13.9 Работа с абзацами
- •Глава 5 Клавиатура
- •5.1 Клавиатура. Основные понятия
- •5.1.1 Игнорирование клавиатуры
- •5.1.2 Фокус ввода
- •5.1.3 Аппаратные и символьные сообщения
- •5.2 Аппаратные сообщения
- •5.2.1 Системные и несистемные аппаратные сообщения клавиатуры
- •5.2.2 Переменная lParam
- •Счетчик повторений
- •Скан-код oem
- •Флаг расширенной клавиатуры
- •Код контекста
- •Флаг предыдущего состояния клавиши
- •Флаг состояния клавиши
- •5.2.3 Виртуальные коды клавиш
- •5.2.4 Состояние клавиш сдвига и клавиш-переключателей
- •5.2.5 Использование сообщений клавиатуры
- •5.4 Символьные сообщения
- •5.4.1 Сообщения wm_char
- •5.4.2 Сообщения немых символов
- •5.6 Каретка (не курсор)
- •5.6.1 Функции работы с кареткой
- •5.6.2 Программа typer
- •5.7 Наборы символов Windows
- •5.7.1 Набор символов oem
- •Поддержка языков различных стран в dos
- •5.7.2 Набор символов ansi
- •5.7.3 Наборы символов oem, ansi и шрифты
- •5.8 Решение проблемы с использованием системы unicode
- •5.8.2 Unicode и библиотека с
- •5.8.3 Типы данных, определенные в Windows для Unicode
- •5.8.4 Unicode- и ansi-функции в Windows
- •5.8.5 Строковые функции Windows
- •5.8.6 Создание программ, способных использовать и ansi, и Unicode
- •5.8.7 Ресурсы
- •5.8.8 Текстовые файлы
- •5.8.9 Перекодировка строк из Unicode в ansi и обратно
- •Глава 6 Мышь
- •6.1 Базовые знания о мыши
- •6.1.1 Несколько кратких определений
- •6.2 Сообщения мыши, связанные с рабочей областью окна
- •6.2.1 Простой пример обработки сообщений мыши
- •6.2.3 Двойные щелчки клавиш мыши
- •6.3 Сообщения мыши нерабочей области
- •6.3.1 Сообщение теста попадания
- •6.3.2 Сообщения порождают сообщения
- •6.4 Тестирование попадания в ваших программах
- •6.4.1 Гипотетический пример
- •6.4.2 Пример программы
- •6.4.3 Эмуляция мыши с помощью клавиатуры
- •6.4.4 Добавление интерфейса клавиатуры к программе checker
- •6.4.5 Использование дочерних окон для тестирования попадания
- •6.4.6 Дочерние окна в программе checker
- •6.5 Захват мыши
- •6.5.1 Рисование прямоугольника
- •6.5.2 Решение проблемы — захват
- •6.5.3 Программа blokout2
- •Глава 7 Таймер
- •7.1 Основы использования таймера
- •7.1.1 Система и таймер
- •7.1.2 Таймерные сообщения не являются асинхронными
- •7.2 Использование таймера: три способа
- •7.2.1 Первый способ
- •Что делать, если таймер недоступен
- •Пример программы
- •7.2.2 Второй способ
- •Пример программы
- •7.2.3 Третий способ
- •7.3 Использование таймера для часов
- •7.3.1 Позиционирование и изменение размеров всплывающего окна
- •7.3.2 Получение даты и времени
- •7.3.3 Обеспечение международной поддержки
- •7.3.4 Создание аналоговых часов
- •7.4 Стандартное время Windows
- •7.5 Анимация
- •Глава 8 Дочерние окна управления
- •8.1 Класс кнопок
- •8.1.1 Создание дочерних окон
- •8.1.2 Сообщения дочерних окон родительскому окну
- •8.1.3 Сообщения родительского окна дочерним окнам
- •8.1.4 Нажимаемые кнопки
- •8.1.5 Флажки
- •8.1.6 Переключатели
- •8.1.7 Окна группы
- •8.1.8 Изменение текста кнопки
- •8.1.9 Видимые и доступные кнопки
- •8.1.10 Кнопки и фокус ввода
- •8.2 Дочерние окна управления и цвета
- •8.2.1 Системные цвета
- •8.2.2 Цвета кнопок
- •8.2.3 Сообщение wm_ctlcolorbtn
- •8.2.4 Кнопки, определяемые пользователем
- •8.3 Класс статических дочерних окон
- •8.4 Класс полос прокрутки
- •8.4.1 Программа colors1
- •8.4.2 Интерфейс клавиатуры, поддерживаемый автоматически
- •8.4.3 Введение новой оконной процедуры
- •8.4.5 Закрашивание фона
- •8.4.5 Окрашивание полос прокрутки и статического текста
- •8.5 Класс редактирования
- •8.5.1 Стили класса редактирования
- •8.5.2 Коды уведомления управляющих окон редактирования
- •8.5.3 Использование управляющих окон редактирования
- •8.5.4 Сообщения управляющему окну редактирования
- •8.6 Класс окна списка
- •8.6.1 Стили окна списка
- •8.6.2 Добавление строк в окно списка
- •8.6.3 Выбор и извлечение элементов списка
- •8.6.4 Получение сообщений от окон списка
- •8.6.5 Простое приложение, использующее окно списка
- •8.6.6 Список файлов
- •Использование атрибутов файлов
- •Упорядочивание списков файлов
- •8.6.7 Утилита Head для Windows
4.6.6 Ваши собственные режимы отображения
Два оставшихся режима отображения называются MM_ISOTROPIC и MM_ANISOTROPIC. Это два режима отображения, в которых Windows позволяет вам изменять протяженность области вывода и окна, и тем самым менять коэффициент масштабирования, который использует Windows для преобразования логических координат в физические. Слово isotropic означает одинаковый во всех направлениях; anisotropic — неодинаковый. Также как и в метрических режимах отображения, рассмотренных ранее, MM_ISOTROPIC использует одинаковые измерения по осям. Логические единицы измерения по оси x имеют такое же представление в физических единицах, как и логические единицы измерения по оси y. Это помогает тогда, когда вам необходимо создать изображение с правильным относительным размером, независимо от относительного размера пикселя дисплея.
Отличие между режимом MM_ISOTROPIC и метрическими режимами отображения в том, что в режиме MM_ISOTROPIC вы можете управлять физическим размером логической единицы измерения. Вы можете сделать физический размер логической единицы измерения таким, что ваши рисунки всегда будут целиком содержаться в рабочей области окна, либо в уменьшенном, либо в увеличенном виде. Программа для Windows может обрабатывать изменение размеров изображения путем соответствующего изменения протяженностей окна и области вывода. В этом случае программа может использовать одни и те же логические единицы измерения при вызове функций рисования независимо от размеров окна.
Иногда режим отображения MM_TEXT и другие метрические режимы называют полностью принудительными режимами отображения. Это означает, что вы не имеете возможности изменять протяженности окна и области вывода, а значит, и масштаб преобразования логических координат в координаты устройства. MM_ISOTROPIC — это частично принудительный режим отображения. Windows позволяет вам изменять протяженности окна и области вывода, но система преобразует их таким образом, чтобы логические координаты x и y имели одинаковое представление о физических единицах измерения.
Режим отображения MM_ANISPTROPIC — непринудительный. Вы можете изменять протяженности окна и области вывода. Система эти значения не преобразует.
Режим отображения mm_isotropic
Режим отображения MM_ISOTROPIC идеален для использования выбранных пользователем осей координат при сохранении равенства логических единиц измерения по обеим осям. Прямоугольники с равными логическими высотой и шириной отображаются как квадраты, эллипсы с равными логическими высотой и шириной отображаются как окружности.
Когда вы впервые устанавливаете режим отображения MM_ISOTROPIC, Windows использует те же протяженности окна и области вывода, что и в режиме MM_LOMETRIC. (Тем не менее, будьте внимательны!) Разница состоит в том, что теперь вы можете изменять протяженности в соответствии со своими предпочтениями, используя функции SetWindowExtEx и SetViewportExtEx. Затем Windows изменит их таким образом, чтобы логические координаты по обеим осям имели одинаковое представление в физических координатах.
Чаще всего вы будете использовать параметры функции SetWindowExtEx как желаемые логические размеры логического окна, а параметры функции SetViewportExtEx — как текущую высоту и ширину рабочей области.
Когда Windows преобразует эти протяженности, она стремится привести в соответствие логическое окно к физической области вывода, что может привести в результате к тому, что часть области вывода окажется за пределами логического окна. Нужно вызывать функцию SetWindowExtEx до вызова функции SetViewportExtEx для того, чтобы сделать использование пространства рабочей области максимально эффективным.
Например, предположим, вы хотите иметь традиционную реальную систему координат с одним квадрантом, где точка (0, 0) — левый нижний угол рабочей области, а ширина и высота меняются в интервале от 0 до 32767. Вы также хотите, чтобы единицы по осям x и y имели одинаковое физическое представление. Для этого сделайте следующее:
SetMapMode(hdc, MM_ISOTROPIC);
SetWindowExtEx(hdc, 32767, 32767, NULL);
SetViewportExtEx(hdc, cxClient, -cyClient, NULL);
SetViewportOrgEx(hdc, 0, cyClient, NULL);
Если затем вы получите значения протяженностей окна и области вывода при помощи GetWindowExtEx и GetViewportExtEx, то они не будут равны заданным вами значениям. Windows преобразует протяженности на базе коэффициента сжатия устройства отображения (aspect ratio) так, чтобы логические единицы измерения по обеим осям имели одинаковые физические размеры.
Если ширина рабочей области больше чем высота (в физических единицах), то Windows изменяет протяженность по x так, что логическое окно становится уже, чем физическая область вывода. Логическое окно помещается в левой части рабочей области:
Вы не можете отображать что-либо в правой части рабочей области за границей оси x, поскольку это требует задания логической координаты x со значением, превышающим 32767.
Если высота рабочей области меньше чем ширина (в физических единицах), то Windows изменяет протяженность по y. Логическое окно помещается в нижней части рабочей области:
Теперь вы не можете отображать что-либо в верхней части рабочей области, поскольку это требует задания логической координаты y со значением, превышающим 32767.
Если вы предпочитаете, чтобы логическое окно всегда находилось слева вверху рабочей области, то вы можете изменить приведенный выше код следующим образом:
SetMapMode(hdc, MM_ISOTROPIC);
SetWindowExtEx(hdc, 32767, 32767, NULL);
SetViewportExtEx(hdc, cxClient, -cyClient, NULL);
SetWindowOrgEx(hdc, 0, 32767, NULL);
Делая вызов функции SetWindowOrgEx, мы хотим, чтобы логическая точка (0, 32767) соответствовала точке с физическими координатами (0, 0). Теперь, если высота рабочей области окажется больше ширины, то система координат будет расположена следующим образом:
Вы можете использовать обычную, имеющую четыре квадранта, Декартову систему координат с масштабируемыми по вашему выбору осями в четырех направлениях и логической точкой (0, 0) в центре рабочей области. Если вы, например, хотите, чтобы диапазон значений по каждой из осей был от 0 до 1000, используйте такой код:
SetMapMode(hdc, MM_ISOTROPIC);
SetWindowExtEx(hdc, 1000, 1000, NULL);
SetViewportExtEx(hdc, cxClient / 2, -cyClient / 2, NULL);
SetViewportOrgEx(hdc, cxClient / 2, cyClient / 2, NULL);
Если ширина рабочей области будет больше высоты, то система логических координат будет выглядеть так:
Система логических координат также будет центрирована, если высота рабочей области окажется больше ширины:
Запомните, что отсечения протяженностей окна и области вывода не предполагается. При вызове функций GDI вы можете использовать логические координаты x и y со значениями меньшими —1000 и больше +1000. В зависимости от формы рабочей области эти точки могут быть видимыми и невидимыми.
В режиме отображения MM_ISOTROPIC можно сделать логические единицы измерения намного больше, чем пиксели. Например, предположим, что вы хотите установить режим отображения так, чтобы точка (0, 0) была в левом верхнем углу экрана, значения координаты y увеличивались при движении вниз (как в режиме MM_TEXT), а логические координаты равнялись 1/16 дюйма. Этот режим отображения позволит вам нарисовать линейку, начинающуюся в левом верхнем углу рабочей области, с делениями, равными 1/16 дюйма:
SetMapMode(hdc, MM_ISOTROPIC);
SetWindowExtEx(hdc, 160 * GetDeviceCaps(hdc, HORZSIZE) / 254,
160 * GetDeviceCaps(hdc, VERTSIZE) / 254, NULL);
SetViewportExtEx(hdc, GetDeviceCaps(hdc, HORZRES),
GetDeviceCaps(hdc, VERTRES), NULL);
В этом коде протяженность области вывода устанавливается равной величине всего экрана в пикселях.
Протяженности окна должны быть установлены в размеры всего экрана в единицах, равных 1/16 дюйма. Используя индексы HORZSIZE и VERTSIZE в функции GetDeviceCaps, мы получаем размеры экрана в миллиметрах. Если бы мы работали с числами с плавающей точкой, мы могли бы преобразовать миллиметры в дюймы путем деления на 25.4, а затем преобразовать дюймы в единицы, равные 1/16 дюйма, умножив результат деления на 16. Но, поскольку, мы работаем с целыми числами, мы должны умножить миллиметры на 160 и разделить на 254.
Для большинства устройств вывода этот код делает логическую единицу измерения много большей, чем физическая единица измерения. Все, что вы выводите на устройство, будет иметь физические координаты, определенные с точностью до 1/16 дюйма. Вы не можете нарисовать две горизонтальные линии, отстоящие друг от друга на 1/32 дюйма, так как это потребовало бы задания дробных логических координат.