【问题标题】:SynEdit OnPaintTransientDemoSynEdit OnPaintTransientDemo
【发布时间】:2013-08-31 12:08:48
【问题描述】:

我正在使用 Delphi 2007SynEdit 组件。

我是开源编辑器 (Tinn-R) 的主要开发人员,我正在尝试从 SynEdit ANSI 切换到 UNICODE

经过几个月的工作,除了 OnPaintTransient 程序外,一切正常。

为了找出问题的根源,我尝试了原始演示 OnPaintTransientDemo。 这在 SynEdit 的最新 ANSI 版本中完美运行。但是,我没有得到与最新 UNICODE 版本相同的结果。

如果指令只占一行,则只有光标附近的一个符号“[] {} or ()”被错误高亮,没有关闭。

换句话说,当您单击第一个括号“(”最后一个括号“)”时不会改变颜色。 它应该为开始和结束标签着色。例如,考虑“|”作为光标位置:

(|aaaa) -> only ( is highlighted
(aaaa|) -> only ) is highlighted

但是,如果符号位于不同的行中,则会正确突出显示:

(|a
a
a
a) -> both () are highlighted

(a
a
a
a|) -> both () are highlighted

这看起来像是组件源代码中的错误!
(做debug没找到bug的来源。)

有人可以帮忙吗?

【问题讨论】:

  • 你能否澄清这句话“如果在同一行,只有光标附近的符号“[] {}或()”被错误地突出显示,而不是关闭。”请?这没有意义。
  • 我觉得现在看起来好多了:抱歉,英语不是我的母语。

标签: delphi editor delphi-2007 synedit


【解决方案1】:

下面的代码 (IceMan is the original author) 适合我:

procedure TForm1.EditorPaintTransient(Sender: TObject; Canvas: TCanvas; TransientType: TTransientType);
var
  Editor: TSynEdit;
  OpenChars: array of WideChar;//[0..2] of WideChar=();
  CloseChars: array of WideChar;//[0..2] of WideChar=();
  Attri: TSynHighlighterAttributes;

function IsCharBracket(AChar: WideChar): Boolean;
begin
  case AChar of
    '{',
    '[',
    '(',
    '<',
    '}',
    ']',
    ')',
    '>':
    Result:= True;
  else
    Result:= False;
  end;
end;

function CharToPixels(P: TBufferCoord): TPoint;
begin
  Result:=Editor.RowColumnToPixels(Editor.BufferToDisplayPos(P));
end;

procedure SetCanvasStyle;
begin
  Editor.Canvas.Brush.Style:= bsSolid; //Clear;
  Editor.Canvas.Font.Assign(Editor.Font);
  Editor.Canvas.Font.Style:= Attri.Style;
  if (TransientType = ttAfter) then begin
    Editor.Canvas.Font.Color:= FBracketFG;
    Editor.Canvas.Brush.Color:= FBracketBG;
  end
  else begin
    Editor.Canvas.Font.Color:= Attri.Foreground;
    Editor.Canvas.Brush.Color:= Attri.Background;
  end;

  if (Editor.Canvas.Font.Color = clNone) then
    Editor.Canvas.Font.Color:= Editor.Font.Color;
  if (Editor.Canvas.Brush.Color = clNone) then
    Editor.Canvas.Brush.Color:= Editor.Color;
end;

var
P  : TBufferCoord;
Pix: TPoint;
D  : TDisplayCoord;
S  : WideString;
I,
 ArrayLength,
 start: Integer;
TmpCharA,
 TmpCharB: WideChar;

begin
  try
    // if Memo1.InReplaceStatus = False then
    // begin
    (*
    if fMain.SyntaxHEnabled = False then exit;
    if Memo1.Highlighter = nil then exit;
    if fMain.BracketMatching = False then exit;
    if TSynEdit(Sender).SelAvail then exit;
    *)
    Editor:= TSynEdit(Sender);
    ArrayLength:= 3;
    (*
    if (Editor.Highlighter = SynHTMLSyn1) or (Editor.Highlighter = SynXMLSyn1) then
    inc(ArrayLength);
    *)
    SetLength(OpenChars,
              ArrayLength);
    SetLength(CloseChars,
              ArrayLength);

    for i:= 0 to ArrayLength - 1 do
      Case i of
        0: begin
             OpenChars[i]:= '(';
             CloseChars[i]:= ')';
           end;
        1: begin
             OpenChars[i]:= '{';
             CloseChars[i]:= '}';
           end;
        2: begin
             OpenChars[i]:= '[';
             CloseChars[i]:= ']';
           end;
        3: begin
             OpenChars[i]:= '<';
             CloseChars[i]:= '>';
           end;
      end;

    P:= Editor.CaretXY;
    D:= Editor.DisplayXY;
    Start:= Editor.SelStart;

    if (Start > 0) and
       (Start <= length(Editor.Text)) then
      TmpCharA:= Editor.Text[Start]
    else
      TmpCharA:= #0;

    if (Start < length(Editor.Text)) then
      TmpCharB:= Editor.Text[Start + 1]
    else
      TmpCharB:= #0;

    if not IsCharBracket(TmpCharA) and
       not IsCharBracket(TmpCharB) then
      Exit;

    S:= TmpCharB;
    if not IsCharBracket(TmpCharB) then begin
      P.Char:= P.Char - 1;
      S:= TmpCharA;
    end;

    Editor.GetHighlighterAttriAtRowCol(P,
                                       S,
                                       Attri);

    if (Editor.Highlighter.SymbolAttribute = Attri) then begin
      for i:= low(OpenChars) to High(OpenChars) do begin
        if (S = OpenChars[i]) or
           (S = CloseChars[i]) then begin
          Pix:= CharToPixels(P);
          SetCanvasStyle;
          Editor.Canvas.TextOut(Pix.X,
                                Pix.Y,
                                S);
          P := Editor.GetMatchingBracketEx(P);

          if (P.Char > 0) and
             (P.Line > 0) then begin
            Pix:= CharToPixels(P);
            if Pix.X > Editor.Gutter.Width then begin
              SetCanvasStyle;
              if S = OpenChars[i] then
                Editor.Canvas.TextOut(Pix.X,
                                      Pix.Y,
                                      CloseChars[i])
              else
                Editor.Canvas.TextOut(Pix.X,
                                      Pix.Y,
                                      OpenChars[i]);
            end; //if Pix.X >
          end; //if (P.Char > 0)
        end; //if (S = OpenChars[i])
      end; //for i:= low(OpenChars)
      Editor.Canvas.Brush.Style := bsSolid;
    end; //if (Editor.Highlighter.SymbolAttribute = Attri)
  except
  // TODO
  end; //try
end;

【讨论】:

    【解决方案2】:

    CharToPixels 与字体颜色混淆,我发现。在绘图之前将 font.color 设置回 FBrackBG 似乎可行。

    【讨论】:

      猜你喜欢
      • 2012-02-24
      • 1970-01-01
      • 2014-07-03
      • 2015-04-19
      • 1970-01-01
      • 1970-01-01
      • 2011-10-07
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多