c++ - 如何保存 TRichEdit 文本 RTF 的特定部分(c++ codegear)

标签 c++ c++builder trichedit

我正在现有的 C++ CodeGear 项目中创建搜索功能。

当您双击一个单词时,所有出现该单词的背景都会像在 notepad++ 中一样涂成绿色。

在应用颜色之前,我将原始的 TRichEDit 文本保存在 TMemoryStream 中以便能够取回原始文本。我在 TRichEdit 中将颜色重置为正常的点击事件。

我想知道是否有一种方法可以将每次出现的搜索词保存在 TMemoryStream 中,或者可以使用 EM_STREAMOUT 之类的消息?

现在一切正常,但是当 TRichEdit 文本太大时,重新加载所有文本的大备忘录需要很长时间。我认为最好只记住更改的单词的颜色而不是重新加载所有文本。

我真的是编程的初学者,非常感谢任何帮助。如果不够清楚,请告诉我。

这是我的代码,它正在工作并将背景颜色添加到出现的单词中: ` void SearchInText::searchWordInText(TRichEdit* reTextToSearch, AnsiString strWordToFind) { lstOccurrences->清除();//重置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);
}

} `

最佳答案

尝试这样的事情:

#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);
}

关于c++ - 如何保存 TRichEdit 文本 RTF 的特定部分(c++ codegear),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26723403/

相关文章:

c++ - 当测试用例数为 1 时,为什么我的程序不接受输入而是打印一个新行?

c++ - 我可以使用 boost 图实现势场/深度优先避障方法吗?

c++ - 为什么在常量引用的 auto 关键字中忽略 const

Delphi RichEdit,获取任意行的 y 像素开始

delphi - Delphi:通过滚动滚动在TRichEdit中的中心特定线

c++ - 输入与输出迭代器 - 命名约定

visual-c++ - 将 Visual C++ 项目通用转换为 Borland C++ Builder 的应用程序

popup - C++ Builder 6 TreeView 的项目和子项目上有不同的弹出菜单,而空白区域上没有弹出菜单

c++ - 动态创建的复选框的事件处理程序

html - 为 TRichEdit 添加真正的超链接支持