Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   GUI-Design mit VCL / FireMonkey / Common Controls (https://www.delphipraxis.net/18-gui-design-mit-vcl-firemonkey-common-controls/)
-   -   Delphi SynEdit: Textfarbe an bestimmter Stelle herausfinden (https://www.delphipraxis.net/42293-synedit-textfarbe-bestimmter-stelle-herausfinden.html)

derpepe 16. Mär 2005 22:33


SynEdit: Textfarbe an bestimmter Stelle herausfinden
 
Hallo,

nun bin ich schon seit gestern fast ununterbrochen auf der Suche und hoffe hier endlich die Lösung zu finden :-)

Ich verwenden in meinem Projekt die TSynEdit-Komponente von http://synedit.sf.net. Ich brauche diese Komponente wegen dem Syntax-Highlighting und kann nicht auf TRichEdit o.ä. ausweichen.

Wie kann ich jetzt nun die Farbe an einer bestimmten Stelle (sagen wir Zeile 5, Zeichen 10) feststellen?
Die Farbe bekommt das SynEdit-Control von dem verknüpften SynHighlighter. Diesen habe ich meinen Wünschen entsprechend angepasst.

Hätte ich ein TRichEdit wäre das einfach, ich könnte per SelAttributes.Color einfach den Wert abfragen.
Auf diesem Gedanken aufbauend habe ich folgenden Code entwickelt (bitte nicht hauen, ist echt grausam):

Delphi-Quellcode:
RichEdit1.Clear;
With SynExporterRTF1 Do Begin
  ExportAll (SynEdit1.Lines);
  CopyToClipboard;
End;
With RichEdit1 Do Begin
  PasteFromClipboard;
  CaretPos := Point(10,5);
  SelLength := 1;
End;
ShowMessage (IntToStr(Richedit1.SelAttributes.Color));
Ich habe es nicht mal geschafft den Text direkt vom SynEdit zum RichEdit zu übernehmen (farbig!), dazu habe ich dann die SynExporterRTF-Komponente verwendet.
Nur nochmal zur Verdeutlichung: obiger Code funktioniert! Er hat jedoch einige Haken:
- unschön (!!)
- langsam (ist in Wirklichkeit sogar recht schnell, dennoch wohl nicht das effektivste)
- die Zwischenablage wird benutzt (eine Lösung hierzu wäre höchstens für andere Projekte hübsch, für meinen Fall ist es jedoch nicht akzeptabel, auch wenn ich den Umweg über die Zwischenablage nicht mehr bräuchte)
- ich brauche die SynExporterRTF-Komponente (darauf müßte man verzichten können)

Man müßte die Farbe über den SynHighlighter abfragen können, leider habe ich nichts passendes gefunden, auch ein Studium der Quelltexte und mehrere intensive Suchversuche (btw: tolles Wort *g*) mit Google führten nicht zum Erfolg.

Ihr seht also, ich habe mir bereits viel Mühe gegeben und hoffe hier ein offenes Ohr zu finden und jemanden der sich mit dem SynEdit besser auskennt als ich oder eine Idee für eine alternative Lösung hat :-)

Vielen Dank schonmal im Voraus und entschuldigt das überlange Post.
Liebe Grüße

Peter

Pr0g 16. Mär 2005 23:41

Re: SynEdit: Textfarbe an bestimmter Stelle herausfinden
 
Hier ein kleines Beispiel:
Delphi-Quellcode:
procedure TForm1.Button1Click(Sender: TObject);
var
  fDummy: String;
  fHighlighter: TSynHighlighterAttributes;
  fPos: TBufferCoord;
  fTextColor: TColor;
begin
  //Spalte 1
  fPos.Char := 1;
  //Reihe 1
  fPos.Line := 1;
  //prüfen, ob die Abfrage überhaupt mit der Position möglich ist
  if SynEdit1.GetHighlighterAttriAtRowCol(fPos, fDummy, fHighlighter) then
  begin
    //Farbe aus dem Highlighter auslesen
    fTextColor := fHighlighter.Foreground;
    //nun kann fTextColor verarbeitet werden
    //...
  end;
end;
MfG Pr0g

bigg 17. Mär 2005 00:26

Re: SynEdit: Textfarbe an bestimmter Stelle herausfinden
 
Liste der Anhänge anzeigen (Anzahl: 1)
Anbei ein Beispiel:

derpepe 17. Mär 2005 06:34

Re: SynEdit: Textfarbe an bestimmter Stelle herausfinden
 
GetHighlighterAttriAtRowCol war die Lösung, warum bin ich darauf nicht selbst gekommen!? Hab ich irgendwie nicht gefunden...
Vielen Dank!

derpepe 17. Mär 2005 07:01

Re: SynEdit: Textfarbe an bestimmter Stelle herausfinden
 
Rein Interessehalber: Hättest Du auch eine Lösung für das übernehmen in den RichEdit? Also ohne Copy&Paste halt.

Übrigens: Mein Proggi funzt soweit, habs implementiert bekommen, Du bist ein Held :-)

Pr0g 17. Mär 2005 12:40

Re: SynEdit: Textfarbe an bestimmter Stelle herausfinden
 
Was willst du denn ins RichEdit übernehmen? Den ganzen Text, mit Farben?

derpepe 17. Mär 2005 12:41

Re: SynEdit: Textfarbe an bestimmter Stelle herausfinden
 
genau!

Pr0g 17. Mär 2005 13:02

Re: SynEdit: Textfarbe an bestimmter Stelle herausfinden
 
Du könntest den Code in einen Stream speichern und daraus laden, hier ein Beispiel:
Delphi-Quellcode:
procedure TForm1.Button1Click(Sender: TObject);
var
  fStream: TMemoryStream; //Stream zum Zwischenspeichern
begin
  //Code in Exporter laden
  SynExporterRTF1.ExportAll(SynEdit1.Lines);
  //Streaminstanz erzeugen
  fStream := TMemoryStream.Create;
  try
    //RTF Text/Code in Stream speichern
    SynExporterRTF1.SaveToStream(fStream);
    //an den Anfang des Stream gehen
    fStream.Position := 0;
    //dann wieder in das RichEdit laden
    RichEdit1.Lines.LoadFromStream(fStream);
  finally
    //und Stream wieder freigeben
    fStream.Free;
  end;
end;
Dem Exporter muss natürlich ein Highlighter zugewiesen werden, damit die Formatierungen übernommen werden.

Edit: Wofür brauchst du das eigentlich?

derpepe 17. Mär 2005 13:17

Re: SynEdit: Textfarbe an bestimmter Stelle herausfinden
 
Liste der Anhänge anzeigen (Anzahl: 1)
Cool, danke :-)

Wofür ich das alles brauche:
Ich muss da einen Quelltext analysieren. Dieser ist in der Sprache TAG geschreiben.
Ich hab ein Beispiel in den Anhang gepackt.

Ich muss jetzt den Quelltext analysieren und habe eine Funktion geschrieben, die alle Räume (gekennzeichnet durch "raum xxxxx") in einer ListBox auflistet.

Jetzt bräuchte ich noch eine Funktion die mir daraus z.B. ausspuckt was bei "Besch" steht.
Das Problem dabei: Die Strings sind teilweise mehrzeilig, Kommentare müssen natürlich ausgelassen werden.
Wenn dafür jemand einen tollen Tipp hat: sehr gerne :-)


Noch eine Frage zu folgendem Screenshot:
http://www.webweaver.ws/webweaver/pics/oberflaeche.jpg
Nimmst Du da auch den SynEdit?
Mich interessiert die graue Zeile (zeigt wohl die aktuelle Zeile an) und die zwei roten Vierecke um die Klammern.
Wie hast Du das realisiert?

derpepe 17. Mär 2005 13:24

Re: SynEdit: Textfarbe an bestimmter Stelle herausfinden
 
Liste der Anhänge anzeigen (Anzahl: 1)
Nochmal zur genaueren Erklärung:
Die Raumliste zur obigen Quelltextdatei sieht in meinem Editor aus wie auf dem Screenshot.
(Sorry für den RichEdit, die EditLine rechts und das Memo, die kommen natürlich später weg)

Ich hätte jetzt gerne eine Funktion
Delphi-Quellcode:
function GetItem(Raum,Bezeichnung:String):String;
die z.B. folgendes zurückgibt:
Delphi-Quellcode:
GetItem('Eingang','Std') = BinIchBlöd
GetItem('Eingang','Besch') = 'Ich stehe hier am Eingang von Karn. Viele Legenden ranken sich um
        das unterirdische Höhlensystem.

        Ein kleines, wenig einladend aussehendes Loch führt nach unten.
        Nebelschwaden ziehen aus dem Loch empor.'
Jemand eine Idee wie das gehen kann?

Pr0g 17. Mär 2005 14:18

Re: SynEdit: Textfarbe an bestimmter Stelle herausfinden
 
Die aktuelle Zeile kannst du farbig markieren, in dem du die Eigenschaft "ActiveLineColor" des SynEdit änderst.

Die roten Markierungen zeichnen ich selber auf das Canvas.

Zu dem Auslesen der Werte, hier mal eine Funktion, wird zwar nicht die beste sein, aber als Denksanstoss bestimmt geignet:
Delphi-Quellcode:
function GetItem(const AData: TStrings; const ARoom, AItem: String): String;
var
  i, j, k,
  fPos,
  fOpenStart: Integer;
  fLine: String;
  fFinish,
  fOpen: Boolean;
begin
  Result := '';
  //nach der Position des Raums suchen
  for i := 0 to AData.Count - 1 do
  begin
    if Pos(ARoom, AData[i]) > 0 then
      if Pos('Raum', AData[i]) = 1 then
      begin
        fPos := i;
        Break;
      end;
  end;
  //Attribut auslesen
  fFinish := False;
  fOpen := False;
  for i := fPos to AData.Count - 1 do
  begin
    if Pos(AItem, AData[i]) = 1 then
    begin
      fLine := AData[i];
      //Wert abtrennen
      for j := Pos(' ', fLine) to Length(fLine) do
      begin
        if fLine[j] <> ' ' then
        begin
          for k := j to Length(fLine) do
            Result := Result + fLine[k];
          Break;
        end;
      end;
      //prüfen, ob der String vollständig ist
      if Result[1] = '''' then
      begin
        fOpen := True;
        fOpenStart := i;
        //Anführungszeichen entfernen
        Delete(Result, 1, 1);
      end else
        fFinish := True;
    end;
    if fOpen then
    begin
      if fOpenStart = i then
        Continue;
      fLine := AData[i];
      if fLine = '' then
        Continue;
      //Wert abtrennen
      for j := Pos(' ', fLine) to Length(fLine) do
      begin
        if fLine[j] <> ' ' then
        begin
          for k := j to Length(fLine) do
            Result := Result + fLine[k];
          Break;
        end;
      end;
      if Result[Length(Result)] = '''' then
      begin
        fOpen := False;
        fFinish := True;
        Delete(Result, Length(Result), 1);
      end;
    end;
    if fFinish then
      Break;
  end;
Hier noch ein Beispiel zur Verwendung. Anstatt die Datei zu laden, kannst du als AData auch bspw. die Lines eines Memos oder so angeben, je nach dem was da auf dem Screenshot ist, weiß ja nicht wo du es brauchst:
Delphi-Quellcode:
procedure TForm1.Button1Click(Sender: TObject);
var
  //Stringliste zum speichern der Daten
  fData: TStrings;
begin
  //Instanz anlegen
  fData := TStringList.Create;
  try
    //Liste laden
    fData.LoadFromFile(ExtractFilePath(ParamStr(0)) + 'Karn.adv.txt');
    //Wert "Std" von "Eingang" auslesen
    Edit1.Text := GetItem(fData, 'Eingang', 'Std');
    //wert "Besch" von Eingang" auslesen
    Memo1.Text := GetItem(fData, 'Eingang', 'Besch');
  finally
    //Liste wieder freigeben
    fData.Free;
  end;
end;

derpepe 17. Mär 2005 14:45

Re: SynEdit: Textfarbe an bestimmter Stelle herausfinden
 
Das mit dem SynEdit.ActiveLineColor war ein guter Tipp, hatte ich nicht gesehen.

Hab sowas ähnliches jetzt programmiert.
Nur gibt es noch Fehler.

Beispielsweise wird folgendes analysiert:
Delphi-Quellcode:
Raum   Pilzraum
Name   'Pilzraum'
Std    Felsen
W      Achteck
O      durch_Pilze
Attr   Dunkel Innen
Besch  'Dies ist eine feuchte, aber recht geräumige Höhle. Die gesamte
        Ostwand ist von einer schleimigen, gelblichen Pilzmasse bedeckt,
        aus der tausende von kleinen braunen Hutpilzen wachsen. Es sieht
        so aus, als ob dort früher ein Durchgang war, aber jetzt ist alles
        zugewachsen. Im Westen geht es zurück in den achteckigen Raum.'
NachAusf
  (Lage)       Wenn (Pilze_weg) dann
                  Text 'Ein großer Teil der Pilze ist verfault, so daß ein
                       häßliches Loch in der Wand klafft, durch das ich gehen
                       kann.'
                Ende
EndeAusf
Gesucht wird nach SO (für Südosten).

Jedoch:
Delphi-Quellcode:
GetItem(fData, 'Eingang', 'so') = aus, als ob dort früher ein Durchgang war, aber jetzt ist alles
Problem ist klar: Das liegt in einem String. Er findet sowas aber auch wenn es in einem Kommentar /* Kommentar */ liegt.
Bisher hab ich das mit dem SynEdit gemacht, da der das korrekt highlighted. Also: Abfrage an aktueller Stelle ob das ein Kommentar oder String ist...

Hast Du einen besseren Vorschlag?

Pr0g 17. Mär 2005 14:54

Re: SynEdit: Textfarbe an bestimmter Stelle herausfinden
 
Ich verstehe das Problem nicht ganz, oder habe was falsch verstanden, der Text, den du da hast ist ja von "Pilzraum", also müsste der Aufruf so aussehen:
Delphi-Quellcode:
GetItem(fData, 'Pilzraum', 'Besch');
und da kommt dann das bei mir raus:
Dies ist eine feuchte, aber recht geräumige Höhle. Die gesamteOstwand ist von einer schleimigen, gelblichen Pilzmasse bedeckt,aus der tausende von kleinen braunen Hutpilzen wachsen. Es siehtso aus, als ob dort früher ein Durchgang war, aber jetzt ist alleszugewachsen. Im Westen geht es zurück in den achteckigen Raum.

derpepe 17. Mär 2005 14:59

Re: SynEdit: Textfarbe an bestimmter Stelle herausfinden
 
Nicht 'Besch', 'SO'!!!

Hab mich auch vertippt, sollte Pilzraum sein, nicht Eingang.

Pr0g 17. Mär 2005 15:05

Re: SynEdit: Textfarbe an bestimmter Stelle herausfinden
 
Wo steht denn dort ein Attribut "SO", dort sind doch nur die zwei einzelnen "W" und "O"?

derpepe 17. Mär 2005 15:10

Re: SynEdit: Textfarbe an bestimmter Stelle herausfinden
 
Liste der Anhänge anzeigen (Anzahl: 1)
Ich häng jetzt meinen TagEdit mal an.
Tut zwar das meiste noch nicht, aber dann kannst Du wenigstens mal ausprobieren was ich hier die ganze Zeit laber.

Das "so" steht in dem String drin!

Deine Prozedur kann das mit Strings, nur mit Kommentaren funktionerts dann nicht.
Delphi-Quellcode:
Raum   Pilzraum
Name   'Pilzraum'
Std    Felsen
W      Achteck
O      durch_Pilze
Attr   Dunkel Innen
Besch  'Die Beschreibung' /* Beginn des mehrzeiligen Kommentars
So wird diese Zeile jetzt gefunden weil "so" am Anfang steht.
Sie ist aber innerhalb eines Kommentars und sollte deshalb nicht gefunden werden */
NachAusf
  (Lage)       Wenn (Pilze_weg) dann
                  Text 'Ein großer Teil der Pilze ist verfault, so daß ein
                       häßliches Loch in der Wand klafft, durch das ich gehen
                       kann.'
                Ende
EndeAusf
Ich will jetzt nicht im Programm Strings und Kommentare einprogrammieren, ich hab ja schon über den SynEdit (mittels Highlighting) definiert was String und was Kommentar ist.

In der angehängten Version funktioniert das ganze, jedoch mach ich einen Umweg über SynEdit2.
Gucks Dir doch mal an und sag mir wie ich den SynEdit2 loswerden kann!!
(SynEdit2 wird sonst für nichts gebraucht).

derpepe 17. Mär 2005 15:24

Re: SynEdit: Textfarbe an bestimmter Stelle herausfinden
 
Mal noch kurz die Funktion um die es geht :-)

Delphi-Quellcode:
function THauptfenster.GetItemPart(identifier,name,pname,part:string):string;
var
  position,line:integer;
  found:boolean;
  aname,s,temp:string;
  xy:tbuffercoord;
  attribute:tsynhighlighterattributes;
begin
  SynEdit2.Lines.Text:=getitem(identifier,name,pname);
  line:=0;
  found:=false;
  while (line<=SynEdit2.lines.count-1) do begin
    temp:=cutby(synedit2.lines[line]);

    xy.Char:=pos(lowercase(part),lowercase(Synedit2.lines[line]))+length(part);
    xy.Line:=line;

    if SynEdit2.GetHighlighterAttriAtRowCol(xy,s,attribute) then
      aname:=attribute.name
    else
      aname:='';

    if (lowercase(copy(temp,1,length(part)+1))=lowercase(part)+' ') and (aname<>commentAttr) and (aname<>stringAttr) then begin
      found:=true;
      break;
    end;
    inc(line);
  end;
  if found then begin
    position:=pos(lowercase(part),lowercase(synedit2.lines[line]));
    getitempart:=cutby(copy(synedit2.lines[line],position+length(part),length(synedit2.lines[line])-position-length(part)+1));
  end else getitempart:='';
end;
Ich würde gerne des SynEdit2 durch eine TStringList ersetzen, allerdings wird dann die GetHighlighterAttriAtRowCol unmöglich. Oder doch nicht?

Pr0g 17. Mär 2005 15:55

Re: SynEdit: Textfarbe an bestimmter Stelle herausfinden
 
GetHighlighterAttriAtRowCol ist vom SynEdit, also kannst du es auch nur mit diesem nutzen.

derpepe 17. Mär 2005 15:57

Re: SynEdit: Textfarbe an bestimmter Stelle herausfinden
 
Kann ich den dann nicht wenigstens zur Laufzeit erstellen, also ohne visuelle Komponente?
So à la
Delphi-Quellcode:
SynEdit2:=TSynEdit.Create;
Einfach nur Visible auf False setzen find ich blöd.

Warum brauch ich da dann den SynEdit? Reicht nicht der SynHighlighter aus!?

Pr0g 17. Mär 2005 16:11

Re: SynEdit: Textfarbe an bestimmter Stelle herausfinden
 
Ob du es zur Laufzeit erstellst, oder mit Visbile ausblendest macht keinen großen Unterschied. Es bleibt eine versteckte, visuelle Komponente.

Das SynEdit wird benötigt, da die Highlighter alleine nicht arbeiten können. Daher brauchst du ja bspw. auch eine Exporter um Text (wie vorhin mit dem RichEdit) kopieren zu können.

derpepe 17. Mär 2005 18:46

Re: SynEdit: Textfarbe an bestimmter Stelle herausfinden
 
Ok, danke :-)
Dann muss ich wohl mit dem versteckten SynEdit leben.


Alle Zeitangaben in WEZ +1. Es ist jetzt 07:00 Uhr.

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz