在DirectDraw的非独占模式中,主表面即为当前屏幕。你可以直接Lock住主表面,从而取得主表面图象数据。但如果你要对大量的数据进行直接的操作,最好还是先在系统内存中建一个和主表面一样大小的后台表面。用BltFast把主表面复制一份到后台表面,然后锁住后台表面,再进行操作,这是因为CPU对显存的操作是什分慢的。

1、初始化DirectDraw
  你可以响应WM_CREATE消息,并在OnCreate中初始化DirectDraw

   void CMainFrame::InitDirectX()
  {
     //创建DirectDraw
     if (FAILED( DirectDrawCreate(NULL,&ddraw1,NULL)))
    {
      TRACE(/"Couldn/'t create DirectDraw object.//n/");
    }
    if (FAILED( ddraw1->QueryInterface(IID_IDirectDraw2,(LPVOID *)&ddraw2)))
    {
      TRACE(/"Couldn/'t query the interface.//n/");
    }
    if (ddraw2)
    {
      ddraw2->SetCooperativeLevel(GetSafeHwnd(),DDSCL_NORMAL);
    }
    if (ddraw1)
    {
      ddraw1->Release();
      ddraw1=NULL;
    }

     //创建主表面
     HRESULT r;

    DDSURFACEDESC desc;
    desc.dwSize = sizeof(desc);
    desc.dwFlags = DDSD_CAPS;
    desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
    r=ddraw2->CreateSurface(&desc, &primsurf, 0);
    if(r!=DD_OK)
    {
      AfxMessageBox(/"Create DirectX Surface failed//n /");
      PostMessage(WM_CLOSE);
    }
    r=ddraw2->CreateClipper(0, &clipper, 0);
    if(r!=DD_OK)
    {
      AfxMessageBox(/"CreateClipper() fialed//n /");
      PostMessage(WM_CLOSE);
    }
    r=clipper->SetHWnd(0,GetSafeHwnd());
    if(r!=DD_OK)
    {
      AfxMessageBox(/"SetHWnd() failed//n /");
      PostMessage(WM_CLOSE);
    }
    r=primsurf->SetClipper(clipper);
    if(r!=DD_OK)
    {
      AfxMessageBox(/"SetClipper() fialed//n /");
      PostMessage(WM_CLOSE);
    }

     //创建后台表面
     ZeroMemory(&desc,sizeof(desc));
    desc.dwSize=sizeof(desc);
    desc.dwFlags=DDSD_WIDTH|DDSD_HEIGHT|DDSD_CAPS;
    desc.dwWidth=::GetSystemMetrics(SM_CXSCREEN);
    desc.dwHeight=::GetSystemMetrics(SM_CYSCREEN);
    desc.ddsCaps.dwCaps = DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN;

    r=ddraw2->CreateSurface(&desc,&backsurf,0);
     //收集图象参数
     DDSURFACEDESC ddsd;

    ZeroMemory(&ddsd, sizeof(ddsd));
    ddsd.dwSize=sizeof(ddsd);
    backsurf->GetSurfaceDesc(&ddsd);
    BitCount = ddsd.ddpfPixelFormat.dwRGBBitCount;
    lPitch = ddsd.lPitch;
    dwWidth = ddsd.dwWidth;
    dwHeight = ddsd.dwHeight;
    dwRBitMask = ddsd.ddpfPixelFormat.dwRBitMask;
    dwGBitMask = ddsd.ddpfPixelFormat.dwGBitMask;
    dwBBitMask = ddsd.ddpfPixelFormat.dwBBitMask;
     //确定16Bit色时的修正(16Bit色时有两种显示格式565和555)
     RMove = 8; //这里先假定为565格式
     GMove = 3;
    BMove = 3;
    if(BitCount==16)
    {
      if(dwGBitMask==992)
      {
         //555格式
         RMove = 7;
        GMove = 2;
      }
      if(dwGBitMask==1984)
         //555格式
         BMove = 2;
    }
  }

2、得到图象数据的起始位置指针

   DDSURFACEDESC ddsd;

  ZeroMemory(&ddsd,sizeof(ddsd));
  ddsd.dwSize=sizeof(ddsd);
  if FAILED(backsurf->Lock(NULL, &ddsd, DDLOCK_WAIT , NULL))
    TRACE(/"backsurf->lock failed//n/"); // ddsd.lpSurface即为图象数据的指针

3、图象数据的转换
  DirectX是不支持图象格式转换的,如果你想得到的是24Bit的图象,而现在的显示模式为16Bit色,你就要自己动手了(看过下面的代码后你可能会发现,经转换后图象是倒置的,这是我为了方便对数进行压缩而进行的,你可以改变其for循环语句把图象换过来)。

   void CMainFrame:: Conversion()
  {
    int x,y;
    DDSURFACEDESC ddsd;

    ZeroMemory(&ddsd,sizeof(ddsd));
    ddsd.dwSize=sizeof(ddsd);

    if FAILED(backsurf->Lock(NULL, &ddsd, DDLOCK_WAIT , NULL))
      TRACE(/"backsurf->lock failed//n/");

    BYTE *scr=new BYTE[3*ddsd.dwHeight*ddsd.dwWidth];
    BYTE *scrt=scr;

     //Surface to RGB switch(BitCount)
     {
      case 8:
      {
         //TRACE(/"8 Bit//n/");
         BYTE *tem=(BYTE *)ddsd.lpSurface;
        PALETTEENTRY entry[256];

        HDC hScrDC=CreateDC(/"DISPLAY/", NULL, NULL, NULL);
        ::GetSystemPaletteEntries(hScrDC,0,256, entry);

        for(y=(int)dwHeight-1;y>=0;y--)
        {
          for(x=0;x<(int)dwWidth;x++)
          {
            *scrt++=entry[tem[x+lPitch*y]].peRed;
            *scrt++=entry[tem[x+lPitch*y]].peGreen;
            *scrt++=entry[tem[x+lPitch*y]].peBlue;
          }
        }
        break;
      }
      case 16:
      {
         //TRACE(/"16 Bit//n/");
         WORD *tem=(WORD *)ddsd.lpSurface;
         WORD color;
        for(y=(int)dwHeight-1;y>=0;y--)
        {
          for(x=0;x<(int)lPitch/2;x++)
          {
            color=tem[x+lPitch/2*y];
            *scrt++=(BYTE)((color&dwRBitMask)>>RMove);
            *scrt++=(BYTE)((color&dwGBitMask)>>GMove);
            *scrt++=(BYTE)(((color&dwBBitMask))<< BMove);
          }
        }
        break;
      }
      case 24:
      {
         //TRACE(/"24 Bit//n/");
         BYTE *tem=(BYTE *)ddsd.lpSurface;
        for(y=(int)dwHeight-1;y>=0;y--)
        {
          for(x=0;x<(int)dwWidth*3;x+=3)
          {
            *scrt++=tem[x+2+y*lPitch];
            *scrt++=tem[x+1+y*lPitch];
            *scrt++=tem[x+y*lPitch];
          }
        }
        break;
      }
      case 32:
      {
        AfxMessageBox(/"目前还不支持32Bit色//n请调整为24Bit色或16Bit色/");
        backsurf->Unlock(NULL);
        delete scr; PostMessage(WM_CLOSE);
        break;
      }
    }
    backsurf->Unlock(NULL);
     //在里进行你的数据处理 delete scr;
    //数据处理完毕释放内存
   }

用DirectDraw实现屏幕截图相关推荐

  1. 计算机桌面怎么截图快捷键,电脑屏幕截图的快捷键是什么

    在我们日常使用电脑时,不管是工作还是娱乐都经常会使用到截图功能.那么电脑屏幕截图的快捷键是什么呢?接下来由小编为大家整理出关于电脑屏幕截图的快捷键是什么,仅供参考,希望能够帮助到大家! 电脑屏幕截图的 ...

  2. 多媒体编程——屏幕截图

    多媒体编程--屏幕截图 为什么要先讲屏幕截图而不是硬件加速渲染图像呢,因为视频播放需要连续渲染图像,而最好的图像来源就是视频文件.但是视频文件解析是一个巨大的课题,哪怕是做一个测试例子,也至少要引入某 ...

  3. iOS开发- OpenGL ES屏幕截图

    之前写过一个常规的屏幕截图:http://blog.csdn.net/hitwhylz/article/details/17189351 可是发现这个办法对于OpenGL 无用.  获取到的数据为空. ...

  4. python截取html图片大小,Python打开html文件,截取屏幕截图,裁剪并保存为图像

    我使用Bokeh软件包生成地图以显示模拟结果.输出是具有交互性的html格式的单独地图.交互性是个别地图所必需的.Python打开html文件,截取屏幕截图,裁剪并保存为图像 请参阅此链接的示例: 仿 ...

  5. android添加截图功能,Android应用开发之Android 5.0及以上编程实现屏幕截图功能的方法...

    本文将带你了解Android应用开发Android 5.0及以上编程实现屏幕截图功能的方法,希望本文对大家学Android有所帮助. 本文实例讲述了Android   5.0及以上编程实现屏幕截图功能 ...

  6. electron 剪贴板 截图_用electron开发了一个屏幕截图工具

    前段时间做了一个钉钉的Linux版本,由于是基于网页版做的,所以缺失了很多桌面应用程序的功能.由于使用的用户多是Linux的用户,所以在Linux的截图功能没有,在几个用户的要求下决定做一个截图功能. ...

  7. 如何在github存储库中添加屏幕截图到README?

    本文翻译自:How to add screenshot to READMEs in github repository? Is it possible to place a screenshot in ...

  8. 屏幕截图功能的实现------Java篇

    2019独角兽企业重金招聘Python工程师标准>>> 屏幕截图功能程序在聊天软件与浏览器插件中运用最广泛,一般使用c#,vc+, now,现在介绍用Java实现屏幕截图效果,因为现 ...

  9. DIRECTDRAW 1:创建一个简单的DIRECTDRAW程序

    步骤 1: 创建一个 DirectDraw 对象 要创建一个 DirectDraw 对象的实例,你的应用程序要象 DDEx1 例程中的 doInit 函数那样先使用 DirectDrawCreate ...

最新文章

  1. ubuntu14.04上搭建android开发环境
  2. 用Python做一个翻译软件,还怕英语不好?
  3. 用 rpm-ostree 数据库检查更新信息和更新日志的方法
  4. 洛谷P1071 潜伏者 字符串
  5. 【数据结构与算法】之深入解析“柱状图中最大的矩形”的求解思路与算法示例
  6. JUnit 5和Selenium –改善项目配置
  7. Linux-Ubuntu 启用root账户
  8. mysql 查看锁_SQL-mysql锁等待与死锁
  9. 51nod 1091 重叠的线段(贪心)
  10. 信号时频图的横纵坐标对调
  11. php 取得user_agent,php通过$_SERVER['HTTP_USER_AGENT']获取浏览器相关参数(转)
  12. vSphere及云端计算的完美集成
  13. 关于vim复制剪贴粘贴命令的总结-转
  14. 电脑电池怎么测试软件,笔记本电池检测软件,小编教你笔记本电池怎么检测
  15. upc 6605: 所罗门王的宝藏(矩阵行列规律)
  16. 红帽子企业版RHEL5.0 的软件包管理
  17. SAP WORKFLOW 1创建一个简单的workflow helloworld
  18. A. K-divisible Sum
  19. 微信公众号新变动!你都发现了吗?
  20. 网易云音乐React Native体系建设与发展

热门文章

  1. SIFT特征原理简析(HELU版)
  2. Qt样式表参考:Qt Style Sheets
  3. 关于反向传播算法中的残差推导理解
  4. idea 2022版本整合svn解决代码冲突问题
  5. Python之深入解析如何一键批量生成真实的手机号码及其号码归属地解析
  6. 短语动词(Phrasal Verb)
  7. ant java delete_ant 入门教程
  8. sleep include linux,linux下 sleep() 与 usleep()
  9. 工程变更-ECN,ECO,ECR,ECA
  10. 分布式电源选址定容 在改进的IEEE33节点系统中分布式电源选择最佳接入点和接入容量