Авторские разработки С++ MFC

О проекте | Новости | Статьи | Исх.тексты | Отзывы | Форум | Главная

Пример простого калькулятора на MFC.

Зачем было сделано

Посмотрел я как-то текст простого калькулятора на Visual Basic и подумал, а как проще сделать калькулятор без программирования каждой клавиши отдельно. Естественно, используя классы. Данная программа является скорее каркасом для дальнейшей работы, чем полнофункциональным калькулятором. Такой есть в Windows и писать нечто подобное не имеет смысла. Но она может служить примером использования класса для вывода в диалоговое окно массива однотипных элементов, в частности кнопок.

Что это такое

Калькулятор выполняет простые арифметические действия и только. Однако, добавить новые действия ничего не стоит. Нужно лишь определить местоположение кнопки на экране и обработчик данного действия в самом калькуляторе. Как это сделать написано дальше.

 снимок экрана (4266 bytes)

Как это сделано.

За прорисовку и обработку нажатий кнопок отвечает класс CButt, который наследуется из библиотечного класса CButton. (Class Wizard->AddClass->New->BaseClass->CButton)

В него добавляем структруру RECT для задания местоположения  кнопки.

    // Generated message map functions
protected:
    RECT rect;
И ссылку на родительское окно, для последующей обработки
    CCalcDlg * w_Parent;
    //{{AFX_MSG(CButt)
    afx_msg void OnClicked();
    //}}AFX_MSG

Определяем метод OnClicked, ... (ClassWizard->ClassName->CButt->Messages->=BN_CLICKED->AddFunction)

который занимается тем, что передает в специальный обработчик вызывающего окна заголовок кнопки...

void CButt::OnClicked()
{
    CString Header;
    GetWindowText(Header);
    w_Parent->ObrNum(Header);
   
}
и переопределяем метод OnCreate(), который при создании кнопки принимает заголовок кнопки, ссылку на родительское окно и координату левого верхнего угла. Сами кнопки квадратные, 40 пиксел

BOOL CButt::Create(LPCTSTR lpszWindowName,CWnd * wnd,UINT nID,UINT top,UINT left)
{
    rect.left=left;
    rect.top=top;
    rect.right=left+40;
    rect.bottom=top+40;
    w_Parent=(CCalcDlg *)wnd;
    return CButton::Create(lpszWindowName, WS_CHILD |WS_VISIBLE, rect, wnd, nID);
}

Изменим класс родительского окна CalcDlg

class CCalcDlg : public CDialog
{
// Construction
public:
    double Operation(); // обработка действий
    void ObrNum(CString Num); // обработка нажатий клавиш
    CCalcDlg(CWnd* pParent = NULL);    // standard constructor
    CButt m_btn[17];  // всего кнопок
..............

В код CCalcDlg::OnInitDialog() добавим инициализацию кнопок

char buff[2];
    buff[1]=0;
    // создание и прорисовка числовых кнопок
    for (int i=0;i<10;i++){
        m_btn[i].Create(itoa(i,buff,10),this,10000+i,i>4?90:45,15+(45*(i<5?i:i-5)));
    }
    // равно
    m_btn[10].Create("=",this,10010,45*3,15+45*5);
    // точка и другие действия
    m_btn[11].Create(".",this,10011,45*3,15+45*0);
    m_btn[12].Create("/",this,10012,45*3,15+45*1);
    m_btn[13].Create("*",this,10013,45*3,15+45*2);
    m_btn[14].Create("+",this,10014,45*3,15+45*3);
    m_btn[15].Create("-",this,10015,45*3,15+45*4);
    m_btn[16].Create("C",this,10016,45,15+45*5);

Определим обработку нажатия кнопки

void CCalcDlg::ObrNum(CString Num)
{
    if (Num=="." && m_Num.Find('.')>=0){ // если точка уже нажата, то не вводить
        return;
    }
    if (Num=="C"){ // сброс
        m_Num="";
        m_Operation="";
        UpdateData(FALSE);
        UpdateWindow();
        return;
    }

    CString PossibleOperation("/+-*"); // если действие, то число и действие запоминаем и сбрасываем табло
    if (PossibleOperation.Find(Num)>=0){
        m_BuffNum=atof(m_Num);
        m_Num="";
        m_Operation=Num;
        UpdateData(FALSE);
        UpdateWindow();
        return;
    }
    double Buff=0;
    if (Num=="="){   // равно - обрабатываем, что получилось
        Buff=Operation();
        m_Num.Format("%f",Buff);
        m_Operation="";
        UpdateData(FALSE);
        UpdateWindow();
        return;
    }


    m_Num+=Num;  // все остальное выводим на табло
    UpdateData(FALSE);
    UpdateWindow();
}

Собственно действия

double CCalcDlg::Operation()
{
    double Buff=0;
    if (m_Operation=="+"){
            Buff=m_BuffNum+atof(m_Num);
        } else if (m_Operation=="-"){
            Buff=m_BuffNum-atof(m_Num);
        } else if (m_Operation=="/" && atof(m_Num)!=0){
            Buff=m_BuffNum/atof(m_Num);
        } else if (m_Operation=="*"){
            Buff=m_BuffNum*atof(m_Num);
        }
        return Buff;
}
   

Запускаем и наслаждаемся нажатием кнопочек. Однако, если действия вводятся с клавиатуры, то они вместо выполнения отображаются на табло. Но как этого избежать, как нибудь в другой раз.

Теперь для того, чтобы добавить новую кнопку, нужно:

  • увеличить массив кнопок     m_btn[17]; до 18.
  • добавить создание этой кнопки в OnInitDialog()
  • добавить действие в CString PossibleOperation("/+-*");
  • добавить его обработку в CCalcDlg::Operation()

И будет работать.
Возможно это не самый лучший пример, но главное - работающий

Программа и полный исходный текст

Скачать:  calc.zip         (105 Kb)  программа.

Скачать:  calc_src.zip    (38.5 Kb) исходные тексты к ней.

 

© Авторские разработки http://progcpp.narod.ru при цитировании ссылка обязательна.

Сайт создан в системе uCoz