C#代码分析
$code = @'
using System;
using System.Runtime.InteropServices;
using System.Drawing;
using System.Drawing.Imaging;
namespace ScreenShotDemo
{
/// <summary>
/// Provides functions to capture the entire screen, or a particular window, and save it to a file.
/// </summary>
public class ScreenCapture
{
/// <summary>
/// Creates an Image object containing a screen shot the active window
/// </summary>
/// <returns></returns>
public Image CaptureActiveWindow()
{
#GetForegroundWindow获取一个前台窗口的句柄(用户当前工作的窗口)
#[DllImport("user32.dll")]
#private static extern IntPtr GetForegroundWindow();
return CaptureWindow( User32.GetForegroundWindow() );
}
/// <summary>
/// Creates an Image object containing a screen shot of the entire desktop
/// </summary>
/// <returns></returns>
public Image CaptureScreen()
{
#GetDesktopWindow,该函数返回桌面窗口的句柄。桌面窗口覆盖整个屏幕。桌面窗口是一个要在其上绘制所有的图标和其他窗口的区域。
return CaptureWindow( User32.GetDesktopWindow() );
}
/// <summary>
/// Creates an Image object containing a screen shot of a specific window
/// </summary>
/// <param name="handle">The handle to the window. (In windows forms, this is obtained by the Handle property)</param>
/// <returns></returns>
private Image CaptureWindow(IntPtr handle)
{
// get te hDC of the target window
#GetWindowDC函数:返回hWnd参数所指定的窗口的设备环境
IntPtr hdcSrc = User32.GetWindowDC(handle);
// get the size
User32.RECT windowRect = new User32.RECT();
//GetWindowRect是一个Windows API函数。该函数返回指定窗口的边框矩形的尺寸,函数原型为void GetWindowRect(LPRECT lpRect) const
User32.GetWindowRect(handle,ref windowRect);
//获取宽度和高度
int width = windowRect.right - windowRect.left;
int height = windowRect.bottom - windowRect.top;
// create a device context we can copy to
#该函数创建一个与指定设备兼容的内存设备上下文环境(DC)
IntPtr hdcDest = GDI32.CreateCompatibleDC(hdcSrc);
// create a bitmap we can copy it to,
// using GetDeviceCaps to get the width/height
//CreateCompatibleBitmap该函数用于创建与指定的设备环境相关的设备兼容的位图
IntPtr hBitmap = GDI32.CreateCompatibleBitmap(hdcSrc,width,height);
// select the bitmap object
//函数功能:该函数选择一对象到指定的设备上下文环境中,该新对象替换先前的相同类型的对象。
IntPtr hOld = GDI32.SelectObject(hdcDest,hBitmap);
// bitblt over
//bitblt就实现了将位图从新创建的设备环境中copy到当前的设备环境当中
//BitBlt 用于从原设备中复制位图到目标设备
//BitBlt(int x,int y,int nWidth,int nHeight,CDC*pSrcDC,int xSrc,int ySrc,DWORDdwRop);
//参数:
//x:目标矩形区域的左上角x轴坐标点。
//y:目标矩形区域的左上角y轴坐标点。
//nWidth:在目标设备中绘制位图的宽度。
//nHight:在目标设备中绘制位图的高度。
//pSrcDC:源设备上下文对象指针。
//xSrc:源设备上下文的起点x轴坐标,函数从该起点复制位图到目标设备。
//ySrc:源设备上下文的起点y轴坐标,函数从该起点复制位图到目标设备。
//dwRop:光栅操作代码
//BLACKNESS 使用黑色填充目标区域
//DSTINVERT 目标矩阵区域颜色取反
//MERGECOPY 使用与运算组合原设备矩形区域的颜色和目标设备的画刷
//MERGEPAINT 使用或运算将反向的源矩形区域的颜色和目标矩形区域的颜色合并
//NOTSRCCOPY 复制源设备区域的反色到目标设备中
//NOTSRCERASE 使用或运算组合源设备区域与目标设备区域的颜色,然后对结果颜色取反
//PATCOPY 复制源设备当前选中的画刷到目标设备
//PATINVERT 使用异或运算组合目标设备选中的画刷和目标设备区域的颜色
//PATPAINT 通过或运算组合目标区域当前选中的画刷和源设备区域反转的颜色
//SRCAND 使用与运算组合源设备和目标设备区域的颜色
//SRCCOPY 直接复制源设备区域到目标设备中
//SRCERASE 使用与运算组合目标设备区域的反色与源设备区域的颜色
//SRCINVERT 使用异或运算组合源设备区域颜色和目标设备区域颜色
//SRCPAINT 使用或运算组合源设备区域颜色和目标设备区域颜色
//WHITENESS 使用白色填充目标区域
//GDI32.BitBlt(hdcDest,0,0,width,height,hdcSrc,0,0,GDI32.SRCCOPY);
// restore selection
GDI32.SelectObject(hdcDest,hOld);
// clean up
//该函数删除指定的设备上下文环境(Dc)
GDI32.DeleteDC(hdcDest);
//ReleaseDC函数释放设备上下文环境(DC)供其他应用程序使用
User32.ReleaseDC(handle,hdcSrc);
// get a .NET image object for it
//从 Windows 句柄创建 Bitmap
Image img = Image.FromHbitmap(hBitmap);
// free up the Bitmap object
GDI32.DeleteObject(hBitmap);
return img;
}
/// <summary>
/// Captures a screen shot of the active window, and saves it to a file
/// </summary>
/// <param name="filename"></param>
/// <param name="format"></param>
public void CaptureActiveWindowToFile(string filename, ImageFormat format)
{
Image img = CaptureActiveWindow();
//将此 Image 以指定格式保存到指定文件
img.Save(filename,format);
}
/// <summary>
/// Captures a screen shot of the entire desktop, and saves it to a file
/// </summary>
/// <param name="filename"></param>
/// <param name="format"></param>
public void CaptureScreenToFile(string filename, ImageFormat format)
{
Image img = CaptureScreen();
img.Save(filename,format);
}
/// <summary>
/// Helper class containing Gdi32 API functions
/// </summary>
private class GDI32
{
public const int SRCCOPY = 0x00CC0020; // BitBlt dwRop parameter
[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>
/// Helper class containing User32 API functions
/// </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);
[DllImport("user32.dll")]
public static extern IntPtr GetForegroundWindow();
}
}
}
'@
下面的powershell代码
#User Add-Type to import the code
#通过代码添加新类型
#ReferencedAssemblies指定类型所依赖的程序集。默认情况下,Add-Type 引用 System.dll 和System.Management.Automation.dll
add-type $code -ReferencedAssemblies 'System.Windows.Forms','System.Drawing'
#Create the object for the Function
$capture = New-Object ScreenShotDemo.ScreenCapture
#Take screenshot of the entire screen
If ($Screen) {
Write-Verbose "Taking screenshot of entire desktop"
#Save to a file
If ($file) {
If ($file -eq "") {
$file = "$pwd\image.bmp"
}
Write-Verbose "Creating screen file: $file with imagetype of $imagetype"
$capture.CaptureScreenToFile($file,$imagetype)
}
ElseIf ($print) {
$img = $Capture.CaptureScreen()
#从 Windows 窗体应用程序打印时,定义一种可重用的可发送到打印机上的对象
$pd = New-Object System.Drawing.Printing.PrintDocument
#在指定位置以原始大小绘制指定的Image。
#Graphics.DrawImage
#使用其原始物理尺寸在坐标对指定的位置绘制指定的图像
#public void DrawImage (System.Drawing.Image image, int x, int y);
$pd.Add_PrintPage({$_.Graphics.DrawImage(([System.Drawing.Image]$img), 0, 0)})
$pd.Print()
}
Else {
$capture.CaptureScreen()
}
}
#Take screenshot of the active window
If ($ActiveWindow) {
Write-Verbose "Taking screenshot of the active window"
#Save to a file
If ($file) {
If ($file -eq "") {
$file = "$pwd\image.bmp"
}
Write-Verbose "Creating activewindow file: $file with imagetype of $imagetype"
$capture.CaptureActiveWindowToFile($file,$imagetype)
}
ElseIf ($print) {
$img = $Capture.CaptureActiveWindow()
$pd = New-Object System.Drawing.Printing.PrintDocument
$pd.Add_PrintPage({$_.Graphics.DrawImage(([System.Drawing.Image]$img), 0, 0)})
$pd.Print()
}
Else {
$capture.CaptureActiveWindow()
}
}
}