2010-11-14 34 views
2

我想在C#.net中创建一个应用程序,它捕获当前活动窗口的屏幕截图,包括使用滚动条必须滚动的区域。以下代码进行截图。为了非常清楚,我希望代码能够对活动窗口进行截图,包括未显示的区域,并且仅通过使用滚动条显示。如何在C#中使用全尺寸窗口截图#

public class ScreenShot 
{ 
    /// <summary> 
    /// Captures the screenshot of the entire desktop 
    /// </summary> 
    /// <returns>Image object containing the screenshot of the desktop</returns> 
    private Image CaptureDesktop() 
    { 
     return CaptureWindow(User32.GetDesktopWindow()); 
    } 

    public Image CaptureAciveWindow() 
    { 
     return CaptureWindow(User32.GetForegroundWindow()); 
    } 

    /// <summary> 
    /// An Internal method, that captures the screenshot of any given Application window, given its Handle. 
    /// </summary> 
    /// <param name="handle">The handle of the window you want to Capture</param> 
    /// <returns>An Image object containing the screenshot of the active application window</returns> 
    private Image CaptureWindow(IntPtr handle) 
    { 
     // get te hDC of the target window 
     IntPtr hdcSrc = User32.GetWindowDC(handle); 
     // get the size 
     User32.RECT windowRect = new User32.RECT(); 
     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 
     IntPtr hdcDest = GDI32.CreateCompatibleDC(hdcSrc); 
     // create a bitmap we can copy it to, 
     // using GetDeviceCaps to get the width/height 
     IntPtr hBitmap = GDI32.CreateCompatibleBitmap(hdcSrc, width, height); 
     // select the bitmap object 
     IntPtr hOld = GDI32.SelectObject(hdcDest, hBitmap); 
     // bitblt over 
     GDI32.BitBlt(hdcDest, 0, 0, width, height, hdcSrc, 0, 0, GDI32.SRCCOPY); 
     // restore selection 
     GDI32.SelectObject(hdcDest, hOld); 
     // clean up 
     GDI32.DeleteDC(hdcDest); 
     User32.ReleaseDC(handle, hdcSrc); 
     // get a .NET image object for it 
     Image img = Image.FromHbitmap(hBitmap); 
     // free up the Bitmap object 
     GDI32.DeleteObject(hBitmap); 

     return img; 
    } 

    /// <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); 
     /// <summary> 
     /// Gets the Handle for current active window 
     /// </summary> 
     /// <returns>Active windows Handle</returns> 
     [DllImport("user32.dll")] 
     public static extern IntPtr GetForegroundWindow(); 
    } 
} 

回答

4

你在这里做一个假设,也不一定是真的:有有什么东西在区域未涡卷早已等候。应用程序可以构建特定高度或宽度的滚动条,并且在用户实际拖动滚动条之前不会实际呈现任何内容到表面。你想捕捉的图像只存在于潜在的位置。这可以用来提高性能—认为即时加载或减少内存使用。这是一种相当常用的技术,所以你所要求的并不合理。

+0

好吧,可能是我必须同意你 – Vamsi 2011-06-25 15:05:58

3

捕获屏幕内容,而无需使用任何Win32 API调用,只是用.NET 2.0的CodeProject

+0

这是一篇很棒的文章,谢谢 – Vamsi 2010-11-15 13:21:19

1

您需要将整个窗口/窗体重新绘制到图形对象上。一个(简单)的例子可以在this CodeProject article找到。您需要实现对项目中需要的所有控件的支持。另外,如果您在示例应用程序中调整窗口大小(隐藏某些控件)并进行测试打印,则会看到主窗体(仅作为另一个控件)绘制在其他控件上,这不是真正的问题,但看起来不太好 - 如果这是一个问题,你可以删除支持绘制主窗体。

或者,如果使用或切换到WPF,则可以使用PrintDialog.PrintVisual()打印控件(包括主窗口)。

相关问题