// MainFrm.cpp : implementation of the CMainFrame class
//
#include "stdafx.h"
#include "AppBarDemo.h"
#include "MainFrm.h"
#include "math.h"
#define DISPLAY_WIDTH 11
COLORREF palette[4][5] = {
{ RGB(255,0,0), RGB(255,127,127), RGB(255,191,191), RGB(255,207,207), RGB(255,239,239) },
{ RGB(0,207,0), RGB(63,207,63), RGB(191,255,191), RGB(199,255,199), RGB(239,255,239) },
{ RGB(0,0,255), RGB(127,127,255), RGB(191,191,255), RGB(207,207,255), RGB(239,239,255) },
{ RGB(127,127,127), RGB(175,175,175), RGB(207,207,207), RGB(217,217,217), RGB(239,239,239) },
};
enum tones { tone0=0, tone127, tone191, tone207, tone239 };
/////////////////////////////////////////////////////////////////////////////
// CMainFrame
IMPLEMENT_DYNAMIC(CMainFrame, CFrameWnd)
BEGIN_MESSAGE_MAP(CMainFrame, CFrameWnd)
//{{AFX_MSG_MAP(CMainFrame)
ON_WM_PAINT()
ON_WM_ERASEBKGND()
ON_WM_GETMINMAXINFO()
ON_WM_SIZE()
ON_WM_CREATE()
ON_WM_LBUTTONDOWN()
ON_WM_CTLCOLOR()
ON_WM_LBUTTONDBLCLK()
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CMainFrame construction/destruction
CMainFrame::CMainFrame()
{
CTime t = CTime::GetCurrentTime();
m_Month = t.GetMonth();
m_Year = t.GetYear();
m_Operator = 0;
m_Status = Result;
m_Display = "0";
m_Value = 0.0;
m_Palette = 2;
m_ClearColor.CreateSolidBrush(palette[m_Palette][tone239]);
}
CMainFrame::~CMainFrame()
{
}
BOOL CMainFrame::PreCreateWindow(CREATESTRUCT& cs)
{
if( !CFrameWnd::PreCreateWindow(cs) )
return FALSE;
return TRUE;
}
int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if (CFrameWnd::OnCreate(lpCreateStruct) == -1)
return -1;
CRect rect;
m_Notepad.Create(WS_VISIBLE|ES_MULTILINE|ES_AUTOVSCROLL, rect, this, 100);
return 0;
}
void CMainFrame::OnPaint()
{
CPaintDC dc(this); // device context for painting
CDC NoFlick;
CBitmap bmp, *oldBmp;
CRect rect;
NoFlick.CreateCompatibleDC(&dc);
GetClientRect(&rect);
bmp.CreateCompatibleBitmap(&dc, rect.Width(), rect.Height());
oldBmp = NoFlick.SelectObject(&bmp);
NoFlick.SelectStockObject(NULL_PEN);
NoFlick.SelectStockObject(SYSTEM_FONT);
NoFlick.SetBkMode(TRANSPARENT);
EraseBackground(&NoFlick);
NoFlick.SetTextColor(palette[m_Palette][tone0]);
NoFlick.TextOut(10,7, "Calculator");
DrawDisplay(&NoFlick);
DrawButtons(&NoFlick);
DrawCalendar(&NoFlick, m_Month, m_Year);
DrawNotepad(&NoFlick);
dc.BitBlt(0, 0, rect.right, rect.bottom, &NoFlick, 0, 0, SRCCOPY);
NoFlick.SelectObject(*oldBmp);
}
BOOL CMainFrame::OnEraseBkgnd(CDC* pDC)
{
return FALSE;
}
HBRUSH CMainFrame::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor)
{
HBRUSH hbr = CFrameWnd::OnCtlColor(pDC, pWnd, nCtlColor);
pDC->SetBkColor(palette[m_Palette][tone239]);
if (nCtlColor==CTLCOLOR_EDIT)
return (HBRUSH)m_ClearColor;
return hbr;
}
void CMainFrame::OnGetMinMaxInfo(MINMAXINFO FAR* lpMMI)
{
lpMMI->ptMinTrackSize = CPoint(150,480);
lpMMI->ptMaxTrackSize = lpMMI->ptMaxSize = CPoint(150,1600);
CFrameWnd::OnGetMinMaxInfo(lpMMI);
}
void CMainFrame::EraseBackground(CDC *pDC)
{
CRect rect;
GetClientRect(&rect);
rect.top = 400;
pDC->FillSolidRect(&rect, palette[m_Palette][tone191]);
// Draws background in degrad�
COLORREF tone,top,bot;
top = palette[m_Palette][tone239];
bot = palette[m_Palette][tone191];
rect.top = 0;
rect.bottom = 2;
for (int i=0; i<200; i++) {
tone = RGB(
(GetRValue(bot)-GetRValue(top))*((float)i)/200.0f+GetRValue(top),
(GetGValue(bot)-GetGValue(top))*((float)i)/200.0f+GetGValue(top),
(GetBValue(bot)-GetBValue(top))*((float)i)/200.0f+GetBValue(top));
pDC->FillSolidRect(rect,tone);
rect.OffsetRect(0,2);
}
// Draw closing close
CPen pen(PS_SOLID,1,palette[m_Palette][tone191]);
pDC->SelectObject(pen);
GetClientRect(&rect);
rect.DeflateRect(rect.Width()-12,4,4,rect.Height()-12);
CPoint poly[7];
poly[0] = rect.TopLeft();
poly[1] = rect.BottomRight();
poly[2] = poly[1] + CSize( 0,-1);
poly[3] = poly[0] + CSize( 1, 0);
poly[4] = poly[3] + CSize(-1, 1);
poly[5] = poly[1] + CSize(-1, 0);
poly[6] = poly[1];
pDC->Polyline(poly, 7);
poly[0] = CPoint(rect.left, rect.bottom);
poly[1] = CPoint(rect.right, rect.top);
poly[2] = poly[1] + CSize( 0, 1);
poly[3] = poly[0] + CSize( 1, 0);
poly[4] = poly[3] + CSize(-1,-1);
poly[5] = poly[1] + CSize(-1, 0);
poly[6] = poly[1];
pDC->Polyline(poly, 7);
pDC->SelectStockObject(NULL_PEN);
}
void CMainFrame::DrawDisplay(CDC *pDC)
{
CRect rect;
CBrush *oldBrush, bg(palette[m_Palette][tone207]);
GetClientRect(&rect);
rect.left +=10;
rect.right -=10;
rect.top +=25;
rect.bottom = rect.top + 25;
oldBrush = (CBrush *)pDC->SelectObject(&bg);
pDC->RoundRect(&rect, CPoint(5,5));
pDC->SelectObject(oldBrush);
rect.DeflateRect(CSize(3,3));
pDC->DrawText(m_Display, &rect, DT_RIGHT);
}
static unsigned char buttons[4][4] = {
'7', '8', '9', 'C',
'4', '5', '6', '/', // Divide
'1', '2', '3', 'x', // Multiply
'0',0xB1, '.', '-' // +/-
};
void CMainFrame::DrawButtons(CDC *pDC)
{
CString label;
CRect rect;
CBrush *oldBrush, bg(palette[m_Palette][tone207]);
int row,col;
GetClientRect(&rect);
float w = (rect.Width()-20)/11.0f;
pDC->SetTextColor(palette[m_Palette][tone127]);
oldBrush = (CBrush *)pDC->SelectObject(&bg);
for (row=0; row<4; row++) {
for (col=0; col<4; col++) {
rect = CRect(10+(int)(col*w*3.0f), 60+row*25, 10+(int)(col*w*3.0+w*2.0), 60+row*25+(int)(w*2.0));
pDC->RoundRect(&rect, CPoint(5,5));
label = buttons[row][col];
rect.top += 2;
pDC->DrawText(label, &rect, DT_CENTER);
}
}
col = 0;
rect = CRect(10+(int)(col*w*3.0f), 60+row*25, 10+(int)(col*w*3.0+w*5.0), 60+row*25+(int)(w*2.0));
pDC->RoundRect(&rect, CPoint(5,5));
rect.top += 2;
pDC->DrawText("=", &rect, DT_CENTER);
col = 2;
rect = CRect(10+(int)(col*w*3.0f), 60+row*25, 10+(int)(col*w*3.0+w*5.0), 60+row*25+(int)(w*2.0));
pDC->RoundRect(&rect, CPoint(5,5));
rect.top += 2;
pDC->DrawText("+", &rect, DT_CENTER);
pDC->SelectObject(oldBrush);
}
void CMainFrame::DrawCalendar(CDC *pDC, int month, int year)
{
static char dow[7] = { 'S', 'M', 'T', 'W', 'T', 'F', 'S' };
CTime t(year, month+1, 1,0,0,0);
t -= CTimeSpan::CTimeSpan(1,0,0,0);
int totdays = t.GetDay();
t = CTime(year, month, 1,0,0,0);
int nDay1 = t.GetDayOfWeek();
CString sMonth = t.Format("%b");
t = CTime::GetCurrentTime();
int nMonth = t.GetMonth();
int nYear = t.GetYear();
int nDay = t.GetDay();
CRect rect;
GetClientRect(&rect);
rect.DeflateRect(10,200,10,0),
rect.bottom = rect.top + 110;
float w = (rect.Width()-4) / 7.0f;
CPen *oldPen, pen(PS_SOLID,1,palette[m_Palette][tone127]);
oldPen = (CPen*)pDC->SelectObject(&pen);
pDC->SelectStockObject(NULL_BRUSH);
pDC->RoundRect(&rect, CPoint(5,5));
pDC->MoveTo(13,230);
pDC->LineTo(rect.right-3,230);
pDC->SelectObject(oldPen);
CString label;
label.Format("%s %i", (LPCTSTR)sMonth, year);
rect.top += 2;
pDC->DrawText(label, &rect, DT_CENTER);
pDC->SelectStockObject(ANSI_VAR_FONT);
for (int col=0; col<7; col++) {
rect = CRect(12+(int)(col*w), 217, 12+(int)((col+1)*w), 280);
label = dow[col];
pDC->DrawText(label, &rect, DT_CENTER);
}
bool thisMonth = false;
if (month==nMonth && year==nYear)
thisMonth = true;
pDC->SelectStockObject(WHITE_BRUSH);
int row = 0;
col = nDay1 - 1;
for (int d=1; d<=totdays; d++) {
rect = CRect(12+(int)(col*w), 233+row*15, 12+(int)((col+1)*w+1), 247+row*15);
if (thisMonth && d==nDay)
pDC->Rectangle(&rect);
label.Format("%i", d);
pDC->DrawText(label, &rect, DT_CENTER);
col++;
if (col>=7) {
col = 0;
row++;
if (row>4)
row = 0;
}
}
pDC->SelectStockObject(SYSTEM_FONT);
CBrush *oldBrush, brush(palette[m_Palette][tone127]);
oldBrush = (CBrush *)pDC->SelectObject(&brush);
CPoint arrow[3];
GetClientRect(&rect);
arrow[0] = CPoint(13,208);
arrow[1] = CPoint(22,202);
arrow[2] = CPoint(22,214);
pDC->Polygon(arrow,3);
arrow[0] = CPoint(rect.right-13,208);
arrow[1] = CPoint(rect.right-22,202);
arrow[2] = CPoint(rect.right-22,214);
pDC->Polygon(arrow,3);
pDC->SelectObject(oldBrush);
}
void CMainFrame::DrawNotepad(CDC *pDC)
{
pDC->SetTextColor(palette[m_Palette][tone0]);
pDC->TextOut(10,321,"Notepad");
CRect rect;
GetClientRect(&rect);
rect.DeflateRect(10,340,10,10);
CBrush *oldBrush = (CBrush *)pDC->SelectObject(&m_ClearColor);
pDC->RoundRect(&rect,CPoint(7,7));
pDC->SelectObject(oldBrush);
}
void CMainFrame::OnSize(UINT nType, int cx, int cy)
{
CFrameWnd::OnSize(nType, cx, cy);
CRect rect;
GetClientRect(&rect);
rect.DeflateRect(10,340,10,10);
rect.DeflateRect(3,3,3,3);
m_Notepad.MoveWindow(&rect);
}
void CMainFrame::OnLButtonDown(UINT nFlags, CPoint point)
{
CRect rect;
GetClientRect(&rect);
int wt = rect.Width();
float w = (wt-20)/11.0f;
for (int row=0; row<4; row++) {
for (int col=0; col<4; col++) {
rect = CRect(10+(int)(col*w*3.0f), 60+row*25, 10+(int)(col*w*3.0+w*2.0), 60+row*25+(int)(w*2.0));
if (rect.PtInRect(point)) {
Operate(buttons[row][col]);
return;
}
}
}
rect = CRect(10, 160, 10+(int)(w*5.0), 160+(int)(w*2.0));
if (rect.PtInRect(point)) {
Operate('=');
return;
}
rect = CRect(10+(int)(w*6.0f), 160, 10+(int)(w*11.0), 160+(int)(w*2.0));
if (rect.PtInRect(point)) {
Operate('+');
return;
}
rect = CRect(13,202,22,214);
if (rect.PtInRect(point)) {
Operate('<');
return;
}
rect = CRect(wt-22,202,wt-13,214);
if (rect.PtInRect(point)) {
Operate('>');
return;
}
GetClientRect(&rect);
rect.DeflateRect(rect.Width()-12,4,4,rect.Height()-12);
if (rect.PtInRect(point))
::AfxPostQuitMessage(0);
CFrameWnd::OnLButtonDown(nFlags, point);
}
void CMainFrame::OnLButtonDblClk(UINT nFlags, CPoint point)
{
CRect rect;
GetClientRect(&rect);
int wt=rect.Width();
rect.DeflateRect(25,202,25,0);
rect.bottom = 214;
if (rect.PtInRect(point)) {
CTime t = CTime::GetCurrentTime();
m_Month = t.GetMonth();
m_Year = t.GetYear();
Invalidate(TRUE);
return;
}
rect = CRect(13,202,22,214);
if (rect.PtInRect(point)) {
Operate('<');
return;
}
rect = CRect(wt-22,202,wt-13,214);
if (rect.PtInRect(point)) {
Operate('>');
return;
}
CFrameWnd::OnLButtonDblClk(nFlags, point);
}
void CMainFrame::Operate(unsigned char button)
{
switch (button) {
case '0':
if (m_Display=="0")
break;
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
if (m_Status==Result || m_Status==Operator) {
m_Display = button;
m_Value = atof(m_Display);
m_Status = Number;
m_bPoint = false;
} else if (m_Status==Number) {
if (m_Display.GetLength()<DISPLAY_WIDTH) {
m_Display += button;
m_Value = atof(m_Display);
}
}
break;
case '.':
if (m_Status==Result || m_Status==Operator) {
m_Display = button;
m_Status = Number;
m_bPoint = true;
} else if (m_Status==Number && !m_bPoint) {
if (m_Display.GetLength()<DISPLAY_WIDTH) {
m_Display += button;
m_bPoint = true;
}
}
break;
case '+':
case '-':
case 'x':
case '/':
if (m_Status==Number && m_Operator)
MakeCalculus();
m_FirstNumber = m_Value;
m_Operator = button;
m_Status = Operator;
NormalizeDisplay();
break;
case 0xB1: // +/-
m_Value = -m_Value;
NormalizeDisplay();
break;
case '=':
if (m_Status==Number && m_Operator)
MakeCalculus();
else if (m_Status==Operator && m_Operator) {
m_FirstNumber = m_Value;
MakeCalculus();
}
m_Operator = 0;
m_Status = Result;
break;
case 'C':
m_Operator = 0;
m_Status = Result;
m_Display = "0";
m_Value = 0.0;
break;
case '<':
m_Month--;
if (!m_Month) {
m_Month = 12;
m_Year--;
}
Invalidate(TRUE);
break;
case '>':
m_Month++;
if (m_Month>12) {
m_Month = 1;
m_Year++;
}
Invalidate(TRUE);
break;
}
Invalidate(TRUE);
}
void CMainFrame::MakeCalculus()
{
double result;
switch (m_Operator) {
case '+':
result = m_FirstNumber + m_Value;
break;
case '-':
result = m_FirstNumber - m_Value;
break;
case 'x':
result = m_FirstNumber * m_Value;
break;
case '/': // Divide
if (m_Value==0.0) {
m_Display = "Error";
m_Status = Result;
m_Value = 0.0;
return;
}
result = m_FirstNumber / m_Value;
break;
default:
return;
}
m_Value = result;
NormalizeDisplay();
}
void CMainFrame::NormalizeDisplay()
{
if (log10(fabs(m_Value))>10.0 || log10(fabs(m_Value))<-10.0)
m_Display.Format("%e", m_Value);
else
m_Display.Format("%.10f", m_Value);
m_Display.TrimRight('0');
m_Display.TrimRight('.');
if (m_Display.GetLength()>13)
m_Display = m_Display.Left(12);
}