todoctrl.cpp

来自「管理项目进度工具的原代码」· C++ 代码 · 共 2,301 行 · 第 1/5 页

CPP
2,301
字号
// ToDoCtrl.cpp : implementation file
//

#include "stdafx.h"
#include "ToDoCtrl.h"
#include "tdlschemadef.h"
#include "taskfile.h"
#include "tdcmsg.h"
#include "todocommentsctrl.h"
#include "tdstringres.h"
#include "resource.h"
#include "tasktimelog.h"

#include "..\shared\holdredraw.h"
#include "..\shared\deferWndMove.h"
#include "..\shared\dlgunits.h"
#include "..\shared\themed.h"
#include "..\shared\datehelper.h"
#include "..\shared\driveinfo.h"
#include "..\shared\toolbarhelper.h"
#include "..\shared\colordef.h"
#include "..\shared\spellcheckdlg.h"
#include "..\shared\passworddialog.h"
#include "..\shared\winclasses.h"
#include "..\shared\wclassdefines.h"
#include "..\shared\enfiledialog.h"
#include "..\shared\misc.h"
#include "..\shared\enstring.h"
#include "..\shared\stringres.h"
#include "..\shared\treectrlhelper.h"
#include "..\shared\filemisc.h"
#include "..\shared\osversion.h"

#include <Windowsx.h>
#include <float.h>
#include <Lmcons.h>
#include <math.h>
#include <afxpriv.h>

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

// note: do not use 'c' as a shortcut letter
static TDCCONTROL TDCCONTROLS[] = 
{
	{ WC_STATIC,	IDS_TDC_FIELD_PROJECT, 0, 0, 0,3,28,8, IDC_PROJECTLABEL },
	{ WC_EDIT,		0, ES_AUTOHSCROLL | WS_TABSTOP, 0, 28,1,142,13, IDC_PROJECTNAME },
	{ WC_STATIC,	IDS_TDC_FIELD_TASKLIST, /*WS_NOTVISIBLE*/0, 0, 0,0,0,0, (UINT)IDC_STATIC },
	{ WC_TREEVIEW,	0, TVS_EDITLABELS | WS_TABSTOP | TVS_SHOWSELALWAYS | TVS_HASLINES | TVS_LINESATROOT | TVS_HASBUTTONS, 0, 0,16,190,108, IDC_TASKLIST },
	{ WC_STATIC,	IDS_TDC_FIELD_PRIORITY, SS_CENTERIMAGE, 0, 119,131,22,8, IDC_PRIORITYLABEL },
	{ WC_COMBOBOX,	0, CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP | CBS_OWNERDRAWFIXED | CBS_HASSTRINGS, 0, 159,128,65,300, IDC_PRIORITY },
	{ WC_STATIC,	IDS_TDC_FIELD_RISK, SS_CENTERIMAGE, 0, 119,131,22,8, IDC_RISKLABEL },
	{ WC_COMBOBOX,	0, CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP, 0, 159,128,65,300, IDC_RISK },
	{ WC_STATIC,	IDS_TDC_FIELD_PERCENT, SS_CENTERIMAGE, 0, 119,148,37,8, IDC_PERCENTLABEL },
	{ WC_EDIT,		0, WS_TABSTOP, 0, 159,146,65,13, IDC_PERCENT },
	{ WC_SPIN,		0, UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_ARROWKEYS, 0, 97,180,13,14, IDC_PERCENTSPIN },
	{ WC_STATIC,	IDS_TDC_FIELD_TIMEEST, SS_CENTERIMAGE, 0, 1,148,40,8, IDC_TIMEESTLABEL },
	{ WC_EDIT,		0, ES_AUTOHSCROLL | WS_TABSTOP, 0, 45,146,65,13, IDC_TIMEEST },
	{ WC_STATIC,	IDS_TDC_FIELD_TIMESPENT, SS_CENTERIMAGE, 0, 1,148,40,8, IDC_TIMESPENTLABEL },
	{ WC_EDIT,		0, ES_AUTOHSCROLL | WS_TABSTOP, 0, 45,146,65,13, IDC_TIMESPENT },
	{ WC_STATIC,	IDS_TDC_FIELD_STARTDATE, SS_CENTERIMAGE, 0, 1,166,33,8, IDC_STARTLABEL },
	{ WC_DATETIMEPICK, 0, DTS_RIGHTALIGN | DTS_SHOWNONE | WS_TABSTOP, 0, 45,164,65,13, IDC_STARTDATE },
	{ WC_STATIC,	IDS_TDC_FIELD_DUEDATE, SS_CENTERIMAGE, 0, 119,166,32,8, IDC_DUELABEL },
	{ WC_DATETIMEPICK, 0, DTS_RIGHTALIGN | DTS_SHOWNONE | WS_TABSTOP, 0, 159,164,65,13, IDC_DUEDATE },
	{ WC_STATIC,	IDS_TDC_FIELD_DONEDATE, SS_CENTERIMAGE, 0, 1,184,34,8, IDC_DONELABEL },
	{ WC_DATETIMEPICK, 0, DTS_RIGHTALIGN | DTS_SHOWNONE | WS_TABSTOP, 0, 45,182,65,13, IDC_DONEDATE },
	{ WC_STATIC,	IDS_TDC_FIELD_RECURRENCE, SS_CENTERIMAGE, 0, 119,184,37,8, IDC_RECURRENCELABEL },
	{ WC_EDIT,		0, ES_AUTOHSCROLL | ES_LEFT | WS_TABSTOP, 0, 159,182,65,13, IDC_RECURRENCE },
	{ WC_STATIC,	IDS_TDC_FIELD_COLOUR, SS_CENTERIMAGE, 0, 1,131,38,8, IDC_COLOURLABEL },
	{ WC_BUTTON,	0, WS_TABSTOP, 0, 1,131,38,8, IDC_COLOUR },
	{ WC_STATIC,	IDS_TDC_FIELD_ALLOCTO, SS_CENTERIMAGE, 0, 1,131,38,8, IDC_ALLOCTOLABEL },
	{ WC_COMBOBOX,	0, CBS_SORT | CBS_DROPDOWN | WS_VSCROLL | CBS_AUTOHSCROLL | CBS_AUTOHSCROLL | WS_TABSTOP | CBS_OWNERDRAWFIXED | CBS_HASSTRINGS, 0, 45,128,65,200, IDC_ALLOCTO },
	{ WC_STATIC,	IDS_TDC_FIELD_ALLOCBY, SS_CENTERIMAGE, 0, 1,131,38,8, IDC_ALLOCBYLABEL },
	{ WC_COMBOBOX,	0, CBS_SORT | CBS_DROPDOWN | WS_VSCROLL | CBS_AUTOHSCROLL | CBS_AUTOHSCROLL | WS_TABSTOP, 0, 45,128,65,200, IDC_ALLOCBY },
	{ WC_STATIC,	IDS_TDC_FIELD_STATUS, SS_CENTERIMAGE, 0, 1,131,38,8, IDC_STATUSLABEL },
	{ WC_COMBOBOX,	0, CBS_SORT | CBS_DROPDOWN | WS_VSCROLL | CBS_AUTOHSCROLL | CBS_AUTOHSCROLL | WS_TABSTOP, 0, 45,128,65,200, IDC_STATUS },
	{ WC_STATIC,	IDS_TDC_FIELD_CATEGORY, SS_CENTERIMAGE, 0, 1,131,38,8, IDC_CATEGORYLABEL },
	{ WC_COMBOBOX,	0, CBS_SORT | CBS_DROPDOWN | WS_VSCROLL | CBS_AUTOHSCROLL | CBS_AUTOHSCROLL | WS_TABSTOP | CBS_OWNERDRAWFIXED | CBS_HASSTRINGS, 0, 45,128,65,200, IDC_CATEGORY },
	{ WC_STATIC,	IDS_TDC_FIELD_EXTID, SS_CENTERIMAGE, 0, 119,184,37,8, IDC_EXTERNALIDLABEL },
	{ WC_EDIT,		0, ES_AUTOHSCROLL | ES_LEFT | WS_TABSTOP, 0, 159,182,65,13, IDC_EXTERNALID },
	{ WC_STATIC,	IDS_TDC_FIELD_COST, SS_CENTERIMAGE, 0, 119,184,37,8, IDC_COSTLABEL },
	{ WC_EDIT,		0, ES_AUTOHSCROLL | ES_LEFT | WS_TABSTOP, 0, 159,182,65,13, IDC_COST },
	{ WC_STATIC,	IDS_TDC_FIELD_DEPENDENCY, SS_CENTERIMAGE, 0, 119,184,37,8, IDC_DEPENDSLABEL },
	{ WC_EDIT,		0, ES_AUTOHSCROLL | ES_LEFT | WS_TABSTOP, 0, 159,182,65,13, IDC_DEPENDS },
	{ WC_STATIC,	IDS_TDC_FIELD_VERSION, SS_CENTERIMAGE, 0, 119,184,37,8, IDC_VERSIONLABEL },
	{ WC_COMBOBOX,	0, CBS_SORT | CBS_DROPDOWN | WS_VSCROLL | CBS_AUTOHSCROLL | CBS_AUTOHSCROLL | WS_TABSTOP, 0, 45,128,65,200, IDC_VERSION },
	{ WC_STATIC,	IDS_TDC_FIELD_FILEREF, SS_CENTERIMAGE, 0, 119,184,37,8, IDC_FILEPATHLABEL },
	{ WC_EDIT,		0, ES_AUTOHSCROLL | ES_LEFT | WS_TABSTOP, 0, 159,182,65,13, IDC_FILEPATH },
	{ WC_STATIC,	IDS_TDC_FIELD_COMMENTS, SS_CENTERIMAGE, 0, 1,201,34,12, IDC_COMMENTSLABEL },
	{ WC_COMBOBOX,	0, CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP, 0, 37,201,65, 200, IDC_COMMENTSTYPE },
	{ WC_STATIC,	0, SS_ETCHEDHORZ, 0, 35, 204, 187, 2, IDC_HSPLITTER },
};

int NUM_CTRLS = sizeof(TDCCONTROLS) / sizeof(TDCCONTROL);

static TDCCOLUMN COLUMNS[] = 
{
	{ TDCC_ID, IDS_TDC_COLUMN_ID, TDC_SORTBYID, DT_LEFT, TRUE, NULL, FALSE, TRUE },
	{ TDCC_PRIORITY, IDS_TDC_COLUMN_PRIORITY, TDC_SORTBYPRIORITY, DT_CENTER, TRUE, NULL, FALSE, FALSE },
	{ TDCC_RISK, 0x4d, TDC_SORTBYRISK, DT_CENTER, TRUE, "Wingdings", TRUE, TRUE },
	{ TDCC_PERCENT, IDS_TDC_COLUMN_PERCENT, TDC_SORTBYPERCENT, DT_CENTER, TRUE, NULL, FALSE, FALSE },
	{ TDCC_TIMEEST, IDS_TDC_COLUMN_TIMEEST, TDC_SORTBYTIMEEST, DT_RIGHT, TRUE, NULL, FALSE, TRUE },
	{ TDCC_TIMESPENT, IDS_TDC_COLUMN_TIMESPENT, TDC_SORTBYTIMESPENT, DT_RIGHT, TRUE, NULL, FALSE, TRUE },
	{ TDCC_TRACKTIME, 0xb9, (TDC_SORTBY)-1, DT_CENTER, FALSE, "Wingdings", TRUE, TRUE },
	{ TDCC_CREATIONDATE, IDS_TDC_COLUMN_CREATEDATE, TDC_SORTBYCREATIONDATE, DT_RIGHT, TRUE, NULL, FALSE, TRUE },
	{ TDCC_CREATEDBY, IDS_TDC_COLUMN_CREATEDBY, TDC_SORTBYCREATEDBY, DT_LEFT, TRUE, NULL, FALSE, TRUE },
	{ TDCC_LASTMOD, IDS_TDC_COLUMN_MODIFYDATE, TDC_SORTBYLASTMOD, DT_RIGHT, TRUE, NULL, FALSE, TRUE },
	{ TDCC_STARTDATE, IDS_TDC_COLUMN_STARTDATE, TDC_SORTBYSTARTDATE, DT_RIGHT, TRUE, NULL, FALSE, TRUE },
	{ TDCC_DUEDATE, IDS_TDC_COLUMN_DUEDATE, TDC_SORTBYDUEDATE, DT_RIGHT, TRUE, NULL, FALSE, TRUE },
	{ TDCC_DONEDATE, IDS_TDC_COLUMN_DONEDATE, TDC_SORTBYDONEDATE, DT_RIGHT, TRUE, NULL, FALSE, TRUE },
	{ TDCC_RECURRENCE, IDS_TDC_COLUMN_RECURRENCE, TDC_SORTBYRECURRENCE, DT_LEFT, TRUE, NULL, FALSE, TRUE },
	{ TDCC_ALLOCTO, IDS_TDC_COLUMN_ALLOCTO, TDC_SORTBYALLOCTO, DT_LEFT, TRUE, NULL, FALSE, TRUE },
	{ TDCC_ALLOCBY, IDS_TDC_COLUMN_ALLOCBY, TDC_SORTBYALLOCBY, DT_LEFT, TRUE, NULL, FALSE, TRUE },
	{ TDCC_STATUS, IDS_TDC_COLUMN_STATUS, TDC_SORTBYSTATUS, DT_LEFT, TRUE, NULL, FALSE, TRUE },
	{ TDCC_CATEGORY, IDS_TDC_COLUMN_CATEGORY, TDC_SORTBYCATEGORY, DT_LEFT, TRUE, NULL, FALSE, TRUE },
	{ TDCC_EXTERNALID, IDS_TDC_COLUMN_EXTID, TDC_SORTBYEXTERNALID, DT_RIGHT, TRUE, NULL, FALSE, TRUE },
	{ TDCC_COST, IDS_TDC_COLUMN_COST, TDC_SORTBYCOST, DT_RIGHT, TRUE, NULL, FALSE, TRUE },
	{ TDCC_DEPENDENCY, 0xc3, (TDC_SORTBY)-1, DT_LEFT, FALSE, "Wingdings", TRUE, TRUE },
	{ TDCC_VERSION, IDS_TDC_COLUMN_VERSION, TDC_SORTBYVERSION, DT_LEFT, TRUE, NULL, FALSE, TRUE },
	{ TDCC_FILEREF, 0x3c, (TDC_SORTBY)-1, DT_LEFT, FALSE, "Wingdings", TRUE, TRUE },
	{ TDCC_FLAG, 0x4f, TDC_SORTBYFLAG, DT_CENTER, TRUE, "Wingdings", TRUE, FALSE },
	{ TDCC_DONE, 0x61, TDC_SORTBYDONE, DT_CENTER, TRUE, "Marlett", TRUE, FALSE },
	
	// special client column
	{ TDCC_CLIENT, IDS_TDC_COLUMN_TASK, TDC_SORTBYNAME, DT_LEFT, TRUE, NULL, FALSE, TRUE },
};

int NUM_COLUMNS = sizeof(COLUMNS) / sizeof(TDCCOLUMN);

static CTRLITEM CTRLITEMS[] = 
{
	{ IDC_PRIORITY,		IDC_PRIORITYLABEL,	TDCC_PRIORITY },
	{ IDC_RISK,			IDC_RISKLABEL,		TDCC_RISK },
	{ IDC_PERCENT,		IDC_PERCENTLABEL,	TDCC_PERCENT },
	{ IDC_TIMEEST,		IDC_TIMEESTLABEL,	TDCC_TIMEEST },
	{ IDC_TIMESPENT,	IDC_TIMESPENTLABEL,	TDCC_TIMESPENT },
	{ IDC_STARTDATE,	IDC_STARTLABEL,		TDCC_STARTDATE },
	{ IDC_DUEDATE,		IDC_DUELABEL,		TDCC_DUEDATE },
	{ IDC_DONEDATE,		IDC_DONELABEL,		TDCC_DONEDATE },
	{ IDC_RECURRENCE,	IDC_RECURRENCELABEL,TDCC_RECURRENCE },
	{ IDC_COLOUR,		IDC_COLOURLABEL,	(TDC_COLUMN)-1 },
	{ IDC_ALLOCTO,		IDC_ALLOCTOLABEL,	TDCC_ALLOCTO },
	{ IDC_ALLOCBY,		IDC_ALLOCBYLABEL,	TDCC_ALLOCBY },
	{ IDC_STATUS,		IDC_STATUSLABEL,	TDCC_STATUS },
	{ IDC_CATEGORY,		IDC_CATEGORYLABEL,	TDCC_CATEGORY },
	{ IDC_EXTERNALID,	IDC_EXTERNALIDLABEL,TDCC_EXTERNALID },
	{ IDC_COST,			IDC_COSTLABEL,		TDCC_COST },
	{ IDC_DEPENDS,		IDC_DEPENDSLABEL,	TDCC_DEPENDENCY },
	{ IDC_VERSION,		IDC_VERSIONLABEL,	TDCC_VERSION },
	{ IDC_FILEPATH,		IDC_FILEPATHLABEL,	TDCC_FILEREF },
};

const int NUM_CTRLITEMS = sizeof(CTRLITEMS) / sizeof(CTRLITEM);

/////////////////////////////////////////////////////////////////////////////
// CToDoCtrl dialog

enum 
{
	ID_TIMEEDITBTN = 0xfff0,
	ID_EXTERNALID_LINK,
	ID_DEPENDS_LINK,
};

const int CTRLHEIGHT = 14; // dlu
const int CTRLVSPACING = 5; // dlu
const int CTRLHSPACING = 4; // dlu
const int CTRLSTARTOFFSET = 45; // dlu
const int CTRLENDOFFSET = 110; // dlu
const unsigned short FILEFORMAT = 8; // increment this when format changes
const unsigned short SPLITSIZE = 6; 
const unsigned short MINCOMMENTSIZE = 0;
const unsigned short DEFCOMMENTSIZE = 260;
const unsigned short MINNONCOMMENTHEIGHT = 250; // what's above the comment section
const unsigned short MINNONCOMMENTWIDTH = 350; // what's to the left of the comment section
const COLORREF BLACK = RGB(0, 0, 0);
const COLORREF WHITE = RGB(240, 240, 240);
const COLORREF NOCOLOR = ((COLORREF)-1);
const UINT CLOCKBTN = 0xb9;
const UINT LINKBTN = 0x24;
const COLORREF COMMENTSCOLOR = RGB(98, 98, 98);
const UINT DAY_IN_SECS = 24 * 60 * 60;

enum 
{
	WM_TDC_RESTOREFOCUSEDITEM = (WM_APP + 1),
	WM_TDC_REFRESHPERCENTSPINVISIBILITY,
};

enum // flags for UpdateTask
{
	UTF_TIMEUNITSONLY	= 0x01,
	UTF_RECALCTIME		= 0x02,		
};

enum { TIMER_TRACK = 1, TIMER_MIDNIGHT };

const int TIMETRACKPERIOD = 10000; // 10 secs in millesecs
const int MIDNIGHTPERIOD = 60000; // 1 minute in millesecs

#ifdef _DEBUG
const double TICKS2HOURS = 10.0 / (1000 * 3600);
#else
const double TICKS2HOURS = 1.0 / (1000 * 3600);
#endif


// private class to help optimize xml parsing
class CXmlParseController : public IXmlParse
{
public:
	CXmlParseController(LPCTSTR szItem) : m_sItem(szItem) {}
	
	virtual BOOL Continue(LPCTSTR szItem, LPCTSTR /*szValue*/) const
	{
		return (m_sItem.CompareNoCase(szItem) != 0);
	}
	
protected:
	CString m_sItem;
};

//////////////////////////////////////////////////////////////////////////////

// static variables
TDLCLIPBOARD CToDoCtrl::s_clipboard;
int CToDoCtrl::s_nCommentsSize = -1; // unset
TODOITEM CToDoCtrl::s_tdDefault;
short CToDoCtrl::s_nExtendedSelection = HOTKEYF_CONTROL | HOTKEYF_SHIFT;

CToDoCtrl::CToDoCtrl(CContentMgr& mgr, const CONTENTFORMAT& cfDefault) : 
						m_bModified(FALSE), 
						m_dwNextUniqueID(1), 
						m_nPriority(-1), 
						m_nSortBy(TDC_SORTUNDEF),
						m_bSortAscending(-1),
						m_nFileVersion(0),
						m_bArchive(FALSE),
						m_dTimeEstimate(0),
						m_dTimeSpent(0),
						m_eFileRef(FES_COMBOSTYLEBTN | FES_GOBUTTON | FES_ALLOWURL),
						m_nFileFormat(FILEFORMAT),
						m_bModSinceLastSort(FALSE),
						m_dwVisibleColumns(0),
						m_crTaskDone(NOCOLOR),
						m_bCheckedOut(FALSE),
						m_nCommentsSize(DEFCOMMENTSIZE),
						m_bSplitting(FALSE),
						m_data(m_tree, m_aStyles),
						m_selection(m_tree),
						m_wKeyPress(FALSE),
						m_dwTimeTrackTaskID(0),
						m_treeDragDrop(Selection(), m_tree, TRUE, TRUE),
						m_htiLastAdded(NULL),
						m_cbAllocBy(TRUE, FALSE),
						m_cbAllocTo(TRUE),
						m_cbCategory(TRUE),
						m_cbStatus(TRUE, FALSE),
						m_cbVersion(TRUE, FALSE),
						m_fontTree(NULL),
						m_fontDone(NULL),
						m_fontComments(NULL),
						m_nMaxInfotipCommentsLength(-1),
						m_ctrlComments(NULL),
						m_bSourceControlled(FALSE),
						m_mgrContent(mgr),
						m_cfDefault(cfDefault),
						m_hilDone(NULL),
						m_dLogTime(0),
						m_fontBold(NULL),
						m_htiEditing(NULL),
						m_crDue(NOCOLOR), 
						m_crDueToday(NOCOLOR),
						m_cbCommentsType(&mgr),
						m_tree(NCGS_DOUBLEBUFFERCLIENT | NCGS_SHOWHEADER)
{
	SetBordersDLU(0);
	
	// add controls
	for (int nCtrl = 0; nCtrl < NUM_CTRLS; nCtrl++)
	{
		const TDCCONTROL& ctrl = TDCCONTROLS[nCtrl];

		AddRCControl("CONTROL", ctrl.szClass, CEnString(ctrl.nIDCaption), 
					ctrl.dwStyle, ctrl.dwExStyle,
					ctrl.nX, ctrl.nY, ctrl.nCx, ctrl.nCy, ctrl.nID);
	}
	
	// machine name
	DWORD LEN = MAX_COMPUTERNAME_LENGTH + 1;
	
	::GetComputerName(m_sMachineName.GetBuffer(LEN), &LEN);
	m_sMachineName.ReleaseBuffer();
	
    // init styles array
    // MFC sets all elements to zero
    m_aStyles.SetSize(TDCS_LAST);
	m_aStyles.SetAt(TDCS_RIGHTALIGNLABELS, 1);
	
	// set up number masks
	m_ePercentDone.SetMask("0123456789");
	m_eCost.SetMask(".0123456789", ME_LOCALIZEDECIMAL);
	
	// add chess clock button to 'time spent'
	m_eTimeSpent.InsertButton(0, ID_TIMEEDITBTN, CLOCKBTN, 
								CEnString(IDS_TDC_STARTSTOPCLOCK), 
								DEF_BTNWIDTH + 4, "Wingdings");

	// add link button to dependency
	m_eDependency.AddButton(ID_DEPENDS_LINK, LINKBTN, 
							CEnString(IDS_TDC_DEPENDSLINK_TIP),
							CALC_BTNWIDTH, "Wingdings");

	// set default task creation date to zero so that new tasks
	// always get the current date
	s_tdDefault.dateCreated.m_dt = 0.0;
	s_tdDefault.sCommentsTypeID = cfDefault;

	m_cpColour.SetSelectionMode(CP_MODE_TEXT);
}

CToDoCtrl::~CToDoCtrl()
{
	EndTimeTracking();
	
	if (m_fontDone)
		::DeleteObject(m_fontDone);
	
	m_brDue.DeleteObject();
	m_brDueToday.DeleteObject();
}

void CToDoCtrl::DoDataExchange(CDataExchange* pDX)
{
	CRuntimeDlg::DoDataExchange(pDX);
	
	DDX_Control(pDX, IDC_TASKLIST, m_tree);
	DDX_Control(pDX, IDC_ALLOCTO, m_cbAllocTo);
	DDX_Control(pDX, IDC_ALLOCBY, m_cbAllocBy);
	DDX_Control(pDX, IDC_STATUS, m_cbStatus);
	DDX_Control(pDX, IDC_CATEGORY, m_cbCategory);
	DDX_Control(pDX, IDC_TIMEEST, m_eTimeEstimate);
	DDX_Control(pDX, IDC_TIMESPENT, m_eTimeSpent);
	DDX_Control(pDX, IDC_DUEDATE, m_dateDue);
	DDX_Control(pDX, IDC_DONEDATE, m_dateDone);
	DDX_Control(pDX, IDC_STARTDATE, m_dateStart);
	DDX_Control(pDX, IDC_PRIORITY, m_cbPriority);
	DDX_Control(pDX, IDC_RISK, m_cbRisk);
	DDX_Control(pDX, IDC_PERCENT, m_ePercentDone);
	DDX_Control(pDX, IDC_COST, m_eCost);
	DDX_Control(pDX, IDC_DEPENDS, m_eDependency);
	DDX_Control(pDX, IDC_PERCENTSPIN, m_spinPercent);
	DDX_Control(pDX, IDC_FILEPATH, m_eFileRef);
	DDX_Control(pDX, IDC_EXTERNALID, m_eExternalID);
	DDX_Control(pDX, IDC_RECURRENCE, m_eRecurrence);
	DDX_Control(pDX, IDC_VERSION, m_cbVersion);
	DDX_Control(pDX, IDC_COMMENTSTYPE, m_cbCommentsType);
	DDX_Control(pDX, IDC_COLOUR, m_cpColour);

	DDX_Text(pDX, IDC_PROJECTNAME, m_sProjectName);
	DDX_Text(pDX, IDC_TIMEEST, m_dTimeEstimate);
	DDX_Text(pDX, IDC_TIMESPENT, m_dTimeSpent);
	DDX_Text(pDX, IDC_EXTERNALID, m_sExternalID);
	DDX_Text(pDX, IDC_DEPENDS, m_sDepends);
	DDX_Text(pDX, IDC_FILEPATH, m_sFileRefPath);
	DDX_Text(pDX, IDC_COST, m_dCost);
	DDX_AutoCBString(pDX, IDC_ALLOCBY, m_sAllocBy);
	DDX_AutoCBString(pDX, IDC_STATUS, m_sStatus);
	DDX_AutoCBString(pDX, IDC_VERSION, m_sVersion);
	DDX_CBPriority(pDX, IDC_PRIORITY, m_nPriority);
	DDX_CBRisk(pDX, IDC_RISK, m_nRisk);
	DDX_ColourPicker(pDX, IDC_COLOUR, m_crColour);
	
	// custom
	if (pDX->m_bSaveAndValidate)
	{
		CString sPercent;
		m_ePercentDone.GetWindowText(sPercent);
		
		m_nPercentDone = max(0, atoi(sPercent));
		m_nPercentDone = min(100, m_nPercentDone);

		m_nTimeEstUnits = m_eTimeEstimate.GetUnits();
		m_nTimeSpentUnits = m_eTimeSpent.GetUnits();

		m_cbCategory.GetChecked(m_aCategory);
		m_cbAllocTo.GetChecked(m_aAllocTo);
		m_eRecurrence.GetRecurrenceOptions(m_tRecurrence);
	}
	else
	{
		m_spinPercent.SetPos(m_nPercentDone);
		
		m_eTimeEstimate.SetUnits(m_nTimeEstUnits);
		m_eTimeSpent.SetUnits(m_nTimeSpentUnits);

		m_cbCategory.SetChecked(m_aCategory);
		m_cbAllocTo.SetChecked(m_aAllocTo);

		m_eRecurrence.SetRecurrenceOptions(m_tRecurrence);
	}
}

void CToDoCtrl::UpdateComments(BOOL bSaveAndValidate)
{
	if (bSaveAndValidate)
	{
		m_ctrlComments.GetTextContent(m_sTextComments);
		m_ctrlComments.GetContent(m_CustomComments);
	}
	else
	{
		// if we can't set the custom comments or
		// there are no custom comments then try setting the text comments
		if (!m_ctrlComments.SetContent(m_CustomComments) || m_CustomComments.IsEmpty())
			m_ctrlComments.SetTextContent(m_sTextComments);
	}
}

BEGIN_MESSAGE_MAP(CToDoCtrl, CRuntimeDlg)
//{{AFX_MSG_MAP(CToDoCtrl)
//}}AFX_MSG_MAP
	ON_WM_SIZE()
	ON_WM_ERASEBKGND()
	ON_WM_DESTROY()
	ON_WM_CONTEXTMENU()
	ON_WM_LBUTTONDOWN()
	ON_WM_LBUTTONUP()
	ON_WM_MOUSEMOVE()
	ON_WM_SETCURSOR()
	ON_WM_CAPTURECHANGED()
	ON_WM_SHOWWINDOW()
	ON_WM_TIMER()
	ON_NOTIFY(NM_SETFOCUS, IDC_TASKLIST, OnTreeChangeFocus)
	ON_NOTIFY(NM_KILLFOCUS, IDC_TASKLIST, OnTreeChangeFocus)
	ON_NOTIFY(NM_CLICK, IDC_TASKLIST, OnTreeClick)
	ON_NOTIFY(NM_DBLCLK, IDC_TASKLIST, OnTreeDblClk)
	ON_NOTIFY(NM_CUSTOMDRAW, IDC_TASKLIST, OnTreeCustomDraw)
	ON_NOTIFY(TVN_GETDISPINFO, IDC_TASKLIST, OnTreeGetDispInfo)
	ON_NOTIFY(TVN_KEYDOWN, IDC_TASKLIST, OnTreeKeyDown)
	ON_NOTIFY(TVN_ENDLABELEDIT, IDC_TASKLIST, OnTreeEndlabeledit)
	ON_NOTIFY(TVN_BEGINLABELEDIT, IDC_TASKLIST, OnTreeBeginlabeledit)
	ON_NOTIFY(TVN_SELCHANGED, IDC_TASKLIST, OnTreeSelChanged)
	ON_NOTIFY(TVN_GETINFOTIP, IDC_TASKLIST, OnTreeGetInfoTip)
	ON_NOTIFY(DTN_DATETIMECHANGE, IDC_DONEDATE, OnTaskDatechange)
	ON_NOTIFY(DTN_DATETIMECHANGE, IDC_DUEDATE, OnTaskDatechange)
	ON_NOTIFY(DTN_DATETIMECHANGE, IDC_STARTDATE, OnTaskDatechange)
	ON_CBN_SELCHANGE(IDC_PRIORITY, OnChangePriority)
	ON_CBN_SELCHANGE(IDC_RISK, OnChangeRisk)
	ON_EN_CHANGE(IDC_TIMEEST, OnChangeTimeEstimate)
	ON_EN_CHANGE(IDC_TIMESPENT, OnChangeTimeSpent)
	ON_EN_CHANGE(IDC_PROJECTNAME, OnChangeProjectName)
	ON_EN_CHANGE(IDC_EXTERNALID, OnChangeExternalID)
	ON_EN_CHANGE(IDC_COST, OnChangeCost)
	ON_EN_CHANGE(IDC_DEPENDS, OnChangeDependency)
	ON_EN_CHANGE(IDC_RECURRENCE, OnChangeRecurrence)
	ON_REGISTERED_MESSAGE(WM_TDCN_COMMENTSCHANGE, OnChangeComments)
	ON_REGISTERED_MESSAGE(WM_NCG_WANTREDRAW, OnGutterWantRedraw)

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?