Модераторы: Poseidon, Snowy, bems, MetalFan
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> WYSIWYG BBCode, Поиск компонента или его реализация 
V
    Опции темы
PriZraK
  Дата 7.4.2010, 12:43 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 65
Регистрация: 22.10.2006

Репутация: нет
Всего: нет



Здравствуйте.
Ищу Delphi компонент реализующий простой редактор WYSIWYG (выделение жирным, подчеркивание, курсив и т.д.), на выходе которого получаем текст, оформленный BBCode кодом.
В данный момент реализовал на TMemo правку с вставкой необходимых BBCode символов прямо в содержание текста.
PM MAIL ICQ Skype GTalk   Вверх
Snowy
Дата 7.4.2010, 15:36 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Модератор
Сообщений: 11363
Регистрация: 13.10.2004
Где: Питер

Репутация: 192
Всего: 484



А TRichEdit чем-то не устраивает?
Вот линк на ролик, как написать WordPad,
Вот код, как из RichEdit перевести в html
Код, правда почему-то так и не внесли в DRKB, но он полностью рабочий.
По аналогии легко сделать BBCode. Благо это даже легче, чем html.
PM MAIL   Вверх
PriZraK
Дата 8.4.2010, 20:55 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 65
Регистрация: 22.10.2006

Репутация: нет
Всего: нет



Спасибо за совет об использовании для этих целей TRichEdit.
На данный момент реализовал простейшие функции (жирный, курсив, подчёркнутый, зачёркнутый).
Сейчас займусь вставкой изображений (будут подгружатся через HTTP) и вставкой ссылок, возможно ещё размер и цвет шрифта.
Код

function RichToBB(RichEdit: TRichEdit): String;
var
  i         : Integer;
  str       : String;
  output    : String;
  bold      : Boolean;
  italic    : Boolean;
  underline : Boolean;
  strike    : Boolean;
begin
  str       := '';
  output    := '';
  bold      := False;
  italic    := False;
  underline := False;
  strike    := False;
  RichEdit.SelStart := 0;
  RichEdit.DefAttributes.Assign(RichEdit.SelAttributes);
  for i := 0 to Length(RichEdit.Text) do begin
    RichEdit.SelStart := i;
    RichEdit.SelLength := 1;
    str := RichEdit.SelText;
    // проверка наличия стилей оформления
    if (fsBold in RichEdit.SelAttributes.Style) or
       (fsItalic in RichEdit.SelAttributes.Style) or
       (fsUnderline in RichEdit.SelAttributes.Style) or
       (fsStrikeOut in RichEdit.SelAttributes.Style) then
    begin
      // жирный текст
      if (fsBold in RichEdit.SelAttributes.Style) then begin
        if (bold = False) then begin
          output := output + '[ B]' + str;
          bold   := True;
        end else if (bold = True) and (Length(RichEdit.Text) = i) then begin
          output := output + str + '[ /B]';
          bold   := False;
        end else if (bold = True) then begin
          output := output + str;
        end;
      end;
      // курсив
      if (fsItalic in RichEdit.SelAttributes.Style) then begin
        if (italic = False) then begin
          output := output + '[I]' + str;
          italic := True;
        end else if (italic = True) and (Length(RichEdit.Text) = i) then begin
          output := output + str + '[/I]';
          italic := False;
        end else if (italic = True) then begin
          output := output + str;
        end;
      end;
      // подчёркнутый текст
      if (fsUnderline in RichEdit.SelAttributes.Style) then begin
        if (underline = False) then begin
          output := output + '[U]' + str;
          underline := True;
        end else if (underline = True) and (Length(RichEdit.Text) = i) then begin
          output := output + str + '[/U]';
          underline := False;
        end else if (underline = True) then begin
          output := output + str;
        end;
      end;
      // зачёркнутый текст
      if (fsStrikeOut in RichEdit.SelAttributes.Style) then begin
        if (strike = False) then begin
          output := output + '[S]' + str;
          strike := True;
        end else if (strike = True) and (Length(RichEdit.Text) = i) then begin
          output := output + str + '[/S]';
          strike := False;
        end else if (strike = True) then begin
          output := output + str;
        end;
      end;
    // стили оформления отсутствуют
    end else begin
      // закрываем тег [ B] (жирный текст)
      if (bold = True) then begin
        output    := output + '[ /B]' + str;
        bold      := False;
      // закрываем тег [I] (курсив)
      end else if (italic = True) then begin
        output    := output + '[/I]' + str;
        italic    := False;
      // закрываем тег [U] (подчёркнутый текст)
      end else if (underline = True) then begin
        output    := output + '[/U]' + str;
        underline := False;
      // закрываем тег [S] (зачёркнутый текст)
      end else if (strike = True) then begin
        output    := output + '[/S]' + str;
        strike    := False;
      end else begin
        output    := output + RichEdit.SelText;
      end;
    end;
  end;
  RichEdit.SelLength := 0;
  // возвращаяем результат
  Result := output;
end;

* пробелы в тегах [ B] [ /B] т.к. парсер vingrad их принимает за выделение

Это сообщение отредактировал(а) PriZraK - 8.4.2010, 21:00
PM MAIL ICQ Skype GTalk   Вверх
PriZraK
  Дата 11.4.2010, 14:23 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 65
Регистрация: 22.10.2006

Репутация: нет
Всего: нет



Пересмотрел код Snowy, решил делать по его принцу, получилось следующее:
Код

function RichToBB(RichEdit: TRxRichEdit): String;
  // очистка от возможных тегов
  function HtmlChar(ch: char): string;
  const
    sim: array[1..6] of string = ('&lt;', '&gt;','&quot;','&amp;', '<br>', '');
    sims = '<>"&'#13#10;
  begin
    if pos(ch, sims) > 0 then result := sim[pos(ch, sims)]
    else result := ch;
  end;

  // конвертер цветов
  function HtmlColor(Col: integer): string;
  begin
    Col := ColorToRGB(Col);
    Result := '#' + Format('%.2x%.2x%.2x', [GetRValue(Col), GetGValue(Col), GetBValue(Col)]);
  end;

  // обработка URL-адресов
  function DetectUrl(txt: string): string;
  var
    i,j: integer;
    s,l: string;
    h:   boolean;
  begin
    result := '';
    l := LowerCase(txt);
    h := false;
    i := 0;
    repeat
      inc(i);
      if txt[i] = #1 then h := not h;
      if h then result := result + txt[i]
      else
        if (copy(l, i, 7) = 'http://')
        or (copy(l, i, 8) = 'https://')
        or (copy(l, i, 6) = 'ftp://')
        or (copy(l, i, 4) = 'www.') then begin
          s := '';
          for j := i to Length(l) do
            if pos(l[j], #1#13#10' <>') = 0 then s := s + txt[j]
            else Break;
          inc(i, Length(s)-1);
          result := result + '[URL]';
          if pos('://', s) = 0 then result := result + 'http://';
          result := result + s + '[/URL]';
        end else result := result + txt[i];
    until i >= Length(l);
  end;

  // обработка MAIL-адресов
  function DetectMail(txt: string): string;
  var
    i,j: integer;
    s,l: string;
    h:   boolean;
  begin
    result := '';
    l := LowerCase(txt);
    h := false;
    i := 0;
    repeat
      inc(i);
      if txt[i] = #1 then h := not h;
      if h then result := result + txt[i]
      else
        if (copy(l, i, 7) = 'mailto:') then begin
          s := '';
          i := i + 7;
          for j := i to Length(l) do
            if pos(l[j], #1#13#10' <>') = 0 then s := s + txt[j]
            else Break;
          inc(i, Length(s)-1);
          result := result + '[MAIL]';
          result := result + s + '[/MAIL]';
        end else result := result + txt[i];
    until i >= Length(l);
  end;

var
  s, f      : String;
  i, sz, cl : Integer;
  st        : TFontStyles;
  n         : TRxNumbering;
  output    : String;
  fontcolor : Boolean;
  bold      : Boolean;
  italic    : Boolean;
  underline : Boolean;
  strike    : Boolean;
begin
  s         := RichEdit.Text;
  f         := '';
  sz        := 0;
  cl        := -1;
  st        := [];
  n         := nsNone;
  output    := '';
  fontcolor := False;
  bold      := False;
  italic    := False;
  underline := False;
  strike    := False;
  for i := 1 to Length(s) do
  begin
    RichEdit.SelStart := i;
    if (RichEdit.CaretPos.X = 0) and (RichEdit.Lines[RichEdit.CaretPos.Y] = '') then
      if (s[i] = #13) then output := output + '[BR]';
    if (RichEdit.CaretPos.X = 1) then begin
      if (n = nsNone) and (i <> 1) then output := output + '[BR]';
      if (n = nsBullet) then output := output + '[/LI]';
      if (RichEdit.Paragraph.Numbering = nsBullet) and (n = nsNone) then begin output := output + '[UL]'; n := nsBullet; end;
      if (RichEdit.Paragraph.Numbering <> nsBullet) and (n = nsBullet) then begin output := output + '[/UL]'; n := nsNone; end;
      if (n = nsBullet) then output := output + '[LI]';
    end;
    with RichEdit.SelAttributes do
      if (f <> Name) or (sz <> Size) or (cl <> Color) or (st <> Style) then begin
        if (s[i] > #31) then begin
          f := Name; sz := Size; cl := Color; st := Style;
          // ----
          if (fontcolor = True) then begin output := output + '[/COLOR]'; fontcolor := False; end;
          if (bold = True) then begin      output := output + '[ /B ]';   bold      := False; end;
          if (italic = True) then begin    output := output + '[/I]';     italic    := False; end;
          if (underline = True) then begin output := output + '[/U]';     underline := False; end;
          if (strike = True) then begin    output := output + '[/S]';     strike    := False; end;
          // ----
          if cl <> 0 then begin            output := output + '[COLOR=' + HtmlColor(cl)+']'; fontcolor := True; end;
          if fsBold in st then begin       output := output + '[ B ]';                       bold      := True; end;
          if fsItalic in st then begin     output := output + '[I]';                         italic    := True; end;
          if fsUnderline in st then begin  output := output + '[U]';                         underline := True; end;
          if fsStrikeOut in st then begin  output := output + '[S]';                         strike    := True; end;
        end;
      end;
    if s[i] > #31 then output := output + HtmlChar(s[i]);
  end;
  if (fontcolor = True) then begin output := output + '[/COLOR]'; fontcolor := False; end;
  if (bold = True) then begin      output := output + '[ /B ]';   bold      := False; end;
  if (italic = True) then begin    output := output + '[/I]';     italic    := False; end;
  if (underline = True) then begin output := output + '[/U]';     underline := False; end;
  if (strike = True) then begin    output := output + '[/S]';     strike    := False; end;
  if n = nsBullet then             output := output + '[/UL]';
  // обработка URL-адресов
  output := DetectUrl(output);
  // обработка MAIL-адресов
  output := DetectMail(output);
  // возвращаяем результат
  Result := output;
end;

Есть небольшая проблема со списком, но в целом работает отлично.
Сейчас встал вопрос о конвертировании данных в RichEdit из текста оформленного с помощью BB-кодов.
Не могу понять как сделать список – на бумаге выходит просто, а в программе не получается.
Вот что есть сейчас:
Код

procedure BBToRich(RichEdit:TRxRichEdit; Str: String);
var
  i         : Integer;
  output    : String;
  bold      : Boolean;
  italic    : Boolean;
  underline : Boolean;
  strike    : Boolean;
begin
  i         := 0;
  output    := '';
  bold      := False;
  italic    := False;
  underline := False;
  strike    := False;
  // --
  while i < Length(Str) do begin
    // перенос строки
    if (copy(Str, i+1, 4) = '[BR]') then begin
      i := i + 4;
      RichEdit.Text := RichEdit.Text + sLineBreak;
    // жирный текст
    end else if (copy(Str, i+1, 3) = '[ B ]') then begin
      i := i + 3;
      bold := True;
    end else if (copy(Str, i+1, 4) = '[ /B ]') then begin
      i := i + 4;
      bold := False;
    // курсив
    end else if (copy(Str, i+1, 3) = '[I]') then begin
      i := i + 3;
      italic := True;
    end else if (copy(Str, i+1, 4) = '[/I]') then begin
      i := i + 4;
      italic := False;
    // подчёркнутый текст
    end else if (copy(Str, i+1, 3) = '[U]') then begin
      i := i + 3;
      underline := True;
    end else if (copy(Str, i+1, 4) = '[/U]') then begin
      i := i + 4;
      underline := False;
    // зачёркнутый текст
    end else if (copy(Str, i+1, 3) = '[S]') then begin
      i := i + 3;
      strike := True;
    end else if (copy(Str, i+1, 4) = '[/S]') then begin
      i := i + 4;
      strike := False;
    end;
    // обработка текста
    i := i + 1;
    RichEdit.SelStart := Length(RichEdit.Text);
    RichEdit.SelLength := 0;
    // жирный текст
    if (bold = True) then begin
      RichEdit.SelAttributes.Style := RichEdit.SelAttributes.Style + [fsBold];
    end else begin
      RichEdit.SelAttributes.Style := RichEdit.SelAttributes.Style - [fsBold];
    end;
    // курсив
    if (italic = True) then begin
      RichEdit.SelAttributes.Style := RichEdit.SelAttributes.Style + [fsItalic];
    end else begin
      RichEdit.SelAttributes.Style := RichEdit.SelAttributes.Style - [fsItalic];
    end;
    // подчёркнутый текст
    if (underline = True) then begin
      RichEdit.SelAttributes.Style := RichEdit.SelAttributes.Style + [fsUnderline];
    end else begin
      RichEdit.SelAttributes.Style := RichEdit.SelAttributes.Style - [fsUnderline];
    end;
    // зачёркнутый текст
    if (strike = True) then begin
      RichEdit.SelAttributes.Style := RichEdit.SelAttributes.Style + [fsStrikeOut];
    end else begin
      RichEdit.SelAttributes.Style := RichEdit.SelAttributes.Style - [fsStrikeOut];
    end;
    RichEdit.SelText := Str[i];
  end;
end;

* пробелы в тегах [ B] [ /B] т.к. парсер vingrad их принимает за выделение
PM MAIL ICQ Skype GTalk   Вверх
PriZraK
  Дата 12.4.2010, 15:13 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 65
Регистрация: 22.10.2006

Репутация: нет
Всего: нет



Переписал обе функции, теперь обе работают корректно.
Код

// КОНВЕРТИРУЕМ RICHEDIT В BBCODE
function RichToBB(RichEdit: TRxRichEdit): String;
var
  i         : Integer;
  Str       : String;
  bold      : Boolean;
  italic    : Boolean;
  underline : Boolean;
  strike    : Boolean;
  bulletul  : Boolean;
  bulletli  : Boolean;
  // --
  procedure ParceRich();
  begin
    // --
    if (RichEdit.SelText = #13) and (bulletul = False) then begin
      Str := Str + '[BR]';
    end;
    // --
    if (fsBold in RichEdit.SelAttributes.Style) and (bold = False) then begin
      Str  := Str + '[ B ]';
      bold := True;
    end else if ([fsBold] <> RichEdit.SelAttributes.Style) and (bold = True) then begin
      Str  := Str + '[ /B ]';
      bold := False;
    end;
    // --
    if (fsItalic in RichEdit.SelAttributes.Style) and (italic = False) then begin
      Str    := Str + '[I]';
      italic := True;
    end else if ([fsItalic] <> RichEdit.SelAttributes.Style) and (italic = True) then begin
      Str    := Str + '[/I]';
      italic := False;
    end;
    // --
    if (fsUnderline in RichEdit.SelAttributes.Style) and (underline = False) then begin
      Str       := Str + '[U]';
      underline := True;
    end else if ([fsUnderline] <> RichEdit.SelAttributes.Style) and (underline = True) then begin
      Str       := Str + '[/U]';
      underline := False;
    end;
    // --
    if (fsStrikeOut in RichEdit.SelAttributes.Style) and (strike = False) then begin
      Str    := Str + '[S]';
      strike := True;
    end else if ([fsStrikeOut] <> RichEdit.SelAttributes.Style) and (strike = True) then begin
      Str    := Str + '[/S]';
      strike := False;
    end;
    // --
    if (RichEdit.Paragraph.Numbering = nsBullet) and (bulletul = False) then begin
      Str := Str + '[UL]';
      bulletul := True;
      ParceRich();
    end;
    // --
    if (RichEdit.Paragraph.Numbering = nsBullet) and (bulletul = True) and (bulletli = False) and (RichEdit.CaretPos.X = 1) then begin
      Str := Str + '[LI]';
      bulletli := True;
    end;
    // --
    if (RichEdit.Paragraph.Numbering = nsBullet) and (bulletul = True) and (bulletli = True) and (RichEdit.SelText = #13) then begin
      Str := Str + '[/LI]';
      bulletli := False;
    end;
    // --
    if (RichEdit.Paragraph.Numbering = nsNone) and (bulletul = True) then begin
      Str := Str + '[/UL]';
      bulletul := False;
      ParceRich();
    end;
  end;
  // --
begin
  Str       := '';
  bold      := False;
  italic    := False;
  underline := False;
  strike    := False;
  bulletul  := False;
  bulletli  := False;
  // --
  for i := 0 to Length(RichEdit.Text) do begin
    // --
    RichEdit.SelStart  := i;
    RichEdit.SelLength := 1;
    // --
    ParceRich();
    // --
    if (RichEdit.SelText <> #13) then begin
      Str := Str + RichEdit.SelText;
    end
  end;
  // возвращаяем результат
  Result := Str;
end;


// КОНВЕРТИРУЕМ BBCODE В RICHEDIT
procedure BBToRich(RichEdit:TRxRichEdit; Str: String);
var
  i         : Integer;
  output    : String;
  bold      : Boolean;
  italic    : Boolean;
  underline : Boolean;
  strike    : Boolean;
  bullet    : Boolean;
  // --
  procedure ParseBB();
  begin
    // перенос строки
    if (copy(Str, i+1, 4) = '[BR]') then begin
      i := i + 4;
      RichEdit.Lines.Add('');
      ParseBB();
    end;
    // жирный текст
    if (copy(Str, i+1, 3) = '[ B ]') then begin
      i := i + 3;
      bold := True;
      ParseBB();
    end;
    if (copy(Str, i+1, 4) = '[ /B ]') then begin
      i := i + 4;
      bold := False;
      ParseBB();
    end;
    // курсив
    if (copy(Str, i+1, 3) = '[I]') then begin
      i := i + 3;
      italic := True;
      ParseBB();
    end;
    if (copy(Str, i+1, 4) = '[/I]') then begin
      i := i + 4;
      italic := False;
      ParseBB();
    end;
    // подчёркнутый текст
    if (copy(Str, i+1, 3) = '[U]') then begin
      i := i + 3;
      underline := True;
      ParseBB();
    end;
    if (copy(Str, i+1, 4) = '[/U]') then begin
      i := i + 4;
      underline := False;
      ParseBB();
    end;
    // зачёркнутый текст
    if (copy(Str, i+1, 3) = '[S]') then begin
      i := i + 3;
      strike := True;
      ParseBB();
    end;
    if (copy(Str, i+1, 4) = '[/S]') then begin
      i := i + 4;
      strike := False;
      ParseBB();
    end;
    // список
    if (copy(Str, i+1, 4) = '[UL]') then begin
      i := i + 4;
      bullet := True;
      ParseBB();
    end;
    if (copy(Str, i+1, 4) = '[LI]') then begin
      i := i + 4;
      ParseBB();
    end;
    if (copy(Str, i+1, 5) = '[/LI]') then begin
      i := i + 5;
      RichEdit.Lines.Add('');
      ParseBB();
    end;
    if (copy(Str, i+1, 5) = '[/UL]') then begin
      i := i + 5;
      bullet := False;
      ParseBB();
    end;
  end;
  // --
begin
  i         := 0;
  output    := '';
  bold      := False;
  italic    := False;
  underline := False;
  strike    := False;
  bullet    := False;
  // --
  while i < Length(Str) do begin
    // запускаем парсер
    ParseBB();
    // обработка текста
    inc(i);
    RichEdit.SelStart := Length(RichEdit.Text);
    RichEdit.SelLength := 0;
    // жирный текст
    if (bold = True) then begin
      RichEdit.SelAttributes.Style := RichEdit.SelAttributes.Style + [fsBold];
    end else begin
      RichEdit.SelAttributes.Style := RichEdit.SelAttributes.Style - [fsBold];
    end;
    // курсив
    if (italic = True) then begin
      RichEdit.SelAttributes.Style := RichEdit.SelAttributes.Style + [fsItalic];
    end else begin
      RichEdit.SelAttributes.Style := RichEdit.SelAttributes.Style - [fsItalic];
    end;
    // подчёркнутый текст
    if (underline = True) then begin
      RichEdit.SelAttributes.Style := RichEdit.SelAttributes.Style + [fsUnderline];
    end else begin
      RichEdit.SelAttributes.Style := RichEdit.SelAttributes.Style - [fsUnderline];
    end;
    // зачёркнутый текст
    if (strike = True) then begin
      RichEdit.SelAttributes.Style := RichEdit.SelAttributes.Style + [fsStrikeOut];
    end else begin
      RichEdit.SelAttributes.Style := RichEdit.SelAttributes.Style - [fsStrikeOut];
    end;
    // список
    if (bullet = True) then begin
      RichEdit.Paragraph.Numbering := nsBullet;
    end else begin
      RichEdit.Paragraph.Numbering := nsNone;
    end;
    RichEdit.SelText := Str[i];
  end;
end;

* пробелы в тегах [ B] [ /B] т.к. парсер vingrad их принимает за выделение

Это сообщение отредактировал(а) PriZraK - 13.4.2010, 01:12
PM MAIL ICQ Skype GTalk   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Delphi: Общие вопросы"
SnowyMetalFan
bemsPoseidon
Rrader

Запрещается!

1. Публиковать ссылки на вскрытые компоненты

2. Обсуждать взлом компонентов и делиться вскрытыми компонентами

  • Литературу по Дельфи обсуждаем здесь
  • Действия модераторов можно обсудить здесь
  • С просьбами о написании курсовой, реферата и т.п. обращаться сюда
  • Вопросы по реализации алгоритмов рассматриваются здесь
  • 90% ответов на свои вопросы можно найти в DRKB (Delphi Russian Knowledge Base) - крупнейшем в рунете сборнике материалов по Дельфи


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Snowy, MetalFan, bems, Poseidon, Rrader.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Delphi: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.0759 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.