/**********************************************************************/ /** Microsoft Windows/NT **/ /** Copyright(c) Microsoft Corp., 1995 **/ /**********************************************************************/ /* FILE HISTORY: */ #define OEMRESOURCE #include "stdafx.h" #include "COMMON.h" #ifdef _DEBUG #undef THIS_FILE static char BASED_CODE THIS_FILE[] = __FILE__; #endif #define new DEBUG_NEW CListBoxExResources::CListBoxExResources( int bmId, // Bitmap resource ID int nBitmaps, // Number of bitmaps COLORREF crBackground // Background colour to mask out ) { m_BitMapId = bmId; m_ColorTransparent = crBackground; m_BitmapWidth = -1; // Set Later m_nBitmaps = nBitmaps; m_BitmapHeight = 0; GetSysColors(); PrepareBitmaps( FALSE ); } CListBoxExResources::~CListBoxExResources() { UnprepareBitmaps(); } void CListBoxExResources::UnprepareBitmaps() { CBitmap* pBmp = (CBitmap*)CGdiObject::FromHandle(m_hOldBitmap); ASSERT(pBmp); VERIFY(m_dcFinal.SelectObject(pBmp)); VERIFY(m_dcFinal.DeleteDC()); VERIFY(m_BmpScreen.DeleteObject()); } void CListBoxExResources::PrepareBitmaps( BOOL reinit ) { ASSERT( m_BitMapId ); if( reinit ) { UnprepareBitmaps(); } CDC dcImage; CDC dcMasks; // // create device contexts compatible with screen // VERIFY(dcImage.CreateCompatibleDC(0)); VERIFY(dcMasks.CreateCompatibleDC(0)); VERIFY(m_dcFinal.CreateCompatibleDC(0)); CBitmap bitmap; VERIFY(bitmap.LoadBitmap(m_BitMapId)); BITMAP bm; VERIFY(bitmap.GetObject(sizeof(BITMAP),&bm)); // // Each bitmap is assumed to be the same size. // m_BitmapWidth = bm.bmWidth / m_nBitmaps; const int bmWidth = bm.bmWidth; const int bmHeight = bm.bmHeight; m_BitmapHeight = bmHeight; CBitmap* pOldImageBmp = dcImage.SelectObject(&bitmap); ASSERT(pOldImageBmp); CBitmap BmpMasks; VERIFY(BmpMasks.CreateBitmap( bmWidth, bmHeight*2,1,1,NULL )); CBitmap* pOldMaskBmp = (CBitmap*)dcMasks.SelectObject(&BmpMasks); ASSERT(pOldMaskBmp); // // create the foreground and object masks // COLORREF crOldBk = dcImage.SetBkColor( m_ColorTransparent ); dcMasks.BitBlt( 0, 0, bmWidth, bmHeight, &dcImage, 0, 0, SRCCOPY ); dcMasks.BitBlt( 0, 0, bmWidth, bmHeight, &dcImage, 0, bmHeight, SRCAND ); dcImage.SetBkColor( crOldBk ); dcMasks.BitBlt( 0, bmHeight, bmWidth, bmHeight, &dcMasks, 0, 0, NOTSRCCOPY ); // // create DC to hold final image // VERIFY(m_BmpScreen.CreateCompatibleBitmap( &dcImage, bmWidth, bmHeight*2 )); CBitmap* pOldBmp = (CBitmap*)m_dcFinal.SelectObject(&m_BmpScreen); ASSERT(pOldBmp); m_hOldBitmap = pOldBmp->m_hObject; CBrush b1, b2; VERIFY(b1.CreateSolidBrush( m_ColorHighlight )); VERIFY(b2.CreateSolidBrush( m_ColorWindow )); m_dcFinal.FillRect( CRect(0,0,bmWidth,bmHeight), &b1 ); m_dcFinal.FillRect( CRect(0,bmHeight,bmWidth,bmHeight*2), &b2 ); // // mask out the object pixels in the destination // m_dcFinal.BitBlt(0,0,bmWidth,bmHeight,&dcMasks,0,0,SRCAND); // // mask out the background pixels in the image // dcImage.BitBlt(0,0,bmWidth,bmHeight,&dcMasks,0,bmHeight,SRCAND); // // XOR the revised image into the destination // m_dcFinal.BitBlt(0,0,bmWidth,bmHeight,&dcImage,0,0,SRCPAINT); // // mask out the object pixels in the destination // m_dcFinal.BitBlt(0,bmHeight,bmWidth,bmHeight,&dcMasks,0,0,SRCAND); // // XOR the revised image into the destination // m_dcFinal.BitBlt(0,bmHeight,bmWidth,bmHeight,&dcImage,0,0,SRCPAINT); VERIFY(dcMasks.SelectObject(pOldMaskBmp)); VERIFY(dcImage.SelectObject(pOldImageBmp)); // // the result of all of this mucking about is a bitmap identical with the // one loaded from the resources but with the lower row of bitmaps having // their background changed from transparent1 to the window // background and the upper row having their background changed from transparent2 to the // highlight colour. A derived CListBoxEx can BitBlt the relevant part // of the image into an item's device context for a transparent bitmap effect // which does not take any extra time over a normal BitBlt. // } void CListBoxExResources::SysColorChanged() { // // reinitialise bitmaps and syscolors // this should be called from the parent of the CListBoxExResources object // from the OnSysColorChange() function. // GetSysColors(); PrepareBitmaps( TRUE ); } void CListBoxExResources::GetSysColors() { m_ColorWindow = ::GetSysColor(COLOR_WINDOW); m_ColorHighlight = ::GetSysColor(COLOR_HIGHLIGHT); m_ColorWindowText = ::GetSysColor(COLOR_WINDOWTEXT); m_ColorHighlightText = ::GetSysColor(COLOR_HIGHLIGHTTEXT); } // // CListBoxEx // IMPLEMENT_DYNAMIC(CListBoxEx,CListBox); BEGIN_MESSAGE_MAP(CListBoxEx, CListBox) //{{AFX_MSG_MAP(CListBoxEx) ON_WM_CREATE() //}}AFX_MSG_MAP END_MESSAGE_MAP() CListBoxEx::CListBoxEx() { m_lfHeight = 0; m_pResources = 0; } CListBoxEx::~CListBoxEx() { } void CListBoxEx::AttachResources( const CListBoxExResources* r ) { if( r != m_pResources ) { ASSERT(r); m_pResources = r; if( m_hWnd ) // if window created { Invalidate(); } } } void CListBoxEx::MeasureItem( LPMEASUREITEMSTRUCT lpMIS ) { ASSERT(m_pResources); int h = lpMIS->itemHeight; int ch = TextHeight(); int bmHeight = m_pResources->BitmapHeight(); #ifdef JAPAN if( !ch ) { // // GetFont returns non NULL when the control is in a dialog box // BUGBUG This should not be necessary if "MS Shell Dlg" is mapped // to the system font. // CFont * pFont = GetFont(); if(!pFont) { LOGFONT lf; ::GetObject(GetStockObject(SYSTEM_FONT), sizeof(LOGFONT), &lf); CFont f; f.CreateFontIndirect(&lf); CalculateTextHeight(&f); } else { CalculateTextHeight(pFont); } } ch = m_lfHeight; #endif /* JAPAN */ lpMIS->itemHeight = (chBitmapHeight(); int h = (bmHeight>m_lfHeight)?bmHeight:m_lfHeight; for(int i=0; ihDC); // // draw focus rectangle when no items in listbox // if(lpDIS->itemID == (UINT)-1) { if(lpDIS->itemAction&ODA_FOCUS) { // // rcItem.bottom seems to be 0 for variable height list boxes // lpDIS->rcItem.bottom = m_lfHeight; pDC->DrawFocusRect( &lpDIS->rcItem ); } return; } else { int selChange = lpDIS->itemAction & ODA_SELECT; int focusChange = lpDIS->itemAction & ODA_FOCUS; int drawEntire = lpDIS->itemAction & ODA_DRAWENTIRE; if(selChange || drawEntire) { BOOL sel = lpDIS->itemState & ODS_SELECTED; COLORREF hlite = ((sel) ? (m_pResources->ColorHighlight()) : (m_pResources->ColorWindow())); COLORREF textcol = ((sel) ? (m_pResources->ColorHighlightText()) : (m_pResources->ColorWindowText())); pDC->SetBkColor(hlite); pDC->SetTextColor(textcol); // // fill the rectangle with the background colour. // pDC->ExtTextOut( 0, 0, ETO_OPAQUE, &lpDIS->rcItem, NULL, 0, NULL ); CListBoxExDrawStruct ds( pDC, (RECT *)&lpDIS->rcItem, sel, (DWORD)lpDIS->itemData, lpDIS->itemID, m_pResources ); // // Now call the draw function of the derived class // DrawItemEx( ds ); } if( focusChange || (drawEntire && (lpDIS->itemState & ODS_FOCUS)) ) { pDC->DrawFocusRect(&lpDIS->rcItem); } } } // // Display text // BOOL CListBoxEx::ColumnText( CDC * pDC, int nLeft, int nTop, int nRight, int nBottom, const CString & str ) { #ifdef _DEBUG pDC->AssertValid(); #endif // _DEBUG CRect rc(nLeft, nTop, nRight, nBottom); pDC->DrawText( str, str.GetLength(), &rc, DT_LEFT | DT_SINGLELINE | DT_NOPREFIX | DT_VCENTER); return TRUE; }