有没有办法在 C# 中制作屏幕录像机?如果是这样,是否有人知道我可以使用的任何教程或有关该主题的任何信息?
问问题
9622 次
4 回答
3
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
于 2009-09-29T03:05:36.153 回答
3
我从 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();
}
}
}
这些是我必须添加的参考:
于 2011-06-20T17:31:51.167 回答
1
对于线程异常,您可以使用此代码避免这种情况
public static void Stop()
{
flag = false;
snap.Join();
}
并将标志作为静态私有布尔(全局)并将其而不是真正的值放在 while 循环中:
while(flag)
那如何避免资源上的线程重叠。我知道这不是主题,但我想分享这条信息,因为线程总是让调试变得讨厌。
问候,法瓦兹
于 2012-12-10T19:12:28.927 回答
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;
}
}
于 2020-04-19T14:23:14.000 回答