Game Screenshot

  • VB.NET

Es gibt 21 Antworten in diesem Thema. Der letzte Beitrag () ist von Bajuvare.

    Game Screenshot

    Hallo

    Ich habe folgendes Problem:

    Ich möchte einen Screenshot von einem Spiel erstellen. Ich habe derzeit versucht über

    VB.NET-Quellcode

    1. CopyFromScreen
    und über das simmulieren des drückens der Druck/S-ABF Taste und anschließenden auslesen der Zwischenablage über

    VB.NET-Quellcode

    1. Clipboard.GetDataObject
    .

    Bei beiden funktionen zeigt er das Spielfenster nicht an sondern screent den normalen Desktop (in der Auflösung des laufenden Spieles)
    Drücke ich selbst die Druck-Taste, öffne Paint und drücke STRG + V so wird ein richtiger Screenshot (auch vom Spiel) in Paint eingefügt.
    Könnte es sein das, dass Spiel über DirectX oder so läuft ?

    Soweit ich weiß geht das per Programm nicht so einfach wie wenn du Ingame bist und DRUCK/STRG+DRUCK drückst.

    Versuchen könntest du über das WindowHandle irgendwas zu basteln bin mir da aber nicht sicher ob das mit DirectX und so funktioniert.
    Falls dies Falsch ist bin ich gerne offen für auch andere Lösungswege zu sehen :P "Man Lernt ja nicht aus"


    Mfg
    Grüße , xChRoNiKx

    Nützliche Links:
    Visual Studio Empfohlene Einstellungen | Try-Catch heißes Eisen
    Ich muss davon ausgehen, dass das Spiel unter DirectX 9.0c läuft. Da ich allerdings durch das drücken von DRUCK einen vollwertigen Screenshot machen kann, dies per Sendkey allerdings nicht wirklich funktioniert verwundert mich. Zeigt allerdings gleichzeitig das es einen weg geben muss dies ohne ohne einen umständlichen Code machen zu können.

    Sollte es doch nicht über einen simplen Code gehen bräuchte ich Tipps wie ich das Problem sonst lösen könnte.
    Die Seiten die du geschikt hast habe ich auch schon gesehen. Leider handelt es sich hierbei um C# und nicht .net

    Ja ich weiß die sprachen sind ähnlich aber ich kann die codeschnipsel, die dort stehen trotzdem nicht in .net übersetzten.

    Hast du evtl noch vorschläge für .net (google spuckt sehr viel zu C# aus)

    Im zweiten Link steht leider auch nichts was mich weiterbringt

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

    C# ist ebenso .NET wie VB.Net. Verwechsel das bitte nicht.

    vb-paradise.de/allgemeines/tip…as-ist-aber-c-nicht-gilt/

    Warum nutzt Du für einen Screenshot nicht einfach die Druck-Taste? Einfacher geht es wohl doch kaum. Ferner bieten die meisten Spiele ohnehin einen Hotkey für Screenshots. So gesehen ist Dein Vorhaben ohnehin recht sinnlos, meinst nicht? Wenn schon, dann würde ich, sofern das Spiel nicht selber die Option bietet, Screenshots zu erstellen und zu speichern, ein Programm entwerfen, dass auf Änderungen der Zwischenablage reagiert und ggf. ein Bild entgegennimmt und speichert. Was willst Du letzen Endes erreichen?
    Die Unendlichkeit ist weit. Vor allem gegen Ende. ?(
    Manche Menschen sind gar nicht dumm. Sie haben nur Pech beim Denken. 8o

    StormBoomer schrieb:

    Leider handelt es sich hierbei um C# und nicht .net

    C# ist .NET nur mal so am Rande.

    Was ich beim Folgen der Links gefunden habe ist das hier: C# – Screen capture and Overlays for Direct3D 9, 10 and 11 using API Hooks
    Sieht sehr viel versprechend (DirectX9,10 und 11 abdeckend) aus.
    Du solltest eig. SlimDX (welches hier benötigt wird) mit VB ansteuern können, müsstest Du mal versuchen.
    Ansonsten kann ich mir nicht vorstellen, das Du dein vorhaben mit reinem VB unmsetzen kannst.
    Denn irgendwie muss Du dich ja zwischen DirectX und dem Device (Grafikkarte) werfen und dein Bild anfertigen, dies scheint mir mit reinem VB unmöglich.
    1. du wirst ja wohl zugreben, dass C# schon anders aussieht (für einen Anfänger) und das es für jemanden der sich nicht so perfekt auskennt schwer ist den code in vb zu übersetzten.

    2. Das spiel bietet keine eigene Screenshot funktion.

    3. Es geht darum das das Programm auch screenshots in bestimmten zeitabfolgen erstellen kann. Ohne das man noch einen Hotkey drücken muss. Ich habe bereits versucht über das Simulieren der Druck-Taste den Screenshot in die Zwischenablage zu kopieren und dann auszulesen. (sollte ich aber eig. auch so schon vorher geschrieben haben) @Dodo danke, dass du unseren Kollegen darauf hingewiesen hast
    @Dodo:

    Drücke ich selbst die Druck-Taste, öffne Paint und drücke STRG + V so wird ein richtiger Screenshot (auch vom Spiel) in Paint eingefügt.


    Darum, selber DRUCK-Taste drücken und im Programm auf nen Screenshot warten.
    Die Unendlichkeit ist weit. Vor allem gegen Ende. ?(
    Manche Menschen sind gar nicht dumm. Sie haben nur Pech beim Denken. 8o
    @Dodo

    Ich habe mir deinen Link einmal angeschaut. Ich habe diesen Converter hier benutzt converter.telerik.com/
    Leider gibt dieser dann einen Fehler aus

    HTML-Quellcode

    1. CONVERSION ERROR: Code could not be converted. Details:
    2. -- line 12 col 34: invalid StructMemberDecl
    3. Please check for any errors in the original code and try again.


    eingegeben habe ich den Code von deinem artikel spazzarama.com/2009/02/07/screencapture-with-direct3d/

    Spoiler anzeigen

    VB.NET-Quellcode

    1. using System;
    2. using System.Collections.Generic;
    3. using System.Text;
    4. using System.Drawing;
    5. using System.Runtime.InteropServices;
    6. namespace Spazzarama.ScreenCapture
    7. {
    8. public static class Direct3DCapture
    9. {
    10. private static SlimDX.Direct3D9.Direct3D _direct3D9 = new SlimDX.Direct3D9.Direct3D();
    11. private static Dictionary<IntPtr, SlimDX.Direct3D9.Device> _direct3DDeviceCache = new Dictionary<IntPtr, SlimDX.Direct3D9.Device>();
    12. /// <summary>
    13. /// Capture the entire client area of a window
    14. /// </summary>
    15. /// <param name="hWnd"></param>
    16. /// <returns></returns>
    17. public static Bitmap CaptureWindow(IntPtr hWnd)
    18. {
    19. return CaptureRegionDirect3D(hWnd, NativeMethods.GetAbsoluteClientRect(hWnd));
    20. }
    21. /// <summary>
    22. /// Capture a region of the screen using Direct3D
    23. /// </summary>
    24. /// <param name="handle">The handle of a window</param>
    25. /// <param name="region">The region to capture (in screen coordinates)</param>
    26. /// <returns>A bitmap containing the captured region, this should be disposed of appropriately when finished with it</returns>
    27. public static Bitmap CaptureRegionDirect3D(IntPtr handle, Rectangle region)
    28. {
    29. IntPtr hWnd = handle;
    30. Bitmap bitmap = null;
    31. // We are only supporting the primary display adapter for Direct3D mode
    32. SlimDX.Direct3D9.AdapterInformation adapterInfo = _direct3D9.Adapters.DefaultAdapter;
    33. SlimDX.Direct3D9.Device device;
    34. #region Get Direct3D Device
    35. // Retrieve the existing Direct3D device if we already created one for the given handle
    36. if (_direct3DDeviceCache.ContainsKey(hWnd))
    37. {
    38. device = _direct3DDeviceCache[hWnd];
    39. }
    40. // We need to create a new device
    41. else
    42. {
    43. // Setup the device creation parameters
    44. SlimDX.Direct3D9.PresentParameters parameters = new SlimDX.Direct3D9.PresentParameters();
    45. parameters.BackBufferFormat = adapterInfo.CurrentDisplayMode.Format;
    46. Rectangle clientRect = NativeMethods.GetAbsoluteClientRect(hWnd);
    47. parameters.BackBufferHeight = clientRect.Height;
    48. parameters.BackBufferWidth = clientRect.Width;
    49. parameters.Multisample = SlimDX.Direct3D9.MultisampleType.None;
    50. parameters.SwapEffect = SlimDX.Direct3D9.SwapEffect.Discard;
    51. parameters.DeviceWindowHandle = hWnd;
    52. parameters.PresentationInterval = SlimDX.Direct3D9.PresentInterval.Default;
    53. parameters.FullScreenRefreshRateInHertz = 0;
    54. // Create the Direct3D device
    55. device = new SlimDX.Direct3D9.Device(_direct3D9, adapterInfo.Adapter, SlimDX.Direct3D9.DeviceType.Hardware, hWnd, SlimDX.Direct3D9.CreateFlags.SoftwareVertexProcessing, parameters);
    56. _direct3DDeviceCache.Add(hWnd, device);
    57. }
    58. #endregion
    59. // Capture the screen and copy the region into a Bitmap
    60. using (SlimDX.Direct3D9.Surface surface = SlimDX.Direct3D9.Surface.CreateOffscreenPlain(device, adapterInfo.CurrentDisplayMode.Width, adapterInfo.CurrentDisplayMode.Height, SlimDX.Direct3D9.Format.A8R8G8B8, SlimDX.Direct3D9.Pool.SystemMemory))
    61. {
    62. device.GetFrontBufferData(0, surface);
    63. // Update: thanks digitalutopia1 for pointing out that SlimDX have fixed a bug
    64. // where they previously expected a RECT type structure for their Rectangle
    65. bitmap = new Bitmap(SlimDX.Direct3D9.Surface.ToStream(surface, SlimDX.Direct3D9.ImageFileFormat.Bmp, new Rectangle(region.Left, region.Top, region.Width, region.Height)));
    66. // Previous SlimDX bug workaround: new Rectangle(region.Left, region.Top, region.Right, region.Bottom)));
    67. }
    68. return bitmap;
    69. }
    70. }
    71. #region Native Win32 Interop
    72. /// <summary>
    73. /// The RECT structure defines the coordinates of the upper-left and lower-right corners of a rectangle.
    74. /// </summary>
    75. [Serializable, StructLayout(LayoutKind.Sequential)]
    76. internal struct RECT
    77. {
    78. public int Left;
    79. public int Top;
    80. public int Right;
    81. public int Bottom;
    82. public RECT(int left, int top, int right, int bottom)
    83. {
    84. this.Left = left;
    85. this.Top = top;
    86. this.Right = right;
    87. this.Bottom = bottom;
    88. }
    89. public Rectangle AsRectangle
    90. {
    91. get
    92. {
    93. return new Rectangle(this.Left, this.Top, this.Right - this.Left, this.Bottom - this.Top);
    94. }
    95. }
    96. public static RECT FromXYWH(int x, int y, int width, int height)
    97. {
    98. return new RECT(x, y, x + width, y + height);
    99. }
    100. public static RECT FromRectangle(Rectangle rect)
    101. {
    102. return new RECT(rect.Left, rect.Top, rect.Right, rect.Bottom);
    103. }
    104. }
    105. [System.Security.SuppressUnmanagedCodeSecurity()]
    106. internal sealed class NativeMethods
    107. {
    108. [DllImport("user32.dll")]
    109. internal static extern bool GetClientRect(IntPtr hWnd, out RECT lpRect);
    110. [DllImport("user32.dll")]
    111. [return: MarshalAs(UnmanagedType.Bool)]
    112. internal static extern bool GetWindowRect(IntPtr hWnd, out RECT lpRect);
    113. /// <summary>
    114. /// Get a windows client rectangle in a .NET structure
    115. /// </summary>
    116. /// <param name="hwnd">The window handle to look up</param>
    117. /// <returns>The rectangle</returns>
    118. internal static Rectangle GetClientRect(IntPtr hwnd)
    119. {
    120. RECT rect = new RECT();
    121. GetClientRect(hwnd, out rect);
    122. return rect.AsRectangle;
    123. }
    124. /// <summary>
    125. /// Get a windows rectangle in a .NET structure
    126. /// </summary>
    127. /// <param name="hwnd">The window handle to look up</param>
    128. /// <returns>The rectangle</returns>
    129. internal static Rectangle GetWindowRect(IntPtr hwnd)
    130. {
    131. RECT rect = new RECT();
    132. GetWindowRect(hwnd, out rect);
    133. return rect.AsRectangle;
    134. }
    135. internal static Rectangle GetAbsoluteClientRect(IntPtr hWnd)
    136. {
    137. Rectangle windowRect = NativeMethods.GetWindowRect(hWnd);
    138. Rectangle clientRect = NativeMethods.GetClientRect(hWnd);
    139. // This gives us the width of the left, right and bottom chrome - we can then determine the top height
    140. int chromeWidth = (int)((windowRect.Width - clientRect.Width) / 2);
    141. return new Rectangle(new Point(windowRect.X + chromeWidth, windowRect.Y + (windowRect.Height - clientRect.Height - chromeWidth)), clientRect.Size);
    142. }
    143. }
    144. #endregion
    145. }