Selaa lähdekoodia

fixed global memory leaks in CQListCtrl::DrawBitMap

git-svn-id: svn://svn.code.sf.net/p/ditto-cp/code/trunk@139 595ec19a-5cb4-439b-94a8-42fb3063c22c
ingenuus 21 vuotta sitten
vanhempi
sitoutus
65b2a7d46a
5 muutettua tiedostoa jossa 58 lisäystä ja 51 poistoa
  1. 1 0
      BitmapHelper.cpp
  2. 3 3
      ProcessPaste.cpp
  3. 49 47
      QListCtrl.cpp
  4. 3 1
      QListCtrl.h
  5. 2 0
      QPasteWnd.cpp

+ 1 - 0
BitmapHelper.cpp

@@ -74,6 +74,7 @@ BOOL CBitmapHelper::GetCBitmap(void	*pClip2, CDC *pDC, CBitmap *pBitMap, int nMa
 			if(pBitMap)
 			{
 				pBitMap->CreateCompatibleBitmap(pDC, nWidth, nHeight);
+				ASSERT(pBitMap->m_hObject != NULL);
 
 				CDC MemDc;
 				MemDc.CreateCompatibleDC(pDC);

+ 3 - 3
ProcessPaste.cpp

@@ -832,11 +832,11 @@ BOOL CProcessPaste::DoPaste()
 		
 		m_pOle->SetClipboard(); // m_pOle is now managed by the OLE clipboard
 		m_pOle = NULL; // m_pOle should not be accessed past this point
-		
-#ifndef _DEBUG
+
+//#ifndef _DEBUG
 		if(m_bSendPaste)
 			theApp.SendPaste(m_bActivateTarget);
-#endif
+//#endif
 		
 		return TRUE;
 	}

+ 49 - 47
QListCtrl.cpp

@@ -502,70 +502,72 @@ void CQListCtrl::OnCustomdrawList(NMHDR* pNMHDR, LRESULT* pResult)
 	}
 }
 
+// DrawBitMap loads a DIB from the DB, draws a crRect thumbnail of the image
+//  to pDC and caches that thumbnail as a DIB in m_ThumbNails[ ItemID ].
+// ALL items are cached in m_ThumbNails (those without images are cached with NULL m_hgData)
 BOOL CQListCtrl::DrawBitMap(int nItem, CRect &crRect, CDC *pDC)
 {
-	CClipFormat Clip;
-	Clip.m_cfType = CF_DIB;
-	CBitmap Bitmap;
-	bool bAddToMap = false;
-	bool bGetDIB = false;
-
+	bool bFromDB = false;
 	long lDatabaseID = GetItemData(nItem);
+	CClipFormat* pThumbnail = NULL; // pointer to the thumbnail in the cache map
 
-	if(m_ThumbNails.Lookup(lDatabaseID, Clip) == FALSE)
+	CMapIDtoCF::CPair* pPair = m_ThumbNails.PLookup(lDatabaseID);
+	if( pPair == NULL )
 	{
-		GetClipData(nItem, Clip);
-			
-		bAddToMap = true;
+		pThumbnail = &(m_ThumbNails[lDatabaseID]);
+		pThumbnail->m_cfType = CF_DIB;
+		GetClipData(nItem, *pThumbnail);
+		bFromDB = true;
 	}
-	
-	if(Clip.m_hgData)
-	{
-		if(CBitmapHelper::GetCBitmap(&Clip, pDC, &Bitmap, crRect.Height()))
-		{
-			int nWidth = CBitmapHelper::GetCBitmapWidth(Bitmap);
-			int nHeight = CBitmapHelper::GetCBitmapHeight(Bitmap);
-
-			CDC MemDc;
-			MemDc.CreateCompatibleDC(pDC);
+	else
+		pThumbnail = &(pPair->value);
 
-			CBitmap* oldBitmap = MemDc.SelectObject(&Bitmap);
+	// if there's no data, then we're done.
+	if( pThumbnail->m_hgData == NULL )
+		return TRUE;
 
-			pDC->BitBlt(crRect.left, crRect.top, nWidth, nHeight, &MemDc, 0, 0, SRCCOPY);
+	CBitmap Bitmap;
+	// Convert DIB to a DDB.
+	if( !CBitmapHelper::GetCBitmap(pThumbnail, pDC, &Bitmap, crRect.Height()) )
+	{
+		Bitmap.DeleteObject();
+		pThumbnail->Free(); // the data is useless, so free it.
+		return FALSE;
+	}
 
-			MemDc.SelectObject(oldBitmap);
+	BITMAP bm;
+	Bitmap.GetBitmap(&bm);
+	int nWidth = bm.bmWidth;
+	int nHeight = bm.bmHeight;
 
-			crRect.left += nWidth + 3;
+	// draw Bitmap
+	CDC MemDc;
+	MemDc.CreateCompatibleDC(pDC);
+	CBitmap* oldBitmap = MemDc.SelectObject(&Bitmap);
+	pDC->BitBlt(crRect.left, crRect.top, nWidth, nHeight, &MemDc, 0, 0, SRCCOPY);
+	MemDc.SelectObject(oldBitmap);
+	MemDc.DeleteDC();
 
-			bGetDIB = true;
-		}
-		else
-		{
-			bAddToMap = false;
-		}
-	}
+	// adjust the rect so other information can be drawn next to the thumbnail
+	crRect.left += nWidth + 3;
 
-	if(bAddToMap)
+	// if the original DIB came from the DB, cache the smaller version we created above.
+	if( bFromDB )
 	{
-		CClipFormat ThumbData(CF_DIB);
+		pThumbnail->Free(); // delete the large image data loaded from the db
+		pThumbnail->m_cfType = CF_DIB;
 
-		//Convert the bitmap to a DIB to cache the bitmap
-		//caching the bitmap had problems
-		if(bGetDIB)
-		{
-			HPALETTE hPal = NULL;
+		// Convert the smaller DDB to a DIB to store in the cache
+		//caching the bitmap had problems (???)
+		HPALETTE hPal = NULL;
+		pThumbnail->m_hgData = CBitmapHelper::hBitmapToDIB( (HBITMAP)Bitmap, BI_RGB, hPal );
+	//	cf.m_hgData = BitmapToDIB(Bitmap.operator HBITMAP(), hPal);
 
-			ThumbData.m_hgData = CBitmapHelper::hBitmapToDIB(Bitmap.operator HBITMAP(), BI_RGB, hPal);
-
-//			ThumbData.m_hgData = BitmapToDIB(Bitmap.operator HBITMAP(), hPal);
-
-			//Map will delete memory in destructor
-			ThumbData.bDeleteData = false;
-		}
-		
-		m_ThumbNails.SetAt(lDatabaseID, ThumbData);
+		ASSERT( pThumbnail->bDeleteData ); // the map owns the data.
 	}
 
+	Bitmap.DeleteObject();
+
 	return TRUE;
 }
 

+ 3 - 1
QListCtrl.h

@@ -36,6 +36,8 @@ public:
 	int cchTextMax; 
 };
 
+typedef CMap<long, long, CClipFormat, CClipFormat&> CMapIDtoCF;
+
 class CQListCtrl : public CListCtrl
 {
 // Construction
@@ -111,7 +113,7 @@ protected:
 	//Accelerator
 	CAccels	m_Accels;
 
-	CMap<long, long, CClipFormat, CClipFormat> m_ThumbNails;
+	CMapIDtoCF m_ThumbNails;
 
 	CToolTipEx *m_pToolTip;
 

+ 2 - 0
QPasteWnd.cpp

@@ -2056,6 +2056,8 @@ LRESULT CQPasteWnd::OnGetClipData(WPARAM wParam, LPARAM lParam)
 	int nItem = (int)wParam;
 	try
 	{
+		ASSERT( pClip->m_hgData == NULL);
+
 		m_Recset.SetAbsolutePosition(nItem);
 
 		CDataTable recset;