用MFC写了一个图形绘制程序,主要的绘制工作由其中一个类的Draw(CDC* pDC, ...)函数完成。
现在想添加一个将绘制出的图形保存为BMP图像的功能。不知道该怎么实现。
网上查了一些东西,好像要弄明白原理内容还是比较多的。这里就先只完成代码了。
请知道的帮我写一写将绘制好的图形(Draw())保存为BMP图像的代码。
先行谢过了!

解决方案 »

  1.   

    WORD wbitsCount;//位图中每个像素所占字节数。
          DWORD dwpalettelsize=0;//调色板大小
          DWORD dwbmdibitsize,dwdibsize,dwwritten;
          BITMAP bitmap;//定义了位图的各种的信息。
          BITMAPFILEHEADER bmfhdr;//定义了大小、类型等BMP文件的信息。
          BITMAPINFOHEADER bi;
          LPBITMAPINFOHEADER lpbi;
          HANDLE fh,fdib;
    GetObject(hBitmap,sizeof(BITMAP),(void *)&bitmap);//得到BITMAP结构。
          //以下代码是用BITMAP的信息填充BITMAPINFOHEADER结构
          wbitsCount=bitmap.bmBitsPixel;
    bi.biSize=sizeof(BITMAPINFOHEADER);
          bi.biWidth=bitmap.bmWidth;
          bi.biHeight=bitmap.bmHeight;
          bi.biPlanes=1;
          bi.biBitCount= bitmap.bmBitsPixel ;
          bi.biClrImportant=0;
          bi.biClrUsed=0;
          bi.biCompression=BI_RGB;
          bi.biSizeImage=0;
          bi.biYPelsPerMeter=0;
          bi.biXPelsPerMeter=0;
    //以下代码是获取调色板的长度,调色板现在的用处很少,因为256色的位图已经不多了。
          if(wbitsCount <=8)
                  dwpalettelsize=(1 < <wbitsCount)*sizeof(RGBQUAD);
    //计算位图的大小,并分配相应的内存空间,注意的是没有分配BITMAPFILEHEADER。
          dwbmdibitsize=((bitmap.bmWidth*wbitsCount+31)/8)*bitmap.bmHeight;
          fdib=GlobalAlloc(GHND,dwbmdibitsize+dwpalettelsize+sizeof(BITMAPINFOHEADER));
          lpbi=(LPBITMAPINFOHEADER)::GlobalLock(fdib);
          *lpbi=bi;//将bi中的数据写入分配的内存中。
          hdc=::GetDC(NULL);
          GetDIBits(hdc,hBitmap,0,(UINT)bitmap.bmHeight,(LPSTR)lpbi+sizeof(BITMAPINFOHEADER)+dwpalettelsize,(BITMAPINFO *)lpbi,DIB_RGB_COLORS);
    /*GetDIBits是最重要的函数,真正获得位图数据的工作就由它完成,它第一个参数为HDC,第二个参数为位图句柄,第三个参数为扫描行的开始行,一般为0,第四个为结束行,一般就是高度,第四个参数最重要,它表示接收数据的起始地址,这个地址一般是在调色板之后。第五个参数指的是接收 BITMAPINFO结构的地址,这个结构上面没有写,它其实就是BITMAPINFO结构加上调色板信息。最后一个参数是格式。一般是 DIB_RGB_COLORS*/
    //创建文件以及文件信息头
    fh=CreateFile(FileName,GENERIC_WRITE,0,NULL,CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL|FILE_FLAG_SEQUENTIAL_SCAN,NULL);
          if(fh==INVALID_HANDLE_VALUE)
                  return FALSE;
    bmfhdr.bfType=0x4d42;//BMP类型,一定要这样写
          dwdibsize=sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER)+dwbmdibitsize+dwpalettelsize; //文件总长,由几个部分组成
          bmfhdr.bfSize=dwdibsize;
          bmfhdr.bfReserved1=0;
          bmfhdr.bfReserved2=0;
    bmfhdr.bfOffBits=(DWORD)sizeof(BITMAPFILEHEADER)+ (DWORD)sizeof(BITMAPINFOHEADER)+dwpalettelsize;//位图数据相对于文件头的偏移量
    //将文件信息头写入文件
    WriteFile(fh,(LPSTR)&bmfhdr,sizeof(BITMAPFILEHEADER),&dwwritten,NULL);
    //将数据写入文件,包含BITMAPINFO结构、调色板、数据
    WriteFile(fh,(LPSTR)lpbi,dwdibsize,&dwwritten,NULL);
    //关闭相关句柄
    ::GlobalUnlock(fdib);
          ::GlobalFree(fdib);
          ::CloseHandle(fh);
          return TRUE; 
      

  2.   

    #include <atlimage.h> 
        HDC hDC = ::GetDC(m_hWnd);     RECT rect; 
        ::GetClientRect(m_hWnd, &rect); 
        HDC hDCMem = ::CreateCompatibleDC(hDC);     HBITMAP hBitMap = ::CreateCompatibleBitmap(hDC, rect.right, rect.bottom); 
        HBITMAP hOldMap = (HBITMAP)::SelectObject(hDCMem, hBitMap);     ::BitBlt(hDCMem, 0, 0, rect.right, rect.bottom, hDC, 0, 0, SRCCOPY);     CImage image; 
        image.Attach(hBitMap); 
        image.Save("c:\\B.bmp"); 
        image.Detach();     ::SelectObject(hDCMem, hOldMap); 
        ::DeleteObject(hBitMap); 
        ::DeleteDC(hDCMem); 
        ::DeleteDC(hDC); 
      

  3.   

    多谢 二位回帖。可能我没有把问题说清楚:
    我写的小程序是一个使用滚动条(就是说绘图区域比可见的客户区大),并且要保存的是整个绘图区域的这么一个程序。其中我使用的是GDI的函数,并且是用MM_LWMETRIC的模式。
    这样的话,程序应该怎么写呢
      

  4.   

    ::BitBlt(hDCMem, 0, 0, rect.right, rect.bottom, hDC, 0, 0, SRCCOPY); //红色部分是画图所用的DC
      

  5.   

    实在是没有看懂,我贴一下我的代码吧:
    SaveAsPicture(CDC* pDC, CString t_FileName, CRect t_BmpRect, CRect t_ClientRect)这是要实现保存图片功能的函数。而具体完成绘制工作的函数是:
    void Draw(CDC *pDC,  CRect t_ClientRect, CPoint t_Point);
    还请你帮我组织一下。
      

  6.   


    //@brief 获取图片文件的编码方式,支持bmp、jpg、jpeg、gif、tiff和png等格式图片
    //@date   1-13-2009  
    //@param [in]  format 图片格式 值可以为以下几种
    //@"image/bmp"
    //@"image/jpeg"
    //@"image/gif"
    //@"image/tiff"
    //@"image/png"
    //@param [in]  pClsid
    //@return  成功则返回值 >= 0,失败则返回值为-1
    int GetEncoderClsid(const WCHAR* format, CLSID *pClsid)
    {
     int nRet = -1;
     ImageCodecInfo* pCodecInfo = NULL;
     UINT nNum = 0,nSize = 0;
     GetImageEncodersSize(&nNum,&nSize);  if (nSize<0)
     {
     return nRet;
     }  pCodecInfo= new ImageCodecInfo[nSize];  if (pCodecInfo==NULL)
     {
      return nRet;
     }  GetImageEncoders(nNum,nSize,pCodecInfo);  for (UINT i=0; i<nNum;i++)
     {
    if (wcscmp(pCodecInfo[i].MimeType,format)==0)
    {
    *pClsid= pCodecInfo[i].Clsid;
    nRet = i;
    delete[] pCodecInfo;
    return nRet;
    }
    else
    {
    continue;
    }
     }  delete[] pCodecInfo;
     return nRet;
    }//@brief 用GDI+将Bitmap图片保存为文件
    //@date   1-13-2009  
    //@param [in]  hBitmap hBitmap的句柄(handle)
    //@param [in]  lpszFileName 保存图片的完整路径
    //@return  成功返回TRUE,失败返回FALSEBOOL SaveBitmapToFile(HBITMAP hBitmap, LPCTSTR lpszFileName)
    {
     CLSID pngClsid;  Bitmap bmp(hBitmap,NULL);  //获取BMP文件的编码方式(如果希望获取JPEG的编码方式,  //那么参数一要设置为:_TEXT("image/jpeg"),其他支持的图片格式类似)
     int nResult = GetEncoderClsid(_TEXT("image/bmp"),&pngClsid);  if(nResult >= 0)
     {
     //保存所截取的屏幕图片
     bmp.Save(lpszFileName,&pngClsid);
     }
     else
     {
     return FALSE;
     }
       
     return TRUE;
    }
      

  7.   

    你把你的东西画到内存DC上 然后将内存DC的所有东西保存成图片