C ++ Builder — Как сохранить определенную часть текста TRichEdit RTF (c ++ codegear)

Я создаю функции поиска в существующем проекте C ++ CodeGear.

При двойном щелчке по слову фон всех вхождений этого слова окрашивается в зеленый цвет, как в notepad ++.

Прежде чем цвет будет применен, я сохраняю оригинал TRichEDit текст в TMemoryStream, чтобы иметь возможность вернуть исходный текст. Я восстановил цвет до нормального при нажатии на событие в TRichEdit,

Я хотел бы знать, есть ли способ сохранить каждое вхождение искомого слова в TMemoryStream или, возможно, с помощью сообщения, как EM_STREAMOUT?

Сейчас все отлично работает, но когда TRichEdit текст слишком велик, требуется много времени, чтобы перезагрузить большую заметку всего текста. Я думаю, что было бы лучше помнить только цвет слова, которое изменилось, а не перезагружать весь текст.

Я действительно новичок в программировании, любая помощь приветствуется. Скажите, если это не достаточно ясно.

Вот мой код, который работает и помещает цвет фона в вхождения слова:
`
void SearchInText :: searchWordInText (TRichEdit * reTextToSearch, AnsiString strWordToFind)
{
lstOccurrences-> Clear (); // сбросим lst

strTextToParse = AnsiReplaceText(strTextToParse, "\r\n", "\n");
int nPrevTagPos = 0;

int nTagPos = strTextToParse.AnsiPos(strWordToFind);

while (nTagPos != 0)
{
int nPosMin = nPrevTagPos + nTagPos - 1;

//List of all the occurrence in the TRichEdit with their position in the text
//It's not a list of int, but it POINT to adresses of INT so it's the same result =)
lstOccurrences->Add((TObject*) nPosMin);

//Change color of background when there is an occurrence
changeBgColor(reTextToSearch, strWordToFind, nPosMin +1, 155, 255, 155); //lime
bColorWasApplied = true;

nPrevTagPos = nPosMin + strWordToFind.Length();
strTextToParse = strTextToParse.SubString(nTagPos + strWordToFind.Length(), strTextToParse.Length());
nTagPos = strTextToParse.AnsiPos(strWordToFind);
}

}
`

0

Решение

Попробуйте что-то вроде этого:

#include <vector>

struct WordOccurrence
{
CHARRANGE Range;
CHARFORMAT2 OriginalFormat;
};

std::vector<WordOccurrence> WordOccurrences;

void TMyForm::HighlightWords(const String &WordToFind)
{
// disable the RichEdit's notification messages
int OriginalEventMask = RichEdit1->Perform(EM_SETEVENTMASK, 0, 0);

// disable the RichEdit's painting
RichEdit1->Perform(WM_SETREDRAW, FALSE, 0);

// save the RichEdit's current selection
CHARRANGE OriginalSelection;
RichEdit1->Perform(EM_EXGETSEL, 0, (LPARAM)&OriginalSelection);

// assign values to use while searching
int WordLen = WordToFind.Length();
int TextLen = RichEdit1->GetTextLen();
TSearchTypes SearchTypes = TSearchTypes() << stWholeWord << stMatchCase;

// find the first occurrence of the word
int StartPos = RichEdit1->FindText(WordToFind, 0, TextLen, SearchTypes);
while (StartPos != -1)
{
WordOccurrence Occurrence;
Occurrence.Range.cpMin = StartPos;
Occurrence.Range.cpMax = StartPos + WordLen;

// select the word
RichEdit1->Perform(EM_EXSETSEL, 0, (LPARAM)&Occurrence.Range);

// get the word's current formatting
Occurrence.OriginalFormat.cbSize = sizeof(CHARFORMAT2);
RichEdit1->Perform(EM_GETCHARFORMAT, SCF_SELECTION, (LPARAM)&Occurrence.OriginalFormat);

// save it for later
WordOccurrences.push_back(Occurrence);

// set the word's new formatting
CHARFORMAT2 NewFormat = Occurrence.OriginalFormat;
NewFormat.dwMask |= (CFM_COLOR | CFM_BACKCOLOR);
NewFormat.crTextColor = ...;
newFormat.crBackColor = ...;
RichEdit1->Perform(EM_SETCHARFORMAT, SCF_SELECTION, (LPARAM)&NewFormat);

// find the next occurrence of the word
StartPos = RichEdit1->FindText(WordToFind, Occurrence.Range.cpMax, TextLen - Occurence.Range.cpMax, SearchTypes);
}

// restore the RichEdit's original selection
RichEdit1->Perform(EM_EXSETSEL, 0, (LPARAM)&OriginalSelection);

// re-enable the RichEdit's painting
RichEdit1->Perform(WM_SETREDRAW, TRUE, 0);
RichEdit1->Invalidate();

// re-enable the RichEdit's notification messages
RichEdit1->Perform(EM_SETEVENTMASK, 0, OriginalEventMask);
}

void TMyForm::RestoreHighlightedWords()
{
// are there any occurrences to restore?
if (WordOccurances.empty())
return;

// disable the RichEdit's notification messages
int OriginalEventMask = RichEdit1->Perform(EM_SETEVENTMASK, 0, 0);

// disable the RichEdit's painting
RichEdit1->Perform(WM_SETREDRAW, FALSE, 0);

// save the RichEdit's current selection
CHARRANGE OriginalSelection;
RichEdit1->Perform(EM_EXGETSEL, 0, (LPARAM)&OriginalSelection);

// restore the formatting of each occurrence
for (std::vector<WordOccurrence>::iterator iter = WordOccurrences.begin();
iter != WordOccurrences.end();
++iter)
{
WordOccurrence &occurrence = *iter;

// select the word
RichEdit1->Perform(EM_EXSETSEL, 0, (LPARAM)&occurrence.Range);

// restore the word's original formatting
RichEdit1->Perform(EM_SETCHARFORMAT, SCF_SELECTION, (LPARAM)&occurrence.OriginalFormat);
}

// clear the list
WordOccurances.clear();

// restore the RichEdit's original selection
RichEdit1->Perform(EM_EXSETSEL, 0, (LPARAM)&OriginalSelection);

// re-enable the RichEdit's painting
RichEdit1->Perform(WM_SETREDRAW, TRUE, 0);
RichEdit1->Invalidate();

// re-enable the RichEdit's notification messages
RichEdit1->Perform(EM_SETEVENTMASK, 0, OriginalEventMask);
}
1

Другие решения

Итак, я наконец-то понял!
Я добавляю структуру в мой .h

Внутри я храню:
-позиция в TRichEdit найденного слова (nStart)
-длина слова (nLength)
-фактический текст и его RTF

struct sSelectedWord : public TObject
{
public:
__fastcall  ~sSelectedWord(); //destructor
int nStart;
int nLength;
TMemoryStream* memoRTF;
};

Вот код, который сохраняет RTF моего TRichEdit в моей структуре, которую я только что создал в .h.

void SearchInText::searchWordInText(TRichEdit* reTextToSearch, AnsiString strWordToFind)

{

lstOccurrences->Clear(); //reset lst
lstOccWithRTFMemo->Clear();
nCountOccurrence = 0;

strTextToParse = AnsiReplaceText(strTextToParse, "\r\n", "\n");
int nPrevTagPos = 0;

int nTagPos = strTextToParse.AnsiPos(strWordToFind);

while (nTagPos != 0)
{
int nPosMin = nPrevTagPos + nTagPos - 1;

//List of all the occurrence in the TRichEdit with their position in the text
//It's not a list of int, but it POINT to adresses of INT so it's the same result =)
lstOccurrences->Add((TObject*) nPosMin);
nCountOccurrence++;

//selected the word in the TRichEdit to save it with is RTF
reTextToSearch->SelStart = nPosMin;
reTextToSearch->SelLength = strWordToFind.Length();

TMemoryStream* memo = new TMemoryStream;
//important part!
rtfSaveStream(reTextToSearch,memo);

sSelectedWord* currentWord = new sSelectedWord;
currentWord->nStart = nPosMin;
currentWord->nLength = strWordToFind.Length();
currentWord->memoRTF = memo;

//Here we go, we add our new object in a list to be able to loop through it when we will want to reset the color
lstOccWithRTFMemo->Add(currentWord);
lstOccWithRTFMemo->Count;

//Change color of background when there is an occurrence
changeBgColor(reTextToSearch, strWordToFind, nPosMin +1, 155, 255, 155); //lime
bColorWasApplied = true;

nPrevTagPos = nPosMin + strWordToFind.Length();
strTextToParse = strTextToParse.SubString(nTagPos + strWordToFind.Length(), strTextToParse.Length());
nTagPos = strTextToParse.AnsiPos(strWordToFind);}

}

Важная часть была сделана с сообщением EM_STREAMOUT.

void SearchInText::rtfSaveStream(TRichEdit* re, TMemoryStream* memo)
{
// Create an instance of an EDITSTREAM that will contain:
// - The detail of our callback (StreamInCallback)
// - The TMemoryStream that contains the text to paste
EDITSTREAM es = {0};
ZeroMemory(&es, sizeof(es));
es.dwCookie = (DWORD_PTR) memo;
es.dwError = 0;
es.pfnCallback = &StreamSaveInCallback ; //pointer to function callBack

//To save the selected word of the TRichEdit, use STREAMOUT
re->Perform(EM_STREAMOUT, SF_RTF | SFF_SELECTION, (LPARAM)&es);
}
DWORD CALLBACK SearchInText::StreamSaveInCallback(DWORD_PTR dwCookie, LPBYTE pbBuff, LONG cb, LONG *pcb)
{
TMemoryStream *memo = (TMemoryStream*)dwCookie;

memo->Write(pbBuff, cb);
*pcb = cb;

return 0;
}

в pbuff, вы можете увидеть слово, которое вы выбрали в вашем TRichEdit с его RTF!

Надеюсь, что это поможет другим с той же проблемой! Спасибо тем, кто предложил код =)

0

По вопросам рекламы [email protected]