⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 gfxheaderctrl.cpp

📁 地址本
💻 CPP
字号:
// GfxHeaderCtrl.cpp : implementation file
//

#include "stdafx.h"
#include "Address.h"


#include "GfxHeaderCtrl.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

/////////////////////////////////////////////////////////////////////////////
// CGfxHeaderCtrl

CGfxHeaderCtrl::CGfxHeaderCtrl()
{
	dwSortUp = 0;
	m_nSortCol = -1;
	pImageList = NULL;
	dwDontShowSortArrow = 0;
	dwNoResizeColumn = 0;
	bIsDragAllowed = true;

// Column dragging support
	m_pWidth = NULL;	
	m_bDragging = FALSE;	
	m_bCheckForDrag = FALSE;
	m_fpDragCol = NULL;	
//	m_pOwnerWnd = NULL;
	bEnableDrag = true;
}

CGfxHeaderCtrl::~CGfxHeaderCtrl()
{
}


BEGIN_MESSAGE_MAP(CGfxHeaderCtrl, CHeaderCtrl)
	//{{AFX_MSG_MAP(CGfxHeaderCtrl)
	ON_WM_SETCURSOR()
	ON_WM_LBUTTONDBLCLK()
	ON_WM_NCHITTEST()
	ON_WM_MOUSEMOVE()
	ON_WM_LBUTTONDOWN()
	ON_WM_LBUTTONUP()
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CGfxHeaderCtrl message handlers

int CGfxHeaderCtrl::SetSortImage( int nCol, BOOL bAsc )
{
	int nPrevCol = m_nSortCol;

	m_nSortCol = nCol;
	m_bSortAsc = bAsc;

	// Change the item to ownder drawn
	HD_ITEM hditem;

	hditem.mask = HDI_FORMAT;
	GetItem(nCol, &hditem);
	hditem.fmt |= HDF_OWNERDRAW;
	SetItem(nCol, &hditem);

	// Invalidate header control so that it gets redrawn
	Invalidate();
	SetSortOrder(nCol, bAsc == TRUE);
	return nPrevCol;
}

void CGfxHeaderCtrl::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct) 
{
	CDC dc;
	dc.Attach(lpDrawItemStruct->hDC);

	CRect rcLabel(lpDrawItemStruct->rcItem);

	int nSavedDC = dc.SaveDC();

	CRgn rgn;
	rgn.CreateRectRgnIndirect(&rcLabel);
	dc.SelectObject(&rgn);
	rgn.DeleteObject();

	// Draw the background
//	dc.FillRect(rcLabel, &CBrush(::GetSysColor(COLOR_3DFACE)));
	dc.FillSolidRect(rcLabel, GetSysColor(COLOR_3DFACE));
	// Labels are offset by a certain amount  
	// This offset is related to the width of a space character
	int offset = dc.GetTextExtent(_T(" "), 1).cx*2;
	// Get the column text and format
	static TCHAR buf[256];
	HD_ITEM hditem;
	hditem.mask = HDI_TEXT | HDI_FORMAT | HDI_LPARAM;
	hditem.pszText = buf;
	hditem.cchTextMax = 255;

	GetItem(lpDrawItemStruct->itemID, &hditem);

	int iSubItem = hditem.lParam;

	// Determine format for drawing column label
	UINT uFormat = DT_SINGLELINE | DT_NOPREFIX | DT_NOCLIP | DT_VCENTER | DT_END_ELLIPSIS ;

	if( hditem.fmt & HDF_CENTER) uFormat |= DT_CENTER;
	else if( hditem.fmt & HDF_RIGHT) uFormat |= DT_RIGHT;
	else uFormat |= DT_LEFT;

	// Adjust the rect if the mouse button is pressed on it
	if (lpDrawItemStruct->itemState == ODS_SELECTED)
	{
		rcLabel.left++;
		rcLabel.top += 2;
		rcLabel.right++;
	}

	// Draw column label
	CString cs(buf);

	if (pImageList && cs.Right(1) == "_")
	{
		int iIdx = atoi(cs);
		IMAGEINFO ii;
		if (pImageList->GetImageInfo(iIdx, &ii))
		{
			CRect rcIma(ii.rcImage);
			if (rcLabel.Width() >= rcIma.Width())
			{
				int x = rcLabel.left + (rcLabel.Width() - rcIma.Width()) / 2;
				int y = rcLabel.top + (rcLabel.Height() - rcIma.Height()) / 2;
				pImageList->Draw(&dc, iIdx, CPoint(x,y), ILD_TRANSPARENT);//ILD_NORMAL);rcLabel.TopLeft()
			}
		}
	}
	else
	{
		// Adjust the rect further if Sort arrow is to be displayed
		if (lpDrawItemStruct->itemID == (UINT)m_nSortCol) rcLabel.right -= 3 * offset;

		rcLabel.left += offset;
		rcLabel.right -= offset;

		if (rcLabel.left < rcLabel.right) 
			dc.DrawText(buf,-1,rcLabel, uFormat);
	}

	// Draw the Sort arrow
	if (lpDrawItemStruct->itemID == (UINT)m_nSortCol && !(dwDontShowSortArrow & 1 << iSubItem))//m_nSortCol))
	{
		CRect rcIcon(lpDrawItemStruct->rcItem);

		// Set up pens to use for drawing the triangle
		CPen penLight(PS_SOLID, 1, GetSysColor(COLOR_3DHILIGHT));
		CPen penShadow(PS_SOLID, 1, GetSysColor(COLOR_3DSHADOW));
		CPen *pOldPen = dc.SelectObject(&penLight);

		if (m_bSortAsc)
		{
			// Draw triangle pointing upwards
			dc.MoveTo(rcIcon.right - 2*offset, offset-1);
			dc.LineTo(rcIcon.right - 3*offset/2, rcIcon.bottom - offset);
			dc.LineTo(rcIcon.right - 5*offset/2-2, rcIcon.bottom - offset);
			dc.MoveTo(rcIcon.right - 5*offset/2-1, rcIcon.bottom - offset-1);

			dc.SelectObject(&penShadow);
			dc.LineTo(rcIcon.right - 2*offset, offset-2);
		}
		else
		{
			// Draw triangle pointing downwords
			dc.MoveTo(rcIcon.right - 3*offset/2, offset-1);
			dc.LineTo(rcIcon.right - 2*offset-1, rcIcon.bottom - offset + 1);
			dc.MoveTo(rcIcon.right - 2*offset-1, rcIcon.bottom - offset);

			dc.SelectObject(&penShadow);
			dc.LineTo(rcIcon.right - 5*offset/2-1, offset -1);
			dc.LineTo(rcIcon.right - 3*offset/2, offset -1);
		}

		// Restore the pen
		dc.SelectObject(pOldPen);
	}

	if ((m_bDragging) && (int)lpDrawItemStruct->itemID == m_nDragCol)//|| m_bCheckForDrag
	{
		CBrush* pBrush = CBrush::FromHandle((HBRUSH) GetStockObject(WHITE_BRUSH));
		HBRUSH hOldBrush = NULL;
		if (pBrush != NULL) hOldBrush = (HBRUSH)SelectObject(dc.m_hDC, pBrush->m_hObject);
		CRect rcx(lpDrawItemStruct->rcItem);
		dc.PatBlt(rcx.left, rcx.top, rcx.Width(), rcx.Height(), PATINVERT);
		if (hOldBrush != NULL) SelectObject(dc.m_hDC, hOldBrush);
	}

	dc.RestoreDC(nSavedDC);
	dc.Detach();
}

bool CGfxHeaderCtrl::GetSortOrder(const int iCol)
{
	return dwSortUp & (1 << iCol) ? true : false;
}

void CGfxHeaderCtrl::SetSortOrder(const int iCol, const bool bAscending)
{
	if (bAscending) dwSortUp |= (1 << iCol);
	else dwSortUp &= ~ (1 << iCol);
}


BOOL CGfxHeaderCtrl::OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message) 
{	
	if (bIsDragAllowed) return CHeaderCtrl::OnSetCursor(pWnd, nHitTest, message);
	SetCursor(AfxGetApp()->LoadStandardCursor(IDC_ARROW));
	return TRUE;
}

void CGfxHeaderCtrl::OnLButtonDblClk(UINT nFlags, CPoint point) 
{
	if (IsDragAllowed(point)) CHeaderCtrl::OnLButtonDblClk(nFlags, point);
}

UINT CGfxHeaderCtrl::OnNcHitTest(CPoint point) 
{
	CPoint clientPoint = point;	
	ScreenToClient(&clientPoint);
	bIsDragAllowed = IsDragAllowed(clientPoint);
	return CHeaderCtrl::OnNcHitTest(point);
}

bool CGfxHeaderCtrl::IsDragAllowed(CPoint point)
{
	if (dwNoResizeColumn == 0) return true;
	HD_ITEM hi;	
	hi.mask = HDI_WIDTH|HDI_LPARAM;

	int dividerLocations = 0;
	int dragWidth = GetSystemMetrics(SM_CXCURSOR);

	bool allowDrag = true;

	int i, max = GetItemCount();
	for (i = 0; i < max; ++i) 
	{		
		GetItem(i, &hi);
		dividerLocations += hi.cxy;
		if (dwNoResizeColumn & (1 << hi.lParam))//i)
			if (point.x > dividerLocations - dragWidth/2 && point.x < dividerLocations + dragWidth/2)
				allowDrag = false;
	}
	return allowDrag;
}

void CGfxHeaderCtrl::OnMouseMove(UINT nFlags, CPoint point) 
{
	if (bEnableDrag)
	{
		if( (MK_LBUTTON & nFlags) == 0)
		{
			// The left mouse button is not pressed - so reset flags
			m_bCheckForDrag = FALSE;
			m_bDragging = FALSE;
		}
		else if (m_bDragging)
		{
			// Get column number that falls under the mouse
			int i=0, cx = 0;
			if( point.x > 0 )
			{
				for( i = 0; i < GetItemCount(); i++ )
				{
					if( point.x >= cx && point.x < cx + m_pWidth[i] )
						break;
					cx += m_pWidth[i];
				}
			}

			if (i != m_nDropPos)
			{
				m_nDropPos = i;

				CRect rect;
				//GetWindowRect(&rect);
				GetClientRect(&rect);

				// Invalidate area occupied by previous marker
				InvalidateRect(&marker_rect);

				// Draw a new marker
				CClientDC dc(this);
				POINT pts[3];

				CBrush rbr(RGB(255,0,0)), * obr = dc.SelectObject(&rbr);
				CPen rpn(PS_SOLID,1,RGB(255,0,0)), * opn = dc.SelectObject(&rpn);

				pts[0].x = cx; pts[1].x = cx -3; pts[2].x = cx +3;
				pts[0].y = rect.Height() - 8; pts[1].y = pts[2].y = rect.Height()-1;

				dc.Polygon(pts, 3);

				// save marker information
				marker_rect.left = cx - 4;
				marker_rect.top = rect.bottom - 8;
				marker_rect.right = cx + 4;
				marker_rect.bottom = rect.bottom;//Height();

				dc.SelectObject(obr);
				dc.SelectObject(opn);
			}

			{
				CClientDC dc(GetParent());
				CPoint spt(point);
				ClientToScreen(&spt);
				GetParent()->ScreenToClient(&spt);

				CRect rcNewDragColumn(spt.x - rcDragColumn.Width() / 2, spt.y - rcDragColumn.Height() / 2, spt.x + rcDragColumn.Width() / 2, spt.y + rcDragColumn.Height() / 2);
				dc.DrawDragRect(&rcNewDragColumn, CSize(2,2), rcLastDragColumn.IsRectEmpty() ? NULL : &rcLastDragColumn, CSize(2,2));
				rcLastDragColumn = rcNewDragColumn;
			}

			return;
		}
		else if(m_bCheckForDrag)
		{
			// The mouse button was pressed over a column header
			// and now the mouse has moved - so start drag
			m_bCheckForDrag = FALSE;

			m_bDragging = TRUE;
			m_nDropPos = m_nDragCol;

			SetCapture();

			// Store information for later use
			int iCount = GetItemCount();
			HD_ITEM hd_item;
			m_pWidth = new int[iCount];
			for (int i = 0; i < iCount; i++)
			{
				hd_item.mask = HDI_WIDTH|HDI_FORMAT;
				GetItem(i, &hd_item);
				m_pWidth[i] = hd_item.cxy;

				if (!(hd_item.fmt & HDF_OWNERDRAW))
				{
					hd_item.mask = HDI_FORMAT;
					hd_item.fmt |= HDF_OWNERDRAW;
					SetItem(i, &hd_item);
				}
			}
			rcLastDragColumn.SetRect(0,0,0,0);
			DrawDragColumn(m_nDragCol);
			Invalidate();
			return;
		}
	}
	
	CHeaderCtrl::OnMouseMove(nFlags, point);
}

void CGfxHeaderCtrl::OnLButtonDown(UINT nFlags, CPoint point) 
{
	// Determine if mouse was pressed over a column header
	if (bEnableDrag)
	{
		HD_HITTESTINFO hd_hittestinfo;
		hd_hittestinfo.pt = point;
		SendMessage(HDM_HITTEST, 0, (LPARAM)(&hd_hittestinfo));
		if( hd_hittestinfo.flags == HHT_ONHEADER )
		{
			m_nDragCol = hd_hittestinfo.iItem;
			m_bCheckForDrag = TRUE;
			Invalidate();
		}
	}
	
	CHeaderCtrl::OnLButtonDown(nFlags, point);
}

void CGfxHeaderCtrl::OnLButtonUp(UINT nFlags, CPoint point) 
{
	if (bEnableDrag)
	{
		if (m_bDragging)
		{
			if (!(rcLastDragColumn.IsRectEmpty())) 
			{
				rcLastDragColumn.top --;
				GetParent()->InvalidateRect(rcLastDragColumn);
				GetParent()->UpdateWindow();
				rcLastDragColumn.SetRect(0,0,0,0);
			}
			m_bDragging = FALSE;
			delete[] m_pWidth;
			ReleaseCapture();
			if (m_nDragCol != m_nDropPos && m_nDragCol != m_nDropPos -1)
			{
				(GetParent()->*m_fpDragCol)(m_nDragCol, m_nDropPos);

				if (m_nSortCol == m_nDragCol) m_nSortCol = m_nDropPos;
				else if (m_nSortCol == m_nDropPos) m_nSortCol = m_nDragCol;
			}
			Invalidate();
		}
	}
	CHeaderCtrl::OnLButtonUp(nFlags, point);
}

void CGfxHeaderCtrl::SetCallback(void (CWnd::*fpDragCol)(int &, int &))
{	
	m_fpDragCol = fpDragCol;
}


void CGfxHeaderCtrl::DrawDragColumn(const int iCol)
{
	int cx = 0;
	cx = m_pWidth[iCol];

	CRect rc;
	GetClientRect(&rc);

	HD_ITEM hditem;
	hditem.mask = HDI_WIDTH;
	GetItem(iCol, &hditem);

	rcDragColumn.SetRect(0, 0, hditem.cxy, rc.Height());
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -