mirror of https://github.com/lianthony/NT4.0
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
814 lines
20 KiB
814 lines
20 KiB
// This is a part of the Microsoft Foundation Classes C++ library.
|
|
// Copyright (C) 1992-1995 Microsoft Corporation
|
|
// All rights reserved.
|
|
//
|
|
// This source code is only intended as a supplement to the
|
|
// Microsoft Foundation Classes Reference and related
|
|
// electronic documentation provided with the library.
|
|
// See these sources for detailed information regarding the
|
|
// Microsoft Foundation Classes product.
|
|
|
|
#include "stdafx.h"
|
|
|
|
#ifdef AFX_CORE4_SEG
|
|
#pragma code_seg(AFX_CORE4_SEG)
|
|
#endif
|
|
|
|
#ifdef _DEBUG
|
|
#undef THIS_FILE
|
|
static char THIS_FILE[] = __FILE__;
|
|
#endif
|
|
|
|
#define new DEBUG_NEW
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// _AFX_CHECKLIST_STATE
|
|
|
|
class _AFX_CHECKLIST_STATE : public CNoTrackObject
|
|
{
|
|
public:
|
|
_AFX_CHECKLIST_STATE();
|
|
virtual ~_AFX_CHECKLIST_STATE();
|
|
|
|
HBITMAP m_hbitmapCheck;
|
|
CSize m_sizeCheck;
|
|
};
|
|
|
|
_AFX_CHECKLIST_STATE::_AFX_CHECKLIST_STATE()
|
|
{
|
|
CBitmap bitmap;
|
|
|
|
if (afxData.bWin4 || AfxGetCtl3dState()->m_pfnSubclassDlgEx != NULL)
|
|
VERIFY(bitmap.LoadBitmap(AFX_IDB_CHECKLISTBOX_95));
|
|
else
|
|
VERIFY(bitmap.LoadBitmap(AFX_IDB_CHECKLISTBOX_NT));
|
|
|
|
BITMAP bm;
|
|
bitmap.GetObject(sizeof (BITMAP), &bm);
|
|
m_sizeCheck.cx = bm.bmWidth / 3;
|
|
m_sizeCheck.cy = bm.bmHeight;
|
|
m_hbitmapCheck = (HBITMAP)bitmap.Detach();
|
|
}
|
|
|
|
_AFX_CHECKLIST_STATE::~_AFX_CHECKLIST_STATE()
|
|
{
|
|
if (m_hbitmapCheck != NULL)
|
|
::DeleteObject(m_hbitmapCheck);
|
|
}
|
|
|
|
EXTERN_PROCESS_LOCAL(_AFX_CHECKLIST_STATE, _afxChecklistState)
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// AFX_CHECK_DATA
|
|
|
|
struct AFX_CHECK_DATA
|
|
{
|
|
public:
|
|
int m_nCheck;
|
|
BOOL m_bEnabled;
|
|
DWORD m_dwUserData;
|
|
|
|
AFX_CHECK_DATA()
|
|
{
|
|
m_nCheck = 0;
|
|
m_bEnabled = TRUE;
|
|
m_dwUserData = 0;
|
|
};
|
|
};
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// CCheckListBox
|
|
|
|
BEGIN_MESSAGE_MAP(CCheckListBox, CListBox)
|
|
//{{AFX_MSG_MAP(CCheckListBox)
|
|
ON_WM_LBUTTONDOWN()
|
|
ON_WM_KEYDOWN()
|
|
ON_WM_CREATE()
|
|
ON_WM_LBUTTONDBLCLK()
|
|
ON_MESSAGE(WM_SETFONT, OnSetFont)
|
|
ON_MESSAGE(LB_ADDSTRING, OnLBAddString)
|
|
ON_MESSAGE(LB_FINDSTRING, OnLBFindString)
|
|
ON_MESSAGE(LB_FINDSTRINGEXACT, OnLBFindStringExact)
|
|
ON_MESSAGE(LB_GETITEMDATA, OnLBGetItemData)
|
|
ON_MESSAGE(LB_GETTEXT, OnLBGetText)
|
|
ON_MESSAGE(LB_INSERTSTRING, OnLBInsertString)
|
|
ON_MESSAGE(LB_SELECTSTRING, OnLBSelectString)
|
|
ON_MESSAGE(LB_SETITEMDATA, OnLBSetItemData)
|
|
ON_MESSAGE(LB_SETITEMHEIGHT, OnLBSetItemHeight)
|
|
//}}AFX_MSG_MAP
|
|
END_MESSAGE_MAP()
|
|
|
|
BOOL CCheckListBox::Create(DWORD dwStyle, const RECT& rect, CWnd* pParentWnd, UINT nID)
|
|
{
|
|
if (!(dwStyle & LBS_OWNERDRAWVARIABLE)) //must be one or the other
|
|
dwStyle |= LBS_OWNERDRAWFIXED;
|
|
return CListBox::Create(dwStyle, rect, pParentWnd, nID);
|
|
}
|
|
|
|
void CCheckListBox::SetCheckStyle(UINT nStyle)
|
|
{
|
|
ASSERT(nStyle == 0 | nStyle == BS_CHECKBOX | nStyle == BS_AUTOCHECKBOX |
|
|
nStyle == BS_AUTO3STATE | nStyle == BS_3STATE);
|
|
|
|
m_nStyle = nStyle;
|
|
}
|
|
|
|
void CCheckListBox::SetCheck(int nIndex, int nCheck)
|
|
{
|
|
ASSERT(::IsWindow(m_hWnd));
|
|
|
|
if (nCheck == 2)
|
|
{
|
|
if (m_nStyle == BS_CHECKBOX || m_nStyle == BS_AUTOCHECKBOX)
|
|
return;
|
|
}
|
|
|
|
LRESULT lResult = DefWindowProc(LB_GETITEMDATA, nIndex, 0);
|
|
if (lResult != LB_ERR)
|
|
{
|
|
|
|
AFX_CHECK_DATA* pState = (AFX_CHECK_DATA*)lResult;
|
|
|
|
if (pState == NULL)
|
|
pState = new AFX_CHECK_DATA;
|
|
|
|
pState->m_nCheck = nCheck;
|
|
VERIFY(DefWindowProc(LB_SETITEMDATA, nIndex, (LPARAM)pState) != LB_ERR);
|
|
|
|
InvalidateCheck(nIndex);
|
|
}
|
|
}
|
|
|
|
int CCheckListBox::GetCheck(int nIndex)
|
|
{
|
|
ASSERT(::IsWindow(m_hWnd));
|
|
|
|
LRESULT lResult = DefWindowProc(LB_GETITEMDATA, nIndex, 0);
|
|
if (lResult != LB_ERR)
|
|
{
|
|
AFX_CHECK_DATA* pState = (AFX_CHECK_DATA*)lResult;
|
|
if (pState != NULL)
|
|
return pState->m_nCheck;
|
|
}
|
|
return 0; // The default
|
|
}
|
|
|
|
void CCheckListBox::Enable(int nIndex, BOOL bEnabled)
|
|
{
|
|
ASSERT(::IsWindow(m_hWnd));
|
|
|
|
LRESULT lResult = DefWindowProc(LB_GETITEMDATA, nIndex, 0);
|
|
if (lResult != LB_ERR)
|
|
{
|
|
AFX_CHECK_DATA* pState = (AFX_CHECK_DATA*)lResult;
|
|
|
|
if (pState == NULL)
|
|
pState = new AFX_CHECK_DATA;
|
|
|
|
pState->m_bEnabled = bEnabled;
|
|
VERIFY(DefWindowProc(LB_SETITEMDATA, nIndex, (LPARAM)pState) != LB_ERR);
|
|
|
|
InvalidateItem(nIndex);
|
|
}
|
|
}
|
|
|
|
int CCheckListBox::IsEnabled(int nIndex)
|
|
{
|
|
ASSERT(::IsWindow(m_hWnd));
|
|
|
|
LRESULT lResult = DefWindowProc(LB_GETITEMDATA, nIndex, 0);
|
|
if (lResult != LB_ERR)
|
|
{
|
|
AFX_CHECK_DATA* pState = (AFX_CHECK_DATA*)lResult;
|
|
if (pState != NULL)
|
|
return pState->m_bEnabled;
|
|
}
|
|
return TRUE; // The default
|
|
}
|
|
|
|
CRect CCheckListBox::OnGetCheckPosition(CRect, CRect rectCheckBox)
|
|
{
|
|
return rectCheckBox;
|
|
}
|
|
|
|
void CCheckListBox::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct)
|
|
{
|
|
// You must override DrawItem and MeasureItem for LBS_OWNERDRAWVARIABLE
|
|
ASSERT((GetStyle() & (LBS_OWNERDRAWFIXED | LBS_HASSTRINGS)) ==
|
|
(LBS_OWNERDRAWFIXED | LBS_HASSTRINGS));
|
|
|
|
CDC* pDC = CDC::FromHandle(lpDrawItemStruct->hDC);
|
|
|
|
if (((LONG)(lpDrawItemStruct->itemID) >= 0) &&
|
|
(lpDrawItemStruct->itemAction & (ODA_DRAWENTIRE | ODA_SELECT)))
|
|
{
|
|
int cyItem = GetItemHeight(lpDrawItemStruct->itemID);
|
|
BOOL fDisabled = !IsWindowEnabled() || !IsEnabled(lpDrawItemStruct->itemID);
|
|
|
|
COLORREF newTextColor = fDisabled ?
|
|
RGB(0x80, 0x80, 0x80) : GetSysColor(COLOR_WINDOWTEXT); // light gray
|
|
COLORREF oldTextColor = pDC->SetTextColor(newTextColor);
|
|
|
|
COLORREF newBkColor = GetSysColor(COLOR_WINDOW);
|
|
COLORREF oldBkColor = pDC->SetBkColor(newBkColor);
|
|
|
|
if (newTextColor == newBkColor)
|
|
newTextColor = RGB(0xC0, 0xC0, 0xC0); // dark gray
|
|
|
|
if (!fDisabled && ((lpDrawItemStruct->itemState & ODS_SELECTED) != 0))
|
|
{
|
|
pDC->SetTextColor(GetSysColor(COLOR_HIGHLIGHTTEXT));
|
|
pDC->SetBkColor(GetSysColor(COLOR_HIGHLIGHT));
|
|
}
|
|
|
|
if (m_cyText == 0)
|
|
VERIFY(cyItem >= CalcMinimumItemHeight());
|
|
|
|
CString strText;
|
|
GetText(lpDrawItemStruct->itemID, strText);
|
|
|
|
pDC->ExtTextOut(lpDrawItemStruct->rcItem.left,
|
|
lpDrawItemStruct->rcItem.top + max(0, (cyItem - m_cyText) / 2),
|
|
ETO_OPAQUE, &(lpDrawItemStruct->rcItem), strText, strText.GetLength(), NULL);
|
|
|
|
pDC->SetTextColor(oldTextColor);
|
|
pDC->SetBkColor(oldBkColor);
|
|
}
|
|
|
|
if ((lpDrawItemStruct->itemAction & ODA_FOCUS) != 0)
|
|
pDC->DrawFocusRect(&(lpDrawItemStruct->rcItem));
|
|
}
|
|
|
|
void CCheckListBox::MeasureItem(LPMEASUREITEMSTRUCT)
|
|
{
|
|
// You must override DrawItem and MeasureItem for LBS_OWNERDRAWVARIABLE
|
|
ASSERT((GetStyle() & (LBS_OWNERDRAWFIXED | LBS_HASSTRINGS)) ==
|
|
(LBS_OWNERDRAWFIXED | LBS_HASSTRINGS));
|
|
}
|
|
|
|
void CCheckListBox::PreDrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct)
|
|
{
|
|
_AFX_CHECKLIST_STATE* pChecklistState = _afxChecklistState;
|
|
|
|
DRAWITEMSTRUCT drawItem;
|
|
memcpy(&drawItem, lpDrawItemStruct, sizeof(DRAWITEMSTRUCT));
|
|
|
|
if ((((LONG)drawItem.itemID) >= 0) &&
|
|
((drawItem.itemAction & (ODA_DRAWENTIRE | ODA_SELECT)) != 0))
|
|
{
|
|
int cyItem = GetItemHeight(drawItem.itemID);
|
|
|
|
CDC* pDC = CDC::FromHandle(drawItem.hDC);
|
|
|
|
COLORREF newBkColor = GetSysColor(COLOR_WINDOW);
|
|
|
|
BOOL fDisabled = !IsWindowEnabled() || !IsEnabled(drawItem.itemID);
|
|
if ((drawItem.itemState & ODS_SELECTED) && !fDisabled)
|
|
newBkColor = GetSysColor(COLOR_HIGHLIGHT);
|
|
|
|
COLORREF oldBkColor = pDC->SetBkColor(newBkColor);
|
|
|
|
CDC bitmapDC;
|
|
if (bitmapDC.CreateCompatibleDC(pDC))
|
|
{
|
|
int nCheck = GetCheck(drawItem.itemID);
|
|
HBITMAP hOldBitmap = (HBITMAP)::SelectObject(bitmapDC.m_hDC, pChecklistState->m_hbitmapCheck);
|
|
|
|
CRect rectCheck = drawItem.rcItem;
|
|
rectCheck.left += 1;
|
|
rectCheck.top += 1 + max(0, (cyItem - pChecklistState->m_sizeCheck.cy) / 2);
|
|
rectCheck.right = rectCheck.left + pChecklistState->m_sizeCheck.cx;
|
|
rectCheck.bottom = rectCheck.top + pChecklistState->m_sizeCheck.cy;
|
|
|
|
CRect rectItem = drawItem.rcItem;
|
|
rectItem.right = rectItem.left + pChecklistState->m_sizeCheck.cx + 2;
|
|
|
|
CRect rectCheckBox = OnGetCheckPosition(rectItem, rectCheck);
|
|
|
|
ASSERT(rectCheck.IntersectRect(rectItem, rectCheckBox));
|
|
ASSERT((rectCheck == rectCheckBox) && (rectCheckBox.Size() == pChecklistState->m_sizeCheck));
|
|
|
|
CBrush brush(newBkColor);
|
|
pDC->FillRect(rectItem, &brush);
|
|
|
|
pDC->BitBlt(rectCheckBox.left, rectCheckBox.top,
|
|
pChecklistState->m_sizeCheck.cx, pChecklistState->m_sizeCheck.cy, &bitmapDC,
|
|
pChecklistState->m_sizeCheck.cx * nCheck, 0, SRCCOPY);
|
|
|
|
::SelectObject(bitmapDC.m_hDC, hOldBitmap);
|
|
}
|
|
pDC->SetBkColor(oldBkColor);
|
|
}
|
|
|
|
if (drawItem.itemData != 0)
|
|
{
|
|
AFX_CHECK_DATA* pState = (AFX_CHECK_DATA*)drawItem.itemData;
|
|
drawItem.itemData = pState->m_dwUserData;
|
|
}
|
|
drawItem.rcItem.left = drawItem.rcItem.left + pChecklistState->m_sizeCheck.cx + 2;
|
|
|
|
DrawItem(&drawItem);
|
|
}
|
|
|
|
void CCheckListBox::PreMeasureItem(LPMEASUREITEMSTRUCT lpMeasureItemStruct)
|
|
{
|
|
int cyItem = CalcMinimumItemHeight();
|
|
|
|
MEASUREITEMSTRUCT measureItem;
|
|
memcpy(&measureItem, lpMeasureItemStruct, sizeof(MEASUREITEMSTRUCT));
|
|
|
|
measureItem.itemHeight = cyItem;
|
|
measureItem.itemWidth = (UINT)-1;
|
|
|
|
// WINBUG: Windows95 and Windows NT disagree on what this value
|
|
// should be. According to the docs, they are both wrong
|
|
if (GetStyle() & LBS_OWNERDRAWVARIABLE)
|
|
{
|
|
LRESULT lResult = DefWindowProc(LB_GETITEMDATA, measureItem.itemID, 0);
|
|
if (lResult != LB_ERR)
|
|
measureItem.itemData = (UINT)lResult;
|
|
else
|
|
measureItem.itemData = 0;
|
|
|
|
// WINBUG: This is only done in the LBS_OWNERDRAWVARIABLE case
|
|
// because Windows 95 does not initialize itemData to zero in the
|
|
// case of LBS_OWNERDRAWFIXED list boxes (it is stack garbage).
|
|
if (measureItem.itemData != 0)
|
|
{
|
|
AFX_CHECK_DATA* pState = (AFX_CHECK_DATA*)measureItem.itemData;
|
|
measureItem.itemData = pState->m_dwUserData;
|
|
}
|
|
}
|
|
|
|
MeasureItem(&measureItem);
|
|
|
|
lpMeasureItemStruct->itemHeight = max(measureItem.itemHeight,(UINT) cyItem);
|
|
lpMeasureItemStruct->itemWidth = measureItem.itemWidth;
|
|
}
|
|
|
|
int CCheckListBox::PreCompareItem(LPCOMPAREITEMSTRUCT lpCompareItemStruct)
|
|
{
|
|
COMPAREITEMSTRUCT compareItem;
|
|
memcpy(&compareItem, lpCompareItemStruct, sizeof(COMPAREITEMSTRUCT));
|
|
|
|
if (compareItem.itemData1 != 0)
|
|
{
|
|
AFX_CHECK_DATA* pState = (AFX_CHECK_DATA*)compareItem.itemData1;
|
|
compareItem.itemData1 = pState->m_dwUserData;
|
|
}
|
|
if (compareItem.itemData2 != 0)
|
|
{
|
|
AFX_CHECK_DATA* pState = (AFX_CHECK_DATA*)compareItem.itemData2;
|
|
compareItem.itemData2 = pState->m_dwUserData;
|
|
}
|
|
return CompareItem(&compareItem);
|
|
}
|
|
|
|
void CCheckListBox::PreDeleteItem(LPDELETEITEMSTRUCT lpDeleteItemStruct)
|
|
{
|
|
DELETEITEMSTRUCT deleteItem;
|
|
memcpy(&deleteItem, lpDeleteItemStruct, sizeof(DELETEITEMSTRUCT));
|
|
|
|
// WINBUG: The following if block is required because Windows NT
|
|
// version 3.51 does not properly fill out the LPDELETEITEMSTRUCT.
|
|
if (deleteItem.itemData == 0)
|
|
{
|
|
LRESULT lResult = DefWindowProc(LB_GETITEMDATA, deleteItem.itemID, 0);
|
|
if (lResult != LB_ERR)
|
|
deleteItem.itemData = (UINT)lResult;
|
|
}
|
|
|
|
if (deleteItem.itemData != 0)
|
|
{
|
|
AFX_CHECK_DATA* pState = (AFX_CHECK_DATA*)deleteItem.itemData;
|
|
deleteItem.itemData = pState->m_dwUserData;
|
|
delete pState;
|
|
}
|
|
DeleteItem(&deleteItem);
|
|
}
|
|
|
|
BOOL CCheckListBox::OnChildNotify(UINT message, WPARAM wParam, LPARAM lParam,
|
|
LRESULT* pResult)
|
|
{
|
|
switch (message)
|
|
{
|
|
case WM_DRAWITEM:
|
|
ASSERT(pResult == NULL); // no return value expected
|
|
PreDrawItem((LPDRAWITEMSTRUCT)lParam);
|
|
break;
|
|
case WM_MEASUREITEM:
|
|
ASSERT(pResult == NULL); // no return value expected
|
|
PreMeasureItem((LPMEASUREITEMSTRUCT)lParam);
|
|
break;
|
|
case WM_COMPAREITEM:
|
|
ASSERT(pResult != NULL); // return value expected
|
|
*pResult = PreCompareItem((LPCOMPAREITEMSTRUCT)lParam);
|
|
break;
|
|
case WM_DELETEITEM:
|
|
ASSERT(pResult == NULL); // no return value expected
|
|
PreDeleteItem((LPDELETEITEMSTRUCT)lParam);
|
|
break;
|
|
default:
|
|
return CListBox::OnChildNotify(message, wParam, lParam, pResult);
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
#ifdef _DEBUG
|
|
void CCheckListBox::PreSubclassWindow()
|
|
{
|
|
CListBox::PreSubclassWindow();
|
|
|
|
// CCheckListBoxes must be owner drawn
|
|
ASSERT(GetStyle() & (LBS_OWNERDRAWFIXED | LBS_OWNERDRAWVARIABLE));
|
|
}
|
|
#endif
|
|
|
|
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);
|
|
}
|
|
|
|
void CCheckListBox::OnLButtonDown(UINT nFlags, CPoint point)
|
|
{
|
|
SetFocus();
|
|
|
|
if (GetStyle() & LBS_OWNERDRAWFIXED)
|
|
{
|
|
int cyItem = GetItemHeight(0);
|
|
if (point.y < cyItem * GetCount())
|
|
{
|
|
int nIndex = GetTopIndex() + point.y / cyItem;
|
|
|
|
if (IsEnabled(nIndex))
|
|
{
|
|
if (m_nStyle != BS_CHECKBOX && m_nStyle != BS_3STATE)
|
|
{
|
|
_AFX_CHECKLIST_STATE* pChecklistState = _afxChecklistState;
|
|
if (point.x < pChecklistState->m_sizeCheck.cx + 2)
|
|
{
|
|
CWnd* pParent = GetParent();
|
|
ASSERT_VALID(pParent);
|
|
|
|
int nModulo = (m_nStyle == BS_AUTO3STATE) ? 3 : 2;
|
|
int nCheck = GetCheck(nIndex);
|
|
nCheck = (nCheck == nModulo) ? nCheck - 1 : nCheck;
|
|
SetCheck(nIndex, (nCheck + 1) % nModulo);
|
|
|
|
InvalidateCheck(nIndex);
|
|
|
|
CListBox::OnLButtonDown(nFlags, point);
|
|
|
|
// Inform of check
|
|
pParent->SendMessage(WM_COMMAND,
|
|
MAKEWPARAM(GetDlgCtrlID(), CLBN_CHKCHANGE),
|
|
(LPARAM)m_hWnd);
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
return; // Swallow LButtons for disabled items
|
|
}
|
|
}
|
|
else
|
|
{
|
|
CRect rectCheck;
|
|
|
|
for (int nIndex = GetTopIndex(); (rectCheck.bottom < point.y) || (nIndex < GetCount()); nIndex++)
|
|
{
|
|
GetItemRect(nIndex, rectCheck);
|
|
if (rectCheck.PtInRect(point))
|
|
{
|
|
if (IsEnabled(nIndex))
|
|
{
|
|
if (m_nStyle != BS_CHECKBOX && m_nStyle != BS_3STATE)
|
|
{
|
|
_AFX_CHECKLIST_STATE* pChecklistState = _afxChecklistState;
|
|
if (point.x < pChecklistState->m_sizeCheck.cx + 2)
|
|
{
|
|
CWnd* pParent = GetParent();
|
|
ASSERT_VALID(pParent);
|
|
|
|
int nModulo = (m_nStyle == BS_AUTO3STATE) ? 3 : 2;
|
|
int nCheck = GetCheck(nIndex);
|
|
nCheck = (nCheck == nModulo) ? nCheck - 1 : nCheck;
|
|
SetCheck(nIndex, (nCheck + 1) % nModulo);
|
|
|
|
InvalidateCheck(nIndex);
|
|
|
|
CListBox::OnLButtonDown(nFlags, point);
|
|
|
|
// Inform of check
|
|
pParent->SendMessage(WM_COMMAND,
|
|
MAKEWPARAM(GetDlgCtrlID(), CLBN_CHKCHANGE),
|
|
(LPARAM)m_hWnd);
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
return; // Swallow LButtons for disabled items
|
|
}
|
|
}
|
|
}
|
|
CListBox::OnLButtonDown(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;
|
|
SetCheck(nIndex, (nCheck + 1) % nModulo);
|
|
|
|
InvalidateCheck(nIndex);
|
|
|
|
// 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;
|
|
}
|
|
|
|
void CCheckListBox::OnLButtonDblClk(UINT nFlags, CPoint point)
|
|
{
|
|
_AFX_CHECKLIST_STATE* pChecklistState = _afxChecklistState;
|
|
if (point.x < pChecklistState->m_sizeCheck.cx)
|
|
{
|
|
// Double and single clicks act the same on the check box!
|
|
OnLButtonDown(nFlags, point);
|
|
return;
|
|
}
|
|
CListBox::OnLButtonDblClk(nFlags, point);
|
|
}
|
|
|
|
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)HIWORD(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)
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|