C# WinForms 控件学习项目

现在我先将这个链接下载下来:

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 ,全程手写控件、讲解组件思想,步骤极简、代码可直接运行,同时补充自定义组件封装(核心学习点)。

前置环境(必须先装好)

  1. 安装 .NET 8 SDK (官网下载,勾选添加到环境变量)
    https://dotnet.microsoft.com/zh-cn/download/dotnet/8.0
  2. 安装 VS Code
  3. VS Code 安装插件:
    • C# Dev Kit(官方C#插件,语法提示、运行调试)

方案一:C# WinForms 控件学习项目(推荐入门)

WinForms 控件直观,所有界面元素都是控件/组件,适合理解:控件创建、属性、事件、容器、自定义组件封装。

1. 创建项目

  1. 新建空文件夹,用 VS Code 打开
  2. 打开终端(视图终端),执行命令创建项目:
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. 基础区域:输入文字、读取/清空内容、复选框、下拉框
  2. 自定义组件区域:两个封装好的组合控件,点击按钮可读取内部数据

二、核心知识点(控件/组件学习重点)

1. 控件本质

所有 WinForms 界面元素都继承自 Control 基类,统一特性:

  • Location:控件坐标
  • Size:控件宽高
  • Text:显示文本
  • Controls:容器集合(存放子控件)
  • 事件:ClickTextChanged 等实现交互

2. 组件化思想(本项目核心)

  1. 基础控件:系统内置(Button、TextBox、Label 等)
  2. 容器控件GroupBoxPanel,用来分组管理子控件
  3. 自定义组件
    • 继承 Control 基类
    • 内部组合多个基础控件
    • 对外暴露公共方法/属性,隐藏内部实现
    • 一次封装,多处复用(组件复用的核心)

3. 常用内置控件速记

控件 用途
Label 静态文字展示
TextBox 文本输入
Button 点击交互按钮
CheckBox 复选(多选)
ComboBox 下拉选择
GroupBox 分组容器

三、拓展练习(巩固控件/组件能力)

基于现有项目继续练习,循序渐进:

  1. 新增控件 :添加 RadioButton 单选框、ProgressBar 进度条
  2. 完善自定义组件 :给 MyInputComponent 增加 TextChanged 事件
  3. 封装新组件:做一个「按钮+标签」的自定义组件
  4. 控件联动:下拉框切换时,自动修改输入框内容
  5. 样式美化:修改控件背景色、字体、边框

四、常见问题排查

  1. dotnet 命令未找到
    → .NET SDK 未安装/未配置环境变量,重启 VS Code 重试。
  2. 运行无窗口弹出
    → 仅支持 Windows 系统,Linux/Mac 无法运行 WinForms。
  3. 中文显示异常
    → 代码中指定 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 桌面窗口程序,三个文件各司其职:

  1. Program.cs程序入口文件
    电脑运行软件时,最先执行这里,负责启动整个窗口程序,只跑一次。
  2. Form1.cs主窗口逻辑文件
    窗口长什么样、放哪些按钮/输入框、点击按钮有什么反应、自定义组件,全部业务代码在这里
  3. Form1.Designer.cs设计器自动生成代码
    如果你用可视化拖拽控件,VS 会自动在这里写代码;纯手写代码可以完全不用管它,本项目里它不影响运行。

二、逐文件、逐行代码详解

1. Program.cs(程序入口,最先运行)

完整代码:

csharp 复制代码
namespace ControlStudyDemo;

internal static class Program
{
    [STAThread]
    static void Main()
    {
        ApplicationConfiguration.Initialize();
        Application.Run(new Form1());
    }
}

逐行解释

  1. namespace ControlStudyDemo;

    命名空间 :相当于给所有代码分一个「文件夹/分组」。

    整个项目的所有类、代码都放在 ControlStudyDemo 这个分组里,避免名字冲突,小白记住:项目自带,不用改

  2. internal static class Program

    • class Program:定义一个名叫 Program(可以理解为代码容器)。
    • static:静态类,这个类不需要创建实例,直接就能用里面的方法。
    • internal:访问权限,仅限当前项目内部使用,外部程序访问不到。
      合起来:这是一个程序入口专用静态类
  3. [STAThread]

    WinForms 窗口程序固定标记 ,是 Windows 系统要求的。

    作用:保证窗口、控件、鼠标点击正常工作,固定写法,不用理解,不用改

  4. static void Main()

    • Main整个程序的入口方法 (重中之重)。
      任何 C# 可运行程序,都是从 Main 方法第一行开始执行。
    • static:静态方法,不用创建对象就能执行。
    • void:这个方法执行完不返回任何结果
  5. ApplicationConfiguration.Initialize();

    .NET 8 新版固定初始化代码。

    作用:初始化窗口程序的基础配置(样式、渲染、系统环境等),固定写法,不用改

  6. Application.Run(new Form1());

    整行核心:启动主窗口

    • Form1:就是我们的主窗口类。
    • new Form1()创建一个主窗口对象(把窗口实例化出来)。
    • Application.Run(窗口对象):让程序跑起来,显示窗口,并一直监听用户操作 (点击按钮、输入文字等)。
      执行完这行,窗口就弹出来了,程序进入「等待用户操作」状态。

2. Form1.cs(主窗口核心,业务全在这里)

这个文件是窗口本体,包含:窗口配置、基础控件、自定义组件、点击事件。

先看类结构 + 构造方法(运行核心),再拆分各个方法。

第一部分:头部引用

csharp 复制代码
using System;
using System.Drawing;
using System.Windows.Forms;
  • using引用系统自带工具包 ,相当于「调用别人写好的工具」。
    1. System:基础通用功能(事件、通用类型)。
    2. System.Drawing:绘图、颜色、字体、大小相关。
    3. System.Windows.Forms所有窗口、按钮、输入框等控件都来自这里
      没有这三行,就不能写窗口代码。

第二部分:窗口类定义

csharp 复制代码
namespace ControlStudyDemo
{
    public partial class Form1 : Form
  1. namespace ControlStudyDemo:和 Program.cs 同一个命名空间,属于同一个项目分组。
  2. public partial class Form1
    • class Form1:定义主窗口类
    • partial分部类,意思是「这个类的代码拆分在两个文件里」(Form1.cs + Form1.Designer.cs),两个文件合起来才是完整的 Form1 窗口。
    • public:公开,外部可以访问。
  3. : Form 继承 ,最关键的面向对象概念。

    Form1 继承了系统自带的 Form(窗口基类)。

    含义:Form1 天生就拥有「窗口」的所有能力(大小、标题、关闭、最大化等)。


第三部分:窗口构造方法(执行顺序第二环)

csharp 复制代码
public Form1()
{
    InitializeComponent();
    InitWindow();
    BuildBasicControls();
    BuildCustomControl();
}
逐行解释 + 执行顺序

Program.cs 执行 new Form1() 时,自动调用这个构造方法,从上到下依次执行:

  1. InitializeComponent();

    调用 Form1.Designer.cs 里的初始化代码(设计器自动生成)。

    本项目纯手写控件,这行保留即可,不用管

  2. InitWindow();

    调用下方自定义方法:初始化窗口本身(标题、大小、位置、字体)。

  3. BuildBasicControls();

    调用下方自定义方法:创建所有系统自带控件(标签、输入框、按钮、复选框等)。

  4. 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() 基础控件搭建

逻辑统一:创建控件 → 设置属性 → 绑定事件 → 加到窗口上

拿几个典型举例,所有控件套路完全一样:

  1. Label lblTip = new Label()
    创建一个标签控件(纯文字展示)。
  2. Location = new Point(左坐标, 上坐标)
    控件在窗口中的位置
  3. Size = new Size(宽, 高)
    控件大小。
  4. Controls.Add(lblTip);
    把控件挂载到窗口上(不加这行,控件就看不见)。
  5. 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
  1. MyInputComponent自己写的全新组件类
  2. : Control:继承系统最顶层的控件基类
    只要继承 Control,它就具备所有控件的通用能力(位置、大小、承载子控件)。

内部逻辑:

  • 定义私有子控件:Label + TextBox(内部零件,外部看不到)。
  • 构造方法:设置整体位置、大小,把标签和输入框装进当前自定义组件
  • Controls.Add(子控件):和窗口添加控件逻辑一致,容器套容器。
  • public string GetInputValue()对外公开的接口
    内部细节隐藏,外部只需要调用这个方法就能拿到输入内容,这就是组件封装思想

3. Form1.Designer.cs(设计器自动代码,极简讲解)

  1. 来源:VS 可视化设计器拖拽控件时自动生成。
  2. 作用:存放控件初始化、布局代码。
  3. 本项目状态:
    我们全程手写控件 ,没有拖拽,所以这个文件里几乎是空的,完全不用修改、不用看懂
  4. 和 Form1.cs 的关系:
    因为 partial 分部类,两个文件合并为一个完整的 Form1 窗口类。

三、完整 程序运行顺序(重中之重,按时间线走)

我按「双击运行程序」开始,一步步梳理执行流程,从上到下、一步不差

步骤 1:系统启动程序 → 进入 Program.cs

  1. 程序找到入口 Main() 方法,开始执行。
  2. 执行 ApplicationConfiguration.Initialize(); 初始化窗口环境。
  3. 执行 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() 结束 → 整个程序退出。


四、小白总结(精简记忆版)

  1. Program.cs :大门入口,只做一件事 → 启动主窗口
  2. Form1.cs:房子本体,里面装修(控件)、功能(点击事件)全在这里。
  3. Form1.Designer.cs:辅助文件,拖拽控件自动生成,手写代码不用管。

执行流程一句话串讲

双击程序 → 运行 Program.cs 的 Main → 创建窗口 new Form1() → 执行 Form1 构造方法(初始化窗口+加载所有控件)→ 窗口显示,等待你点击操作 → 关闭窗口,程序结束。

控件核心套路(所有控件通用)

创建控件 → 设位置/大小/文字 → 绑定事件(可选)→ Controls.Add() 加到父容器(窗口/自定义组件)。

相关推荐
右耳朵猫AI2 小时前
Go周刊2026W22 | GoReleaser 2.16、chi 5.3、tldx 1.4、wazero 1.12、Buf 1.70
开发语言·后端·golang
段一凡-华北理工大学2 小时前
工业领域的Hadoop架构学习~系列文章22:Hadoop生态展望 - 面向未来的技术演进
大数据·人工智能·hadoop·分布式·学习·架构·高炉炼铁
AI人工智能+电脑小能手2 小时前
【大白话说Java面试题 第105题】【并发篇】第5题:说一下 synchronized 关键字的底层原理?
java·开发语言·面试
yueping22 小时前
【无标题】
java·开发语言
YangYang9YangYan2 小时前
学数据分析对学习编程的价值
学习·数据挖掘·数据分析
踏着七彩祥云的小丑2 小时前
Go学习第3天:变量+常量+运算符
开发语言·学习·golang·go
专注搞钱2 小时前
用Python写了个SPC自动分析工具,效率提升10倍
开发语言·python
JaydenAI2 小时前
[MAF预定义Agent中间件-03]FunctionInvocationDelegatingAgent:将AOP引入函数调用
ai·c#·agent·aop·maf
码云骑士2 小时前
【3.Java基础】Java运算符详解:从算数运算到逻辑判断,一篇文章全部掌握
java·开发语言