Как я отображаю отформатированный (цвет, стиль и т.д.) входят в систему Delphi?

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

AppDomain.CurrentDomain.AssemblyLoad += ....
5
задан norgepaul 13 June 2009 в 09:27
поделиться

6 ответов

Простое решение: используйте TListBox с настраиваемыми методами рисования и поместите записи журнала в TObjectList, используя объекты, которые содержат только основную информацию, а не форматирование (это будет применяться в коде презентации ).

Или используйте компонент Virtual String List / VirtualTreeView . Будут отображаться только те элементы, которые необходимо отобразить, это сэкономит ресурсы.

9
ответ дан 18 December 2019 в 12:01
поделиться

Предполагая, что ваш журнал имеет длину 1 000 000 строк, вы можете забыть об использовании HTML или RTF, самого чистого решения (а я обрабатываю 100–1 000 000 строк) ) заключается в использовании (как предлагает mjustin) TListBox с

Style := lbVirtualOwnerDraw;
OnDrawItem := ListDrawItem; // your own function (example in help file)
  1. . Определите свой массив данных в любом формате, который будет полезен для остальной части приложения. Я использую простой LogObject.
  2. Сохраняю все LogObject в ObjectList, каждый раз, когда в список вносятся изменения (добавьте, remove), настройте TListBox.Count в соответствии с новым счетчиком ObjectList.
  3. Определите ListDrawItem самостоятельно, чтобы получить индекс, и вы можете получить информацию из своего ObjectList (базы данных, что угодно ...) и проанализировать по запросу.

Поскольку вы будете просматривать только несколько записей за раз, подход «синтаксического анализа по требованию» значительно лучше, поскольку нет «замедления» во время загрузки при попытке проанализировать все миллионы строк.

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

Усовершенствования включают прикрепление элемента управления заголовком над списком (я объединяю их вместе в панели), и вы можете создать превосходный элемент управления TListView. Прикрепите немного логики сортировки к событию щелчка в элементе управления заголовком, и вы можете отсортировать список объектов, и все, что вам нужно сделать, это вызвать ListBox.Invalidate, чтобы обновить представление (когда это возможно).

++ Для обновления в реальном времени . Я делаю это в данный момент, чтобы вызвать событие таймера для настройки ListBox.Count, поскольку вы не хотите обновлять список 1000 раз в секунду ..: -)

4
ответ дан 18 December 2019 в 12:01
поделиться

You might want to purchase a lexical scanner or source code / syntax highlighter component for Delphi. There are many available and most are not very expensive. In your case, you'll want to test a few and find one that's efficient enough for your needs.

A few examples are:

For efficiency in highlighting a very large log file, look at the ones that specialize in highlighting text files. They should be extremely fast. But RichEdit is really no slouch either.

1
ответ дан 18 December 2019 в 12:01
поделиться

Если вы решите использовать TListbox, как предлагается, убедитесь, что вы разрешаете пользователям копировать сведения о просматриваемой ими строке в буфер обмена. Нет ничего хуже, чем копирование строк из журнала.

1
ответ дан 18 December 2019 в 12:01
поделиться

Я так понимаю, вы хотите показать существующий текстовый журнал, но применить к нему цвета?

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

  • Запись RTF напрямую; AFAIK, TRichEdit предоставляет прямой доступ к коду RTF; просто переключите свойство PlainText на False, затем установите свойство Text string. Но ... удачи в сборке правильного кода RTF.
  • Преобразуйте ваш журнал в HTML и используйте элемент управления TWebBrowser для его отображения.
  • Используйте элемент управления подсветкой Scintilla (или другой), и разверните свой собственный выделитель синтаксиса ...

Если вы пишете журнал самостоятельно, вы можете также использовать TRichEdit для создания журнала в RTF. Или вы можете сгенерировать журнал в HTML или XML (который затем можно преобразовать во что угодно, используя XSLT).

0
ответ дан 18 December 2019 в 12:01
поделиться

Для тех, кому интересно, вот код, который я в итоге использовал. Если вы присоедините это к событию OnAfterCellPaint объекта TVirtualStringTree, это даст желаемые результаты.

(*
  DrawHTML - Draws text on a canvas using tags based on a simple subset of HTML/CSS

  <B> - Bold e.g. <B>This is bold</B>
  <I> - Italic e.g. <I>This is italic</I>
  <U> - Underline e.g. <U>This is underlined</U>
  <font-color=x> Font colour e.g.
                <font-color=clRed>Delphi red</font-color>
                <font-color=#FFFFFF>Web white</font-color>
                <font-color=$000000>Hex black</font-color>
  <font-size=x> Font size e.g. <font-size=30>This is some big text</font-size>
  <font-family> Font family e.g. <font-family=Arial>This is arial</font-family>
*)
procedure TfrmSNMPMIBBrowser.DrawHTML(const ARect: TRect; const ACanvas: TCanvas; const Text: String);

  function CloseTag(const ATag: String): String;
  begin
    Result := concat('/', ATag);
  end;

  function GetTagValue(const ATag: String): String;
  var
    p: Integer;
  begin
    p := pos('=', ATag);

    if p = 0 then
      Result := ''
    else
      Result := copy(ATag, p + 1, MaxInt);
  end;

  function ColorCodeToColor(const Value: String): TColor;
  var
    HexValue: String;
  begin
    Result := 0;

    if Value <> '' then
    begin
      if (length(Value) >= 2) and (copy(Uppercase(Value), 1, 2) = 'CL') then
      begin
        // Delphi colour
        Result := StringToColor(Value);
      end else
      if Value[1] = '#' then
      begin
        // Web colour
        HexValue := copy(Value, 2, 6);

        Result := RGB(StrToInt('$'+Copy(HexValue, 1, 2)),
                      StrToInt('$'+Copy(HexValue, 3, 2)),
                      StrToInt('$'+Copy(HexValue, 5, 2)));
      end
      else
        // Hex or decimal colour
        Result := StrToIntDef(Value, 0);
    end;
  end;

const
  TagBold = 'B';
  TagItalic = 'I';
  TagUnderline = 'U';
  TagBreak = 'BR';
  TagFontSize = 'FONT-SIZE';
  TagFontFamily = 'FONT-FAMILY';
  TagFontColour = 'FONT-COLOR';

var
  x, y, idx, CharWidth, MaxCharHeight: Integer;
  CurrChar: Char;
  Tag, TagValue: String;
  PreviousFontColor: TColor;
  PreviousFontFamily: String;
  PreviousFontSize: Integer;

begin
  // Start - required if used with TVirtualStringTree
  ACanvas.Font.Size := Canvas.Font.Size;
  ACanvas.Font.Name := Canvas.Font.Name;
  ACanvas.Font.Color := Canvas.Font.Color;
  ACanvas.Font.Style := Canvas.Font.Style;
  // End

  PreviousFontColor := ACanvas.Font.Color;
  PreviousFontFamily := ACanvas.Font.Name;
  PreviousFontSize := ACanvas.Font.Size;

  x := ARect.Left;
  y := ARect.Top;
  idx := 1;

  MaxCharHeight := ACanvas.TextHeight('Ag');

  While idx <= length(Text) do
  begin
    CurrChar := Text[idx];

    // Is this a tag?
    if CurrChar = '<' then
    begin
      Tag := '';

      inc(idx);

      // Find the end of then tag
      while (Text[idx] <> '>') and (idx <= length(Text)) do
      begin
        Tag := concat(Tag,  UpperCase(Text[idx]));

        inc(idx);
      end;

      ///////////////////////////////////////////////////
      // Simple tags
      ///////////////////////////////////////////////////
      if Tag = TagBold then
        ACanvas.Font.Style := ACanvas.Font.Style + [fsBold] else

      if Tag = TagItalic then
        ACanvas.Font.Style := ACanvas.Font.Style + [fsItalic] else

      if Tag = TagUnderline then
        ACanvas.Font.Style := ACanvas.Font.Style + [fsUnderline] else

      if Tag = TagBreak then
      begin
        x := ARect.Left;

        inc(y, MaxCharHeight);
      end else

      ///////////////////////////////////////////////////
      // Closing tags
      ///////////////////////////////////////////////////
      if Tag = CloseTag(TagBold) then
        ACanvas.Font.Style := ACanvas.Font.Style - [fsBold] else

      if Tag = CloseTag(TagItalic) then
        ACanvas.Font.Style := ACanvas.Font.Style - [fsItalic] else

      if Tag = CloseTag(TagUnderline) then
        ACanvas.Font.Style := ACanvas.Font.Style - [fsUnderline] else

      if Tag = CloseTag(TagFontSize) then
        ACanvas.Font.Size := PreviousFontSize else

      if Tag = CloseTag(TagFontFamily) then
        ACanvas.Font.Name := PreviousFontFamily else

      if Tag = CloseTag(TagFontColour) then
        ACanvas.Font.Color := PreviousFontColor else

      ///////////////////////////////////////////////////
      // Tags with values
      ///////////////////////////////////////////////////
      begin
        // Get the tag value (everything after '=')
        TagValue := GetTagValue(Tag);

        if TagValue <> '' then
        begin
          // Remove the value from the tag
          Tag := copy(Tag, 1, pos('=', Tag) - 1);

          if Tag = TagFontSize then
          begin
            PreviousFontSize := ACanvas.Font.Size;
            ACanvas.Font.Size := StrToIntDef(TagValue, ACanvas.Font.Size);
          end else

          if Tag = TagFontFamily then
          begin
            PreviousFontFamily := ACanvas.Font.Name;
            ACanvas.Font.Name := TagValue;
          end;

          if Tag = TagFontColour then
          begin
            PreviousFontColor := ACanvas.Font.Color;
            ACanvas.Font.Color := ColorCodeToColor(TagValue);
          end;
        end;
      end;
    end
    else
    // Draw the character if it's not a ctrl char
    if CurrChar >= #32 then
    begin
      CharWidth := ACanvas.TextWidth(CurrChar);

      if x + CharWidth > ARect.Right then
      begin
        x := ARect.Left;

        inc(y, MaxCharHeight);
      end;

      if y + MaxCharHeight < ARect.Bottom then
      begin
        ACanvas.Brush.Style := bsClear;

        ACanvas.TextOut(x, y, CurrChar);
      end;

      x := x + CharWidth;
    end;

    inc(idx);
  end;
end;
0
ответ дан 18 December 2019 в 12:01
поделиться
Другие вопросы по тегам:

Похожие вопросы: