★★ 关于抓屏的一个技术性问题

Fu7iang 2006-07-07 11:37:47

 本人对 GDI 不熟悉,可目前又急需高效的抓屏方法,用 C + GDI 的就行,
 请不要说写驱动或 DirectShow 之类的,
 BitBlt 这种常规方法的已经实现了,但希望找到一种速度更快的方法,
 据说 GetDIBits、GetObject、GetCurrentObject 之类的某个函数可以直接从
 屏幕 HDC 中取得 BITMAP,不知到该怎么写。。。。。。
 
 大家帮帮忙,高分相赠。谢谢!!!

...全文
816 18 打赏 收藏 转发到动态 举报
写回复
用AI写文章
18 条回复
切换为时间正序
请发表友善的回复…
发表回复
Fu7iang 2006-07-08
  • 打赏
  • 举报
回复

 被这问题困扰 3 天了,郁闷 ...
Fu7iang 2006-07-08
  • 打赏
  • 举报
回复
改成

if(bh.bmiHeader.biBitCount == 16)
nBitClrUsed = 2;
...

可问题依旧... 应该如何解决呢?
Fu7iang 2006-07-08
  • 打赏
  • 举报
回复

 应该怎样解决呢?
蒋晟 2006-07-08
  • 打赏
  • 举报
回复
if(bh.bmiHeader.biBitCount == 16)
nBitClrUsed = 2;

自己在单步调试的时候监视&hScreen之前的几个字节就可以看到
Fu7iang 2006-07-08
  • 打赏
  • 举报
回复
void TestRGB( void )
{
HDC hScreen = GetDC(NULL);
HBITMAP hBmp = (HBITMAP) GetCurrentObject (hScreen, OBJ_BITMAP);

BITMAPINFO bh = {0};
bh.bmiHeader.biSize = sizeof(bh.bmiHeader);
GetDIBits(hScreen, hBmp, 0, 0, NULL, &bh, DIB_RGB_COLORS);

int nBitClrUsed = 0;
if (bh.bmiHeader.biBitCount == 24)
nBitClrUsed = 3;
else if(bh.bmiHeader.biBitCount == 16)
nBitClrUsed = 3;
else if(bh.bmiHeader.biBitCount == 32)
nBitClrUsed = 4;

BYTE * bits =new BYTE[ bh.bmiHeader.biWidth * bh.bmiHeader.biHeight * nBitClrUsed ];
GetDIBits(hScreen, hBmp, 0, bh.bmiHeader.biHeight, bits, &bh, DIB_RGB_COLORS);

return;
}

这就是那个函数,有什么地方会操作了 stack 呢?
蒋晟 2006-07-08
  • 打赏
  • 举报
回复
执行到 return 会抛出个异常估计是写stack变量时越界,覆盖了返回地址。检查你对局部变量的写入操作。
Fu7iang 2006-07-08
  • 打赏
  • 举报
回复

pomelowu兄,上面的代码可以执行,我把他放在一个函数里
 
void TestRGB( void )
{
HDC hDC = GetDC( NULL );
..........
.......... // 获取 bits 的代码,除了颜色位那里,其它未作任何修改
..........
GetDIBits(hScreen, hBmp, 0, bh.bmiHeader.biHeight, bits, &bh, DIB_RGB_COLORS);
// 监视此处 GetDIBits() 返回的扫描行是 768,正常!

return; // 执行到 return 会抛出个异常,
// 内存错误之类的,用 Debug 捕获不到
}

测试环境如下:
XP Sp2,
VS.Net 2005,
Win32 Console Project [C++]
颜色: 16, 32 位模式分别测试


==============================================================================

另外 bh.bmiHeader.biBitCount 如果为 16 和 32,nBitClrUsed 应该是几呢?
初学 GDI,见笑了...
Fu7iang 2006-07-08
  • 打赏
  • 举报
回复
多谢羽兄
我对 DirectX 更陌生,暂时没空研究了。

请问 GetDIBits 比 BitBlt 能快多少呢?
(我的目标不是完整的BMP,只要能得到 "RGB位图数组" 就可以了:)

另外在 http://www.shenming.net/shen/oblog/user1/shenming/archives/2006/50.html
中提到 DIBSection 要更快些,要从 Screen 获取 DIBSection 应该按怎样的顺序调用呢?

我想从 BitBlt、GetDIBits、DIBsection 中选择一个最快的方法就可以了
pomelowu 2006-07-08
  • 打赏
  • 举报
回复
再精确下去,你其实就不要在GDI上下功夫了,提高效率也有限。。。还是DShow来得快些。。
pomelowu 2006-07-08
  • 打赏
  • 举报
回复
HDC hScreen = GetDC(NULL); // 取得屏幕 DC
HBITMAP hBmp = (HBITMAP) GetCurrentObject (hScreen, OBJ_BITMAP);
// 取得屏幕DC装载的位图句柄

BITMAPINFO bh = {0};
bh.bmiHeader.biSize = sizeof(bh.bmiHeader);
GetDIBits(hScreen, hBmp, 0, 0, NULL, &bh, DIB_RGB_COLORS); // 查询BITMAPINFO

int nBitClrUsed = 0;
if (bh.bmiHeader.biBitCount == 24)
nBitClrUsed = 3; // 每个像素占用的字节数,以24位为例,其余色深自己判断
BYTE * bits =new BYTE[bh.bmiHeader.biWidth * bh.bmiHeader.biHeight * nBitClrUsed];
GetDIBits(hScreen, hBmp, 0, bh.bmiHeader.biHeight, bits, &bh, DIB_RGB_COLORS);
// 获得整张位图的数据,保存到bits指向的空间

然后就可以按图像的坐标在bits中查找你要的像素的RGB信息了。


BitBlt 是复制位图,GetDIBits 是取位图的位图数组。
此外,有一个结论是,BitBlt将图像从屏幕拷到内存DC较慢,而用BitBlt将图像从内存DC拷到屏幕则相对快一些。
Fu7iang 2006-07-08
  • 打赏
  • 举报
回复
自己顶一下
Fu7iang 2006-07-08
  • 打赏
  • 举报
回复
改用 CreateDIBSection、DIBSection 速度会有提高么?
Fu7iang 2006-07-08
  • 打赏
  • 举报
回复
HDC hScreen = GetDC(NULL); // 取得屏幕 DC

能不能直接从这个 DC 中察看 BITMAP 中某些点的 RGB 数据? (不用 GetPixel)

另外,谁知道 BitBlt 和 GetDIBits 的区别和效率有什么不同呢?
Fu7iang 2006-07-08
  • 打赏
  • 举报
回复
多谢 QuickGo兄

BitBlt 这种传统方法已经做过了,效率不太理想,有更快的方法么?

fu7iang@qq.com
QQ: 75553995
QuickGo 2006-07-08
  • 打赏
  • 举报
回复
需要截获显示器的显示内容,首先创建显示器的设备内容句柄,也就是在GetDC的时候传入一个NULL,而不是某个窗口的句柄,传入NULL可以获得整个当前屏幕的设备内容句柄。然后再准备一个内存位图和一个内存DC,把内存位图选入内存Dc,并且用Bitblt把整个屏幕的位图画到内存位图上,从而完成截图的过程。如果你需要一个简单的示例,可以发邮件给我。QuickGo@Gmail.com
Fu7iang 2006-07-08
  • 打赏
  • 举报
回复
蒋大哥,这片文章我很早就拜读过了,谢谢你给我的启发!
但里面只有概念,没有实例,
希望能有个实实在在的快速抓屏函数,以解燃眉之急。。。。。
蒋晟 2006-07-08
  • 打赏
  • 举报
回复
blog.joycode.com/jiangsheng/ archive/2004/01/01/10410.aspx
Fu7iang 2006-07-07
  • 打赏
  • 举报
回复
http://community.csdn.net/Expert/topic/4867/4867627.xml?temp=.3163721
http://community.csdn.net/Expert/topic/4867/4867625.xml?temp=.266659
http://community.csdn.net/Expert/topic/4867/4867626.xml?temp=.2284204
依托Android最新的主流平台为Android4.0,面向最新的SDK和相关工具,同时还涵盖了老版平台中的一些常用功能,以帮助开发人员适应目前市面上所有的主流设备。《Android移动应用开发(第3版)卷Ⅰ:基础篇》涵盖了作者数年来在移动开发领域所积累的经验,以及成功进行移动项目开发所需的全部概念和实用技术,包括移动开发过程与传统软件开发的区别,还包括帮助你节约宝贵时间和规避隐患的技巧。不管你的项目有多大规模,《Android移动应用开发(第3版)卷Ⅰ:基础篇》都能为你提供帮助。 内容推荐   《Android移动应用开发(第3版)卷Ⅰ:基础篇》涵盖了Android开发从概念、技术到市场推广应用的全部主题,内容包括Android平台概览、Android应用程序设计精髓、Android用户界面设计精髓、Android应用程序设计精髓、对外发布你的Android应用程序和附录6个部分。附录还包含了Android开发常用工具(模拟器、DDMS和Eclipse)的使用指南。   《Android移动应用开发(第3版)卷Ⅰ:基础篇》卷Ⅰ以及本书的卷Ⅱ,不仅适合Android应用程序开发人员阅读,还能为QA测试人员提供指导。另外,本书还可以帮助项目经理更好地管理项目进程和项目团队,帮助市场推广人员更好地把握市场,创造令人瞩目的销售业绩。 作者简介 Lauren Darcey LaurenDarcey是一家专注于移动开发的软件公司的技术主管,所涉及的技术包括Android、iPhone、Blackberry、PalmPre、BREW和J2ME,还包括咨询服务。拥有20年专业软件产品研发经验的Lauren被公认为企业架构和商业级移动应用开发的权威。Lauren获得了加州大学圣克鲁兹分校授予的计算机科学专业学士学位。Shane Conder ShaneConder拥有丰富的开发经验,在过去的10年中,他把主要精力集中在移动和嵌入式开发领域,迄今已设计并开发了基于Android、iPhone、BREW、Blackberry、J2ME、Palm和WindowsMobile的诸多商业软件。Shane撰写了大量关于移动通信行业和评估移动开发平台的文章,这些文章发表在他的个人技术博客上,在业界受到了广泛的关注。Shane获得了加州大学授予的计算机科学专业学士学位。 目录 第一部分 Android平台概览 第1章 Android简介  第一部分 Android平台概览 第1章 Android简介  第2章 搭建你的Android开发环境  第3章 编写第一个Android应用程序  第4章 掌握Android开发工具  第二部分 Android应用程序设计基础 第5章 剖析Android应用程序  第6章 使用Android Manifest文件定义应用程序  第7章 管理应用程序资源  第三部分 Android用户界面设计精髓 第8章 探索用户界面屏幕元素  第9章 使用布局设计用户界面  第10章 使用Fragment  第11章 使用对话框  第四部分 Android应用程序设计精髓 第12章 使用Android首选项  第13章 使用文件和目录  第14章 使用内容提供器  第15章 设计高兼容性应用程序  第五部分 对外发布你的Android应用程序 第16章 移动软件开发过程  第17章 设计和开发"防弹"Android应用程序  第18章 测试Android应用程序  第19章 发布你的Android应用程序  第六部分 附录 附录A Android模拟器快速入门  A.1 模拟器的目的:虚拟现实  A.2 使用Android虚拟设备(AVD)  A.2.1 使用Android SDK和AVD管理器  A.2.2 创建AVD  A.3 使用指定AVD启动模拟器  A.3.1 维持模拟器高效运行  A.3.2 配置模拟器启动项  A.3.3 启动模拟器运行应用程序  A.3.4 从Android SDK和AVD管理器中启动模拟器  A.4 配置模拟器的GPS位置信息  A.5 在两个模拟器实例之间拨打电话  A.6 在两个模拟器实例之间发送消息  A.7 通过控制台与模拟器交互  A.7.1 使用控制台模拟来电  A.7.2 使用控制台模拟短消息  A.7.3 使用控制台发送GPS坐标  A.7.4 使用控制台监视网络状态  A.7.5 使用控制台操作电源设置  A.7.6 使用其他控制台命令  A.8 享受模拟器  A.9 认识模拟器的局限  参考资料和更多信息  附录B Android DDMS快速入门  B

15,979

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC 界面
社区管理员
  • 界面
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧