2025-11-27 16:46:48 +09:00

374 lines
8.9 KiB
C++

// calcdlg.cpp : implementation file
//
#include "stdafx.h"
#include "utsampleabout.h"
#include "calc.h"
#include "calcdlg.h"
#include "calckey.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/////////////////////////////////////////////////////////////////////////////
// CCalculator dialog
CCalculator::CCalculator(CWnd* pParent /*=NULL*/)
: CDialog(CCalculator::IDD, pParent)
{
//{{AFX_DATA_INIT(CCalculator)
// NOTE: the ClassWizard will add member initialization here
//}}AFX_DATA_INIT
// Note that LoadAccelerator does not require DestroyAcceleratorTable
m_hAccel = LoadAccelerators(AfxGetResourceHandle(),MAKEINTRESOURCE(IDD));
// Initialize the move variable
m_bTrackMove = FALSE;
}
void CCalculator::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
//{{AFX_DATA_MAP(CCalculator)
// NOTE: the ClassWizard will add DDX and DDV calls here
//}}AFX_DATA_MAP
}
/////////////////////////////////////////////////////////////////////////////
// CCalculator Internal Methods
// Called to perform an operation - add, subtract, etc.
void CCalculator::PerformOperation()
{
// Return if in an invalid state
if (m_errorState != ErrNone)
return;
// If we can perform an operation...
if (m_bOperandAvail)
{
// Perform the selected operation
if (m_operator == OpNone)
m_accum = m_operand;
else if (m_operator == OpMultiply)
m_accum *= m_operand;
else if (m_operator == OpDivide)
{
if (m_operand == 0)
m_errorState = ErrDivideByZero;
else
m_accum /= m_operand;
}
else if (m_operator == OpAdd)
m_accum += m_operand;
else if (m_operator == OpSubtract)
m_accum -= m_operand;
}
// Set the next state
m_bOperandAvail = FALSE;
UpdateDisplay();
}
// Called to update the total display
void CCalculator::UpdateDisplay()
{
// Display "Error" is an error occurs, otherwise display the total
CString str;
if (m_errorState != ErrNone)
str = "Error";
else
{
long lVal = (m_bOperandAvail) ? m_operand : m_accum;
str.Format(_T("%ld"), lVal);
}
GetDlgItem(IDC_DISPLAY)->SetWindowText(str);
}
// Draws a tracking rectangle by inverting an area the size of the dialog
void CCalculator::InvertTracker(CPoint point)
{
CRect rectFrame;
GetWindowRect(&rectFrame);
CDC dc;
dc.Attach(::GetDC(NULL));
// Create the frame with a reverse video effect
dc.PatBlt(point.x-m_ptMouse.x, point.y-m_ptMouse.y, rectFrame.Width(),
2, PATINVERT);
dc.PatBlt(point.x-m_ptMouse.x+rectFrame.Width(), point.y-m_ptMouse.y,
2, rectFrame.Height(), PATINVERT);
dc.PatBlt(point.x-m_ptMouse.x, point.y-m_ptMouse.y+rectFrame.Height(),
rectFrame.Width()+2, 2, PATINVERT);
dc.PatBlt(point.x-m_ptMouse.x, point.y-m_ptMouse.y+2, 2,
rectFrame.Height()-2, PATINVERT);
::ReleaseDC(NULL,dc.Detach());
}
BEGIN_MESSAGE_MAP(CCalculator, CDialog)
//{{AFX_MSG_MAP(CCalculator)
ON_COMMAND_RANGE(IDC_0,IDC_9,OnNumber)
ON_BN_CLICKED(IDC_ADD, OnAdd)
ON_BN_CLICKED(IDC_CLEAR, OnClear)
ON_BN_CLICKED(IDC_DIV, OnDiv)
ON_BN_CLICKED(IDC_EQUAL, OnEqual)
ON_BN_CLICKED(IDC_MUL, OnMul)
ON_BN_CLICKED(IDC_SUB, OnSub)
ON_BN_CLICKED(IDC_ABOUT, OnAbout)
ON_WM_LBUTTONDOWN()
ON_WM_LBUTTONUP()
ON_WM_MOUSEMOVE()
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CCalculator message handlers
BOOL CCalculator::OnInitDialog()
{
CDialog::OnInitDialog();
CString sCaption;
sCaption.LoadString(IDR_MAINFRAME);
SetWindowText(sCaption);
// Set the icon for this dialog. The framework does this automatically
// when the application's main window is not a dialog
SetIcon(m_hIcon, TRUE); // Set big icon
SetIcon(m_hIcon, FALSE); // Set small icon
// Set the rounded-corner calculator shape
CPoint point(30,30);
SetRoundRectShape(NULL,&point);
// Make sure the starfield paints before everything else
GetDlgItem(IDC_STARFIELD)->SetWindowPos(&wndTop,0,0,0,0,
SWP_NOMOVE|SWP_NOSIZE);
// Shape the number keys
CCalcKey* pKey;
int nID;
for(nID = IDC_0; nID <= IDC_9; nID++)
{
pKey = (CCalcKey*) GetDlgItem(nID);
ASSERT(pKey != NULL);
// Make them star shaped
pKey->SetStarShape();
// Set color to yellow when not pressed, red when pressed
pKey->SetColors(RGB(0,0,0),RGB(255,255,0),RGB(0,0,0),RGB(255,0,0));
}
// Shape the operation keys
for(nID = IDC_SUB; nID <= IDC_ADD; nID++)
{
pKey = (CCalcKey*) GetDlgItem(nID);
ASSERT(pKey != NULL);
// Make them round-corned rectangles
CPoint point(20,20);
pKey->SetRoundRectShape(NULL,&point);
// Set color to light gray when not pressed, white when pressed
pKey->SetColors(RGB(0,0,0),RGB(192,192,192),
RGB(0,0,0),RGB(255,255,255));
}
// Set the total display's appearance
pKey = (CCalcKey*) GetDlgItem(IDC_DISPLAY);
ASSERT(pKey != NULL);
// Make it a white ellipse
pKey->SetEllipseShape(NULL);
pKey->SetColors(RGB(0,0,0),RGB(255,255,255));
// Set the close button's appearance
pKey = (CCalcKey*) GetDlgItem(IDCANCEL);
ASSERT(pKey != NULL);
// Make it a light gray ellipse
pKey->SetEllipseShape(NULL);
pKey->SetColors(RGB(0,0,0),RGB(192,192,192));
// Set the close button's appearance
pKey = (CCalcKey*) GetDlgItem(IDC_ABOUT);
ASSERT(pKey != NULL);
// Make it a light gray ellipse
pKey->SetEllipseShape(NULL);
// Set color to light gray when not pressed, white when pressed
pKey->SetColors(RGB(0,0,0),RGB(192,192,192),
RGB(0,0,0),RGB(255,255,255));
// Center the dialog on the screen
CenterWindow();
// Initialize the calculator's work variables
OnClear();
return TRUE; // return TRUE unless you set the focus to a control
}
// Called when a number button is clicked
void CCalculator::ClickedNumber(long l)
{
// Return if in an invalid state
if (m_errorState != ErrNone)
return;
// If we can perform an operation...
if (!m_bOperandAvail)
m_operand = 0L;
// Set the next state
SetOperand(m_operand*10+l);
UpdateDisplay();
}
void CCalculator::OnAbout(){
CUTSampleAboutDlg aboutDlg(IDR_MAINFRAME,ID_DESCRIPTION_FILE);
aboutDlg.DoModal();
}
// Called when the left mouse button is pressed
void CCalculator::OnLButtonDown(UINT nFlags, CPoint point)
{
UNREFERENCED_PARAMETER(nFlags);
// Save the starting point where the mouse was clicked
m_ptMouse = point;
// Save the point in screen coordinates too
ClientToScreen(&point);
m_ptLast = point;
}
// Called when the left mouse button is released
void CCalculator::OnLButtonUp(UINT nFlags, CPoint point)
{
UNREFERENCED_PARAMETER(nFlags);
// If moving...
if (m_bTrackMove)
{
// Reset for next move
m_bTrackMove = FALSE;
ReleaseCapture();
InvertTracker(m_ptLast);
// Calculate how far we have moved and update
ClientToScreen(&point);
SetWindowPos(NULL, point.x-m_ptMouse.x, point.y-m_ptMouse.y,0,0,
SWP_NOZORDER|SWP_NOSIZE);
}
}
// Called when the mouse moves
void CCalculator::OnMouseMove(UINT nFlags, CPoint point)
{
// Are we not moving the window and the left mouse button is now down???
if(!m_bTrackMove && (nFlags & MK_LBUTTON))
{
// Begin the move operation
m_bTrackMove = TRUE;
SetCapture();
InvertTracker(m_ptLast);
}
// If we moving...
if (m_bTrackMove)
{
// Remove the old tracking rectangle
ClientToScreen(&point);
InvertTracker(m_ptLast);
// Draw a new one
m_ptLast = point;
InvertTracker(m_ptLast);
}
else CWnd::OnMouseMove(nFlags,point);
}
// Called when a number key is pressed
void CCalculator::OnNumber(UINT nID)
{
ASSERT(nID >= IDC_0 && nID <= IDC_9);
ClickedNumber(nID-IDC_0);
}
// Called when the clear key is pressed
void CCalculator::OnClear()
{
// Reset the internal state, empty the totals
m_operator = OpNone;
m_operand = 0L;
m_accum = 0L;
m_bOperandAvail = FALSE;
m_errorState = ErrNone;
UpdateDisplay();
}
// Called when the divide key is pressed
void CCalculator::OnDiv()
{
// Perform the division and save the operation
PerformOperation();
m_operator = OpDivide;
}
// Called when the equal key is pressed
void CCalculator::OnEqual()
{
// Get the total and save the operation
PerformOperation();
m_operator = OpNone;
}
// Called when the subtract key is pressed
void CCalculator::OnSub()
{
// Perform the subtraction and save the operation
PerformOperation();
m_operator = OpSubtract;
}
// Called when the add key is pressed
void CCalculator::OnAdd()
{
// Perform the addition and save the operation
PerformOperation();
m_operator = OpAdd;
}
// Called when the multiply key is pressed
void CCalculator::OnMul()
{
// Perform the multiplication and save the operation
PerformOperation();
m_operator = OpMultiply;
}
// Saves the last operand value
void CCalculator::SetOperand(long nNewValue)
{
// Save the operand value and indicate that operation was performed
m_operand = nNewValue;
m_bOperandAvail = TRUE;
}
// Translate the accelerators for the button keys
BOOL CCalculator::PreTranslateMessage(MSG* pMsg)
{
if (m_hAccel != NULL && TranslateAccelerator(m_hWnd, m_hAccel, pMsg))
return TRUE;
return CDialog::PreTranslateMessage(pMsg);
}