- •Содержание
- •Глава 1 README.TXT
- •Вызов, брошенный программистам
- •Основные правила
- •Краткая история Windows
- •Краткая история этой книги
- •Начнем
- •Глава 2 Hello, Windows 95
- •Отличительная особенность Windows
- •Графический интерфейс пользователя
- •Концепции и обоснование GUI
- •Содержимое интерфейса пользователя
- •Преимущество многозадачности
- •Управление памятью
- •Независимость графического интерфейса от оборудования
- •Соглашения операционной системы Windows
- •Вызовы функций
- •Объектно-ориентированное программирование
- •Архитектура, управляемая событиями
- •Оконная процедура
- •Ваша первая программа для Windows
- •Что в этой программе неправильно?
- •Файлы HELLOWIN
- •Make-файл
- •Вызовы функций Windows
- •Идентификаторы, написанные прописными буквами
- •Новые типы данных
- •Описатели
- •Венгерская нотация
- •Точка входа программы
- •Регистрация класса окна
- •Создание окна
- •Отображение окна
- •Цикл обработки сообщений
- •Оконная процедура
- •Обработка сообщений
- •Воспроизведение звукового файла
- •Сообщение WM_PAINT
- •Сообщение WM_DESTROY
- •Сложности программирования для Windows
- •Не вызывай меня, я вызову тебя
- •Синхронные и асинхронные сообщения
- •Думайте о ближнем
- •Кривая обучения
- •Глава 3 Рисование текста
- •Рисование и обновление
- •Сообщение WM_PAINT
- •Действительные и недействительные прямоугольники
- •Введение в графический интерфейс устройства (GDI)
- •Контекст устройства
- •Структура информации о рисовании
- •Получение описателя контекста устройства. Второй метод
- •Функция TextOut. Подробности
- •Системный шрифт
- •Размер символа
- •Метрические параметры текста. Подробности
- •Форматирование текста
- •Соединим все вместе
- •Не хватает места!
- •Размер рабочей области
- •Полосы прокрутки
- •Диапазон и положение полос прокрутки
- •Сообщения полос прокрутки
- •Прокрутка в программе SYSMETS
- •Структурирование вашей программы для рисования
- •Создание улучшенной прокрутки
- •Мне не нравится пользоваться мышью
- •Глава 4 Главное о графике
- •Концепция GDI
- •Структура GDI
- •Типы функций
- •Примитивы GDI
- •Другие аспекты
- •Контекст устройства
- •Получение описателя контекста устройства
- •Программа DEVCAPS1
- •Размер устройства
- •О цветах
- •Атрибуты контекста устройства
- •Сохранение контекста устройства
- •Рисование отрезков
- •Ограничивающий прямоугольник
- •Сплайны Безье
- •Использование стандартных перьев
- •Создание, выбор и удаление перьев
- •Закрашивание пустот
- •Режимы рисования
- •Рисование закрашенных областей
- •Функция Polygon и режим закрашивания многоугольника
- •Закрашивание внутренней области
- •Режим отображения
- •Координаты устройства (физические координаты) и логические координаты
- •Системы координат устройства
- •Область вывода и окно
- •Работа в режиме MM_TEXT
- •Метрические режимы отображения
- •Ваши собственные режимы отображения
- •Программа WHATSIZE
- •Прямоугольники, регионы и отсечение
- •Работа с прямоугольниками
- •Случайные прямоугольники
- •Создание и рисование регионов
- •Отсечения: прямоугольники и регионы
- •Программа CLOVER
- •Пути
- •Создание и воспроизведение путей
- •Расширенные перья
- •Bits and Blts
- •Цвета и битовые образы
- •Файл DIB
- •Упакованный формат хранения DIB
- •Отображение DIB
- •Преобразование DIB в объекты "битовые образы"
- •Битовый образ — объект GDI
- •Создание битовых образов в программе
- •Формат монохромного битового образа
- •Формат цветного битового образа
- •Контекст памяти
- •Мощная функция BitBlt
- •Перенос битов с помощью функции BitBlt
- •Функция DrawBitmap
- •Использование других ROP кодов
- •Дополнительные сведения о контексте памяти
- •Растяжение битовых образов с помощью функции StretchBlt
- •Кисти и битовые образы
- •Метафайлы
- •Простое использование метафайлов памяти
- •Сохранение метафайлов на диске
- •Расширенные метафайлы
- •Делаем это лучше
- •Базовая процедура
- •Заглянем внутрь
- •Вывод точных изображений
- •Текст и шрифты
- •Вывод простого текста
- •Атрибуты контекста устройства и текст
- •Использование стандартных шрифтов
- •Типы шрифтов
- •Шрифты TrueType
- •Система EZFONT
- •Внутренняя работа
- •Форматирование простого текста
- •Работа с абзацами
- •Глава 5 Клавиатура
- •Клавиатура. Основные понятия
- •Игнорирование клавиатуры
- •Фокус ввода
- •Аппаратные и символьные сообщения
- •Аппаратные сообщения
- •Системные и несистемные аппаратные сообщения клавиатуры
- •Переменная lParam
- •Виртуальные коды клавиш
- •Использование сообщений клавиатуры
- •Модернизация SYSMETS: добавление интерфейса клавиатуры
- •Логика обработки сообщений WM_KEYDOWN
- •Посылка асинхронных сообщений
- •Символьные сообщения
- •Сообщения WM_CHAR
- •Сообщения немых символов
- •Каретка (не курсор)
- •Функции работы с кареткой
- •Программа TYPER
- •Наборы символов Windows
- •Набор символов OEM
- •Набор символов ANSI
- •Наборы символов OEM, ANSI и шрифты
- •Международные интересы
- •Работа с набором символов
- •Связь с MS-DOS
- •Использование цифровой клавиатуры
- •Решение проблемы с использованием системы UNICODE в Windows NT
- •Глава 6 Мышь
- •Базовые знания о мыши
- •Несколько кратких определений
- •Сообщения мыши, связанные с рабочей областью окна
- •Простой пример обработки сообщений мыши
- •Обработка клавиш <Shift>
- •Сообщения мыши нерабочей области
- •Сообщение теста попадания
- •Сообщения порождают сообщения
- •Тестирование попадания в ваших программах
- •Гипотетический пример
- •Пример программы
- •Эмуляция мыши с помощью клавиатуры
- •Добавление интерфейса клавиатуры к программе CHECKER
- •Использование дочерних окон для тестирования попадания
- •Дочерние окна в программе CHECKER
- •Захват мыши
- •Рисование прямоугольника
- •Решение проблемы — захват
- •Программа BLOKOUT2
- •Глава 7 Таймер
- •Основы использования таймера
- •Система и таймер
- •Таймерные сообщения не являются асинхронными
- •Использование таймера: три способа
- •Первый способ
- •Второй способ
- •Третий способ
- •Использование таймера для часов
- •Позиционирование и изменение размеров всплывающего окна
- •Получение даты и времени
- •Обеспечение международной поддержки
- •Создание аналоговых часов
- •Стандартное время Windows
- •Анимация
- •Класс кнопок
- •Создание дочерних окон
- •Сообщения дочерних окон родительскому окну
- •Сообщения родительского окна дочерним окнам
- •Нажимаемые кнопки
- •Флажки
- •Переключатели
- •Окна группы
- •Изменение текста кнопки
- •Видимые и доступные кнопки
- •Кнопки и фокус ввода
- •Дочерние окна управления и цвета
- •Системные цвета
- •Цвета кнопок
- •Сообщение WM_CTLCOLORBTN
- •Кнопки, определяемые пользователем
- •Класс статических дочерних окон
- •Класс полос прокрутки
- •Программа COLORS1
- •Интерфейс клавиатуры, поддерживаемый автоматически
- •Введение новой оконной процедуры
- •Закрашивание фона
- •Окрашивание полос прокрутки и статического текста
- •Класс редактирования
- •Стили класса редактирования
- •Коды уведомления управляющих окон редактирования
- •Использование управляющих окон редактирования
- •Сообщения управляющему окну редактирования
- •Класс окна списка
- •Стили окна списка
- •Добавление строк в окно списка
- •Выбор и извлечение элементов списка
- •Получение сообщений от окон списка
- •Простое приложение, использующее окно списка
- •Список файлов
- •Утилита Head для Windows
- •Компиляция ресурсов
- •Значки и курсоры
- •Редактор изображений
- •Получение описателя значков
- •Использование значков в вашей программе
- •Использование альтернативных курсоров
- •Битовые образы: картинки в пикселях
- •Использование битовых образов и кистей
- •Символьные строки
- •Использование ресурсов-символьных строк
- •Меню
- •Структура меню
- •Шаблон меню
- •Ссылки на меню в вашей программе
- •Меню и сообщения
- •Образец программы
- •Этикет при организации меню
- •Сложный способ определения меню
- •Третий подход к определению меню
- •Независимые всплывающие меню
- •Использование системного меню
- •Изменение меню
- •Другие команды меню
- •Использование в меню битовых образов
- •Два способа создания битовых образов для меню
- •Контекст памяти
- •Создание битового образа, содержащего текст
- •Масштабирование битовых образов
- •Соберем все вместе
- •Добавление интерфейса клавиатуры
- •Быстрые клавиши
- •Зачем нужны быстрые клавиши?
- •Некоторые правила назначения быстрых клавиш
- •Таблица быстрых клавиш
- •Преобразование нажатий клавиш клавиатуры
- •Получение сообщений быстрых клавиш
- •Программа POPPAD, имеющая меню и быстрые клавиши
- •Разрешение пунктов меню
- •Обработка опций меню
- •Глава 11 Окна диалога
- •Модальные окна диалога
- •Создание окна диалога About
- •Шаблон окна диалога
- •Диалоговая процедура
- •Вызов окна диалога
- •Дополнительная информация о стиле окна диалога
- •Дополнительная информация об определении дочерних окон элементов управления
- •Более сложное окно диалога
- •Работа с дочерними элементами управления окна диалога
- •Кнопки OK и Cancel
- •Позиции табуляции и группы
- •Рисование в окне диалога
- •Использование с окном диалога других функций
- •Определение собственных окон управления
- •Окна сообщений
- •Информация во всплывающих окнах
- •Немодальные окна диалога
- •Различия между модальными и немодальными окнами диалога
- •Новая программа COLORS
- •Программа HEXCALC: обычное окно или окно диалога?
- •Творческое использование идентификаторов дочерних окон элементов управления
- •Диалоговые окна общего пользования
- •Модернизированная программа POPPAD
- •Изменение шрифта
- •Поиск и замена
- •Программа для Windows, содержащая всего один вызов функции
- •Основы элементов управления общего пользования
- •Инициализация библиотеки
- •Создание элементов управления общего пользования
- •Стили элементов управления общего пользования
- •Уведомляющие сообщения от элементов управления общего пользования
- •Элементы управления главного окна
- •Панели инструментов
- •Создание панели инструментов
- •Строка состояния
- •Программа GADGETS
- •Наборы страниц свойств
- •Создание набора страниц свойств
- •Процедуры диалогового окна страницы свойств
- •Программа PROPERTY
352
MENUITEM "&Paste\tCtrl+V", |
IDM_PASTE |
|||
MENUITEM "De&lete\tDel", |
IDM_DEL |
|||
MENUITEM SEPARATOR |
|
|||
MENUITEM "&Select All", |
IDM_SELALL |
|||
} |
|
|
|
|
POPUP "&Help" |
|
|
|
|
{ |
|
|
|
|
MENUITEM "&Help...", |
IDM_HELP |
|||
MENUITEM "&About PopPad2...", IDM_ABOUT |
||||
} |
|
|
|
|
} |
|
|
|
|
PopPad2 ACCELERATORS |
|
|
||
{ |
|
|
|
|
"^Z", |
IDM_UNDO |
|
|
|
VK_BACK, |
IDM_UNDO, |
VIRTKEY, ALT |
|
|
"^X", |
IDM_CUT |
|
|
|
VK_DELETE, IDM_CUT, |
VIRTKEY, SHIFT |
|||
"^C", |
IDM_COPY |
|
|
|
VK_INSERT, IDM_COPY, |
VIRTKEY, CONTROL |
|||
"^V", |
IDM_PASTE |
|
|
|
VK_INSERT, IDM_PASTE, VIRTKEY, SHIFT |
||||
VK_DELETE, IDM_DEL, |
VIRTKEY |
|
||
VK_F1, |
IDM_HELP, |
VIRTKEY |
|
|
} |
|
|
|
|
POPPAD2.H |
|
|
|
|
/*----------------------- |
|
|
||
POPPAD2.H header file |
|
|
||
-----------------------*/ |
|
|||
#define IDM_NEW |
|
1 |
|
|
#define IDM_OPEN |
2 |
|
|
|
#define IDM_SAVE |
3 |
|
|
|
#define IDM_SAVEAS |
4 |
|
|
|
#define IDM_PRINT |
5 |
|
|
|
#define IDM_EXIT |
6 |
|
|
|
#define IDM_UNDO |
10 |
|
|
|
#define IDM_CUT |
|
11 |
|
|
#define IDM_COPY |
12 |
|
|
|
#define IDM_PASTE |
13 |
|
|
|
#define IDM_DEL |
|
14 |
|
|
#define IDM_SELALL |
15 |
|
|
|
#define IDM_HELP |
20 |
|
|
|
#define IDM_ABOUT |
22 |
|
|
POPPAD2.ICO
Рис. 10.10 Программа POPPAD2
В файле описания ресурсов POPPAD2.RC содержится меню и таблица быстрых клавиш. Обратите внимание, что все быстрые клавиши показаны после символа табуляции (\t) внутри символьных строк всплывающего меню Edit.
Разрешение пунктов меню
Основная работа оконной процедуры состоит теперь в разрешении и запрещении пунктов меню Edit, что осуществляется при обработке сообщения WM_INITMENUPOPUP. Сначала программа проверяет, отображается
353
ли всплывающее меню Edit. Поскольку индекс положения пункта Edit в меню (начинающегося с пункта File, чей индекс положения равен 0) равен 1, то lParam равен 1 в том случае, если отображается всплывающее меню Edit.
Для того чтобы определить, может ли быть разрешена опция Undo, программа POPPAD2 посылает сообщение EM_CANUNDO дочернему окну редактирования. Возвращаемое значение функции SendMessage не равно нулю, если дочернее окно редактирования может выполнить операцию Undo, в этом случае опция Undo делается разрешенной; в противном случае опция делается недоступной:
EnableMenuItem((HMENU) wParam, IDM_UNDO,
SendMessage(hwndEdit, EM_CANUNDO, 0, 0) ? MF_ENABLED : MF_GRAYED);
Опцию Paste следует делать разрешенной только в том случае, если в данный момент в папке обмена имеется текст. Определить это можно с помощью функции IsClipboardFormatAvailable с идентификатором CF_TEXT:
EnableMenuItem((HMENU) wParam, IDM_PASTE,
IsClipboardFormatAvailable(CF_TEXT) ? MF_ENABLED : MF_GRAYED);
Опции Cut, Copy и Delete следует делать разрешенными только в том случае, если в окне редактирования был выделен текст. При посылке окну управления сообщения EM_GETSEL возвращаемым значением функции SendMessage является целое, в котором содержится эта информация:
iSelect = SendMessage(hwndEdit, EM_GETSEL, 0, 0);
Младшим словом iSelect является положение первого выбранного символа; старшим словом iSelect является положение первого символа после выделения. Если два этих слова равны, то в окне редактирования нет выбранного текста:
if(HIWORD(iSelect) == LOWORD(iSelect)) iEnable = MF_GRAYED;
else
iEnable = MF_ENABLED;
Затем значение iEnable используется для опций Cut, Copy и Delete:
EnableMenuItem((HMENU) wParam, IDM_CUT, iEnable);
EnableMenuItem((HMENU) wParam, IDM_COPY, iEnable);
EnableMenuItem((HMENU) wParam, IDM_DEL, iEnable);
Обработка опций меню
Конечно, если бы мы в программе POPPAD2 не использовали элемент управления — дочернее окно редактирования, то теперь нам пришлось бы заняться проблемами, связанными с фактической реализацией опций Undo, Cut, Copy, Paste, Delete и Select All из меню Edit. Но окно редактирования делает этот процесс элементарным: мы просто посылаем окну редактирования сообщение для каждой из этих опций:
case IDM_UNDO :
SendMessage(hwndEdit, WM_UNDO, 0, 0); return 0;
case IDM_CUT :
SendMessage(hwndEdit, WM_CUT, 0, 0); return 0;
case IDM_COPY :
SendMessage(hwndEdit, WM_COPY, 0, 0); return 0;
case IDM_PASTE :
SendMessage(hwndEdit, WM_PASTE, 0, 0); return 0;
case IDM_DEL :
SendMessage(hwndEdit, WM_CLEAR, 0, 0); return 0;
case IDM_SELALL :
SendMessage(hwndEdit, WM_SETSEL, 0, -1); return 0;
Обратите внимание, что мы могли бы еще больше все упростить, приравняв значения IDM_UNDO, IDM_CUT и другие — значениям соответствующих сообщений окна WM_UNDO, WM_CUT и т. д.
Опция About всплывающего меню File вызывает простое окно сообщения:
354
case IDM_ABOUT :
MessageBox(hwnd, "POPPAD2(c) Charles Petzold, 1996", szAppName, MB_OK | MB_ICONINFORMATION);
return 0;
В главе 11 мы создадим здесь окно диалога. Окно сообщения появляется также при выборе опции Help этого меню или при нажатии быстрой клавиши <F1>.
Опция Exit посылает оконной процедуре сообщение WM_CLOSE:
case IDM_EXIT :
SendMessage(hwndEdit, WM_CLOSE, 0, 0); return 0;
Это именно то, что делает функция DefWindowProc при получении сообщения WM_SYSCOMMAND с параметром wParam, равным SC_CLOSE.
В предыдущих программах мы не обрабатывали сообщение WM_CLOSE в оконной процедуре, а просто передавали его в DefWindowProc. DefWindowProc поступает с сообщениями WM_CLOSE очень просто: она вызывает функцию DestroyWindow. Однако в программе POPPAD2 сообщение WM_CLOSE обрабатывается, а не пересылается в DefWindowProc. В данном случае это не имеет большого значения, но обработка сообщения WM_CLOSE станет важна, когда, как будет показано в главе 11, программа POPPAD будет фактически редактировать файлы:
case WM_CLOSE :
if(IDYES == AskConfirmation(hwnd)) DestroyWindow(hwnd); return 0;
В программе POPPAD2 функция AskConfirmation выводит на экран окно сообщения, запрашивая подтверждение на завершение программы:
AskConfirmation(HWND hwnd)
{
return MessageBox(hwnd, "Do you really want to close Poppad2?", szAppName, MB_YESNO | MB_ICONQUESTION);
}
Окно сообщения (как и функция AskConfirmation) возвращает IDYES, если нажата кнопка Yes. Только после этого программа POPPAD2 вызывает функцию DestroyWindow. В противном случае программа не завершается.
Если перед завершением программы требуется подтверждение, то необходимо также обрабатывать сообщение
WM_QUERYENDSESSION. Windows посылает каждой оконной процедуре сообщение WM_QUERYENDSESSION,
когда пользователь заканчивает сеанс работы с Windows. Если какая-либо оконная процедура возвращает 0 в ответ на это сообщение, то сеанс работы с Windows не завершается. Мы обрабатываем сообщение WM_QUERYENDSESSION следующим образом:
case WM_QUERYENDSESSION :
if( IDYES == AskConfirmation(hwnd)) return 1;
else
return 0;
Сообщения WM_CLOSE и WM_QUERYENDSESSION — это два сообщения, которые требуют обработки, если необходимо запрашивать пользователя о подтверждении завершения программы. По этой причине в программе POPPAD2 опция Exit отправляет оконной процедуре сообщение WM_CLOSE. Это сделано во избежание еще и третьего запроса на подтверждение завершения.
Если вы обрабатываете сообщение WM_QUERYENDSESSION, вас заинтересует и сообщение WM_ENDSESSION. Windows посылает это сообщение каждой оконной процедуре, которая ранее получила сообщение WM_QUERYENDSESSION. Параметр wParam этого сообщения равен 0, если сеанс работы не может завершиться изза того, что другая программа возвратила 0 в ответ на сообщение WM_QUERYENDSESSION. Практически сообщение WM_ENDSESSION отвечает на вопрос: "Я сообщил Windows, что могу закончить свою работу, но завершена ли она на самом деле?"
Хотя в меню File программы POPPAD2 включены обычные опции New, Open, Save и Save As, в этой программе они не работают. Для обработки этих опций необходимо использовать окна диалога. Сейчас мы готовы перейти к их изучению.