7
votes

Comment écrire un enregistreur d'écran dans .NET?

Y a-t-il un moyen de faire un enregistreur d'écran en C #? Si oui, quelqu'un connaît-il des tutoriels que je pourrais utiliser ou des informations sur le sujet?


5 commentaires

Je parie que vous pouvez le faire de la même manière qu'un enregistreur d'écran VB.NET.


@John Saunders - Avez-vous une idée sur la manière dont cela serait fait ou un lien vers un didacticiel, etc.?


Oui. Tout comme avec vb.net ou toute autre langue .NET - cela n'a rien à voir avec C #. Vous pouvez en réalité savoir que, mais vous semblez être comme vous ne le faites pas. Si vous n'êtes pas réellement ignorant, alors je m'excuse.


Je ne pense pas que vous ayez besoin de "gratte-écran" dans les balises. Le grattage de l'écran fait généralement référence à la sortie de texte d'une ou plusieurs commandes ou écrans dans une autre application.


@John Saunders - Je savais que cela s'appliquait à une langue .NET.


4 Réponses :


3
votes

Jetez un oeil à ce code VB.NET.

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


7 commentaires

Le problème était les barres obliques dans la citation. Je ne connais pas un équivalent vb.net qui ne confond pas l'éditeur, alors je vous laisse ça.


J'ai écrit quelque chose de très similaire dans C # sont de quelques années de retour. La performance était horrible. Je serais intéressé par la manière dont cela fonctionne.


@Jason Jackson - Toutes les chances que je puisse jeter un coup d'oeil au code juste pour avoir une idée?


Je ne pense pas que j'ai le code plus longtemps. Je l'ai écrit pour un employeur il y a environ 6 ans. Je suis sûr qu'il est toujours assis dans leur référentiel CVS, mais ces bits sont probablement longs de la mine. Pardon. Il a suivi le même concept de base: tir périodique coupé sur disque. Je me souviens d'avoir essayé de nombreuses façons de le faire en essayant de l'optimiser, mais ne vous rappelez pas les détails. Trop de code écrit entre alors et maintenant.


OK, eh bien je vais l'utiliser, converti-le sur c # (je préfère c # sur vb). J'espère que tout va bien. Merci.


Peut-être que vous pourriez poster la version C # sur CodEpex pour une utilisation future. Bonne chance!


Ce code a besoin de Nettoyage très sérieux et il suffit de ne pas être utilisé - il est apparu dans d'autres questions et a provoqué des problèmes: l'ouverture des flux sans utilisation, la méthode formatrine essaie de faire le Même chose que ce qu'est une simple chaîne.format avec un format "D8" uniquement de manière beaucoup plus lente et inutile. Écrire directement sur le bureau de l'utilisateur. Arrêtez un fil en appelant `thread.abort ', garantissant ainsi les flux non protégés restera ouverte.



3
votes

J'ai pris le code VB.NET de Lucas McCoy et l'a transformé en C #. Ces enregistrements pendant 5 secondes et enregistré le GIF sur le bureau. PS: Je reçois une erreur parfois lorsque la dernière capture d'écran a toujours abandonné via le thread, puis le flux tente de le lire.

code très lent. P>

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();
        }
    }
}


1 commentaires

Si quelqu'un aime utiliser le code, vérifiez ma réponse pour obtenir une solution de travail plus rapidement Ici



1
votes

Pour l'exception de thread, vous pouvez éviter cela avec ce code xxx pré>

et mettre le drapeau comme statique privé (global) et le mettre au lieu de la vraie valeur dans la boucle TOUT: P>

while(flag)


0 commentaires

0
votes

J'ai pris parox code et réparez-le pour être moins buggy et plus approprié pour les compilateurs de langue C #.

Ce que je peux dire en tant que programmeur C #, il n'est pas surprenant que le code jette des erreurs. Certaines parties pourraient même conduire à la pile débordent ou tuant les exceptions de l'application - mais c'est le domaine où nous sommes à ce Q & A;)

Encore long TIME L'enregistrement peut conduire à Overflow PNGS primordials pris à partir des premières secondes d'enregistrement et probablement d'autres problèmes, mais à mon avis, il est suffisamment vif pour être attaché dans le fil pour d'autres: xxx


0 commentaires