
- •Уп. 3. Вывод в окно
- •3.1. Сообщение wm_paint
- •3.2. Виды контекста отображения
- •Общий контекст отображения
- •Контекст отображения для класса окон
- •Личный контекст отображения
- •Родительский контекст отображения
- •Контекст отображения для окна
- •3.3. Установка атрибутов контекста отображения
- •3.4. Вывод текста
- •3.4.1. Настройка параметров шрифта
- •3.4.2. Выбор шрифта в контекст отображения
- •3.4.3. Функции вывода текста
- •3.4.4. Пример вывода текста в окно
- •3.4.5. Определение метрик шрифта
- •3.5. Рисование геометрических фигур
- •3.5.1. Функции рисования точки
- •3.5.2. Функции рисования линий
- •3.5.3. Функции рисования замкнутых фигур
- •Контрольные вопросы
- •Упражнения
- •Приложение 3
Личный контекст отображения
Этим контекстом обладают окна класса со стилем CS_OWNDC. Личный контекст получают один раз и настраивают его атрибуты, а освобождают только при завершении работы приложения. Функции BeginPaint, EndPaint, GetDC и ReleaseDC не влияют на личный контекст. Личный контекст экономит расход оперативной памяти.
Рассмотрим пример с таким контекстом. В предыдущем приложении стиль класса изменим на класс окон с личным контекстом:
wc.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
Тогда произойдут следующие изменения:
1. При запуске приложения устанавливаются атрибуты контекста только для окна hwnd1:
ContAttr(hwnd1);
Это можно заметить сразу после запуска. Окно hwnd1 при выводе использует атрибуты личного контекста, установленные функцией ContAttr. Окно hwnd2 использует атрибуты личного контекста, установленные по умолчанию операционной системой.
2. Экспериментируя с окнами, нажимая на клавиши мыши, можно заметить, что изменения атрибутов контекста одного окна никак не изменяют атрибутов вывода в другом окне. То есть каждое окно обладает своим личным контекстом.
Родительский контекст отображения
Этот контекст используют дочерние окна. Он позволяет дочерним окнам "унаследовать" атрибуты контекста отображения у родительского окна. Например, дочернее окно может использовать для вывода текста тот же шрифт и цвета, что и родительское окно.
С этой целью в стиле класса дочерних окон указывают значение CS_PARENTDC.
Контекст отображения для окна
Описанные выше контексты позволяют рисовать только в рабочей области окна. Контекст отображения для окна позволяет рисовать в любом месте окна – в области заголовка, системного меню, рамок, кнопок изменения размера окна и т. п.
Контекст отображения для окна получают с помощью функции GetWindowDC. Далее он используется аналогично общему контексту отображения. При этом начало системы координат находится в левом верхнем углу окна, а не рабочей области. Прототип функции подобен прототипу функции GetDC:
HDC GetWindowDC( HWND hwnd);
Для освобождения контекста отображения для окна вызывают функцию ReleaseDC.
Для вывода в различные части окна нужно предварительно определить метрики окна с помощью функции GetSystemMetrics.
Задача. Заголовок окна вывести красным шрифтом.
Листинг 3.5. Вывод в область заголовка окна.
#include <windows.h>
#include <tchar.h>
BOOL RegClass(WNDPROC, LPCTSTR, UINT);
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
HINSTANCE hInstance;
TCHAR szClass[] = TEXT("MyCaption");
int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrevInst, LPSTR lpszCmdLine, int nCmdShow)
{
MSG msg;
HWND hwnd;
hInstance = hInst;
if (!RegClass(WndProc, szClass, COLOR_WINDOW))
return FALSE;
hwnd = CreateWindow(szClass, NULL,
WS_OVERLAPPEDWINDOW | WS_VISIBLE,
CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
0, 0, hInstance, NULL);
if (!hwnd) return FALSE;
while(GetMessage(&msg, 0, 0, 0)) DispatchMessage(&msg);
return msg.wParam;
}
BOOL RegClass(WNDPROC Proc, LPCTSTR szName, UINT brBackground)
{
WNDCLASS wc;
wc.style = wc.cbClsExtra = wc.cbWndExtra = 0;
wc.lpfnWndProc = Proc;
wc.hInstance = hInstance;
wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = (HBRUSH)(brBackground+1);
wc.lpszMenuName = NULL;
wc.lpszClassName = szName;
return (RegisterClass(&wc) != 0);
}
LRESULT CALLBACK WndProc( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
static short nCap, nFr;
TCHAR szCap[] = TEXT("Мой заголовок окна");
switch (msg)
{
case WM_CREATE:
{
//Определяем высоту заголовка окна
nCap = GetSystemMetrics(SM_CYCAPTION);
//Определяем толщину рамки окна
nFr = GetSystemMetrics(SM_CYFRAME);
return 0;
}
case WM_MOVE:
case WM_SIZE:
{
HDC hdc = GetWindowDC(hwnd);
//Установка атрибутов вывода и вывод текста
SetTextColor(hdc, RGB(255, 0, 0));
SetBkMode(hdc, TRANSPARENT);
TextOut(hdc, nCap+nFr, 3*nFr/2, szCap, _tcslen(szCap));
ReleaseDC(hwnd, hdc);
return 0;
}
case WM_DESTROY: { PostQuitMessage(0); return 0; }
}
return DefWindowProc(hwnd, msg, wParam, lParam);
}
При создании окна определены высота заголовка и толщина рамки окна:
nCap = GetSystemMetrics(SM_CYCAPTION);
nFr = GetSystemMetrics(SM_CYFRAME);
При любом изменении размеров и перемещении окна в область заголовка выводится строка "Мой заголовок окна". В соответствии с требованиями задачи установлены красный цвет шрифта и прозрачный режим вывода (текущий фон используется в качестве фона вывода текста):
SetTextColor(hdc, RGB(255, 0, 0));
SetBkMode( hdc, TRANSPARENT);