我从网上找到了这个在ctreectrl中加入透明背景图案的程序,加入程序后运行没有任何问题,我想把他用于clistctrl控件,把基类由ctreectrl换成clistctrl,其他未改,编译没有问题,运行时,有图标和文字的地方都显示正常,背景也能透明地显示出来,但没有图标和文字的地方却全部变黑了,背景图案不见了。不知道在onpait中,ctreectrl和clistctrl有什么不同,请高手指点?有问题的语句我已指出。为树控制设置背景图象
树控制是一个不支持自绘的控件。这就为显示背景图像增加了一定的难度。但
无论如何,它是能够做到的,我们将讨论如何做。一个基本的方法是将树控制
绘制在一个内存设备上,并透明的覆盖在背景图像上,那么其结果将是背景图
像显示在控件服务区。当然,这些相关资料较少。
树控制使用背景位图,一个好的用途是显示公司商标。还有我们必须保证使
用的位图不能影响我们的阅读。首先我们要求图像已被作为资源加入工程,我们可以使用256色的位图(16色
的应当也被支持)。如果加入的图像小于控件的面积,图像将平铺在控件服务
区。步骤1: 加入位图到资源
使用导入功能加入位图到资源编辑器。
步骤2: 加入变量
protected:
CPalette m_pal;
CBitmap m_bitmap;
int m_cxBitmap, m_cyBitmap;步骤3: 加入设置背景图像的成员函数
我们加入了两个重载函数去设置背景图像,这两个函数应当是公共函数,第一函数参数为资源ID,第二个函数参数为资源名。
这些函数能够被调用来改变一个已经被指定的位图。首先它们将删除GDI对象上已有的位图与调色板。然后它们加载位图,并将它们附加到CBitmap对象上。我们调用了全局函数::LoadImage()而没有调用CBitmap::LoadBitmap()。这样做的原因是我们需要访问位图的DIBSECTION,为什么要访问位图的DIBSECTION,这是因为我产需要创建一个与位图颜色相配的逻辑调色板。 如果你没有设置和使用这个逻辑调色板,那么图象看上去将非常DULL。同时为了将来使用我们也保存了位图的尺寸。如果位图是256色的或更少,我们将创建调色板。我们分配足够的空间保存位图颜色表并调用 ::GetDIBColorTable()函数从位图中获得它。我们分配的足够的内存去创建调色板并从位图颜色表中获得颜色调色板信息。调色板的版本应当是0x300。 BOOL CTreeCtrlX::SetBkImage(UINT nIDResource)
{
return SetBkImage( (LPCTSTR)nIDResource );
}BOOL CTreeCtrlX::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: 加入WM_PAINT消息响应函数
void CTreeCtrlX::OnPaint()
{
// Remove comments from next five lines if you don't need any
// specialization beyond adding a background image
// if( m_bitmap.m_hObject == NULL )
// {
// CTreeCtrl::OnPaint();
// return;
// } CPaintDC dc(this); CRect rcClip, rcClient;
dc.GetClipBox( &rcClip );
GetClientRect(&rcClient); // Create a compatible memory DC
CDC memDC;
memDC.CreateCompatibleDC( &dc ); // Select a compatible bitmap into the memory DC
CBitmap bitmap, bmpImage;
bitmap.CreateCompatibleBitmap( &dc, rcClient.Width(), rcClient.Height() );
memDC.SelectObject( &bitmap );
// First let the control do its default drawing.
CWnd::DefWindowProc( WM_PAINT, (WPARAM)memDC.m_hDC, 0 ); // Draw bitmap in the background if one has been set
if( m_bitmap.m_hObject != NULL )
{
// Now create a mask
CDC maskDC;
maskDC.CreateCompatibleDC(&dc);
CBitmap maskBitmap; // Create monochrome bitmap for the mask
maskBitmap.CreateBitmap( rcClient.Width(), rcClient.Height(),
1, 1, NULL );
maskDC.SelectObject( &maskBitmap );
memDC.SetBkColor( ::GetSysColor( COLOR_WINDOW ) ); // Create the mask from the memory DC
maskDC.BitBlt( 0, 0, rcClient.Width(), rcClient.Height(), &memDC,
rcClient.left, rcClient.top, SRCCOPY );
CDC tempDC;
tempDC.CreateCompatibleDC(&dc);
tempDC.SelectObject( &m_bitmap ); CDC imageDC;
CBitmap bmpImage;
imageDC.CreateCompatibleDC( &dc );
bmpImage.CreateCompatibleBitmap( &dc, rcClient.Width(),
rcClient.Height() );
imageDC.SelectObject( &bmpImage ); if( dc.GetDeviceCaps(RASTERCAPS) & RC_PALETTE && m_pal.m_hObject != NULL )
{
dc.SelectPalette( &m_pal, FALSE );
dc.RealizePalette(); imageDC.SelectPalette( &m_pal, FALSE );
} // Get x and y offset
CRect rcRoot;
GetItemRect( GetRootItem(), rcRoot, FALSE );
rcRoot.left = -GetScrollPos( SB_HORZ ); // Draw bitmap in tiled manner to imageDC
for( int i = rcRoot.left; i < rcClient.right; i += m_cxBitmap )
for( int j = rcRoot.top; j < rcClient.bottom; j += m_cyBitmap )
imageDC.BitBlt( i, j, m_cxBitmap, m_cyBitmap, &tempDC,
0, 0, SRCCOPY ); // Set the background in memDC to black. Using SRCPAINT with
//black and any other
// color results in the other color, thus making black the transparent color
memDC.SetBkColor(RGB(0,0,0));
memDC.SetTextColor(RGB(255,255,255));
memDC.BitBlt(rcClip.left, rcClip.top, rcClip.Width(),
rcClip.Height(), &maskDC, rcClip.left, rcClip.top, SRCAND); // Set the foreground to black. See comment above.
imageDC.SetBkColor(RGB(255,255,255)); // 问题在这三条语句上
imageDC.SetTextColor(RGB(0,0,0)); //
imageDC.BitBlt(rcClip.left, rcClip.top, rcClip.Width(),
rcClip.Height(), &maskDC, rcClip.left, rcClip.top, SRCAND); // // Combine the foreground with the background
imageDC.BitBlt(rcClip.left, rcClip.top, rcClip.Width(),
rcClip.Height(), memDC, rcClip.left, rcClip.top,SRCPAINT); // Draw the final image to the screen
dc.BitBlt( rcClip.left, rcClip.top, rcClip.Width(), rcClip.Height(),
&imageDC, rcClip.left, rcClip.top, SRCCOPY );
}
else
{
dc.BitBlt( rcClip.left, rcClip.top, rcClip.Width(),
rcClip.Height(), &memDC,
rcClip.left, rcClip.top, SRCCOPY );
}
}步骤5: 处理滚动消息
void CTreeCtrlX::OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar)
{
if( m_bitmap.m_hObject != NULL )
InvalidateRect(NULL);
CTreeCtrl::OnVScroll(nSBCode, nPos, pScrollBar);
}void CTreeCtrlX::OnHScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar)
{
if( m_bitmap.m_hObject != NULL )
InvalidateRect(NULL);
CTreeCtrl::OnHScroll(nSBCode, nPos, pScrollBar);
}步骤6: 处理TVN_ITEMEXPANDING消息
void CTreeCtrlX::OnItemExpanding(NMHDR* pNMHDR, LRESULT* pResult)
{
NM_TREEVIEW* pNMTreeView = (NM_TREEVIEW*)pNMHDR; if( m_bitmap.m_hObject != NULL )
InvalidateRect(NULL); *pResult = 0;
}步骤7: 加入WM_ERASEBKGND响应函数
BOOL CTreeCtrlX::OnEraseBkgnd(CDC* pDC)
{
if( m_bitmap.m_hObject != NULL )
return TRUE;
return CTreeCtrl::OnEraseBkgnd(pDC);
}步骤8: 处理WM_QUERYNEWPALETTE & WM_PALETTECHANGED消息
BOOL CTreeCtrlX::OnQueryNewPalette()
{
CClientDC dc(th
树控制是一个不支持自绘的控件。这就为显示背景图像增加了一定的难度。但
无论如何,它是能够做到的,我们将讨论如何做。一个基本的方法是将树控制
绘制在一个内存设备上,并透明的覆盖在背景图像上,那么其结果将是背景图
像显示在控件服务区。当然,这些相关资料较少。
树控制使用背景位图,一个好的用途是显示公司商标。还有我们必须保证使
用的位图不能影响我们的阅读。首先我们要求图像已被作为资源加入工程,我们可以使用256色的位图(16色
的应当也被支持)。如果加入的图像小于控件的面积,图像将平铺在控件服务
区。步骤1: 加入位图到资源
使用导入功能加入位图到资源编辑器。
步骤2: 加入变量
protected:
CPalette m_pal;
CBitmap m_bitmap;
int m_cxBitmap, m_cyBitmap;步骤3: 加入设置背景图像的成员函数
我们加入了两个重载函数去设置背景图像,这两个函数应当是公共函数,第一函数参数为资源ID,第二个函数参数为资源名。
这些函数能够被调用来改变一个已经被指定的位图。首先它们将删除GDI对象上已有的位图与调色板。然后它们加载位图,并将它们附加到CBitmap对象上。我们调用了全局函数::LoadImage()而没有调用CBitmap::LoadBitmap()。这样做的原因是我们需要访问位图的DIBSECTION,为什么要访问位图的DIBSECTION,这是因为我产需要创建一个与位图颜色相配的逻辑调色板。 如果你没有设置和使用这个逻辑调色板,那么图象看上去将非常DULL。同时为了将来使用我们也保存了位图的尺寸。如果位图是256色的或更少,我们将创建调色板。我们分配足够的空间保存位图颜色表并调用 ::GetDIBColorTable()函数从位图中获得它。我们分配的足够的内存去创建调色板并从位图颜色表中获得颜色调色板信息。调色板的版本应当是0x300。 BOOL CTreeCtrlX::SetBkImage(UINT nIDResource)
{
return SetBkImage( (LPCTSTR)nIDResource );
}BOOL CTreeCtrlX::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: 加入WM_PAINT消息响应函数
void CTreeCtrlX::OnPaint()
{
// Remove comments from next five lines if you don't need any
// specialization beyond adding a background image
// if( m_bitmap.m_hObject == NULL )
// {
// CTreeCtrl::OnPaint();
// return;
// } CPaintDC dc(this); CRect rcClip, rcClient;
dc.GetClipBox( &rcClip );
GetClientRect(&rcClient); // Create a compatible memory DC
CDC memDC;
memDC.CreateCompatibleDC( &dc ); // Select a compatible bitmap into the memory DC
CBitmap bitmap, bmpImage;
bitmap.CreateCompatibleBitmap( &dc, rcClient.Width(), rcClient.Height() );
memDC.SelectObject( &bitmap );
// First let the control do its default drawing.
CWnd::DefWindowProc( WM_PAINT, (WPARAM)memDC.m_hDC, 0 ); // Draw bitmap in the background if one has been set
if( m_bitmap.m_hObject != NULL )
{
// Now create a mask
CDC maskDC;
maskDC.CreateCompatibleDC(&dc);
CBitmap maskBitmap; // Create monochrome bitmap for the mask
maskBitmap.CreateBitmap( rcClient.Width(), rcClient.Height(),
1, 1, NULL );
maskDC.SelectObject( &maskBitmap );
memDC.SetBkColor( ::GetSysColor( COLOR_WINDOW ) ); // Create the mask from the memory DC
maskDC.BitBlt( 0, 0, rcClient.Width(), rcClient.Height(), &memDC,
rcClient.left, rcClient.top, SRCCOPY );
CDC tempDC;
tempDC.CreateCompatibleDC(&dc);
tempDC.SelectObject( &m_bitmap ); CDC imageDC;
CBitmap bmpImage;
imageDC.CreateCompatibleDC( &dc );
bmpImage.CreateCompatibleBitmap( &dc, rcClient.Width(),
rcClient.Height() );
imageDC.SelectObject( &bmpImage ); if( dc.GetDeviceCaps(RASTERCAPS) & RC_PALETTE && m_pal.m_hObject != NULL )
{
dc.SelectPalette( &m_pal, FALSE );
dc.RealizePalette(); imageDC.SelectPalette( &m_pal, FALSE );
} // Get x and y offset
CRect rcRoot;
GetItemRect( GetRootItem(), rcRoot, FALSE );
rcRoot.left = -GetScrollPos( SB_HORZ ); // Draw bitmap in tiled manner to imageDC
for( int i = rcRoot.left; i < rcClient.right; i += m_cxBitmap )
for( int j = rcRoot.top; j < rcClient.bottom; j += m_cyBitmap )
imageDC.BitBlt( i, j, m_cxBitmap, m_cyBitmap, &tempDC,
0, 0, SRCCOPY ); // Set the background in memDC to black. Using SRCPAINT with
//black and any other
// color results in the other color, thus making black the transparent color
memDC.SetBkColor(RGB(0,0,0));
memDC.SetTextColor(RGB(255,255,255));
memDC.BitBlt(rcClip.left, rcClip.top, rcClip.Width(),
rcClip.Height(), &maskDC, rcClip.left, rcClip.top, SRCAND); // Set the foreground to black. See comment above.
imageDC.SetBkColor(RGB(255,255,255)); // 问题在这三条语句上
imageDC.SetTextColor(RGB(0,0,0)); //
imageDC.BitBlt(rcClip.left, rcClip.top, rcClip.Width(),
rcClip.Height(), &maskDC, rcClip.left, rcClip.top, SRCAND); // // Combine the foreground with the background
imageDC.BitBlt(rcClip.left, rcClip.top, rcClip.Width(),
rcClip.Height(), memDC, rcClip.left, rcClip.top,SRCPAINT); // Draw the final image to the screen
dc.BitBlt( rcClip.left, rcClip.top, rcClip.Width(), rcClip.Height(),
&imageDC, rcClip.left, rcClip.top, SRCCOPY );
}
else
{
dc.BitBlt( rcClip.left, rcClip.top, rcClip.Width(),
rcClip.Height(), &memDC,
rcClip.left, rcClip.top, SRCCOPY );
}
}步骤5: 处理滚动消息
void CTreeCtrlX::OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar)
{
if( m_bitmap.m_hObject != NULL )
InvalidateRect(NULL);
CTreeCtrl::OnVScroll(nSBCode, nPos, pScrollBar);
}void CTreeCtrlX::OnHScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar)
{
if( m_bitmap.m_hObject != NULL )
InvalidateRect(NULL);
CTreeCtrl::OnHScroll(nSBCode, nPos, pScrollBar);
}步骤6: 处理TVN_ITEMEXPANDING消息
void CTreeCtrlX::OnItemExpanding(NMHDR* pNMHDR, LRESULT* pResult)
{
NM_TREEVIEW* pNMTreeView = (NM_TREEVIEW*)pNMHDR; if( m_bitmap.m_hObject != NULL )
InvalidateRect(NULL); *pResult = 0;
}步骤7: 加入WM_ERASEBKGND响应函数
BOOL CTreeCtrlX::OnEraseBkgnd(CDC* pDC)
{
if( m_bitmap.m_hObject != NULL )
return TRUE;
return CTreeCtrl::OnEraseBkgnd(pDC);
}步骤8: 处理WM_QUERYNEWPALETTE & WM_PALETTECHANGED消息
BOOL CTreeCtrlX::OnQueryNewPalette()
{
CClientDC dc(th
解决方案 »
- 在公司实习2个月后,公司给我看一个程序代码,请指教
- ado连接sql数据库
- 怎样用文件路径获得文件的Position
- 高分求潘爱民的<<com原理与应用>>中的例子源代码!!!!
- 请望高人赐教,在用C#开发软件时,MFC中的类和函数是否能在C#程序中使用?还有,C++标准类库中的类和函数是否也能用在C#程序中?
- 在List 控件中响应双击并删除一条记录问题
- 最简单的com实例疑问
- vc2008中跨文件夹DLL调用的若干问题
- MFC里面有没有一个可以隐藏静态文本框的函数呢?
- 求教一个与数理统计有关的c编程问题
- 在sdk程式中,使用CButton派生出一個新類時,怎樣處理CButton本身未處理的消息.
- 用连接点机制到底能不能实现跨机器的回调???
整理后的代码如下#if !defined(AFX_ODLISTCTRL_H__A16CA812_6254_4F10_9F43_CD53DF0316E1__INCLUDED_)
#define AFX_ODLISTCTRL_H__A16CA812_6254_4F10_9F43_CD53DF0316E1__INCLUDED_#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
// ODListCtrl.h : header file
///////////////////////////////////////////////////////////////////////////////
// CODListCtrl windowclass AFX_EXT_CLASS CODListCtrl : public CListCtrl
{
// Construction
public:
CODListCtrl();// Attributes
public:// Operations
public:// Overrides
// ClassWizard generated virtual function overrides
//{{AFX_VIRTUAL(CODListCtrl)
protected:
virtual BOOL OnNotify(WPARAM wParam, LPARAM lParam, LRESULT* pResult);
//}}AFX_VIRTUAL// Implementation
public:
virtual ~CODListCtrl();
virtual void DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct);
void RepaintSelectedItems(); // Generated message map functions
protected:
//{{AFX_MSG(CODListCtrl)
afx_msg void OnPaint();
afx_msg void OnSetFocus(CWnd* pOldWnd);
afx_msg void OnKillFocus(CWnd* pNewWnd);
afx_msg BOOL OnEraseBkgnd(CDC* pDC);
//}}AFX_MSG DECLARE_MESSAGE_MAP()
public:
BOOL SetBkImage(LPCTSTR lpszResourceName);
BOOL SetBkImage(UINT nIDResource);
enum EHighlight {HIGHLIGHT_NORMAL, HIGHLIGHT_ALLCOLUMNS, HIGHLIGHT_ROW};
int m_nHighlight; // Indicate type of selection highlighting
int m_nBack;
CBitmap m_bitmap;
int m_nBmpWidth, m_nBmpHeight;
};///////////////////////////////////////////////////////////////////////////////{{AFX_INSERT_LOCATION}}
// Microsoft Visual C++ will insert additional declarations immediately before the previous line.#endif // !defined(AFX_ODLISTCTRL_H__A16CA812_6254_4F10_9F43_CD53DF0316E1__INCLUDED_)
//#include "stdafx.h"
#include "ODListCtrl.h"#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif/////////////////////////////////////////////////////////////////////////////
// CODListCtrlCODListCtrl::CODListCtrl()
{
m_nHighlight = HIGHLIGHT_NORMAL;
m_nBack = 0;
}CODListCtrl::~CODListCtrl()
{
}
BEGIN_MESSAGE_MAP(CODListCtrl, CListCtrl)
//{{AFX_MSG_MAP(CODListCtrl)
ON_WM_PAINT()
ON_WM_SETFOCUS()
ON_WM_KILLFOCUS()
ON_WM_ERASEBKGND()
//}}AFX_MSG_MAP
END_MESSAGE_MAP()/////////////////////////////////////////////////////////////////////////////
// CODListCtrl message handlersvoid CODListCtrl::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 rcWnd;
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(&rcWnd);
rcHighlight = rcBounds;
rcHighlight.left = rcLabel.left;
rcHighlight.right = rcWnd.right;
break;
default:
rcHighlight = rcLabel;
} // Draw bitmap in the background if one has been set
if(m_nBack == 4 && m_bitmap.m_hObject != NULL )
{
CDC tempDC;
tempDC.CreateCompatibleDC(pDC);
tempDC.SelectObject( &m_bitmap ); CRect rcClient;
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();
CRect rcFirstItem;
GetItemRect(0, rcFirstItem, LVIR_BOUNDS);
for( int i = rcFirstItem.left; i < rcClient.right; i += m_nBmpWidth )
for( int j = rcFirstItem.top; j < rcClient.bottom; j += m_nBmpHeight )
pDC->BitBlt( i, j, m_nBmpWidth, m_nBmpHeight, &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
switch(m_nBack){
case 0:
case 3:
pDC->FillRect(rcHighlight, &CBrush(::GetSysColor(COLOR_WINDOW)));
break;
case 1:
{
CRect rcClient, rcRow = rcItem;
GetClientRect(&rcClient);
rcRow.right = rcClient.right; pDC->FillRect(rcRow, &CBrush(RGB(255,255,0)));
}
break;
case 2:
{
CRect rcClient, rcRow = rcItem;
GetClientRect(&rcClient);
rcRow.right = rcClient.right; pDC->FillRect(rcRow, &CBrush(nItem%2 ? ::GetSysColor(COLOR_WINDOW) :
RGB(255,255,0)));
}
break;
} // Set clip region
rcCol.right = rcCol.left + GetColumnWidth(0);
CRgn rgn;
rgn.CreateRectRgnIndirect(&rcCol);
pDC->SelectClipRgn(&rgn);
rgn.DeleteObject();
if(m_nBack == 3){
// Draw column background
if( !bHighlight )
pDC->FillRect(rcCol, &CBrush(RGB(255,255,0)));
}
// 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; if(m_nBack == 3){
// Draw column background
if( !bHighlight || ( bHighlight && m_nHighlight == HIGHLIGHT_NORMAL ) )
if( (nColumn+1) % 2 )
pDC->FillRect(rcCol, &CBrush(RGB(255,255,0)));
}
if(m_nBack == 4){
// Draw the background if needed
if( m_bitmap.m_hObject == NULL && m_nHighlight == HIGHLIGHT_NORMAL )
pDC->FillRect(rcCol, &CBrush(::GetSysColor(COLOR_WINDOW)));
} // Draw the background if needed
// if( 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 );
}
{
CRect rcBounds, rcLabel; // Invalidate focused item so it can repaint
int nItem = GetNextItem(-1, LVNI_FOCUSED); if(nItem != -1)
{
GetItemRect(nItem, rcBounds, LVIR_BOUNDS);
GetItemRect(nItem, rcLabel, LVIR_LABEL);
rcBounds.left = rcLabel.left; InvalidateRect(rcBounds, FALSE);
} // Invalidate selected items depending on LVS_SHOWSELALWAYS
if(!(GetStyle() & LVS_SHOWSELALWAYS))
{
for(nItem = GetNextItem(-1, LVNI_SELECTED);
nItem != -1; nItem = GetNextItem(nItem, LVNI_SELECTED))
{
GetItemRect(nItem, rcBounds, LVIR_BOUNDS);
GetItemRect(nItem, rcLabel, LVIR_LABEL);
rcBounds.left = rcLabel.left; InvalidateRect(rcBounds, FALSE);
}
} UpdateWindow();
}
void CODListCtrl::OnPaint()
{
// in full row select mode, we need to extend the clipping region
// so we can paint a selection all the way to the right
if (m_nHighlight == HIGHLIGHT_ROW &&
(GetStyle() & LVS_TYPEMASK) == LVS_REPORT )
{
CRect rcBounds;
GetItemRect(0, rcBounds, LVIR_BOUNDS); CRect rcClient;
GetClientRect(&rcClient);
if(rcBounds.right < rcClient.right)
{
CPaintDC dc(this); CRect rcClip;
dc.GetClipBox(rcClip); rcClip.left = min(rcBounds.right-1, rcClip.left);
rcClip.right = rcClient.right; InvalidateRect(rcClip, FALSE);
}
} CListCtrl::OnPaint();
}void CODListCtrl::OnSetFocus(CWnd* pOldWnd)
{
CListCtrl::OnSetFocus(pOldWnd);
// check if we are getting focus from label edit box
if(pOldWnd!=NULL && pOldWnd->GetParent()==this)
return; // repaint items that should change appearance
if((GetStyle() & LVS_TYPEMASK)==LVS_REPORT)
RepaintSelectedItems();
}void CODListCtrl::OnKillFocus(CWnd* pNewWnd)
{
CListCtrl::OnKillFocus(pNewWnd); // check if we are losing focus to label edit box
if(pNewWnd != NULL && pNewWnd->GetParent() == this)
return; // repaint items that should change appearance
if((GetStyle() & LVS_TYPEMASK) == LVS_REPORT)
RepaintSelectedItems();
}BOOL CODListCtrl::SetBkImage(UINT nIDResource)
{
return SetBkImage( (LPCTSTR)nIDResource );
}BOOL CODListCtrl::SetBkImage(LPCTSTR lpszResourceName)
{
// If this is not the first call then Delete GDI objects
if(m_bitmap.m_hObject != NULL) m_bitmap.DeleteObject();
m_bitmap.LoadBitmap(lpszResourceName); BITMAP bm;
m_bitmap.GetBitmap( &bm );
m_nBmpWidth = bm.bmWidth;
m_nBmpHeight = bm.bmHeight; Invalidate();
return TRUE;
}BOOL CODListCtrl::OnNotify(WPARAM wParam, LPARAM lParam, LRESULT* pResult)
{
if(m_nBack == 4){
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);
}BOOL CODListCtrl::OnEraseBkgnd(CDC* pDC)
{
if(m_nBack == 4 && m_bitmap.m_hObject != NULL )
return TRUE;
return CListCtrl::OnEraseBkgnd(pDC);
}注意这是个用于演示的类,当 m_nBack 为 5 时 可显示透明背景图
CODListCtrl m_lst3m_lst3.SetImageList(&m_imglst, LVSIL_SMALL);
m_lst3.GetClientRect(&r);
nWidth = r.Width() / 3;
m_lst3.InsertColumn(0, "Col 1", LVCFMT_LEFT, nWidth);
m_lst3.InsertColumn(1, "Col 2", LVCFMT_LEFT, nWidth);
m_lst3.InsertColumn(2, "Col 3", LVCFMT_LEFT, nWidth);
for(i = 0; i < 9; i++){
CString str;
str.Format("Item %d", i + 1);
m_lst3.InsertItem(i, str, i % 8);
str.Format("Sub %d1", i + 1);
m_lst3.SetItemText(i, 1, str);
str.Format("Sub %d2", i + 1);
m_lst3.SetItemText(i, 2, str);
}
m_lst3.SetExtendedStyle(LVS_EX_FULLROWSELECT);
m_lst3.SetBkImage(IDB_MISCLISTCTRL2_BITMAP1);
m_lst3.m_nBack = 5;此外 CListCtrl::SetBkImage在xp common controls V6下也能显示背景图
谢谢你的程序,不知你的程序运行过没有?我试了一下,在ICON方式下是不行的.
我很久以前,在这个坛子也问过相同的问题,有幸得到了MS专家的回答,他说clistctrl在ICON方式下的自画是无效的,在MASN上也有说.我现在已经找不到那个贴子了,手头上也没有MSDN,所以也找不到相关的说明.我刚才在程序中跟踪了一下,发现程序并没有执行void CODListCtrl::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct),这个你可以试一下,除了ICON方式以外的其他方式应该是可以的,但我没有试,因为我要的就是ICON方式.
我想要的不是ctreectrl而是clistctrl
SetTextBkColor(CLR_NONE);
你问的是哪个 MS专家,“有幸得到了MS专家的回答,他说clistctrl在ICON方式下的自画是无效的,在MASN上也有说.” 他要不就是水平太差,要不就是不想告诉你。
我就做过在 ICON方式下面自己画 CListCtrl 的Item, 效果和 ACDSee 的图片预览窗口一样(你要的就这效果?),连文本都是自己画的。
误人子弟!
你是用NM_CUSTOMDRAW 还是用DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct),我用DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct)来做,我跟踪了一下,发现程序的确没有进行DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct)中.用NM_CUSTOMDRAW 我没有试过.你能不能给个例子呢,十分感谢.
说实话,来这儿我是聊天的, 问问题我很少会在这儿。
http://expert.csdn.net/Expert/topic/649/649062.xml?temp=.0342676
你好好到下面看看:http://www.codeproject.com/listctrl/
你想把CListCtrl 做成什么样都行,这可是有代码的。多看几个, 你也是专家.