закладке
File View и выполним двойной щелчек на пункте
DrawDIg.h.
• Включите объявления переменных m_PrevX и m_PrevY следующим образом:
// DrawDIg.h: header file
//
////////////////////////////////////////////////////
// CDrawDIg dialog c
lass CDrawDIg: public CDialog
{
// Construction
public:
CDrawDlg(CWnd* pParent = NULL); // standard constructor
////////Мой код начинается здесь///////////
int m_PrevX;
int m_PrevY;
////////Мой код заканчивается здесь///////////
//…. //….
}
• Вы объявили две переменные целого типа для хранения предыдущих координат мыши. Заметьте, что вы их включили после слова public: — это означает, что эти переменные доступны всем функциям класса.
• Теперь модифицируем функцию OnMouseMove в файле DrawDIg.cpp
void CDrawDIg::OnMouseMove(UINT nFlags, CPoint point)
{
// TODO: Add your message handler code here and/or call default
////////Мой код начинается здесь///////////
if((nFlags & MK_LBUTTON)==MK_LBUTTON)
{
CCIientDC dc(this);
// dc.SetPixel(point.x, point.y, RGB(123,211,98));
CPen NewPen(PS_SOLID, 10, RGB(255,0,0);
dc.SelectObject(&NewPen);
dc.MoveTo(m_PrevX, m_PrevY);
dc.LineTo(point.x, point.y);
m_PrevX=poi nt.x;
m_PrevY=poi nt.y;
}
////////Мой код заканчивается здесь///////////
CDialog::OnMouseMove(nFlags, point);
}
• Рассмотрим код приведенный выше:
• Код вызова функции SetPixel(), помещен в комментарий, так как он нам больше не понадобиться.
• Следующий код CPen NewPen(PS_SOLID, 10, RGB(255,0,0)) создает новое перо с именем NewPen класса СРеn с заданным размером шрифта 10 пикселов и красным цветом. Параметр PC_SOLID говорит, что будет рисоваться сплошная линия.
• После этого выполняется функция SelectObject, выбирающая новое перо:
dc.SelectObject(&NewPen);
Этой функцией вы включаете перо в работу.
• Следующие два оператора:
dc.MoveTo(m_PrevX, m_PrevY);
dc.LineTo(point.x, point.y);
рисуют линию, используя координаты начала(это определяет функция MoveTo()) и координат конца (LineTo).
• И последний два оператора:
m_PrevX=point.x;
m_P revY=point.y;
сохраняют в переменных m_PrevX и m_PrevY, текущие координаты, которые в следующий раз будут использоваться, как предыдущие(начальная позиция).
• Теперь запустите программу и проверьте правильность ее работы.
• Вы должны заметить, что при первом нажатии на кнопку мышки в любой области диалоговой панели, есть лишняя линия, которая выходит из краев окна. Дело в том, что вы при первом рисовании линии, т. е после первого щелчка мыши и ее передвижении, начальные координаты не определены, а будут известны только текущие.
• Это выглядит примерно так:
• Для решения этой проблемы, вы должны связать код событием WM_LBUTTONDOWN, которое происходит при нажатии на левую кнопку мыши.
• Выберете ClassWizard в меню View
• Выберете закладку Message Maps в панели ClassWizard
• Используйте диалоговую панель ClassWizard для выбора следующего события:
Class Name: CDrawDIg
Object ID: CDrawDIg
Messages: WM_LBUTTONDOWN
• Щелкните на кнопку Add Fucntion.
• Нажмите кнопку Edit Code и напишите следующий код в функции OnLButtonDown():
void CDrawDlg::OnLButtonDown(UINT nFlags, CPoint point)
{
// TODO: Add your message handler code here and/or call default
////////Мой код начинается здесь///////////
m_PrevX=point.x;
m_PrevY=point.y;
////////Мой код заканчивается здесь///////////
…
}
• Код, который вы напечатали, обновляет значения переменных m_PrevX и m_PrevY, тем местоположением мыши, где был совершен щелчок по ее левой кнопке, соответственно при первом и последующих нажатиях кнопки, линия будет начинаться из данной точки нажатия.
• Поэкспериментируйте с программой Draw и щелкните на кнопку Exit для ее прекращения.
Резюме и Упражнение
Упражнение
Сделайте так, чтобы линия, которую вы рисуете была шириной 5 пикселов.
Ответ к упражнению
Для того, чтобы выполнить упражнение вам необходимо изменить код функции OnMouseMove следующим образом:
void CDrawDlg::OnMouseMove(UINT nFlags, CPoint point)
{
// TODO: Add your message handler code here and/or call default
////////Мой код начинается здесь///////////
if((nFlags 8l MK_LBUTTON)==MK_LBUTTON)
{
CCIientDC dc(this);
// dc.SetPixel(point.x, poi nt.y, RGB(123,211,98));
CPen NewPen(PS_SOLID, 5, RGB(255,0,0);
dc.SelectObject(&NewPen);
dc.MoveTo(m_PrevX, m_PrevY);
dc.LineTo(point.x, point.y);
m_PrevX=poi nt.x;
m_PrevY=poi nt.y;
}
////////Мой код заканчивается здесь///////////
CDialog::OnMouseMove(nFlags, point);
}
Резюме
Вы создали и выполнили программу Draw.exe, с помощью которой вы можете рисовать, путем передвижения мыши, при нажатой ее левой кнопки. Также вы познакомились с функцией OnMouseMove, которая выполняется при передвижении мыши, и с функцией OnLButtonDown — при нажатии на левую кнопку мыши.
Вы закончили третий урок!
Ведет Данила Мастер
1. Положим, что мы хотим приблизить вещественное число α € £(0,1) с точностью ε т. е. подобрать с помощью некоторого изображающего аппарата рациональное число — так чтобы p/q
| α — (p/q)|< ε
Воспользуемся для этого двумя изображающими аппаратами, именно систематическими (двоичными) дробями с одной стороны и цепными (непрерывными) дробями — с другой, и оценим потребные для хранения числа а количества информации при каждом из способов представления.
Случай систематических дробей хорошо известен. При разложении числа в двоичную дробь длины m, т. е. при использовании m значащих бит для мантиссы погрешность приближения числа α составит — (1/2)∙2-m = 2-m-1. Поэтому для достижения потребной точности ε мы должны иметь
2-m-1 < ε => -m - 1 < log2 ε => m > -log2 ε - 1 = log2(1/ε) - 1.
Таким образом для достижения точности ε мы должны затратить по меньшей мере
I2(ε) = log2 (1/ε) — 1 (1)
бит информации.
2. Разложим теперь наше число α в цепную дробь:
и возьмем в качестве представления числа α последовательность {а1, а2…., аn}, обрезая цепную дробь на n-м члене, т. е. беря n-ю подходящую дробь (поскольку α € (0,1), то, очевидно, а0 = 0).
Известно, что для записи числа αi, — требуется в среднем log2 αi — бит, и значит для хранения последовательности {а1, а2…., аn} этих бит потребуется по меньшей мере
Iс = Σni=1 log2 ai = log2 Пni=1ai
(2)
Остается связать данное количество информации с потребной точностью представления числа α. Этим мы и займемся.
Известно (см. [1], стр. 40, формула (30)), что подходящая дробь
построенная по числу а, приближает его с точностью 1/q2n:
|α — (pn/qn)| < 1/q2n
Поэтому