请教:如何使listbox的每行显示不同的颜色。 我需要建一个ListBox来显示报警信息,一行一条报警信息。根据报警优先级的不同,用不同颜色显示各行。不知怎么做? 是用CListBox 或CListCtrl 的DrawItem()吗?难道需要我自己用label凑个ListBox吗? 解决方案 » 免费领取超大流量手机卡,每月29元包185G流量+100分钟通话, 中国电信官方发货 不是啊,DrawItem函数里面可以对DRAWITEMSTRUCT的hdc SetBKColor 下面是用模板封装的一个colored list view 的源代码,供参考://///////////////////////////////////////////////////////////////////////////// CColoredListViewCtrl - A ListView control with individual item colourstemplate <class T, class TBase = CListViewCtrl, class TWinTraits = CControlWinTraits>class ATL_NO_VTABLE CColoredListViewImpl : public CWindowImpl< T, TBase, TWinTraits >, public CCustomDraw< T >{public: DECLARE_WND_SUPERCLASS(NULL, TBase::GetWndClassName()) typedef struct LVCOLORPARAM { COLORREF clrText; COLORREF clrBackground; HFONT hFont; LPARAM lParam; }; int m_nColumns; // Operations BOOL SubclassWindow(HWND hWnd) { ATLASSERT(m_hWnd==NULL); ATLASSERT(::IsWindow(hWnd));#ifdef _DEBUG // Check class TCHAR szBuffer[16]; if( ::GetClassName(m_hWnd, szBuffer, sizeof(szBuffer)/sizeof(TCHAR)) ) { ATLASSERT(::lstrcmpi(szBuffer, TBase::GetWndClassName())==0); }#endif BOOL bRet = CWindowImpl< T, TBase, TWinTraits >::SubclassWindow(hWnd); if( bRet ) _Init(); return bRet; } int InsertItem(UINT nMask, int nItem, LPCTSTR lpszItem, UINT nState, UINT nStateMask, int nImage=-1, LPARAM lParam=0) { ATLASSERT(::IsWindow(m_hWnd)); // You must have initialized columns before calling this! // And you are not allowed to add columns once the list is populated! CHeaderCtrl ctrlHeader = GetHeader(); if( m_nColumns==0 ) m_nColumns = ctrlHeader.GetItemCount(); ATLASSERT(m_nColumns > 0); ATLASSERT(ctrlHeader.GetItemCount()==m_nColumns); // Create a place-holder of property controls for each subitem... LVCOLORPARAM* pParams; ATLTRY( pParams = new LVCOLORPARAM[m_nColumns] ); ATLASSERT(pParams); if( pParams==NULL ) return -1; ::FillMemory(pParams, sizeof(LVCOLORPARAM) * m_nColumns, -1); // Finally create the listview item itself... if( nItem==-1 ) nItem = GetItemCount(); nMask |= LVIF_PARAM; pParams[0].lParam = lParam; return TBase::InsertItem(nMask, nItem, lpszItem, nState, nStateMask, nImage, (LPARAM) pParams); } int InsertItem(int nItem, LPCTSTR lpszItem, int nImage) { ATLASSERT(::IsWindow(m_hWnd)); return InsertItem(LVIF_TEXT|LVIF_IMAGE, nItem, lpszItem, 0, 0, nImage, 0); } DWORD_PTR GetItemData(int nItem) const { ATLASSERT(::IsWindow(m_hWnd)); LVITEM lvi = { 0 }; lvi.iItem = nItem; lvi.mask = LVIF_PARAM; if( GetItem(&lvi)==-1 ) return 0; LVCOLORPARAM* pParams = (LVCOLORPARAM*) lvi.lParam; return (DWORD_PTR) pParams[0].lParam; } BOOL SetItemColors(int nItem, int nSubItem, COLORREF clrText, COLORREF clrBk) { ATLASSERT(::IsWindow(m_hWnd)); LVITEM lvi = { 0 }; lvi.iItem = nItem; lvi.mask = LVIF_PARAM; if( GetItem(&lvi)==-1 ) return FALSE; LVCOLORPARAM* pParams = (LVCOLORPARAM*) lvi.lParam; ATLASSERT(nSubItem>=0 && nSubItem<GetHeader().GetItemCount()); pParams[ nSubItem ].clrText = clrText; pParams[ nSubItem ].clrBackground = clrBk; // Repaint RedrawItems(nItem, nItem); return TRUE; } // Unsupported ListView methods BOOL SetItemData(int nItem, DWORD_PTR dwData) { ATLASSERT(false); // not supported return FALSE; } int AddItem(int nItem, int nSubItem, LPCTSTR strItem, int nImageIndex = -1) { ATLASSERT(false); // not supported return -1; } // Implementation void _Init() { ATLASSERT(::IsWindow(m_hWnd)); m_nColumns = 0; } // Message map and handlers BEGIN_MSG_MAP(CColoredListViewImpl) MESSAGE_HANDLER(WM_CREATE, OnCreate) REFLECTED_NOTIFY_CODE_HANDLER(LVN_DELETEITEM, OnDeleteItem) CHAIN_MSG_MAP_ALT( CCustomDraw< T >, 1 ) // Because WTL 3.1 does not support subitem custom drawing. // Should be forward-compatible with new versions... REFLECTED_NOTIFY_CODE_HANDLER(NM_CUSTOMDRAW, OnNotifyCustomDraw) DEFAULT_REFLECTION_HANDLER() END_MSG_MAP() LRESULT OnCreate(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& /*bHandled*/) { LRESULT lRes = DefWindowProc(uMsg, wParam, lParam); _Init(); return lRes; } LRESULT OnDeleteItem(int /*idCtrl*/, LPNMHDR pnmh, BOOL& /*bHandled*/) { ATLASSERT(m_nColumns>0); LPNMLISTVIEW pnmlv = (LPNMLISTVIEW) pnmh; ATLASSERT(pnmlv->lParam); LVCOLORPARAM* pParams = reinterpret_cast<LVCOLORPARAM*>(pnmlv->lParam); delete [] pParams; return 0; } LRESULT OnNotifyCustomDraw(int idCtrl, LPNMHDR pnmh, BOOL& bHandled) { T* pT = static_cast<T*>(this); pT->SetMsgHandled(FALSE); LPNMCUSTOMDRAW lpNMCustomDraw = (LPNMCUSTOMDRAW) pnmh; DWORD dwRet = 0; switch( lpNMCustomDraw->dwDrawStage ) { case CDDS_ITEMPREPAINT | CDDS_SUBITEM: dwRet = pT->OnSubItemPrePaint(idCtrl, lpNMCustomDraw); pT->SetMsgHandled(TRUE); return dwRet; } bHandled = FALSE; return dwRet; } // Custom painting DWORD OnPrePaint(int /*idCtrl*/, LPNMCUSTOMDRAW /*lpNMCustomDraw*/) { return CDRF_NOTIFYITEMDRAW; // We need per-item notifications } DWORD OnItemPrePaint(int /*idCtrl*/, LPNMCUSTOMDRAW /*lpNMCustomDraw*/) { return CDRF_NOTIFYSUBITEMDRAW; // We need per-subitem notifications } DWORD OnSubItemPrePaint(int /*idCtrl*/, LPNMCUSTOMDRAW lpNMCustomDraw) { LPNMLVCUSTOMDRAW lpNMLVCD = (LPNMLVCUSTOMDRAW) lpNMCustomDraw; ATLASSERT(lpNMLVCD->nmcd.lItemlParam); LVCOLORPARAM* pParams = reinterpret_cast<LVCOLORPARAM*>(lpNMLVCD->nmcd.lItemlParam); const LVCOLORPARAM& param = pParams[ lpNMLVCD->iSubItem ]; if( param.clrText!=-1 ) lpNMLVCD->clrText = param.clrText; if( param.clrBackground!=-1 ) lpNMLVCD->clrTextBk = param.clrBackground; return CDRF_NEWFONT; // We changed the colors }};class CColoredListViewCtrl : public CColoredListViewImpl<CColoredListViewCtrl>{public: DECLARE_WND_SUPERCLASS(_T("WTL_ColoredListView"), GetWndClassName()) }; 为什么VC6.0里PWINDOWINFO无法编译通过,而VS2008编译通过 高分求助,关于线程函数问题。求一个比较好的解决方案,详见内容 一个类与数据库中多个表连接的问题!急!!! CDialog的WM_DESTORY 在MFC的程序里如何写windows service?? 请问如何在程序中参照系统时间? GetDlgItem()的问题! VB6写的Dll能否在VC6中引用 OpenGL的程序为什么运行一段时间后出错 求助:刷新问题~ 哪位懂得测试工具CodeReview在哪下载?(来着有分) 英语高手请进!!1
DrawItem函数里面可以对DRAWITEMSTRUCT的hdc SetBKColor
/////////////////////////////////////////////////////////////////////////////
// CColoredListViewCtrl - A ListView control with individual item colourstemplate <class T, class TBase = CListViewCtrl, class TWinTraits = CControlWinTraits>
class ATL_NO_VTABLE CColoredListViewImpl :
public CWindowImpl< T, TBase, TWinTraits >,
public CCustomDraw< T >
{
public:
DECLARE_WND_SUPERCLASS(NULL, TBase::GetWndClassName()) typedef struct LVCOLORPARAM {
COLORREF clrText;
COLORREF clrBackground;
HFONT hFont;
LPARAM lParam;
};
int m_nColumns; // Operations BOOL SubclassWindow(HWND hWnd)
{
ATLASSERT(m_hWnd==NULL);
ATLASSERT(::IsWindow(hWnd));
#ifdef _DEBUG
// Check class
TCHAR szBuffer[16];
if( ::GetClassName(m_hWnd, szBuffer, sizeof(szBuffer)/sizeof(TCHAR)) ) {
ATLASSERT(::lstrcmpi(szBuffer, TBase::GetWndClassName())==0);
}
#endif
BOOL bRet = CWindowImpl< T, TBase, TWinTraits >::SubclassWindow(hWnd);
if( bRet ) _Init();
return bRet;
} int InsertItem(UINT nMask, int nItem, LPCTSTR lpszItem, UINT nState, UINT nStateMask, int nImage=-1, LPARAM lParam=0)
{
ATLASSERT(::IsWindow(m_hWnd));
// You must have initialized columns before calling this!
// And you are not allowed to add columns once the list is populated!
CHeaderCtrl ctrlHeader = GetHeader();
if( m_nColumns==0 ) m_nColumns = ctrlHeader.GetItemCount();
ATLASSERT(m_nColumns > 0);
ATLASSERT(ctrlHeader.GetItemCount()==m_nColumns);
// Create a place-holder of property controls for each subitem...
LVCOLORPARAM* pParams;
ATLTRY( pParams = new LVCOLORPARAM[m_nColumns] );
ATLASSERT(pParams);
if( pParams==NULL ) return -1;
::FillMemory(pParams, sizeof(LVCOLORPARAM) * m_nColumns, -1);
// Finally create the listview item itself...
if( nItem==-1 ) nItem = GetItemCount();
nMask |= LVIF_PARAM;
pParams[0].lParam = lParam;
return TBase::InsertItem(nMask, nItem, lpszItem, nState, nStateMask, nImage, (LPARAM) pParams);
}
int InsertItem(int nItem, LPCTSTR lpszItem, int nImage)
{
ATLASSERT(::IsWindow(m_hWnd));
return InsertItem(LVIF_TEXT|LVIF_IMAGE, nItem, lpszItem, 0, 0, nImage, 0);
}
DWORD_PTR GetItemData(int nItem) const
{
ATLASSERT(::IsWindow(m_hWnd));
LVITEM lvi = { 0 };
lvi.iItem = nItem;
lvi.mask = LVIF_PARAM;
if( GetItem(&lvi)==-1 ) return 0;
LVCOLORPARAM* pParams = (LVCOLORPARAM*) lvi.lParam;
return (DWORD_PTR) pParams[0].lParam;
}
BOOL SetItemColors(int nItem, int nSubItem, COLORREF clrText, COLORREF clrBk)
{
ATLASSERT(::IsWindow(m_hWnd));
LVITEM lvi = { 0 };
lvi.iItem = nItem;
lvi.mask = LVIF_PARAM;
if( GetItem(&lvi)==-1 ) return FALSE;
LVCOLORPARAM* pParams = (LVCOLORPARAM*) lvi.lParam;
ATLASSERT(nSubItem>=0 && nSubItem<GetHeader().GetItemCount());
pParams[ nSubItem ].clrText = clrText;
pParams[ nSubItem ].clrBackground = clrBk;
// Repaint
RedrawItems(nItem, nItem);
return TRUE;
} // Unsupported ListView methods BOOL SetItemData(int nItem, DWORD_PTR dwData)
{
ATLASSERT(false); // not supported
return FALSE;
}
int AddItem(int nItem, int nSubItem, LPCTSTR strItem, int nImageIndex = -1)
{
ATLASSERT(false); // not supported
return -1;
} // Implementation void _Init()
{
ATLASSERT(::IsWindow(m_hWnd));
m_nColumns = 0;
} // Message map and handlers BEGIN_MSG_MAP(CColoredListViewImpl)
MESSAGE_HANDLER(WM_CREATE, OnCreate)
REFLECTED_NOTIFY_CODE_HANDLER(LVN_DELETEITEM, OnDeleteItem)
CHAIN_MSG_MAP_ALT( CCustomDraw< T >, 1 )
// Because WTL 3.1 does not support subitem custom drawing.
// Should be forward-compatible with new versions...
REFLECTED_NOTIFY_CODE_HANDLER(NM_CUSTOMDRAW, OnNotifyCustomDraw)
DEFAULT_REFLECTION_HANDLER()
END_MSG_MAP() LRESULT OnCreate(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& /*bHandled*/)
{
LRESULT lRes = DefWindowProc(uMsg, wParam, lParam);
_Init();
return lRes;
}
LRESULT OnDeleteItem(int /*idCtrl*/, LPNMHDR pnmh, BOOL& /*bHandled*/)
{
ATLASSERT(m_nColumns>0);
LPNMLISTVIEW pnmlv = (LPNMLISTVIEW) pnmh;
ATLASSERT(pnmlv->lParam);
LVCOLORPARAM* pParams = reinterpret_cast<LVCOLORPARAM*>(pnmlv->lParam);
delete [] pParams;
return 0;
}
LRESULT OnNotifyCustomDraw(int idCtrl, LPNMHDR pnmh, BOOL& bHandled)
{
T* pT = static_cast<T*>(this);
pT->SetMsgHandled(FALSE);
LPNMCUSTOMDRAW lpNMCustomDraw = (LPNMCUSTOMDRAW) pnmh;
DWORD dwRet = 0;
switch( lpNMCustomDraw->dwDrawStage ) {
case CDDS_ITEMPREPAINT | CDDS_SUBITEM:
dwRet = pT->OnSubItemPrePaint(idCtrl, lpNMCustomDraw);
pT->SetMsgHandled(TRUE);
return dwRet;
}
bHandled = FALSE;
return dwRet;
} // Custom painting DWORD OnPrePaint(int /*idCtrl*/, LPNMCUSTOMDRAW /*lpNMCustomDraw*/)
{
return CDRF_NOTIFYITEMDRAW; // We need per-item notifications
}
DWORD OnItemPrePaint(int /*idCtrl*/, LPNMCUSTOMDRAW /*lpNMCustomDraw*/)
{
return CDRF_NOTIFYSUBITEMDRAW; // We need per-subitem notifications
}
DWORD OnSubItemPrePaint(int /*idCtrl*/, LPNMCUSTOMDRAW lpNMCustomDraw)
{
LPNMLVCUSTOMDRAW lpNMLVCD = (LPNMLVCUSTOMDRAW) lpNMCustomDraw;
ATLASSERT(lpNMLVCD->nmcd.lItemlParam);
LVCOLORPARAM* pParams = reinterpret_cast<LVCOLORPARAM*>(lpNMLVCD->nmcd.lItemlParam);
const LVCOLORPARAM& param = pParams[ lpNMLVCD->iSubItem ];
if( param.clrText!=-1 ) lpNMLVCD->clrText = param.clrText;
if( param.clrBackground!=-1 ) lpNMLVCD->clrTextBk = param.clrBackground;
return CDRF_NEWFONT; // We changed the colors
}
};class CColoredListViewCtrl : public CColoredListViewImpl<CColoredListViewCtrl>
{
public:
DECLARE_WND_SUPERCLASS(_T("WTL_ColoredListView"), GetWndClassName())
};