Перейти к содержанию
Fire Monkey от А до Я

Nick Peterson

Пользователи
  • Постов

    59
  • Зарегистрирован

  • Посещение

Сообщения, опубликованные Nick Peterson

  1. 2 часа назад, Евгений Корепов сказал:

    добавление по таймеру 100 строк в секунду отнимает примерно 0% процессорного времени

    Благодарю! Стало чуть понятнее - если добавлять 1 строку без Memo.BeginUpdate; из-за какого-то другого бага FMX в процедуре TStyledMemo.DoViewportPositionChange  ContentSizeChanged выставлялся в TRUE, даже если фактические размеры не менялись. Из-за этого запускался цикл

      if ContentSizeChanged then
      begin
        for I := 0 to FLineObjects.Count - 1 do
        begin
          Line := FLineObjects[I];
          if Line.Layout <> nil then
            FLineObjects.UpdateLayoutParams(Line.Layout);
          Line.InvalidateSize;
        end;
        FLineObjects.RenderLayouts;
      end

    приводящий к фризам. Если делать Memo.BeginUpdate, этого не происходит; увидеть фризы, о которых я говорю, можно растягивая форму с Memo.Align = Bottom.

    Теперь к вопросу ЦПУ: Ваш пример в работе на 1-ядерной виртуалке

    image.thumb.png.2b57eefb42f10c95f82ef75ffac8ec47.png

     

    На домашнем компе с GlobalUseDirect2D := false;

    image.thumb.png.8743a438c3b7b65c67d54d54cfb7ac68.png

    Прикладываю архив с тестовым проектом, кому интересно поиграться :)

    MemoSpeedTest.zip

  2. 8 часов назад, krapotkin сказал:

    memo на 5000 строк (в VCL программе, т.е. "те парни из MS") пожирает 80% CPU при изменении/добавлении строки. по сути вся программа работает на лог.

    мой скрин как бы показывает обратное

    два приложения, два одинаковых таймера (100мс в данном случае) на добавление строки. Одна и та же машина (2х ядерная виртуалка).

    1 скрин FMX приложение, второй VCL

    1 потребляет 30-50% CPU второй 6-8%

    Мне нужен след. функционал: текст, являющийся логом и позволяющий промотать хоть немного вверх и скопировать любую.часть себя. Сейчас я ограничил до 300 строк, и с учетом убирания вот этого кода

    image.png.35e2e0c1750d3abee96f244cec274c0e.png

    фризы ушли. Юзеры конечно недовольны, что для просмотра остального надо жать дополнительные кнопки..

    Позвольте пока считать вопрос открытым, может у кого есть на примере компонент или идеи с функционалом , описанным выше

  3. В 20.09.2018 в 11:43, Вадим Смоленский сказал:

    Куда именно при этом переходит фокус, непонятно.

    Было похожее, правда только с окном в состоянии fsStayOnTop

    Временно решил так, пока разбираюсь с более серьёзными глюками платформы))

    procedure TPumpHelper.FormMouseMove(Sender: TObject; Shift: TShiftState; X, Y: Single);
    begin
      If Visible and not Active
        then Show;
    end;

     

  4. 6 часов назад, POV сказал:

    А зачем мемо на 100 тысяч строк?

    специально же приписал в конце, зачем:))

    Вопрос конечно же не в том, "как сделать TMemo на 100 000 строк"

    Вопрос в том, почему TMemo на 100 000 строк так сильно лагает.

    TMemo на 1000 стрк тоже лагает, просто не так сильно, чтобы показать это наглядно на скрине, я не знаю как наглядно аргументировать пост на форуме "TMemo на 1000 строк лагает". В приложении это чувствуется по отзывчивости UI как микрофризы. Они частично лечатся выкидыванием кода как на скрине выше.

    Именно с этими микрофризами я пытаюсь бороться, при этом сохранив возможность видеть лог в виде текста (почему не в БД? потому что запись в БД ведется параллельно, она не лагает и с ней вопросов нет. Но нужно еще и дать пользователю видеть все последние события и иметь возможноть отмотать выше на N-Ное время для сравнения, и вот в этой части как раз вопросы есть).

    А вот мемо на 100 000 лагает так, что это прекрасно видно на графике загрузки ЦПУ, я считаю что это не нормально, поскольку такое же видновое мемо ведет себя совершенно иначе. Значит, это возможно , парням из майкрософта удалось это сделать!:)) Интересно, как...

  5. Провожу тест: заполняю мемо изначально 100 000 строк, затем в таймере добавляю по 1 строке:

    procedure TForm19.Timer1Timer(Sender: TObject);
    begin
    //  While Memo1.Lines.Count > 1000 do Memo1.lines.delete(0); { <- не влияет на поведение }
      inc(Counter);
      Memo1.Lines.Add(Format('==================  new test string number # %d  -- ', [ Counter ]));
      Memo1.GoToTextEnd;
    end;

    Примерно раз в 10 секунд это приложение подвисает секунды на 3-4:(на скрине 2х ядерная виртуалка, т.е. основной поток в эти моменты не отвечает).

    image.thumb.png.b85c3c6ec1ce734af9861e481c94aa00.png

     

    Загрузка ЦПУ в остальное время тоже не кажется мне адекватной, в сравнении с аналогичным VCL приложением:

    image.thumb.png.23551b8c9b3f6e99f909beb4b4a17e8d.png

     

    Первую проблему с фризами можно убрать таким образом:

    image.png.d1bc4211ba4bb95b2b376b6b31a4d974.png

     

    В этом случае отображения скроллбаров становится не совсем корректным, зато убираются фризы, сильно раздражающие пользователей.

    Вопросы такие:

    1) есть ли более быстрый аналог TMemo (для целей вывода лога с возможностью копировать из лога куски, не обязательно целые строки, т.к. ListBox не подходит )

    2) Можно ли как-то получше оптимизировать работу с имеющимся TMemo?

    P.S. 100 000 строк взято для наглядности. В реальном приложении в логе около 1-3 тыс. строк, но и загружено оно помимо вывода лога другими задачами, так что фризы все равно ощутимы.(хотя и не так видны на графике ЦПУ)

     

  6. Реализация VCL

    procedure TTimer.UpdateTimer;
    begin
      KillTimer(FWindowHandle, 1);
      if (FInterval <> 0) and FEnabled and Assigned(FOnTimer) then
        if SetTimer(FWindowHandle, 1, FInterval, nil) = 0 then
          raise EOutOfResources.Create(SNoTimers);
    end;

     

    В FMX иначе, интересно, почему так? есть какая то причина, или просто поленились дописать?

    procedure TTimer.UpdateTimer;
    begin
    {...}
        FTimerHandle := FPlatformTimer.CreateTimer(FInterval, Timer);
        if FTimerHandle = 0 then
          FEnabled := False; // Упс.. таймер просто молча сдохнет)) и будешь гадать что случилось с приложением, почему оно "зависло"
    
    end;

     

  7. В 21.12.2018 в 14:54, POV сказал:

    И пролистай далее до кратного высоте строки числу пикселей.

    Супер! Спасибо, почти идеально стало. Кроме случаев, когда мы уперлись в самый низ))

  8. Возможно это два разных вопроса, и я зря объединил их

    1) Как ускорить ScrollBox? Например, берем грид и начинаем его быстро скроллить вверх-вниз. Для чистоты эксперимента я проверяю на 1-ядерной виртуалке, скоролл жрет 50% ЦПУ. Насколько я понял, так происходит потому, что скролл не использует буфер и отрисовывает каждый раз всю область заново, причем именно на каждое событие мыши

    2) Дальший поиск в гугле привел к TScene https://github.com/eugenekryukov/TScene , инфа о которой крайне скудна, пример выглядит круто, но я не понял, как использовать в боевых условиях ? и в каких именно случаях он помогает, например можно ли решить вопрос N1 с его помощью?

  9. Что делать: находить способы исправления системных глюков и багов FMX (т.е. содержащихся в исходниках FMX)

    Оплата: разовые оплаты в зависимости от сложности.

    Пример: в теме ниже описано 6 "фишек", за все 6 плачу 500$.

    За решение вопроса со шрифтами на D2D канве еще 300$.

    Возможны иные варианты оплаты, пишите ваши предложения в личку.

    (скрин с иллюстрацией проблемы шрифтов

    image.png.4a6a03c928af84402156745130538def.png )

    Возможно дальнейшее сотрудничество (править глюки платформы - это не самоцель разумеется, а вынужденная необходимость)

     

  10. Всем привет:) Еще парочка мелких, но досадных глюков, исправить которые сходу не удалось - буду премного благодарен за помощь!:)

    1) Если включен кастомный стиль (один из Premium pack, например) то форма не растягивается за верхнюю часть, только за нижний угол

    2) TMemo обрезает строчки сверху, которые не влезли целиком. Т.е. рисует кусочки букв вместо того, чтобы вообще не выводить строку

    3) При перетаскивании проги на 2-й монитор ее ярлык остается на основном мониторе.

    4) В TComboColorBox не вписать цвет в числах. Читал на форуме про TEdit в TPopup, подозреваю тут та же проблема, однако от этого не легче))

    5) Если поставить GlobalUseDirect2D := false; то Edit не отображает юникод симводов

    6) если написать так

      FormStyle := TFormStyle.StayOnTop;
      FormStyle := TFormStyle.Normal;

    то хинты перестают отображаться

    Прикладываю тестовый проект с вышеописанным

    Bugs2.zip

  11. 35 минут назад, dnekrasov сказал:

    Проблема есть. Но только на дефолтном стиле. Если загрузить какой-то стиль - проблема исчезает. Так что проблема не в FMX а в дефолтном стиле.

    Точно, спс! Этого я проверить не сообразил, уже легче

  12. 26 минут назад, #WAMACO сказал:

    у меня все отлично!  

    Что значит " у меня " ?)) И при чем тут состояния? в проекте нет ни 1 строки кода, на форме ни одно состояние не тронуто, все дефолтное (кроме свойста StaysPressed). Немного не понял, что Вы имели в виду - если допустить, что баг существует, как именно его можно поправить при помощи модели (в данном тестовом примере)? У меня пока не получилось найти решения.

    Баг существует на 10.2.3 и 10.3, более ранних версий нет под рукой

  13. 1 час назад, #WAMACO сказал:

    и почему SpeedButton, а не Button? 

    Почему? да просто накидал по быстрому тестовый пример. В реальном проекте нет кучи кнопок, там даже при 2х кнопках вылезает баг, но редко. Если кинуть 20 кнопок , то баг вылезет сразу же

    Фокус он держит

    image.png.07ffa4177b6c62a395d752d1b9211afc.png

     

    Тестовый проект для удивления прикладываю:))

     

    Bugs.zip

  14. 2 часа назад, #WAMACO сказал:

    Были вопросы, но они все замечательно решились.

    Вот наткнулся на очередной баг, его исправить быстро уже не удается.. Вы как это решили? или просто не заметили?

    Суть бага: берем TVertScrollBox  кидаем в него кучу кнопок (так, чтобы не все кнопки были в видимой части скролбокса)

    Запускаем, жмем 1 кнопку. Затем скролим пару раз, и видим что нажато стало много кнопок:)

    1) Запустили, нажали SpeedButton9

    image.png.60261996ef6a8e6eaf22ab6a8460cfd8.png

     

    2) покрутили скролл туда-сюда, и видим

    image.png.97ab79823c600d6b98386532fbc9c91f.png

    (багрепорт https://quality.embarcadero.com/browse/RSP-22933?filter=-2 )

  15. По итогу месяца работы на FMX хочу сказать - это глюкодром адский!:)) Вернулся бы обратно на VCL, но жаль потраченного месяца работы :))

    Несколько моментов, может кому будет интересно, кто пойдет по этому пути перевода проекта с VCL:

    1) рисование в буфере перед выводом на PaintBox (знаю что не обязательно, но именно в моей проге нужно, разные куски картинки готовятся в разное время)

    Инфы в одном месте не найти. Даже на этом форуме она не полна и в одном месте ошибочна:)

      XScale := GetWndScale(FormToHWND(OwnerForm)); // только так! Другие методы получения Scale не работают при 
        // перетаскивании проги на другой монитор.   
      w:=trunc(XScale * Image.Width);
      h:=trunc(XScale * Image.Height);
      // при перетаскивании на второй мониторе с другим масштабом Image.Width и Image.Height могут станут неверными. 
      // Помогает только пересоздание хэндла формы (баг)  
      If (bm.Width<>w) or (bm.Height<>h) then 
        bm.SetSize(w,h);
      bm.Canvas.BeginScene;
      bm.Canvas.SetMatrix(TMatrix.CreateScaling( XScale,  XScale) * Matrix);

    1.1) Как нарисовать линию толщиной 1 пиксель? Этот простой вопрос отнял у меня пол дня:) Пришлось править код FMX.Canvas.D2D, по-другому никак не отключить антиалиасинг в битмапе. На форме его можно отключить свойством Quality, вот только его значения перепутаны - HighQuality на самом деле означает худшее качество с размытой графикой.

    Даже после отключения AA нужна еще 1 хитрость - чтобы линия (горизонтальная или вертикальная) получилась толщиной ровно 1 пиксель,  у меня получился примерно такой код

    procedure TCanvasHelper.LineToPix(xFrom, yFrom, xTo, yTo, Opacity: single);
    var pFrom, pTO: TPointF; xs: single;
    begin
      xs := Max(1, Matrix.m11);
      If xs > 1.1 then begin
        pFrom := PointF(xFrom, yFrom).Round;
        pTO   := PointF(xTo, yTo).Round;
      end else begin
        pFrom := PointF(round(xFrom) + 0.5, round(yFrom) + 0.5);
        pTO   := PointF(round(xTo) + 0.5, round(yTo) + 0.5);
      end;
      Stroke.Thickness := 1/xs;
    
      DrawLine( pFrom, pTO, Opacity);
    end;

    2) Шрифты. Это жуть!:) Впрочем об этом пишут везде.

    Заставить в D2D канве (винда) работать ClearType не удалось

    (хотя при рисовании в битмапе как написано выше он у меня заработал, путем очередной правки FMX.Canvas.D2D. Надо еще отметить, что править системные коды я никогда не любил, и на VCL приходилось всего 1 раз, тут же у меня исходники очень быстро лишились девственности:))

    2.2) Шрифты и так выглядят не очень, но еще круче их портит свойство TAlign.Scale, из-за которого позиции контролов принимают не целые значения. Просто киньте на форму пару Label'ов с TAlign.Scale , запустите и начните медленно растягивать, наблюдая как мерцают и размыливаются буковки:))

    Вообще по итогу шрифты оказались самым неприятным моментом, все остальное кое-как правится, кроме внешнего вида приложения с замыленными шрифтами... (отключать D2D канву не предлагать!)

    Почему не доделали SetTextRenderingParams в FMX.Canvas.D2D.pas, почему не работает SetTextAntialiasMode - для меня пока загадка.

    3) Сворачивание приложения кликом по таскбару. Оно не работает:) (Почему за столько лет существования FMX никто этого не заметил? всем плевать, или никто не пользуется?) Да, на форуме есть пара решений, но они не идеальны, если у вас внимательные юзеры, они обязательно заметят странное мелькание приложения при разворачивании. Очередная правка системных кодов.

    4) FMX.TrayIcon.Win - штатного нет, но код выложенный на этом форуме работает идеально. Респект его автору. С ужасом думаю, что буду делать на MacOS..:)

    5) Если в TEdit нажать CTRL-V при пустом буфере, вылезает AV:) Правится не сложно, но блин, очередной системный юнит легко лишился девственности:))

    6) Выделение дабл-кликом на TEdit не работает..... (10.3) Хорошо что FMX.Edit.pas уже лежит в папке с проектом, долго искать не пришлось:))

    7) А на этот с виду несложный вопрос я так и не нашел ответа..

     

  16. Как заставить эврику генерить багрепорты из потоков ? в VCL работало так, в FMX не работает почему-то (10.2.3)

    procedure TTestThread.Execute;
    begin
      try
        raise EAbstractError.Create('Hi!');
      except
        ApplicationHandleException(nil);
      end;
    {...}

     

  17. Как поменять стиль на дефолтный (скажем win10style) после того, как был установлен кастомный?

    TStyleManager.TrySetStyleFromResource('win10style'); 

    работает только 1 раз, второй раз не срабатывает из-за этой проверки
     

    class procedure TStyleManager.SetStyle(const Context, Style: TFmxObject);
    
        if FStyleResources.TryGetValue(StyleResource, OldStyle) and (OldStyle = Style) then
          Exit;

     

    Стили меняю так (в ресурсах у меня zip архив со стилями):

          If CurrentStyle > 0 then begin
            StylesPack[ CurrentStyle - 1 ].Position := 0;
            S := TStyleStreaming.LoadFromStream(StylesPack[ CurrentStyle - 1 ]);
            If S <> nil then TStyleManager.SetStyle(S);
          end else TStyleManager.TrySetStyleFromResource('win10style'); // не работает

     

  18. 14 часов назад, dnekrasov сказал:

    Попробуйте SetForegroundWindow(FormToHWND(Self))

    Работает, если приложение не было свернуто перед этим.

    Остается вопрос, как его развернуть корректно с учетом этой темы:))

     

  19. Как программно вытащить главную форму приложения наверх? (Винда)

    Перепробовал все, стабильно ничего не работает

      // Вариант 1
      WindowState := TWindowState.wsMinimized;
      Show;
      WindowState := TWindowState.wsMaximized;
    
      // Вариант 2
      If TPlatformServices.Current.SupportsPlatformService(IFMXWindowService, ws) 
        then ws.BringToFront(self);
    
      // Вариант 3
      PostMessage(FormToHWND(Self), WM_ShowWindow, SW_PARENTOPENING, 1);
    
      // Вариант 3b
      PostMessage(ApplicationHWND, WM_ACTIVATEAPP, 1, 0);

     

  20. 10 часов назад, mmover сказал:

    Вот такая конструкция получилась (Delphi 10.2.3):

    Данный код не решает вопрос полностью, главное окно сворачивается на десктоп..

    Вот полный лог сообщений, которые проходят по нажатию на иконку в таскбаре

    00:31:19.313  WM_NCACTIVATE  0  0 
    00:31:19.313  WM_ACTIVATEAPP: 0  10176 
    00:31:19.401  SW_PARENTCLOSING  0  1 
    00:31:19.404  WM_ACTIVATEAPP: 1  0  
    00:31:19.410  WM_NCACTIVATE  0  8784630 
    00:31:19.416  WM_NCACTIVATE  1  3213944 
    00:31:19.422  WM_NCACTIVATE  2097152  8784630 
    00:31:19.425  WM_ACTIVATEAPP: 0  5628  
    
    /// нажали снова чтобы развернуть
    
    00:31:22.349  WM_ACTIVATEAPP: 1  10176 
    00:31:22.352  WM_NCACTIVATE  1  8784630 
    00:31:22.383  WM_NCACTIVATE  0  8784630 
    00:31:22.385  SW_PARENTOPENING  1  3 
    00:31:22.388  WM_NCACTIVATE  1  8784630 
    00:31:22.393  WM_NCACTIVATE  0  8784630 

     

    Пока что я придумал только совсем дикое решение - повесить второй аналогичный хук на FMX.Platform.Win.ApplicationHWND с целью игнорировать второе "лишнее" WM_ACTIVATEAPP с wParam=1

     

    P.S. Забавный парадокс, начал переходить на мультиплатформенный фреймворк - пришлось плотнее углубиться в изучение WinAPI:))) (эта тема плюс

     

×
×
  • Создать...