如何在richtextbox中查找相反的文本?

时间:2016-01-17 20:56:14

标签: c# search find richtextbox reverse

我试图制作一个搜索代码,允许您在两个方向(右侧和左侧)查找文本。我已经制作了一个代码,可以向右搜索文本,但不是向左搜索。

我尝试做的例子:

  

example1 example2 example3 example4

让我们说我找到了' example3' (向右走)现在我需要找到example2(向左)我将如何制作该代码?

问题: 如何制作一个搜索文本向左(反向)的代码?

以下是我尝试搜索左侧文字的示例:

{{1}}

4 个答案:

答案 0 :(得分:0)

一种简单的方法是向后迭代并检查当前字符串是否包含给定的字符串:

public static class Extension{
    public static bool ReverseContains(this string container, string token)
    {
        if (string.IsNullOrEmpty (container) || string.IsNullOrEmpty (token)) 
        {
            return false;       
        }
        int offset = container.Length - token.Length;
        string start = container.Substring (offset);
        for (int i = offset - 1; i >= 0; i--) 
        {
            start = container[i] + start;
            if(start.Contains(token)){ return true;}
        }
        return false;
    }
}

如果容器包含令牌,则返回true。搜索将从最后开始。

不考虑大写/小写,因此在“一堆单词”中找不到“单词”。如果需要,您必须添加一个额外的参数以使其全部小写。

string str = "My string with many words to be found";
string wordToFind = "words";

bool result = str.ReverseContains(wordToFind);

答案 1 :(得分:0)

我有同样的需要。这是一个工作的WinForms应用程序进行演示。解决此问题的灵感来自CodeGuru上的线程"RichTextBox reverse find"

在我的演示中,实时出价工具已预加载了文本,并且是只读的,即我没有尝试解决与使用可编辑的实时出价工具实现向前和向后查找相关的问题。

demo program screen shot

该表单具有以下控件:

  • Forms.Button,名为objButtonFind。文字=“查找”
  • 名为objTextBoxSearchWord的Forms.TextBox
  • Forms.Checkbox名为objReverse。文字=“反向”
  • Forms.Checkbox名为objCheckBoxMatchCase。文字=“匹配情况”
  • Forms.Checkbox名为objCheckBoxWholeWord。文字=“整个单词”
  • Forms.Lable名为label1。文字=“ RTB开始位置”
  • 名为objTextBoxStartPos的Forms.TextBox。
  • 从Forms.RichTextBox派生的ClsRichTextBox类

ClsProgram.cs

using System;
using System.Windows.Forms;

namespace RichTextBoxFindWithReverse
{
    static class ClsProgram
    {
        /// <summary>
        /// The main entry point for the application.
        /// </summary>
        [STAThread]
        static void Main()
        {
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            Application.Run(new ClsFormMain());
        }
    }

    /// <summary>
    /// https://stackoverflow.com/questions/1550293/stopping-textbox-flicker-during-update
    /// </summary>
    public static class ControlExtensions
    {
        [System.Runtime.InteropServices.DllImport("user32.dll")]
        public static extern bool LockWindowUpdate(IntPtr hWndLock);

        public static void Suspend(this Control control)
        {
            LockWindowUpdate(control.Handle);
        }

        public static void Resume(this Control control)
        {
            LockWindowUpdate(IntPtr.Zero);
        }
    }
}

ClsFormMain.cs

using System;
using System.Windows.Forms;

namespace RichTextBoxFindWithReverse
{
    public partial class ClsFormMain : Form
    {
        public ClsFormMain()
        {
            InitializeComponent();
            objRichTextBox.SelectionDataIsInteresting += ObjRichTextBox_SelectionDataIsInteresting;
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            objRichTextBox.Text = "cat\ndog\nsnail\nOtter\ntigerelephant\ncatcatcat\ncatcatdog\ncatcatsnail\ncatcatOtter\ncatcattiger\ncatcatelephant\ncatdogcat\ncatdogdog\ncatdogsnail\ncatdogOtter\ncatdogtiger\ncatdogelephant\ncatsnailcat\ncatsnaildog\ncatsnailsnail\ncatsnailOtter\ncatsnailtiger\ncatsnailelephant\ncatOttercat\ncatOtterdog\ncatOttersnail\ncatOtterOtter\ncatOttertiger\ncatOtterelephant\ncattigercat\ncattigerdog\ncattigersnail";
            objButtonFind.Enabled = false;
            objReverse.Enabled = false;
            objCheckBoxMatchCase.Enabled = false;
            objCheckBoxWholeWord.Enabled = false;
        }

        private void ObjTextBoxSearchWord_TextChanged(object sender, EventArgs e)
        {

            if (objRichTextBox.Text.Length > 0 && objTextBoxSearchWord.Text.Length > 0)
            {
                objButtonFind.Enabled = true;
                objReverse.Enabled = true;
                objCheckBoxMatchCase.Enabled = true;
                objCheckBoxWholeWord.Enabled = true;
            }
            else
            {
                objButtonFind.Enabled = false;
                objReverse.Enabled = false;
                objCheckBoxMatchCase.Enabled = false;
                objCheckBoxWholeWord.Enabled = false;
            }
        }

        private void ObjButtonFind_Click(object sender, EventArgs e)
        {
            string options = "";

            if (!objCheckBoxMatchCase.Checked && !objCheckBoxWholeWord.Checked)
            {
                options = "Don't match case.\nMatch on partial word or whole word.";
            }
            else if (!objCheckBoxMatchCase.Checked && objCheckBoxWholeWord.Checked)
            {
                options = "Don't match case.\nMatch on whole word only.";
            }
            else if (objCheckBoxMatchCase.Checked && !objCheckBoxWholeWord.Checked)
            {
                options = "Match case.\nMatch on partial word or whole word.";
            }
            else //(objCheckBoxMatchCase.Checked && objCheckBoxWholeWord.Checked)
            {
                options = "Match case.\nMatch on whole word only.";
            }

            bool found = objRichTextBox.FindTextCustom(objTextBoxSearchWord.Text, objReverse.Checked, objCheckBoxMatchCase.Checked, objCheckBoxWholeWord.Checked);

            if (!found)
            {
                System.Windows.Forms.MessageBox.Show(string.Format("Can't find '{0}'.\n\nYour options:\n\n{1}", objTextBoxSearchWord.Text, options), "RichTextBox Find With Reverse", MessageBoxButtons.OK, MessageBoxIcon.Information);
            }
        }

        /// <summary>
        /// Display rich text box selection data
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void ObjRichTextBox_SelectionDataIsInteresting(object sender, ClsRichTextBoxSelectionArgs e)
        {
            objTextBoxStartPos.Text = e.SelectionStart.ToString();
        }
    }
}

ClsRichTextBox.cs

using System;
using System.Drawing;
using System.Windows.Forms;

namespace RichTextBoxFindWithReverse
{
    class ClsRichTextBox : RichTextBox
    {
        ClsFindMetadata objFindMetadata = null;
        ClsRichTextBoxSelectionArgs objRichTextBoxSelectionArgs = null;

        public ClsRichTextBox() : base()
        {
            SelectionChanged += ClsRichTextBox_SelectionChanged;
            objFindMetadata = new ClsFindMetadata();
            objRichTextBoxSelectionArgs = new ClsRichTextBoxSelectionArgs();
        }

        /// <summary>
        /// Clear the find data and highlighting (yellow background) if the user clicks on the text in the control
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void ClsRichTextBox_SelectionChanged(object sender, EventArgs e)
        {
            ClearLastFind();

            objRichTextBoxSelectionArgs.Set(SelectionStart);
            OnSelectionDataIsInteresting(objRichTextBoxSelectionArgs);
        }

        /// <summary>
        /// If last find data is available (findIndex, findLength), clear the highlighting 
        /// </summary>
        public void ClearLastFind()
        {
            SelectionChanged -= ClsRichTextBox_SelectionChanged;
            ControlExtensions.Suspend(this);
            int saveSelectionStart = SelectionStart;

            if (objFindMetadata.findStart != -1)
            {
                objFindMetadata.ClearFind();
            }

            if (objFindMetadata.highLightStart != -1)
            {
                Select(objFindMetadata.highLightStart, objFindMetadata.highLightLength);
                objFindMetadata.ClearHighLight();
                SelectionBackColor = Color.White;
                SelectionLength = 0;
            }

            SelectionStart = saveSelectionStart;
            ControlExtensions.Resume(this);
            SelectionChanged += ClsRichTextBox_SelectionChanged;
        }

        // -----------------------------------------------------------------------
        // -----------------------------------------------------------------------
        // -----------------------------------------------------------------------

        /// <summary>
        /// If searchText is found, returns true. Otherwise, returns false
        /// </summary>
        /// <param name="searchText"></param>
        /// <param name="isReverse"></param>
        /// <param name="isMatchCase"></param>
        /// <param name="isWholeWord"></param>
        /// <returns></returns>
        public bool FindTextCustom(string searchText, bool isReverse, bool isMatchCase, bool isWholeWord)
        {
            int previousSaveFindIndex = objFindMetadata.findStart;
            int previousSaveFindLength = objFindMetadata.findLength;

            int localForwardOffset = 1;
            int saveSelectionStart = SelectionStart;
            int saveSelectionLength = SelectionLength;
            int indexToplineCharOne = GetCharIndexFromPosition(new Point(0, 0));
            bool found = false;

            SelectionChanged -= ClsRichTextBox_SelectionChanged;

            ControlExtensions.Suspend(this);

            SelectionStart = saveSelectionStart;

            if (saveSelectionStart == 0 && objFindMetadata.findStart == -1)
            {
                localForwardOffset = 0;
            }

            if (!isReverse && !isMatchCase && !isWholeWord)
            {
                objFindMetadata.findStart = Find(searchText, Math.Min(SelectionStart + localForwardOffset, TextLength), Text.Length, RichTextBoxFinds.None);
            }
            else if (!isReverse && !isMatchCase && isWholeWord)
            {
                objFindMetadata.findStart = Find(searchText, Math.Min(SelectionStart + localForwardOffset, TextLength), Text.Length, RichTextBoxFinds.WholeWord);
            }
            else if (!isReverse && isMatchCase && !isWholeWord)
            {
                objFindMetadata.findStart = Find(searchText, Math.Min(SelectionStart + localForwardOffset, TextLength), Text.Length, RichTextBoxFinds.MatchCase);
            }
            else if (!isReverse && isMatchCase && isWholeWord)
            {
                objFindMetadata.findStart = Find(searchText, Math.Min(SelectionStart + localForwardOffset, TextLength), Text.Length, RichTextBoxFinds.MatchCase | RichTextBoxFinds.WholeWord);
            }
            else if (isReverse && !isMatchCase && !isWholeWord)
            {
                objFindMetadata.findStart = Find(searchText, 0, SelectionStart, RichTextBoxFinds.Reverse);
            }
            else if (isReverse && !isMatchCase && isWholeWord)
            {
                objFindMetadata.findStart = Find(searchText, 0, SelectionStart, RichTextBoxFinds.WholeWord | RichTextBoxFinds.Reverse);
            }
            else if (isReverse && isMatchCase && !isWholeWord)
            {
                objFindMetadata.findStart = Find(searchText, 0, SelectionStart, RichTextBoxFinds.MatchCase | RichTextBoxFinds.Reverse);
            }
            else // (isReverse && isMatchCase && isWholeWord)
            {
                objFindMetadata.findStart = Find(searchText, 0, SelectionStart, RichTextBoxFinds.MatchCase | RichTextBoxFinds.WholeWord | RichTextBoxFinds.Reverse);
            }

            found = false;

            if (objFindMetadata.findStart >= 0)
            {
                if (!isReverse)
                {
                    if (saveSelectionStart <= objFindMetadata.findStart)
                    {
                        found = true;
                    }
                }
                else
                {
                    if (SelectionStart < saveSelectionStart)
                    {
                        found = true;
                    }
                }
            }

            if (found)
            {
                // ClearLastFind isn't applicable because it clears find metadata. Just clear the highlight
                if (previousSaveFindIndex != -1)
                {
                    Select(objFindMetadata.highLightStart, objFindMetadata.highLightLength);
                    objFindMetadata.ClearHighLight();
                    SelectionBackColor = Color.White;
                }

                objFindMetadata.highLightStart = objFindMetadata.findStart;
                objFindMetadata.highLightLength = objFindMetadata.findLength = searchText.Length;

                Select(objFindMetadata.findStart, objFindMetadata.findLength);
                SelectionBackColor = Color.Yellow;
                SelectionLength = 0;
            }
            else
            {
                objFindMetadata.ClearFind();
                SelectionLength = 0;
                SelectionStart = saveSelectionStart;
            }

            ControlExtensions.Resume(this);
            objRichTextBoxSelectionArgs.Set(SelectionStart);
            OnSelectionDataIsInteresting(objRichTextBoxSelectionArgs);
            SelectionChanged += ClsRichTextBox_SelectionChanged;
            Focus();
            return found;
        }

        /// <summary>
        /// Method used to invoke the event that is used to report RTB SelectionStart to interested parties
        /// https://docs.microsoft.com/en-us/dotnet/api/system.eventhandler-1?view=netframework-4.7.2
        /// </summary>
        /// <param name="e"></param>
        protected virtual void OnSelectionDataIsInteresting(ClsRichTextBoxSelectionArgs e)
        {
            SelectionDataIsInteresting?.Invoke(this, e);
        }

        /// <summary>
        /// Event used to report RTB SelectionStart to interested parties
        /// </summary>
        public event EventHandler<ClsRichTextBoxSelectionArgs> SelectionDataIsInteresting;

        /// <summary>
        /// Class used to record state of find results and find highlighting
        /// </summary>
        private class ClsFindMetadata
        {
            internal int findStart = -1;
            internal int findLength = -1;

            internal int highLightStart = -1;
            internal int highLightLength = -1;

            internal void ClearFind()
            {
                findStart = -1;
                findLength = -1;
            }
            internal void ClearHighLight()
            {
                highLightStart = -1;
                highLightLength = -1;
            }
        }
    }

    /// <summary>
    /// Class used to report RTB SelectionStart to interested parties
    /// </summary>
    public class ClsRichTextBoxSelectionArgs : EventArgs
    {
        internal void Set(int selectionStart)
        {
            SelectionStart = selectionStart;
        }

        public int SelectionStart { get; set; }
    }
}

答案 2 :(得分:0)

public string searchExpress = string.Empty;
public int findPos = 0;
private void reverseSearchButton_Click(object sender, EventArgs e)
    {
        // this is to check whether new search term is written in searchbox toolStripTextBox2

        string findterm = string.Empty;
        findterm = toolStripTextBox2.Text;

        if (findterm != searchExpress)
        {
            findPos = GetRichTextBox().TextLength;
            searchExpress = findterm;
        }



        if (toolStripTextBox2.Text.Length > 0)
        {
            try
            {



                findPos = GetRichTextBox().Find(findterm, 0, GetRichTextBox().SelectionStart , RichTextBoxFinds.Reverse);


                GetRichTextBox().Select(findPos, toolStripTextBox2.Text.Length);
                GetRichTextBox().ScrollToCaret();
                GetRichTextBox().Focus();
                findPos += toolStripTextBox2.Text.Length + 1;


            }
            catch
            {
                findPos = 0;
            }

        }
    }

答案 3 :(得分:0)

要向前搜索,请使用以下代码:

int p;
p = RichTextBox1.Find(textToFind, RichTextBox1.SelectionStart + 1, RichTextBoxFinds.None);
if (p == -1)
    Interaction.MsgBox("Search text was not found.");

要向后搜索,请使用以下代码:

int p;
p = RichTextBox1.Find(textToFind, 0, RichTextBox1.SelectionStart, RichTextBoxFinds.Reverse);
if (p == -1)
    Interaction.MsgBox("Search text was not found.");