win32汇编 屏幕截图保存BMP 学习笔记<第二篇>之东拼西凑

原创 2016年05月12日 12:28:06

接下来开始动手 先看raiky的代码

_GetCaptureBmp proc uses ebx esi edi
     LOCAL @hDc,@MemDc,@Data
     LOCAL @bi:BITMAPINFO

     invoke RtlZeroMemory,addr @bi,sizeof @bi
     mov ebx,sizeof BITMAPINFO
     mov @bi.bmiHeader.biSize,ebx
     invoke GetSystemMetrics,SM_CXSCREEN
     mov @bi.bmiHeader.biWidth,eax
     invoke GetSystemMetrics,SM_CYSCREEN
     mov @bi.bmiHeader.biHeight,eax
     mov @bi.bmiHeader.biPlanes,1
     mov @bi.bmiHeader.biBitCount,24
     invoke GetDC,NULL
     mov @hDc,eax
     invoke CreateCompatibleDC,@hDc
     mov @MemDc,eax
     invoke CreateDIBSection,@MemDc,addr @bi,DIB_RGB_COLORS,addr @Data,NULL,0

     mov hBmp,eax
     invoke SelectObject,@MemDc,hBmp
     invoke BitBlt,@MemDc,   0,   0,   @bi.bmiHeader.biWidth,   @bi.bmiHeader.biHeight,@hDc,   0,   0,   SRCCOPY 

     invoke ReleaseDC,NULL,   @hDc
     invoke DeleteDC,@MemDc  
   xor eax,eax
      ret
 _GetCaptureBmp endp

我看不出什么大的问题来
唯一值得商榷的是他对屏幕分辨率的侦测不适合DPI比较高的情况 比如我的笔记本DPI 150%分辨率会侦测不正确
这本身不是什么大问题
用GetDeviceCaps取代GetSystemMetrics即可

     invoke GetDC,NULL
     mov hDc,eax
     invoke RtlZeroMemory,addr bi,sizeof bi  ;ok
     mov ebx,sizeof BITMAPINFO
     mov bi.bmiHeader.biSize,ebx
    invoke GetDeviceCaps,hDc,DESKTOPHORZRES
     ;invoke GetSystemMetrics,SM_CXSCREEN  
     mov bi.bmiHeader.biWidth,eax
     print ustr$(eax),"DESKTOPVERTRES",13,10 ;debug 输出物理分辨率    
     invoke GetDeviceCaps,hDc,DESKTOPVERTRES
     ;invoke GetSystemMetrics,SM_CYSCREEN ;NG 高DPI下取分辨率值不正常
     mov bi.bmiHeader.biHeight,eax

     invoke ReleaseDC,NULL,   hDc ;--------------------------------------end of init for resolution detection

上面这段代码呢 就是完成屏幕分辨率的获取 这个比较简单

下面这段是初始化bmiHeader根据norains的解释 1,24这两个值没问题

 mov bi.bmiHeader.biPlanes,1
 mov bi.bmiHeader.biBitCount,24 
   ;norains 文章里提到一切从最简单做起,对于BMP而言,最简单的自然是24位位图,这就是为什么biPlanes和biBitCount分别设置为1和24的原因。  那这里不会有错

按照norains成功的范例来看整个流程应该是这样的
以下介绍有C的有汇编的混杂在一起 大家能懂这个意思就行 懒得move eax了 原谅我
1.首先要GetDC返回值传给hDc
HDC hDc = GetDC(NULL);
2. 然后以hDc为参数创建兼容的缓存DC 返回值为MemDc
MemDc= CreateCompatibleDC(hDc);
你问我什么是缓存DC 我现在也没参悟出这是什么鬼
3. 然后要用函数CreateDIBSection 这一步非常重要
invoke CreateDIBSection,MemDc,addr bi,DIB_RGB_COLORS,addr Data,NULL,0 ;OK
这里引用norains的描述
Data是分配的一个内存空间,将来用来存储HDC的内容,只不过现在一切都是空的。如果你将这数据保存出来,你会发现一团漆黑。
4. 将HBITMAP和HDC结合:
invoke SelectObject,MemDc,hBmp ;将HBITMAP和HDC结合: 至此为止,我们前期工作已经准备就绪,我们只需要将HDC的内容用BitBlt绘制到缓存中即可:
5. invoke BitBlt,MemDc, 0, 0, bi.bmiHeader.biWidth, bi.bmiHeader.biHeight,hDc, 0, 0, SRCCOPY
;在调用该函数之后,Data所指向的内存缓冲区已经改变 这点我们下篇用debug的方式去验证

上面1到5的步骤完整代码如下

     invoke GetDC,NULL
     mov hDc,eax
     invoke CreateCompatibleDC,hDc
     mov MemDc,eax
     invoke CreateDIBSection,MemDc,addr bi,DIB_RGB_COLORS,addr Data,NULL,0 ;OK
     ;Data是分配的一个内存空间,将来用来存储HDC的内容,只不过现在一切都是空的。如果你将这数据保存出来,你会发现一团漆黑。
     mov hBmp,eax
     invoke SelectObject,MemDc,hBmp ;将HBITMAP和HDC结合: 至此为止,我们前期工作已经准备就绪,我们只需要将HDC的内容用BitBlt绘制到缓存中即可:
     invoke BitBlt,MemDc,   0,   0,   bi.bmiHeader.biWidth,   bi.bmiHeader.biHeight,hDc,   0,   0,   SRCCOPY 
        ;在调用该函数之后,Data所指向的内存缓冲区已经改变
     invoke ReleaseDC,NULL,   hDc
     invoke DeleteDC,MemDc      

到了这里 Data所指向的内存缓冲区已经改变。是的,没错,这些改变的数据就是我们所需要的。接下来我们所需要做的仅仅是,将这数据按BMP文件的格式,保存下来即可。 By Norains
真的吗 我怎么感觉有点不踏实呢
看起来 raiky的第一个函数其实已经完成了截图的大部分啊为什么大费周章的写那么长的第二个函数呢 这里先不管了

心里有点不塌实 我觉得还是用debug的软件实际查看下内存的内容来验证下实际状况到底怎么样吧 请看下篇

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/ppluer/article/details/51383097

重温 Win32 API ----- 截屏指定窗口并打印

朋友说在一个VC++6.0开发的项目中要加入打印窗口的功能,让帮忙写个代码供其调用。这么老的IDE当然不想碰了,而且也不喜欢MFC笨拙不清晰的封装,所以决定采用纯Win32 API,然后用C++类简单...
  • smstong
  • smstong
  • 2014-12-22 17:12:57
  • 7138

win32汇编 屏幕截图保存BMP 学习笔记<第三篇>之odbg调试

我们来回顾下raiky code 根据帖子里的讨论错误的疑点在于 1. 对每个像素所占字节的估算可能有误 wBitCount;位图中每个像素所占字节数 简单的赋值4 2. 涉及到后面的调色板的...
  • ppluer
  • ppluer
  • 2016-05-12 12:52:33
  • 740

重温WIN32 API ------ 窗口上绘制位图文件

1 基本思路做界面仿真时,经常需要在窗口上贴图,随着图片数量的增多,通过资源文件中添加位图的方式会变得越来越不可控。所以本着“资源与程序分离“的原则,还是使用外部位图文件更加清晰明了。那么如何管理位图...
  • smstong
  • smstong
  • 2014-12-22 18:49:42
  • 4786

VC屏幕截图,保存为Bmp文件

新建一个MFC基于对话框的应用程序,在界面上放一个Button,为其实现点击事件,代码如下: void CScreenShotDlg::OnBtnScreenshot() { RECT rect ...
  • JoeBlackzqq
  • JoeBlackzqq
  • 2012-06-17 17:55:02
  • 7192

截屏并保存为bmp格式

嗯,代码大部分是在网上找的.自己组合了一下.算是拿来主义吧...哈.void CSaveBmpDlg::OnButton1() { // TODO: Add your control n...
  • zaijzhgh
  • zaijzhgh
  • 2010-09-09 13:37:00
  • 760

VC屏幕截图并保存为bmp、jpg、png等格式文件

int main(){HDC hdcSrc = GetDC(NULL);int nBitPerPixel = GetDeviceCaps(hdcSrc, BITSPIXEL);int nWidth =...
  • chinafe
  • chinafe
  • 2013-11-25 10:41:14
  • 4511

win32汇编 屏幕截图保存BMP 学习笔记<第四篇>之生成BMP文件

到目前BMP内容已经生成在内存 可是不能直接保存为BMP文件 因为BMP需要在开头写一些header数据 总计54字节 如下图 BMP header都是些什么呢 以windows平台为例 用...
  • ppluer
  • ppluer
  • 2016-05-13 15:14:06
  • 368

vc屏幕截图实现

1.获取保存截图文件的路径,暂时选定为桌面 //把截图的文件保存到桌面 virtual BOOL CaptureLolToDesktop(HWND hWnd) { Sleep(1*1000); ...
  • qingzai_
  • qingzai_
  • 2015-08-06 17:05:33
  • 2737

VC 抓屏的各种方法

VC 抓屏的各种方法2008-06-16 09:15目录:l          导言l          用GID函数抓屏l          用DirectX方式抓屏l          用Wind...
  • henry19850318
  • henry19850318
  • 2010-07-13 16:31:00
  • 5534

图片操作(二)--保存DC到BMP文件 win32

画了一下午的时间总算在mobile上保存了图片。BOOL SaveDcToBMP(HDC m_hdcMem){ BOOL bReturn = TRUE; HA...
  • infsafe
  • infsafe
  • 2010-01-05 22:32:00
  • 4081
收藏助手
不良信息举报
您举报文章:win32汇编 屏幕截图保存BMP 学习笔记<第二篇>之东拼西凑
举报原因:
原因补充:

(最多只允许输入30个字)