Сначала исследуем косметическое перо. Некоторые его стили, задаваемые символьными константами, занесем в массив. Введем внутрь тела оконной процедуры (после объявления 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, которая состоит из последовательности следующих шагов: