Xiangism

从一个无知角落里开始,蹒跚学步,一个未知到另一个未知,在跌跌撞撞中越走越快,越走越远,最后宇宙也为之开源。对于探索者来说,最后他们的思想总是变得和自己的足迹一样伟大。
随笔 - 62, 文章 - 1, 评论 - 220, 阅读 - 20万
  博客园  :: 首页  :: 联系 :: 管理
< 2025年3月 >
23 24 25 26 27 28 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31 1 2 3 4 5

MFC,C++ 截屏

Posted on   Xiangism  阅读(10878)  评论(3编辑  收藏  举报

以前本人用C#制作过一些小游戏的外挂,其中一步最重要的原理是截取电脑的屏幕,然后分析关键像素点的信息。现在用C++重用这些程序时,在截屏上遇到一些问题,现在终于解决了,贴出自己整理后的代码。

分为win32代码和MFC代码,如下

复制代码
 1 void Test_captrueScreenwin32()
 2 {
 3     HDC hDesktopDc=CreateDC(_T("DISPLAY"), NULL, NULL, NULL);
 4     int width=GetDeviceCaps(hDesktopDc,HORZRES);
 5     int height=GetDeviceCaps(hDesktopDc,VERTRES);
 6 
 7     HBITMAP hMemBmp;
 8     HDC hMemDc;
 9     hMemBmp=  CreateCompatibleBitmap(hDesktopDc,width,height);
10     hMemDc=CreateCompatibleDC(hDesktopDc);
11     ::SelectObject(hMemDc,hMemBmp);
12 
13     BitBlt(hMemDc,0,0,width,height,hDesktopDc,0,0,SRCCOPY);  //一定得先复制到内存中去
14      
15     BITMAP bmp;
16     ::GetObject(hMemBmp,sizeof(bmp),&bmp);   //从HBITMAP 到BITMAP
17     
18     BITMAPINFOHEADER m_bihScreen;
19     ZeroMemory(&m_bihScreen, sizeof(BITMAPINFOHEADER));//位图信息头
20     m_bihScreen.biBitCount = bmp.bmBitsPixel;//每个像素字节大小
21     m_bihScreen.biCompression = BI_RGB;
22     m_bihScreen.biHeight = bmp.bmHeight;//高度
23     m_bihScreen.biPlanes = 1;
24     m_bihScreen.biSize = sizeof(BITMAPINFOHEADER);
25     m_bihScreen.biSizeImage = bmp.bmWidthBytes * bmp.bmHeight;//图像数据大小
26     m_bihScreen.biWidth = bmp.bmWidth;//宽度
27 
28     byte *m_pbmScreenData = new byte[bmp.bmWidthBytes * bmp.bmHeight];
29     GetDIBits(hMemDc,hMemBmp, 0, height, m_pbmScreenData,  
30         (LPBITMAPINFO) &m_bihScreen, DIB_RGB_COLORS);//获取位图数据  从BITMAP到内存数据
31 
32     TwoDimesionArray<RGBQUAD> colors(width,height);
33     for (int j=0;j<height;++j)
34     {
35         for (int i=0;i<width;++i)
36         {
37             byte *p=m_pbmScreenData+(height-1-j)*bmp.bmWidthBytes+i*4;
38             RGBQUAD c={int(*p),int(*(p+1)),int(*(p+2))};   //这里获取每个位置上的像素
39             colors.SetValue(i,j,c);
40         }
41     }
42 
43     ImageIO writer;
44     writer.WriteBmp(colors,"D:\\z.bmp");
45 }
复制代码
复制代码
 1 void Test_captureScreenMFC()
 2 {
 3     CDC *pDesktopDC = CDC::FromHandle(::GetDC(NULL));//获取当前整个屏幕DC
 4     int width = pDesktopDC->GetDeviceCaps(HORZRES);
 5     int height = pDesktopDC->GetDeviceCaps(VERTRES);
 6 
 7     CBitmap    memBmp;
 8     CDC memDC;
 9     memBmp.CreateCompatibleBitmap(pDesktopDC, width, height);
10     memDC.CreateCompatibleDC(pDesktopDC);
11     memDC.SelectObject(&memBmp);  //将memBitmap选入内存DC
12 
13     memDC.BitBlt(0, 0, width, height, pDesktopDC, 0, 0, SRCCOPY);//复制屏幕图像到内存DC
14     
15     BITMAP bmp;
16     memBmp.GetBitmap(&bmp); //CBitmap到BITMAP
17 
18     BITMAPINFOHEADER m_bihScreen;  
19     ZeroMemory(&m_bihScreen, sizeof(BITMAPINFOHEADER));//位图信息头
20     m_bihScreen.biBitCount = bmp.bmBitsPixel;//每个像素字节大小
21     m_bihScreen.biCompression = BI_RGB;
22     m_bihScreen.biHeight = bmp.bmHeight;//高度
23     m_bihScreen.biPlanes = 1;
24     m_bihScreen.biSize = sizeof(BITMAPINFOHEADER);
25     m_bihScreen.biSizeImage = bmp.bmWidthBytes * bmp.bmHeight;//图像数据大小
26     m_bihScreen.biWidth = bmp.bmWidth;//宽度
27 
28     byte *m_pbmScreenData = new byte[bmp.bmWidthBytes * bmp.bmHeight];
29     GetDIBits(/*pDesktopDC->m_hDC*/memDC.m_hDC, (HBITMAP)memBmp.m_hObject, 0, height, m_pbmScreenData,  
30         (LPBITMAPINFO) &m_bihScreen, DIB_RGB_COLORS);//获取位图数据  从BITMAP到内存数据
31 
32     TwoDimesionArray<RGBQUAD> colors(width,height);
33     for (int j=0;j<height;++j)
34     {
35         for (int i=0;i<width;++i)
36         {
37             byte *p=m_pbmScreenData+(height-1-j)*bmp.bmWidthBytes+i*4;
38             RGBQUAD c={int(*p),int(*(p+1)),int(*(p+2))};
39             colors.SetValue(i,j,c);
40         }
41     }
42 
43     ImageIO writer;
44     writer.WriteBmp(colors,"D:\\z.bmp");
45 }
复制代码
GetDIBits是DDB转化为DIB的关键函数。
TwoDimesionArray<T>是自定义的模板类,封装了二维数组的相关操作。
ImageIO 是保存图片到文件的类。

通过这两段代码显示了win32和MFC对应数据类型的不同

编辑推荐:
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· 展开说说关于C#中ORM框架的用法!
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
点击右上角即可分享
微信分享提示