0

我创建了一个读取文本文件的小程序。

在 RichEdit 中打开文本文件后,我想更改包含某个字符串的行的背景颜色,或者隐藏所有不包含该字符串的行。是否可以?

我试图搜索字符串,但我不知道如何做我所要求的。

function SearchText(Control: TCustomEdit; Search: string; SearchOptions: TSearchOptions): Boolean;
var
  Text: string;
  Index: Integer;
begin
  if soIgnoreCase in SearchOptions then
  begin
    Search := UpperCase(Search);
    Text := UpperCase(Control.Text);
  end
  else
    Text := Control.Text;

  Index := 0;
  if not (soFromStart in SearchOptions) then
    Index := PosEx(Search, Text, Control.SelStart + Control.SelLength + 1);
  if (Index = 0) and
      ((soFromStart in SearchOptions) or
       (soWrap in SearchOptions)) then
    Index := PosEx(Search, Text, 1);
  Result := Index > 0;
  if Result then
  begin
    Control.SelStart := Index - 1;
    Control.SelLength := Length(Search);
  end;
end;
4

2 回答 2

1

最好在将文本放入 RichEdit之前对其进行搜索和过滤。

但是,如果文本已经加载到 RichEdit 中,TRichEdit并且确实有FindText()可以使用的方法,则不应Text手动搜索其属性。例如:

function SearchText(Control: TCustomRichEdit; const Search: string; SearchOptions: TSearchOptions): Boolean;
var
  StartPos, SearchLen, Index: Integer;
  Options: TSearchTypes;
begin
  if soIgnoreCase in SearchOptions then
    Options := []
  else
    Options := [stMatchCase];

  if soFromStart in SearchOptions then
  begin
    StartPos := 0;
    SearchLen := Control.GetTextLen;
    Index := Control.FindText(Search, StartPos, SearchLen, Options);
  end else
  begin
    StartPos := Control.SelStart + Control.SelLength;
    SearchLen := Control.GetTextLen - StartPos;
    Index := Control.FindText(Search, StartPos, SearchLen, Options);
    if (Index = -1) and (soWrap in SearchOptions) then
      Index := Control.FindText(Search, 0, StartPos, Options);
  end;
  Result := Index <> -1;
  if Result then
  begin
    Control.SelStart := Index;
    Control.SelLength := Length(Search);
  end;
end;

话虽如此,设置线条的背景颜色或删除线条(没有“隐藏”线条的选项)相当简单。

给定任何字符索引,您可以向 RichEdit 发送EM_LINEFROMCHAR消息以确定字符出现的行索引。

然后,您可以使用该TRichEdit.Lines.Delete()方法从 RichEdit 中删除该行。

设置线条的背景颜色需要几个步骤:

  • 发送 RichEditEM_LINEINDEXEM_LINELENGTH消息以确定行的开始和结束字符索引。

  • 设置 RichEdit 的SelStartSelLength属性(或向 RichEdit 发送EM_EXSETSEL消息)。

  • 向 RichEdit 发送一条EM_SETCHARFORMAT消息,指定 SCF_SELECTION 标志并使用CHARFORMAT2记录来设置选择的背景颜色。

于 2022-01-29T20:43:40.410 回答
0

这是一个糟糕的 SO 问题,因为它有点像“请为我编写代码”。

自然的方法是找到问题的独立部分:

  1. 如何在 Delphi 中表示字符串(行)数组?

  2. 如何将 Delphi 中的文本文件加载到一些内存中的字符串数组中?

  3. 如何在Delphi中搜索字符串中的子字符串?

  4. 如何过滤 Delphi 内存中的字符串数组?[如果你知道 1 并且听说过循环,这很简单。有效地执行它会更有趣。]

  5. 如何填充 DelphiTRichEdit控件?

确实,如果您知道 1--5 的答案,那么做您想做的事就是微不足道的!

我现在可能看起来像一个脾气暴躁的老人,但我认为我确实有一个非常重要的观点,即如何解决编程问题。

无论如何,让我们一次解决一个问题:

  1. array of string今天的书面TArray<string>作品的老派方法。这是一个动态的字符串数组。由于 Delphi 动态数组是由编译器管理的,所以它们很方便,因为您不需要手动创建和释放它们。但是,它们有点低级,有时会被滥用。

    可能对您来说更好的选择是使用TStringList该类。

  2. IOUtils中,您会发现TFile.ReadAllLineswhich 采用文件名并将(文本)文件的内容作为字符串数组返回。

    或者TStringList.LoadFromFile,如果您有TStringList.

  3. 传统上,您将使用该Pos功能。但是今天你可以使用stringhelper: MyString.Contains()。显然,您需要决定是否要将大写字母和小写字母视为相同。

  4. 根据 3 中的测试,使用琐碎forfor in循环从原始数组填充第二个数组。

  5. 如果你有TStringList,只需使用TRichEdit.Lines.Assign.

将它们放在一起,使用相当聪明的string数组组合和TStringList

procedure TForm1.Button1Click(Sender: TObject);
begin

  var Lines := TFile.ReadAllLines('K:\test.txt');

  var FilteredLines := TStringList.Create;
  try

    for var Line in Lines do
      if Line.Contains('MyString') then
        FilteredLines.Add(Line);

    RichEdit1.Lines.Assign(FilteredLines);

  finally
    FilteredLines.Free;
  end;

end;
于 2022-01-29T19:16:46.830 回答