【C#】【源码】直接可用的远程桌面应用

【背景】

封闭环境无法拷贝外来的远程桌面软件,所以就直接自己用C#写一个。

【效果】

【说明】

本篇会给出完整的编程步骤,照着写就能拥有你自己的远程桌面应用,直接可以运行在局域网。

如果不想自己敲代码,也可以选择直接下载项目资源,解包后直接用VS2019打开即可运行或自行打包成exe:

https://download.csdn.net/download/weixin_41697242/88350078

【设计】

远程桌面需要一个服务端,一个客户端,各自是一个项目文件。

本项目中客户端分享画面(发送截屏数据流),服务端则是监听并接收画面,因此服务端需要两个Form(窗体)。

【项目源码】

客户端UI

只需要一个Form1,布局如下:

具体组件和属性设置如下:

Label1,text改为IP即可;

Label2,text改为Port即可;

textbox1,名称改为txtIP;

textbox2,名称改为txtPort,text改为80

button1,text改为Connect,名称改为btnConnect

button2,text改为ShareScreen,名称改为btnShare

客户端源码

csharp 复制代码
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

using System.Net.Sockets;
using System.Drawing.Imaging;
using System.Runtime.Serialization.Formatters.Binary;

namespace OriginalClient
{
    public partial class Form1 : Form
    {
        private readonly TcpClient client = new TcpClient();
        private NetworkStream mainStream;
        private int portNumber;

        private static Image GrabDesktop()
        {
            Rectangle bound = Screen.PrimaryScreen.Bounds;
            Bitmap screenshot = new Bitmap(bound.Width, bound.Height, PixelFormat.Format32bppArgb);
            Graphics graphics = Graphics.FromImage(screenshot);
            graphics.CopyFromScreen(bound.X, bound.Y, 0, 0, bound.Size, CopyPixelOperation.SourceCopy);

            return screenshot;
        }

        private void SendDesktopImage()
        {
            BinaryFormatter binFormatter = new BinaryFormatter();
            mainStream = client.GetStream();
            binFormatter.Serialize(mainStream, GrabDesktop());
        }

        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            btnShare.Enabled = false;

        }

        private void btnConnect_Click(object sender, EventArgs e)
        {
            portNumber = int.Parse(txtPort.Text);
            try
            {
                client.Connect(txtIP.Text, portNumber);
                btnConnect.Text = "Connected";
                MessageBox.Show("Connected");
                btnConnect.Enabled = false;
                btnShare.Enabled = true;
            }
            catch (Exception)
            {
                MessageBox.Show("Failed to connect");
                btnConnect.Text = "Not Connected";
            }
        }

        private void btnShare_Click(object sender, EventArgs e)
        {
            if (btnShare.Text.StartsWith("Share"))
            {
                timer1.Start();
                btnShare.Text = "Stop Sharing";
            }
            else 
            {
                timer1.Stop();
                btnShare.Text = "Share My Screen";
            }
        }

        private void timer1_Tick(object sender, EventArgs e)
        {
            SendDesktopImage();
        }
    }
}

服务端UI

Form1

textBox1,name设置为txtPort

button1,name设置为btnListen

Form1代码
csharp 复制代码
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

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

        private void Form1_Load(object sender, EventArgs e)
        {

        }

        private void btnListen_Click(object sender, EventArgs e)
        {
            new Form2(int.Parse(txtPort.Text)).Show();
            btnListen.Enabled = false;
        }
    }
}
Form2

源项目中追加一个窗体。

一个窗体里放一个imageBox,mode设置为zoom,dock设置为停靠。

Form2源码
csharp 复制代码
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

using System.Net.Sockets;
using System.Net;
using System.Threading;
using System.Runtime.Serialization.Formatters.Binary;

namespace OriginalServer
{
    public partial class Form2 : Form
    {
        private readonly int port;
        private TcpClient client;
        private TcpListener server;
        private NetworkStream mainStream;

        private readonly Thread Listening;
        private readonly Thread GetImage;

        public Form2(int Port)
        {
            port = Port;
            client = new TcpClient();
            Listening = new Thread(StartListening);
            GetImage = new Thread(Receiveimage);


            InitializeComponent();
        }

        private void StartListening()
        {
            while (!client.Connected) 
            {
                server.Start();
                client = server.AcceptTcpClient();
            }
            GetImage.Start();
        }

        private void StopListening() 
        {
            server.Stop();
            client = null;
            if (Listening.IsAlive) Listening.Abort();
            if (GetImage.IsAlive) Listening.Abort();
        }

        private void Receiveimage()
        {
            BinaryFormatter binFormatter = new BinaryFormatter();
            while (client.Connected) 
            {
                mainStream = client.GetStream();
                pictureBox1.Image = (Image)binFormatter.Deserialize(mainStream);
            }
        }

        protected override void OnLoad(EventArgs e)
        {
            base.OnLoad(e);
            server = new TcpListener(IPAddress.Any, port);
            Listening.Start();
        }

        protected override void OnFormClosing(FormClosingEventArgs e)
        {
            base.OnFormClosing(e);
            StopListening();
        }

        private void pictureBox1_Click(object sender, EventArgs e)
        {

        }

        private void Form2_Load(object sender, EventArgs e)
        {

        }
    }
}
相关推荐
兔兔兔兔11 分钟前
记录C++ 13
开发语言·c++·算法
码行山野赴时序归途6 分钟前
从暴力到最优:三道 C 语言入门题的解法思路
c语言·开发语言·数据结构·算法·leetcode·排序算法
郑州光合科技余经理32 分钟前
本地生活平台搭建:统一订单表与多后台切换怎么拆
java·开发语言·前端·系统架构·uni-app·php·ai编程
天下无敌笨笨熊37 分钟前
C#视频开发心得
开发语言·c#·音视频
LccKyI1 小时前
C#基础编程 面试题汇总(三)
笔记·c#
淼澄研学1 小时前
基于Docker与iptables的AI智能体网络隔离实操指南
开发语言·python
莫陌尛.1 小时前
Java核心知识点:直接内存、CPU密集型线程池、并行流对比文档
java·开发语言
西峰u1 小时前
Java多线程初阶完整总结|线程、锁、volatile、等待通知、常见案例
java·开发语言·jvm
夜雨声烦丿2 小时前
从需求到页面:日期计算器应用的 ArkTS 原生实现
开发语言·javascript·华为·harmonyos
程序员雪球2 小时前
本地IDEA打断点debug容器
java·开发语言