[C#]/[C# 윈폼] 혼자해보는 윈도우 메모장 만들기

[C#] 텍스트 에디터(윈도우 메모장) 만들기 8

JuJu(INTJ) 2024. 2. 15. 18:34

1. 찾기 2. 이전 찾기 3. 다음 찾기 4. 대/소문자 구분 5. 위/아래 방향 변경을 구현해보자.

 


1. 찾기 폼 만들기

  • 찾기, 이전 찾기, 다음 찾기를 구현하기 위해 우선 찾기 폼을 새로 만들어줬다.

Find Form Designer 코드

namespace MyTextEditor
{
    partial class FindForm
    {
        /// <summary>
        /// Required designer variable.
        /// </summary>
        private System.ComponentModel.IContainer components = null;

        /// <summary>
        /// Clean up any resources being used.
        /// </summary>
        /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
        protected override void Dispose(bool disposing)
        {
            if (disposing && (components != null))
            {
                components.Dispose();
            }
            base.Dispose(disposing);
        }

        #region Windows Form Designer generated code

        /// <summary>
        /// Required method for Designer support - do not modify
        /// the contents of this method with the code editor.
        /// </summary>
        private void InitializeComponent()
        {
            FindLabel = new Label();
            textBoxToSearch = new TextBox();
            FindButton = new Button();
            cancleButton = new Button();
            caseCheckBox = new CheckBox();
            roundCheckBox = new CheckBox();
            directionGroupBox = new GroupBox();
            backwardRadioButton = new RadioButton();
            forwardRadioButton = new RadioButton();
            directionGroupBox.SuspendLayout();
            SuspendLayout();
            // 
            // FindLabel
            // 
            FindLabel.AutoSize = true;
            FindLabel.Location = new Point(10, 25);
            FindLabel.Name = "FindLabel";
            FindLabel.Size = new Size(83, 15);
            FindLabel.TabIndex = 0;
            FindLabel.Text = "찾을 내용(N) :";
            FindLabel.TextAlign = ContentAlignment.MiddleCenter;
            // 
            // textBoxToSearch
            // 
            textBoxToSearch.Location = new Point(100, 20);
            textBoxToSearch.Name = "textBoxToSearch";
            textBoxToSearch.Size = new Size(200, 23);
            textBoxToSearch.TabIndex = 1;
            // 
            // FindButton
            // 
            FindButton.Location = new Point(310, 20);
            FindButton.Name = "FindButton";
            FindButton.Size = new Size(85, 30);
            FindButton.TabIndex = 2;
            FindButton.Text = "다음 찾기(F)";
            FindButton.UseVisualStyleBackColor = true;
            FindButton.Click += FindButton_Click;
            // 
            // cancleButton
            // 
            cancleButton.Location = new Point(310, 60);
            cancleButton.Name = "cancleButton";
            cancleButton.Size = new Size(85, 30);
            cancleButton.TabIndex = 3;
            cancleButton.Text = "취소";
            cancleButton.UseVisualStyleBackColor = true;
            cancleButton.Click += CancleButton_Click;
            // 
            // caseCheckBox
            // 
            caseCheckBox.AutoSize = true;
            caseCheckBox.Location = new Point(10, 60);
            caseCheckBox.Name = "caseCheckBox";
            caseCheckBox.Size = new Size(123, 19);
            caseCheckBox.TabIndex = 4;
            caseCheckBox.Text = "대/소문자 구분(C)";
            caseCheckBox.UseVisualStyleBackColor = true;
            caseCheckBox.CheckedChanged += CaseCheckBox_CheckedChanged;
            // 
            // roundCheckBox
            // 
            roundCheckBox.AutoSize = true;
            roundCheckBox.Enabled = false;
            roundCheckBox.Location = new Point(10, 90);
            roundCheckBox.Name = "roundCheckBox";
            roundCheckBox.Size = new Size(105, 19);
            roundCheckBox.TabIndex = 5;
            roundCheckBox.Text = "주위에 배치(R)";
            roundCheckBox.UseVisualStyleBackColor = true;
            roundCheckBox.CheckedChanged += RoundCheckBox_CheckedChanged;
            // 
            // directionGroupBox
            // 
            directionGroupBox.Controls.Add(backwardRadioButton);
            directionGroupBox.Controls.Add(forwardRadioButton);
            directionGroupBox.Location = new Point(140, 50);
            directionGroupBox.Name = "directionGroupBox";
            directionGroupBox.Size = new Size(160, 60);
            directionGroupBox.TabIndex = 6;
            directionGroupBox.TabStop = false;
            directionGroupBox.Text = "방향";
            // 
            // backwardRadioButton
            // 
            backwardRadioButton.AutoSize = true;
            backwardRadioButton.Checked = true;
            backwardRadioButton.Location = new Point(80, 25);
            backwardRadioButton.Name = "backwardRadioButton";
            backwardRadioButton.Size = new Size(78, 19);
            backwardRadioButton.TabIndex = 1;
            backwardRadioButton.TabStop = true;
            backwardRadioButton.Text = "아래로(D)";
            backwardRadioButton.UseVisualStyleBackColor = true;
            backwardRadioButton.CheckedChanged += BackwardRadioButton_CheckedChanged;
            // 
            // forwardRadioButton
            // 
            forwardRadioButton.AutoSize = true;
            forwardRadioButton.Location = new Point(10, 25);
            forwardRadioButton.Name = "forwardRadioButton";
            forwardRadioButton.Size = new Size(65, 19);
            forwardRadioButton.TabIndex = 0;
            forwardRadioButton.Text = "위로(U)";
            forwardRadioButton.UseVisualStyleBackColor = true;
            forwardRadioButton.CheckedChanged += ForwardRadioButton_CheckedChanged;
            // 
            // FindForm
            // 
            AutoScaleDimensions = new SizeF(7F, 15F);
            AutoScaleMode = AutoScaleMode.Font;
            ClientSize = new Size(414, 141);
            Controls.Add(directionGroupBox);
            Controls.Add(roundCheckBox);
            Controls.Add(caseCheckBox);
            Controls.Add(cancleButton);
            Controls.Add(FindButton);
            Controls.Add(textBoxToSearch);
            Controls.Add(FindLabel);
            Name = "FindForm";
            Text = "찾기";
            directionGroupBox.ResumeLayout(false);
            directionGroupBox.PerformLayout();
            ResumeLayout(false);
            PerformLayout();
        }

        #endregion

        private Label FindLabel;
        private TextBox textBoxToSearch;
        private Button FindButton;
        private Button cancleButton;
        private CheckBox caseCheckBox;
        private CheckBox roundCheckBox;
        private GroupBox directionGroupBox;
        private RadioButton backwardRadioButton;
        private RadioButton forwardRadioButton;
    }
}

 

2. 메모장 Form

메모장 Form

using Microsoft.VisualBasic;
using System.Drawing.Printing;

namespace MyTextEditor
{
    public partial class 메모장 : Form
    {
        private FindForm findDialog;
        public string lastSearchText = string.Empty;
        public bool IsCase = false;

        public 메모장()
        {
            InitializeComponent();
        }

		//찾기(Ctrl+F)
        private void FindTextToolTip_Click(object sender, EventArgs e)
        {
            ShowDialogs("find");
        }


        //다음 찾기(F3)
        private void FindNextToolTip_Click(object sender, EventArgs e)
        {
            if (!string.IsNullOrEmpty(lastSearchText))
            {
                RichTextBoxFinds options = IsCase ? RichTextBoxFinds.MatchCase : RichTextBoxFinds.None;
                findDialog.FindDown(lastSearchText, options);
            }
            else
            {
                ShowDialogs("find");
            }
        }

        //이전 찾기(SHIFT+F3)
        private void FindBeforeToolTip_Click(object sender, EventArgs e)
        {
            if (!string.IsNullOrEmpty(lastSearchText))
            {
                RichTextBoxFinds options = IsCase ? RichTextBoxFinds.MatchCase : RichTextBoxFinds.None;
                findDialog.FindUp(lastSearchText, options);
            }
            else
            {
                ShowDialogs("find");
            }
        }
        
        
        // 찾기, 줄 이동 다이얼로그 호출
        private void ShowDialogs(string spec)
        {
            if (spec == "find")
            {
                if (findDialog == null || findDialog.IsDisposed)
                {
                    findDialog = new FindForm(this);
                    findDialog.Show(this);
                }
                else
                {
                    findDialog.BringToFront();
                }
            }
        }
        
        
  	}
  }

 

  • 마지막으로 찾기에 입력한 값을 저장해주고 해당 값으로 검색을 진행한다.
  • 이전 찾기, 다음 찾기 실행 시, lastSearchText에 값이 없다면 "찾기" 다이어로그를 연다. lastSearchText에 값이 있다면 해당 값으로 찾기를 진행한다.
  •  findDialog.Show(this) => this를 해줘야 포커스가 제대로 맞춰진다.
  • options를 넣어서 대/소문자에 따른 검색을 해준다.

 

3. Find.cs Form

using System.Data;

namespace MyTextEditor
{
  
    //찾기 폼
    public partial class FindForm : Form
    {
        메모장 Memo;
        public int lastSearchIndex = -1;
        public bool isSearchForward = true; // 찾는 방향 (기본값: 아래로)
     
        public FindForm(메모장 mainMemo)
        { 
            Memo = mainMemo;
            InitializeComponent();
            textBoxToSearch.Text = Memo.lastSearchText;
            caseCheckBox.Checked = Memo.IsCase;
        }

        public void FindButton_Click(object sender, EventArgs e)
        {
            string searchText = textBoxToSearch.Text;
            bool isCase = caseCheckBox.Checked;

            // 대/소문자 구분 설정 적용
            RichTextBoxFinds options = isCase ? RichTextBoxFinds.MatchCase : RichTextBoxFinds.None;

            if (!string.IsNullOrWhiteSpace(searchText))
            {
                Find(searchText, options);
            }
            else
            {
                MessageBox.Show("찾을 내용을 입력하세요.", "알림", MessageBoxButtons.OK, MessageBoxIcon.Information);
            }

        }

        public void Find(string searchText, RichTextBoxFinds options)
        {
            Memo.lastSearchText = searchText; // 마지막으로 찾은 문자열 저장
           
            if (isSearchForward)
                FindDown(searchText, options);
            else
                FindUp(searchText, options);
            Memo.MyTextArea.Focus();
        }


        public void FindDown(string searchText, RichTextBoxFinds options) {

            int startIndex = lastSearchIndex == -1 ? 0 : lastSearchIndex + 1;
            int resultIndex = Memo.MyTextArea.Find(searchText, startIndex, options);

            if (resultIndex != -1)
            {
                Memo.MyTextArea.Select(resultIndex, searchText.Length);
                lastSearchIndex = resultIndex;
            }
            else
            {
                MessageBox.Show($"다음 {searchText}를 찾을 수 없습니다.", "찾기", MessageBoxButtons.OK, MessageBoxIcon.Information);
             
            }

        }

        public void FindUp(string searchText, RichTextBoxFinds options)
        {
            int startIndex = lastSearchIndex == -1 ? Memo.MyTextArea.Text.Length - 1 : lastSearchIndex - 1;
            int resultIndex = Memo.MyTextArea.Find(searchText, 0, startIndex, options | RichTextBoxFinds.Reverse);

            if (resultIndex != -1)
            {
                Memo.MyTextArea.Select(resultIndex, searchText.Length);
                lastSearchIndex = resultIndex;
            }
            else
            {
                MessageBox.Show($"이전 {searchText}를 찾을 수 없습니다.", "찾기", MessageBoxButtons.OK, MessageBoxIcon.Information);
            }
        }


        //취소 버튼
        private void CancleButton_Click(object sender, EventArgs e)
        {
            this.Close();
        }

        // 대/소문자 구분 체크박스 이벤트 핸들러
        private void CaseCheckBox_CheckedChanged(object sender, EventArgs e)
        {
            Memo.IsCase = caseCheckBox.Checked;
        }

       
        // 방향 설정 라디오 버튼 이벤트 핸들러
        private void BackwardRadioButton_CheckedChanged(object sender, EventArgs e)
        {
            isSearchForward = backwardRadioButton.Checked;
        }

        private void ForwardRadioButton_CheckedChanged(object sender, EventArgs e)
        {
            isSearchForward = !forwardRadioButton.Checked;
        }


    }

}
  • 찾기 폼에서 다음 찾기 버튼 눌렀을 때, 값이 없으면 메세지 박스를 띄어주고 있으면 Find 함수를 호출한다.
  • Find 함수에서 방향 설정에 따른 FindUp, FindDown 함수를 실행시킨다.
  • FindUp, FindDown 함수에서 방향에 따른 검색을 진행한다. -> lastSerchIndex를 추가해 마지막 검색 값을 저장시켜 검색했다. 
  • 이전에는 끝까지 검색해도 멈추지 않고 처음으로 돌아가졌는데 이 코드를 추가하고 나니 마지막이나 이전 검색 시 제대로 돌아간다.

 

 

 

 

 

 

 

반응형