如何从网格线到图像中删除小空间? [英] How remove small space from line of grid to image?

查看:115
本文介绍了如何从网格线到图像中删除小空间?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

嗨!

我已将图片添加到

Hi!
I have added image to row in second column of

CListCtrl

第二列的行中。但是我可以在

. But I can see a small space between image and grid in

CListCtrl

中看到图像和网格之间的小空间。我该如何删除它?

. How can I remove it?

iIndent

没有帮助!



您还可以在选择项目时看到更宽的格线! br />
坦克你!

doesn't help!

Also you can see wider gride line when selection an item!
Tank you!

推荐答案

没问题,这里就是



标题文件:



No problem, here goes

The header file:

//===============================================================================
// ListCtrlHDOD.h : List Control with Header Drag-Drop, Owner-Draw Header, 
//					Column Show/Hide -w- Context Menu, Header Height Adjustment
//===============================================================================
#ifndef ___LISTCTRLHDOD_H___
#define ___LISTCTRLHDOD_H___
#pragma once

//===============================================================================
// CColumnData
//===============================================================================
class CColumnData : public CObject
{
public:
	CColumnData()
	{
		m_bHidden		= FALSE;
		m_bDisableHide	= FALSE;
		m_bResizeable	= TRUE;
		m_bSortable		= TRUE;
		m_iMinWidth		= 30;
		m_cstrToolTip	= _T("");
		m_iFormat		= LVCFMT_LEFT;
		m_iDefWidth		= 0;
		m_iCurWidth		= 0;
	}

	BOOL		m_bHidden;
	BOOL		m_bDisableHide;
	BOOL		m_bResizeable;
	BOOL		m_bSortable;
	int			m_iMinWidth;
	CString		m_cstrToolTip;

	int			m_iFormat;
	int			m_iDefWidth;
	int			m_iCurWidth;
};


//===============================================================================
// CHeaderCtrlHDOD
//===============================================================================
class CHeaderCtrlHDOD : public CHeaderCtrl
{
	friend class CListCtrlHDOD;
public:
	DECLARE_DYNAMIC(CHeaderCtrlHDOD)

	// Construction / Destruction
	CHeaderCtrlHDOD();
	virtual ~CHeaderCtrlHDOD();

protected:
	int				m_iHeight;
	CFont			m_Font;
	float			m_fFontHeight;
	COLORREF		m_crText;
	COLORREF		m_crLineLight;
	COLORREF		m_crLineDark;
	COLORREF		m_crBackStart;
	COLORREF		m_crBackEnd;

public:	
	// Implementation
	void SetHeight(int iHeight);

protected:
	// Overrides
	BOOL SubclassDlgItem(UINT nID, CWnd* pParent);

	// Messages
	DECLARE_MESSAGE_MAP()
	afx_msg void OnDestroy();
	afx_msg LRESULT OnLayout(WPARAM wParam, LPARAM lParam);
	afx_msg void OnPaint();
	afx_msg BOOL OnEraseBkgnd(CDC* pDC);
	afx_msg BOOL OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message);	
	afx_msg void OnHdnBeginDrag(NMHDR* pNMHDR, LRESULT* pResult);
	afx_msg void OnHdnItemDblClick(NMHDR* pNMHDR, LRESULT* pResult);
};


//===============================================================================
// CListCtrlHDOD
//===============================================================================
class CListCtrlHDOD : public CListCtrl
{
	friend class CHeaderCtrlHDOD;
public:
	DECLARE_DYNAMIC(CListCtrlHDOD)

	// Construction / Destruction
	CListCtrlHDOD();
	virtual ~CListCtrlHDOD();

protected:
	CHeaderCtrlHDOD		m_HeaderCtrl;

	// Properties
	int					m_iSortCol;
	bool				m_bSortAsc;
	int					m_iItemHeight;
	CString				m_cstrFontName;
	float				m_fItemFontHeight;
	float				m_fMenuFontHeight;
	COLORREF			m_crItemText;
	COLORREF			m_crDisItemText;
	COLORREF			m_crSelItemText;
	COLORREF			m_crItemBack;
	COLORREF			m_crSelItemBack;
	COLORREF			m_crMenuBack;
	COLORREF			m_crMenuBorder;
	COLORREF			m_crMenuBarStart;
	COLORREF			m_crMenuBarEnd;
	int					m_iMenuItemWidth;
	CMenu				m_HeaderMenu;
	PFNLVCOMPARE		m_pfnCompareFunc;

public:	
	// Property Accessor Functions
	int GetSortColumn(){return m_iSortCol;}
	void SetSortColumn(int i){m_iSortCol=i;}
	bool GetSortAscending(){return m_bSortAsc;}
	void SetSortAscending(bool b){m_bSortAsc=b;}
	int GetItemHeight(){return m_iItemHeight;}
	void SetItemHeight(int iHeight);
	COLORREF GetItemTextColor(){return m_crItemText;}
	void SetItemTextColor(COLORREF cr){__SET_VIS_PROP(m_crItemText, cr)};
	COLORREF GetDisabledItemTextColor(){return m_crDisItemText;}
	void SetDisabledItemTextColor(COLORREF cr){__SET_VIS_PROP(m_crDisItemText, cr)};
	COLORREF GetSelectedItemTextColor(){return m_crSelItemText;}
	void SetSelectedItemTextColor(COLORREF cr){__SET_VIS_PROP(m_crSelItemText, cr)};
	COLORREF GetItemBackColor(){return m_crItemBack;}
	void SetItemBackColor(COLORREF cr){__SET_VIS_PROP(m_crItemBack, cr)};
	COLORREF GetSelectedItemBackColor(){return m_crSelItemBack;}
	void SetSelectedItemBackColor(COLORREF cr){__SET_VIS_PROP(m_crSelItemBack, cr)};
	void SetCompareFunction(PFNLVCOMPARE pfn){m_pfnCompareFunc = pfn;}

	// Header Property Accessor Functions
	int GetHeaderHeight(){return m_HeaderCtrl.m_iHeight;}
	void SetHeaderHeight(int iHeight){m_HeaderCtrl.SetHeight(iHeight);}
	float GetHeaderFontHeight(){return m_HeaderCtrl.m_fFontHeight;}
	void SetHeaderFontHeight(float fHeight){m_HeaderCtrl.m_fFontHeight=fHeight;}

	// Implementation
	int InsertColumn(int nCol, LPCTSTR lpszColumnHeading, int nFormat, 
		int nWidth, int nSubItem, BOOL bHidden = FALSE, BOOL bDisableHide = FALSE,
		BOOL bResizeable = TRUE, BOOL bSortable = TRUE, int iMinWidth = 30, 
		CString cstrToolTip = _T(""));
	BOOL DeleteColumn(int nCol);
	void SortList();

protected:
	// Sort Callback
	static int CALLBACK CompareFunc(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort);

	// Overrides
	virtual void PreSubclassWindow();
	virtual BOOL OnCommand(WPARAM wParam, LPARAM lParam);

	// Messages
	DECLARE_MESSAGE_MAP()
	afx_msg void OnDestroy();
	afx_msg void OnPaint();
	afx_msg BOOL OnLvnColumnClick(NMHDR* pNMHDR, LRESULT* pResult);
	afx_msg BOOL OnLvnItemChanged(NMHDR *pNMHDR, LRESULT *pResult);
	afx_msg void OnHdnBegintrack(NMHDR* pNMHDR, LRESULT* pResult);
	afx_msg void OnHdnTrack(NMHDR* pNMHDR, LRESULT *pResult);
	afx_msg void OnContextMenu(CWnd* pWnd, CPoint point);
	afx_msg void OnDrawItem(int nIDCtl, DRAWITEMSTRUCT* pDI);
	afx_msg void OnMeasureItem(int nIDCtl, MEASUREITEMSTRUCT* pMI);
	afx_msg void MeasureItem(MEASUREITEMSTRUCT* pMI);
};


#endif // ___LISTCTRLHDOD_H___





cpp文件:



The cpp file:

//===============================================================================
// ListCtrlHDOD.cpp : 
//===============================================================================
#include "stdafx.h"
#include "ListCtrlHDOD.h"
#include "DbConfig.h"

//===============================================================================
// CHeaderCtrlHDOD 
//===============================================================================
BEGIN_MESSAGE_MAP(CHeaderCtrlHDOD, CHeaderCtrl)
	ON_WM_DESTROY()
	ON_MESSAGE(HDM_LAYOUT, &CHeaderCtrlHDOD::OnLayout)
	ON_WM_PAINT()
	ON_WM_ERASEBKGND()
	ON_WM_SETCURSOR()
	ON_NOTIFY(HDN_BEGINDRAG, 0, &CHeaderCtrlHDOD::OnHdnBeginDrag)
	ON_NOTIFY(HDN_ITEMDBLCLICKA, 0, &CHeaderCtrlHDOD::OnHdnItemDblClick)
	ON_NOTIFY(HDN_ITEMDBLCLICKW, 0, &CHeaderCtrlHDOD::OnHdnItemDblClick)
END_MESSAGE_MAP()

IMPLEMENT_DYNAMIC(CHeaderCtrlHDOD, CHeaderCtrl)

//=================================================
// Construction / Destruction
//=================================================
CHeaderCtrlHDOD::CHeaderCtrlHDOD()
{
	m_iHeight			= ((CApp*)AfxGetApp())->m_iListHeaderHeight;
	m_fFontHeight		= ((CApp*)AfxGetApp())->m_fListHeaderFontHeight;
	m_crText			= ((CApp*)AfxGetApp())->m_crListHeaderText;
	m_crLineLight		= RGB(255,255,255);//((CApp*)AfxGetApp())->m_crListHeaderDivLight;
	m_crLineDark		= RGB(157,157,161);//((CApp*)AfxGetApp())->m_crListHeaderDivDark;
	m_crBackStart		= ((CApp*)AfxGetApp())->m_crListHeaderStart;
	m_crBackEnd			= ((CApp*)AfxGetApp())->m_crListHeaderEnd;
}

CHeaderCtrlHDOD::~CHeaderCtrlHDOD()
{
}

//=================================================
// Overrides
//=================================================
BOOL CHeaderCtrlHDOD::SubclassDlgItem(UINT nID, CWnd* pParent)
{
	if(!CHeaderCtrl::SubclassDlgItem(nID, pParent))
		return FALSE;
	SetHeight(m_iHeight);
	return TRUE;
}

//=================================================
// Messages
//=================================================
void CHeaderCtrlHDOD::OnDestroy()
{
	CHeaderCtrl::OnDestroy();

	// Delete header item data
	HDITEM hdi = {0};
	hdi.mask = HDI_LPARAM;
	while(GetItemCount() > 0)
	{
		VERIFY(GetItem(0, &hdi));
		CColumnData* pColData = (CColumnData*)hdi.lParam;
		ASSERT(pColData);
		delete pColData;
		DeleteItem(0);
	}
}

LRESULT CHeaderCtrlHDOD::OnLayout(WPARAM wParam, LPARAM lParam)
{
	LRESULT lResult = CHeaderCtrl::DefWindowProc(HDM_LAYOUT, 0, lParam);

	HD_LAYOUT& hdl = *(HD_LAYOUT*)lParam;
	RECT* prc = hdl.prc;
	WINDOWPOS* pwpos = hdl.pwpos;

	pwpos->cy = m_iHeight;
	prc->top = m_iHeight;

	return lResult;
}

void CHeaderCtrlHDOD::OnPaint()
{
	CPaintDC dc(this); 
	CRect rClient;
	GetClientRect(&rClient);

	CListCtrlHDOD* pParent = (CListCtrlHDOD*)GetParent();
	bool bNoSort = ((pParent->GetStyle() & LVS_NOSORTHEADER) == LVS_NOSORTHEADER);

	// Double buffer to eliminate flashing
	CDC dcMem;
	dcMem.CreateCompatibleDC(&dc);
	CBitmap bmp;
	bmp.CreateDiscardableBitmap(&dc, 
		rClient.Width(), rClient.Height());
	dcMem.SelectObject(&bmp);

	dcMem.FillSolidRect(rClient, RGB(224,226,235));

	Graphics gfx(dcMem.GetSafeHdc());
	gfx.SetTextRenderingHint(TextRenderingHintClearTypeGridFit);
	gfx.SetSmoothingMode(SmoothingModeAntiAlias);

	Color clrBackStart, clrBackEnd;
	clrBackStart.SetFromCOLORREF(m_crBackStart);
	clrBackEnd.SetFromCOLORREF(m_crBackEnd);
	Color clrLineLight, clrLineDark;
	clrLineLight.SetFromCOLORREF(m_crLineLight);
	clrLineDark.SetFromCOLORREF(m_crLineDark);
	Pen pnLineLight(clrLineLight, 1);
	Pen pnLineDark(clrLineDark, 1);	

	for(int x = 0; x < GetItemCount(); x++)
	{
		// Get item area
		CRect rItem;
		GetItemRect(x, &rItem);

		// Get column info
		LVCOLUMN lvc = {0};
		lvc.mask = LVCF_FMT;
		pParent->GetColumn(x, &lvc);

		// Get item text
		HDITEM hdi = {0};
		TCHAR  szBuffer[256] = {_T('\0')};
		hdi.pszText = szBuffer;
		hdi.cchTextMax = 255;
		hdi.mask = HDI_TEXT;//|HDI_LPARAM;
		VERIFY(GetItem(x, &hdi));
		CString strItemText(hdi.pszText);
		//CColumnData* pColData = (CColumnData*)hdi.lParam;
		//ASSERT(pColData);
		
		LinearGradientBrush brBack(RC2GPR(rItem), 
			clrBackStart, clrBackEnd, 
			LinearGradientModeVertical);
		gfx.FillRectangle(&brBack, RC2GPR(rItem));

		// Paint item background
		if(!bNoSort)
		{
			// Paint item border
			rItem.InflateRect(0, -2, -1, -2);
			if(rItem.left > 0) {
				gfx.DrawLine(&pnLineDark,  
					Point(rItem.left, rItem.top), 
					Point(rItem.left, rItem.bottom));
			}
			gfx.DrawLine(&pnLineLight, 
				Point(rItem.right, rItem.top), 
				Point(rItem.right, rItem.bottom));

			// Draw sort marker
			rItem.InflateRect(0, 0, -5, 0);
			if(x == pParent->m_iSortCol)
			{
				// 10 X 6
				CRect rMarker(
					rItem.right - 10, rItem.CenterPoint().y - 3, 
					rItem.right, rItem.CenterPoint().y + 3 );
				if(pParent->m_bSortAsc)
				{
					gfx.DrawLine(&pnLineDark,  
						Point(rMarker.left, rMarker.bottom), 
						Point(rMarker.right, rMarker.bottom));
					gfx.DrawLine(&pnLineDark,  
						Point(rMarker.left, rMarker.bottom - 1), 
						Point(rMarker.left + 5, rMarker.top));
					gfx.DrawLine(&pnLineLight,  
						Point(rMarker.right, rMarker.bottom - 1), 
						Point(rMarker.right - 5, rMarker.top));
				}
				else
				{
					gfx.DrawLine(&pnLineDark,  
						Point(rMarker.left, rMarker.top), 
						Point(rMarker.right, rMarker.top));
					gfx.DrawLine(&pnLineDark,  
						Point(rMarker.left, rMarker.top + 1), 
						Point(rMarker.left + 5, rMarker.bottom));
					gfx.DrawLine(&pnLineLight,  
						Point(rMarker.right, rMarker.top + 1), 
						Point(rMarker.right - 5, rMarker.bottom));
				}
				rItem.right -= 11;
			}
		}

		// Draw item text
		rItem.InflateRect(-2, -2, 0, -2);
		if(strItemText.GetLength() > 0)
		{
			Color clrText;
			clrText.SetFromCOLORREF(m_crText);
			SolidBrush brItemText(clrText);
			Font fntItem(CT2OLE(pParent->m_cstrFontName), 
				m_fFontHeight, FontStyleRegular);
			StringFormat strfmt;
			strfmt.SetAlignment(StringAlignmentNear);
			if(lvc.fmt & LVCFMT_CENTER)
				strfmt.SetAlignment(StringAlignmentCenter);
			if(lvc.fmt & LVCFMT_RIGHT)
				strfmt.SetAlignment(StringAlignmentFar);
			strfmt.SetLineAlignment(StringAlignmentCenter);
			strfmt.SetTrimming(StringTrimmingEllipsisCharacter);
			gfx.DrawString(CT2OLE(strItemText), 
				strItemText.GetLength(), &fntItem, 
				RC2GPRF(rItem), &strfmt, &brItemText);
		}
	}

	// Update the screen
	dc.BitBlt(0, 0, rClient.Width(), rClient.Height(), &dcMem, 0, 0, SRCCOPY);
}

BOOL CHeaderCtrlHDOD::OnEraseBkgnd(CDC* pDC)
{
	return TRUE;
}

BOOL CHeaderCtrlHDOD::OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT msg)
{
	// Hit test the header control
	CPoint pt;
	GetCursorPos(&pt);
	ScreenToClient(&pt);
	HDHITTESTINFO hhti = {0};
	hhti.pt.x = pt.x;
	hhti.pt.y = pt.y;
	SendMessage(HDM_HITTEST, 0, (LPARAM)&hhti);
	if(hhti.iItem != -1)
	{
		HDITEM hdi = {0};
		hdi.mask = HDI_TEXT|HDI_WIDTH|HDI_LPARAM;
		VERIFY(GetItem(hhti.iItem, &hdi));
		CColumnData* pColData = (CColumnData*)hdi.lParam;
		ASSERT(pColData);
		if((hdi.cxy <= 0) || (!pColData->m_bResizeable))
			return 1;
	}
	return CHeaderCtrl::OnSetCursor(pWnd, nHitTest, msg);
}

void CHeaderCtrlHDOD::OnHdnBeginDrag(NMHDR* pNMHDR, LRESULT* pResult)
{
	LPNMHEADER phdr = reinterpret_cast<lpnmheader>(pNMHDR);
	*pResult = 0;
	// TODO : Add 'CanDrag' property to ColumnData and implement here
}

void CHeaderCtrlHDOD::OnHdnItemDblClick(NMHDR* pNMHDR, LRESULT* pResult)
{
	LPNMHEADER phdr = reinterpret_cast<lpnmheader>(pNMHDR);
	*pResult = 0;
	// TODO : When user double-clicks on a column resize column to widest string
}

//=================================================
// Implementation
//=================================================
void CHeaderCtrlHDOD::SetHeight(int iHeight)
{
	m_iHeight = iHeight;
	return;

	// The old way to set the height
	//if(!GetSafeHwnd())
	//	return;
	//if(m_Font.GetSafeHandle())
	//	m_Font.DeleteObject();

	//CClientDC dc(this);
	//CString cstrFontName = ((CMsgListCtrl*)GetParent())->m_cstrFontName;
	//int iFntHeight = CalcFontHeight(&dc, _T("XX"), CRect(0,0,500,iHeight), cstrFontName); 

	//VERIFY(m_Font.CreateFont(iFntHeight, 0, 0, 0, FW_NORMAL, FALSE, FALSE, 0, 
	//	ANSI_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, 
	//	DEFAULT_PITCH|FF_SWISS, cstrFontName));
}

//===============================================================================
// CListCtrlHDOD 
//===============================================================================
BEGIN_MESSAGE_MAP(CListCtrlHDOD, CListCtrl)
	ON_WM_DESTROY()
	ON_WM_PAINT()
	ON_WM_CONTEXTMENU()
	ON_WM_DRAWITEM()
	ON_WM_MEASUREITEM()
	ON_WM_MEASUREITEM_REFLECT()
	ON_NOTIFY_REFLECT_EX(LVN_COLUMNCLICK, OnLvnColumnClick)
	ON_NOTIFY_REFLECT_EX(LVN_ITEMCHANGED, OnLvnItemChanged)
	ON_NOTIFY(HDN_BEGINTRACKA, 0, OnHdnBegintrack)
	ON_NOTIFY(HDN_BEGINTRACKW, 0, OnHdnBegintrack)
	ON_NOTIFY(HDN_TRACKA, 0, OnHdnTrack)
	ON_NOTIFY(HDN_TRACKW, 0, OnHdnTrack)
END_MESSAGE_MAP()

IMPLEMENT_DYNAMIC(CListCtrlHDOD, CListCtrl)

//=================================================
// Construction / Destruction
//=================================================
CListCtrlHDOD::CListCtrlHDOD()
{
	m_iSortCol				= 0;
	m_bSortAsc				= true;
	m_cstrFontName			= ((CApp*)AfxGetApp())->m_cstrFontName;
	m_fItemFontHeight		= 8;
	m_fMenuFontHeight		= 8;	
	m_crItemText			= RGB(0,0,0);
	m_crDisItemText			= RGB(128,128,128);
	m_crSelItemText			= RGB(255,255,255);
	m_crItemBack			= RGB(255,255,255);
	m_crSelItemBack			= RGB(10,36,106);//RGB(0,152,206);
	m_crMenuBack			= RGB(255,255,255);
	m_crMenuBorder			= RGB(128,128,128);
	m_crMenuBarStart		= ((CApp*)AfxGetApp())->m_crGradStart; 
	m_crMenuBarEnd			= ((CApp*)AfxGetApp())->m_crGradEnd;
	m_iMenuItemWidth		= 0;
	// Set default compare function
	m_pfnCompareFunc		= CListCtrlHDOD::CompareFunc;
}

CListCtrlHDOD::~CListCtrlHDOD()
{
}

//=================================================
// Overrides
//=================================================
void CListCtrlHDOD::PreSubclassWindow()
{
	CListCtrl::PreSubclassWindow();

	DWORD dwStyle = GetStyle();

	// Check for bad styles
	if(dwStyle & LVS_AUTOARRANGE)
	{
		TRACE(_T("The CListCtrlHDOD class cannot have the LVS_AUTOARRANGE style\n"));
		ASSERT(0);
	}
	if(dwStyle & LVS_OWNERDATA)
	{
		TRACE(_T("The CListCtrlHDOD class cannot have the LVS_OWNERDATA style\n"));
		ASSERT(0);
	}
	
	// Check for required styles
	if(!(dwStyle & LVS_REPORT))
	{
		TRACE(_T("The CListCtrlHDOD class must have the LVS_REPORT style\n"));
		ASSERT(0);
	}
}

BOOL CListCtrlHDOD::OnCommand(WPARAM wParam, LPARAM lParam)
{
	if(HIWORD(wParam) == 0)
	{
		int iCol = LOWORD(wParam);
		// Get header item (lParam)
		HDITEM hdi = {0};
		hdi.mask = HDI_LPARAM;
		VERIFY(m_HeaderCtrl.GetItem(iCol, &hdi));
		CColumnData* pColData = (CColumnData*)hdi.lParam;
		ASSERT(pColData);
		if(GetColumnWidth(iCol) == 0)
			SetColumnWidth(iCol, pColData->m_iCurWidth);
		else
			SetColumnWidth(iCol, 0);
	}

	return CListCtrl::OnCommand(wParam, lParam);
}

//=================================================
// Messages
//=================================================
void CListCtrlHDOD::OnDestroy()
{
	CListCtrl::OnDestroy();

}

void CListCtrlHDOD::OnPaint()
{
	if(!(GetStyle() & LVS_OWNERDRAWFIXED))
	{
		CListCtrl::Default();
		return;
	}

	CPaintDC dc(this); 
	CRect rClient;
	GetClientRect(&rClient);
	
	CRect rView = rClient;
	int iHOffset = GetScrollPos(SB_HORZ);
	int iVOffset = GetScrollPos(SB_VERT);
	rView.OffsetRect(iHOffset, iVOffset);

	// Double buffer 
	CDC dcMem;
	dcMem.CreateCompatibleDC(&dc);
	CBitmap bmpMem;
	bmpMem.CreateDiscardableBitmap(&dc, 
		rClient.Width(), rClient.Height());
	dcMem.SelectObject(&bmpMem);

	// Fillbackground
	dcMem.FillSolidRect(rClient, m_crItemBack);

	Graphics gfx(dcMem.GetSafeHdc());
	Color clrBack, clrText;
	Font fnt(CT2OLE(m_cstrFontName), m_fItemFontHeight, FontStyleRegular);

	// Turn on high quality image resizing algorithm
	gfx.SetInterpolationMode(InterpolationModeHighQualityBicubic);
	// Turn on anti-alias text rendering
	gfx.SetTextRenderingHint(TextRenderingHintAntiAlias);

	// Get pointer to our header control
	CHeaderCtrl* pHeaderCtrl = GetHeaderCtrl();
	ASSERT(pHeaderCtrl);

	// Draw all items
	for(int iItem = 0; iItem < GetItemCount(); iItem ++)
	{
		// Get item rect
		CRect rItem;
		GetItemRect(iItem, &rItem, LVIR_BOUNDS);

		// Skip invisible items
		if((rItem.bottom < rView.top) || (rItem.top > rView.bottom))
			continue;

		// Get item state
		LV_ITEM lvi = {0};
		lvi.mask = LVIF_STATE;
		lvi.iItem = iItem;
		lvi.stateMask = 0xFFFF; 
		GetItem(&lvi);
		bool bSelected = ((lvi.state & LVIS_SELECTED) == LVIS_SELECTED);

		clrBack.SetFromCOLORREF(bSelected ? m_crSelItemBack : m_crItemBack);
		clrText.SetFromCOLORREF(bSelected ? m_crSelItemText : m_crItemText);
		SolidBrush brBack(clrBack);
		SolidBrush brText(clrText);

		for(int iCol = 0; iCol < pHeaderCtrl->GetItemCount(); iCol ++)
		{
			// Get column format
			LVCOLUMN lvc = {0};
			lvc.mask = LVCF_FMT;
			GetColumn(iCol, &lvc);
			// Get sub-item coordinates
			CRect rSubItem;
			GetSubItemRect(iItem, iCol, LVIR_LABEL, rSubItem);
			// Paint sub-item background
			gfx.FillRectangle(&brBack, RC2GPRF(rSubItem));
			// Check for image column
			if(lvc.fmt & LVCFMT_IMAGE)//LVCFMT_COL_HAS_IMAGES)
			{
				// Get image index
				LV_ITEM lvisi = {0};
				lvisi.mask = LVIF_IMAGE;
				lvisi.iItem = iItem;
				lvisi.iSubItem = iCol;
				GetItem(&lvisi);
				if(lvisi.iImage >= 0)
				{
					// Get imagelist
					CImageList* pIL = GetImageList(LVSIL_SMALL);
					if(pIL)
					{
						// Get image size
						int cx = 0;
						int cy = 0;
						if(ImageList_GetIconSize(pIL->GetSafeHandle(), &cx, &cy))
						{
							// Draw the image centered
							CPoint pt(
								rSubItem.left + ((rSubItem.Width() - cx) / 2), 
								rSubItem.top + ((rSubItem.Height() - cy) / 2));
							CSize sz(cx, cy);
							pIL->DrawEx(&dcMem, lvisi.iImage, pt, sz, CLR_NONE, CLR_NONE, ILD_TRANSPARENT);
							// Adjust rect, for some reason column 0 will always be 
							//  shifted if there is any columns with images
							if(iCol > 0)
								rSubItem.left += (cx + 2);
						}
					}
				}
			}

			// Draw text 
			CString cstrText = GetItemText(iItem, iCol);
			if(cstrText.IsEmpty())
				continue;
			// Setup text alignment using column format
			StringFormat strfmt;
			strfmt.SetAlignment(StringAlignmentNear);
			strfmt.SetLineAlignment(StringAlignmentCenter);
			if(lvc.fmt & LVCFMT_CENTER)
				strfmt.SetAlignment(StringAlignmentCenter);
			if(lvc.fmt & LVCFMT_RIGHT)
				strfmt.SetAlignment(StringAlignmentFar);
			strfmt.SetFormatFlags(StringFormatFlagsNoWrap);
			strfmt.SetTrimming(StringTrimmingEllipsisCharacter);
			// Draw the text
			gfx.DrawString(CT2OLE(cstrText), 
				cstrText.GetLength(), &fnt, 
				RC2GPRF(rSubItem), &strfmt, &brText);
		 }
	}
	// Update the screen
	dc.BitBlt(0, 0, rClient.Width(), rClient.Height(), &dcMem, 0, 0, SRCCOPY);
}

BOOL CListCtrlHDOD::OnLvnColumnClick(NMHDR* pNMHDR, LRESULT* pResult)
{
	LPNMLISTVIEW pNMLV = reinterpret_cast<lpnmlistview>(pNMHDR);
	*pResult = 0;

	// The parent setting the ComapreFunc to NULL indicates 
	//   that all sorting will be handled by parent
	if(m_pfnCompareFunc == NULL)
		return FALSE; // Allow parent to receive this message too

	CHeaderCtrl* pHeaderCtrl = GetHeaderCtrl();
	ASSERT(pHeaderCtrl);
	CRect rSortItem;
	pHeaderCtrl->GetItemRect(m_iSortCol, &rSortItem);

	HDITEM hdi = {0};
	hdi.mask = HDI_LPARAM;
	VERIFY(pHeaderCtrl->GetItem(pNMLV->iSubItem, &hdi));
	CColumnData* pColData = (CColumnData*)hdi.lParam;
	ASSERT(pColData);
	if(!pColData->m_bSortable)
		return FALSE;

	if(m_iSortCol == pNMLV->iSubItem)
	{
		m_bSortAsc = !m_bSortAsc;
		InvalidateRect(rSortItem);
	}
	else
	{
		m_iSortCol = pNMLV->iSubItem;
		CRect rNewItem;
		pHeaderCtrl->GetItemRect(m_iSortCol, &rNewItem);
		InvalidateRect(rSortItem);
		InvalidateRect(rNewItem);
	}

	// Sort the list control
	SortList();

	return FALSE; // Allow parent to receive this message too
}

BOOL CListCtrlHDOD::OnLvnItemChanged(NMHDR *pNMHDR, LRESULT *pResult)
{
	NM_LISTVIEW* pNMLV = (NM_LISTVIEW*)pNMHDR;
	*pResult = 0;

	if(GetStyle() & LVS_OWNERDRAWFIXED)
	{
		// Redraw selected item
		CRect rItem;
		GetItemRect(pNMLV->iItem, &rItem, LVIR_BOUNDS);
		InvalidateRect(rItem);
	}

	return FALSE; // Allow parent to receive this message too
}

void CListCtrlHDOD::OnHdnBegintrack(NMHDR *pNMHDR, LRESULT *pResult)
{
	LPNMHEADER phdr = reinterpret_cast<lpnmheader>(pNMHDR);
	*pResult = 0;

	// Get header item (lParam)
	HDITEM hdi = {0};
	hdi.mask = HDI_LPARAM;
	VERIFY(m_HeaderCtrl.GetItem(phdr->iItem, &hdi));
	CColumnData* pColData = (CColumnData*)hdi.lParam;
	ASSERT(pColData);
	if((!pColData->m_bResizeable) || (GetColumnWidth(phdr->iItem) == 0))
		*pResult = 1;
}

void CListCtrlHDOD::OnHdnTrack(NMHDR *pNMHDR, LRESULT *pResult)
{
	LPNMHEADER phdr = reinterpret_cast<lpnmheader>(pNMHDR);
	*pResult = 0;

	// Get header item (lParam)
	HDITEM hdi = {0};
	hdi.mask = HDI_LPARAM;
	VERIFY(m_HeaderCtrl.GetItem(phdr->iItem, &hdi));
	CColumnData* pColData = (CColumnData*)hdi.lParam;
	ASSERT(pColData);
	if(phdr->pitem->cxy < pColData->m_iMinWidth)
		phdr->pitem->cxy = pColData->m_iMinWidth;
	pColData->m_iCurWidth = phdr->pitem->cxy;
}

void CListCtrlHDOD::OnContextMenu(CWnd* pWnd, CPoint point)
{
	// See if right-click was in listview header
	CPoint pt = point;
	ScreenToClient(&pt);
	CRect rHeader;
	CHeaderCtrl* pHeaderCtrl = GetHeaderCtrl();
	ASSERT(pHeaderCtrl);
	pHeaderCtrl->GetClientRect(&rHeader);
	if(!rHeader.PtInRect(pt))
		return;

	// Create context menu
	if(!m_HeaderMenu.CreatePopupMenu())
		return;

	// Measure strings as we build the menu
	m_iMenuItemWidth = 0;
	Font fnt(CT2OLE(m_cstrFontName), m_fMenuFontHeight, FontStyleRegular);
	Graphics gfx(::GetDC(NULL));

	// Build menu with all columns and their states
	for(int x = 0; x < pHeaderCtrl->GetItemCount(); x++)
	{
		HDITEM hdi = {0};
		TCHAR  szText[256] = {_T('\0')};
		hdi.pszText = szText;
		hdi.cchTextMax = 255;
		hdi.mask = HDI_TEXT|HDI_WIDTH|HDI_LPARAM;
		VERIFY(pHeaderCtrl->GetItem(x, &hdi));

		// TODO : make this work
		StringReplace(hdi.pszText, -1, _T('\n'), _T(' '));

		UINT nFlags = MF_BYPOSITION|MF_STRING|MF_OWNERDRAW;
		CColumnData* pColData = (CColumnData*)hdi.lParam;
		if(!pColData->m_bDisableHide)
			nFlags |= ((hdi.cxy > 0) ? MF_CHECKED : MF_UNCHECKED);
		else
			nFlags |= MF_GRAYED;
		m_HeaderMenu.InsertMenu(x, nFlags, x, szText);

		RectF rect;
		CString str(hdi.pszText);
		gfx.MeasureString(CT2OLE(str), str.GetLength(), &fnt, RectF(0, 0, 500, 500), &rect);
		if(rect.Width > m_iMenuItemWidth)
			m_iMenuItemWidth = (int)rect.Width;
	}

	// Show Menu
	m_HeaderMenu.TrackPopupMenu(TPM_LEFTALIGN, point.x, point.y, this, 0);
	m_HeaderMenu.DestroyMenu();
}

void CListCtrlHDOD::OnDrawItem(int nIDCtl, DRAWITEMSTRUCT* pDI)
{
	if(pDI->CtlType != ODT_MENU)
	{
		CListCtrl::OnDrawItem(nIDCtl, pDI);
		return;
	}

	CDC* pDC = CDC::FromHandle(pDI->hDC);
	ASSERT(pDC);
	Graphics gfx(pDC->GetSafeHdc());
	gfx.SetSmoothingMode(SmoothingModeAntiAlias);
	CRect rItem(pDI->rcItem);
	UINT nState = pDI->itemState;
	BOOL bDisabled	= ((nState & ODS_DISABLED)||(nState & ODS_GRAYED));
	BOOL bChecked = (nState & ODS_CHECKED);
	BOOL bHighlight = ((pDI->itemState & ODS_SELECTED) && (pDI->itemAction & (ODA_SELECT|ODA_DRAWENTIRE)));

	/*TODO : handle itemAction ?  app flashes when change hilight too fast
	Specifies the drawing action required. This member can be one or more of the values. 
	ODA_DRAWENTIRE - The entire control needs to be drawn.
	ODA_FOCUS - The control has lost or gained the keyboard focus. The itemState member should be checked to determine whether the control has the focus.
	ODA_SELECT - The selection status has changed. The itemState member should be checked to determine the new selection state.*/
		
	if(!(pDI->itemAction & ODA_DRAWENTIRE))
	{
		int z = 0;
	}

	// Get the menu item text
	CHeaderCtrl* pHeaderCtrl = GetHeaderCtrl();
	ASSERT(pHeaderCtrl);
	HDITEM hdi = {0};
	TCHAR  szText[256] = {_T('\0')};
	hdi.pszText = szText;
	hdi.cchTextMax = 255;
	hdi.mask = HDI_TEXT|HDI_WIDTH|HDI_LPARAM;
	VERIFY(pHeaderCtrl->GetItem(pDI->itemID, &hdi));
	CString strText = szText;

	CRect rMenuBar = rItem;
	rMenuBar.right = rItem.left + 24;
	Color clrMenuBarStart;
	clrMenuBarStart.SetFromCOLORREF(m_crMenuBarStart);
	Color clrMenuBarEnd;
	clrMenuBarEnd.SetFromCOLORREF(m_crMenuBarEnd);
	LinearGradientBrush brMenuBar(RC2GPR(rMenuBar), 
		clrMenuBarStart, clrMenuBarEnd, 
			LinearGradientModeHorizontal);
	gfx.FillRectangle(&brMenuBar, RC2GPR(rMenuBar));

	if(bChecked)
	{
		CRect rCheckBox = rMenuBar;
		//rCheckBox.InflateRect(-1,-2,-3,-2);
		rCheckBox.InflateRect(-2,-3,-4,-3);
		SolidBrush br(Color(20,0,0,128));
		gfx.FillRectangle(&br, RC2GPR(rCheckBox));
		Pen pnCheckFrame(Color(255,0,0,128), 1);
		Pen pnCheckMark(Color(255,0,0,0), 1.5);
		gfx.DrawRectangle(&pnCheckFrame, RC2GPR(rCheckBox));
		CPoint ptCenter = rCheckBox.CenterPoint();
		//gfx.DrawLine(&pnCheckMark, ptCenter.x, ptCenter.y + 3, ptCenter.x - 3, ptCenter.y );
		//gfx.DrawLine(&pnCheckMark, ptCenter.x, ptCenter.y + 3, ptCenter.x + 5, ptCenter.y - 3);
		gfx.DrawLine(&pnCheckMark, ptCenter.x, ptCenter.y + 3, ptCenter.x - 2, ptCenter.y );
		gfx.DrawLine(&pnCheckMark, ptCenter.x, ptCenter.y + 3, ptCenter.x + 5, ptCenter.y - 2);
	}

	CRect rText = rItem;
	rText.left += 24;
	Color clrBack;
	clrBack.SetFromCOLORREF(m_crMenuBack);
	SolidBrush brBack(clrBack);
	gfx.FillRectangle(&brBack, RC2GPR(rText));

	if(strText.GetLength() > 0)
	{
		rText.left += 2;
		Font fnt(CT2OLE(m_cstrFontName), m_fMenuFontHeight, FontStyleRegular);
		StringFormat strfmtLC;
		strfmtLC.SetAlignment(StringAlignmentNear);
		strfmtLC.SetLineAlignment(StringAlignmentCenter);
		strfmtLC.SetTrimming(StringTrimmingEllipsisCharacter);
		Color clrText;
		clrText.SetFromCOLORREF(bDisabled ? m_crDisItemText : m_crItemText);
		SolidBrush brItemText(clrText);
		
		gfx.DrawString(CT2OLE(strText), strText.GetLength(), 
			&fnt, RC2GPRF(rText), &strfmtLC, &brItemText);
	}

	if(bHighlight)
	{
		CRect rHighlight = rItem;
		rHighlight.InflateRect(-1,-1,-1,-1);
		Pen pnHLBorder(Color(255,0,0,0), 1);
		SolidBrush brHighlight(Color(80,0,0,128));
		gfx.FillRectangle(&brHighlight, RC2GPR(rHighlight));
		gfx.DrawRectangle(&pnHLBorder, RC2GPR(rHighlight));
	}
}

void CListCtrlHDOD::OnMeasureItem(int nIDCtl, MEASUREITEMSTRUCT* pMI)
{
	if(pMI->CtlType == ODT_MENU)
	{
		pMI->itemHeight = 24;
		pMI->itemWidth = (m_iMenuItemWidth + 24);
	}

	CListCtrl::OnMeasureItem(nIDCtl, pMI);
}

void CListCtrlHDOD::MeasureItem(MEASUREITEMSTRUCT* pMI)
{
	pMI->itemHeight = m_iItemHeight;
}

//=================================================
// Property Accessor Functions
//=================================================
void CListCtrlHDOD::SetItemHeight(int iHeight)
{
	if(m_iItemHeight == iHeight)
		return;
	m_iItemHeight = iHeight;

	// Force measure item 
	CRect rThis;
	GetWindowRect(&rThis);
	WINDOWPOS wp = {0};
	wp.hwnd = GetSafeHwnd();
	wp.cx = rThis.Width();
	wp.cy = rThis.Height();
	wp.flags = SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOOWNERZORDER|SWP_NOZORDER;
	SendMessage(WM_WINDOWPOSCHANGED, 0, (LPARAM)&wp);
}

//=================================================
// Implementation
//=================================================
int CListCtrlHDOD::InsertColumn(int nCol, LPCTSTR lpszColumnHeading, int nFormat, 
	int nWidth, int nSubItem, BOOL bHidden/*=FALSE*/, BOOL bDisableHide/*=FALSE*/,
	BOOL bResizeable/*=TRUE*/, BOOL bSortable/*=TRUE*/, int iMinWidth/*=30*/, 
	CString cstrToolTip/*=_T("")*/)
{
	// Call base class
	int iItem = CListCtrl::InsertColumn(nCol, 
		lpszColumnHeading, nFormat, (bHidden ? 0 : nWidth), nSubItem);
	if(iItem < 0)
		return iItem;

	// Header control is not created until first column is added
	if(!m_HeaderCtrl.GetSafeHwnd())
		VERIFY(m_HeaderCtrl.SubclassDlgItem(0, this));

	// Store column data 
	CColumnData* pColData = new CColumnData;
	ASSERT(pColData);
	pColData->m_bHidden = bHidden;
	pColData->m_bDisableHide = bDisableHide;
	pColData->m_bResizeable = bResizeable;
	pColData->m_bSortable = bSortable;
	pColData->m_iMinWidth = iMinWidth;
	pColData->m_cstrToolTip = cstrToolTip;
	pColData->m_iFormat = nFormat;
	pColData->m_iDefWidth = nWidth;
	pColData->m_iCurWidth = nWidth;

	// Get newly created header item
	HDITEM hdi = {0};
	hdi.mask = HDI_LPARAM;
	VERIFY(m_HeaderCtrl.GetItem(nCol, &hdi));
	hdi.lParam = (LPARAM)pColData;
	VERIFY(m_HeaderCtrl.SetItem(nCol, &hdi));

	return iItem;
}

BOOL CListCtrlHDOD::DeleteColumn(int nCol)
{
	// Delete header item data
	HDITEM hdi = {0};
	hdi.mask = HDI_LPARAM;
	VERIFY(m_HeaderCtrl.GetItem(nCol, &hdi));
	CColumnData* pColData = (CColumnData*)hdi.lParam;
	ASSERT(pColData);
	delete pColData;
	return CListCtrl::DeleteColumn(nCol);
}

void CListCtrlHDOD::SortList()
{
	if(!m_pfnCompareFunc)
		return;
	SortItems(m_pfnCompareFunc, (DWORD_PTR)this);
}

//=================================================
// Sort Callback
//=================================================
int CALLBACK CListCtrlHDOD::CompareFunc(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort)
{
	CListCtrlHDOD* pThis = (CListCtrlHDOD*)lParamSort;
	ASSERT(pThis);

	LVFINDINFO lvfi1 = {0};
	lvfi1.flags = LVFI_PARAM;
	lvfi1.lParam = lParam1;
	LVFINDINFO lvfi2 = {0};
	lvfi2.flags = LVFI_PARAM;
	lvfi2.lParam = lParam2;
	int iIndex1 = pThis->FindItem(&lvfi1);
	ASSERT(iIndex1 != -1);
	int iIndex2 = pThis->FindItem(&lvfi2);
	ASSERT(iIndex2 != -1);

	CString strItem1 = pThis->GetItemText(iIndex1, pThis->m_iSortCol);
	CString strItem2 = pThis->GetItemText(iIndex2, pThis->m_iSortCol);
	int iResult = _tcscmp(strItem1, strItem2);

	return (pThis->m_bSortAsc ? iResult : (-iResult));
}

</lpnmheader></lpnmheader></lpnmlistview></lpnmheader></lpnmheader>


这篇关于如何从网格线到图像中删除小空间?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆