GDI32Api、Direct3D屏幕截图

最近因为工作需要,认真研究了一下屏幕截图的方法。
最主要的方法有两种,一、调用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,  00, WinGdi32Api.GetDeviceCaps(source,  8), WinGdi32Api.GetDeviceCaps(source,  10), source,  000x00CC0020);
            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,  00, control.Width, control.Height, source,  000x00CC0020);
            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( 00, 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 ;
 }

 

转载于:https://www.cnblogs.com/pulove/archive/2012/04/13/2446024.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值