tdcstruct.h

来自「管理项目进度工具的原代码」· C头文件 代码 · 共 408 行

H
408
字号
#if !defined(AFX_TDCSTRUCT_H__5951FDE6_508A_4A9D_A55D_D16EB026AEF7__INCLUDED_)
#define AFX_TDCSTRUCT_H__5951FDE6_508A_4A9D_A55D_D16EB026AEF7__INCLUDED_

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000

// tdlutil.h : header file
//

#include "tdcenum.h"
#include "taskfile.h"

#include "..\shared\TreeSelectionHelper.h"
#include "..\shared\TreeCtrlHelper.h"
#include "..\shared\misc.h"
#include "..\shared\datehelper.h"

typedef CMap<TDC_STYLE, TDC_STYLE, BOOL, BOOL&> CTDCStyles;
typedef CMap<CString, LPCTSTR, COLORREF, COLORREF&> CTDCColorMap;

struct TDIRECURRENCE
{
//  nRegularity       dwSpecific1        dwSpecific2

//	RTER_DAILY        every 'n' days     --- (0)
//	RTER_WEEKLY       every 'n' weeks    weekdays (TDIW_...)
//	RTER_MONTHLY      every 'n' months   day of month (1-31)
//	RTER_YEARLY       month (1-12)       day of month (1-31)

	TDIRECURRENCE() : nRegularity(TDIR_ONCE), dwSpecific1(1), dwSpecific2(0), bRecalcFromDue(TRUE) {}

	BOOL operator==(const TDIRECURRENCE& tr) const
	{
		return (tr.nRegularity == nRegularity && tr.dwSpecific1 == dwSpecific1 &&
				tr.dwSpecific2 == dwSpecific2 && tr.bRecalcFromDue == bRecalcFromDue);
	}

	BOOL operator!=(const TDIRECURRENCE& tr) const
	{
		return !(*this == tr);
	}

	BOOL GetNextOccurence(const COleDateTime& dtFrom, COleDateTime& dtNext) const
	{
		if (dtFrom.GetStatus() != COleDateTime::valid || dtFrom.m_dt == 0.0)
			return FALSE;

		if (nRegularity == TDIR_ONCE)
			return FALSE;

		dtNext = dtFrom;

		switch (nRegularity)		
		{
		case TDIR_DAILY:
			if ((int)dwSpecific1 <= 0)
				return FALSE;

			// add number of days specified by dwSpecific1
			CDateHelper::OffsetDate(dtNext, (int)dwSpecific1, DHU_DAYS);
			break;

		case TDIR_WEEKLY:
			{
				if ((int)dwSpecific1 <= 0/* || !dwSpecific2*/)
					return FALSE;

				// if no weekdays have been set we just add the specified number of weeks
				if (!dwSpecific2)
					CDateHelper::OffsetDate(dtNext, (int)dwSpecific1, DHU_WEEKS);

				else // go looking for the next specified weekday
				{
					// first add any weeks greater than one
					CDateHelper::OffsetDate(dtNext, (int)(dwSpecific1 - 1), DHU_WEEKS);

					// then look for the next weekday *after* this one

					// build a 2 week weekday array so we don't have to deal with 
					// wrapping around
					UINT nWeekdays[14] = 
					{
						(dwSpecific2 & TDIW_SUNDAY) ? 1 : 0,
						(dwSpecific2 & TDIW_MONDAY) ? 1 : 0,
						(dwSpecific2 & TDIW_TUESDAY) ? 1 : 0,
						(dwSpecific2 & TDIW_WEDNESDAY) ? 1 : 0,
						(dwSpecific2 & TDIW_THURSDAY) ? 1 : 0,
						(dwSpecific2 & TDIW_FRIDAY) ? 1 : 0,
						(dwSpecific2 & TDIW_SATURDAY) ? 1 : 0,
						(dwSpecific2 & TDIW_SUNDAY) ? 1 : 0,
						(dwSpecific2 & TDIW_MONDAY) ? 1 : 0,
						(dwSpecific2 & TDIW_TUESDAY) ? 1 : 0,
						(dwSpecific2 & TDIW_WEDNESDAY) ? 1 : 0,
						(dwSpecific2 & TDIW_THURSDAY) ? 1 : 0,
						(dwSpecific2 & TDIW_FRIDAY) ? 1 : 0,
						(dwSpecific2 & TDIW_SATURDAY) ? 1 : 0,
					};

					dtNext += 1.0; // always next day at least

					int nStart = dtFrom.GetDayOfWeek();
					int nEnd = nStart + 7; // week later

					for (int nWeekday = nStart; nWeekday < nEnd; nWeekday++)
					{
						if (nWeekdays[nWeekday] != 0)
							break;
						else
							dtNext += 1.0; 
					}
				}
			}
			break;

		case TDIR_MONTHLY:
			{
				if ((int)dwSpecific1 <= 0 || (dwSpecific2 < 1 || dwSpecific2 > 31))
					return FALSE;
				
				// add number of months specified by dwSpecific1
				CDateHelper::OffsetDate(dtNext, (int)dwSpecific1, DHU_MONTHS);

				// then enforce the day
				SYSTEMTIME st;
				dtNext.GetAsSystemTime(st);
				st.wDay = (WORD)dwSpecific2;

				dtNext = COleDateTime(st);
			}
			break;

		case TDIR_YEARLY:
			{
				if ((dwSpecific1 < 1 || dwSpecific1 > 12) || (dwSpecific2 < 1 || dwSpecific2 > 31))
					return FALSE;
				
				// add a year 
				CDateHelper::OffsetDate(dtNext, 1, DHU_YEARS);

				// then enforce the month and the day
				SYSTEMTIME st;
				dtNext.GetAsSystemTime(st);
				st.wMonth = (WORD)dwSpecific1;
				st.wDay = (WORD)dwSpecific2;

				dtNext = COleDateTime(st);
			}
			break;

		default:
			return FALSE;
		}

		return TRUE;
	}

	TDI_REGULARITY nRegularity;
	DWORD dwSpecific1;
	DWORD dwSpecific2;
	BOOL bRecalcFromDue; // else recalc from 'completed'
};

struct TDCFILTER
{
	TDCFILTER() : 
			nFilter(TDCF_ALL), dwFlags(TDCGT_ISODATES) {}

	TDCFILTER(TDC_FILTER filter, DWORD flags, double dueBy = 0) :
			nFilter(filter), dwFlags(flags), dateDueBy(dueBy) {}

	TDC_FILTER nFilter;
	COleDateTime dateDueBy;
	DWORD dwFlags;
	CString sAllocTo;
};

struct TDLSELECTION
{
	TDLSELECTION(CTreeCtrl& tree) : selection(tree), htiLastHandledLBtnDown(NULL), 
									tch(tree), nLBtnDownFlags(0), nNcLBtnDownColID(-1) {}

	CTreeSelectionHelper selection;
	CTreeCtrlHelper tch;
	HTREEITEM htiLastHandledLBtnDown;
	UINT nLBtnDownFlags;
	int nNcLBtnDownColID;

	BOOL HasIncompleteSubtasks()
	{
		POSITION pos = selection.GetFirstItemPos();

		while (pos)
		{
			HTREEITEM hti = selection.GetNextItem(pos);

			if (ItemHasIncompleteSubtasks(hti))
				return TRUE;
		}

		return FALSE;
	}
	
	BOOL ItemHasIncompleteSubtasks(HTREEITEM hti)
	{
		const CTreeCtrl& tree = selection.TreeCtrl();
		HTREEITEM htiChild = tree.GetChildItem(hti);

		while (htiChild)
		{
			if (tch.GetItemCheckState(htiChild) != TCHC_CHECKED || ItemHasIncompleteSubtasks(htiChild))
				return TRUE;
			
			htiChild = tree.GetNextItem(htiChild, TVGN_NEXT);
		}

		return FALSE;
	}
};

struct TDLCLIPBOARD
{
	TDLCLIPBOARD() : hwndToDoCtrl(NULL) {}
	
	CTaskFile tasks;
	HWND hwndToDoCtrl;
};

struct TDCCONTROL
{
	LPCTSTR szClass;
	UINT nIDCaption;
	DWORD dwStyle;
	DWORD dwExStyle; 
	int nX;
	int nY;
	int nCx;
	int nCy;
	UINT nID;
};

struct TDCCOLUMN
{
	TDC_COLUMN nColID;
	UINT nIDName;
	TDC_SORTBY nSortBy;
	UINT nAlignment;
	BOOL bClickable;
	LPCTSTR szFont;
	BOOL bSymbolFont;
	BOOL bSortAscending;
};

struct CTRLITEM
{
	UINT nCtrlID;
	UINT nLabelID;
	TDC_COLUMN nCol;
};

struct SEARCHPARAMS
{
	SEARCHPARAMS() : nFindWhat(0), dwFlags(0), nFrom(0), nTo(0), dFrom(0), dTo(0) {}
	int nFindWhat;
	DWORD dwFlags; // see above
	
	CString sText;
	CStringArray aItems;
	COleDateTime dateFrom, dateTo;
	int nFrom, nTo;
	double dFrom, dTo;
};

struct SEARCHRESULT
{
	SEARCHRESULT() : dwID(0), hti(NULL), nMatch(0), dMatch(0), bDone(0) {}
	DWORD dwID;
	HTREEITEM hti;
	CString sMatch;
	COleDateTime dateMatch;
	int nMatch;
	double dMatch;
	BOOL bDone;
};

typedef CArray<SEARCHRESULT, SEARCHRESULT&> CResultArray;

struct FTDCFILTER
{
	FTDCFILTER() : nFilter(FT_ALL), nPriority(FT_ANYPRIORITY), nRisk(FT_ANYRISK), dwFlags(FT_ANYALLOCTO | FT_ANYCATEGORY) 
	{
	}

	void operator=(const FTDCFILTER& filter)
	{
		nFilter = filter.nFilter;
		nPriority = filter.nPriority;
		nRisk = filter.nRisk;
		aAllocTo.Copy(filter.aAllocTo);
		sStatus = filter.sStatus;
		sAllocBy = filter.sAllocBy;
		aCategories.Copy(filter.aCategories);
		dwFlags = filter.dwFlags;
	}

	BOOL operator==(const FTDCFILTER& filter) const
	{
		return (filter.nFilter == nFilter && 
				filter.nPriority == nPriority &&
				filter.nRisk == nRisk && 
				filter.sStatus == sStatus && 
				filter.sAllocBy == sAllocBy &&
				Misc::ArraysMatch(aCategories, filter.aCategories) &&
				Misc::ArraysMatch(aAllocTo, filter.aAllocTo) &&
				dwFlags == filter.dwFlags);
	}

	BOOL operator!=(const FTDCFILTER& filter) const
	{
		return !(*this == filter);
	}
	
	BOOL IsSet() const
	{
		return (nFilter != FT_ALL || nPriority != FT_ANYPRIORITY || nRisk != FT_ANYRISK ||
				aCategories.GetSize() || aAllocTo.GetSize() || 
				!sStatus.IsEmpty() || !sAllocBy.IsEmpty()) ? 1 : 0;
	}

	BOOL HasFlag(DWORD dwFlag) const
	{
		return ((dwFlags & dwFlag) == dwFlag);
	}

	void SetFlag(DWORD dwFlag, BOOL bOn = TRUE)
	{
		if (bOn)
			dwFlags |= dwFlag;
		else
			dwFlags &= ~dwFlag;
	}

	BOOL MatchAllocTo(const CStringArray& aAllocTos) const
	{
		return MatchItems(aAllocTo, aAllocTos, HasFlag(FT_ANYALLOCTO));
	}

	BOOL MatchCategories(const CStringArray& aCats) const
	{
		return MatchItems(aCategories, aCats, HasFlag(FT_ANYCATEGORY));
	}

	void Reset()
	{
		*this = FTDCFILTER(); // empty filter
	}
	
	FILTER_TYPE nFilter;
	int nPriority, nRisk;
	CStringArray aCategories, aAllocTo;
	CString sStatus, sAllocBy;
	DWORD dwFlags;

	protected:

	static BOOL MatchItems(const CStringArray& aItems1, const CStringArray& aItems2, BOOL bAny)
	{
		if (bAny)
		{
			// special case: if aCats is empty, test for empty
			// string in aCategories
			if (aItems2.GetSize() == 0)
				return (Misc::Find(aItems1, "") != -1);
			else
				return Misc::MatchAny(aItems1, aItems2);
		}

		// else exact match required
		// since we cannot filter against both having a category
		// and not having a category at the same time
		// we ignore the empty string unless that's all there is
		if (aItems1.GetSize() == 1 && aItems1[0].IsEmpty())
			return (aItems2.GetSize() == 0);

		int nBlank = Misc::Find(aItems1, "");
		
		if (nBlank != -1)
		{
			CStringArray aCopy; 
			aCopy.Copy(aItems1);
			
			while (nBlank != -1)
			{
				aCopy.RemoveAt(nBlank);
				nBlank = Misc::Find(aCopy, "");
			}
			
			// compare what's left
			return Misc::ArraysMatch(aCopy, aItems2);
		}
		else // simple compare
			return Misc::ArraysMatch(aItems1, aItems2);
	}
};


#endif // AFX_TDCSTRUCT_H__5951FDE6_508A_4A9D_A55D_D16EB026AEF7__INCLUDED_

⌨️ 快捷键说明

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