Click here to Skip to main content
15,880,972 members
Articles / Desktop Programming / MFC

Calendar Plug-in for .dan.g.'s ToDoList - In 10 Easy Steps™

Rate me:
Please Sign up or sign in to vote.
4.99/5 (63 votes)
10 Jun 2008CC (ASA 2.5)12 min read 1.1M   7.7K   252  
A Calendar UI extension component for the ToDoList, giving you a timeline view of your tasks
//Written for the ToDoList (http://www.codeproject.com/KB/applications/todolist2.aspx)
//Design and latest version - http://www.codeproject.com/KB/applications/TDL_Calendar.aspx
//by demon.code.monkey@googlemail.com

#include "stdafx.h"
#include "BigCalendarCtrl.h"
#include "BigCalendarTask.h"
#include "CalendarData.h"
#include "CalendarDefines.h"
#include "..\..\Shared\Misc.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

#define COLOUR_DOT_TASK_START		RGB(50,200,50)
#define COLOUR_DOT_TASK_END			RGB(230,50,50)
#define COLOUR_DOT_COMPLETED_TASK	RGB(200,200,200)

#define MAX_TOOLTIP_LENGTH			1024

CBigCalendarTask::CBigCalendarTask(CBigCalendarCtrl* _pParent/*=NULL*/,
								   DWORD _dwStyleCompletedTasks/*=0*/)
:	m_pParent(_pParent),
	m_pszTooltipText(NULL)
{
	m_pszTooltipText = new char[MAX_TOOLTIP_LENGTH+1];

	BOOL bGrey = ((_dwStyleCompletedTasks & COMPLETEDTASKS_GREY) != 0);
	BOOL bStrikethru = ((_dwStyleCompletedTasks & COMPLETEDTASKS_STRIKETHRU) != 0);
	SetCompletedItemDisplayStyle(bGrey, bStrikethru);
}

CBigCalendarTask::~CBigCalendarTask()
{
	if (m_pszTooltipText)
	{
		delete m_pszTooltipText;
	}
}

BEGIN_MESSAGE_MAP(CBigCalendarTask, CTransparentListBox)
	//{{AFX_MSG_MAP(CBigCalendarTask)
	ON_WM_CREATE()
	ON_WM_PAINT()
	ON_WM_LBUTTONDOWN()
	ON_WM_RBUTTONDOWN()
	ON_WM_MOUSEWHEEL()
	ON_WM_SETCURSOR()
	ON_NOTIFY_EX(TTN_NEEDTEXT, 0, OnToolTipText)
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

int CBigCalendarTask::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
	if (CTransparentListBox::OnCreate(lpCreateStruct) == -1)
		return -1;

	return 0;
}

void CBigCalendarTask::OnPaint() 
{
	CTransparentListBox::OnPaint();
	Invalidate(); //this call seems necessary otherwise our dots don't get drawn

	int nItems = GetCount();
	if (nItems > 0)
	{
		CPaintDC dc(this);

		CRect rcListBox;
		GetWindowRect(rcListBox);
		ScreenToClient(rcListBox);

		//draw a little dot next to each task (if the item is visible)
		for (int i = 0; i < nItems; i++)
		{
			CRect rc;
			GetItemRect(i, rc);
			CPoint ptCheck(rc.left+1, rc.top+1);
			if (rcListBox.PtInRect(ptCheck))
			{
				//this item is currently visible
				CRect rcDot(rc.left, rc.top+2, rc.left+3, rc.bottom-2);

				CBrush br;
				DWORD dwTaskID = ((SItem*)GetItemData(i))->dwItemData;

				BOOL bCompleteTask = FALSE;
				m_mapTaskIDToCompleteTask.Lookup(dwTaskID, bCompleteTask);
				if (bCompleteTask)
				{
					//completed task (blue)
					br.CreateSolidBrush(COLOUR_DOT_COMPLETED_TASK);
				}
				else
				{
					BOOL bStartTask = FALSE;
					m_mapTaskIDToStartTask.Lookup(dwTaskID, bStartTask);
					if (bStartTask)
					{
						//start task (green)
						br.CreateSolidBrush(COLOUR_DOT_TASK_START);
					}
					else
					{
						//due task (red)
						br.CreateSolidBrush(COLOUR_DOT_TASK_END);
					}
				}
				dc.FillRect(&rcDot, &br);
			}
		}
	}
}

void CBigCalendarTask::OnLButtonDown(UINT nFlags, CPoint point) 
{
	CTransparentListBox::OnLButtonDown(nFlags, point);

	//inform parent of newly-selected task
	int nListboxID = GetDlgCtrlID();
	int nSelectedTask = GetCurSel();
	m_pParent->SelectTask(nListboxID, nSelectedTask);
	m_pParent->ClickedOnTaskInListbox();
}

void CBigCalendarTask::OnRButtonDown(UINT nFlags, CPoint point) 
{
	CTransparentListBox::OnRButtonDown(nFlags, point);

	//inform parent of newly-selected task
	int nListboxID = GetDlgCtrlID();
	int nSelectedTask = GetCurSel();
	m_pParent->SelectTask(nListboxID, nSelectedTask);
	m_pParent->ClickedOnTaskInListbox();

	//TODO: show popup
}

BOOL CBigCalendarTask::OnMouseWheel(UINT nFlags, short zDelta, CPoint pt) 
{
	return m_pParent->OnMouseWheel(nFlags, zDelta, pt);
}

BOOL CBigCalendarTask::OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message) 
{
	SetCursor(Misc::HandCursor());
	return TRUE;
}

int CBigCalendarTask::AddItem(const CString& _strText,
							  DWORD _dwTaskID,
							  BOOL _bStartTask,
							  BOOL _bCompleteTask)
{
	m_mapTaskIDToStartTask.SetAt(_dwTaskID, _bStartTask);
	m_mapTaskIDToCompleteTask.SetAt(_dwTaskID, _bCompleteTask);
	int nReturn = AddString(_strText, _dwTaskID, _bCompleteTask);
	return nReturn;
}

void CBigCalendarTask::ResetContent()
{
	m_mapTaskIDToStartTask.RemoveAll();
	m_mapTaskIDToCompleteTask.RemoveAll();
	CTransparentListBox::ResetContent();
}

void CBigCalendarTask::PreSubclassWindow()
{
	CTransparentListBox::PreSubclassWindow();
	EnableToolTips(TRUE);
}

int CBigCalendarTask::OnToolHitTest(CPoint point, TOOLINFO* pTI) const
{
	BOOL bNotUsed = FALSE;
	UINT iItemIndex = ItemFromPoint(point, bNotUsed);
	if (iItemIndex != -1)
	{
		pTI->hwnd = m_hWnd;
		pTI->uId = iItemIndex;
		GetItemRect(iItemIndex, &pTI->rect);
		pTI->lpszText = LPSTR_TEXTCALLBACK;
	}
	return iItemIndex;
}

BOOL CBigCalendarTask::OnToolTipText(UINT id, NMHDR* pTTTStruct, LRESULT* pResult)
{
	TOOLTIPTEXT* pTTT = (TOOLTIPTEXT*)pTTTStruct;

	CToolTipCtrl* pttc = AfxGetThreadState()->m_pToolTip;
	if (pttc)
	{
		pttc->SetMaxTipWidth(0);					//enable multi-line tooltips
		pttc->SetDelayTime(TTDT_AUTOPOP, SHRT_MAX);	//set the maximum possible time for the tooltip to stay up for
	}

	DWORD dwTaskID = ((SItem*)GetItemData(pTTTStruct->idFrom))->dwItemData;
	CString strParentsString = m_pParent->GetCalendarData()->GetTaskParentsString(dwTaskID);

	if (strParentsString.GetLength() > MAX_TOOLTIP_LENGTH)
	{
		strParentsString.SetAt(MAX_TOOLTIP_LENGTH, '\0');
	}
	strcpy(m_pszTooltipText, strParentsString);

 	pTTT->lpszText = m_pszTooltipText;

	*pResult = 0;

	return TRUE;    
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Creative Commons Attribution-ShareAlike 2.5 License


Written By
Software Developer (Senior)
United Kingdom United Kingdom
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions