- Сечас откройте Class Wizard, а там закладку Member
Variables.
- Отметьте мышкой индетификатор IDC_SHAPES и нажмите на
кнопку Add Variable
- Введите название переменной m_ShapesCombo,
Category - Control, Variable Type -
CComboBox.
- Нажмите OK.
- Закройте ClassWizard.
- Откройте функцию OnInitDialog и в конец(перед
оператором return) добавьте следующий код:
////-Ваш код начинается здесь -////
//Установить начальную позицию
курсора
m_ShapesCombo.SetCurSel(0);
////-Ваш код заканчивается здесь -////
- Этим оператором вы устанавливаете начальную позицию курсора,
на первой строчке.
- Теперь пришло время разобраться в теории, для рисования линий
и фигур нам необходимо применять метод резиновой нити, т.е. когда
вы нажали на мышки и хотите нарисовать фигуру, вы же вначале
подбираете ее размер, т.е. при выборе размера, вы тоже рисуете, но
при каждом движении мыши предыдущий объект должен стираться до тех
пор пока, не будет отпущена мышка, когда это произойдет, надо
будет нарисовать окончательный объект. Так вот метод резиновой
нити рисует фигуру, с инвертированием цветов под ним, т.е. мы
можем различать, когда мы выбираем размеры и когда уже
оканчательно нарисовано. Вся изюменка этого метода в том, что при
повторном рисовании фигуры, предыдущая стирается, а когда кнопку
мышки отпускаете, то рисуется все окончательно без всяких
приколов.
- Теперь расскажу, как все организовать. Вначале мы добавим
переменную m_IsDrawing типа bool, которая будет
принимать два значения false и true, эта переменная
будет отвечать за,то чтобы рисовать при движении мыши или нет.
- Необходимо будет написать саму функцию рисования фигур, в
которой и будет релиазоваться метод резиновой нити и само
рисование, она будет использовать переменную stretch для
определения метода рисования.
- Затем нужно будет изменить немного все функции связанные с
событиями мыши.
- Ну что, начнем.
Добавление функции
DrawShape
- C помощью WorkSpace добавьте функцию с
названием
DrawShape(bool stretch=false), с типом
void и доступом Private. Откроем ее в окне
редактирования. И напишем следующий код, в котором скоро
разберемся:
void CPaintORamaDlg::DrawShape(bool stretch)
{
//Получить
объект контекста устройства
CClientDC dc(this);
//Установить атрибуты
DC
dc.SetAttribDC(dc);
dc.IntersectClipRect(m_Canvas);
//Получить номер позиции из спика названий фигур
int
drawmode=m_ShapesCombo.GetCurSel();
//Выбрать перо
dc.SelectObject(&m_Pen);
//Метод резиновой нити
if(stretch &&
drawmode!=0)
{
//Установить метод резиновой
нити
dc.SetROP2(R2_NOT);
}
//Конструкция выбора
фигуры
switch(drawmode)
{
//Свободное рисование
case
0:
dc.MoveTo(m_LineStart);
dc.LineTo(m_LineEnd);
m_LineStart=m_LineEnd;
break;
//Рисование линий
case
1:
dc.MoveTo(m_LineStart);
dc.LineTo(m_LineEnd);
break;
//Рисование элипсов
case
2:
dc.Ellipse(CRect(m_LineStart,m_LineEnd));
break;
//Рисование прямоугольника
case
3:
dc.Rectangle(CRect(m_LineStart,m_LineEnd));
break;
}
}
- Вначале по стандарту получаем объект контекста устройства,
потом устанавливаем атрибуты DC. Считываем номер выбранного
элемента в списке фигур и записываем его в переменную
drawmode.
- Переменная stretch отвечает за то, чтобы применять
метод резиновой нити или нет, так например, для рисования в
свободной форме(точка за точкой) не нужно удалять предыдущее
состояние, или когда отпускаете кнопку мыши, тоже не надо
применять метод РН.
- Конструкция оператора IF проверяет, что если режим
рисования и номер выбранной фигуры не равны 0, то применить метод
резиновой нити, т.е. если не выбрано свободное рисование и мы
находитесь в стадии выбора размера фигуры, то применить метод
резиновой нити.
- Потом конструкция оператора switch реализует выбор
фигуры и ее рисование. Например, если вы выбрали фигуру овал, то
drawmode будет равен 2, т.е. оператор switch найдет
метку 2 и нарисует элипс, заданный координатами прямоугольника
класса CRect, вы, наверное, заметили, что координаты заданы
двумя переменными и они инициализируют объект класса, который в
свою очередь возращает значение всех четырех координат.
- Оператор break выходит из конструкции оператора
switch, после того, как что-нибудь будет нарисовано.
- И еще заметьте, что предыдущие координаты для свободного
рисования изменяются сразу.
- Теперь надо, изменить все функции обработки сообщений мыши.
- Измените функцию OnLButtonDown следующим образом:
BOOL CPaintORamaDlg::OnLButtonDown(UINT nFlags, CPoint
point)
{
.....
//Проверить было ли нажатие внутри области
рисования.
if(m_Canvas.PtInRect(point))
{
//Присвоить
координаты начала двум переменным
m_LineStart=
point;
m_LineEnd=point;
/////-Ваш код начинается здесь-///
m_IsDrawing=true;
/////-Ваш код заканчивается здесь-/////
m_Pen.DeleteObject();
//Обновить переменные значениями в окне
прграммы
UpdateData(TRUE);
//Создать новую кисть с учетом
размера
m_Pen.CreatePen(PS_SOLID, m_PenWidth, m_PenColor);
//Захватить мышь
SetCapture();
}
}
- Добавленый оператор присваивает значение true
переменной m_IsDrawing, т.е. включается режим рисования,
при отпускании кнопки мыши он будет равен false, т.е.
отключен.
- Теперь нужно в корни изменить код функции OnMouseMove,
удалите весь код внутри оператора IF, т.к. он содержит код
рисования, а он нам не нужен так, как он будет реализован в
функции DrawShape.
- Функция OnMouseMove будет выполнять роль рисования
методом резиновой нити, т.к. пока вы двигаете мышкой, то вы
изменяете размеры фигуры, значит предыдущию фигуру надо стереть,
обновить координаты конца, и опять нарисовать. А окончательно
фигура нарисуется только в том случае, если вы отпускаете кнопку
мыши.
- Откройте функцию OnMouseMove, модифицируйте ее
следующим образом:
void CPaintORamaDlg::OnMouseMove(UINT nFlags, CPoint
point)
{
////-Мой код начинается здесь-///
if(m_IsDrawing&& (nFlags &
MK_LBUTTON) && m_Canvas.PtInRect(point))
{
//Нарисовать фигуру методом резиновой нити
DrawShape(true);
/*Поменять координаты конца на текущее положение
курсора
m_LineStart=m_LineEnd;
//Стереть предыдущую и нарисовать новую
фигуру
DrawShape(true);
////-Мой код заканчивается здесь-///
}
}
- Вначале вы рисуете фигуру методом резиновой нити, передавая
для этого значение аргумента функции true.
- Потом меняете координаты конца на текущее положение курсора, а
повтором первого оператора, вы удаляете предыдущую фигуру
нарисованную методом резиновой нити и рисуете новую.
- Вот такой несложный код.
- Теперь осталось только изменить код функции
OnLButtonUp.
- Нам необходимо, проверить была ли отпущена кнопка, внутри окна
рисования, если да то нарисовать фигуру уже окончательно, а если
нет то стереть предыдущюю фигуру, т.к. когда вы за областью окна
рисования отпускаете мышку, то фигура нарисованная методом
резиновой нити не зарисовывается окончательной, а остается.
- Добавьте следующий код в функцию OnLButtonUp:
void CPaintORamaDlg::OnLButtonUp(UINT nFlags, CPoint point)
{
////-Ваш код начинается здесь-////
//Отключить режим рисования
m_IsDrawing=FALSE;
/*Если мышка отпущена внутри области рисования, то нарисовать
фигуру
окончательно*/
if(m_Canvas.PtInRect(point))
{
m_LineEnd=point;
DrawShape();
}
//Если
нет, то
стереть
else
{
DrawShape(true);
}
m_LineStart=point;
//Отпустить мышь
ReleaseCapture();
////-Ваш код заканчивается здесь-////
}
- Оператор присваивания отключает режим рисования.
- Оператором IF вы проверяете была ли отпущена кнопка
внутри области рисования,
- Если да, то рисуете окончательную фигуру, закрашивая фигуру
нарисованную методом резиновай нити.
- Если нет, то стираете предыдущую фигуру, нарисованную методом
резиновай нити.
- Вот и все с рисованием фигур, но нам еще предстоит, добавить
код выбора стиля закраски фигур и цвет самой закраски. Запустите
программу и попробуйте выбирать любую фигуру и нарисовать
что-нибудь.