简单的C#屏幕共享应用程序

17

我想要在C#中创建一个非常基本的屏幕分享应用程序,不需要远程控制。 我只希望用户能够将他们的屏幕广播到 Web 服务器。

我该如何实现?(任何指向正确方向的指针都将不胜感激)。

不需要高帧率,每5秒更新一次会足够。您认为仅上传每5秒钟的屏幕截图是否足够?


6
不是我所说的“简单”。 - Stephen Cleary
是的,你可以打电话 :) - Noman Ahmad
5个回答

18

我之前发表过一篇关于远程屏幕共享软件如何工作的博客文章,虽然不是针对C#的,但它可以给你关于这个主题的基本理解。该文章还链接了远程帧缓冲规范,你也可能想要阅读。

基本上你需要截屏,并将这些截图传输并在另一端显示。你可以保留最后一个屏幕截图,并按块比较截图以查看需要发送哪些块的屏幕截图。在发送数据之前,通常会进行某种形式的压缩。

为了实现远程控制,你可以跟踪鼠标移动并传输它,并在另一端设置指针位置。同样,键盘输入也是如此。

至于在C#中进行压缩,你可以简单地使用JpegBitmapEncoder来创建具有所需质量的JPEG压缩的屏幕截图。

JpegBitmapEncoder encoder = new JpegBitmapEncoder();
encoder.QualityLevel = 40; 

如果您想比较文件块,最好在旧块和新块上创建哈希,然后检查它们是否相同。您可以使用任何哈希算法来完成此操作。


太棒了!我应该查看哪些内容来比较这些屏幕截图,还有我需要关注什么类型的压缩? - Andy Hin
远程屏幕链接无法使用,它已经失效了。 - motevalizadeh
https://brianbondy.com/blog/87/how-vnc-fog-creek-copilot-and-other-remote-control-software-works - Diego Vieira

3
这里是获取屏幕截图的代码,以位图形式未压缩:
    public static Bitmap TakeScreenshot() {
        Rectangle totalSize = Rectangle.Empty;

        foreach (Screen s in Screen.AllScreens)
            totalSize = Rectangle.Union(totalSize, s.Bounds);

        Bitmap screenShotBMP = new Bitmap(totalSize.Width, totalSize.Height, PixelFormat.
            Format32bppArgb);

        Graphics screenShotGraphics = Graphics.FromImage(screenShotBMP);

        screenShotGraphics.CopyFromScreen(totalSize.X, totalSize.Y, 0, 0, totalSize.Size,
            CopyPixelOperation.SourceCopy);

        screenShotGraphics.Dispose();

        return screenShotBMP;
    }

现在只需压缩它并通过网络发送,你就完成了。

此代码将多屏设置中的所有屏幕合并为一张图像。根据需要进行调整。


2

2

那么,它可以很简单,只需截取屏幕截图,压缩它们,然后通过网络发送。但是,已经存在可以完成此操作的软件。这是为了练习吗?


1
屏幕共享/复制的关键组件是一个名为RPDViewer的COM组件。 输入图像描述 将该COM组件添加到您的窗体和引用中。 然后在窗体加载时添加以下代码,即可在您的窗体中复制屏幕:

enter image description here

using RDPCOMAPILib;
using System;
using System.Windows.Forms;

namespace screenSharingAttempt
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        RDPSession x = new RDPSession(); 
        private void Incoming(object Guest)
        {
            IRDPSRAPIAttendee MyGuest = (IRDPSRAPIAttendee)Guest; 
            MyGuest.ControlLevel = CTRL_LEVEL.CTRL_LEVEL_INTERACTIVE;
        }


        //access to COM/firewall will prompt 
        private void button1_Click(object sender, EventArgs e)
        {
            x.OnAttendeeConnected += Incoming;
            x.Open();
        }

        //connect
        private void button2_Click(object sender, EventArgs e)
        {
            IRDPSRAPIInvitation Invitation = x.Invitations.CreateInvitation("Trial", "MyGroup", "", 10);
            textBox1.Text = Invitation.ConnectionString;
        }

        //Share screen

        private void button4_Click(object sender, EventArgs e)
        {
            string Invitation = textBox1.Text;// "";// Interaction.InputBox("Insert Invitation ConnectionString", "Attention");
            axRDPViewer1.Connect(Invitation, "User1", "");
        }


        //stop sharing
        private void button5_Click(object sender, EventArgs e)
        {
            axRDPViewer1.Disconnect();
        }
    }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接