📄 listvwex.cpp
字号:
if( !m_bSortFirstCol )
nStart = 1;
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] = ListCtrl.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
ListCtrl.GetItem(&lvItem1);
ListCtrl.GetItem(&lvItem2);
//set the text for the lo (left)
for(i = nStart; i < nMaxColumns; i++)
{
ListCtrl.SetItemText(nRow1, i, ListCtrl.GetItemText(nRow2, i));
}
lvItem2.iItem = nRow1;
ListCtrl.SetItem(&lvItem2);
for(i = nStart; i < nMaxColumns; i++)
{
ListCtrl.SetItemText(nRow2, i, rowText[i]);
}
lvItem1.iItem = nRow2;
ListCtrl.SetItem(&lvItem1);
}
return bOk;
}
//////////////////////////////////////////////////////////////////////
// ParseDateTime()
// Parameters: lpszDate - date time string
// Action: get date time from string
// Returns: COleDateTime
//////////////////////////////////////////////////////////////////////
COleDateTime CListVwEx::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:
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);
}
}
odtVal = COleDateTime(nYear,nMon,nDay,nHour,nMin,nSec);
return odtVal;
}
void CListVwEx::SetView(DWORD dwView)
{
ModifyStyle( LVS_TYPEMASK, dwView & LVS_TYPEMASK );
}
//////////////////////////////////////////////////
// OnToolTipText() //
// Modify this function to change the text //
// displayed in the Tool Tip. //
// Currently, it uses GetItemText() to just //
// show the item's name. But you should change //
// it to show other info like file size, etc. //
//////////////////////////////////////////////////
BOOL CListVwEx::OnToolTipText( UINT id, NMHDR * pNMHDR, LRESULT * pResult )
{
// need to handle both ANSI and UNICODE versions of the message
TOOLTIPTEXTA* pTTTA = (TOOLTIPTEXTA*)pNMHDR;
TOOLTIPTEXTW* pTTTW = (TOOLTIPTEXTW*)pNMHDR;
CString strTipText, strItemText;
UINT nID = pNMHDR->idFrom;
CListCtrl& ListCtrl = GetListCtrl();
CHeaderCtrl* pHDCtrl = ListCtrl.GetHeaderCtrl();
HDITEM HeaderItem;
TCHAR lpBuffer[256];
if( nID == 0 ) // Notification in NT from automatically
return FALSE; // created tooltip
int row = ((nID-1) >> 10) & 0x3fffff ;
int col = (nID-1) & 0x3ff;
if( row >= ListCtrl.GetItemCount() )
return FALSE;
if( col >= 10 )
return FALSE;
HeaderItem.mask = HDI_TEXT;
HeaderItem.pszText = lpBuffer;
HeaderItem.cchTextMax = 256;
pHDCtrl->GetItem(col,&HeaderItem);
// Use Item's name as the tool tip. Change this for something different.
// Like use its file size, etc.
BOOL bSum = false;
for(int i = 0; i< m_nSumNum; i++)
{
if( col == m_nSumPos[i] )
{
bSum = true;
break;
}
}
if( ListCtrl.GetSelectedCount() > 1 && bSum )
{
strTipText.Format("合计%s:",HeaderItem.pszText);
POSITION Pos = ListCtrl.GetFirstSelectedItemPosition();
double fValue = 0;
int nH = 0, nM = 0, nS = 0;
BOOL bTime = false;
while(Pos)
{
int nItem = ListCtrl.GetNextSelectedItem(Pos);
strItemText = ListCtrl.GetItemText( nItem, col );
strItemText.TrimLeft();
int nIndex = strItemText.Find(":");
if( nIndex < 0 )
fValue += atof(strItemText);
else
{
bTime = true;
nH += atoi(strItemText.Left(nIndex)) ;
nM += atoi(strItemText.Mid(nIndex+1,2)) ;
nS += atoi(strItemText.Right(2)) ;
}
}
if( bTime )
{
nM += nS/60;
nS = nS%60;
nH += nM/60;
nM = nM%60;
strItemText.Format("%d:%02d:%02d",nH,nM,nS);
}
else
strItemText.Format("%10.2f",fValue);
strItemText.TrimLeft();
strTipText += strItemText;
}
else
{
strTipText.Format("%s:",HeaderItem.pszText);
strItemText = ListCtrl.GetItemText( row, col );
strItemText.TrimLeft();
strTipText += strItemText;
}
#ifndef _UNICODE
if (pNMHDR->code == TTN_NEEDTEXTA)
lstrcpyn(pTTTA->szText, strTipText, 80);
else
_mbstowcsz(pTTTW->szText, strTipText, 80);
#else
if (pNMHDR->code == TTN_NEEDTEXTA)
_wcstombsz(pTTTA->szText, strTipText, 80);
else
lstrcpyn(pTTTW->szText, strTipText, 80);
#endif
*pResult = 0;
return TRUE; // message was handled
}
////////////////////////////////////////////
// Tool Tip Text Functions //
// Modified algorithm from codeguru.com //
// by Kory Becker, kory@dummysoftware.com //
////////////////////////////////////////////
int CListVwEx::OnToolHitTest(CPoint point, TOOLINFO * pTI) const
{
int row, col;
RECT cellrect;
row = CellRectFromPoint(point, &cellrect, &col );
if ( row == -1 )
{
return -1;
}
pTI->hwnd = m_hWnd;
pTI->uId = (UINT)((row<<10)+(col&0x3ff)+1);
pTI->lpszText = LPSTR_TEXTCALLBACK;
pTI->rect = cellrect;
return pTI->uId;
}
// CellRectFromPoint - Determine the row, col and bounding rect of a cell
// Returns - row index on success, -1 otherwise
// point - point to be tested.
// cellrect - to hold the bounding rect
// col - to hold the column index
int CListVwEx::CellRectFromPoint(CPoint & point, RECT * cellrect, int * col) const
{
int colnum;
CHeaderCtrl* pHeader;
int nColumnCount;
CListCtrl& ListCtrl = GetListCtrl();
// If not REPORT style for the list, then use 1 column
// Otherwise, find the column in the report style view.
if( (GetWindowLong(m_hWnd, GWL_STYLE) & LVS_TYPEMASK) != LVS_REPORT )
{
// Window is not Report style, so no headers. Deal with it!
nColumnCount = 1;
}
else
{
// Get the number of columns in Report style.
pHeader = (CHeaderCtrl*)GetDlgItem(0);
nColumnCount = pHeader->GetItemCount();
}
// Get the top and bottom row visible
int row = ListCtrl.GetTopIndex();
int bottom = row + ListCtrl.GetCountPerPage();
if( bottom > ListCtrl.GetItemCount() )
bottom = ListCtrl.GetItemCount();
// Loop through the visible rows
for( ;row <=bottom;row++)
{
// Get bounding rect of item and check whether point falls in it.
CRect rect, rectLabel;
if( (GetWindowLong(m_hWnd, GWL_STYLE) & LVS_TYPEMASK) != LVS_REPORT )
{
// If not Report style, get label / icon boundaries.
ListCtrl.GetItemRect( row, &rect, LVIR_ICON );
ListCtrl.GetItemRect( row, &rectLabel, LVIR_LABEL );
}
else
{
// If Report style, get bounds of cell.
ListCtrl.GetItemRect( row, &rect, LVIR_BOUNDS );
}
if( rect.PtInRect(point) ||
rectLabel.PtInRect(point))
{
bool InLabel = false;
// Store which part user clicked on if in ICON view,
// clicked the Label or the Icon?
if (rect.PtInRect(point))
{
InLabel = false;
}
else if (rectLabel.PtInRect(point))
{
InLabel = true;
}
// Now find the column
for( colnum = 0; colnum < nColumnCount; colnum++ )
{
// Getting column width
int colwidth;
if( (GetWindowLong(m_hWnd, GWL_STYLE) & LVS_TYPEMASK) != LVS_REPORT )
{
colwidth = 100000; // don't count colwidth.
}
else
{
// If REPORT, check inside column width.
colwidth = ListCtrl.GetColumnWidth(colnum);
}
if( (point.x >= rect.left
&& point.x <= (rect.left + colwidth )) ||
(point.x >= rectLabel.left
&& point.x <= (rectLabel.left + colwidth )))
{
RECT rectClient;
GetClientRect( &rectClient );
if( col ) *col = colnum;
rect.right = rect.left + colwidth;
rectLabel.right = rectLabel.left + colwidth;
// Make sure that the right extent does not exceed
// the client area
if ( rect.right > rectClient.right )
rect.right = rectClient.right;
if ( rectLabel.right > rectClient.right )
rectLabel.right = rectClient.right;
if (!InLabel)
{
*cellrect = rect;
}
else
{
*cellrect = rectLabel;
}
return row;
}
rect.left += colwidth;
rectLabel.left += colwidth;
}
}
}
return -1;
}
///////////////////////////////////////////////////////////////////////////////
void CListVwEx::OnClick(NMHDR* pNMHDR, LRESULT* pResult)
{
// TODO: Add your control notification handler code here
if( GetFocus() != this)
SetFocus();
NM_LISTVIEW* pNMListView = (NM_LISTVIEW*)pNMHDR;
if ( pNMListView->iSubItem >= 0 && m_nColumnCtrl[pNMListView->iSubItem] == eCombo )
ComboItem(pNMListView->iItem, pNMListView->iSubItem);
*pResult = 0;
}
void CListVwEx::OnKeydown(NMHDR* pNMHDR, LRESULT* pResult)
{
CListCtrl& ListCtrl = GetListCtrl();
LV_KEYDOWN* pLVKeyDow = (LV_KEYDOWN*)pNMHDR;
switch(pLVKeyDow->wVKey)
{
case VK_DELETE:
{
int nItem = ListCtrl.GetSelectionMark();
if(nItem!=-1) // valid item
{
ListCtrl.DeleteItem( nItem );
}
} break;
default :break;
}
*pResult = 0;
}
CComboBox * CListVwEx::ComboItem(int nItem, int nSubItem)
{
#define IDC_COMBOBOXINLISTVIEW 0x1235
CListCtrl& ListCtrl = GetListCtrl();
CString strFind = ListCtrl.GetItemText(nItem, nSubItem);
//basic code start
CRect rect;
int offset = 0;
// Make sure that the item is visible
if( !ListCtrl.EnsureVisible(nItem, TRUE))
return NULL;
ListCtrl.GetSubItemRect(nItem, nSubItem, LVIR_BOUNDS, rect);
// Now scroll if we need to expose the column
CRect rcClient;
GetClientRect(rcClient);
if( offset + rect.left < 0 || offset + rect.left > rcClient.right )
{
CSize size;
size.cx = offset + rect.left;
size.cy = 0;
ListCtrl.Scroll(size);
rect.left -= size.cx;
}
rect.left += offset;
rect.right = rect.left + ListCtrl.GetColumnWidth(nSubItem);
if(rect.right > rcClient.right)
rect.right = rcClient.right;
//basic code end
rect.bottom += 100 * rect.Height();//dropdown area
DWORD dwStyle = WS_CHILD | WS_VISIBLE | WS_VSCROLL | CBS_DROPDOWNLIST | CBS_DISABLENOSCROLL;
CComboBox *pList = new CComboItem(nItem, nSubItem, &m_strList[nSubItem]);
pList->Create(dwStyle, rect, this, IDC_COMBOBOXINLISTVIEW);
pList->ModifyStyleEx(0,WS_EX_CLIENTEDGE);//can we tell at all
pList->ShowDropDown();
pList->SelectString(-1, strFind.GetBuffer(1));
// The returned pointer should not be saved
return pList;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -