简单的自绘CListBox,支持多行显示和前景色和背景色的更换。下面是相关的H头文件和CPP文件。
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
// MulitLineListBox.h : header file
//
/////////////////////////////////////////////////////////////////////////////
// CMulitLineListBox window
typedef struct _LISTBOX_COLOR_
{
CString strText;
COLORREF fgColor;
COLORREF bgColor;
_LISTBOX_COLOR_()
{
strText.Empty();
fgColor = RGB(0, 0, 0);
bgColor = RGB(255, 255, 255);
}
}LISTBOX_COLOR, *PLISTBOX_COLOR;
class CMulitLineListBox : public CListBox
{
// Construction
public:
CMulitLineListBox();
// Attributes
public:
void AppendString(LPCSTR lpszText, COLORREF fgColor, COLORREF bgColor);
// Operations
public:
// Overrides
// ClassWizard generated virtual function overrides
//{{AFX_VIRTUAL(CMulitLineListBox)
public:
virtual void MeasureItem(LPMEASUREITEMSTRUCT lpMeasureItemStruct);
virtual void DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct);
//}}AFX_VIRTUAL
// Implementation
public:
virtual ~CMulitLineListBox();
// Generated message map functions
protected:
//{{AFX_MSG(CMulitLineListBox)
afx_msg void OnDestroy();
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
};
/////////////////////////////////////////////////////////////////////////////
//{{AFX_INSERT_LOCATION}}
// Microsoft Visual C++ will insert additional declarations immediately before the previous line.
#endif // !defined(AFX_MULITLINELISTBOX_H__D705CB99_9FD0_424E_BD71_027547449AE5__INCLUDED_)
#include "stdafx.h"
#include "MulitLineListBox.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/////////////////////////////////////////////////////////////////////////////
// CMulitLineListBox
CMulitLineListBox::CMulitLineListBox()
{
}
CMulitLineListBox::~CMulitLineListBox()
{
}
BEGIN_MESSAGE_MAP(CMulitLineListBox, CListBox)
//{{AFX_MSG_MAP(CMulitLineListBox)
ON_WM_DESTROY()
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CMulitLineListBox message handlers
void CMulitLineListBox::AppendString(LPCSTR lpszText, COLORREF fgColor, COLORREF bgColor)
{
LISTBOX_COLOR* pInfo = new LISTBOX_COLOR;
pInfo->strText.Format(_T("%s"), lpszText);
pInfo->fgColor = fgColor;
pInfo->bgColor = bgColor;
SetItemDataPtr(AddString(pInfo->strText), pInfo);
}
void CMulitLineListBox::MeasureItem(LPMEASUREITEMSTRUCT lpMeasureItemStruct)
{
// TODO: Add your code to determine the size of specified item
ASSERT(lpMeasureItemStruct->CtlType == ODT_LISTBOX);
CString strText(_T(""));
GetText(lpMeasureItemStruct->itemID, strText);
ASSERT(TRUE != strText.IsEmpty());
CRect rect;
GetItemRect(lpMeasureItemStruct->itemID, &rect);
CDC* pDC = GetDC();
lpMeasureItemStruct->itemHeight = pDC->DrawText(strText, -1, rect, DT_WORDBREAK | DT_CALCRECT);
ReleaseDC(pDC);
}
void CMulitLineListBox::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct)
{
// TODO: Add your code to draw the specified item
ASSERT(lpDrawItemStruct->CtlType == ODT_LISTBOX);
LISTBOX_COLOR* pListBox = (LISTBOX_COLOR*)GetItemDataPtr(lpDrawItemStruct->itemID);
ASSERT(NULL != pListBox);
CDC dc;
dc.Attach(lpDrawItemStruct->hDC);
// Save these value to restore them when done drawing.
COLORREF crOldTextColor = dc.GetTextColor();
COLORREF crOldBkColor = dc.GetBkColor();
// If this item is selected, set the background color
// and the text color to appropriate values. Also, erase
// rect by filling it with the background color.
if ((lpDrawItemStruct->itemAction | ODA_SELECT) &&
(lpDrawItemStruct->itemState & ODS_SELECTED))
{
dc.SetTextColor(pListBox->bgColor);
dc.SetBkColor(pListBox->fgColor);
dc.FillSolidRect(&lpDrawItemStruct->rcItem, pListBox->fgColor);
}
else
{
dc.SetTextColor(pListBox->fgColor);
dc.SetBkColor(pListBox->bgColor);
dc.FillSolidRect(&lpDrawItemStruct->rcItem, pListBox->bgColor);
}
lpDrawItemStruct->rcItem.left += 5;
// Draw the text.
dc.DrawText(pListBox->strText, pListBox->strText.GetLength(), &lpDrawItemStruct->rcItem, DT_WORDBREAK);
// Reset the background color and the text color back to their
// original values.
dc.SetTextColor(crOldTextColor);
dc.SetBkColor(crOldBkColor);
dc.Detach();
}
void CMulitLineListBox::OnDestroy()
{
int nCount = GetCount();
for(int i=0; i<nCount; i++)
{
LISTBOX_COLOR* pList = (LISTBOX_COLOR*)GetItemDataPtr(i);
delete pList;
pList = NULL;
}
CListBox::OnDestroy();
// TODO: Add your message handler code here
}
调用方法,在主对话框类的OnInitDialog函数中加入下面的代码即可
#define IDC_LISTBOX 0x11
CRect rc;
GetClientRect(&rc);
rc.bottom -= 35;
rc.DeflateRect(CSize(10, 10));
m_listBox.Create(WS_CHILD | WS_VISIBLE | WS_BORDER | WS_HSCROLL | WS_VSCROLL |
LBS_OWNERDRAWVARIABLE | LBS_HASSTRINGS, rc, this, IDC_LISTBOX);
CString strText(_T(""));
COLORREF fgColor;
COLORREF bgColor;
for(int i=0; i<20; i++)
{
if(i%2)
strText = _T("Hello, World!");
else
strText = _T("Hello, World!/r/nHello, World!");
fgColor = RGB(128, 0, i*7%128);
bgColor = RGB(0, i*7%128, 0);
m_listBox.AppendString(strText, fgColor, bgColor);
}
显示的效果图如下所示: