Muchas gracias espero entonces con el codigo que me dejastes anteriormente me tira la foto cuando esta en FullScreen en Negro completamente lo que no mire es en que resolucion estaba trabajando.
Se toma en negro por que como intenté explicarte antes de tomar la captura primero debes minimizar y maximizar el juego para que la imagen estática del juego se actualice. Es complicado esta mierd@ de DirectX y no comprendo del todo como funciona en ese sentido, pero hay que hacer eso ...si utilizamos la metodología Win32/GDI.
De todas formas aun quisiera sino te molesta tratar de ejecutar con exito el tuyo para tenerlo como otra opción.
Lamentablemente eso no va a ser posible, no he logrdo solucionar el problema de no poder "actualizar" la imagen de forma automatizada (quiero decir, sin minimizar y maximizar manualmente la ventana del juego), y he probado técnicas que en un principio deberian funcionar (funciones:
ShowWindow,
SetForegroundwindow, etc) pero no, eso no funciona, DirectX parece trabajar de una forma compleja la ventana.
Si ni siquiera Windows por si solo ni tampoco (algunas)aplicaciones profesionales pueden tomar una captura en condiciones del juego cuando éste está en fullscreen, mucho menos soy capaz de hacerlo yo sin ser un experto en la materia de gráficos. Es complicado al menos.
Es necesario evitar las limitaciones gráficas del modelo Win32 y recurrir a una metodología más potente como DirectX para tomar ese tipo de captura, por ejemplo usando el wrapper de SharpDX para .NET.
Bueno nada ya espero entonces por esta que trabaja a la par con DirectX.
Aquí tienes. Con esta metodología basada en DirectX ya si que no va a haber problemas para tomar la captura del juego en fullscreen.
Imports System.Drawing.Imaging
Imports System.IO
Imports SharpDX
Imports SharpDX.Direct3D11
Imports SharpDX.DXGI
Imports Device = SharpDX.Direct3D11.Device
Imports MapFlags = SharpDX.Direct3D11.MapFlags
'Imports Elektro.Imaging.Tools
Namespace Test
Public NotInheritable Class SharpDXUtil
''' ----------------------------------------------------------------------------------------------------
''' <summary>
''' Capture the screen output using the default graphics card adapter.
''' <para></para>
''' This DirectX based methodology is useful to take screenshot of games that are running in full screen.
''' <para></para>
''' However, using this methodology for other common desktop screen captures will produce unexpected results (such as wrong colors);
''' so for common screenshots you should use the methods exposed in <see cref="Elektro.Imaging.Tools.ImageUtil"/> instead.
''' </summary>
''' ----------------------------------------------------------------------------------------------------
''' <returns>
''' The resulting <see cref="System.Drawing.Image"/>.
''' </returns>
''' ----------------------------------------------------------------------------------------------------
Public Shared Function TakeScreenshot() As Image
Return SharpDXUtil.TakeScreenshot(adapterIndex:=0)
End Function
''' ----------------------------------------------------------------------------------------------------
''' <summary>
''' Captures the screen output using the specified graphics card adapter.
''' <para></para>
''' This DirectX based methodology is useful to take screenshot of games that are running in full screen.
''' <para></para>
''' However, using this methodology for other common desktop screen captures will produce unexpected results (such as wrong colors);
''' so for common screenshots you should use the methods exposed in <see cref="Elektro.Imaging.Tools.ImageUtil"/> instead.
''' </summary>
''' ----------------------------------------------------------------------------------------------------
''' <param name="adapterIndex">
''' The index of the graphics card adapter.
''' <para></para>
''' Set this value to <c>0</c> if you don't have more than one graphics card.
''' </param>
''' ----------------------------------------------------------------------------------------------------
''' <returns>
''' The resulting <see cref="System.Drawing.Image"/>.
''' </returns>
''' ----------------------------------------------------------------------------------------------------
Public Shared Function TakeScreenshot(ByVal adapterIndex As Integer) As Image
Dim factory As Factory1
Dim adapter As Adapter1
Dim device As Device
Dim output As Output
Dim output1 As Output1
Dim scrSize As Size
Dim textureDesc As Texture2DDescription
Dim screenTexture As Texture2D
Dim duplicatedOutput As OutputDuplication
Dim captureDone As Boolean = False
Dim capture As Bitmap = Nothing
Dim i As Integer = 0
factory = New Factory1()
adapter = factory.GetAdapter1(adapterIndex)
device = New Device(adapter)
output = adapter.GetOutput(adapterIndex)
output1 = output.QueryInterface(Of Output1)()
scrSize = New Size(width:=CType(output.Description.DesktopBounds, SharpDX.Rectangle).Width,
height:=CType(output.Description.DesktopBounds, SharpDX.Rectangle).Height)
' Create Staging texture CPU-accessible.
textureDesc = New Texture2DDescription() With {
.CpuAccessFlags = CpuAccessFlags.Read,
.BindFlags = BindFlags.None,
.Format = Format.B8G8R8A8_UNorm,
.Width = scrSize.Width,
.Height = scrSize.Height,
.OptionFlags = ResourceOptionFlags.None,
.MipLevels = 1,
.ArraySize = 1,
.SampleDescription = New SampleDescription With {.Count = 1, .Quality = 0},
.Usage = ResourceUsage.Staging
}
screenTexture = New Texture2D(device, textureDesc)
duplicatedOutput = output1.DuplicateOutput(device)
While Not (captureDone)
Try
Dim screenResource As DXGI.Resource = Nothing
Dim duplicateFrameInformation As OutputDuplicateFrameInformation
' Try to get duplicated frame within given time.
duplicatedOutput.AcquireNextFrame(10000, duplicateFrameInformation, screenResource)
If (i > 0) Then
' Copy resource into memory that can be accessed by the CPU.
Using screenTexture2D As Texture2D = screenResource.QueryInterface(Of Texture2D)()
device.ImmediateContext.CopyResource(screenTexture2D, screenTexture)
End Using
' Get the desktop capture texture.
Dim mapSource As DataBox = device.ImmediateContext.MapSubresource(screenTexture, 0, MapMode.Read, MapFlags.None)
' Create the bitmap.
capture = New System.Drawing.Bitmap(scrSize.Width, scrSize.Height, PixelFormat.Format32bppArgb)
Dim boundsRect As New System.Drawing.Rectangle(0, 0, scrSize.Width, scrSize.Height)
' Copy pixels from screen capture Texture to GDI bitmap.
Dim mapDest As BitmapData = capture.LockBits(boundsRect, ImageLockMode.WriteOnly, capture.PixelFormat)
Dim sourcePtr As IntPtr = mapSource.DataPointer
Dim destPtr As IntPtr = mapDest.Scan0
For y As Integer = 0 To (scrSize.Height - 1)
' Copy a single line.
Utilities.CopyMemory(destPtr, sourcePtr, (scrSize.Width * 4))
' Advance pointers.
sourcePtr = IntPtr.Add(sourcePtr, mapSource.RowPitch)
destPtr = IntPtr.Add(destPtr, mapDest.Stride)
Next y
capture.UnlockBits(mapDest)
device.ImmediateContext.UnmapSubresource(screenTexture, 0)
captureDone = True
End If
screenResource.Dispose()
duplicatedOutput.ReleaseFrame()
Catch e As SharpDXException
If (e.ResultCode.Code <> DXGI.ResultCode.WaitTimeout.Result.Code) Then
Throw e
End If
End Try
i += 1
End While
If (duplicatedOutput IsNot Nothing) Then
duplicatedOutput.Dispose()
End If
If (screenTexture IsNot Nothing) Then
screenTexture.Dispose()
End If
If (output1 IsNot Nothing) Then
output1.Dispose()
End If
If (output IsNot Nothing) Then
output.Dispose()
End If
If (device IsNot Nothing) Then
device.Dispose()
End If
If (adapter IsNot Nothing) Then
adapter.Dispose()
End If
If (factory IsNot Nothing) Then
factory.Dispose()
End If
Return capture
End Function
End Class
End Namespace
Ejemplo de uso:
Test.SharpDXUtil.TakeScreenshot().Save("C:\Screenshot.png")
PD: Creo no hace falta decirlo, pero por si acaso: Necesitas descargar la librería de
SharpDX y para usar el código de arriba debes referenciar los siguientes ensamblados: SharpDX.dll, SharpDX.Direct3D11.dll, SharpDX.DXGI.dll y SharpDX.Mathematics.dll
Saludos