Screenshot und DirectX

  • VB.NET

Es gibt 9 Antworten in diesem Thema. Der letzte Beitrag () ist von Springbok.

    Screenshot und DirectX

    Hallo liebe Coder,

    ich hab ein Problem mit der Erstellung eines Programms. Ich möchte gerne Screenshots eines Spiels anlegen (Microsoft Flight Simulator X/FSX) und diese dann auf der Festplatte speichern.
    Ich habe schon dieser "Standardmethode " ausprobiert und es funktionierte auch wunderbar auf allen getesteten Programmen (Notepad, Windows Explorer,...). Dann wollte ich mein Programm umbauen um es dann so einzustellen damit es nur das FSX-Fenster speichert. Nachdem ich ein bisschen herumprobiert hatte und verschiedene Möglichkeiten ausprobiert hatte, hat mich dieser Code am meisten zufrieden gestellt (da ich alles zuerst mit Notepad/Windows Explorer,... teste). Nachdem ich das ganze dann mit dem FSX testete ging es nicht und nach etwas Google Recherche war das Problem auch schnell gefunden: DirectX geht den Weg direkt über die Grafikkarte anstatt nochmal mit Windows zu reden. Deshalb kann ich also keine Screenshots von einem Spiel machen. Danach stellte ich mein Programmieren für ein paar Tage ein um mich eingehend mal mit dem Thema zu beschäftigen und Alternativen zu finden. Microsoft bietet ja laut meiner Recherche eine Hilfe an zum Schnäppchenpreis von knappen 10000€ was ich aber heute nun nicht gerne ausgeben will :)

    Dann habe ich nach etwas Recherche eine Anleitung gefunden nachdem diese DirectX Hook (hoffe das heisst jetzt so..) Methode nur geht wenn man ein Framework unter 4 (ich nahm 3.5) und eine X86 CPU auswählt. (Informationen hab ich von hier). Alles also eingestellt wie es sein soll und auch den Code so programmiert wie er eigentlich sein sollte. Hier dann mal mein Code:

    VB.NET-Quellcode

    1. Public Function CaptureScreenshot(ByVal Device As Direct3D.Device, ByVal Filename As String, ByVal ImageFormat As Direct3D.ImageFileFormat) As Boolean
    2. Dim B As Direct3D.Surface
    3. Try
    4. B = Device.GetBackBuffer(0, 0, DirectX.Direct3D.BackBufferType.Mono)
    5. Direct3D.SurfaceLoader.Save(Filename, ImageFormat, B)
    6. B.Dispose()
    7. Catch ex As Exception
    8. Return False
    9. End Try
    10. Return True
    11. End Function
    12. Public Shared Function CaptureScreenshot(ByVal Device As Direct3D.Device, ByVal Filename As String) As Boolean
    13. Return CaptureScreenshot(Device, Filename, Direct3D.ImageFileFormat.Bmp)
    14. End Function


    Natürlich hab ich auch nicht die Namespace(s) vergessen:

    VB.NET-Quellcode

    1. Imports System.IO
    2. Imports System.Drawing
    3. Imports System.Drawing.Imaging
    4. Imports System.Runtime.InteropServices
    5. Imports Microsoft.DirectX


    und ja nun sagt mir VS Express 2012 folgendes:
    - "DirectX" wurde nicht deklariert. Auf das Objekt kann aufgrund seiner Schutzstufe möglicherweise nicht zugegriffen werden.
    - Auf einen Instanzmember einer Klasse kann nicht ohne explizite Instanz einer Klasse von einer/m freigegebenen Methode/Member aus verwiesen werden.
    - Auf einen Instanzmember einer Klasse kann nicht ohne explizite Instanz einer Klasse von einer/m freigegebenen Methode/Member aus verwiesen werden.

    Laut Google muss man da eine Instanz einstellen/generieren aber bevor ich daran wieder jetzt rumpfusche wollte ich erst einmal fragen ob ich alles bisher richtig gemacht hab?

    Vielen Danke für eure Hilfe!
    cheers Kevin

    Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von „Springbok“ ()

    Derfuhr schrieb:


    Imortiere auch "Microsoft.DirectX.Direct3D", für den "SurfaceLoader" und für das "Direct3D.ImageFileFormat" must du noch einen verweis(ohne imports) auf "Microsoft.DirectX.Direct3DX" einfügen.


    Ok hab nun folgendes importiert (ganz am Anfang Imports ...):

    VB.NET-Quellcode

    1. Imports System.IO
    2. Imports System.Drawing
    3. Imports System.Drawing.Imaging
    4. Imports System.Runtime.InteropServices
    5. Imports Microsoft.DirectX
    6. Imports Microsoft.DirectX.Direct3D


    Und dann nochmal unter Verweise folgendes:



    Aber der Fehler ist (und bleibt da)....
    cheers Kevin
    Hab das mal nachgebaut, in dieser Zeile hat die IDE gemeckert "B = Device.GetBackBuffer(0, 0, DirectX.Direct3D.BackBufferType.Mono)", einfach das erste DirectX entfernen. Hab mal ein wenig mit dem Code gearbeitet und habe eine bmp erstellen können(anhang), das ergebnis ist zwar noch nicht Perfekt, aber du kann ja den Code noch anpassen. (Läuft unter FW3.5)

    VB.NET-Quellcode

    1. Imports System.IO
    2. Imports System.Drawing
    3. Imports System.Drawing.Imaging
    4. Imports System.Runtime.InteropServices
    5. Imports Microsoft.DirectX
    6. Imports Microsoft.DirectX.Direct3D
    7. Public Class Form1
    8. Dim WithEvents t1 As New Timer
    9. Dim x As Integer
    10. Public Shared Function CaptureScreenshot(ByVal Device As Direct3D.Device, ByVal Filename As String, ByVal ImageFormat As Direct3D.ImageFileFormat) As Boolean
    11. Dim B As Direct3D.Surface
    12. Try
    13. B = Device.GetBackBuffer(0, 0, Direct3D.BackBufferType.Mono)
    14. Direct3D.SurfaceLoader.Save(Filename, ImageFormat, B)
    15. B.Dispose()
    16. Catch ex As Exception
    17. Return False
    18. End Try
    19. Return True
    20. End Function
    21. Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
    22. t1.Interval = 2500
    23. t1.Start()
    24. End Sub
    25. Private Sub t1_tick() Handles t1.Tick
    26. x += 1
    27. Dim params As PresentParameters = New PresentParameters
    28. params.SwapEffect = SwapEffect.Discard
    29. params.Windowed = True
    30. params.AutoDepthStencilFormat = DepthFormat.D32
    31. Dim Dev = New Device(0, DeviceType.Hardware, Me.Handle, CreateFlags.SoftwareVertexProcessing, params)
    32. CaptureScreenshot(CType(Dev, Device), "C:\dxtemp\" & x & ".bmp", Direct3D.ImageFileFormat.Bmp)
    33. End Sub
    34. End Class


    mfG

    Derfuhr
    Bilder
    • 1.png

      118,52 kB, 292×266, 166 mal angesehen
    @Derfuhr

    Ich glaub ich spinn:
    Also hab genau das selbe wie du nun in meiner IDE die Funktion CaptureScreenShot stehen unter Framework 3.5 und jetzt krieg ich bei folgenden Zeilen den Error:

    VB.NET-Quellcode

    1. B = Device.GetBackBuffer(0, 0, Direct3D.BackBufferType.Mono)
    2. Direct3D.SurfaceLoader.Save(Filename, ImageFormat, B)


    Auf einen Instanzmember einer Klasse kann nicht ohne explizite Instanz einer Klasse von einer/m freigegebenen Methode/Member aus verwiesen werden.

    Beide Mal wird das Direct3D gezackt unterstrichen. Das ist nicht normal oder?
    cheers Kevin
    Um es klar zu machen: It is a mistake on my side.

    Man darf die Funktion CaptureScreenshot NICHT auf

    VB.NET-Quellcode

    1. Public Shared Function

    stellen sondern, und wie sollte es auch anders sein auf:

    VB.NET-Quellcode

    1. Public Function


    Und tadaaa! Die IDE meldet keinen Fehler mehr und das Programm startet ohne zu meckern und/oder Fehlermeldungen rauszuspucken.

    1. Post natürlich berichtigt!

    Danke an alle! :)
    cheers Kevin

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „Springbok“ ()