最近因为工作需要,认真研究了一下屏幕截图的方法。
最主要的方法有两种,一、调用windows GDI32 API函数。二、使用DirectX9.0来实现。
另外,光注了一下Microsoft Expression Encoder 4 Screen Capture这个微软新出的功能,Expression Encoder 4 可实现屏幕录制,录制 文件格式为WMV ,为免费使用版本,Expression Encoder 4 Pro为 收费版本。
还 看了一下基于windows图形驱动技术的屏幕截图方法 ,文章链接地址:http://blog.csdn.net/jia162/article/details/2509974。实现起来可能比较困难与复杂。没找到实例参考及技术实现的算法,因此也就没有深入研究。
下面两种方法
一、GDI32 API截图,600*480大小生成Bitmap位图大概需要45ms左右,生成位图并save成bmp文件需要大概110ms左右,图片越大,耗费的时间越长,效率比较低。
二、DirectX截图,是把整个屏幕的拷贝到内存里,再进行截取,执行拷贝屏幕的方法g_pd3dDevice->GetFrontBufferData(0, g_pSurface)需要80ms-100ms,效率也比较低
若那位技术牛人有好滴方法,请推荐一下哦!!!
方法一实现:

using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices; namespace DataFrameFetch
{
    public class WinGdi32Api
    {
        [DllImport("GDI32.dll")]
        public static extern bool BitBlt(int hdcDest, int nXDest, int nYDest, int nWidth, int nHeight, int hdcSrc, int nXSrc, int nYSrc, int dwRop);
        [DllImport("GDI32.dll")]
        public static extern int CreateCompatibleBitmap(int hdc, int nWidth, int nHeight);
        [DllImport("GDI32.dll")]
        public static extern int CreateCompatibleDC(int hdc);
        [DllImport("GDI32.dll")]
        public static extern bool DeleteDC(int hdc);
        [DllImport("GDI32.dll")]
        public static extern bool DeleteObject(int hObject);
        [DllImport("GDI32.dll")]
        public static extern int GetDeviceCaps(int hdc, int nIndex);
        [DllImport("GDI32.dll")]
        public static extern int SelectObject(int hdc, int hgdiobj);
        [DllImport("User32.dll")]
        public static extern int GetDesktopWindow();
        [DllImport("User32.dll")]
        public static extern int GetWindowDC(int hWnd);
        [DllImport("User32.dll")]
        public static extern int GetDC(int hWnd);
        [DllImport("User32.dll")]
        public static extern int ReleaseDC(int hWnd, int hDC);
    }
}     using System;
using System.Collections.Generic;
using System.Text;
using System.Windows.Forms;
using System.Runtime.InteropServices;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO; namespace DataFrameFetch
{
    public class DataFetch
    {         public DataFetch()
        { }              /// <summary>
        /// 全屏截图
        /// </summary>
        /// <returns></returns>
        public Bitmap CaptureScreen()
        {
            DateTime dt_start = DateTime.Now;
            int source = WinGdi32Api.GetWindowDC(WinGdi32Api.GetDesktopWindow());
            int bitmap = WinGdi32Api.CreateCompatibleBitmap(source, WinGdi32Api.GetDeviceCaps(source, 8), WinGdi32Api.GetDeviceCaps(source, 10));             int destination = WinGdi32Api.CreateCompatibleDC(source);
            WinGdi32Api.SelectObject(destination, bitmap);
            WinGdi32Api.BitBlt(destination, 0, 0, WinGdi32Api.GetDeviceCaps(source, 8), WinGdi32Api.GetDeviceCaps(source, 10), source, 0, 0, 0x00CC0020);
            Bitmap img = this.GetBitmap(bitmap);
            this.Cleanup(bitmap, source, destination);
            DateTime dt_end = DateTime.Now;
            TimeSpan ts = dt_end - dt_start;   
            System.Diagnostics.Debug.WriteLine(ts.Milliseconds.ToString());
            return img;
        }         public Bitmap CaptureScreen(Control control)
        {
            DateTime dt_start = DateTime.Now;             int source = WinGdi32Api.GetDC(control.Handle.ToInt32());
            int bitmap = WinGdi32Api.CreateCompatibleBitmap(source, control.Width,control.Height);             int destination = WinGdi32Api.CreateCompatibleDC(source);
            WinGdi32Api.SelectObject(destination, bitmap);
            WinGdi32Api.BitBlt(destination, 0, 0, control.Width, control.Height, source, 0, 0, 0x00CC0020);
            Bitmap img = this.GetBitmap(bitmap);
            this.Cleanup(bitmap, source, destination);             byte[] buffer = this.ConvertBitmapToRGBByteArray(img);             string filename = "F:\\img\\" + dt_start.ToString("yyyyMMddHHmmss") + dt_start.Millisecond.ToString();             FileStream fs = new FileStream(filename + ".olc", FileMode.Create);
            fs.Write(buffer, 0, buffer.Length);
            fs.Flush();
            fs.Close();             //Bitmap bmp = this.FromRGB(buffer, img.Width, img.Height);
            //bmp.Save(filename + "_1.bmp");             DateTime dt_end = DateTime.Now;
            TimeSpan ts = dt_end - dt_start;
            System.Diagnostics.Debug.WriteLine(ts.Milliseconds.ToString());
            return img;
        }         private void Cleanup(int bitmap, int source, int destination)
        {
            WinGdi32Api.ReleaseDC(WinGdi32Api.GetDesktopWindow(), source);
            WinGdi32Api.DeleteDC(destination);
            WinGdi32Api.DeleteObject(bitmap);
        }         private Bitmap GetBitmap(int hbitmap)
        {
            Bitmap bmp = new Bitmap(Image.FromHbitmap(new IntPtr(hbitmap)), Image.FromHbitmap(new IntPtr(hbitmap)).Width, Image.FromHbitmap(new IntPtr(hbitmap)).Height);
            return bmp;
        }                /// <summary>
        /// 将位图转换成数组
        /// </summary>
        /// <param name="bmp"></param>
        /// <returns></returns>
        private byte[] ConvertBitmapToRGBByteArray(Bitmap bmp)
        {
            Rectangle rect = new Rectangle(new Point(0,0),bmp.Size);
            BitmapData bmpdata = bmp.LockBits(rect, ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);             int len = bmp.Width * bmp.Height * 3;
            byte[] buffer = new byte[len];
            int index = 0;
            unsafe
            {
                byte* color = (byte*)bmpdata.Scan0;
                for (int y = 0; y < bmp.Height; y++)
                {
                    for (int x = 0; x < bmp.Width; x++)
                    {
                        buffer[index++] = *color;
                        buffer[index++] = *(color + 1);
                        buffer[index++] = *(color + 2);
                        color += 3;
                    }
                    //color += bmpdata.Stride - bmpdata.Width * 3;
                }
            }
            bmp.UnlockBits(bmpdata);
            return buffer;
        }           /// <summary>
        /// 图像象素数组转成位图
        /// </summary>
        /// <param name="buffer"></param>
        /// <param name="width"></param>
        /// <param name="height"></param>
        /// <returns></returns>
        public Bitmap ConvertRGBByteArrayToBitmap(byte[] buffer, int width, int height)
        {
            // 申请目标位图的变量,并将其内存区域锁定 
            Bitmap bmp = new Bitmap(width, height, PixelFormat.Format24bppRgb);//创建新图像 
            Rectangle rect = new Rectangle(0, 0, width, height);
            BitmapData bmpData = bmp.LockBits(rect,ImageLockMode.WriteOnly,PixelFormat.Format24bppRgb);
            //// 用Marshal的Copy方法,将刚才得到的内存字节数组复制到BitmapData中 
            Marshal.Copy(buffer, 0, bmpData.Scan0, buffer.Length);
            bmp.UnlockBits(bmpData);  // 解锁内存区域 
  
            return bmp;
        }
    }
}

方法二以VC++实现


BOOL ScreenShot(HWND hWnd, TCHAR* fileName) {    HRESULT hr;        IDirect3D9*   gpD3D=NULL;    IDirect3DDevice9* gpd3dDevice=NULL;    IDirect3DSurface9* gpSurface=NULL; D3DDISPLAYMODE ddm; D3DPRESENT_PARAMETERS d3dpp; if((gpD3D=Direct3DCreate9(D3D_SDK_VERSION))==NULL) {  ErrorMessage("Unable to Create Direct3D ");  return E_FAIL; } if(FAILED(gpD3D->GetAdapterDisplayMode(D3DADAPTER_DEFAULT,&ddm))) {  ErrorMessage("Unable to Get Adapter Display Mode");  return E_FAIL; }  ZeroMemory(&d3dpp,sizeof(D3DPRESENT_PARAMETERS)); d3dpp.Windowed=WINDOW_MODE; d3dpp.Flags=D3DPRESENTFLAG_LOCKABLE_BACKBUFFER; d3dpp.BackBufferFormat=ddm.Format; d3dpp.BackBufferHeight=nDisplayHeight=gScreenRect.bottom =ddm.Height; d3dpp.BackBufferWidth=nDisplayWidth=gScreenRect.right =ddm.Width; d3dpp.MultiSampleType=D3DMULTISAMPLE_NONE; d3dpp.SwapEffect=D3DSWAPEFFECT_DISCARD; d3dpp.hDeviceWindow=hWnd; d3dpp.PresentationInterval=D3DPRESENT_INTERVAL_DEFAULT; d3dpp.FullScreen_RefreshRateInHz=D3DPRESENT_RATE_DEFAULT; if(FAILED(gpD3D->CreateDevice(D3DADAPTER_DEFAULT,D3DDEVTYPE_HAL,hWnd,D3DCREATE_SOFTWARE_VERTEXPROCESSING ,&d3dpp,&gpd3dDevice))) {  ErrorMessage("Unable to Create Device");  return E_FAIL; } if(FAILED(gpd3dDevice->CreateOffscreenPlainSurface(ddm.Width, ddm.Height, D3DFMT_A8R8G8B8, D3DPOOL_SCRATCH, &gpSurface, NULL))) {  ErrorMessage("Unable to Create Surface");  return E_FAIL; }  if (FAILED(hr = gpd3dDevice->GetFrontBufferData(0, gpSurface)))     {        gpSurface->Release() ;        return hr ;    } hr = D3DXSaveSurfaceToFile(fileName, D3DXIFF_BMP, gpSurface, NULL, NULL);     gpSurface->Release() ;    return hr ; }

基于GDI和D3D的抓屏技术的更多相关文章

  1. Windows桌面共享中一些常见的抓屏技术

    1. BitBlt 我想做Windows开发应该都知道这个API, 它能实现DC间的内容拷贝, 如果我们把源DC指定成Monitor DC或是桌面DC, 它就能实现抓屏功能. 对于通过这种方式的抓屏, ...

  2. Windows抓屏技术

    Windows桌面共享中一些常见的抓屏技术 1. BitBlt   我想做Windows开发应该都知道这个API, 它能实现DC间的内容拷贝, 如果我们把源DC指定成Monitor DC或是桌面DC, ...

  3. 基于MirrorDriver的录屏技术

    计算机屏幕图像的截取在屏幕的录制.计算机远程控制以及多媒体教学软件中都是关键术,基于Windows操作系统有多种截屏方法,研究的重点集中在如何快速有效的截取DBI(Device-Independent ...

  4. 基于Casperjs的网页抓取技术【抓取豆瓣信息网络爬虫实战示例】

    CasperJS is a navigation scripting & testing utility for the PhantomJS (WebKit) and SlimerJS (Ge ...

  5. DXGI快速截屏录屏技术

    DXGI快速截屏录屏技术 概述   很多地方都需要用到截屏/录屏技术,比如桌面直播,桌面录制等等.在微软Windows平台,有很多截屏的接口,不过大多数性能并不理想,Windows8以后微软引入了一套 ...

  6. 解析电子墨水屏技术(工作原理与LCD的区别)【转】

    转自:https://blog.csdn.net/weixin_42509369/article/details/84646808 阅读电子书早已成为大家生活中一部分,方便轻巧的电子版书籍更便于携带, ...

  7. ffmpeg抓屏输出的设置

    之前做windows下抓屏输出时使用ffmpeg.exe作为抓屏输出测试,命令行如下: ffmpeg -f gdigrab -i "desktop" -r 25 -vcodec m ...

  8. QQ群排名霸屏技术居然是这样简单

    最近做了一些收费的QQ群,收多少钱,一块钱的入门费,也就是说进入我的QQ群必须要1块钱的会费. 我的QQ群主要是干嘛呢,放些电影,比如说市面上电影院,正在播放的,最新最热门的,火爆的一些电影. 先前呢 ...

  9. 方别《QQ群霸屏技术》,又见《QQ群建群细则》

    规则,时刻变动;QQ群系列,咱们再来一轮. QQ群霸屏技术,你说建群貌似很菜,大家仿佛都知道,其实只知其一不知其二. QQ群类别 群分类,常规的就以下几种. 普通群. 建群随意,偏个性化,一言不合就拉 ...

随机推荐

  1. 一个Java发送邮件的案例

    经常有些要发送邮件的需求,但是去网上拷代码老是拷不到能直接运行的,还经常要去以前的项目里面拷,今天直接发出来算了,免得每次都要去别的项目拷. (只支持发送简单的文本文件,发附件的稍微复杂一丢丢,这里就 ...

  2. 百胜中国使用Rainbond实现云原生落地的实践

    百胜中国使用Rainbond实现云原生落地的实践 关于百胜中国 自从1987年第一家餐厅开业以来,截至2021年第二季度,百胜中国在中国大陆的足迹遍布所有省市自治区,在1500多座城镇经营着11023 ...

  3. SpringBoot 动态代理实现三方接口调用

    目录 一.定义注解 二.建立动态代理类 三.注入spring容器 四.编写拦截器 五.创建客户端调用类 六.main方法测试 七.启动项目 在某些业务场景中,我们只需要业务代码中定义相应的接口或者相应 ...

  4. Codeforces 1067E - Random Forest Rank(找性质+树形 dp)

    Codeforces 题面传送门 & 洛谷题面传送门 一道不知道能不能算上自己 AC 的 D1E(?) 挺有意思的结论题,结论倒是自己猜出来了,可根本不会证( 开始搬运题解 ing: 碰到这样 ...

  5. python3 excel读、写、修改操作

    python3上Excel文件操作的库比较多,新手一开始不知道如何选择合适的库,故整理如下: xlwt: 只能写不能读,只支持python2.3到python2.7版本,只支持xls文件. xlrd ...

  6. Kubernetes:Pod 升级、回滚

    本篇主要讨论如何实现滚动更新和回滚,任意更换版本并且回滚以前的版本(版本更新),而下一章会讨论到 Pod 缩放,根据机器资源自动拓展和收缩应用(自动扩容实例). 本文为作者的 Kubernetes 系 ...

  7. Nginx nginx: [emerg] using regex "\.php$" requires PCRE library 或 编译nginx错误:make[1]: *** [/pcre//Makefile] Error 127

    nginx: [emerg] using regex "\.php$" requires PCRE library  或 编译nginx错误:make[1]: *** [/pcre ...

  8. quota

    一.什么是磁盘配额 磁盘配额从字面意思上看就是给一个磁盘配置多少额度,而quota就是有多少限额的意思,所以总的来说就是限制用户对磁盘空间的使用量.因为Linux是多用户多任务的操作系统,许多人公用磁 ...

  9. C 语言do while 循环

    do while 循环小练习 1 #include <stdio.h> 2 #include <stdlib.h> 3 4 int main(void) 5 { 6 int a ...

  10. jquery chosen onchange 值改变时触发方法

    jquery chosen onchange 值改变时触发方法如下:$(".chzn-select").chosen().on("change", functi ...