📄 listctrlex.cpp
字号:
* @author Mark Findlay
*/
CString CListCtrlEx::GetTrueItemText(int row, int col)const
{
// Get the header control
CHeaderCtrl* pHeader = (CHeaderCtrl*)GetDlgItem(0);
_ASSERTE(pHeader);
// get the current number of columns
int nCount = pHeader->GetItemCount();
// find the actual column requested. We will compare
// against hi.iOrder
for (int x=0; x< nCount; x++)
{
HD_ITEM hi = {0};
hi.mask = HDI_ORDER;
BOOL bRet = pHeader->GetItem(x,&hi);
_ASSERTE(bRet);
if (hi.iOrder == col)
{
// Found it, get the associated text
return GetItemText(row,x);
}
}
_ASSERTE(FALSE);
return "We better never fall through to here!";
}
/**
* @author Mark Findlay
*/
int CListCtrlEx::GetTrueColumnWidth(int nCurrentPosition)const
{
CHeaderCtrl* pHeader = (CHeaderCtrl*)GetDlgItem(0);
_ASSERTE(pHeader);
int nCount = pHeader->GetItemCount();
for (int x=0; x< nCount; x++)
{
HD_ITEM hi = {0};
hi.mask = HDI_WIDTH | HDI_ORDER;
BOOL bRet = pHeader->GetItem(x,&hi);
_ASSERTE(bRet);
if (hi.iOrder == nCurrentPosition)
return hi.cxy;
}
_ASSERTE(FALSE);
return 0; // We would never fall through to here!
}
/**
* @param point [in] point in client coordinates
* @param iRow [out] row containing the point
* @param iColunm [out] column containing the point
*
* @author Matthew Bells
*/
BOOL CListCtrlEx::HitTestRowCol(CPoint& point, int& iRow, int& iColumn)const
{
// Make sure that the ListView is in LVS_REPORT
if((GetStyle() & LVS_TYPEMASK) != LVS_REPORT)
return FALSE;
int iPosX = point.x;
iRow = HitTest(point);
// Get the number of columns
CHeaderCtrl* pHeader = (CHeaderCtrl*)GetDlgItem(0);
int iColumnCount = pHeader->GetItemCount();
for(iColumn = 0; iColumn < iColumnCount; ++iColumn)
{
iPosX -= GetTrueColumnWidth(iColumn);
if(iPosX < 0)
break;
}
if(iColumn == iColumnCount)
iColumn = -1;
return (iRow != -1 && iColumn != -1);
}
void CListCtrlEx::RepaintSelectedItems()
{
CRect rcItem;
CRect rcLabel;
// Invalidate focused item so it can repaint
int iItem = GetNextItem(-1, LVNI_FOCUSED);
if(iItem != -1)
{
GetItemRect(iItem, rcItem, LVIR_BOUNDS);
GetItemRect(iItem, rcLabel, LVIR_LABEL);
rcItem.left = rcLabel.left;
InvalidateRect(rcItem, FALSE);
}
// Invalidate selected items depending on LVS_SHOWSELALWAYS
if(!(GetStyle() & LVS_SHOWSELALWAYS))
{
for(iItem = GetNextItem(-1, LVNI_SELECTED);
iItem != -1; iItem = GetNextItem(iItem, LVNI_SELECTED))
{
GetItemRect(iItem, rcItem, LVIR_BOUNDS);
GetItemRect(iItem, rcLabel, LVIR_LABEL);
rcItem.left = rcLabel.left;
InvalidateRect(rcItem, FALSE);
}
}
UpdateWindow();
}
/////////////////////////////////////////////////////////////////////////////
// CListCtrlEx message handlers
void CListCtrlEx::OnDestroy()
{
//m_titletip.DestroyWindow();
CListCtrl::OnDestroy();
}
void CListCtrlEx::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags)
{
inherited::OnChar(nChar, nRepCnt, nFlags);
//HideTitleTip();
SendSelChangedNotification();
}
void CListCtrlEx::OnKillFocus(CWnd* pNewWnd)
{
CListCtrl::OnKillFocus(pNewWnd);
// This should be hidden no matter if another control is getting focus
// or the edit box.
//HideTitleTip();
// this really still has focus if one of its chilren (ie. the edit box)
// has focus
if(pNewWnd != NULL && pNewWnd->GetParent() == this)
return;
// repaint items that should change appearance
if(m_bFullRowSel && (GetStyle() & LVS_TYPEMASK) == LVS_REPORT)
RepaintSelectedItems();
}
void CListCtrlEx::OnLButtonDown(UINT nFlags, CPoint point)
{
int iTest = GetKeyState(VK_LMENU);
// Shortcut to editing.
if((GetKeyState(VK_LMENU) & 0x8000) || (GetKeyState(VK_RMENU) & 0x8000))
{
int iRow;
int iColumn;
if(HitTestRowCol(point, iRow, iColumn))
{
SetFocus();
PostMessage(LVM_EDITLABEL, (WPARAM)iRow, 0);
}
}
else
{
inherited::OnLButtonDown(nFlags, point);
//ShowTitleTip(point); // Make sure TitleTip changes if needed.
SendSelChangedNotification();
}
}
void CListCtrlEx::OnMouseMove(UINT nFlags, CPoint point)
{
CListCtrl::OnMouseMove(nFlags, point);
}
/*
* When the regular list view control repaints an item, it repaints only the
* area occupied by defined columns. If the last column does not extend to the
* end of the client area, then the space to the right of the last column is
* not repainted. If we are highlighting the full row then this area also needs
* to be invalidated so that the code in DrawItem() can add or remove the
* highlighting from this area.
*/
void CListCtrlEx::OnPaint()
{
// in full row select mode, we need to extend the clipping region
// so we can paint a selection all the way to the right
if (m_bClientWidthSel &&
(GetStyle() & LVS_TYPEMASK) == LVS_REPORT && GetFullRowSel())
{
m_clrText = ::GetSysColor(COLOR_WINDOWTEXT);
m_clrTextBk = ::GetSysColor(COLOR_WINDOW);
m_clrBkgnd = ::GetSysColor(COLOR_WINDOW);
CRect rcAllLabels;
GetItemRect(0, rcAllLabels, LVIR_BOUNDS);
CRect rcClient;
GetClientRect(&rcClient);
if(rcAllLabels.right < rcClient.right)
{
// need to call BeginPaint (in CPaintDC c-tor)
// to get correct clipping rect
CPaintDC dc(this);
CRect rcClip;
dc.GetClipBox(rcClip);
rcClip.left = min(rcAllLabels.right-1, rcClip.left);
rcClip.right = rcClient.right;
InvalidateRect(rcClip, FALSE);
// EndPaint will be called in CPaintDC d-tor
}
}
CListCtrl::OnPaint();
}
LRESULT CListCtrlEx::OnSetBkColor(WPARAM wParam, LPARAM lParam)
{
m_clrBkgnd = (COLORREF)lParam;
return(Default());
}
/*
* This is another step to mimic the default behaviour of the list view
* control. When the control loses focus, the focus rectangle around the
* selected (focus) item has to be removed. When the control gets back
* focus, then the focus rectangle has to be redrawn. Both these handlers
* call the RepaintSelectedItems() helper function.
*/
void CListCtrlEx::OnSetFocus(CWnd* pOldWnd)
{
CListCtrl::OnSetFocus(pOldWnd);
// check if we are getting focus from label edit box
// if(pOldWnd!=NULL && pOldWnd->GetParent()==this)
// return;
// repaint items that should change appearance
if(m_bFullRowSel && (GetStyle() & LVS_TYPEMASK)==LVS_REPORT)
RepaintSelectedItems();
}
LRESULT CListCtrlEx::OnSetTextBkColor(WPARAM wParam, LPARAM lParam)
{
m_clrTextBk = (COLORREF)lParam;
return(Default());
}
LRESULT CListCtrlEx::OnSetTextColor(WPARAM wParam, LPARAM lParam)
{
m_clrText = (COLORREF)lParam;
return(Default());
}
void CListCtrlEx::PreSubclassWindow()
{
CListCtrl::PreSubclassWindow();
m_bFullRowSel = TRUE;
// m_titletip.Create(this);
// m_titletip.SetBackground(CBrush(GetBkColor()));
}
void CListCtrlEx::SendSelChangedNotification()
{
NMHDR nmh;
nmh.hwndFrom = *this;
nmh.idFrom = GetDlgCtrlID();
nmh.code = LVNU_SELCHANGED;
GetParent()->SendMessage(WM_NOTIFY, GetDlgCtrlID(), (LPARAM)&nmh);
}
// SortTextItems - Sort the list based on column text
// Returns - Returns true for success
// nCol - column that contains the text to be sorted
// bAscending - indicate sort order
// low - row to start scanning from - default row is 0
// high - row to end scan. -1 indicates last row
BOOL CListCtrlEx::SortTextItems( int nCol, BOOL bAscending,
int low /*= 0*/, int high /*= -1*/ )
{
if( nCol >= ((CHeaderCtrl*)GetDlgItem(0))->GetItemCount() )
return FALSE;
if( high == -1 ) high = GetItemCount() - 1;
int lo = low;
int hi = high;
CString midItem;
if( hi <= lo ) return FALSE;
midItem = GetItemText( (lo+hi)/2, nCol );
// loop through the list until indices cross
while( lo <= hi )
{
// rowText will hold all column text for one row
CStringArray rowText;
// find the first element that is greater than or equal to
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -