Можно создать единственный контекст отображения для всех окон некоторого класса. Для этого при регистрации класса указывают стиль CS_CLASSDC. Тогда все окна этого класса будут пользоваться одним общим контекстом отображения.
Приложения, однажды получив контекст отображения для класса окон, могут не освобождать его. Причем вызов функций EndPaint и ReleaseDC не освобождает такой контекст (хотя и. не вредит работе приложения). Для сохранения единого стиля работы с контекстами рекомендуется всегда вызывать эти функции.
Контекст отображения для класса окон создают один раз. Если создано несколько окон этого класса, область ограничения и начало системы физических координат вывода автоматически настраиваются на то окно, которое использует контекст отображения. Но если на базе класса стиля CS_CLASSDC приложение создало только одно окно, оно может получить контекст отображения для класса окон один раз и не освобождать его.
Таким образом, контекст отображения для класса окон повышает производительность вывода в окна тем, что не требует настройку многочисленных атрибутов контекста отображения после каждого вызова функции BeginPaint или EndPaint.
Задача. Для окон класса стиля CS_CLASSDC создать единый контекст и установить его атрибуты по умолчанию. После нажатия левой клавиши мыши изменить атрибуты контекста, а после нажатия правой клавиши – восстановить исходные значения атрибутов.
Листинг 3.4. Установка атрибутов контекста для класса по умолчанию, изменение атрибутов и восстановление их исходных значений.
#include <windows.h>
#include <tchar.h>
BOOL RegClass(WNDPROC, LPCTSTR, UINT);
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
void ContAttr(HWND hwnd);
HINSTANCE hInstance;
TCHAR szClass[] = TEXT("ClassContext");
int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrevInst, LPSTR lpszCmdLine, int nCmdShow)
{
MSG msg;
HWND hwnd1, hwnd2;
hInstance = hInst;
if (!RegClass(WndProc, szClass, COLOR_WINDOW))
return FALSE;
hwnd1 = CreateWindow(szClass, TEXT("Первое окно"),
WS_OVERLAPPEDWINDOW | WS_VISIBLE,
CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
0, 0, hInstance, NULL);
if (!hwnd1) return FALSE;
hwnd2 = CreateWindow(szClass, TEXT("Второе окно"),
WS_OVERLAPPEDWINDOW | WS_VISIBLE,
CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
0, 0, hInstance, NULL);
if (!hwnd2) return FALSE;
//Устанавливаем исходные атрибуты контекста
ContAttr(hwnd1);
while(GetMessage(&msg, 0, 0, 0)) DispatchMessage(&msg);
return msg.wParam;
}
BOOL RegClass(WNDPROC Proc, LPCTSTR szName, UINT brBackground)
{
WNDCLASS wc;
wc.cbClsExtra = wc.cbWndExtra = 0;
wc.style = CS_HREDRAW | CS_VREDRAW | CS_CLASSDC;
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 cx, cy;
switch (msg)
{
case WM_SIZE:
{ cx = LOWORD(lParam); cy =HIWORD(lParam); return 0; }
case WM_PAINT:
{
TCHAR szText[]=TEXT("Вывод с атрибутами контекста класса");
PAINTSTRUCT ps;
HDC hdc=BeginPaint(hwnd, &ps);
TextOut(hdc, cx/2, cy/2, szText, _tcslen(szText));
EndPaint(hwnd, &ps);
return 0;
}
case WM_LBUTTONDOWN:
{
TCHAR szText[]=TEXT("Изменяем атрибуты контекста класса и выводим");
HDC hdc=GetDC(hwnd);
//Цветом вывода символов выбираем малиновый
SetTextColor(hdc, RGB(255, 0, 255));
//Цветом фона вывода символов выбираем кремовый
SetBkColor(hdc, RGB(255, 251, 240));
TextOut(hdc, cx/2, cy/2-60, szText, _tcslen(szText));
ReleaseDC(hwnd, hdc);
return 0;
}
case WM_RBUTTONDOWN:
{
//Восстанавливаем атрибуты контекста
ContAttr(hwnd);
TCHAR szText[]=TEXT("Восстанавливаем атрибуты контекста класса и выводим");
HDC hdc=GetDC(hwnd);
TextOut(hdc, cx/2, cy/2+60, szText, _tcslen(szText));
ReleaseDC(hwnd, hdc);
return 0;
}
case WM_DESTROY: { PostQuitMessage(0); return 0; }
}
return DefWindowProc(hwnd, msg, wParam, lParam);
}
void ContAttr(HWND hwnd)
{
HDC hdc=GetDC(hwnd);
//Цветом вывода символов устанавливаем синий
SetTextColor(hdc, RGB(0, 0, 255));
//Цветом фона вывода символов устанавливаем желтый
SetBkColor(hdc, RGB(255, 255, 0));
SetTextAlign(hdc, TA_CENTER);
ReleaseDC(hwnd, hdc);
}
Приложение регистрирует класс со стилем контекста для класса:
wc.style = CS_HREDRAW | CS_VREDRAW | CS_CLASSDC;
Затем создает два различных окна этого класса с координатами по умолчанию и устанавливает исходные атрибуты контекста класса:
ContAttr(hwnd1);
При этом не имеет значения, дескриптор которого из окон данного класса служит аргументом этой функции. Для установки атрибутов контекста класса равноправны все окна данного класса.
Оба окна в центре рабочей области содержат один и тот же текст " Вывод с атрибутами контекста класса ", выведенный синим шрифтом на желтом фоне.
Нажатие левой клавиши мыши над рабочей областью любого из двух окон приводит к изменению атрибутов контекста класса. В данном случае цвет шрифта изменяется на малиновый, а цвет фона – на кремовый. Выше текста " Вывод с атрибутами контекста класса " отображается новая строка, выведенная новыми атрибутами: " Изменяем атрибуты контекста класса и выводим ". Обратите внимание, что ни в одном окне цвета шрифта и фона для строки " Вывод с атрибутами контекста класса " еще не изменились.
Если изменить размеры любого из окон, то в этом окне появится строка " Вывод с атрибутами контекста класса " с изменившимися цветами шрифта и фона. То есть при обработке сообщения WM_PAINT используются новые атрибуты контекста.
Нажатие правой клавиши мыши над рабочей областью любого из двух окон приводит к установке исходных атрибутов контекста класса. С этой целью опять вызываем функцию ContAttr. Ниже строки " Вывод с атрибутами контекста класса " появляется новая строка, выведенная с исходными атрибутами: " Восстанавливаем атрибуты контекста класса и выводим ". Обратите внимание, что ни в одном окне цвета шрифта и фона для строки " Вывод с атрибутами контекста класса " еще не изменились.
Если изменить размеры любого из окон, то в этом окне появится строка " Вывод с атрибутами контекста класса " с исходными цветами шрифта и фона. То есть при обработке сообщения WM_PAINT используются исходные атрибуты контекста.