本人现在在做位图保存,矢量图形保存成bmp!以前大虾们给我提供了一些代码,我回去运行后发现了很多错误,望各位大虾指点!错误在下一篇! HBITMAP CopyScreenToBitmap(LPRECT lpRect)
 //lpRect 代表选定区域
{
HDC       hScrDC, hMemDC;      
 // 屏幕和内存设备描述表
HBITMAP    hBitmap, hOldBitmap;   
 // 位图句柄
int       nX, nY, nX2, nY2;      
// 选定区域坐标
int       nWidth, nHeight;      
// 位图宽度和高度
int       xScrn, yScrn;         
// 屏幕分辨率   // 确保选定区域不为空矩形
   if (IsRectEmpty(lpRect))
     return NULL;
   //为屏幕创建设备描述表
   hScrDC = CreateDC("DISPLAY", NULL, NULL, NULL);
   //为屏幕设备描述表创建兼容的内存设备描述表
   hMemDC = CreateCompatibleDC(hScrDC);
   // 获得选定区域坐标
   nX = lpRect- >left;
   nY = lpRect- >top;
   nX2 = lpRect- >right;
   nY2 = lpRect- >bottom;
   // 获得屏幕分辨率
   xScrn = GetDeviceCaps(hScrDC, HORZRES);
   yScrn = GetDeviceCaps(hScrDC, VERTRES);
   //确保选定区域是可见的
   if (nX 〈0)
      nX = 0;
   if (nY 〈  0)
      nY = 0;
   if (nX2 > xScrn)
      nX2 = xScrn;
   if (nY2 > yScrn)
      nY2 = yScrn;
   nWidth = nX2 - nX;
   nHeight = nY2 - nY;
   // 创建一个与屏幕设备描述表兼容的位图
hBitmap = CreateCompatibleBitmap
 (hScrDC, nWidth, nHeight);
   // 把新位图选到内存设备描述表中
   hOldBitmap = SelectObject(hMemDC, hBitmap);
   // 把屏幕设备描述表拷贝到内存设备描述表中
BitBlt(hMemDC, 0, 0, nWidth, nHeight,
 hScrDC, nX, nY, SRCCOPY);
   //得到屏幕位图的句柄
   hBitmap = SelectObject(hMemDC, hOldBitmap);
   //清除 
   DeleteDC(hScrDC);
   DeleteDC(hMemDC);
   // 返回位图句柄
   return hBitmap;
}
   
得到屏幕位图句柄以后,我们
可以把屏幕内容粘贴到剪贴板上.
    if (OpenClipboard(hWnd)) 
     //hWnd为程序窗口句柄
      {
        //清空剪贴板
        EmptyClipboard();
        //把屏幕内容粘贴到剪贴板上,
        hBitmap 为刚才的屏幕位图句柄
        SetClipboardData(CF_BITMAP, hBitmap);
        //关闭剪贴板
        CloseClipboard();
      }
   我们也可以把屏幕内容以位图格式存到磁盘文件上.
      
int SaveBitmapToFile(HBITMAP hBitmap , 
    LPSTR lpFileName) //hBitmap 为刚才的屏幕位图句柄
{         //lpFileName 为位图文件名
    HDC            hDC;         
       //设备描述表
      int            iBits;      
     //当前显示分辨率下每个像素所占字节数
    WORD            wBitCount;   
       //位图中每个像素所占字节数
      //定义调色板大小, 位图中像素字节大小 ,
      位图文件大小 , 写入文件字节数
    DWORD           dwPaletteSize=0,
                dwBmBitsSize,
                 dwDIBSize, dwWritten;
    BITMAP          Bitmap;        
    //位图属性结构
    BITMAPFILEHEADER   bmfHdr;        
    //位图文件头结构
      BITMAPINFOHEADER   bi;            
    //位图信息头结构 
    LPBITMAPINFOHEADER lpbi;          
    //指向位图信息头结构
      HANDLE          fh, hDib, hPal,hOldPal=NULL;
    //定义文件,分配内存句柄,调色板句柄
  
   //计算位图文件每个像素所占字节数
   hDC = CreateDC("DISPLAY",NULL,NULL,NULL);
iBits = GetDeviceCaps(hDC, BITSPIXEL) * 
GetDeviceCaps(hDC, PLANES);
   DeleteDC(hDC);
   if (iBits 〈 = 1)
      wBitCount = 1;
   else if (iBits 〈 = 4)
      wBitCount = 4;
   else if (iBits 〈  = 8)
      wBitCount = 8;
   else if (iBits 〈 = 24)
      wBitCount = 24;
   //计算调色板大小
   if (wBitCount 〈 = 8)
      dwPaletteSize = (1 〈 〈   wBitCount) *
      sizeof(RGBQUAD);
   
   //设置位图信息头结构
   GetObject(hBitmap, sizeof(BITMAP), (LPSTR)&Bitmap);
   bi.biSize            = sizeof(BITMAPINFOHEADER);
   bi.biWidth           = Bitmap.bmWidth;
   bi.biHeight          = Bitmap.bmHeight;
   bi.biPlanes          = 1;
   bi.biBitCount         = wBitCount;
   bi.biCompression      = BI_RGB;
   bi.biSizeImage        = 0;
   bi.biXPelsPerMeter     = 0;
   bi.biYPelsPerMeter     = 0;
   bi.biClrUsed         = 0;
   bi.biClrImportant      = 0;   dwBmBitsSize = ((Bitmap.bmWidth *
    wBitCount+31)/32)* 4
     *Bitmap.bmHeight ;
   //为位图内容分配内存
   hDib  = GlobalAlloc(GHND,dwBmBitsSize+
    dwPaletteSize+sizeof(BITMAPINFOHEADER));
   lpbi = (LPBITMAPINFOHEADER)GlobalLock(hDib);
   *lpbi = bi;
   // 处理调色板   
   hPal = GetStockObject(DEFAULT_PALETTE);
   if (hPal)
   {
      hDC  = GetDC(NULL);
      hOldPal = SelectPalette(hDC, hPal, FALSE);
      RealizePalette(hDC);
   }
   // 获取该调色板下新的像素值
   GetDIBits(hDC, hBitmap, 0, (UINT) Bitmap.bmHeight,
     (LPSTR)lpbi + sizeof(BITMAPINFOHEADER)
    +dwPaletteSize,
     (BITMAPINFOHEADER *)
    lpbi, DIB_RGB_COLORS);
   //恢复调色板   
   if (hOldPal)
   {
      SelectPalette(hDC, hOldPal, TRUE);
      RealizePalette(hDC);
      ReleaseDC(NULL, hDC);
   }
   //创建位图文件    
fh = CreateFile(lpFileName, GENERIC_WRITE, 
0, NULL, CREATE_ALWAYS,
         FILE_ATTRIBUTE_NORMAL | FILE_
         FLAG_SEQUENTIAL_SCAN, NULL);
   if (fh == INVALID_HANDLE_VALUE)
      return FALSE;
   // 设置位图文件头
   bmfHdr.bfType = 0x4D42;  // "BM"
dwDIBSize    = sizeof(BITMAPFILEHEADER) 
           + sizeof(BITMAPINFOHEADER)
            + dwPaletteSize + dwBmBitsSize;  
   bmfHdr.bfSize = dwDIBSize;
   bmfHdr.bfReserved1 = 0;
   bmfHdr.bfReserved2 = 0;
   bmfHdr.bfOffBits = (DWORD)sizeof
   (BITMAPFILEHEADER) 
      + (DWORD)sizeof(BITMAPINFOHEADER)
     + dwPaletteSize;
   // 写入位图文件头
WriteFile(fh, (LPSTR)&bmfHdr, sizeof
(BITMAPFILEHEADER), &dwWritten, NULL);
   // 写入位图文件其余内容
   WriteFile(fh, (LPSTR)lpbi, dwDIBSize, 
   &dwWritten, NULL);
   //清除   
   GlobalUnlock(hDib);
   GlobalFree(hDib);
   CloseHandle(fh);
}

解决方案 »

  1.   

    这是上面程序运行后的错误,前两个是第一个函数的,后面的是第二个函数!//中间那些我已经去掉了!
    E:\Test\TestView.cpp(188) : error C2440: '=' : cannot convert from 'void *' to 'struct HBITMAP__ *'
            Conversion from 'void*' to pointer to non-'void' requires an explicit cast
    E:\Test\TestView.cpp(190) : error C2440: '=' : cannot convert from 'void *' to 'struct HBITMAP__ *'
            Conversion from 'void*' to pointer to non-'void' requires an explicit cast
    E:\Test\TestView.cpp(246) : error C2660: 'GetDC' : function does not take 1 parameters
    E:\Test\TestView.cpp(247) : error C2664: 'SelectPalette' : cannot convert parameter 2 from 'void *' to 'struct HPALETTE__ *'
            Conversion from 'void*' to pointer to non-'void' requires an explicit cast
    E:\Test\TestView.cpp(254) : error C2664: 'GetDIBits' : cannot convert parameter 6 from 'struct tagBITMAPINFOHEADER *' to 'struct tagBITMAPINFO *'
            Types pointed to are unrelated; conversion requires reinterpret_cast, C-style cast or function-style cast
    E:\Test\TestView.cpp(257) : error C2664: 'SelectPalette' : cannot convert parameter 2 from 'void *' to 'struct HPALETTE__ *'
            Conversion from 'void*' to pointer to non-'void' requires an explicit cast
    E:\Test\TestView.cpp(259) : error C2660: 'ReleaseDC' : function does not take 2 parameters
    Error executing cl.exe.Test.exe - 7 error(s), 0 warning(s)
      

  2.   

    这是我根据以前下的一个算法改的,在我的机器上运行的很好,你看一下吧
    HBITMAP CScrSnapView::CopyScreenToBitmap(LPRECT lpRect)
    {
    HDC hScrDC,hMemDC; //屏幕和内存设备描述表
    HBITMAP hBitmap,hOldBitmap;//位图句柄
    int nX,nY,nX2,nY2; //选定区域坐标
    int nWidth,nHeight; //位图宽度和高度
    int xScrn,yScrn; //屏幕宽度和高度 //确保选定区域不为空矩形
    if(IsRectEmpty(lpRect)) 
    return NULL; 

    //为屏幕创建设备描述表
    hScrDC=CreateDC("DISPLAY", NULL, NULL, NULL);
    //为屏幕设备描述表创建兼容的内存设备描述表
    hMemDC=CreateCompatibleDC(hScrDC); //或者::CreateCompatibleDC(NULL) //获得选定区域坐标 
    nX=lpRect->left;
    nY=lpRect->top;
    nX2=lpRect->right;
    nY2=lpRect->bottom;  //获得屏幕宽度和高度
    xScrn=GetDeviceCaps(hScrDC,HORZRES);
    yScrn=GetDeviceCaps(hScrDC,VERTRES);  //确保选定区域是可见的
    if (nX<0)
    nX=0;
    if (nY<0)
    nY=0;
    if (nX2>xScrn)
    nX2=xScrn; 
    if (nY2>yScrn)
    nY2=yScrn;  nWidth=nX2-nX; 
    nHeight=nY2-nY; //创建一个与屏幕设备描述表兼容的位图 
    hBitmap=CreateCompatibleBitmap(hScrDC,nWidth,nHeight);  //把新位图选到内存设备描述表中 
    hOldBitmap=(HBITMAP)SelectObject(hMemDC,hBitmap); //把屏幕设备描述表拷贝到内存设备描述表中
    BitBlt(hMemDC,0,0,nWidth,nHeight,hScrDC,nX,nY,SRCCOPY);

    //得到屏幕位图的句柄
    hBitmap=(HBITMAP)SelectObject(hMemDC,hOldBitmap);

    //清除
    DeleteDC(hScrDC);
    DeleteDC(hMemDC);
    return hBitmap; //返回位图句柄
    }BOOL CScrSnapView::SaveBitmapToFile(HBITMAP hBitmap, LPSTR lpFileName)

    WORD wBitCount;  //位图中每个像素所占字节数  //定义调色板大小,位图中像素字节大小,位图文件大小,写入文件字节数 
    DWORD dwPaletteSize=0,dwBmBitsSize,dwDIBSize, dwWritten; 
    BITMAP Bitmap; //位图属性结构 
    BITMAPFILEHEADER bmfHdr;  //位图文件头结构 
    BITMAPINFOHEADER bi;  //位图信息头结构 
    HANDLE fh;  //定义文件,分配内存句柄,调色板句柄
    LPSTR lpbk,lpmem; wBitCount = 32; 
    //设置位图信息头结构 
    GetObject(hBitmap, sizeof(BITMAP), (LPSTR)&Bitmap); 
    bi.biSize = sizeof(BITMAPINFOHEADER); 
    bi.biWidth = Bitmap.bmWidth; 
    bi.biHeight = Bitmap.bmHeight; //为负,正向的位图;为正,倒向的位图
    bi.biPlanes = 1; 
    bi.biBitCount = wBitCount; 
    bi.biCompression = BI_RGB; 
    bi.biSizeImage=0; 
    bi.biXPelsPerMeter=0; 
    bi.biYPelsPerMeter=0; 
    bi.biClrUsed=0; 
    bi.biClrImportant=0; 
    dwBmBitsSize=((Bitmap.bmWidth*wBitCount+31)/32)*4*Bitmap.bmHeight;  //创建位图文件 
    fh = CreateFile(lpFileName, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 
    FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN, NULL); 
    if (fh == INVALID_HANDLE_VALUE) 
    return FALSE; 
    //设置位图文件头 
    bmfHdr.bfType = 0x4D42; // "BM" 
    dwDIBSize = sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER)+dwBmBitsSize; 
    bmfHdr.bfSize = dwDIBSize; 
    bmfHdr.bfReserved1 = 0; 
    bmfHdr.bfReserved2 = 0; 
    bmfHdr.bfOffBits = (DWORD)sizeof(BITMAPFILEHEADER)+(DWORD)sizeof(BITMAPINFOHEADER);

    //写入位图文件头 
    WriteFile(fh, (LPSTR)&bmfHdr, sizeof(BITMAPFILEHEADER),&dwWritten, NULL); 
    //写入位图信息头
    WriteFile(fh, (LPSTR)&bi,sizeof(BITMAPINFOHEADER),&dwWritten, NULL); //获取位图阵列
    lpmem=new char[dwBmBitsSize];
    lpbk=(LPSTR) new char[dwBmBitsSize];
    GetBitmapBits(hBitmap,dwBmBitsSize,lpmem);//正向的内存图象数据

    //转化为倒向数据(仅在bmHeight为正时需要)
    for(int i=0;i<Bitmap.bmHeight;i++)
    {
    memcpy(lpbk+Bitmap.bmWidth*i*4,lpmem+Bitmap.bmWidth*(Bitmap.bmHeight-i-1)*4,Bitmap.bmWidth*4);
    }
    //写位图数据
    WriteFile(fh, lpbk,dwBmBitsSize,&dwWritten, NULL); //清除 
    delete []lpbk;
    delete []lpmem; CloseHandle(fh);
    return TRUE;
    }不过保存的位图在windows下可以查看,而在linux下却有问题,我也没有改了。
      

  3.   


    BOOL CDib::Save( const char *pszFilename )
    { // If we have no data, we can't save.
    if( m_pDib == NULL )
    return( FALSE ); CFile cf; // Attempt to create the file.
    if( !cf.Open( pszFilename,
    CFile::modeCreate | CFile::modeWrite ) )
    return( FALSE );

    // Write the data.
    try{ // First, create a BITMAPFILEHEADER
    // with the correct data.
    BITMAPFILEHEADER BFH;
    memset( &BFH, 0, sizeof( BITMAPFILEHEADER ) );
    BFH.bfType = 'MB';
    BFH.bfSize = sizeof( BITMAPFILEHEADER ) + m_dwDibSize;
    BFH.bfOffBits = sizeof( BITMAPFILEHEADER ) +
    sizeof( BITMAPINFOHEADER ) +
    m_nPaletteEntries * sizeof( RGBQUAD ); // Write the BITMAPFILEHEADER and the
    // Dib data.
    cf.Write( &BFH, sizeof( BITMAPFILEHEADER ) );
    cf.Write( m_pDib, m_dwDibSize );
    } // If we get an exception, delete the exception and
    // return FALSE.
    catch( CFileException *e ){
    e->Delete();
    return( FALSE );
    } return( TRUE );
    }
      

  4.   

    这个dib类只是对存在位图是才有用地吧!
    如果本身不存在的会出现内存不足的警告!
      

  5.   

    yangkwch(情殇) 不行啊,保存的图形有问题!他保存的是当前屏幕的图形,而不是当前视图的图形!能不能把你的程序发给我?我现在急需啊!
    [email protected]  谢谢!
      

  6.   

    你是指内存里的ddb保存为dib位图吗?
      

  7.   

    To  flysundy(毛毛虫) 
    我得图形是通过CDC画出来的,怎样保存呢?
      

  8.   

    最老土的办法,CDC::GetPixel  ,逐个取再填到DIB中,就是慢点,呵呵
      

  9.   

    HDC hMemDC=CreateCompatableDC(hDC,,);
    SelectObject(HBITMAP);
    BitBlt();//把hDC画入hMemDC。
    GetBitmapBits();然后去Save();
      

  10.   

    E:\Test\TestView.cpp(188) : error C2440: '=' : cannot convert from 'void *' to 'struct HBITMAP__ *'
            Conversion from 'void*' to pointer to non-'void' requires an explicit cast
    E:\Test\TestView.cpp(190) : error C2440: '=' : cannot convert from 'void *' to 'struct HBITMAP__ *'
    这两个错误是你没有自已进行强制转换,
    (HBITMAP*)在那个前面加上这个应该就可以了。        Conversion from 'void*' to pointer to non-'void' requires an explicit cast
    E:\Test\TestView.cpp(246) : error C2660: 'GetDC' : function does not take 1 parameters
    这个我就不太清楚了。我也这样用过的。E:\Test\TestView.cpp(247) : error C2664: 'SelectPalette' : cannot convert parameter 2 from 'void *' to 'struct HPALETTE__ *'
            Conversion from 'void*' to pointer to non-'void' requires an explicit cast
    E:\Test\TestView.cpp(254) : error C2664: 'GetDIBits' : cannot convert parameter 6 from 'struct tagBITMAPINFOHEADER *' to 'struct tagBITMAPINFO *'
    跟前面一个错误一样没有进行类型转换,
    (BITMAPINFO *)XXX
            Types pointed to are unrelated; conversion requires reinterpret_cast, C-style cast or function-style cast
    E:\Test\TestView.cpp(257) : error C2664: 'SelectPalette' : cannot convert parameter 2 from 'void *' to 'struct HPALETTE__ *'
    同上面的原因一样的。
            Conversion from 'void*' to pointer to non-'void' requires an explicit cast
    E:\Test\TestView.cpp(259) : error C2660: 'ReleaseDC' : function does not take 2 parameters
    好像只要releasedc(hdc)就可以了。