Saving Views as bitmaps

Hello friends,
   I have written an application in which the view is derived from a CSrollView. The view contains a number of objects (like circles, rectangles etc.) drawn on it. Please note that the actual view size is bigger than the viewport and hence many of these objects will be hidden and one needs to scroll to view the hidden objects. The point I am trying to emphasize is that not all objects are visible on the screen at a time.
   I have written code to save the view as a Device Independent Bitmap (i.e. a .bmp file) However I am able to save only the visual portion of the screen into the .bmp file. I am unable to figure out any technique as to how to save the entire view (including the hidden objects) into the bitmap. Can someone help ?
   I am attaching some portion of the code that I have written for your reference.

/////// code begins ////////
/* this is the function that saves the bitmap */


BOOL SaveBitmapFile(HDC hDC, HBITMAP hBmp, PSTR pszFileName)
{
    int         hFile;
    OFSTRUCT    ofReOpenBuff;
    HBITMAP     hTmpBmp, hBmpOld;
    BOOL        bSuccess;
    BITMAPFILEHEADER    bfh;
    PBITMAPINFO pbmi;
    PBYTE       pBits;
    BITMAPINFO  bmi;
    PBYTE pjTmp, pjTmpBmi;
    ULONG sizBMI;


    bSuccess = TRUE;
#if 0
    if (ghPal) {
        SelectPalette(hDC, ghPal, FALSE);
        RealizePalette(hDC);
    }
#endif
    if (!hBmp) {
        ::AfxMessageBox("hBmp");
        return FALSE;
    }

    //
    // Let the graphics engine to retrieve the dimension of the bitmap for us
    // GetDIBits uses the size to determine if it's BITMAPCOREINFO or BITMAPINFO
    // if BitCount != 0, color table will be retrieved
    //
    bmi.bmiHeader.biSize = 0x28;              // GDI need this to work
    bmi.bmiHeader.biBitCount = 0;             // don't get the color table
    if ((GetDIBits(hDC, hBmp, 0, 0, (LPSTR)NULL, &bmi, DIB_RGB_COLORS)) == 0) {
       return FALSE;
    }

    //
    // Now that we know the size of the image, alloc enough memory to retrieve
    // the actual bits
    //
    if ((pBits = (PBYTE)GlobalAlloc(GMEM_FIXED | GMEM_ZEROINIT,
                bmi.bmiHeader.biSizeImage)) == NULL) {
        return FALSE;
    }

    //
    // Note: 24 bits per pixel has no color table.  So, we don't have to
    // allocate memory for retrieving that.  Otherwise, we do.
    //
    pbmi = &bmi;                                      // assume no color table

    switch (bmi.bmiHeader.biBitCount) {
        case 24:                                      // has color table
            sizBMI = sizeof(BITMAPINFOHEADER);
            break;
        case 16:
        case 32:
            sizBMI = sizeof(BITMAPINFOHEADER)+sizeof(DWORD)*3;
            break;
        default:
            sizBMI = sizeof(BITMAPINFOHEADER)+sizeof(RGBQUAD)*(1<<bmi.bmiHeader.biBitCount);
            break;

    }

    //
    // Allocate memory for color table if it is not 24bpp...
    //
    if (sizBMI != sizeof(BITMAPINFOHEADER)) {
        ULONG       sizTmp;
        //
        // I need more memory for the color table
        //
        if ((pbmi = (PBITMAPINFO)GlobalAlloc(GMEM_FIXED | GMEM_ZEROINIT, sizBMI )) == NULL) {
            bSuccess = FALSE;
            goto ErrExit1;
        }
        //
        // Now that we've a bigger chunk of memory, let's copy the Bitmap
        // info header data over
        //
        pjTmp = (PBYTE)pbmi;
        pjTmpBmi = (PBYTE)&bmi;
        sizTmp = sizeof(BITMAPINFOHEADER);

        while(sizTmp--)
        {
            *(((PBYTE)pjTmp)++) = *((pjTmpBmi)++);
        }
    }

    //
    // Let's open the file and get ready for writing
    //
    if ((hFile = OpenFile(pszFileName, (LPOFSTRUCT)&ofReOpenBuff,
                 OF_CREATE | OF_WRITE)) == -1) {
        AfxMessageBox("OpenFile");
        goto ErrExit2;
    }

    //
    // But first, fill in the info for the BitmapFileHeader
    //
    bfh.bfType = 0x4D42;                            // 'BM'
    bfh.bfSize = sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER)+sizBMI+
        pbmi->bmiHeader.biSizeImage;
    bfh.bfReserved1 =
    bfh.bfReserved2 = 0;
    bfh.bfOffBits = sizeof(BITMAPFILEHEADER)+sizBMI;

    //
    // Write out the file header now
    //
    if (_lwrite(hFile, (LPSTR)&bfh, sizeof(BITMAPFILEHEADER)) == -1) {
        bSuccess = FALSE;
        goto ErrExit3;
    }

    //
    // Bitmap can't be selected into a DC when calling GetDIBits
    // Assume that the hDC is the DC where the bitmap would have been selected
    // if indeed it has been selected
    //
    if (hTmpBmp = CreateCompatibleBitmap(hDC, pbmi->bmiHeader.biWidth, pbmi->bmiHeader.biHeight))
      {
        hBmpOld = (HBITMAP)SelectObject(hDC, (HBITMAP)hTmpBmp);
        if ((GetDIBits(hDC, hBmp, 0, pbmi->bmiHeader.biHeight, (LPSTR)pBits, pbmi, DIB_RGB_COLORS))==0){
            bSuccess = FALSE;
            goto ErrExit4;
        }
    } else {
        AfxMessageBox("IDS_BITMAP_NOT_CREATED");
        bSuccess = FALSE;
        goto ErrExit3;
    }

    //
    // Now write out the BitmapInfoHeader and color table, if any
    //
    if (_lwrite(hFile, (LPSTR)pbmi, sizBMI) == -1) {
        bSuccess = FALSE;
        goto ErrExit4;
    }

    //
    // write the bits also
    //
    if (_lwrite(hFile, (LPSTR)pBits, pbmi->bmiHeader.biSizeImage) == -1) {
        bSuccess = FALSE;
        goto ErrExit4;
    }


ErrExit4:
    SelectObject(hDC, hBmpOld);
    DeleteObject(hTmpBmp);
ErrExit3:
    _lclose(hFile);
ErrExit2:
    GlobalFree(pbmi);
ErrExit1:
    GlobalFree(pBits);
    return bSuccess;
}


/** usage of this function **/

void CBitmapsView::OnFileSaveasbitmap()
{
      // TODO: Add your command handler code here

      // get screen DC
      CDC *pDC = GetDC();

        // dummy drawing code
      pDC->Rectangle(10,10,100,100);
      CRect rect;
      GetClientRect(rect);
      // create an empty DC
      CDC memDC;

      // make a screen DC compatible DC of it
      memDC.CreateCompatibleDC(pDC);

      CBitmap memBitmap;
      memBitmap.CreateCompatibleBitmap( pDC,
                                                        rect.Width(),
                                                        rect.Height()
                                                      );

      CBitmap *pOldBMP = memDC.SelectObject(&memBitmap);

      memDC.BitBlt( 0,
                          0,
                          rect.Width(),
                          rect.Height(),
                          pDC,
                          0,
                          0,
                          SRCCOPY
                          );
      
      memDC.SelectObject(pOldBMP);
      SaveBitmapFile(pDC->GetSafeHdc(),(HBITMAP)memBitmap,"c:\\Ganesh\\bitmap.bmp");
      ReleaseDC(pDC);
      
      memBitmap.DeleteObject();
}

ganeshokadeAsked:
Who is Participating?

[Webinar] Streamline your web hosting managementRegister Today

x
 
jianliuerConnect With a Mentor Commented:
I think what you have saved is just the clipped part of the objects drawn on the scrollview client area.
To solve this problem , just draw the objects directly onto the memdc which had the memory bitmap selected, and bitblt the memdc to pDC.I think it should do work.
Test like this:

void CBitmapsView::OnFileSaveasbitmap()
{
// TODO: Add your command handler code here

// get screen DC
CDC *pDC = GetDC();

        // dummy drawing code
//pDC->Rectangle(10,10,100,100);
CRect rect;
GetClientRect(rect);
// create an empty DC
CDC memDC;

// make a screen DC compatible DC of it
memDC.CreateCompatibleDC(pDC);

CBitmap memBitmap;
memBitmap.CreateCompatibleBitmap( pDC,
  1000,//should be large enough or can be the size of your scroll view
  1000
  //rect.Width(),
  //rect.Height()
);

CBitmap *pOldBMP = memDC.SelectObject(&memBitmap);

////modify code here
memDC.Rectangle(10,10,100,100);

pDC->BitBlt(0,
  0,
  rect.Width(),
  rect.Height(),
  &memDC,
  0,
  0,
  SRCCOPY
  );

/*memDC.BitBlt( 0,
  0,
  rect.Width(),
  rect.Height(),
  pDC,
  0,
  0,
  SRCCOPY
  );
*/

SaveBitmapFile(memDC.GetSafeHdc(),(HBITMAP)memBitmap,"c:\\Ganesh\\bitmap.bmp");

memDC.SelectObject(pOldBMP);

/*SaveBitmapFile(pDC->GetSafeHdc(),(HBITMAP)memBitmap,"c:\\Ganesh\\bitmap.bmp");
*/
ReleaseDC(pDC);

memBitmap.DeleteObject();
}



Good Luck.
0
 
ganeshokadeAuthor Commented:
It worked!!! Thanks
0
All Courses

From novice to tech pro — start learning today.