filterbar.cpp
来自「管理项目进度工具的原代码」· C++ 代码 · 共 456 行
CPP
456 行
// FilterBar.cpp : implementation file
//
#include "stdafx.h"
#include "todolist.h"
#include "FilterBar.h"
#include "tdcmsg.h"
#include "filteredtodoctrl.h"
#include "..\shared\deferwndmove.h"
#include "..\shared\dlgunits.h"
#include "..\shared\enstring.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/////////////////////////////////////////////////////////////////////////////
const int FILTERCTRLXSPACING = 6; // dlu
const int FILTERCTRLYSPACING = 2; // dlu
struct FILTERCTRL
{
UINT nIDLabel;
UINT nIDCtrl;
int nLenLabelDLU;
int nLenCtrlDLU;
TDC_COLUMN nType;
};
static FILTERCTRL FILTERCTRLS[] =
{
{ IDC_FILTERLABEL, IDC_FILTERCOMBO, 22, 150, (TDC_COLUMN)-1 },
{ IDC_PRIORITYFILTERLABEL, IDC_PRIORITYFILTERCOMBO, 45, 75, TDCC_PRIORITY },
{ IDC_RISKFILTERLABEL, IDC_RISKFILTERCOMBO, 45, 75, TDCC_RISK },
{ IDC_ALLOCTOFILTERLABEL, IDC_ALLOCTOFILTERCOMBO, 45, 75, TDCC_ALLOCTO },
{ 0, IDC_ALLALLOCTO, 1, 119, TDCC_ALLOCTO },
{ IDC_ALLOCBYFILTERLABEL, IDC_ALLOCBYFILTERCOMBO, 45, 75, TDCC_ALLOCBY },
{ IDC_STATUSFILTERLABEL, IDC_STATUSFILTERCOMBO, 45, 75, TDCC_STATUS },
{ IDC_CATEGORYFILTERLABEL, IDC_CATEGORYFILTERCOMBO, 45, 75, TDCC_CATEGORY },
{ 0, IDC_ALLCATEGORIES, 1, 119, TDCC_CATEGORY }
};
const int NUMFILTERCTRLS = sizeof(FILTERCTRLS) / sizeof(FILTERCTRL);
#define WM_WANTCOMBOPROMPT (WM_APP+1)
/////////////////////////////////////////////////////////////////////////////
// CFilterBar dialog
CFilterBar::CFilterBar(CWnd* pParent /*=NULL*/)
: CDialog(IDD_FILTER_BAR, pParent),
m_cbCategoryFilter(TRUE, IDS_NOCATEGORY, IDS_TDC_ANY),
m_cbAllocToFilter(TRUE, IDS_NOALLOCTO, IDS_TDC_ANYONE),
m_cbAllocByFilter(FALSE, 0, IDS_TDC_ANYONE),
m_cbStatusFilter(FALSE, 0, IDS_TDC_ANY)
{
//{{AFX_DATA_INIT(CFilterBar)
m_bMatchAllAllocTo = FALSE;
m_bMatchAllCategory = FALSE;
//}}AFX_DATA_INIT
m_aVisibility.SetSize(TDCC_LAST);
}
void CFilterBar::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
//{{AFX_DATA_MAP(CFilterBar)
//}}AFX_DATA_MAP
DDX_Control(pDX, IDC_FILTERCOMBO, m_cbTaskFilter);
DDX_Control(pDX, IDC_ALLOCTOFILTERCOMBO, m_cbAllocToFilter);
DDX_Control(pDX, IDC_ALLOCBYFILTERCOMBO, m_cbAllocByFilter);
DDX_Control(pDX, IDC_CATEGORYFILTERCOMBO, m_cbCategoryFilter);
DDX_Control(pDX, IDC_STATUSFILTERCOMBO, m_cbStatusFilter);
DDX_Control(pDX, IDC_PRIORITYFILTERCOMBO, m_cbPriorityFilter);
DDX_Control(pDX, IDC_RISKFILTERCOMBO, m_cbRiskFilter);
DDX_CBIndex(pDX, IDC_FILTERCOMBO, (int&)m_filter.nFilter);
DDX_CBString(pDX, IDC_ALLOCBYFILTERCOMBO, m_filter.sAllocBy);
DDX_CBString(pDX, IDC_STATUSFILTERCOMBO, m_filter.sStatus);
// special handling
if (pDX->m_bSaveAndValidate)
{
int nIndex;
// priority
DDX_CBIndex(pDX, IDC_PRIORITYFILTERCOMBO, nIndex);
if (nIndex == 0) // any
m_filter.nPriority = FT_ANYPRIORITY;
else if (nIndex == 1) // none
m_filter.nPriority = FT_NOPRIORITY;
else
m_filter.nPriority = nIndex - 2;
// risk
DDX_CBIndex(pDX, IDC_RISKFILTERCOMBO, nIndex);
if (nIndex == 0) // any
m_filter.nRisk = FT_ANYRISK;
else if (nIndex == 1) // none
m_filter.nRisk = FT_NORISK;
else
m_filter.nRisk = nIndex - 2;
// cats
m_cbCategoryFilter.GetChecked(m_filter.aCategories);
DDX_Check(pDX, IDC_ALLCATEGORIES, m_bMatchAllCategory);
m_filter.SetFlag(FT_ANYCATEGORY, !m_bMatchAllCategory);
// allocto
m_cbAllocToFilter.GetChecked(m_filter.aAllocTo);
DDX_Check(pDX, IDC_ALLALLOCTO, m_bMatchAllAllocTo);
m_filter.SetFlag(FT_ANYALLOCTO, !m_bMatchAllAllocTo);
}
else
{
int nIndex;
// priority
if (m_filter.nPriority == FT_ANYPRIORITY)
nIndex = 0;
else if (m_filter.nPriority == FT_NOPRIORITY)
nIndex = 1;
else
nIndex = m_filter.nPriority + 2;
DDX_CBIndex(pDX, IDC_PRIORITYFILTERCOMBO, nIndex);
// risk
if (m_filter.nRisk == FT_ANYRISK)
nIndex = 0;
else if (m_filter.nRisk == FT_NORISK)
nIndex = 1;
else
nIndex = m_filter.nRisk + 2;
DDX_CBIndex(pDX, IDC_RISKFILTERCOMBO, nIndex);
// cats
m_cbCategoryFilter.SetChecked(m_filter.aCategories);
m_bMatchAllCategory = !m_filter.HasFlag(FT_ANYCATEGORY);
DDX_Check(pDX, IDC_ALLCATEGORIES, m_bMatchAllCategory);
// allocto
m_cbAllocToFilter.SetChecked(m_filter.aAllocTo);
m_bMatchAllAllocTo = !m_filter.HasFlag(FT_ANYALLOCTO);
DDX_Check(pDX, IDC_ALLALLOCTO, m_bMatchAllAllocTo);
}
}
BEGIN_MESSAGE_MAP(CFilterBar, CDialog)
//{{AFX_MSG_MAP(CFilterBar)
ON_WM_SIZE()
ON_BN_CLICKED(IDC_ALLALLOCTO, OnSelchangeFilter)
ON_BN_CLICKED(IDC_ALLCATEGORIES, OnSelchangeFilter)
//}}AFX_MSG_MAP
ON_CBN_SELCHANGE(IDC_FILTERCOMBO, OnSelchangeFilter)
ON_CBN_SELCHANGE(IDC_ALLOCTOFILTERCOMBO, OnSelchangeFilter)
ON_CBN_SELCHANGE(IDC_ALLOCBYFILTERCOMBO, OnSelchangeFilter)
ON_CBN_SELCHANGE(IDC_STATUSFILTERCOMBO, OnSelchangeFilter)
ON_CBN_SELCHANGE(IDC_PRIORITYFILTERCOMBO, OnSelchangeFilter)
ON_CBN_SELCHANGE(IDC_CATEGORYFILTERCOMBO, OnSelchangeFilter)
ON_CBN_SELCHANGE(IDC_RISKFILTERCOMBO, OnSelchangeFilter)
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CFilterBar message handlers
BOOL CFilterBar::Create(CWnd* pParentWnd, UINT nID)
{
if (CDialog::Create(IDD_FILTER_BAR, pParentWnd))
{
SetDlgCtrlID(nID);
return TRUE;
}
return FALSE;
}
void CFilterBar::OnSelchangeFilter()
{
UpdateData();
GetParent()->SendMessage(WM_FBN_FILTERCHNG, 0, (LPARAM)&m_filter);
}
void CFilterBar::RefreshFilterControls(const CFilteredToDoCtrl& tdc)
{
// get filter
tdc.GetFilter(m_filter);
// alloc to filter
CStringArray aItems;
tdc.GetAllocToNames(aItems);
// add blank item to top
aItems.Add("");
SetComboBoxItems(m_cbAllocToFilter, aItems);
// alloc by filter
tdc.GetAllocByNames(aItems);
// add blank item to top
aItems.Add("");
SetComboBoxItems(m_cbAllocByFilter, aItems);
// category filter
tdc.GetCategoryNames(aItems);
// add blank item to top
aItems.Add("");
SetComboBoxItems(m_cbCategoryFilter, aItems);
// status filter
tdc.GetStatusNames(aItems);
// add blank item to top
aItems.Add("");
SetComboBoxItems(m_cbStatusFilter, aItems);
// priority
m_cbPriorityFilter.SetColors(m_aPriorityColors);
m_cbPriorityFilter.InsertColor(0, (COLORREF)-1, CEnString(IDS_TDC_ANY)); // add a blank item
// risk never needs changing
// update UI
UpdateData(FALSE);
}
void CFilterBar::SetFilterLabelAlignment(BOOL bLeft)
{
UINT nAlign = bLeft ? SS_LEFT : SS_RIGHT;
int nLabel = NUMFILTERCTRLS;
while (nLabel--)
{
UINT nLabelID = FILTERCTRLS[nLabel].nIDLabel;
if (nLabelID)
{
CWnd* pLabel = GetDlgItem(nLabelID);
pLabel->ModifyStyle(SS_TYPEMASK, nAlign);
pLabel->Invalidate();
}
}
}
void CFilterBar::SetPriorityColors(const CDWordArray& aColors)
{
m_aPriorityColors.Copy(aColors);
if (m_cbPriorityFilter.GetSafeHwnd())
{
// save and restore current selection
int nSel = m_cbPriorityFilter.GetCurSel();
m_cbPriorityFilter.SetColors(aColors);
m_cbPriorityFilter.InsertColor(0, (COLORREF)-1, CEnString(IDS_TDC_ANY)); // add a blank item
m_cbPriorityFilter.SetCurSel(nSel);
}
}
void CFilterBar::OnSize(UINT nType, int cx, int cy)
{
CDialog::OnSize(nType, cx, cy);
// check we're not in the middle of creation
if (m_cbStatusFilter.GetSafeHwnd())
ReposControls(cx, FALSE);
}
int CFilterBar::CalcHeight(int nWidth)
{
return ReposControls(nWidth, TRUE);
}
void CFilterBar::SetVisibleFilters(const CTDCColumnArray& aFilters)
{
// clear first
int nFilter = m_aVisibility.GetSize();
while (nFilter--)
m_aVisibility[nFilter] = FALSE;
// then set the visible ones
int nItem = aFilters.GetSize();
while (nItem--)
{
nFilter = aFilters[nItem];
m_aVisibility[nFilter] = TRUE;
}
ReposControls();
}
BOOL CFilterBar::WantShowFilter(TDC_COLUMN nType)
{
if ((int)nType < 0) // first filter is -1 and is therefore always visible
return TRUE;
return (BOOL)m_aVisibility[(DWORD)nType];
}
void CFilterBar::EnableMultiSelection(DWORD dwFlags)
{
m_cbCategoryFilter.EnableMultiSelection(dwFlags & FB_MULTISELCAT);
m_cbAllocToFilter.EnableMultiSelection(dwFlags & FB_MULTISELALLOCTO);
}
int CFilterBar::ReposControls(int nWidth, BOOL bCalcOnly)
{
CDeferWndMove dwm(bCalcOnly ? 0 : NUMFILTERCTRLS);
if (nWidth <= 0)
{
CRect rClient;
GetClientRect(rClient);
nWidth = rClient.Width();
}
int nCtrlHeight = dwm.OffsetCtrl(this, IDC_FILTERCOMBO).Height();
int nXPos = 0, nYPos = 0, nVisible = 0;
CDlgUnits dlu(*this);
// indent controls after the first line so that they
// line up neatly with the first line. Unless we're only
// at the second control in which case there is nothing
// to line up with
const FILTERCTRL& fc0 = FILTERCTRLS[0];
const FILTERCTRL& fc1 = FILTERCTRLS[1];
int nLineIndent = dlu.ToPixelsX(fc0.nLenLabelDLU +
fc0.nLenCtrlDLU -
fc1.nLenLabelDLU -
fc1.nLenCtrlDLU - 1);
for (int nCtrl = 0; nCtrl < NUMFILTERCTRLS; nCtrl++)
{
CRect rCtrl;
const FILTERCTRL& fc = FILTERCTRLS[nCtrl];
// display this control only if the corresponding column
// is also showing
BOOL bWantCtrl = WantShowFilter(fc.nType);
if (bWantCtrl)
{
// if we're at the start of the line then just move ctrls
// else we must check whether there's enough space to fit
if (nXPos > 0 || (nYPos > 0 && nXPos > nLineIndent)) // we're not the first
{
// work out the total length of label + ctrl
int nLen = dlu.ToPixelsX(fc.nLenLabelDLU + FILTERCTRLXSPACING + fc.nLenCtrlDLU);
// do we fit?
if ((nLen + nXPos) > nWidth) // no
{
// move to next line
nXPos = nLineIndent;
nYPos += dlu.ToPixelsY(FILTERCTRLYSPACING) + nCtrlHeight;
}
}
// move label
rCtrl.left = nXPos;
rCtrl.right = nXPos + dlu.ToPixelsX(fc.nLenLabelDLU);
rCtrl.top = nYPos;
rCtrl.bottom = nYPos + nCtrlHeight;
if (fc.nIDLabel && !bCalcOnly)
dwm.MoveWindow(GetDlgItem(fc.nIDLabel), rCtrl);
// update XPos for the label
nXPos = rCtrl.right;
// add spacing
nXPos += dlu.ToPixelsX(FILTERCTRLXSPACING);
// move ctrl
rCtrl.left = nXPos;
rCtrl.right = nXPos + dlu.ToPixelsX(fc.nLenCtrlDLU);
rCtrl.top = nYPos;
rCtrl.bottom = nYPos + nCtrlHeight;
if (!bCalcOnly)
dwm.MoveWindow(GetDlgItem(fc.nIDCtrl), rCtrl);
// update XPos for the control
nXPos = rCtrl.right + dlu.ToPixelsX(FILTERCTRLXSPACING);
nVisible++;
}
//show/hide as appropriate
if (!bCalcOnly)
{
if (fc.nIDLabel)
{
GetDlgItem(fc.nIDLabel)->ShowWindow(bWantCtrl ? SW_SHOW : SW_HIDE);
GetDlgItem(fc.nIDLabel)->EnableWindow(bWantCtrl);
}
GetDlgItem(fc.nIDCtrl)->ShowWindow(bWantCtrl ? SW_SHOW : SW_HIDE);
GetDlgItem(fc.nIDCtrl)->EnableWindow(bWantCtrl);
}
}
return nYPos + nCtrlHeight + 2;
}
void CFilterBar::SetFilter(const FTDCFILTER& filter)
{
m_filter = filter;
UpdateData(FALSE);
// the droplists don't get set properly if they
// are empty but were not previously so we do it manually
if (m_filter.sAllocBy.IsEmpty())
m_cbAllocByFilter.SetCurSel(0);
if (m_filter.sStatus.IsEmpty())
m_cbStatusFilter.SetCurSel(0);
}
BOOL CFilterBar::OnInitDialog()
{
CDialog::OnInitDialog();
// one-time init for risk filter combo
m_cbRiskFilter.InsertString(0, CEnString(IDS_TDC_ANY)); // add a blank item
return TRUE; // return TRUE unless you set the focus to a control
// EXCEPTION: OCX Property Pages should return FALSE
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?