2010-11-14 36 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()打印控件(包括主窗口)。

相關問題