Home > Обертка для контекста устройств > Обертка для контекста устройств
Sep
29

Холст или контекст устройств 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, но во многих случаях это было бы массовым убийством.

Pages: 1 2

, , , , , , , , , ,

Comments are closed.

Потребление памяти: 11.13MB