todoctrl.cpp

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

CPP
2,301
字号
			break;
		}
		
		pCtrl->ShowWindow(nShowCtrl);
		pLabel->ShowWindow(nShowCtrl);
		
		SetControlState(*pLabel, nState);
		SetControlState(*pCtrl, nState);
	}
	
	// comments
	BOOL bCommentsAlways = HasStyle(TDCS_SHOWCOMMENTSALWAYS);
	RT_CTRLSTATE nState = ((!bCommentsAlways && bMaximize) || !hti) ? RTCS_DISABLED : 
							((bReadOnly || !bEditComments) ? RTCS_READONLY : RTCS_ENABLED);

	switch (nState)
	{
	case RTCS_DISABLED:
		SetControlState(this, IDC_COMMENTS, nState);
		break;

	case RTCS_ENABLED:
		SetControlState(this, IDC_COMMENTS, nState);
		m_ctrlComments.SetReadOnly(FALSE);
		break;

	case RTCS_READONLY:
		SetControlState(this, IDC_COMMENTS, RTCS_ENABLED);
		m_ctrlComments.SetReadOnly(TRUE);
		break;
	}

	SetControlState(this, IDC_COMMENTSLABEL, nState);

	// if bEditComments is FALSE it means we have multiple comments types
	// selected. So we enable the selected comments type but keep the 
	// comments control readonly
	if (nState == RTCS_READONLY && !bReadOnly)
		SetControlState(this, IDC_COMMENTSTYPE, RTCS_ENABLED);
	else
		SetControlState(this, IDC_COMMENTSTYPE, nState);

	SetControlState(this, IDC_COMMENTSLABEL, nState);
	ShowControls(IDC_COMMENTSLABEL, IDC_COMMENTS, (bCommentsAlways || !bMaximize));

	// re-hide the comments type combo if necessary
	if (m_mgrContent.GetNumContent() <= 1)
		m_cbCommentsType.ShowWindow(SW_HIDE);

	// and comments divider
	if (HasStyle(TDCS_VERTCOMMENTS) || HasStyle(TDCS_MAXIMIZE))
		GetDlgItem(IDC_HSPLITTER)->ShowWindow(SW_HIDE);
	else
		GetDlgItem(IDC_HSPLITTER)->ShowWindow(SW_SHOW);
	
	// project name
	BOOL bShowProjectName = !bMaximize && HasStyle(TDCS_SHOWPROJECTNAME);

	nState = !bShowProjectName ? RTCS_DISABLED : (bReadOnly ? RTCS_READONLY : RTCS_ENABLED);
	SetControlsState(this, IDC_PROJECTLABEL, IDC_PROJECTNAME, nState);
	ShowControls(this, IDC_PROJECTLABEL, IDC_PROJECTNAME, bShowProjectName);
	
	// tree
	m_tree.ModifyStyle(bReadOnly ? TVS_EDITLABELS : 0, bReadOnly ? 0 : TVS_EDITLABELS);
	m_treeDragDrop.EnableDragDrop(!bReadOnly);
}

void CToDoCtrl::SetCtrlDate(CDateTimeCtrl& ctrl, const COleDateTime& date)
{
	if (date.m_dt)
		ctrl.SetTime(date);
	else
	{
		ctrl.SetTime(COleDateTime::GetCurrentTime());
		ctrl.SendMessage(DTM_SETSYSTEMTIME, GDT_NONE, 0);
	}
}

void CToDoCtrl::SetLabelAlignment(int nStyle)
{
	// now enable/disable appropriate controls
	for (int nCtrl = 0; nCtrl < NUM_CTRLITEMS; nCtrl++)
	{
		CWnd* pLabel = GetDlgItem(CTRLITEMS[nCtrl].nLabelID);
		
		if (!pLabel)
			continue;
		
		pLabel->ModifyStyle(SS_TYPEMASK, nStyle);
	}
}

void CToDoCtrl::UpdateTask(TDC_ATTRIBUTE nAttrib, DWORD dwFlags/* = 0*/)
{
	if (!m_tree.GetSafeHwnd())
		return;
	
	HTREEITEM hti = GetSelectedItem();
	
	if (!hti)
		return;
	
	// else
	UpdateData();
	
	switch (nAttrib)
	{
		//	case TDCA_TASKNAME:
		//		break;
		
	case TDCA_DONEDATE:
		{
			COleDateTime date;
			m_dateDone.GetTime(date);
			
			if (SetSelectedTaskDate(TDCD_DONE, date, FALSE))
			{
				// check if we need to modify percent done also
				if (!IsSelectedTaskDone())
				{
					int nPercentDone = GetSelectedTaskPercent();
					
					if (nPercentDone == 100)
						nPercentDone = 0;
					
					SetSelectedTaskPercentDone(nPercentDone);
					m_nPercentDone = nPercentDone;
					
					UpdateData(FALSE);
				}
				else if (m_nPercentDone != 100) // make the percent field look right
				{
					m_nPercentDone = 100;
					UpdateData(FALSE);
				}
			}
			else
			{
				UpdateControls(hti);
			}
		}
		break;
		
	case TDCA_STARTDATE:
		{
			COleDateTime date;
			m_dateStart.GetTime(date);
			
			SetSelectedTaskDate(TDCD_START, date);
			RecalcSelectedTimeEstimate();
		}
		break;
		
	case TDCA_DUEDATE:
		{
			COleDateTime date;
			m_dateDue.GetTime(date);
			
			SetSelectedTaskDate(TDCD_DUE, date);
			RecalcSelectedTimeEstimate();
		}
		break;
		
	case TDCA_COST:
		SetSelectedTaskCost(m_dCost);
		break;
		
	case TDCA_RECURRENCE:
		SetSelectedTaskRecurrence(m_tRecurrence);
		break;
		
	case TDCA_DEPENDENCY:
		m_eDependency.EnableButton(ID_DEPENDS_LINK, !m_sDepends.IsEmpty());
		SetSelectedTaskDependency(m_sDepends);
		break;
		
	case TDCA_PRIORITY:
		SetSelectedTaskPriority(m_nPriority);
		break;
		
	case TDCA_RISK:
		SetSelectedTaskRisk(m_nRisk);
		break;
		
	case TDCA_COLOR:
		SetSelectedTaskColor(m_crColour);
		break;
		
	case TDCA_EXTERNALID:
		SetSelectedTaskExtID(m_sExternalID);
		break;
		
	case TDCA_ALLOCTO:
		SetSelectedTaskAllocTo(m_aAllocTo);
		break;
		
	case TDCA_ALLOCBY:
		SetSelectedTaskAllocBy(m_sAllocBy);
		break;
		
	case TDCA_STATUS:
		SetSelectedTaskStatus(m_sStatus);
		break;
		
	case TDCA_VERSION:
		SetSelectedTaskVersion(m_sVersion);
		break;
		
	case TDCA_CATEGORY:
		SetSelectedTaskCategories(m_aCategory);
		break;
		
	case TDCA_PERCENT:
		{
			// note: we need to take account of 'done' state too because
			// we maintain the task percent at its pre-done state even
			// if the UI says its '100%'
			BOOL bWasDone = IsSelectedTaskDone();
			SetSelectedTaskPercentDone(m_nPercentDone);
			
			// check if we need to update 'done' state
			BOOL bDoneChange = (bWasDone && m_nPercentDone < 100) || (!bWasDone && m_nPercentDone == 100);
			
			if (bDoneChange)
			{
				SetSelectedTaskDone(m_nPercentDone == 100, FALSE);
				nAttrib = TDCA_DONEDATE;
			}
		}
		break;
		
	case TDCA_TIMEEST:
		if (dwFlags & UTF_TIMEUNITSONLY)
			SetSelectedTaskTimeEstimateUnits(m_nTimeEstUnits, dwFlags & UTF_RECALCTIME);
		else
			SetSelectedTaskTimeEstimate(m_dTimeEstimate, m_nTimeEstUnits);
		break;
		
	case TDCA_TIMESPENT:
		if (dwFlags & UTF_TIMEUNITSONLY)
			SetSelectedTaskTimeSpentUnits(m_nTimeSpentUnits, dwFlags & UTF_RECALCTIME);
		else
			SetSelectedTaskTimeSpent(m_dTimeSpent, m_nTimeSpentUnits);
		break;
		
	case TDCA_FILEREF:
		SetSelectedTaskFileRef(m_sFileRefPath);
		break;
		
	case TDCA_COMMENTS:
		UpdateComments(TRUE); // no longer handled by UpdateData
		SetSelectedTaskComments(m_sTextComments, m_CustomComments, TRUE); // TRUE == internal call
		break;
		
	default:
		return;
	}
}

void CToDoCtrl::RecalcSelectedTimeEstimate()
{
	if (HasStyle(TDCS_AUTOCALCTIMEESTIMATES))
	{
		TODOITEM* pTDI = GetSelectedTask();
		
		if (pTDI)
		{
			double dStart = pTDI->dateStart, dDue = pTDI->dateDue;
			
			if (dStart > 0 && dDue >= dStart) // exists
			{
				int nWeekdays = CDateHelper::CalcWeekdaysFromTo(dStart, dDue, TRUE);
				SetSelectedTaskTimeEstimate((double)nWeekdays, TDITU_DAYS);
			}
			else
				SetSelectedTaskTimeEstimate(0);
		}
	}
}

void CToDoCtrl::OnChangePriority()
{
	UpdateTask(TDCA_PRIORITY);
}

void CToDoCtrl::OnChangeRisk()
{
	UpdateTask(TDCA_RISK);
}

void CToDoCtrl::OnTaskDatechange(NMHDR* pNMHDR, LRESULT* pResult)
{
	switch (pNMHDR->idFrom)
	{
	case IDC_DONEDATE:	UpdateTask(TDCA_DONEDATE);	break;
	case IDC_STARTDATE:	UpdateTask(TDCA_STARTDATE); break;
	case IDC_DUEDATE:	UpdateTask(TDCA_DUEDATE); 	break;
	}
	
	*pResult = 0;
}

BOOL CToDoCtrl::OnEraseBkgnd(CDC* pDC) 
{
	int nDC = pDC->SaveDC();
	
	// clip out all the child controls to reduce flicker
	if (!(GetStyle() & WS_CLIPCHILDREN))
	{
		if (m_tree.GetSafeHwnd())
			ExcludeControls(pDC, IDC_FIRST + 1, IDC_LAST - 1);
	}
	
	BOOL bRes = CRuntimeDlg::OnEraseBkgnd(pDC);
	
	pDC->RestoreDC(nDC);
	
	return bRes;
}

void CToDoCtrl::SetDefaultAllocToNames(const CStringArray& aNames)
{
	m_cbAllocTo.AddUniqueItems(aNames);
}

void CToDoCtrl::SetDefaultAllocByNames(const CStringArray& aNames)
{
	m_cbAllocBy.AddUniqueItems(aNames);
}

void CToDoCtrl::SetDefaultCategoryNames(const CStringArray& aNames)
{
	m_cbCategory.AddUniqueItems(aNames);
}

void CToDoCtrl::SetDefaultStatusNames(const CStringArray& aNames)
{
	m_cbStatus.AddUniqueItems(aNames);
}

void CToDoCtrl::NewList()
{
	BOOL bConfirmDelete = HasStyle(TDCS_CONFIRMDELETE);
	
	if (bConfirmDelete)
		SetStyle(TDCS_CONFIRMDELETE, FALSE);
	
	DeleteAllTasks();
	
	if (bConfirmDelete)
		SetStyle(TDCS_CONFIRMDELETE, TRUE);
	
	m_sProjectName.Empty();
	m_nFileVersion = 0;
	m_bModified = FALSE;
	m_sPassword.Empty();
	
	UpdateData(FALSE);
	UpdateComments(FALSE);
}

BOOL CToDoCtrl::SetSelectedTaskColor(COLORREF color)
{
	if (IsReadOnly())
		return FALSE;
	
	POSITION pos = Selection().GetFirstItemPos();
	int nRes = SET_NOCHANGE;
	
	while (pos)
	{
		HTREEITEM hti = Selection().GetNextItem(pos);
		int nItemRes = m_data.SetTaskColor(GetTaskID(hti), color);
		
		if (nItemRes == SET_CHANGE)
			nRes = SET_CHANGE;
	}
	
	if (nRes == SET_CHANGE)
	{
		m_cpColour.SetColour(color);
		SetModified(TRUE, TDCA_COLOR);
	}
	
	return (nRes != SET_FAILED);
}

BOOL CToDoCtrl::CanPasteText()
{
	return (!IsReadOnly() && CWinClasses::IsEditControl(::GetFocus()));
}

BOOL CToDoCtrl::PasteText(LPCTSTR szText)
{
	if (!CanPasteText() || !szText || !*szText)
		return FALSE;

	HWND hFocus = ::GetFocus();
	
	::SendMessage(hFocus, EM_REPLACESEL, TRUE, (LPARAM)szText);

	// figure out who changed
	// TODO

	SetModified(TRUE, TDCA_NONE);
	
	return TRUE;
}

// external version
BOOL CToDoCtrl::SetSelectedTaskComments(LPCTSTR szComments, const CString& sCustomComments)
{
	return SetSelectedTaskComments(szComments, sCustomComments, FALSE);
}

BOOL CToDoCtrl::SetSelectedTaskComments(LPCTSTR szComments, const CString& sCustomComments, BOOL bInternal)
{
	if (IsReadOnly())
		return FALSE;
	
	POSITION pos = Selection().GetFirstItemPos();
	int nRes = SET_NOCHANGE;

	// do not change the custom comments unless the comments
	// type matches the current content control type
	BOOL bCanChangeCustom = (m_mgrContent.FindContent(m_cfComments) != -1);
	
	while (pos)
	{
		HTREEITEM hti = Selection().GetNextItem(pos);
		int nItemRes = m_data.SetTaskComments(GetTaskID(hti), szComments);
		
		if (nItemRes == SET_CHANGE)
			nRes = SET_CHANGE;

		if (bCanChangeCustom)
		{
			nItemRes = m_data.SetTaskCustomComments(GetTaskID(hti), sCustomComments, m_cfComments);
		
			if (nItemRes == SET_CHANGE)
				nRes = SET_CHANGE;
		}
	}
	
	if (nRes == SET_CHANGE)
	{
		// refresh the comments of the active task if we were called externally
		// note: we don't use SetTextChange because that doesn't handle custom comments
		if (!bInternal)
		{
			// try custom comments if that's what they are
			if (!bCanChangeCustom || 
				!m_ctrlComments.SetContent(sCustomComments) || 
				sCustomComments.IsEmpty())
			{
				// else text comments
				m_ctrlComments.SetTextContent(szComments);
			}
		}

		Selection().InvalidateAll();

⌨️ 快捷键说明

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