Последним испытанием для геометрического пера будет произвольное bitmap-изображение. Если задать BS_PATTERN в качестве стиля кисти, на основе которой создается перо, то линия рисунка может иметь произвольный узор и толщину, что дает волю фантазии разработчика. Однако сначала следует создать ресурс bitmap-изображения, загрузить его и задать его описатель в поле IbHatch логической кисти. Для создания изображения:
Перейдите в окно Resource View.
Раскройте узел дерева под именем API.rc и убедитесь, что в дереве нет узла с именем Bitmap.
Вызовите контекстное меню на узле API.rc и дайте команду Add Resource.
В диалоге Add Resource выберите тип Bitmap и нажмите кнопку New.
Откройте окно Properties и в поле справа от текста ID задайте идентификатор IDB_PAT1 новому точечному изображению.
Измените размер изображения, уменьшив его до 5x5. Используйте для этой цели элементами управления (resize handles) рамки.
Создайте произвольное изображение с помощью контрастирующих цветов.
В окне Resource View вызовите контекстное меню на узле дерева IDВ_РАТ1 и выберите команду Insert Copy.
Измените язык копии на тот, который поддерживается системой, например English (United States), иначе не получится, и нажмите ОК.
Теперь вы имеете копию изображения с теми же размерами и идентификатором. Здесь удобно перевести окно Properties в режим Floating или сдвинуть его нижнюю границу вверх. Измените идентификатор нового изображения на юв_РАТ2 и, при желании, возвратите язык ресурса.
Измените узор второго изображения и повторите пункты 7-10, задав идентификатор ЮВ_РАТЗ для третьего изображения.
Возвратитесь в окно API.CPP и введите в число локальных переменных функции wndProc новые массивы:
//===== Массив идентификаторов bitmap
static UINT nPatterns[] =
{
IDB_PAT1, IDB_PAT2, IDB_PAT3
};
static string bitmap!] =
{
"BS_PATTERN, 1", "BS_PATTERN, 2", "BS_PATTERN, 3"
);
Вслед за фрагментом, моделирующим стиль PS_USERSTYLE , вставьте следующий код:
//======= Геометричесое перо (bitmap)
Ib.lbStyle = BS_PATTERN;
sText = "Стили на основе bitmap-узора (Geometric pen)";
HPEN hp = ExtCreatePen(PS_GEOMETRIC, 5, &lb, 0, 0) ;
HPEN hOld = (HPEN)SelectObject(hdc, hp) ;
iYPos += szText.cy;
MoveToEx(hdc, 10, iYPos, NULL);
LineTofhdc, iXMax,iYPos);
SelectObject(hdc, hOld);
DeleteObject(hp);
TextOut(hdc, 10, iYPos, bitmap[i].c_str(),
bitmap[i] .size () ) ;
}
Запустите на выполнение и проверьте результат. Вы должны получить окно, которое выглядит так, как показано на рис. 3.3. Отметьте, что остались неисследованными еще несколько возможностей по управлению пером — это стили типа PS_ENDCAP_* и PS_JOIN_*. Вы, вероятно, захотите их исследовать самостоятельно. При этом можете использовать уже надоевшую, но достаточно эффективную схему, которой мы пользуемся сейчас.
Рис. 3.3. Стили пера в Win32
Теперь ответим на один из вопросов, которые были заданы по ходу текста этой главы. Для того чтобы изменился цвет текста, надо вставить вызов API-функции SetTextColor. И сделать это надо в ветви обработки сообщения WM_PAINT перед вызовом функции TextOut.
SetTextColor(hdc, color) ;
Подведем итоги. Наш пример иллюстрирует характерные особенности строения приложения, управляемого событиями:
оно должно состоять как минимум из двух функций: winMain и регистрируемой оконной процедуры;
последняя имеет вид отдельных ветвей, обрабатывающих те команды пользователя или сообщения Windows, которые выбрал разработчик;
в более сложных случаях для обработки событий, конечно же, необходимо предусмотреть множество отдельных функций или модулей программы;
приложения Win32, разработанные по рассмотренной схеме, имеют то преимущество, что они не несут дополнительной нагрузки в виде скрытого от ваших глаз каркаса приложения, поэтому дают очень быстрый код;
недостатком приложения Win32 является то, что для их разработки необходимо ориентироваться в мире из тысяч API-функций, вспомогательных структур, макросов и интерфейсов.