Captura de pantalla Incluyendo ventanas semitransparentes en .NET

Me gustaría una forma relativamente libre de pirateo para hacer esto, ¿alguna idea? Por ejemplo, lo siguiente toma una captura de pantalla que no incluye la ventana semitransparente:

Public Class Form1 Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Shown Text = "Opaque Window" Dim win2 As New Form win2.Opacity = 0.5 win2.Text = "Tranparent Window" win2.Show() win2.Top = Top + 50 win2.Left = Left() + 50 Dim bounds As Rectangle = System.Windows.Forms.Screen.GetBounds(Point.Empty) Using bmp As Bitmap = New Bitmap(bounds.Width, bounds.Height) Using g As Graphics = Graphics.FromImage(bmp) g.CopyFromScreen(Point.Empty, Point.Empty, bounds.Size) End Using bmp.Save("c:\temp\scn.gif") End Using Process.Start(New Diagnostics.ProcessStartInfo("c:\temp\scn.gif") With {.UseShellExecute = True}) End Sub End Class 

O mi google-fu realmente apesta o esto no es tan fácil como parece. Estoy bastante seguro de por qué sucede esto debido a la forma en que el controlador de video tendría que separar la memoria para hacer que esto funcione, pero no me importa por qué no funciona, solo quiero hacerlo sin …
* pirateo de teclas de la pantalla de impresión
* Software de terceros
* Las funciones de SDK son correctas, pero votaré cada uno de los objetos que posea el usuario que puedan mostrarme en un marco puro (es broma, pero sería bueno).

Si esta es la única manera de hacerlo, ¿cómo puedo hacer eso en VB?
1M gracias.

Los formularios que tienen la propiedad TransparencyKey u Opacity configurada son las denominadas ventanas estratificadas. Se muestran usando la función “superposición” del adaptador de video. Lo que los hace capaces de tener sus efectos de transparencia.

Capturarlos requiere activar la opción CopyPixelOperation.CaptureBlt en la sobrecarga CopyFromScreen que acepta el argumento CopyPixelOperation.

Desafortunadamente, esta sobrecarga tiene un error crítico que impide que esto funcione. No valida el valor correctamente. Todavía no está arreglado en .NET 4.0. No hay otra solución buena, pero recurra al uso de P / Invoke para hacer la captura de pantalla. Aquí hay un ejemplo:

 using System; using System.Drawing; using System.Windows.Forms; using System.Runtime.InteropServices; namespace WindowsApplication1 { public partial class Form1 : Form { public Form1() { InitializeComponent(); } private void button1_Click(object sender, EventArgs e) { Size sz = Screen.PrimaryScreen.Bounds.Size; IntPtr hDesk = GetDesktopWindow(); IntPtr hSrce = GetWindowDC(hDesk); IntPtr hDest = CreateCompatibleDC(hSrce); IntPtr hBmp = CreateCompatibleBitmap(hSrce, sz.Width, sz.Height); IntPtr hOldBmp = SelectObject(hDest, hBmp); bool b = BitBlt(hDest, 0, 0, sz.Width, sz.Height, hSrce, 0, 0, CopyPixelOperation.SourceCopy | CopyPixelOperation.CaptureBlt); Bitmap bmp = Bitmap.FromHbitmap(hBmp); SelectObject(hDest, hOldBmp); DeleteObject(hBmp); DeleteDC(hDest); ReleaseDC(hDesk, hSrce); bmp.Save(@"c:\temp\test.png"); bmp.Dispose(); } // P/Invoke declarations [DllImport("gdi32.dll")] static extern bool BitBlt(IntPtr hdcDest, int xDest, int yDest, int wDest, int hDest, IntPtr hdcSource, int xSrc, int ySrc, CopyPixelOperation rop); [DllImport("user32.dll")] static extern bool ReleaseDC(IntPtr hWnd, IntPtr hDc); [DllImport("gdi32.dll")] static extern IntPtr DeleteDC(IntPtr hDc); [DllImport("gdi32.dll")] static extern IntPtr DeleteObject(IntPtr hDc); [DllImport("gdi32.dll")] static extern IntPtr CreateCompatibleBitmap(IntPtr hdc, int nWidth, int nHeight); [DllImport("gdi32.dll")] static extern IntPtr CreateCompatibleDC(IntPtr hdc); [DllImport("gdi32.dll")] static extern IntPtr SelectObject(IntPtr hdc, IntPtr bmp); [DllImport("user32.dll")] public static extern IntPtr GetDesktopWindow(); [DllImport("user32.dll")] public static extern IntPtr GetWindowDC(IntPtr ptr); } } 

Fwiw, una versión posterior de Windows proporcionó una solución para este error. No estoy exactamente seguro de cuál, creo que fue Win7 SP1. La función BitBlt () ahora hará lo que usted desee si solo pasa la opción CopyPixelOperation.CaptureBlt. Pero, por supuesto, esa solución no se aplicó retroactivamente a las versiones anteriores de Windows, por lo que realmente no se puede depender de ella.