📄 chklistbox.cpp
字号:
// Do we call this again?
if(pItem->pParentItem->pParentItem != NULL)
ChangeParentItems(pDC, pItem->pParentItem);
}
LISTITEM* CCheckControl::GetItemClickedOn( CPtrList* pItemList, int nItem )
{
// loop for all items
LISTITEM* pListItem = NULL;
POSITION Pos = pItemList->GetHeadPosition();
while(Pos)
{
// Get this item
pListItem = (LISTITEM*)pItemList->GetNext(Pos);
m_nCurrentRow++;
// Is this the item
if( m_nCurrentRow == nItem)
return pListItem;
// Are there any open items in this?
if( pListItem->m_ItemList.GetCount() != 0 )
{
pListItem = GetItemClickedOn( &pListItem->m_ItemList, nItem);
if( pListItem )
return pListItem;
}
}
return NULL;
}
void CCheckControl::SetTopIndex(int nTop)
{
m_nTop = nTop;
UpdateScrollBar();
RedrawWindow();
}
int CCheckControl::SetCurSel(int nSelection)
{
// Is this for no selection? SetCurSel
if( nSelection == -1 )
{
m_pPrevSelItem = NULL;
m_nPrevSelRow = -1;
return 0;
}
// Get the item they have selected
m_nCurrentRow = 0;
LISTITEM* pItem = GetItemClickedOn( m_pRootPtrList, nSelection + 1 );
if( pItem == NULL )
return LB_ERR;
// Unpaint the last selection
m_nScreenRow = nSelection - 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;
}
}
// Set the new selected item
m_pPrevSelItem = pItem;
m_nPrevSelRow = m_nTop + m_nScreenRow;
pItem->bSelected = true;
// Should we spend the time redraw this item (NO-if it can't be seen)
if(nSelection >= m_nTop && nSelection <= m_nTop + m_nViewableRows)
DrawItem(pDC, pItem);
ReleaseDC(pDC);
return 0;
}
int CCheckControl::SetCheck(int nItem, int nCheckState)
{
// Get the item they have selected
m_nCurrentRow = 0;
LISTITEM* pItem = GetItemClickedOn( m_pRootPtrList, nItem + 1 );
if( pItem == NULL )
return LB_ERR;
// Set the attribute
m_nScreenRow = nItem - m_nTop;
CDC* pDC = GetWindowDC();
pItem->nCheckedState = nCheckState;
// Should we spend the time redraw this item (NO-if it can't be seen)
if(nItem >= m_nTop && nItem <= m_nTop + m_nViewableRows)
DrawItem(pDC, pItem);
// Update the parents
ChangeParentItems(pDC, pItem);
ReleaseDC(pDC);
return 0;
}
void CCheckControl::OnPaint()
{
int nSize = m_pRootPtrList->GetCount();
CPaintDC dc(this); // device context for painting
// Starting positions
m_nCurrentRow = 0;
m_nScreenRow = 0;
// Draw the items
DrawItems(&dc, m_pRootPtrList);
}
bool CCheckControl::DrawItems(CDC* pDC, CPtrList* pItemList, bool bChangeCheckedState, int nCheckedState)
{
// loop for all items
bool bKeepPainting = true;
LISTITEM* pListItem;
POSITION Pos = pItemList->GetHeadPosition();
while(Pos && bKeepPainting)
{
// Get this item (is it open?
pListItem = (LISTITEM*)pItemList->GetNext(Pos);
// Should we change the checked state?
if( bChangeCheckedState )
pListItem->nCheckedState = nCheckedState;
// Draw this item
if( m_nCurrentRow >= m_nTop )
{
DrawItem( pDC, pListItem );
m_nScreenRow++;
}
m_nCurrentRow++; //Increment the row encountered
// Only draw the maximum to fit on the screen
if( m_nScreenRow > m_nViewableRows )
bKeepPainting = false;
// Are there any open items in this?
if( pListItem->m_ItemList.GetCount() != 0 && bKeepPainting)
bKeepPainting = DrawItems( pDC, &pListItem->m_ItemList, bChangeCheckedState, nCheckedState);
}
return bKeepPainting;
}
void CCheckControl::DrawItem(CDC* pDC, LISTITEM* pListItem)
{
CPen* pOldPen = pDC->SelectObject(m_pParent->GetBkPen());
CFont* pOldFont = pDC->SelectObject(m_pParent->GetTextFont());
CBrush* pOldBrush = pDC->SelectObject(m_pParent->GetBkBrush());
// Positioning
int nYPos = (m_nScreenRow * m_pParent->GetLineHeight()) + PADDING;
// Draw Rectangle
CRect TextRect( -m_nLeft, nYPos, m_WindowRect.Width(), nYPos + m_pParent->GetLineHeight() );
pDC->Rectangle( TextRect );
// Draw the image (Calculate the center position)
TextRect.left += (pListItem->nLevel - 1) * m_pParent->GetImageWidth() + PADDING;
CSize ImagePos( TextRect.left, nYPos );
if( m_pParent->GetLineHeight() > m_pParent->GetImageHeight() )
ImagePos.cy = nYPos + (m_pParent->GetLineHeight() - m_pParent->GetImageHeight() ) / 2;
DrawBitmap( pDC, ImagePos, pListItem->nCheckedState );
// Is this a selected item
TextRect.left += m_pParent->GetImageWidth();
pDC->SetTextColor( pListItem->crTextColor );
if( pListItem->bSelected )
{
// Draw Highlight
CRect FocusRect = TextRect;
pDC->DrawText( pListItem->csText, pListItem->csText.GetLength(), FocusRect, DT_CALCRECT|DT_LEFT|DT_VCENTER );
// Is this past the window
if( FocusRect.right > m_WindowRect.right )
FocusRect.right = m_WindowRect.right - 4;
FocusRect.right += 5; FocusRect.left -= 4;
pDC->SetTextColor( RGB(0,0,0) );
pDC->DrawFocusRect( FocusRect );
// Set highlight color
pDC->SetTextColor( pListItem->crTextHighColor );
// Draw the selected background
CBrush HighlightBgBrush(pListItem->crBgHighlightColor);
FocusRect.InflateRect(-1, -1 );
pDC->FillRect(FocusRect, &HighlightBgBrush);
}
// Draw the Text
int nOldBkMode = pDC->SetBkMode( TRANSPARENT );
pDC->DrawText( pListItem->csText, pListItem->csText.GetLength(), TextRect, DT_LEFT|DT_VCENTER );
// Set back the old stuff
pDC->SetBkMode( nOldBkMode );
pDC->SelectObject( pOldFont );
pDC->SelectObject( pOldBrush );
pDC->SelectObject( pOldPen );
}
void CCheckControl::DrawBitmap( CDC* pdc, CSize ImagePos, int nCheckedState )
{
CDC dcBM;
BITMAP bm;
CBitmap* pOldBM;
CBitmap* pBitmap;
// Obtain the Bitmap to draw
if( nCheckedState == CHECKED )
pBitmap = m_pParent->GetCheckImage();
else if( nCheckedState == UNCHECKED )
pBitmap = m_pParent->GetUnCheckImage();
else
pBitmap = m_pParent->GetMiddleImage();
// Create a compatible DC
dcBM.CreateCompatibleDC(pdc);
// Draw the Bitmap
pBitmap->GetObject(sizeof(bm), &bm );
pOldBM = dcBM.SelectObject(pBitmap);
pdc->BitBlt( ImagePos.cx, ImagePos.cy, bm.bmWidth, bm.bmHeight, &dcBM, 0,0, SRCCOPY);
// Select the old object
pdc->SelectObject(pOldBM);
}
////////////////////////////////////////////////////////////////////////////////
// Main window
////////////////////////////////////////////////////////////////////////////////
CCheckList::CCheckList()
{
m_pCheckControl = NULL;
m_pBkPen = NULL;
m_pBkBrush = NULL;
m_pCheck = NULL;
m_pUnCheck = NULL;
m_pMiddleCheck = NULL;
m_bDeleteFont = false;
m_nTotalRowCount= 0;
m_nWidestItem = 0;
}
CCheckList::~CCheckList()
{
// Delete the data
DeleteItems(&m_RootItemList);
// Delete the control
if( m_pCheckControl ) delete m_pCheckControl;
// Delete the images
if(m_pCheck) delete m_pCheck;
if(m_pUnCheck) delete m_pUnCheck;
if(m_pMiddleCheck) delete m_pMiddleCheck;
// Delete GDI Items
if(m_pBkPen) delete m_pBkPen;
if(m_pBkBrush) delete m_pBkBrush;
if(m_bDeleteFont) delete m_pTextFont;
}
void CCheckList::DeleteItems(CPtrList* pItemList)
{
// Delete list item Structures
LISTITEM* pListItem;
POSITION Pos = pItemList->GetHeadPosition();
while(Pos)
{
// Get this item
pListItem = (LISTITEM*)pItemList->GetNext(Pos);
// Are there items in this
if( pListItem->m_ItemList.GetCount() != 0 )
DeleteItems( &pListItem->m_ItemList);
// Whas this item selected
if( pListItem->bSelected )
m_pCheckControl->SetCurSel(-1);
m_nTotalRowCount--;
delete pListItem;
}
// Remove the pointers
pItemList->RemoveAll();
}
BEGIN_MESSAGE_MAP(CCheckList, CWnd)
//{{AFX_MSG_MAP(CCheckList)
ON_WM_PAINT()
ON_WM_SIZE()
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
BOOL CCheckList::Create( CRect Rect, CWnd* pParent, UINT uID, UINT nCheckBitmap, UINT nUnCheckBitmap, UINT nMiddleCheckBitmap, COLORREF crBkColor, CFont* pCustomFont )
{
// 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 );
// First load the bitmaps
if( !LoadBitmaps(nCheckBitmap, nUnCheckBitmap, nMiddleCheckBitmap) )
return FALSE;
// Create the Contol
if( !CWnd::Create( csWndClass, "CLISTBOX", WS_CHILD|WS_VISIBLE, Rect, pParent, uID ))
return FALSE;
// Create the standard brush and pens and save the colors desired
m_pBkPen = new CPen(PS_SOLID, 1, crBkColor);
m_pBkBrush = new CBrush(crBkColor);
// Did they send a custom Font
m_pTextFont = pCustomFont;
if(m_pTextFont==NULL)
{
// Create the default font
m_bDeleteFont = true;
m_pTextFont = new CFont();
m_pTextFont->CreateFont( 14, 0, 0, 0, FW_NORMAL, 0, 0, 0, ANSI_CHARSET, OUT_TT_PRECIS,
CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
"TAHOMA");
}
// Set the height of an item
CDC* pdc = GetWindowDC();
TEXTMETRIC tm;
CFont* pOldFont = pdc->SelectObject(m_pTextFont);
pdc->GetTextMetrics(&tm);
pdc->SelectObject( pOldFont );
ReleaseDC(pdc);
// Is the font greater than the bitmap heights
if( tm.tmHeight + tm.tmDescent > m_nLineHeight )
m_nLineHeight = tm.tmHeight + tm.tmDescent;
// The number of viewable rows
GetClientRect(m_WindowRect);
// Call the create of the child
m_pCheckControl = new CCheckControl();
if( !m_pCheckControl->Create( m_WindowRect, this, uID + 1, pParent, &m_RootItemList, crBkColor ) )
return FALSE;
return TRUE;
}
bool CCheckList::LoadBitmaps(UINT nCheckBitmap, UINT nUnCheckBitmap, UINT nMiddleCheckBitmap)
{
// Create two new bitmap and load them
m_pCheck = new CBitmap();
if( !m_pCheck->LoadBitmap(nCheckBitmap) )
{
AfxMessageBox("Unable to load CHECK bitmap.");
return false;
}
m_pUnCheck = new CBitmap();
if( !m_pUnCheck->LoadBitmap(nUnCheckBitmap) )
{
AfxMessageBox("Unable to load UNCHECK bitmap.");
return false;
}
m_pMiddleCheck = new CBitmap();
if( !m_pMiddleCheck->LoadBitmap(nMiddleCheckBitmap) )
{
AfxMessageBox("Unable to load MIDDLE Check bitmap.");
return false;
}
// Make sure the hight and width are the same for both images
BITMAP checkbm, uncheckbm, middlecheckbm;
m_pCheck->GetObject(sizeof(checkbm), &checkbm );
m_pUnCheck->GetObject(sizeof(uncheckbm), &uncheckbm );
m_pMiddleCheck->GetObject(sizeof(middlecheckbm), &middlecheckbm );
if( checkbm.bmHeight != uncheckbm.bmHeight || checkbm.bmWidth != uncheckbm.bmWidth || checkbm.bmHeight != middlecheckbm.bmHeight || checkbm.bmWidth != middlecheckbm.bmWidth)
{
AfxMessageBox("Images must be the same size!");
return false;
}
m_cBitmapDimen.cx = uncheckbm.bmWidth;
m_cBitmapDimen.cy = uncheckbm.bmHeight;
// Increase the dimensions for spacing
m_cBitmapDimen.cx += 6;
m_cBitmapDimen.cy += 6;
// Set the Line height
m_nLineHeight = m_cBitmapDimen.cy;
return true;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -