www.pudn.com > CListCtrlTest.rar > MyListCtrl.cpp


// MyListCtrl.cpp : implementation file 
// 
 
#include "stdafx.h" 
#include "CListCtrlTest.h" 
#include "MyListCtrl.h" 
#include  
#include  
using namespace std; 
 
#ifdef _DEBUG 
#define new DEBUG_NEW 
#undef THIS_FILE 
static char THIS_FILE[] = __FILE__; 
#endif 
 
///////////////////////////////////////////////////////////////////////////// 
// CMyListCtrl 
 
CMyListCtrl::CMyListCtrl() 
{ 
	m_bkColor = RGB(255, 255, 255); //背景白色 
	m_TextColor = RGB(0, 0, 0);  //默认文字颜色黑色 
	m_bGridPro = false;          //默认无网格 
	m_ColumnCount = 3;           //默认列数为0    
	m_GridColor = RGB(128, 128, 128);  
 
} 
 
CMyListCtrl::~CMyListCtrl() 
{ 
} 
 
 
BEGIN_MESSAGE_MAP(CMyListCtrl, CListCtrl) 
	//{{AFX_MSG_MAP(CMyListCtrl) 
	ON_WM_DESTROY() 
	ON_WM_PAINT() 
	//}}AFX_MSG_MAP 
END_MESSAGE_MAP() 
 
///////////////////////////////////////////////////////////////////////////// 
// CMyListCtrl message handlers 
 
//动态判断输出图片的位置,并输出 
void * CMyListCtrl::ShowImage( const char * filepath, int nitem, int subitem, bool flag )  //flag = true 文字在图标前 
																						  //默认flag = true		 
{ 
	CRect subitemrect = 0;  //子列 
	CPoint point = 0;       //图标输出坐标 
	 
	//计算列宽 
	int columnwidth = 0;    //列宽 
	columnwidth = GetColumnWidth(subitem); 
 
	//算列字体宽 
	int length = 0;         //文字宽 
	CString str = ""; 
	str = GetItemText(nitem, subitem); 
	CClientDC dc(this); 
	CSize size = 0; 
	size = dc.GetTextExtent(str); 
	length = size.cx;   //length = GetStringWidth(str); 测试出来宽度不准确  
	 
	if(flag)//图片在文字后 
	{	 
		//判断字体宽度和列宽度,决定是否进行在指定位置化图 
		//栏宽度小于图标出现位置 
		if(columnwidth <= (length  + 13 + 5 )) //+13图片宽度,+5为文字和图片间隔宽度  
			return 0; 
		else  
		{ 
 
			if(subitem == 0)  //所要绘制为第一列时 
			{	 
				CPoint pointtemp = 0; 
				if( GetItemPosition(nitem, &pointtemp) ) 
				{ 
						point.x = pointtemp.x + length + 5 ;  
						point.y = pointtemp.y; 
				} 
				else 
				{ 
					AfxMessageBox("获得所绘坐标失败!"); 
					return 0; 
				} 
			} 
			else 
			{ 
				if( GetSubItemRect(nitem, subitem, LVIR_BOUNDS, subitemrect) ) 
				{ 
					point.x = subitemrect.left + length +5;   
					point.y = subitemrect.top; 
				} 
				else 
				{ 
					AfxMessageBox("获得所绘坐标失败!"); 
					return 0; 
				} 
			} 
		} 
	} 
	else//图标在文字前 
	{ 
		if(columnwidth <= 13 + 5) //+13图片宽度, +5为文字和图片间隔宽度  
			return 0; 
		else 
		{ 
			if(subitem == 0)  //所要绘制为第一列时 
			{	 
				CPoint pointtemp = 0; 
				if( GetItemPosition(nitem, &pointtemp) ) 
				{ 
						point.x = pointtemp.x ;  
						point.y = pointtemp.y; 
				} 
				else 
				{ 
					AfxMessageBox("获得所绘坐标失败!"); 
					return 0; 
				} 
			} 
			else 
			{ 
				if( GetSubItemRect(nitem, subitem, LVIR_BOUNDS, subitemrect) ) 
				{ 
					point.x = subitemrect.left ; 
					point.y = subitemrect.top; 
				} 
				else 
				{ 
					AfxMessageBox("获得所绘坐标失败!"); 
					return 0; 
				} 
			} 
		} 
 
	} 
     
	//加载bmp 
	CBitmap bmp; 
	HBITMAP   hbmp   =  (HBITMAP)::LoadImage(AfxGetInstanceHandle(),      
						filepath,   IMAGE_BITMAP,   0,   0,   LR_CREATEDIBSECTION|LR_LOADFROMFILE);    
	if (hbmp != NULL) 
	{ 
	  bmp.Attach(hbmp); 
       
      CDC dcMemory, *pDC; 
	  pDC = this->GetDC(); 
      dcMemory.CreateCompatibleDC(pDC); 
      
      CBitmap* pOldBitmap = dcMemory.SelectObject(&bmp); 
 
	  pDC->BitBlt(point.x, point.y, 13, 13, &dcMemory,  
         0, 0, SRCCOPY); 
	  
      dcMemory.SelectObject(pOldBitmap); 
	  this->ReleaseDC(pDC); 
	  this->ReleaseDC(&dcMemory); 
	} 
	else 
	{ 
      TRACE0("ERROR: Where's IDB_BITMAP1?\n"); 
	  AfxMessageBox("bitmap loading fail!"); 
	} 
	 
	return 0; 
	/* 
	DWORD dwStyle = WS_BORDER|WS_CHILD|WS_VISIBLE|WS_VSCROLL 
					|CBS_DROPDOWNLIST|CBS_DISABLENOSCROLL; 
	CComboBox *pList = new CComboBox(); 
	pList->Create( dwStyle, CRect(point.x, point.y, 260, 30), this, IDC_IPEDIT ); 
	pList->SetItemHeight( -1, 2); 
	//pList->SetHorizontalExtent( GetColumnWidth( nCol )); 
	pList->ShowWindow(SW_SHOW);*/ 
	/* 
	CBitmap bitmap; 
	bitmap.LoadBitmap(IDB_BITMAP2); 
	CDC * cdc1; 
	cdc1 = this->GetDC(); 
	CBrush brush(&bitmap); 
	cdc1->SelectObject(&brush); 
	cdc1->Rectangle(point.x, point.y, 260, 30); 
	this->ReleaseDC(cdc1); 
	rect11 = CRect(point.x, point.y, 260, 30); 
	this->ClientToScreen(&rect11); 
	*/ 
} 
int CMyListCtrl::AddImgInfo( char * filepath, const int & nitem, const int &subitem,  bool flag) 
{ 
	CMyStorgeImg * data = new CMyStorgeImg; 
	data->m_nitem = nitem; 
	data->m_subitem = subitem; 
	data->m_pfilepath = filepath; 
	data->m_flag = flag; 
	return m_pArrayImg.Add(data); 
} 
int CMyListCtrl::AddTextInfo(const CString &str, const int & nitem, const int &subitem, const CRect & textrect, bool flag, COLORREF rc, bool ImpView) 
{ 
	CMyStorgeText * data = new CMyStorgeText; 
	data->m_nitem = nitem; 
	data->m_subitem = subitem; 
	data->m_textrect = CRect(textrect); 
	data->m_str = str; 
	data->m_flag = flag; 
	data->m_ImpColor = rc; 
	data->m_bImpView = ImpView; 
	return m_pArrayText.Add(data); 
} 
bool CMyListCtrl::GetDrawTextRect(CRect * rect, const CString & str,  int nitem, int subitem, bool flag )//默认flag = true 
{	 
	int width = 0;	 
	CRect temprect = 0; 
	 
	if (GetSubItemRect(nitem, subitem, LVIR_LABEL, temprect) != 0) 
	{ 
		if(flag) //文字在图片前 
		{ 
			*rect = CRect(temprect); 
			 
		} 
		else    //文字在图片后 
		{ 
			*rect = CRect(temprect); 
			rect->left += 13 + 5;  //+13图片宽,+5图片和文字间隔 
			 
		} 
		return true; 
	} 
	else 
	{ 
		*rect = 0; 
		return false; 
	} 
} 
 
bool CMyListCtrl::SetBkColorEx(COLORREF cr) 
{ 
	m_bkColor = cr; 
	this->Invalidate(); 
	return true; 
} 
bool CMyListCtrl::SetTextColorEx(COLORREF cr) 
{ 
	m_TextColor = cr; 
	this->Invalidate(); 
	//this->UpdateData(); 
	//this->PostMessage(WM_PAINT); 
	return true; 
} 
bool CMyListCtrl::SetGridColorEx(COLORREF cr) 
{ 
	m_GridColor = cr; 
	this->Invalidate(); 
	return true; 
} 
void CMyListCtrl::SetGridPro(bool GridPro) 
{ 
	m_bGridPro = GridPro;  //网格属性 
	this->Invalidate(); 
} 
 
void CMyListCtrl::SetColumnCount(int count) 
{ 
	m_ColumnCount = count; 
} 
void CMyListCtrl::OnDestroy()  
{ 
	CListCtrl::OnDestroy(); 
	 
	// TODO: Add your message handler code here 
	for(int i = 0; i < m_pArrayText.GetSize(); i++) 
	{ 
		delete ((CMyStorgeText*)m_pArrayText.GetAt(i)); 
		 
	} 
	  
	for(int j = 0; j < m_pArrayImg.GetSize(); j++) 
	{ 
		delete ((CMyStorgeImg*)m_pArrayImg.GetAt(j)); 
	} 
} 
 
void CMyListCtrl::OnPaint()  
{ 
	CPaintDC dc(this); // device context for painting 
 
	COLORREF  syscolor = dc.GetBkColor(); 
	DWORD dwStyle = ::GetWindowLong(m_hWnd, GWL_STYLE); 
	::SetWindowLong(m_hWnd, GWL_STYLE, dwStyle|LVS_REPORT ); 
 
	/*  //字体改变后输出后图形显示错乱 
	CFont font; 
	VERIFY(font.CreatePointFont(200, "Arial", &dc)); 
	dc.SelectObject(&font); 
	*/ 
	CFont * DefFont = dc.SelectObject(this->GetFont()); 
	//设置虚拟图片,目的是调整栏高度 
	/* 
	static int flag=2; 
	if(flag==2) 
	{//只调用一次SetImageList,否则出错 
		m_ImageList.Create(0, 20, ILC_COLORDDB|ILC_MASK, 1, 1); //20图片高度,所以拦高度也为20 
		this->SetImageList(&m_ImageList,LVSIL_SMALL); 
	} 
	flag=1; 
	*/ 
	//DWORD style = GetExtendedStyle(); 
//	this->SetExtendedStyle(style | LVS_EX_GRIDLINES); 
	 
	//设置背景色 
	CBrush brush(m_bkColor); 
	CBrush * DefBrush; 
	CPen pen(PS_SOLID , 1, m_bkColor); 
	CPen * DefPen; 
	dc.SetBkColor(m_bkColor); //设置字体背景色和CListCtrl背景色相同,保证字体不显示背景 
	DefBrush = dc.SelectObject(&brush); 
	DefPen = (CPen *)dc.SelectObject(&pen); 
	CRect ClientRect; 
	this->GetClientRect(&ClientRect); 
	dc.Rectangle(&ClientRect); 
	dc.SelectObject(DefPen); 
	dc.SelectObject(DefBrush); 
//	dc.SetBkColor(syscolor); 
 
	//设置字体颜色 
	dc.SetTextColor(m_TextColor); 
	 
	//数据变化后从新定位并绘制 
	for(int k = 0; k < m_pArrayText.GetSize(); k++) 
	{ 
		CString str; 
		str = ((CMyStorgeText*)m_pArrayText.GetAt(k))->m_str; 
	 
		CRect *rect = new CRect; 
		GetDrawTextRect( 
						rect,   
						((CMyStorgeText*)m_pArrayText.GetAt(k))->m_str, 
						((CMyStorgeText*)m_pArrayText.GetAt(k))->m_nitem, 
						((CMyStorgeText*)m_pArrayText.GetAt(k))->m_subitem, 
						((CMyStorgeText*)m_pArrayText.GetAt(k))->m_flag 
	 
						); 
		//设置字体突出显示的背景色 
 
		if( ((CMyStorgeText*)m_pArrayText.GetAt(k))->m_bImpView )  //文字需要突出显示时 
		{ 
			CRect rect22; 
 
			this->GetSubItemRect(((CMyStorgeText*)m_pArrayText.GetAt(k))->m_nitem, ((CMyStorgeText*)m_pArrayText.GetAt(k))->m_subitem , LVIR_BOUNDS, rect22 ); 
			if(0 == ((CMyStorgeText*)m_pArrayText.GetAt(k))->m_subitem )   //第一列时GetSubItemRect测出是整行的矩形区域 
			{				 
				int length; 
				length = this->GetColumnWidth(((CMyStorgeText*)m_pArrayText.GetAt(k))->m_subitem); 
				rect22.right = length; 
			} 
			CBrush  brush22( ((CMyStorgeText*)m_pArrayText.GetAt(k))->m_ImpColor ); 
			CPen pen22(PS_SOLID, 1, ((CMyStorgeText*)m_pArrayText.GetAt(k))->m_ImpColor); 
			CBrush * DefBrush22 = dc.SelectObject(&brush22); 
			CPen * DefPen22 = dc.SelectObject(&pen22); 
			dc.Rectangle(&rect22); 
			dc.SetBkColor(((CMyStorgeText*)m_pArrayText.GetAt(k))->m_ImpColor); 
 
			dc.DrawText( 
						((CMyStorgeText*)m_pArrayText.GetAt(k))->m_str, 
						rect, 
						DT_LEFT | DT_END_ELLIPSIS  //显示省略号 
					); 
			dc.SelectObject(DefBrush22); 
			dc.SelectObject(DefPen22); 
		} 
		else 
		{ 
		//	CBrush brusha(m_bkColor); 
		//	CBrush * defbrush = dc.SelectObject(&brusha); 
			dc.SetBkColor(m_bkColor);   //ListCtrl背景色 
 
			dc.DrawText( 
						((CMyStorgeText*)m_pArrayText.GetAt(k))->m_str, 
						rect, 
						DT_LEFT | DT_END_ELLIPSIS  //显示省略号 
					); 
		//	dc.SelectObject(defbrush); 
		} 
 
		delete rect; 
 
		 
	} 
	 
	//显示图片 
  	for(int j = 0; j < m_pArrayImg.GetSize(); j++) 
  	{ 
		//ShowImage(const char * filepath, int nitem, int subitem, bool flag ) 
  		ShowImage(   
  					((CMyStorgeImg*)m_pArrayImg.GetAt(j))->m_pfilepath, 
  					((CMyStorgeImg*)m_pArrayImg.GetAt(j))->m_nitem, 
  					((CMyStorgeImg*)m_pArrayImg.GetAt(j))->m_subitem, 
					((CMyStorgeImg*)m_pArrayImg.GetAt(j))->m_flag 
					); 
	} 
 
	//绘制网格线 
	if(m_bGridPro && (m_ColumnCount != 0)) 
	{ 
		CRect rect; 
		CPen pen(PS_SOLID, 1, m_GridColor); 
		CPen * DefPen = dc.SelectObject(&pen); 
		//绘制行 
		for(int p = 0; p < this->GetItemCount(); p++) 
		{ 
			this->GetItemRect(p, &rect, LVIR_BOUNDS); 
			 
			dc.MoveTo(rect.left, rect.top); 
			dc.LineTo(rect.right, rect.top); 
			dc.MoveTo(rect.left, rect.bottom);  //绘制最后一行底 
			dc.LineTo(rect.right, rect.bottom); 
		} 
		//绘制列 
		for(int column = 0; column < m_ColumnCount; column++) 
		{ 
			this->GetSubItemRect(0, column, LVIR_BOUNDS, rect); 
			CRect temprect; 
			this->GetItemRect(GetItemCount() - 1, &temprect, LVIR_BOUNDS);  //最后一行的矩形区域坐标 
			//绘制左边线 
			dc.MoveTo(rect.left, rect.top); 
			dc.LineTo(rect.left, temprect.bottom ); 
			//绘制右边线 
			dc.MoveTo(rect.right, rect.top); 
			dc.LineTo(rect.right, temprect.bottom); 
		} 
		dc.SelectObject(DefPen); 
	} 
	//dc.SetBkColor(syscolor); 
	//设置子栏背景色 
 
	//CListCtrl一创建起来就绘制网格 
	if(m_ColumnCount != 0) 
	{ 
		CRect rect; 
		CRect rect1; 
		CRect rect2; 
		CPen pen(PS_SOLID, 1, RGB(255, 0, 0)); 
		CPen * DefPen = dc.SelectObject(&pen); 
		//绘制行 
		if(this->m_pArrayText.GetSize() != 0)  //避免画行时每栏高度和字体背景色不一致,精确的画 
		{ 
			this->GetClientRect(&rect); 	 
			this->GetItemRect(0, &rect2, LVIR_BOUNDS); 
			this->GetHeaderCtrl()->GetClientRect(&rect1); 
			rect.top  = rect.top + (rect1.bottom - rect1.top); 
			rect.right = rect1.right - rect1.left; 
			for(int row = 0; row < (rect.bottom - rect.top) / (rect2.bottom - rect2.top) + 1; row++) 
			{ 
				dc.MoveTo(rect.left, rect.top + (rect2.bottom - rect2.top) * row); 
				dc.LineTo(rect.right, rect.top +(rect2.bottom - rect2.top) * row); 
			} 
		} 
	 
		else //粗略的绘制行 原因是没加数据之前,算不出每行的高 
		{ 
			this->GetClientRect(&rect); 
			this->GetHeaderCtrl()->GetClientRect(&rect1); 
			//rect.left = rect.left; 
			rect.top  = rect.top + (rect1.bottom - rect1.top); 
			rect.right = rect1.right - rect1.left; 
			//rect.bottom = rect.bottom; 
			for(int row = 0; row < rect.bottom - rect.top/20 + 1; row++) 
			{ 
				dc.MoveTo(rect.left, rect.top + 20 * row); 
				dc.LineTo(rect.right, rect.top + 20 * row); 
			} 
		} 
		 
		//绘制列 
		CRect temprect; 
		for(int column = 0; column < m_ColumnCount; column++) 
		{ 
			this->GetSubItemRect(0, column, LVIR_BOUNDS, rect); 
			this->GetClientRect(&temprect); 
			//绘制左边线 
			dc.MoveTo(rect.left, rect.top); 
			dc.LineTo(rect.left, temprect.bottom ); 
			 
			//绘制右边线 
			dc.MoveTo(rect.right , rect.top); 
			dc.LineTo(rect.right , temprect.bottom); 
	 
		} 
		dc.SelectObject(DefPen); 
	} 
	 
	dc.SelectObject(DefFont); 
	dc.SetBkColor(syscolor); 
/* 
	CBrush brush(m_bkColor); 
	CBrush * DefBrush; 
	CPen pen(PS_SOLID , 1, m_bkColor); 
	CPen * DefPen; 
	dc.SetBkColor(m_bkColor); //设置字体背景色和CListCtrl背景色相同,保证字体不显示背景 
	DefBrush = dc.SelectObject(&brush); 
	DefPen = (CPen *)dc.SelectObject(&pen); 
	CRect ClientRect; 
	this->GetClientRect(&ClientRect); 
	dc.Rectangle(&ClientRect); 
	dc.SelectObject(DefPen); 
	dc.SelectObject(DefBrush); 
	*/ 
 
	// Do not call CListCtrl::OnPaint() for painting messages 
}