📄 listctrlex.cpp
字号:
// ListCtrlEx.cpp : implementation file
//
#include "stdafx.h"
#include "ListCtrlEx.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
CListCellEdit:: CListCellEdit(int nItem, int nSubItem, CString strInitText)
:m_bEscape (FALSE)
{
m_nItem = nItem;
m_nSubItem = nSubItem;
m_strInitText = strInitText;
}
CListCellEdit::~CListCellEdit()
{
}
BEGIN_MESSAGE_MAP(CListCellEdit, CEdit)
//{{AFX_MSG_MAP(CListCellEdit)
ON_WM_KILLFOCUS()
ON_WM_NCDESTROY()
ON_WM_CHAR()
ON_WM_CREATE()
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CListCellEdit message handlers
void CListCellEdit::OnKillFocus(CWnd* pNewWnd)
{
CEdit::OnKillFocus(pNewWnd);
// TODO: Add your message handler code here
SetListItemText();
DestroyWindow();
}
void CListCellEdit::OnNcDestroy()
{
CEdit::OnNcDestroy();
// TODO: Add your message handler code here
delete this;
}
BOOL CListCellEdit::PreTranslateMessage(MSG* pMsg)
{
// TODO: Add your specialized code here and/or call the base class
if( pMsg->message == WM_KEYDOWN )
{
if(pMsg->wParam == VK_RETURN
|| pMsg->wParam == VK_DELETE
|| pMsg->wParam == VK_ESCAPE
|| GetKeyState( VK_CONTROL)
)
{
::TranslateMessage(pMsg);
::DispatchMessage(pMsg);
return TRUE; // DO NOT process further
}
}
return CEdit::PreTranslateMessage(pMsg);
}
void CListCellEdit::OnChar(UINT nChar, UINT nRepCnt, UINT nFlags)
{
// TODO: Add your message handler code here and/or call default
if( nChar == VK_ESCAPE || nChar == VK_RETURN)
{
if( nChar == VK_ESCAPE )
m_bEscape = TRUE;
GetParent()->SetFocus();
return;
}
// Resize edit control if needed
// Get text extent
CString str;
GetWindowText( str );
CWindowDC dc(this);
CFont *pFont = GetParent()->GetFont();
CFont *pFontDC = dc.SelectObject( pFont );
CSize size = dc.GetTextExtent( str );
dc.SelectObject( pFontDC );
size.cx += 5; // add some extra buffer
// Get client rect
CRect rect, parentrect;
GetClientRect( &rect );
GetParent()->GetClientRect( &parentrect );
// Transform rect to parent coordinates
ClientToScreen( &rect );
GetParent()->ScreenToClient( &rect );
// Check whether control needs to be resized
// and whether there is space to grow
if( size.cx > rect.Width() )
{
if( size.cx + rect.left < parentrect.right )
rect.right = rect.left + size.cx;
else
rect.right = parentrect.right;
MoveWindow( &rect );
}
CEdit::OnChar(nChar, nRepCnt, nFlags);
}
int CListCellEdit::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if (CEdit::OnCreate(lpCreateStruct) == -1)
return -1;
// Set the proper font
CFont* font = GetParent()->GetFont();
SetFont(font);
SetWindowText( m_strInitText );
SetFocus();
SetSel( 0, -1 );
return 0;
}
void CListCellEdit::SetListItemText()
{
CString Text;
GetWindowText (Text);
// Send Notification to parent of ListView ctrl
LV_DISPINFO dispinfo;
dispinfo.hdr.hwndFrom = GetParent()->m_hWnd;
dispinfo.hdr.idFrom = GetDlgCtrlID();
dispinfo.hdr.code = LVN_ENDLABELEDIT;
dispinfo.item.mask = LVIF_TEXT;
dispinfo.item.iItem = m_nItem;
dispinfo.item.iSubItem = m_nSubItem;
dispinfo.item.pszText = m_bEscape ? NULL : LPTSTR ((LPCTSTR) Text);
dispinfo.item.cchTextMax = Text.GetLength();
GetParent()->GetParent()->SendMessage (WM_NOTIFY, GetParent()->GetDlgCtrlID(), (LPARAM) &dispinfo);
}
/////////////////////////////////////////////////////////////////////////////
// CListCtrlEx
CListCtrlEx::CListCtrlEx()
{
}
CListCtrlEx::~CListCtrlEx()
{
}
BEGIN_MESSAGE_MAP(CListCtrlEx, CListCtrl)
//{{AFX_MSG_MAP(CListCtrlEx)
ON_NOTIFY_REFLECT(NM_CUSTOMDRAW, OnCustomDraw)
ON_WM_LBUTTONDOWN()
ON_WM_VSCROLL()
ON_WM_HSCROLL()
ON_WM_SIZE()
ON_NOTIFY_REFLECT(LVN_ENDLABELEDIT, OnEndlabeledit)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
// CListCtrlEx message handlers
// OnCustomDraw
void CListCtrlEx::OnCustomDraw(NMHDR* pNMHDR, LRESULT* pResult)
{
NMLVCUSTOMDRAW* pLVCD = reinterpret_cast<NMLVCUSTOMDRAW*>(pNMHDR);
// Take the default processing unless we set this to something else below.
*pResult = CDRF_DODEFAULT;
// First thing - check the draw stage. If it's the control's prepaint
// stage, then tell Windows we want messages for every item.
if (pLVCD->nmcd.dwDrawStage == CDDS_PREPAINT)
{
*pResult = CDRF_NOTIFYITEMDRAW;
}
else if (pLVCD->nmcd.dwDrawStage == CDDS_ITEMPREPAINT)
{
// This is the notification message for an item. We'll request
// notifications before each subitem's prepaint stage.
*pResult = CDRF_NOTIFYSUBITEMDRAW;
}
else if (pLVCD->nmcd.dwDrawStage == (CDDS_ITEMPREPAINT | CDDS_SUBITEM))
{
// This is the prepaint stage for a subitem. Here's where we set the
// item's text and background colors. Our return value will tell
// Windows to draw the subitem itself, but it will use the new colors
// we set here.
int nItem = static_cast<int> (pLVCD->nmcd.dwItemSpec);
int nSubItem = pLVCD->iSubItem;
/*
if(nSubItem == 2) //颜色框
{
COLORREF clr = GetItemData(nItem);
CDC* pDC = CDC::FromHandle(pLVCD->nmcd.hdc);
CRect rect;
GetSubItemRect(nItem, nSubItem, LVIR_BOUNDS, rect);
rect.bottom -= 1;
rect.left += 1;
pDC->Rectangle(rect);
rect.DeflateRect(1,1);
pDC->FillSolidRect(&rect, clr);
*pResult = CDRF_SKIPDEFAULT; // We've painted everything.
}
*/
}
}
void CListCtrlEx::OnLButtonDown(UINT nFlags, CPoint point)
{
CListCtrl::OnLButtonDown(nFlags, point);
// TODO: Add your message handler code here and/or call default
int nItem;
int nSubItem;
if ((nItem = HitTestEx (point, nSubItem)) != -1)
{
if(nSubItem == 1) //地物名称
{
EditSubItem(nItem, nSubItem);
}
else if(nSubItem == 2) //颜色栏
{
EditSubItem(nItem, nSubItem);
/*
CColorDialog dlg;
if(dlg.DoModal() == IDOK)
{
COLORREF clr = dlg.GetColor();
SetItemData(nItem, clr);
}
*/
}
}
}
int CListCtrlEx::HitTestEx (CPoint& Point, int& nSubItem)
{
nSubItem = 0;
int ColumnNum = 0;
int Row = HitTest (Point, NULL);
// Make sure that the ListView is in LVS_REPORT
if ((GetWindowLong (m_hWnd, GWL_STYLE) & LVS_TYPEMASK) != LVS_REPORT)
return Row;
// Get the top and bottom row visible
Row = GetTopIndex();
int Bottom = Row + GetCountPerPage();
if (Bottom > GetItemCount())
Bottom = GetItemCount();
// Get the number of columns
CHeaderCtrl* pHeader = (CHeaderCtrl*) GetDlgItem(0);
int nColumnCount = pHeader->GetItemCount();
// Loop through the visible rows
for(; Row <= Bottom; Row++)
{
// Get bounding rect of item and check whether point falls in it.
CRect Rect;
GetItemRect (Row, &Rect, LVIR_BOUNDS);
if (Rect.PtInRect (Point))
{
// Now find the column
for (ColumnNum = 0; ColumnNum < nColumnCount; ColumnNum++)
{
int ColWidth = GetColumnWidth (ColumnNum);
if (Point.x >= Rect.left && Point.x <= (Rect.left + ColWidth))
{
nSubItem = ColumnNum;
return Row;
}
Rect.left += ColWidth;
}
}
}
return -1;
}
CEdit* CListCtrlEx::EditSubItem(int nItem, int nSubItem)
{
// The returned pointer should not be saved
// Make sure that the item is visible
if (!EnsureVisible (nItem, TRUE)) return NULL;
// Make sure that nCol is valid
CHeaderCtrl* pHeader = (CHeaderCtrl*) GetDlgItem(0);
int nColumnCount = pHeader->GetItemCount();
if (nSubItem >= nColumnCount || GetColumnWidth (nSubItem) < 5)
return NULL;
// Get the column offset
int Offset = 0;
for (int iColumn = 0; iColumn < nSubItem; iColumn++)
Offset += GetColumnWidth (iColumn);
CRect Rect;
GetItemRect (nItem, &Rect, LVIR_BOUNDS);
// Now scroll if we need to expose the column
CRect ClientRect;
GetClientRect (&ClientRect);
if (Offset + Rect.left < 0 || Offset + Rect.left > ClientRect.right)
{
CSize Size;
if (Offset + Rect.left > 0)
Size.cx = -(Offset - Rect.left);
else
Size.cx = Offset - Rect.left;
Size.cy = 0;
Scroll (Size);
Rect.left -= Size.cx;
}
// Get nSubItem 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;
Rect.left += Offset+4;
Rect.right = Rect.left + GetColumnWidth (nSubItem) - 3;
if (Rect.right > ClientRect.right)
Rect.right = ClientRect.right;
dwStyle |= WS_BORDER | WS_CHILD | WS_VISIBLE | ES_AUTOHSCROLL;
CEdit *pEdit = new CListCellEdit (nItem, nSubItem, GetItemText (nItem, nSubItem));
pEdit->Create (dwStyle, Rect, this, 101);
return pEdit;
}
void CListCtrlEx::OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar)
{
// TODO: Add your message handler code here and/or call default
if (GetFocus() != this) SetFocus();
CListCtrl::OnVScroll(nSBCode, nPos, pScrollBar);
}
void CListCtrlEx::OnHScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar)
{
// TODO: Add your message handler code here and/or call default
if (GetFocus() != this) SetFocus();
CListCtrl::OnHScroll(nSBCode, nPos, pScrollBar);
}
void CListCtrlEx::OnSize(UINT nType, int cx, int cy)
{
CListCtrl::OnSize(nType, cx, cy);
// TODO: Add your message handler code here
}
void CListCtrlEx::OnEndlabeledit(NMHDR* pNMHDR, LRESULT* pResult)
{
LV_DISPINFO *plvDispInfo = (LV_DISPINFO *)pNMHDR;
LV_ITEM *plvItem = &plvDispInfo->item;
if (plvItem->pszText != NULL)
{
SetItemText (plvItem->iItem, plvItem->iSubItem, plvItem->pszText);
}
*pResult = FALSE;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -