Форум программистов, компьютерный форум, киберфорум
C# .NET
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.80/40: Рейтинг темы: голосов - 40, средняя оценка - 4.80
0 / 0 / 0
Регистрация: 23.05.2016
Сообщений: 3

Передача скриншота рабочего стола с удаленного ПК по TCP

23.05.2016, 12:06. Показов 8230. Ответов 8
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Доброго дня всем! Пытаюсь написать для себя программу для удаленного доступа к ПК, используя протокол TCP. Застрял уже на первом этапе - пересылки скриншотов рабочего стола с удаленного ПК. Для этого клиентская часть в бесконечном цикле каждые 40 мс (25 кадров в секунду) отправляет размер пересылаемого сжатого скриншота, а потом сам скриншот:
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
using (FileStream fs = new FileStream("screenshot.gz", FileMode.Open))  //создаем файловый поток fs для чтения сжатого скриншота
                    {
                        using (BinaryReader br = new BinaryReader(fs))      //считываем в двоичный поток br из потока fs
                        {
                            int ReadedBytes;    //количество считанных байт
                            int len = (Int32)fs.Length;     //размер скриншота
                            byte[] length = Encoding.Unicode.GetBytes(len.ToString());      //переводим в байтовый массив размер скриншота
                            stream.Write(length, 0, length.Length);     //отправляем сначала размер скриншота
                            do
                            {
                                ReadedBytes = br.Read(buf, 0, buf.Length);      //считываем максимально возможно количество байт файла в массив buf и записываем количество считанных байт в переменную ReadedBytes
                                stream.Write(buf, 0, ReadedBytes);      //отправляем массив buf
                                len -= ReadedBytes;     //вычитаем из общего размера файла количество отправленных байт
                            } while (len != 0);     //повторяем до тех пор, пока не отправим весь файл "кусок" за "куском"
                        }
                    }
Серверная часть принимает также в бесконечном цикле сначала размер скриншота и затем сам скриншот:
C#
1
2
3
4
                    int ReceivedBytes = Stream.Read(ScreenLengthB, 0, ScreenLengthB.Length);    //считываем из потока в массив ScreenLengthB размер очередного скриншота и записываем в переменную ReceivedBytes количество прочитанных байт
                    int ScrLength = int.Parse(Encoding.Unicode.GetString(ScreenLengthB, 0, ReceivedBytes)); //преобразуем массив ScreenLengthB в число
                    //далее принимаем скриншот
                    ...
Ошибка возникает на этапе получения размера очередного скриншота (размер сжатого скриншота колеблется от 60 000 байт до 110 000 байт) - он почему-то через раз на несколько тысяч байт меньше реального. Причем, если я каждый раз пересылаю один и тот же заранее созданный скриншот, то размер всегда корректный.
Также оговорюсь, что:
1. Это лишь заготовка, поэтому подключение пока создается на localhost;
2. Предполагается множественное подключение, поэтому используется класс ClientObject (в будущем планирую список всех активных подключений держать в List'е).

Ниже прилагаю исходный код клиентской (которым будут управлять) и серверной (который будет управлять) частей.
Сервер:
Кликните здесь для просмотра всего текста

C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Drawing.Imaging;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.IO;
using System.Net;
using System.Net.Sockets;
using System.Runtime.Serialization.Formatters.Binary;
using LibraryTV;
 
namespace Server
{
    public partial class ServerTV : Form
    {
        TcpListener tcpListener;
        ClientObject clientObject;
        Thread Srv;
 
        public ServerTV()
        {
            InitializeComponent();
            Screen.Width = this.ClientSize.Width;   //устанавливаем размер pictureBox (имя Screen)
            Screen.Height = this.ClientSize.Height; //устанавливаем размер pictureBox (имя Screen)
            Screen.SizeMode = PictureBoxSizeMode.StretchImage;  //устанавливаем свойство pictureBox для увеличения/уменьшения изображения в нем по мере необходимости
            Srv = new Thread(new ThreadStart(Connect));     //создаем отдельный поток для метода Connect
            Srv.Start();    //запускаем созданный поток
        }
 
        private void Connect()
        {
            try
            {
                tcpListener = new TcpListener(IPAddress.Any, 50000);    //будем слушать 50000 порт и обрабатывать запросы с любого IP-адреса
                tcpListener.Start();
                while (true)
                {
                    TcpClient client = tcpListener.AcceptTcpClient();   //получаем входящее подключение
                    clientObject = new ClientObject(client, ref Screen);    //создаем объект класса clientObject и передаем ему по ссылке pictureBox и наш TcpClient
 
                    Thread clientThread = new Thread(new ThreadStart(clientObject.Process));    //создаем отдельный поток для метода Process созданного выше объекта
                    clientThread.Start();   //запускаем созданный поток
                }
            }
            catch (Exception ex)
            { MessageBox.Show(ex.Message); }
            finally
            { if (tcpListener != null) tcpListener.Stop(); }
        }
 
        private void ServerTV_FormClosing(object sender, FormClosingEventArgs e)
        {
            tcpListener.Stop();
            Srv.Abort();
        }
    }
 
    public class ClientObject
    {
        public TcpClient client;
        public PrintScreen Screen;
        private PictureBox PB;
        protected internal NetworkStream Stream { get; private set; }
 
        public ClientObject(TcpClient tcpClient, ref PictureBox PictB)      //конструктор класса
        {
            client = tcpClient;
            PB = PictB;
            Screen = new PrintScreen();     //объект класса, который будет создавать скриншоты и сжимать их
        }
 
        public void Process()
        {
            try
            {
                Stream = client.GetStream();    //получаем сетевой поток для чтения
                while (true)    //в бесконечном цикле выполняем процедуру GetScreen получения данных
                {
                    try
                    { GetScreen(); }
                    catch
                    { MessageBox.Show("Не удалось получить скриншот экрана"); }
                }
            }
            catch (Exception ex)
            { MessageBox.Show(ex.Message); }
            finally
            {
                if (Stream != null)
                    Stream.Close();
                if (client != null)
                    client.Close();
            }
        }
 
        private void GetScreen()
        {
            try
            {
                byte[] ScreenLengthB = new byte[10];    //создаем байтовый массив, в который будем записывать размер очередного сжатого скриншота
                do
                {
                    int ReceivedBytes = Stream.Read(ScreenLengthB, 0, ScreenLengthB.Length);    //считываем из потока в массив ScreenLengthB размер очередного скриншота и записываем в переменную ReceivedBytes количество прочитанных байт
                    int ScrLength = int.Parse(Encoding.Unicode.GetString(ScreenLengthB, 0, ReceivedBytes)); //преобразуем массив ScreenLengthB в число
 
                    using (MemoryStream FileR = new MemoryStream()) //будем записывать сжатый скриншот сначала в память
                    {
                        byte[] FileScr = new byte[ScrLength];   //создаем байтовый массив по размеру скриншота, полученного ранее
                        do
                        {
                            ReceivedBytes = Stream.Read(FileScr, 0, FileScr.Length);    //считываем из потока в массив FileScr очередной "кусочек" скриншота (по возможности весь скриншот, поэтому указывается размер оставшейся части скриншота) и записываем в переменную ReceivedBytes количество прочитанных байт
                            FileR.Write(FileScr, 0, ReceivedBytes); //записываем в память полученный "кусок" скриншота
                            ScrLength -= ReceivedBytes;     //вычитаем из размера скриншота размер принятого "куска"
                            FileScr = new byte[ScrLength];  //создаем массив по новому размеру
                        } while (ScrLength > 0);    //выполняем всю последовательность, пока не примем весь скриншот
 
                        using (FileStream File = new FileStream("screenshot.gz", FileMode.Create))  //создаем файл с именем screenshot.gz
                        { File.Write(FileR.ToArray(), 0, FileR.ToArray().Length); } //записываем в созданный файл скриншот из памяти
                    }
 
                    Screen.Decompress();    //выполняем декомпрессию принятого сжатого скриншота
                    PB.LoadAsync(@"screenshot");    //асинхронно подгружаем в pictureBox скриншот
                } while (Stream.DataAvailable);     //читаем пока в потоке есть данные, доступные для чтения
            }
            catch (Exception ex)
            { MessageBox.Show(ex.Message); }
        }
    }
}

Клиент:
Кликните здесь для просмотра всего текста

C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.IO;
using System.Net.Sockets;
using LibraryTV;
 
namespace Client
{
    public partial class Client : Form
    {
        TcpClient tcpClient;
        NetworkStream stream;
        private const string addr = "127.0.0.1";
        private const int port = 50000;
        PrintScreen screenshot;
 
        public Client()
        {
            InitializeComponent();
            Location = new Point(Screen.PrimaryScreen.WorkingArea.Width - this.Width, Screen.PrimaryScreen.WorkingArea.Height - this.Height);   //задаем местоположение окна приложеня в правом нижнем углу экрана
            screenshot = new PrintScreen(); //создаем объект класса PrintScreen, с помощью которого будем создавать скриншоты и сжимать их
            Thread SendThread = new Thread(new ThreadStart(Connect));   //создаем отдельный поток для метода Connect
            SendThread.Start();     //запускаем созданный поток
        }
 
        public void Connect()
        {
            try
            {
                tcpClient = new TcpClient(addr, port);      //пытаемся подключиться к серверу на заданный IP-адрес и порт
                stream = tcpClient.GetStream();     //получаем сетевой поток для записи
                SendDisplay();
            }
            catch (Exception ex)
            { MessageBox.Show(ex.Message); }
            finally
            { Disconnect(); }
        }
 
        public void SendDisplay()
        {
            while (true)
            {
                try
                {
                    byte[] buf = new byte[55000];   //создаем байтовый массив в 55000 байт
                    screenshot.makeScreenshot();    //создаем скриншот
                    screenshot.Compress();  //сжимаем созданный скриншот
 
                    using (FileStream fs = new FileStream("screenshot.gz", FileMode.Open))  //создаем файловый поток fs для чтения сжатого скриншота
                    {
                        using (BinaryReader br = new BinaryReader(fs))      //считываем в двоичный поток br из потока fs
                        {
                            int ReadedBytes;    //количество считанных байт
                            int len = (Int32)fs.Length;     //размер скриншота
                            byte[] length = Encoding.Unicode.GetBytes(len.ToString());      //переводим в байтовый массив размер скриншота
                            stream.Write(length, 0, length.Length);     //отправляем сначала размер скриншота
                            do
                            {
                                ReadedBytes = br.Read(buf, 0, buf.Length);      //считываем максимально возможно количество байт файла в массив buf и записываем количество считанных байт в переменную ReadedBytes
                                stream.Write(buf, 0, ReadedBytes);      //отправляем массив buf
                                len -= ReadedBytes;     //вычитаем из общего размера файла количество отправленных байт
                            } while (len != 0);     //повторяем до тех пор, пока не отправим весь файл "кусок" за "куском"
                        }
                    }
 
                    Thread.Sleep(40);       //останавливаем потом на 40 мс (25 кадров в секунду)
                }
                catch (Exception ex)
                {
                    MessageBox.Show(ex.Message);
                    Disconnect();
                }
            }
        }
 
        public void Disconnect()
        {
            if (stream != null)
                stream.Close(); //отключение потока
            if (tcpClient != null)
                tcpClient.Close();  //отключение клиента
            Environment.Exit(0);    //завершение процесса
        }
    }
}
0
Лучшие ответы (1)
IT_Exp
Эксперт
34794 / 4073 / 2104
Регистрация: 17.06.2006
Сообщений: 32,602
Блог
23.05.2016, 12:06
Ответы с готовыми решениями:

Передача данных между сеансами удаленного рабочего стола
Коллеги, подскажите пожалуйста, как лучше всего решить данную задачу. У меня две программы, обе написанных на C#. Хочу организовать...

Изобретение велосипеда, как тренировка студента. Передача видео или изображения рабочего стола по сети
Собственно, есть задание и коротко оно звучит так: "написать то, что будет передавать видео или изображения рабочего стола на другой...

Передача удаленного рабочего стола
Добрые люди, помогите - как можно осуществить передачу удаленного рабочего стола? нужно для написания программы системного...

8
Эксперт .NET
 Аватар для insite2012
5548 / 4311 / 1218
Регистрация: 12.10.2013
Сообщений: 12,371
Записей в блоге: 2
23.05.2016, 12:43
Xovanchik, что касается скриншота, может использовать WCF? Сейчас дам вам свой пример, как-то делал такое...
0
Эксперт .NET
 Аватар для insite2012
5548 / 4311 / 1218
Регистрация: 12.10.2013
Сообщений: 12,371
Записей в блоге: 2
23.05.2016, 12:47
Xovanchik, вот пример моего тестового скриншотера.
Вложения
Тип файла: rar ScreenViewer.rar (86.7 Кб, 130 просмотров)
0
14 / 14 / 3
Регистрация: 16.05.2016
Сообщений: 47
23.05.2016, 17:05
Xovanchik, вообще, конечно лучше переписать на что-то более вменяемое. Конкретно: у Вас размер данных передается строкой вначале - это может быть причиной ошибки, так как у вас кодируется в юникод и массив под строку только в 10 байт, то максимальное число, которое можно передать в вашем коде - 99999. Решение: передавайте количество интом, а не строкой. Второе: зачем сохранять картинку в файл а потом ее читать??? преобразовывайте ее в битмап и выводите на пикчебокс сразу, без записи в файл. Ну и вообще - лучше использовать что-то готовое, хотя-бы WCF.
1
0 / 0 / 0
Регистрация: 23.05.2016
Сообщений: 3
23.05.2016, 18:54  [ТС]
insite2012 спасибо большое за пример, однако никогда не пользовался данным фреймворком. Посмотрел исходник и увы все, что связано с wcf, не понял. Мне уже советовали использовать данный фреймворк, однако посмотрел, что по нему пишут отдельные книги, поэтому пришлось отказаться пока от этой идеи (иначе придется пользоваться чужими кусками кода, которых я или полностью, или отчасти не буду понимать, или отложить решение данной задачи на n-ое количество времени, пока изучу wcf).

noant, да, я обратил внимание на то, что максимальное число 99999, я уже думал использовать массив размером 20 байт, а незанятые элементы массива "забивать" значением char 'a' из юникода (097). Такого размера массива должно хватить с запасом, однако моя ошибка возникает даже при размере скриншота в 60 Кб.
Передавать количество интом не пробовал (не знал что так можно, все источники, которые встречал, говорили о том, что передавать нужно байтовый массив. Сейчас поищу как это делается. Спасибо за совет!).
Сохраняю я картинку в файл, потому что она отправляется по сети в сжатом виде, и нужно ее подвергнуть декомпрессии прежде чем загрузить в пикчербокс.

Добавлено через 38 минут
noant попробовал передавать количество интом - не помогло. Проблема сохраняется.

Добавлено через 37 минут
noant огромное спасибо! Помогло! Ваши слова о том, что нужно передавать интом натолкнули меня на мысль, что обратное преобразование возможно только в int16-32-64 или uint16-32-64 (просто инта нет), по итогу ошибка была в первом байте, который отводится под знак. Когда я с обоих концов все преобразовал в uint32 - проблема исчезла.
0
Эксперт .NET
6691 / 4102 / 1607
Регистрация: 09.05.2015
Сообщений: 9,569
23.05.2016, 18:59
Цитата Сообщение от Xovanchik Посмотреть сообщение
обратное преобразование возможно только в int16-32-64 или uint16-32-64 (просто инта нет)
Вы не поверите, но просто "int", это Int32, uint - UInt32, long - Int64 и т.д.
0
14 / 14 / 3
Регистрация: 16.05.2016
Сообщений: 47
23.05.2016, 19:09
Xovanchik, есть нормальный способ компрессии изображения. То, что вы его сохраняете в файл - плохой костыль! Лишний раз напрягать жесткий диск - не есть хорошо!
https://www.cyberforum.ru/csha... 11772.html
http://forums.codeguru.com/sho... a-jpg-file
http://www.codeproject.com/Art... e-Compress
0
0 / 0 / 0
Регистрация: 23.05.2016
Сообщений: 3
23.05.2016, 19:18  [ТС]
Someone007 это я знаю. Однако факт остается фактом, проблема исчезла после преобразования в uint. Могу скинуть исходники, если вдруг ошибка была в другом, и сможете указать, буду премного благодарен (мало ли где в будущем могу натолкнуться вновь на данную ошибку).

noant спасибо, сейчас посмотрю. Я знаю что костыль кривой, однако по-другому пока не умею. Исправлюсь! Прям сейчас и начну исправляться
0
Эксперт .NETАвтор FAQ
 Аватар для Storm23
10425 / 5155 / 1825
Регистрация: 11.01.2015
Сообщений: 6,226
Записей в блоге: 34
23.05.2016, 19:22
Лучший ответ Сообщение было отмечено OwenGlendower как решение

Решение

Цитата Сообщение от Xovanchik Посмотреть сообщение
Передача скриншота рабочего стола с удаленного ПК по TCP
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.Net.Sockets;
using System.Threading;
using System.Windows.Forms;
 
namespace WindowsFormsApplication344
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
 
            //создаем PictureBox для отображения скриншотов
            var pb = new PictureBox { Parent = this, Dock = DockStyle.Fill, SizeMode = PictureBoxSizeMode.Zoom };
 
            //создаем поток для клиента (на самом деле это должно запускаться на машине клиента, но для теста, клиент запускается здесь)
            ThreadPool.QueueUserWorkItem(delegate { new Client().Start(); });
 
            //создаем поток для сервера
            ThreadPool.QueueUserWorkItem(
            delegate
            {
                //получаем в цикле скриншоты с клиента
                foreach (var bmp in new Server().GetScreenshots())
                {
                    //уничтожаем предыдущее изображение
                    if (pb.Image != null) pb.Image.Dispose();
                    //заносим скриншот в PictureBox
                    pb.Image = bmp;
                }
            });
        }
    }
 
    /// <summary>
    /// Сервер
    /// </summary>
    class Server
    {
        public IEnumerable<Image> GetScreenshots(int port = 24432)
        {
            var list = new TcpListener(port);
            list.Start();
 
            using (var tcp = list.AcceptTcpClient())//принимаем конект
            using (var stream = tcp.GetStream())//создаем сетевой поток
            using (var br = new BinaryReader(stream)) //создаем BinaryReader
            while (true)//делаем бесконечно
            {
                //принимаем длину массива
                var len = br.ReadInt32();
                //принимаем массив
                var arr = br.ReadBytes(len);
                using(var ms = new MemoryStream(arr))//создаем временный поток для сжатого изображения
                {
                    //создаем изображение
                    yield return Bitmap.FromStream(ms);
                }
            }
        }
    }
    
    /// <summary>
    /// Клиент
    /// </summary>
    class Client
    {
        public void Start(string host = "localhost", int port = 24432)
        {
            //размеры экрана
            var rect = Screen.PrimaryScreen.Bounds;
 
            //конкетимся к серверу, получаем поток
            using (var tcp = new TcpClient(host, port)) //создаем TcpClient
            using (var stream = tcp.GetStream()) //получаем сетевой поток
            using (var bw = new BinaryWriter(stream)) //создаем BinaryWriter
            using (var bmp = new Bitmap(rect.Width, rect.Height)) //создаем битмап для отправки
            using (var gr = Graphics.FromImage(bmp)) //создаем канву
            using (var ms = new MemoryStream()) //создаем временный поток для сжатого изображения
            while (true) //делаем бесконечно
            {
                //захватываем изображение экрана
                gr.CopyFromScreen(rect.Left, rect.Top, 0, 0, rect.Size);
                //конвертируем изображение в массив байт в формате jpeg
                ms.Position = 0;
                bmp.Save(ms, ImageFormat.Jpeg);
                var arr = ms.ToArray(); //получаем массив байт
                //отправляем длину массива данных
                bw.Write(arr.Length);
                //отправляем массив
                bw.Write(arr);
                //точно, отправялем
                bw.Flush();
            }
        }
    }
}
4
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
BasicMan
Эксперт
29316 / 5623 / 2384
Регистрация: 17.02.2009
Сообщений: 30,364
Блог
23.05.2016, 19:22
Помогаю со студенческими работами здесь

Лицензия удаленного рабочего стола
Нужна лицензия или взломать

Отображение удаленного рабочего стола
Как сделать, так чтобы в picturebox, ну или хоть в чём отображался другой(удалённый) рабочий стол?

Viewer удаленного рабочего стола
Занимаюсь написанием вьвера Удаленного рабочего стола использую вот это апи...

Просмотр удаленного рабочего стола
Реально ли сделать просмотр удаленного рабочего стола на VB6 или VB.NET? Можно примеры?

Подключение удаленного рабочего стола
Добрый день. Есть система Windows 7 Embedded Standart, подскажите как там включить Подключение удаленного рабочего стола. В...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
9
Ответ Создать тему
Новые блоги и статьи
PhpStorm 2025.3: WSL Terminal всегда стартует в ~
and_y87 14.12.2025
PhpStorm 2025. 3: WSL Terminal всегда стартует в ~ (home), игнорируя директорию проекта Симптом: После обновления до PhpStorm 2025. 3 встроенный терминал WSL открывается в домашней директории. . .
Access
VikBal 11.12.2025
Помогите пожалуйста !! Как объединить 2 одинаковые БД Access с разными данными.
Новый ноутбук
volvo 07.12.2025
Всем привет. По скидке в "черную пятницу" взял себе новый ноутбук Lenovo ThinkBook 16 G7 на Амазоне: Ryzen 5 7533HS 64 Gb DDR5 1Tb NVMe 16" Full HD Display Win11 Pro
Музыка, написанная Искусственным Интеллектом
volvo 04.12.2025
Всем привет. Некоторое время назад меня заинтересовало, что уже умеет ИИ в плане написания музыки для песен, и, собственно, исполнения этих самых песен. Стихов у нас много, уже вышли 4 книги, еще 3. . .
От async/await к виртуальным потокам в Python
IndentationError 23.11.2025
Армин Ронахер поставил под сомнение async/ await. Создатель Flask заявляет: цветные функции - провал, виртуальные потоки - решение. Не threading-динозавры, а новое поколение лёгких потоков. Откат?. . .
Поиск "дружественных имён" СОМ портов
Argus19 22.11.2025
Поиск "дружественных имён" СОМ портов На странице: https:/ / norseev. ru/ 2018/ 01/ 04/ comportlist_windows/ нашёл схожую тему. Там приведён код на С++, который показывает только имена СОМ портов, типа,. . .
Сколько Государство потратило денег на меня, обеспечивая инсулином.
Programma_Boinc 20.11.2025
Сколько Государство потратило денег на меня, обеспечивая инсулином. Вот решила сделать интересный приблизительный подсчет, сколько государство потратило на меня денег на покупку инсулинов. . . .
Ломающие изменения в C#.NStar Alpha
Etyuhibosecyu 20.11.2025
Уже можно не только тестировать, но и пользоваться C#. NStar - писать оконные приложения, содержащие надписи, кнопки, текстовые поля и даже изображения, например, моя игра "Три в ряд" написана на этом. . .
Мысли в слух
kumehtar 18.11.2025
Кстати, совсем недавно имел разговор на тему медитаций с людьми. И обнаружил, что они вообще не понимают что такое медитация и зачем она нужна. Самые базовые вещи. Для них это - когда просто люди. . .
Создание Single Page Application на фреймах
krapotkin 16.11.2025
Статья исключительно для начинающих. Подходы оригинальностью не блещут. В век Веб все очень привыкли к дизайну Single-Page-Application . Быстренько разберем подход "на фреймах". Мы делаем одну. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2025, CyberForum.ru