[C#] 텍스트 에디터(윈도우 메모장) 만들기 6
2024. 2. 6. 10:55ㆍ[C#]/[C# 윈폼] 혼자해보는 윈도우 메모장 만들기
오늘은 메모장을 살펴보니
1. 찾기 & 다음 찾기 & 이전 찾기는 텍스트가 입력됐을 때 메뉴 활성화
2. 잘라내기 & 삭제 & 복사는 텍스트가 선택됐을 때 메뉴 활성화를 먼저 해주고
3. X를 눌러 종료 시 저장 여부를 추가해줘야한다.
4. 줄 이동
1. 찾기 & 다음 찾기 & 이전 찾기 메뉴 활성화
- 우선 속성에서 해당 내용들의 Enable을 false로 변경해준다.
// 텍스트 변경 여부 확인 메소드
private void MyTextArea_TextChanged(object sender, EventArgs e)
{
isTextChanged = true;
UpdateFormTitle();
if (MyTextArea.Text.Length > 0)
{
FindTextToolTip.Enabled = true;
FindNextToolTip.Enabled = true;
FindBeforeToolTip.Enabled = true;
}
else
{
FindTextToolTip.Enabled = false;
FindNextToolTip.Enabled = false;
FindBeforeToolTip.Enabled = false;
}
}
- Text길이가 0 이상이면 찾기 기능 등을 활성화 시켜주고 아니면 다시 비활성화 시켜준다.
2. 잘라내기 & 삭제 & 복사 메뉴 활성화
- 텍스트 선택 시 활성화 시켜준다.
private void MyTextArea_SelectionChanged(object sender, EventArgs e)
{
// 텍스트가 선택되었는지 여부를 확인하여 메뉴의 활성화 여부를 설정
bool isTextSelected = MyTextArea.SelectionLength > 0;
CutTextToolTip.Enabled = isTextSelected;
CopyTextToolTip.Enabled = isTextSelected;
DeleteTextToolTip.Enabled = isTextSelected;
}
3. X를 눌러 종료 시 저장 여부, 끝내기
- 여기서 시간을 엄청 잡아먹었다.
- 코드를 추가하고 기존 코드를 변경하는 작업에서 코드가 꼬인 것 같다.
기존 코드
private void ExitToolTip_Click(object sender, EventArgs e)
{
if (isTextChanged)
{
DialogResult result = MessageBox.Show("변경된 내용을 저장하시겠습니까?", "저장 확인", MessageBoxButtons.YesNoCancel, MessageBoxIcon.Question);
if (result == DialogResult.Yes)
{
// 저장
SaveFile();
}
else if (result == DialogResult.Cancel)
{
// 취소
return;
}
}
Close();
}
private void 메모장_FormClosing(object sender, FormClosingEventArgs e)
{
// 현재 열려있는 폼이 없으면 프로그램 종료
if (Application.OpenForms.Count == 0)
{
Application.Exit();
}
}
=>
private void 메모장_FormClosing(object sender, FormClosingEventArgs e)
{
if (isTextChanged)
{
DialogResult result = MessageBox.Show("변경된 내용을 저장하시겠습니까?", "저장 확인", MessageBoxButtons.YesNoCancel, MessageBoxIcon.Question);
if (result == DialogResult.Yes)
{
SaveFile();
}
else if (result == DialogResult.Cancel)
{
e.Cancel = true; // 취소 선택 시 창을 닫지 않음
}
}
if (Application.OpenForms.Count == 0)
{
Application.Exit();
}
}
- 처음에는 끝내기 버튼을 눌렀을 때, 텍스트가 변경되었다면 저장 여부를 물어보는 로직만 구현했었다.
- 근데 타이틀바에 X표시 부분을 눌렀을 때도, 똑같은 로직으로 돌아가야하는데 FormClosing 이벤트에 저장 여부를 묻는 코드를 넣자 다이얼로그가 두번 호출되는 버그가 생겼다.
변경된 코드
//끝내기
private void ExitToolTip_Click(object sender, EventArgs e)
{
// FormClosing 이벤트를 수동으로 호출하여 종료할 때의 동작을 수행
메모장_FormClosing(this, new FormClosingEventArgs(CloseReason.UserClosing, false));
}
private void 메모장_FormClosing(object sender, FormClosingEventArgs e)
{
if (isTextChanged)
{
DialogResult result = MessageBox.Show("변경된 내용을 저장하시겠습니까?", "저장 확인", MessageBoxButtons.YesNoCancel, MessageBoxIcon.Question);
if (result == DialogResult.Yes)
{
SaveFile();
}
else if (result == DialogResult.Cancel)
{
e.Cancel = true; // 취소 선택 시 창을 닫지 않음
}
}
}
#endregion
private void 메모장_FormClosed(object sender, FormClosedEventArgs e)
{
// 현재 열려있는 폼이 없으면 프로그램 종료
if (Application.OpenForms.Count == 0)
{
Application.Exit();
}
}
- Form이 닫힐 때, 텍스트가 변경됐다면 저장 여부를 물어보는 로직을 작성하고
- 이를 끝내기를 눌렀을 때도 FormClosing을 호출하여 처리해줬다.
- "새 창" 기능에서 여러 폼을 띄워줄 때 부모 폼이 죽으면 자식폼들도 다 죽는 문제를 해결하기 위해 Program.cs를 수정한 적이 있다. 이 부분에서 폼을 하나씩 닫는 로직은 돌아가지만 모든 폼을 다 닫아도 프로젝트가 종료되지 않는 버그를 수정하기 위해 FormClosed 이벤트에 코드를 추가해줬다.
6. 이동(줄 이동)
public class MoveDialog : Form
{
private Label findLabel;
private RichTextBox textBoxToMove;
private Button moveButton;
private Button cancleButton;
public event EventHandler MoveEvent;
public int TargetLine => int.Parse(textBoxToMove.Text);
public string MoveText => textBoxToMove.Text;
public MoveDialog(RichTextBox richtextBox)
{
textBoxToMove = richtextBox;
InitializeUI();
this.Text = "줄 이동";
this.Width = 270;
this.Height = 160;
}
private void InitializeUI()
{
findLabel = new Label();
textBoxToMove = new RichTextBox();
moveButton = new Button();
cancleButton = new Button();
//라벨
findLabel.Text = "줄 번호(L) :";
findLabel.Location = new Point(10, 10);
findLabel.AutoSize = true;
//찾을 내용 TextBox
textBoxToMove.Height = 30;
textBoxToMove.Width = 230;
textBoxToMove.Location = new Point(10, 40);
textBoxToMove.KeyPress += TextBoxToMove_KeyPress;
//이동 버튼
moveButton.Text = "이동";
moveButton.Height = 25;
moveButton.Width = 70;
moveButton.Location = new Point(90, 80);
moveButton.Click += MoveButton_Click;
//취소 버튼
cancleButton.Text = "취소";
cancleButton.Height = 25;
cancleButton.Width = 70;
cancleButton.Location = new Point(170, 80);
cancleButton.Click += CancelButton_Click;
// Add controls to the form
Controls.Add(findLabel);
Controls.Add(textBoxToMove);
Controls.Add(moveButton);
Controls.Add(cancleButton);
}
private void MoveButton_Click(object sender, EventArgs e)
{
MoveEvent?.Invoke(this, EventArgs.Empty);
}
private void CancelButton_Click(object sender, EventArgs e)
{
// 취소 버튼 클릭 시 폼 닫기
this.Close();
}
// TextBox 입력 제한 - 숫자만 입력 가능하도록
private void TextBoxToMove_KeyPress(object sender, KeyPressEventArgs e)
{
if (!char.IsControl(e.KeyChar) && !char.IsDigit(e.KeyChar))
{
e.Handled = true;
}
}
}
- 폼을 추가해주고, 숫자만 입력할 수 있게 TextBoxToMove_KeyPress에 입력했다. 원래는 문자를 입력하면 툴팁을 추가하려 했으나 추후에 추가할 예정이다.
//이동(Ctrl+G)
private void MoveTextToolTip_Click(object sender, EventArgs e)
{
ShowDialogs("move");
}
// 찾기 다이얼로그 표시
private void ShowDialogs(string spec)
{
if(spec == "find")
{
if (findDialog == null || findDialog.IsDisposed)
{
findDialog = new FindDialog(MyTextArea);
findDialog.Show();
}
else
{
findDialog.BringToFront();
}
}
else if(spec == "move")
{
if (moveDialog == null || moveDialog.IsDisposed)
{
moveDialog = new MoveDialog(MyTextArea);
moveDialog.MoveEvent += MoveDialog_MoveEvent;
moveDialog.Show();
}
else
{
moveDialog.BringToFront();
}
}
}
// 줄 이동 이벤트 핸들러
private void MoveDialog_MoveEvent(object sender, EventArgs e)
{
// MoveDialog에서 줄 이동 버튼을 클릭하면 호출되는 이벤트 핸들러
MoveDialog moveDialog = sender as MoveDialog;
if (moveDialog != null)
{
// 줄 이동 처리
int targetLine = moveDialog.TargetLine;
if (targetLine >= 1 && targetLine <= MyTextArea.Lines.Length)
{
// 해당 줄로 커서 이동
MyTextArea.SelectionStart = MyTextArea.GetFirstCharIndexFromLine(targetLine - 1);
MyTextArea.ScrollToCaret();
MyTextArea.Focus();
moveDialog.Close();
}
else
{
// 유효하지 않은 줄 번호일 경우 메시지 표시
MessageBox.Show("유효하지 않은 줄 번호입니다.", "오류", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
}
반응형
'[C#] > [C# 윈폼] 혼자해보는 윈도우 메모장 만들기' 카테고리의 다른 글
[C#] 텍스트 에디터(윈도우 메모장) 만들기 8 (0) | 2024.02.15 |
---|---|
[C#] 텍스트 에디터(윈도우 메모장) 만들기 7 (0) | 2024.02.07 |
[C#] 텍스트 에디터(윈도우 메모장) 만들기 5 (1) | 2024.02.05 |
[C#] 텍스트 에디터(윈도우 메모장) 만들기 4 (0) | 2024.02.04 |
[C#] 텍스트 에디터(윈도우 메모장) 만들기 3 (0) | 2024.02.04 |