Динамическое отображение диаграммОдна из возможных областей применения GDIPlus — это создание динамически изменяющихся диаграмм и графиков. Представьте себе такую ситуацию, когда диаграмма формируется одновременно с вводом или корректировкой данных в таблице, отображаемой в управляющем элементе Grid. Пользователь меняет данные и сразу видит результат в виде графика. В этом разделе мы рассмотрим один из способов решения этой задачи на примере формы с условным названием «Итоги по продажам». Создайте таблицу с именем demotable. Записи этой таблицы должны содержать следующие поля:
Введите в таблицу двенадцать строк (по числу месяцев), в
поле montname укажите наименования месяцев (январь, февраль и т.д.), а
остальные поля заполните любыми положительными числами; ограничим
максимальное значение суммы продаж в месяце числом 99999 (предположим, что
это тысячи рублей).
PUBLIC oDPI cPath = JUSTPATH(SYS(16)) SET DEFAULT TO (cPath) SET CLASSLIB TO vfpgdiplus CLOSE TABLES ALL * Открываем таблицу DEMOTABLE.DBF USE demotable IN 0 * Создаём объект GdipImages и в нём - растр размером 510 на 265 пикселей oGPI = CREATEOBJECT("GdipImages") oGPI.CreateBitmap(510, 265, 0xFFEEFFEE) * Рисуем на растре "фон": наименования месяцев и координатные оси lnTop = 10 && Начальное смещение по вертикали lnStep = 20 && Приращение oGPI.CreateSolidBrush(0xFF000000) && Создаём чёрную кисть oGPI.CreateFont("Arial", 13, 0) && Создаём шрифт высотой 13 пикселей SELECT demotable * Рисуем на растре наименования месяцев * с отступом 5 пикселей от левого края SCAN oGPI.DrawString(5, lnTop, 0, 0, ALLTRIM(demotable.monthname)) lnTop = lnTop + lnStep ENDSCAN * Создаём чёрное перо толщиной 1 пиксель ярко-синего цвета llStatus = oGPI.CreatePen(1, 0xFF0000FF) IF llStatus * Рисуем координатные оси, отступив от левого края растра 70 пикселей * (это место занято наименованиями месяцев) llStatus = oGPI.DrawLine(70,5,70,248) llStatus = oGPI.DrawLine(70,248,500,248) ENDIF IF llStatus * Загружаем форму, на которой будем рисовать диаграмму DO FORM DemoChart ELSE * Если имела место ошибка, то сообщаем её код = MESSAGEBOX("Ошибка" + STR(oGPI.GetStatus())) ENDIF RELEASE oGPI В этом коде создаётся растр, который будет использоваться в качестве «фонового рисунка» диаграммы, а в глобальной переменной oGPI запоминается ссылка на объект — экземпляр класса GdipImages. Следующий шаг — создание формы DemoChart. Эта форма должна быть модальной. Установите размеры клиентской области формы равными 725 (ширина) на 275 (высота) пикселей. В принципе, вы можете выбрать любые другие размеры; в моём примере получилось так. Разместите на форме управляющий элемент Grid, расположенный вплотную у левой границы окна формы; установите его ширину равной 205 пикселям. На пять пикселей правее Grid’а будет располагаться область для вывода диаграммы. Свяжите Grid с таблицей demotable.dbf; запретите редактирование первой колонки (с именами месяцев). Добавьте в форму свойство oGPW, которое будет использоваться для хранения ссылки на объект — экземпляр класса GdipWindow. Откройте на редактирование метод Init формы и введите в него следующий код: this.oGPW = CREATEOBJECT("GdipWindow", this) IF VARTYPE(this.oGPW) != "O" RETURN .F. ENDIF Как вы помните, класс GdipWindow предполагает наличие у формы метода ToDraw, который и выполняет рисование. Добавьте этот метод в форму. Его код приведён в листинге 23.18.
LOCAL lnGraphics, llStatus, lnMax, lnValue, lnScale, ; lnTop, lnLeft, lnStep * Копируем таблицу в курсор и находим * максимальное значение для полей year2005 и year2006 STORE 0 TO lnMax, lnValue, lnScale, lnTop, lnLeft, lnStep SELECT * FROM demotable INTO CURSOR t_demo GO TOP SCAN IF lnMax < t_demo.year2005 lnMax = t_demo.year2005 ENDIF IF lnMax < t_demo.year2006 lnMax = t_demo.year2006 ENDIF ENDSCAN * Ширина области для рисования гистограммы равна 420 пикселей lnRegion = 420 lnScale = lnRegion / lnMax && Коэффициент масштабирования lnTop = 12 && Начальное смещение от верхней границы области рисования lnStep = 20 && Шаг приращения * Левая граница гистограмм вычисляется так: * смещение до области вывода растра (210 пикселей) + смещение до оси * координат X на растре (70 пикселей - см. demochart.prg) + 1 пиксель lnLeftRegion = 281 && Левая граница гистограмм * Копируем в lnGraphics дескриптор объекта Graphics, связанного с окном lnGraphics = this.oGPW.GetGraphics() * Рисуем в окне растр; он используется как фоновый рисунок oGPI.DrawImage(this.oGPW.GetGraphics(), 210, 3) * Изменяем цвет пера на зелёный; перо было создано ранее в demochart.prg oGPI.SetPenColor(0xFF00AA00) * Рисуем столбцы гистограммы; каждый столбец шириной 11 пикселей GO TOP SCAN oGPI.SetColorSolidBrush(0xFF0099FF) && Синяя кисть oGPI.FillRectangle(lnLeftRegion, lnTop, t_demo.year2005 * lnScale, 11, lnGraphics) oGPI.DrawRectangle(lnLeftRegion, lnTop, t_demo.year2005 * lnScale, 11, lnGraphics) oGPI.SetColorSolidBrush(0xCC55EE00) && Зелёная чуть прозрачная кисть oGPI.FillRectangle(lnLeftRegion, lnTop+6, t_demo.year2006 * lnScale, 11, lnGraphics) oGPI.DrawRectangle(lnLeftRegion, lnTop+6, t_demo.year2006 * lnScale, 11, lnGraphics) lnTop = lnTop + lnStep ENDSCAN * Рисуем вертикальные линии разметки. Будет выведено 10 вертикальных линий разметки lnStep = lnRegion / 10 oGPI.SetPenColor(0x88AAAAAA) && Меняем цвет пера на светло-серый FOR lnLeft = lnLeftRegion+lnStep TO 10*(lnLeftRegion+lnStep) STEP lnStep oGPI.DrawLine(lnLeft, 10, lnLeft, 250, lnGraphics) ENDFOR * Рисуем текст под разметкой (числовые значения) oGPI.SetColorSolidBrush(0xFF000000) && Меняем цвет кисти на чёрный * Создаём объект StringFormat и устанавливаем режим центрирования текста oGPI.CreateStringFormat() oGPI.SetStringFormatParameter(1) * Определяем инкремент для значений разметки lnMax = lnMax / 10 * В цикле выводим значения разметки lnLeft = 255 FOR i = 1 TO 11 oGPI.DrawString(lnLeft, 253, 50, 16, LTRIM(STR(lnValue)), lnGraphics) lnLeft = lnLeft + lnStep lnValue = lnValue + lnMax ENDFOR Сохраните форму и запустите файл demochart.prg на выполнение. Вы должны увидеть примерно следующее:
Рис.23.3. Вид формы DemoChart Измените несколько значений полей в таблице. Гистограмма тот час же изменится.
|