CListCtrl 是在 Windows Common Control 的 List-View 基础上的吧. List-View 有个消息可以设置背景图片: LVM_SETBKIMAGE. 这个消息牵涉到一个结构:typedef struct tagLVBKIMAGE
{
ULONG ulFlags;
HBITMAP hbm;
LPTSTR pszImage;
UINT cchImageMax;
int xOffsetPercent;
int yOffsetPercent;
} LVBKIMAGE, FAR *LPLVBKIMAGE;另外有个帮助宏:BOOL ListView_SetBkImage(
HWND hwndLV,
LPLVBKIMAGE plvbki;
);各位大侠, 谁能告诉我怎么设置背景图象? 谁给出满意的答案, 我马上给分, 只给一个!
{
ULONG ulFlags;
HBITMAP hbm;
LPTSTR pszImage;
UINT cchImageMax;
int xOffsetPercent;
int yOffsetPercent;
} LVBKIMAGE, FAR *LPLVBKIMAGE;另外有个帮助宏:BOOL ListView_SetBkImage(
HWND hwndLV,
LPLVBKIMAGE plvbki;
);各位大侠, 谁能告诉我怎么设置背景图象? 谁给出满意的答案, 我马上给分, 只给一个!
这方面的关键在于, 怎么设置 LVBKIMAGE 结构, 此结构各成员含义如何?期盼回复!
回复人: rushing(勇敢的心) :
-------------------------------------
我就是费尽心思尝试去做了, MSDN 相关章节看了 N 遍, 却不得其要领. 兄台若知道, 还请指点一二, 谢谢
LVBKIMAGE bki;// If no background image is set for the list view control use
// the Microsoft homepage image as the background image.
if (pmyListCtrl->GetBkImage(&bki) && (bki.ulFlags == LVBKIF_SOURCE_NONE))
{
pmyListCtrl->SetBkImage(
TEXT("http://www.microsoft.com/library/images/gifs/homepage/microsoft.gif"),
TRUE);
}
要不这里:
www.codeproject.com
www.codeguru.com
1、建立控件时设置LVS_OWNERDRAWFIXED
cs.style |= LVS_OWNERDRAWFIXED;2、加入成员变量
protected:
CPalette m_pal;
CBitmap m_bitmap;
int m_cxBitmap, b_cyBitmap;3、加入两个成员函数
BOOL CMyListCtrl::SetBkImage(UINT nIDResource)
{
return SetBkImage( (LPCTSTR)nIDResource );
}BOOL CMyListCtrl::SetBkImage(LPCTSTR lpszResourceName)
{ // If this is not the first call then Delete GDI objects
if( m_bitmap.m_hObject != NULL )
m_bitmap.DeleteObject();
if( m_pal.m_hObject != NULL )
m_pal.DeleteObject();
HBITMAP hBmp = (HBITMAP)::LoadImage( AfxGetInstanceHandle(),
lpszResourceName, IMAGE_BITMAP, 0,0, LR_CREATEDIBSECTION ); if( hBmp == NULL )
return FALSE; m_bitmap.Attach( hBmp );
BITMAP bm;
m_bitmap.GetBitmap( &bm );
m_cxBitmap = bm.bmWidth;
m_cyBitmap = bm.bmHeight;
// Create a logical palette for the bitmap
DIBSECTION ds;
BITMAPINFOHEADER &bmInfo = ds.dsBmih;
m_bitmap.GetObject( sizeof(ds), &ds ); int nColors = bmInfo.biClrUsed ? bmInfo.biClrUsed : 1 << bmInfo.biBitCount; // Create a halftone palette if colors > 256.
CClientDC dc(NULL); // Desktop DC
if( nColors > 256 )
m_pal.CreateHalftonePalette( &dc );
else
{
// Create the palette RGBQUAD *pRGB = new RGBQUAD[nColors];
CDC memDC;
memDC.CreateCompatibleDC(&dc); memDC.SelectObject( &m_bitmap );
::GetDIBColorTable( memDC, 0, nColors, pRGB ); UINT nSize = sizeof(LOGPALETTE) + (sizeof(PALETTEENTRY) * nColors);
LOGPALETTE *pLP = (LOGPALETTE *) new BYTE[nSize]; pLP->palVersion = 0x300;
pLP->palNumEntries = nColors; for( int i=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(); return TRUE;
}
4、修改DrawItem
void CMyListCtrl::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct)
{
CDC* pDC = CDC::FromHandle(lpDrawItemStruct->hDC);
CRect rcItem(lpDrawItemStruct->rcItem);
int nItem = lpDrawItemStruct->itemID;
CImageList* pImageList; // Save dc state
int nSavedDC = pDC->SaveDC();
// Get item image and state info
LV_ITEM lvi;
lvi.mask = LVIF_IMAGE | LVIF_STATE;
lvi.iItem = nItem;
lvi.iSubItem = 0;
lvi.stateMask = 0xFFFF; // get all state flags
GetItem(&lvi); // Should the item be highlighted
BOOL bHighlight = ((lvi.state & LVIS_DROPHILITED)
|| ( (lvi.state & LVIS_SELECTED)
&& ((GetFocus() == this)
|| (GetStyle() & LVS_SHOWSELALWAYS)
)
)
);
// Get rectangles for drawing
CRect rcBounds, rcLabel, rcIcon;
GetItemRect(nItem, rcBounds, LVIR_BOUNDS);
GetItemRect(nItem, rcLabel, LVIR_LABEL);
GetItemRect(nItem, rcIcon, LVIR_ICON);
CRect rcCol( rcBounds );
CString sLabel = GetItemText( nItem, 0 ); // Labels are offset by a certain amount
// This offset is related to the width of a space character
int offset = pDC->GetTextExtent(_T(" "), 1 ).cx*2; CRect rcHighlight;
CRect rcClient;
int nExt;
switch( m_nHighlight )
{
case 0:
nExt = pDC->GetOutputTextExtent(sLabel).cx + offset;
rcHighlight = rcLabel;
if( rcLabel.left + nExt < rcLabel.right )
rcHighlight.right = rcLabel.left + nExt;
break;
case 1:
rcHighlight = rcBounds;
rcHighlight.left = rcLabel.left;
break;
case 2:
GetClientRect(&rcClient);
rcHighlight = rcBounds;
rcHighlight.left = rcLabel.left;
rcHighlight.right = rcClient.right;
break;
default:
rcHighlight = rcLabel;
} // Draw bitmap in the background if one has been set
if( m_bitmap.m_hObject != NULL )
{
CDC tempDC;
tempDC.CreateCompatibleDC(pDC);
tempDC.SelectObject( &m_bitmap ); GetClientRect(&rcClient); CRgn rgnBitmap;
CRect rcTmpBmp( rcItem );
rcTmpBmp.right = rcClient.right; // We also need to check whether it is the last item
// The update region has to be extended to the bottom if it is
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();
} CRect rcFirstItem;
GetItemRect(0, rcFirstItem, LVIR_BOUNDS);
for( int i = rcFirstItem.left; i < rcClient.right; i += m_cxBitmap )
for( int j = rcFirstItem.top; j < rcClient.bottom; j += m_cyBitmap )
pDC->BitBlt( i, j, m_cxBitmap, m_cyBitmap, &tempDC,
0, 0, SRCCOPY );
} // Draw the background color
if( bHighlight )
{
pDC->SetTextColor(::GetSysColor(COLOR_HIGHLIGHTTEXT));
pDC->SetBkColor(::GetSysColor(COLOR_HIGHLIGHT)); pDC->FillRect(rcHighlight, &CBrush(::GetSysColor(COLOR_HIGHLIGHT)));
}
else if( m_bitmap.m_hObject == NULL )
pDC->FillRect(rcHighlight, &CBrush(::GetSysColor(COLOR_WINDOW))); // Set clip region
rcCol.right = rcCol.left + GetColumnWidth(0);
CRgn rgn;
rgn.CreateRectRgnIndirect(&rcCol);
pDC->SelectClipRgn(&rgn);
rgn.DeleteObject(); // Draw state icon
if (lvi.state & LVIS_STATEIMAGEMASK)
{
int nImage = ((lvi.state & LVIS_STATEIMAGEMASK)>>12) - 1;
pImageList = GetImageList(LVSIL_STATE);
if (pImageList)
{
pImageList->Draw(pDC, nImage,
CPoint(rcCol.left, rcCol.top), ILD_TRANSPARENT);
}
}
// Draw normal and overlay icon
pImageList = GetImageList(LVSIL_SMALL);
if (pImageList)
{
UINT nOvlImageMask=lvi.state & LVIS_OVERLAYMASK;
pImageList->Draw(pDC, lvi.iImage,
CPoint(rcIcon.left, rcIcon.top),
(bHighlight?ILD_BLEND50:0) | ILD_TRANSPARENT | nOvlImageMask );
}
// Draw item label - Column 0
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);
// Draw labels for remaining columns
LV_COLUMN lvc;
lvc.mask = LVCF_FMT | LVCF_WIDTH; if( m_nHighlight == 0 ) // Highlight only first column
{
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(int nColumn = 1; GetColumn(nColumn, &lvc); nColumn++)
{
rcCol.left = rcCol.right;
rcCol.right += lvc.cx; // Draw the background if needed
if( m_bitmap.m_hObject == NULL && m_nHighlight == HIGHLIGHT_NORMAL )
pDC->FillRect(rcCol, &CBrush(::GetSysColor(COLOR_WINDOW))); sLabel = GetItemText(nItem, nColumn);
if (sLabel.GetLength() == 0)
continue;
// Get the text justification
UINT nJustify = DT_LEFT;
switch(lvc.fmt & LVCFMT_JUSTIFYMASK)
{
case LVCFMT_RIGHT:
nJustify = DT_RIGHT;
break;
case LVCFMT_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);
} // Draw focus rectangle if item has focus
if (lvi.state & LVIS_FOCUSED && (GetFocus() == this))
pDC->DrawFocusRect(rcHighlight);
// Restore dc
pDC->RestoreDC( nSavedDC );
}
BOOL CMyListCtrl::OnEraseBkgnd(CDC* pDC)
{
if( m_bitmap.m_hObject != NULL )
return TRUE;
return CListCtrl::OnEraseBkgnd(pDC);
}
6、重载OnNotify()并且得到列的缩放
BOOL CMyListCtrl::OnNotify(WPARAM wParam, LPARAM lParam, LRESULT* pResult)
{
HD_NOTIFY *pHDN = (HD_NOTIFY*)lParam; // This code is for using bitmap in the background
// Invalidate the right side of the control when a column is resized
if(pHDN->hdr.code == HDN_ITEMCHANGINGW || pHDN->hdr.code == HDN_ITEMCHANGINGA)
{
if( m_bitmap.m_hObject != NULL )
{
CRect rcClient;
GetClientRect( &rcClient );
DWORD dwPos = GetMessagePos();
CPoint pt( LOWORD(dwPos), HIWORD(dwPos) );
ScreenToClient( &pt );
rcClient.left = pt.x;
InvalidateRect( &rcClient );
}
}
return CListCtrl::OnNotify(wParam, lParam, pResult);
}
7、WM_QUERYNEWPALETTE & WM_PALETTECHANGED
BOOL CMyListCtrl::OnQueryNewPalette()
{
CClientDC dc(this);
if( dc.GetDeviceCaps(RASTERCAPS) & RC_PALETTE && m_pal.m_hObject != NULL )
{
dc.SelectPalette( &m_pal, FALSE );
BOOL result = dc.RealizePalette();
if( result )
Invalidate();
return result;
}
return CListCtrl::OnQueryNewPalette();
}void CMyListCtrl::OnPaletteChanged(CWnd* pFocusWnd)
{
CListCtrl::OnPaletteChanged(pFocusWnd);
if( pFocusWnd == this )
return; OnQueryNewPalette();
}
8、
void CListViewDlg::OnPaletteChanged(CWnd* pFocusWnd)
{
CDialog::OnPaletteChanged(pFocusWnd);
m_listctrl.SendMessage( WM_PALETTECHANGED, (WPARAM)pFocusWnd->m_hWnd );
}BOOL CListViewDlg::OnQueryNewPalette()
{
CDialog::OnQueryNewPalette(); return m_listctrl.SendMessage( WM_QUERYNEWPALETTE );
}
--------------------------------------
兄台使用的是 MFC . 我没测试. 我更希望有 API 的, 不过我突然想到跟踪 MFC 源码.......跟踪之下, 发现也极简单, 用了一小段, 成了!呵呵, 给分. 回复人: rushing(勇敢的心) (
--------------------------------
看了一个源码, 挺不错的, 在基层没提供接口的情况下, 写自绘制代码以实现画背景. 还有兄台直接将代码贴了出来.
下面贴出我代码.
listview 是已经创建成功 List-View 控件的句柄 LVBKIMAGE lv;
ZeroMemory(&lv, sizeof(lv));
lv.ulFlags = LVBKIF_SOURCE_URL | LVBKIF_STYLE_TILE;
lv.pszImage = "C:\\wlp.jpg";
lv.xOffsetPercent = 0;
lv.yOffsetPercent = 0; ListView_SetBkImage(listview, &lv);