Перья и кисти внутри классов

Перья и кисти внутри классов

Рисование перьями и раскрашивание кистями

Перевод А. И. Легалова

Англоязычный оригинал находится на сервере компании Reliable Software

Подобно живописцу, Вы нуждаетесь в перьях и кистях, чтобы создать шедевр на вашем холсте. Когда Вы вызываете метод Canvas::Line или Canvas::Rectangle, Windows использует текущие установки пера, чтобы рисовать линии, и текущие установки кисти, чтобы заполнять охватываемые контуры.

Когда объект сопоставляется с Холстом, нельзя забывать освободить его после окончания работы. Это надо делать до тех пор, пока вы не обеспечите такой возможностью вашу программу на языке C++. Используйте только локальные объекты, чьи конструкторы присоединяют, а деструкторы (вызываемые автоматически, при выходе области действия) освобождают объекты (см. страницу «Управление ресурсами» для более детального знакомства с этой методологией). Обратите внимание, что ниже следующие объекты используют HDC (дескрипторы контекстов устройств) в качестве параметры в их конструкторах. Однако, взамен этого, Вы должны просто передать им объект Canvas. Помните, что «Холст» может автоматически приводиться к HDC.

class StockObject {

public:

 StockObject(HDC hdc, int type) : _hdc(hdc) {

  _hObjOld = SelectObject(_hdc, GetStockObject(type));

 }

~StockObject () {

 SelectObject(_hdc, _hObjOld);

 }

private:

 HGDIOBJ _hObjOld;

 HDC _hdc;

};

Windows имеет набор предопределенных перьев и кистей. Если Вы хотите использовать их, то достаточно присоединить выбранные перья и кисти к вашему холсту не некоторое время.

class WhitePen : public StockObject {

public:

 WhitePen(HDC hdc): StockObject(hdc, WHITE_PEN) {}

};

// example

void Controller::Paint(HWND hwnd) {

 PaintCanvas canvas(hwnd);

 WhitePen pen(canvas);

 canvas.Line(0, 10, 100, 10);

 // destructor of WhitePen

 // destructor of PaintCanvas

}

Если ваша программа поддерживает использование несколько перьев, отсутствующих в Windows, Вы можете предварительно создать их (например, внедрив их в объект View) и использовать объект PenHolder, для временного присоединения к Холсту.

class Pen {

public:

 Pen(COLORREF color) {

  _hPen = CreatePen(PS_SOLID, 0, color);

 }

 ~Pen() {

  DeleteObject(_hpen);

 }

 operator HPEN() {

  return _hPen;

 }

private:

 HPEN _hPen;

};

class PenHolder {

public:

 PenHolder(HDC hdc, HPEN hPen) : _hdc (hdc) {

  _hPenOld = (HPEN)SelectObject (_hdc, hPen);

 }

 ~PenHolder() {

  SelectObject(_hdc, _hPenOld);

 }

private:

 HDC _hdc;

 HPEN _hPenOld;

};

class View {

public:

 View() : _penGreen (RGB (0, 255, 128)) {}

 void Paint(Canvas& canvas) {

  PenHolder holder(canvas, _penGreen);

  canvas.Line(0, 10, 100, 10);

  // destructor of PenHolder

 }

private:

 Pen _penGreen;

};

И, наконец, если ваша программа нуждается в произвольных цветных перьях, то есть, невозможно предварительно определить всех цветов, в которых вы будете нуждаться, Вы должны использовать цветные перья. Когда Вы определяете автоматический объект ColorPen, его конструктор создает и присоединяет перо. Когда, в конце области действия, вызывается деструктор, он отсоединяет перо и удаляет его.

class ColorPen {

public:

 ColorPen(HDC hdc, COLORREF color) : _hdc (hdc) {

  _hPen = CreatePen(PS_SOLID, 0, color);

  _hPenOld = (HPEN)SelectObject(_hdc, _hPen);

 }

 ~ColorPen() {

   SelectObject(_hdc, _hPenOld);

   DeleteObject(_hPen);

 }

private:

 HDC _hdc;

 HPEN _hPen;

 HPEN _hPenOld;

};

Точно таким же способом Вы можете работать с кистями (кистей, поддерживаемых Windows, гораздо больше, чем перьев). В качестве примера, ниже дается определение ColorBrush.

class ColorBrush {

public:

 ColorBrush(HDC hdc, COLORREF color) : _hdc (hdc) {

  _hBrush = CreateSolidBrush(color);

  _hBrushOld = (HBRUSH)SelectObject(_hdc, _hBrush);

 }

 ~ColorBrush() {

  SelectObject(_hdc, _hBrushOld);

  DeleteObject(_hBrush);

 }

private:

 HDC _hdc;

 HBRUSH _hBrush;

 HBRUSH _hBrushOld;

};

Как всегда, мы пощряем Ваши собственные эксперименты.

Далее: совершенно иная тема — «Потоки».