MFC C++ Projects - 2003 .NET                               

   Contact
   C
   C++
   Visual Basic
   Java
   JavaScript
   DHTML
   Style Sheets
   About
   Normalization
   Active X
   TDC Binding
   PHP
   Perl and CGI
   Flash
   XML
   SQL
   Chat
   MCSE
   Linux
   Cabling   
 

   
 
    
    
C++ Win 32 Project 1:   MFC Calculator Binary Executable:  MFCcalculator.exe

Objective:  This project will compile to produce a simple calculator using the MFC.  As you debug, look at how pointers are used along with MFC member functions to communicate with the Windows API.  This project will consist of 4 files. Don't forget that you must go to your Visual C++ menu and select:  Project -> Settings -> Microsoft Foundation Classes and then select "Use MFC in a shared DLL" and click "OK".

1. Launch your Visual C++ compiler.
2. Select  File->New  and then select "Win 32 Application" from the list of available options.
3. In the Project Name box, type "Calculator".
4. Click "OK".  On the next screen, make sure "Create an Empty Project" is selected and click "Finish".
5. The compiler will tell you it is creating a new skeleton project.  Select "OK" to continue.
6. Add files to the project.  Click File->New and select "C/C++ Header File" for the files below with the ".h" extension.  Select "C++
    Source File" for the files with the ".cpp" extension, and "Text File" for files with the ".rc" extension.  Do not forget to reformat
    text that wraps around multiple lines in the HTML.  This will create errors in your C++ programs unless this text is placed on the
    same line.
7. Then paste the code in the HTML tables below into the appropriate C++ project files.
8. Click Project->Settings and select "Use MFC in a Shared DLL" from the combobox.  Click "OK".
9. Rebuild, compile and link.

 File 1: resource.h

// ©2004 C. Germany File 1 of 3.  Type this into a file and save it as "resource.h". 
// Defines Message Numbers.  Don't forget to add a carriage return after the last #define!
//{{NO_DEPENDENCIES}}
// Microsoft Visual C++ generated include file.
// Used by Calculator.rc
//
#define IDD_Calculator                  101
#define IDR_MENU1                       102
#define IDC_INPUTOUTPUT                 1001
#define IDC_1                           1002
#define IDC_2                           1003
#define IDC_3                           1004
#define IDC_4                           1005
#define IDC_5                           1006
#define IDC_6                           1007
#define IDC_7                           1008
#define IDC_8                           1009
#define IDC_9                           1010
#define IDC_0                           1011
#define IDC_PERIOD                      1012
#define IDC_PLUSMINUS                   1013
#define IDC_SQUAREROOT                  1013
#define IDC_PLUS                        1014
#define IDC_ADD                         1014
#define IDC_MINUS                       1015
#define IDC_SUBTRACT                    1015
#define IDC_MULTIPLY                    1016
#define IDC_DIVIDE                      1017
#define IDC_EQUALS                      1018
#define IDC_SQUARE                      1019
#define IDC_CUBE                        1020
#define IDC_ERASE                       1021
#define IDC_MEMORY1                     1022
#define IDC_MEMORY2                     1023
#define IDC_CEL                         1024
#define IDC_CEL2                        1025
#define IDC_FAR                         1025
#define IDC_BUTTON1                     1026
#define IDC_QUIT                        1026
#define IDC_POWER                       1027
#define ID_FILE_EXIT                    40001
#define ID_OTHER_HELP                   40002
#define ID_OTHER_ABOUT                  40003

// Next default values for new objects
// 
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NEXT_RESOURCE_VALUE        103
#define _APS_NEXT_COMMAND_VALUE         40004
#define _APS_NEXT_CONTROL_VALUE         1027
#define _APS_NEXT_SYMED_VALUE           101
#endif
#endif
Notice that the file above is once again defining our message identifiers, so that later we can listen for them and they can be used to launch message handlers.

File 2: calculator.cpp

// File 2 of 3.  The "WinMain()" portion of the calculator program with MFC dialog box
// Save as "calculator.cpp"

//-----------------------------------------------------------------------------------------
#include <afxwin.h>     // MFC core and standard components
#include "resource.h"   // main symbols
#include <cmath>
//-----------------------------------------------------------------------------------------

// File 2 of 3.  The "WinMain()" portion of the calculator program with MFC dialog box
// Save as "calculator.cpp"

//-----------------------------------------------------------------------------------------
#include <afxwin.h>     // MFC core and standard components
#include <afxcmn.h>	// Additional MFC components
#include "resource.h"   // main symbols
#include <cmath>
//-----------------------------------------------------------------------------------------

//Globals
CEdit * InputOutput;
double Number1;
double Number2;
double Result;
double Memory;
bool NextExpression;
bool NeedToClear;
bool ClickedEquals;
bool PasteMemory;
char oper; 

class Calculator : public CDialog
{
    public:
    Calculator(CWnd* pParent = NULL): CDialog(Calculator::IDD, pParent) {    }

    // Dialog Data, name of dialog form
    enum{IDD = IDD_Calculator};

    CBrush CalculatorBrush;

    //--------------------------------------------------------

    //Called right after constructor. Initialize things here.
    virtual BOOL OnInitDialog() 
    { 
            CDialog::OnInitDialog();
            InputOutput = (CEdit *) GetDlgItem(IDC_InputOutput);
	        CalculatorBrush.CreateSolidBrush(RGB(255, 255, 255));
            NextExpression = false;
	        NeedToClear = false;
	        ClickedEquals = false;
	        PasteMemory = false;
	        Number1 = 0.0; 
	        Number2 = 0.0; 
	        Result = 0.0;
	        Memory = 0.0;
	        oper = ' ';
            return true; 
    }

    //--------------------------------------------------------

   afx_msg HBRUSH OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor)
   {
      switch (nCtlColor) 
      {
	          case CTLCOLOR_EDIT:   pDC->SetTextColor(RGB(255,0,255));
              case CTLCOLOR_STATIC: pDC->SetTextColor(RGB(255,0,255));
              case CTLCOLOR_DLG:    return CalculatorBrush;
              default:  return CDialog::OnCtlColor(pDC, pWnd, nCtlColor);
      }
   }

//--------------------------------------------------------

//To Get Keyboard Messages and bypass buggy CDialog MFC Keyboard Message Handlers 

BOOL PreTranslateMessage(MSG* pMsg) 
{
      if(pMsg->message == WM_KEYDOWN) 
	  {            
            int nVirtKey = (int) pMsg->wParam;

            if(nVirtKey == VK_UP) { MessageBox("Up Key Pressed!"); }
            if(nVirtKey == VK_DOWN) { MessageBox("Down Key Pressed!"); }
            //if(nVirtKey == 65) { MessageBox("The \"a\" Key Was Pressed!"); }

            if(nVirtKey == '\r')  { Equals(); }
            if(nVirtKey == 43)    { MessageBox("+!"); Calculate('a'); } //PLUS
			if(nVirtKey == 45)    { Calculate('s'); } //MINUS
			if(nVirtKey == 42)    { Calculate('m'); } //MULTIPLY
			if(nVirtKey == 47)    { Calculate('d'); } //DIVIDE
            if(nVirtKey == 61)    { Equals(); }       //EQUALS
      }
      
      return CDialog::PreTranslateMessage(pMsg);

      //See ASCII Chart at Bottom for codes
}

//--------------------------------------------------------

    //Message Handlers for Dialog class object
	afx_msg void key0() { KeyNumber("0"); }
	afx_msg void key1() { KeyNumber("1"); }
	afx_msg void key2() { KeyNumber("2"); }
	afx_msg void key3() { KeyNumber("3"); }
	afx_msg void key4() { KeyNumber("4"); }
	afx_msg void key5() { KeyNumber("5"); }
	afx_msg void key6() { KeyNumber("6"); }
	afx_msg void key7() { KeyNumber("7"); }
	afx_msg void key8() { KeyNumber("8"); }
	afx_msg void key9() { KeyNumber("9"); }
	afx_msg void keyPeriod() { KeyNumber("."); }
	afx_msg void keyEquals() { Equals(); }
	afx_msg void keyAdd() { Calculate('a'); }
	afx_msg void keySubtract() { Calculate('s'); }
	afx_msg void keyMultiply() { Calculate('m'); }
	afx_msg void keyDivide() { Calculate('d'); }
	afx_msg void keyPower() { Calculate('p'); }
	afx_msg void keyCube() { Cube(); }
	afx_msg void keySquare() { Square(); }
	afx_msg void keySquareRoot() { SquareRoot(); }
	afx_msg void keyMemory() { MemoryKey(); }
	afx_msg void EraseMemory() { MemoryClear(); }
	afx_msg void keyCE() { Erase(); }
	afx_msg void keyFarenheit() { CelciusToFarenheit(); }
	afx_msg void keyCelcius() { FarenheitToCelcius(); }
	afx_msg void keyMiles() { MilesToKilometers(); }
	afx_msg void keyKilometers() { KilometersToMiles(); }
	afx_msg void Quit() { EndDialog(IDOK); }

    //--------------------------------------------------------
	
	afx_msg void About() 
	{  
	        MessageBox("Calculator 3.0 - 2006 - C. Germany", "Calculator 3.0 - HELP");
	}

    //--------------------------------------------------------

	afx_msg void Help() 
	{ 
            char HELPTEXT[5][55] = { 
				 "This program is a fully functional calculator.\r\n",
			     "It was created as an MFC tutorial for students.\n",
				 "Its purpose is to display the logic processes\n",
				 "and progam flow between the user interface and \n",
				 "processing of input through the MFC CEdit control."
	             };

            char Message[280] = ""; 

	    for(int z = 0; z < 5; z++)
            { strncat(Message, HELPTEXT[z], 55); }

	    MessageBox(Message, "Calculator 3.0 - HELP");
	}
	
    //--------------------------------------------------------

    //Calculator Functions
	void KeyNumber(char x[1])
	{
	     if(NeedToClear) 
	     { 
                InputOutput->SetWindowText(""); 
                NeedToClear = false; 
             }

             char num[21] = "";
             InputOutput->GetWindowText(num, 20);
	     strncat(num,x,20);
	     InputOutput->SetWindowText(num);
	}

    //--------------------------------------------------------

    void Calculate(char op)
    {
         oper = op;
         char num[21];
         InputOutput->GetWindowText(num,20);

         if(NextExpression)
         {
	       if(!ClickedEquals)
	       {
                 Number2 = atof(num);

                 switch(oper)
                 {
                     case 'a' : Number1 = Number1 + Number2; break;
                     case 's' : Number1 = Number1 - Number2; break;
                     case 'm' : Number1 = Number1 * Number2; break;
					 case 'd' : if(Number2 == 0) { Number1 = 0; }
								else { Number1 = Number1 / Number2; } 
								break;
                     case 'p' : Number1 = pow(Number1,Number2); break;
                     default : break;
                 }
                  
                   char Answer[20];
			  
		   //itoa(Number1, Answer, 10); //Converts int, but truncates decimal
                   //Instead, use sprintf() to convert double or double to string
	           sprintf(Answer,"%g",Number1);
                   InputOutput->SetWindowText(Answer);
		   NeedToClear = true;
	        }

	     else { ClickedEquals = false; }
       }

       else
       {
	       Number1 = atof(num);
	       NeedToClear = true;
	       NextExpression = true;
       }

    }//close Calculate()

    //--------------------------------------------------------

    void Equals() 
    { 
	 Calculate(oper);
	 NeedToClear = true;
	 ClickedEquals = true;
    }

    //--------------------------------------------------------

    void Erase()
    {
         InputOutput->SetWindowText("");
         NextExpression = false;
	 NeedToClear = false;
	 ClickedEquals = false;
	 Number1 = 0.0; 
	 Number2 = 0.0; 
	 Result = 0.0;
	 oper = ' ';
    }

    //--------------------------------------------------------

    void Cube()
    {
         char num[20] = ""; 
	 double numtemp = 0.0;
	 InputOutput->GetWindowText(num, 10);
	 numtemp = atof(num);
         numtemp = numtemp * numtemp * numtemp;
	 sprintf(num,"%g",numtemp);
	 InputOutput->SetWindowText(num);
    }

    //--------------------------------------------------------

    void Square()
    {
         char num[20] = ""; 
	 double numtemp = 0.0;
	 InputOutput->GetWindowText(num, 10);
	 numtemp = atof(num);
         numtemp = numtemp * numtemp;
	 sprintf(num,"%g",numtemp);
	 InputOutput->SetWindowText(num);
    }

    //--------------------------------------------------------

    void SquareRoot()
    {
	 char num[20] = "";
	 InputOutput->GetWindowText(num, 10);
	 Number1 = atof(num);
	 Number1 = sqrt(Number1);
         sprintf(num,"%g",Number1);
	 InputOutput->SetWindowText(num);
    }

    //--------------------------------------------------------

    void MemoryKey()
    {
         char num[20] = "";

         if(PasteMemory)
	 {
              sprintf(num,"%g",Memory);
	      InputOutput->SetWindowText(num);
	 }

	 else
	 {
             InputOutput->GetWindowText(num, 10);
             Memory = atof(num);
	     PasteMemory = true;
	 }
    }

    //--------------------------------------------------------

    void MemoryClear() 
    { 
	 PasteMemory = false; 
	 Memory = 0.0; 
    }

    //--------------------------------------------------------

    void CelciusToFarenheit()
    {
         char num[20];    
         InputOutput->GetWindowText(num, 15);
	 double Farenheit = atof(num);
	 Farenheit = (Farenheit * 9 / 5) + 32;
         sprintf(num,"%g",Farenheit);    
         InputOutput->SetWindowText(num);
    }

//-------------------------------------------------------------

    void FarenheitToCelcius()
    {
         char num[20];    
         InputOutput->GetWindowText(num, 15);
	 double Celcius = atof(num);
	 Celcius = ((Celcius - 32) * 5) / 9;
         sprintf(num,"%g",Celcius);     
         InputOutput->SetWindowText(num);
    }
//-------------------------------------------------------------

    void KilometersToMiles()
    { 
	 char num[20] = "";
	 InputOutput->GetWindowText(num,10);
	 double x = atof(num);
	 x = x / 1.609347;
	 sprintf(num,"%g",x);
	 InputOutput->SetWindowText(num);
    }
//-------------------------------------------------------------

    void MilesToKilometers()
    { 
	 char num[20] = "";
	 InputOutput->GetWindowText(num,10);
	 double x = x * 1.609347; 
	 sprintf(num,"%g",x);
	 InputOutput->SetWindowText(num);
    }
//-------------------------------------------------------------

DECLARE_MESSAGE_MAP()

}; //closing class specification
//----------------------------------------------------------


BEGIN_MESSAGE_MAP(Calculator, CDialog)
           
      ON_WM_CTLCOLOR()           //Listen for and map COLOR events
      ON_COMMAND(IDC_Num0, key0)
      ON_COMMAND(IDC_Num1, key1)
      ON_COMMAND(IDC_Num2, key2)
      ON_COMMAND(IDC_Num3, key3)
      ON_COMMAND(IDC_Num4, key4)
      ON_COMMAND(IDC_Num5, key5)
      ON_COMMAND(IDC_Num6, key6)
      ON_COMMAND(IDC_Num7, key7)
      ON_COMMAND(IDC_Num8, key8)
      ON_COMMAND(IDC_Num9, key9)
      ON_COMMAND(IDC_Num7, key7)
      ON_COMMAND(IDC_Num8, key8)
      ON_COMMAND(IDC_Num9, key9)
      ON_COMMAND(IDC_NumPeriod, keyPeriod)
      ON_COMMAND(IDC_NumEquals, keyEquals)
      ON_COMMAND(IDC_NumAdd, keyAdd)
      ON_COMMAND(IDC_NumSubtract, keySubtract)
      ON_COMMAND(IDC_NumMultiply, keyMultiply)
      ON_COMMAND(IDC_NumDivide, keyDivide)
      ON_COMMAND(IDC_NumCube, keyCube)
      ON_COMMAND(IDC_NumSquare, keySquare)
      ON_COMMAND(IDC_NumSquareRoot, keySquareRoot)
      ON_COMMAND(IDC_POWER,keyPower)
      ON_COMMAND(IDC_NumMemory, keyMemory)
      ON_COMMAND(IDC_MemoryErase, EraseMemory)
      ON_COMMAND(IDC_NumCE, keyCE)
      ON_COMMAND(IDC_Farenheit, keyFarenheit)
      ON_COMMAND(IDC_Celcius, keyCelcius)
      ON_COMMAND(IDC_Miles, keyMiles)
      ON_COMMAND(IDC_Kilometers, keyKilometers)
      ON_COMMAND(IDC_QUIT, Quit)
      ON_COMMAND(ID_FILE_EXIT,Quit)
      ON_COMMAND(ID_OTHER_HELP,Help)
      ON_COMMAND(ID_OTHER_ABOUT,About)

END_MESSAGE_MAP()

//----------------------------------------------------------

//----------------------------------------------------------

class Calc : public CWinApp
{

public:
Calc() {  }

virtual BOOL InitInstance()
{
        CWinApp::InitInstance();
        Calculator x;
        m_pMainWnd = &x;
        INT_PTR nResponse = x.DoModal();
        return FALSE;
} //close function

   DECLARE_MESSAGE_MAP()       

};
//----------------------------------------------------------

BEGIN_MESSAGE_MAP(Calc, CWinApp)
END_MESSAGE_MAP()

//----------------------------------------------------------

Calc SuperFun;


/*
sprintf() builds and formats a string from a number you pass into it. Arguments are:
------------------------------------------------------------------------------------
c = Character a 
d  = or i Signed decimal integer 392 
e = Scientific notation (mantise/exponent) using e character 3.9265e+2 
E = Scientific notation (mantise/exponent) using E character 3.9265E+2 
f = Decimal floating point 392.65 
g = Use the shorter of %e or %f 392.65 
G = Use the shorter of %E or %f 392.65 
o = Signed octal 610 
s = String of characters sample 
u = Unsigned decimal integer 7235 
x = Unsigned hexadecimal integer 7fa 
X = Unsigned hexadecimal integer (capital letters) 7FA 
p = Pointer address B800:0000 
n = Nothing printed. The argument must be a pointer to a signed int, 
   where the number of characters written so far is stored.  
% = A % followed by another % character will write % to the string. 

EXAMPLE:
  char buffer [50];
  int n, a=5, b=3;
  n=sprintf (buffer, "%d plus %d is %d", a, b, a+b);
  printf ("[%s] is a %d char long string\n",buffer,n);

------------------------------------------------------------------------------------

Mouse and Keyboard Message Macros and Their Handlers:

      //ON_WM_LBUTTONDOWN( )    //Listen for LEFT mouse button click
	  //ON_WM_KEYDOWN()         //Keyboard Events
	  //ON_WM_KEYUP()           //Keyboard Events
      //ON_WM_CHAR()            //Keyboard Events

   afx_msg void OnKeyDown(UINT uChar, UINT uRepCnt, UINT uFlg)
   {
           //char x[1];
		   //x[0] = (char)uChar;
		   //MessageBox(x);
           MessageBox("MADE IT to OnChar()!");
   
           switch(uChar) 
           {
                 case '\r': Equals(); break;
                 case '\b': Erase(); break;
				 case '+' : Calculate('a'); break;
                 case '-': Calculate('s'); break;
                 case '*': Calculate('m'); break;
				 case '/' : Calculate('d'); break;
                 case '=' : Equals(); break;
				 case 'a' : MessageBox("Heard an A!"); break;
				 default : break;
		   }

   }

   afx_msg void buttonPushed()
   {
           MessageBox("MADE IT HERE in buttonPushed()!");
   }

   afx_msg void OnLButtonDown( UINT, CPoint )
   {
	       MessageBox("Mouse Clicked!", "Event Triggered");
   }

ASCII Values for PreTranslate Messages
//-----------------------------------------------------
Decimal      Character     Description 
0               NUL  
1               SOH         start of header 
2               STX         start of text 
3               ETX         end of text 
4               EOT         end of transmission 
5               ENQ         enquiry 
6               ACK         acknowledge 
7               BEL         bell 
8               BS          backspace 
9               HT          horizontal tab 
10              LF          line feed 
11              VT          vertical tab 
12              FF          form feed 
13              CR          carriage return 
14              SO          shift out 
15              SI          shift in 
16              DLE         data link escape 
17              DC1         no assignment, but usually XON 
18              DC2  
19              DC3         no assignment, but usually XOFF 
20              DC4  
21              NAK         negative acknowledge 
22              SYN         synchronous idle 
23              ETB         end of transmission block 
24              CAN         cancel 
25              EM          end of medium 
26              SUB         substitute 
27              ESC         escape 
28              FS          file seperator 
29              GS          group seperator 
30              RS          record seperator 
31              US          unit seperator 
32              SPC         space 
33  !  
34  "  
35  #  
36  $  
37  %  
38  &  
39  '  
40  (  
41  )  
42  *  
43  +  
44  ,  
45  -  
46  .  
47  /  
48  0  
49  1  
50  2  
51  3  
52  4  
53  5  
54  6  
55  7  
56  8  
57  9  
58  :  
59  ;  
60  <  
61  =  
62  >  
63  ?  
64  @  
65  A  
66  B  
67  C  
68  D  
69  E  
70  F  
71  G  
72  H  
73  I  
74  J  
75  K  
76  L  
77  M  
78  N  
79  O  
80  P  
81  Q  
82  R  
83  S  
84  T  
85  U  
86  V  
87  W  
88  X  
89  Y  
90  Z  
91  [  
92  \  
93  ]  
94  ^  
95  _  
96  `  
97   a  
98   b  
99   c  
100  d  
101  e  
102  f  
103  g  
104  h  
105  i  
106  j  
107  k  
108  l  
109  m  
110  n  
111  o  
112  p  
113  q  
114  r  
115  s  
116  t  
117  u  
118  v  
119  w  
120  x  
121  y  
122  z  
123  {  
124  |  
125  }  
126  ~  
127  DEL delete 

//-----------------------------------------------------------------------------

*/
In the file above, this time we derive from the CDialog class instead of the CFrameWnd class.  We must choose either CFrameWnd or CDialog to derive from, but in this instance we choose CDialog, since we will need to receive user input in the window we create.   We define the "Calculator" class specification, which derives from the CDialog class. 

Calculator's constructor specifies the name of the resource file to use for this project, passing it in as the string argument "CALCULATOR".

Next, we prototype our message handler functions inside the class specification.  They will be defined outside, in the source file.  Notice that each message handler function is prefixed with "afx_msg", indicating it is a special message handler function, as opposed to a normal one.

Finally, we declare our mandatory message map, since we are using a resource file, by writing "DECLARE_MESSAGE_MAP".

In the source file above, we begin by defining message handler functions for each of the buttons in our resource file, and each message handler corresponds to a calculator function.  Here we introduce the CEdit object, a textbox which the user can type input into.  This input is received as string data, and so ultimately it is an ASCII char array.  Since this is the case, if we want to perform calculations on what the user types in, we must take what we receive as string data and convert it to an integer, float, double or long data type.

We convert this string data to an integer using the atoi() function.  With the atoi() function, any string data that you pass to it as an argument will be converted to an integer.  Since CEdit boxes only display string data, we will have to use the opposite of atoi(), which is the itoa() function.   The itoa() function reverses the process and converts the integer data back into a char array.  This string data can then be displayed.

In order to retrieve the values typed into the CEdit controls, we must first find their addresses by invoking the GetDlgItem() function, which is then cast to a pointer to a CEdit object and then assigned to a pointer to a CEdit object.  The reason that we have to explicitly cast the pointer to a CEdit object on the right side of the assignment operator (using parentheses) before assigning it to our CEdit pointer on the left side of the assignment operator is interesting.  We are actually casting a base class pointer (a pointer to a CWnd class object) to a derived class pointer (a pointer to a CEdit class object).  We must call GetDlgItem() each time the message handler is called, since objects will go out of scope each time windows are deleted and created.  We don't want our pointers to end up pointing to objects that have fallen out of scope and therefore no longer exist. 

GetDlgItem() merely sets up pointers to the CEdit objects.  In order to access the text from these items, we must use the GetWindowText() function.  GetWindowText() is inherited from CWnd.  It retrieves the string data in the text box so that it can then be assigned to a char array.  The length of our char array must correspond to the length of the textbox specified in the resource file.  We add one for a terminating NULL.

Later, we must use SetWindowText(), also derived from CWnd, to place our text string back into the CEdit objects.  We then call the function, SetFocus(), to move the cursor back into the CEdit text box so that the user can enter another value.  

 Finally, we create a class, "CalculatorApplication" that derives from our mandatory CWinApp class.  Inside this class specification, we have changed the "boilerplate code" used in previous examples that we would normally place inside InitInstance().  Here, we:

  • Create an instance of Calculator which derives from the CDialog class
  • Call DoModal(), which makes the application modal (no other windows allowed until this window is closed)
  • The value "FALSE" will be returned to indicate that the application has ended

  We then instantiate an object of our class in order to launch the window and run the application. 


 File 3: calculator.rc

//File 3 of 3. Resource file for the project (all the visual MFC //stuff).
//This was done using the visual editor.  After clicking your way into glory,
//you can save it as "calculator.rc" file and open it in a text editor.

#include "resource.h"
#include "afxres.h"

IDD_Calculator DIALOGEX 0, 0, 217, 143
STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | 
    WS_SYSMENU
CAPTION "Calculator 3.0 - 2006 C. Germany "
MENU IDR_MENU1
FONT 8, "MS Shell Dlg", 400, 0, 0x1
BEGIN
    EDITTEXT        IDC_INPUTOUTPUT,10,11,197,15,ES_RIGHT | ES_AUTOHSCROLL | 
                    ES_NUMBER
    PUSHBUTTON      "1",IDC_1,16,76,18,15
    PUSHBUTTON      "2",IDC_2,38,76,18,15
    PUSHBUTTON      "3",IDC_3,60,76,18,15
    PUSHBUTTON      "4",IDC_4,16,57,18,15
    PUSHBUTTON      "5",IDC_5,38,57,18,15
    PUSHBUTTON      "6",IDC_6,60,57,18,15
    PUSHBUTTON      "7",IDC_7,16,39,18,15
    PUSHBUTTON      "8",IDC_8,38,39,18,15
    PUSHBUTTON      "9",IDC_9,60,39,18,15
    PUSHBUTTON      "0",IDC_0,16,94,18,15
    PUSHBUTTON      ".",IDC_PERIOD,60,94,18,15
    PUSHBUTTON      "Sq&Rt",IDC_SQUAREROOT,180,77,18,15
    GROUPBOX        "Numeric",IDC_STATIC,10,28,76,86,BS_CENTER
    PUSHBUTTON      "&+",IDC_ADD,99,41,18,15
    PUSHBUTTON      "&-",IDC_SUBTRACT,99,59,18,15
    PUSHBUTTON      "&*",IDC_MULTIPLY,99,77,18,15
    PUSHBUTTON      "&/",IDC_DIVIDE,99,95,18,15
    GROUPBOX        "Operator",IDC_STATIC,89,28,38,87,BS_CENTER
    PUSHBUTTON      "&=",IDC_EQUALS,38,94,18,15
    PUSHBUTTON      "&Sq",IDC_SQUARE,180,41,18,15
    PUSHBUTTON      "C&u",IDC_CUBE,180,59,18,15
    PUSHBUTTON      "&CE",IDC_ERASE,139,42,18,15
    GROUPBOX        "Function",IDC_STATIC,130,28,38,87,BS_CENTER
    PUSHBUTTON      "M1",IDC_MEMORY1,139,59,18,15
    PUSHBUTTON      "M2",IDC_MEMORY2,139,76,18,15
    PUSHBUTTON      "CELCIUS",IDC_CEL,12,118,43,15
    PUSHBUTTON      "FARENHEIT",IDC_FAR,62,118,43,15
    GROUPBOX        "Special",IDC_STATIC,170,29,38,87,BS_CENTER
    PUSHBUTTON      "&QUIT",IDC_QUIT,138,95,21,12
    PUSHBUTTON      "&Pow",IDC_POWER,180,95,18,15
END


IDR_MENU1 MENU 
BEGIN
    POPUP "&File"
    BEGIN
        MENUITEM "E&xit",                       ID_FILE_EXIT
    END
    POPUP "&Other"
    BEGIN
        MENUITEM "&Help",                       ID_OTHER_HELP
        MENUITEM "&About",                      ID_OTHER_ABOUT
    END
END
The resource file above introduces several new resource objects and their features.  The fist of these is the style definition.  The style definition may specify attributes as follows:

STYLE:
  • DS_MODALFRAME - makes the window modal (nothing can be accessed until the window is closed.
  • WS_POPUP - makes a stand-alone window, it is not the child of another window.
  • WS_CAPTION - makes a window with a title bar.
  • WS_SYSMENU - makes a window with maximize, minimize and restore.
  • WS_VISIBLE - makes a window visible.
  • WS_BORDER - creates a window with a border.
  • WS_TABSTOP - prevents a button from receiving focus() when the TAB key is pressed.

Static Text Controls:

  • CTEXT - centered text, no message identifier needed since static text boxes do not generate messages or take input.
  • RTEXT - right aligned text, no message identifier needed since static text boxes do not generate messages or take input.
  • LTEXT - left aligned text, no message identifier needed since static text boxes do not generate messages or take input.

EDITTEXT - creates an editable text box that takes input and transmits messages.

DEFPUSHBUTTON - defines default pushbutton.

PUSHBUTTON - creates a pushbutton.

SS_CENTER - centers text in a CStatic Window.

For your next project, take this calculator program and use it as a template.  Plug into it algorithms for doing conversions between English and metric measurement systems, computing sales tax or converting decimal to binary or hexadecimal.  Add buttons, message identifiers, and message handlers.  You can create a super fantastic calculator of your own!

©2004 C. Germany