查找替换RTF格式的文本时对锁定文本的处理问题

基于.NET平台下的RichTextBox控件,封装了几乎所有的RTF文档的功能,可以完全基于此控件来编写一个强大的文本编辑器。也许你会想,RichTextBox控件的所有功能早就在M$ Word下实现了,而且人家的软件做的那么好,何必自己再去费神开发一个文本编辑器呢?其实,我们做程序并不都是为了实用性,通过做一个程序,哪怕只是个简单的计算器,也能学到不少知识的。何况,你可以用RichTextBox控件实现一个Word没有的功能——把一个特定的文本锁定使在解锁前无法对其进行任何更改~呵呵,你试过了吗?

你一定会很满意这个功能的,因为RichTextBox可以自行阻止用户对已锁定的文本进行任何更改,而你不需要再添加任何多余的代码(至少大多数情况下是如此的)。但是无论控件的功能封装得多好,它的智商还是有限,比如当你试图在你的软件里实现查找替换文本功能时,RichTextBox呆头呆脑的特性就暴露无遗了——一旦试图对已锁定的文本进行替换,文件的指针就会被强行退回到该被锁定的文本的前一个未锁定的字符上,然后继续下一步,继续再次被退回……于是你的程序就这样陷入了死循环中,就听见你那CPU狂转呀……

于是我们得亲自教导一下RichTextBox了,让它知道怎样聪明地处理锁定文本的替换问题。我们的目标是,能够让RichTextBox的被保护文本不被替换并保证指针顺利前进,并在替换完成后通知用户被替换的文本有多少处以及被保护而无法替换的文本有多少处。

下面是我提供的解决方案 : ->

If MyReplaceForm.ShowDialog = DialogResult.OK Then
'这两个变量记录要被替换的文本和替换成的文本
Dim FindText As String = MyReplaceForm.TextBoxFind.Text
Dim ReplaceText As String = MyReplaceForm.TextBoxReplace.Text
'此变量用于标记是否找到了被锁定的文本
Dim ProtectedThisTimeFound As Boolean
'此变量用于标记被替换的数量
Dim ReplaceCount As Integer
'此变量用于标记被保护的文本的数量
Dim ProtectedCount As Integer
'以下是替换时在文档内移动的指针
Dim NextPos As Integer
Dim ProbePos As Integer
Dim i As Integer
With RichTextBox
If .Find(FindText, FindStyle) = -1 Then
MessageBox.Show("未找到要被替换的内容!", "替换失败", MessageBoxButtons.OK, MessageBoxIcon.Exclamation)
MyReplaceForm.TextBoxFind.Focus()
Else
If FindText = ReplaceText Then
MessageBox.Show("做这样的替换是没有意义的!", "拒绝替换", MessageBoxButtons.OK, MessageBoxIcon.Exclamation)
MyReplaceForm.TextBoxReplace.Focus()
Else
'把指针指向开头
NextPos = 0
Do
'定位至第一个待替换点
'FindStyle是一个RichTextBoxFinds的全局变量,记录的是查找方式,例如严格区分大小写、全字查找等等。
NextPos = .Find(FindText, NextPos, FindStyle)
'开始使用探测指针,一一判断每个字符是否被锁定
ProbePos = NextPos
ProtectedThisTimeFound = False
For i = 0 To FindText.Length - 1
ProbePos = .Find(FindText.Substring(i, 1), ProbePos, RichTextBoxFinds.None)
If .SelectionProtected = True Then '看当前查找字符是否被锁定
'发现的话
ProtectedThisTimeFound = True '发现!
ProtectedCount += 1 '计数
If ProbePos + FindText.Length - i > RichTextBox.TextLength - 1 Then
'如果此字符串是文档末尾
Exit Do
Else
'不是的话
NextPos += (FindText.Length - i)
Exit For
End If
End If
Next i
If ProtectedThisTimeFound = False Then '如果循环探测下来发现该字符串未被锁定
NextPos = .Find(FindText, NextPos, FindStyle)
.SelectedText = ReplaceText
ReplaceCount += 1 '计数
End If
Loop Until .Find(FindText, NextPos, FindStyle) = -1
If ProtectedCount = 0 Then
MessageBox.Show("统统替换完毕。总共替换了" & CStr(ReplaceCount) & "处。", "替换成功", MessageBoxButtons.OK, MessageBoxIcon.Information)
Else
If ReplaceCount <> 0 Then
MessageBox.Show("统统替换完毕。总共替换了" & CStr(ReplaceCount) & "处。" & vbCrLf & vbCrLf & "仍存在" & CStr(ProtectedCount) & "处文字因被锁定而无法替换。", "替换完毕", MessageBoxButtons.OK, MessageBoxIcon.Information)
Else
MessageBox.Show("文中搜索到符合替换条件的文本共" & ProtectedCount & "处,但因被锁定而无法替换。", "统统替换无果", MessageBoxButtons.OK, MessageBoxIcon.Exclamation)
End If
End If
End If
End If
End With
End If

Published At
Categories with Web编程
Tagged with
comments powered by Disqus