📄 mylistctrl.cpp
字号:
// MyListCtrl.cpp : implementation file
//
#include "stdafx.h"
#include "GPMIS.h"
#include "MyListCtrl.h"
#include <sys/types.h>
#include <sys/stat.h>
#include <afxdisp.h> // OLE stuff
#include <shlwapi.h> // Shell functions (PathFindExtension() in this case)
#include <afxpriv.h> // ANSI to/from Unicode conversion macros
#include "ComboItem.h"
#include "EditItem.h"
#include "global.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/////////////////////////////////////////////////////////////////////////////
// CMyListCtrl
CMyListCtrl::CMyListCtrl() : CListCtrl(),m_nSortedColumn(-1),
m_bSortAscending(TRUE),m_nCompareAs(ELCT_STRING_CASE),
m_nDateTimeType(0),m_nMinColumnWidth(10),m_nMaxColumnWidth(1000)
{
for( int i = 0; i<64; i++ )
{
m_bCanEdit[i] = FALSE;
m_nColumnType[i] = ELCT_STRING_CASE;
m_nColumnCtrl[i] = eLast;
}
m_nDisableStartRow = -1;;
m_nDisableEndRow = -1;
//
// Default drop mode
//
m_dropMode.iMask = DL_ACCEPT_FILES | DL_ACCEPT_FOLDERS;
m_dropMode.pfnCallback = NULL;
//
// Initialize OLE libraries
//
m_bMustUninitOLE = FALSE;
_AFX_THREAD_STATE* pState = AfxGetThreadState();
if (!pState->m_bNeedTerm) // TRUE if OleUninitialize needs to be called
{
HRESULT hr = ::OleInitialize(NULL);
if (FAILED(hr))
// Or something of your choosing...
AfxMessageBox(_T("OLE initialization failed.\n\nMake sure that the OLE libraries are the correct version."));
else
m_bMustUninitOLE = TRUE;
}
m_bSortFirstCol = TRUE;
}
CMyListCtrl::~CMyListCtrl()
{
if(m_bMustUninitOLE)
{
::OleUninitialize();
}
m_MultiHeadArray.RemoveAll();
}
//////////////////////////////////////////////////////////////////////
// Message Maps
//////////////////////////////////////////////////////////////////////
BEGIN_MESSAGE_MAP(CMyListCtrl, CListCtrl)
//{{AFX_MSG_MAP(CMyListCtrl)
ON_NOTIFY(HDN_ITEMCLICKA, 0, OnHeaderClicked)
ON_NOTIFY(HDN_ITEMCLICKW, 0, OnHeaderClicked)
ON_WM_DROPFILES()
ON_WM_CREATE()
ON_NOTIFY_REFLECT(LVN_ENDLABELEDIT, OnEndlabeledit)
ON_NOTIFY_REFLECT(NM_CLICK, OnClick)
ON_NOTIFY_REFLECT(LVN_KEYDOWN, OnKeydown)
//}}AFX_MSG_MAP
ON_NOTIFY_EX_RANGE(TTN_NEEDTEXTW, 0, 0xFFFF, OnToolTipText)
ON_NOTIFY_EX_RANGE(TTN_NEEDTEXTA, 0, 0xFFFF, OnToolTipText)
END_MESSAGE_MAP()
//////////////////////////////////////////////////////////////////////
// AddRow()
// Parameters: nRow - .
// lpszItem -
// oid
// Action: Insert a item into list
//////////////////////////////////////////////////////////////////////
int CMyListCtrl::AddRow(int nRow, LPCTSTR lpszItem )
{
int nRet = CListCtrl::InsertItem(nRow,lpszItem);
return nRet;
}
int CMyListCtrl::AddRow( const LVITEM* pItem )
{
int nRet = CListCtrl::InsertItem(pItem);
return nRet;
}
//////////////////////////////////////////////////////////////////////
// DeleteRow()
// Parameters: nRow - .
// oid
// Action: Delete a item into list
//////////////////////////////////////////////////////////////////////
int CMyListCtrl::DeleteRow(int nRow)
{
int nRet = CListCtrl::DeleteItem(nRow);
return nRet;
}
//////////////////////////////////////////////////////////////////////
// OnHeaderClicked()
// Parameters: pNMHDR - Contains information about a notificationmessage.
// LRESULT - Contains the result from the message
// Action: Sort the column that the user clicks on. If it is not
// the same column as the last sorting then sorting ascending.
// If is the same column then toggle the sorting style. The
// list only recieves this message if the "no sort header" is
// NOT checked in the resource.// Returns: Nothing.
//////////////////////////////////////////////////////////////////////
void CMyListCtrl::OnHeaderClicked(NMHDR* pNMHDR, LRESULT* pResult)
{
HD_NOTIFY *phdNotify = (HD_NOTIFY *)pNMHDR;
if (phdNotify->iButton == 0)
{
m_bSortAscending = (phdNotify->iItem == m_nSortedColumn) ?!m_bSortAscending : TRUE;
m_nSortedColumn = phdNotify->iItem;
m_nCompareAs = (ListCompareType)m_nColumnType[m_nSortedColumn];
Sort();
}
*pResult = 0;
}
//////////////////////////////////////////////////////////////////////// Sort()
// Parameters: None.
// Action: This function is called when the user clicks on a column
// header. Derived classes should override this function
// if they want to change the m_nCompareAs based on the
// the column that was selected.// Returns: Nothing.
//////////////////////////////////////////////////////////////////////
void CMyListCtrl::Sort()
{
Sort(m_nSortedColumn, m_bSortAscending, m_nCompareAs);
}
//////////////////////////////////////////////////////////////////////// Sort()
// Parameters: nColumn - column to sort by
// bAscending - TRUE ascending sort, FALSE descending
// nCompareAs - How to compare the values as
// Action: Set all the sorting attributes then do a quick sort
// on the whole list. Derived class may want to override
// this if they want to use a different sort algorithm or
// want to use a different range// Returns: Nothing.
//////////////////////////////////////////////////////////////////////
void CMyListCtrl::Sort(int nColumn, BOOL bAscending, ListCompareType nCompareAs)
{
m_nSortedColumn = nColumn;
m_bSortAscending = bAscending;
m_nCompareAs = nCompareAs;
QuickSort(0, GetItemCount() - 1);
}
//////////////////////////////////////////////////////////////////////
// QuickSort()
// Parameters: p - start position, usually index 0
// q - end position, usually last index
// Action: Standard quick sort algorthim// Returns: Nothing.
//////////////////////////////////////////////////////////////////////
void CMyListCtrl::QuickSort(int p, int r)
{
if (p < r)
{
int q = Partition(p, r);
QuickSort(p, q);
QuickSort(q + 1, r);
}
}
//////////////////////////////////////////////////////////////////////
// Partition()
// Parameters: p - start position// q - end position
// Action: Partition of the array in the quick sort algorithm
// Returns: Nothing.
///////////////////////////////////////////////////////////////////
int CMyListCtrl::Partition(int p, int r)
{
CString tmp;
CString x = GetItemText( p, m_nSortedColumn);
int i = p - 1;
int j = r + 1;
while (i < j)
{
do
{
j--;
tmp = GetItemText(j, m_nSortedColumn);
}
while (CompareBy(tmp, x, m_bSortAscending ? ELOT_GT : ELOT_LT));
do
{
i++;
tmp = GetItemText(i, m_nSortedColumn);
}
while (CompareBy(tmp, x, m_bSortAscending ? ELOT_LT : ELOT_GT));
if (i < j)
{
SwapRow(i, j);
}
}
return j;
}
//////////////////////////////////////////////////////////////////////
// CompareBy()
// Parameters: str1 - string 1 (left operand)
// str2 - string 2 (right operand)
// op - operator type
// Action: Convert strings to new data type based on m_nCompareAs'
// value. Compare the strings using the operator.
// Returns: The result of (str1 op str2)
//////////////////////////////////////////////////////////////////////
BOOL CMyListCtrl::CompareBy(CString str1, CString str2, ListOperatorType op)
{
BOOL bReturn = FALSE;
switch (m_nCompareAs)
{
case ELCT_INTEGER:
{
int val1 = atoi(str1);
int val2 = atoi(str2);
if (op == ELOT_LT)
bReturn = (val1 < val2);
else if (op == ELOT_GT)
bReturn = (val1 > val2);
else if (op == ELOT_LTE)
bReturn = (val1 <= val2);
else if (op == ELOT_GTE)
bReturn = (val1 >= val2);
else
bReturn = (val1 == val2);
break;
}
case ELCT_DOUBLE:
{
double val1 = atof(str1);
double val2 = atof(str2);
if (op == ELOT_LT)
bReturn = (val1 < val2);
else if (op == ELOT_GT)
bReturn = (val1 > val2);
else if (op == ELOT_LTE)
bReturn = (val1 <= val2);
else if (op == ELOT_GTE)
bReturn = (val1 >= val2);
else
bReturn = (val1 == val2);
break;
}
case ELCT_DATETIME:
{
COleDateTime val1 = ParseDateTime(str1);
COleDateTime val2 = ParseDateTime(str2);
if (op == ELOT_LT)
bReturn = (val1 < val2);
else if (op == ELOT_GT)
bReturn = (val1 > val2);
else if (op == ELOT_LTE)
bReturn = (val1 <= val2);
else if (op == ELOT_GTE)
bReturn = (val1 >= val2);
else
bReturn = (val1 == val2);
break;
}
case ELCT_STRING_NOCASE:
{
str1.MakeUpper();
str2.MakeUpper();
}
case ELCT_STRING_CASE:
default:
{
if (op == ELOT_LT)
bReturn = (str1 < str2);
else if (op == ELOT_GT)
bReturn = (str1 > str2);
else if (op == ELOT_LTE)
bReturn = (str1 <= str2);
else if (op == ELOT_GTE)
bReturn = (str1 >= str2);
else
bReturn = (str1 == str2);
break;
}
}
return bReturn;
}
//////////////////////////////////////////////////////////////////////
// GetColumnCount()
// Parameters: None.// Action:
// Returns: The number of columns in the list control
//////////////////////////////////////////////////////////////////////
int CMyListCtrl::GetColumnCount() const
{
//Get the header control
CHeaderCtrl* pHeader = (CHeaderCtrl*)GetDlgItem(0);
//Return the number of items in it (i.e. the number of columns)
return pHeader->GetItemCount();
}
//////////////////////////////////////////////////////////////////////
// SwapRow()
// Parameters: nRow1 - row index (zero based)
// nRow2 - row index (zero based)
// Action: Swap nRow1 with nRow2
// Returns: TRUE if successful, else FALSE
//////////////////////////////////////////////////////////////////////
BOOL CMyListCtrl::SwapRow(int nRow1, int nRow2)
{
BOOL bOk = FALSE;
int nStart = 0;
if( !m_bSortFirstCol )
nStart = 1;
int nMaxRows = GetItemCount();
if ((nRow1 >= 0) && (nRow1 < nMaxRows) &&
(nRow2 >= 0) && (nRow2 < nMaxRows) &&
(nRow1 != nRow2))
{
int nMaxColumns = GetColumnCount(); //swap rows
LV_ITEM lvItem1, lvItem2; //hold all text for a single row
CStringArray rowText;
rowText.SetSize(nMaxColumns);
//save all the text in row
for(int i = nStart; i < nMaxColumns; i++)
{
rowText[i] = GetItemText(nRow1, i);
}
//setup parameters to get item data
lvItem1.mask = LVIF_IMAGE | LVIF_PARAM | LVIF_STATE;
lvItem1.iItem = nRow1; lvItem1.iSubItem = 0;
lvItem1.stateMask = LVIS_CUT | LVIS_DROPHILITED |
LVIS_FOCUSED | LVIS_SELECTED |
LVIS_OVERLAYMASK | LVIS_STATEIMAGEMASK;
lvItem2 = lvItem1;
lvItem2.iItem = nRow2;
//get item data
GetItem(&lvItem1);
GetItem(&lvItem2);
//set the text for the lo (left)
for(i = nStart; i < nMaxColumns; i++)
{
SetItemText(nRow1, i, GetItemText(nRow2, i));
}
lvItem2.iItem = nRow1;
SetItem(&lvItem2);
for(i = nStart; i < nMaxColumns; i++)
{
SetItemText(nRow2, i, rowText[i]);
}
lvItem1.iItem = nRow2;
SetItem(&lvItem1);
CString key1;
key1.Format("%d",nRow1);
CString key2;
key2.Format("%d",nRow2);
}
return bOk;
}
//////////////////////////////////////////////////////////////////////
// ParseDateTime()
// Parameters: lpszDate - date time string
// Action: get date time from string
// Returns: COleDateTime
//////////////////////////////////////////////////////////////////////
COleDateTime CMyListCtrl::ParseDateTime(LPCTSTR lpszDate)
{
COleDateTime odtVal;// = COleDateTime::GetCurrentTime();
CString strDate;
strDate.Format("%s",lpszDate);
int nYear,nMon,nDay;
int nHour=0,nMin=0,nSec=0;
if( !odtVal.ParseDateTime(lpszDate) )
{
switch(m_nDateTimeType)
{
case 0:
default:
if( strchr(lpszDate,' ') != NULL )
sscanf(lpszDate,"%4d%2d%2d %2d:%2d:%2d",
&nYear,&nMon,&nDay,&nHour,&nMin,&nSec);
else
sscanf(lpszDate,"%4d%2d%2d",
&nYear,&nMon,&nDay);
break;
case 1:
if( strchr(lpszDate,' ') != NULL )
sscanf(lpszDate,"%4d/%d/%d %2d:%2d:%2d",
&nYear,&nMon,&nDay,&nHour,&nMin,&nSec);
else
sscanf(lpszDate,"%4d/%d/%d",
&nYear,&nMon,&nDay);
break;
case 2:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -