Сначала исследуем косметическое перо. Некоторые
его стили, задаваемые символьными константами,
занесем в массив. Введем внутрь тела оконной
процедуры (после объявления CustColors)
объявления новых локальных переменных:
//======
х-координаты:
static int
iXCenter; // центра окна,
static int
iXPos; // текущей позиции
static int
iXMax; // допустимой позиции
int
iYPos =0; // Текущая у-координата вывода
int
nLines; // Количество линий
SIZE szText; //
Экранные размеры строки текста
//======
Стили пера
Windows
static
DWORD dwPenStyle[] =
{
PS_NULL, PS_SOLID,
PS_DOT, PS_DASH,
PS__DASHDOT,
PS_DASHDOTDOT
};
//====== Строки текста для вывода в окно
static
string style[] =
{
"PS_NULL","PS_SOLID","PS_DOT","PS_DASH",
"PS_DASHDOT","PS_DASHDOTDOT"
};
string sText; //
Дежурная строка текста
//===== Логическая кисть — как основа для
создания пера
LOGBRUSH lb = {
BS_SOLID, color, 0 };
Если вы хотите, чтобы ваш вывод в окно
реагировал на изменения пользователем размеров
окна, то всегда вводите в оконную процедуру
ветвь обработки WM_SIZE. Сделайте это сейчас
вместе с изменениями в ветви WM_PAINT:
case
WM_SIZE:
//==== В IParam упрятаны размеры окна.
//==== Нас интересует только ширина окна
iXMax = LOWORD(IParam)
- 50;
iXCenter =
LOWORD(IParam)/2; break;
case
WM_PAINT:
hdc = BeginPaint(hWnd,
&ps);
//===== Режим выравнивания текста (см.
MSDN)
SetTextAlign(hdc,
TA_NOUPDATECP | TA_LEFT | TA_BASELINE) ;
sText = "Стили
линий в
Win32 (Cosmetic pen)";
//==
Выясняем размеры строки с текстом заголовка
GetTextExtentPoint(hdc,sText.c_str(), sText.size(),
//== Сдвигаем точку вывода вниз на одну строку
iYPos += szText.cy;
iXPos = iXCenter -
szText.cx/2;
//====
Выводим заголовок
TextOut(hdc,iXPos,
iYPos, sText.c_str(), sText. size ()
}
//====
Перебираем массив стилей пера
nLines = sizeof(style)/sizeof(style[0]);
for
(int i = 0; i < nLines; i++)
{
//=====
Устанавливаем биты стиля пера
DWORD dw =
PS_COSMETIC | dwPenStyle[i];
//
Создаем перо толщиной в
1
пиксел
HPEN hp =
ExtCreatePen(dw, 1, Sib, 0,NULL);
//=====
Выбираем перо в контекст устройства
HPEN hOld = (HPEN)SelectObject(hdc,hp);
iYPos += szText.cy;
// Сдвиг позиции
//===== Помещаем перо в точку (10, iYPos)
MoveToEx(hdc, 10,
iYPos, NULL);
//==== Проводим линию до точки (iXMax, iYPos)
LineTo(hdc, iXMax,
iYPos);
//== Возвращаем старое перо в контекст
устройства
SelectObject(hdc,
hold);
//===
Освобождаем ресурс пера
DeleteObject(hp);
//===
Выводим поясняющий текст
TextOut(hdc, 10,
iYPos, style[i].c_str(), style [i] .size ()
} ;
EndPaint(hWnd, &ps)
;
break;
Комментарии в тексте поясняют суть
происходящего. Отметьте, что здесь применена
стандартная тактика работы с ресурсами GDI,
которая состоит из последовательности следующих
шагов:
-
создаем свой инструмент;
-
выбираем его в контекст устройства (SelectObject)
и одновременно запоминаем тот инструмент,
который используется в контексте в настоящий
момент;
-
рисуем с помощью нашего инструмента;
-
возвращаем в контекст прежний инструмент;
-
освобождаем память, занимаемую нашим
инструментом.
Так как система работает с ресурсами GDI
динамически, то нарушение этой тактики может
привести к недостатку памяти и непредсказуемому
поведению приложения. Перед тем как запустить
проект, попробуйте ответить на вопросы:
-
Будет ли изменяться цвет линий при
пользовании стандартным диалогом, который мы
уже реализовали?
-
Будет ли изменяться цвет текста при
тех же условиях?
Теперь запустите приложение и протестируйте его,
изменяя размеры окна и пользуясь диалогом. Как
вы узнали из документации, косметическое перо
может иметь толщину только в 1 пиксел. Если
косметическое перо имеет еще один атрибут
PS_ALTERNATE, то каждый второй пиксел линии
пропускается (не выводится) и создается иллюзия,
что перо стало тоньше, чем 1 пиксел. Опробуем
эту возможность в нашем примере. Для этого
введите в функцию WndProc еще один локальный
массив подсказок.
static
string alt[] = {"PS_ALTERNATE", "PS_COSMETIC" };
Вставьте следующий код в ветвь WM_PAINT перед
вызовом EndPaint, затем запустите и проверьте
результат:
//=======
Косметическое перо
(alternate - solid)
Ib.lbStyle =
BS_SOLID;
sText =
"Косметическое перо alternate или solid";
GetTextExtentPoint(hdc,sText.c_str(),
sText.size(),SszText);
iYPos += 2 *
szText.cy;
iXPos = iXCenter -
szText.cx/2;
TextOut(hdc, iXPos,
iYPos, sText.c_str(), sText.size());
for
(i = 0; i < 2; i+ + ) {
DWORD dw = i ?
PS_COSMETIC : PS_COSMETIC I PS_ALTERNATE;
HPEN hp =
ExtCreatePen(dw, 1, &lb, 0, NULL);
HPEN hOld = (HPEN)SelectObject(hdc,
hp) ;
iYPos += szText.cy;
MoveToEx(hdc, 10,
iYPos, NULL);
LineTo(hdc,
iXMax,iYPos);
SelectObject(hdc,
hold);
DeleteObject(hp);
TextOut(hdc, 10,
iYPos, alt[i].c str(), alt [i] . size ()); |