有没有办法用C#制作屏幕录像机?如果是的话,是否有人知道我可以使用的任何教程或有关该主题的任何信息?
答案 0 :(得分: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
答案 1 :(得分:1)
我从Lucas McCoy那里获取了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();
}
}
}
这些是我必须添加的参考:
答案 2 :(得分:1)
对于Thread Exception,您可以使用此代码
来避免这种情况 public static void Stop()
{
flag = false;
snap.Join();
}
并将标志作为静态私有bool(全局)并将其放入while循环中而不是true值:
while(flag)
如何避免线程重叠资源。我知道这不是主题,但我想分享这条信息因为线程总是让调试变得讨厌。
此致 法瓦兹
答案 3 :(得分:0)
我使用了Parox代码并对其进行了修复,以减少错误,并更适合C#语言编译器。
我作为C#程序员可以说的话,代码抛出错误并不奇怪。某些部分甚至可能导致堆栈溢出或杀死应用程序异常-但这就是我们参与此问答的领域;)
长时间录制仍然会导致Counter
溢出并覆盖从录制的最初几秒钟开始的PNG,可能还有其他问题,但我认为最好将其附加到线程中以供其他人使用:
public class ScreenRecorder
{
// C:\Users\sebas.000\AppData\Local\Temp\snapshot
private static string tempSnapshotDir = Path.GetTempPath() + "snapshot\\";
private static Thread snapThread = new Thread(Snapshot);
private static bool flag = false;
private static Rectangle _Bounds = Screen.PrimaryScreen.Bounds;
public static Rectangle Bounds
{
get { return _Bounds; }
set { _Bounds = value; }
}
private static void Snapshot()
{
ClearRecording();
using (var memoryBitmap = new Bitmap(_Bounds.Width, _Bounds.Height, Imaging.PixelFormat.Format32bppArgb))
using (var graphSurface = Graphics.FromImage(memoryBitmap))
{
//var currentBounds = new Rectangle();
var Counter = (UInt64)0;
var freshPoint = new System.Drawing.Point();
flag = true;
do
{
Thread.Sleep(100);
graphSurface.CopyFromScreen(_Bounds.Location, freshPoint, _Bounds.Size);
// add cursor
//currentBounds.Size = Cursor.Current.Size;
//currentBounds.Location = System.Drawing.Point.Subtract(Cursor.Position, Bounds.Size);
//Cursors.Default.Draw(graphSurface, currentBounds);
Counter++;
var fileName = FormatFileName(Counter.ToString(), 6, '0', ".png");
using (var FS = new FileStream(string.Concat(tempSnapshotDir, fileName), FileMode.Create, FileAccess.Write))
{
memoryBitmap.Save(FS, ImageFormat.Png);
}
} while (flag);
}
}
private static void ClearRecording()
{
if (Directory.Exists(tempSnapshotDir))
Directory.Delete(tempSnapshotDir, true);
Directory.CreateDirectory(tempSnapshotDir);
}
public static void StartRecording()
{
//snapThread = new Thread(Snapshot);
snapThread.Start();
}
public static void StopRecording()
{
flag = false;
snapThread.Join();
}
public static void Save(string outpuFinlename)
{
var gifBitmapEncoder = new GifBitmapEncoder();
var fileStreamList = new List<FileStream>();
// encode GIF from PNGs
foreach (string pngFile in Directory.GetFiles(tempSnapshotDir, "*.png", SearchOption.TopDirectoryOnly)) // efficiency !!! create list like Counter !!!
{
var tempStream = new FileStream(pngFile, FileMode.Open);
var bitmapFrame = BitmapFrame.Create(tempStream);
fileStreamList.Add(tempStream);
gifBitmapEncoder.Frames.Add(bitmapFrame);
}
// save GIF to disk
using (var fileStream = new FileStream(outpuFinlename, FileMode.Create, FileAccess.Write))
{
gifBitmapEncoder.Save(fileStream);
}
fileStreamList.Clear();
ClearRecording();
}
private static string FormatFileName(string S, int places, char character, string extension)
{
if (S.Length >= places)
return S;
return S.PadLeft(places, '0') + extension;
}
}