2009-09-03 43 views
2

好吧,这是一个唠叨的问题,我看不到一个明确的答案。 如何查找和标记单词的所有实例?标记一个单词的所有实例(德尔福,RichText)

我的意思是,我搜索一个词(说:人)。如果这个单词存在,我用richedit标记(使用红色或其他颜色)该单词的所有实例。如果我按Esc键,则会取消选择。

任何想法?

代码表示赞赏。

回答

2

wonderer,我写了这个代码,我希望这将是有用的:

Procedure MarkString(RichEdit:TRichEdit;strtomark : string); 
Var 
FoundAt : integer; 
begin 
    FoundAt:=RichEdit.FindText(strtomark,0,maxInt,[stWholeWord]); 
    while FoundAt <> -1 do 
    begin 
      RichEdit.SelStart := FoundAt; 
      RichEdit.SelLength := Length(strtomark); 
      RichEdit.SelAttributes.Style := [fsBold]; 
      RichEdit.SelAttributes.Color := clRed; 
      RichEdit.SelText :=strtomark; 
      FoundAt:=RichEdit.FindText(strtomark,FoundAt + length(strtomark),maxInt,[stWholeWord]); 
    end; 
end; 


Procedure UnMarkString(RichEdit:TRichEdit;strtomark : string); 
Var 
FoundAt : integer; 
begin 
    FoundAt:=RichEdit.FindText(strtomark,0,maxInt,[stWholeWord]); 
    while FoundAt <> -1 do 
    begin 
      RichEdit.SelStart := FoundAt; 
      RichEdit.SelLength := Length(strtomark); 
      RichEdit.SelAttributes.Style := []; 
      RichEdit.SelAttributes.Color := clBlack; 
      RichEdit.SelText :=strtomark; 
      FoundAt:=RichEdit.FindText(strtomark,FoundAt + length(strtomark),maxInt,[stWholeWord]); 
    end; 
end; 


MarkString(RichEdit1,'delphi'); //To Mark a string 

UnMarkString(RichEdit1,'delphi'); //To UnMark a string 

再见。

+0

太棒了!谢谢。现在我需要对它进行一些修改,以便在该字符串上设置背景颜色,并且我都已设置完毕。 – wonderer 2009-09-04 14:09:40

3

以下代码将在丰富的编辑控件中搜索给定单词(区分大小写)的所有匹配项,将字体颜色更改为红色,并最终恢复控件的原始选择(全部尽可能少的闪烁)希望):

procedure TForm1.FindWord(const AWord: string; AOptions: TSearchTypes); 
var 
    OrigSelStart, OrigSelLen: integer; 
    Start, Found: integer; 
begin 
    if AWord = '' then 
    exit; 

    OrigSelStart := RichEdit1.SelStart; 
    OrigSelLen := RichEdit1.SelLength; 

    RichEdit1.Perform(WM_SETREDRAW, 0, 0); 
    try 
    Start := 0; 
    Found := RichEdit1.FindText(AWord, Start, MaxInt, AOptions); 
    while Found <> -1 do begin 
     RichEdit1.SelStart := Found; 
     RichEdit1.SelLength := Length(AWord); 
     // TODO: save start of search match and original font colour 
     RichEdit1.SelAttributes.Color := clRed; 
     Start := Found + Length(AWord); 
     Found := RichEdit1.FindText(AWord, Start, MaxInt, AOptions); 
    end; 
    finally 
    RichEdit1.SelStart := OrigSelStart; 
    RichEdit1.SelLength := OrigSelLen; 
    RichEdit1.Perform(WM_SETREDRAW, 1, 0); 
    RichEdit1.Repaint; 
    end; 
end; 

现在你只需要到比赛保存加上原有的文本属性的列表,并使用这些信息在此列表中恢复所有对Esc新闻界的变化。然而,如果你认为这些匹配可能包含不同的字体样式,颜色等,这可能会非常难以正确执行。因此,我没有提供任何代码来保存格式,这取决于您的要求。

哦,确保在文本可以再次更改之前删除突出显示的匹配项,否则您将无法正确恢复原始文本格式。

+0

为了帮助避免闪烁并加快处理速度,您还应该使用EM_SETEVENTMASK消息禁用RichEdit的内部通知给自己,或者将其重新启用,这在此类文本处理过程中不是必需的。 – 2009-09-03 21:49:25

+0

@Remy:这[http://msdn.microsoft.com/en-us/library/bb774366(VS.85).aspx]建议RichEdit的默认掩码是ENM_NONE,所以我的印象可能是不必要的。尽管如此,尝试有意义,并且看起来EM_GETEVENTMASK将提供当前掩码,在使用EM_SETEVENTMASK(EM_NONE)并进行更新后可以保存该掩码以进行恢复。只是为了防止我错过了某些东西而放置这些东西。 – Argalatyr 2009-09-04 01:33:22

+0

只需对此进行跟踪 - 它看起来像VCL修改了事件掩码,这意味着当您按原样使用TRichEdit组件时,默认EM_NONE不适用:闪烁。为了减少闪烁 - 最好的解决办法似乎是按照Remy的建议将EM_SETEVENTMASK发送给none。这样做会产生相当好的结果。执行BeginUpdate/EndUpdate内的所有更新似乎更糟糕。在.Perform(WM_SETREDRAW,0,0).. .Perform(WM_SETREDRAW,1,0)内部进行更新.Repaint似乎也一样糟糕。似乎没有真正好的解决方案,这个控制不是双缓冲的。 – 2011-04-16 06:21:59