📄 treelistctrl.cpp
字号:
// 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 + -