[FAQ] Syntax highlighting (RichEdit)



  • Hi,

    ich hab da ne frage:

    ich benutze in meinem Projekt das FAQ Beispiel Syntax highlighten (http://thunder.prohosting.com/~cbdn/a_syn.htm).

    Wenn ich eine Datei in mein RichEdit lade, passiert nichts!
    Wenn ich dann z.b. vor die ganze zeile ein leerzeichen setze, werden die entsprechenden schlüsselwörter hervorgehoben! hat da jemand ne idee, wie ich das ändern kann?

    mein code(ausschnitt):

    char *Keywords[34]={
    "for","while","do","switch","case","break","sizeof","true",
    "false","int","char","String","AnsiString","#include","#ifndef",
    "#define","#pragma","void","return","if","else","bool","class",
    "public","__published","private","struct","long","unsigned","short",
    "float","try","catch","system"
    };
    
    //in FormCreate:
      OpenDialog1->InitialDir=ExtractFilePath(Application->ExeName);
      SaveDialog1->InitialDir=ExtractFilePath(Application->ExeName);
      if(ParamStr(1)!="")
        RichEdit1->Lines->LoadFromFile(ParamStr(1));
      path=ExtractFilePath(Application->ExeName)+"\\settings.ini";
      CHARFORMAT Default;
      Default.cbSize=sizeof(Default);
      Default.dwMask=CFM_BOLD | CFM_FACE | CFM_SIZE | CFM_CHARSET;
      Default.dwEffects=0;
      Default.yHeight=200;
      Default.bCharSet=0xEE;
      strcpy(Default.szFaceName,"Courier New");
      RichEdit1->Perform(EM_SETCHARFORMAT,SCF_ALL,(LPARAM)&Default);
      RichEdit1->Perform(EM_SETEVENTMASK,0,(LPARAM)ENM_CHANGE);
    // funktionen des highlighting:
    
    int TForm1::GetFirstPos(int Line)
    {
        int Pos=RichEdit1->Perform(EM_LINEINDEX,Line,0);
        return Pos;
    }
    //---------------------------------------------------------------------------
    
    int TForm1::GetLastPos(int Line)
    {
      if(Line==RichEdit1->Lines->Count-1)
        return RichEdit1->Text.Length();
      else{
        int Pos=RichEdit1->Perform(EM_LINEINDEX,Line+1,0);
        return (Pos-1);
      }
    }
    //---------------------------------------------------------------------------
    
    void TForm1::HighlightWords(TColor Color)
    {
        int EventMask=RichEdit1->Perform(EM_SETEVENTMASK,0,ENM_NONE);
        LockWindowUpdate(RichEdit1->Handle);
        RichEdit1->Perform(EM_HIDESELECTION,true,false);
    
        CHARRANGE Original;
        RichEdit1->Perform(EM_EXGETSEL,0,(LPARAM)&Original);
    
        int CurrentLine=RichEdit1->Perform(EM_LINEFROMCHAR,Original.cpMin,0);
        int Start=GetFirstPos(CurrentLine);
        int End=GetLastPos(CurrentLine);
        int FoundPos,FindLength;
    
        CHARRANGE LineSelection;
        LineSelection.cpMin=Start;
        LineSelection.cpMax=End;
        RichEdit1->Perform(EM_EXSETSEL,0,(LPARAM)&LineSelection);
    
        CHARFORMAT FormatNormal;
        memset(&FormatNormal,0,sizeof(FormatNormal));
        FormatNormal.cbSize=sizeof(FormatNormal);
        FormatNormal.dwMask=CFM_COLOR | CFM_BOLD;
        FormatNormal.crTextColor=clBlack;
        FormatNormal.dwEffects=0;
        RichEdit1->Perform(EM_SETCHARFORMAT,SCF_SELECTION,(LPARAM)&FormatNormal);
    
        PreviousLine=CurrentLine;
        PreviousMatchCount=0;
    
        for(int x=0;x<sizeof(Keywords)/sizeof(Keywords[0]);x++)
        {
            FindLength=strlen(Keywords[x]);
    
            ::FINDTEXT FindText;
            FindText.lpstrText=Keywords[x];
            FindText.chrg.cpMin=Start;
            FindText.chrg.cpMax=End;
            FoundPos=RichEdit1->Perform(EM_FINDTEXT,FT_WHOLEWORD,(LPARAM)&FindText);
    
            while(FoundPos>-1)
            {
                PreviousMatchCount++;
                RichEdit1->SelStart=FoundPos;
                RichEdit1->SelLength=FindLength;
    
                CHARFORMAT FormatKey;
                memset(&FormatKey,0,sizeof(FormatKey));
                FormatKey.cbSize=sizeof(FormatKey);
                FormatKey.dwMask=CFM_COLOR | CFM_BOLD;
                FormatKey.crTextColor=Color;
                FormatKey.dwEffects=CFE_BOLD;
                RichEdit1->Perform(EM_SETCHARFORMAT,SCF_SELECTION,(LPARAM)&FormatKey);
    
                FindText.chrg.cpMin=FoundPos+FindLength;
                FoundPos=RichEdit1->Perform(EM_FINDTEXT,FT_WHOLEWORD,(LPARAM)&FindText);
            }
        }
        RichEdit1->Perform(EM_EXSETSEL,0,(LPARAM)&Original);
        RichEdit1->Perform(EM_SETCHARFORMAT,SCF_SELECTION,(LPARAM)&FormatNormal);
        RichEdit1->Perform(EM_HIDESELECTION,false,false);
        LockWindowUpdate(NULL);
        RichEdit1->Perform(EM_SETEVENTMASK, 0, EventMask);
    }
    
    bool TForm1::CanAvoidHighlight()
    {
        int CurrentLine=RichEdit1->Perform(EM_LINEFROMCHAR,-1,0);
        int Start=GetFirstPos(CurrentLine);
        int End=GetLastPos(CurrentLine);
        int FoundPos,FindLength;
        int TempMatchCount=0;
    
        if(PreviousLine!=CurrentLine)
            return false;
    
        for(int x=0;x<sizeof(Keywords)/sizeof(Keywords[0]);x++)
        {
            FindLength=strlen(Keywords[x]);
    
            ::FINDTEXT FindText;
            FindText.lpstrText=Keywords[x];
            FindText.chrg.cpMin=Start;
            FindText.chrg.cpMax=End;
            FoundPos=RichEdit1->Perform(EM_FINDTEXT,FT_WHOLEWORD,(LPARAM)&FindText);
    
            while(FoundPos>-1)
            {
                TempMatchCount++;
                FindText.chrg.cpMin=FoundPos+FindLength;
                FoundPos=RichEdit1->Perform(EM_FINDTEXT,FT_WHOLEWORD,(LPARAM)&FindText);
            }
        }
        if(TempMatchCount==PreviousMatchCount)
          return true;
        else
          return false;
    }
    
    // on change:
    
    void __fastcall TForm1::RichEdit1Change(TObject *Sender)
    {
      sicher=false;
      if((highlight)&&(!CanAvoidHighlight()))
        HighlightWords(clBlack);
    }
    

    danke!

    PS: wenn ich in einer datei syntax highlighting hatte und eine lade, wird die komplette neue datei schwarz und fett geschrieben!
    wieso das denn??
    aso:

    // Laden ist mein MenuItem "Öffnen"
    void __fastcall TForm1::Laden1Click(TObject *Sender)
    {
      try
      {
        if(OpenDialog1->Execute())
        {
          RichEdit1->Lines->LoadFromFile(OpenDialog1->FileName);
          SaveDialog1->FileName=OpenDialog1->FileName;
          Kompilieren1->Enabled=true;
          KompUndShell->Enabled=true;
          AnsiString oldtext;
          for(int i=0;i<RichEdit1->Lines->Count+1;i++)
          {
            oldtext=RichEdit1->Lines->Strings[i];
            RichEdit1->Lines->Strings[i]="a";
            RichEdit1->Lines->Strings[i]=oldtext;
          }
          sicher=true;
          Form1->Caption="EditText 1.5";
        }
      }
      catch(...)
      {
        ShowMessage("Fehler! Die Datei konnte nicht geladen werden!");
      }
    }
    //---------------------------------------------------------------------------
    


  • Blackhawk schrieb:

    Wenn ich eine Datei in mein RichEdit lade, passiert nichts!
    Wenn ich dann z.b. vor die ganze zeile ein leerzeichen setze, werden die entsprechenden schlüsselwörter hervorgehoben! hat da jemand ne idee, wie ich das ändern kann?

    Klar: Analysiere den Quelltext und schau mal (mit HIlfe des Debuggers) was genau das Highlightning auslöst. Anschliessend versuchst du herauszufinden, wieso es nicht beim Laden ausgelöst wird.

    Blackhawk schrieb:

    PS: wenn ich in einer datei syntax highlighting hatte und eine lade, wird die komplette neue datei schwarz und fett geschrieben!
    wieso das denn??

    Auch hier empfiehlt es sich wohl, den Debugger zu bemühen... Kleiner test für dich: Was passiert, wenn du die Schlüsselwörter blau färbst und als letztes in der Datei ein Schlüsselwort steht und du dann die Datei lädst?

    -junix



  • hat alles nix genützt, hab auch rausgefunden, dass man die funktion ganz umschreiben müsste, damit man das highlighten könnte, wenn man ne datei lädt.

    wenn jemand ein anderes beispiel kennt, bitte posten, ansonsten schreib ich mir die funktion irgendwann mal um.



  • Hallo,

    sieht so aus, als würde das OnChange - Event vom RichEdit nicht ausgelöst werden, wenn ne Datei geladen wird. Lösung: Event selber auslösen, nachdem du die Datei geladen hast!

    ciao
    Robert



  • hab ich auch schon ausprobiert mit:

    for(int i=0;i<RichEdit1->Lines->Count+1;i++)
    {
      AnsiString oldtext=RichEdit1->Lines->Strings[i];
      RichEdit1->Lines->Strings[i]+="a";
      RichEdit1->Lines->Strings[i]=oldtext;
    }
    

    dann hab ich das mit einer projektdatei von mir ausprobiert (~800 zeilen) und wie ihr euch schon dneken könnt hat das ungefähr 25 sekunden gebraucht bis alles dann durchsucht wurde nach den schlüsselwörtern. Noch ne idee? oder hattest du was anderes gemeint?



  • Hi,
    schreib doch einfach mal RichEdit1Change(Sender); hinter das Laden....

    MfG

    Alexander Sulfrian



  • Ich hatte gemeint:

    RichEdit1->OnChange(RichEdit1);
    


  • ..bringt wieder nur die erste zeile 😞

    aber trotzdem danke für eure antworten



  • Highlighte nur das was du auch wirklich anzeigst...

    Lässt sich theoretisch sehr einfach durch die Integration einer Document/View Architektur erreichen...

    -junix



  • Highlighte nur das was du auch wirklich anzeigst...

    was?? was soll das denn heissen? 😕

    aber die klasse TMyDocument von dir bringts echt voll 👍

    werd ich dann mal ausprobieren



  • Blackhawk schrieb:

    Highlighte nur das was du auch wirklich anzeigst...

    was?? was soll das denn heissen? 😕

    Das was da steht: Schick nur den Teil des Textes der sichtbar ist durch den Highlighter...

    Blackhawk schrieb:

    aber die klasse TMyDocument von dir bringts echt voll 👍

    Wie soll ich das jetzt interpretieren?

    -junix



  • dass ich die klasse voll genial finde! Super idee!


Anmelden zum Antworten