- •Часть 2 (продолжение): Прикладное программирование в Windows
- •Глава 8. Виртуальное окно: работа с текстом
- •8.1. Оконные координаты, цвета, отображение строк
- •Кодировка rgb-значений
- •Размеры системных метрик
- •8.2. Виртуальное окно
- •Способы заполнения прямоугольной области
- •8.3. Изменение шрифтов
- •Макроимена распространенных шрифтов
- •8.4. Создание собственных шрифтов
- •Глава 9. Программирование графики
- •9.1. Логическая система координат
- •Рекомендуемый самый яркий состав цветов
- •9.2. Пиксели, линии, дуги, прямоугольники, эллипсы и секторы
- •9.3. Работа с перьями и кистями
- •Типы линий, создаваемых пером
- •9.4. Технология виртуального окна
- •9.5. Режимы отображения и области вывода
- •Текущий режим отображения (mappind mode)
- •Глава 10. Работа с панелями инструментов
- •10.1. Общие элементы управления
- •Общие элементы управления
- •10.2. Подключение и инициализация общих элементов управления
- •10.3. Работа с панелью инструментов
- •Начальные состояния кнопок панели инструментов
- •Стиль кнопки определяется (значения поля fsStyle)
- •Сообщения к панели инструментов
- •10.4. Создание растрового изображения для панели инструментов
- •10.5. Включение подсказок
- •Глава 11. Спины, ползунки и индикаторы процессов
- •11.1. Работа со спином
- •Стили «up-down control»
- •Сообщения, которые можно посылать спину
- •11.2. Создание спина с «приятельским» окном
- •11.3. Работа с ползунком
- •Значения стилей для ползунка
- •Перечень сообщений, которые можно посылать ползунку
- •Перечень нотификационных сообщения ползунка
- •11.4. Индикатор процесса
- •Управляющие сообщения индикатору
- •Глава 12. Многозадачность: процессы и потоки
- •12.1. Создание нового процесса (отдельной задачи)
- •Разрешенные значения поля dwFlags
- •12.2. Многопотоковые программы
- •12.3. Работа с несколькими потоками
- •12.4. Синхронизация процессов и потоков: семафоры
- •12.5. Обработка событий
- •Глава 13. Приемы программного управления вычислительным процессом
- •13.1. Использование функций Проводника Explorer для работы в файловой системе
- •Управляющая информация Проводника
- •Режимы обработки файлов
- •13.2. Создание собственных динамических библиотек (dll-файлов)
- •13.3. Работа с буфером обмена Clipboard
- •Функции подсистемы Clipboard
- •Свойства выделяемого блока памяти
- •Форматы и типы данных
- •Литература
Кодировка rgb-значений
№ |
Байт |
Цвет |
1 |
Байт 0 (младший) |
Красный |
2 |
Байт 1 |
Зеленый |
3 |
Байт 2 |
Синий |
4 |
Байт 3 (старший) |
Должен быть 0 |
Интенсивность каждого цвета в RGB-значении может задаваться в диапазоне от О до 255, причем значение 0 определяет минимальную, а значение 255 – максимальную интенсивность задаваемого цвета. Например, следующее длинное целое задает фиолетовый («марганцовочный» – magenta) цвет:
00 |
255 |
00 |
255 |
Хотя RGB-значения можно формировать вручную, в Windows определен макрос RGB(), предназначенный для этих целей:
COLORREF RGB(int red, int green, int blue);
Здесь значения Red, Ggreen и Blue должны принадлежать диапазону от 0 до 255. Таким образом, для задания марганцовочного цвета можно использовать RGB(255,0,255). Белый цвет задается при помощи RGB(255,255,255), а черный – при помощи RGB(0,0,0). Для задания других цветов необходимо комбинировать три базовых цвета с различной интенсивностью. Например, RGB(0,100,100) задает темный серо-голубой цвет. Вы можете поэкспериментировать с различными комбинациями RGB и определить наиболее подходящие цвета для своего приложения.
Установка режима отображения фона. Способом отображения фона при выводе текста можно управлять с помощью функции API SetBkMode():
int SetBkMode(HDC hdc, int mode);
Эта функция определяет, что произойдет с текущим цветом фона при выводе текста (и некоторых других видов графики). Режим отображения фона определяется параметром mode, который может задаваться одним из двух макросов: OPAQUE или TRANSPARENT. Функция возвращает значение предыдущего режима отображения фона или 0 в случае возникновения ошибки. Если значение mode равно OPAQUE, цвет фона при выводе текста каждый раз будет меняться на текущий цвет фона, заданный функцией SetBkColor(). Если mode равно TRANSPARENT, цвет фона при выводе текста не изменяется. В этом случае установка текущего цвета фона функцией SetBkColor() не дает никакого видимого эффекта. По умолчанию способ отображения фона задается как OPAQUE.
Получение метрик текста. Большинство шрифтов в Windows являются пропорциональными, поэтому символы одного и того же кегля могут иметь различную ширину. Кроме того, высота символов и размер нижних выносных элементов (например, как у букв р и g) могут быть различными у разных шрифтов. Разными могут быть и расстояния между строками текста. Однако то, что эти (и многие другие) атрибуты шрифта могут изменяться, в данном случае не имеет большого значения; важно лишь то, что Windows требует, чтобы программист самостоятельно управлял практически всем процессом отображения текста.
Windows обеспечивает только минимальную поддержку отображения текста в рабочей области окна. Основной функцией вывода текста является TextOut(). Эта функция лишь выводит строку текста на экран, начиная с заданной позиции. Она никак не форматирует выводимый текст и даже не выполняет операции возврата каретки (CR) или перехода на новую строку (LF). Управление выводом текста в рабочую область окна полностью возлагается на программиста.
То обстоятельство, что размеры шрифтов могут быть разными (и что сами шрифты могут изменяться в процессе выполнения программы), предполагает, что должен существовать способ определения атрибутов текущего шрифта. Например, чтобы вывести на экран новую строку текста под выведенной строкой, необходимо определить высоту шрифта и интервал между строками. Функция API, с помощью которой приложение может получить информацию о текущем шрифте, называется GetTextMetrics() и имеет следующий прототип:
BOOL GetTextMetrics(HDC hdc, LPTEXTMETRIC lpTAttrib);
Здесь hdc является дескриптором контекста устройства отображения, который может быть получен при помощи функций GetDC() или BeginPaint(), a lpTAttrib должен быть указателем на структуру типа TEXTMETRIC, которая при успешном завершении функции будет содержать все параметры (метрики) выбранного шрифта. Структура TEXTMETRIC определяется следующим образом:
typedef struct tagTEXTMETRIC
{
LONG tmHeight; // Полная высота шрифта (кегль)
LONG tmAscent; // Высота над основной линией
LONG tmDescent; // Размер нижнего выступа
LONG tmlnternalLeading; // Размер верхнего выступа
LONG tmExternalLeading; // Межстрочный интервал
LONG tmAveCharWidth; // Средняя ширина символа
LONG tmMaxCharWidth; // Максимальная ширина символа
LONG tmWeight; // Насыщенность шрифта
LONG tmOverhang; // Дополнительная ширина символа
// - для специальных шрифтов
LONG tmDigitizedAspectX; // Горизонтальный аспект
LONG tmDigitizedAspectY; // Вертикальный аспект
BYTE tmFirstChar; // Первый символ
BYTE tmLastChar; // Последний символ
BYTE tmDefaultChar; // Символ по умолчанию
BYTE tmBreakChar; // Символ для обозн.границы слова
BYTE tmItalic; // Не 0, если шрифт наклон.(italic)
BYTE tmUnderlined; // Не 0, если буквы подчеркнуты
BYTE tmStruckOut; // Не 0, если буквы зачеркнуты
BYTE tmPitchAndFamily; // Семейство и гарнитура
BYTE tmCharSet; // Идентификатор множества символов
}
Большинство атрибутов шрифтов, получаемых программой с помощью этой функции, в примерах данной главы не используется. Сейчас для нас важны только те, которые применяются для определения расстояния между строками текста. Это значение понадобится, если Вы захотите вывести в окно несколько строк текста. В отличие от консольного приложения, использующего всегда только один шрифт фиксированного размера, в окне можно использовать несколько шрифтов. При этом каждый шрифт может иметь свой размер и межстрочный интервал. А это, в свою очередь, означает, что нельзя предварительно определить вертикальную (Y) координату следующей строки. Поэтому для определения начала следующей строки необходимо вызвать функцию GetTextMetrics() и получить значения высоты символа и межстрочного интервала. Эти значения хранятся в полях tmHeight и tmExternalLeading соответственно. Сложив их, получаем расстояние между строками в логических единицах.
Помните: величина tmExternalLeading определяет значение межстрочного интервала в логических единицах. Это значение может быть никак не связано с высотой шрифта (кеглем). Поэтому для определения координат начала следующей строки необходимы оба значения. Вскоре Вы увидите, как это реализуется на практике.
Имеется также расширенная, с несколькими дополнительными полями в конце, версия структуры TEXTMETRIC, которая называется NEWTEXTMETRIC. Дополнительные поля предназначены для поддержки работы с TrueType-шрифтами, обеспечивающими более широкие возможности масштабирования, поворотов и других операций над шрифтами. Вот эти новые поля:
DWORD ntmFlags; // Индикатор типа шрифта
UINT ntmSizeEM; // Размер комбинации em
UINT ntmCellHeight; // Высота шрифта
UINT ntmAvgWidth; // Средняя ширина символа
И хотя эти поля не используются в данной главе, в дальнейшем они могут сыграть важную роль при написании Ваших собственных приложений. Более подробную информацию о них Вы найдете в Руководстве Программиста по функциям и структурам данных API.
Определение длины строки. Поскольку различные символы одного и того же шрифта могут иметь разную ширину, нельзя определить длину строки текста в логических единицах, исходя только из информации о количестве выводимых символов. Поэтому результат функции strlen() не позволяет управлять выводом текста в окне. Для этих целей в Windows предусмотрена функция API GetTextExtentPoint32(), которая имеет следующий прототип:
BOOL GetTextExtentPoint32(HDC hdc, LPCSTR lpszString,
int len, LPSIZE lpSize);
Здесь hdc определяет контекст устройства вывода. Параметр lpszString задает указатель на строку, длину которой в логических единицах Вы хотите узнать. Параметр lenзадает количество символов в этой строке. Вычисленные ширина и высота строки текста в логических единицах записываются в структуру SIZE, указатель на которую задается параметром lpSize. Структура SIZE определяется следующим образом:
typedef struct tagSIZE
{
LONG cx; // Ширина
LONG су; // Высота
} SIZE;
После возврата из функции GetTextExtentPoint32() поле сх структуры SIZE содержит длину строки. Таким образом, это значение можно использовать для определения начала следующей строки в том случае, если Вы хотите выводить следующую строку, начиная с того места, где заканчивается предыдущая.
Получение системных метрик. Хотя Windows автоматически воспринимает и преобразует логические координаты в пиксели, Вам иногда может понадобиться определить реальные размеры и другие параметры экрана компьютера, на котором запускается Ваше приложение. Для получения этой информации используется функция API GetSystemMetrics():
int GetSystemMetrics(int what);
Параметр what определяет величину, которую Вы хотите получить. Размеры элементов экрана указываются в пикселях. В таблице 8.2. приведены некоторые макросы для получения этих величин.
Таблица 8.2
