C# 爬虫:疫情实时信息图

运行结果:

using System;
using System.Drawing;
using System.Text;
using NSoup;
using NSoup.Nodes;
using System.IO;
using System.Net;
using System.Text.RegularExpressions;
using System.Windows.Forms;namespace Pneumonia
{public partial class MainForm : DevComponents.DotNetBar.OfficeForm{static string confirmedCount, suspectedCount, deadCount, curedCount, updateTime,dataUpdateTime;static string url = "https://3g.dxy.cn/newh5/view/pneumonia";static int count = 0;static Document doc;public MainForm()
{this.EnableGlass = false;InitializeComponent();this.SizeChanged += new Resize(this).Form1_Resize;  //窗口自适应代码}private void MainForm_Load(object sender, EventArgs e)
{timer1.Enabled = true;timer1.Interval = 1;timer1.Start();WebClient wc = new WebClient();byte[] htmlData = wc.DownloadData(url);string html = Encoding.UTF8.GetString(htmlData);logWrite(html);//将网页内容写入txt文件,以方便查看toolStripStatusLabel1.Text = DateTime.Now.ToString();}private void timer1_Tick(object sender, EventArgs e)
{dataUpdateTime = DateTime.Now.ToString();count++;timer1.Interval = 300000;GetData();lbl1.Text = "☛ 病毒: " + regularMatchStr("getStatisticsService", "virus\":\"(.+?)\",");lbl2.Text = "☛ 传染源: " + regularMatchStr("getStatisticsService", "infectSource\":\"(.+?)\",");lbl3.Text = "☛ 传播途径: " + regularMatchStr("getStatisticsService", "passWay\":\"(.+?)\",");lbl4.Text ="☛ "+regularMatchStr("getStatisticsService", "remark1\":\"(.+?)\",");lbl5.Text ="☛ "+regularMatchStr("getStatisticsService", "remark2\":\"(.+?)\",");Image map =UrlToImage("https://img1.dxycdn.com/2020/0201/450/3394153392393266839-135.png");pictureBox1.Image = map;Image chart = UrlToImage("https://img1.dxycdn.com/2020/0201/693/3394145745204021706-135.png");pictureBox2.Image = chart;updateTimeLbl.Text = "截至 " + updateTime + " 全国数据统计";confirmedLbl.Text = confirmedCount;suspectedLbl.Text = suspectedCount;deadLbl.Text = deadCount;curedLbl.Text = curedCount;}public static void GetData()
{//直接通过url来获取Document对象doc = NSoupClient.Connect(url).Get();//先获取id为artContent的元素,再获取所有的p标签updateTime = ConvertStringToDateTime(regularMatchStr("getStatisticsService", "modifyTime\":(.+?),")).ToString();confirmedCount = regularMatchStr("getStatisticsService", "confirmedCount\":(.+?),");suspectedCount = regularMatchStr("getStatisticsService", "suspectedCount\":(.+?),");deadCount = regularMatchStr("getStatisticsService", "deadCount\":(.+?),");curedCount = regularMatchStr("getStatisticsService", "curedCount\":(.+?),");}#region 下载图片到Imagepublic static Image UrlToImage(string url)
{WebClient mywebclient = new WebClient();byte[] Bytes = mywebclient.DownloadData(url);using (MemoryStream ms = new MemoryStream(Bytes)){Image outputImg = Image.FromStream(ms);return outputImg;}}#endregionpublic static DateTime ConvertStringToDateTime(string timeStamp)
{DateTime dtStart = TimeZone.CurrentTimeZone.ToLocalTime(new DateTime(1970, 1, 1));long lTime = long.Parse(timeStamp + "0000");TimeSpan toNow = new TimeSpan(lTime);return dtStart.Add(toNow);}public static string regularMatchStr(string elementId, string regex)
{Element p = doc.GetElementById(elementId);Regex reg = new Regex(regex, RegexOptions.IgnoreCase);//例如我想提取line中的NAME值Match match = reg.Match(p.Html());string value = match.Groups[1].Value;return value;}public static void logWrite(string Message)
{if (!File.Exists(AppDomain.CurrentDomain.BaseDirectory + "\\log.txt"))File.Create(AppDomain.CurrentDomain.BaseDirectory + "\\log.txt").Close();string fileName = AppDomain.CurrentDomain.BaseDirectory + "\\log.txt";string content = DateTime.Now.ToLocalTime() + Message + "\r\n";StreamWriter sw = new StreamWriter(fileName, true);sw.Write(content);sw.Close(); sw.Dispose();}private void notifyIcon1_MouseDoubleClick(object sender, MouseEventArgs e)
{if (e.Button == MouseButtons.Left)//判断鼠标的按键            {//点击时判断form是否显示,显示就隐藏,隐藏就显示               if (this.WindowState == FormWindowState.Normal){this.WindowState = FormWindowState.Minimized;this.Hide();}else if (this.WindowState == FormWindowState.Minimized){this.Show();this.WindowState = FormWindowState.Normal;this.Activate();}}else if (e.Button == MouseButtons.Right){//右键退出事件                if (MessageBox.Show("是否需要关闭程序?", "提示:", MessageBoxButtons.OKCancel, MessageBoxIcon.Exclamation) == DialogResult.OK)//出错提示                {//关闭窗口                    DialogResult = DialogResult.No;Dispose();Close();}}}private void timer2_Tick(object sender, EventArgs e)
{toolStripStatusLabel1.Text = DateTime.Now.ToString() + "  刷新次数 : " + count + "  最新刷新时间 :" + dataUpdateTime;}private void MainForm_FormClosing(object sender, FormClosingEventArgs e)
{if (MessageBox.Show("是否确认退出程序?", "退出", MessageBoxButtons.OKCancel, MessageBoxIcon.Question) == DialogResult.OK){// 关闭所有的线程this.Dispose();this.Close();}else{e.Cancel = true;}}private void MainForm_SizeChanged(object sender, EventArgs e)
{//判断是否选择的是最小化按钮if (WindowState == FormWindowState.Minimized){//隐藏任务栏区图标this.ShowInTaskbar = false;//图标显示在托盘区notifyIcon1.Visible = true;}}private void 退出ToolStripMenuItem_Click(object sender, EventArgs e){if (MessageBox.Show("是否确认退出程序?", "退出", MessageBoxButtons.OKCancel, MessageBoxIcon.Question) == DialogResult.OK){// 关闭所有的线程this.Dispose();this.Close();}}private void 显示ToolStripMenuItem_Click(object sender, EventArgs e){WindowState = FormWindowState.Normal;}}
}

resize类

using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;namespace Pneumonia
{class Resize{private MainForm _form;public Resize(MainForm form){int count = form.Controls.Count * 2 + 2;float[] factor = new float[count];int i = 0;factor[i++] = form.Size.Width;factor[i++] = form.Size.Height;foreach (Control ctrl in form.Controls){factor[i++] = ctrl.Location.X / (float)form.Size.Width;factor[i++] = ctrl.Location.Y / (float)form.Size.Height;ctrl.Tag = ctrl.Size;}form.Tag = factor;this._form = form;}public void Form1_Resize(object sender, EventArgs e){float[] scale = (float[])this._form.Tag;int i = 2;foreach (Control ctrl in this._form.Controls) //panel的长宽增长到一个固定的值就不会再增长了,原因:Panel的宽和高上限是65535像素(https://blog.csdn.net/dufangfeilong/article/details/41805073?utm_source=blogxgwz5){ctrl.Left = (int)(this._form.Size.Width * scale[i++]);ctrl.Top = (int)(this._form.Size.Height * scale[i++]);ctrl.Width = (int)(this._form.Size.Width / (float)scale[0] * ((Size)ctrl.Tag).Width);ctrl.Height = (int)(this._form.Size.Height / (float)scale[1] * ((Size)ctrl.Tag).Height);}}}
}

C# Winform控件自适应窗体大小:方法1(推荐)

需求:当窗体尺寸动态改变时,窗体中的各种控件(包括Panel以及Panel中的子控件)可以动态调节自身大小,以适应窗体内容比例。

方法:

第一步,新建一个类,代码如下:

class Resize{private Form _form;public Resize(Form form){int count = form.Controls.Count * 2 + 2;float[] factor = new float[count];int i = 0;factor[i++] = form.Size.Width;factor[i++] = form.Size.Height;foreach (Control ctrl in form.Controls){factor[i++] = ctrl.Location.X / (float)form.Size.Width;factor[i++] = ctrl.Location.Y / (float)form.Size.Height;ctrl.Tag = ctrl.Size;}form.Tag = factor;this._form = form;}public void Form1_Resize(object sender, EventArgs e){float[] scale = (float[])this._form.Tag;int i = 2;foreach (Control ctrl in this._form.Controls) //panel的长宽增长到一个固定的值就不会再增长了,原因:Panel的宽和高上限是65535像素(https://blog.csdn.net/dufangfeilong/article/details/41805073?utm_source=blogxgwz5){ctrl.Left = (int)(this._form.Size.Width * scale[i++]);ctrl.Top = (int)(this._form.Size.Height * scale[i++]);ctrl.Width = (int)(this._form.Size.Width / (float)scale[0] * ((Size)ctrl.Tag).Width);ctrl.Height = (int)(this._form.Size.Height / (float)scale[1] * ((Size)ctrl.Tag).Height);}}}第二步,在Form的初始化函数中使用这个类:public Form_StockCount(){InitializeComponent();this.SizeChanged += new Resize(this).Form1_Resize;  //窗口自适应代码}

C# Winform窗体和控件自适应大小:方法2

1.在项目中创建类AutoSizeForm

AutoSizeForm.cs文件代码:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace CSharpFormApplication
{class AutoResizeForm{//(1).声明结构,只记录窗体和其控件的初始位置和大小。public struct controlRect{public int Left;public int Top;public int Width;public int Height;}//(2).声明 1个对象//注意这里不能使用控件列表记录 List nCtrl;,因为控件的关联性,记录的始终是当前的大小。//      public List oldCtrl= new List();//这里将西文的大于小于号都过滤掉了,只能改为中文的,使用中要改回西文public List<controlRect> oldCtrl = new List<controlRect>();int ctrlNo = 0;//1;//(3). 创建两个函数//(3.1)记录窗体和其控件的初始位置和大小,public void controllInitializeSize(Control mForm){controlRect cR;cR.Left = mForm.Left; cR.Top = mForm.Top; cR.Width = mForm.Width; cR.Height = mForm.Height;oldCtrl.Add(cR);//第一个为"窗体本身",只加入一次即可AddControl(mForm);//窗体内其余控件还可能嵌套控件(比如panel),要单独抽出,因为要递归调用//this.WindowState = (System.Windows.Forms.FormWindowState)(2);//记录完控件的初始位置和大小后,再最大化//0 - Normalize , 1 - Minimize,2- Maximize}private void AddControl(Control ctl){foreach (Control c in ctl.Controls){  //**放在这里,是先记录控件的子控件,后记录控件本身//if (c.Controls.Count > 0)//    AddControl(c);//窗体内其余控件还可能嵌套控件(比如panel),要单独抽出,因为要递归调用controlRect objCtrl;objCtrl.Left = c.Left; objCtrl.Top = c.Top; objCtrl.Width = c.Width; objCtrl.Height = c.Height;oldCtrl.Add(objCtrl);//**放在这里,是先记录控件本身,后记录控件的子控件if (c.Controls.Count > 0)AddControl(c);//窗体内其余控件还可能嵌套控件(比如panel),要单独抽出,因为要递归调用}}//(3.2)控件自适应大小,public void controlAutoSize(Control mForm){if (ctrlNo == 0){ //*如果在窗体的Form1_Load中,记录控件原始的大小和位置,正常没有问题,但要加入皮肤就会出现问题,因为有些控件如dataGridView的的子控件还没有完成,个数少//*要在窗体的Form1_SizeChanged中,第一次改变大小时,记录控件原始的大小和位置,这里所有控件的子控件都已经形成controlRect cR;//  cR.Left = mForm.Left; cR.Top = mForm.Top; cR.Width = mForm.Width; cR.Height = mForm.Height;cR.Left = 0; cR.Top = 0; cR.Width = mForm.PreferredSize.Width; cR.Height = mForm.PreferredSize.Height;oldCtrl.Add(cR);//第一个为"窗体本身",只加入一次即可AddControl(mForm);//窗体内其余控件可能嵌套其它控件(比如panel),故单独抽出以便递归调用}float wScale = (float)mForm.Width / (float)oldCtrl[0].Width;//新旧窗体之间的比例,与最早的旧窗体float hScale = (float)mForm.Height / (float)oldCtrl[0].Height;//.Height;ctrlNo = 1;//进入=1,第0个为窗体本身,窗体内的控件,从序号1开始AutoScaleControl(mForm, wScale, hScale);//窗体内其余控件还可能嵌套控件(比如panel),要单独抽出,因为要递归调用}private void AutoScaleControl(Control ctl, float wScale, float hScale){int ctrLeft0, ctrTop0, ctrWidth0, ctrHeight0;//int ctrlNo = 1;//第1个是窗体自身的 Left,Top,Width,Height,所以窗体控件从ctrlNo=1开始foreach (Control c in ctl.Controls){ //**放在这里,是先缩放控件的子控件,后缩放控件本身//if (c.Controls.Count > 0)//   AutoScaleControl(c, wScale, hScale);//窗体内其余控件还可能嵌套控件(比如panel),要单独抽出,因为要递归调用ctrLeft0 = oldCtrl[ctrlNo].Left;ctrTop0 = oldCtrl[ctrlNo].Top;ctrWidth0 = oldCtrl[ctrlNo].Width;ctrHeight0 = oldCtrl[ctrlNo].Height;//c.Left = (int)((ctrLeft0 - wLeft0) * wScale) + wLeft1;//新旧控件之间的线性比例//c.Top = (int)((ctrTop0 - wTop0) * h) + wTop1;c.Left = (int)((ctrLeft0) * wScale);//新旧控件之间的线性比例。控件位置只相对于窗体,所以不能加 + wLeft1c.Top = (int)((ctrTop0) * hScale);//c.Width = (int)(ctrWidth0 * wScale);//只与最初的大小相关,所以不能与现在的宽度相乘 (int)(c.Width * w);c.Height = (int)(ctrHeight0 * hScale);//ctrlNo++;//累加序号//**放在这里,是先缩放控件本身,后缩放控件的子控件if (c.Controls.Count > 0)AutoScaleControl(c, wScale, hScale);//窗体内其余控件还可能嵌套控件(比如panel),要单独抽出,因为要递归调用if (ctl is DataGridView){DataGridView dgv = ctl as DataGridView;Cursor.Current = Cursors.WaitCursor;int widths = 0;for (int i = 0; i < dgv.Columns.Count; i++){dgv.AutoResizeColumn(i, DataGridViewAutoSizeColumnMode.AllCells);  // 自动调整列宽  widths += dgv.Columns[i].Width;   // 计算调整列后单元列的宽度和                       }if (widths >= ctl.Size.Width)  // 如果调整列的宽度大于设定列宽  dgv.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.DisplayedCells;  // 调整列的模式 自动  elsedgv.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.Fill;  // 如果小于 则填充  Cursor.Current = Cursors.Default;}}}}}2.在要自适应大小的Form中自定义全局类对象AutoResizeForm asc = new AutoResizeForm();3.在要自适应大小的Form的load事件和SizeChange事件中执行对象方法private void WidgetAutoResizeForm_Load(object sender, EventArgs e){asc.controllInitializeSize(this);}private void WidgetAutoResizeForm_SizeChanged(object sender, EventArgs e){asc.controlAutoSize(this);}From窗体代码: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 CSharpFormApplication
{public partial class WidgetAutoResizeForm : Form{AutoResizeForm asc = new AutoResizeForm();public WidgetAutoResizeForm(){InitializeComponent();}private void WidgetAutoResizeForm_Load(object sender, EventArgs e){asc.controllInitializeSize(this);}private void WidgetAutoResizeForm_SizeChanged(object sender, EventArgs e){asc.controlAutoSize(this);}}
}   

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/301612.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

史上最黑科技 | 人造肌肉、DNA折叠、柔性外骨骼…

全世界只有3.14 % 的人关注了数据与算法之美说起被机器人支配&#xff0c;一部分人恐惧得不行&#xff0c;另一部人只当个笑话&#xff0c;但无论哪一边&#xff0c;都忍不住想看看这个神秘的领域正在发生什么&#xff0c;这是本能&#xff1a;“我得盯着你&#xff0c;如果哪天…

linux l显示详细信息,fdisk -l显示信息详解

fdisk -l显示信息详解[rootwww.linuxidc.com ~]# fdisk -lDisk /dev/sda: 10.7 GB, 10737418240 bytes255 heads, 63 sectors/track, 1305 cylindersUnits cylinders of 16065 * 512 8225280 bytesSector size (logical/physical): 512 bytes / 512 bytesI/O size (minimum/o…

有钱真的能为所欲为,微软用75亿美元解决了比尔盖茨的“心头大患”

全世界只有3.14 % 的人关注了数据与算法之美2018年6月4日&#xff0c;微软在官方博客上宣布&#xff1a;以75 亿美元的价格收购了全球最大的开源代码托管平台GitHub。谁也没想到&#xff0c;微软和开源这场长达几十年的战争&#xff0c;到最后双方竟然喜结连理了。不过&#xf…

linux 逻辑卷 pe size 4.00 mib大小怎么改,linux逻辑卷的建立

开始的时候系统各目录的挂载情况如下&#xff1a;增加了一个8G大小的scsi磁盘启动系统之后。[rootpoint1 ~]#fdisk &#xfffd;Cl增加了一个sdb设别。一、分区并格式化磁盘[rootpoint1 ~]#fdisk /dev/sdb输入m是显示帮助菜单输入n创建一个分区&#xff0c;选择p创建主分区&…

svn 自动同步到web站点目录post-commit.bat

为什么80%的码农都做不了架构师&#xff1f;>>> 需求分析: 在服务器上搭建了visualSVN server &#xff0c;然后为了统一测试环境&#xff0c;又在服务器上搭建了web server。现在的需求是&#xff0c;当开发人员通过svn提交更新的时候&#xff0c;让svn自动将文件…

.NET之模型绑定和验证

介绍模型绑定就是接收将来自HTTP请求的数据映射到模型的过程。如果找不到模型属性的值&#xff0c;并不会报错&#xff0c;而是给该属性设置默认值。示例&#xff1a;比如我们有一个接口为[HttpGet("{id}")] public ActionResult<Pet> GetById(int id, bool do…

每日一笑 | 大学教室的真实写照...

全世界只有3.14 % 的人关注了数据与算法之美&#xff08;图片来源于网络&#xff0c;侵权删&#xff09;

linux调用v4l2获取视频,嵌入式Linux:V4L2视频采集操作流程和接口说明

一般操作流程(视频设备)&#xff1a;1. 打开设备文件。 int fdopen("/dev/video0",O_RDWR);2. 取得设备的capability&#xff0c;看看设备具有什么功能&#xff0c;比如是否具有视频输入,或者音频输入输出等。VIDIOC_QUERYCAP,struct v4l2_capability3. 选择视频输入…

面向对象技术——UML

UML&#xff0c;统一建模语言是一种可视化建模语言。 UML包括九种类型的图&#xff1a;用例图&#xff0c;类图&#xff0c;对象图&#xff0c;顺序图&#xff0c;协作图&#xff0c;状态图&#xff0c;活动图&#xff0c;构件图&#xff0c;及部署图&#xff0c;各种图示系统在…

美国返还中国文物,阿里谣言粉碎机获奖,教育部规范研究生培养,腾讯严打微信跑分活动,推动降低港澳漫游费,这就是今天的大新闻。...

今天是3月1日农历正月廿五今天星期五相信大家都很舍不得放下工作下面是今天的大新闻美国返还361件中国文物&#xff08;中国日报&#xff09;当地时间2月28日&#xff0c;美国政府向中国返还361件&#xff08;套&#xff09;流失文物。这些中国流失文物&#xff0c;由美国联邦调…

Linux怎么更新镜像,利用 Zsync 更新已有的 Ubuntu ISO 镜像

对! 是升级iso镜像, 不是升级系统. 从旧的镜像升级到新的镜像.可能有点迟了~大家都down好了镜像~ 我现在才有心情和时间写blog哦~由alpha的iso升到正式版都可以. 呃~ 当然,估计由alpha开始的话,下载量也与直接下载正式版区别不大~这么多人下载, 速度当然会慢喇~ 用zsync来升级镜…

你有做 Code Review 吗?

在代码的编写中有一个很重要的环节&#xff0c;经常会被忽视&#xff0c;那就是 Code Review ,据说在 Facebook、Google 这种互联网大公司&#xff0c;要求每一个提交都必须通过审查&#xff0c;对于每个工程师来说 Code Review 是一项十分重要的工作&#xff0c;甚至比写代码本…

PhotoShop CS5制作残旧的印章效果

编者按&#xff1a;不少网友喜欢个性印章效果&#xff0c;因此常常搜索个性印章在线制作。其实&#xff0c;Photoshop就可以完成个性印章制作。事实上&#xff0c;使用 Photoshop制作残旧的印章效果文字有多种方法&#xff0c;例如可以使用云彩滤镜。本文作者介绍了另一种实现方…

限时秒杀┃秒杀90%的玩具,让孩子爱上科学的彩虹实验2来了!

▲数据汪特别推荐点击上图进入玩酷屋之前小木有推荐过“彩虹实验”&#xff0c;这款是可以让孩子在探索中能够独立思考&#xff0c;主动地构建知识库&#xff0c;培养创造力。&#xff08;传送门&#xff09;让孩子们在家开展科学游戏&#xff0c;既能提升动手能力&#xff0c;…

感想四

2019独角兽企业重金招聘Python工程师标准>>> 随着年龄的增长&#xff0c;对人对事物的认知就越真&#xff0c;包括知识也是如此。&#xfeff; 很多年前&#xff0c;在软件开发领域中发生了一个有趣的转变&#xff0c;软件变成了系统中最为昂贵、最为重要的部分。从…

.NET Worker Service 作为 Windows 服务运行及优雅退出改进

上一篇文章我们了解了如何为 Worker Service 添加 Serilog 日志记录&#xff0c;今天我接着介绍一下如何将 Worker Service 作为 Windows 服务运行。我曾经在前面一篇文章的总结中提到过可以使用 sc.exe 实用工具将 Worker Service 安装为 Windows 服务运行&#xff0c;本文中我…

私有云存储 linux,搭建nextcloud私有云存储网盘

本文将要为您介绍的是搭建nextcloud私有云存储网盘,具体完成步骤:简介&#xff1a;搭建个人云存储一般会想到ownCloud&#xff0c;堪称是自建云存储服务的经典。而Nextcloud是ownCloud原开发团队打造的号称是“下一代”存储.真正试用过后就由衷地赞同这个Nextcloud&#xff1a;…

我报了个税,隐私就被扒光了?

全世界只有3.14 % 的人关注了数据与算法之美1月14日&#xff0c;据外媒报道&#xff0c;美国参议院金融委员会正在向美国财政部和国税局施压&#xff0c;要求他们采取网络安全措施。相关数据显示&#xff0c;2015年美国约有700,000名纳税人身份信息遭到泄露&#xff0c;为了解决…

C# 外接(网口)双摄像头视频获取

【注意事项】------------------------------------1. 更新设备网络SDK时&#xff0c;SDK开发包【库文件】里的HCNetSDK.dll、HCCore.dll、PlayCtrl.dll、SuperRender.dll、AudioRender.dll、HCNetSDKCom文件夹、ssleay32.dll、libeay32.dll、hlog.dll、hpr.dll、zlib1.dll、lo…

Visual Studio 2022 Preview 1 和.NET 6 Preview 5 正式发布

具有里程碑意义的Visual Studio 2022 Preview 1正式发布&#xff0c;重点是64位&#xff0c;而没有增加新功能&#xff0c;并且同时也发布了.NET 6 Preview 5。https://devblogs.microsoft.com/visualstudio/visual-studio-2022-preview-1-now-available/https://devblogs.micr…