Thứ tư, ngày 18 tháng 7 năm 2018

C# – Tạo Find and Replace dialog cho RichTextBox

Ngày đăng: 16/3/2012, 14:1:7PM | Lượt xem: 3,505
Hot!

Mặc dù RichTextBox đã hỗ trợ sẵn phương thức Find, tuy nhiên nhiều người vẫn thắc mắc về hiện thực chức năng Find Next cho control này. Để giải quyết vấn đề này, tôi sẽ minh họa cách tạo một cửa sổ Find and Replace đơn giản như trong Notepad.

Mặc dù RichTextBox đã hỗ trợ sẵn phương thức Find, tuy nhiên nhiều người vẫn thắc mắc về hiện thực chức năng Find Next cho control này. Để giải quyết vấn đề này, tôi sẽ minh họa cách tạo một cửa sổ Find and Replace đơn giản như trong Notepad.

Download sourcecode+demo(29KB)

RichTextBox hỗ trợ nhiều phiên bản của phương thức Find. Một overload cơ bản mà ta sẽ dùng để tìm kiếm trong RichTextBox là:

public int Find(
	string str,
	int start,
	RichTextBoxFinds options
)

Trong đó:

  • str: Chuỗi tìm kiếm
  • start: Vị trí bắt đầu tìm kiếm, đặt là vị trí cuối cùng của vùng chọn trong RichTextBox để Find Next.
  • options: Các tùy chọn tìm kiếm (như match case, match whole word,…). Bạn có thể kết hợp các tùy chọn lại bằng toán tử bitwise OR ‘|’

Phương thức này sẽ trả về vị trí của chuỗi được tìm thấy, sau đó ta kết hợp với chiều dài của chuỗi cần tìm để tạo vùng chọn (highlight) trong RichTextBox.

Mặc định Find() sẽ tìm kiếm từ trên xuống dưới, để tìm kiếm theo hướng ngược lại, ta cần dùng tùy chọn RichTextBoxFinds.Reverse, đồng thời sử dụng một phiên bản khác của Find() để tìm kiếm từ vị trí đầu tiên đến vị trí hiện tại của cursor trong RichTextBox:

public int Find(
	string str,
	int start,
	int end,
	RichTextBoxFinds options
)

Các điểm cần chú ý:

- RichTextBox.HideSelecion=false : Hiển thị vùng chọn trong RichTextBox khi không được focus.

- Sử dụng Form.Show(IWin32Window) để form Find luôn hiển thị lên trên form Main, và có thể chuyển focus qua lại 2 form.

- Thay đổi ClientSize.Height thay vì Form.Height, vì Form.Height bao gồm luôn cả titlebar.

Ok! Rất đơn giản, vậy ta có thể tạo một form có chức năng Find Next và Replace như sau:

FindForm.cs

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

namespace Demo_Editor
{
	public partial class FindForm : Form
	{
		RichTextBox _richTextBox;

		bool _close;

		public FindForm(RichTextBox richTextBox)
		{
			InitializeComponent();

			_richTextBox=richTextBox;
		}

		protected override void OnFormClosing(FormClosingEventArgs e)
		{
			if(!_close)
			{
				// hide instead of close
				this.Hide();
				e.Cancel=true;
			}

			base.OnFormClosing(e);
		}
		public void ForceClose()
		{
			_close=true;
			this.Close();
		}

		public void ShowFind(bool replaceMode)
		{
			this.Text= replaceMode ? "Find" : "Replace";
			pnlReplace.Visible=replaceMode;

			if(!this.Visible)
				this.Show(_richTextBox);
			// resize form
			this.ClientSize = new Size(this.ClientSize.Width,pnlOptions.Bottom);

			txtFindText.Focus();
			txtFindText.SelectAll();
		}

		void BtnFindNextClick(object sender, EventArgs e)
		{
			Find(_richTextBox, txtFindText.Text,chkMatchCase.Checked,chkMatchWholeWord.Checked,radDirectionUp.Checked);
		}
		void Find(RichTextBox richText, string text, bool matchCase, bool matchWholeWord, bool upDirection)
		{
			RichTextBoxFinds options=RichTextBoxFinds.None;
			if(matchCase)
				options|= RichTextBoxFinds.MatchCase;
			if(matchWholeWord)
				options|=RichTextBoxFinds.WholeWord;
			if(upDirection)
				options|=RichTextBoxFinds.Reverse;

			int index;
			if(upDirection)
				index = richText.Find(text,0,richText.SelectionStart,options);
			else
				index = richText.Find(text,richText.SelectionStart+richText.SelectionLength,options);

			if(index>=0)
			{
				richText.SelectionStart=index;
				richText.SelectionLength=text.Length;
			}
			else // text not found
			{
				MessageBox.Show(Application.ProductName + " has finished searching the document.",
				                Application.ProductName,MessageBoxButtons.OK,
				                MessageBoxIcon.Information);
			}
		}

		void BtnReplaceClick(object sender, EventArgs e)
		{
			_richTextBox.SelectedText=txtReplace.Text;
		}

		void BtnReplaceAllClick(object sender, EventArgs e)
		{
			_richTextBox.Text=_richTextBox.Text.Replace(txtFindText.Text,txtReplace.Text);
		}
	}
}

Cách sử dung:
FormMain.cs

using System;
using System.Windows.Forms;

namespace Demo_Editor
{
	public partial class MainForm : Form
	{
		FindForm _findForm;
		public MainForm()
		{
			InitializeComponent();
		}
		protected override void OnFormClosing(FormClosingEventArgs e)
		{
			if(_findForm!=null)
				_findForm.ForceClose();

			// if there are unclosed forms in your application,
			// e.Cancel will be true
			e.Cancel=false;

			base.OnFormClosing(e);
		}
		void BtnFindClick(object sender, EventArgs e)
		{
			if(_findForm==null || _findForm.IsDisposed)
				_findForm=new FindForm(this,richTextBox1);
			_findForm.ShowFind(false);
		}

		void BtnReplaceClick(object sender, EventArgs e)
		{
			if(_findForm==null || _findForm.IsDisposed)
				_findForm=new FindForm(this,richTextBox1);
			_findForm.ShowFind(true);
		}
	}
}

Đây chỉ là ví dụ minh họa đơn giản nên chưa xét hết các trường hợp lỗi. Bạn có thể tạo một sub class của RichTextBox và tích hợp hộp thoại Find & Replace này vào, hoặc cũng có thể build ra một thư viện riêng để sử dụng khi cần thiết.

http://yinyangit.wordpress.com

 Chia sẻ qua: 
Hot!
Ý kiến bạn đọc

These items will be permanently deleted and cannot be recovered. Are you sure?

Gallery

image

Maecenas viverra rutrum pulvinar

Maecenas viverra rutrum pulvinar! Aenean vehicula nulla sit amet metus aliquam et malesuada risus aliquet. Vestibulum rhoncus, dolor sit amet venenatis porta, metus purus sagittis nisl, sodales volutpat elit lorem…

Read more

Text Links

Thiết kế logo chuyên nghiệp Insky
DAFABET
W88 w88b.com/dang-ky-tai-khoan-w88
W88
ca do bong da online
Copyright © 2011 - 2012 vietshare.vn by phamkhuong102@gmail.com doanhkisi2315@gmail.com. All rights reserved.