Fragen zu SynEdit

Rund um die LCL und andere Komponenten
Mathias
Beiträge: 6164
Registriert: Do 2. Jan 2014, 17:21
OS, Lazarus, FPC: Linux (die neusten Trunk)
CPU-Target: 64Bit
Wohnort: Schweiz

Fragen zu SynEdit

Beitrag von Mathias »

Wie kann ich es machen, das anstelle des Rechtecks, einen Zeilenumbruch kommt. Siehe Anhang.

Code: Alles auswählen

const
  cs = 'Zeile 1' + LineEnding + 'Zeile 2';
 
procedure TForm1.Button1Click(Sender: TObject);
var
  lc:Integer;
begin
  SynEdit1.Lines.Add(cs);
end;   


Auch wen ich es so mache:

Code: Alles auswählen

procedure TForm1.Button1Click(Sender: TObject);
var
  lc: integer;
begin
  lc := SynEdit1.Lines.Count - 1;
  SynEdit1.Lines[lc] := SynEdit1.Lines[lc] + cs;
end;
Werden das LineEnding ingnoriert.

Auch wen ich es so mache:

Code: Alles auswählen

  cs = 'Zeile 1' + #13#10 + 'Zeile 2';
Kommen nur Rechtecke.

Jemand einen Rat ?
Dateianhänge
Bildschirmfoto vom 2020-04-26 13-39-47.png
Bildschirmfoto vom 2020-04-26 13-39-47.png (6.07 KiB) 3748 mal betrachtet
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot

martin_frb
Beiträge: 572
Registriert: Mi 25. Mär 2009, 21:12
OS, Lazarus, FPC: Laz trunk / fpc latest release / Win and other
CPU-Target: mostly 32 bit

Re: Fragen zu SynEdit

Beitrag von martin_frb »

Mit SynEdit.Lines
- muss jede Zeile einzeln ge-add-et werden.
- wird der undo/redo buffer zurück-gesetzt.
SynEdit.Lines ist zum einmaligem initialisieren am Anfang.

SynEdit.TextBetweenPoints[ Point(1, StartY), Point(1, EndY) ] := 'foo' + lineending + 'bar';
(Funktioniert mit undo/redo)

Oder mit mehr Optionen SetTextBetweenPointsEx
Siehe Sektion "text" https://wiki.lazarus.freepascal.org/Edi ... :_TSynEdit

wp_xyz
Beiträge: 4869
Registriert: Fr 8. Apr 2011, 09:01

Re: Fragen zu SynEdit

Beitrag von wp_xyz »

Mathias hat geschrieben:Wie kann ich es machen, das anstelle des Rechtecks, einen Zeilenumbruch kommt. Siehe Anhang.

Code: Alles auswählen

const
  cs = 'Zeile 1' + LineEnding + 'Zeile 2';


Kannst du nicht eine temp StringList benutzen, der du per .Text den String cs zuweist. Im nächsten Schritt durchläufst du die Stringliste Zeile für Zeile und hängst jede an die Lines des SynEdit:

Code: Alles auswählen

procedure TForm1.Button1Click(Sender: TObject);
var
  L: TStrings;
  i: Integer;
  lc: Integer;
begin
  L := TStringList.Create;
  try
    L.Text := cs;
    if L.Count = 0 then
      exit;
    // Sonderbehandlung bis zum ersten Linebreak in cs: direkt an die letzte Zeile im SynEdit anhängen
    lc := SynEdit1.Lines.Count - 1;
    SynEdit1.Lines[lc] := SynEdit1.Lines[lc] + L[0];
    // alle folgenden Zeilen als neue Zeilen ins SynEdit anhängen
    for i:= 1 to L.Count-1 do
      SynEdit1.Lines.Add(L[i]);
  finally
    L.Free;
  end;
end;

Mathias
Beiträge: 6164
Registriert: Do 2. Jan 2014, 17:21
OS, Lazarus, FPC: Linux (die neusten Trunk)
CPU-Target: 64Bit
Wohnort: Schweiz

Re: Fragen zu SynEdit

Beitrag von Mathias »

Danke, dies hat mir weit geholfen.

Ich habe die Temporäre StringList in den Classen Kopf verschoben.
Es reicht, wen man diesen einmal im Constructer erzeugt. Im Destructer wird der Speicher wieder frei gegeben.

Sogar der AutoScroll scheint zu funktionieren. Wenigstens mit Linux, mit Windows nicht getestet.
Die Nummer die man im Text sieht, sind nur zur Kontrolle.
Siehe Anhang.
Dateianhänge
Memo_Test.zip
(127.73 KiB) 144-mal heruntergeladen
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot

sstvmaster
Beiträge: 575
Registriert: Sa 22. Okt 2016, 23:12
OS, Lazarus, FPC: W10, L 2.2.6
CPU-Target: 32+64bit
Wohnort: Dresden

Re: Fragen zu SynEdit

Beitrag von sstvmaster »

Mathias hat geschrieben:... mit Windows nicht getestet.


Funktioniert auch unter Windows. Hier W10 + LAZ 208 / FPC 304 als i386 und x86_64
LG Maik

Windows 10,
- Lazarus 2.2.6 (stable) + fpc 3.2.2 (stable)
- Lazarus 2.2.7 (fixes) + fpc 3.3.1 (main/trunk)

Mathias
Beiträge: 6164
Registriert: Do 2. Jan 2014, 17:21
OS, Lazarus, FPC: Linux (die neusten Trunk)
CPU-Target: 64Bit
Wohnort: Schweiz

Re: Fragen zu SynEdit

Beitrag von Mathias »

Dann kan ich es ja getrost in meinen Serial Monitor einbauen. :wink:

Ist es möglich in SynEdit jedem Zeichen eine andere Farbe zu zuordnen ?
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot

martin_frb
Beiträge: 572
Registriert: Mi 25. Mär 2009, 21:12
OS, Lazarus, FPC: Laz trunk / fpc latest release / Win and other
CPU-Target: mostly 32 bit

Re: Fragen zu SynEdit

Beitrag von martin_frb »

Mathias hat geschrieben:Ist es möglich in SynEdit jedem Zeichen eine andere Farbe zu zuordnen ?


Leider nicht.

Verschiedene Möglichkeiten:

Eigener Highlighter => Beispiel auf der Wiki
Oder SynAnySyn Highlighter => Vorsicht: Langsam.

Markup: TSynEditMarkupHighlightAll / TSynEditMarkupHighlightAllMulti
Man kann einzelnen Wörern/WortGruppen/WortTeilen/... (solange alles in einer Zeile) Farben zuweisen.

Mathias
Beiträge: 6164
Registriert: Do 2. Jan 2014, 17:21
OS, Lazarus, FPC: Linux (die neusten Trunk)
CPU-Target: 64Bit
Wohnort: Schweiz

Re: Fragen zu SynEdit

Beitrag von Mathias »

Leider nicht.

Ich dachte, man hätte vielleicht in ferner Zukunft mal einen Serial-Monitor bauen könne, welcher Escape-Sequenzen abarbeitet.
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot

Mathias
Beiträge: 6164
Registriert: Do 2. Jan 2014, 17:21
OS, Lazarus, FPC: Linux (die neusten Trunk)
CPU-Target: 64Bit
Wohnort: Schweiz

Re: Fragen zu SynEdit

Beitrag von Mathias »

wp_xyz hat geschrieben:
Mathias hat geschrieben:Wie kann ich es machen, das anstelle des Rechtecks, einen Zeilenumbruch kommt. Siehe Anhang.

Code: Alles auswählen

const
  cs = 'Zeile 1' + LineEnding + 'Zeile 2';


Kannst du nicht eine temp StringList benutzen, der du per .Text den String cs zuweist. Im nächsten Schritt durchläufst du die Stringliste Zeile für Zeile und hängst jede an die Lines des SynEdit:

Code: Alles auswählen

procedure TForm1.Button1Click(Sender: TObject);
var
  L: TStrings;
  i: Integer;
  lc: Integer;
begin
  L := TStringList.Create;
  try
    L.Text := cs;
    if L.Count = 0 then
      exit;
    // Sonderbehandlung bis zum ersten Linebreak in cs: direkt an die letzte Zeile im SynEdit anhängen
    lc := SynEdit1.Lines.Count - 1;
    SynEdit1.Lines[lc] := SynEdit1.Lines[lc] + L[0];
    // alle folgenden Zeilen als neue Zeilen ins SynEdit anhängen
    for i:= 1 to L.Count-1 do
      SynEdit1.Lines.Add(L[i]);
  finally
    L.Free;
  end;
end;

Ich musste die Funktion noch ein wenig modifizieren. Wen man SynEdit1.Clear macht, führte dies zum Absturz.

Ich habe eine Prüfung eingebaut, jetzt schein es zu funktionieren.

Code: Alles auswählen

      SLCount := SynEdit1.Lines.Count - 1;
      if SLCount < 1 then begin
        SynEdit1.Lines.Add(TempSL[0]);
      end else begin
        SynEdit1.Lines[SLCount] := SynEdit1.Lines[SLCount] + TempSL[0];
      end;   
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot

Mathias
Beiträge: 6164
Registriert: Do 2. Jan 2014, 17:21
OS, Lazarus, FPC: Linux (die neusten Trunk)
CPU-Target: 64Bit
Wohnort: Schweiz

Re: Fragen zu SynEdit

Beitrag von Mathias »

Noch etwas musste ich einbauen. Es wurde das letzte LineEnding verschluckt.
Ich manche eine einfache Prüfung, ob das letzte Zeichen im Puffer zu einem LineEnding gehört.

Perfekt ist es aber immer noch nicht. Wen der Zufall es will, und der Puffer am Ende genau zwischen dem 13 und 10 abschneidet, gibt es ein Doppel LineEnding.

Code: Alles auswählen

rocedure TSerial_Monitor_Form.Timer1Timer(Sender: TObject);
var
  bufCount, SLCount, i: integer;
begin
  Timer1.Enabled := False;
  try
    bufCount := SerReadTimeout(SerialHandle, ReadBuffer, Length(ReadBuffer) - 1, SpinEdit_TimeOut.Value);
    if bufCount > 0 then begin
      ReadBuffer[bufCount] := 0;
      TempSL.Text := PChar(@ReadBuffer[0]);
 
      SLCount := SynEdit1.Lines.Count - 1;
      if SLCount < 1 then begin
        SynEdit1.Lines.Add(TempSL[0]);
      end else begin
        SynEdit1.Lines[SLCount] := SynEdit1.Lines[SLCount] + TempSL[0];
      end;
 
      for i := 1 to TempSL.Count - 1 do begin
        SynEdit1.Lines.Add(TempSL[i]);
      end;
 
      if ReadBuffer[bufCount - 1] in [10, 13] then begin  // neu
        SynEdit1.Lines.Add('');
      end;
 
      if CheckBox_AutoScroll.Checked then begin
        SynEdit1.CaretY := SynEdit1.Lines.Count;
      end;
 
    end;
  finally
    Timer1.Enabled := True;
  end;
end;
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot

Benutzeravatar
Winni
Beiträge: 1577
Registriert: Mo 2. Mär 2009, 16:45
OS, Lazarus, FPC: Laz2.2.2, fpc 3.2.2
CPU-Target: 64Bit
Wohnort: Fast Dänemark

Re: Fragen zu SynEdit

Beitrag von Winni »

Hi!

Dann musst Du halt genau abfragen ob CRLF vorliegt:

Code: Alles auswählen

if (bufCount  >2) and (ReadBuffer[bufCount - 2] = 13) and (ReadBuffer[bufCount - 1] = 10) then 
      begin 
        SynEdit1.Lines.Add('');
      end;
 


Winni

Mathias
Beiträge: 6164
Registriert: Do 2. Jan 2014, 17:21
OS, Lazarus, FPC: Linux (die neusten Trunk)
CPU-Target: 64Bit
Wohnort: Schweiz

Re: Fragen zu SynEdit

Beitrag von Mathias »

Da werde ich wohl nicht drum kommen.
Ich werde die Zeichen manuell suchen und dann Block für Blöck in die SynEdit schreiben.
Dafür kann ich auf die temporäre Stringlist verzichten.
Mit

Code: Alles auswählen

PChar(@ReadBuffer[ofs])
kann ich in jeder Positon die Blöcke rausschneiden. Ich kann dann ein 13 oder 10 durch eine 0 ersetzen.
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot

Mathias
Beiträge: 6164
Registriert: Do 2. Jan 2014, 17:21
OS, Lazarus, FPC: Linux (die neusten Trunk)
CPU-Target: 64Bit
Wohnort: Schweiz

Re: Fragen zu SynEdit

Beitrag von Mathias »

Folgendermassen sieht es fast so aus, wie es funktionieren würde.

Code: Alles auswählen

procedure TSerial_Monitor_Form.Timer1Timer(Sender: TObject);
var
  bufCount, SLCount: integer;
const
  maxPuffer: integer = 0;
begin
  Timer1.Enabled := False;
  try
//       bufCount := SerReadTimeout(SerialHandle, ReadBuffer, Length(ReadBuffer) - 1, SpinEdit_TimeOut.Value);
    bufCount := SerRead(SerialHandle, ReadBuffer, Length(ReadBuffer) - 1);
    if bufCount > maxPuffer then begin
      maxPuffer := bufCount;
      Caption:=maxPuffer.ToString;
    end;
 
    if bufCount > 0 then begin
      SLCount := SynEdit1.Lines.Count - 1;
      ReadBuffer[bufCount] := 0;
 
//      TempSL.LineBreak := #13#10;
//      TempSL.SkipLastLineBreak := True;
      TempSL.Text := SynEdit1.Lines[SLCount] + PChar(@ReadBuffer[0]);
      SynEdit1.Lines.Delete(SLCount);
      SynEdit1.Lines.AddStrings(TempSL);
      if ReadBuffer[bufCount - 1] = 10 then begin
        SynEdit1.Lines.Add('');
      end;
 
      if CheckBox_AutoScroll.Checked then begin
        SynEdit1.CaretY := SynEdit1.Lines.Count;
      end;
 
    end;
  finally
    Timer1.Enabled := True;
  end;
end
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot

martin_frb
Beiträge: 572
Registriert: Mi 25. Mär 2009, 21:12
OS, Lazarus, FPC: Laz trunk / fpc latest release / Win and other
CPU-Target: mostly 32 bit

Re: Fragen zu SynEdit

Beitrag von martin_frb »

Mathias hat geschrieben:
Mo 27. Apr 2020, 13:57
Leider nicht.
Ich dachte, man hätte vielleicht in ferner Zukunft mal einen Serial-Monitor bauen könne, welcher Escape-Sequenzen abarbeitet.
Ist der SynEdit read only?

Du kannst dafür einen TLazSynDisplayView/TSynEditStringsLinked schreiben. Damit kann man token aus dem Text fischen, und Farbe/Style hinzufügen.

Mathias
Beiträge: 6164
Registriert: Do 2. Jan 2014, 17:21
OS, Lazarus, FPC: Linux (die neusten Trunk)
CPU-Target: 64Bit
Wohnort: Schweiz

Re: Fragen zu SynEdit

Beitrag von Mathias »

Das sollte er sein, muss ihn nur noch auf ReadOnly setzten. Nur markieren und kopieren sollten möglich sein.
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot

Antworten