mfc로 만든 계산기 질문입니다

mfc로 만든 계산기 질문입니다

작성일 2022.08.20댓글 1건
    게시물 수정 , 삭제는 로그인 필요

안녕하세요 계산기를 만들어 보면서 mfc를 공부중입니다만
아무리 생각해봐도 막히는 부분이 있어서 질문을 하려고 합니다

아래 사진처럼 있는데 아래에 있는 에디트 컨트롤이 m_edit1 이고 위에 있는 에디트 컨트롤이 m_edit2 입니다


m_edit1 이 값만 출력되고 m_edit2는 계산과정만 출력되는.

지금은 다른 블로그에서 작성해주신걸 보고 만들었는데 제 식대로 바꿔보고 싶은데 이게 막혀서 한발짝도 못나가고 있습니다


첫번째로 키보드로 입력 받는걸 제가 구현을 해놨는데 이게 이상하게 출력이 됩니다 버튼으로 눌렀을땐 1 + 2 + 3 + 이런식으로 나오는데 

키보드로 저렇게 누르면 사진처럼 이상하게 나옵니다
키보드로 1 + 2 +3 눌렀을때


버튼으로 1 + 2 +3 눌렀을때



두번째는 숫자 버튼을 누르면 바로 m_edit2 에 출력되게 하고 싶은데 m_edit1에 먼저 출력이 되고 사칙연산 버튼을 눌러야 m_edit2에 눌러진 사칙연산과 함께 출력됩니다

m_edit1 에는 = 버튼을 눌렀을때 결과만이 나오게 하고 싶은데 이 부분도 제가 아는 선에서 여기저기 고쳐봤지만 결국 답이 안보입니다

예시를 곁들인 조언 부탁드립니다 도저히 답이 안보입니다....




// 0819Dlg.cpp : 구현 파일
//

#include "stdafx.h"
#include "0819.h"
#include "0819Dlg.h"
#include "afxdialogex.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#endif


// 응용 프로그램 정보에 사용되는 CAboutDlg 대화 상자입니다.

class CAboutDlg : public CDialogEx
{
public:
CAboutDlg();

// 대화 상자 데이터입니다.
enum { IDD = IDD_ABOUTBOX };

protected:
virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV 지원입니다.

// 구현입니다.
protected:
DECLARE_MESSAGE_MAP()
};

CAboutDlg::CAboutDlg() : CDialogEx(CAboutDlg::IDD)
{
}

void CAboutDlg::DoDataExchange(CDataExchange* pDX)
{
CDialogEx::DoDataExchange(pDX);
}

BEGIN_MESSAGE_MAP(CAboutDlg, CDialogEx)
END_MESSAGE_MAP()


// CMy0819Dlg 대화 상자



CMy0819Dlg::CMy0819Dlg(CWnd* pParent /*=NULL*/)
: CDialogEx(CMy0819Dlg::IDD, pParent)
{
m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}

void CMy0819Dlg::DoDataExchange(CDataExchange* pDX)
{
CDialogEx::DoDataExchange(pDX);
DDX_Control(pDX, IDC_EDIT1, m_edit1);
DDX_Control(pDX, IDC_EDIT2, m_edit2);
}

BEGIN_MESSAGE_MAP(CMy0819Dlg, CDialogEx)
ON_WM_SYSCOMMAND()
ON_WM_PAINT()
ON_WM_QUERYDRAGICON()
ON_BN_CLICKED(B_Plus, &CMy0819Dlg::OnBnClickedPlus)
ON_BN_CLICKED(B_Minus, &CMy0819Dlg::OnBnClickedMinus)
ON_BN_CLICKED(B_Divi, &CMy0819Dlg::OnBnClickedDivi)
ON_BN_CLICKED(B_Mult, &CMy0819Dlg::OnBnClickedMult)
ON_BN_CLICKED(B_Eq, &CMy0819Dlg::OnBnClickedEq)
ON_BN_CLICKED(B_Clear, &CMy0819Dlg::OnBnClickedClear)
END_MESSAGE_MAP()


// CMy0819Dlg 메시지 처리기

BOOL CMy0819Dlg::OnInitDialog()
{
CDialogEx::OnInitDialog();

// 시스템 메뉴에 "정보..." 메뉴 항목을 추가합니다.

// IDM_ABOUTBOX는 시스템 명령 범위에 있어야 합니다.
ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
ASSERT(IDM_ABOUTBOX < 0xF000);

CMenu* pSysMenu = GetSystemMenu(FALSE);
if (pSysMenu != NULL)
{
BOOL bNameValid;
CString strAboutMenu;
bNameValid = strAboutMenu.LoadString(IDS_ABOUTBOX);
ASSERT(bNameValid);
if (!strAboutMenu.IsEmpty())
{
pSysMenu->AppendMenu(MF_SEPARATOR);
pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
}
}

// 이 대화 상자의 아이콘을 설정합니다.  응용 프로그램의 주 창이 대화 상자가 아닐 경우에는
//  프레임워크가 이 작업을 자동으로 수행합니다.
SetIcon(m_hIcon, TRUE); // 큰 아이콘을 설정합니다.
SetIcon(m_hIcon, FALSE); // 작은 아이콘을 설정합니다.

// TODO: 여기에 추가 초기화 작업을 추가합니다.

return TRUE;  // 포커스를 컨트롤에 설정하지 않으면 TRUE를 반환합니다.
}

void CMy0819Dlg::OnSysCommand(UINT nID, LPARAM lParam)
{
if ((nID & 0xFFF0) == IDM_ABOUTBOX)
{
CAboutDlg dlgAbout;
dlgAbout.DoModal();
}
else
{
CDialogEx::OnSysCommand(nID, lParam);
}
}

// 대화 상자에 최소화 단추를 추가할 경우 아이콘을 그리려면
//  아래 코드가 필요합니다.  문서/뷰 모델을 사용하는 MFC 응용 프로그램의 경우에는
//  프레임워크에서 이 작업을 자동으로 수행합니다.

void CMy0819Dlg::OnPaint()
{
if (IsIconic())
{
CPaintDC dc(this); // 그리기를 위한 디바이스 컨텍스트입니다.

SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0);

// 클라이언트 사각형에서 아이콘을 가운데에 맞춥니다.
int cxIcon = GetSystemMetrics(SM_CXICON);
int cyIcon = GetSystemMetrics(SM_CYICON);
CRect rect;
GetClientRect(&rect);
int x = (rect.Width() - cxIcon + 1) / 2;
int y = (rect.Height() - cyIcon + 1) / 2;

// 아이콘을 그립니다.
dc.DrawIcon(x, y, m_hIcon);
}
else
{
CDialogEx::OnPaint();
}
}

// 사용자가 최소화된 창을 끄는 동안에 커서가 표시되도록 시스템에서
//  이 함수를 호출합니다.
HCURSOR CMy0819Dlg::OnQueryDragIcon()
{
return static_cast<HCURSOR>(m_hIcon);
}



BOOL CMy0819Dlg::OnCommand(WPARAM wParam, LPARAM lParam)
{
if (B_Number0 <= wParam&&wParam <= B_Number9)
{
CString str,str2, number_str;
number_str.Format(L"%d", wParam - B_Number0);

if (m_step == 0)
{
m_edit1.GetWindowTextW(str2);
}
else if (m_step == 1)
{
m_edit1.GetWindowTextW(str);
m_step = 0;
m_value = _wtof(str);
}
m_edit1.SetWindowTextW(str2 + number_str);

}
// TODO: 여기에 특수화된 코드를 추가 및/또는 기본 클래스를 호출합니다.

return CDialogEx::OnCommand(wParam, lParam);
}


void CMy0819Dlg::OnBnClickedPlus()
{
CString str, str2, str3, omg;
double m_value_two;

m_value_two = _ttoi(str2);
m_edit1.GetWindowTextW(str2);

m_edit1.GetWindowTextW(omg);
m_value_two = _wtof(omg);

m_count++;
if (m_count == 1)
{
m_value = m_value_two;
}
else
{
M_Operate(m_value_two);
}
m_operater_flag = 0;
m_step = 1;

m_edit1.GetWindowTextW(str2);
m_edit2.GetWindowTextW(str);
m_edit2.SetWindowTextW(str + str2 + "+");


omg.Format(L"%f", m_value);
omg.TrimRight(L"0");
omg.TrimRight(L".");
m_edit1.SetWindowTextW(omg);

// TODO: 여기에 컨트롤 알림 처리기 코드를 추가합니다.
}


void CMy0819Dlg::OnBnClickedMinus()
{
CString str, str2, omg;
double m_value_two;

m_value_two = _ttoi(str2);
m_edit1.GetWindowTextW(str2);

m_edit1.GetWindowTextW(omg);
m_value_two = _wtof(omg);

m_count++;
if (m_count == 1)
{
m_value = m_value_two;
}
else
{
M_Operate(m_value_two);
}
m_operater_flag = 1;
m_step = 1;

m_edit1.GetWindowTextW(str2);
m_edit2.GetWindowTextW(str);
m_edit2.SetWindowTextW(str + str2 + "-");


omg.Format(L"%f", m_value);
omg.TrimRight(L"0");
omg.TrimRight(L".");
m_edit1.SetWindowTextW(omg);
// TODO: 여기에 컨트롤 알림 처리기 코드를 추가합니다.
}


void CMy0819Dlg::OnBnClickedDivi()
{
CString str, str2, omg;
double m_value_two;

m_value_two = _ttoi(str2);
m_edit1.GetWindowTextW(str2);

m_edit1.GetWindowTextW(omg);
m_value_two = _wtof(omg);

m_count++;
if (m_count == 1)
{
m_value = m_value_two;
}
else
{
M_Operate(m_value_two);
}
m_operater_flag = 2;
m_step = 1;

m_edit1.GetWindowTextW(str2);
m_edit2.GetWindowTextW(str);
m_edit2.SetWindowTextW(str + str2 + "*");


omg.Format(L"%f", m_value);
omg.TrimRight(L"0");
omg.TrimRight(L".");
m_edit1.SetWindowTextW(omg);
// TODO: 여기에 컨트롤 알림 처리기 코드를 추가합니다.
}


void CMy0819Dlg::OnBnClickedMult()
{
CString str, str2, omg;
double m_value_two;

m_value_two = _ttoi(str2);
m_edit1.GetWindowTextW(str2);

m_edit1.GetWindowTextW(omg);
m_value_two = _wtof(omg);

m_count++;
if (m_count == 1)
{
m_value = m_value_two;
}
else
{
M_Operate(m_value_two);
}
m_operater_flag = 3;
m_step = 1;

m_edit1.GetWindowTextW(str2);
m_edit2.GetWindowTextW(str);
m_edit2.SetWindowTextW(str + str2 + "/");


omg.Format(L"%f", m_value);
omg.TrimRight(L"0");
omg.TrimRight(L".");
m_edit1.SetWindowTextW(omg);
// TODO: 여기에 컨트롤 알림 처리기 코드를 추가합니다.
}


void CMy0819Dlg::OnBnClickedEq()
{



CString str;
double m_value_two;
m_value_two = _wtof(str);
m_edit1.GetWindowTextW(str);
m_edit1.GetWindowTextW(str);

m_value_two = _wtof(str);


M_Operate(m_value_two);

m_count = 0;

str.Format(L"%f", m_value);
str.TrimRight(L"0");
str.TrimRight(L".");
m_edit1.SetWindowTextW(str);
// TODO: 여기에 컨트롤 알림 처리기 코드를 추가합니다.
}

void CMy0819Dlg::M_Operate(double m_value_two)
{
CString str, m_value_two2;
m_edit1.GetWindowTextW(m_value_two2);

double m_value_two1;

m_value_two1 = _ttoi(m_value_two2);


switch (m_operater_flag)
{
case 0:
m_value += m_value_two;
break;

case 1:
m_value -= m_value_two;
break;

case 2:
m_value *= m_value_two;
break;

case 3:
if (m_value_two != 0)
{
m_value /= m_value_two;
}
else
{
m_value = 0;
}
break;
}
}

void CMy0819Dlg::OnBnClickedClear()
{
UpdateData(TRUE);
m_edit1.SetWindowTextW(L" ");
m_edit2.SetWindowTextW(L" ");

m_value = 0;
m_step = 0;
m_operater_flag = 0;
m_count = 0;

UpdateData(FALSE);
// TODO: 여기에 컨트롤 알림 처리기 코드를 추가합니다.
}


BOOL CMy0819Dlg::PreTranslateMessage(MSG* pMsg)
{
// TODO: 여기에 특수화된 코드를 추가 및/또는 기본 클래스를 호출합니다.

switch (pMsg->message)
{
case WM_KEYDOWN:
switch (pMsg->wParam)
{
case VK_NUMPAD0: B_Number0; break;
case VK_NUMPAD1: B_Number1; break;
case VK_NUMPAD2: B_Number2; break;
case VK_NUMPAD3: B_Number3; break;
case VK_NUMPAD4: B_Number4; break;
case VK_NUMPAD5: B_Number5; break;
case VK_NUMPAD6: B_Number6; break;
case VK_NUMPAD7: B_Number7; break;
case VK_NUMPAD8: B_Number8; break;
case VK_NUMPAD9: B_Number9; break;
case VK_ADD: OnBnClickedPlus(); break;
case VK_SUBTRACT: OnBnClickedMinus(); break;
case VK_DIVIDE: OnBnClickedDivi(); break;
case VK_MULTIPLY: OnBnClickedMult(); break;
case VK_RETURN: OnBnClickedEq(); break; return true;
}
break;
}

return CDialogEx::PreTranslateMessage(pMsg);
}


#mfc로 만든 프로그램

profile_image 익명 작성일 -

첫번째에 대해서~~

키보드로 입력하는 경우, CMy0819Dlg::PreTranslateMessage( MSG *pMsg )에서 처리하는 것은 맞습니다.

PreTranslateMessage()에서 입력 받은 키를 처리한 후에 return TRUE 하면 키가 무시 되지만,

return FALSE 또는 return 0 하면 키 입력이 처리되지 않은 것으로 인식하고 버튼이나 에디트 컨트롤로 키보드 값이 전달 됩니다. 따라서 전달되지 않도록 해야 합니다.

switch (pMsg->message) { case WM_KEYDOWN: switch (pMsg->wParam) { case VK_NUMPAD0: B_Number0; break; case VK_NUMPAD1: B_Number1; break; case VK_NUMPAD2: B_Number2; break; case VK_NUMPAD3: B_Number3; break; case VK_NUMPAD4: B_Number4; break; case VK_NUMPAD5: B_Number5; break; case VK_NUMPAD6: B_Number6; break; case VK_NUMPAD7: B_Number7; break; case VK_NUMPAD8: B_Number8; break; case VK_NUMPAD9: B_Number9; break; case VK_ADD: OnBnClickedPlus(); break; case VK_SUBTRACT: OnBnClickedMinus(); break; case VK_DIVIDE: OnBnClickedDivi(); break; case VK_MULTIPLY: OnBnClickedMult(); break; case VK_RETURN: OnBnClickedEq(); break; return true; } break; }

위 코드는 숫자랑 사칙연산 처리 후에는 다 return TRUE 하도록 수정해야 합니다.

먼저 VK_NUMPAD 처리 부분은 아무 기능도 없습니다. B_Number? 는 버튼의 기호 정의로 단순한 숫자 입니다.

현재, 위 코드에서 B_Number? 에 대해서는 OnCommand() 함수에서 처리하고 있습니다. 따라서

case VK_NUMPAD0: OnCommand( B_Number0, 0 ) return TRUE;

이렇게 전부다 고쳐야 합니다. 그런데 VK_NUMPAD0~9는 순차적으로 존재하므로..

if( pMsg->wParam >= VK_NUMPAD0 && pMsg->wParam <= VK_NUMPAD9 ) { OnCommand( pMsg->wParam - VK_NUMPAD0 + B_Number0, 0 ); return TRUE; }

이렇게 하면 10개 키를 한꺼번에 처리할 수 있습니다.

NUMPAD 말고도 0~9 까지 숫자키도 있으므로..

if( pMsg->wParam >= '0' && pMsg->wParam <= '9' ) { OnCommand( pMsg->wParam - '0' + B_Number0, 0 ); return TRUE; }

이 코드도 추가하면 좋을 것입니다.

다음으로 사칙 연산 키 처리 부분은 처리후 return TRUE 하도록 수정합니다.

case VK_ADD: OnBnClickedPlus(); return TRUE; case VK_SUBTRACT: OnBnClickedMinus(); return TRUE; case VK_DIVIDE: OnBnClickedDivi(); return TRUE; case VK_MULTIPLY: OnBnClickedMult(); return TRUE; case VK_RETURN: OnBnClickedEq(); return TRUE;

이렇게 하면.. 첫번째 키보드 입력은 해결 됩니다.

두번째 EDIT1,2 바꿔 표기하는 부분은..

사칙 연산 함수와 숫자 처리 함수다 모두 EDIT1, 2의 값을 쓰기 때문에 고칠려면 숫자처리함수 사칙 연산 함수등 근본을 다 바꿔야 합니다. 즉, 수정 할 내용이 기존 내용 전부 삭제 후, 새 기능에 맞춰 만드는게 됩니다. 새로 만드는 것보다 더 복잡습니다.

차라리 수정하지 마시고 새로 만드시는게 정신 건강에 좋습니다.

수고하세요~~

MFC 프로그래밍 중 다른 프로그램이나...

... 있어서 질문합니다 예를 들어 저런식으로 계산기... 다른 mfc로 만든 프로그램을 보면 저런 동작이 가능해서 기능을 찾고싶어서 질문합니다 이런 기능을 명칭하거나...

2010 계산기 연동 계산하기질문이...

... 진짜 계산기같이 그래픽 있는 프로그램을 만드시려면 API나 MFC(전문 언어), visual basic(쉬운 언어) 등을 배우시는 것을 추천합니다. c언어로 만든 까만...

c++이후에 공부할책 추천좀여.

... api, mfc 를 배워야 합니다. 일단은 어떤 프로그램을 만들던간에. 심지어 계산기를 만들고, 전화번호부같은걸... 뒤에 만든 년도. 2003, 2005년을 붙이더군요. 질문추가 아...

c++ 제 꿈이 뒤바뀔지도 모른다는질문....

... 어떤분들은 '내가만든!!계산기 프로그램!!' 이러고 모... 저도 질문이 잘 이해가 안가기는 하지만 아마도... 0기반에서는 API와 MFC가있습니다 이걸 배우면 수월하게...

안드로이드 어플

... 생겨서 질문드립니다..! 어플만들기 위해서 어떤 공부... 언어) mfc(간단한 계산기까지 만들 수 있습니다.) 파이썬... 개발자계정으로 만든 후 냈더니 등록이 바로...

다음계산기 소스좀 고쳐주세요

다음 계산기 프로그램을 키보드에서 N을... printf("\n"); } } 그리고 님의 질문 추가 에 (Y/N)을... 님이나 만든사람이 아닌사람은 어떻게...