最近因為工作需要,認真研究了一下屏幕截圖的方法。
最主要的方法有兩種,一、調用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>
/// 圖像象素數組轉成位圖
///
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>
/// 圖像象素數組轉成位圖
///