Подтвердить что ты не робот

Использование RichEdit 2.0 одного символа CR в качестве линейной линии отбрасывает вычисления SelStart (Delphi XE2)

При переходе с Delphi 2006 на Delphi XE2 одна из вещей, которые мы узнали, заключается в том, что RichEdit 2.0 заменяет внутренние пары CRLF одним символом CR. Это приводит к неудачному эффекту отбрасывания всех вычислений индекса символов на основе фактической текстовой строки на стороне VCL.

Поведение, которое я вижу, отслеживая код VCL, выглядит следующим образом:

  • Отправка сообщения WM_GETTEXT (сделано в TControl.GetTextBuf) возвращает текстовый буфер, содержащий пары CRLF.
  • Отправка сообщения WM_GETTEXTLENGTH (сделано в TControl.GetTextLen) вернет значение, как если бы текст по-прежнему содержал символы CRLF.
  • В отличие от этого отправка сообщения EM_SETSELEX (т.е. установка SelStart) будет обрабатывать входное значение, как если бы текст содержал только символы CR.

Это приводит к сбою всех видов (например, подсветка синтаксиса) в нашем приложении. Как вы можете сказать, все отключено ровно одним символом для каждой новой строки до этой точки.

Очевидно, что, поскольку это противоречивое поведение, мы должны что-то пропускать или делать что-то очень неправильное.

Есть ли у кого-нибудь еще опыт перехода от RichEdit 1.0 к элементу управления RichEdit 2.0 и как вы решили эту проблему? Наконец, есть ли способ заставить RichEdit 2.0 использовать пары CRLF так же, как RichEdit 1.0?

4b9b3361

Ответ 1

Мы также столкнулись с этой проблемой.

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

Этот индекс не соответствует между pos (mystring, RichEdit.Text) и индексом позиционирования в текст RichEdit с использованием RichText.SelStart нарушил наше слияние.

У меня нет хорошего ответа, но я придумал обходной путь. Это немного громоздко (занижение!), Но пока не появится лучшее решение...

Обходной путь - использовать скрытый TMemo и скопировать текст RichEdit в него и изменить пары CR/LF только на CR. Затем используйте TMemo, чтобы найти правильное позиционирование с помощью pos (string, TMemo) и использовать его для получения позиции selstart для использования в TRichEdit.

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

Я покажу небольшой пример кода...

Поскольку мы заменяем текст, используя seltext, нам нужно заменить текст в BOTH элементом управления RichEdit и элементом управления TMemo, чтобы сохранить два синхронизированных.

StartToken и EndToken являются разделителями кода слияния и являются константой.

function TEditForm.ParseTest: boolean;
var TagLength: integer;
var ValueLength: integer;
var ParseStart: integer;
var ParseEnd: integer;
var ParseValue: string;
var Memo: TMemo;
begin
  Result := True;//Default
  Memo := TMemo.Create(nil);
  try
    Memo.Parent := self;
    Memo.Visible := False;
    try
      Memo.Lines.Clear;
      Memo.Lines.AddStrings(RichEditor.Lines);
      Memo.Text := stringreplace(Memo.Text,#13#10,#13,[rfReplaceAll]);//strip CR/LF pairs and replace with CR

      while (Pos(StartToken, Memo.Text) > 0) and (Pos(EndToken, Memo.Text) > 0) do begin
        ParseStart := Pos(StartToken, Memo.SelText);
        ParseEnd := Pos(EndToken, Memo.SelText) + Length(EndToken);
        if ParseStart >= ParseEnd then begin//oops, something wrong - bail out
          Result := true;
          myEditor.SelStart := 0;
          exit;
        end;
        TagLength := ParseEnd - ParseStart;
        ValueLength := (TagLength - Length(StartToken)) - Length(EndToken);
        ParseValue := Copy(Memo.SelText, (ParseStart + Length(StartToken)), ValueLength);
        Memo.selstart := ParseStart - 1; //since the .text is zero based, but pos is 1 based we subtract 1
        Memo.sellength := TagLength;
        RichEditor.selstart := ParseStart - 1; //since the .text is zero based, but pos is 1 based we subtract 1
        RichEditor.sellength := TagLength;

        TempText := GetValue(ParseValue);
        Memo.SelText := TempText;
        RichEditor.SelText := TempText;
      end;

    except
       on e: exception do
          begin
          MessageDlg(e.message,mtInformation,[mbOK],0);
          result := false;
          end;
       end;//try..except
  finally
    FreeAndNil(Memo);
  end;
end;

Ответ 2

Как насчет вычитания EM_LINEFROMCHAR из позиции каретки? (ИЛИ позиция EM_GETSEL) в зависимости от того, что вам нужно.

Вы даже можете получить две переменные EM_LINEFROMCHAR. Один из начального выбора, а другой - из желаемой позиции каретки/выбора, если вы хотите узнать, сколько пар cl/cr находится в выборе.