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

📄 treelistctrl.cpp

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

#include "stdafx.h"
#include "TreeListDC.h"
#include "TreeListHeaderCtrl.h"
#include "TreeListTipCtrl.h"
#include "TreeListStaticCtrl.h"
#include "TreeListEditCtrl.h"
#include "TreeListComboCtrl.h"
#include "TLCDragWnd.h"
#include "TLCDropWnd.h"
#include "TreeListCtrl.h"
#include "TreeListResource.h"
#include "TreeListItem.h"

#include "resource.h"

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

/////////////////////////////////////////////////////////////////////////////
// CTreeListCtrl
IMPLEMENT_DYNCREATE(CTreeListCtrl, CWnd)

CTreeListCtrl::CTreeListCtrl() : 
	m_nItemHeight( 0 ),
	m_dwStyle( 0 ),
	m_dwState( TLS_OFFSCREENBUFFER ),
	m_pRootItem( NULL ),
	m_iSelCol( -1 ),
	m_pFocusItem( NULL ),
	m_pTargetItem( NULL ),
	m_pHoverItem( NULL ),
	m_iHoverItem( -1 ),
	m_iModifyCol( -1 ),
	m_pModifyItem( NULL ),
	m_pUpdateItem( NULL ),
	m_hButton( NULL ),
	m_hCheck( NULL ),
	m_hLock( NULL ),
	m_hDrop( NULL ),
	m_hStop( NULL ),
	m_pImageList( NULL ),
	m_pDragWnd( NULL ),
	m_pDropWnd( NULL ),
	m_pTargetWnd( NULL )
{
	// construct

	// create windows class
	WNDCLASS wndclass;
	HINSTANCE hInst = AfxGetInstanceHandle();
	CTreeListResource	TreeListResource;

	if( !::GetClassInfo(hInst, TREELISTCTRL_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	= TREELISTCTRL_CLASSNAME;

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

	// back ground colors of normal status
	m_crBkColor				= 0xFFFFE0;				
	m_crBkColor_0			= 0xFCFCFC;				
	m_crBkColor_1			= 0xF0F0F0;				
	m_crBkColor_2			= 0xF8F8F8;				

	// back ground colors of disable status
	m_crBkDisable			= 0xC0C080;				
	m_crBkDisable_0			= 0xCCCCCC;				
	m_crBkDisable_1			= 0xC0C0C0;				
	m_crBkDisable_2			= 0xC8C8C8;				

	// back ground colors of selected item
	m_crBkSelected			= 0xC08080;				
	m_crBkSelectedRow		= 0xA00000;				
	m_crBkSelectedColumn	= 0xD00000;				
	m_crBkSelectedNoFocus	= 0xD0A0A0;				

	// text colors
	m_crTextSelected		= 0xE8E8E8;				
	m_crTextSelectedRow		= 0xF0F0F0;				
	m_crTextSelectedColumn	= 0xFFFFFF;				
	m_crTextSelectedNoFocus	= 0xE0E0E0;				

	// normal text color
	m_crText				= 0x000000;				
	m_crTextHover			= 0x00FF00;				

	// grid color
	m_crGrid				= 0xD0D0D0;				
	m_crTreeLine			= 0x808080;				

	m_Palette.CreateStockObject( DEFAULT_PALETTE );
	m_Font.CreateStockObject( SYSTEM_FIXED_FONT );

	m_hButton	= AfxGetApp()->LoadCursor( IDC_CURSOR_BUTTON );
	m_hCheck	= AfxGetApp()->LoadCursor( IDC_CURSOR_CHECK );
	m_hLock		= AfxGetApp()->LoadCursor( IDC_CURSOR_LOCK );

	m_hDrop		= AfxGetApp()->LoadCursor( IDC_CURSOR_DROP );
	m_hStop		= AfxGetApp()->LoadCursor( IDC_CURSOR_STOP );
	m_hArrow	= AfxGetApp()->LoadStandardCursor( IDC_ARROW );

	m_pRootItem = new CTreeListItem( 1 );
	m_pRootItem->Expand();
}

CTreeListCtrl::~CTreeListCtrl()
{
	// deconstruct
	m_wndHeader.DestroyWindow();
	m_wndTip.DestroyWindow();

	if( m_Palette.m_hObject != NULL )
		m_Palette.DeleteObject();

	if( m_Font.m_hObject != NULL )
		m_Font.DeleteObject();

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

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

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

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

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

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

	while( m_arColumns.GetSize() > 0 )
	{
		CTreeListColumnInfo* pColumnInfo;
		int nIndex;
		
		nIndex = m_arColumns.GetUpperBound();
		pColumnInfo = (CTreeListColumnInfo*) m_arColumns[nIndex];

		m_arColumns.RemoveAt( nIndex );
		delete pColumnInfo;
	}

	m_bmpBkBitmap.DeleteObject();
	m_bmpBkDisable.DeleteObject();

	m_imgCheck.DeleteImageList();
	m_imgLock.DeleteImageList();
	m_imgTree.DeleteImageList();

	delete m_pRootItem;
}

BEGIN_MESSAGE_MAP(CTreeListCtrl, CWnd)
	//{{AFX_MSG_MAP(CTreeListCtrl)
	ON_WM_ERASEBKGND()
	ON_WM_PAINT()
	ON_WM_ENABLE()
	ON_WM_NCCALCSIZE()
	ON_WM_NCPAINT()
	ON_WM_SIZE()
	ON_WM_HSCROLL()
	ON_WM_VSCROLL()
	ON_WM_MOUSEWHEEL()
	ON_WM_MOUSEMOVE()
	ON_WM_LBUTTONDOWN()
	ON_WM_RBUTTONDOWN()
	ON_WM_SETFOCUS()
	ON_WM_KILLFOCUS()
	ON_WM_LBUTTONUP()
	ON_WM_RBUTTONUP()
	ON_WM_LBUTTONDBLCLK()
	ON_WM_DESTROY()
	ON_WM_TIMER()
	ON_WM_CANCELMODE()
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CTreeListCtrl message handler
BOOL CTreeListCtrl::Create( DWORD dwStyle, const RECT& rect, CWnd* pParentWnd, UINT nID )
{
	// create control
	SetState( TLS_SUBCLASSFROMCREATE );
	DWORD dwExStyle = 0;

	if( dwStyle&WS_BORDER )
	{
		dwStyle &= ~WS_BORDER;
		dwExStyle |= WS_EX_CLIENTEDGE;
	}

	if( !CWnd::CreateEx( dwExStyle, TREELISTCTRL_CLASSNAME, NULL, dwStyle, rect, pParentWnd, nID ) )
		return FALSE;

	if( !Create() )
		return FALSE;

	return TRUE;
}

BOOL CTreeListCtrl::Create()
{
	// create control
	CRect Rect( 0, 0, 0, 0);

	if( !m_wndHeader.Create( 0, Rect, this, 0 ) )
		return FALSE;

	if( !m_wndTip.Create( this ) )
		return FALSE;

	DWORD dwStyle;

	dwStyle = WS_BORDER | WS_CHILD | SS_NOTIFY | SS_CENTERIMAGE;
	if( !m_wndStatic.Create( _T("123"), dwStyle, Rect, this, 0 ) )
		return FALSE;

	dwStyle = WS_BORDER | WS_CHILD | ES_CENTER | ES_AUTOHSCROLL;

	if( !m_wndEdit.Create( dwStyle, Rect, this, 0 ) )
		return FALSE;

	dwStyle = WS_CHILD | CBS_DROPDOWNLIST | CBS_AUTOHSCROLL | CBS_NOINTEGRALHEIGHT;

	if( !m_wndCombo.Create( dwStyle, Rect, this, 0 ) )
		return FALSE;

	if( !m_bmpBkBitmap.LoadBitmap( IDB_TREELIST_BITMAP ) )
		return FALSE;

	if( !m_bmpBkDisable.LoadBitmap( IDB_TREELIST_DISABLE ) )
		return FALSE;

	if( !m_imgCheck.Create( IDB_TREELIST_CHECK, 16, 3, 0xFF00FF ) )
		return FALSE;

	if( !m_imgLock.Create( IDB_TREELIST_LOCK, 8, 3, 0xFF00FF ) )
		return FALSE;

	if( !m_imgTree.Create( IDB_TREELIST_TREE, 16, 3, 0xFFFFFF ) )
		return FALSE;

	m_pImageList = &m_imgTree;

	SetFont();
	SetItemHeight();
	
	m_wndHeader.SetHeaderFont();
	m_wndHeader.SetHeaderHeight();
	m_wndTip.SetFont();
	
	m_wndStatic.SetFont( GetFont() );
	m_wndEdit.SetFont( GetFont() );
	m_wndCombo.SetFont( GetFont() );

	Layout();

	return TRUE;
}

void CTreeListCtrl::PreSubclassWindow() 
{
	// pre subclass window
	CWnd::PreSubclassWindow();

	if( !GetState( TLS_SUBCLASSFROMCREATE ) )
	{
		if( !Create() )
		{
			AfxThrowMemoryException();
			return;
		}
	}

	return;
}

void CTreeListCtrl::OnDestroy() 
{
	CWnd::OnDestroy();
	
	m_arShows.RemoveAll();
	m_arSorts.RemoveAll();

	DeleteItem( TLI_ROOT );
}

void CTreeListCtrl::SetAllScroll()
{
	// set all scroll bars
	CRect rcPreClient;
	GetWindowRect( &rcPreClient );
	rcPreClient.DeflateRect( 1, 1 );

	int cx = ::GetSystemMetrics( SM_CXVSCROLL );
	int cy = ::GetSystemMetrics( SM_CYHSCROLL );

	SCROLLINFO siv;
	SCROLLINFO sih;

	GetScrollInfo( SB_VERT, &siv, SIF_POS | SIF_RANGE );
	GetScrollInfo( SB_HORZ, &sih, SIF_POS | SIF_RANGE );

	BOOL bHorzScroll = FALSE;
	BOOL bVertScroll = FALSE;

	if( rcPreClient.Width() < GetWidth() )
	{
		bHorzScroll = TRUE;

		if( rcPreClient.Height() - cy < m_wndHeader.GetHeaderHeight() + GetVisibleCount() * GetItemHeight() )
			bVertScroll = TRUE;
	}
	else if( rcPreClient.Height() < m_wndHeader.GetHeaderHeight() + GetVisibleCount() * GetItemHeight() )
	{
		bVertScroll = TRUE;

		if( rcPreClient.Width() - cx < GetWidth() )
			bHorzScroll = TRUE;
	}

	if( sih.nPos != sih.nMin )
		bHorzScroll = TRUE;

	if( siv.nPos != siv.nMin )
		bVertScroll = TRUE;

	if( bHorzScroll )
	{
		if( rcPreClient.Width() > cx )
			rcPreClient.right -= cx;
		else
			rcPreClient.right = rcPreClient.left;
	}

	if( bVertScroll )
	{
		if( rcPreClient.Height() > cy )
			rcPreClient.bottom -= cy;
		else
			rcPreClient.bottom = rcPreClient.top;
	}

	SetHorzScroll( &rcPreClient );
	SetVertScroll( &rcPreClient );
}

void CTreeListCtrl::SetHorzScroll( CRect* pPreClient )
{
	// set horizonal scroll
	SCROLLINFO si;
	GetScrollInfo( SB_HORZ, &si, SIF_ALL );

	if( pPreClient->Width() < GetWidth() )
	{
		si.cbSize	= sizeof( SCROLLINFO );
		si.nMin		= 0;
		si.nMax		= GetWidth() - 1;
		si.nPage	= pPreClient->Width();
		si.nPos		= si.nPos;
		si.fMask	=  SIF_PAGE | SIF_RANGE | SIF_POS;
		if( si.nPos > si.nMax - (int)si.nPage )
			si.nPos = si.nMax - (int)si.nPage;
	}
	else
	{
		si.cbSize	= sizeof( SCROLLINFO );
		si.nMin		= 0;
		si.nMax		= 0;
		si.nPage	= 0;
		si.nPos		= 0;
		si.fMask	=  SIF_PAGE | SIF_RANGE | SIF_POS;
	}
	
	SetScrollInfo( SB_HORZ, &si, TRUE );
}

void CTreeListCtrl::SetVertScroll( CRect* pPreClient )
{
	// set vertical scroll
	SCROLLINFO si;
	GetScrollInfo( SB_VERT, &si, SIF_ALL );

	if( pPreClient->Height() < m_wndHeader.GetHeaderHeight() + GetVisibleCount() * GetItemHeight() || si.nPos != si.nMin )
	{
		int nShowRows	=	m_rcTreeList.Height() / GetItemHeight();

		si.cbSize	= sizeof( SCROLLINFO );
		si.nMin		= 0;
		si.nMax		= GetVisibleCount() - 1;
		si.nPos		= si.nPos;
		si.nPage	= max( nShowRows, 1 ); // min( pPreClient->Height()/m_nRowHeight, si.nMax -si.nPos );
		si.fMask	=  SIF_PAGE | SIF_RANGE | SIF_POS;
		if( si.nPos > si.nMax )
			si.nPos = si.nMax;
	}
	else
	{
		si.cbSize	= sizeof( SCROLLINFO );
		si.nMin		= 0;
		si.nMax		= 0;
		si.nPage	= 0;
		si.nPos		= 0;
		si.fMask	=  SIF_PAGE | SIF_RANGE | SIF_POS;
	}

	SetScrollInfo( SB_VERT, &si, TRUE );
}


void CTreeListCtrl::OnHScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar) 
{
	// on horizonal scroll
	SCROLLINFO si;
	GetScrollInfo( SB_HORZ, &si, SIF_ALL );

	switch( nSBCode )
	{
	case SB_LINEUP:
		if( si.nPos > si.nMin )
			si.nPos--;
		break;

	case SB_LINEDOWN:
		if( si.nPos <= si.nMax - (int)si.nPage )
			si.nPos++;
		break;

	case SB_PAGEUP:
		si.nPos -= si.nPage;
		if( si.nPos < si.nMin )
			si.nPos = si.nMin;
		break;

	case SB_PAGEDOWN:
		si.nPos += si.nPage;
		if( si.nPos > si.nMax )
			si.nPos = si.nMax;
		break;

	case SB_TOP:
		si.nPos = si.nMin;
		break;

	case SB_BOTTOM:
		si.nPos = si.nMax;
		break;

	case SB_THUMBPOSITION:
	case SB_THUMBTRACK:
		si.nPos = si.nTrackPos;
		break;

	default:
		break;
	}
	
	SetScrollPos( SB_HORZ, si.nPos );
	m_wndHeader.RedrawWindow();
	RedrawWindow();
}

void CTreeListCtrl::OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar) 
{
	// on vertival scroll
	SCROLLINFO si;
	GetScrollInfo( SB_VERT, &si, SIF_ALL );

	switch( nSBCode )
	{
	case SB_LINEUP:
		if( si.nPos > si.nMin )
			si.nPos--;
		break;

	case SB_LINEDOWN:
		if( si.nPos <= si.nMax - (int)si.nPage )
			si.nPos++;;
		break;

	case SB_PAGEUP:
		si.nPos -= si.nPage;
		if( si.nPos < si.nMin )
			si.nPos = si.nMin;
		break;

	case SB_PAGEDOWN:
		si.nPos += si.nPage;
		if( si.nPos > si.nMax )
			si.nPos = si.nMax;
		break;

	case SB_TOP:
		si.nPos = si.nMin;
		break;

	case SB_BOTTOM:
		si.nPos = si.nMax;
		break;

	case SB_THUMBPOSITION:
	case SB_THUMBTRACK:
		si.nPos = si.nTrackPos;
		break;

	default:
		break;
	}

	if( si.nPos == si.nMin )
	{
		if(  si.nMax-si.nMin+1 <= m_rcClient.Height()/m_nItemHeight )
		{
			Layout();
		}
	}

	SetScrollPos( SB_VERT, si.nPos );

	Invalidate();
}

LRESULT CTreeListCtrl::Notify( DWORD dwMessage, CTreeListItem* pItem, int iCol )
{
	// notify a message
	NMTREELIST nm;
	nm.hdr.hwndFrom = GetSafeHwnd();
	nm.hdr.idFrom	= GetDlgCtrlID();
	nm.hdr.code		= dwMessage;

	nm.pItem	= pItem;
	nm.iCol		= iCol;

	if( nm.iCol == -1 )
		nm.iCol = 0;

	CWnd* pWnd		= GetParent();
	LRESULT lResult	= 0;

	if( pWnd == NULL )
		lResult = 0;

⌨️ 快捷键说明

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