2009-04-13 2 views
6

Мне нужно сделать распечатки экрана приложения Windows очень быстро, чтобы сделать видео из него ... Я использую C# полностью, но я открыт для любого языка, на котором этот процесс может Быстрее.Самый быстрый способ поймать экран? Любой язык

я использовал много методов:

  • функции .net: Bitmap.CopyFromScreen()
  • GDI
  • Direct3d/DirectX

Самый быстрый у меня был с помощью GDI и все же я получаю менее 10 фотограмм в секунду. Мне понадобилось бы немного больше, по крайней мере, 20 или 30 ...

Мне кажется очень странным, что такая простая операция настолько требовательна. И похоже, что использование более быстрого процессора не меняет ситуацию.

Что я могу сделать? Можно ли напрямую захватить чертеж приложения с помощью gdi или что-то еще? Или, может быть, даже функции нижнего уровня, чтобы поймать информацию, которую бросают на видеокарту?

Любой свет по этому вопросу будет в значительной степени оценен. Большое спасибо

+0

Действительно ли это «фотограмма»? – bzlm

+0

Есть много приложений, которые делают это красиво. Вы действительно хотите изобрести колесо? –

+1

Давайте посмотрим ... это сайт «полезных приложений» или сайт для вопросов программирования? Это один из них, но я все время забываю. – bzlm

ответ

1

Многие программы используют драйвер и позволяют вашему приложению подключаться к нижестоящим меню. Я не совсем уверен, как это делается, но это возможно. Вот отправная точка при написании драйвера Windows. http://msdn.microsoft.com/en-us/library/ms809956.aspx

Вот то, что я только что нашел с помощью Google: http://www.hmelyoff.com/index.php?section=17

+0

Почему я проголосовал? –

+0

Ах, вечный вопрос. – bzlm

+1

Ссылка Google мертва. Это поможет сделать выдержку для таких случаев. – JYelton

1

Вы, вероятно, хотите использовать что-то вроде Camtasia. Зависит от того, почему вы делаете видео.

Я использую перезаписанную версию Jeff's User-Friendly Exception Handling, и он использует BitBlt из GDI для захвата скриншотов. Кажется достаточно быстрым для меня, но я не тестировал его, и мы просто используем его для однократных выстрелов, когда возникает необработанное исключение.

#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

Крис, решение gdi, которое я сделал, очень похож на тот, который вы опубликовали, но поскольку у него есть некоторые отличия, я решил попробовать его. Однако он не распознает функции «GetDC», «BiBlt» и «ReleaseDC». Эти функции написаны вами? Не могли бы вы предоставить мне их? – 2009-04-13 15:49:05

+0

Эти функции называются атрибутами DllImport. Я считаю, что они должны автоматически ссылаться на gdi32.dll и user32.dll. –

Смежные вопросы