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

📄 treelistheaderctrl.cpp

📁 一个关于数据结结的
💻 CPP
📖 第 1 页 / 共 3 页
字号:
// TreeListHeaderCtrl.cpp : implementation file
//

#include "stdafx.h"
#include "TreeListColumnInfo.h"
#include "TreeListDC.h"
#include "TLHDragWnd.h"
#include "TLHDropWnd.h"
#include "TreeListHeaderCtrl.h"
#include "TreeListTipCtrl.h"
#include "TreeListStaticCtrl.h"
#include "TreeListEditCtrl.h"
#include "TreeListComboCtrl.h"
#include "TreeListCtrl.h"
#include "TreeListResource.h"

#include "resource.h"

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

/////////////////////////////////////////////////////////////////////////////
// CTreeListHeaderCtrl

CTreeListHeaderCtrl::CTreeListHeaderCtrl() :
	m_dwStyle( 0 ),
	m_bSubclassFromCreate( FALSE ),
	m_bOffScreenBuffer( TRUE ),
	m_pImageList( NULL ),
	m_pTreeListCtrl( NULL ),
	m_hSize( NULL ),
	m_hSplit( NULL ),
	m_hArrow( NULL ),
	m_bSplit( FALSE ),
	m_bSizing( FALSE ),
	m_bDraging( FALSE ),
	m_nHeaderHeight( 0 ),
	m_pDragWnd( NULL ),
	m_pDropWnd( NULL )
{
	// register window class
	WNDCLASS wndclass;
	HINSTANCE hInst = AfxGetInstanceHandle();
	CTreeListResource	TreeListResource;

	if( !::GetClassInfo(hInst, TREELISTHEADERCTRL_CLASSNAME, &wndclass) )
	{
        wndclass.style			= CS_DBLCLKS | CS_HREDRAW | CS_VREDRAW;
		wndclass.lpfnWndProc	= ::DefWindowProc;
		wndclass.cbClsExtra		= 0;
		wndclass.cbWndExtra		= 0;
		wndclass.hInstance		= hInst;
		wndclass.hIcon			= NULL;
		wndclass.hCursor		=  AfxGetApp()->LoadStandardCursor( IDC_ARROW );
		wndclass.hbrBackground	= (HBRUSH)COLOR_WINDOW;
		wndclass.lpszMenuName	= NULL;
		wndclass.lpszClassName	= TREELISTHEADERCTRL_CLASSNAME;

		if (!AfxRegisterClass(&wndclass))
			AfxThrowResourceException();
	}

	// default color
	m_cr3DBkgnd		= 0x808080;
	m_cr3DFace		= GetSysColor( COLOR_3DFACE );
	m_cr3DLight		= GetSysColor( COLOR_3DHILIGHT );
	m_cr3DShadow	= GetSysColor( COLOR_3DSHADOW );
	m_crText		= GetSysColor( COLOR_BTNTEXT );

	// default font
	m_Font.CreateStockObject( SYSTEM_FIXED_FONT );

	// load cursors
	m_hSize		= AfxGetApp()->LoadCursor( IDC_CURSOR_SIZE );
	m_hSplit	= AfxGetApp()->LoadCursor( IDC_CURSOR_SPLIT );
	m_hArrow	= AfxGetApp()->LoadStandardCursor( IDC_ARROW );
}

CTreeListHeaderCtrl::~CTreeListHeaderCtrl()
{
	// free font
	if( m_Font.m_hObject != NULL )
		m_Font.DeleteObject();

	// free cursors
	if( m_hSize != NULL )
		DestroyCursor( m_hSize );

	if( m_hSplit != NULL )
		DestroyCursor( m_hSplit );

	if( m_hArrow != NULL )
		DestroyCursor( m_hArrow );
}

BEGIN_MESSAGE_MAP(CTreeListHeaderCtrl, CWnd)
	//{{AFX_MSG_MAP(CTreeListHeaderCtrl)
	ON_WM_ERASEBKGND()
	ON_WM_PAINT()
	ON_WM_MOUSEMOVE()
	ON_WM_LBUTTONDOWN()
	ON_WM_LBUTTONUP()
	ON_WM_LBUTTONDBLCLK()
	ON_WM_CANCELMODE()
	ON_WM_RBUTTONDOWN()
	ON_WM_RBUTTONUP()
	ON_WM_RBUTTONDBLCLK()
	//}}AFX_MSG_MAP
	ON_MESSAGE(HDM_LAYOUT, OnLayout)
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CTreeListHeaderCtrl message handlers
BOOL CTreeListHeaderCtrl::Create()
{
	// create sort image
	if( !m_imgSort.Create( IDB_TREELIST_SORT, 8, 4, 0xFF00FF ) )
		return FALSE;

	// create header image
	if( !m_imgHeader.Create( IDB_TREELIST_HEADER, 16, 4, 0xFF00FF ) )
		return FALSE;

	m_pImageList = &m_imgHeader;

	return TRUE;
}

BOOL CTreeListHeaderCtrl::Create( DWORD dwStyle, const RECT& rect, CTreeListCtrl* pParentWnd, UINT nID )
{
	// create window
	ASSERT_VALID( pParentWnd );

	m_dwStyle = dwStyle;
	m_pTreeListCtrl = pParentWnd;
	m_bSubclassFromCreate = TRUE;

	dwStyle |= WS_CHILD | WS_VISIBLE | WS_EX_TRANSPARENT;

	if( !CWnd::Create( TREELISTHEADERCTRL_CLASSNAME, NULL, dwStyle, rect, pParentWnd, nID ) )
		return FALSE;

	if( !Create() )
		return FALSE;

	return TRUE;
}

void CTreeListHeaderCtrl::SetHeaderFont()
{
	// set font
	CWnd* pWnd = GetParent();
	CTreeListCtrl* pTreeListCtrl = (CTreeListCtrl*)pWnd;

	if( pTreeListCtrl != NULL )
	{
		CFont* pFont = pTreeListCtrl->GetFont();
		if( pFont != NULL )
		{
			LOGFONT lf;
			pFont->GetLogFont( &lf );

			m_Font.DeleteObject();
			m_Font.CreateFontIndirect( &lf );
		}
	}
}

CFont* CTreeListHeaderCtrl::GetHeaderFont()
{
	// get font
	return &m_Font;
}


int CTreeListHeaderCtrl::SetHeaderHeight( int nHeight )
{
	// set header height
	int nOldHeight = m_nHeaderHeight;

	if( nHeight == -1 )
	{
		ASSERT( m_Font.m_hObject != NULL );
		
		LOGFONT lf;
		m_Font.GetLogFont( &lf );

		if( lf.lfHeight > 0 )
		{
			m_nHeaderHeight = lf.lfHeight + 6;
		}
		else if( lf.lfHeight == 0 )
		{
			m_nHeaderHeight = DEFAULT_HEIGHT;
		}
		else
		{
			m_nHeaderHeight = -lf.lfHeight + 6;
		}
	}
	else
	{
		m_nHeaderHeight = nHeight;
	}

	return nOldHeight;
}

int CTreeListHeaderCtrl::GetHeaderHeight()
{
	// get header height
	if( !(GetStyle()&TLHS_SHOWHEAD) )
		return 0;

	return m_nHeaderHeight;
}

int CTreeListHeaderCtrl::GetHeaderWidth()
{
	// get header width
	ASSERT( m_pTreeListCtrl != NULL );
	return m_pTreeListCtrl->GetWidth();
}

BOOL CTreeListHeaderCtrl::GetHeaderRect( CRect& rcHeader, int iCol )
{
	// get header rect
	CPtrArray&			arColumns	= m_pTreeListCtrl->m_arColumns;
	CArray<int,int>&	arShows		= m_pTreeListCtrl->m_arShows;

	BOOL bFound = FALSE;
	int nPerfix = 0;
	for( int iShow=0; iShow<arShows.GetSize(); iShow++ )
	{
		CTreeListColumnInfo* pColumnInfo;

		int iColumn = arShows[iShow];
		pColumnInfo = (CTreeListColumnInfo*)arColumns[iColumn];
		if( iColumn == iCol )
		{
			bFound = TRUE;
			rcHeader.SetRect( 0, 0, pColumnInfo->m_nWidth, GetHeaderHeight() );
			rcHeader.OffsetRect( nPerfix, 0 );
			break;
		}

		nPerfix += pColumnInfo->m_nWidth;
	}

	return bFound;
}

BOOL CTreeListHeaderCtrl::OnEraseBkgnd(CDC* pDC) 
{
	// do not erase bkgnd
	return TRUE;
}

void CTreeListHeaderCtrl::OnPaint() 
{
	// paint header control
	CPaintDC dc(this);

	if( m_bOffScreenBuffer )
	{
		CTreeListDC TreeListDC( &dc );
		DrawCtrl( &TreeListDC );
	}
	else
	{
		DrawCtrl( &dc );
	}
}

BOOL CTreeListHeaderCtrl::DrawCtrl( CDC* pDC )
{
	// draw control
	ASSERT_VALID( pDC );

	CRect rcClip;
	if( pDC->GetClipBox( &rcClip ) == ERROR )
		return FALSE;

	CRect rcClient;
	GetClientRect( &rcClient );

	if( m_pTreeListCtrl->GetStyle()&TLC_BKGNDCOLOR )
	{
		pDC->FillSolidRect( &rcClient, m_cr3DBkgnd );	
	}
	else
	{
		pDC->FillSolidRect( &rcClient, m_cr3DFace );
		pDC->Draw3dRect( &rcClient, m_cr3DLight, m_cr3DShadow );
	}

	DrawHeaders( pDC );

	return TRUE;
}

BOOL CTreeListHeaderCtrl::DrawHeaders( CDC* pDC )
{
	// draw every column headers
	CPtrArray&			Columns = m_pTreeListCtrl->m_arColumns;
	CArray<int, int>&	Shows	= m_pTreeListCtrl->m_arShows;

	// no columns or zero size
	if( m_pTreeListCtrl->GetWidth() == 0 )
		return TRUE;

	int nWinPos = GetParent()->GetScrollPos( SB_HORZ );

	// get client area
	CRect rcClient;
	GetClientRect( &rcClient );
	
	// draw background
	CRect rcFace;
	rcFace.SetRect( 0, rcClient.top, GetHeaderWidth(), rcClient.bottom );
	rcFace.OffsetRect( -nWinPos, 0 );

	pDC->FillSolidRect( &rcFace, m_cr3DFace );
	pDC->Draw3dRect( &rcFace, m_cr3DLight, m_cr3DShadow );
	
	CTreeListColumnInfo* pColumnInfo;
	int nHeaderPos = 0;
	for( int iShow=0; iShow<Shows.GetSize(); iShow++, nHeaderPos += pColumnInfo->m_nWidth )
	{
		int iCol;
		
		// do NOT draw zero column
		iCol = Shows[iShow];  //*m_pShow[iShow];
		pColumnInfo = (CTreeListColumnInfo*)Columns[iCol];
		if( pColumnInfo->m_nWidth == 0 )
			continue;

		CRect rcHeader;
		rcHeader.SetRect( 0, 0, pColumnInfo->m_nWidth, GetHeaderHeight() );
		rcHeader.OffsetRect( -nWinPos, 0 );
		rcHeader.OffsetRect( nHeaderPos, 0 );

		// do NOT draw out of screen column
		if( rcHeader.right < rcClient.left || rcHeader.left > rcClient.right )
			continue;

		DrawHeader( pDC, rcHeader, iCol );
	}

	return TRUE;
}

BOOL CTreeListHeaderCtrl::DrawHeader( CDC* pDC, CRect rcHeader, int iCol )
{
	// draw one column header
	CPtrArray&			Columns = m_pTreeListCtrl->m_arColumns;
	CArray<int, int>&	Shows	= m_pTreeListCtrl->m_arShows;
	CArray<int, int>&	Sorts	= m_pTreeListCtrl->m_arSorts;
	CTreeListColumnInfo* pColumn = (CTreeListColumnInfo*)Columns[iCol];

	ASSERT( Shows.GetSize() > 0 );

	// draw drag of columns
	CRect rcBkgnd;
	rcBkgnd = rcHeader;
	if( rcBkgnd.Height() > 0 )
	{
		if( m_bDraging && iCol == m_iCol )
			pDC->Draw3dRect( rcBkgnd, 0xFF0000, 0xFF0000 );
	}

	// draw gaps between columns
	CRect rcGaps;
	rcGaps = rcHeader;
	rcGaps.DeflateRect( 0, 2, 0, 2 );
	if( rcGaps.Height() > 0 )
	{
		pDC->IntersectClipRect( rcHeader );
		pDC->IntersectClipRect( rcGaps );

		if( !m_bDraging || iCol != m_iCol )
		{
			if( iCol != Shows[0] )
				pDC->DrawEdge( rcGaps, BDR_RAISEDINNER, BF_LEFT );

			if( iCol != Shows[Shows.GetUpperBound()] )
				pDC->DrawEdge( rcGaps, BDR_RAISEDINNER, BF_RIGHT );
		}

		::ExtSelectClipRgn( pDC->m_hDC, DEFAULT_HRGN, RGN_COPY );
	}

	if( !m_bDraging || iCol != m_iCol)
		rcHeader.DeflateRect( 0, 0, 1, 1 );
	else
		rcHeader.DeflateRect( 1, 1, 0, 0 );

	rcHeader.DeflateRect( 2, 0, 3, 0 );
	if( rcHeader.Width() <= 0 || rcHeader.Height() <= 0 )
		return TRUE;

	// draw sort arrow
	int iSort = GetSortIndex( iCol );
	if( pColumn->m_dwFormat&TLF_CAPTION_SORT && Sorts.GetSize()>0 )
	{
		CRect rcSort;
		rcSort = rcHeader;
		rcSort.left = rcSort.right - TLL_WIDTH/2;

		POINT pt;
		pt.x = rcSort.left;
		pt.y = rcSort.top + ( rcSort.Height() - TLL_HEIGHT)/2;

		pDC->IntersectClipRect( rcHeader );
		pDC->IntersectClipRect( rcSort );

		if( iSort == 0 )
		{
			// first sort column
			ASSERT( pColumn->m_dwFormat&TLF_SORT_MASK );

			if( pColumn->m_dwFormat&TLF_SORT_ASC )
				m_imgSort.Draw( pDC, TLH_SORT_ASC, pt, ILD_TRANSPARENT );
			else
				m_imgSort.Draw( pDC, TLH_SORT_DESC, pt, ILD_TRANSPARENT );
		}
		else if( iSort > 0 )
		{
			// other sort column
			ASSERT( pColumn->m_dwFormat&TLF_SORT_MASK );

			if( pColumn->m_dwFormat&TLF_SORT_ASC )
				m_imgSort.Draw( pDC, TLH_SORT_ASC2, pt, ILD_TRANSPARENT );
			else
				m_imgSort.Draw( pDC, TLH_SORT_DESC2, pt, ILD_TRANSPARENT );
		}
		else
		{
			// can sort column
			ASSERT( !(pColumn->m_dwFormat&TLF_SORT_MASK) );

			m_imgSort.Draw( pDC, TLH_SORT_NO, pt, ILD_TRANSPARENT );				
		}

		::ExtSelectClipRgn( pDC->m_hDC, DEFAULT_HRGN, RGN_COPY );

		rcHeader.DeflateRect( 0, 0, TLL_WIDTH/2, 0 );
	}

	if( rcHeader.Width() <= 0 )
		return TRUE;

	// draw image
	if( pColumn->m_dwFormat&TLF_CAPTION_IMAGE && pColumn->m_iImage>=0 )
	{
		pDC->IntersectClipRect( rcHeader );

		CRect rcImage;
		if( pColumn->m_dwFormat&TLF_IMAGEALIGN_LEFT )
		{
			rcImage			= rcHeader;
			rcImage.right	= rcHeader.left + TLL_WIDTH;
			rcHeader.left	= rcHeader.left + TLL_WIDTH;
		}
		else if( pColumn->m_dwFormat&TLF_IMAGEALIGN_RIGHT )

⌨️ 快捷键说明

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