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