📄 chklistbox.cpp
字号:
/////////////////////////////////////////////////////////////////////////////
// Check List Box for 32 bit
/////////////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "ChkListbox.h"
////////////////////////////////////////////////////////////////////////////
// ChkLstbx
/////////////////////////////////////////////////////////////////////////////
CCheckControl::CCheckControl()
{
m_nTop = 0;
m_nLeft = 0;
m_pPrevSelItem = NULL;
m_pParent = NULL;
m_nPrevSelRow=LB_ERR;
}
CCheckControl::~CCheckControl()
{
}
BEGIN_MESSAGE_MAP(CCheckControl, CWnd)
//{{AFX_MSG_MAP(CCheckControl)
ON_WM_PAINT()
ON_WM_LBUTTONDOWN()
ON_WM_SIZE()
ON_WM_VSCROLL()
ON_WM_HSCROLL()
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CCheckControl message handlers
BOOL CCheckControl::Create( CRect Rect, CCheckList* pParent, UINT nID, CWnd* pSuperParent, CPtrList* pRootPtrList, COLORREF crBkColor )
{
// Gets window colors, brushes
HCURSOR hCursor = AfxGetApp()->LoadStandardCursor(IDC_ARROW);
HBRUSH Brush = CreateSolidBrush(crBkColor);
CString csWndClass = AfxRegisterWndClass( CS_DBLCLKS|CS_HREDRAW|CS_VREDRAW, hCursor, Brush );
// Adjust the Rect for the border
Rect.top += 2;
Rect.left += 2;
Rect.bottom -= 2;
Rect.right -= 2;
// Create the Contol
if( !CWnd::Create( csWndClass, "Check Control", WS_CHILD|WS_VISIBLE, Rect, pParent, nID ))
return FALSE;
// Save the window Rect
GetClientRect(m_WindowRect);
m_nViewableRows = m_WindowRect.bottom / pParent->GetLineHeight();
// Save the Parent
m_pParent = pParent;
m_pSuperParent = pSuperParent;
m_pRootPtrList = pRootPtrList;
return TRUE;
}
void CCheckControl::OnSize(UINT nType, int cx, int cy)
{
CWnd::OnSize(nType, cx, cy);
GetClientRect(m_WindowRect);
if(m_pParent)
{
m_nViewableRows = m_WindowRect.bottom / m_pParent->GetLineHeight();
UpdateScrollBar();
}
}
void CCheckControl::UpdateScrollBar()
{
// Update the H scrollbar
GetClientRect(m_WindowRect);
// Do we need a scroll bar?
if( m_pParent->GetCount() > m_nViewableRows )
{
// Sets the scrollbar range up
ShowScrollBar(SB_VERT, TRUE);
SetScrollRange(SB_VERT, 0, m_pParent->GetCount() - m_nViewableRows, TRUE);
SetScrollPos(SB_VERT, m_nTop, TRUE);
}
else
{
// Sets the scrollbar range up
ShowScrollBar(SB_VERT, FALSE);
}
if( m_pParent->GetWidestItem() > m_WindowRect.right )
{
// Sets the scrollbar range up
ShowScrollBar(SB_HORZ, TRUE);
SetScrollRange(SB_HORZ, 0, m_pParent->GetWidestItem() - m_WindowRect.right, TRUE);
SetScrollPos(SB_HORZ, m_nLeft, TRUE);
}
else
{
// Sets the scrollbar range up
ShowScrollBar(SB_HORZ, FALSE);
}
}
void CCheckControl::OnHScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar)
{
// Reposition the m_nTop
switch( nSBCode )
{
case SB_LINELEFT:
if( m_nLeft > 0 )
{
m_nLeft -= HSCROLLAMOUNT;
SetScrollPos(SB_HORZ, m_nLeft, TRUE);
ScrollWindow( HSCROLLAMOUNT, 0 );
}
break;
case SB_LINERIGHT:
if( m_nLeft < m_pParent->GetWidestItem() - m_WindowRect.right )
{
m_nLeft += HSCROLLAMOUNT;
SetScrollPos(SB_HORZ, m_nLeft, TRUE);
ScrollWindow( -HSCROLLAMOUNT, 0);
}
break;
case SB_PAGELEFT:
if( m_nLeft == 0 )
return;
if( m_nLeft < m_WindowRect.right )
{
// Only scroll for remaining rows
ScrollWindow( m_nLeft, 0 );
m_nLeft = 0;
}
else
{
// Scroll for the total amount of viewable rows
m_nLeft -= m_WindowRect.right - 1;
ScrollWindow( m_nLeft * HSCROLLAMOUNT, 0 );
}
SetScrollPos(SB_HORZ, m_nLeft, TRUE);
break;
case SB_PAGERIGHT:
if( m_pParent->GetWidestItem() - m_WindowRect.right - m_nLeft < m_WindowRect.right )
{
// Only scroll for remaining rows
m_nLeft += m_pParent->GetWidestItem() - m_WindowRect.right - m_nLeft;
}
else
{
// Scroll for the total amount of viewable rows
m_nLeft += m_WindowRect.right - 1;
}
ScrollWindow( m_nLeft * -HSCROLLAMOUNT, 0 );
SetScrollPos(SB_HORZ, m_nLeft, TRUE);
break;
case SB_THUMBTRACK:
int nScrollBy;
if( (int)nPos == m_nLeft )
{
return;
}
else
{
nScrollBy = (int)nPos - m_nLeft;
}
m_nLeft += nScrollBy;
SetScrollPos(SB_HORZ, m_nLeft, TRUE);
ScrollWindow( -nScrollBy, 0 );
break;
}
CWnd::OnHScroll(nSBCode, nPos, pScrollBar);
}
void CCheckControl::OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar)
{
// Reposition the m_nTop
switch( nSBCode )
{
case SB_LINEUP:
if( m_nTop > 0 )
{
m_nTop--;
SetScrollPos(SB_VERT, m_nTop, TRUE);
ScrollWindow( 0, m_pParent->GetLineHeight() );
}
break;
case SB_LINEDOWN:
if( m_nTop < m_pParent->GetCount() - m_nViewableRows )
{
m_nTop++;
SetScrollPos(SB_VERT, m_nTop, TRUE);
ScrollWindow( 0, -m_pParent->GetLineHeight());
}
break;
case SB_PAGEDOWN:
if( m_nTop + m_nViewableRows == m_pParent->GetCount())
return;
if( m_pParent->GetCount() - m_nViewableRows - m_nTop < m_nViewableRows )
{
// Only scroll for remaining rows
m_nTop += m_pParent->GetCount() - m_nViewableRows - m_nTop;
ScrollWindow( 0, m_nTop * -m_pParent->GetLineHeight() );
}
else
{
// Scroll for the total amount of viewable rows
m_nTop += m_nViewableRows - 1;
ScrollWindow( 0, m_nTop * -m_pParent->GetLineHeight() );
}
SetScrollPos(SB_VERT, m_nTop, TRUE);
break;
case SB_PAGEUP:
if( m_nTop == 0 )
return;
if( m_nTop < m_nViewableRows )
{
// Only scroll for remaining rows
ScrollWindow( 0, m_nTop * m_pParent->GetLineHeight() );
m_nTop = 0;
}
else
{
// Scroll for the total amount of viewable rows
m_nTop -= m_nViewableRows - 1;
ScrollWindow( 0, m_nTop * m_pParent->GetLineHeight() );
}
SetScrollPos(SB_VERT, m_nTop, TRUE);
break;
case SB_THUMBTRACK:
int nScrollBy;
if( (int)nPos == m_nTop )
{
return;
}
else
{
nScrollBy = (int)nPos - m_nTop;
}
m_nTop += nScrollBy;
SetScrollPos(SB_VERT, m_nTop, TRUE);
ScrollWindow( 0, -m_pParent->GetLineHeight() * nScrollBy );
break;
}
CWnd::OnVScroll(nSBCode, nPos, pScrollBar);
}
void CCheckControl::OnLButtonDown(UINT nFlags, CPoint point)
{
// Starting positions
m_nCurrentRow = 0;
m_nScreenRow = 0;
// Calculate the item clicked on
int nItem = point.y / m_pParent->GetLineHeight() + m_nTop;
LISTITEM* pItem = GetItemClickedOn( m_pRootPtrList, nItem + 1 );
// Is this item out of view (if so then scroll window)
if( nItem >= m_nTop + m_nViewableRows )
{
m_nTop++;
ScrollWindow( 0, -m_pParent->GetLineHeight() );
SetScrollPos(SB_VERT, m_nTop, TRUE);
}
// Did we find the item?
if( pItem )
{
// Set the screen item
m_nScreenRow = nItem - m_nTop;
CDC* pDC = GetWindowDC();
// Unselect the previous one
int nTempRow = m_nScreenRow;
if( m_pPrevSelItem )
{
// Is this item on the screen? (Otherwise don't waste the time
m_pPrevSelItem->bSelected = false;
if( m_nPrevSelRow >= m_nTop && m_nPrevSelRow < m_nTop + m_nViewableRows )
{
// Draw this item unselected
m_nScreenRow = m_nPrevSelRow - m_nTop;
DrawItem(pDC, m_pPrevSelItem);
m_nScreenRow = nTempRow;
}
}
// Save the this item as the previous item
m_pPrevSelItem = pItem;
m_nPrevSelRow = m_nTop + m_nScreenRow;
// Select this item
pItem->bSelected = true;
// Did they click on the bitmap?
CRect ImageRect;
ImageRect.left = ( (m_pParent->GetImageWidth() * (pItem->nLevel - 1)) + PADDING );
ImageRect.right = ImageRect.left + m_pParent->GetImageWidth();
ImageRect.top = (m_nScreenRow * m_pParent->GetImageHeight()) + PADDING;
ImageRect.bottom= ImageRect.top * m_pParent->GetImageHeight();
// Common calls
if( ImageRect.PtInRect(point))
{
// Select this item
if( pItem->nCheckedState == UNCHECKED )
pItem->nCheckedState = CHECKED;
else
pItem->nCheckedState = UNCHECKED;
// Draw This Item
DrawItem(pDC, pItem);
// Draw all children items
int nOldRowPos = m_nScreenRow++;
DrawItems(pDC, &pItem->m_ItemList, true, pItem->nCheckedState );
// Change all parent items if nessary
m_nScreenRow = nOldRowPos;
ChangeParentItems(pDC, pItem);
// ReleaseDC(pDC);
}
else
{
// Draw This Item
DrawItem(pDC, pItem);
}
ReleaseDC(pDC);
}
// Invalidate();
CWnd::OnLButtonDown(nFlags, point);
}
void CCheckControl::ChangeParentItems(CDC* pDC, LISTITEM* pItem)
{
// Get this items parent
if(pItem->pParentItem == NULL)
return;
// Set the items
bool bCheckedItem = false;
bool bUnCheckedItem = false;
LISTITEM* pSubItem;
// Are all these item checked
int nMoveUpAmount = 1;
bool bIncreaseMoveUpAmount = true;
POSITION Pos = pItem->pParentItem->m_ItemList.GetHeadPosition();
while(Pos)
{
// Find a selected Item
pSubItem = (LISTITEM*)pItem->pParentItem->m_ItemList.GetNext(Pos);
if( pSubItem->nCheckedState == CHECKED || pSubItem->nCheckedState == INDETERMINATE)
bCheckedItem = true;
else if( pSubItem->nCheckedState == UNCHECKED )
bUnCheckedItem = true;
// Was this the orginal item sent in?
if( pItem == pSubItem )
bIncreaseMoveUpAmount = false;
// Are we still moving up a row?
if( bIncreaseMoveUpAmount )
nMoveUpAmount++;
}
// What should we set it too?
if(bCheckedItem && !bUnCheckedItem)
{
// All Items are checked
m_nScreenRow -= nMoveUpAmount;
pItem->pParentItem->nCheckedState = CHECKED;
DrawItem(pDC, pItem->pParentItem);
}
else if(!bCheckedItem && bUnCheckedItem)
{
// All Items are Unchecked
m_nScreenRow -= nMoveUpAmount;
pItem->pParentItem->nCheckedState = UNCHECKED;
DrawItem(pDC, pItem->pParentItem);
}
else
{
// Combination
m_nScreenRow -= nMoveUpAmount;
pItem->pParentItem->nCheckedState = INDETERMINATE;
DrawItem(pDC, pItem->pParentItem);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -