2009-04-13 13 views
6

Necesito tomar las pantallas de impresión de una aplicación de Windows muy rápido para hacer un video de eso ... He estado usando C# todo el camino, pero estoy abierto a cualquier idioma en el que este proceso pueda se más rápido.¿La forma más rápida de ver la pantalla? Cualquier idioma

He utilizado muchas técnicas:

  • funciones .net: Bitmap.CopyFromScreen()
  • GDI
  • Direct3d/DirectX

El más rápido Tengo que estaba usando GDI y aún obtengo menos de 10 fotogramos por segundo. Necesitaría un poco más que eso, al menos 20 o 30 ...

Me parece muy extraño que una operación tan simple sea tan exigente. Y parece que usar una CPU más rápida no cambia la situación.

¿Qué puedo hacer? ¿Es posible capturar directamente el dibujo de una aplicación usando gdi o algo así? ¿O tal vez incluso funciones de nivel inferior para captar la información que se envía a la tarjeta gráfica?

Cualquier luz sobre este tema sería muy apreciada. Muchas gracias

+0

¿Es "fotograma" una palabra real? – bzlm

+0

Hay muchas aplicaciones que hacen esto maravillosamente. ¿Estás seguro de que quieres reinventar la rueda? –

+1

Veamos ... ¿es este un sitio de "aplicaciones útiles" o un sitio de preguntas de programación? Es uno de ellos, pero sigo olvidando cuál. – bzlm

Respuesta

1

Una gran cantidad de programas utilizan un conductor y permite su aplicación para enganchar en las rutinas de visualización de nivel inferior. No estoy exactamente seguro de cómo se hace esto, pero es posible. Aquí hay un punto de partida para escribir el controlador de Windows. http://msdn.microsoft.com/en-us/library/ms809956.aspx

Aquí es algo que acabo de encontrar a través de Google: http://www.hmelyoff.com/index.php?section=17

+0

¿Por qué me votaron abajo? –

+0

Ah, la eterna pregunta. – bzlm

+1

El enlace de Google está muerto. Ayudaría tener un extracto para tales ocasiones. – JYelton

1

Es posible que desee usar algo como Camtasia. Depende de por qué estás haciendo el video.

Utilizo una versión reescrita de User-Friendly Exception Handling de Jeff, y él usa BitBlt de GDI para capturar capturas de pantalla. Parece lo suficientemente rápido para mí, pero no lo he comparado, y lo usamos para tomas de una en una cuando hay una excepción no controlada.

#region Win32 API screenshot calls 

// Win32 API calls necessary to support screen capture 
[DllImport("gdi32", EntryPoint = "BitBlt", CharSet = CharSet.Ansi, SetLastError = true, ExactSpelling = true)] 
private static extern int BitBlt(int hDestDC, int x, int y, int nWidth, int nHeight, int hSrcDC, int xSrc, 
           int ySrc, int dwRop); 

[DllImport("user32", EntryPoint = "GetDC", CharSet = CharSet.Ansi, SetLastError = true, ExactSpelling = true)] 
private static extern int GetDC(int hwnd); 

[DllImport("user32", EntryPoint = "ReleaseDC", CharSet = CharSet.Ansi, SetLastError = true, ExactSpelling = true)] 
private static extern int ReleaseDC(int hwnd, int hdc); 

#endregion 

private static ImageFormat screenshotImageFormat = ImageFormat.Png; 

/// <summary> 
/// Takes a screenshot of the desktop and saves to filename and format specified 
/// </summary> 
/// <param name="fileName"></param> 
private static void TakeScreenshotPrivate(string fileName) 
{ 
    Rectangle r = Screen.PrimaryScreen.Bounds; 

    using (Bitmap bitmap = new Bitmap(r.Right, r.Bottom)) 
    { 
     const int SRCCOPY = 13369376; 

     using (Graphics g = Graphics.FromImage(bitmap)) 
     { 
      // Get a device context to the windows desktop and our destination bitmaps 
      int hdcSrc = GetDC(0); 
      IntPtr hdcDest = g.GetHdc(); 

      // Copy what is on the desktop to the bitmap 
      BitBlt(hdcDest.ToInt32(), 0, 0, r.Right, r.Bottom, hdcSrc, 0, 0, SRCCOPY); 

      // Release device contexts 
      g.ReleaseHdc(hdcDest); 
      ReleaseDC(0, hdcSrc); 

      string formatExtension = screenshotImageFormat.ToString().ToLower(); 
      string expectedExtension = string.Format(".{0}", formatExtension); 

      if (Path.GetExtension(fileName) != expectedExtension) 
      { 
       fileName += expectedExtension; 
      } 

      switch (formatExtension) 
      { 
       case "jpeg": 
        BitmapToJPEG(bitmap, fileName, 80); 
        break; 
       default: 
        bitmap.Save(fileName, screenshotImageFormat); 
        break; 
      } 

      // Save the complete path/filename of the screenshot for possible later use 
      ScreenshotFullPath = fileName; 
     } 
    } 
} 

/// <summary> 
/// Save bitmap object to JPEG of specified quality level 
/// </summary> 
/// <param name="bitmap"></param> 
/// <param name="fileName"></param> 
/// <param name="compression"></param> 
private static void BitmapToJPEG(Image bitmap, string fileName, long compression) 
{ 
    EncoderParameters encoderParameters = new EncoderParameters(1); 
    ImageCodecInfo codecInfo = GetEncoderInfo("image/jpeg"); 

    encoderParameters.Param[0] = new EncoderParameter(Encoder.Quality, compression); 
    bitmap.Save(fileName, codecInfo, encoderParameters); 
} 
+0

Chris, la solución de gdi que hice es muy similar a la que publicaste, pero como tiene algunas diferencias, decidí probarla. Sin embargo, no reconoce las funciones "GetDC", "BiBlt" y "ReleaseDC". Son estas funciones escritas por usted? ¿Podrías proporcionarme con ellos? –

+0

Esas funciones son las que se mencionan en los atributos DllImport. Creo que deberían hacer referencia gdi32.dll y user32.dll automáticamente. –

Cuestiones relacionadas