Microsoft KB Archive/142960

= FIX: CCheckListBox Fails with Style LBS_MULTICOLUMN =

Article ID: 142960

Article Last Modified on 11/21/2006

-

APPLIES TO

 Microsoft Foundation Class Library 4.2, when used with:  Microsoft Visual C++ 4.0 Standard Edition

 Microsoft Visual C++ 4.1 Subscription 

-



This article was previously published under Q142960



SYMPTOMS
When using the CCheckListBox class and specifying a style of LBS_MULTICOLUMN, the user will be unable to check or uncheck items that are not displayed in the first column.



CAUSE
The hit-testing that is done in CCheckListBox::OnLButtonDown does not take into consideration which column the user is clicking.



RESOLUTION
Derive a class from CCheckListBox and override OnLButtonDown to do proper hit-testing. It will also be necessary to override OnLButtonDblClk and the constructor.

Step-by-Step Example
<ol> Bring up ClassWizard. Use "Add Class" to add a new class called CMyCheckListBox derived from CListBox. In the .h and .cpp files generated for the new class, change all occurrences of CListBox to CCheckListBox.</li> Add a protected member variable of type int called m_nCheckWidth to the new class.</li>  Modify the default constructor for CMyCheckListBox to look like this: CMyCheckListBox::CMyCheckListBox {       // the following code initializes the member variable // m_nCheckWidth to be the width of a check box.

CBitmap bitmap; BOOL bWin4 = (BYTE)GetVersion >= 4; HINSTANCE hInst = bWin4 ? NULL : LoadLibraryA("CTL3D32.DLL"); FARPROC pfnProc = (NULL == hInst) ? NULL : GetProcAddress(hInst,                                                  (LPCSTR)21);

if (bWin4 || pfnProc != NULL) VERIFY(bitmap.LoadBitmap(AFX_IDB_CHECKLISTBOX_95)); else VERIFY(bitmap.LoadBitmap(AFX_IDB_CHECKLISTBOX_NT));

BITMAP bm; bitmap.GetObject(sizeof (BITMAP), &bm); m_nCheckWidth = bm.bmWidth / 3;

if (hInst) FreeLibrary(hInst); }                       </li>  Use ClassWizard to add a handler for WM_LBUTTONDOWN, and implement it as follows: void CMyCheckListBox::OnLButtonDown(UINT nFlags, CPoint point) {       CRect itemRect; CRect clientRect;

GetClientRect(clientRect); for(int nIndex = GetTopIndex; nIndex < GetCount; nIndex++) {           GetItemRect(nIndex, &itemRect); if (!clientRect.PtInRect(itemRect.TopLeft)) break; if (itemRect.PtInRect(point) && IsEnabled(nIndex)) {               if (m_nStyle != BS_CHECKBOX && m_nStyle != BS_3STATE) {                   if (point.x - itemRect.left < m_nCheckWidth + 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 }       }        // call CListBox::OnLButtonDown // DO NOT call CCheckListBox::OnLButtonDown CListBox::OnLButtonDown(nFlags, point); }                       </li>  Use ClassWizard to add a handler for WM_LBUTTONDDBLCLK and just call CMyCheckListBox::OnLButtonDown: void CMyCheckListBox::OnLButtonDblClk(UINT nFlags, CPoint point) {       OnLButtonDown(nFlags, point); }                       </li></ol>

<div class="status_section">

STATUS
Microsoft has confirmed this to be a bug in the Microsoft products listed at the beginning of this article. This problem was corrected in Visual C++, 32-bit Edition, version 4.2.

Additional query words: kbVC400bug 4.00 4.10 vcfixlist420

Keywords: kbbug kbcode kbfix kblistbox kbnoupdate kbuidesign kbvc420fix KB142960

-

[mailto:TECHNET@MICROSOFT.COM Send feedback to Microsoft]

© Microsoft Corporation. All rights reserved.