I am building a MFC 2008 mdi application which displays images. When i scroll all the images must be re-loaded. I am tring to avoid this by saving the CPngImage and CBitmap files the first time through, then re-use them subsequently.
The statement pngBmp[iPic].GetBitmap(&bi); causing a break the second time through once the files have been loaded;
Can someone help me with this. The code is listed below;
// Global
#define MAX_IMAGE 100
CPngImage pngImage[MAX_IMAGE];
CBitmap pngBmp[MAX_IMAGE];
void CFileViewerView::DrawImages(CDC* pDC)
{
CString pngPath,imageLegend;
CDC bmDC;
CBitmap *pOldbmp;
BITMAP bi;
int xPos = marginRect.left, yPos,nPic,nPage;
int xOffset,yOffset,imageHeight,imageWidth,numPics;
float aspect;
BOOL status;
PayAppReport report =
projectList[m_pModeless->GetCurrentProject()].reports[m_pModeless->GetCurrentReport()];
numPics = report.GetNumberOfPictures();
bmDC.CreateCompatibleDC(pDC);
imageHeight = 6500;
//yPos = pageRect.bottom + marginRect.top;
nPage = numPics/6;
for(int iPic=0; iPic<numPics; iPic++)
{
if(!imagesLoaded)
{
pngPath = report.GetPictures(iPic);
pngPath.TrimRight();
pngImage[iPic].LoadFromFile(pngPath);
status = pngBmp[iPic].Attach(pngImage[iPic].Detach());
if(!status)
{
CString err;
err.Format(_T("Cannot open image file \n\r %s"),pngPath);
MessageBox(err,_T("Image Loading Error"),MB_ICONERROR);
return;
}
}
else
pngBmp[iPic].Attach(pngImage[iPic].Detach());
pngBmp[iPic].GetBitmap(&bi); // ****** ABORTS Here
pOldbmp= bmDC.SelectObject(&pngBmp[iPic]);
aspect = (float)bi.bmWidth / (float)bi.bmHeight;
imageWidth = (int)(aspect*imageHeight),numPics;
xOffset = imageWidth;
yOffset = (int)(-imageHeight*1.20f);
nPic = iPic;
if(iPic > 5)
nPic = iPic - (iPic/6)*6;
if(nPic == 0)
{
xPos = marginRect.left;
yPos = (pageRect.bottom + marginRect.top)*((iPic/6)+1);
}
else if(nPic < 3)
{
xPos = marginRect.left;
yPos += yOffset;
}
else if(nPic == 3)
{
xPos = marginRect.right-imageWidth;
yPos = (pageRect.bottom + marginRect.top)*((iPic/6)+1);
}
else if(nPic > 3 && nPic < 6)
{
xPos = marginRect.right-imageWidth;
yPos += yOffset;
}
_ftprintf(dbgFile,_T("iPic %d nPic %d xPos %d yPos %d\n"),iPic,nPic,xPos,yPos);
pDC->SetStretchBltMode(HALFTONE);
SetBrushOrgEx(bmDC,0,0,NULL);
pDC->StretchBlt(xPos,yPos,imageWidth,-imageHeight,&bmDC,0,0,bi.bmWidth, bi.bmHeight,SRCCOPY);
bmDC.SelectObject(pOldbmp);
pngBmp[iPic].Detach();
imageLegend.Format(_T("Photo %2d"),iPic+1);
CSize rSize = pDC->GetTextExtent(imageLegend, imageLegend.GetLength());
pDC->TextOut(xPos+(imageWidth/2)-rSize.cx/2,yPos-imageHeight,imageLegend, imageLegend.GetLength());
}
imagesLoaded = true;
}
You have called
Detach()
onpngImage
, sopngImage
is no longer valid. In the next callpngBmp
will be invalid.pngBmp[iPic].GetBitmap(&bi);
will fail if there is no validHBITMAP
Easier solution:
CPngImage
is derived fromCBitmap
, it can do everythingCBitmap
does. You can simplify your code by removingpngBmp
altogether and usepngImage
for painting.You can test the validity of png image with: