- •Оглавление
- •Глава 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
2.2.12 Отображение окна
К тому времени, когда функция CreateWindow возвращает управление программе, окно уже создано внутри Windows. Однако, на экране монитора оно еще не появилось. Необходимы еще два вызова. Первый из них:
ShowWindow(hwnd, iCmdShow);
Первым параметром является описатель только что созданного функцией CreateWindow окна. Вторым параметром является величина iCmdShow, передаваемая в качестве параметра функции WinMain. Он задает начальный вид окна на экране. Если iCmdShow имеет значение SW_SHOWNORMAL (т. е. 1), на экран выводится обычное окно. Если iCmdShow имеет значение SW_SHOWMINNOACTIVE (т. е. 7), то окно не выводится, а на панели задач появляются его имя и иконка.
Функция ShowWindow выводит окно на экран. Если второй параметр ShowWindow имеет значение SW_SHOWNORMAL, то фон рабочей области окна закрашивается той кистью, которая задана в классе окна. Вызов функции:
UpdateWindow(hwnd);
вызывает затем перерисовку рабочей области. Для этого в оконную процедуру (функция WndProc в HELLOWIN.CPP) посылается сообщение WM_PAINT. Вскоре мы изучим, как WndProc обрабатывает это сообщение.
2.2.13 Цикл обработки сообщений
После вызова функции UpdateWindow, окно окончательно выведено на экран. Теперь программа должна подготовить себя для получения информации от пользователя через клавиатуру и мышь. Windows поддерживает "очередь сообщений" (message queue) для каждой программы, работающей в данный момент в системе Windows.
Когда происходит ввод информации, Windows преобразует ее в "сообщение", которое помещается в очередь сообщений программы.
Программа извлекает сообщения из очереди сообщений, выполняя блок команд, известный как "цикл обработки сообщений" (message loop):
while(GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return msg.wParam;
Переменная msg — это структура типа MSG, которая определяется в заголовочных файлах Windows следующим образом:
typedef struct tagMSG
{
HWND hwnd;
UINT message;
WPARAM wParam;
LPARAM lParam;
DWORD time;
POINT pt;
} MSG;
Тип данных POINT — это тип данных другой структуры, которая определяется так:
typedef struct tagPOINT
{
LONG x;
LONG y;
} POINT;
Вызов функции GetMessage, с которого начинается цикл обработки сообщений, извлекает сообщение из очереди сообщений:
GetMessage(&msg, NULL, 0, 0)
Этот вызов передает Windows указатель на структуру msg типа MSG. Второй, третий и четвертый параметры, NULL или 0, показывают, что программа получает все сообщения от всех окон, созданных этой программой.
Windows заполняет поля структуры сообщений информацией об очередном сообщении из очереди сообщений.
Поля этой структуры следующие:
hwnd — описатель окна, для которого предназначено сообщение. В программе HELLOWIN, он тот же, что и hwnd, являющийся возвращаемым значением функции CreateWindow, поскольку у нашей программы имеется только одно окно.
message — идентификатор сообщения. Это число, которое идентифицирует сообщение. Для каждого сообщения имеется соответствующий ему идентификатор, который задается в заголовочных файлах Windows и начинается с префикса WM (оконное сообщение — window message). Например, если вы установите указатель мыши в рабочей области программы HELLOWIN и нажмете левую кнопку мыши, Windows поставит сообщение в очередь сообщений с полем message равным WM_LBUTTONDOWN, значение которого 0x0201.
wParam — 32-разрядный параметр сообщения (message parameter), смысл и значение которого зависят от особенностей сообщения.
lParam — другой 32-разрядный параметр, зависящий от сообщения.
time — время, когда сообщение было помещено в очередь сообщений.
pt — координаты курсора мыши в момент помещения сообщения в очередь сообщений.
Если поле message сообщения, извлеченного из очереди сообщений, равно любому значению, кроме WM_QUIT (т. е., 0x0012), то функция GetMessage возвращает ненулевое значение. Сообщение WM_QUIT заставляет программу прервать цикл обработки сообщений. На этом программа заканчивается, возвращая число wParam структуры msg.
Инструкция:
TranslateMessage(&msg);
передает структуру msg обратно в Windows для преобразования какого-либо сообщения с клавиатуры. (Более подробно об этом будет рассказано в главе 5.)
Инструкция:
DispatchMessage(&msg);
также передает структуру msg обратно в Windows. Windows отправляет сообщение для его обработки соответствующей оконной процедуре — таким образом, Windows вызывает оконную процедуру. Такой оконной процедурой в HELLOWIN является функция WndProc. После того, как WndProc обработает сообщение, оно возвращается в Windows, которая все еще обслуживает вызов функции DispatchMessage. Когда Windows возвращает управление в программу HELLOWIN к следующему за вызовом DispatchMessage коду, цикл обработки сообщений в очередной раз возобновляет работу, вызывая GetMessage.