RichEdit Zeile einfügen



  • Aus der Borland Hilfe:

    AnsiString& __fastcall Insert(const AnsiString& str, int index);

    Was glaubst du wird da zurückgegeben?

    -junix



  • Ach was @most, ich nehm's doch gar nicht persönlich 😉 . Hatte nur irgendwie gedacht, von dir kommen auch mal ein paar Überlegungen. Deine Worte klingen so, als wartest du nur. Aber ich glaub, du siehst gar nicht, was passiert. Die Aufgabe kann so gar nicht gelingen... wegen dem VK_RETURN!

    Ole, Problem erkannt = Problem gebann.

    Damit es perfekt wird, brauch ich den
    SubString(RE->SelStar,[ZeilenEnde][bis zum nächsten \n]).

    Aber möglichst ohne Schleifenarbeit. Ist das realisierbar? Hab keinen Weg gefunden. Wo sind die String->Koryphäen? 🙂



  • Denkfehler.

    SubString(RE->SelStar,ZeilenEnde) wird gebraucht.



  • War doch nicht so schlimm mit der Schleife, als ich erst gedacht hatte. Aber fertig ist es noch nicht. In der 1. Zeile würde Text zerstört. Hab keinen Plan, also hier normales entern.

    @Junix, Insert kann nur mit Zeichen gehen, Leerzeichen werden durch das VK_RETURN gelöscht (frag mich nicht warum, sag mir's lieber 🙂 ).

    Roger, \n wird gezielt eingesetzt, VK_RETURN wird am Schluß gelöscht.

    Daher Einschränkung: Function nur im OnKeyPress möglich.

    Keine Leerzeichen am Zeilenanfang sondern Tab's? NULL Problemo.

    Cursor nicht am Zeilenende sondern irgendwo in der Zeile? Wird berücksichtigt.

    Bleiben noch Wünsche offen? a.) 1.Textzeile, b.) Function muß ein- und ausschaltbar gemacht werden oder VK_BACK bemühen. c.) FAQ? Sicher nicht. Sowas schreibt man in 5 min :p d.) ?

    Code? Wenn's unbedingt sein muß...:

    void __fastcall TChild::REKeyPress(TObject *Sender, char &Key)
    {
      if (Key == VK_RETURN)
      {
        int line_nr = RE->CaretPos.y, lz = 1, start, i;
        String line_RE = RE->Lines->Strings[line_nr], lzs = "";
        // Function würde Text löschen
        if (line_nr == 0)
          return;
        // Leerzeichen am Zeilenanfang
        else if (line_nr > 0 && RE->Lines->Strings[line_nr].SubString(0,1) == ' ')
        {
          // wieviele Leerzeichen?
          for (lz; lz <= line_RE.Length(); lz++)
            if (line_RE[lz] != ' ')
              break;
          // wenn Leerzeichen am Anfang
          if (lz > 1)
          {
            // LeerzeichenString für die EnterZeile zusammenbauen
            for (i=0;i<lz-1;i++)
              lzs = lzs + " ";
            // aktuelle ZeilenNr erfassen
            line_nr = RE->CaretPos.y;
            // CursorPosition erfassen
            start = RE->SelStart;
            // Cursor ans Zeilenende jagen und wieder auf start zurücksetzen
            int check = RE->CaretPos.y;
            while (RE->CaretPos.y < check)
              RE->SelStart++;
            // OperationsEndpunkt erfassen
            int end = RE->SelStart;
            RE->SelStart = start;
            // String für die EnterZeile zusammensetzen
            RE->Lines->Strings[line_nr] =
                RE->Lines->Strings[line_nr].SubString(0,RE->CaretPos.x)+
                "\n"+lzs+RE->Lines->Strings[line_nr].SubString(RE->CaretPos.x+1,
                end-RE->CaretPos.x);
            // Cursor in der EnterZeile hinter die Leerzeichen plazieren
            RE->SelStart = start + lz;
            // oben haben wir \n befohlen, VK_RETORN auf 0 setzen
            Key = 0;
          }
        }  
        // dto. für TABstobs am Zeilenanfang
        else if (line_nr > 0 && RE->Lines->Strings[line_nr].SubString(0,1) == '\t')
        { 
          for (lz; lz <= line_RE.Length(); lz++)
            if (line_RE[lz] != '\t')
              break;
          if (lz > 1)
          {
            for (i=0;i<lz-1;i++)
              lzs = lzs + "\t";
            line_nr = RE->CaretPos.y;
            start = RE->SelStart;
            int check = RE->CaretPos.y;
            while (RE->CaretPos.y < check)
              RE->SelStart++;
            int end = RE->SelStart;
            RE->SelStart = start;
            RE->Lines->Strings[line_nr] =
                RE->Lines->Strings[line_nr].SubString(0,RE->CaretPos.x)+
                "\n"+lzs+RE->Lines->Strings[line_nr].SubString(RE->CaretPos.x+1,
                end-RE->CaretPos.x);
            RE->SelStart = start + lz;
            Key = 0;
          }
        }
      }  
    }
    

    Ob das ganze auch kürzer geht?

    [ Dieser Beitrag wurde am 19.05.2003 um 10:23 Uhr von Jansen editiert. ]



    if (line_nr == 0)
          return;
    

    Was soll das denn? Demnach würden Leerzeichen am Anfang der ersten Zeile ignoriert!?

    Text1
    __Text2
    __Text3
    

    Wenn jetzt der Cursor hinter Text2 gesetzt und Enter gedrückt wird entsteht vor Text3 eine zusätzliche, ungewollte Leerzeile (Unterstriche = Leerzeichen).

    1. Den Leerzeichen-String kannst du ja wohl gleich in der ersten Leerzeichen-Testschleife zusammenbauen.


    1. Hab es doch begründet. Bezieh ich die 1.Textzeile mit ein, wird der Text hinter den Cursor gelöscht, anstatt in die entstandene Zeile übernommen zu werden. Hab keinen Plan, wie das zu vermeiden wäre.

    2. Nachdem sogar der ich das soweit hinbekommen hat, trau ich jedem Spieler zu, daß er die Function für jedes beliebige Zeichen erweitern kann.
      lzs = ""; initialisiert, da läßt sich für den Zeilenanfang jedes Zeichen einstellen.

    3. Danke @Jansen. Da es so geht und richtig ist, werte ich meinen Ansatz sogar als diletantisch.

    for (lz; lz <= line_txt.Length(); lz++)
            if (line_txt[lz] != ' ')
              break;
            else
              lzs = lzs + " ";
    

    der oben declarierte int i entfällt.

    1. @Jansen, ich geb mich keinerlei Illusionen hin. Ohne dein Basisgerüst wär ich chancenlos gewesen oder hätte sehr lange dran gekaut. Ich dank dir sehr. Die Aufgabe war / ist teilweise immer noch herrlicher Lehrstoff zum Üben der Methoden von AnsiString. - Hat abgesehen vom anfänglichen Drüselkopf Spaß gemacht. 🙂

    2. Mein Notepad hat nun eine weitere interessante Function - die später auch gut in eine rtf-Textverarbeitung paßt... falls ich sowas mal bau.



  • zu 1) Dass du das begründet hast ändert doch nichts an dem Umstand, dass die Lösung damit untauglich ist. Oder willst du dem Benutzer vorschreiben, wo er automatische Einrückungen erwarten darf und wo nicht? Da hilft also nur weiter "drüseln", im BCB-Editor funktioniert's ja auch. 😉

    zu 2) Ich verstehe nicht so recht, was deine Erklärung mit dem von mir gezeigten "Bug" zu tun hat. Und wenn es um universelle Lösung für beliebige Zeichen geht dann sollte das Ganze nach Möglichkeit auch ohne doppelten Code auskommen.

    Du hast die FAQ in's Spiel gebracht, also sollte die Lösung auch einigermassen wasserdicht sein. 🙂



  • zu1) Ich begründe nur meine Unfähigkeit, @Jansen. 'n kleicher Tip aus der Runde, vielleicht auch mal 'ne Codezeile, ansonsten heißt es erst mal Suchen. Ich find keinen Anhaltspunkt.

    zu2) Bei mir wirkt sich das nicht als Bug aus. Ich erhalte keine zusätzliche Leerzeile. Die Bedingungen sind nicht true, VK_RETURN wirkt ganz normal. Man müßte dann die Zeile manuell mit dem Unterstrich beginnen.

    Hast Recht. Doppelter Code ist sowieso nie sinnvoll. Werd nachher gleich drangehen.

    Über '_', '-' (vielleicht auch '+', '*', was käme noch infrage?)) hab ich mir mal Gedanken gemacht. Das entscheidende Kriterium dürfte sein, daß direkt davor ein '\n' zu sein hat, wenn das Zeichen eine Aufzählung einleiten soll. Bei vorangestellten ' ' oder '\t' wird man aber auch ein '\n' direkt davor sicher nicht prüfen brauchen.

    -Oh ich armer ich. 😉 Mußte grad dran denken, daß solche Textausrichtungen noch fehlen. Sonst hätte ich die FAQ gar nicht erwähnt. Für mich hier lokal mach ich da sowieso keinen Unterschied. Nur reifer Code ist akzeptabler Code. Was heute nicht gelingt, wird morgen wieder in Angriff genommen. Für die "Vitrine" kommen dann nur noch die Kommentare dazu.

    Gebraucht wird also auf jeden Fall die Lösung für die erste Zeile.



  • Ole, ich wär dann soweit. '+', '-' und '_' werden nach '\t' oder ' ' oder am Zeilenanfang nach '\n' miterfasst. Wenn ich noch den '*' mit aufnehmen soll, werden die Bedingungsketten recht lang. Weiß nicht, ob sowas Nachteile haben kann.

    Wer stiftet die Lösung für die 1. Zeile? 🙂 Text nach Cursor darf nicht abgeschnitten werden. Ich find keinen Hinweis, warum es das macht.



  • 😕 Ich komm mit deinem Code nicht klar. Weil er bei mir nicht die Eigenschaften zeigt die du hier berichtest. Er fügt 2 Zeilen ein nachdrücken der Enter Taste , wobei in der ersten Zeile kurzzeitig der Zeilenvorschub AMrkiert sichtbar ist. Ich kuck mir das morgen nochmal genauer an aber zurzeit hinke ich irgendwie hinterher?



  • Nanu? Ausnahmslos Spezalisten an Bord? 😉

    Also ohne Code für die erste Zeile = keine FAQ:

    <snip>siehe nachfolgende Beiträge</snip>

    [ Dieser Beitrag wurde am 20.05.2003 um 15:54 Uhr von Jansen editiert. ]



  • *Au_weia*! Den Code aus meinem letzten Beitrag bitte meistbietend verbrennen - gröbste Schnitzer. 🙄

    Ich glaub, jetzt bin ich erst mal zufrieden. Sind noch Bugs drin?:

    <snip>siehe nachfolgende Beiträge</snip>

    [ Dieser Beitrag wurde am 20.05.2003 um 15:55 Uhr von Jansen editiert. ]



  • Hab vorhin gemerxt, wenn ich den Cursor vorn in einer Zeiel ansetz und einen Zeilenumbruch schaffe, dann auf
    *RE->Lines->Strings[line_nr-1].AnsiLastChar() == '\n'
    prüfe, bekomm ich eine Zugriffsverletzung. Tatsächlich ist dann das letzte sichtbare Zeichen der vorangegangenen Zeile der AnsiLastChar(). Mein Vorhaben, nur erkennbar gewollte Aufzählungszeichen zu akzeptieren, dürfte damit gescheitert sein.

    Hab diese Prüfungen und damit auch einige if-Zweige weggelassen. Jetzt kann ich keinen Bug mehr feststellen.

    Ich sollte diese Version nochmal posten. Aber die vielen fast gleichen Versionen hinternander, da blickt niemand durch. Ich will auch nicht den Thread total verbomben. Soll ich es posten und einer der Mods wär ggf. so freundlich, die störenden Beiträge incl. diesem zu löschen?



  • Jo, mach mal. Aber nimm doch bitte die C++Code-Tags.



  • Ole, das war's. Bei mir arbeitet die Function jetzt sauber. Hier noch mal der Code + Function für die Wechselschaltung (bei mir) über MenuItem:

    void __fastcall TChild::EinrueckClick(TObject *Sender)
    {
      Einrueck->Checked = !Einrueck->Checked;
      if (Einrueck->Checked)
        Einrueck->Tag = 1;
      else
        Einrueck->Tag = 0;
    }
    //---------------------------------------------------------------------------
    void __fastcall TChild::REKeyPress(TObject *Sender, char &Key)
    {
      if (Key == VK_RETURN && Einrueck->Tag == 1)
      {
        int line_nr = RE->CaretPos.y, lz = 1, start;
        String line_txt = RE->Lines->Strings[line_nr], lzs = "";
        // Auf erstes Zeichen prüfen
        if (RE->Lines->Strings[line_nr].SubString(0,1) == ' ' ||
            RE->Lines->Strings[line_nr].SubString(0,1) == '\t' ||
            RE->Lines->Strings[line_nr].SubString(0,1) == '+' ||
            RE->Lines->Strings[line_nr].SubString(0,1) == '-' ||
            RE->Lines->Strings[line_nr].SubString(0,1) == '_')
        {
          // Anzahl der Zeichen in der Zeile ermitteln
          for (lz; lz <= line_txt.Length(); lz++)
          {
            // aussteigen, wenn am Zeilenanfang kein zu referierendes Zeichen
            if ((line_txt[lz] != ' ' && line_txt[lz] != '\t' &&
                line_txt[lz] != '+' && line_txt[lz] != '-' &&
                line_txt[lz] != '_') || lz > RE->CaretPos.x)
              break;
            // String für Zeilenanfang zusammenstellen
            else if (line_txt[lz] == ' ')
              lzs = lzs + " ";
            else if (line_txt[lz] == '\t')
              lzs = lzs + "\t";
            else if (line_txt[lz] == '+')
              lzs = lzs + "+";
            else if (line_txt[lz] == '-')
              lzs = lzs + "-";
            else if (line_txt[lz] == '_')
              lzs = lzs + "_";
          }
          // mindestens 1 zu wiederholendes Zeichen gefunden?
          if (lz > 1)
          {
            // ZeilenNummer aktuell ermitteln
            line_nr = RE->CaretPos.y;
            // CursorPosition merken
            start = RE->SelStart;
            // Aus aktueller Zeile 2 Zeilen machen:
            // LeerString + String hinter Cursor in neue Zeile
            RE->Lines->Strings[line_nr] =
                RE->Lines->Strings[line_nr].SubString(0,RE->CaretPos.x)+
                "\r\n"+lzs+RE->Lines->Strings[line_nr].SubString(RE->CaretPos.x+1,
                line_txt.Length()-RE->CaretPos.x+1);
            // Cursor hinter LeerzeichenString positionieren
            RE->SelStart = start + lz +1;
            // '\n' wurde eingearbeitet, Key löschen
            Key = 0;
          }
        }
      } // war keine Bedingung true, löst VK_RETURN Zeilenwechsel aus
    }
    


  • Sorry @Jansen, hab erst nach dem Posten deinen Hinweis auf die C++-Codetags gesehen. Ich blick auf den Text, seh im Augenwinkel das Wort "Code" und drück drauf - *Zerstreuter Prof*. Ich gelobe Besserung. 🙄

    @mosta, sorry für das Durcheinander. Da waren ein paar Haken und Ösen, ein paar unverstandene Sachen, Überraschungen, Neuland, teilweise dünne Scheibe :p . 🙄 Dafür sollte es jetzt aber blitzsauber laufen. Hab jedenfalls keinen krummen Hund mehr entdeckt.



  • Bei mir bearbeited er Key=0 nicht er setzt einfach eine neue Zeile ein. Was muss ich für Einstellung an der RichEdit vornehmen.



  • Bist du im OnKeyPress? In anderen Ereignissen kannst du nicht Key=0 setzen. Hatte ich aber klar geschrieben, als ich die Doppelfunction gepostst hab.



  • Oh, ich hatte KeyDown 🙄


Anmelden zum Antworten