2009-04-13 17 views
6

Ich muss sehr schnell Druck-Bildschirme einer Windows-Anwendung nehmen, um ein Video daraus zu machen ... Ich habe C# den ganzen Weg benutzt, aber ich bin für jede Sprache offen, in der dieser Prozess möglicherweise sei schneller.Der schnellste Weg, um den Bildschirm zu fangen? Beliebige Sprache

ich verwendet habe viele Techniken:

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

Der schnellste ich habe wurde GDI und trotzdem bekomme ich weniger als 10 fotogramme pro sekunde. Ich würde ein bisschen mehr als das brauchen, mindestens 20 oder 30 ...

Es scheint mir sehr seltsam, dass solch eine einfache Operation so anspruchsvoll ist. Und es sieht so aus, als ob die Verwendung einer schnelleren CPU die Situation nicht ändert.

Was kann ich tun? Ist es möglich, die Zeichnung einer Anwendung direkt mit gdi oder so zu erfassen? Oder vielleicht sogar Funktionen auf niedrigerer Ebene, um die Informationen zu erfassen, die auf die Grafikkarte geworfen werden?

Jedes Licht zu diesem Thema würde sehr geschätzt werden. Vielen Dank

+0

Ist "fotogram" ein aktuelles Wort? – bzlm

+0

Es gibt viele viele Apps, die das wunderbar machen. Möchtest du das Rad wirklich neu erfinden? –

+1

Mal sehen ... ist das eine "nützliche Apps" -Seite oder eine Programmier-Frage-Seite? Es ist einer von ihnen, aber ich vergesse immer wieder was. – bzlm

Antwort

1

Viele Programme verwenden einen Treiber und ermöglicht es Ihrer Anwendung, in die unteren Ebenen der Routinen einzubinden. Ich bin mir nicht ganz sicher, wie das gemacht wird, aber es ist möglich. Hier ist ein Ausgangspunkt zum Schreiben von Windows-Treiber. http://msdn.microsoft.com/en-us/library/ms809956.aspx

Hier ist etwas, was ich nur über Google gefunden: http://www.hmelyoff.com/index.php?section=17

+0

Warum wurde ich abgelehnt? –

+0

Ah, die ewige Frage. – bzlm

+1

Google-Link ist tot. Es würde helfen, einen Auszug für solche Gelegenheiten zu haben. – JYelton

1

Sie wahrscheinlich so etwas wie Camtasia verwenden möchten. Kommt darauf an, warum du das Video machst.

Ich benutze eine neu geschriebene Version von Jeff User-Friendly Exception Handling, und er verwendet BitBlt von GDI, um Screenshots zu erfassen. Scheint schnell genug zu mir, aber ich habe es nicht bewertet, und wir verwenden es nur für einzelne Schüsse, wenn eine unbehandelte Ausnahme ausgelöst wird.

#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, die gdi-Lösung, die ich gemacht habe, ist der, die du gepostet hast, sehr ähnlich, aber da es einige Unterschiede gibt, habe ich beschlossen, es auszuprobieren. Es erkennt jedoch nicht die Funktionen "GetDC", "BiBlt" und "ReleaseDC". Sind diese Funktionen von Ihnen geschrieben? Könnten Sie mir diese zur Verfügung stellen? –

+0

Diese Funktionen werden von den DllImport-Attributen referenziert. Ich glaube, dass diese automatisch auf gdi32.dll und user32.dll verweisen sollten. –

Verwandte Themen