From efe85cd64ba78d80ddf1740772f3ac37f83f4093 Mon Sep 17 00:00:00 2001
From: Grant Winney <1354059+grantwinney@users.noreply.github.com>
Date: Thu, 19 Dec 2024 15:52:10 -0500
Subject: [PATCH] examples for .net 8 / 9 features
---
.NET 08/GetStockIcon/GetStockIconTest.sln | 22 +++
.../GetStockIconTest/Form1.Designer.cs | 151 ++++++++++++++++++
.../GetStockIcon/GetStockIconTest/Form1.cs | 97 +++++++++++
.../GetStockIcon/GetStockIconTest/Form1.resx | 135 ++++++++++++++++
.../GetStockIconTest/GetStockIconTest.csproj | 11 ++
.../GetStockIcon/GetStockIconTest/Program.cs | 17 ++
.../Properties/Resources.Designer.cs | 63 ++++++++
.../Properties/Resources.resx | 120 ++++++++++++++
.../FolderBrowserDialogMultiSelect.sln | 28 ++++
.../FolderBrowserDialogMultiSelect.csproj | 11 ++
.../Form1.Designer.cs | 107 +++++++++++++
.../FolderBrowserDialogMultiSelect/Form1.cs | 23 +++
.../FolderBrowserDialogMultiSelect/Form1.resx | 123 ++++++++++++++
.../FolderBrowserDialogMultiSelect/Program.cs | 17 ++
.../FolderBrowserDialogOriginal.csproj | 11 ++
.../Form1.Designer.cs | 62 +++++++
.../FolderBrowserDialogOriginal/Form1.cs | 15 ++
.../FolderBrowserDialogOriginal/Form1.resx | 123 ++++++++++++++
.../FolderBrowserDialogOriginal/Program.cs | 17 ++
README.md | 55 ++++---
20 files changed, 1186 insertions(+), 22 deletions(-)
create mode 100644 .NET 08/GetStockIcon/GetStockIconTest.sln
create mode 100644 .NET 08/GetStockIcon/GetStockIconTest/Form1.Designer.cs
create mode 100644 .NET 08/GetStockIcon/GetStockIconTest/Form1.cs
create mode 100644 .NET 08/GetStockIcon/GetStockIconTest/Form1.resx
create mode 100644 .NET 08/GetStockIcon/GetStockIconTest/GetStockIconTest.csproj
create mode 100644 .NET 08/GetStockIcon/GetStockIconTest/Program.cs
create mode 100644 .NET 08/GetStockIcon/GetStockIconTest/Properties/Resources.Designer.cs
create mode 100644 .NET 08/GetStockIcon/GetStockIconTest/Properties/Resources.resx
create mode 100644 .NET 09/FolderBrowserDialogMultiSelect/FolderBrowserDialogMultiSelect.sln
create mode 100644 .NET 09/FolderBrowserDialogMultiSelect/FolderBrowserDialogMultiSelect/FolderBrowserDialogMultiSelect.csproj
create mode 100644 .NET 09/FolderBrowserDialogMultiSelect/FolderBrowserDialogMultiSelect/Form1.Designer.cs
create mode 100644 .NET 09/FolderBrowserDialogMultiSelect/FolderBrowserDialogMultiSelect/Form1.cs
create mode 100644 .NET 09/FolderBrowserDialogMultiSelect/FolderBrowserDialogMultiSelect/Form1.resx
create mode 100644 .NET 09/FolderBrowserDialogMultiSelect/FolderBrowserDialogMultiSelect/Program.cs
create mode 100644 .NET 09/FolderBrowserDialogMultiSelect/FolderBrowserDialogOriginal/FolderBrowserDialogOriginal.csproj
create mode 100644 .NET 09/FolderBrowserDialogMultiSelect/FolderBrowserDialogOriginal/Form1.Designer.cs
create mode 100644 .NET 09/FolderBrowserDialogMultiSelect/FolderBrowserDialogOriginal/Form1.cs
create mode 100644 .NET 09/FolderBrowserDialogMultiSelect/FolderBrowserDialogOriginal/Form1.resx
create mode 100644 .NET 09/FolderBrowserDialogMultiSelect/FolderBrowserDialogOriginal/Program.cs
diff --git a/.NET 08/GetStockIcon/GetStockIconTest.sln b/.NET 08/GetStockIcon/GetStockIconTest.sln
new file mode 100644
index 0000000..62d5502
--- /dev/null
+++ b/.NET 08/GetStockIcon/GetStockIconTest.sln
@@ -0,0 +1,22 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio Version 17
+VisualStudioVersion = 17.12.35514.174 d17.12
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GetStockIconTest", "GetStockIconTest\GetStockIconTest.csproj", "{9A3E489E-90B6-4419-9B18-9A3C6BEF4D76}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Release|Any CPU = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {9A3E489E-90B6-4419-9B18-9A3C6BEF4D76}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {9A3E489E-90B6-4419-9B18-9A3C6BEF4D76}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {9A3E489E-90B6-4419-9B18-9A3C6BEF4D76}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {9A3E489E-90B6-4419-9B18-9A3C6BEF4D76}.Release|Any CPU.Build.0 = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+EndGlobal
diff --git a/.NET 08/GetStockIcon/GetStockIconTest/Form1.Designer.cs b/.NET 08/GetStockIcon/GetStockIconTest/Form1.Designer.cs
new file mode 100644
index 0000000..6dd21a6
--- /dev/null
+++ b/.NET 08/GetStockIcon/GetStockIconTest/Form1.Designer.cs
@@ -0,0 +1,151 @@
+namespace GetStockIconTest
+{
+ partial class Form1
+ {
+ ///
+ /// Required designer variable.
+ ///
+ private System.ComponentModel.IContainer components = null;
+
+ ///
+ /// Clean up any resources being used.
+ ///
+ /// true if managed resources should be disposed; otherwise, false.
+ protected override void Dispose(bool disposing)
+ {
+ if (disposing && (components != null))
+ {
+ components.Dispose();
+ }
+ base.Dispose(disposing);
+ }
+
+ #region Windows Form Designer generated code
+
+ ///
+ /// Required method for Designer support - do not modify
+ /// the contents of this method with the code editor.
+ ///
+ private void InitializeComponent()
+ {
+ components = new System.ComponentModel.Container();
+ button1 = new Button();
+ imageList1 = new ImageList(components);
+ toolStrip1 = new ToolStrip();
+ imageList2 = new ImageList(components);
+ pictureBox1 = new PictureBox();
+ flowLayoutPanel1 = new FlowLayoutPanel();
+ toolTip1 = new ToolTip(components);
+ btnSaveIcons = new Button();
+ folderBrowserDialog1 = new FolderBrowserDialog();
+ lboxSaveIcons = new ListBox();
+ ((System.ComponentModel.ISupportInitialize)pictureBox1).BeginInit();
+ SuspendLayout();
+ //
+ // button1
+ //
+ button1.ImageAlign = ContentAlignment.MiddleLeft;
+ button1.ImageList = imageList1;
+ button1.Location = new Point(15, 138);
+ button1.Name = "button1";
+ button1.Size = new Size(114, 23);
+ button1.TabIndex = 0;
+ button1.Text = "Connected";
+ button1.TextAlign = ContentAlignment.MiddleRight;
+ button1.UseVisualStyleBackColor = true;
+ button1.Click += button1_Click;
+ //
+ // imageList1
+ //
+ imageList1.ColorDepth = ColorDepth.Depth32Bit;
+ imageList1.ImageSize = new Size(16, 16);
+ imageList1.TransparentColor = Color.Transparent;
+ //
+ // toolStrip1
+ //
+ toolStrip1.LayoutStyle = ToolStripLayoutStyle.Flow;
+ toolStrip1.Location = new Point(0, 0);
+ toolStrip1.Name = "toolStrip1";
+ toolStrip1.Size = new Size(877, 0);
+ toolStrip1.TabIndex = 2;
+ toolStrip1.Text = "toolStrip1";
+ //
+ // imageList2
+ //
+ imageList2.ColorDepth = ColorDepth.Depth32Bit;
+ imageList2.ImageSize = new Size(64, 64);
+ imageList2.TransparentColor = Color.Transparent;
+ //
+ // pictureBox1
+ //
+ pictureBox1.Location = new Point(167, 94);
+ pictureBox1.Name = "pictureBox1";
+ pictureBox1.Size = new Size(128, 128);
+ pictureBox1.TabIndex = 3;
+ pictureBox1.TabStop = false;
+ //
+ // flowLayoutPanel1
+ //
+ flowLayoutPanel1.AutoScroll = true;
+ flowLayoutPanel1.Dock = DockStyle.Bottom;
+ flowLayoutPanel1.Location = new Point(0, 268);
+ flowLayoutPanel1.Name = "flowLayoutPanel1";
+ flowLayoutPanel1.Size = new Size(877, 311);
+ flowLayoutPanel1.TabIndex = 4;
+ //
+ // btnSaveIcons
+ //
+ btnSaveIcons.Location = new Point(634, 138);
+ btnSaveIcons.Name = "btnSaveIcons";
+ btnSaveIcons.Size = new Size(75, 23);
+ btnSaveIcons.TabIndex = 5;
+ btnSaveIcons.Text = "Save Icons";
+ toolTip1.SetToolTip(btnSaveIcons, "Save icons in .ico/.bmp formats");
+ btnSaveIcons.UseVisualStyleBackColor = true;
+ btnSaveIcons.Click += btnSaveIcons_Click;
+ //
+ // lboxSaveIcons
+ //
+ lboxSaveIcons.FormattingEnabled = true;
+ lboxSaveIcons.ItemHeight = 15;
+ lboxSaveIcons.Items.AddRange(new object[] { "16", "32", "64", "128", "256" });
+ lboxSaveIcons.Location = new Point(583, 94);
+ lboxSaveIcons.Name = "lboxSaveIcons";
+ lboxSaveIcons.Size = new Size(35, 94);
+ lboxSaveIcons.TabIndex = 6;
+ //
+ // Form1
+ //
+ AutoScaleDimensions = new SizeF(7F, 15F);
+ AutoScaleMode = AutoScaleMode.Font;
+ ClientSize = new Size(877, 579);
+ Controls.Add(lboxSaveIcons);
+ Controls.Add(btnSaveIcons);
+ Controls.Add(flowLayoutPanel1);
+ Controls.Add(pictureBox1);
+ Controls.Add(toolStrip1);
+ Controls.Add(button1);
+ MinimumSize = new Size(800, 600);
+ Name = "Form1";
+ Text = "Form1";
+ FormClosed += Form1_FormClosed;
+ Load += Form1_Load;
+ ((System.ComponentModel.ISupportInitialize)pictureBox1).EndInit();
+ ResumeLayout(false);
+ PerformLayout();
+ }
+
+ #endregion
+
+ private Button button1;
+ private ToolStrip toolStrip1;
+ private ImageList imageList1;
+ private ImageList imageList2;
+ private PictureBox pictureBox1;
+ private FlowLayoutPanel flowLayoutPanel1;
+ private ToolTip toolTip1;
+ private Button btnSaveIcons;
+ private FolderBrowserDialog folderBrowserDialog1;
+ private ListBox lboxSaveIcons;
+ }
+}
diff --git a/.NET 08/GetStockIcon/GetStockIconTest/Form1.cs b/.NET 08/GetStockIcon/GetStockIconTest/Form1.cs
new file mode 100644
index 0000000..4ed0359
--- /dev/null
+++ b/.NET 08/GetStockIcon/GetStockIconTest/Form1.cs
@@ -0,0 +1,97 @@
+using System.Linq;
+
+namespace GetStockIconTest;
+
+public partial class Form1 : Form
+{
+ readonly Bitmap connImg;
+ readonly Bitmap disconnImg;
+
+ public Form1()
+ {
+ InitializeComponent();
+
+ connImg = SystemIcons.GetStockIcon(StockIconId.DriveNet, 128).ToBitmap();
+ disconnImg = SystemIcons.GetStockIcon(StockIconId.DriveNetDisabled, 128).ToBitmap();
+ }
+
+ private void Form1_FormClosed(object sender, FormClosedEventArgs e)
+ {
+ connImg.Dispose();
+ disconnImg.Dispose();
+ }
+
+ private void Form1_Load(object sender, EventArgs e)
+ {
+ lboxSaveIcons.SelectedIndex = 0;
+
+ // Populate image list with default size, which should be 32 px
+ imageList1.Images.Add("Conn", SystemIcons.GetStockIcon(StockIconId.DriveNet));
+ imageList1.Images.Add("Disconn", SystemIcons.GetStockIcon(StockIconId.DriveNetDisabled));
+
+ button1.ImageKey = "Conn";
+ pictureBox1.Image = connImg;
+
+ // Populate another image list with 64 px size
+ foreach (StockIconId icon in Enum.GetValues(typeof(StockIconId)))
+ imageList2.Images.Add(icon.ToString(), SystemIcons.GetStockIcon(icon, 64));
+
+ // Then use the icons in the second list to populate the toolbar
+ // and generate a bunch of pictures with the icon at the larger size
+ foreach (var imageKey in imageList2.Images.Keys)
+ {
+ var btn = new ToolStripButton(imageList2.Images[imageKey]);
+ btn.Click += (s, e) => MessageBox.Show($"Stock Icon: {imageKey}");
+ btn.Image = imageList2.Images[imageKey];
+ btn.ToolTipText = imageKey;
+ toolStrip1.Items.Add(btn);
+
+ var pb = new PictureBox
+ {
+ Width = 64, Height = 64,
+ Image = imageList2.Images[imageKey]
+ };
+ toolTip1.SetToolTip(pb, imageKey);
+ flowLayoutPanel1.Controls.Add(pb);
+ }
+ }
+
+ private void button1_Click(object sender, EventArgs e)
+ {
+ // Toggle between two icons
+ if (button1.ImageKey == "Conn")
+ {
+ button1.ImageKey = "Disconn";
+ button1.Text = "Disconnected";
+ pictureBox1.Image = disconnImg;
+ }
+ else
+ {
+ button1.ImageKey = "Conn";
+ button1.Text = "Connected";
+ pictureBox1.Image = connImg;
+ }
+ }
+
+ private void btnSaveIcons_Click(object sender, EventArgs e)
+ {
+ // Save all icons in .ico format (which looks ugly)
+ // and in .bmp format (which looks great)
+ var result = folderBrowserDialog1.ShowDialog();
+ if (result == DialogResult.OK)
+ {
+ var savePath = folderBrowserDialog1.SelectedPath;
+ foreach (StockIconId icon in Enum.GetValues(typeof(StockIconId)))
+ {
+ var stockIcon = SystemIcons.GetStockIcon(icon, Convert.ToInt32(lboxSaveIcons.SelectedItem));
+
+ // Save .bmp file
+ stockIcon.ToBitmap().Save(Path.Combine(savePath, $"{icon}.bmp"));
+
+ // Save .ico file
+ using FileStream fs = new(Path.Combine(savePath, $"{icon}.ico"), FileMode.Create);
+ stockIcon.Save(fs);
+ }
+ }
+ }
+}
diff --git a/.NET 08/GetStockIcon/GetStockIconTest/Form1.resx b/.NET 08/GetStockIcon/GetStockIconTest/Form1.resx
new file mode 100644
index 0000000..f87e594
--- /dev/null
+++ b/.NET 08/GetStockIcon/GetStockIconTest/Form1.resx
@@ -0,0 +1,135 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ 16, 19
+
+
+ 189, 20
+
+
+ 293, 20
+
+
+ 404, 20
+
+
+ 636, 20
+
+
\ No newline at end of file
diff --git a/.NET 08/GetStockIcon/GetStockIconTest/GetStockIconTest.csproj b/.NET 08/GetStockIcon/GetStockIconTest/GetStockIconTest.csproj
new file mode 100644
index 0000000..663fdb8
--- /dev/null
+++ b/.NET 08/GetStockIcon/GetStockIconTest/GetStockIconTest.csproj
@@ -0,0 +1,11 @@
+
+
+
+ WinExe
+ net8.0-windows
+ enable
+ true
+ enable
+
+
+
\ No newline at end of file
diff --git a/.NET 08/GetStockIcon/GetStockIconTest/Program.cs b/.NET 08/GetStockIcon/GetStockIconTest/Program.cs
new file mode 100644
index 0000000..a7d2630
--- /dev/null
+++ b/.NET 08/GetStockIcon/GetStockIconTest/Program.cs
@@ -0,0 +1,17 @@
+namespace GetStockIconTest
+{
+ internal static class Program
+ {
+ ///
+ /// The main entry point for the application.
+ ///
+ [STAThread]
+ static void Main()
+ {
+ // To customize application configuration such as set high DPI settings or default font,
+ // see https://aka.ms/applicationconfiguration.
+ ApplicationConfiguration.Initialize();
+ Application.Run(new Form1());
+ }
+ }
+}
\ No newline at end of file
diff --git a/.NET 08/GetStockIcon/GetStockIconTest/Properties/Resources.Designer.cs b/.NET 08/GetStockIcon/GetStockIconTest/Properties/Resources.Designer.cs
new file mode 100644
index 0000000..fe34a0a
--- /dev/null
+++ b/.NET 08/GetStockIcon/GetStockIconTest/Properties/Resources.Designer.cs
@@ -0,0 +1,63 @@
+//------------------------------------------------------------------------------
+//
+// This code was generated by a tool.
+// Runtime Version:4.0.30319.42000
+//
+// Changes to this file may cause incorrect behavior and will be lost if
+// the code is regenerated.
+//
+//------------------------------------------------------------------------------
+
+namespace GetStockIconTest.Properties {
+ using System;
+
+
+ ///
+ /// A strongly-typed resource class, for looking up localized strings, etc.
+ ///
+ // This class was auto-generated by the StronglyTypedResourceBuilder
+ // class via a tool like ResGen or Visual Studio.
+ // To add or remove a member, edit your .ResX file then rerun ResGen
+ // with the /str option, or rebuild your VS project.
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")]
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+ [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
+ internal class Resources {
+
+ private static global::System.Resources.ResourceManager resourceMan;
+
+ private static global::System.Globalization.CultureInfo resourceCulture;
+
+ [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
+ internal Resources() {
+ }
+
+ ///
+ /// Returns the cached ResourceManager instance used by this class.
+ ///
+ [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+ internal static global::System.Resources.ResourceManager ResourceManager {
+ get {
+ if (object.ReferenceEquals(resourceMan, null)) {
+ global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("GetStockIconTest.Properties.Resources", typeof(Resources).Assembly);
+ resourceMan = temp;
+ }
+ return resourceMan;
+ }
+ }
+
+ ///
+ /// Overrides the current thread's CurrentUICulture property for all
+ /// resource lookups using this strongly typed resource class.
+ ///
+ [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+ internal static global::System.Globalization.CultureInfo Culture {
+ get {
+ return resourceCulture;
+ }
+ set {
+ resourceCulture = value;
+ }
+ }
+ }
+}
diff --git a/.NET 08/GetStockIcon/GetStockIconTest/Properties/Resources.resx b/.NET 08/GetStockIcon/GetStockIconTest/Properties/Resources.resx
new file mode 100644
index 0000000..1af7de1
--- /dev/null
+++ b/.NET 08/GetStockIcon/GetStockIconTest/Properties/Resources.resx
@@ -0,0 +1,120 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
\ No newline at end of file
diff --git a/.NET 09/FolderBrowserDialogMultiSelect/FolderBrowserDialogMultiSelect.sln b/.NET 09/FolderBrowserDialogMultiSelect/FolderBrowserDialogMultiSelect.sln
new file mode 100644
index 0000000..5a9ffdf
--- /dev/null
+++ b/.NET 09/FolderBrowserDialogMultiSelect/FolderBrowserDialogMultiSelect.sln
@@ -0,0 +1,28 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio Version 17
+VisualStudioVersion = 17.12.35514.174 d17.12
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FolderBrowserDialogMultiSelect", "FolderBrowserDialogMultiSelect\FolderBrowserDialogMultiSelect.csproj", "{49830232-8F63-45EF-A429-48E3CF5C14D9}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FolderBrowserDialogOriginal", "FolderBrowserDialogOriginal\FolderBrowserDialogOriginal.csproj", "{83AB174E-87E1-42F6-A984-ADDE53976961}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Release|Any CPU = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {49830232-8F63-45EF-A429-48E3CF5C14D9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {49830232-8F63-45EF-A429-48E3CF5C14D9}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {49830232-8F63-45EF-A429-48E3CF5C14D9}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {49830232-8F63-45EF-A429-48E3CF5C14D9}.Release|Any CPU.Build.0 = Release|Any CPU
+ {83AB174E-87E1-42F6-A984-ADDE53976961}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {83AB174E-87E1-42F6-A984-ADDE53976961}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {83AB174E-87E1-42F6-A984-ADDE53976961}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {83AB174E-87E1-42F6-A984-ADDE53976961}.Release|Any CPU.Build.0 = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+EndGlobal
diff --git a/.NET 09/FolderBrowserDialogMultiSelect/FolderBrowserDialogMultiSelect/FolderBrowserDialogMultiSelect.csproj b/.NET 09/FolderBrowserDialogMultiSelect/FolderBrowserDialogMultiSelect/FolderBrowserDialogMultiSelect.csproj
new file mode 100644
index 0000000..c27cd77
--- /dev/null
+++ b/.NET 09/FolderBrowserDialogMultiSelect/FolderBrowserDialogMultiSelect/FolderBrowserDialogMultiSelect.csproj
@@ -0,0 +1,11 @@
+
+
+
+ WinExe
+ net9.0-windows
+ enable
+ true
+ enable
+
+
+
\ No newline at end of file
diff --git a/.NET 09/FolderBrowserDialogMultiSelect/FolderBrowserDialogMultiSelect/Form1.Designer.cs b/.NET 09/FolderBrowserDialogMultiSelect/FolderBrowserDialogMultiSelect/Form1.Designer.cs
new file mode 100644
index 0000000..3fb0a76
--- /dev/null
+++ b/.NET 09/FolderBrowserDialogMultiSelect/FolderBrowserDialogMultiSelect/Form1.Designer.cs
@@ -0,0 +1,107 @@
+namespace FolderBrowserDialogMultiSelect
+{
+ partial class Form1
+ {
+ ///
+ /// Required designer variable.
+ ///
+ private System.ComponentModel.IContainer components = null;
+
+ ///
+ /// Clean up any resources being used.
+ ///
+ /// true if managed resources should be disposed; otherwise, false.
+ protected override void Dispose(bool disposing)
+ {
+ if (disposing && (components != null))
+ {
+ components.Dispose();
+ }
+ base.Dispose(disposing);
+ }
+
+ #region Windows Form Designer generated code
+
+ ///
+ /// Required method for Designer support - do not modify
+ /// the contents of this method with the code editor.
+ ///
+ private void InitializeComponent()
+ {
+ fbd = new FolderBrowserDialog();
+ btnSelect = new Button();
+ rdoYes = new RadioButton();
+ rdoNo = new RadioButton();
+ label1 = new Label();
+ SuspendLayout();
+ //
+ // btnSelect
+ //
+ btnSelect.Anchor = AnchorStyles.Top;
+ btnSelect.Location = new Point(155, 109);
+ btnSelect.Name = "btnSelect";
+ btnSelect.Size = new Size(75, 43);
+ btnSelect.TabIndex = 3;
+ btnSelect.Text = "&Select Folders";
+ btnSelect.UseVisualStyleBackColor = true;
+ btnSelect.Click += btnSelect_Click;
+ //
+ // rdoYes
+ //
+ rdoYes.Anchor = AnchorStyles.Top;
+ rdoYes.AutoSize = true;
+ rdoYes.Checked = true;
+ rdoYes.Location = new Point(143, 73);
+ rdoYes.Name = "rdoYes";
+ rdoYes.Size = new Size(42, 19);
+ rdoYes.TabIndex = 4;
+ rdoYes.TabStop = true;
+ rdoYes.Text = "&Yes";
+ rdoYes.UseVisualStyleBackColor = true;
+ rdoYes.CheckedChanged += rdoYes_CheckedChanged;
+ //
+ // rdoNo
+ //
+ rdoNo.Anchor = AnchorStyles.Top;
+ rdoNo.AutoSize = true;
+ rdoNo.Location = new Point(205, 73);
+ rdoNo.Name = "rdoNo";
+ rdoNo.Size = new Size(41, 19);
+ rdoNo.TabIndex = 5;
+ rdoNo.Text = "No";
+ rdoNo.UseVisualStyleBackColor = true;
+ //
+ // label1
+ //
+ label1.Anchor = AnchorStyles.Top;
+ label1.AutoSize = true;
+ label1.Location = new Point(143, 44);
+ label1.Name = "label1";
+ label1.Size = new Size(103, 15);
+ label1.TabIndex = 6;
+ label1.Text = "Allow multiselect?";
+ //
+ // Form1
+ //
+ AutoScaleDimensions = new SizeF(7F, 15F);
+ AutoScaleMode = AutoScaleMode.Font;
+ ClientSize = new Size(384, 261);
+ Controls.Add(label1);
+ Controls.Add(rdoNo);
+ Controls.Add(rdoYes);
+ Controls.Add(btnSelect);
+ Name = "Form1";
+ Text = "Form1";
+ ResumeLayout(false);
+ PerformLayout();
+ }
+
+ #endregion
+
+ private FolderBrowserDialog fbd;
+ private Button btnSelect;
+ private RadioButton rdoYes;
+ private RadioButton rdoNo;
+ private Label label1;
+ }
+}
diff --git a/.NET 09/FolderBrowserDialogMultiSelect/FolderBrowserDialogMultiSelect/Form1.cs b/.NET 09/FolderBrowserDialogMultiSelect/FolderBrowserDialogMultiSelect/Form1.cs
new file mode 100644
index 0000000..7978905
--- /dev/null
+++ b/.NET 09/FolderBrowserDialogMultiSelect/FolderBrowserDialogMultiSelect/Form1.cs
@@ -0,0 +1,23 @@
+namespace FolderBrowserDialogMultiSelect
+{
+ public partial class Form1 : Form
+ {
+ public Form1()
+ {
+ InitializeComponent();
+
+ fbd.Multiselect = true;
+ }
+
+ private void btnSelect_Click(object sender, EventArgs e)
+ {
+ if (fbd.ShowDialog() == DialogResult.OK)
+ MessageBox.Show($"The path(s) to process:\n\n{string.Join("\n", fbd.SelectedPaths)}");
+ }
+
+ private void rdoYes_CheckedChanged(object sender, EventArgs e)
+ {
+ fbd.Multiselect = rdoYes.Checked;
+ }
+ }
+}
diff --git a/.NET 09/FolderBrowserDialogMultiSelect/FolderBrowserDialogMultiSelect/Form1.resx b/.NET 09/FolderBrowserDialogMultiSelect/FolderBrowserDialogMultiSelect/Form1.resx
new file mode 100644
index 0000000..0ba4502
--- /dev/null
+++ b/.NET 09/FolderBrowserDialogMultiSelect/FolderBrowserDialogMultiSelect/Form1.resx
@@ -0,0 +1,123 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ 17, 17
+
+
\ No newline at end of file
diff --git a/.NET 09/FolderBrowserDialogMultiSelect/FolderBrowserDialogMultiSelect/Program.cs b/.NET 09/FolderBrowserDialogMultiSelect/FolderBrowserDialogMultiSelect/Program.cs
new file mode 100644
index 0000000..7324bfb
--- /dev/null
+++ b/.NET 09/FolderBrowserDialogMultiSelect/FolderBrowserDialogMultiSelect/Program.cs
@@ -0,0 +1,17 @@
+namespace FolderBrowserDialogMultiSelect
+{
+ internal static class Program
+ {
+ ///
+ /// The main entry point for the application.
+ ///
+ [STAThread]
+ static void Main()
+ {
+ // To customize application configuration such as set high DPI settings or default font,
+ // see https://aka.ms/applicationconfiguration.
+ ApplicationConfiguration.Initialize();
+ Application.Run(new Form1());
+ }
+ }
+}
\ No newline at end of file
diff --git a/.NET 09/FolderBrowserDialogMultiSelect/FolderBrowserDialogOriginal/FolderBrowserDialogOriginal.csproj b/.NET 09/FolderBrowserDialogMultiSelect/FolderBrowserDialogOriginal/FolderBrowserDialogOriginal.csproj
new file mode 100644
index 0000000..663fdb8
--- /dev/null
+++ b/.NET 09/FolderBrowserDialogMultiSelect/FolderBrowserDialogOriginal/FolderBrowserDialogOriginal.csproj
@@ -0,0 +1,11 @@
+
+
+
+ WinExe
+ net8.0-windows
+ enable
+ true
+ enable
+
+
+
\ No newline at end of file
diff --git a/.NET 09/FolderBrowserDialogMultiSelect/FolderBrowserDialogOriginal/Form1.Designer.cs b/.NET 09/FolderBrowserDialogMultiSelect/FolderBrowserDialogOriginal/Form1.Designer.cs
new file mode 100644
index 0000000..2bead71
--- /dev/null
+++ b/.NET 09/FolderBrowserDialogMultiSelect/FolderBrowserDialogOriginal/Form1.Designer.cs
@@ -0,0 +1,62 @@
+namespace FolderBrowserDialogOriginal
+{
+ partial class Form1
+ {
+ ///
+ /// Required designer variable.
+ ///
+ private System.ComponentModel.IContainer components = null;
+
+ ///
+ /// Clean up any resources being used.
+ ///
+ /// true if managed resources should be disposed; otherwise, false.
+ protected override void Dispose(bool disposing)
+ {
+ if (disposing && (components != null))
+ {
+ components.Dispose();
+ }
+ base.Dispose(disposing);
+ }
+
+ #region Windows Form Designer generated code
+
+ ///
+ /// Required method for Designer support - do not modify
+ /// the contents of this method with the code editor.
+ ///
+ private void InitializeComponent()
+ {
+ fbd = new FolderBrowserDialog();
+ btnSelect = new Button();
+ SuspendLayout();
+ //
+ // btnSelect
+ //
+ btnSelect.Anchor = AnchorStyles.None;
+ btnSelect.Location = new Point(155, 109);
+ btnSelect.Name = "btnSelect";
+ btnSelect.Size = new Size(75, 43);
+ btnSelect.TabIndex = 2;
+ btnSelect.Text = "&Select Folder";
+ btnSelect.UseVisualStyleBackColor = true;
+ btnSelect.Click += btnSelect_Click;
+ //
+ // Form1
+ //
+ AutoScaleDimensions = new SizeF(7F, 15F);
+ AutoScaleMode = AutoScaleMode.Font;
+ ClientSize = new Size(384, 261);
+ Controls.Add(btnSelect);
+ Name = "Form1";
+ Text = "Form1";
+ ResumeLayout(false);
+ }
+
+ #endregion
+
+ private FolderBrowserDialog fbd;
+ private Button btnSelect;
+ }
+}
diff --git a/.NET 09/FolderBrowserDialogMultiSelect/FolderBrowserDialogOriginal/Form1.cs b/.NET 09/FolderBrowserDialogMultiSelect/FolderBrowserDialogOriginal/Form1.cs
new file mode 100644
index 0000000..2430325
--- /dev/null
+++ b/.NET 09/FolderBrowserDialogMultiSelect/FolderBrowserDialogOriginal/Form1.cs
@@ -0,0 +1,15 @@
+namespace FolderBrowserDialogOriginal;
+
+public partial class Form1 : Form
+{
+ public Form1()
+ {
+ InitializeComponent();
+ }
+
+ private void btnSelect_Click(object sender, EventArgs e)
+ {
+ if (fbd.ShowDialog() == DialogResult.OK)
+ MessageBox.Show($"The path to process:\n\n{fbd.SelectedPath}");
+ }
+}
diff --git a/.NET 09/FolderBrowserDialogMultiSelect/FolderBrowserDialogOriginal/Form1.resx b/.NET 09/FolderBrowserDialogMultiSelect/FolderBrowserDialogOriginal/Form1.resx
new file mode 100644
index 0000000..0ba4502
--- /dev/null
+++ b/.NET 09/FolderBrowserDialogMultiSelect/FolderBrowserDialogOriginal/Form1.resx
@@ -0,0 +1,123 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ 17, 17
+
+
\ No newline at end of file
diff --git a/.NET 09/FolderBrowserDialogMultiSelect/FolderBrowserDialogOriginal/Program.cs b/.NET 09/FolderBrowserDialogMultiSelect/FolderBrowserDialogOriginal/Program.cs
new file mode 100644
index 0000000..fab3e34
--- /dev/null
+++ b/.NET 09/FolderBrowserDialogMultiSelect/FolderBrowserDialogOriginal/Program.cs
@@ -0,0 +1,17 @@
+namespace FolderBrowserDialogOriginal
+{
+ internal static class Program
+ {
+ ///
+ /// The main entry point for the application.
+ ///
+ [STAThread]
+ static void Main()
+ {
+ // To customize application configuration such as set high DPI settings or default font,
+ // see https://aka.ms/applicationconfiguration.
+ ApplicationConfiguration.Initialize();
+ Application.Run(new Form1());
+ }
+ }
+}
\ No newline at end of file
diff --git a/README.md b/README.md
index dc4d20a..c5e5dc5 100644
--- a/README.md
+++ b/README.md
@@ -15,59 +15,70 @@ So to all my fellow devs that find themselves supporting the old coldness, let's
_(p.s. I have other repos for [C# / .NET code](https://github.com/grantwinney/CSharpDotNetExamples) and [misc topics](https://github.com/grantwinney/BlogCodeSamples), and some shorter snippets hosted on [Gist](https://gist.github.com/grantwinney) and [JsFiddle](https://jsfiddle.net/user/grantwinney/fiddles/).)_
+## .NET Additions
+
+### .NET 8
+
+- GetStockIcon to get Windows icons ([blog post](https://grantwinney.com/how-to-use-getstockicon-for-winforms), [source code](https://github.com/grantwinney/Surviving-WinForms/tree/master/.NET%2008/GetStockIcon))
+
+### .NET 9
+
+- Selecting multiple directories with FolderBrowserDialog ([blog post](https://grantwinney.com/selecting-multiple-directories-with-the-winforms-folderbrowserdialog-in-dotnet), [source code](https://github.com/grantwinney/Surviving-WinForms/tree/master/.NET%2009/FolderBrowserDialogMultiSelect))
+
+
## Avoiding Anti-Patterns
-* Using nameof to avoid magic strings ([blog post](https://grantwinney.com/using-nameof-to-avoid-magic-strings), [source code](https://github.com/grantwinney/Surviving-WinForms/tree/master/AntiPatterns/MagicStrings/NameOfVersusMagicStrings))
+- Using nameof to avoid magic strings ([blog post](https://grantwinney.com/using-nameof-to-avoid-magic-strings), [source code](https://github.com/grantwinney/Surviving-WinForms/tree/master/AntiPatterns/MagicStrings/NameOfVersusMagicStrings))
## Clarity / Conciseness
-* Checking for null using the null-conditional and null-coalescing operators ([blog post](https://grantwinney.com/null-conditional-and-null-coalescing-operators), [source code](https://github.com/grantwinney/Surviving-WinForms/tree/master/ClarityConciseness/NullHandlingOperators))
-* Local functions in C# (aka nested methods) ([blog post](https://grantwinney.com/local-functions-in-csharp-aka-nested-methods), [source code](https://github.com/grantwinney/Surviving-WinForms/tree/master/ClarityConciseness/LocalFunctions))
-* Named arguments in C# - pass what you want and forget the rest ([blog post](https://grantwinney.com/named-arguments-in-c-pass-what-you-want-and-forget-the-rest), [source code](https://github.com/grantwinney/Surviving-WinForms/tree/master/ClarityConciseness/NamedArguments))
-* String interpolation to craft readable strings ([blog post](https://grantwinney.com/using-string-interpolation-to-craft-readable-strings), [source code](https://github.com/grantwinney/Surviving-WinForms/tree/master/ClarityConciseness/StringInterpolation))
-* Tuples and deconstruction for quickly returning multiple values ([blog post](https://grantwinney.com/using-tuple-and-deconstruction-to-return-multiple-values), [source code](https://github.com/grantwinney/Surviving-WinForms/tree/master/ClarityConciseness/TupleDeconstruction))
+- Checking for null using the null-conditional and null-coalescing operators ([blog post](https://grantwinney.com/null-conditional-and-null-coalescing-operators), [source code](https://github.com/grantwinney/Surviving-WinForms/tree/master/ClarityConciseness/NullHandlingOperators))
+- Local functions in C# (aka nested methods) ([blog post](https://grantwinney.com/local-functions-in-csharp-aka-nested-methods), [source code](https://github.com/grantwinney/Surviving-WinForms/tree/master/ClarityConciseness/LocalFunctions))
+- Named arguments in C# - pass what you want and forget the rest ([blog post](https://grantwinney.com/named-arguments-in-c-pass-what-you-want-and-forget-the-rest), [source code](https://github.com/grantwinney/Surviving-WinForms/tree/master/ClarityConciseness/NamedArguments))
+- String interpolation to craft readable strings ([blog post](https://grantwinney.com/using-string-interpolation-to-craft-readable-strings), [source code](https://github.com/grantwinney/Surviving-WinForms/tree/master/ClarityConciseness/StringInterpolation))
+- Tuples and deconstruction for quickly returning multiple values ([blog post](https://grantwinney.com/using-tuple-and-deconstruction-to-return-multiple-values), [source code](https://github.com/grantwinney/Surviving-WinForms/tree/master/ClarityConciseness/TupleDeconstruction))
## Debugging / Logging
-* A dev-friendly error box with links to the docs ([blog post](https://grantwinney.com/the-helpful-exception-box/), [source code](https://github.com/grantwinney/Surviving-WinForms/tree/master/Debugging/Misc/MessageBoxForDevs))
+- A dev-friendly error box with links to the docs ([blog post](https://grantwinney.com/the-helpful-exception-box/), [source code](https://github.com/grantwinney/Surviving-WinForms/tree/master/Debugging/Misc/MessageBoxForDevs))
### NLog
-* Logging errors in WinForms using NLog ([blog post](https://grantwinney.com/log-errors-in-winforms-with-nlog), [source code](https://github.com/grantwinney/Surviving-WinForms/tree/master/Debugging/Logging/NLogUtility)) (part 1)
-* How to log messages to multiple targets with NLog ([blog post](https://grantwinney.com/how-to-log-messages-to-multiple-targets-with-nlog), [source code](https://github.com/grantwinney/Surviving-WinForms/tree/master/Debugging/Logging/MultipleNLogTargets)) (part 2)
+- Logging errors in WinForms using NLog ([blog post](https://grantwinney.com/log-errors-in-winforms-with-nlog), [source code](https://github.com/grantwinney/Surviving-WinForms/tree/master/Debugging/Logging/NLogUtility)) (part 1)
+- How to log messages to multiple targets with NLog ([blog post](https://grantwinney.com/how-to-log-messages-to-multiple-targets-with-nlog), [source code](https://github.com/grantwinney/Surviving-WinForms/tree/master/Debugging/Logging/MultipleNLogTargets)) (part 2)
## Presentation
-* Alternative ways to send notifications besides using a MessageBox ([blog post](https://grantwinney.com/other-ways-to-notify-user-besides-messagebox), [source code](https://github.com/grantwinney/Surviving-WinForms/tree/master/Presentation/Native/AlternativesToMessageBox))
+- Alternative ways to send notifications besides using a MessageBox ([blog post](https://grantwinney.com/other-ways-to-notify-user-besides-messagebox), [source code](https://github.com/grantwinney/Surviving-WinForms/tree/master/Presentation/Native/AlternativesToMessageBox))
## Testing
-* Mocking the MessageBox ([blog post](https://grantwinney.com/mocking-messagebox-in-winforms/), [source code](https://github.com/grantwinney/Surviving-WinForms/tree/master/Testing/MockingMessageBox))
-* Using MVP to test a WinForms app ([blog post](https://grantwinney.com/its-possible-to-test-a-winforms-app-using-mvp), [source code](https://github.com/grantwinney/Surviving-WinForms/tree/master/Testing/MVP))
+- Mocking the MessageBox ([blog post](https://grantwinney.com/mocking-messagebox-in-winforms/), [source code](https://github.com/grantwinney/Surviving-WinForms/tree/master/Testing/MockingMessageBox))
+- Using MVP to test a WinForms app ([blog post](https://grantwinney.com/its-possible-to-test-a-winforms-app-using-mvp), [source code](https://github.com/grantwinney/Surviving-WinForms/tree/master/Testing/MVP))
## Threading
-* Async, CancellationToken, and IProgress in 5 Short Examples ([blog post](https://grantwinney.com/async-in-5-short-examples), [source code](https://github.com/grantwinney/Surviving-WinForms/tree/master/Threading/SimpleAsyncExamples))
-* Calling an async method from a synchronous one ([blog post](https://grantwinney.com/call-an-async-method-from-a-synchronous-one), [source code](https://github.com/grantwinney/Surviving-WinForms/tree/master/Threading/CallingAsyncMethodFromSynchronousCode))
-* Turning a BackgroundWorker into a Task with TaskCompletionSource ([blog post](https://grantwinney.com/turning-a-backgroundworker-into-a-task-with-taskcompletionsource), [source code](https://github.com/grantwinney/Surviving-WinForms/tree/master/Threading/TaskCompletion))
-* Using Async, Await, and Task to keep the WinForms UI responsive ([blog post](https://grantwinney.com/using-async-await-and-task-to-keep-the-winforms-ui-more-responsive), [source code](https://github.com/grantwinney/Surviving-WinForms/tree/master/Threading/AsyncAwait))
+- Async, CancellationToken, and IProgress in 5 Short Examples ([blog post](https://grantwinney.com/async-in-5-short-examples), [source code](https://github.com/grantwinney/Surviving-WinForms/tree/master/Threading/SimpleAsyncExamples))
+- Calling an async method from a synchronous one ([blog post](https://grantwinney.com/call-an-async-method-from-a-synchronous-one), [source code](https://github.com/grantwinney/Surviving-WinForms/tree/master/Threading/CallingAsyncMethodFromSynchronousCode))
+- Turning a BackgroundWorker into a Task with TaskCompletionSource ([blog post](https://grantwinney.com/turning-a-backgroundworker-into-a-task-with-taskcompletionsource), [source code](https://github.com/grantwinney/Surviving-WinForms/tree/master/Threading/TaskCompletion))
+- Using Async, Await, and Task to keep the WinForms UI responsive ([blog post](https://grantwinney.com/using-async-await-and-task-to-keep-the-winforms-ui-more-responsive), [source code](https://github.com/grantwinney/Surviving-WinForms/tree/master/Threading/AsyncAwait))
## Time
-* Using TimeProvider and FakeTimeProvider in WinForms ([blog post](https://grantwinney.com/using-timeprovider-and-faketimeprovider-in-winforms), [source code](https://github.com/grantwinney/Surviving-WinForms/tree/master/Time/TimeAbstraction))
+- Using TimeProvider and FakeTimeProvider in WinForms ([blog post](https://grantwinney.com/using-timeprovider-and-faketimeprovider-in-winforms), [source code](https://github.com/grantwinney/Surviving-WinForms/tree/master/Time/TimeAbstraction))
## Web
CEFSharp
-* Hosting a simple webpage in WinForms with CEFSharp ([blog post](https://grantwinney.com/hosting-a-simple-webpage-in-winforms-with-cefsharp), [source code](https://github.com/grantwinney/Surviving-WinForms/tree/master/Web/CEFSharp/BasicCefSharp)) (part 1)
-* Displaying an IIS hosted site in CEFSharp ([blog post](https://grantwinney.com/displaying-an-iis-hosted-site-in-cefsharp), [source code](https://github.com/grantwinney/Surviving-WinForms/tree/master/Web/CEFSharp/BasicCefSharpIIS)) (part 2)
+- Hosting a simple webpage in WinForms with CEFSharp ([blog post](https://grantwinney.com/hosting-a-simple-webpage-in-winforms-with-cefsharp), [source code](https://github.com/grantwinney/Surviving-WinForms/tree/master/Web/CEFSharp/BasicCefSharp)) (part 1)
+- Displaying an IIS hosted site in CEFSharp ([blog post](https://grantwinney.com/displaying-an-iis-hosted-site-in-cefsharp), [source code](https://github.com/grantwinney/Surviving-WinForms/tree/master/Web/CEFSharp/BasicCefSharpIIS)) (part 2)
# Other Resources
Other interesting and helpful links, in no particular order:
-* [WinForms source code for .NET Core](https://github.com/dotnet/winforms)
-* [Top WinForms open source projects on GitHub](https://awesomeopensource.com/projects/winforms)
-* [What's new in Windows Forms in .NET 6.0 - .NET Blog](https://devblogs.microsoft.com/dotnet/whats-new-in-windows-forms-in-net-6-0) _(Igor Velikorossov)_
+- [WinForms source code for .NET Core](https://github.com/dotnet/winforms)
+- [Top WinForms open source projects on GitHub](https://awesomeopensource.com/projects/winforms)
+- [What's new in Windows Forms in .NET 6.0 - .NET Blog](https://devblogs.microsoft.com/dotnet/whats-new-in-windows-forms-in-net-6-0) _(Igor Velikorossov)_