Обертка для контекста устройств
Холст или контекст устройств 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 — для рисования во фрагментах памяти, и т.д.
Далее: Использование перьев и кистей для рисования на холсте.
Перья и кисти внутри классов
Рисование перьями и раскрашивание кистями
Перевод А. И. Легалова
Англоязычный оригинал находится на сервере компании Reliable Software
Подобно живописцу, Вы нуждаетесь в перьях и кистях, чтобы создать шедевр на вашем холсте. Когда Вы вызываете метод Canvas::Line или Canvas::Rectangle, Windows использует текущие установки пера, чтобы рисовать линии, и текущие установки кисти, чтобы заполнять охватываемые контуры.