2009-04-13 9 views
6

Ho bisogno di prendere le schermate di stampa di un'applicazione Windows molto velocemente per farne un video ... Ho usato C# fino in fondo, ma sono aperto a qualsiasi lingua in cui questo processo possa essere più veloceIl modo più veloce per catturare lo schermo? Any Language

Ho usato molte tecniche:

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

Il più veloce che ho stava usando GDI e ancora ottengo meno di 10 fotogrammi al secondo. Avrei bisogno di un po 'di più, almeno 20 o 30 ...

Mi sembra molto strano che un'operazione così semplice sia così impegnativa. E sembra che usare una CPU più veloce non cambi la situazione.

Cosa posso fare? È possibile catturare direttamente il disegno di un'applicazione usando gdi o qualcosa del genere? O forse anche funzioni di livello inferiore per catturare le informazioni che vengono lanciate sulla scheda grafica?

Qualsiasi luce su questo argomento sarebbe molto apprezzata. Grazie mille

+0

"fotogramma" è una parola effettiva? – bzlm

+0

Ci sono molte molte app che lo fanno magnificamente. Sei sicuro di voler reinventare la ruota? –

+1

Vediamo ... questo è un sito di "app utili" o un sito di domande di programmazione? È uno di loro, ma continuo a dimenticare quale. – bzlm

risposta

1

Molti programmi utilizzano un driver e consentono all'applicazione di collegarsi alle routine di visualizzazione di livello inferiore. Non sono esattamente sicuro di come sia fatto, ma è possibile. Ecco un punto di partenza per scrivere il driver di Windows. http://msdn.microsoft.com/en-us/library/ms809956.aspx

Ecco qualcosa che ho appena trovato tramite Google: http://www.hmelyoff.com/index.php?section=17

+0

Perché sono stato votato? –

+0

Ah, l'eterna domanda. – bzlm

+1

Il collegamento Google è morto. Sarebbe utile avere un estratto, per tali occasioni. – JYelton

1

Probabilmente si desidera usare qualcosa come Camtasia. Dipende dal motivo per cui stai realizzando il video.

Uso una versione riscritta di Jeff's User-Friendly Exception Handling e utilizza BitBlt da GDI per acquisire schermate. Sembra abbastanza veloce per me, ma non l'ho confrontato, e lo usiamo solo per scatti singoli quando c'è un'eccezione non gestita lanciata.

#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 soluzione GDI che ho fatto è molto simile a quella che hai postato, ma dal momento che ha alcune differenze ho deciso di provarlo. Tuttavia, non riconosce le funzioni "GetDC", "BiBlt" e "ReleaseDC". Queste funzioni sono scritte da te? Potresti fornirmi con loro? –

+0

Queste funzioni sono quelle a cui fanno riferimento gli attributi DllImport. Credo che quelli dovrebbero fare riferimento gdi32.dll e user32.dll automaticamente. –

Problemi correlati