📄 mylistctrl.cpp
字号:
if( (GetWindowLong(m_hWnd, GWL_STYLE) & LVS_TYPEMASK) != LVS_REPORT )
{
colwidth = 100000; // don't count colwidth.
}
else
{
// If REPORT, check inside column width.
colwidth = 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;
}
//////////////////////////////////////////////////
// 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 CMyListCtrl::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;
CHeaderCtrl* pHDCtrl = 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 >= GetItemCount() )
return FALSE;
HeaderItem.mask = HDI_TEXT;
HeaderItem.pszText = lpBuffer;
HeaderItem.cchTextMax = 256;
if( pHDCtrl )
{
pHDCtrl->GetItem(col,&HeaderItem);
// Use Item's name as the tool tip. Change this for something different.
// Like use its file size, etc.
strTipText.Format("%s:",HeaderItem.pszText);
}
else
{
strTipText = "";
}
strItemText = 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
}
///////////////////////////////////////////////
//
inline
void CMyListCtrl::AddColumn(LPCTSTR str, int col)
{
VERIFY(-1 < InsertColumn(col, (LPTSTR) str, LVCFMT_LEFT,
GetStringWidth((LPTSTR) str) + 12, col));
}
/*
* nStringID: The ID of the String stored in the String Table
* strPre: The prefix of the Column header
*/
void CMyListCtrl::ExpandColumns(UINT nStringID, CString& strPre,int starcount)
{
CString strHeadings;
VERIFY(strHeadings.LoadString(nStringID));
int nPos;
int cols;
CHeaderCtrl* pHeader = (CHeaderCtrl*) GetDlgItem(0);
cols = pHeader->GetItemCount();
//加入到列表
if(strPre!="")
{
//记录到CArray中
m_MultiHeadArray.SetItem(cols,starcount,strPre);
strPre=strPre+"@@";
}
else
strPre="";
while ((nPos = strHeadings.Find(_T(","))) != -1)
{
CString strItem;
strItem = strPre+strHeadings.Left(nPos);
AddColumn(strItem, cols++);
strItem = strHeadings.Mid(nPos + 1);
strHeadings = strItem;
}
AddColumn( strPre+strHeadings, cols);
}
//lpzsItems's Format like this:"MS 3500$123*234*345*456"
//根据*的多少来判断所对应的类型的标题头的格式
int CMyListCtrl::InsertItems(int nItem, CString lpszItems,UINT nStringID)
{
CString strNeType=lpszItems.Left(lpszItems.Find("$"));
CString strDatas=lpszItems.Right(lpszItems.GetLength()-lpszItems.Find("$")-1);
int starcount = 0;
int pos = 0;
int nCol;
while(pos < lpszItems.GetLength())
if (lpszItems[pos++] == '*')
starcount ++;
int nIndex=GetMultiHeadIndex(strNeType);
if(nIndex==-1)
{
ExpandColumns(nStringID, strNeType,starcount+1);
InsertItems(nItem,lpszItems,nStringID);
}
else
{
nCol=m_MultiHeadArray[nIndex].iStartCol;
int nPos;
while ((nPos = strDatas.Find(_T("*"))) != -1)
{
CString strItem;
strItem = strDatas.Left(nPos);
UpdateCell(nItem,nCol++,strItem);
strItem = strDatas.Mid(nPos + 1);
strDatas = strItem;
}
UpdateCell(nItem,nCol,strDatas);
}
return -1;
}
void
CMyListCtrl::UpdateCell(int row, int col, LPCTSTR str, int icon)
{
UINT mask = 0;
if(0 != str)
mask |= LVIF_TEXT;
if(-1 != icon)
mask |= LVIF_IMAGE;
if(::IsWindow(m_hWnd))
{
SetItem(row, col, mask, (LPTSTR) str, icon, 0, 0, 0);
}
}
int CMyListCtrl::GetMultiHeadIndex(CString & strName)
{
int nUpper=m_MultiHeadArray.GetUpperBound();
for (int i=0 ; i <= nUpper; i++)
{
if(m_MultiHeadArray[i].strName == strName)
{
return i;
}
}
return -1;
}
void CMyListCtrl::InitializeClear()
{
while(DeleteColumn(0));
m_MultiHeadArray.RemoveAll();
DeleteAllItems();
}
int CMyListCtrl::CMultiHeadArray::SetItem(int iStartCol,
int iColCount,CString strName)
{
for (int i = 0; i <= GetUpperBound() && (*this)[i].strName != strName; i ++);
if (i > GetUpperBound()) //insert a new item.
{
CMultiHeadIndex item;
item.iStartCol=iStartCol;
item.iColCount=iColCount;
item.strName=strName;
Add(item);
}
return i;
}
BOOL CMyListCtrl::OnNotify(WPARAM wParam, LPARAM lParam, LRESULT* pResult)
{
HD_NOTIFY *pHDN = (HD_NOTIFY*)lParam;
if((pHDN->hdr.code == HDN_ITEMCHANGINGW || pHDN->hdr.code == HDN_ITEMCHANGINGA)
&& (pHDN->pitem->cxy < m_nMinColumnWidth || pHDN->pitem->cxy > m_nMaxColumnWidth))
{
*pResult = TRUE; // disable change
return TRUE; // Processed message
}
return CListCtrl::OnNotify(wParam, lParam, pResult);
}
// [ 2007.04.08
CEdit* CMyListCtrl::EditItem(int nItem, int nSubItem)
{
CRect rect;
int offset = 0;
if(!EnsureVisible(nItem, TRUE))
{
return NULL;
}
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(offset + rect.left,0);
Scroll(size);
rect.left -= size.cx;
}
rect.left += offset;
rect.right = rect.left + GetColumnWidth(nSubItem);
if(rect.right > rcClient.right)
rect.right = rcClient.right;
// 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;
CEdit *pEdit = new CEditItem(nItem, nSubItem, GetItemText(nItem, nSubItem));
#define IDC_EDITCTRL 0x1234
pEdit->Create(dwStyle, rect, this, IDC_EDITCTRL);
// pEdit->ModifyStyleEx(0,WS_EX_CLIENTEDGE);
//funny thing happend here, uncomment this,
//and then edit an item,
//enter a long text so that the ES_AUTOHSCROLL comes to rescue
//yes that's look funny, ???.
return pEdit;
}
CComboBox * CMyListCtrl::ComboItem(int nItem, int nSubItem)
{
#define IDC_COMBOBOXINLISTVIEW 0x1235
CString strFind = GetItemText(nItem, nSubItem);
//basic code start
CRect rect;
int offset = 0;
// Make sure that the item is visible
if( !EnsureVisible(nItem, TRUE))
return NULL;
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;
Scroll(size);
rect.left -= size.cx;
}
rect.left += offset;
rect.right = rect.left + GetColumnWidth(nSubItem);
if(rect.right > rcClient.right)
rect.right = rcClient.right;
//basic code end
rect.bottom += 30 * rect.Height();//dropdown area
DWORD dwStyle = WS_CHILD | WS_VISIBLE | WS_VSCROLL | WS_HSCROLL|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;
}
void CMyListCtrl::OnEndlabeledit(NMHDR* pNMHDR, LRESULT* pResult)
{
LV_DISPINFO *plvDispInfo = (LV_DISPINFO*)pNMHDR;
LV_ITEM *plvItem = &plvDispInfo->item;
if( plvItem->iItem != -1 && // valid item
plvItem->pszText ) // valid text
{
SetItemText( plvItem->iItem, plvItem->iSubItem, plvItem->pszText);
// this will invoke an ItemChanged handler in parent
if ( plvItem->iSubItem != 0 )
{
char szText[0x10+1];
GetItemText( plvItem->iItem, 0, szText, 0x10);
SetItemText( plvItem->iItem, 0, szText);
}
}
*pResult = 0;
}
void CMyListCtrl::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);
else if ( pNMListView->iSubItem >= 0 && m_nColumnCtrl[pNMListView->iSubItem] == eEdit )
{
if( m_bCanEdit[pNMListView->iSubItem] )
{
if( m_nDisableStartRow >= 0 &&
(pNMListView->iItem < m_nDisableStartRow || pNMListView->iItem > m_nDisableEndRow ) )
EditItem (pNMListView->iItem, pNMListView->iSubItem);
}
}
*pResult = 0;
}
void CMyListCtrl::OnKeydown(NMHDR* pNMHDR, LRESULT* pResult)
{
LV_KEYDOWN* pLVKeyDow = (LV_KEYDOWN*)pNMHDR;
switch(pLVKeyDow->wVKey)
{
case VK_DELETE:
{
int nItem = GetSelectionMark();
if(nItem!=-1) // valid item
{
DeleteItem( nItem );
}
} break;
default :break;
}
*pResult = 0;
}
// 2007.04.08]
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -