用gdi 实现屏幕截图功能

来源:互联网 发布:php 判断小数点位数 编辑:程序博客网 时间:2024/04/27 20:12

    最近在工作中要实现一个截图的功能,由于之前没接触过这类东西,搜索了大部分资料,终于完成了,总结下;

    首先,所谓的桌面截图其实并不是在真正的桌面上截图,只是把当前屏幕的图片复制的自己创建的对话框中,作为对话框的背景,然后在自己的对话框中截图,好了废话不多说了,说说实现了;

   1  要获取到桌面的截图,首先要获取到桌面的DC,得到桌面dc后,根据桌面dc,创建一个内存兼容的内存dc和内存位图bmp,然后把bmp选入当前内存dc,最后调用BitBlt把桌面dc复制到内存dc中(创建内存dc是为了双缓冲,防止屏幕闪烁)。

    

   HDC dcScreen;   HBITMAP  m_bmpScreen;   HBITMAP hOldBitmap;   HDC  m_dcMem;   dcScreen = CreateDC("DISPLAY", NULL, NULL, NULL);    //创建屏幕设备dc   m_size.cx =  GetDeviceCaps(dcScreen, HORZRES);   m_size.cy= GetDeviceCaps(dcScreen, VERTRES);   m_dcMem = CreateCompatibleDC(dcScreen); //创建与设备dc兼容的内存dc   m_bmpScreen = CreateCompatibleBitmap(dcScreen, m_size.cx,m_size.cy);//创建于屏幕dc兼容的位图   hOldBitmap = (HBITMAP)SelectObject(m_dcMem,m_bmpScreen);   BitBlt(m_dcMem, 0, 0,m_size.cx, m_size.cy,dcScreen, 0, 0, SRCCOPY);  
2 在对话框的OnPaint函数中,把内存dc复制到对话框dc中,这样对话框就有桌面的图片了

 StretchBlt(dc,0,0,m_size.cx, m_size.cy,

m_dcMem,0,0,m_size.cx, m_size.cy,SRCCOPY);
3 实现截图,截图首先要随着鼠标移动,画一个矩形区域,此处也要用到双缓冲技术

  

  HDC mydc;   mydc = CreateCompatibleDC(dc);   HBITMAP bmp,oldbmp;   bmp = CreateCompatibleBitmap(dc,m_size.cx,m_size.cy);   oldbmp = (HBITMAP)SelectObject(mydc,bmp);   BitBlt(mydc,0,0,m_size.cx,m_size.cy,m_dcMem,0,0,SRCCOPY);   HPEN hPen = ::CreatePen(PS_DASHDOT, 1, RGB(255, 0, 0));   HBRUSH brush =  (HBRUSH)GetStockObject(NULL_BRUSH);   HPEN oldpen = (HPEN)SelectObject(mydc,hPen);   HBRUSH oldbrush = (HBRUSH)SelectObject(mydc,brush);   MoveToEx(mydc,p_begin.x, p_begin.y,NULL);   LineTo(mydc,X, p_begin.y);   LineTo(mydc,X, Y);   LineTo(mydc,p_begin.x, Y);   LineTo (mydc,p_begin.x, p_begin.y);   p_end.x = X;   p_end.y = Y; AnsiString  str = "当前图片大小为:"; str += IntToStr((int)a); str += "*"; str += IntToStr((int)b);   TextOut(mydc,X,Y+10,str.c_str(),strlen(str.c_str()));   StretchBlt(dc,0,0,m_size.cx, m_size.cy,mydc,0,0,m_size.cx, m_size.cy,SRCCOPY);   SelectObject(mydc,oldpen);   SelectObject(mydc,oldbrush);   DeleteDC(mydc);   DeleteObject(bmp);   ReleaseDC(this->Handle, dc);
4 截图功能  仿照qq截图,要把图片内容存入剪贴板

HDC dcSave;   state = 1;   dcSave = CreateCompatibleDC(NULL);   TPoint c_point;   c_point.x = ((t_begin.x - t_end.x)>0)?t_end.x:t_begin.x;   c_point.y = ((t_begin.y - t_end.y)>0)?t_end.y:t_begin.y;   BITMAP   bm;   HBITMAP bitmap;   GetObject(m_bmpScreen,sizeof(bm),&bm);   bm.bmWidth = width;   bm.bmHeight = height;   bitmap =  CreateBitmapIndirect(&bm);   HBITMAP bit = (HBITMAP)SelectObject(dcSave,bitmap);   StretchBlt(dcSave,0,0, width,height,m_dcMem,c_point.x ,c_point.y,width, height, SRCCOPY);   SelectObject(dcSave,bit);   if(::OpenClipboard(this->Handle))   {::EmptyClipboard();::SetClipboardData(CF_BITMAP, bitmap);::CloseClipboard();   }

 5  从剪贴板取数据

if(::OpenClipboard(handle)){bitmap = (HBITMAP)::GetClipboardData(CF_BITMAP);::CloseClipboard();return true;}
6 存入本地 ,从剪贴板取得数据是HBITMAP,需要转化为TBitmap(保存本地有两种方法一种如下,两一种按照bmp的文件格式写文件) 

 Graphics::TBitmap *DrawBMP=new Graphics::TBitmap();  DrawBMP->Handle = bitmap;  DrawBMP->SaveToFile(filepath+".bmp");  delete DrawBMP;

  ps:上述工程在c++ builder2009中用,在VC++ 中函数一样,写法可能会不一样

  HBITMAP 是 bitmap的指针

  CBitmap 是是mfc中封装bitmap的类;

 BITMAP 是一个结构体,封装着bitmap的一些信息。定义了逻辑位图的高,宽,颜色格式和位值

 三者之间的转化

 

HBITMAP hBitmap;

CBitmap bitmap;

BITMAP bm;

//下面是三者之间的联系:

bitmap.Attach(hBitmap);//由HBITMAP 得到关联的CBitmap

bitmap.GetBitmap(&bm); // 由CBitmap 得到关联的BITMAP 
hBitmap=(HBITMAP)bitmap.GetSafeHandle();//由CBitmap得到相关的HBITMAP

工程地址(C++ builder ):点击打开链接

                    (MFC ): 点击打开链接

   

  

  

   

0 0