Рисующее приложение в версии .NET, страница 10

В окне свойств задайте цвет фона (BackColor), выбрав его из выпадающего списка. Обычно такие окна имеют цвет, обозначенный константой Window (см. список из 26 системных цветов). В поле свойства Text введите DrawDoc, а в поле (Name)DrawView. Для удобства связи с данными документа и взаимодействия с главным окном введите в класс следующие переменные:

private DrawDoc doc;

private MainWindow mainWnd;

public Line curLine;    // Текущая линия рисунка

public Point prevPoint; // Последняя введенная точка текущей линии

Здесь важно вспомнить, что первые три элемента данных хранят ссылки на объекты соответствующих классов, так как их тип — reference, а последний хранит сам объект, так как он имеет тип value. Причина в том, что Point является структура, а не классом. Замените существующий конструктор класса на:

public DrawView (DrawDoc doc, MainWindow parent)

{

InitializeComponent();

this.doc = doc;

this.MdiParent = parent; // Устанавливаем тип взаимодействия с главным окном

mainWnd = parent;

Text = "DrawDoc"+doc.docID.ToString()+":"+doc.viewList.Count.ToString();// Заголовок окна документа

}

По аналогии с MFC создадим метод для получения ссылки на документ, который связан с данным видом.

public DrawDoc GetDocument() { return doc; }

Введение реакций на сообщения Windows

Для того, чтобы рисовать мышью в окне вида текущего документа, в класс DrawView необходимо ввести реакции на сообщения мыши, а также на сообщение о перерисовки окна.

¨  Переведите фокус в окно разработки формы (Design) и нажмите кнопку Events;

¨  В списке событий найдите строку с событием MouseDown и выполните на ней двойной щелчок.

В классе DrawView появится заготовка функции – обработчика события. В ее тело введите следующие коды:

private void DrawView_MouseDown(object sender, MouseEventArgs e)

{

curLine = doc.NewLine();

Point pt = new Point(e.X, e.Y);

curLine.points.Add(pt); // Вставляем первую точку в коллекцию точек линии

prevPoint = pt;

Capture = true; // Захват мышиных сообщений

}

Каждый элемент управления (то есть объект класса, производного от класса Control) имеет свойство Capture, которое имеет тип bool и соответствует режиму обработки сообщений мыши. Если это свойство установлено в true, то это означает, что окно получает все сообщения от мыши, независимо от текущего местонахождения курсора. Для нас это означает: во-первых, возможность рисовать в невидимые части окна вида, во-вторых, не обрабатывать сообщения мыши, если левая кнопка мыши не нажата. Теперь введите в класс вида реакцию на событие MouseMove и вставьте в функцию обработки следующие коды.

private void DrawView_MouseMove(object sender, MouseEventArgs e)

{

if (!this.Capture)     // Если кнопка не нажата, уходим

return;

Point pt = new Point(e.X , e.Y);

curLine.points.Add(pt);

Graphics g = CreateGraphics();

g.DrawLine (doc.curPen, prevPoint, pt);

prevPoint = pt;

}

В отличие от С++-версии приложения, где процесс рисования начинался уже в обработчике нажатия левой кнопки мыши, здесь рисование начинается только при смещении указателя мыши. При этом в игру вступает объект нового для нас класса Graphics, определенного в пространстве имен  System.Drawing. Как сказано в MSDN, он связан со знакомым нам контекстом устройства и инкапсулирует функциональность поверхности для рисования, которая используется подсистемой GDI+, входящей в операционную систему Windows XP. При упоминании о поверхности вспоминается объект canvas, используемый для этой же цели в С++ Builder. Новыми возможностями в GDI+ являются:

¨  преобразования координат (вращение, смещение и масштабирование), производимые с помощью матриц,

¨  управление прозрачностью объектов (alpha blending),

¨  сплайновая аппроксимация кривых (cardinal splines), отличающаяся от существующей в GDI аппроксимации на основе Bézier-сплайнов,

¨  градиентные кисти для заполнения внутренних областей геометрических примитивов,

¨  поддержка различных форматов хранения графики (bmp, gif, jpeg, png, tiff, exif, icon,wmf, emf),