Иногда возникает необходимость управлять какими-либо параметрами тренда или журнала. В качестве примера мы рассмотрим управление видимостью перьев на тренде.
Прежде чем изменять или обращаться к каким-либо параметрами тренда нужно сначала получить его класс. Принцип получения класса и журнала, и тренда полностью идентичен, но способ получения класса отличается в зависимости от того находится тренд/журнал на мнемосхеме или сделан как отдельный документ.
В качестве примера сделаем скрипт, который будет управлять видимостью трех перьев тренда расположенного на мнемосхеме.
Сначала сделаем необходимую заготовку проекта – создадим три значения с имитацией (их мы добавим на тренд), три команды видимости перьев (ими мы будем управлять видимостью), команду Применить и скрипт, с 4 входами – состоянием видимости и Применить. На мнемосхему добавим тренд и элементы управления видимостью.

Видимость перьев будет применять только после нажатия оператором кнопки Применить. Сделаем чтобы код вызывался по переднему фронту:
public partial class ФБ : ScriptBase { bool? M=false; public override void Execute() { if (Применить==true && M==false) { } M=Применить; } } |
Скрипт будет обращаться к тренду, расположенному на мнемосхеме объекта в котором он расположен. При этом на одной мнемосхеме может быть расположено несколько трендов, кроме того возможна ситуация, когда открыты разные окна (например, мнемосхема и окно объекта), каждое из которых будет иметь по тренду. Поэтому мы добавим две константы – с именем тренда, и названием документа на котором он расположен. Также добавим переменную хранящую текущий объект, а также переменную для всего проекта – она нам понадобится для поиска тренда.
const string ИМЯ_ТРЕНДА = "Тренд"; const string ИМЯ_ОКНА = "Мнемосхема"; bool? M=false; public override void Execute() { //Ссылка на текущий проект var проект = HostFB.TreeItemHlp.Project; //получаем корневой объект var объект = (ITreeItemHlp)HostFB.TreeItemHlp.Parent; |
Теперь обратимся к тренду. В MasterSCADA все тренды реализованы в виде отдельных потоков, поэтому обратится к тренду расположенному на определенной мнемосхеме нельзя – нужно найти его среди открытых трендов, и уже после этого работать с ним. Поскольку мы будем обращаться к другим потокам, то код выполняющий данную операцию должен быть заключен в метод BeginInvoke:
https://msdn.microsoft.com/ru-ru/library/0b1bf3y3(v=vs.110).aspx
Код будет выглядеть следующим образом:
//получаем тренд RTManager.Instance.ThreadHolder.BeginInvoke(new ThreadStart(delegate { //здесь разместим код для работы с трендом })); |
Для того чтобы метод BeginInvoke был доступен, нужно в секции using подключить сборку using MasterSCADA.RT.
Теперь приступим к перебору всех открытых трендов:
//получаем тренд RTManager.Instance.ThreadHolder.BeginInvoke(new ThreadStart(delegate { //перебираем открытые тренды foreach (Trend trend in проект.GetService<TrendService>().Opened) { var host = trend.Host as System.Windows.Forms.Control; if (host!=null) { Object name = WinFormsControlBase.GetAmbientProperty(host, WindowlessControlBase.DISPID.DISPID_AMBIENT_NAME); if (name.ToString()!=ИМЯ_ТРЕНДА || trend.Attribute.TreeItem.ID!=объект.ID || trend.Attribute.DisplayName!=ИМЯ_ОКНА) continue; } } })); |
С помощью цикла foreach, мы перебираем все открытые тренды. Каждый тренд полученный в цикле (переменная trend), мы с помощью оператора as проверяем и приводим полученный элемент к типу System.Windows.Forms.Control, после чего проверяем его на null – таким образом мы должны убедится, что действительно обратились к контролу. Затем мы определяем имя полученного контрола.
Теперь проверим что мы получили именно тот тренд, который нам нужен – мы проверим совпадает ли имя с прописанной в константе ИМЯ_ТРЕНДА, убедимся, что ID объекта мнемосхемы, на котором расположен тренд, равен ID объекта в который вставлен скрипт, и что название документа, на котором расположен тренд, равен константе ИМЯ_ОКНА. В противном случае мы переходим к следующему контролу с помощью оператор continue.
После этого начинать работать с переменной trend – обращаться к его свойствам. В данном случае нам нужно получить коллекцию перьев, а затем поочередно задать видимость каждого пера, согласно значению на входе.
//получаем коллекцию перьев var list = trend.Settings.Objects.OfType<MasterSCADA.Graph.Objects.Graph2D>().ToList(); //далее поиск по номеру //получаем нулевое перо var param=list[0]; //скрыть видимость параметра тренда param.Visible=Видимость_пера_0.Value; //получаем первое перо param=list[1]; //скрыть видимость параметра тренда param.Visible=Видимость_пера_1.Value; //получаем второе перо param=list[2]; //скрыть видимость параметра тренда param.Visible=Видимость_пера_2.Value; |
Скрипт готов. Итоговый код выглядит так:
public partial class ФБ : ScriptBase { const string ИМЯ_ТРЕНДА = "Тренд"; const string ИМЯ_ОКНА = "Мнемосхема"; bool? M=false; public override void Execute() { if (Применить==true && M==false) { //Ссылка на текущий проект var проект = HostFB.TreeItemHlp.Project; //получаем корневой объект var объект = (ITreeItemHlp)HostFB.TreeItemHlp.Parent; //получаем тренд RTManager.Instance.ThreadHolder.BeginInvoke(new ThreadStart(delegate { foreach (Trend trend in проект.GetService<TrendService>().Opened) { var host = trend.Host as System.Windows.Forms.Control; if (host!=null) { Object name = WinFormsControlBase.GetAmbientProperty(host, WindowlessControlBase.DISPID.DISPID_AMBIENT_NAME); if (name.ToString()!=ИМЯ_ТРЕНДА || trend.Attribute.TreeItem.ID!=объект.ID || trend.Attribute.DisplayName!=ИМЯ_ОКНА) continue; //получаем коллекцию перьев var list = trend.Settings.Objects.OfType<MasterSCADA.Graph.Objects.Graph2D>().ToList(); //далее поиск по номеру //получаем нулевое перо var param=list[0]; //скрыть видимость параметра тренда param.Visible=Видимость_пера_0.Value; //получаем первое перо param=list[1]; //скрыть видимость параметра тренда param.Visible=Видимость_пера_1.Value; //получаем второе перо param=list[2]; //скрыть видимость параметра тренда param.Visible=Видимость_пера_2.Value; } } })); } M=Применить; } } |
Проверим работу скрипта – запустим режим исполнения и попробуем скрыть какое-либо перо.

Если необходимо менять настройки закрытых трендов или в режиме разработки, то в этом случае применяются другие методы – загружается файл настроек тренда и выполняются изменения.
В качестве примера мы будем менять путь к папке снимков (папка по умолчанию куда происходит сохранение экспортируемых в графические форматы графиков) у тренда «Тренд» текущего объекта.
Сначала обратимся к текущему объекту и переберем все его тренды. Если имя тренда не равно, то выйдем из цикла.
var объект=HostFB.TreeItemHlp.Parent; IAttributesHlp trends = объект.Attributes; foreach (IAttributeHlp trend in trends) { if (trend.Attribute.DisplayName!= "Тренд") continue; } |
Теперь откроем настройки тренда и выполним изменение настройки «Папка снимков».
var объект=HostFB.TreeItemHlp.Parent; IAttributesHlp trends = объект.Attributes; foreach (IAttributeHlp trend in trends) { if (trend.Attribute.DisplayName!= "Тренд") continue; using (var changer = new TrendSettingsChanger()) { //загрузка настроек var настройки = changer.Load(trend.DocFile); //изменение настроек string ИМЯ_НАСТРОЙКИ_ТРЕНДА = "Папка снимков"; string ЗНАЧЕНИЕ_НАСТРОЙКИ_ТРЕНДА= @"D:\Тренды"; if (trend.Opened==false) { var результат = настройки.SetProperty(trend, ИМЯ_НАСТРОЙКИ_ТРЕНДА, ЗНАЧЕНИЕ_НАСТРОЙКИ_ТРЕНДА); } } } |
Больше ничего не требуется.
Проверка на состояние открытия тренда требуется из-за того, что данный метод работает только для закрытых трендов. У открытых трендов настройки меняются по методу, описанному выше. Поэтому если требуется менять параметры трендов в режиме исполнения, то нужно комбинировать оба метода – сначала менять настройки всех открытых трендов, а затем закрытых.
По ссылке можно скачать пример такого скрипта, в котором происходит изменение настроек всех трендов проекта (как закрытых, так и открытых).