现在我先将这个链接下载下来:
csharp
git clone https://github.com/Programming-With-Chris/OpenCVTutorials.git
我自己的一个GitHub地址:
csharp
https://github.com/hitycc/csharp-learning.git
一、查看 .NET Core/.NET 5+(推荐用命令)
按 Win + R → 输入 cmd 或 powershell → 回车
输入:
csharp
dotnet --version
结合 VS Code + .NET,我提供两套方案:WinForms(Windows桌面控件,最适合入门控件学习) 和 WPF ,全程手写控件、讲解组件思想,步骤极简、代码可直接运行,同时补充自定义组件封装(核心学习点)。
前置环境(必须先装好)
- 安装 .NET 8 SDK (官网下载,勾选添加到环境变量)
https://dotnet.microsoft.com/zh-cn/download/dotnet/8.0 - 安装 VS Code
- VS Code 安装插件:
- C# Dev Kit(官方C#插件,语法提示、运行调试)
方案一:C# WinForms 控件学习项目(推荐入门)
WinForms 控件直观,所有界面元素都是控件/组件,适合理解:控件创建、属性、事件、容器、自定义组件封装。
1. 创建项目
- 新建空文件夹,用 VS Code 打开
- 打开终端(
视图→终端),执行命令创建项目:
bash
# 创建WinForms项目
dotnet new winforms -n ControlStudyDemo
# 进入项目文件夹
cd ControlStudyDemo
2. 项目文件说明
ControlStudyDemo/
├── Program.cs 程序入口(不用改)
├── Form1.cs 主窗体 + 所有控件逻辑(核心)
├── Form1.Designer.cs 设计器自动代码(可忽略)
└── ControlStudyDemo.csproj
3. 替换代码
① Program.cs(保持默认,无需修改)
csharp
namespace ControlStudyDemo;
internal static class Program
{
[STAThread]
static void Main()
{
ApplicationConfiguration.Initialize();
Application.Run(new Form1());
}
}
② Form1.cs(核心代码:系统控件 + 自定义组件)
完整替换原有代码,包含:基础控件使用 + 手写自定义复合组件(重点学习组件封装)
csharp
using System;
using System.Drawing;
using System.Windows.Forms;
namespace ControlStudyDemo
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
InitWindow(); // 初始化主窗口
BuildBasicControls();// 搭建系统自带控件
BuildCustomControl();// 搭建【自定义组件】(重点)
}
#region 窗口基础配置
private void InitWindow()
{
Text = "C# 控件&组件学习项目";
Size = new Size(600, 500);
StartPosition = FormStartPosition.CenterScreen;
Font = new Font("微软雅黑", 9f);
}
#endregion
#region 一、系统基础控件演示
private void BuildBasicControls()
{
int top = 20;
int left = 20;
// 1. Label 标签(静态文本组件)
Label lblTip = new Label
{
Text = "===== 基础系统控件 =====",
Location = new Point(left, top),
Font = new Font("微软雅黑", 12, FontStyle.Bold),
AutoSize = true
};
Controls.Add(lblTip);
top += 35;
// 2. TextBox 文本输入框
Label lblInput = new Label { Text = "输入框:", Location = new Point(left, top), AutoSize = true };
TextBox txtInput = new TextBox
{
Name = "txtInput",
Location = new Point(left + 60, top),
Size = new Size(200, 23),
PlaceholderText = "请输入内容"
};
Controls.Add(lblInput);
Controls.Add(txtInput);
top += 35;
// 3. Button 按钮 + 点击事件
Button btnRead = new Button
{
Text = "读取输入",
Location = new Point(left, top),
Size = new Size(90, 30)
};
btnRead.Click += BtnRead_Click; // 绑定点击事件
Controls.Add(btnRead);
Button btnClear = new Button
{
Text = "清空内容",
Location = new Point(left + 100, top),
Size = new Size(90, 30)
};
btnClear.Click += BtnClear_Click;
Controls.Add(btnClear);
top += 45;
// 4. CheckBox 复选框
GroupBox groupCheck = new GroupBox
{
Text = "复选框(多选)",
Location = new Point(left, top),
Size = new Size(180, 80)
};
CheckBox chk1 = new CheckBox { Text = "音乐", Location = new Point(20, 25) };
CheckBox chk2 = new CheckBox { Text = "运动", Location = new Point(80, 25) };
groupCheck.Controls.Add(chk1);
groupCheck.Controls.Add(chk2);
Controls.Add(groupCheck);
top += 100;
// 5. ComboBox 下拉选择框
Label lblCombo = new Label { Text = "下拉选择:", Location = new Point(left, top), AutoSize = true };
ComboBox cbo = new ComboBox
{
Location = new Point(left + 80, top),
Size = new Size(150, 23)
};
cbo.Items.AddRange(new[] { "一年级", "二年级", "三年级" });
cbo.SelectedIndex = 0;
Controls.Add(lblCombo);
Controls.Add(cbo);
}
// 读取输入框内容
private void BtnRead_Click(object? sender, EventArgs e)
{
if (Controls["txtInput"] is TextBox txt)
{
MessageBox.Show($"你输入的内容:{txt.Text}", "提示");
}
}
// 清空输入框
private void BtnClear_Click(object? sender, EventArgs e)
{
if (Controls["txtInput"] is TextBox txt)
{
txt.Clear();
}
}
#endregion
#region 二、自定义复合组件(核心学习:组件封装)
// 封装一个【标签+输入框】组合组件,实现复用
private void BuildCustomControl()
{
Label lblCustomTitle = new Label
{
Text = "===== 自定义封装组件 =====",
Location = new Point(300, 20),
Font = new Font("微软雅黑", 12, FontStyle.Bold),
AutoSize = true
};
Controls.Add(lblCustomTitle);
// 实例化自己写的自定义组件
MyInputComponent comp1 = new MyInputComponent("姓名:", 300, 60);
MyInputComponent comp2 = new MyInputComponent("年龄:", 300, 110);
// 将自定义组件添加到窗体
Controls.Add(comp1);
Controls.Add(comp2);
// 测试按钮:读取自定义组件的值
Button btnGetCustom = new Button
{
Text = "获取自定义组件内容",
Location = new Point(300, 160),
Size = new Size(140, 30)
};
btnGetCustom.Click += (s, e) =>
{
string name = comp1.GetInputValue();
string age = comp2.GetInputValue();
MessageBox.Show($"姓名:{name}\n年龄:{age}", "自定义组件取值");
};
Controls.Add(btnGetCustom);
}
#endregion
}
// ===================== 自定义组件类(重点)=====================
// 继承 Control 基类,制作可复用的复合组件
public class MyInputComponent : Control
{
// 内部子控件
private readonly Label _label;
private readonly TextBox _textBox;
// 构造方法:初始化组件
public MyInputComponent(string labelText, int x, int y)
{
// 组件整体大小和位置
Location = new Point(x, y);
Size = new Size(220, 25);
// 内部标签
_label = new Label
{
Text = labelText,
Location = new Point(0, 2),
Size = new Size(60, 20)
};
// 内部输入框
_textBox = new TextBox
{
Location = new Point(65, 0),
Size = new Size(150, 23)
};
// 将子控件挂载到当前自定义组件中
Controls.Add(_label);
Controls.Add(_textBox);
}
// 对外公开方法:获取输入框内容(组件对外接口)
public string GetInputValue()
{
return _textBox.Text;
}
// 对外公开方法:设置输入框内容
public void SetInputValue(string value)
{
_textBox.Text = value;
}
}
}
4. 运行项目
终端中执行:
bash
dotnet run
会弹出桌面窗口,功能说明:
- 基础区域:输入文字、读取/清空内容、复选框、下拉框
- 自定义组件区域:两个封装好的组合控件,点击按钮可读取内部数据
二、核心知识点(控件/组件学习重点)
1. 控件本质
所有 WinForms 界面元素都继承自 Control 基类,统一特性:
Location:控件坐标Size:控件宽高Text:显示文本Controls:容器集合(存放子控件)- 事件:
Click、TextChanged等实现交互
2. 组件化思想(本项目核心)
- 基础控件:系统内置(Button、TextBox、Label 等)
- 容器控件 :
GroupBox、Panel,用来分组管理子控件 - 自定义组件 :
- 继承
Control基类 - 内部组合多个基础控件
- 对外暴露公共方法/属性,隐藏内部实现
- 一次封装,多处复用(组件复用的核心)
- 继承
3. 常用内置控件速记
| 控件 | 用途 |
|---|---|
| Label | 静态文字展示 |
| TextBox | 文本输入 |
| Button | 点击交互按钮 |
| CheckBox | 复选(多选) |
| ComboBox | 下拉选择 |
| GroupBox | 分组容器 |
三、拓展练习(巩固控件/组件能力)
基于现有项目继续练习,循序渐进:
- 新增控件 :添加
RadioButton单选框、ProgressBar进度条 - 完善自定义组件 :给
MyInputComponent增加TextChanged事件 - 封装新组件:做一个「按钮+标签」的自定义组件
- 控件联动:下拉框切换时,自动修改输入框内容
- 样式美化:修改控件背景色、字体、边框
四、常见问题排查
dotnet命令未找到
→ .NET SDK 未安装/未配置环境变量,重启 VS Code 重试。- 运行无窗口弹出
→ 仅支持 Windows 系统,Linux/Mac 无法运行 WinForms。 - 中文显示异常
→ 代码中指定Font = new Font("微软雅黑")即可。
补充方案:跨平台选择(如果不用Windows)
如果你的系统不是 Windows,WinForms 无法运行,可以改用 .NET MAUI(跨平台UI框架),同样学习控件与组件,创建命令:
bash
dotnet new maui -n MauiControlDemo
用法逻辑和控件思想和 WinForms 一致,只是API略有区别。
我是一个小白 请帮我解释一下Program.cs、Form1.cs 、Form1.Designer.cs中每一行代码的意思 并且他们的运行顺序是什么
结合你这份 WinForms 代码,用小白能听懂的大白话 逐行解释 + 梳理整体运行顺序,先讲文件作用,再逐行拆解,最后梳理执行流程。
一、三个文件整体作用(先搞懂分工)
整个程序是 Windows 桌面窗口程序,三个文件各司其职:
- Program.cs :程序入口文件
电脑运行软件时,最先执行这里,负责启动整个窗口程序,只跑一次。 - Form1.cs :主窗口逻辑文件
窗口长什么样、放哪些按钮/输入框、点击按钮有什么反应、自定义组件,全部业务代码在这里。 - Form1.Designer.cs :设计器自动生成代码
如果你用可视化拖拽控件,VS 会自动在这里写代码;纯手写代码可以完全不用管它,本项目里它不影响运行。
二、逐文件、逐行代码详解
1. Program.cs(程序入口,最先运行)
完整代码:
csharp
namespace ControlStudyDemo;
internal static class Program
{
[STAThread]
static void Main()
{
ApplicationConfiguration.Initialize();
Application.Run(new Form1());
}
}
逐行解释
-
namespace ControlStudyDemo;命名空间 :相当于给所有代码分一个「文件夹/分组」。
整个项目的所有类、代码都放在
ControlStudyDemo这个分组里,避免名字冲突,小白记住:项目自带,不用改。 -
internal static class Programclass Program:定义一个名叫Program的类(可以理解为代码容器)。static:静态类,这个类不需要创建实例,直接就能用里面的方法。internal:访问权限,仅限当前项目内部使用,外部程序访问不到。
合起来:这是一个程序入口专用静态类。
-
[STAThread]WinForms 窗口程序固定标记 ,是 Windows 系统要求的。
作用:保证窗口、控件、鼠标点击正常工作,固定写法,不用理解,不用改。
-
static void Main()Main:整个程序的入口方法 (重中之重)。
任何 C# 可运行程序,都是从Main方法第一行开始执行。static:静态方法,不用创建对象就能执行。void:这个方法执行完不返回任何结果。
-
ApplicationConfiguration.Initialize();.NET 8 新版固定初始化代码。
作用:初始化窗口程序的基础配置(样式、渲染、系统环境等),固定写法,不用改。
-
Application.Run(new Form1());整行核心:启动主窗口
Form1:就是我们的主窗口类。new Form1():创建一个主窗口对象(把窗口实例化出来)。Application.Run(窗口对象):让程序跑起来,显示窗口,并一直监听用户操作 (点击按钮、输入文字等)。
执行完这行,窗口就弹出来了,程序进入「等待用户操作」状态。
2. Form1.cs(主窗口核心,业务全在这里)
这个文件是窗口本体,包含:窗口配置、基础控件、自定义组件、点击事件。
先看类结构 + 构造方法(运行核心),再拆分各个方法。
第一部分:头部引用
csharp
using System;
using System.Drawing;
using System.Windows.Forms;
using:引用系统自带工具包 ,相当于「调用别人写好的工具」。System:基础通用功能(事件、通用类型)。System.Drawing:绘图、颜色、字体、大小相关。System.Windows.Forms:所有窗口、按钮、输入框等控件都来自这里 。
没有这三行,就不能写窗口代码。
第二部分:窗口类定义
csharp
namespace ControlStudyDemo
{
public partial class Form1 : Form
namespace ControlStudyDemo:和 Program.cs 同一个命名空间,属于同一个项目分组。public partial class Form1class Form1:定义主窗口类。partial:分部类,意思是「这个类的代码拆分在两个文件里」(Form1.cs + Form1.Designer.cs),两个文件合起来才是完整的 Form1 窗口。public:公开,外部可以访问。
: Form继承 ,最关键的面向对象概念。Form1继承了系统自带的Form(窗口基类)。含义:
Form1天生就拥有「窗口」的所有能力(大小、标题、关闭、最大化等)。
第三部分:窗口构造方法(执行顺序第二环)
csharp
public Form1()
{
InitializeComponent();
InitWindow();
BuildBasicControls();
BuildCustomControl();
}
逐行解释 + 执行顺序
当 Program.cs 执行 new Form1() 时,自动调用这个构造方法,从上到下依次执行:
-
InitializeComponent();调用
Form1.Designer.cs里的初始化代码(设计器自动生成)。本项目纯手写控件,这行保留即可,不用管。
-
InitWindow();调用下方自定义方法:初始化窗口本身(标题、大小、位置、字体)。
-
BuildBasicControls();调用下方自定义方法:创建所有系统自带控件(标签、输入框、按钮、复选框等)。
-
BuildCustomControl();调用下方自定义方法:创建我们自己封装的自定义组件(重点学习的复合控件)。
总结:创建窗口 → 初始化窗口外观 → 加载原生控件 → 加载自定义组件。
第四部分:各个自定义方法拆解(小白通俗版)
① InitWindow() 窗口初始化
csharp
private void InitWindow()
{
Text = "C# 控件&组件学习项目";
Size = new Size(600, 500);
StartPosition = FormStartPosition.CenterScreen;
Font = new Font("微软雅黑", 9f);
}
private void InitWindow():私有方法,只能当前窗口内部调用,无返回值。Text:窗口标题文字(窗口最上面那条栏的文字)。Size = new Size(宽, 高):设置窗口大小 600像素 × 500像素。StartPosition:窗口弹出时居中显示。Font:设置窗口默认字体、字号。
② BuildBasicControls() 基础控件搭建
逻辑统一:创建控件 → 设置属性 → 绑定事件 → 加到窗口上
拿几个典型举例,所有控件套路完全一样:
Label lblTip = new Label()
创建一个标签控件(纯文字展示)。Location = new Point(左坐标, 上坐标)
控件在窗口中的位置。Size = new Size(宽, 高)
控件大小。Controls.Add(lblTip);
把控件挂载到窗口上(不加这行,控件就看不见)。btnRead.Click += BtnRead_Click;
绑定点击事件 :按钮被鼠标点击时,自动执行BtnRead_Click这个方法。
所有控件(TextBox、Button、CheckBox、ComboBox)全是这套逻辑。
③ 事件方法(按钮点击后执行)
示例:
csharp
private void BtnRead_Click(object? sender, EventArgs e)
{
if (Controls["txtInput"] is TextBox txt)
{
MessageBox.Show($"你输入的内容:{txt.Text}", "提示");
}
}
BtnRead_Click:点击「读取输入」按钮时触发。object? sender:触发事件的控件(这里就是按钮)。EventArgs e:事件附带的参数(点击位置、按键等,初学不用管)。Controls["txtInput"]:根据名字找到窗口里名叫txtInput的输入框。MessageBox.Show():弹出系统提示框。
④ BuildCustomControl() + 自定义组件 MyInputComponent(核心)
csharp
public class MyInputComponent : Control
MyInputComponent:自己写的全新组件类。: Control:继承系统最顶层的控件基类 。
只要继承Control,它就具备所有控件的通用能力(位置、大小、承载子控件)。
内部逻辑:
- 定义私有子控件:
Label+TextBox(内部零件,外部看不到)。 - 构造方法:设置整体位置、大小,把标签和输入框装进当前自定义组件。
Controls.Add(子控件):和窗口添加控件逻辑一致,容器套容器。public string GetInputValue():对外公开的接口 。
内部细节隐藏,外部只需要调用这个方法就能拿到输入内容,这就是组件封装思想。
3. Form1.Designer.cs(设计器自动代码,极简讲解)
- 来源:VS 可视化设计器拖拽控件时自动生成。
- 作用:存放控件初始化、布局代码。
- 本项目状态:
我们全程手写控件 ,没有拖拽,所以这个文件里几乎是空的,完全不用修改、不用看懂。 - 和 Form1.cs 的关系:
因为partial分部类,两个文件合并为一个完整的Form1窗口类。
三、完整 程序运行顺序(重中之重,按时间线走)
我按「双击运行程序」开始,一步步梳理执行流程,从上到下、一步不差:
步骤 1:系统启动程序 → 进入 Program.cs
- 程序找到入口
Main()方法,开始执行。 - 执行
ApplicationConfiguration.Initialize();初始化窗口环境。 - 执行
Application.Run(new Form1());
→ 开始创建 Form1 主窗口对象。
步骤 2:创建 Form1 对象 → 执行 Form1 的构造方法
csharp
public Form1()
{
InitializeComponent(); // 1. 执行 Designer.cs 代码
InitWindow(); // 2. 设置窗口标题、大小、位置
BuildBasicControls(); // 3. 创建标签、按钮、输入框等原生控件
BuildCustomControl(); // 4. 创建自己封装的 MyInputComponent 组件
}
执行完构造方法 → 整个窗口和所有控件全部渲染完成,窗口弹出。
步骤 3:程序进入「监听状态」
Application.Run() 会让程序一直运行、等待用户操作:
- 鼠标移动、点击按钮、输入文字、勾选复选框......都会被程序捕获。
- 比如点击「读取输入」按钮 → 自动执行绑定好的
BtnRead_Click方法 → 弹出提示框。
步骤 4:关闭窗口
点击窗口右上角关闭按钮 → Application.Run() 结束 → 整个程序退出。
四、小白总结(精简记忆版)
- Program.cs :大门入口,只做一件事 → 启动主窗口。
- Form1.cs:房子本体,里面装修(控件)、功能(点击事件)全在这里。
- Form1.Designer.cs:辅助文件,拖拽控件自动生成,手写代码不用管。
执行流程一句话串讲
双击程序 → 运行 Program.cs 的 Main → 创建窗口 new Form1() → 执行 Form1 构造方法(初始化窗口+加载所有控件)→ 窗口显示,等待你点击操作 → 关闭窗口,程序结束。
控件核心套路(所有控件通用)
创建控件 → 设位置/大小/文字 → 绑定事件(可选)→ Controls.Add() 加到父容器(窗口/自定义组件)。