📄 sortlistctrl.cpp
字号:
if ( !bInsertNorOK && !bInsertSmalOK )
return FALSE;
return TRUE;
}
BOOL CSortListCtrl::InsertBmpToImageList(
CImageList &ImgList,
CBitmap *pbmpInsert, // 要插入的图片
int nWidthPerImage, // 单张小图的宽度,用来计算图像列表中小图的个数
COLORREF crMask/*=RGB(255,255,0)*/
)
{
if ( !pbmpInsert || !pbmpInsert->GetSafeHandle() )
{
return FALSE;
}
BITMAP bm;
pbmpInsert->GetBitmap ( &bm );
m_nImageNum = bm.bmWidth / nWidthPerImage;
ImgList.Add ( pbmpInsert, crMask);
return TRUE;
}
int CSortListCtrl::GetColumnCount()
{
return m_iNumColumns;
}
int CSortListCtrl::InsertItem(int iItem, CStringArray &StrAry, int nImageIndex)
{
if ( iItem == -1 )
iItem = GetItemCount();
// Use the LV_ITEM structure to insert the items
ASSERT ( StrAry.GetSize() == m_iNumColumns );
LVITEM lvItem;
CString csText;
csText = StrAry.GetAt(0);
LPCTSTR* arrpsz = new LPCTSTR[ m_iNumColumns ];
arrpsz[ 0 ] = new TCHAR[ csText.GetLength() + 1 ];
(void)lstrcpy( (TCHAR*)arrpsz[ 0 ], csText.GetBuffer(0) );
// Insert the first item
lvItem.mask = LVIF_IMAGE | LVIF_TEXT;
lvItem.iItem = iItem;
lvItem.iSubItem = 0;
csText = csText;
lvItem.pszText = (LPTSTR)(LPCTSTR)( csText );
CImageList *pImgList_Nor = GetImageList ( LVSIL_NORMAL );
CImageList *pImgList_Sma = GetImageList ( LVSIL_SMALL );
if ( m_nImageNum < 1 )
{
if ( pImgList_Nor ) m_nImageNum = pImgList_Nor->GetImageCount ();
else if ( pImgList_Sma ) m_nImageNum = pImgList_Sma->GetImageCount ();
}
if ( nImageIndex < 0 ) nImageIndex = 0;
if ( nImageIndex >= 0 && m_nImageNum > 0 )
lvItem.iImage = nImageIndex%m_nImageNum;
iItem = CListCtrl::InsertItem(&lvItem);
for( int iColumn = 1; iColumn < m_iNumColumns; iColumn++ )
{
csText = StrAry.GetAt ( iColumn );
ASSERT_VALID_STRING( csText.GetBuffer(0) );
VERIFY( CListCtrl::SetItemText( iItem, iColumn, csText ) );
arrpsz[ iColumn ] = new TCHAR[ csText.GetLength() + 1 ];
(void)lstrcpy( (TCHAR*)arrpsz[ iColumn ], csText.GetBuffer(0) );
}
VERIFY( SetTextArray( iItem, arrpsz ) );
InsertItemSuccess ( iItem );
return iItem;
}
BOOL CSortListCtrl::RowIsExist ( CStringArray &StrAry )
{
ASSERT ( StrAry.GetSize() == m_iNumColumns );
for ( int nItem=0; nItem<GetItemCount(); nItem++ )
{
BOOL bExist = TRUE;
for ( int nSubItem=0; nSubItem<m_iNumColumns; nSubItem++ )
{
CString csText = GetItemText ( nItem, nSubItem );
if ( csText != StrAry.GetAt ( nSubItem ) )
{
bExist = FALSE;
break;
}
}
if ( bExist ) return TRUE;
}
return FALSE;
}
int CSortListCtrl::InsertItem ( int iItem, int nImageIndex, LPCTSTR pszText, ... )
{
CStringArray StrAry;
StrAry.Add ( pszText );
va_list list;
va_start( list, pszText );
for( int iColumn = 1; iColumn < m_iNumColumns; iColumn++ )
{
pszText = va_arg( list, LPCTSTR );
ASSERT_VALID_STRING( pszText );
StrAry.Add ( pszText );
}
va_end( list );
return InsertItem ( iItem, StrAry, nImageIndex );
}
//改变列表框的属性,使之具有分割线、选中时所有项高亮
void CSortListCtrl::SetListCtrlGridAttr ( BOOL bSaveTypeMask, DWORD dwInitTypeMask )
{
DWORD dwStyle = (DWORD)SendMessage(LVM_GETEXTENDEDLISTVIEWSTYLE);
dwStyle |= LVS_EX_HEADERDRAGDROP | LVS_EX_GRIDLINES;
dwStyle |= LVS_EX_FULLROWSELECT;
SendMessage(LVM_SETEXTENDEDLISTVIEWSTYLE, 0, (LPARAM)dwStyle);
m_bSaveTypeMask = bSaveTypeMask;
m_dwInitTypeMask = dwInitTypeMask;
}
void CSortListCtrl::SetListView(DWORD dwView)
{
dwView = dwView&LVS_TYPEMASK;
DWORD dwOldStyle;
HWND hWndList = GetSafeHwnd();
dwOldStyle = GetWindowLong(hWndList,GWL_STYLE);
if ( (dwOldStyle & LVS_TYPEMASK) != dwView )
{
dwOldStyle &= ~LVS_TYPEMASK;
dwOldStyle |= dwView;
SetWindowLong ( hWndList,GWL_STYLE,dwOldStyle );
}
m_dwInitTypeMask = dwView;
}
DWORD CSortListCtrl::GetTypeMask ()
{
DWORD dwOldStyle;
HWND hWndList = GetSafeHwnd();
dwOldStyle = GetWindowLong(hWndList,GWL_STYLE);
return (dwOldStyle& LVS_TYPEMASK);
}
BOOL CSortListCtrl::SubclassWindow()
{
return m_ctlHeader.SubclassWindow( GetHeaderCtrl()->GetSafeHwnd() );
}
//
// 某点是否包含在某个子项目里
// return :
// 0 : 不在这个范围里
// 1 : 在这个范围里
//
int CSortListCtrl::PtInRect ( int iItem, CPoint &pt )
{
CRect rc;
CListCtrl::GetItemRect ( iItem, &rc, LVIR_BOUNDS );
ClientToScreen ( &rc );
if ( rc.PtInRect ( pt ) )
return 1;
return 0;
}
//
// 鼠标是否指向有效的范围,即有数据的格子里
//
BOOL CSortListCtrl::IsCursorInValidRect()
{
BOOL bSelected = FALSE;
if ( GetTypeMask() == LVS_REPORT )
{
CRect rc,rcClient;
if ( GetItemCount() > 0 )
{
CListCtrl::GetItemRect ( 0, &rc, LVIR_BOUNDS );
rcClient.top = rc.top;
rcClient.left = rc.left;
CListCtrl::GetItemRect ( GetItemCount()-1, &rc, LVIR_BOUNDS );
rcClient.right = rc.right;
rcClient.bottom = rc.bottom;
ClientToScreen ( &rcClient );
CPoint pt;
::GetCursorPos ( &pt );
if ( rcClient.PtInRect ( pt ) )
bSelected = TRUE;
}
}
else if ( GetItemCount() > 0 )
{
if ( GetSelectionMark() < 0 )
return FALSE;
else
{
CPoint pt;
::GetCursorPos ( &pt );
int nTopIndex = GetTopIndex();
int nCountPerPage = GetCountPerPage();
for ( int nRow=0; nRow<nCountPerPage; nRow++ )
{
int nRet = PtInRect ( nRow+nTopIndex, pt );
if ( nRet == -1 ) return FALSE;
else if ( nRet == 1 ) return TRUE;
}
}
}
if ( !bSelected ) SetSelectionMark ( -1 );
return bSelected;
}
BOOL CSortListCtrl::GetCurSelAllSubItemText(CStringArray &StrAry)
{
int iItem = GetSelectionMark();
if ( iItem < 0 || iItem >= GetItemCount() )
return FALSE;
if ( m_nLastSelItem == iItem )
return FALSE;
m_nLastSelItem = iItem;
CString csText;
for ( int i=0; i<GetColumnCount(); i++ )
{
StrAry.Add ( GetItemText ( iItem, i ) );
}
return TRUE;
}
CString CSortListCtrl::GetItemText(int iItem, int nSubItem) const
{
if ( iItem < 0 ) return _T("ItemError");
if ( nSubItem < 0 ) return _T("SubItemError");
LPCTSTR* arrpsz = GetTextArray( iItem );
LPCTSTR pszText = arrpsz[ nSubItem ];
return GET_SAFE_STRING ( pszText );
}
BOOL CSortListCtrl::SetItemText( int iItem, int nSubItem, LPCTSTR lpszText )
{
if ( iItem < 0 || nSubItem < 0 ) return FALSE;
if( !CListCtrl::SetItemText( iItem, nSubItem, lpszText ) )
return FALSE;
LPCTSTR* arrpsz = GetTextArray( iItem );
if ( !arrpsz ) return FALSE;
LPCTSTR pszText = arrpsz[ nSubItem ];
delete[] pszText;
pszText = new TCHAR[ lstrlen( lpszText ) + 1 ];
(void)lstrcpy( (TCHAR*)pszText, lpszText );
arrpsz[ nSubItem ] = pszText;
return TRUE;
}
BOOL CSortListCtrl::SetItemText( int iItem, CStringArray &StrAry )
{
if ( iItem < 0 || iItem >= GetItemCount() ) return FALSE;
ASSERT ( StrAry.GetSize() == m_iNumColumns );
for ( int i=0; i<m_iNumColumns; i++ )
{
SetItemText ( iItem, i, StrAry.GetAt(i) );
}
return TRUE;
}
//
// 改变一行的图标,注意:要少用,因为这个函数实际上就是将原来
// 一行删除再添加的,所以操作比较慢
//
void CSortListCtrl::ChangeItemImage(int iItem, int nNewImageIndex)
{
SetRedraw ( FALSE );
CStringArray StrAry;
StrAry.Add ( GetItemText ( iItem, 0 ) );
UINT nItemState = GetItemState ( iItem, LVIS_SELECTED );
ASSERT ( iItem>=0 && iItem<GetItemCount() );
for( int iColumn = 1; iColumn < m_iNumColumns; iColumn++ )
{
StrAry.Add ( GetItemText ( iItem, iColumn ) );
}
CUIntArray UIntAry_ItemData;
for ( int i=0; i<MAX_ITEMDATA_COUNT; i++ )
{
UIntAry_ItemData.Add ( GetItemData ( iItem, i ) );
}
DeleteItem ( iItem, FALSE );
iItem = InsertItem ( iItem, StrAry, nNewImageIndex );
for ( int i=0; i<MAX_ITEMDATA_COUNT; i++ )
{
SetItemData ( iItem, UIntAry_ItemData.GetAt(i), i );
}
SetItemState ( iItem, nItemState, LVIS_SELECTED );
SetRedraw ( TRUE );
}
int CSortListCtrl::GetSelectionMark()
{
m_nCurSelItem = CListCtrl::GetSelectionMark();
return m_nCurSelItem;
}
void CSortListCtrl::ReSizing()
{
if ( !::IsWindow(m_hWnd) ) return;
CRect rcParent;
CWnd *pWnd = GetParent();
ASSERT ( pWnd );
pWnd->GetClientRect ( &rcParent );
MoveWindow ( &rcParent );
}
void CSortListCtrl::OnCustomdrawList(NMHDR *pNMHDR, LRESULT *pResult)
{
NMLVCUSTOMDRAW* pLVCD = reinterpret_cast<NMLVCUSTOMDRAW*>( pNMHDR );
// Take the default processing unless we set this to something else below.
*pResult = 0;
// First thing - check the draw stage. If it's the control's prepaint
// stage, then tell Windows we want messages for every item.
if ( CDDS_PREPAINT == pLVCD->nmcd.dwDrawStage )
{
*pResult = CDRF_NOTIFYITEMDRAW;
}
else if ( CDDS_ITEMPREPAINT == pLVCD->nmcd.dwDrawStage )
{
// This is the prepaint stage for an item. Here's where we set the
// item's text color. Our return value will tell Windows to draw the
// item itself, but it will use the new color we set here.
// We'll cycle the colors through red, green, and light blue.
if ( GetItemCount() > 0 )
{
int iItem = pLVCD->nmcd.dwItemSpec;
if ( iItem < GetItemCount() )
{
ItemData* pid = reinterpret_cast<ItemData*>( CListCtrl::GetItemData( iItem ) );
if ( pid )
{
if ( pid->pAppItemData )
{
pLVCD->clrText = pid->pAppItemData->clrItemText;
pLVCD->clrTextBk = pid->pAppItemData->clrItemBK;
}
}
}
}
// Tell Windows to paint the control itself.
*pResult = CDRF_DODEFAULT;
}
}
//
// 改变一行的颜色,有些skin库可能会将 NM_CUSTOMDRAW 通知拦截了而导致该函数不能生效
//
void CSortListCtrl::ChangeLineColor(int iItem, COLORREF clrText, COLORREF clrTextBk/*=CLR_NONE*/)
{
ASSERT ( iItem >= 0 && iItem < GetItemCount() );
if ( clrText == clrTextBk )
{
clrText = GetInverseColor ( clrTextBk );
}
CSortListCtrl::t_ItemAppData ItemAppData;
GetItemAppData ( iItem, ItemAppData );
if ( clrText != CLR_NONE )
ItemAppData.clrItemText = clrText;
if ( clrTextBk != CLR_NONE )
ItemAppData.clrItemBK = clrTextBk;
SetItemAppData ( iItem, ItemAppData );
RedrawItems ( iItem, iItem );
}
void CSortListCtrl::GetLineColor ( int iItem, COLORREF &clrText, COLORREF &clrTextBk )
{
ASSERT ( iItem >= 0 && iItem < GetItemCount() );
CSortListCtrl::t_ItemAppData ItemAppData;
GetItemAppData ( iItem, ItemAppData );
clrText = ItemAppData.clrItemText;
clrTextBk = ItemAppData.clrItemBK;
}
void CSortListCtrl::OnClick(NMHDR* pNMHDR, LRESULT* pResult)
{
*pResult = 0;
NM_LISTVIEW* pNMListView = (NM_LISTVIEW*)pNMHDR;
m_nCurSelItem = pNMListView->iItem;
m_nCurSelSubItem = pNMListView->iSubItem;
if ( !ModifySelItemContent ( m_nCurSelItem, m_nCurSelSubItem ) )
{
CWnd* pWnd = GetParent();
if ( pWnd )
pWnd->SendMessage ( WM_ITEM_CLICK, (WPARAM)pNMHDR );
}
}
BOOL CSortListCtrl::ModifySelItemContent ( int iItem, int nSubItem )
{
m_nCurSelItem = iItem;
m_nCurSelSubItem = nSubItem;
if ( m_nCurSelSubItem < 0 || m_nCurSelSubItem >= m_iNumColumns )
return FALSE;
// Make sure that the item is visible
if ( !EnsureVisible ( m_nCurSelItem, TRUE ) )
{
return FALSE;
}
// 是禁止编辑的项
if ( !CanEdit ( iItem ) ) return FALSE;
E_COLUMN_TYPE eColumnType = E_COLUMN_TYPE_INVALID;
int nRet = GetParent()->SendMessage ( WM_ITEM_ClickSubItem, WPARAM(m_nCurSelItem), LPARAM(m_nCurSelSubItem) );
// 被父窗口处理了,所以我不管了
if ( nRet == E_COLUMN_TYPE_NORMAL )
{
return FALSE;
}
// 父窗口告诉我应该画何种控件
else if ( nRet > E_COLUMN_TYPE_NORMAL )
{
eColumnType = (E_COLUMN_TYPE)nRet;
}
// 父窗口根本没理会这条消息
else
{
eColumnType = (E_COLUMN_TYPE)m_UIntAry_ColumnType.GetAt( m_nCurSelSubItem );
}
m_StrAry_CommonText.RemoveAll();
if (
m_Callback_ListCtrl_AddListString
&&
(
eColumnType == E_COLUMN_TYPE_MENU ||
eColumnType == E_COLUMN_TYPE_COMBO
)
)
{
m_Callback_ListCtrl_AddListString ( m_nCurSelItem, m_nCurSelSubItem, &m_StrAry_CommonText, eColumnType, NULL );
}
if ( eColumnType == E_COLUMN_TYPE_COMBO )
{
ComboItem ( m_nCurSelItem, m_nCurSelSubItem, m_StrAry_CommonText );
}
else if ( eColumnType == E_COLUMN_TYPE_MENU )
{
PopupMenuItem ( m_nCurSelItem, m_nCurSelSubItem, m_StrAry_CommonText );
}
else if ( eColumnType == E_COLUMN_TYPE_EDIT )
{
EditItem ( m_nCurSelItem, m_nCurSelSubItem );
}
else return FALSE;
return TRUE;
}
void CSortListCtrl::PopupMenuItem(int iItem, int nSubItem, CStringArray &StrAry)
{
// Make sure that the item is visible
if( !EnsureVisible ( iItem, TRUE ) )
{
return;
}
CRect rect;
GetItemExposeRect ( iItem, nSubItem, rect );
CPoint pt ( rect.left, rect.bottom );
ClientToScreen ( &pt );
// GenerateAndPopupMenuXP ( StrAry, SORTLISTCTRL_START_MENU_ID, this, &pt );
}
BOOL CSortListCtrl::OnCommand(WPARAM wParam, LPARAM lParam)
{
if ( wParam >= SORTLISTCTRL_START_MENU_ID )
{
int nMenuIndex = wParam-SORTLISTCTRL_START_MENU_ID;
if ( nMenuIndex < m_StrAry_CommonText.GetSize() &&
m_nCurSelItem >= 0 && m_nCurSelSubItem >= 0 )
{
SetItemText ( m_nCurSelItem, m_nCurSelSubItem,
m_StrAry_CommonText.GetAt ( nMenuIndex ) );
}
}
return CListCtrl::OnCommand(wParam, lParam);
}
void CSortListCtrl::SetColumnType(E_COLUMN_TYPE eColumnType, int nCol, LPVOID lpParameter/*=NULL*/)
{
ASSERT ( nCol >= 0 && nCol < m_iNumColumns );
ASSERT ( m_iNumColumns == m_UIntAry_ColumnType.GetSize() );
ASSERT ( eColumnType >= E_COLUMN_TYPE_NORMAL && eColumnType < E_COLUMN_TYPE_NUM );
m_UIntAry_ColumnType.SetAt ( nCol, eColumnType );
}
void CSortListCtrl::SetColumnType(E_COLUMN_TYPE eColumnType, LPCTSTR lpszColumnText, LPVOID lpParameter/*=NULL*/)
{
int nCol = GetColumnIndexByText ( lpszColumnText );
SetColumnType ( eColumnType, nCol, lpParameter );
}
int CSortListCtrl::GetColumnIndexByText(LPCTSTR lpszColumnText)
{
ASSERT ( lpszColumnText );
for ( int i=0; i<m_iNumColumns; i++ )
{
if ( lstrcmpi ( GetColumnText(i), lpszColumnText ) == 0 )
return i;
}
return -1;
}
CString CSortListCtrl::GetColumnText ( int nCol )
{
ASSERT ( nCol >= 0 && nCol < GetColumnCount() );
TCHAR szText[1024] = {0};
LV_COLUMN lvCol;
memset ( &lvCol, 0, sizeof(LV_COLUMN) );
lvCol.mask = LVCF_TEXT;
lvCol.pszText = szText;
lvCol.cchTextMax = sizeof(szText);
lvCol.iSubItem = nCol;
if ( GetColumn ( nCol, &lvCol ) )
{
return lvCol.pszText;
}
return _T("");
}
void CSortListCtrl::SetColumnText ( int nCol, CString csNewColText )
{
ASSERT ( nCol >= 0 && nCol < GetColumnCount() );
TCHAR szText[1024] = {0};
LV_COLUMN lvCol;
memset ( &lvCol, 0, sizeof(LV_COLUMN) );
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -