📄 reportctrl.cpp
字号:
int nCount = 0;
while (TRUE)
{
if (!DeleteItem(0))
return BOOL(nCount);
nCount++;
}
return (BOOL)nCount;
}
int CReportCtrl::_StringCompare(const CString& s1, const CString& s2)
{
if (s1 < s2)
return -1;
if (s1 > s2)
return 1;
return 0;
}
BOOL CReportCtrl::_IsNumber(LPCTSTR pszText)
{
const int LEN = _tcslen(pszText);
if (LEN == 0)
return FALSE;
BOOL bPointFound = FALSE;
for(int i = 0; i < LEN; i++)
{
const TCHAR c = pszText[i];
if (c == _T('.'))
bPointFound = TRUE;
if ((c >= _T('0') && c <= _T('9'))
|| (c == _T('.') && !bPointFound)
|| (i == 0 && LEN > 1 && (c == _T('-')) || c == _T('+')))
{
// ok
}
else
{
return FALSE;
}
}
return TRUE;
}
int CReportCtrl::_NumberCompare(LPCTSTR pszNumber1, LPCTSTR pszNumber2)
{
const double fNumber1 = _tcstod(pszNumber1, NULL);
const double fNumber2 = _tcstod(pszNumber2, NULL);
if(fNumber1 < fNumber2)
return -1;
if(fNumber1 > fNumber2)
return 1;
return 0;
}
BOOL CReportCtrl::_IsDate(LPCTSTR pszText)
{
COleDateTime date;
date.ParseDateTime(pszText);
return date.GetStatus() == COleDateTime::valid;
}
int CReportCtrl::_DateCompare(const CString& strDate1, const CString& strDate2)
{
COleDateTime date1, date2;
date1.ParseDateTime(strDate1);
date2.ParseDateTime(strDate2);
if (date1.GetStatus() != COleDateTime::valid || date2.GetStatus() != COleDateTime::valid)
return _StringCompare(strDate1, strDate2); // not date
if (date1 < date2)
return -1;
if (date1 > date2)
return 1;
return 0;
}
////////////////////////////////////////////////////////////////////////////////
// Mark Jackson's code, modified by Bin Liu
////////////////////////////////////////////////////////////////////////////////
int CALLBACK CReportCtrl::_CompareFunction(LPARAM lParam1, LPARAM lParam2, LPARAM lParamData)
{
CReportCtrl* pListCtrl = reinterpret_cast<CReportCtrl*>(lParamData);
ASSERT(pListCtrl->IsKindOf(RUNTIME_CLASS(CListCtrl)));
ItemData* pid1 = reinterpret_cast<ItemData*>(lParam1);
ItemData* pid2 = reinterpret_cast<ItemData*>(lParam2);
ASSERT(pid1);
ASSERT(pid2);
CString s1 = pid1->arrStr[ pListCtrl->m_wndHeader.GetSortedColumn()];
CString s2 = pid2->arrStr[ pListCtrl->m_wndHeader.GetSortedColumn()];
s1.TrimLeft();
s1.TrimRight();
s2.TrimLeft();
s2.TrimRight();
if (s1.IsEmpty() || s2.IsEmpty())
return pListCtrl->m_wndHeader.IsSortAscending()== 1? _StringCompare(s1, s2) : _StringCompare(s2, s1);
if(_IsNumber(s1))
return pListCtrl->m_wndHeader.IsSortAscending()== 1? _NumberCompare(s1, s2) : _NumberCompare(s2, s1);
else if(_IsDate(s1))
return pListCtrl->m_wndHeader.IsSortAscending()==1 ? _DateCompare(s1, s2) : _DateCompare(s2, s1);
else
// text.
return pListCtrl->m_wndHeader.IsSortAscending()==1 ? _StringCompare(s1, s2) : _StringCompare(s2, s1);
}
////////////////////////////////////////////////////////////////////////////////
// Mark Jackson's code
////////////////////////////////////////////////////////////////////////////////
void CReportCtrl::OnColumnClick(NMHDR* pNMHDR, LRESULT* pResult)
{
NM_LISTVIEW* pNMListView = (NM_LISTVIEW*)pNMHDR;
const int iColumn = pNMListView->iSubItem;
// if it's a second click on the same column then reverse the sort order,
// otherwise sort the new column in ascending order.
// Sort(iColumn, iColumn == m_wndHeader.GetSortedColumn() ? !m_wndHeader.IsSortAscending()==1 : TRUE);
int nAscend = m_wndHeader.IsSortAscending();
if (nAscend == 0)
nAscend = 1;
else
nAscend = -1 * nAscend;
Sort(iColumn, nAscend);
*pResult = 0;
}
void CReportCtrl::Sort(int iColumn, int iAscending)
{
if (iColumn < 0 || iColumn >= GetColumnCount())
return;
m_wndHeader.SetSortedColumn(iColumn);
m_wndHeader.SetSortAscending(iAscending);
// show the appropriate arrow in the header control.
m_wndHeader.UpdateSortArrow();
VERIFY(SortItems(_CompareFunction, reinterpret_cast<DWORD>(this)));
}
void CReportCtrl::OnDestroy()
{
for(int iItem = 0; iItem < GetItemCount(); iItem ++)
_FreeItemMemory(iItem);
CListCtrlBase::OnDestroy();
}
BOOL CReportCtrl::SetItemText(int nItem, int nSubItem, LPCTSTR lpszText)
{
if(!CListCtrl::SetItemText(nItem, nSubItem, lpszText))
{
return false;
}
ItemData* pid = reinterpret_cast<ItemData*>(CListCtrl::GetItemData(nItem));
ASSERT(pid);
pid->arrStr[nSubItem] = lpszText;
return true;
}
BOOL CReportCtrl::SetItemText(int nItem, LPCSTR pItemName, LPCTSTR lpszText)
{
int nSubItem;
nSubItem = GetSubItem(pItemName);
if (nSubItem < 0) return FALSE;
if(!CListCtrl::SetItemText(nItem, nSubItem, lpszText))
return FALSE;
ItemData* pid = reinterpret_cast<ItemData*>(CListCtrl::GetItemData(nItem));
ASSERT(pid);
pid->arrStr[nSubItem] = lpszText;
return TRUE;
}
////////////////////////////////////////////////////////////////////////////////
// Mark Jackson's code
////////////////////////////////////////////////////////////////////////////////
BOOL CReportCtrl::SetItemData(int nItem, DWORD dwData)
{
if(!_IsValidIndex(nItem))
return FALSE;
ItemData* pid = reinterpret_cast<ItemData*>(CListCtrl::GetItemData(nItem));
ASSERT(pid);
pid->dwData = dwData;
return TRUE;
}
////////////////////////////////////////////////////////////////////////////////
// Mark Jackson's code
////////////////////////////////////////////////////////////////////////////////
DWORD CReportCtrl::GetItemData(int nItem) const
{
ASSERT(_IsValidIndex(nItem));
ItemData* pid = reinterpret_cast<ItemData*>(CListCtrl::GetItemData(nItem));
ASSERT(pid);
return pid->dwData;
}
BOOL CReportCtrl::_AssignNewItemData(int iItem, LPCTSTR lpItem)
{
ASSERT(_IsValidIndex(iItem));
ItemData* pid = new ItemData;
pid->dwData = CListCtrl::GetItemData(iItem); // get original data
pid->arrStr.SetSize(GetColumnCount());
pid->arrStr[0] = lpItem;
return CListCtrl::SetItemData(iItem, reinterpret_cast<DWORD>(pid));
}
BOOL CReportCtrl::_AssignNewItemData(int iItem, const CString* pTexts, int nSize)
{
ASSERT(pTexts != NULL);
ASSERT(_IsValidIndex(iItem));
ItemData* pid = new ItemData;
pid->dwData = CListCtrl::GetItemData(iItem); // get original data
pid->arrStr.SetSize(GetColumnCount());
for (int i = 0; i < min(nSize, GetColumnCount()); i++)
pid->arrStr[i] = pTexts[i];
return CListCtrl::SetItemData(iItem, reinterpret_cast<DWORD>(pid));
}
int CReportCtrl::GetColumnCount() const
{
return m_wndHeader.GetItemCount();
}
int CReportCtrl::GetFirstSelectedItem(int nStartAfter) const
{
nStartAfter = max(nStartAfter, -1);
for (int i = nStartAfter + 1; i < GetItemCount(); i++)
{
if (IsItemSelected(i))
return i;
}
return -1;
}
void CReportCtrl::Sort()
{
Sort(m_wndHeader.GetSortedColumn(), m_wndHeader.IsSortAscending());
}
int CReportCtrl::InsertItem(const LVITEM *pItem)
{
const int nIndex = CListCtrl::InsertItem(pItem);
if (!_IsValidIndex(nIndex))
return nIndex;
VERIFY(_AssignNewItemData(nIndex, pItem->pszText));
return nIndex;
}
int CReportCtrl::InsertItem(int nItem, LPCTSTR lpszItem, int nImage)
{
const int nIndex = CListCtrl::InsertItem(nItem, lpszItem, nImage);
if (!_IsValidIndex(nIndex))
return nIndex;
VERIFY(_AssignNewItemData(nIndex, lpszItem));
return nIndex;
}
int CReportCtrl::InsertItem(int nItem, LPCTSTR lpszItem)
{
const int nIndex = CListCtrl::InsertItem(nItem, lpszItem);
if (!_IsValidIndex(nIndex))
return nIndex;
VERIFY(_AssignNewItemData(nIndex, lpszItem));
return nIndex;
}
int CReportCtrl::InsertItem(UINT nMask, int nItem, LPCTSTR lpszItem, UINT nState, UINT nStateMask, int nImage, LPARAM lParam)
{
const int nIndex = CListCtrl::InsertItem(nMask, nItem, lpszItem, nState, nStateMask, nImage, lParam);
if (!_IsValidIndex(nIndex))
return nIndex;
VERIFY(_AssignNewItemData(nIndex, lpszItem));
return nIndex;
}
void CReportCtrl::SetFullRowSelect(BOOL bSet)
{
DWORD dwStype = CListCtrl::GetExtendedStyle();
if (bSet)
dwStype |= LVS_EX_FULLROWSELECT;
else
dwStype &= ~LVS_EX_FULLROWSELECT;
CListCtrl::SetExtendedStyle(dwStype);
}
void CReportCtrl::SetGridLines(BOOL bSet)
{
DWORD dwStype = CListCtrl::GetExtendedStyle();
if (bSet)
dwStype |= LVS_EX_GRIDLINES;
else
dwStype &= ~LVS_EX_GRIDLINES;
CListCtrl::SetExtendedStyle(dwStype);
}
int CReportCtrl::InsertColumn(int nCol, const LVCOLUMN *pColumn)
{
const int nIndex = CListCtrl::InsertColumn(nCol, pColumn);
if (nIndex > -1)
{
for (int i = 0; i < GetItemCount(); i++)
_ResetTextArray(i);
}
return nIndex;
}
int CReportCtrl::InsertColumn(int nCol, LPCTSTR lpszColumnHeading, int nFormat, int nWidth, int nSubItem)
{
const int nIndex = CListCtrl::InsertColumn(nCol, lpszColumnHeading, nFormat, nWidth, nSubItem);
if (nIndex > -1)
{
for (int i = 0; i < GetItemCount(); i++)
_ResetTextArray(i);
}
return nIndex;
}
BOOL CReportCtrl::_ResetTextArray(int nItem)
{
if (!_IsValidIndex(nItem))
return FALSE;
ItemData* pid = reinterpret_cast<ItemData*>(CListCtrl::GetItemData(nItem));
if (pid == NULL)
return FALSE;
pid->arrStr.SetSize(GetColumnCount());
for (int i = 0; i < GetColumnCount(); i++)
pid->arrStr[i] = CListCtrl::GetItemText(nItem, i);
return TRUE;
}
BOOL CReportCtrl::DeleteColumn(int nCol)
{
if (!CListCtrl::DeleteColumn(nCol))
return FALSE;
for (int i = 0; i < GetItemCount(); i++)
_ResetTextArray(i);
return TRUE;
}
BOOL CReportCtrl::SelectItem(int nItem, BOOL bSelectAdjacentIfNotAvailable)
{
if (!_IsValidIndex(nItem))
{
if (!bSelectAdjacentIfNotAvailable)
{
return FALSE;
}
else
{
if (nItem < 0)
nItem = 0;
if (nItem >= GetItemCount())
nItem = GetItemCount() - 1;
}
}
return SetItemState(nItem, LVIS_SELECTED, LVIS_SELECTED);
}
BOOL CReportCtrl::IsItemSelected(int nItem) const
{
POSITION pos = GetFirstSelectedItemPosition();
if (pos != NULL)
{
while (pos)
{
if (nItem == GetNextSelectedItem(pos))
return TRUE;
}
}
return FALSE;
}
int CReportCtrl::DeleteAllSelectedItems(ITEMDATAPROC lpFunc, LPARAM lParam)
{
int nCount = 0;
while (TRUE)
{
const int n = GetFirstSelectedItem();
if (!DeleteItem(n, FALSE, lpFunc, lParam))
return nCount;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -