首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 开发语言 > C++ >

关于截图不能成功,该怎么解决

2012-03-05 
关于截图不能成功//拷贝截图到文件,lpRect代表选定区域HBITMAPCIECaptureDlg::CopyScreenToBitmap(LPRECTl

关于截图不能成功
//拷贝截图到文件,lpRect   代表选定区域
HBITMAP   CIECaptureDlg::CopyScreenToBitmap(LPRECT   lpRect,BOOL   bSave)
{
                  HDC               hScrDC,   hMemDC;            
//   屏幕和内存设备描述表
HBITMAP       hBitmap,   hOldBitmap;      
//   位图句柄
int               nX,   nY,   nX2,   nY2;            
//   选定区域坐标
int               nWidth,   nHeight;
//the   pointer   will   save   all   pixel   point 's   color   value
                  BYTE     *lpBitmapBits   =   NULL;  

                  //   确保选定区域不为空矩形
if   (   IsRectEmpty(   lpRect   )   )
{
return   NULL;
}
//为屏幕创建设备描述表
hScrDC   =   CreateDC(   _T(   "DISPLAY "   ),   NULL,   NULL,   NULL   );
//为屏幕设备描述表创建兼容的内存设备描述表
hMemDC   =   CreateCompatibleDC(   hScrDC   );

//   获得选定区域坐标
nX     =   lpRect-> left;
nY     =   lpRect-> top;
nX2   =   lpRect-> right;
nY2   =   lpRect-> bottom;

//确保选定区域是可见的
if   (   nX   <   0   )
{
nX   =   0;
}
if   (   nY   <   0   )
{
nY   =   0;
}
if   (   nX2   >   m_xScreen   )
{
nX2   =   m_xScreen;
}
if   (   nY2   >   m_yScreen   )
{
nY2   =   m_yScreen;
}
nWidth     =   nX2   -   nX;
nHeight   =   nY2   -   nY;
        //initialize   the   struct   BITMAPINFO   for   the   bitmap   infomation,
        //in   order   to   use   the   function   CreateDIBSection
        //on   wince   os,   each   pixel   stored   by   24   bits(biBitCount=24)  
        //and   no   compressing(biCompression=0)
        BITMAPINFO   RGB24BitsBITMAPINFO;  
        memset(   &RGB24BitsBITMAPINFO,   0,   sizeof(BITMAPINFO)   );
        RGB24BitsBITMAPINFO.bmiHeader.biSize           =   sizeof(BITMAPINFOHEADER);
        RGB24BitsBITMAPINFO.bmiHeader.biWidth         =   nWidth;
        RGB24BitsBITMAPINFO.bmiHeader.biHeight       =   nHeight;
        RGB24BitsBITMAPINFO.bmiHeader.biPlanes       =   1;
        RGB24BitsBITMAPINFO.bmiHeader.biBitCount   =   24;
     
        //use   the   function   CreateDIBSection   and   SelectObject  
        //in   order   to   get   the   bitmap   pointer   :   lpBitmapBits
        hBitmap   =   CreateDIBSection(   hMemDC,   (BITMAPINFO*)&RGB24BitsBITMAPINFO,  


                                            DIB_RGB_COLORS,   (void   **)&lpBitmapBits,   NULL,   0   );
      //   把新位图选到内存设备描述表中
      hOldBitmap   =   (HBITMAP)SelectObject(hMemDC,   hBitmap);

      //   把屏幕设备描述表拷贝到内存设备描述表中
      if(bSave)
      {
//创建兼容DC,当bSave为真时把开始保存的全屏位图,按截取矩形大小保存
CDC   dcCompatible;
dcCompatible.CreateCompatibleDC(   CDC::FromHandle(   hMemDC   )   );
dcCompatible.SelectObject(   m_pBitmap   );
               
BitBlt(   hMemDC,   0,   0,   nWidth,   nHeight,   dcCompatible,   nX,   nY,   SRCCOPY   );

//bimap   file   header   in   order   to   write   bmp   file
BITMAPFILEHEADER   bmBITMAPFILEHEADER;
memset(&bmBITMAPFILEHEADER,   0,   sizeof(BITMAPFILEHEADER));
bmBITMAPFILEHEADER.bfType         =   0x4d42;     //bmp    
bmBITMAPFILEHEADER.bfOffBits   =   sizeof(BITMAPFILEHEADER)   +   sizeof(BITMAPINFOHEADER);
bmBITMAPFILEHEADER.bfSize         =   bmBITMAPFILEHEADER.bfOffBits   +   ((nWidth*nHeight)*3);   ///3=(24   /   8)

                  //保存文件名及路径
                  int   filecount   =   0;
CString   name;
name.Format(   _T(   "picture%d.bmp "   ),   filecount++   );
               
CFile   file;
if(   file.Open(name,   CFile::modeCreate|CFile::modeWrite)   )
{
        file.Write(   &bmBITMAPFILEHEADER,   sizeof(BITMAPFILEHEADER)   );
        file.Write(   &(RGB24BitsBITMAPINFO.bmiHeader),   sizeof(BITMAPINFOHEADER)   );
        file.Write(   lpBitmapBits,   3*nWidth*nHeight   );
        file.Close();
}
      }
      else
      {
BitBlt(   hMemDC,   0,   0,   nWidth,   nHeight,hScrDC,   nX,   nY,       SRCCOPY   );
        }
 
        //得到屏幕位图的句柄
        hBitmap   =   (HBITMAP)SelectObject(   hMemDC,   hOldBitmap   );

        //清除  
        DeleteDC(   hScrDC   );
        DeleteDC(   hMemDC   );

        //   返回位图句柄
        return   hBitmap;
}
这是我的截图图像并保存到本地的一个函数
但是在截图的时候,保存到本地后,打开BMP图像显示“绘图失败”,但有时打开BMP图像显示的是截取到的图片。
有达人指点下
看这个函数有什么问题?
谢谢


[解决办法]
不知道有没有别的地方有问题,
但这两行是有问题的

bmBITMAPFILEHEADER.bfSize = bmBITMAPFILEHEADER.bfOffBits + ((nWidth*nHeight)*3);

file.Write( lpBitmapBits, 3*nWidth*nHeight );

BMP有规定,图像的每一行数据所占用的字节数必须为4的整数倍.
比如
nWidth = 16, 则每行占16 * 3 = 48个字节(正好是4的整数倍)
nWidth = 17, 则每行占17 * 3 = 51个字节, 不是4的整数倍, 此时会加一个填充字节(这个字节里的数据无任何意义), 让这行图像数据占到52字节(为4的整数倍).同样若差3个字节是4的整数倍, 那就会加3个填充字节.



所以你上面计算数据长度的公式是错的.
实际每行数据占用的长度是(nWidth*3 + 3) / 4 * 4
改成下面这个样子.

bmBITMAPFILEHEADER.bfSize = bmBITMAPFILEHEADER.bfOffBits + ((nWidth*3 + 3) / 4 * 4 * nHeight);

file.Write( lpBitmapBits, ((3*nWidth + 3) / 4 * 4 *nHeight );


热点排行