Шаг 92 - Резиновый контур

Если Вы работали с графическими программами типа Corel Draw или с этим Вы точно работали Pain, то вы должны знать этот прием. Когда выделяете несколько объектов или рисуете приямоугольник, то у Вас появляется резиновый контур, который будет тянуться за мышкой. С технологией программирования данного метода мы и познакомимся.

Создавайте проект MFC AppWizard имя проекта MouseSelect ставьте Single Document и жмите Finish. Вы можете делать по другому скажем для Doc здесь все упрощено ;-)))).

Все методы будут для класса CMouseSelectView. Итак давайте разберемся с логикой.

 Нажали мышкой. 
	Тут надо сообщить, что начали рисовать и
	получить начальные координаты
 Тащим.
	Постоянного перерисовываем контур
 Отпускаем.
	Прекращаем рисовать о чем сообщаем

Создаем две переменные одна типа CRect, в которой мы будем хранить координаты квадрата вторая BOOL, чтобы определить, что мы действительно рисуем квадрат, а не метаемся по экрану от скуки.

class CMouseSelectView : public CView
{	
	.....
	BOOL TestDraw;
	CRect MouseRect;
	........
};
Теперь нужно начальная инициализация
CMouseSelectView::CMouseSelectView()
{
	// TODO: add construction code here
	TestDraw=FALSE;
}

Нажатие мышкой

void CMouseSelectView::OnLButtonDown(UINT nFlags, CPoint point) 
{
	// TODO: Add your message handler code here and/or call default
	TestDraw=TRUE;
	DrawLine();
	MouseRect.left=point.x;
	MouseRect.top=point.y; 
	MouseRect.right =point.x;
	MouseRect.bottom =point.y; 
        SetCapture();
	CView::OnLButtonDown(nFlags, point);
}

Тащим

void CMouseSelectView::OnMouseMove(UINT nFlags, CPoint point) 
{
	if (TestDraw)
	{
	DrawLine();
	MouseRect.right=point.x; 
	MouseRect.bottom = point.y; 	
	DrawLine();
	CView::OnMouseMove(nFlags, point);
	}
}

Отпускаем

void CMouseSelectView::OnLButtonUp(UINT nFlags, CPoint point) 
{
	TestDraw=FALSE;
	ReleaseCapture();
	CView::OnLButtonUp(nFlags, point);
}

А это загадочная DrawLine:

void CMouseSelectView::DrawLine()
{
 CClientDC dc(this);
 int oldMode=dc.SetROP2(R2_NOT); 
 CBrush* oldBrush=(CBrush*)dc.SelectStockObject(NULL_BRUSH); 
 CPen* oldPen = (CPen*) dc.SelectStockObject(BLACK_PEN);
 dc.Rectangle(MouseRect); 
 dc.SelectObject(oldBrush); 
 dc.SelectObject(oldPen); 
 dc.SetROP2(oldMode); 
}

Итак смотрим. При нажатии левой кнопкой мы устанавливаем координаты MouseRect, в точку. После этого вызываем SetCapture. Это интересная функция. Она скажет Windows, что мышка работает только для данного приложения даже за его приделами. Когда мы мышку перемещаем, то стираем старый прямоугольник и рисуем новый с измененными координатами. В момент когда мышка отпущена освобождаем мышку :-) ReleaseCapture и сбрасываем флаг рисования.

Самое интересно происходит в DrawLine мы получаем контекст устройства, с которым работаем dc(this). Мы устанавливаем режим инвертирования пикселей dc.SetROP2(R2_NOT) сохраняя старый режим. Зачем ? Инвентировали в одну сторону видно, еще раз и изображение восстановилось. Это много лучше, чем перерисовывать весь экран. Дальше устанавливаем перья, рисуем прямоугольник и восстанавливаем режим и перья контекста.

Здесь не предусмотрено много. Например поменяйте размер окна и изображение будет подпорченно. Появится квадрат. Ну это уже не очень большая проблемма. Пишите дополнения :-)))).


Загрузить проект | Предыдущий Шаг | Следующий Шаг | Оглавление
Автор Каев Артем.