Zeile in RichEdit neu zeichnen



  • code_pilot schrieb:

    Huhu erstmal danke. Im Netz findet man wirklich nix zu dem Thema.

    @AZIS: Der Link funzt net 😞

    Eigenartig... Bei mir tut er das.

    code_pilot schrieb:

    @WebFritzi: Danke für die Funktion 🙂 Hmm aber weist du auch wie man das nun machen kann das er den Bereich nicht updated? So etwas wie LockWindowUpdate() nur halt für das Rechteck das deine Funktion zurückgibt ...

    Ich denke das müsste die Rendering-Engine von RichEdit unterstützen. Soweit ich weiß gibt es keine Message, mit der man das machen kann.



  • Hi @ Aziz: Hab ihn doch gefunden und mal angeguckt ... naja so wir da ist mein Syntax highlighting derzeit auch, also flackert ein wenig (wobei das da noch extremer ist, bei mir flackert er nur ein wenig wenn du ein Keyword löschst).

    Gruss,
    ~cp



  • code_pilot schrieb:

    Kann ich für eine bestimmte Zeile, also die in der ich grad im Editor editiere, das automatische Updaten abschalten, und wenn er mit dem highlighting fertig ist die Zeile 1X aktualisieren? Ich hab das mal mit LockWindowUpdate() probiert, aber das kann man vergessen weil dann anstatt die aktuelle Zeile gleich das gesamte Editfeld flackert, wenn er etwas highlighted.

    ValidateRect()



  • Wollte nochmal meine Funktion korrigieren bzw. erweitern.

    BOOL RichEdit_GetLineRect(HWND hwnd, int line_index, RECT* lprc)
    {
       POINTL pl_1, pl_2;
       int char_id;
       POINT pt;
    
       char_id = SendMessage(hwnd, EM_LINEINDEX, line_index, 0);
       SendMessage(hwnd, EM_POSFROMCHAR, (WPARAM)&pl_1, (LPARAM)char_id);
       char_id = SendMessage(hwnd, EM_LINEINDEX, line_index + 1, 0);
       SendMessage(hwnd, EM_POSFROMCHAR, (WPARAM)&pl_2, (LPARAM)char_id);
    
       // Der Zeilenindex ist zu groß
       if( pl_2.y <= 1)
          return FALSE;
    
       ::GetClientRect(hwnd, lprc);
    
       lprc->left   = pl_1.x;
       lprc->top    = pl_1.y;
       lprc->bottom = pl_2.y;
    
       return TRUE;
    }
    


  • Hi!
    Hmm bekomme das aber leider irgendwie nicht zum laufen.

    Mein Code (Auszüge)...
    (Achtung, ich verwende die API-Calls in einem C++ Builder Projekt, daher Editor->Handle als HWND usw...)

    RECT currentLine_rect;
    bool unLockWindow = false;
    
    /* ... */
    
    int Start, End, selStart, CurrentLine;
    
    CurrentLine = Editor->Perform(EM_LINEFROMCHAR, Original.cpMin, 0);
    
    if(GetLineRect(Editor->Handle, CurrentLine, &currentLine_rect))
    {
          ValidateRect(Editor->Handle, &currentLine_rect);
          unLockWindow = true;
    }
    
    /*
        HIGHLIGHTING...
    */
    
    if(unLockWindow) InvalidateRect( Editor->Handle, &currentLine_rect, true);
    

    Es flackert aber genauso wie vorher ... weis jemand eine Lösung bzw. was falsch sein könnte?

    Gruss,
    ~code_pilot



  • In welcher Message-Behandlung steht der obige Code?



  • Hi Webfritzi ...

    oh öhhhh ... in gar keiner 🙄 öhhh ... naja wie schon gesagt ich habe das in einem C++Builder Projekt in eine Klassenfunktion eingebaut ... muss das ins WM_PAINT rein? (Fragt sich nur wo das im C++Builder bei VCL/WinAPI-Kreuzungsprojekten ist...)

    😕

    wo muss es denn eigentlich rein???

    Grüsse,
    ~copde_pilot 🙄



  • code_pilot schrieb:

    in gar keiner

    Na, dann wird es ja auch garnicht aufgerufen. Ist doch Quatsch. In jedem GUI-Programm unter Windows wird jedes Stückchen Code in einer Nachrichtenbehandlung ausgeführt. Jedenfalls alles, was nach Aufruf der Message-Loop kommt. Also, wo in deinem Programm wird der Code aufgerufen?



  • Hi, ja ich weis wie Windows API-Programme arbeiten (programmiere ja auch oft direkt in WinAPI), nur weil ich eben auch mit VCL viel mache wollte ich beides kombinieren (aus dem einfachen grund weil API-Calls um einiges schneller sind als VCL-Calls).

    Naja der Code wird aufgerufen wenn das OnKeyUp-Event ausgeführt wird und eine weitere Funktion "grünes Licht gibt" (nur wenn neue Sachen zum highlighten dazugekommen sind). Und die Funktionen WERDEN ausgeführt (geben sogar TRUE bzw. kein Fehler zurück, habe das geprüft).

    *grummel* 😉

    Gruss,
    code_pilot



  • Probier mal folgendes: validiere den gesamten Client-Bereich des RichEdit-Fensters, und dann invalidiere die Zeile, die der User bearbeitet hat.

    In deinem Code sehe ich, dass du die Zeile validierst, aber das kann nicht stimmen, oder?

    Wenn mein Kommentar voll daneben ist, bitte ich um Entschuldigung 🙂



  • code_pilot schrieb:

    Naja der Code wird aufgerufen wenn das OnKeyUp-Event ausgeführt wird

    Na also. Das wollt ich wissen. Leider kann ich so auch nicht weiterhelfen. Vielleicht wäre es gut, wenn du dein Problem nochmal genauer beschreiben würdest. Es flackert. OK. Aber WARUM flackert es? Hast du das schon herausgefunden?



  • Hi WebFritzi,

    ja es flackert, weil er, wenn er die ein neues Schlüsselwort in der Zeile findet, die komplette Zeile neu highlighted. Das funktioniert auch recht gut, da ja die Markierung ausgeschaltet und somit unsichtbar wird, wenn der Cursor die einzelnen Keywords/Strings markiert. Aber dieser Prozess veranlasst ja das RichEdit-Feld die Zeile neu zu laden. Und das flackert dann manchmal (andere Editoren haben so etwas nicht)

    Desweiteren ist mir aufgefallen, das wenn die Zeile etwas länger ist, und der Text über die Breite des RichEdits hinhausgeht das gesamte Feld extremst flackert, aus dem einfachen Grund das wenn der Highlighter ein neues Keyword findet ja die gesamte Zeile neu machen will. Dafür geht er ja an den Zeilen-Anfang und das RichEdit scrollt natürlich automatisch weg. Kann man das auch irgendwie ausschalten?

    Was ich mir aus dem ganzen erhoffe ist, das ich den einen Bereich, der gerade gehighlighted wird sperren kann, und er wirklich nur ein einziges mal alles neu zeichnet, wenn er mit dem highlighten fertig ist. Ich denke mal stark bei anderen Sourcecode-Editoren das die eine eigene Komponente oder so verwenden ... ich weis aber ehrlich gesagt nicht wie man ohne RichEdit ein Syntax-Highlighting schreiben soll ... ist bestimmt irrsinnig viel Arbeit 😞 ...

    Viele Grüsse,
    Jan Max

    PS: Es gibt ja im Netz Zig Syntax-Highlighting Komponenten für C++Builder, auch die Version 4 mit der ich arbeite. Aber irgendwie kann ich die Scheissdinger nicht installieren in meinen C++Builder, wohlgemerkt Standard Edition... 😞 naja ich würd das alles lieber selber schreiben ... wollt ich nurmal anmerken bevor jemand sagt "Benutz doch die Komponente XY". 🙄 :p



  • Ich hab es mir nicht genauer angeschaut, aber vielleicht hilft dir ja einer dieser Source-Codes weiter:
    - http://www.codeguru.com/Cpp/controls/richedit/syntaxhilighting/article.php/c5369
    - http://www.codeproject.com/richedit/htmlricheditctrlssl.asp



  • Jein. Kann damit nicht viel anfangen weil MFC sich stark von VCL unterscheidet. z.B. wüsste ich nicht wie ich den Scheiss code "mal eben" im C++Builder zum laufen bekommen könnte (MFC-Projekt Konverter von C++Builder: Vergesst es!). Erstmal wäre mein Problem wie ich das mit dem automatischen Scrollen kurzzeitig ausstellen kann, irgendwie mit SetWindowLong() aber wie?

    Grüsse,
    code_pilot 🙄



  • code_pilot schrieb:

    Erstmal wäre mein Problem wie ich das mit dem automatischen Scrollen kurzzeitig ausstellen kann

    WM_HSCROLL abfangen?

    case WM_HSCROLL:
      if( HilightningMode )
         return 0;
    


  • Hi Webfritzi,

    hmmm weist du vielleicht wo ich die WndProc beim C++ Builder finde? Die wird wo irgendwo tief in der VCL verankert sein. Anders kann man das nicht machen, oder?

    ➡ Bitte nicht ins C++Builder Forum verschieben, es geht hier um WinAPI...

    thx,
    code_pilot



  • code_pilot schrieb:

    Hi Webfritzi,
    hmmm weist du vielleicht wo ich die WndProc beim C++ Builder finde?

    Schau bitte in die BCB-Forum-FAQs. Da ist ein Artikel mit dem Namen "Windows-Messages mit dem BCB" oder so ähnlich.



  • Juhuuu ich habs jetzt so ziemlich gut hingekriegt.

    Habe jetzt eine WindowProc implementiert die, wenn er highlighted, einige Messages abfängt, und damit das flackern zu 90% veringert.

    void __fastcall TMain::NewWndProc(TMessage& Msg) 
    {
            if(onHighlight)
            {
                    switch(Msg.Msg)
                    {
                            case WM_PAINT:
                            case WM_ERASEBKGND:
                            case WM_NCPAINT:
                            case WM_PRINTCLIENT:
                            case WM_HSCROLL:
                            case WM_COMMAND:
                            case WM_SYSCOMMAND:
                            case WM_SETCURSOR:
                            case WM_SETREDRAW:
                            case WM_CLEAR:
                                    return;
                    }
            }
            OldWndProc(Msg); 
    }
    

    Ausserdem hab ich jetzt noch ein verstecktes Input-Feld hinter dem RichEdit, das den Fokus zugewiesen bekommt wärend er highlighted. Funkt wunderbar!

    Naja uch wenn das mit der einzelnen Zeile highlighten nix geworden ist, vielen dank an euch 🙂 :p


Anmelden zum Antworten