📄 sortlistctrl.cpp
字号:
lvCol.mask = LVCF_TEXT;
lvCol.pszText = szText;
lvCol.cchTextMax = sizeof(szText);
lvCol.iSubItem = nCol;
lstrcpyn ( szText, csNewColText, LENGTH(szText) );
SetColumn ( nCol, &lvCol );
}
//
// 使选中的项全部显示出来,如果有部分被遮住了,那么就调整
// 滚动条使它显示出来。
//
void CSortListCtrl::GetItemExposeRect ( int iItem, int nSubItem, CRect &rect )
{
GetSubItemRect ( iItem, nSubItem, LVIR_BOUNDS, rect );
// Now scroll if we need to expose the column
CRect rcClient;
GetClientRect(rcClient);
if( rect.left < 0 || rect.left > rcClient.right )
{
CSize size(rect.left,0);
Scroll(size);
rect.left -= size.cx;
}
GetSubItemRect ( iItem, nSubItem, LVIR_LABEL, rect );
if(rect.right > rcClient.right)
rect.right = rcClient.right;
}
void CSortListCtrl::ComboItem(int iItem, int nSubItem, CStringArray &StrAry)
{
m_pCombo = new CComboBoxForListCtrl ( iItem, nSubItem, &StrAry, &m_pCombo );
if ( !m_pCombo ) return;
CString strFind = GetItemText ( iItem, nSubItem );
// Make sure that the item is visible
if( !EnsureVisible ( iItem, TRUE ) )
{
delete m_pCombo;
return;
}
CRect rect;
GetItemExposeRect ( iItem, nSubItem, rect );
//basic code end
rect.bottom += 10 * rect.Height(); // dropdown area
DWORD dwStyle = WS_CHILD | WS_VISIBLE | WS_VSCROLL | CBS_DROPDOWNLIST ;
m_pCombo->Create ( dwStyle, rect, this, SORTLISTCTRL_COMBO_ID );
m_pCombo->ModifyStyleEx ( 0, WS_EX_CLIENTEDGE ); // can we tell at all
m_pCombo->ShowDropDown();
m_pCombo->SelectString( -1, strFind.GetBuffer(1) );
}
void CSortListCtrl::EditItem(int iItem, int nSubItem)
{
CRect rect;
if(!EnsureVisible(iItem, TRUE)) return;
GetItemExposeRect ( iItem, nSubItem, rect );
// Get Column alignment
LV_COLUMN lvcol;
lvcol.mask = LVCF_FMT;
GetColumn(nSubItem, &lvcol);
DWORD dwStyle;
if((lvcol.fmt & LVCFMT_JUSTIFYMASK) == LVCFMT_LEFT)
dwStyle = ES_LEFT;
else if((lvcol.fmt & LVCFMT_JUSTIFYMASK) == LVCFMT_RIGHT)
dwStyle = ES_RIGHT;
else
dwStyle = ES_CENTER;
dwStyle |=WS_BORDER|WS_CHILD | WS_VISIBLE | ES_AUTOHSCROLL;
m_pEdit = new CEditForListCtrl(iItem, nSubItem, GetItemText(iItem, nSubItem), &m_pEdit );
rect.InflateRect ( 0, 2 );
m_pEdit->Create(dwStyle, rect, this, SORTLISTCTRL_EDIT_ID);
}
void CSortListCtrl::KillAllSubCtrlFocus()
{
if ( m_pEdit && ::IsWindow ( m_pEdit->m_hWnd ) )
m_pEdit->SendMessage ( WM_KILLFOCUS, (WPARAM)m_hWnd );
if ( m_pCombo && ::IsWindow ( m_pCombo->m_hWnd ) )
m_pCombo->SendMessage ( WM_KILLFOCUS, (WPARAM)m_hWnd );
}
void CSortListCtrl::OnHScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar)
{
KillAllSubCtrlFocus ();
CListCtrl::OnHScroll(nSBCode, nPos, pScrollBar);
}
void CSortListCtrl::OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar)
{
KillAllSubCtrlFocus ();
CListCtrl::OnVScroll(nSBCode, nPos, pScrollBar);
}
int CSortListCtrl::GetItemInt(int iItem, int nSubItem)
{
CString csText = GetItemText ( iItem, nSubItem );
return atoi ( GetMultiByteChar(csText) );
}
int CSortListCtrl::FindItemBySubItem(int nSubItem, WPARAM lpFindVar, BOOL bInteger)
{
int nCount = GetItemCount();
for ( int i=0; i<nCount; i++ )
{
CString csText = GetItemText ( i, nSubItem );
int nIntValue = 0;
if ( bInteger )
{
nIntValue = atoi ( GetMultiByteChar(csText) );
if ( nIntValue == (int)lpFindVar )
return i;
}
else
{
if ( csText == (LPCTSTR)lpFindVar )
return i;
}
}
return -1;
}
RECT CSortListCtrl::GetItemRect( UINT nCode )
{
CRect rc(0,0,0,0);
if ( GetColumnCount() < 1 ) return rc;
int nCount = GetItemCount();
if ( nCount < 1 )
{
CStringArray StrAry;
for ( int i=0; i<GetColumnCount(); i++ )
StrAry.Add ( _T(" ") );
InsertItem ( 0, StrAry, -1 );
StrAry.RemoveAll();
}
CListCtrl::GetItemRect ( 0, &rc, nCode );
if ( nCount < 1 )
{
DeleteItem ( 0 );
}
return rc;
}
//
// 设置禁止编辑的项,输入时以 -1 结尾
//
void CSortListCtrl::SetDisableEditItem(int iItem, ...)
{
CSortListCtrl::t_ItemAppData ItemAppData;
int nTemp = iItem;
va_list va;
va_start( va, iItem ); /* Initialize variable arguments. */
while ( nTemp >= 0 )
{
// do sth.
GetItemAppData ( nTemp, ItemAppData );
ItemAppData.bDisableEditItem = TRUE;
SetItemAppData ( nTemp, ItemAppData );
nTemp = va_arg( va, int);
}
va_end( va );
}
BOOL CSortListCtrl::CanEdit(int iItem)
{
ASSERT ( iItem >= 0 && iItem < GetItemCount() );
// 是禁止编辑的项
CSortListCtrl::t_ItemAppData *pItemAppData = GetItemAppData ( iItem );
if ( pItemAppData && pItemAppData->bDisableEditItem )
{
return FALSE;
}
return TRUE;
}
int CSortListCtrl::OnToolHitTest(CPoint point, TOOLINFO * pTI) const
{
//See if the point falls onto a list item
//UINT nFlags = 0;
LVHITTESTINFO lvhitTestInfo;
lvhitTestInfo.pt = point;
int iItem = ListView_SubItemHitTest(
m_hWnd,
&lvhitTestInfo);
int nSubItem = lvhitTestInfo.iSubItem;
UINT nFlags = lvhitTestInfo.flags;
//nFlags is 0 if the SubItemHitTest fails
//Therefore, 0 & <anything> will equal FALSE
if (nFlags & m_wHitMask)
{
//If it did fall on a list item,
//and it was also hit one of the
//item specific sub-areas we wish to show tool tips for
//Get the client (area occupied by this control
RECT rcClient;
GetClientRect( &rcClient );
//Fill in the TOOLINFO structure
pTI->hwnd = m_hWnd;
pTI->uId = (UINT) (iItem * MAX_COLUMN_COUNT + nSubItem);
pTI->lpszText = LPSTR_TEXTCALLBACK;
pTI->rect = rcClient;
return pTI->uId; //By returning a unique value per listItem,
//we ensure that when the mouse moves over another list item,
//the tooltip will change
}else{
//Otherwise, we aren't interested, so let the message propagate
return -1;
}
}
BOOL CSortListCtrl::OnToolTipText( UINT id, NMHDR * pNMHDR, LRESULT * pResult )
{
//Handle both ANSI and UNICODE versions of the message
TOOLTIPTEXTA* pTTTA = (TOOLTIPTEXTA*)pNMHDR;
TOOLTIPTEXTW* pTTTW = (TOOLTIPTEXTW*)pNMHDR;
//Ignore messages from the built in tooltip, we are processing them internally
if( (pNMHDR->idFrom == (UINT)m_hWnd) &&
( ((pNMHDR->code == TTN_NEEDTEXTA) && (pTTTA->uFlags & TTF_IDISHWND)) ||
((pNMHDR->code == TTN_NEEDTEXTW) && (pTTTW->uFlags & TTF_IDISHWND)) ) )
{
return FALSE;
}
*pResult = 0;
//Get the mouse position
const MSG* pMessage;
pMessage = GetCurrentMessage();
ASSERT ( pMessage );
CPoint pt;
pt = pMessage->pt; //Get the point from the message
ScreenToClient( &pt ); //Convert the point's coords to be relative to this control
//See if the point falls onto a list item
LVHITTESTINFO lvhitTestInfo;
lvhitTestInfo.pt = pt;
int iItem = SubItemHitTest ( &lvhitTestInfo );
int nSubItem = lvhitTestInfo.iSubItem;
if ( iItem < 0 || nSubItem < 0 ) return FALSE;
UINT nFlags = lvhitTestInfo.flags;
//nFlags is 0 if the SubItemHitTest fails
//Therefore, 0 & <anything> will equal FALSE
if( nFlags & m_wHitMask )
{
CString strTipText = GetItemToolTipText ( iItem );
if( strTipText.GetLength() > 0 )
{
//If there was a CString associated with the list item,
//copy it's text (up to 80 characters worth, limitation of the TOOLTIPTEXT structure)
//into the TOOLTIPTEXT structure's szText member
const int nMaxTipLen = 80;
//Deal with UNICODE
#ifndef _UNICODE
if (pNMHDR->code == TTN_NEEDTEXTA)
lstrcpyn(pTTTA->szText, strTipText, nMaxTipLen);
else
_mbstowcsz(pTTTW->szText, strTipText, nMaxTipLen);
#else
if (pNMHDR->code == TTN_NEEDTEXTA)
_wcstombsz(pTTTA->szText, strTipText, nMaxTipLen);
else
lstrcpyn(pTTTW->szText, strTipText, nMaxTipLen);
#endif
return FALSE; //We found a tool tip,
//tell the framework this message has been handled
////////////////////////////////////////////////////////////////////////////////
// ****** Special note *****
//
// Still don't understand why the function must return FALSE for CListCtrl
// so as not to cause flickering, as opposed to Nate Maynard's derivation
// from CTreeCtrl.
// I have experimented with disabling Tooltips for the control
// and found out that a "ghost" tooltip appears for a fraction of a second...
//
// I am completely at a loss...
// Seems to work, though...
//
////////////////////////////////////////////////////////////////////////////////
}
}
return FALSE; //We didn't handle the message,
//let the framework continue propagating the message
}
WORD CSortListCtrl::SetToolTipHitMask( WORD wHitMask )
{
WORD oldHitMask = m_wHitMask;
m_wHitMask = wHitMask;
return oldHitMask;
}
void CSortListCtrl::Serialize(CArchive &ar)
{
if ( !m_bSaveTypeMask ) return;
if ( ar.IsStoring() )
{
ar << m_dwInitTypeMask;
}
else
{
ar >> m_dwInitTypeMask;
}
}
void CSortListCtrl::ClearShowRecordView()
{
}
void CSortListCtrl::InsertItemSuccess(int nItem)
{
}
void CSortListCtrl::SyncSRWItem(int nStartItem)
{
}
void CSortListCtrl::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags)
{
// 按下了 Ctrl+A
if ( ( nChar == 'A' || nChar == 'a' ) && ::GetAsyncKeyState(VK_CONTROL) )
{
if ( !(GetWindowLong(GetSafeHwnd(),GWL_STYLE) & LVS_SINGLESEL) )
{
for ( int i=0; i<GetItemCount(); i++ )
{
hwSelectOneItem ( i );
}
}
}
CListCtrl::OnKeyDown(nChar, nRepCnt, nFlags);
}
void CSortListCtrl::hwSelectOneItem(int nItem, BOOL bSelected/*=TRUE*/)
{
ASSERT ( nItem>=0 && nItem<GetItemCount() );
RemarkListSelected ( this, nItem, bSelected );
}
BOOL CSortListCtrl::SetOrCreateImageList(CImageList *pImgListNor/*=NULL*/, CImageList *pImgListSma/*=NULL*/)
{
DeleteImageList ();
BOOL bImgListOK = ( (pImgListNor && pImgListNor->GetSafeHandle()) ||
( pImgListSma && pImgListSma->GetSafeHandle() ) );
if ( bImgListOK )
{
if ( pImgListNor && pImgListNor->GetSafeHandle() )
{
m_ImageListNor.Create ( pImgListNor );
if ( !( pImgListSma && pImgListSma->GetSafeHandle() ) )
{
m_ImageListSma.Create ( pImgListNor );
}
}
if ( pImgListSma && pImgListSma->GetSafeHandle() )
{
m_ImageListSma.Create ( pImgListSma );
if ( !( pImgListNor && pImgListNor->GetSafeHandle() ) )
{
m_ImageListNor.Create ( pImgListSma );
}
}
}
else
{
CreateImageList ( 32, m_ImageListNor );
CreateImageList ( 16, m_ImageListSma );
}
if ( m_ImageListNor.GetSafeHandle() )
CListCtrl::SetImageList(&m_ImageListNor, LVSIL_NORMAL);
if ( m_ImageListSma.GetSafeHandle() )
CListCtrl::SetImageList(&m_ImageListSma, LVSIL_SMALL);
return ( m_ImageListSma.GetSafeHandle () && m_ImageListSma.GetSafeHandle() );
}
void CSortListCtrl::DeleteImageList()
{
if ( m_ImageListNor.GetSafeHandle() )
{
for ( int i=0; i<m_ImageListNor.GetImageCount(); i++ )
{
HICON hIcon = m_ImageListNor.ExtractIcon (i);
if ( hIcon ) ::DestroyIcon ( hIcon );
}
m_ImageListNor.DeleteImageList ();
}
if ( m_ImageListSma.GetSafeHandle() )
{
for ( int i=0; i<m_ImageListSma.GetImageCount(); i++ )
{
HICON hIcon = m_ImageListSma.ExtractIcon (i);
if ( hIcon ) ::DestroyIcon ( hIcon );
}
m_ImageListSma.DeleteImageList ();
}
}
//
// 找一行纪录与 StrAry 完全相等的行
//
int CSortListCtrl::FindItem(CStringArray &StrAry)
{
if ( StrAry.GetSize() != GetColumnCount() )
return -1;
CString csText;
for ( int nItem=0; nItem<GetItemCount(); nItem++ )
{
BOOL bEqual = TRUE;
for ( int nSubItem=0; nSubItem<StrAry.GetSize(); nSubItem++ )
{
csText = GetItemText ( nItem, nSubItem );
if ( StrAry.GetAt(nSubItem) != csText )
{
bEqual = FALSE;
break;
}
}
if ( bEqual ) return nItem;
}
return -1;
}
//
// 从单元格中查找字符串等于 lpszText 的行和列
//
int CSortListCtrl::FindCell ( LPCTSTR lpszText, OUT int &nSubItem_Out,
BOOL bMatchEntire/*=TRUE*/ )
{
if ( !lpszText ) return -1;
CString csText;
for ( int nItem=0; nItem<GetItemCount(); nItem++ )
{
for ( int nSubItem=0; nSubItem<GetColumnCount(); nSubItem ++ )
{
csText = GetItemText ( nItem, nSubItem );
if (
( bMatchEntire && csText == lpszText )
||
( !bMatchEntire && csText.Find(lpszText)>=0 )
)
{
nSubItem_Out = nSubItem;
return nItem;
}
}
}
return -1;
}
//
// 找第 nSubItem 列纪录等于 lpszItemText 的行
//
int CSortListCtrl::FindItem( LPCTSTR lpszItemText, int nSubItem )
{
if ( !lpszItemText || nSubItem < 0 || nSubItem >= GetColumnCount() )
return -1;
CString csText;
for ( int nItem=0; nItem<GetItemCount(); nItem++ )
{
csText = GetItemText ( nItem, nSubItem );
if ( csText == lpszItemText )
return nItem;
}
return -1;
}
//
// 找附加数据相等的行
//
int CSortListCtrl::FindItem ( CUIntArray &UIntAry_Data )
{
if ( UIntAry_Data.GetSize() < 1 || UIntAry_Data.GetSize() >= MAX_ITEMDATA_COUNT )
return -1;
for ( int nItem=0; nItem<GetItemCount(); nItem++ )
{
BOOL bEqual = TRUE;
for ( int i=0; i<UIntAry_Data.GetSize(); i++ )
{
DWORD dwTempData = GetItemData ( nItem, i );
if ( dwTempData != UIntAry_Data.GetAt(i) )
{
bEqual = FALSE;
break;
}
}
if ( bEqual ) return nItem;
}
return -1;
}
void CSortListCtrl::CreateImageList(int nSize, CImageList &ImageList)
{
ASSERT ( !ImageList.GetSafeHandle() );
HIMAGELIST hList = ImageList_Create(nSize,nSize, ILC_COLOR16 |ILC_MASK , 8, 1);
ImageList.Attach ( hList );
}
void CSortListCtrl::CopyImageList ( CImageList &ImageList_Dst, CImageList &ImageList_Src )
{
for ( int i=0; i<ImageList_Src.GetImageCount(); i++ )
{
ImageList_Dst.Add ( ImageList_Src.ExtractIcon (i) );
}
}
void CSortListCtrl::SetCheckAll(BOOL fCheck/*=TRUE*/ )
{
for ( int i=0; i<GetItemCount(); i++ )
{
SetCheck ( i, fCheck );
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -