自定义的列表控件必须是自绘制的,因此需要在资源编辑器中设置LVS_OWNERDRAWFIXED标志,而且还必须在自定义的控件类中实现DrawItem函数。

<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />
代码如下:
classCListCtrlEx:publicCListCtrl


{
//Construction
public:
CListCtrlEx();

public:

CPalettem_pal;//调色板
CBitmapm_bitmap;//背景位图
intm_cxBitmap,m_cyBitmap;//背景位图高度,宽度信息
intm_nHighlight;//高亮方式

BOOLSetBkImage(LPCTSTRlpszResourceName);//设置背景图片
BOOLSetBkImage(UINTnIDResource);
intGetColumnCount();//获取列数目
voidAdjustColumnWidth();//调整列宽

//Operations
public:

//Overrides
//ClassWizardgeneratedvirtualfunctionoverrides
//{{AFX_VIRTUAL(CListCtrlEx)
//}}AFX_VIRTUAL

//Implementation
public:
virtual~CListCtrlEx();

//Generatedmessagemapfunctions
protected:
//{{AFX_MSG(CListCtrlEx)
afx_msgvoidOnHScroll(UINTnSBCode,UINTnPos,CScrollBar*pScrollBar);//水平滚动
afx_msgvoidOnVScroll(UINTnSBCode,UINTnPos,CScrollBar*pScrollBar);//垂直滚动
afx_msgBOOLOnEraseBkgnd(CDC*pDC);//擦除背景
afx_msgvoidOnPaletteChanged(CWnd*pFocusWnd);//调色板更改
afx_msgBOOLOnQueryNewPalette();//查询新调色板
afx_msgBOOLOnNotify(WPARAMwParam,LPARAMlParam,LRESULT*pResult);
//}}AFX_MSG
virtualvoidDrawItem(LPDRAWITEMSTRUCTlpDrawItemStruct);//画每一行
DECLARE_MESSAGE_MAP()
};

/**//////////////////////////////////////////////////////////////////////////////
//CListCtrlEx

CListCtrlEx::CListCtrlEx()


{
m_nHighlight=0;
}

CListCtrlEx::~CListCtrlEx()


{
}


BEGIN_MESSAGE_MAP(CListCtrlEx,CListCtrl)
//{{AFX_MSG_MAP(CListCtrlEx)
ON_WM_HSCROLL()
ON_WM_VSCROLL()
ON_WM_ERASEBKGND()
ON_WM_PALETTECHANGED()
ON_WM_QUERYNEWPALETTE()//}}AFX_MSG_MAP
END_MESSAGE_MAP()


/**//////////////////////////////////////////////////////////////////////////////
//CListCtrlExmessagehandlers
BOOLCListCtrlEx::SetBkImage(UINTnIDResource)


{
returnSetBkImage((LPCTSTR)nIDResource);
}

BOOLCListCtrlEx::SetBkImage(LPCTSTRlpszResourceName)


{
//IfthisisnotthefirstcallthenDeleteGDIobjects
if(m_bitmap.m_hObject!=NULL)
m_bitmap.DeleteObject();
if(m_pal.m_hObject!=NULL)
m_pal.DeleteObject();


HBITMAPhBmp=(HBITMAP)::LoadImage(AfxGetInstanceHandle(),
lpszResourceName,IMAGE_BITMAP,0,0,LR_CREATEDIBSECTION);

if(hBmp==NULL)
returnFALSE;

m_bitmap.Attach(hBmp);
BITMAPbm;
m_bitmap.GetBitmap(&bm);
m_cxBitmap=bm.bmWidth;
m_cyBitmap=bm.bmHeight;


//Createalogicalpaletteforthebitmap
DIBSECTIONds;
BITMAPINFOHEADER&bmInfo=ds.dsBmih;
m_bitmap.GetObject(sizeof(ds),&ds);

intnColors=bmInfo.biClrUsed?bmInfo.biClrUsed:1<<bmInfo.biBitCount;

//Createahalftonepaletteifcolors>256.
CClientDCdc(NULL);//DesktopDC
if(nColors>256)
m_pal.CreateHalftonePalette(&dc);
else


{
//Createthepalette

RGBQUAD*pRGB=newRGBQUAD[nColors];
CDCmemDC;
memDC.CreateCompatibleDC(&dc);

memDC.SelectObject(&m_bitmap);
::GetDIBColorTable(memDC,0,nColors,pRGB);

UINTnSize=sizeof(LOGPALETTE)+(sizeof(PALETTEENTRY)*nColors);
LOGPALETTE*pLP=(LOGPALETTE*)newBYTE[nSize];

pLP->palVersion=0x300;
pLP->palNumEntries=nColors;

for(inti=0;i<nColors;i++)


{
pLP->palPalEntry[i].peRed=pRGB[i].rgbRed;
pLP->palPalEntry[i].peGreen=pRGB[i].rgbGreen;
pLP->palPalEntry[i].peBlue=pRGB[i].rgbBlue;
pLP->palPalEntry[i].peFlags=0;
}

m_pal.CreatePalette(pLP);

delete[]pLP;
delete[]pRGB;
}
Invalidate();

returnTRUE;

}

voidCListCtrlEx::OnHScroll(UINTnSBCode,UINTnPos,CScrollBar*pScrollBar)


{
//TODO:Addyourmessagehandlercodehereand/orcalldefault
if(m_bitmap.m_hObject!=NULL)
InvalidateRect(NULL);

CListCtrl::OnHScroll(nSBCode,nPos,pScrollBar);
}

voidCListCtrlEx::OnVScroll(UINTnSBCode,UINTnPos,CScrollBar*pScrollBar)


{
//TODO:Addyourmessagehandlercodehereand/orcalldefault
if(m_bitmap.m_hObject!=NULL)
InvalidateRect(NULL);

CListCtrl::OnVScroll(nSBCode,nPos,pScrollBar);
}

BOOLCListCtrlEx::OnEraseBkgnd(CDC*pDC)


{
//TODO:Addyourmessagehandlercodehereand/orcalldefault
if(m_bitmap.m_hObject!=NULL)
returnTRUE;

returnCListCtrl::OnEraseBkgnd(pDC);
}

voidCListCtrlEx::OnPaletteChanged(CWnd*pFocusWnd)


{
CListCtrl::OnPaletteChanged(pFocusWnd);

//TODO:Addyourmessagehandlercodehere
if(pFocusWnd==this)
return;

OnQueryNewPalette();
}

BOOLCListCtrlEx::OnQueryNewPalette()


{
//TODO:Addyourmessagehandlercodehereand/orcalldefault
CClientDCdc(this);
if(dc.GetDeviceCaps(RASTERCAPS)&RC_PALETTE&&m_pal.m_hObject!=NULL)


{
dc.SelectPalette(&m_pal,FALSE);
BOOLresult=dc.RealizePalette();
if(result)
Invalidate();
returnresult;
}

returnCListCtrl::OnQueryNewPalette();
}

voidCListCtrlEx::DrawItem(LPDRAWITEMSTRUCTlpDrawItemStruct)


{

CDC*pDC=CDC::FromHandle(lpDrawItemStruct->hDC);
CRectrcItem(lpDrawItemStruct->rcItem);
intnItem=lpDrawItemStruct->itemID;
CImageList*pImageList;

//Savedcstate
intnSavedDC=pDC->SaveDC();

//Getitemimageandstateinfo
LV_ITEMlvi;
lvi.mask=LVIF_IMAGE|LVIF_STATE;
lvi.iItem=nItem;
lvi.iSubItem=0;
lvi.stateMask=0xFFFF;//getallstateflags
GetItem(&lvi);

//Shouldtheitembehighlighted
BOOLbHighlight=((lvi.state&LVIS_DROPHILITED)||((lvi.state&LVIS_SELECTED)&&((GetFocus()==this)||
(GetStyle()&LVS_SHOWSELALWAYS))));

//Getrectanglesfordrawing
CRectrcBounds,rcLabel,rcIcon;
GetItemRect(nItem,rcBounds,LVIR_BOUNDS);
GetItemRect(nItem,rcLabel,LVIR_LABEL);
GetItemRect(nItem,rcIcon,LVIR_ICON);
CRectrcCol(rcBounds);

CStringsLabel=GetItemText(nItem,0);

//Labelsareoffsetbyacertainamount
//Thisoffsetisrelatedtothewidthofaspacecharacter
intoffset=pDC->GetTextExtent(_T(""),1).cx*2;

CRectrcHighlight;
CRectrcClient;
intnExt;
switch(m_nHighlight)


{
case0:
nExt=pDC->GetOutputTextExtent(sLabel).cx+offset;
rcHighlight=rcLabel;
//if(rcLabel.left+nExt

if(m_bitmap.m_hObject!=NULL)


{
CDCtempDC;
tempDC.CreateCompatibleDC(pDC);
tempDC.SelectObject(&m_bitmap);

GetClientRect(&rcClient);

CRgnrgnBitmap;
CRectrcTmpBmp(rcItem);

rcTmpBmp.right=rcClient.right;

//Wealsoneedtocheckwhetheritisthelastitem
//Theupdateregionhastobeextendedtothebottomifitis
if(nItem==GetItemCount()-1)
rcTmpBmp.bottom=rcClient.bottom;

rgnBitmap.CreateRectRgnIndirect(&rcTmpBmp);
pDC->SelectClipRgn(&rgnBitmap);
rgnBitmap.DeleteObject();

if(pDC->GetDeviceCaps(RASTERCAPS)&RC_PALETTE&&m_pal.m_hObject!=NULL)


{
pDC->SelectPalette(&m_pal,FALSE);
pDC->RealizePalette();
}

CRectrcFirstItem;
GetItemRect(0,rcFirstItem,LVIR_BOUNDS);

for(inti=rcFirstItem.left;i<rcTmpBmp.right;i+=m_cxBitmap)
for(intj=rcFirstItem.top;j<rcTmpBmp.bottom;j+=m_cyBitmap)
pDC->BitBlt(i,j,m_cxBitmap,m_cyBitmap,&tempDC,0,0,SRCCOPY);

}
}
//Drawthebackgroundcolor
if(bHighlight)


{
pDC->SetTextColor(::GetSysColor(COLOR_HIGHLIGHTTEXT));
pDC->SetBkColor(::GetSysColor(COLOR_HIGHLIGHT));

pDC->FillRect(rcHighlight,&CBrush(::GetSysColor(COLOR_HIGHLIGHT)));
}
elseif(m_bitmap.m_hObject==NULL)
pDC->FillRect(rcHighlight,&CBrush(::GetSysColor(COLOR_WINDOW)));



//Setclipregion
rcCol.right=rcCol.left+GetColumnWidth(0);
CRgnrgn;
rgn.CreateRectRgnIndirect(&rcCol);
pDC->SelectClipRgn(&rgn);
rgn.DeleteObject();

//Drawstateicon
if(lvi.state&LVIS_STATEIMAGEMASK)


{
intnImage=((lvi.state&LVIS_STATEIMAGEMASK)>>12)-1;
pImageList=GetImageList(LVSIL_STATE);
if(pImageList)


{
pImageList->Draw(pDC,nImage,
CPoint(rcCol.left,rcCol.top),ILD_TRANSPARENT);
}
}

//Drawnormalandoverlayicon
pImageList=GetImageList(LVSIL_SMALL);
if(pImageList)


{
UINTnOvlImageMask=lvi.state&LVIS_OVERLAYMASK;
pImageList->Draw(pDC,lvi.iImage,
CPoint(rcIcon.left,rcIcon.top),
(bHighlight?ILD_BLEND50:0)|ILD_TRANSPARENT|nOvlImageMask);
}



//Drawitemlabel-Column0
rcLabel.left+=offset/2;
rcLabel.right-=offset;

pDC->DrawText(sLabel,-1,rcLabel,DT_LEFT|DT_SINGLELINE|DT_NOPREFIX|DT_NOCLIP
|DT_VCENTER|DT_END_ELLIPSIS);


//Drawlabelsforremainingcolumns
LV_COLUMNlvc;
lvc.mask=LVCF_FMT|LVCF_WIDTH;

if(m_nHighlight==0)//Highlightonlyfirstcolumn


{
pDC->SetTextColor(::GetSysColor(COLOR_WINDOWTEXT));
pDC->SetBkColor(::GetSysColor(COLOR_WINDOW));
}

rcBounds.right=rcHighlight.right>rcBounds.right?rcHighlight.right:
rcBounds.right;
rgn.CreateRectRgnIndirect(&rcBounds);
pDC->SelectClipRgn(&rgn);

for(intnColumn=1;GetColumn(nColumn,&lvc);nColumn++)


{
rcCol.left=rcCol.right;
rcCol.right+=lvc.cx;

//Drawthebackgroundifneeded&&m_nHighlight==HIGHLIGHT_NORMAL
if(m_bitmap.m_hObject==NULL)
pDC->FillRect(rcCol,&CBrush(::GetSysColor(COLOR_WINDOW)));

sLabel=GetItemText(nItem,nColumn);
if(sLabel.GetLength()==0)
continue;


//Getthetextjustification
UINTnJustify=DT_LEFT;
switch(lvc.fmt&LVCFMT_JUSTIFYMASK)


{
caseLVCFMT_RIGHT:
nJustify=DT_RIGHT;
break;
caseLVCFMT_CENTER:
nJustify=DT_CENTER;
break;
default:
break;
}

rcLabel=rcCol;
rcLabel.left+=offset;
rcLabel.right-=offset;

pDC->DrawText(sLabel,-1,rcLabel,nJustify|DT_SINGLELINE
|DT_NOPREFIX|DT_VCENTER|DT_END_ELLIPSIS);
}

//Drawfocusrectangleifitemhasfocus
if(lvi.state&LVIS_FOCUSED&&(GetFocus()==this))
pDC->DrawFocusRect(rcHighlight);


//Restoredc
pDC->RestoreDC(nSavedDC);

}

voidCListCtrlEx::AdjustColumnWidth()


{
SetRedraw(FALSE);
intnColumnCount=GetColumnCount();

for(inti=0;i<nColumnCount;i++)


{
SetColumnWidth(i,LVSCW_AUTOSIZE);
intnColumnWidth=GetColumnWidth(i);
SetColumnWidth(i,LVSCW_AUTOSIZE_USEHEADER);
intnHeaderWidth=GetColumnWidth(i);

SetColumnWidth(i,max(nColumnWidth,nHeaderWidth));
}
SetRedraw(TRUE);
}

intCListCtrlEx::GetColumnCount()


{
CHeaderCtrl*pHeaderCtrl=GetHeaderCtrl();
return(pHeaderCtrl->GetItemCount());
}

BOOLCListCtrlEx::OnNotify(WPARAMwParam,LPARAMlParam,LRESULT*pResult)


{
HD_NOTIFY*pHDN=(HD_NOTIFY*)lParam;

//Thiscodeisforusingbitmapinthebackground
//Invalidatetherightsideofthecontrolwhenacolumnisresized
if(pHDN->hdr.code==HDN_ITEMCHANGINGW||pHDN->hdr.code==HDN_ITEMCHANGINGA)


{
if(m_bitmap.m_hObject!=NULL)


{
CRectrcClient;
GetClientRect(&rcClient);
DWORDdwPos=GetMessagePos();
CPointpt(LOWORD(dwPos),HIWORD(dwPos));
ScreenToClient(&pt);
rcClient.left=pt.x;
InvalidateRect(&rcClient);
}
}
returnCListCtrl::OnNotify(wParam,lParam,pResult);
}
BOOLCCdDlg::OnInitDialog()


{
CDialog::OnInitDialog();

//Add"About
"menuitemtosystemmenu.

//IDM_ABOUTBOXmustbeinthesystemcommandrange.
ASSERT((IDM_ABOUTBOX&0xFFF0)==IDM_ABOUTBOX);
ASSERT(IDM_ABOUTBOX<0xF000);

CMenu*pSysMenu=GetSystemMenu(FALSE);
if(pSysMenu!=NULL)


{
CStringstrAboutMenu;
strAboutMenu.LoadString(IDS_ABOUTBOX);
if(!strAboutMenu.IsEmpty())


{
pSysMenu->AppendMenu(MF_SEPARATOR);
pSysMenu->AppendMenu(MF_STRING,IDM_ABOUTBOX,strAboutMenu);
}
}

//Settheiconforthisdialog.Theframeworkdoesthisautomatically
//whentheapplication'smainwindowisnotadialog
SetIcon(m_hIcon,TRUE);//Setbigicon
SetIcon(m_hIcon,FALSE);//Setsmallicon

m_list.InsertColumn(0,_T("用户编号"));
m_list.InsertColumn(1,_T("用户名称"));
m_list.InsertColumn(2,_T("年龄"));
m_list.InsertColumn(3,_T("性别"));
m_list.InsertColumn(4,_T("用户住址"));
charch[5];

for(intj=1;j<=200;j++)


{
m_list.InsertItem(j,itoa(j,ch,10));
}

for(inti=0;i<200;i++)


{

m_list.SetItemText(i,1,strcat(itoa(i+1,ch,10),"号用户"));
m_list.SetItemText(i,2,itoa((i+100)%100,ch,10));
if(i%2==0)


{
m_list.SetItemText(i,3,"男");
}
else


{
m_list.SetItemText(i,3,"女");
}
m_list.SetItemText(i,4,strcat(itoa(i+1,ch,10),"号大街"));
}



ListView_SetExtendedListViewStyle(m_list.m_hWnd,LVS_EX_FULLROWSELECT|LVS_EX_FLATSB|LVS_EX_HEADERDRAGDROP);
m_list.SetBkImage(IDB_Bless);
m_list.AdjustColumnWidth();
returnTRUE;//returnTRUEunlessyousetthefocustoacontrol
}
效果如图所示:

但是这里还有一个问题,就是当下拉滚动条的时候,如何让背景图片不动,而只是数据行变化,这是接下来要做的工作。
参考资料:
http://www.codeguru.com/Cpp/controls/listview/backgroundcolorandimage/article.php/c983/