todoctrl.cpp
来自「管理项目进度工具的原代码」· C++ 代码 · 共 2,301 行 · 第 1/5 页
CPP
2,301 行
ON_REGISTERED_MESSAGE(WM_NCG_DRAWITEM, OnGutterDrawItem)
ON_REGISTERED_MESSAGE(WM_NCG_POSTDRAWITEM, OnGutterPostDrawItem)
ON_REGISTERED_MESSAGE(WM_NCG_RECALCCOLWIDTH, OnGutterRecalcColWidth)
ON_REGISTERED_MESSAGE(WM_NCG_NOTIFYHEADERCLICK, OnGutterNotifyHeaderClick)
ON_REGISTERED_MESSAGE(WM_NCG_WIDTHCHANGE, OnGutterWidthChange)
ON_REGISTERED_MESSAGE(WM_NCG_GETCURSOR, OnGutterGetCursor)
ON_REGISTERED_MESSAGE(WM_NCG_NOTIFYITEMCLICK, OnGutterNotifyItemClick)
ON_REGISTERED_MESSAGE(WM_NCG_ISITEMSELECTED, OnGutterIsItemSelected)
ON_REGISTERED_MESSAGE(WM_NCG_GETSELECTEDCOUNT, OnGutterGetSelectedCount)
ON_REGISTERED_MESSAGE(WM_EE_BTNCLICK, OnEEBtnClick)
ON_CBN_SELCHANGE(IDC_ALLOCTO, OnSelChangeAllocTo)
ON_CBN_SELCHANGE(IDC_ALLOCBY, OnSelChangeAllocBy)
ON_CBN_SELCHANGE(IDC_STATUS, OnSelChangeStatus)
ON_CBN_SELCHANGE(IDC_VERSION, OnSelChangeVersion)
ON_CBN_SELCHANGE(IDC_CATEGORY, OnSelChangeCategory)
ON_EN_CHANGE(IDC_PERCENT, OnChangePercent)
ON_EN_CHANGE(IDC_FILEPATH, OnChangeFileRefPath)
ON_REGISTERED_MESSAGE(WM_FE_GETFILEICON, OnFileEditWantIcon)
ON_REGISTERED_MESSAGE(WM_FE_DISPLAYFILE, OnFileEditDisplayFile)
ON_REGISTERED_MESSAGE(WM_TLDT_DROPFILE, OnDropFileRef)
ON_REGISTERED_MESSAGE(WM_TEN_UNITSCHANGE, OnTimeUnitsChange)
ON_REGISTERED_MESSAGE(WM_DD_DRAGABORT, OnTreeDragDrop)
ON_REGISTERED_MESSAGE(WM_DD_DRAGDROP, OnTreeDragDrop)
ON_REGISTERED_MESSAGE(WM_DD_DRAGENTER, OnTreeDragDrop)
ON_REGISTERED_MESSAGE(WM_DD_DRAGOVER, OnTreeDragDrop)
ON_REGISTERED_MESSAGE(WM_DD_PREDRAGMOVE, OnTreeDragDrop)
ON_MESSAGE(WM_TDC_RESTOREFOCUSEDITEM, OnTreeRestoreFocusedItem)
ON_REGISTERED_MESSAGE(WM_TDCM_HASCLIPBOARD, OnTDCHasClipboard)
ON_REGISTERED_MESSAGE(WM_TDCM_GETCLIPBOARD, OnTDCGetClipboard)
ON_REGISTERED_MESSAGE(WM_TDCM_TASKLINK, OnTDCDoTaskLink)
ON_REGISTERED_MESSAGE(WM_ACB_ITEMADDED, OnAutoComboAddDelete)
ON_REGISTERED_MESSAGE(WM_ACB_ITEMDELETED, OnAutoComboAddDelete)
ON_MESSAGE(WM_GETFONT, OnGetFont)
ON_REGISTERED_MESSAGE(WM_ICC_WANTSPELLCHECK, OnCommentsWantSpellCheck)
ON_CBN_SELENDOK(IDC_COMMENTSTYPE, OnSelChangeCommentsType)
ON_WM_SETTINGCHANGE()
ON_MESSAGE(WM_TDC_REFRESHPERCENTSPINVISIBILITY, OnRefreshPercentSpinVisibility)
ON_MESSAGE(CPN_SELENDOK, OnChangeColour)
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CToDoCtrl message handlers
void CToDoCtrl::EnableExtendedSelection(BOOL bCtrl, BOOL bShift)
{
if (bCtrl)
s_nExtendedSelection |= HOTKEYF_CONTROL;
else
s_nExtendedSelection &= ~HOTKEYF_CONTROL;
if (bShift)
s_nExtendedSelection |= HOTKEYF_SHIFT;
else
s_nExtendedSelection &= ~HOTKEYF_SHIFT;
}
TDC_FILEFMT CToDoCtrl::CompareFileFormat() const
{
if (m_nFileFormat == FILEFORMAT)
return TDCFF_SAME;
else if (m_nFileFormat > FILEFORMAT)
return TDCFF_NEWER;
else
return TDCFF_OLDER;
}
void CToDoCtrl::EnableEncryption(BOOL bEnable)
{
if (!bEnable && !m_sPassword.IsEmpty())
{
m_sPassword.Empty();
SetModified(TRUE, TDCA_NONE);
}
else if (bEnable && m_sPassword.IsEmpty())
{
CEnString sExplanation(IDS_ENABLEENCRYPTION);
if (CPasswordDialog::RetrievePassword(TRUE, m_sPassword, sExplanation))
SetModified(TRUE, TDCA_NONE);
}
}
BOOL CToDoCtrl::VerifyPassword(LPCTSTR szExplanation) const
{
if (!IsEncrypted())
return TRUE; // no password to check
return CPasswordDialog::VerifyPassword(m_sPassword, szExplanation);
}
BOOL CToDoCtrl::CanEncrypt()
{
return CTaskFile::CanEncrypt();
}
BOOL CToDoCtrl::Create(const RECT& rect, CWnd* pParentWnd, UINT nID, BOOL bVisible)
{
DWORD dwStyle = WS_CHILD | (bVisible ? WS_VISIBLE : 0);
return CRuntimeDlg::Create(NULL, dwStyle, WS_EX_NOPARENTNOTIFY, rect, pParentWnd, nID);
}
BOOL CToDoCtrl::OnInitDialog()
{
CRuntimeDlg::OnInitDialog();
VERIFY (CreateContentControl());
// percent spin
m_spinPercent.SetRange(0, 100);
m_spinPercent.SetBuddy(GetDlgItem(IDC_PERCENT));
UDACCEL uda = { 0, 5 };
m_spinPercent.SetAccel(1, &uda);
// extra gutter columns
for (int nCol = 0; nCol < NUM_COLUMNS; nCol++)
{
TDCCOLUMN& tdcc = COLUMNS[nCol];
if (tdcc.nColID != TDCC_CLIENT)
{
m_tree.AddGutterColumn(tdcc.nColID, NULL, 0, tdcc.nAlignment);
if (tdcc.bSymbolFont)
m_tree.SetGutterColumnHeaderTitle(tdcc.nColID, (UINT)tdcc.nIDName, tdcc.szFont);
else
m_tree.SetGutterColumnHeaderTitle(tdcc.nColID, CEnString(tdcc.nIDName), tdcc.szFont);
}
else
m_tree.SetGutterColumnHeaderTitle(tdcc.nColID, CEnString(tdcc.nIDName));
}
// set name of pos column
m_tree.SetGutterColumnHeaderTitle(OTC_POSCOLUMNID, CEnString(IDS_TDC_COLUMN_POS));
UpdateColumnHeaderClicking();
// init dates
m_dateStart.SendMessage(DTM_SETSYSTEMTIME, GDT_NONE, 0);
m_dateDue.SendMessage(DTM_SETSYSTEMTIME, GDT_NONE, 0);
m_dateDone.SendMessage(DTM_SETSYSTEMTIME, GDT_NONE, 0);
m_dtTree.Register(&m_tree, this);
m_dtFileRef.Register(&m_eFileRef, this);
// custom font
if (m_fontTree)
{
m_tree.SendMessage(WM_SETFONT, (WPARAM)m_fontTree, TRUE);
if (HasStyle(TDCS_COMMENTSUSETREEFONT))
m_ctrlComments.SendMessage(WM_SETFONT, (WPARAM)m_fontTree, TRUE);
else if (m_fontComments)
m_ctrlComments.SendMessage(WM_SETFONT, (WPARAM)m_fontComments, TRUE);
}
InitEditPrompts();
m_cpColour.SetWindowText(CEnString(IDS_SAMPLETEXT));
// tree drag drop
m_treeDragDrop.Initialize(this);
// enabled states
UpdateControls();
SetLabelAlignment(HasStyle(TDCS_RIGHTALIGNLABELS) ? SS_RIGHT : SS_LEFT);
m_tree.SetFocus();
LoadSplitPos();
// notify parent that we have been created
CWnd* pParent = GetParent();
if (pParent)
pParent->SendMessage(WM_PARENTNOTIFY, MAKEWPARAM(WM_CREATE, GetDlgCtrlID()), (LPARAM)GetSafeHwnd());
// and start the track timer
// which runs persistently
SetTimer(TIMER_TRACK, TIMETRACKPERIOD, NULL);
// and the time which checks for midnight (day changeover)
SetTimer(TIMER_MIDNIGHT, MIDNIGHTPERIOD, NULL);
return FALSE; // return TRUE unless you set the focus to a control
// EXCEPTION: OCX Property Pages should return FALSE
}
BOOL CToDoCtrl::CreateContentControl()
{
// check to see if we really need to (re)create the control
if (m_ctrlComments.IsFormat(m_cfComments))
return TRUE;
CRect rect(0, 211, 171, 238); // in DLU
CDlgUnits(*this).ToPixels(rect);
if (m_ctrlComments.GetSafeHwnd())
{
::GetWindowRect(m_ctrlComments, &rect);
ScreenToClient(rect);
}
BOOL bSuccess = m_mgrContent.CreateContentControl(m_cfComments, m_ctrlComments,
IDC_COMMENTS, WS_TABSTOP | WS_CHILD | WS_VISIBLE,
WS_EX_CLIENTEDGE, rect, *this);
if (!bSuccess)
{
// now that we are going to fallback on m_cfDefault
// check to see if we really need to (re)create the control
if (!m_ctrlComments.IsFormat(m_cfDefault))
{
bSuccess = m_mgrContent.CreateContentControl(m_cfDefault, m_ctrlComments,
IDC_COMMENTS, WS_TABSTOP | WS_CHILD,
WS_EX_CLIENTEDGE, rect, *this);
}
else
bSuccess = TRUE;
// update comments type
if (bSuccess)
m_cfComments = m_cfDefault;
}
if (bSuccess)
{
// set the font
SetTreeFont(m_fontTree);
SetCommentsFont(m_fontComments);
// make sure its in the right pos in the tab order
::SetWindowPos(m_ctrlComments, ::GetDlgItem(*this, IDC_COMMENTSLABEL), 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
// (re)set the edit prompt
m_mgrPrompts.SetEditPrompt(m_ctrlComments, IDS_TDC_EDITPROMPT_COMMENTS);
}
return bSuccess;
}
void CToDoCtrl::InitEditPrompts()
{
m_mgrPrompts.SetEditPrompt(IDC_PROJECTNAME, *this, IDS_TDC_EDITPROMPT_PROJECT);
m_mgrPrompts.SetEditPrompt(m_eFileRef, IDS_TDC_EDITPROMPT_FILEREF);
m_mgrPrompts.SetEditPrompt(m_eExternalID, IDS_TDC_EDITPROMPT_EXTID);
m_mgrPrompts.SetEditPrompt(m_eDependency, IDS_TDC_EDITPROMPT_DEPENDS);
m_mgrPrompts.SetComboEditPrompt(m_cbAllocBy, IDS_TDC_EDITPROMPT_NAME);
m_mgrPrompts.SetComboEditPrompt(m_cbAllocTo.GetSafeHwnd(), IDS_TDC_EDITPROMPT_NAME);
m_mgrPrompts.SetComboEditPrompt(m_cbCategory.GetSafeHwnd(), IDS_TDC_EDITPROMPT_CATEGORY);
m_mgrPrompts.SetComboEditPrompt(m_cbStatus, IDS_TDC_EDITPROMPT_STATUS);
m_mgrPrompts.SetComboEditPrompt(m_cbVersion, IDS_TDC_EDITPROMPT_VER);
m_mgrPrompts.SetEditPrompt(m_ctrlComments, IDS_TDC_EDITPROMPT_COMMENTS);
m_mgrPrompts.SetPrompt(m_tree, IDS_TDC_TASKLISTPROMPT, TVM_GETCOUNT);
}
void CToDoCtrl::SetTaskCompletedColor(COLORREF color)
{
if (color != m_crTaskDone)
{
m_crTaskDone = color;
if (m_tree.GetSafeHwnd())
m_tree.Invalidate(FALSE);
}
}
BOOL CToDoCtrl::SetTreeFont(HFONT hFont)
{
m_fontTree = hFont;
if (m_tree.GetSafeHwnd())
{
if (!hFont) // set to our font
{
// for some reason i can not yet explain, our font
// is not correctly set so we use our parent's font instead
// hFont = (HFONT)SendMessage(WM_GETFONT);
hFont = (HFONT)GetParent()->SendMessage(WM_GETFONT);
}
HFONT hTreeFont = (HFONT)m_tree.SendMessage(WM_GETFONT);
BOOL bChange = (hFont != hTreeFont || !Misc::SameFontNameSize(hFont, hTreeFont));
if (bChange)
m_tree.SendMessage(WM_SETFONT, (WPARAM)hFont, TRUE);
// done font
if (bChange || m_fontDone == NULL)
{
::DeleteObject(m_fontDone);
if (HasStyle(TDCS_STRIKETHOUGHDONETASKS))
{
LOGFONT lf;
::GetObject(hFont, sizeof(lf), &lf);
lf.lfStrikeOut = TRUE;
m_fontDone = CreateFontIndirect(&lf);
}
else
m_fontDone = NULL;
// bold tree font
LOGFONT lf;
::GetObject(hFont, sizeof(lf), &lf);
lf.lfWeight = FW_BOLD;
::DeleteObject(m_fontBold);
m_fontBold = CreateFontIndirect(&lf);
}
// comments font
if (HasStyle(TDCS_COMMENTSUSETREEFONT))
m_ctrlComments.SendMessage(WM_SETFONT, (WPARAM)hFont, TRUE);
}
return TRUE;
}
BOOL CToDoCtrl::SetCommentsFont(HFONT hFont)
{
m_fontComments = hFont;
if (m_ctrlComments.GetSafeHwnd())
{
if (!HasStyle(TDCS_COMMENTSUSETREEFONT))
{
if (!hFont)
hFont = (HFONT)GetStockObject(DEFAULT_GUI_FONT);
m_ctrlComments.SendMessage(WM_SETFONT, (WPARAM)hFont, TRUE);
// we've had some trouble with plugins using the
// richedit control so after a font change we always
// resend the content
if (m_CustomComments.GetLength())
{
if (!m_ctrlComments.SetContent(m_CustomComments))
m_ctrlComments.SetTextContent(m_sTextComments);
}
else
m_ctrlComments.SetTextContent(m_sTextComments);
}
}
return TRUE;
}
TDCCOLUMN* CToDoCtrl::GetColumn(UINT nColID)
{
int nCol = NUM_COLUMNS;
while (nCol--)
{
if (COLUMNS[nCol].nColID == (TDC_COLUMN)nColID)
return &COLUMNS[nCol];
}
// else
return NULL;
}
TDCCOLUMN* CToDoCtrl::GetColumn(TDC_SORTBY nSortBy)
{
int nCol = NUM_COLUMNS;
while (nCol--)
{
if (COLUMNS[nCol].nSortBy == nSortBy)
return &COLUMNS[nCol];
}
// else
return NULL;
}
void CToDoCtrl::OnSize(UINT nType, int cx, int cy)
{
CRuntimeDlg::OnSize(nType, cx, cy);
m_tree.TCH().EndLabelEdit(TRUE);
Resize(cx, cy);
}
void CToDoCtrl::Resize(int cx, int cy)
{
if (m_tree.GetSafeHwnd())
{
if (!cx && !cy)
{
CRect rClient;
GetClientRect(rClient);
cx = rClient.right;
cy = rClient.bottom;
// check again
if (!cx && !cy)
return;
}
BOOL bVertComments = HasStyle(TDCS_VERTCOMMENTS);
// written to use DeferWindowPos()
{
CDeferWndMove dwm(30);
CRect rComments;
ReposComments(cx, cy, &dwm, rComments);
// first count up the visible controls
// so we can allocate the correct amount of space
BOOL bAllVisible = !HasStyle(TDCS_SHOWCTRLSASCOLUMNS);
int nVisibleCtrls = VisibleCtrlCount();
// for converting dlus to pixels
CDlgUnits dlu(*this);
int nCols = 2; // default
// figure out number of ctrl rows
if (HasStyle(TDCS_AUTOREPOSCTRLS))
{
int nAvailWidth = bVertComments ? rComments.left : cx;
int nCtrlWidth = dlu.ToPixelsX(CTRLENDOFFSET + CTRLHSPACING);
nCols = max(2, nAvailWidth / nCtrlWidth);
}
int nRows = (nVisibleCtrls / nCols) + ((nVisibleCtrls % nCols) ? 1 : 0);
// calc ctrl rect
CRect rCtrls(0, 0, 0, 0);
rCtrls.right = bVertComments ? rComments.left - SPLITSIZE : cx;
rCtrls.bottom = bVertComments ? cy + CTRLVSPACING : rComments.top;
rCtrls.top = rCtrls.bottom - nRows * dlu.ToPixelsY(CTRLHEIGHT + CTRLVSPACING);
// resize tree now that we can calculate where its bottom is
CRect rProject = ResizeCtrl(IDC_PROJECTNAME); // a get
CRect rTree(0, rProject.bottom + 4, cx, cy);
BOOL bMaximize = HasStyle(TDCS_MAXIMIZE);
if (bMaximize || !HasStyle(TDCS_SHOWPROJECTNAME))
rTree.top = rProject.top;
if (bMaximize)
{
if (HasStyle(TDCS_SHOWCOMMENTSALWAYS))
{
if (bVertComments)
rTree.right = rCtrls.right;
else
rTree.bottom = rComments.top - dlu.ToPixelsY(CTRLVSPACING);
}
}
else
{
rTree.right = rCtrls.right;
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?