| / | Форум |
|
vit46
30.12.2009 15:49
Господа, скажите, как вы удаляете объекты индикатора. При этом так, чтобы объекты созданные другими индикаторами или те что были вручную созданы оставались? Я это делаю так, как посоветовали здесь http://forum.mql4.com/ru/12206: void DeleteObjects() { int stop; string name; for(int n=ObjectsTotal()-1;n>=0;n--) { // получаем имя объекта name = ObjectName(n); // удаляем только те, имя которых начинается с префикса в переменной GOGP if (StringFind(name, GOGP, 0)==0) ObjectDelete(name); stop++; if (stop > 100000) break; } Comment("stop=" + stop); } Однако, есть проблема, которая заключается в том, что фактически эта функция прерывается по таймауту, если есть объекты не принадлежащие индикатору по признаку префикса в имени объектов. Как все-таки сделать красиво, но чтобы не считать созданные объекты?? Сразу приведу мой начальный вариант, который более громоздкий, но все-таки работает (состоит из двух процедур): // удаление объектов на графике, которые принадлежат данному индикатору. void DeleteObjectsN() { // Для перехвата последующих ошибок удаления обнуляем предыдущие ошибки которые могли быть. int err = GetLastError(); // Максимальное число попыток удаления объектов. Обычно делает до 20. int MaxTryCount = 1000; // Делаем цикличное удаление до полного отсутствия ошибок. for (int i=0;i<MaxTryCount;i++) { DeleteObjects2(); err = GetLastError(); if (err == 0) break; } // очищаем коммент //Comment(""); return(0); } // это удаляет объекты, но нужно делать много раз, 20 например... // происходит какой-то глюк, хотя при следующем подходе все нормально удаляется. void DeleteObjects2() { int obj_total=ObjectsTotal(); string name; for(int n=0;n<obj_total;n++) { // получаем имя объекта name = ObjectName(n); // здесь происходит ошибка 4202 ERR_OBJECT_DOES_NOT_EXIST, // которая ведет за собой ошибку удаления // удаляем только те, имя которых начинается с префикса в переменной GOGP // и чтобы имя не пустое было, а то это влечет за собой следующую ошибку 4202 или 4204 if (StringFind(name, GOGP, 0)==0 && name!="") ObjectDelete(name); } } |
|
Увеличьте эффективность групповой работы Поставьте TeamWox и увеличьте эффективность групповой работы в вашей компании. TeamWox позволяет хранить всю рабочую информацию в одном месте: письма, документы, файлы, платежи и история сообщений в чате. Так решается проблема сохранности данных и удобной групповой работы с ними. |
|
Integer
30.12.2009 15:51
Уберите stop++; if (stop > 100000) break;и все будет хорошо. |
|
StSpirit
30.12.2009 16:27
Я обычно пишу такой цикл в deinit: for(i = ObjectsTotal() - 1; i >= 0; i--) { if (StringSubstr("полное имя найденного графического объекта", 0, "количество символов сначала строки") != "те самые символы, которые мы выбирали из строки имени объекта") continue; ObjectDelete("полное имя найденного графического объекта"); }При этом в индикаторе стараюсь создавать объекты с уникальными именами, чтобы при удалении объектов построенных индикатором не снести что-нибудь лишнее.
|
|
keekkenen
30.12.2009 16:32
я просто делаю, почти также как и в вашем решении.. к имени каждого объекта добавляется имя кода (советника, индикатора) string name = "bla-bla" + "_" + WindowExpertName(); и по вхождению этого имени объекты удаляются.. objectsDelete(WindowExpertName()); с помощью аналогичной (первый ваш кусок кода) функции .. |
|
Svinozavr
30.12.2009 18:48
У меня когда-то возникла проблема присоединения нескольких копий одного индикатора с графикой, но с разн. параметрами, к одному инструменту. Проблема заключалась как разделить названия объектов, как определить подокно, в ктр. менять объекты в работе или при изменении параметров. Короче, чтобы они не мешали друг дружке сосуществовать. Понятно, что это крайняя ситуация, но ее решение уж точно позволит не заморачиваться с менее сложными, когда индикаторы разные (обычный случай). Сделал маленькую библиотечку. Общие переменные такие: string NAME[]; // массив имен графических объектов int NameCount; // счетчик графических объектов string ShortName=""; // имя инидкатора для вывода в подокно string _ID; // идентификатор (номер) копии индикатора string _GV="Objects"; // имя гл.терм.переменной Сначала, при инициализации индикатора нужно получить через гл.терм.переменную его уникальный ID. Функция GetID() в библиотеке. _ID=GetID() в init(). // генерарация идентификатора индикатора string GetID() { int ID=GlobalVariableGet(_GV); // получить существующий идентификатор индикатора ID++; // новый номер GlobalVariableSet(_GV,ID); // новый номер в гл.пер; (если гл.пер. нет, то создается) return(DoubleToStr(ID,0)); // возврат идентификатора индикатора } Далее, имя объекта создается как ID + [необ.имя] + порядковый номер объекта. Ф-я Name(). Т.е. string ObjName=Name() всегда будет уникальным. Имена ф-я сохраняет в массив string NAME[]. string Name(string obj="") { NameCount++; // счетчик граф. объектов string _Name=_ID+": "+obj+NameCount; // имя объекта = ID индикатора + имя объекта + № гр.объекта ArrayResize(NAME,NameCount); // увеличение массива граф. объектов на 1 NAME[NameCount-1]=_Name; // занесение имени объекта в массив return(_Name); // возврат уникального имени объекта } При создании объекта нужно знать, в каком подокне это делать. Для этого существует ф-я GetWinNumber(). Неважно сколько одинаковых или разных индикаторов, использующих графику, прикреплено - нужный номер найдется без ошибок, т.к. ф-я сначала подставляет в короткое имя ID индикатора, потом узнает по этому имени номер подокна, а потом восстанавливает оригинальное короткое имя. // выяснение текущего номера подокна индикатора int GetWinNumber() { IndicatorShortName(_ID); // подмена: имя индикатора = идентификатору (номеру) копии индикатора int win=WindowFind(_ID); // считан номер подокна с именем идентификатора (номера) копии индикатора IndicatorShortName(ShortName); // восстановлено имя индикатора return(win); // возврат номера подокна } Для удаления созданных индикатором объектов используется ф-я DelObjects(). Используется в deinit() и при пересчете (когда IndicatorCounted() сбрасывается в 0), когда произошла подкачка баров - чтоб графика не сбилась. // уничтожение объектов void DelObjects() { for(int i=0; i<NameCount; i++) ObjectDelete(NAME[i]); // Стереть созданные индикатором объекты ArrayResize(NAME,1); NameCount=0; // сброс массива и счетчика } При удалении индикатора с графика нужно освободить его ID в гл.терм.переменной. Для это есть ф-я DeinitObjects(). Вызывается из deinit(). // осовобождение идентификатора void DeinitObjects() { int ID=GlobalVariableGet(_GV); // получить существующий идентификатор (номер) копии индикатора ID--; // уменьшить номер if(ID==0) {GlobalVariableDel(_GV); return;} // если индикаторов,исп.объекты больше нет,удалить гл.пер. GlobalVariableSet(_GV,ID); // новый номер в гл.пер. }В аттаче эта библиотечка и пример ее использования. В примере графически рисуется МАшка с пиковыми значениями по High/Low. Можете сколько угодно сделать подокон с этим инидкатором, потом индивидуально для каждого менять параметры, уничтожать окна - мешать они друг другу не будут. |
|
Svinozavr
30.12.2009 18:51
А... забыл примерчик.
|
|
gip
01.01.2010 08:02
string Сессия = ""; ... int init() { Сессия = MathRand(); ... int deinit() { Clear(); ... string objname = "Абырвалг " + Сессия; ... void Clear() { int obj_total = ObjectsTotal(); for(int obj = obj_total - 1; obj >= 0; obj--) { string objname = ObjectName(obj); if (StringFind(objname, "Абырвалг " + Сессия) >= 0) ObjectDelete(objname); } }Если я правильно тебя понял. Понималкка отключалась... С прраздником всех... Уфх, отметился... |
|
vit46
01.01.2010 13:47
Svinozavr >>:
У меня когда-то возникла проблема присоединения нескольких копий одного индикатора с графикой, но с разн. параметрами, к одному инструменту. Проблема заключалась как разделить названия объектов, как определить подокно, в ктр. менять объекты в работе или при изменении параметров. Короче, чтобы они не мешали друг дружке сосуществовать. Понятно, что это крайняя ситуация, но ее решение уж точно позволит не заморачиваться с менее сложными, когда индикаторы разные (обычный случай). Сделал маленькую библиотечку. Общие переменные такие: Сначала, при инициализации индикатора нужно получить через гл.терм.переменную его уникальный ID. Функция GetID() в библиотеке. _ID=GetID() в init(). Далее, имя объекта создается как ID + [необ.имя] + порядковый номер объекта. Ф-я Name(). Т.е. string ObjName=Name() всегда будет уникальным. Имена ф-я сохраняет в массив string NAME[]. При создании объекта нужно знать, в каком подокне это делать. Для этого существует ф-я GetWinNumber(). Неважно сколько одинаковых или разных индикаторов, использующих графику, прикреплено - нужный номер найдется без ошибок, т.к. ф-я сначала подставляет в короткое имя ID индикатора, потом узнает по этому имени номер подокна, а потом восстанавливает оригинальное короткое имя. Для удаления созданных индикатором объектов используется ф-я DelObjects(). Используется в deinit() и при пересчете (когда IndicatorCounted() сбрасывается в 0), когда произошла подкачка баров - чтоб графика не сбилась. При удалении индикатора с графика нужно освободить его ID в гл.терм.переменной. Для это есть ф-я DeinitObjects(). Вызывается из deinit(). В аттаче эта библиотечка и пример ее использования. В примере графически рисуется МАшка с пиковыми значениями по High/Low. Можете сколько угодно сделать подокон с этим инидкатором, потом индивидуально для каждого менять параметры, уничтожать окна - мешать они друг другу не будут.Суппер. Ну свинтозавр ты мегамонстр :) Учел всё. Думаю твое решение исчерпывающее. Спасибо. С новым годом всех :) |
|
gip
01.01.2010 14:25
Икк... Конкурс зрительских симпатий выиграл пандеромоторолет Свинозавра... Новоиспеченный пандеромоторолет`чик готов к испытаниям... Ик...
|
|
Svinozavr
01.01.2010 15:44
Всех с НГ. Все-таки конфликт имен возможен. Чтобы он гарантированного не возникал, просто не используйте ф-ю DeinitObjects(). Тогда, правда, гл.терм.переменная будет увеличиваться каждый раз при присоединении нового индикатора с графикой, но не будет уменьшаться при его удалении. Но это - фигня. Вряд ли кому-нить удастся достигнуть предела по double (гл.терм переменные имеют тип double) - это до 1.7 * e308.))) |
|
gip
01.01.2010 18:19
Я плакалъ. Просто возьмите мой код и перестаньте создавать себе проблемы на пустом месте.
|
Авторизуйтесь или зарегистрируйтесь, чтобы добавить комментарий