Italian community of Lazarus and Free Pascal

Programmazione => LCL => Topic aperto da: darione - Gennaio 11, 2019, 12:04:07 am

Titolo: Tsynedit per evidenziare solo alcune parole del testo
Inserito da: darione - Gennaio 11, 2019, 12:04:07 am
Salve a tutti,
avrei questo quesito.
 
Dovrei visualizzare in un memo un brano ed evidenziare di rosso solo alcune parole particolari.

Ho provato con TSynEdit ma non ho capito come fare, non riesco a trovare una chiara documentazione on line ... si vede che è un componente assai complesso e flessibile, ma un semplice tutorial su come evidenziare solamente delle proprie parole io non l'ho trovato. Magari sono imbranato io ... :-(

Qualcuno può indicarmi come fare?
Grazie mille, Darione :-)
Titolo: Re:Tsynedit per evidenziare solo alcune parole del testo
Inserito da: Stilgar - Gennaio 11, 2019, 05:49:18 pm
Ciao.Ho trovato questo.http://forum.lazarus.freepascal.org/index.php?topic=1004.0

 blockbegin
 blockend
:)
Stilgar
Titolo: Re:Tsynedit per evidenziare solo alcune parole del testo
Inserito da: bonmario - Gennaio 11, 2019, 06:23:40 pm
Ciao,
scusami, ma in questo periodo ho poco tempo a disposizione ...

Qui sotto ti metto una unit che mi sono fatto io per racchiudere tutte le gestioni particolari delle TSynEdit.

Codice: [Seleziona]
{
In questa unit cercherò di racchiudere tutte le procedure / funzioni che usano
gli "oggetti Syn" (TSynEdit, ecc.)
}

{$mode objfpc}{$H+}

unit BonMarSyn;

interface

uses Graphics, LCLType, Forms, Controls, Classes, LCLProc, SynEdit,
     SynHighlighterPosition, SynEditHighlighter, SysUtils, strutils, SynEditTypes;

  procedure TrovaInSynEdit(var WrkSynEdit:TSynEdit; StrDaCerc:String; VFPartiDaInizio, VFIgnoraMinMai:Boolean);
  procedure EvidenziaInSyn(NumRiga:Integer; St, StrDaCerc:String);
  procedure InizializzaHighLighter(var WrkSynEdit: TSynEdit; ColoreCarattere, ColoreSfondo:TColor);
  procedure ClearHighLighter;
  procedure AttivaHighLighter;
  procedure EvidenziaInSynPerBat(var WrkSynEdit:TSynEdit);


var WrkHighlighter:TSynPositionHighlighter;
    MyAttr, MyAttrBatComm, MyAttrBatLabel, MyAttrBatRigheEseg:TtkTokenKind;

implementation
  uses BonMarUtils;


  procedure TrovaInSynEdit(var WrkSynEdit: TSynEdit; StrDaCerc:String; VFPartiDaInizio, VFIgnoraMinMai:Boolean);
  var WrkOptions: TSynSearchOptions;
  begin
    WrkOptions:=[];
    if VFPartiDaInizio then begin
      WrkOptions:=WrkOptions + [ssoEntireScope];
    end else begin
      WrkOptions:=WrkOptions + [ssoFindContinue];
    end;

    if (not VFIgnoraMinMai) then begin
      WrkOptions:=WrkOptions + [ssoMatchCase];
    end;

    if (WrkSynedit.SearchReplace(StrDaCerc, '', WrkOptions) = 0) then begin
      EmettiErrore(28);
    end;
  end;



  procedure EvidenziaInSyn(NumRiga:Integer; St, StrDaCerc: String);
  var Posx, LenStrDaCerc, UltChrDaEvid:Integer;
      WrkLoop:Integer;
  begin
    //A volte il programma andava in loop.
    //Questa variabile serve per verificare se riesco ad evitarlo
    WrkLoop:=0;

    //Valorizzo la stringa che dovrò evidenziare e la sua lunghezza.
    //Se non si vuole evidenziare niente di specifico, evidenzio tutta la riga
    if (StrDaCerc = '') then begin
      StrDaCerc:=St;
    end;
    StrDaCerc:=UpperCase(StrDaCerc);
    LenStrDaCerc:=Length(StrDaCerc);

    //La stringa che devo cercare può essere contenuta più volte.
    //Faccio in modo di evidenziarle tutte
    Posx:=RPos(StrDaCerc, UpperCase(St));
    while (Posx > 0) and (WrkLoop < 100) do begin
      //Incremento il contatore per verifica loop
      WrkLoop:=WrkLoop + 1;

      //Se mi capita un probabile loop, provo a modificare il colore di sfondo.
      //In questo modo magari iesco a capire dov'è il problema
      if (WrkLoop > 50) then begin
        WrkHighlighter.TextAttri.Background:=clRed;
      end;

      //Per ogni riga devo definire che:
      //- Dalla posizione iniziale, fino al carattere prima della stringa che sto cercando, non va fatta nessuna formattazione
      //- Dalla posizione in cui è stata trovata la stringa va fatta la formattazione
      //- Dalla posizione successiva alla fine della stringa da cercare non serve nessuna formattazione
      UltChrDaEvid:=Posx + LenStrDaCerc - 1;

      if (UltChrDaEvid < Length(St)) then begin
        //Se la stringa da cercare è proprio in fondo, questa parte non va eseguita,
        //altrimenti l'istruzione successiva la annullerebbe !!!
        WrkHighlighter.AddToken(NumRiga, Length(St), tkText);
      end;
      WrkHighlighter.AddToken(NumRiga, UltChrDaEvid, MyAttr);
      WrkHighlighter.AddToken(NumRiga, Posx - 1, tkText);

      //Cancello dalla stringa la parte relativa all'occorrenza che ho appena
      //evidenziato e verifico se ce ne sono altre
      System.Delete(St, Posx, Length(St));
      Posx:=RPos(StrDaCerc, UpperCase(St));
    end;
  end;



  procedure InizializzaHighLighter(var WrkSynEdit: TSynEdit; ColoreCarattere, ColoreSfondo:TColor);
  begin
    WrkHighlighter:=TSynPositionHighlighter.Create(nil);
    WrkHighlighter.Enabled:=False;
    WrkSynEdit.Highlighter:=WrkHighlighter;

    //Definisco la modalità di evidenziazione
    MyAttr:=WrkHighlighter.CreateTokenID('MyAttr', ColoreCarattere, ColoreSfondo, [fsBold]);
  end;



  procedure ClearHighLighter;
  begin
    WrkHighlighter.Enabled:=False;
    WrkHighlighter.ClearAllTokens;
  end;

  procedure AttivaHighLighter;
  begin
    WrkHighlighter.Enabled:=True;
  end;





  procedure EvidenziaInSynPerBat(var WrkSynEdit:TSynEdit);
  var NumRiga:Integer;
      WrkSt:String;
  begin
    //Creo il nuovo HighLighter con le impostazioni specifiche per i files BAT
    WrkHighlighter:=TSynPositionHighlighter.Create(nil);
    WrkHighlighter.Enabled:=False;
    WrkSynEdit.Highlighter:=WrkHighlighter;

    //Commento
    MyAttrBatComm:=WrkHighlighter.CreateTokenID('BatComm', clGreen, WrkSynEdit.Color, []);

    //Label
    MyAttrBatLabel:=WrkHighlighter.CreateTokenID('BatLabel', clRed, WrkSynEdit.Color, []);

    //Righe che verranno eseguite: le faccio nel colore di default, ma in grassetto + italico
    MyAttrBatRigheEseg:=WrkHighlighter.CreateTokenID('BatExe', WrkSynEdit.Font.Color, WrkSynEdit.Color, [fsBold, fsItalic]);


    //Ora esamino riga per riga, per vedere se la devo colorare o no
    for NumRiga:=0 to WrkSynEdit.Lines.Count - 1 do begin
      //Valorizzo la stringa nell'output
      WrkSt:=LowerCase(Trim(WrkSynEdit.Lines[NumRiga]));

      //Commento
      if (Copy(WrkSt, 1, 2) = '::') or
         (Copy(WrkSt, 1, 4) = 'rem ') then begin
        WrkHighlighter.AddToken(NumRiga, Length(WrkSynEdit.Lines[NumRiga]), MyAttrBatComm);
      end else begin
        //Label per GoTo
        if (Copy(WrkSt, 1, 1) = ':') then begin
          WrkHighlighter.AddToken(NumRiga, Length(WrkSynEdit.Lines[NumRiga]), MyAttrBatLabel);
        end else begin
          //Tutte le altre righe, quindi quelle che verranno effettivamente eseguite,
          //le faccio in grassetto + italico
          WrkHighlighter.AddToken(NumRiga, Length(WrkSynEdit.Lines[NumRiga]), MyAttrBatRigheEseg);
        end;
      end;
    end;

    //Attivo l'highlighter
    AttivaHighLighter;
  end;



finalization
FreeAndNil(WrkHighlighter);

end.



Probabilmente ti darà degli errori dovuti alla dipendenza con "BonMarUtils", che non posso condividere, ma togliendo la sua uses e verificando gli errori, dovresti comunque ricavarne qualcosa di utile.

Poi, ad esempio, nella OnChange della tua TSynEdit, puoi mettere questo:

Codice: [Seleziona]
procedure TForm1.MemoCmdDosPrimaChange(Sender: TObject);
begin
  //Lancio la procedura che i occupa di colorare le righe in base al loro
  //contenuto
  EvidenziaInSynPerBat(MemoCmdDosPrima);
end;


Ciao, MArio