📄 winctrl3.cpp
字号:
int CCheckListBox::CalcMinimumItemHeight()
{
int nResult;
_AFX_CHECKLIST_STATE* pChecklistState = _afxChecklistState;
if ((GetStyle() & (LBS_HASSTRINGS | LBS_OWNERDRAWFIXED)) ==
(LBS_HASSTRINGS | LBS_OWNERDRAWFIXED))
{
CClientDC dc(this);
CFont* pOldFont = dc.SelectObject(GetFont());
TEXTMETRIC tm;
VERIFY (dc.GetTextMetrics ( &tm ));
dc.SelectObject(pOldFont);
m_cyText = tm.tmHeight;
nResult = max(pChecklistState->m_sizeCheck.cy + 1, m_cyText);
}
else
{
nResult = pChecklistState->m_sizeCheck.cy + 1;
}
return nResult;
}
void CCheckListBox::InvalidateCheck(int nIndex)
{
CRect rect;
_AFX_CHECKLIST_STATE* pChecklistState = _afxChecklistState;
GetItemRect(nIndex, rect);
rect.right = rect.left + pChecklistState->m_sizeCheck.cx + 2;
InvalidateRect(rect, FALSE);
}
void CCheckListBox::InvalidateItem(int nIndex)
{
CRect rect;
GetItemRect(nIndex, rect);
InvalidateRect(rect, FALSE);
}
int CCheckListBox::CheckFromPoint(CPoint point, BOOL& bInCheck)
{
// assume did not hit anything
bInCheck = FALSE;
int nIndex = -1;
_AFX_CHECKLIST_STATE* pChecklistState = _afxChecklistState;
if ((GetStyle() & (LBS_OWNERDRAWFIXED|LBS_MULTICOLUMN)) == LBS_OWNERDRAWFIXED)
{
// optimized case for ownerdraw fixed, single column
int cyItem = GetItemHeight(0);
if (point.y < cyItem * GetCount())
{
nIndex = GetTopIndex() + point.y / cyItem;
if (point.x < pChecklistState->m_sizeCheck.cx + 2)
++bInCheck;
}
}
else
{
// general case for ownerdraw variable or multiple column
for (int i = GetTopIndex(); i < GetCount(); i++)
{
CRect itemRect;
GetItemRect(i, &itemRect);
if (itemRect.PtInRect(point))
{
nIndex = i;
if (point.x < itemRect.left + pChecklistState->m_sizeCheck.cx + 2)
++bInCheck;
break;
}
}
}
return nIndex;
}
void CCheckListBox::SetSelectionCheck( int nCheck )
{
int* piSelectedItems;
int nSelectedItems;
int iSelectedItem;
nSelectedItems = GetSelCount();
if( nSelectedItems > 0 )
{
piSelectedItems = (int*)_alloca( nSelectedItems*sizeof( int ) );
GetSelItems( nSelectedItems, piSelectedItems );
for( iSelectedItem = 0; iSelectedItem < nSelectedItems; iSelectedItem++ )
{
if( IsEnabled( piSelectedItems[iSelectedItem] ) )
{
SetCheck( piSelectedItems[iSelectedItem], nCheck );
InvalidateCheck( piSelectedItems[iSelectedItem] );
}
}
}
}
void CCheckListBox::OnLButtonDown(UINT nFlags, CPoint point)
{
SetFocus();
// determine where the click is
BOOL bInCheck;
int nIndex = CheckFromPoint(point, bInCheck);
// if the item is disabled, then eat the click
if (!IsEnabled(nIndex))
return;
if (m_nStyle != BS_CHECKBOX && m_nStyle != BS_3STATE)
{
// toggle the check mark automatically if the check mark was hit
if (bInCheck)
{
CWnd* pParent = GetParent();
ASSERT_VALID( pParent );
int nModulo = (m_nStyle == BS_AUTO3STATE) ? 3 : 2;
int nCheck;
int nNewCheck;
nCheck = GetCheck( nIndex );
nCheck = (nCheck == nModulo) ? nCheck-1 : nCheck;
nNewCheck = (nCheck+1)%nModulo;
SetCheck( nIndex, nNewCheck );
InvalidateCheck( nIndex );
if( (GetStyle()&(LBS_EXTENDEDSEL|LBS_MULTIPLESEL)) && GetSel(
nIndex ) )
{
// The listbox is a multi-select listbox, and the user clicked on
// a selected check, so change the check on all of the selected
// items.
SetSelectionCheck( nNewCheck );
}
else
{
CListBox::OnLButtonDown( nFlags, point );
}
// Inform parent of check
pParent->SendMessage( WM_COMMAND, MAKEWPARAM( GetDlgCtrlID(),
CLBN_CHKCHANGE ), (LPARAM)m_hWnd );
return;
}
}
// do default listbox selection logic
CListBox::OnLButtonDown( nFlags, point );
}
void CCheckListBox::OnLButtonDblClk(UINT nFlags, CPoint point)
{
BOOL bInCheck;
CheckFromPoint(point, bInCheck);
if (bInCheck)
{
// Double and single clicks act the same on the check box!
OnLButtonDown(nFlags, point);
return;
}
CListBox::OnLButtonDblClk(nFlags, point);
}
void CCheckListBox::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags)
{
if (nChar == VK_SPACE)
{
int nIndex = GetCaretIndex();
CWnd* pParent = GetParent();
ASSERT_VALID(pParent);
if (nIndex != LB_ERR)
{
if (m_nStyle != BS_CHECKBOX && m_nStyle != BS_3STATE)
{
if ((GetStyle() & LBS_MULTIPLESEL) != 0)
{
if (IsEnabled(nIndex))
{
BOOL bSelected = GetSel(nIndex);
if (bSelected)
{
int nModulo = (m_nStyle == BS_AUTO3STATE) ? 3 : 2;
int nCheck = GetCheck(nIndex);
nCheck = (nCheck == nModulo) ? nCheck - 1 : nCheck;
SetCheck(nIndex, (nCheck + 1) % nModulo);
// Inform of check
pParent->SendMessage(WM_COMMAND,
MAKEWPARAM(GetDlgCtrlID(), CLBN_CHKCHANGE),
(LPARAM)m_hWnd);
}
SetSel(nIndex, !bSelected);
}
else
SetSel(nIndex, FALSE); // unselect disabled items
return;
}
else
{
// If there is a selection, the space bar toggles that check,
// all other keys are the same as a standard listbox.
if (IsEnabled(nIndex))
{
int nModulo = (m_nStyle == BS_AUTO3STATE) ? 3 : 2;
int nCheck = GetCheck(nIndex);
nCheck = (nCheck == nModulo) ? nCheck - 1 : nCheck;
int nNewCheck = (nCheck+1)%nModulo;
SetCheck(nIndex, nNewCheck);
InvalidateCheck(nIndex);
if( GetStyle()&LBS_EXTENDEDSEL )
{
// The listbox is a multi-select listbox, and the user
// clicked on a selected check, so change the check on all
// of the selected items.
SetSelectionCheck( nNewCheck );
}
// Inform of check
pParent->SendMessage(WM_COMMAND,
MAKEWPARAM(GetDlgCtrlID(), CLBN_CHKCHANGE),
(LPARAM)m_hWnd);
}
else
SetSel(nIndex, FALSE); // unselect disabled items
return;
}
}
}
}
CListBox::OnKeyDown(nChar, nRepCnt, nFlags);
}
int CCheckListBox::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if (CListBox::OnCreate(lpCreateStruct) == -1)
return -1;
if ((GetStyle() & (LBS_OWNERDRAWFIXED | LBS_HASSTRINGS))
== (LBS_OWNERDRAWFIXED | LBS_HASSTRINGS))
SetItemHeight(0, CalcMinimumItemHeight());
return 0;
}
LRESULT CCheckListBox::OnSetFont(WPARAM , LPARAM)
{
Default();
if ((GetStyle() & (LBS_OWNERDRAWFIXED | LBS_HASSTRINGS))
== (LBS_OWNERDRAWFIXED | LBS_HASSTRINGS))
SetItemHeight(0, CalcMinimumItemHeight());
return 0;
}
LRESULT CCheckListBox::OnLBAddString(WPARAM wParam, LPARAM lParam)
{
AFX_CHECK_DATA* pState = NULL;
if (!(GetStyle() & LBS_HASSTRINGS))
{
pState = new AFX_CHECK_DATA;
pState->m_dwUserData = lParam;
lParam = (LPARAM)pState;
}
LRESULT lResult = DefWindowProc(LB_ADDSTRING, wParam, lParam);
if (lResult == LB_ERR && pState != NULL)
delete pState;
return lResult;
}
LRESULT CCheckListBox::OnLBFindString(WPARAM wParam, LPARAM lParam)
{
if (GetStyle() & LBS_HASSTRINGS)
return DefWindowProc(LB_FINDSTRING, wParam, lParam);
int nIndex = wParam;
if (nIndex == -1) nIndex = 0;
for(; nIndex < GetCount(); nIndex++)
if ((DWORD)lParam == GetItemData(nIndex))
return nIndex;
return LB_ERR;
}
LRESULT CCheckListBox::OnLBFindStringExact(WPARAM wParam, LPARAM lParam)
{
if (GetStyle() & (LBS_HASSTRINGS | LBS_SORT))
return DefWindowProc(LB_FINDSTRINGEXACT, wParam, lParam);
int nIndex = wParam;
if (nIndex == -1) nIndex = 0;
for(; nIndex < GetCount(); nIndex++)
if ((DWORD)lParam == GetItemData(nIndex))
return nIndex;
return LB_ERR;
}
LRESULT CCheckListBox::OnLBGetItemData(WPARAM wParam, LPARAM lParam)
{
LRESULT lResult = DefWindowProc(LB_GETITEMDATA, wParam, lParam);
if (lResult != LB_ERR)
{
AFX_CHECK_DATA* pState = (AFX_CHECK_DATA*)lResult;
if (pState == NULL)
return 0; // default
lResult = pState->m_dwUserData;
}
return lResult;
}
LRESULT CCheckListBox::OnLBGetText(WPARAM wParam, LPARAM lParam)
{
LRESULT lResult = DefWindowProc(LB_GETTEXT, wParam, lParam);
if (GetStyle() & LBS_HASSTRINGS)
return lResult;
if (lResult != LB_ERR)
{
AFX_CHECK_DATA* pState = (AFX_CHECK_DATA*)lParam;
if (pState != NULL)
lParam = pState->m_dwUserData;
}
return lResult;
}
LRESULT CCheckListBox::OnLBInsertString(WPARAM wParam, LPARAM lParam)
{
AFX_CHECK_DATA* pState = NULL;
if (!(GetStyle() & LBS_HASSTRINGS))
{
pState = new AFX_CHECK_DATA;
pState->m_dwUserData = lParam;
lParam = (LPARAM)pState;
}
LRESULT lResult = DefWindowProc(LB_INSERTSTRING, wParam, lParam);
if (lResult == LB_ERR && pState != NULL)
delete pState;
return lResult;
}
LRESULT CCheckListBox::OnLBSelectString(WPARAM wParam, LPARAM lParam)
{
if (GetStyle() & LBS_HASSTRINGS)
return DefWindowProc(LB_SELECTSTRING, wParam, lParam);
int nIndex = wParam;
if (nIndex == -1) nIndex = 0;
for(; nIndex < GetCount(); nIndex++)
if ((DWORD)lParam == GetItemData(nIndex))
{
SetCurSel(nIndex);
return nIndex;
}
return LB_ERR;
}
LRESULT CCheckListBox::OnLBSetItemData(WPARAM wParam, LPARAM lParam)
{
LRESULT lResult = DefWindowProc(LB_GETITEMDATA, wParam, 0);
if (lResult != LB_ERR)
{
AFX_CHECK_DATA* pState = (AFX_CHECK_DATA*)lResult;
if (pState == NULL)
pState = new AFX_CHECK_DATA;
pState->m_dwUserData = lParam;
lResult = DefWindowProc(LB_SETITEMDATA, wParam, (LPARAM)pState);
if (lResult == LB_ERR)
delete pState;
}
return lResult;
}
LRESULT CCheckListBox::OnLBSetItemHeight(WPARAM wParam, LPARAM lParam)
{
int nHeight = max(CalcMinimumItemHeight(),(int)LOWORD(lParam));
return DefWindowProc(LB_SETITEMHEIGHT, wParam, MAKELPARAM(nHeight,0));
}
#ifdef AFX_INIT_SEG
#pragma code_seg(AFX_INIT_SEG)
#endif
IMPLEMENT_DYNAMIC(CCheckListBox, CListBox)
#pragma warning(disable: 4074)
#pragma init_seg(lib)
PROCESS_LOCAL(_AFX_CHECKLIST_STATE, _afxChecklistState)
/////////////////////////////////////////////////////////////////////////////
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -