Screenshots mit DirectX

  • VB.NET

Es gibt 37 Antworten in diesem Thema. Der letzte Beitrag () ist von Nanco.

    Screenshots mit DirectX

    Guten Tag!

    Nachdem ich nun schon mehrere Foren durchsucht habe (+ etwa 50 Googleseiten auf Deutsch/Englisch/Italienisch) bin ich der Lösung meines Problems noch immer nicht näher gekommen.
    Seit etwa 3 Monaten versuche ich verzweifelt, einen simplen Screenshot einer Vollbildanwendung (z.B. PC-Spiel) mit DirectX zu erstellen. Nach meiner Suchanfrage konnte ich in diesem Forum auch 3 Themen ausfindig machen, jedoch funktionierten die darin gezeigten Lösungsansätze bei mir nicht. Ich verwende das Visual Studio Express 2008.
    Was ich in Erfahrung bringen konnte ist, dass man vor dem Screenshot anscheinend ein Device erstellen muss. Habe ich auch versucht --> hat am Ende nicht funktioniert.
    Ich habe sogar einige Code-Schnipsel von C# in VB.NET umgeschrieben (z.B. msdn.microsoft.com/en-us/library/bb153278(VS.85).aspx) und auch versucht, während Screenshots das Aerodesign Auf coreproject.com habe ich eine Methode für C++ gefunden, ich habe versucht diese mit ähnlichen Befehlen für VB.NET umzuschreiben, ist mir jedoch nicht gelungen:
    codeproject.com/kb/dialog/scre…way%20of%20doing%20it%20:



    Meine Frage lautet also: Wie erstelle ich mit VB.NET einen DirectX-Screenshot?
    Sollte es jemandem gelingen, hier einen funktionierenden Code zu posten, wäre das wahrscheinlich das erste Forum in Europa mit einer Lösung für einen DirectX-Screenshot mit VB.NET...

    Mit freundlichen Grüßen,
    Markus

    PS: Bitte keine Antworten alá "Dazu gibt es schon genügend Themen/Beiträge", denn das weiß ich, jedoch enden die meisten von diesen Themen in einer Raterunde und auf eine Lösung - die am Ende nicht funktioniert - kommen diese nur selten.

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

    Jep, hab ich auch schon probiert. Klappt eigentlich auch alles perfekt (zumindest auf dem Desktop), wenn ich aber im Spiel bin, minimiert es sich und ich bekomme ich den Error "Device Lost" (siehe Anhang).
    Danke für die Antwort.
    Bilder
    • device_lost.PNG

      84,04 kB, 1.919×563, 495 mal angesehen
    Ich denke, damit lassen sich nur Screenshots von Spielen herstellen, die auf der XNA Game Engine basieren, da kein DirectX verwendet wird. Meines Wissens ist die Aufnahme von modernen Spielen (die alle auf DirectX basieren) auch nur mit DirectX möglich.

    So viel hab ich bis jetzt erfahren (bitte korrigiert mich, falls ich mich irre):
    DirectX nimmt nicht den Umweg über Windows, sonderen zeichnet direkt über die Grafikkarte. Sonst wäre ein einfacher Screenshot mit GDI(+) auch möglich, mit der Verwendung von GDI(+) erhält man aber bei Windows 7 nur Bilder vom Desktop, da für Windows 7 das Spiel streng genommen nicht geöffnet ist (zumindest kann es kein Abbild des Fensters erstellen, nur des normalen Desktops, der ja im Hintergrund läuft).
    Also muss man mit Managed DirectX zuerst ein Device (=Abbild?) des jeweiligen Spielfensters erstellen, kann dieses Device anschließend in ein Surface laden (oder zu einem Surface umwandeln) und dieses Surface danach als Textur (Bild) abspeichern.
    MfG

    PS: Ich kann mir einfach nicht vorstellen, dass es unmöglich ist, einen DirectX-Screenshot zu erstellen. Anscheinend ist es das aber doch, da ich bis jetzt (und ich habe vieeel gesucht und gefragt) keine Lösung erhielt.

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

    ups sry, aber das hier ist für DirectX (wenn du einen Screen von deinem eigenen DirectX Programm machen willst)
    riemers.net/eng/Tutorials/Dire…es3/Render_To_Texture.php
    Ich wollte auch mal ne total überflüssige Signatur:
    ---Leer---
    Ok, das ist nun mit DirectX.
    Allerdings bekomme ich beim Nachmachen diesen Fehler: "Device" ist kein Typ und kann nicht als Ausdruck verwendet werden.
    Außerdem kann ich nicht erkennen, wo genau da das Ganze in einer Bilddatei gespeichert wird.
    MfG
    also ich hab hier zwar kein VS drauf, aber habs mir trotzdem mal angeguckt und ich sehe dabei nirgends etwas, was mit DirectX gerendert wird, also willst du einen Screenshot vom gesamten Bildschirm machen? Oder in etwa von dem was du mit DirectX zeichnen lässt?
    Dieser Code war nämlich nicht für den gesamten Bildschirm gedacht ;)
    Ich wollte auch mal ne total überflüssige Signatur:
    ---Leer---
    nein dafür ist das ganze nicht gedacht...
    aber ich hab mir das von CodeProject mal angeguckt, das könnte dann ca so aussehen:

    VB.NET-Quellcode

    1. Private dev As Device
    2. Sub CaptureScreen()
    3. Dim pSurface As Surface = dev.CreateOffScreenPlainSurface(Windows.Forms.Screen.PrimaryScreen.Bounds.Width,Windows.Forms.Screen.PrimaryScreen.Bounds.Height,Direct3D,Format.A8R8G8B8,Direct3D.Pool.Scratch)'die variablen hab ich mich zusammengegooglet->bin nicht sicher ob die stimmen
    4. dev.GetFrontBufferData(0,pSurface)
    5. 'Speichern:
    6. SurfaceLoader.Save("Dateiname",ImageFileFormat.Bmp,pSurface)
    7. End Sub

    die Device musst du hierbei noch festlegen, weiß nicht genau wie das hier geht(ob du es wie bei einem normalen Projekt auch machen musst, oder anders?!)
    Ich wollte auch mal ne total überflüssige Signatur:
    ---Leer---
    Das sieht doch schonmal gut aus :)

    VB.NET-Quellcode

    1. Dim pSurface As Surface = dev.CreateOffScreenPlainSurface(Windows.Forms.Screen.PrimaryScreen.Bounds.Width, Windows.Forms.Screen.PrimaryScreen.Bounds.Height, Direct3D, Format.A8R8G8B8, Direct3D.Pool.Scratch)


    Hier bekomme ich bei "Direct3D" folgenden Fehler: "Microsoft.DirectX.Direct3D" ist ein Namespace und kann nicht als Ausdruck verwendet werden.
    Wenn ich "Direct3D" aus der Zeile lösche, heißt es bei der Ausführung, mein Programm sei keine zulässige Win32-Anwendung.
    Das mit dem Device festlegen, da weiß ich leider auch nicht mehr. Ist wahrscheinlich das größte Problem, denn sobald man das richtige Device hat, kann man das einfach in ein Surface und damit in eine Bilddatei speichern...
    MfG

    VB.NET-Quellcode

    1. Dim pSurface As Surface = dev.CreateOffScreenPlainSurface(Windows.Forms.Screen.PrimaryScreen.Bounds.Width, Windows.Forms.Screen.PrimaryScreen.Bounds.Height, Direct3D.Format.A8R8G8B8, Direct3D.Pool.Scratch)

    das war ausversehen, hab ein Komma anstatt einem Punkt gemacht^^
    hab mir das C++ Projekt mal runtergeladen...

    Quellcode

    1. d3dpp.Windowed=WINDOW_MODE;
    2. d3dpp.Flags=D3DPRESENTFLAG_LOCKABLE_BACKBUFFER;
    3. d3dpp.BackBufferFormat=ddm.Format;
    4. d3dpp.BackBufferHeight=nDisplayHeight=gScreenRect.bottom =ddm.Height;
    5. d3dpp.BackBufferWidth=nDisplayWidth=gScreenRect.right =ddm.Width;
    6. d3dpp.MultiSampleType=D3DMULTISAMPLE_NONE;
    7. d3dpp.SwapEffect=D3DSWAPEFFECT_DISCARD;
    8. d3dpp.hDeviceWindow=hWnd;
    9. d3dpp.PresentationInterval=D3DPRESENT_INTERVAL_DEFAULT;
    10. d3dpp.FullScreen_RefreshRateInHz=D3DPRESENT_RATE_DEFAULT;
    11. CreateDevice(D3DADAPTER_DEFAULT,D3DDEVTYPE_HAL,hWnd,D3DCREATE_SOFTWARE_VERTEXPROCESSING ,&d3dpp,&g_pd3dDevice)

    in VB sollte das glaub ich ca. so aussehen:

    VB.NET-Quellcode

    1. 'PresentationParameters:
    2. Dim _pp As New PresentationParameters()
    3. _pp.Windowed = True 'C++ ebenso
    4. _pp.Flag = Flag.LockableBackBuffer ' hoffenltich gibts das :P
    5. _pp.BackBufferFormat = Direct3D, Format.A8R8G8B8'hoffentlich dasselbe wie beim Surface
    6. _pp.BackBufferHeight = Windows.Forms.Screen.PrimaryScreen.Bounds.Height '???
    7. _pp.BackBufferWidth = Windows.Forms.Screen.PrimaryScreen.Bounds.Width '???
    8. _pp.MultiSample = MultiSampleType.None ' scheint richtig zu sein
    9. _pp.SwapEffect = SwapEffect.Discard ' jo kenn ich so
    10. _pp.DeviceWindowHandle = Me.Handle
    11. _pp.PresentationInterval = PresentationInterval.Default ' hmm musste wohl gucken
    12. '_pp.FullScreenRefreshRateInHz = ->lass das mal weg :P
    13. '0 ist Standardadapter ;)
    14. 'DeviceType: ist standardmäßig Hardware und etwas anderes konnte ich daraus nicht schließen^^
    15. 'hwnd: ist in .Net immer das Handle und kenn ich hier auch nicht anders...
    16. 'CreateFlags: kenn ich so und ist so...
    17. dev = New Device(0,DeviceType.Hardware,Me.Handle,CreateFlags.SoftwareVertexProcessing,_pp)
    Ich wollte auch mal ne total überflüssige Signatur:
    ---Leer---
    Vielen Dank, dass du dir die Mühe gemacht hast. Leider bekomme ich da trotzdem Fehler (siehe Anhang).
    Wenn ich nur das aufrufe:

    VB.NET-Quellcode

    1. Dim pSurface As Surface = dev.CreateOffscreenPlainSurface(Windows.Forms.Screen.PrimaryScreen.Bounds.Width, Windows.Forms.Screen.PrimaryScreen.Bounds.Height, Direct3D.Format.A8R8G8B8, Direct3D.Pool.Scratch) dev.GetFrontBufferData(0, pSurface) 'Speichern: SurfaceLoader.Save("C:/testdx.bmp", ImageFileFormat.Bmp, pSurface)


    bekomme ich zwar im Code selbst keinen Fehler, jedoch bei der Ausführung heißt es dann "BadImageFormatException - keine zulässige Win32-Anwendung". Habs mit anderen Dateitypen (.png) versucht, klappt allerdings auch nicht...
    MfG