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)_