외로운 Nova의 작업실

c# 계산기프로그램만들기 - 4 본문

Programming/C#

c# 계산기프로그램만들기 - 4

Nova_ 2022. 3. 22. 11:33

저번에 더하기 빼기만 있는 계산기프로그램을 만들어보았다.

이번에는 곱하기 나누기도 추가하고, 키보드와 계산기를 연결해볼것이다.

곱하기와 나누기를 추가하는것은 어렵지않았지만 키보드와 계산기를 연결하는것은 굉장히 어려웟다.

어려운 이유는 어떻게해야하는지 몰랐기 때문이다.

간략하게 설명하자면 enter버튼을 누르면 계산값이 나오게하고싶엇지만 막상해보면 마지막으로 누른 버튼이 계속 입력 되었다. 이 부분을 해결하는 부분이 어려웠다.

또한 키보드를 누르게되면 무엇이 키보드를 받는건지가 중요하다. 버튼이 키보드를 받을수 도 있지만 꼭 폼에 키보드를 입력해줘야한다. 또한 처음에 하게되면 키보드가 안먹히는데 이 안먹히는 이유도 아래에 간략하게 설명하겠다.

일단 아래는 계산기 모양이다.

나누기 버튼과 곱셈 버튼을 두었다.

구현하는 코드는 어렵지않았는데, 코드는 아래와 같다.

namespace CalCulator
{
    public partial class Form1 : Form
    {

        int result = 0;
        int gear = 0;// 빼기엿는지 더하기 엿는지 확인하는 변수 1-더하기 2-빼기 3-결과보기 result버튼 클릭시 이 변수를 확인해서 연산함public Form1()
        {
            InitializeComponent();
        }

//여기서부터는 내장 함수 정의private void WriteNumber(String Number)//숫자를 문자열로 넣으면 스크린에 문자를 넣어주는 함수,반환값은 없다
        {
            if (Screen.Text == "0")
            {
                Screen.Text = Number;
            }
            else if (gear == 5)
            {
                Screen.Text = Number;
                ChangeGear(0);
                result = 0;
            }
            else
            {
                Screen.Text += Number;
            }

            return;

        }

        private void Add()//스크린 숫자를 result변수에 더해줌
        {
            result = result + Convert.ToInt32(Screen.Text);

            return;
        }
        private void Sub()//스크린 숫자를 result변수에서 빼줌
        {
            result = result - Convert.ToInt32(Screen.Text);

            return;
        }
        private void Div()//스크린 숫자를 result변수에서 나눠줌
        {
            result = result / Convert.ToInt32(Screen.Text);

            return;
        }
        private void Multi()//스크린 숫자를 result변수에 곱해줌
        {
            result = result * Convert.ToInt32(Screen.Text);
        }
        private void ChangeGear(int Temp)
        {
            gear = Temp;
        }

        private void PreResultProcessing()
        {
            if (gear == 0)
            {
                Add();
            }
            else if (gear == 1)
            {
                Add();
            }
            else if (gear == 2)
            {
                Sub();
            }
            else if (gear == 3)
            {
                Div();
            }
            else if (gear == 4)
            {
                Multi();
            }

            return;
        }

//여기서부터는 숫자버튼 이벤트 함수 정의private void NumberButton1_Click(object sender, EventArgs e)
        {
            WriteNumber("1");
            FocusOnLabel.Focus();
        }

        private void NumberButton2_Click(object sender, EventArgs e)
        {
            WriteNumber("2");
            FocusOnLabel.Focus();
        }

        private void NumberButton3_Click(object sender, EventArgs e)
        {
            WriteNumber("3");
            FocusOnLabel.Focus();
        }

        private void NumberButton4_Click(object sender, EventArgs e)
        {
            WriteNumber("4");
            FocusOnLabel.Focus();

        }

        private void NumberButton5_Click(object sender, EventArgs e)
        {
            WriteNumber("5");
            FocusOnLabel.Focus();
        }

        private void NumberButton6_Click(object sender, EventArgs e)
        {
            WriteNumber("6");
            FocusOnLabel.Focus();
        }

        private void NumberButton7_Click(object sender, EventArgs e)
        {
            WriteNumber("7");
            FocusOnLabel.Focus();
        }

        private void NumberButton8_Click(object sender, EventArgs e)
        {
            WriteNumber("8");
            FocusOnLabel.Focus();
        }

        private void NumberButton9_Click(object sender, EventArgs e)
        {
            WriteNumber("9");
            FocusOnLabel.Focus();
        }

        private void NumberButton0_Click(object sender, EventArgs e)
        {
            WriteNumber("0");
            FocusOnLabel.Focus();
        }

//기호버튼 이벤트 함수 정의private void PlusButton_Click(object sender, EventArgs e)
        {
            PreResultProcessing();
            ChangeGear(1);

            Screen.Text = "0";

            FocusOnLabel.Focus();
        }

        private void MinusButton_Click(object sender, EventArgs e)
        {
            PreResultProcessing();
            ChangeGear(2);

            Screen.Text = "0";

            FocusOnLabel.Focus();
        }

        private void DivisionButton_Click(object sender, EventArgs e)
        {
            PreResultProcessing();

            ChangeGear(3);

            Screen.Text = "0";

            FocusOnLabel.Focus();
        }

        private void MultipleButton_Click(object sender, EventArgs e)
        {
            PreResultProcessing();

            ChangeGear(4);

            Screen.Text = "0";

            FocusOnLabel.Focus();
        }
        private void ResultButton_Click(object sender, EventArgs e)
        {

            PreResultProcessing();

            ChangeGear(5);

            Screen.Text = result.ToString();

            FocusOnLabel.Focus();
        }

        private void CancelButton_Click(object sender, EventArgs e)
        {
            result = 0;
            gear = 0;
            Screen.Text = "0";

            MessageBox.Show("계산기가 초기화 되었습니다");

            FocusOnLabel.Focus();
        }
    }
}

나누기,곱샘함수를 만들고, 버튼이 눌러졋을때 기어를 바꾸고 합산을 하거나 다른 연산기호를 눌렀을때 기어에 맞는 연산 함수가 호출되게 구현하였다.

이번에는 키보드랑 버튼을 연동해볼 차례인데 코드는 아래와같다.

//여기서부터는 키보드랑 버튼 연동 함수private void Form1_KeyDown(object sender, KeyEventArgs e)

        {
            switch (e.KeyCode)
            {
                case Keys.Enter:
                    ResultButton_Click(sender, e);
                    break;
                case Keys.D0:
                    NumberButton0_Click(sender, e);
                    break;
                case Keys.NumPad1:
                    NumberButton1_Click(sender, e);
                    break;
                case Keys.NumPad2:
                    NumberButton2_Click(sender, e);
                    break;
                case Keys.NumPad3:
                    NumberButton3_Click(sender, e);
                    break;
                case Keys.NumPad4:
                    NumberButton4_Click(sender, e);
                    break;
                case Keys.NumPad5:
                    NumberButton5_Click(sender, e);
                    break;
                case Keys.NumPad6:
                    NumberButton6_Click(sender, e);
                    break;
                case Keys.NumPad7:
                    NumberButton7_Click(sender, e);
                    break;
                case Keys.NumPad8:
                    NumberButton8_Click(sender, e);
                    break;
                case Keys.NumPad9:
                    NumberButton9_Click(sender, e);
                    break;
                case Keys.Add:
                    PlusButton_Click(sender, e);
                    break;
                case Keys.Subtract:
                    MinusButton_Click(sender, e);
                    break;
                case Keys.Multiply:
                    MultipleButton_Click(sender, e);
                    break;
                case Keys.Divide:
                    DivisionButton_Click(sender, e);
                    break;
                default:
                    break;
            }

중요한점은 키다운 이벤트를 폼에 적용시켜야한다는점이다.

이렇게 코드를 쓰는데, 필요한 지식은 아래와 같다

e.KeyCode = 어떤 키가 눌렸는지에대한 변수이다

Keys. = 각 키보드 키값에대한 객체이다.

ex) Keys.D0 = 0번 버튼을 의미하는것이다.

Keys 객체에대한 여러가지 버튼들은 아래 주소에서 확인할 수 있다.

https://docs.microsoft.com/ko-kr/dotnet/api/system.windows.forms.keys?redirectedfrom=MSDN&view=netframework-4.7.2

Keys 열거형 (System.Windows.Forms) 키 코드와 한정자를 지정합니다. docs.microsoft.com

또한 저렇게 코드를 쓰고 실행시켜보면 키보드가 안먹는다. 이는 키보드랑 폼 이벤트랑 연동을 안시켜줘서 그렇다. 코드는 작성되어있지만 물리적으로 키보드랑 폼이벤트랑 연동이 안되어있는 상황인데, 이는 간편하게 폼 속성에서 KeyPreview 속성을 true로 변경해주면 연동이 되어진다.

이후 버튼을 누르게되면 동작을 하게되는데, 여기서 문제가 발생한다. 코드에서처럼 enter키를 누르면 결과값이 도출되어야하는데 실제로 해보면 방금전에 눌럿던 버튼이나 포커싱이 가있는 버튼이 계속 입력된다는 것이다.

이를 해결하는데 정말 많은 시간이 걸렷다. 결국 외국 영상을 참조해서 해결했는데, 그 방법은 키 다운시 label에 포커싱이 가게 하는것이다. 위 계산기 사진에보면 가운데 쪽에 레이블이 하나 빈칸으로 있는데 거기에 포커싱을 가게하는것이다. 레이블에 포커싱을 가게해도 입력 커서가 안뜬다.

아래는 관련 코드와 관련 영상이다.

   private void DivisionButton_Click(object sender, EventArgs e)
        {
            PreResultProcessing();

            ChangeGear(3);

            Screen.Text = "0";

            FocusOnLabel.Focus();//키를 누른다음에 아무것도 없는 레이블로 포커싱을 가게한다
        }

https://www.youtube.com/watch?v=i_2hjwLrDDU&t=407s

적용시켜보면 아주 잘된다는것을 알 수 있다.

다음에는 이전에 햇던 계산기록들과 어떤 연산을 입력시켜놓았는지 알려주는 부분을 만들어볼 생각이다.

근데 실수형 처리를 할때는 어떻게 하면 좋을지 잘 생각이안난다.

screen.text에 소수점이 있으면 실수형인데 소수점이 있는지 없는지 판단해주는 함수가 있을까?

한번 찾아보야겟다.

Comments