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 + -
显示快捷键?