findtaskdlg.cpp

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

CPP
1,310
字号
// FindTaskDlg.cpp : implementation file
//

#include "stdafx.h"
#include "todolist.h"
#include "FindTaskDlg.h"

#include "..\shared\deferwndmove.h"
#include "..\shared\dlgunits.h"
#include "..\shared\enstring.h"
#include "..\shared\dialoghelper.h"
#include "..\shared\misc.h"

#include <multimon.h>

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

/////////////////////////////////////////////////////////////////////////////

enum { COL_TASK, COL_MATCH, COL_PATH };
const int MATCH_COLWIDTH = 50;

struct SEARCHFIELD
{
	UINT nIDWhat;
	FIND_WHAT nWhat;
	UINT nIDColumn;
	int nAlign;
};

static SEARCHFIELD SEARCHFIELDS[] = 
{
	{ IDS_FTD_TITLECOMMENTS,FW_TITLECOMMENTS,	0,						LVCFMT_LEFT },
	{ IDS_FTD_PRIORITY,		FW_PRIORITY,		IDS_TDLBC_PRIORITY,		LVCFMT_RIGHT },
	{ IDS_FTD_PERCENT,		FW_PERCENTDONE,		IDS_TDLBC_PERCENT,		LVCFMT_RIGHT },
	{ IDS_FTD_TIMEEST,		FW_TIMEEST,			IDS_TDLBC_TIMEEST,		LVCFMT_RIGHT },
	{ IDS_FTD_TIMESPENT,	FW_TIMESPENT,		IDS_TDLBC_TIMESPENT,	LVCFMT_RIGHT },
	{ IDS_FTD_STARTDATE,	FW_STARTDATE,		IDS_TDLBC_STARTDATE,	LVCFMT_RIGHT },
	{ IDS_FTD_DUEDATE,		FW_DUEDATE,			IDS_TDLBC_DUEDATE,		LVCFMT_RIGHT },
	{ IDS_FTD_DONEDATE,		FW_DONEDATE,		IDS_TDLBC_DONEDATE,		LVCFMT_RIGHT },
	{ IDS_FTD_ALLOCTO,		FW_ALLOCTO,			IDS_TDLBC_ALLOCTO,		LVCFMT_LEFT },
	{ IDS_FTD_ALLOCBY,		FW_ALLOCBY,			IDS_TDLBC_ALLOCBY,		LVCFMT_LEFT },
	{ IDS_FTD_STATUS,		FW_STATUS,			IDS_TDLBC_STATUS,		LVCFMT_LEFT },
	{ IDS_FTD_CATEGORY,		FW_CATEGORY,		IDS_TDLBC_CATEGORY,		LVCFMT_LEFT },
	{ IDS_FTD_ID,			FW_TASKID,			IDS_TDLBC_ID,			LVCFMT_RIGHT },
	{ IDS_FTD_FLAG,			FW_FLAG,			0,						LVCFMT_LEFT },
	{ IDS_FTD_CREATEDATE,	FW_CREATIONDATE,	IDS_TDLBC_CREATEDATE,	LVCFMT_LEFT },
	{ IDS_FTD_CREATEDBY,	FW_CREATEDBY,		IDS_TDLBC_CREATEDBY,	LVCFMT_LEFT },
	{ IDS_FTD_RISK,			FW_RISK,			IDS_TDLBC_RISK,			LVCFMT_RIGHT },
	{ IDS_FTD_LASTMOD,		FW_LASTMOD,			IDS_TDLBC_MODIFYDATE,	LVCFMT_RIGHT },
	{ IDS_FTD_EXTID,		FW_EXTERNALID,		IDS_TDLBC_EXTERNALID,	LVCFMT_RIGHT },
	{ IDS_FTD_COST,			FW_COST,			IDS_TDLBC_COST,			LVCFMT_RIGHT },
	{ IDS_FTD_VERSION,		FW_VERSION,			IDS_TDLBC_VERSION,		LVCFMT_LEFT },
	// add new fields on the end
};

const UINT FIELDCOUNT = sizeof(SEARCHFIELDS) / sizeof(SEARCHFIELD);

const SEARCHFIELD* GetSearchField(FIND_WHAT nWhat)
{
	int nField = FIELDCOUNT;
	
	while (nField--)
	{
		if (SEARCHFIELDS[nField].nWhat == nWhat)
			return &SEARCHFIELDS[nField];
	}
	
	// else
	return NULL;
}

const int TABSTOPS = 20;
const DWORD HEADERROW = 0xffffffff;

const UINT WM_FTD_SELECTITEM = (WM_APP+1);

/////////////////////////////////////////////////////////////////////////////
// CFindTaskDlg dialog

CFindTaskDlg::CFindTaskDlg(CWnd* pParent /*=NULL*/)
	: CDialog(CFindTaskDlg::IDD, pParent), 
	m_pageTimeEst(FALSE, FALSE), 
	m_pageTimeSpent(FALSE, FALSE), 
	m_pageCost(FALSE, FALSE), 
	m_pageTaskID(TRUE, FALSE),
	m_pageVersion(0),
	m_bDockable(FALSE),
	m_bSearchResults(FALSE), 
	m_nCurSel(-1)
{
	m_sResultsLabel.LoadString(IDS_FTD_RESULTS);
	
	//{{AFX_DATA_INIT(CFindTaskDlg)
	m_bAutoSelectSingles = FALSE;
	//}}AFX_DATA_INIT
	
	m_bAllTasklists = AfxGetApp()->GetProfileInt("FindTasks", "SearchAllTaskLists", FALSE);
	m_bIncludeDone = AfxGetApp()->GetProfileInt("FindTasks", "IncludeDoneTasks", FALSE);
	m_nFindOption = (FIND_WHAT)max(FW_TITLECOMMENTS, (int)AfxGetApp()->GetProfileInt("FindTasks", "LastFindOption", FW_TITLECOMMENTS));
	m_bAutoSelectSingles = AfxGetApp()->GetProfileInt("FindTasks", "AutoSelectSingles", FALSE);
	
	CPropertyPage* pPages[] = 
	{
		// same order as SEARCHFIELDS
		&m_pageTitleComments, &m_pagePriority, &m_pagePercent, &m_pageTimeEst, 
		&m_pageTimeSpent, &m_pageStartDate, &m_pageDueDate, &m_pageDoneDate, 
		&m_pageAllocTo, &m_pageAllocBy, &m_pageStatus, &m_pageCategory, 
		&m_pageTaskID, &m_pageFlag, &m_pageCreationDate, &m_pageCreatedBy,
		&m_pageRisk, &m_pageLastMod, &m_pageExtID, &m_pageCost, &m_pageVersion 
	};
	
	for (int nField = 0; nField < FIELDCOUNT; nField++)
	{
		const SEARCHFIELD& field = SEARCHFIELDS[nField];
		m_host.AddPage(pPages[nField], CEnString(field.nIDWhat), field.nWhat);
	}
}

CFindTaskDlg::~CFindTaskDlg()
{
}

void CFindTaskDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
	//{{AFX_DATA_MAP(CFindTaskDlg)
	DDX_Control(pDX, IDC_FINDOPTION, m_cbFindOptions);
	DDX_Control(pDX, IDC_RESULTS, m_lcResults);
	DDX_CBIndex(pDX, IDC_TASKLISTOPTIONS, m_bAllTasklists);
	DDX_Text(pDX, IDC_RESULTSLABEL, m_sResultsLabel);
	DDX_Check(pDX, IDC_INCLUDEDONE, m_bIncludeDone);
	DDX_CBIndex(pDX, IDC_FINDOPTION, m_nSelFindIndex);
	DDX_Check(pDX, IDC_AUTOSELECTSINGLES, m_bAutoSelectSingles);
	DDX_Check(pDX, IDC_SEARCHRESULTS, m_bSearchResults);
	//}}AFX_DATA_MAP
}

BEGIN_MESSAGE_MAP(CFindTaskDlg, CDialog)
//{{AFX_MSG_MAP(CFindTaskDlg)
	ON_BN_CLICKED(IDC_FIND, OnFind)
	ON_WM_CLOSE()
	ON_WM_SIZE()
	ON_WM_DESTROY()
	ON_CBN_SELCHANGE(IDC_FINDOPTION, OnSelchangeFindoption)
	ON_WM_GETMINMAXINFO()
	ON_BN_CLICKED(IDC_SELECTALL, OnSelectall)
	ON_COMMAND(ID_DOCKRIGHT, OnDockright)
	ON_UPDATE_COMMAND_UI(ID_DOCKRIGHT, OnUpdateDockright)
	ON_COMMAND(ID_DOCKLEFT, OnDockleft)
	ON_UPDATE_COMMAND_UI(ID_DOCKLEFT, OnUpdateDockleft)
	ON_COMMAND(ID_UNDOCK, OnUndock)
	ON_UPDATE_COMMAND_UI(ID_UNDOCK, OnUpdateUndock)
	ON_COMMAND(ID_DOCKBELOW, OnDockbelow)
	ON_UPDATE_COMMAND_UI(ID_DOCKBELOW, OnUpdateDockbelow)
	ON_BN_CLICKED(IDC_SEARCHRESULTS, OnSearchresults)
	ON_WM_SETCURSOR()
	ON_NOTIFY(LVN_ITEMCHANGING, IDC_RESULTS, OnItemchangingResults)
	//}}AFX_MSG_MAP
	ON_NOTIFY(LVN_ITEMACTIVATE, IDC_RESULTS, OnItemActivated)
	ON_NOTIFY(NM_CUSTOMDRAW, IDC_RESULTS, OnCustomDraw)
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////////////

BOOL CFindTaskDlg::Initialize(CWnd* pParent, BOOL bDockable)
{
	ASSERT (pParent || !bDockable);
	
	if (!pParent && bDockable)
		return FALSE;
	
	if (GetSafeHwnd())
		return TRUE;
	
	m_bDockable = bDockable;
	
	if (!Create(IDD_FIND_DIALOG, pParent))
		return FALSE;
	
	return TRUE;
}

void CFindTaskDlg::SetPriorityColors(const CDWordArray& aColors)
{
	m_pagePriority.SetPriorityColors(aColors);
}

BOOL CFindTaskDlg::OnInitDialog() 
{
	CDialog::OnInitDialog();
	
	m_host.Create(IDC_PAGEHOST, this);
		
	// build combobox of pages
	int nPages = m_host.GetPageCount();
	
	for (int nPage = 0; nPage < nPages; nPage++)
	{
		int nIndex = m_cbFindOptions.InsertString(nPage, m_host.GetPageTitle(nPage));
		m_cbFindOptions.SetItemDataPtr(nIndex, m_host.GetPage(nPage));
		
		// init active page
		if (m_nFindOption == (int)m_host.GetPageItemData(nPage))
		{
			m_nSelFindIndex = nIndex;
			m_cbFindOptions.SetCurSel(nIndex);
			m_host.SetActivePage(nPage);
		}
	}
	
	// toolbar
	if (m_toolbar.CreateEx(this, TBSTYLE_FLAT, WS_CHILD | WS_VISIBLE | CBRS_ALIGN_TOP))
	{
		if (m_toolbar.LoadToolBar(IDR_FINDDLG))
			m_toolbar.SetImage(IDB_FIND16, RGB(255, 0, 255));
	}
	
	m_tbHelper.Initialize(&m_toolbar, this);
	
	// very important - turn OFF all the auto positioning and sizing
	// by default have no borders
	UINT nStyle = m_toolbar.GetBarStyle();
	nStyle &= ~(CCS_NORESIZE | CCS_NOPARENTALIGN | CBRS_BORDER_ANY);
	nStyle |= (CBRS_SIZE_FIXED | CBRS_TOOLTIPS | CBRS_FLYBY);
	m_toolbar.SetBarStyle(nStyle);
	
	CRect rToolbar;
	GetDlgItem(IDC_TOOLBAR)->GetWindowRect(rToolbar);
	ScreenToClient(rToolbar);
	m_toolbar.MoveWindow(rToolbar);

	// subclass the results header ctrl to allow locking
	CWnd* pHeader = m_lcResults.GetHeaderCtrl();

	if (pHeader)
		m_hdrResults.SubclassWindow(pHeader->GetSafeHwnd());
	
	// gripper
	// position resize icon as close to bottom left as pos
	GetDlgItem(IDC_GRIPPER)->ModifyStyle(0, SBS_SIZEGRIP | SBS_SIZEBOXTOPLEFTALIGN | WS_CLIPSIBLINGS);
	CDeferWndMove(1).OffsetCtrl(this, IDC_GRIPPER, 1, 2);
	
	// setup up result list
	m_lcResults.InsertColumn(COL_TASK, "Task", LVCFMT_LEFT, 200);
	m_lcResults.InsertColumn(COL_MATCH, "", LVCFMT_LEFT, MATCH_COLWIDTH);
	m_lcResults.InsertColumn(COL_PATH, "Path", LVCFMT_LEFT, 100);

	m_lcResults.SetExtendedStyle(m_lcResults.GetExtendedStyle() | LVS_EX_ONECLICKACTIVATE | LVS_EX_UNDERLINEHOT);
	m_lcResults.SetHotCursor(AfxGetApp()->LoadStandardCursor(IDC_ARROW));
		

	GetDlgItem(IDC_SELECTALL)->EnableWindow(FALSE);
	CenterWindow();
	
	LoadSettings();
	
    m_toolbar.RefreshButtonStates();
	
	ResizeDlg();
	
	return TRUE;  // return TRUE unless you set the focus to a control
	// EXCEPTION: OCX Property Pages should return FALSE
}

void CFindTaskDlg::LoadSettings()
{
	// restore column widths
	m_lcResults.SetColumnWidth(COL_MATCH, AfxGetApp()->GetProfileInt("FindTasks", "MatchColWidth", MATCH_COLWIDTH));
	m_lcResults.SetColumnWidth(COL_PATH, AfxGetApp()->GetProfileInt("FindTasks", "PathColWidth", 100));
	InitFieldColumn();
	
	if (m_bDockable)
	{
		DM_POS nPos = DMP_UNDOCKED, nLastPos = DMP_RIGHT;
		DWORD dwTopLeft = (DWORD)AfxGetApp()->GetProfileInt("FindTasks", "TopLeft", -1);
		DWORD dwBottomRight = (DWORD)AfxGetApp()->GetProfileInt("FindTasks", "BottomRight", -1);
		
		if (dwBottomRight != -1 && dwTopLeft != -1)
		{
			nPos = (DM_POS)AfxGetApp()->GetProfileInt("FindTasks", "DockPos", DMP_UNDOCKED);
			nLastPos = (DM_POS)AfxGetApp()->GetProfileInt("FindTasks", "LastDockPos", DMP_RIGHT);

			CRect rect(GET_X_LPARAM(dwTopLeft), GET_Y_LPARAM(dwTopLeft), 
				GET_X_LPARAM(dwBottomRight), GET_Y_LPARAM(dwBottomRight));
			
			// ensure this intersects with the desktop
			if (NULL != MonitorFromRect(rect, MONITOR_DEFAULTTONULL))
				MoveWindow(rect);
		}
		
		// use the default size of the page host to initialize the 
		// docked width/height
		CSize rDef = GetMinDockedSize(nPos);
		
		int nWidthDocked = AfxGetApp()->GetProfileInt("FindTasks", "DockedWidth", rDef.cx);
		int nWidthDockedMax = AfxGetApp()->GetProfileInt("FindTasks", "DockedWidthMax", -1);
		
		int nHeightDocked = AfxGetApp()->GetProfileInt("FindTasks", "DockedHeight", rDef.cy);
		int nHeightDockedMax = AfxGetApp()->GetProfileInt("FindTasks", "DockedHeightMax", -1);
		
		m_dockMgr.Initialize(GetParent(), this, nPos, nLastPos,
							nWidthDocked, nWidthDockedMax, nHeightDocked, nHeightDockedMax);
	}
}

CSize CFindTaskDlg::GetMinDockedSize(DM_POS nPos)
{
	// start with Host size
	CRect rHost;
	m_host.GetWindowRect(rHost);
	ScreenToClient(rHost);

	// and RHS of find button
	CRect rFind;
	GetDlgItem(IDC_FIND)->GetWindowRect(rFind);
	ScreenToClient(rFind);
	rHost.right = rFind.right;

	if (nPos == DMP_BELOW)
		rHost.right += CDlgUnits(this).ToPixelsX(40); // so the results list is visible
	else	
		rHost.bottom += CDlgUnits(this).ToPixelsY(40); // so the results list is visible
	
	// add border
	int nBorder = CDlgUnits(this).ToPixelsX(7);
	rHost.InflateRect(nBorder, nBorder);
	
	// allow for non-client border
	rHost.left = rHost.top = 0;
	CalcWindowRect(rHost);
	
	return rHost.Size();
}

BOOL CFindTaskDlg::Show(BOOL bShow)
{
	if (!GetSafeHwnd())
		return FALSE;
	
	if (bShow)
	{
		// reset m_bSearchResults if dialog was previously hidden
		if (!IsWindowVisible())
		{
			m_bSearchResults = FALSE;
			UpdateData(FALSE);
		}
		
	    m_toolbar.RefreshButtonStates();

		ShowWindow(SW_SHOW);
		SetForegroundWindow(); // give it the focus

		// activate the current page
		m_host.GetActivePage()->OnSetActive();
	}
	else
		ShowWindow(SW_HIDE);
	
	return TRUE;
}

void CFindTaskDlg::AddResult(LPCTSTR szTask, LPCTSTR szMatch, LPCTSTR szPath, BOOL bDone, DWORD dwItemData, int nTaskList)
{
	if (GetSafeHwnd())
	{
		int nPos = m_lcResults.GetItemCount();
		
		// add result
		int nIndex = m_lcResults.InsertItem(nPos, szTask);
		
		m_lcResults.SetItemText(nIndex, COL_PATH, szPath);

		if (szMatch && lstrlen(szMatch))
			m_lcResults.SetItemText(nIndex, COL_MATCH, szMatch);
		
		m_lcResults.UpdateWindow();
		
		// map identifying data
		FTDRESULT res;
		res.dwItemData = dwItemData;
		res.nTaskList = nTaskList;
		res.bDone = bDone;
		
		DWORD dwKey = m_lcResults.GetItemCount();
		m_lcResults.SetItemData(nIndex, dwKey);
		m_mapResults[dwKey] = res;
		
		// update 'found' count
		m_sResultsLabel.Format(IDS_FTD_SOMERESULTS, m_mapResults.GetCount());
		UpdateData(FALSE);
		
		// focus first item added
		if (!GetDlgItem(IDC_SELECTALL)->IsWindowEnabled())
		{
            SelectItem(nIndex);

			// update 'search results' button' state
			m_toolbar.RefreshButtonStates();
			
			// enable 'select all' button
			GetDlgItem(IDC_SELECTALL)->EnableWindow(TRUE);
		}
	}
}

void CFindTaskDlg::AddHeaderRow(LPCTSTR szText, BOOL bSpaceAbove)
{
	int nPos = m_lcResults.GetItemCount();

	// add space above?
	if (bSpaceAbove)
	{
		int nIndex = m_lcResults.InsertItem(nPos, "");
		m_lcResults.SetItemData(nIndex, HEADERROW);
		nPos++;
	}
	
	// add result
	int nIndex = m_lcResults.InsertItem(nPos, szText);
	m_lcResults.SetItemData(nIndex, HEADERROW);

	// bold font for rendering
	if (m_fontBold.GetSafeHandle() == NULL)
		Misc::CreateFont(m_fontBold, (HFONT)m_lcResults.SendMessage(WM_GETFONT), MFS_BOLD);
}

BOOL CFindTaskDlg::GetSearchAllTasklists()
{
	if (GetSafeHwnd())
		UpdateData();
	

⌨️ 快捷键说明

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