СClientDC (CWnd *Windows);
где параметр Windows является указателем на окно, которому предоставляется контекст устройства. Для активного окна можно указать ключевое слово this.
Вывод в клиентскую область окна программы может обеспечиваться с помощью функции TextOut():
virtual BOOL CDC::TextOut(int X, int Y, LPCSTR lpszStr, int Length);
где X, Y – координаты точки начала вывода в пикселях (относительно левого верхнего угла окна программы), lpszStr – указатель на строку, которая выводится, а Length – его длина. Пример иллюстрирует возможный вариант реализации обработчика нажатия клавиш клавиатуры - в точку (1, 1) окна программы.
Пример обработчика нажатия клавиш клавиатуры
char str [80]; // строка символов для вывода
void CMainWin::OnChar(UINT nChar, UINT nRepCnt, UINT nFlags)
{CClientDC dc(this); // получение контекста окна
dc.TextOut(1,1," ", 3); // удаление старого текста
wsprintf(str,"%с", ch); // формирование строки с кодом клавиши
dc.TextOut(1, 1, str, strlen(str)); // вывод строки в координату (1, 1)
}
Таким образом, каждый раз, когда необходимо вывести информацию в рабочую область окна, необходимо получить контекст устройства с помощью CClientDC. Частным случаем является применения сообщения WM_PAINT.
Обновление содержимого рабочей области окна программы
Для обновления содержимого рабочего окна программы необходимо отослать сообщение WM_PAINT. Вне его применения содержимое окна может не отображаться. Т.е. каждый раз, когда есть потребность выводить информацию в окно программы, следует обращаться к этому сообщению.
Сообщению WM_PAINT отвечает макрокоманда ON_WM_PAINT(), а макрокоманде – обработчик OnPaint(). Этот обработчик может выглядеть следующим образом:
Пример обработчика сообщения WM_PAINT
void CMainWin::OnPaint()
{CPaintDC dc(this); // получение контекста окна
dc.TextOut(1,1, str, strlen(str)); // отображение символа
}
В примере приведен обработчик OnPaint(), который обеспечивает вывод на экран символа, введенного с клавиатуры пользователем соответственно обработчику OnChar(), записанному в предыдущем примере. Видно, что для получения контекста устройства здесь использован объект другого типа, а именно CPaintDC. В отличие от CClientDC, который работает только с клиентской частью окна программы, CPaintDC обеспечивает роботу со всей плоскостью окна.
В программе желательным было бы, чтобы Windows самостоятельно решала, когда ей вызвать сообщение WM_PAINT. Это так и происходит, например, когда пользователь программы минимизирует окно, максимизирует, движет экраном, изменяет размеры окна и т.п.. Но иногда необходимо проводить обновление окна принудительно. Для того, чтобы прислать сообщение WM_PAINT, программа вызывает функцию InvalidateRect() – член класса CWnd, которая имеет следующий прототип:
void CWnd::InvalidateRect(LPCRECT lpRegion, BOOL Erase=TRUE);
где lpRegion – указатель на область окна, которую необходимо обновить, Erase – флаг, который в значении TRUE устанавливает изъятие предыдущего содержимого окна. Если указать первому параметру значения NULL, произойдет полное обновление окна. Вызов функции InvalidateRect() обеспечивает принудительную посылку сообщения WM_PAINT и выполнение обработчика OnPaint().
Полное обновление окна, как например:
InvalidateRect(NULL);
занимает много ресурсов системы, которая визуально может выглядеть мерцанием рабочего окна программы. Этого можно избегнуть, задав отдельно область обновления, например:
СRect region(10,10,100,100);
InvalidateRect(region);
в таком случае будет обновляться лишь область, ограниченная прямоугольником с левым верхним углом (10,10) и нижним правым углом (100,100). Такой вариант обновления становится особенно интересным, если необходимо обеспечить подвижность отдельных элементов окна, а этого можно достичь с одновременным применением обработки сообщения таймера WM_TIMER.
3. Основы работы с текстом в MFC. Функции вывода текста, установки цветов, режимов отображения, получение метрик
В Windows есть практически неограниченные возможности по управлению выводом текста. Некоторые из функций сейчас утратили свое былое значение (или то, что было задумано, оказалось почти невозможным реализовать), другие же очень широко используются.
Небольшое введение
Любой шрифт, с которым мы имеем дело в Windows, характеризуется несколькими параметрами. Гарнитура (typeface) - это совокупность нескольких начертаний шрифта, объединенных стилевыми и другими признаками. Пример гарнитур: Arial, TimesNewRoman, MSSansSerif. Размер шрифта - это высота прямоугольника, в который помещаются все символы шрифта, выражается в специальных единицах - пунктах. Пункт равен 1/72 части дюйма. Эта единица пришла из полиграфии. Начертание - это специфические характеристики шрифта. В Windows доступны четыре начертания: нормальное (normal), курсивное (italic), жирное (bold) и жирное курсивное (bolditalic). Кроме того, шрифты могут быть моноширинные (fixedpitch', пример - CourierNew, и пропорциональные (variablepitch), пример - TimesNewRoman.
Сейчас в Windows в основном используются шрифты двух групп: растровые (примеры - MSSansSerif, Fixedsys) и контурные TrueType (примеры - Arial, CourierNew). Первые представляют собой жестко определенные битовые матрицы для каждого символа и предназначены для отображения не очень крупного текста на экране. Вторые представляют собой очень сложные объекты. В них заданы контуры символов, которые закрашиваются по определенным правилам. Каждый шрифт TrueType - это программа на специальном языке, которая выполняется интерпретатором под названием растеризатор. Программа шрифта полностью определяет способ расчета конкретных битовых матриц символов на основе контуров. При использовании символов маленького размера (высотой приблизительно до 30 точек) модель контуров становится некорректной и символы сильно искажаются. Для борьбы с этим в качественных шрифтах используется разметка (хинты). Разметка шрифта -чрезвычайно сложный и долгий процесс, поэтому на рынке встречается немного качественно размеченных шрифтов. Поэтому использовать TrueType шрифты для вывода текста на экран нежелательно, за исключением стандартных шрифтов Windows (TimesNewRoman, Arial и CourierNew), которые очень качественно размечены.
Координаты при выводе текста
За вывод текста в окно в MFCотвечает функция CDC::TextOut(). Ей нужно указать координаты для вывода строки. Эти координаты являются логическими координатами, то есть они измеряются в логических единицах. Это относится и к другим функциям вывода информации в окно. В процессе отображения информации логические координаты преобразуются в пиксели. По умолчанию логическими координатами являются пиксели, что для нас очень удобно.
Задание цвета текста и фона
При выводе текста с помощью функции TextOutQпо умолчанию текст выводится черным цветом на текущем (обычно белом) фоне. Однако с помощью следующих функций эти параметры можно изменить:
virtualCOLORREFCDC::SetTextColor(COLORREFColor); virtualCOLORREFCDC::SetBkColor(COLORREFColor);
Функции возвращают значение предыдущего цвета. Тип COLORREFпредставляет собой 32-разрядное беззнаковое целое число - представление цвета в виде красной, зеленой и синей компонент, каждая размером в 8 бит. Для формирования этого значения существует макрос RGB().
Задание режима отображения фона
С помощью функции SetBkMode() можно задать режим отображения фона. Прототип функции такой: intCDC::SetBkMode(intMode);
Функция определяет, что происходит с текущим цветом фона (а также некоторых других элементов) при отображении текста. Режим может принимать одно из двух значений: OPAQUEи TRANSPARENT. В первом случае при выводе текста будет выводится также и текущий фон. Во втором случае фон выводится не будет (он будет "прозрачным"). По умолчанию используется режим OPAQUE.
Получение метрик текста
Большинство текстовых шрифтов являются пропорциональными, то есть ширина символов у них разная. Кроме того, расстояние между строками зависит как от шрифта, так и от его размера. Весь вывод текста в Windows осуществляется программно, поэтому необходимо учитывать все эти параметры.
Например, при выводе одной текстовой строки после другой предполагается, что известны высота шрифта и количество пикселей между строками. Получить эту информацию можно с помощью функции:
BOOLCDC::GetTextMetrics(LPTEXTMETRICSTextAtttrib) const; Параметр является указателем на структуру TEXTMETRIC, в которую будут записаны установки текущего шрифта контекста устройства. Структура имеет достаточно много полей. Наиболее важные поля следующие:
LONGtmHeightПолная высота шрифта
LONGtmAscentВысота над базовой линией
LONGtmDescentВысота подстрочных элементов
LONGtmlntemalLeadingПустое пространство над символами
LONGtmExternalLeadingПустой интервал между строками
LONGtmMaxCharWidthМаксимальная ширина символов
Для получения числа логических единиц по вертикали между строками нужно сложить значения tmHeightи tmExternalLeading. Это не то же самое, что и высота символов.
Изменение шрифтов
Предположим, что мы имеем готовый инициализированный экземпляр класса CFont, содержащий некоторый шрифт (как это сделать, мы рассмотрим чуть ниже). Для изменения шрифта в контексте устройства используется член-функция SelectObject(), которая в нашем случае принимает один параметр - указатель на объект шрифта. После выполнения этой функции текст будет выводится новым шрифтом. Хотя функция возвращает указатель на объект старого шрифта, сохранять его вовсе не обязательно.