[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를 추가해 마지막 검색 값을 저장시켜 검색했다.
- 이전에는 끝까지 검색해도 멈추지 않고 처음으로 돌아가졌는데 이 코드를 추가하고 나니 마지막이나 이전 검색 시 제대로 돌아간다.
반응형