屏幕截图--Take-ScreenShot分析

段干高歌
2023-12-01

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() 
        }     
    }      
}    

 类似资料: