/******************************************************************************* * * (C) COPYRIGHT MICROSOFT CORPORATION, 2000 * * TITLE: CHKLISTV.CPP * * VERSION: 1.0 * * AUTHOR: ShaunIv * * DATE: 11/13/2000 * * DESCRIPTION: Listview with checkmarks * *******************************************************************************/ #include #include #include #include #include #include #include "chklistv.h" CCheckedListviewHandler::CCheckedListviewHandler(void) : m_bFullImageHit(false), m_hImageList(NULL), m_nCheckedImageIndex(-1), m_nUncheckedImageIndex(-1) { ZeroMemory(&m_sizeCheck,sizeof(m_sizeCheck)); CreateDefaultCheckBitmaps(); } CCheckedListviewHandler::~CCheckedListviewHandler(void) { // // Free all allocated memory // DestroyImageList(); } HBITMAP CCheckedListviewHandler::CreateBitmap( int nWidth, int nHeight ) { // // Create a 24bit RGB DIB section of a given size // HBITMAP hBitmap = NULL; HDC hDC = GetDC( NULL ); if (hDC) { BITMAPINFO BitmapInfo = {0}; BitmapInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); BitmapInfo.bmiHeader.biWidth = nWidth; BitmapInfo.bmiHeader.biHeight = nHeight; BitmapInfo.bmiHeader.biPlanes = 1; BitmapInfo.bmiHeader.biBitCount = 24; BitmapInfo.bmiHeader.biCompression = BI_RGB; PBYTE *pBits = NULL; hBitmap = CreateDIBSection( hDC, &BitmapInfo, DIB_RGB_COLORS, (void**)&pBits, NULL, 0 ); ReleaseDC( NULL, hDC ); } return hBitmap; } void CCheckedListviewHandler::DestroyImageList(void) { // // Destroy the image list and initialize related variables // if (m_hImageList) { ImageList_Destroy( m_hImageList ); m_hImageList = NULL; } m_nCheckedImageIndex = m_nUncheckedImageIndex = -1; m_sizeCheck.cx = m_sizeCheck.cy = 0; } bool CCheckedListviewHandler::ImagesValid(void) { // // Make sure the images in the image list are valid // return (m_hImageList && m_nCheckedImageIndex >= 0 && m_nUncheckedImageIndex >= 0 && m_sizeCheck.cx && m_sizeCheck.cy); } void CCheckedListviewHandler::Attach( HWND hWnd ) { if (m_WindowList.Find(hWnd) < 0) { m_WindowList.Append(hWnd); } } void CCheckedListviewHandler::Detach( HWND hWnd ) { int nIndex = m_WindowList.Find(hWnd); if (nIndex >= 0) { m_WindowList.Delete( nIndex ); } } bool CCheckedListviewHandler::WindowInList( HWND hWnd ) { return (m_WindowList.Find(hWnd) >= 0); } // // Private helpers // BOOL CCheckedListviewHandler::InCheckBox( HWND hwndList, int nItem, const POINT &pt ) { BOOL bResult = FALSE; if (WindowInList(hwndList)) { #if defined(DBG) WIA_TRACE((TEXT("nItem: %d"), nItem )); LVHITTESTINFO LvHitTestInfo = {0}; LvHitTestInfo.pt = pt; ListView_SubItemHitTest( hwndList, &LvHitTestInfo ); WIA_TRACE((TEXT("LvHitTestInfo.iItem: %d"), LvHitTestInfo.iItem )); #endif RECT rcItem = {0}; if (ListView_GetItemRect( hwndList, nItem, &rcItem, LVIR_ICON )) { WIA_TRACE((TEXT("pt: (%d, %d)"), pt.x, pt.y )); WIA_TRACE((TEXT("rcItem: (%d, %d), (%d, %d)"), rcItem.left, rcItem.top, rcItem.right, rcItem.bottom )); rcItem.right -= c_sizeCheckMarginX; rcItem.top += c_sizeCheckMarginY; rcItem.left = rcItem.right - m_sizeCheck.cx; rcItem.bottom = rcItem.top + m_sizeCheck.cy; bResult = PtInRect( &rcItem, pt ); } } return bResult; } UINT CCheckedListviewHandler::GetItemCheckState( HWND hwndList, int nIndex ) { UINT nResult = LVCHECKSTATE_NOCHECK; NMGETCHECKSTATE NmGetCheckState = {0}; NmGetCheckState.hdr.hwndFrom = hwndList; NmGetCheckState.hdr.idFrom = GetWindowLong( hwndList, GWL_ID ); NmGetCheckState.hdr.code = NM_GETCHECKSTATE; NmGetCheckState.nItem = nIndex; nResult = static_cast(SendMessage( reinterpret_cast(GetWindowLongPtr(hwndList,GWLP_HWNDPARENT)), WM_NOTIFY, GetWindowLong( hwndList, GWL_ID ), reinterpret_cast(&NmGetCheckState) ) ); return nResult; } UINT CCheckedListviewHandler::SetItemCheckState( HWND hwndList, int nIndex, UINT nCheck ) { UINT nResult = GetItemCheckState( hwndList, nIndex ); NMSETCHECKSTATE NmSetCheckState = {0}; NmSetCheckState.hdr.hwndFrom = hwndList; NmSetCheckState.hdr.idFrom = GetWindowLong( hwndList, GWL_ID ); NmSetCheckState.hdr.code = NM_SETCHECKSTATE; NmSetCheckState.nItem = nIndex; NmSetCheckState.nCheck = nCheck; SendMessage( reinterpret_cast(GetWindowLongPtr(hwndList,GWLP_HWNDPARENT)), WM_NOTIFY, GetWindowLong( hwndList, GWL_ID ), reinterpret_cast(&NmSetCheckState) ); return nResult; } int CCheckedListviewHandler::GetItemCheckBitmap( HWND hwndList, int nIndex ) { int nResult = -1; if (WindowInList(hwndList)) { UINT nCheck = GetItemCheckState( hwndList, nIndex ); switch (nCheck) { case LVCHECKSTATE_CHECKED: nResult = m_nCheckedImageIndex; break; case LVCHECKSTATE_UNCHECKED: nResult = m_nUncheckedImageIndex; break; } } return nResult; } BOOL CCheckedListviewHandler::RealHandleListClick( WPARAM wParam, LPARAM lParam, bool bIgnoreHitArea ) { BOOL bResult = FALSE; NMITEMACTIVATE *pNmItemActivate = reinterpret_cast(lParam); if (pNmItemActivate) { if (WindowInList(pNmItemActivate->hdr.hwndFrom)) { if (bIgnoreHitArea || InCheckBox(pNmItemActivate->hdr.hwndFrom,pNmItemActivate->iItem,pNmItemActivate->ptAction)) { UINT nCheck = GetItemCheckState( pNmItemActivate->hdr.hwndFrom, pNmItemActivate->iItem ); switch (nCheck) { case LVCHECKSTATE_UNCHECKED: SetItemCheckState( pNmItemActivate->hdr.hwndFrom, pNmItemActivate->iItem, LVCHECKSTATE_CHECKED ); break; case LVCHECKSTATE_CHECKED: SetItemCheckState( pNmItemActivate->hdr.hwndFrom, pNmItemActivate->iItem, LVCHECKSTATE_UNCHECKED ); break; } } bResult = TRUE; } } return 0; } // // Message handlers // BOOL CCheckedListviewHandler::HandleListClick( WPARAM wParam, LPARAM lParam ) { return RealHandleListClick( wParam, lParam, m_bFullImageHit ); } BOOL CCheckedListviewHandler::HandleListDblClk( WPARAM wParam, LPARAM lParam ) { return RealHandleListClick( wParam, lParam, true ); } BOOL CCheckedListviewHandler::HandleListKeyDown( WPARAM wParam, LPARAM lParam, LRESULT &lResult ) { BOOL bHandled = FALSE; NMLVKEYDOWN *pNmLvKeyDown = reinterpret_cast(lParam); if (WindowInList(pNmLvKeyDown->hdr.hwndFrom)) { lResult = 0; bool bControl = (GetKeyState(VK_CONTROL) & 0x8000) != 0; bool bShift = (GetKeyState(VK_SHIFT) & 0x8000) != 0; bool bAlt = (GetKeyState(VK_MENU) & 0x8000) != 0; if (pNmLvKeyDown->wVKey == VK_SPACE && !bControl && !bShift && !bAlt) { int nFocusedItem = ListView_GetNextItem( pNmLvKeyDown->hdr.hwndFrom, -1, LVNI_FOCUSED ); if (nFocusedItem >= 0) { UINT nCheckState = GetItemCheckState( pNmLvKeyDown->hdr.hwndFrom, nFocusedItem ); if (LVCHECKSTATE_CHECKED == nCheckState) { nCheckState = LVCHECKSTATE_UNCHECKED; } else if (LVCHECKSTATE_UNCHECKED == nCheckState) { nCheckState = LVCHECKSTATE_CHECKED; } if (nCheckState != LVCHECKSTATE_NOCHECK) { int nCurrItem = -1; while (true) { nCurrItem = ListView_GetNextItem( pNmLvKeyDown->hdr.hwndFrom, nCurrItem, LVNI_SELECTED ); if (nCurrItem < 0) { break; } SetItemCheckState( pNmLvKeyDown->hdr.hwndFrom, nCurrItem, nCheckState ); } } } lResult = TRUE; bHandled = TRUE; InvalidateRect( pNmLvKeyDown->hdr.hwndFrom, NULL, FALSE ); UpdateWindow( pNmLvKeyDown->hdr.hwndFrom ); } } return bHandled; } BOOL CCheckedListviewHandler::HandleListCustomDraw( WPARAM wParam, LPARAM lParam, LRESULT &lResult ) { BOOL bHandled = FALSE; NMLVCUSTOMDRAW *pNmCustomDraw = reinterpret_cast(lParam); if (pNmCustomDraw) { if (WindowInList(pNmCustomDraw->nmcd.hdr.hwndFrom)) { lResult = CDRF_DODEFAULT; #if defined(DUMP_NM_CUSTOMDRAW_MESSAGES) DumpCustomDraw(lParam,TEXT("SysListView32"),CDDS_ITEMPOSTPAINT); #endif if (CDDS_PREPAINT == pNmCustomDraw->nmcd.dwDrawStage) { lResult = CDRF_NOTIFYITEMDRAW; } else if (CDDS_ITEMPREPAINT == pNmCustomDraw->nmcd.dwDrawStage) { lResult = CDRF_NOTIFYPOSTPAINT|CDRF_NOTIFYSUBITEMDRAW; } else if (CDDS_ITEMPOSTPAINT == pNmCustomDraw->nmcd.dwDrawStage) { int nImageListIndex = GetItemCheckBitmap( pNmCustomDraw->nmcd.hdr.hwndFrom, static_cast(pNmCustomDraw->nmcd.dwItemSpec) ); if (nImageListIndex >= 0) { RECT rcItem = {0}; if (ListView_GetItemRect( pNmCustomDraw->nmcd.hdr.hwndFrom, pNmCustomDraw->nmcd.dwItemSpec, &rcItem, LVIR_ICON )) { ImageList_Draw( m_hImageList, nImageListIndex, pNmCustomDraw->nmcd.hdc, rcItem.right - m_sizeCheck.cx - c_sizeCheckMarginX, rcItem.top + c_sizeCheckMarginY, ILD_NORMAL ); lResult = CDRF_SKIPDEFAULT; } } } bHandled = TRUE; } } return bHandled; } void CCheckedListviewHandler::Select( HWND hwndList, int nIndex, UINT nSelect ) { if (WindowInList(hwndList)) { // // -1 means all images // if (nIndex < 0) { for (int i=0;i