Холст или контекст устройств Windows
Перевод А. И. Легалова
Англоязычный оригинал находится на сервере компании
Reliable Software
Чтобы раукрашивать, рисовать или
печатать в окне, Вам необходим
контекст устройств (device context или,
кратко, DC). DC - это ресурс, который
заимствуется у Windows и, как
предполагается, возвращается сразу
же после того, как вы сделаете свою
работу. Отсюда и берет корни объект Canvas
(Холст). Конструктор Холста
получает DC, а деструктор
освобождает его. Важно то, что Вы
создаете объекты Canvas как
автоматические (стековые)
переменные. Это гарантирует, что,
когда программа выйдет из
локальной области (контекста),
всегда вызовется их деструктор, в
которой определены ресурсы (прдлагаемый
класс является примером более
общей методологии Управления
ресурсами). Типичное
использование объекта Canvas
демонстрируется следующем кодом (вы
его уже видели в программе Generic):
void Controller::Paint ()
{
// prepare the canvas and let View do the rest
PaintCanvas canvas (_hwnd);
_view.Paint (canvas, _model);
// Notice: The destructor of PaintCanvas called automatically!
}
Различные типы Холста совместно
используют общего предка - класс
Canvas. Обратите внимание, что
конструктор Холста защищен. Фактически,
Вы не можете сформировать объект
этого класса. Однако, наследующие
классы открыты, чтобы обеспечить
доступ к их собственным
конструкторам. Между прочим, Вы
можете осуществлять добавление
новых методов к Холсту, по мере
возникновения такой потребности.
class Canvas
{
public:
// operator cast to HDC
// (used when passing Canvas to Windows API)
operator HDC () { return _hdc; }
void Point (int x, int y, COLORREF color)
{
::SetPixel (_hdc, x, y, color);
}
void MoveTo (int x, int y)
{
::MoveToEx (_hdc, x, y, 0);
}
void Line ( int x1, int y1, int x2, int y2 )
{
MoveToEx (_hdc, x1, y1, 0);
LineTo (_hdc, x2, y2);
}
void Rectangle (int left, int top, int right, int bottom)
{
// draw rectangle using current pen
// and fill it using current brush
::Rectangle (_hdc, left, top, right, bottom);
}
void GetTextSize (int & cxChar, int & cyChar)
{
TEXTMETRIC tm;
GetTextMetrics (_hdc, & tm);
cxChar = tm.tmAveCharWidth;
cyChar = tm.tmHeight + tm.tmExternalLeading;
}
void Text (int x, int y, char const * buf, int cBuf)
{
::TextOut ( _hdc, x, y, buf, cBuf );
}
void Char (int x, int y, char c)
{
TextOut (_hdc, x, y, & c, 1);
}
void SelectObject (void* pObj)
{
::SelectObject (_hdc, pObj);
}
protected:
Canvas (HDC hdc): _hdc (hdc) {}
HDC _hdc;
};
В ответ на сообщение WM_PAINT нужно
создать объект PaintCanvas. Обратите
внимание на способ получения и
освобождения DC объектом PaintCanvas.
class PaintCanvas: public Canvas
{
public:
// Constructor obtains the DC
PaintCanvas (HWND hwnd)
: Canvas (BeginPaint (hwnd, & _paint)),
_hwnd (hwnd)
{}
// Destructor releases the DC
~PaintCanvas ()
{
EndPaint (_hwnd, & _paint);
}
protected:
PAINTSTRUCT _paint;
HWND _hwnd;
};
Другой важный пример - класс
UpdateCanvas, который используется для
графических операций вне контекста
обработки сообщения WM_PAINT. Конечно,
ваша программа может всегда
инициировать перерисовку, вызывая
InvalidateRect, но во многих случаях это
было бы массовым убийством. Если
ваша программа осуществляет
перерисовку новых объектов, когда
они обрабатываются или в ответ на
действия пользователя, Вы можете
модифицировать окно, используя
UpdateCanvas.
class UpdateCanvas: public Canvas
{
public:
UpdateCanvas (HWND hwnd)
: Canvas (GetDC (hwnd)),
_hwnd(hwnd)
{}
~UpdateCanvas ()
{
ReleaseDC (_hwnd, _hdc);
}
protected:
HWND _hwnd;
};
Можно создать и другие типы
Холста: DrawItemCanvas используется для
рисования элементов управления их
владельцем, MemCanvas - для рисования во
фрагментах памяти, и т.д.
Далее: Использование
перьев и кистей для рисования на холсте.
|