7

我将 TSynEdit 用作对用户更友好的 TMemo,主要用于高级快捷方式、UNDO/REDO 等。

其他都OK,除了自动换行,请看下面的截图,SynEdit 最左边有个奇怪的空格。

如何避免这种情况并让它看起来像 TMemo?

在此处输入图像描述

TSynEdit 的关键属性设置:

    synEdit1.UseCodeFolding := False;
    synEdit1.Options := [eoAutoIndent, eoDragDropEditing, eoEnhanceEndKey, 
eoGroupUndo, eoScrollPastEol, eoSmartTabDelete, 
eoSmartTabs, eoTabsToSpaces];
      synEdit1.ScrollBars := ssVertical;
      synEdit1.TabWidth := 4;
      synEdit1.WantTabs := True;
      synEdit1.WordWrap := True;
      synEdit1.FontSmoothing := fsmNone;
4

1 回答 1

4

这不是对 q 的完整、经过测试的答案,但可以为坚定的读者提供一个指向功能解决方案的起点。

TSynEdit 的自动换行行为由其当前的 TSynWordWrapPlugin. 默认插件在 SynEditWordWrap.Pas 中定义并包含过程TSynWordWrapPlugin.WrapLines方法,从我昨天使用 D10.2.3 GetIt 管理器下载的版本的第 512 行开始。

从第 560 行开始,有一段代码,据我所知,它占了每个包装行开头的空间,如 q 所示:

      if Editor.IsWordBreakChar(vRunner^) then
      begin
        vRowEnd := vRunner;
        break;
      end;
      Dec(vRunner);

vRunner并且vRowEnd是该WrapLines方法中使用的许多 PWideChar 变量之一。

观察这段代码的行为,它在一个while循环内(它正在寻找一个进行自动换行的地方),它运行使得当Editor.IsWordBreakChar(vRunner^)返回 true 时,vRunner 指针已经向后移动超过了 word-break char,它这就是为什么它(空格)在下一行结束,导致 OP 指出的问题。

将代码更改为

      if Editor.IsWordBreakChar(vRunner^) then
      begin
        {ma} Inc(vRunner);  //  WARNING: not fully tested
        vRowEnd := vRunner;
        break;
      end;
      Dec(vRunner);

强制 vRunner 指针向前超过断字字符,以便空格包含在行尾而不是下一行的开头,因此 SynEdit 然后像标准 TMemo 一样显示其包装文本。

就个人而言,我不会使用此更改,而是会看看我是否可以说服 SynEdit 开发人员提供官方解决方案。如果我确实使用了上面显示的更改,我当然不会通过更改 SynEditWordWrap.Pas 的源来做到这一点,我会通过编写替换来做到这一点,TSynWordWrapPlugin并且我会检查inc(vRunner)不超过缓冲区用于进行自动换行。

于 2019-02-03T15:30:15.547 回答