详细讲解基于.NET的WinForm桌面应用程序的运行过程和代码原理-C# 7

本博客详细讲解基于.NET的WinForm桌面应用程序的运行过程和原理。
所用的语言是C#。
WinForm 的桌面程序在执行过程中与普通的控制台应用程序相同而又不同。
本文以一个例程,讲解WinForm 的详细过程,有助于各位加深了解WinForm。

具体而言,VS 把Winform 封装的很好,我们接下来一步步讲解。
首先我把这个例程及程序运行的界面给大家展示出来。

///Program.cs 片段
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace WindowsFormsApp1
{
    
    
    static class Program
    {
    
    
        /// <summary>
        /// 应用程序的主入口点。
        /// </summary>
        [STAThread]
        static void Main()
        {
    
    
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            Application.Run(new Form1());
        }
    }
}
//Form1.Designer.cs 片段
namespace WindowsFormsApp1
{
    
    
    partial class Form1
    {
    
    
        /// <summary>
        /// 必需的设计器变量。
        /// </summary>
        private System.ComponentModel.IContainer components = null;

        /// <summary>
        /// 清理所有正在使用的资源。
        /// </summary>
        /// <param name="disposing">如果应释放托管资源,为 true;否则为 false。</param>
        protected override void Dispose(bool disposing)
        {
    
    
            if (disposing && (components != null))
            {
    
    
                components.Dispose();
            }
            base.Dispose(disposing);
        }

        #region Windows 窗体设计器生成的代码

        /// <summary>
        /// 设计器支持所需的方法 - 不要修改
        /// 使用代码编辑器修改此方法的内容。
        /// </summary>
        private void InitializeComponent()
        {
    
    
            this.pictureBox1 = new System.Windows.Forms.PictureBox();
            this.button1 = new System.Windows.Forms.Button();
            ((System.ComponentModel.ISupportInitialize)(this.pictureBox1)).BeginInit();
            this.SuspendLayout();
            // 
            // pictureBox1
            // 
            this.pictureBox1.BorderStyle = System.Windows.Forms.BorderStyle.Fixed3D;
            this.pictureBox1.Location = new System.Drawing.Point(201, 51);
            this.pictureBox1.Name = "pictureBox1";
            this.pictureBox1.Size = new System.Drawing.Size(410, 253);
            this.pictureBox1.SizeMode = System.Windows.Forms.PictureBoxSizeMode.Zoom;
            this.pictureBox1.TabIndex = 0;
            this.pictureBox1.TabStop = false;
            // 
            // button1
            // 
            this.button1.Location = new System.Drawing.Point(338, 349);
            this.button1.Name = "button1";
            this.button1.Size = new System.Drawing.Size(149, 46);
            this.button1.TabIndex = 1;
            this.button1.Text = "button1";
            this.button1.UseVisualStyleBackColor = true;
            this.button1.Click += new System.EventHandler(this.button1_Click);
            // 
            // Form1
            // 
            this.AutoScaleDimensions = new System.Drawing.SizeF(8F, 15F);
            this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
            this.ClientSize = new System.Drawing.Size(800, 450);
            this.Controls.Add(this.button1);
            this.Controls.Add(this.pictureBox1);
            this.Name = "Form1";
            this.Text = "Form1";
            ((System.ComponentModel.ISupportInitialize)(this.pictureBox1)).EndInit();
            this.ResumeLayout(false);

        }

        #endregion

        private System.Windows.Forms.PictureBox pictureBox1;
        private System.Windows.Forms.Button button1;
    }
}

//Form1.cs 片段 
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace WindowsFormsApp1
{
    
    
    public partial class Form1 : Form
    {
    
    
        public Form1()
        {
    
    
            InitializeComponent();
        }

        private void button1_Click(object sender, EventArgs e)
        {
    
    
            pictureBox1.Image = Image.FromFile("C:\\C#\\Test_WinForm\\3_PictureBox_Test\\bin\\Debug\\4.jpg");
        }
    }
}


程序运行的窗体
桌面程序和控制台程序相同有一个入口程序,及Program.cs
我们可以看到在Program.cs中有:

  static class Program
    {
    
    
        /// <summary>
        /// 应用程序的主入口点。
        /// </summary>
        [STAThread]
        static void Main()
        {
    
    
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            Application.Run(new Form1());
        }
    }

其中Application是一个密封类,你可以看到他的定义为:

public sealed class Application {
    
     }

Application下面的属性和方法全部都是静态的。
然后程序开始执行下面两句,这是程序的预处理,自动开辟一个线程,运行窗体有关。

Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);

紧接着我们可以看到,程序开始执行下面这句:

Application.Run(new Form1());

这里在内存的堆中新建立了一个匿名的Form1对象。
然后程序跳转到Form1类,此类继承了System.Windows.Forms.Form基类,
我们在Form1上所添加的任何控件和事件都是重写System.Windows.Forms.Form基类的属性和方法。
程序这里跳转到:

//Form1.Designer.cs
//即:
private System.ComponentModel.IContainer components = null;

首先执行上面这句,以提供窗体必须的容器,我们可以看到,我们基本上是看不到Form1.Designer.cs这个片段的,因为VS 把它封装的很好,
至于我们接下来要看到的Form1.cs ,只是Form1.Designer.cs的一个片段而已。这是因为Form1.cs 有一个关键字partial,这是部分类的关键字,VS很巧妙的将项目内部运行的Form1.Designer.cs 和可以让开发者DIY 的Form1.cs通过partial 分割开来,一个对内封闭,一个对外公开。而且一旦你修改Form1.Designer.cs的代码,程序就会崩溃,这正是这个设计巧妙的地方。
顺其自然,自然而然执行Form1的构造方法,

//Form1.cs
public Form1()
        {
    
    
            InitializeComponent();
        }

我们可以看到 InitializeComponent() 是初始化容器的内部成员方法。紧接着,程序跳转到内部片段Form1.Designer.cs执行Form1类的私有方法InitializeComponent()

  #region Windows 窗体设计器生成的代码

        /// <summary>
        /// 设计器支持所需的方法 - 不要修改
        /// 使用代码编辑器修改此方法的内容。
        /// </summary>
        private void InitializeComponent()
        {
    
    
            this.pictureBox1 = new System.Windows.Forms.PictureBox();
            this.button1 = new System.Windows.Forms.Button();
            ((System.ComponentModel.ISupportInitialize)(this.pictureBox1)).BeginInit();
            this.SuspendLayout();
            // 
            // pictureBox1
            // 
            this.pictureBox1.BorderStyle = System.Windows.Forms.BorderStyle.Fixed3D;
            this.pictureBox1.Location = new System.Drawing.Point(201, 51);
            this.pictureBox1.Name = "pictureBox1";
            this.pictureBox1.Size = new System.Drawing.Size(410, 253);
            this.pictureBox1.SizeMode = System.Windows.Forms.PictureBoxSizeMode.Zoom;
            this.pictureBox1.TabIndex = 0;
            this.pictureBox1.TabStop = false;
            // 
            // button1
            // 
            this.button1.Location = new System.Drawing.Point(338, 349);
            this.button1.Name = "button1";
            this.button1.Size = new System.Drawing.Size(149, 46);
            this.button1.TabIndex = 1;
            this.button1.Text = "button1";
            this.button1.UseVisualStyleBackColor = true;
            this.button1.Click += new System.EventHandler(this.button1_Click);
            // 
            // Form1
            // 
            this.AutoScaleDimensions = new System.Drawing.SizeF(8F, 15F);
            this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
            this.ClientSize = new System.Drawing.Size(800, 450);
            this.Controls.Add(this.button1);
            this.Controls.Add(this.pictureBox1);
            this.Name = "Form1";
            this.Text = "Form1";
            ((System.ComponentModel.ISupportInitialize)(this.pictureBox1)).EndInit();
            this.ResumeLayout(false);

        }

        #endregion

       

由于我在窗体上放了一个PictureBox和一个Button, InitializeComponent() 成员函数会自动初始化和记录我所创建的控件。
我们可以在Form1.Designer.cs看到我所创建的字段,如下所示。

 private System.Windows.Forms.PictureBox pictureBox1;
 private System.Windows.Forms.Button button1;

执行完InitializeComponent() 后,程序会回到构造方法,然后再回到主程序Program.cs,然后窗体就会显示出来,
然后就是大家熟悉的窗体操作环节,而这写我们DIY 的代码都会在对外的Form1.cs 中。
在这里插入图片描述

然后,当我们关闭程序的是时候,VS 会自动清理堆中的数据,就是我们当初创建的匿名Form1 对象,此时执行:

/// <summary>
        /// 清理所有正在使用的资源。
        /// </summary>
        /// <param name="disposing">如果应释放托管资源,为 true;否则为 false。</param>
        protected override void Dispose(bool disposing)
        {
    
    
            if (disposing && (components != null))
            {
    
    
                components.Dispose();
            }
            base.Dispose(disposing);
        }

这有点类似于C++中的delete 。不过我们这里是自动调用的。
然后程序最终返回主程序Program.cs,至此程序执行完毕。
至此主题讲解完毕。
如果我们要添加另一个类,就是在当前名称空间下创建一个类即可,这和控制台应用程序是一样的。
我们可以通过控制访问权限来控制访问。
而有关程序集的一般信息由以下代码控制。更改这些特性值可修改
与程序集关联的信息。即我们可以找到的AssemblyInfo.cs 中的代码。

using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;

// 有关程序集的一般信息由以下
// 控制。更改这些特性值可修改
// 与程序集关联的信息。
[assembly: AssemblyTitle("WindowsFormsApp1")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("WindowsFormsApp1")]
[assembly: AssemblyCopyright("Copyright ©  2020")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]

// 将 ComVisible 设置为 false 会使此程序集中的类型
//对 COM 组件不可见。如果需要从 COM 访问此程序集中的类型
//请将此类型的 ComVisible 特性设置为 true。
[assembly: ComVisible(false)]

// 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID
[assembly: Guid("8260d835-8536-4eab-94e7-c3cf7b435afb")]

// 程序集的版本信息由下列四个值组成: 
//
//      主版本
//      次版本
//      生成号
//      修订号
//
//可以指定所有这些值,也可以使用“生成号”和“修订号”的默认值
//通过使用 "*",如下所示:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]

感兴趣的同学和读者,可以百度一下,这里不做过多讲解。

猜你喜欢

转载自blog.csdn.net/m0_47472749/article/details/109540335