home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Using Visual C++ 4 (Special Edition)
/
Using_Visual_C_4_Special_Edition_QUE_1996.iso
/
ch11
/
calenctl.cpp
< prev
next >
Wrap
C/C++ Source or Header
|
1995-10-26
|
19KB
|
766 lines
// CalenCtl.cpp : Implementation of the CCalenCtrl OLE control class.
#include "stdafx.h"
#include "Calen.h"
#include "CalenCtl.h"
#include "CalenPpg.h"
#include "dayppg.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
int DaysInMonth[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
char *MonthsInYear[] =
{
"January",
"February",
"March",
"April",
"May",
"June",
"July",
"August",
"September",
"October",
"November",
"December"
};
char *DaysOfWeek[] =
{
"Sun",
"Mon",
"Tue",
"Wed",
"Thu",
"Fri",
"Sat"
};
IMPLEMENT_DYNCREATE(CCalenCtrl, COleControl)
/////////////////////////////////////////////////////////////////////////////
// Message map
BEGIN_MESSAGE_MAP(CCalenCtrl, COleControl)
//{{AFX_MSG_MAP(CCalenCtrl)
ON_WM_LBUTTONDOWN()
//}}AFX_MSG_MAP
ON_OLEVERB(AFX_IDS_VERB_PROPERTIES, OnProperties)
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// Dispatch map
BEGIN_DISPATCH_MAP(CCalenCtrl, COleControl)
//{{AFX_DISPATCH_MAP(CCalenCtrl)
DISP_PROPERTY_NOTIFY(CCalenCtrl, "Year", m_year, OnYearChanged, VT_I2)
DISP_PROPERTY_NOTIFY(CCalenCtrl, "CtrlBorderStyle", m_ctrlBorderStyle, OnCtrlBorderStyleChanged, VT_I2)
DISP_PROPERTY_NOTIFY(CCalenCtrl, "BorderRiseColor", m_borderRiseColor, OnBorderRiseColorChanged, VT_COLOR)
DISP_PROPERTY_NOTIFY(CCalenCtrl, "BorderFallColor", m_borderFallColor, OnBorderFallColorChanged, VT_COLOR)
DISP_PROPERTY_NOTIFY(CCalenCtrl, "BorderNormalColor", m_borderNormalColor, OnBorderNormalColorChanged, VT_COLOR)
DISP_PROPERTY_NOTIFY(CCalenCtrl, "ThreeD", m_threeD, OnThreeDChanged, VT_BOOL)
DISP_PROPERTY_NOTIFY(CCalenCtrl, "SelectedDayColor", m_selectedDayColor, OnSelectedDayColorChanged, VT_COLOR)
DISP_PROPERTY_NOTIFY(CCalenCtrl, "DayColor", m_dayColor, OnDayColorChanged, VT_COLOR)
DISP_PROPERTY_NOTIFY(CCalenCtrl, "DayBorderStyle", m_dayBorderStyle, OnDayBorderStyleChanged, VT_I2)
DISP_PROPERTY_NOTIFY(CCalenCtrl, "DayRiseColor", m_dayRiseColor, OnDayRiseColorChanged, VT_COLOR)
DISP_PROPERTY_NOTIFY(CCalenCtrl, "DayFallColor", m_dayFallColor, OnDayFallColorChanged, VT_COLOR)
DISP_PROPERTY_EX(CCalenCtrl, "DayFont", GetDayFont, SetDayFont, VT_FONT)
DISP_PROPERTY_EX(CCalenCtrl, "Day", GetDay, SetDay, VT_I2)
DISP_PROPERTY_EX(CCalenCtrl, "Month", GetMonth, SetMonth, VT_I2)
DISP_FUNCTION(CCalenCtrl, "SetDate", SetDate, VT_BOOL, VTS_I2 VTS_I2 VTS_I2)
DISP_STOCKPROP_BACKCOLOR()
DISP_STOCKPROP_FORECOLOR()
DISP_STOCKPROP_FONT()
//}}AFX_DISPATCH_MAP
DISP_FUNCTION_ID(CCalenCtrl, "AboutBox", DISPID_ABOUTBOX, AboutBox, VT_EMPTY, VTS_NONE)
END_DISPATCH_MAP()
/////////////////////////////////////////////////////////////////////////////
// Event map
BEGIN_EVENT_MAP(CCalenCtrl, COleControl)
//{{AFX_EVENT_MAP(CCalenCtrl)
EVENT_CUSTOM("Select", FireSelect, VTS_I2)
EVENT_STOCK_CLICK()
//}}AFX_EVENT_MAP
END_EVENT_MAP()
/////////////////////////////////////////////////////////////////////////////
// Property pages
// TODO: Add more property pages as needed. Remember to increase the count!
BEGIN_PROPPAGEIDS(CCalenCtrl, 4)
PROPPAGEID(CCalenPropPage::guid)
PROPPAGEID(CLSID_CFontPropPage)
PROPPAGEID(CLSID_CColorPropPage)
PROPPAGEID(CDayPropPage::guid)
END_PROPPAGEIDS(CCalenCtrl)
/////////////////////////////////////////////////////////////////////////////
// Initialize class factory and guid
IMPLEMENT_OLECREATE_EX(CCalenCtrl, "CALEN.CalenCtrl.1",
0xf0464dd3, 0xd57, 0x11cf, 0xb4, 0xcd, 0, 0x80, 0xc8, 0x1a, 0x39, 0x7c)
/////////////////////////////////////////////////////////////////////////////
// Type library ID and version
IMPLEMENT_OLETYPELIB(CCalenCtrl, _tlid, _wVerMajor, _wVerMinor)
/////////////////////////////////////////////////////////////////////////////
// Interface IDs
const IID BASED_CODE IID_DCalen =
{ 0xf0464dd1, 0xd57, 0x11cf, { 0xb4, 0xcd, 0, 0x80, 0xc8, 0x1a, 0x39, 0x7c } };
const IID BASED_CODE IID_DCalenEvents =
{ 0xf0464dd2, 0xd57, 0x11cf, { 0xb4, 0xcd, 0, 0x80, 0xc8, 0x1a, 0x39, 0x7c } };
/////////////////////////////////////////////////////////////////////////////
// Control type information
static const DWORD BASED_CODE _dwCalenOleMisc =
OLEMISC_ACTIVATEWHENVISIBLE |
OLEMISC_SETCLIENTSITEFIRST |
OLEMISC_INSIDEOUT |
OLEMISC_CANTLINKINSIDE |
OLEMISC_RECOMPOSEONRESIZE;
IMPLEMENT_OLECTLTYPE(CCalenCtrl, IDS_CALEN, _dwCalenOleMisc)
/////////////////////////////////////////////////////////////////////////////
// CCalenCtrl::CCalenCtrlFactory::UpdateRegistry -
// Adds or removes system registry entries for CCalenCtrl
BOOL CCalenCtrl::CCalenCtrlFactory::UpdateRegistry(BOOL bRegister)
{
if (bRegister)
return AfxOleRegisterControlClass(
AfxGetInstanceHandle(),
m_clsid,
m_lpszProgID,
IDS_CALEN,
IDB_CALEN,
FALSE, // Not insertable
_dwCalenOleMisc,
_tlid,
_wVerMajor,
_wVerMinor);
else
return AfxOleUnregisterClass(m_clsid, m_lpszProgID);
}
/////////////////////////////////////////////////////////////////////////////
// CCalenCtrl::CCalenCtrl - Constructor
CCalenCtrl::CCalenCtrl() : m_dayFont(NULL)
{
InitializeIIDs(&IID_DCalen, &IID_DCalenEvents);
m_dayFont.InitializeFont();
SetInitialSize(8*30,8*30);
}
/////////////////////////////////////////////////////////////////////////////
// CCalenCtrl::~CCalenCtrl - Destructor
CCalenCtrl::~CCalenCtrl()
{
// TODO: Cleanup your control's instance data here.
}
/////////////////////////////////////////////////////////////////////////////
// CCalenCtrl::OnDraw - Drawing function
void CCalenCtrl::OnDraw(CDC* pdc, const CRect& rcBounds,
const CRect& rcInvalid)
{
// Fill in background
CBrush brBack(TranslateColor(GetBackColor()));
pdc->FillRect(&rcInvalid,&brBack);
DrawBorder(rcBounds,pdc);
DrawMonth(rcBounds,pdc);
DrawDaysOfWeek(rcBounds,pdc);
DrawDays(rcBounds,pdc);
DrawSelectedDay(TRUE,rcBounds,pdc);
}
/////////////////////////////////////////////////////////////////////////////
// CCalenCtrl::DoPropExchange - Persistence support
void CCalenCtrl::DoPropExchange(CPropExchange* pPX)
{
ExchangeVersion(pPX, MAKELONG(_wVerMinor, _wVerMajor));
COleControl::DoPropExchange(pPX);
CTime time = CTime::GetCurrentTime();
PX_Bool(pPX,"ThreeD",m_threeD,FALSE);
PX_Short(pPX,"CtrlBorderStyle", m_ctrlBorderStyle,0);
PX_ULong(pPX,"BorderRiseColor", m_borderRiseColor, RGB(255,255,255));
PX_ULong(pPX,"BorderFallColor", m_borderFallColor, RGB(128,128,128));
PX_ULong(pPX,"BorderNormalColor", m_borderNormalColor, RGB(0,0,0));
PX_Font(pPX,"DayFont", m_dayFont,NULL,AmbientFont());
PX_ULong(pPX,"DayColor", m_dayColor, RGB(192,192,192));
PX_Short(pPX, "DayBorderStyle", m_dayBorderStyle, 0);
PX_ULong(pPX, "DayRiseColor", m_dayRiseColor, RGB(255,255,255));
PX_ULong(pPX, "DayFallColor", m_dayFallColor, RGB(128,128,128));
PX_Short(pPX, "Month", m_Month, time.GetMonth());
PX_Short(pPX, "Day", m_Day, time.GetDay());
PX_Short(pPX, "Year", m_year, time.GetYear());
PX_ULong(pPX, "SelectedDayColor", m_selectedDayColor, RGB(0,255,64));
}
/////////////////////////////////////////////////////////////////////////////
// CCalenCtrl::OnResetState - Reset control to default state
void CCalenCtrl::OnResetState()
{
COleControl::OnResetState(); // Resets defaults found in DoPropExchange
// TODO: Reset any other control state here.
}
/////////////////////////////////////////////////////////////////////////////
// CCalenCtrl::AboutBox - Display an "About" box to the user
void CCalenCtrl::AboutBox()
{
CDialog dlgAbout(IDD_ABOUTBOX_CALEN);
dlgAbout.DoModal();
}
/////////////////////////////////////////////////////////////////////////////
// CCalenCtrl message handlers
LPFONTDISP CCalenCtrl::GetDayFont()
{
return m_dayFont.GetFontDispatch();
}
void CCalenCtrl::SetDayFont(LPFONTDISP newValue)
{
SetModifiedFlag();
m_dayFont.InitializeFont(NULL,newValue);
InvalidateControl();
}
short CCalenCtrl::GetDay()
{
return m_Day;
}
void CCalenCtrl::SetDay(short nNewValue)
{
SetModifiedFlag();
// Make some attempt to determine if the day is within a given
// range. Note that this does not check for leap years
ASSERT(m_Month >= 1 && m_Month <= 12);
if(nNewValue <1 ||nNewValue > DaysInMonth[m_Month-1] )
{
ThrowError(CTL_E_INVALIDPROPERTYVALUE,
"Day is outside of allowable range");
}
else
{
CRect NullRect(0,0,0,0);
DrawSelectedDay(FALSE,NullRect);
m_Day = nNewValue;
DrawSelectedDay(TRUE,NullRect);
}
}
short CCalenCtrl::GetMonth()
{
return m_Month;
}
void CCalenCtrl::SetMonth(short nNewValue)
{
SetModifiedFlag();
if(nNewValue>0&&nNewValue<13)
{
m_Month = nNewValue;
InvalidateControl();
}
else
{
ThrowError(CTL_E_INVALIDPROPERTYVALUE,
"Month is outside of allowable range");
}
}
void CCalenCtrl::OnYearChanged()
{
InvalidateControl();
SetModifiedFlag();
}
void CCalenCtrl::OnCtrlBorderStyleChanged()
{
CRect NullRect(0,0,0,0);
DrawBorder(NullRect);
SetModifiedFlag();
}
void CCalenCtrl::OnBorderRiseColorChanged()
{
CRect NullRect(0,0,0,0);
DrawBorder(NullRect);
SetModifiedFlag();
}
void CCalenCtrl::OnBorderFallColorChanged()
{
CRect NullRect(0,0,0,0);
DrawBorder(NullRect);
SetModifiedFlag();
}
void CCalenCtrl::OnBorderNormalColorChanged()
{
CRect NullRect(0,0,0,0);
DrawBorder(NullRect);
SetModifiedFlag();
}
void CCalenCtrl::OnThreeDChanged()
{
CRect NullRect(0,0,0,0);
DrawBorder(NullRect);
SetModifiedFlag();
}
void CCalenCtrl::OnSelectedDayColorChanged()
{
InvalidateControl();
SetModifiedFlag();
}
void CCalenCtrl::OnDayColorChanged()
{
InvalidateControl();
SetModifiedFlag();
}
void CCalenCtrl::OnDayBorderStyleChanged()
{
InvalidateControl();
SetModifiedFlag();
}
void CCalenCtrl::OnDayRiseColorChanged()
{
InvalidateControl();
SetModifiedFlag();
}
void CCalenCtrl::OnDayFallColorChanged()
{
InvalidateControl();
SetModifiedFlag();
}
void CCalenCtrl::DrawBorder(const CRect& rcBounds, CDC *pDC)
{
BOOL nullDC = FALSE;
CRect cRect(rcBounds);
if(pDC==NULL)
{
pDC = GetDC();
GetClientRect(cRect);
nullDC = TRUE;
}
if(m_threeD)
{
// Determine the border colors based on the control style
COLORREF clrOne, clrTwo;
if (m_ctrlBorderStyle == 0)
{
//raised
clrOne = TranslateColor(m_borderRiseColor);
clrTwo = TranslateColor(m_borderFallColor);
}
else
{
//inset
clrOne = TranslateColor(m_borderFallColor);
clrTwo = TranslateColor(m_borderRiseColor);
}
CPen LeftTop;
CPen RightBottom;
// Make sure create pen succeeds and draw our 3D border
if(LeftTop.CreatePen(PS_SOLID,1,clrOne)
&& RightBottom.CreatePen(PS_SOLID,1,clrTwo))
{
CPen *OldPen = pDC->SelectObject(&LeftTop);
pDC->MoveTo(cRect.left,cRect.bottom-1);
pDC->LineTo(cRect.left,cRect.top);
pDC->LineTo(cRect.right-1,cRect.top);
pDC->SelectObject(&RightBottom);
pDC->LineTo(cRect.right-1,cRect.bottom-1);
pDC->LineTo(cRect.left-1,cRect.bottom-1);
pDC->SelectObject(OldPen);
}
}
else
{
CPen Pen;
if(Pen.CreatePen(PS_SOLID,1,TranslateColor(m_borderNormalColor)))
{
CPen *OldPen = pDC->SelectObject(&Pen);
pDC->MoveTo(cRect.left,cRect.top);
pDC->LineTo(cRect.right-1,cRect.top);
pDC->LineTo(cRect.right-1,cRect.bottom-1);
pDC->LineTo(cRect.left,cRect.bottom-1);
pDC->LineTo(cRect.left,cRect.top);
pDC->SelectObject(OldPen);
}
}
if(nullDC)
ReleaseDC(pDC);
}
void CCalenCtrl::DrawMonth(const CRect& rcBounds, CDC *pdc)
{
int oldBkMode;
CFont *oldFont;
COLORREF oldColor;
BOOL nullDC = FALSE;
CRect cRect(rcBounds);
if(pdc==NULL)
{
pdc = GetDC();
GetClientRect(cRect);
nullDC = TRUE;
}
// Draw the month in the top section of the frame
CRect littleRect(cRect.left,cRect.top,cRect.left+7*30,cRect.top+30);
oldFont = SelectStockFont(pdc);
oldBkMode = pdc->SetBkMode(TRANSPARENT);
oldColor = pdc->SetTextColor(TranslateColor(GetForeColor()));
pdc->DrawText(MonthsInYear[m_Month-1],lstrlen(MonthsInYear[m_Month-1]),
littleRect,DT_VCENTER|DT_CENTER|DT_SINGLELINE);
pdc->SetTextColor(oldColor);
pdc->SelectObject(oldFont);
pdc->SetBkMode(oldBkMode);
if(nullDC)
ReleaseDC(pdc);
}
void CCalenCtrl::DrawDaysOfWeek(const CRect& rcBounds, CDC *pdc)
{
int oldBkMode;
CFont *oldFont;
COLORREF oldColor;
CRect cRect(rcBounds);
BOOL nullDC = FALSE;
if(pdc==NULL)
{
pdc = GetDC();
GetClientRect(cRect);
nullDC = TRUE;
}
oldColor = pdc->SetTextColor(TranslateColor(GetForeColor()));
oldFont = SelectFontObject(pdc,m_dayFont);
oldBkMode = pdc->SetBkMode(TRANSPARENT);
// Get a reasonable distance from the start of the days
CSize cSize = pdc->GetTextExtent("X",1);
CRect littleRect(cRect.left+16,cRect.top+60-(cSize.cy+10),
cRect.left+45,cRect.top+60);
// Draw the days of the week
for(int i=0 ; i<7 ; i++)
{
pdc->DrawText(DaysOfWeek[i],lstrlen(DaysOfWeek[i]),littleRect,DT_VCENTER|DT_CENTER|DT_SINGLELINE);
littleRect.SetRect(cRect.left+16+(i+1)*30,cRect.top+60-(cSize.cy+10),
cRect.left+16+(i+1)*30+30,cRect.top+60);
}
pdc->SetTextColor(oldColor);
pdc->SelectObject(oldFont);
pdc->SetBkMode(oldBkMode);
if(nullDC)
ReleaseDC(pdc);
}
void CCalenCtrl::DrawDays(const CRect& rcBounds, CDC *pdc)
{
int oldBkMode;
CFont *oldFont;
CPen *oldPen;
COLORREF oldColor;
CRect cRect(rcBounds);
BOOL nullDC = FALSE;
if(pdc==NULL)
{
pdc = GetDC();
GetClientRect(cRect);
nullDC = TRUE;
}
// Setup border colors
COLORREF clrOne, clrTwo;
if (m_dayBorderStyle == 0)
{
//raised
clrOne = TranslateColor(m_dayRiseColor);
clrTwo = TranslateColor(m_dayFallColor);
}
else
{
//inset
clrOne = TranslateColor(m_dayFallColor);
clrTwo = TranslateColor(m_dayRiseColor);
}
oldColor = pdc->SetTextColor(TranslateColor(m_dayColor));
oldFont = SelectFontObject(pdc,m_dayFont);
oldBkMode = pdc->SetBkMode(TRANSPARENT);
CRect littleRect;
CPen LeftTop, RightBottom;
if(LeftTop.CreatePen(PS_SOLID,1,clrOne)
&& RightBottom.CreatePen(PS_SOLID,1,clrTwo))
{
oldPen = pdc->SelectObject(&LeftTop);
int row=0;
int col = 0;
CTime time(m_year, m_Month, 1, 1, 1, 1);
char day[4];
int firstday = time.GetDayOfWeek() - 1;
//day of week is 1-based; row and col are zero-based
int lastday = firstday + DaysInMonth[m_Month-1];
//notice this ignores leap years again
int i;
while (row < 6)
{
i = row*7+col;
if ( (i >= firstday) && (i <= lastday) )
{
// draw the square
littleRect.SetRect(cRect.left+15+2+col*30,
cRect.top+60+row*30+2, cRect.left+45-2+30*col,
cRect.top+90-2+row*30);
pdc->MoveTo(littleRect.left,littleRect.bottom);
pdc->SelectObject(&LeftTop);
pdc->LineTo(littleRect.left,littleRect.top);
pdc->LineTo(littleRect.right,littleRect.top);
pdc->SelectObject(&RightBottom);
pdc->LineTo(littleRect.right,littleRect.bottom);
pdc->LineTo(littleRect.left,littleRect.bottom);
// Draw the day number
sprintf(day, "%d", (i - firstday + 1));
pdc->TextOut(littleRect.left + 2, littleRect.top + 2,
day, lstrlen(day));
}
if (col == 6)
{
row++;
col = 0;
}
else
{
col++;
}
}
}
pdc->SetTextColor(oldColor);
pdc->SelectObject(oldPen);
pdc->SelectObject(oldFont);
pdc->SetBkMode(oldBkMode);
if(nullDC)
ReleaseDC(pdc);
}
void CCalenCtrl::DrawSelectedDay(BOOL bSelected, const CRect& rcBounds, CDC *pdc)
{
int oldBkMode;
CFont *oldFont;
COLORREF clrColor, oldColor;
CRect cRect(rcBounds);
BOOL nullDC = FALSE;
if(pdc==NULL)
{
pdc = GetDC();
GetClientRect(cRect);
nullDC = TRUE;
}
oldFont = SelectFontObject(pdc,m_dayFont);
oldBkMode = pdc->SetBkMode(TRANSPARENT);
CBrush cBrush;
char day[4];
// Determine the colors for brush and background
if(bSelected)
{
oldColor = pdc->SetTextColor(TranslateColor(GetForeColor()));
clrColor = TranslateColor(m_selectedDayColor);
}
else
{
oldColor = pdc->SetTextColor(TranslateColor(m_dayColor));
clrColor = TranslateColor(GetBackColor());
}
if(cBrush.CreateSolidBrush(clrColor))
{
// Determine exactly what the day coordinates are,
// fill the rectangle, and redraw the day text.
CRect littleRect;
CTime time(m_year, m_Month, 1, 1, 1 ,1);
int maxPos = (time.GetDayOfWeek()-1+m_Day-1) * 30;
int cx = maxPos % (7*30);
int cy = maxPos / (7*30) * 30;
littleRect.SetRect(cRect.left+15+cx+3,cRect.top+60+cy+3,
cRect.left+45+cx-2, cRect.top+90+cy-2);
pdc->FillRect(littleRect,&cBrush);
// Draw the day number
sprintf(day, "%d", m_Day);
pdc->TextOut(littleRect.left+1, littleRect.top+1,
day, lstrlen(day));
}
pdc->SetTextColor(oldColor);
pdc->SelectObject(oldFont);
pdc->SetBkMode(oldBkMode);
if(nullDC)
ReleaseDC(pdc);
}
BOOL CCalenCtrl::SetDate(short month, short day, short year)
{
BOOL RetVal = FALSE;
if(month >= 1 && month <= 12)
{
if(day >= 1 && day <= DaysInMonth[month-1])
{
m_Month = month;
m_Day = day;
m_year = year;
InvalidateControl();
RetVal = TRUE;
}
else
ThrowError(CTL_E_INVALIDPROPERTYVALUE,
"Day is outside of allowable range");
}
else
ThrowError(CTL_E_INVALIDPROPERTYVALUE,
"Month is outside of allowable range");
return RetVal;
}
void CCalenCtrl::OnLButtonDown(UINT nFlags, CPoint point)
{
COleControl::OnLButtonDown(nFlags, point);
short day;
if((day = HitTest(point))!=-1)
{
CRect NullRect(0,0,0,0);
DrawSelectedDay(FALSE,NullRect);
m_Day = day;
DrawSelectedDay(TRUE,NullRect);
FireSelect(day);
}
}
short CCalenCtrl::HitTest(CPoint &point)
{
short retval = -1;
// Must be at least past the start of the days
if(point.y>60)
{
// Must be at least between the first and last day on width
if(point.x > 15 && point.x < (15+30*7))
{
CTime cTime(m_year, m_Month, 1, 1, 1, 1);
// Calculate the row and the column
int row = (point.y-60)/30;
int col = (point.x-15)/30;
int day = row*7+col;
day = day + 1 - cTime.GetDayOfWeek() + 1;
// If the day is within the bounds, then return the value
if(day > 0 && day <= DaysInMonth[m_Month-1])
retval = day;
}
}
return retval;
}