Пользовательские графические элементы управления. Часть 2. Библиотека элементов управления
Введение
В статье "Пользовательские графические элементы управления. Часть 1. Создание простого элемента управления" были рассмотрены принципы создания графических элементов управления, на основе этих принципов был создан набор элементов управления для решения основных задач, возникающих при обеспечении взаимодействия между программой (советником, скриптом, индикатором) и ее пользователем.
Часть элементов управления почти полностью соответствует общеизвестным стандартным элементам управления, некоторые разработаны с учетом особенностей и возможностей, предоставляемых терминалом. Все элементы управления выполнены в виде отдельных классов, добавлены в файл IncGUI.mqh, применявшийся в предыдущей статье (теперь файл имеет имя IncGUI_v2.mqh).
Кроме добавления классов с новыми элементами управления, в файле имеются некоторые изменения: в класс CGraphicObjectShell добавлены методы для одновременной установки координат и размеров: SetXYDistance(), SetXYSize(), исправлена опечатка в слове Distance у имен некоторых методов (было Distanse).
В классе CInputBox исправлена опечатка в названии метода SetValueString() (было SetValueStrind), добавлены методы SetReadOnly(), ReadOnly(). Методом SetReadOnly() включается/выключается возможность изменения значения в текстовом поле с клавиатуры, соответственно метод ReadOnly() позволят узнать, разрешен или запрещен ввод с клавиатуры.
У класса CColorSchemes изменен порядок расположения цветовых образцов отображаемых методом Show(), в цветовых схемах получилось несколько большее количество цветов, чем предполагалось, поэтому схемы располагаются по вертикали, а цвета по горизонтали. Кроме этого, в класс CColorSchemes добавлено несколько новых цветовых схем.
В данной статье предлагается библиотека, содержащая следующие элементы управления:
- CInputBox (поле ввода),
- CSpinInputBox (поле ввода с кнопками +/-),
- CCheckBox (чекбокс),
- CRadioGroup (группа радиокнопок),
- CVSсrollBar (вертикальная полоса прокрутки),
- CHSсrollBar (горизонтальная полоса прокрутки),
- CList (список),
- CListMS (список с множественным выделением),
- CComBox (выпадающий список),
- CHMenu (горизонтальное меню),
- CVMenu (вертикальное меню),
- CHProgress (горизонтальная строка прогресса),
- CDialer (номеронабиратель),
- CDialerInputBox (поле ввода с номеронабирателем),
- CTable (таблица).
Рассмотрим каждый из элементов управления с примерами их применения (за исключением CInputBox, он достаточно подробно рассмотрен в статье "Пользовательские графические элементы управления. Часть 1. Создание простого элемента управления").
1. Класс CSpinInputBox
Поле ввода с кнопками "+/-" (рис. 1).
Рис. 1. Класс CSpinInputBox (поле ввода с кнопками +/-)
При щелчке мышкой на кнопке "+" значение, отображаемое в текстовом поле, увеличивается на установленную величину, при щелчке на кнопке "-" - уменьшается.
Кроме изменения значения кнопками "+/-" возможно включить разрешение ввода в текстовое поле с клавиатуры (метод SetReadOnly()). Этот элемент управления создан на основе элемента CInputBox работающего в числовом режиме и имеет подобные ему методы для установки границ изменения значения: SetMaxValue(), SetMinValue().
В отличие от CInputBox, у CSpinInputBox, при вызове метода Init(), вместо параметра Digits передается параметр Change - величина изменения значения при нажатии на кнопки +/-. На основе значения Change определяется количество знаков после запятой, с которым форматируется значение, отображаемое в текстовом поле. Программная установка и получение значения выполняется методами SetValue() и Value(). Методом Digits() можно получить количество знаков после запятой, с которым выполняется форматирование значения.
Пример использования элемента управления находится в приложении в файле eIncGUI_v2_Test_CSpinInputBox.mq5.
2. Класс CCheckBox
Чекбокс или выключатель (рис. 2).
Рис. 2. Класс CCheckBox (чекбокс или выключатель)
Довольно простой элемент управления, может принимать одно из двух значений: включено и выключено. В выключенном состоянии представляет собой квадрат. Во включенном состоянии на квадрате отображается значок "галка". Программное изменение и получение значения выполняется методом SetValue() и Value().
Пример использования элемента управления находится в приложении в файле eIncGUI_v2_Test_CCheckBox.mq5.
3. Класс CRadioGroup
Группа радиокнопок (рис. 3).
Рис. 3. Класс CRadioGroup (группа радиокнопок)
Группа радиокнопок предназначена для выбора какого-то одного из нескольких вариантов (например, выбор типа ордера). Используется элемент управления подобно остальным элементам управления - сначала вызывается метод Init() с указанием в параметрах имени группы, затем создаются кнопки. Кнопки создаются методом AddButton().
Первым параметром метода AddButton() определяется текст надписи, расположенный правее кнопки, затем координаты X и Y кнопки относительно координат всего элемента управления.
Таким образом, кнопки в группе можно расположить в любом порядке (не только по горизонтали или вертикали), можно перемещать всю группу кнопок путем изменения координат группы без пересчета координат отдельных кнопок. Сколько кнопок нужно создать в группе, столько раз должен быть вызван метод AddButton().
После создания кнопок необходимо указать выбранную кнопку, это выполняется методом SetValue(), у метода один параметр, указывающий индекс выбранной кнопки, кнопки нумеруются от нуля в том порядке, в котором они создавались методом AddButton(). Для получения индекса выбранной кнопки используется метод Value().
Пример использования элемента управления находится в приложении в файле eIncGUI_v2_Test_CRadioGroup.mq5.
4. Класс CVSсrollBar
Вертикальная полоса прокрутки (рис. 4).
Рис. 4. Класс CVSсrollBar (вертикальная полоса прокрутки)
Очень распространенный и известный элемент управления. Вертикальная полоса прокрутки имеет свойства: минимальное значение, максимальное значение (определяют допустимый диапазон изменений значения элемента управления), малое изменение (величина изменения значения при щелчке на верхней или нижней кнопке), большое изменение (величина изменения значения при щелчке на поле между кнопкой и ползунком).
Кроме изменения значения на величину малого изменения посредством клика на кнопках, и на величину большого изменение посредством клика на полях между ползунком и кнопками, возможно перемещение ползунка в указанную позицию. Для перемещения ползунка в указанную позицию необходимо щелкнуть мышкой на ползунке, после этого он будет выделен (изменит цвет), затем необходимо щелкнуть на поле в нужном месте, после этого ползунок перескочит в указанное место и сбросит выделение.
Если ползунок выделен по ошибке, для того, чтобы сбросить его выделение, необходимо повторно щелкнуть на нем. Если при выделенном ползунке щелкнуть на одной из кнопок, ползунок перескочит на соответствующий край, и элемент управления будет иметь максимальное или минимальное значение.
Применение элемента управления начинается с вызова метода Init() с указанием в параметрах имени, высоты и условного размера (размер от 1-го до 4-ех).
Затем методами SetMin(), SetMax() определяются границы изменения значения, методом SetSmallChange() устанавливается величина малого изменения, методом SetLageChange() величина большого изменения. Получение значения элемента управления (положения ползунка) выполняется методом Value().
Возможно программное изменение положение ползунка, выполняется методом SetValue().
Пример использования элемента управления находится в приложении в файле eIncGUI_v2_Test_CVSсrollBar.mq5.
5. Класс CHSсrollBar
Горизонтальная полоса прокрутки (рис. 5).
Рис. 5. Класс CHSсrollBar (горизонтальная полоса прокрутки)
Этот элемент управления полностью аналогичен вертикальной полосе прокрутке, за исключением того, что при вызове метода Init(), вторым параметром указывается ширина полосы, а не высота.
Пример использования элемента управления находится в приложении в файле eIncGUI_v2_Test_CHSсrollBar.mq5.
6. Класс CList
Список (рис. 6).
Рис. 6. Класс CList (список)
Элемент управления представляет собой несколько текстовых полей в которых отображаются пункты списка. Количество видимых полей определяется при инициализации элемента управления. Если количество пунктов списка превышает количество видимых полей, отображается вертикальная полоса прокрутки.
Один из пунктов списка может быть выделен (цветной пункт на рис. 6). В отношении выделения пункта, элемент управления может работать в двух режимах: с разрешением снимать выделение с пункта и без, эти режимы работы устанавливаются методом SetAllowDeselect().
При вызове метода Init() в параметрах передается имя элемента управления, его ширина в пикселях и высота в количестве пунктов.
После вызова метода Init() используется метод AddItem() для добавления в список нового пункта. Затем, при необходимости, методом SetSelectedIndex() устанавливается выделенный пункт. Программно всегда можно снять выделение пункта, передав в метод SetSelectedIndex() значение -1.
Определить выделенный пункт можно методом SelectedIndex(), если метод возвращает -1, это означает, что в списке нет выделенного пункта. Кроме того, можно получить текст выделенного пункта методом SelectedText().
Для получения текста любого пункта списка используется метод Text() с указанием индекса пункта. Возможно изменение текста любого пункта - метод SetText(), удаление пункта - метод DeleteItem(), полная очистка списка - метод Clear().
Пример использования элемента управления находится в приложении в файле eIncGUI_v2_Test_CList.mq5.
7. Класс CListMS
Список с множественным выделением (рис. 7).
Рис. 7. Класс CListMS (список с множественным выделением)
Этот элемент управления идентичен элементу управления "Список" за одним исключением, допускается одновременное существование нескольких выделенных пунктов. Соответственно используется несколько иной способ доступа к выделенным пунктам.
У простого списка в метод SetSelected() передается один параметр, указывающий индекс выделяемого пункта (при выделении нового пункта, с предыдущего снимается выделение), у этого списка в метод SetSelected() передается два параметра: индекс и состояние пункта (true/false - выделен/не выделен). Для проверки выделен ли пункт, используется метод Selected(), в который передается индекс проверяемого пункта.
Для работы со всеми выделенными пунктами списка используются методы FirstSelected() и NextSelected(). Метод FirstSelected() возвращает индекс первого выделенного пункта списка, метод NextSelected() - возвращает индекс следующего выделенного пункта, после индекса пункта полученного при последнем вызове метода FirstSelected() или NextSelected().
Для прохода в цикле по всем выделенным пунктам можно использовать следующую конструкцию:
// Перебор в цикле всех выделенных пунктов int Selected=lstm.FirstSelected(); while(Selected!=-1){ //======================================= // Что-нибудь делаем с выделенным пунктом // ====================================== Selected=lstm.NextSelected(); }
Пример использования элемента управления находится в приложении в файле eIncGUI_v2_Test_CListMS.mq5.
8. Класс CComBox
Выпадающий список (рис. 8.1).
Рис. 8.1. Класс CComBox (выпадающий список)
Элемент управления представляет собой текстовое поле с небольшой кнопкой, при щелчке мышкой на кнопке раскрывается список (рис. 8.2). Для отображения списка используется элемент управления "Список". Текст выделенного в списке пункта отображается в видимом текстовом поле.
Этот элемент управления может использоваться в двух режимах: в одном режиме допускается только выбор из списка, во втором - допускается ввод с клавиатуры (режим устанавливается методом SetReadOnly()). В связи с этим, имеются некоторые отличия этого элемента управления от списка.
Если введенное с клавиатуры значение имеется в списке, то в списке будет выделен соответствующий пункт, а метод SelectedIndex() будет возвращать индекс этого пункта.
Если же введенного значения нет в списке, метод SelectedIndex() будет возвращать -1, поэтому для получения значения этого элемента управления используется метод Value(), метод возвращает содержимое видимого текстового поля, соответственно для программной установки значения может использоваться метод SetSelectedIndex() (идентично щелчку мышкой на пункте) или метод SetValue() (идентично вводу значения с клавиатуры).
Рис. 8.2. Выпадающий список в развернутом состоянии
Пример использования элемента управления находится в приложении в файле eIncGUI_v2_Test_CComBox.mq5.
9. Класс CHMenu
Горизонтальное меню (рис. 9.1).
Рис. 9.1. CHMenu (горизонтальное меню)
Элемент управления представляет собой несколько текстовых полей, являющихся пунктами меню, расположенных в горизонтальный ряд, и кнопок по краям. Крайние кнопки с вертикальной линией используются для прокрутки меню к началу и концу, кнопки с уголками - для прокрутки на один "экран" (на количество видимых пунктов). Основное назначение меню - выполнение каких-либо действий в программе.
При щелчке мышкой на пункте меню генерируется событие, по которому должна выполняться какая-нибудь команда. Кроме непосредственного выполнения команд, меню может использоваться для включения/выключения каких-нибудь инструментов.
Например, в эксперте используется несколько вариантов закрытия позиции: по индикаторам 1, 2 и 3. Пользователь может включить какой-то один вариант, все вместе или любое сочетание из двух инструментов, чтобы закрытие позиции произошло по тому индикатору, который даст сигнал к закрытию раньше других.
Предполагается такая схема: при щелчке на меню открывается окно с параметрами инструмента и выключателем инструмента, пользователь устанавливает параметры, включает выключатель, нажимает кнопку "Оk" и инструмент начинает работать.
Для того, чтобы было наглядно видно, какие инструменты включены в работу, имеется метод для установки на пункте отметки (значка "галки") - метод SetChecked(). Если в меню имеются выделенные пункты, оно меняет цвет, что бы было понятно, что в меню имеются включенные инструменты, даже если включенный пункт прокручен за пределы видимости. Узнать программно о существовании отмеченных пунктов можно методом CheckedExist(), а методом Checked() узнать, является ли какой-то конкретный пункт меню отмеченным.
Рис. 9.2. Горизонтальное меню с отмеченным пунктом
Работа с этим элементом управления, также как и со всеми другими элементами управления начинается с метода Init(), в него передается имя элемента управления, ширина в пикселях и количество видимых пунктов. После Init() используется метод AddItem() для добавления пунктов.
Поскольку этот элемент управления подразумевает отображение по его командам других элементов управления, у него имеются методы для получения координат пункта меню на котором выполнялся щелчок мышкой, метод для получения четверти экрана в которой расположен пункт и метод получения ширины пункта, чтобы расположить отображаемый элемент управления на подходящей четверти экрана.
Получение координат выполняется методами LastClickedX() и LastClickedY(), четверти - методом LastClickedQuarter() (значение 1 - левый верхний угол, 2 - правый верхний, 3 - нижний левый, 4 - нижний правый), ширина пункта - методом LastClickedW().
Пример использования элемента управления находится в приложении в файле eIncGUI_v2_Test_CHMenu.mq5.
10. Класс CVMenu
Вертикальное меню (рис. 10).
Рис. 10. Класс CVMenu (вертикальное меню)
Этот элемент управления по своему назначению, функциональным возможностям и способу применения полностью аналогичен горизонтальному меню, только пункты расположены вертикально, а для прокрутки используется вертикальная полоса прокрутки. Одно отличие - вместо метода LastClickedW(), используемого у горизонтального меню для определения ширины пункта, здесь, для определения высоты пункта используется метод ItemHeight().
Пример использования элемента управления находится в приложении в файле eIncGUI_v2_Test_CVMenu.mq5.
11. Класс CHProgress
Горизонтальная строка прогресса (рис. 11).
Рис. 11. Класс CHProgress (горизонтальная строка прогресса)
Этот элемент управления предназначен для контроля процента выполнения какой-нибудь задачи. Например, в исследовательских целях требуется выполнить какой-то сложный, требующий ощутимого времени, расчет для каждого бара на графике. Будет интересно знать на сколько задача выполнена, сколько времени еще остается до окончания ее полного выполнения, чтобы спланировать свое время или хотя бы знать, что программа выполняется, а не зависла. В левой части строки прогресса отображается процент выполнения, в правой части - предположительное время до завершения.
При вызове метода Init() в него передается два параметра: имя и ширина в пикселях. Непосредственно перед входом в контролируемый цикл необходимо вызвать метод Begin(), в который передаются параметры цикла: минимальное значение и максимальное значение. Внутри цикла методом SetValue() устанавливается значение, отображаемое строкой прогресса. По выходу из цикла выполняется метод Reset() для переключения строки прогресса к исходному виду.
При каждом вызове метода SetValue() выполняется перерисовка графических объектов, поэтому использование строки прогресса может стать основным потребителем ресурсов компьютера, что может значительно увеличить время выполнения цикла до уровня не рациональности использования строки прогресса. На такой случай у элемента управления имеется метод SetRefreshInterval(), в который передается интервал обновления в секундах.
При установке интервала обновления, на каждом вызове SetValue() предварительно будет проверяться время последнего обновления элемента управления, если время превышает указанный интервал, то только в этом случае будет выполняться расчет и перерисовка строки прогресса.
Пример использования элемента управления находится в приложении в файле eIncGUI_v2_Test_CHProgress.mq5.
12. Класс CDialer
Номеронабиратель (рис. 12).
Рис. 12. Класс CDialer (номеронабиратель)
Этот элемент управления предназначен для использования в составе класса CDialerInputBox, но может использоваться и самостоятельно.
Например, при нажатии на какую-нибудь кнопку, элемент управления становится видим, пользователь набирает значение, нажимает кнопку "OK" и далее программа использует значение получаемое методом Value(), что, собственно, и сделано в элементе управления "поле ввода с номеронабирателем", только последнее введенное значение всегда отображается в текстовом поле, возле которого расположена кнопка для открытия номеронабирателя.
В метод Init() передается один параметр - имя.
Назначение кнопок: кнопка "Х" - закрытие номеронабирателя без изменения значения, "C" - сброс набранного значения, "OK" - применение набранного значения, назначение кнопок с цифрами очевидно, кнопка с точкой - ввод десятичного разделителя, кнопка "-" - смена знака числа (положительное/отрицательное). В текстовом поле в нижней части номеронабирателя отображаются набираемые цифры.
Пример использования элемента управления находится в приложении в файле eIncGUI_v2_Test_CDialer.mq5.
13. Класс CDialerInputBox
Поле ввода с номеронабирателем (рис. 13).
Рис. 13. Класс CDialerInputBox (поле ввода с номеронабирателем)
Этот элемент управления создан на основе элементов управления "поле ввода" и "номеронабиратель", внешне представляет собой текстовое поле с расположенной рядом кнопкой для открытия номеронабирателя. Элемент управления может работать в двух режимах: с вводом только через номеронабиратель и дополнительно с вводом с клавиатуры.
Включение/выключение разрешения ввода с клавиатуры выполняется методом SetReadOnly().
В метод Init() передается четыре параметра: имя, ширина в пикселях, количество знаков после запятой, с которым будет выполняться форматирование значения при отображении и текст надписи, отображаемой рядом с элементом управления.
Пример использования элемента управления находится в приложении в файле eIncGUI_v2_Test_CDialerInputBox.mq5.
14. Класс CTable
Таблица (рис. 14).
Рис. 14. Класс CTable (таблица)
Название элемента управления говорит само за себя - он предназначен для отображения на экране таблиц с данными.
В метод Init() передается три параметра: имя, ширина и высота в пикселях. Фактические размеры таблицы определяются количеством строк, столбцов и их размерами, но не могут быть больше размеров, указанных при вызове Init(). Если фактические размеры таблицы превышают размеры, указанные при вызове Init(), отображаются полосы прокрутки.
Применение. После инициализации таблицы методом Init() выполняется определение количества столбцов таблицы - метод SetCollsCount() и количество строк - метод SetRowsCount(). Вместо метода SetRowsCount() можно использовать метод AddRow(), каждый вызов которого добавляет к таблице одну строку. После определения размеров таблицы (количества колонок и строк) выполняется заполнение ячеек значениями.
Для заполнения ячеек значениями используется метод SetCellText(). Кроме установки текста у ячеек можно менять и все другие свойства: цвет фона, цвет текста, размер шрифта, тип шрифта (методы SetCellBGColor(), SetCellTxtColor(), SetCellFontSize(), SetCellFont()). Для изменения высоты строки используется метод SetRowHeight(), для изменения ширины столбца - SetCollWidth().
Метод SetCellsMerge() используется для объединения нескольких ячеек в одну, у метода четыре параметра: индекс строки, индекс колонки, параметры RowSpan, и CollSpan (аналогичны атрибутам RowSpan и CollSpan в HTML).
Параметром RowSpan определяется количество объединяемых ячеек по вертикали, а параметром CollSpan по горизонтали. Объединенные ячейки можно восстановить, если установить значения RowSpan и CollSpan равными 1.
Для удобства просмотра таблицы она оснащена функцией перекрестья. При щелчке мышкой на какой-нибудь ячейке, столбец и строка этой ячейки выделяются другим цветом. Повторный щелчок на этой строке возвращает таблице нормальный цвет (также и прокрутка возвращает нормальный цвет). Функция перекрестья включается/выключается методом SetAllowSelection(). Ячейку, на которой был выполнен щелчок мышкой, можно узнать при помощи методов LastClickedRaw() и LastClickedColl().
Методом HTML() можно получить HTML-код таблицы для сохранения ее в html файле и последующего просмотра в браузере. Впрочем, этот метод можно использовать и без отображения элемента управления, а просто для получения html-кода таблицы.
Пример использования элемента управления находится в приложении в файле eIncGUI_v2_Test_CTable.mq5.
Заключение
Возможно, представленный в этой статье набор элементов управления не позволит решить все задачи, возникающие при обеспечении взаимодействия программы и ее пользователя, но все же, большинство наиболее распространенных задач охватывается сполна:
- Включение/выключение при помощи чекбокса;
- Выбор различных вариантов при помощи радиокнопок и списков;
- Несколько вариантов быстрого и удобного ввода значений (ввод с клавиатуры, ввод кнопками +/-, номеронабирателем);
- Средства визуального представления данных - те же списки, таблица.
В тех случаях, когда этих элементов управления будет недостаточно, некоторые из них можно использовать как составные части при разработке других элементов управления, более точно соответствующих решаемой задаче. В любом случае, надеюсь, представленные элементы управления будут очень полезны.
Приложение
Список файлов приложения:
- IncGUI_v2.mqh - подключаемый файл с классами CGraphicObjectShell, CWorkPiece, CColorSchemes, CInputBox и классами всех элементов управления, рассмотренных в этой статье. Файл должен располагаться в каталоге MQL5/Include каталога данных терминала).
- eIncGUI_v2_Test_CSpinInputBox.mq5 - пример использования класса CSpinInputBox. Этот и последующие файлы (со 2-го по 16-ый) должны располагаться в каталоге MQL5/Experts.
- eIncGUI_v2_Test_CCheckBox.mq5 - пример использования класса CCheckBox.
- eIncGUI_v2_Test_CRadioGroup.mq5 - пример использования класса CRadioGroup.
- eIncGUI_v2_Test_CVSсrollBar.mq5 - пример использования класса CVSсrollBar.
- eIncGUI_v2_Test_CHSсrollBar.mq5 - пример использования класса CHSсrollBar.
- eIncGUI_v2_Test_CList.mq5 - пример использования класса CList.
- eIncGUI_v2_Test_CListMS.mq5 - пример использования класса CListMS.
- eIncGUI_v2_Test_CComBox.mq5 - пример использования класса CComBox.
- eIncGUI_v2_Test_CHMenu.mq5 - пример использования класса CHMenu.
- eIncGUI_v2_Test_CVMenu.mq5 - пример использования класса CVMenu.
- eIncGUI_v2_Test_CHProgress.mq5 - пример использования класса CHProgress.
- eIncGUI_v2_Test_CDialer.mq5 - пример использования класса CDialer CDialer.
- eIncGUI_v2_Test_CDialerInputBox.mq5 - пример использования класса CDialerInputBox.
- eIncGUI_v2_Test_CTable.mq5 - пример использования элемента класса CTable.
- eIncGUI_v2_Test_All - создание всех элементов управления в одном эксперте.
- IncGUIv2mqh.chm - документация к файлу IncGUI_v2.mqh.
- Бесплатные приложения для трейдинга
- 8 000+ сигналов для копирования
- Экономические новости для анализа финансовых рынков
Вы принимаете политику сайта и условия использования
Кстати, к статье приложена документация по всем классам.
а можно попросить в следующей статье добавить CDialerInputBox для даты и времени?
а за разработку GUI - отдельное спасибо. практически разобрался с функционалом и дописываю свою программку.
а можно попросить в следующей статье добавить CDialerInputBox для даты и времени?
а за разработку GUI - отдельное спасибо. практически разобрался с функционалом и дописываю свою программку.
В следующей статье этого не будет точно. Статья уже готова, остался последний штрих.
Ввод даты, времени... тут еще и календарь напрашивается. Вообще в планах есть, но не в ближайших, к сожалению довольно в отдаленных. Штука сложная, требует тчательного обдумывания, еще хочется ее с вертикальной линией объединить, чтобы можно было дату вертикальной линией указывать (на выбор).
Можно наскоряк слепить из комбоксов, единственый сложный момент - разрулить в каком месяце по сколько дней. Здесь надо записать дату-время начала следующего месяца строкой, строку преобразовать во время, отнять одну секунду, извлечь день месяца.
не знаю может уже и не актуально, но спрошу
когда тяну горизонтальный скрол то и график тянется, это ни как не исправить???