Отображение графика
График отображается в такой последовательности. Сначала рисуется ограничивающий прямоугольник (рамка), затем дважды вызывается функция Scale, которая подготавливает данные для разметки осей. После этого выводятся экстремальные значения функции. В этот момент в более сложном случае следует создавать и выводить так называемую легенду графика – информацию о соответствии маркеров и стилей линий определенным кривым. Так как мы изображаем только одну кривую, то эта часть работы сведена к минимуму. Перед тем как отобразить координатную сетку, следует создать и выбрать в контекст другое перо (gridPen). Сама сетка изображается в двух последовательных циклах прохода по диапазонам координат, подготовленных в методе Scale.
В каждом цикле мы сначала нормируем текущую координату, затем преобразовываем ее в оконную, вызывая одну из функций типа MapToLog*. Одновременно с линией сетки выводится цифровая метка. В ходе процесса нам несколько раз приходится менять способ выравнивания текста (см. вызовы SetTextAlign). Подстройка местоположения текста осуществляется с помощью переменной m_LH (better Height), значение которой зависит от выбранного размера шрифта. После вывода координатной сетки происходит вывод трех строк текста: метки осей и заголовок графика. В последнюю очередь происходит вывод самой кривой графика. В более сложном случае, который не реализован, мы в цикле проходим по всем объектам класса MyLine и просим каждую линию изобразить себя в нашем контексте устройства. Каждая линия при этом помнит и использует свой стиль, толщину, цвет и маркировку:
void CGraph::Draw(CDC *pDC) { //====== С помощью контекста устройства //====== узнаем адрес окна, его использующего CWnd *pWnd =pDC › GetWindow(); CRect r; pWnd › GetClientRect(ir); //====== Уточняем размеры окна m_Size = r.Size(); m_Center = CPoint(m_Size.cx/2, m_Size.cy/2); //====== Сохраняем атрибуты контекста int nDC = pDC › SaveDC(); //====== Создаем черное перо для изображения рамки CPen pen(PS_SOLID, О, COLORREF(0)); pDC › SelectObject(Spen); //====== Преобразуем координаты рамки int It = MapToLogX(-0.S), rt = MapToLogX(0.S), tp = MapToLogY(0.S), bm = MapToLogY(-0.S); pDC › Rectangle (It, tp, rt, bm); //====== Задаем цвет и выравнивание текста pDC › SetTextColor (0); pDC › SetTextAlign(TA_LEFT | TA_BASELINE); //====== Выбираем шрифт pDC › SelectObject (&m_Font); //====== Вычисляем атрибуты координатных осей Scale(m_DataX); Scale(m_DataY); //====== Выводим экстремумы функции CString s; s.Format("Min = %.3g",m_DataY.Min); pDC › TextOut(rt+m_LH, tp+m_LH, s); s.Format("Max = %.3g",m_DataY.Max); pDC › TextOut(rt+m_LH, tp+m_LH+m_LH, s); //====== Готовимся изображать координатную сетку CPen gridPen(PS_SOLID, 0, RGB(92.200, 178)); pDC › SelectObject(SgridPen); pDC › SetTextAlign(TA_CENTER | TA_BASELINE); //====== Рисуем вертикальные линии сетки for (double x = m_DataX.Start; X < m_DataX.End – m_DataX.Step/2.; x += m_DataX.Step) { //====== Нормируем координату х double xn = (x – m_DataX.Start) / (m_DataX.End – m_DataX.Start) -0.5; //====== Вычисляем оконную координату int xi = MapToLogX(xn); //====== Пропускаем крайние линии, //====== так как они совпатают с рамкой if (x > m_DataX.Start && x < m_DataX.End) { pDC › MoveTo(xi, bm); pDC › LineTo(xi, tp);)