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

2024. 2. 4. 17:33[C#]/[C# 윈폼] 혼자해보는 윈도우 메모장 만들기

오늘은 1. 파일명 표시 & 텍스트가 바뀌면 파일명 앞에 * 표시 2. 끝내기 3. 실행 취소 & 잘라내기 & 복사 & 붙여넣기 & 삭제 기능을 구현할 것이다. + 실행 복구

 


1. 파일명 표시 & 텍스트 변경 시 파일명 앞 * 표시

 

//파일 이름 변경
private void UpdateFormTitle()
{
    string fileName = string.IsNullOrEmpty(currentFilePath) ? "제목 없음" : Path.GetFileName(currentFilePath);
    this.Text = isTextChanged ? $"*{fileName}" : fileName;
}
  • 우선 파일명을 업데이트하는 메소드를 만들었다.
  • 저장을 안한 상태(처음 만든 상태)면 제목을 "제목 없음"으로 표시하고 파일을 가져오거나 저장해서 파일명이 있는 상태면 파일명을 표시해준다.
  • 만약 가져온 뒤에 텍스트의 변경이 있으면 파일명 앞에 *을 붙여준다.
// 텍스트 에디터 내용 변경 여부 확인
private void MyTextArea_TextChanged(object sender, EventArgs e)
{
    isTextChanged = true;
    UpdateFormTitle(); //추가된 코드
}
  • 이렇게 저장, 열기, 텍스트 변경 시 등 필요한 부분에 호출해서 사용해준다.

 

2. 끝내기 기능

우선 끝내기 기능을 하기 앞서 문제가 생겼다.

  • "새 창"을 이용해서 새로운 폼들을 열고 처음 생성된 메인 폼을 닫았을 때, "새 창"을 이용해 연 자식 폼들까지 같이 닫힌다는 것이다.

이를 해결하기 위해 Program.cs를 변경해줬다.

//기존 코드
ApplicationConfiguration.Initialize();
Application.Run(new 메모장());

//변경된 코드
(new 메모장()).Show();
Application.Run();
  • 이렇게하면 메인 메모장이 닫히더라도 프로그램이 닫히지 않기 때문에 자식 폼들이 살아남을 수 있다.

 

끝내기 기능 코드

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();

}

 

  • 닫기 전에 변경된 내용이 있으면 저장 여부를 물어본다. Yes를 누르면 파일을 저장해주고, 아니면 그냥 종료한다.

하지만 Program.cs를 변경하니 모든 폼을 닫아도 프로그램 전체가 종료되지 않는 버그가 있었다.

이는 FormClosing 이벤트를 통해 해결했다.

private void 메모장_FormClosing(object sender, FormClosingEventArgs e)
{
    
// 모든 폼이 닫히면 프로그램 종료
if (Application.OpenForms.Count == 1)
{
    Application.Exit();
}
    
}
  • 폼을 닫을 때, 열린 폼의 갯수가 1개이면 프로그램을 종료해준다.

 

 

2. 복사 & 붙여넣기 & 자르기 & 삭제 & 실행취소

 //복사(Ctrl+C)
 private void CopyTextToolTip_Click(object sender, EventArgs e)
 {
     if (MyTextArea.SelectionLength > 0)
     {
         MyTextArea.Copy();
     }
 }
 
 //붙여넣기(Ctrl+V)
 private void PasteTextToolTip_Click(object sender, EventArgs e)
 {
     MyTextArea.Paste();
 }
 
 //자르기(Ctrl+X)
 private void CutTextToolTip_Click(object sender, EventArgs e)
 {
     if (MyTextArea.SelectionLength > 0)
     {
         MyTextArea.Cut();
     }
 }
 
 //실행 취소(Ctrl+Z)
 private void DoCancleToolTip_Click(object sender, EventArgs e)
 {
     if (MyTextArea.CanUndo)
     {
         MyTextArea.Undo();
     }
 }

 //실행 복구(Ctrl+Y)
 private void RedoToolTip_Click(object sender, EventArgs e)
 {
     if (MyTextArea.CanRedo)
     {
         MyTextArea.Redo();
     }
 }

 //삭제(Delete)
 private void DeleteTextToolTip_Click(object sender, EventArgs e)
 {
     if (MyTextArea.SelectionLength > 0)
     {
         MyTextArea.SelectedText = string.Empty;
     }
 }

전체 코드

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

namespace MyTextEditor
{
    public partial class 메모장 : Form
    {
        private string currentFilePath = string.Empty;
        private bool isTextChanged = false;

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

        #region 파일
        // 새 파일(Ctrl+N)
        private void NewFileToolTip_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;
                }
            }

            // 새 파일 초기화
            MyTextArea.Text = string.Empty;
            currentFilePath = string.Empty;
            isTextChanged = false;
        }

        //새창(Ctrl+Shift+N)
        private void NewMemoToolTip_Click(object sender, EventArgs e)
        {
            // 새 창을 만들기 위해 메모장의 복사본을 생성
            메모장 newMemo = new 메모장();
            // 새 창을 보여줌
            newMemo.Show();
        }

        //열기(Ctrl+O)
        private void OpenToolTip_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;
                }
            }

            //OpenFileDialog 호출(.txt text 파일만 열기)
            OpenFileDialog openFileDialog = new OpenFileDialog();
            openFileDialog.Filter = "텍스트 파일 (*.txt)|*.txt|모든 파일 (*.*)|*.*";

            if (openFileDialog.ShowDialog() == DialogResult.OK)
            {
                currentFilePath = openFileDialog.FileName;
                MyTextArea.Text = File.ReadAllText(currentFilePath);
                isTextChanged = false;
                UpdateFormTitle();
            }
        }

        // 저장(Ctrl+S)
        private void SaveToolTip_Click(object sender, EventArgs e)
        {
            SaveFile();
        }

        //다른 이름으로 저장(Ctrl+Shift+S)
        private void DnameSaveToolTip_Click(object sender, EventArgs e)
        {
            SaveFileDialog saveFileDialog = new SaveFileDialog();
            saveFileDialog.Filter = "텍스트 파일 (*.txt)|*.txt|모든 파일 (*.*)|*.*";

            if (saveFileDialog.ShowDialog() == DialogResult.OK)
            {
                currentFilePath = saveFileDialog.FileName;
                SaveFile();
            }

        }

        //페이지 설정
        private void PageSettingToolTip_Click(object sender, EventArgs e)
        {

        }

        //인쇄(Ctrl+P)
        private void PrintToolTip_Click(object sender, EventArgs e)
        {
            PrintDialog printDialog = new PrintDialog();
            printDialog.Document = new PrintDocument();

            if (printDialog.ShowDialog() == DialogResult.OK)
            {
                printDialog.Document.PrintPage += new PrintPageEventHandler(PrintDocument_PrintPage);
                printDialog.Document.Print();
            }

        }

        //끝내기
        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();
        }
        #endregion



        #region 편집

        //복사(Ctrl+C)
        private void CopyTextToolTip_Click(object sender, EventArgs e)
        {
            if (MyTextArea.SelectionLength > 0)
            {
                MyTextArea.Copy();
            }

        }
        //붙여넣기(Ctrl+V)

        private void PasteTextToolTip_Click(object sender, EventArgs e)
        {
            MyTextArea.Paste();
        }
        //자르기(Ctrl+X)

        private void CutTextToolTip_Click(object sender, EventArgs e)
        {
            if (MyTextArea.SelectionLength > 0)
            {
                MyTextArea.Cut();
            }
        }
        //실행 취소(Ctrl+Z)

        private void DoCancleToolTip_Click(object sender, EventArgs e)
        {
            if (MyTextArea.CanUndo)
            {
                MyTextArea.Undo();
            }
        }

        //실행 복구(Ctrl+Y)
        private void RedoToolTip_Click(object sender, EventArgs e)
        {
            if (MyTextArea.CanRedo)
            {
                MyTextArea.Redo();
            }
        }

        //삭제(Delete)
        private void DeleteTextToolTip_Click(object sender, EventArgs e)
        {
            if (MyTextArea.SelectionLength > 0)
            {
                MyTextArea.SelectedText = string.Empty;
            }
        }

        //시간 입력(F5)
        private void TimeTextToolTip_Click(object sender, EventArgs e)
        {
            //현재 시간 추가
            MyTextArea.Text += DateTime.Now.ToString();
            //커서 맨 뒤로 이동
            MyTextArea.SelectionStart = MyTextArea.Text.Length;
            MyTextArea.SelectionLength = 0;
            MyTextArea.Focus();
        }
        #endregion


        #region 메소드
        // 파일 저장 메소드
        private void SaveFile()
        {
            if (string.IsNullOrEmpty(currentFilePath))
            {
                // 파일 경로가 없는 경우 SaveFileDialog 표시
                SaveFileDialog saveFileDialog = new SaveFileDialog();
                saveFileDialog.Filter = "텍스트 파일 (*.txt)|*.txt|모든 파일 (*.*)|*.*";
                saveFileDialog.FilterIndex = 1;

                if (saveFileDialog.ShowDialog() == DialogResult.OK)
                {
                    currentFilePath = saveFileDialog.FileName;
                }
                else
                {
                    return; // 사용자가 취소한 경우 저장 중단
                }
            }

            try
            {
                // 텍스트 에디터의 내용을 파일에 저장
                File.WriteAllText(currentFilePath, MyTextArea.Text);
                isTextChanged = false; // 저장 후 변경되지 않은 상태로 표시
                UpdateFormTitle(); // 저장 후 파일 이름 표시 갱신
            }
            catch (Exception ex)
            {
                MessageBox.Show($"파일 저장 중 오류가 발생했습니다: {ex.Message}", "오류", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }

        // 텍스트 변경 여부 확인 메소드
        private void MyTextArea_TextChanged(object sender, EventArgs e)
        {
            isTextChanged = true;
            UpdateFormTitle();
        }

        //파일 이름 변경 메소드
        private void UpdateFormTitle()
        {
            string fileName = string.IsNullOrEmpty(currentFilePath) ? "제목 없음" : Path.GetFileName(currentFilePath);
            this.Text = isTextChanged ? $"*{fileName}" : fileName;
        }

        // 프린트할 때 호출되는 이벤트 핸들러
        private void PrintDocument_PrintPage(object sender, PrintPageEventArgs e)
        {
            Font font = new Font("Arial", 12);
            e.Graphics.DrawString(MyTextArea.Text, font, Brushes.Black, 10, 10);
        }

        private void 메모장_FormClosing(object sender, FormClosingEventArgs e)
        {
            // 모든 폼이 닫히면 프로그램 종료
            if (Application.OpenForms.Count == 1)
            {
                Application.Exit();
            }
        }
        #endregion
        
    }
}

 

Program.cs

namespace MyTextEditor
{
    internal static class Program
    {
        /// <summary>
        ///  The main entry point for the application.
        /// </summary>
        [STAThread]
        static void Main()
        {
            // To customize application configuration such as set high DPI settings or default font,
            // see https://aka.ms/applicationconfiguration.

            (new 메모장()).Show();
            Application.Run();
        }
    }
}
반응형