2009-09-29 97 views
6

有沒有辦法在C#中製作屏幕錄像機?如果是這樣,是否有人知道我可以使用的任何教程或有關該主題的任何信息?如何在.NET中編寫屏幕錄像機?

+0

我敢打賭,你可以做這一樣一個VB.NET屏幕錄像機。 – 2009-09-29 02:57:43

+1

@John Saunders - 你有一個關於這將如何完成或鏈接到教程等的想法? – user 2009-09-29 03:01:50

+0

是的。就像使用VB.NET或任何其他.NET語言一樣 - 它與C#無關。你可能真的知道,但你聽起來像你沒有。如果你實際上不是那麼無知,那麼我很抱歉。 – 2009-09-29 03:14:15

回答

3

Take a look at this VB.NET code.

Public Class ScreenRecorder 

Private Shared tempDir As String = My.Computer.FileSystem.SpecialDirectories.Temp & "snapshot" 
Private Shared snap As New System.Threading.Thread(AddressOf Snapshot) 
Private Shared _Bounds As System.Drawing.Rectangle = System.Windows.Forms.Screen.PrimaryScreen.Bounds 

Public Shared Property Bounds() As System.Drawing.Rectangle 
    Get 
     Return _Bounds 
    End Get 
    Set(ByVal value As System.Drawing.Rectangle) 
     _Bounds = value 
    End Set 
End Property 

Private Shared Sub Snapshot() 
    If Not My.Computer.FileSystem.DirectoryExists(tempDir) Then _ 
     My.Computer.FileSystem.CreateDirectory(tempDir) 
    Dim Co As Integer = 0 
    Do 
     Co += 1 
     System.Threading.Thread.Sleep(50) 
     Dim X As New System.Drawing.Bitmap(_Bounds.Width, _Bounds.Height, System.Drawing.Imaging.PixelFormat.Format32bppArgb) 
     Using G = System.Drawing.Graphics.FromImage(X) 
      G.CopyFromScreen(_Bounds.Location, New System.Drawing.Point(), _Bounds.Size) 
      Dim CurBounds As New System.Drawing.Rectangle(System.Windows.Forms.Cursor.Position - Bounds.Location, System.Windows.Forms.Cursor.Current.Size) 
      Forms.Cursors.Default.Draw(G, CurBounds) 
     End Using 
     Dim FS As New IO.FileStream(tempDir & FormatString(Co.ToString, 5, "0"c) & ".png", IO.FileMode.OpenOrCreate) 
     X.Save(FS, System.Drawing.Imaging.ImageFormat.Png) 
     X.Dispose() 
     FS.Close() 
    Loop 
End Sub 

Public Shared Sub ClearRecording() 
    If My.Computer.FileSystem.DirectoryExists(tempDir) Then _ 
    My.Computer.FileSystem.DeleteDirectory(tempDir, FileIO.DeleteDirectoryOption.DeleteAllContents) 
    My.Computer.FileSystem.CreateDirectory(tempDir) 
End Sub 

Public Shared Sub Save(ByVal Output As String) 
    Dim G As New Windows.Media.Imaging.GifBitmapEncoder 

    Dim X As New List(Of IO.FileStream) 
    For Each Fi As String In My.Computer.FileSystem.GetFiles(tempDir, FileIO.SearchOption.SearchTopLevelOnly, "*.png") 
     Dim TempStream As New IO.FileStream(Fi, IO.FileMode.Open) 
     Dim Frame = Imaging.BitmapFrame.Create(TempStream) 
     X.Add(TempStream) 
     G.Frames.Add(Frame) 
    Next 
    Dim FS As New IO.FileStream(Output, IO.FileMode.OpenOrCreate) 
    G.Save(FS) 
    FS.Close() 

    For Each St As IO.FileStream In X 
     St.Close() 

    Next 

End Sub 

Public Shared Sub Start() 
    snap = New System.Threading.Thread(AddressOf Snapshot) 
    snap.Start() 
End Sub 

Public Shared Sub [Stop]() 
    snap.Abort() 
End Sub 

Private Shared Function FormatString(ByVal S As String, ByVal places As Integer, ByVal character As Char) As String 
    If S.Length >= places Then Return S 
    For X As Integer = S.Length To places 
     S = character & S 
    Next 
    Return S 
End Function 

End Class 
+0

問題在於報價中的正斜槓。我不知道一個不會讓編輯混淆的VB.NET等價物,所以我把它留給你。 – 2009-09-29 03:17:23

+0

幾年前,我在C#中寫了一些非常類似的東西。表演很糟糕。我會對這種表現感興趣。 – 2009-09-29 03:20:06

+0

Thread.Sleep()警報! – MusiGenesis 2009-09-29 03:35:23

1

我把VB.net代碼盧卡斯麥考伊,把它變成C#。 這記錄5秒鐘並將gif保存到桌面。 PS:我有時會遇到錯誤,當最後的屏幕截圖仍然通過線程中止時,然後流嘗試讀取它。

非常慢的代碼。

using System; 
using System.Collections.Generic; 
using System.IO; 
using System.Drawing; 
using System.Drawing.Imaging; 


namespace ConsoleApplication1 
{ 

    public class ScreenRecorder 
    { 

     private static string tempDir = Path.GetTempPath() + "/snapshot/"; 
     private static System.Threading.Thread snap = new System.Threading.Thread(Snapshot); 

     private static System.Drawing.Rectangle _Bounds = System.Windows.Forms.Screen.PrimaryScreen.Bounds; 
     public static System.Drawing.Rectangle Bounds 
     { 
      get { return _Bounds; } 
      set { _Bounds = value; } 
     } 

     private static void Snapshot() 
     { 
      if (!Directory.Exists(tempDir)) 
       Directory.CreateDirectory(tempDir); 
      int Co = 0; 
      do 
      { 
       Co += 1; 
       System.Threading.Thread.Sleep(50); 
       System.Drawing.Bitmap X = new System.Drawing.Bitmap(_Bounds.Width, _Bounds.Height, System.Drawing.Imaging.PixelFormat.Format32bppArgb); 
       using(System.Drawing.Graphics G = System.Drawing.Graphics.FromImage(X)) { 
        G.CopyFromScreen(_Bounds.Location, new System.Drawing.Point(), _Bounds.Size); 
        System.Drawing.Rectangle CurBounds = new System.Drawing.Rectangle(System.Drawing.Point.Subtract(System.Windows.Forms.Cursor.Position,Bounds.Size), System.Windows.Forms.Cursor.Current.Size); 
        System.Windows.Forms.Cursors.Default.Draw(G, CurBounds); 
       } 
       System.IO.FileStream FS = new System.IO.FileStream(tempDir + FormatString(Co.ToString(), 5, '0') + ".png", System.IO.FileMode.OpenOrCreate); 
       X.Save(FS, System.Drawing.Imaging.ImageFormat.Png); 
       X.Dispose(); 
       FS.Close(); 
      } while (true); 
     } 

     public static void ClearRecording() 
     { 
      if (Directory.Exists(tempDir)) 
       Directory.Delete(tempDir, true); 
       Directory.CreateDirectory(tempDir); 
     } 

     public static void Save(string Output) 
     { 
      System.Windows.Media.Imaging.GifBitmapEncoder G = new System.Windows.Media.Imaging.GifBitmapEncoder(); 

      List<System.IO.FileStream> X = new List<System.IO.FileStream>(); 
      foreach (string Fi in Directory.GetFiles(tempDir, "*.png", SearchOption.TopDirectoryOnly)) 
      { 
       System.IO.FileStream TempStream = new System.IO.FileStream(Fi, System.IO.FileMode.Open); 
       System.Windows.Media.Imaging.BitmapFrame Frame = System.Windows.Media.Imaging.BitmapFrame.Create(TempStream); 
       X.Add(TempStream); 
       G.Frames.Add(Frame); 
      } 
      System.IO.FileStream FS = new System.IO.FileStream(Output, System.IO.FileMode.OpenOrCreate); 
      G.Save(FS); 
      FS.Close(); 

      foreach (System.IO.FileStream St in X) 
      { 
       St.Close(); 

      } 

     } 

     public static void Start() 
     { 
      snap = new System.Threading.Thread(Snapshot); 
      snap.Start(); 
     } 

     public static void Stop() 
     { 
      snap.Abort(); 
     } 

     private static string FormatString(string S, int places, char character) 
     { 
      if (S.Length >= places) 
       return S; 
      for (int X = S.Length; X <= places; X++) 
      { 
       S = character + S; 
      } 
      return S; 
     } 

    } 

    class Program 
    { 
     static void Main(string[] args) 
     { 
      ScreenRecorder.Start(); 
      System.Threading.Thread.Sleep(5000); 
      ScreenRecorder.Stop(); 
      ScreenRecorder.Save(Environment.GetFolderPath(Environment.SpecialFolder.Desktop) + "\\video.gif"); 
      ScreenRecorder.ClearRecording(); 
     } 
    } 
} 

這是引用我不得不添加:

enter image description here

1

對於線程異常,那麼就可以避免這種代碼

public static void Stop() 
    { 
     flag = false; 
     snap.Join(); 
    } 

,並把靜態的私人旗布爾(全局),並把它代替while循環中的真實值:

while(flag) 

您如何避免線程在資源上重疊。我知道這不是主題,但我想分享這塊信息,因爲線程總是使調試變得討厭。

問候, 法瓦茲

+0

謝謝你戴維的糾正 – Fawaz 2012-12-10 23:09:54