Не получается посчитать размер строки в пикселях, не создавая OBJ_LABEL.

Aleksandr Slavskii  

Здравствуйте.

Задача, написать строку длиннее 62 символов.

Типа такой:


Разбил текст на две строки, от 0 до 11 и от 12 до 24, пытаюсь написать их последовательно.

Для этого надо узнать размер первой строки.

   string txt = "0  " + "1  " + "2  " + "3  " + "4  " + "5  " + "6  " + "7  " + "8  " + "9  " + "10 " + "11 ";
   TextSetFont("Consolas", 20);
   TextGetSize("0", width, height); //  width=9
   int Len = StringLen(txt);        //  Len=36
   Len = Len * (int)width;          //  Len=324

или так

   uint width, height;
   string txt = "0  " + "1  " + "2  " + "3  " + "4  " + "5  " + "6  " + "7  " + "8  " + "9  " + "10 " + "11 ";
   TextSetFont("Consolas", 20);
   TextGetSize(txt, width, height);  //width=324

В результате получаю такую картинку

Но если получать не размер строки, а размер OBJ_LABEL с текстом строки, то получаем совсем другой результат

x_size = (int)ObjectGetInteger(0, "1", OBJPROP_XSIZE); // x_size=540

Как вы видите 540 != 324.  И если вместо 324   поставить отступ 540, то всё рисует как надо. 

Но мне такой способ нахождения размера строки не подходит.

Я понимаю, что что то упускаю из вида, не пойму что.


Скрипт.

#property  script_show_inputs
input int font_size = 20;
//+------------------------------------------------------------------+
void OnStart()
  {
   int X = 10, Y = 10, x_size;
   uint width, height;

   string txt = "0  " + "1  " + "2  " + "3  " + "4  " + "5  " + "6  " + "7  " + "8  " + "9  " + "10 " + "11 ";
   DrawLABEL("1", txt, X, Y);
   ChartRedraw();

   TextSetFont("Consolas", font_size);
   TextGetSize("0", width, height);   // width=9
   int Len = StringLen(txt); //  Len=36
   Len = Len * (int)width;   //  Len=324

   TextGetSize(txt, width, height);  //width=324

   x_size = (int)ObjectGetInteger(0, "1", OBJPROP_XSIZE); // x_size=540

   txt = "12 " + "13 " + "14 " + "15 " + "16 " + "17 " + "18 " + "19 " + "20 " + "21 " + "22 " + "23 " + "24 ";
   DrawLABEL("2", txt, X + (int)width, Y);
   ChartRedraw();
   Sleep(3000);
  }
//+------------------------------------------------------------------+
void DrawLABEL(string Name, string _text, int x, int y)
  {
   ObjectCreate(0, Name, OBJ_LABEL, 0, 0, 0);
   ObjectSetInteger(0, Name, OBJPROP_XDISTANCE, x);
   ObjectSetInteger(0, Name, OBJPROP_YDISTANCE, y);
   ObjectSetInteger(0, Name, OBJPROP_FONTSIZE, font_size);
   ObjectSetString(0, Name, OBJPROP_FONT, "Consolas");
   ObjectSetString(0, Name, OBJPROP_TEXT, _text);
   ObjectSetInteger(0, Name, OBJPROP_COLOR, clrBlack);
  }
//+------------------------------------------------------------------+
Maxim Kuznetsov  

Canvas и прочие resource уже советовали ? 

сделать один bmp и его выводить куда надо

OBJ_LABEL ужасен

Mikhail Dovbakh  
Aleksandr Slavskii:

Здравствуйте.

Задача, написать строку длиннее 62 символов.

Типа такой:


Разбил текст на две строки, от 0 до 11 и от 12 до 24, пытаюсь написать их последовательно.

Для этого надо узнать размер первой строки.

или так

В результате получаю такую картинку

Но если получать не размер строки, а размер OBJ_LABEL с текстом строки, то получаем совсем другой результат

Как вы видите 540 != 324.  И если вместо 324   поставить отступ 540, то всё рисует как надо. 

Но мне такой способ нахождения размера строки не подходит.

Я понимаю, что что то упускаю из вида, не пойму что.


Скрипт.

Используйте другой штрифт. Например, Courier New - там где все символы одной длины.

Aleksandr Slavskii  
Maxim Kuznetsov #:

Canvas и прочие resource уже советовали ? 

сделать один bmp и его выводить куда надо

OBJ_LABEL ужасен

Хочется масштабируемость, а с ресурсами придётся кучу картинок добавлять с разными размерами.

К  Canvas у меня почему то предвзятое отношение, как то раз что то сделал, так оно тестер тормозило безбожно. не стал разбираться переделал на объектах и всё получилось ок.

Aleksandr Slavskii  
Mikhail Dovbakh #:

Используйте другой штрифт. Например, Courier New - там где все символы одной длины.

Я использовал Consolas, это моноширинный шрифт.

Maxim Kuznetsov  
Aleksandr Slavskii #:

Хочется масштабируемость, а с ресурсами придётся кучу картинок добавлять с разными размерами.

К  Canvas у меня почему то предвзятое отношение, как то раз что то сделал, так оно тестер тормозило безбожно. не стал разбираться переделал на объектах и всё получилось ок.

просто судя по скриншоту - вы хотите сделать что-то типа "линейки" и упираетесь в ограничения кол-ва символов и размера OBJ_LABEL. И к тому ширина в пикселях OBJ_LABEL не определена до обновления чарта.

если нечто редко меняется, то очень большой смысл делать его отдельным bmp (resource) и лишь иногда его переделывать. 

сам не люблю Canvas (считаю это очередным костылём) и предпочитаю DLL использовать для генерации подобного. По старинке Cairo surface bmp. Кто хорошо владеет OpenGL могут им

Nikolai Semko  
Aleksandr Slavskii #:

Хочется масштабируемость, а с ресурсами придётся кучу картинок добавлять с разными размерами.

К  Canvas у меня почему то предвзятое отношение, как то раз что то сделал, так оно тестер тормозило безбожно. не стал разбираться переделал на объектах и всё получилось ок.

Ключевое слово - почему-то.

Тормозило, потому что не понимаете специфики канваса и просто не умеете его готовить.
С канвасом реально было бы все проще и надежнее.

По производительности работа канваса и графических объектов примерна одинаково.

Главное отличие заключается в том, что объекты перерисовываются асинхронно вне зависимости от вашего желания.

Перерисовкой канваса полностью управляете вы. Поэтому нужно постоянно контролировать время формирование канваса и его перерисовки.

Торможение в тестере - это не что иное, как то, что вы формируете кадр канваса намного чаще, чем происходит его перерисовка, т.е. например 300 раз в секунду вместо 30 кадров в секунду. Конечно будет тормозить. Не формируйте канвас пока не прошло 20-30 милисекунд после последнего формирования канваса (через GetTickCount()). Тогда не будет тормозов.

Aleksandr Slavskii  
Maxim Kuznetsov #:

И к тому ширина в пикселях OBJ_LABEL не определена до обновления чарта.

Вот это уже интереснее. Если можна поподробнее или ссылочку где об этом пишут.

Aleksandr Slavskii  
Nikolai Semko #:

Ключевое слово - почему-то.

Тормозило, потому что не понимаете специфики канваса и просто не умеете его готовить.
С канвасом реально было бы все проще и надежнее.

Спасибо. Но хочется разобраться именно с этим,  как узнать размер строки.

Nikolai Semko  
Aleksandr Slavskii #:

Спасибо. Но хочется разобраться именно с этим,  как узнать размер строки.

это недоработка MQ. Попробуйте просто умножать на 1.6666 (540/324). Но нет гарантий что потом вылезет другая проблема с мониторами разного DPI.
Проще через канвас. Там выдаст правильное значение, причем не нужно делать даже ChartRedraw, т.е. выводить канвас.

Maxim Kuznetsov  
Aleksandr Slavskii #:

Вот это уже интереснее. Если можна поподробнее или ссылочку где об этом пишут.

сугубо практика :-) попробуйте создать объект OBJ_LABEL и прочитать его XSIZE. До обновления чарта он 0. Более чем объяснимо, и я бы на месте разработчиков сделал бы так-же. Запросить требуемые параметры экрана (который кстати в другом треде), отрендерить по ним шрифт и получить ширину - это долго на самом деле. А собрать коллекцию объектов+опций и потом все их группой в едином месте пересчитать быстрее.

Причина обращения: