简单的自绘CListBox,支持多行显示和前景色和背景色的更换。下面是相关的H头文件和CPP文件。
#if !defined(AFX_MULITLINELISTBOX_H__D705CB99_9FD0_424E_BD71_027547449AE5__INCLUDED_) #define AFX_MULITLINELISTBOX_H__D705CB99_9FD0_424E_BD71_027547449AE5__INCLUDED_ #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_)
// MulitLineListBox.cpp : implementation file // #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函数中加入下面的代码即可
CMulitLineListBox m_listBox; // 成员变量 #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); }
显示的效果图如下所示: