Taking screenshots from DirectX games

Collapse
X
 
  • Time
  • Show
Clear All
new posts
  • SimpleData
    New Member
    • Jul 2009
    • 10

    Taking screenshots from DirectX games

    Hi
    I need to capture screenshots from DirectX games. I am using this code but sometimes I get totally blank images or the image of the desktop (but the game is open)

    int screenWidth = Screen.GetBound s(new Point(0, 0)).Width;
    int screenHeight = Screen.GetBound s(new Point(0, 0)).Height;
    Bitmap bmpScreenShot = new Bitmap(screenWi dth, screenHeight);
    Graphics gfx = Graphics.FromIm age((Image)bmpS creenShot);
    gfx.CopyFromScr een(0, 0, 0, 0, new Size(screenWidt h, screenHeight));
    bmpScreenShot.S ave("test.jpg", ImageFormat.Jpe g);

    There is actually no problem on XP, sometimes on Vista I get blank screen and on Windows 7 I get the view of desktop all the time but the game is on foreground. I see the game as a little black box at upper left corner on Windows 7.



    I really need help.

    Thanks.
  • tlhintoq
    Recognized Expert Specialist
    • Mar 2008
    • 3532

    #2
    Do you just need screen shots?
    Or do you need to take screen shots from within your own application?
    It may just be easier to use something like "SnagIt" which can take shots of DirectX applications - than to re-invent the wheel

    Comment

    • SimpleData
      New Member
      • Jul 2009
      • 10

      #3
      Originally posted by tlhintoq
      Do you just need screen shots?
      Or do you need to take screen shots from within your own application?
      It may just be easier to use something like "SnagIt" which can take shots of DirectX applications - than to re-invent the wheel
      I need my application to take screenshots from DirectX applications.

      Comment

      • tlhintoq
        Recognized Expert Specialist
        • Mar 2008
        • 3532

        #4
        There is actually no problem on XP, sometimes on Vista I get blank screen and on Windows 7 I get the view of desktop all the time but the game is on foreground.
        You need to dig into how DirectX actually works. It doesn't draw to the screen memory. That's why you are capturing the desktop, because the desktop is what is in Windows and in that memory space.

        DirectX makes use of the video card memory and hardware acceleration.

        In short, you need to learn about DirectX before you are going to be able to capture it.

        Comment

        • SimpleData
          New Member
          • Jul 2009
          • 10

          #5
          Originally posted by tlhintoq
          You need to dig into how DirectX actually works. It doesn't draw to the screen memory. That's why you are capturing the desktop, because the desktop is what is in Windows and in that memory space.

          DirectX makes use of the video card memory and hardware acceleration.

          In short, you need to learn about DirectX before you are going to be able to capture it.
          Thank you for your answer first of all. I still don't understand why it was ok when I was on XP and Vista. On Vista I sometimes got black screen but on Win7 I just got desktop.

          I will look into how DirectX works but I really don't have any idea how to capture from an external DirectX application. Isn't there a simple code just to take screenshot from DX apps? Because I won't need to do anything with DX in future.

          Is this the thing I am looking for?

          Comment

          • RedSon
            Recognized Expert Expert
            • Jan 2007
            • 4980

            #6
            That link looks good. Have you tried it?

            Comment

            • SimpleData
              New Member
              • Jul 2009
              • 10

              #7
              Originally posted by RedSon
              That link looks good. Have you tried it?
              I didn't actually understood how to use it? What's the device and how can I set it according to the DX app I want to capture from.

              Comment

              • GaryTexmo
                Recognized Expert Top Contributor
                • Jul 2009
                • 1501

                #8
                I only know a bit of XNA, but the device is usually a reference to an object that interacts with the graphics device. In XNA it comes as a member variable to the main Game class... perhaps it's similar for DirectX?

                I don't know how similar they are though.

                Comment

                • SimpleData
                  New Member
                  • Jul 2009
                  • 10

                  #9
                  Originally posted by GaryTexmo
                  I only know a bit of XNA, but the device is usually a reference to an object that interacts with the graphics device. In XNA it comes as a member variable to the main Game class... perhaps it's similar for DirectX?

                  I don't know how similar they are though.
                  Thanks for your help but of course device doesn't exist in my application because I am not taking screenshot of my own DX app. I am taking screenshots from an external DX app.

                  Comment

                  • SimpleData
                    New Member
                    • Jul 2009
                    • 10

                    #10
                    I have successfully managed to compile this code but now when I run this code I get "Attempted to read or write protected memory. This is often an indication that other memory is corrupt." I think capturing from an external application is not possible with this method. I think I need another method.

                    Process[] procs = Process.GetProc essesByName("TH E APP I WANT TO CAPTURE FROM");
                    IntPtr hWnd = IntPtr.Zero;

                    foreach (Process prc in procs)
                    {
                    if (prc.MainWindow Handle != IntPtr.Zero)
                    {
                    hWnd = prc.MainWindowH andle;
                    break;
                    }
                    }

                    Device device = new Device(hWnd);

                    Surface backbuffer = device.GetBackB uffer(0, 0, BackBufferType. Mono);
                    SurfaceLoader.S ave("Screenshot .bmp", ImageFileFormat .Bmp, backbuffer);
                    backbuffer.Disp ose();

                    Comment

                    • GaryTexmo
                      Recognized Expert Top Contributor
                      • Jul 2009
                      • 1501

                      #11
                      Does this article help?

                      Comment

                      • SimpleData
                        New Member
                        • Jul 2009
                        • 10

                        #12
                        Originally posted by GaryTexmo
                        Nope, still the same black screen or the view of desktop.

                        Comment

                        • SimpleData
                          New Member
                          • Jul 2009
                          • 10

                          #13
                          When I disable Aero with this method I can take screenshots successfully. But is there any way of doing this without disabling aero?

                          public readonly uint DWM_EC_DISABLEC OMPOSITION = 0;
                          public readonly uint DWM_EC_ENABLECO MPOSITION = 1;
                          [DllImport("dwma pi.dll", EntryPoint = "DwmEnableCompo sition")]
                          protected static extern uint Win32DwmEnableC omposition(uint uCompositionAct ion);

                          public void Aero(bool a)
                          {
                          if (a)
                          Win32DwmEnableC omposition(DWM_ EC_ENABLECOMPOS ITION);
                          if (!a)
                          Win32DwmEnableC omposition(DWM_ EC_DISABLECOMPO SITION);
                          }

                          Comment

                          • v8maro
                            New Member
                            • Aug 2009
                            • 2

                            #14
                            I have the exact same issue and I cannot figure it out. Could you post the full code you got working in vista with aero off?

                            Comment

                            • SimpleData
                              New Member
                              • Jul 2009
                              • 10

                              #15
                              Sure.

                              Just add using System.Runtime. InteropServices to your usings and add this to your code.

                              public readonly uint DWM_EC_DISABLEC OMPOSITION = 0;
                              public readonly uint DWM_EC_ENABLECO MPOSITION = 1;
                              [DllImport("dwma pi.dll", EntryPoint = "DwmEnableCompo sition")]
                              protected static extern uint Win32DwmEnableC omposition(uint uCompositionAct ion);

                              public void ManageAero(bool a)
                              {
                              if (a)
                              Win32DwmEnableC omposition(DWM_ EC_ENABLECOMPOS ITION );
                              if (!a)
                              Win32DwmEnableC omposition(DWM_ EC_DISABLECOMPO SITIO N);
                              }

                              ManageAero(true ) enables aero and ManageAero(fals e) disables it.

                              You may want to use ManageAero(true or false) in a try/catch block because when you are on XP or a prior Windows which doesnt have Desktop Window Manager it throws and exception.

                              Comment

                              Working...