home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Windows Gam…ming Gurus (2nd Edition) / Disc2.iso / msdn_vcb / samples / vc98 / mfc / ole / mfccalc / calcdlg.cpp next >
C/C++ Source or Header  |  1998-03-26  |  11KB  |  508 lines

  1. // calcdlg.cpp : implementation file
  2. //
  3. // This is a part of the Microsoft Foundation Classes C++ library.
  4. // Copyright (C) 1992-1998 Microsoft Corporation
  5. // All rights reserved.
  6. //
  7. // This source code is only intended as a supplement to the
  8. // Microsoft Foundation Classes Reference and related
  9. // electronic documentation provided with the library.
  10. // See these sources for detailed information regarding the
  11. // Microsoft Foundation Classes product.
  12.  
  13. #include "stdafx.h"
  14. #include "mfccalc.h"
  15. #include "calcdlg.h"
  16.  
  17. #ifdef _DEBUG
  18. #undef THIS_FILE
  19. static char BASED_CODE THIS_FILE[] = __FILE__;
  20. #endif
  21.  
  22. /////////////////////////////////////////////////////////////////////////////
  23. // CAboutDlg dialog used for App About
  24.  
  25. class CAboutDlg : public CDialog
  26. {
  27. public:
  28.     CAboutDlg();
  29.  
  30. // Dialog Data
  31.     //{{AFX_DATA(CAboutDlg)
  32.     enum { IDD = IDD_ABOUTBOX };
  33.     //}}AFX_DATA
  34.  
  35. // Implementation
  36. protected:
  37.     virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV support
  38.     //{{AFX_MSG(CAboutDlg)
  39.     virtual BOOL OnInitDialog();
  40.     //}}AFX_MSG
  41.     DECLARE_MESSAGE_MAP()
  42. };
  43.  
  44. CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD)
  45. {
  46.     //{{AFX_DATA_INIT(CAboutDlg)
  47.     //}}AFX_DATA_INIT
  48. }
  49.  
  50. void CAboutDlg::DoDataExchange(CDataExchange* pDX)
  51. {
  52.     CDialog::DoDataExchange(pDX);
  53.     //{{AFX_DATA_MAP(CAboutDlg)
  54.     //}}AFX_DATA_MAP
  55. }
  56.  
  57. BEGIN_MESSAGE_MAP(CAboutDlg, CDialog)
  58.     //{{AFX_MSG_MAP(CAboutDlg)
  59.         // No message handlers
  60.     //}}AFX_MSG_MAP
  61. END_MESSAGE_MAP()
  62.  
  63. /////////////////////////////////////////////////////////////////////////////
  64. // CAboutDlg message handlers
  65.  
  66. BOOL CAboutDlg::OnInitDialog()
  67. {
  68.     CDialog::OnInitDialog();
  69.  
  70.     // TODO: Add extra initialization here
  71.  
  72.     return TRUE;
  73. }
  74.  
  75. /////////////////////////////////////////////////////////////////////////////
  76. // CCalcDlg dialog
  77.  
  78. IMPLEMENT_DYNCREATE(CCalcDlg, CDialog)
  79.  
  80. BEGIN_DISPATCH_MAP(CCalcDlg, CDialog)
  81.     //{{AFX_DISPATCH_MAP(CCalcDlg)
  82.     DISP_PROPERTY_EX(CCalcDlg, "Accum", GetAccum, SetAccum, VT_I4)
  83.     DISP_PROPERTY_EX(CCalcDlg, "Operand", GetOperand, SetOperand, VT_I4)
  84.     DISP_PROPERTY_EX(CCalcDlg, "Operation", GetOperation, SetOperation, VT_I2)
  85.     DISP_PROPERTY_EX(CCalcDlg, "Visible", GetVisible, SetVisible, VT_BOOL)
  86.     DISP_FUNCTION(CCalcDlg, "Evaluate", Evaluate, VT_BOOL, VTS_NONE)
  87.     DISP_FUNCTION(CCalcDlg, "Clear", Clear, VT_EMPTY, VTS_NONE)
  88.     DISP_FUNCTION(CCalcDlg, "Display", Display, VT_EMPTY, VTS_NONE)
  89.     DISP_FUNCTION(CCalcDlg, "Close", Close, VT_EMPTY, VTS_NONE)
  90.     DISP_FUNCTION(CCalcDlg, "Button", Button, VT_BOOL, VTS_BSTR)
  91.     //}}AFX_DISPATCH_MAP
  92. END_DISPATCH_MAP()
  93.  
  94. #ifndef IMPLEMENT_OLECREATE_SINGLE
  95. // MFC will provide this macro in the future.  For now, we define it.
  96. #define IMPLEMENT_OLECREATE_SINGLE(class_name, external_name, \
  97.     l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8) \
  98.     AFX_DATADEF COleObjectFactory class_name::factory(class_name::guid, \
  99.         RUNTIME_CLASS(class_name), TRUE, _T(external_name)); \
  100.     const AFX_DATADEF GUID class_name::guid = \
  101.         { l, w1, w2, { b1, b2, b3, b4, b5, b6, b7, b8 } };
  102. #endif
  103.  
  104. // {62C4DD10-F45E-11cd-8C3D-00AA004BB3B7}
  105. IMPLEMENT_OLECREATE_SINGLE(CCalcDlg, "mfccalc.calculator",
  106.     0x62c4dd10, 0xf45e, 0x11cd, 0x8c, 0x3d, 0x0, 0xaa, 0x0, 0x4b, 0xb3, 0xb7);
  107.  
  108. CCalcDlg::CCalcDlg(CWnd* pParent /*=NULL*/)
  109.     : CDialog(CCalcDlg::IDD, pParent)
  110. {
  111.     m_bAutoDelete = TRUE;       // default to auto-delete
  112.     m_dwRegister = 0;               // not registered as active by default
  113.  
  114.     //{{AFX_DATA_INIT(CCalcDlg)
  115.         // NOTE: the ClassWizard will add member initialization here
  116.     //}}AFX_DATA_INIT
  117.  
  118.     // Note that LoadIcon does not require a subsequent DestroyIcon in Win32
  119.     m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
  120.  
  121.     // Note that LoadAccelerator does not require DestroyAcceleratorTable
  122.     m_hAccel = LoadAccelerators(AfxGetInstanceHandle(), MAKEINTRESOURCE(IDD));
  123.  
  124.     // clear the contents of the calculator and reset state
  125.     OnClickedClear();
  126.  
  127.     // enable this object for OLE automation
  128.     EnableAutomation();
  129. }
  130.  
  131. CCalcDlg::~CCalcDlg()
  132. {
  133.     if (m_dwRegister != 0)
  134.         RevokeActiveObject(m_dwRegister, NULL);
  135. }
  136.  
  137. void CCalcDlg::DoDataExchange(CDataExchange* pDX)
  138. {
  139.     CDialog::DoDataExchange(pDX);
  140.     //{{AFX_DATA_MAP(CCalcDlg)
  141.         // NOTE: the ClassWizard will add DDX and DDV calls here
  142.     //}}AFX_DATA_MAP
  143. }
  144.  
  145. /////////////////////////////////////////////////////////////////////////////
  146. // CCalcDlg implementation
  147.  
  148. void CCalcDlg::PerformOperation()
  149. {
  150.     if (m_errorState != ErrNone)
  151.         return;
  152.  
  153.     if (m_bOperandAvail)
  154.     {
  155.         if (m_operator == OpNone)
  156.             m_accum = m_operand;
  157.         else if (m_operator == OpMultiply)
  158.             m_accum *= m_operand;
  159.         else if (m_operator == OpDivide)
  160.         {
  161.             if (m_operand == 0)
  162.                 m_errorState = ErrDivideByZero;
  163.             else
  164.                 m_accum /= m_operand;
  165.         }
  166.         else if (m_operator == OpAdd)
  167.             m_accum += m_operand;
  168.         else if (m_operator == OpSubtract)
  169.             m_accum -= m_operand;
  170.     }
  171.  
  172.     m_bOperandAvail = FALSE;
  173.     UpdateDisplay();
  174. }
  175.  
  176. void CCalcDlg::ClickedNumber(long l)
  177. {
  178.     if (m_errorState != ErrNone)
  179.         return;
  180.  
  181.     if (!m_bOperandAvail)
  182.         m_operand = 0L;
  183.  
  184.     SetOperand(m_operand*10+l);
  185.     UpdateDisplay();
  186. }
  187.  
  188. void CCalcDlg::UpdateDisplay()
  189. {
  190.     if (GetSafeHwnd() == NULL)
  191.         return;
  192.  
  193.     CString str;
  194.     if (m_errorState != ErrNone)
  195.         str.LoadString(IDS_ERROR);
  196.     else
  197.     {
  198.         long lVal = (m_bOperandAvail) ? m_operand : m_accum;
  199.         str.Format(_T("%ld"), lVal);
  200.     }
  201.     GetDlgItem(IDE_ACCUM)->SetWindowText(str);
  202.     GetDlgItem(IDC_INVISIBLE_FOCUS)->SetFocus();
  203. }
  204.  
  205. BEGIN_MESSAGE_MAP(CCalcDlg, CDialog)
  206.     //{{AFX_MSG_MAP(CCalcDlg)
  207.     ON_WM_SYSCOMMAND()
  208.     ON_WM_PAINT()
  209.     ON_WM_QUERYDRAGICON()
  210.     ON_COMMAND_RANGE(IDB_0, IDB_9, OnClickedNumber)
  211.     ON_BN_CLICKED(IDB_CLEAR, OnClickedClear)
  212.     ON_BN_CLICKED(IDB_DIVIDE, OnClickedDivide)
  213.     ON_BN_CLICKED(IDB_EQUAL, OnClickedEqual)
  214.     ON_BN_CLICKED(IDB_MINUS, OnClickedMinus)
  215.     ON_BN_CLICKED(IDB_PLUS, OnClickedPlus)
  216.     ON_BN_CLICKED(IDB_TIMES, OnClickedTimes)
  217.     ON_EN_SETFOCUS(IDE_ACCUM, OnSetFocusAccum)
  218.     //}}AFX_MSG_MAP
  219. END_MESSAGE_MAP()
  220.  
  221. /////////////////////////////////////////////////////////////////////////////
  222. // CCalcDlg message handlers
  223.  
  224. BOOL CCalcDlg::OnInitDialog()
  225. {
  226.     CDialog::OnInitDialog();
  227.  
  228.     // Add "About..." menu item to system menu.
  229.  
  230.     // IDM_ABOUTBOX must be in the system command range.
  231.     ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
  232.     ASSERT(IDM_ABOUTBOX < 0xF000);
  233.  
  234.     CMenu* pSysMenu = GetSystemMenu(FALSE);
  235.     CString strAboutMenu;
  236.     strAboutMenu.LoadString(IDS_ABOUTBOX);
  237.     if (!strAboutMenu.IsEmpty())
  238.     {
  239.         pSysMenu->AppendMenu(MF_SEPARATOR);
  240.         pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
  241.     }
  242.  
  243.     pSysMenu->RemoveMenu(SC_MAXIMIZE, MF_BYCOMMAND);
  244.     pSysMenu->RemoveMenu(SC_SIZE, MF_BYCOMMAND);
  245.  
  246.     // want focus to stay on the dialog itself (until a button is clicked)
  247.     SetFocus();
  248.     return FALSE;
  249. }
  250.  
  251. void CCalcDlg::OnSysCommand(UINT nID, LPARAM lParam)
  252. {
  253.     if ((nID & 0xFFF0) == IDM_ABOUTBOX)
  254.     {
  255.         CAboutDlg dlgAbout;
  256.         dlgAbout.DoModal();
  257.     }
  258.     else
  259.     {
  260.         CDialog::OnSysCommand(nID, lParam);
  261.     }
  262. }
  263.  
  264. // If you add a minimize button to your dialog, you will need the code below
  265. //  to draw the icon.  For MFC applications using the document/view model,
  266. //  this is automatically done for you by the framework.
  267.  
  268. void CCalcDlg::OnPaint()
  269. {
  270.     if (!IsIconic())
  271.     {
  272.         CDialog::OnPaint();
  273.         return;
  274.     }
  275.  
  276.     CPaintDC dc(this); // device context for painting
  277.  
  278.     SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0);
  279.  
  280.     // Center icon in client rectangle
  281.     int cxIcon = GetSystemMetrics(SM_CXICON);
  282.     int cyIcon = GetSystemMetrics(SM_CYICON);
  283.     CRect rect;
  284.     GetClientRect(&rect);
  285.     int x = (rect.Width() - cxIcon + 1) / 2;
  286.     int y = (rect.Height() - cyIcon + 1) / 2;
  287.  
  288.     // Draw the icon
  289.     dc.DrawIcon(x, y, m_hIcon);
  290. }
  291.  
  292. // The system calls this to obtain the cursor to display while the user drags
  293. //  the minimized window.
  294. HCURSOR CCalcDlg::OnQueryDragIcon()
  295. {
  296.     return (HCURSOR)m_hIcon;
  297. }
  298.  
  299. void CCalcDlg::OnClickedNumber(UINT nID)
  300. {
  301.     ASSERT(nID >= IDB_0 && nID <= IDB_9);
  302.     ClickedNumber(nID - IDB_0);
  303. }
  304.  
  305. void CCalcDlg::OnClickedClear()
  306. {
  307.     m_operator = OpNone;
  308.     m_operand = 0L;
  309.     m_accum = 0L;
  310.     m_bOperandAvail = FALSE;
  311.     m_errorState = ErrNone;
  312.     UpdateDisplay();
  313. }
  314.  
  315. void CCalcDlg::OnClickedDivide()
  316. {
  317.     PerformOperation();
  318.     m_operator = OpDivide;
  319. }
  320.  
  321. void CCalcDlg::OnClickedEqual()
  322. {
  323.     PerformOperation();
  324.     m_operator = OpNone;
  325. }
  326.  
  327. void CCalcDlg::OnClickedMinus()
  328. {
  329.     PerformOperation();
  330.     m_operator = OpSubtract;
  331. }
  332.  
  333. void CCalcDlg::OnClickedPlus()
  334. {
  335.     PerformOperation();
  336.     m_operator = OpAdd;
  337. }
  338.  
  339. void CCalcDlg::OnClickedTimes()
  340. {
  341.     PerformOperation();
  342.     m_operator = OpMultiply;
  343. }
  344.  
  345. BOOL CCalcDlg::PreTranslateMessage(MSG* pMsg)
  346. {
  347.     if (m_hAccel != NULL && TranslateAccelerator(m_hWnd, m_hAccel, pMsg))
  348.         return TRUE;
  349.  
  350.     return CDialog::PreTranslateMessage(pMsg);
  351. }
  352.  
  353. void CCalcDlg::PostNcDestroy()
  354. {
  355.     if (m_bAutoDelete)
  356.         delete this;
  357. }
  358.  
  359. void CCalcDlg::OnCancel()
  360. {
  361.     DestroyWindow();
  362. }
  363.  
  364. void CCalcDlg::OnOK()
  365. {
  366. }
  367.  
  368. void CCalcDlg::OnSetFocusAccum()
  369. {
  370.     GetDlgItem(IDC_INVISIBLE_FOCUS)->SetFocus();
  371. }
  372.  
  373. /////////////////////////////////////////////////////////////////////////////
  374. // CCalcDlg automation
  375.  
  376. BOOL CCalcDlg::RegisterActive()
  377. {
  378.     // attempt to register as the active object for the CCalcDlg CLSID
  379.     return RegisterActiveObject(GetInterface(&IID_IUnknown),
  380.         CCalcDlg::guid, NULL, &m_dwRegister) == NOERROR;
  381. }
  382.  
  383. long CCalcDlg::GetAccum()
  384. {
  385.     return m_accum;
  386. }
  387.  
  388. void CCalcDlg::SetAccum(long nNewValue)
  389. {
  390.     m_accum = nNewValue;
  391. }
  392.  
  393. long CCalcDlg::GetOperand()
  394. {
  395.     return m_operand;
  396. }
  397.  
  398. void CCalcDlg::SetOperand(long nNewValue)
  399. {
  400.     m_operand = nNewValue;
  401.     m_bOperandAvail = TRUE;
  402. }
  403.  
  404. short CCalcDlg::GetOperation()
  405. {
  406.     return m_operator;
  407. }
  408.  
  409. void CCalcDlg::SetOperation(short nNewValue)
  410. {
  411.     m_operator = (Operator)nNewValue;
  412. }
  413.  
  414. BOOL CCalcDlg::GetVisible()
  415. {
  416.     return m_hWnd != NULL && (GetStyle() & WS_VISIBLE) != 0;
  417. }
  418.  
  419. void CCalcDlg::SetVisible(BOOL bNewValue)
  420. {
  421.     if (bNewValue == GetVisible())
  422.         return;
  423.  
  424.     if (bNewValue)
  425.     {
  426.         // create it if necessary
  427.         if (m_hWnd == NULL && !Create(CCalcDlg::IDD))
  428.             return;
  429.  
  430.         // set up as the active window for the application
  431.         if (AfxGetThread()->m_pMainWnd == NULL)
  432.             AfxGetThread()->m_pMainWnd = this;
  433.  
  434.         // show it
  435.         ShowWindow(SW_SHOWNORMAL);
  436.     }
  437.     else
  438.     {
  439.         if (m_hWnd != NULL)
  440.             ShowWindow(SW_HIDE);
  441.     }
  442. }
  443.  
  444. BOOL CCalcDlg::Evaluate()
  445. {
  446.     OnClickedEqual();
  447.     return m_errorState == ErrNone;
  448. }
  449.  
  450. void CCalcDlg::Clear()
  451. {
  452.     OnClickedClear();
  453. }
  454.  
  455. void CCalcDlg::Display()
  456. {
  457.     UpdateDisplay();
  458. }
  459.  
  460. void CCalcDlg::Close()
  461. {
  462.     if (m_hWnd == NULL)
  463.     {
  464.         AfxPostQuitMessage(0);
  465.         return;
  466.     }
  467.  
  468.     BOOL bAutoDelete = m_bAutoDelete;
  469.     m_bAutoDelete = FALSE;
  470.     DestroyWindow();
  471.     m_bAutoDelete = bAutoDelete;
  472. }
  473.  
  474. BOOL CCalcDlg::Button(LPCTSTR szButton)
  475. {
  476.     switch (szButton[0])
  477.     {
  478.     case 'c':
  479.     case 'C':
  480.         OnClickedClear();
  481.         break;
  482.  
  483.     case '/':
  484.         OnClickedDivide();
  485.         break;
  486.     case '+':
  487.         OnClickedPlus();
  488.         break;
  489.     case '-':
  490.         OnClickedMinus();
  491.         break;
  492.     case '*':
  493.         OnClickedTimes();
  494.         break;
  495.     case '=':
  496.         OnClickedEqual();
  497.         break;
  498.  
  499.     default:
  500.         if (szButton[0] >= '0' && szButton[0] <= '9')
  501.             ClickedNumber(szButton[0] - '0');
  502.         else
  503.             return FALSE;
  504.         break;
  505.     }
  506.     return TRUE;
  507. }
  508.