Positionserkennung im TRichEdit



  • Hallo

    ich hoffe ihr könnt mir bei einem kleinen Problem helfen:
    Ich bin dabei, ein Chatprogramm zu schreiben, was auf eine spezielle Community ausgerichtet ist. Dabei möchte ich ein TRichEdit, das als Ausgabe des geschriebenen fungiert, die Benutzernamen Fett markieren. Klingt ja an sich nicht weiter schwierig, nur ist die Erkennung der Positionen, wie ich sie mache, leider nicht ganz fehlerfrei.

    Hier einmal der Code:

    GetLocalTime(&Main->st);
     GetTimeFormat(LOCALE_USER_DEFAULT, 0, &Main->st, NULL, Main->sz,
      (sizeof(Main->sz) / sizeof(Main->sz[0])));
     AnsiString Time = Main->sz;
     aspMessage      = RowHandling(aspMessage, "get");
     Main->Chat->Dialog[aspSender]->treChatOutput->SelStart =
         Main->Chat->Dialog[aspSender]->treChatOutput->GetTextLen();
     Main->Chat->Dialog[aspSender]->treChatOutput->SelAttributes->Color = clBlack;
     Main->Chat->Dialog[aspSender]->treChatOutput->Lines->Add
         ("<" + Time + "> " + aspSender + ": " + Main->API->DecodeFromSPiN
      (aspMessage));
     // Den Nickname Fett markieren
     int ilDoppelPunktPos   = 0;
     int ilNicknameStartPos = 0;
     for (int i = Main->Chat->Dialog[aspSender]->treChatOutput->Text.Length();
      i > 0; i--)
     {
      if (Main->Chat->Dialog[aspSender]->treChatOutput->Text.SubString(i, 1) == ":")
      {
       ilDoppelPunktPos = i;
      }
      if ((Main->Chat->Dialog[aspSender]->treChatOutput->Text.SubString(i,
         1) == " ") && (ilDoppelPunktPos != 0))
      {
       ilNicknameStartPos = i;
      }
      if ((ilNicknameStartPos != 0) && (ilDoppelPunktPos != 0))
      {
       Main->Chat->Dialog[aspSender]->treChatOutput->SelStart =
           ilNicknameStartPos + 1;
       Main->Chat->Dialog[aspSender]->treChatOutput->SelLength =
           ilDoppelPunktPos - ilNicknameStartPos;
       break;
      }
     }
    

    Also die ersten Zeilen sind einfach und funktionieren auch. Jemand schickt eine Nachricht, sie wird in schwarzer Schrift (die eigenen Nachrichten in Grauer Schrift) eingefügt.
    Nach dem Kommentar kommt dann die Suche nach dem Nicknamen. Ich ermittele die Positionen, und markiere dann die entsprechende Position Fett.
    Meines erachtens nach müsste die Positionsermittlung stimmen, trotzdem markiert er mir nachher die falsche Stelle. (Das Fett markieren ist derzeit im Code noch nicht enthalten, fällt mir gerade auf).

    Mal ein Screenshot:
    http://brekerbohm.net/dialog.png

    Das Kuriose ist, dass mit jeder weiteren Zeile die eingefügt wird, die Markierung immer weiter eins nach rechts rutscht. D.h. bei der nächsten Zeile würde die Markierung erst bei dem zweiten l anfangen.

    Meine Vermutung liegt darin, dass ich dort irgendwelche Steuerzeichen drin hab, die irgendwo und irgendwie nicht berücksichtigt werden, ich hab nur leider keine Ahnung, wie ich das mit der Methode beheben könnte.
    Was mir noch einfällt wäre, dass ich den Nickname vorher im AnsiString raussuche und formatiere, allerdings habe ich keine Ahnung, ob es überhaupt möglich wäre, den AnsiString so vorzubereiten, dass er komplett korrekt formatiert in das RichEdit eingefügt wird.

    Ich hoffe ihr könnt mir ein klein wenig aushelfen ! 🙂

    Gruß,
    Zero91



  • Habe damals TRxRichEdit genommen auf nem BCB6, weil der auch Grafiken / Smileys einfügen konnte. TRxRichEdit ist dann mit in die Jedi Komponenten gewandert.

    Es gibt auch zu deinem Fall viele TRxRichEdit Beispiele über google zu finden.

    Viel Erfolg & Spaß



  • Ok, hab gefunden wie ich die Smileys im nachhinein durch ein Bild ersetze.

    setRichEditTextColor(frmConfig->ShapePartnerText->Brush->Color);

    smileySearchPos = RichEdit->Text.Length();
    smileySearchPosEnd = smileySearchPos + AnsiString(msg).Length();

    RichEdit->Lines->Add(AnsiString(msg));

    replaceNewTextWithSmileys(smileySearchPos, smileySearchPosEnd);

    void TfrmChat::setRichEditTextColor(TColor color)
    {
    CHARFORMAT FormatNormal;
    memset(&FormatNormal, 0, sizeof(FormatNormal));
    FormatNormal.cbSize = sizeof(FormatNormal);
    FormatNormal.dwMask = CFM_COLOR | CFM_BOLD;
    FormatNormal.crTextColor = color;
    FormatNormal.dwEffects = 0;
    RichEdit->Perform(EM_SETCHARFORMAT, SCF_SELECTION, (LPARAM)&FormatNormal);
    }

    void TfrmChat::replaceNewTextWithSmileys(int startpos, int endpos)
    {
    smileyToIndexMap_t::iterator iter;
    AnsiString curSmiley;
    int curSmileyIndex;
    CHARRANGE range;
    int foundIndex;
    int lastFoundIndex;

    Graphics::TBitmap *bmp = new Graphics::TBitmap();
    bmp->Width = 18;
    bmp->Height = 18;
    bmp->PixelFormat = pf24bit;
    bmp->Canvas->Brush->Color = clWhite;
    bmp->Canvas->Pen->Color = clWhite;

    for (iter = smileyIndexes.begin(); iter != smileyIndexes.end(); iter++)
    {
    curSmiley = iter->first;
    curSmileyIndex = iter->second;

    range.cpMin = smileySearchPos;
    range.cpMax = smileySearchPosEnd;

    while( (foundIndex = FindText(RichEdit->Handle, curSmiley.c_str(), &range)) > -1)
    {

    bmp->Canvas->Rectangle(0,0,18,18);
    ImageListSmileys->GetBitmap(curSmileyIndex, bmp);

    Clipboard()->Open();
    Clipboard()->Clear();
    Clipboard()->Assign(bmp);
    Clipboard()->Close();

    RichEdit->ReadOnly = false;
    RichEdit->SelStart = foundIndex;
    RichEdit->SelLength = curSmiley.Length();
    SendMessage(RichEdit->Handle, WM_PASTE, 0, 0);
    RichEdit->ReadOnly = true;

    range.cpMin = foundIndex + 1;
    }
    }

    delete bmp;
    }

    int FindText(HWND hEdit, char *Text, CHARRANGE *Range) {
    ::FINDTEXTEX TextSearch;
    int MatchCount = 0;
    int MatchFound;

    TextSearch.chrg = *Range;
    TextSearch.lpstrText = Text;
    TextSearch.chrgText.cpMin = -1;

    MatchFound = SendMessage(hEdit, EM_FINDTEXTEX, /*FR_WHOLEWORD*/ (WPARAM)FR_DOWN, (LPARAM) &TextSearch);

    return MatchFound;
    }

    Damit solltest du es hinbekommen.

    GL & HF!



  • Okay, ich lade gerade mal die Jedi Komponenten runter und schaue sie mir dann an.
    Aber wäre das nicht eigentlich nur ein Ausweichen auf eine andere Komponente, und hoffen, bzw. es im Endeffekt auch wissen, dass diese einfach nur anders arbeitet?
    Im Endeffekt wird es wahrscheinlich für den Anwender keinen UNterschied machen, elche Komponente ich da genutzt habe, aber ich persönl. würd schon gern verstehen können, wo genau da das Problem bei der bestehenden Borland Komponente oder eben bei mir ist... ^^
    Deine vorgeschl. Komponente schaue ich mir aber auch auf jeden Fall mal an. 🙂



  • Ich habs jetzt ein wneig anders gemacht.
    Und zwar hab ich es direkt auf der RTF Ebene geändert.
    Den ganzen Kram mit Formatierung in ein stringstream geladen, das geändert was ich wollte, und wieder neu eingefügt. Also überschrieben.
    Macht genau das was ich wollte. 🙂
    Mit den Komponenten konnte ich leider gar nicht so viel Anfangen, hab mich aber auch nicht sehr da rein gefuchst gehabt.


Log in to reply