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

代码如下:
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/
本文介绍了一种自定义列表控件的方法,通过设置LVS_OWNERDRAWFIXED标志并实现DrawItem函数来实现自绘制列表控件。此外,还介绍了如何在列表控件中设置背景图片,并保持滚动时背景图片固定不变。
2542

被折叠的 条评论
为什么被折叠?



