如何截取非前端表單的
首先說一下PrintWindow這個API的使用
public static Bitmap GetWindowCapture(IntPtr hWnd)
{
IntPtr hscrdc = GetWindowDC(hWnd);
RECT windowRect = new RECT();
GetWindowRect(hWnd, ref windowRect);
int width = windowRect.right - windowRect.left;
int height = windowRect.bottom - windowRect.top;
IntPtr hbitmap = CreateCompatibleBitmap(hscrdc, width, height);
IntPtr hmemdc = CreateCompatibleDC(hscrdc);
SelectObject(hmemdc, hbitmap);
PrintWindow(hWnd, hmemdc, 0);
Bitmap bmp = Bitmap.FromHbitmap(hbitmap);
DeleteDC(hscrdc);//刪除用過的對象
DeleteDC(hmemdc);//刪除用過的對象
return bmp;
}
[DllImport("user32.dll")]
public static extern IntPtr GetWindowRect(IntPtr hWnd, ref RECT rect);
[DllImport("gdi32.dll")]
public static extern IntPtr CreateDC(
string lpszDriver, // driver name驅動名
string lpszDevice, // device name裝置名稱
string lpszOutput, // not used; should be NULL
IntPtr lpInitData // optional printer data
);
[DllImport("gdi32.dll")]
public static extern int BitBlt(
IntPtr hdcDest, // handle to destination DC目標裝置的控制代碼
int nXDest, // x-coord of destination upper-left corner目標對象的左上方的X座標
int nYDest, // y-coord of destination upper-left corner目標對象的左上方的Y座標
int nWidth, // width of destination rectangle目標對象的矩形寬度
int nHeight, // height of destination rectangle目標對象的矩形長度
IntPtr hdcSrc, // handle to source DC源裝置的控制代碼
int nXSrc, // x-coordinate of source upper-left corner來源物件的左上方的X座標
int nYSrc, // y-coordinate of source upper-left corner來源物件的左上方的Y座標
UInt32 dwRop // raster operation code光柵的操作值
);
[DllImport("gdi32.dll")]
public static extern IntPtr CreateCompatibleDC(
IntPtr hdc // handle to DC
);
[DllImport("gdi32.dll")]
public static extern IntPtr CreateCompatibleBitmap(
IntPtr hdc, // handle to DC
int nWidth, // width of bitmap, in pixels
int nHeight // height of bitmap, in pixels
);
[DllImport("gdi32.dll")]
public static extern IntPtr SelectObject(
IntPtr hdc, // handle to DC
IntPtr hgdiobj // handle to object
);
[DllImport("gdi32.dll")]
public static extern int DeleteDC(
IntPtr hdc // handle to DC
);
[DllImport("user32.dll")]
public static extern bool PrintWindow(
IntPtr hwnd, // Window to copy,Handle to the window that will be copied.
IntPtr hdcBlt, // HDC to print into,Handle to the device context.
UInt32 nFlags // Optional flags,Specifies the drawing options. It can be one of the following values.
);
[DllImport("user32.dll")]
public static extern IntPtr GetWindowDC(
IntPtr hwnd
);
很遺憾,上面的確可以截取非前端表單的,但是非GDI的程式是無法的比如DirectX
下面說一下BitBlt這個API的使用
/// <summary>
/// 提供全屏和指定視窗的 以及儲存為檔案的類
/// </summary>
public class ScreenCapture
{
/// <summary>
/// 全屏
/// </summary>
/// <returns></returns>
public Image CaptureScreen()
{
return CaptureWindow(User32.GetDesktopWindow());
}
/// <summary>
/// 指定視窗
/// </summary>
/// <param name="handle">視窗控制代碼. (在windows應用程式中, 從Handle屬性獲得)</param>
/// <returns></returns>
public Image CaptureWindow(IntPtr handle)
{
IntPtr hdcSrc = User32.GetWindowDC(handle);
User32.RECT windowRect = new User32.RECT();
User32.GetWindowRect(handle, ref windowRect);
int width = windowRect.right - windowRect.left;
int height = windowRect.bottom - windowRect.top;
IntPtr hdcDest = GDI32.CreateCompatibleDC(hdcSrc);
IntPtr hBitmap = GDI32.CreateCompatibleBitmap(hdcSrc, width, height);
IntPtr hOld = GDI32.SelectObject(hdcDest, hBitmap);
GDI32.BitBlt(hdcDest, 0, 0, width, height, hdcSrc, 0, 0, GDI32.SRCCOPY);
GDI32.SelectObject(hdcDest, hOld);
GDI32.DeleteDC(hdcDest);
User32.ReleaseDC(handle, hdcSrc);
Image img = Image.FromHbitmap(hBitmap);
GDI32.DeleteObject(hBitmap);
return img;
}
/// <summary>
/// 指定視窗 儲存為圖片檔案
/// </summary>
/// <param name="handle"></param>
/// <param name="filename"></param>
/// <param name="format"></param>
public void CaptureWindowToFile(IntPtr handle, string filename, ImageFormat format)
{
Image img = CaptureWindow(handle);
img.Save(filename, format);
}
/// <summary>
/// 全屏 儲存為檔案
/// </summary>
/// <param name="filename"></param>
/// <param name="format"></param>
public void CaptureScreenToFile(string filename, ImageFormat format)
{
Image img = CaptureScreen();
img.Save(filename, format);
}
/// <summary>
/// 輔助類 定義 Gdi32 API 函數
/// </summary>
private class GDI32
{
public const int SRCCOPY = 0x00CC0020;
[DllImport("gdi32.dll")]
public static extern bool BitBlt(IntPtr hObject, int nXDest, int nYDest,
int nWidth, int nHeight, IntPtr hObjectSource,
int nXSrc, int nYSrc, int dwRop);
[DllImport("gdi32.dll")]
public static extern IntPtr CreateCompatibleBitmap(IntPtr hDC, int nWidth,
int nHeight);
[DllImport("gdi32.dll")]
public static extern IntPtr CreateCompatibleDC(IntPtr hDC);
[DllImport("gdi32.dll")]
public static extern bool DeleteDC(IntPtr hDC);
[DllImport("gdi32.dll")]
public static extern bool DeleteObject(IntPtr hObject);
[DllImport("gdi32.dll")]
public static extern IntPtr SelectObject(IntPtr hDC, IntPtr hObject);
}
/// <summary>
/// 輔助類 定義User32 API函數
/// </summary>
private class User32
{
[StructLayout(LayoutKind.Sequential)]
public struct RECT
{
public int left;
public int top;
public int right;
public int bottom;
}
[DllImport("user32.dll")]
public static extern IntPtr GetDesktopWindow();
[DllImport("user32.dll")]
public static extern IntPtr GetWindowDC(IntPtr hWnd);
[DllImport("user32.dll")]
public static extern IntPtr ReleaseDC(IntPtr hWnd, IntPtr hDC);
[DllImport("user32.dll")]
public static extern IntPtr GetWindowRect(IntPtr hWnd, ref RECT rect);
}
}
上面的類 使用了BitBlt這個API 可以截取GDI或者非GDI圖形 只不過,非前端表單圖形不能截獲...
下面說一下不使用API 最簡單的全屏方案
public static Bitmap CopyPrimaryScreen()
{
Screen s = Screen.PrimaryScreen;
Rectangle r = s.Bounds;
int w = r.Width;
int h = r.Height;
Bitmap bmp = new Bitmap(w, h);
Graphics g = Graphics.FromImage(bmp);
g.CopyFromScreen
(
new Point(0, 0),
new Point(0, 0),
new Size(w, h)
);
return bmp;
}
最後,試試下面這個辦法:
只要表單的visable為true,即使它在螢幕的外面也可以抓到圖。如果為false,就是一張黑圖了,赫赫。
public static Bitmap GetWindow(IntPtr hWnd)
{
IntPtr hscrdc = GetWindowDC(hWnd);
Control control = Control.FromHandle(hWnd);
IntPtr hbitmap = CreateCompatibleBitmap(hscrdc, control.Width, control.Height);
IntPtr hmemdc = CreateCompatibleDC(hscrdc);
SelectObject(hmemdc, hbitmap);
PrintWindow(hWnd, hmemdc, 0);
Bitmap bmp = Bitmap.FromHbitmap(hbitmap);
DeleteDC(hscrdc);//刪除用過的對象
DeleteDC(hmemdc);//刪除用過的對象
return bmp;
}
API聲明
[DllImport("gdi32.dll")]
public static extern IntPtr CreateDC(
string lpszDriver, // driver name驅動名
string lpszDevice, // device name裝置名稱
string lpszOutput, // not used; should be NULL
IntPtr lpInitData // optional printer data
);
[DllImport("gdi32.dll")]
public static extern int BitBlt(
IntPtr hdcDest, // handle to destination DC目標裝置的控制代碼
int nXDest, // x-coord of destination upper-left corner目標對象的左上方的X座標
int nYDest, // y-coord of destination upper-left corner目標對象的左上方的Y座標
int nWidth, // width of destination rectangle目標對象的矩形寬度
int nHeight, // height of destination rectangle目標對象的矩形長度
IntPtr hdcSrc, // handle to source DC源裝置的控制代碼
int nXSrc, // x-coordinate of source upper-left corner來源物件的左上方的X座標
int nYSrc, // y-coordinate of source upper-left corner來源物件的左上方的Y座標
UInt32 dwRop // raster operation code光柵的操作值
);
[DllImport("gdi32.dll")]
public static extern IntPtr CreateCompatibleDC(
IntPtr hdc // handle to DC
);
[DllImport("gdi32.dll")]
public static extern IntPtr CreateCompatibleBitmap(
IntPtr hdc, // handle to DC
int nWidth, // width of bitmap, in pixels
int nHeight // height of bitmap, in pixels
);
[DllImport("gdi32.dll")]
public static extern IntPtr SelectObject(
IntPtr hdc, // handle to DC
IntPtr hgdiobj // handle to object
);
[DllImport("gdi32.dll")]
public static extern int DeleteDC(
IntPtr hdc // handle to DC
);
[DllImport("user32.dll")]
public static extern bool PrintWindow(
IntPtr hwnd, // Window to copy,Handle to the window that will be copied.
IntPtr hdcBlt, // HDC to print into,Handle to the device context.
UInt32 nFlags // Optional flags,Specifies the drawing options. It can be one of the following values.
);
[DllImport("user32.dll")]
public static extern IntPtr GetWindowDC(
IntPtr hwnd
);