Winform编程基础篇(1) WinForm代码结构

本文为转载文章,原文标题为C# Winform编程(1)基础篇,作者为songyulong,原文链接为https://songyulong.blog.csdn.net/article/details/133361675。本文仅为分享和传播信息的目的,如有侵权,请联系原作者进行删除。

WinForm代码结构

Form.cs和Form.Designer.cs其实是一个类,Visual Studio为了让我们方便管理,用partial关键字把窗体类给拆开了。

  1. Form.Designer.cs(窗体的设计类)存放窗体的布局,你的窗体定义了哪些控件,那些控件的名字、属性等等,都是存放在Form.Designer.cs里面的----最好不要在这里写/修改代码;
  2. 而Form.cs(窗体的逻辑类)则是用来存放处理方法的,比如你的按钮点击事件绑定了Button_Click这个方法,就会出现在Form.cs里;
  3. 而Form.resx则是用来存放你的窗体资源的,比如你自定义了你的窗体的图标,这个图标就会出现在Form.resx里面。

其实在早期版本的Visual Studio里,是没有Form.Designer.cs的,窗体的设计类和逻辑类全在一个文件里。 用partial关键字把窗体类拆开之后:便于管理。编程的时能够更加直观。
代码结构

程序入口Program.cs(自动生成)

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace WindowsFormsBase
{
    internal static class Program
    {
        /// <summary>
        /// 应用程序的主入口点。
        /// </summary>
        [STAThread]//单线程
        static void Main()
        {
            Application.EnableVisualStyles();//启动视觉样式
            Application.SetCompatibleTextRenderingDefault(false);//关闭GDI+渲染引擎,因为他是画图的,而winforms一般不需要进行图形绘制
            Application.Run(new Form1());// 设置哪个窗体文件首先被执行
        }
    }
}

为什么在vs中新建一个项目,默认就是将GDI+关闭呢

在 Visual Studio 中创建一个新的项目时,默认情况下确实是将 GDI+ 关闭的。这是因为 GDI+ 是一个用于图形绘制的 Windows 图形设备接口,如果你的项目不需要进行图形绘制操作,关闭 GDI+ 可以减少不必要的资源占用,提高项目性能。当你需要使用 GDI+ 进行图形绘制时,你可以手动启用 GDI+。你可以按照以下步骤进行操作:1. 打开 Visual Studio 中的项目。2. 在解决方案资源管理器中,右击项目,选择“属性”。3. 在属性页中找到“生成”选项卡。4. 在右侧的“高级”下拉菜单中找到“启用 GDI+”选项,将其设置为“是”。这样就可以在你的项目中启用 GDI+,并使用它进行图形绘制的相关操作了。需要注意的是,只有当你确实需要在项目中进行图形绘制时,才建议启用 GDI+,否则保持其关闭状态可以提高项目的性能和资源利用效率。

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 WinFormsBase
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent(); // Form1.Designer.cs里面定义初始化组件
        }

        private void Form1_Load(object sender, EventArgs e)
        {

        }
    }
}

Form1.Designer.cs

namespace WinFormsBase
{
    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)//dispose处理
        {
            if (disposing && (components != null))
            {
                components.Dispose();//执行与释放或重置非托管资源关联的应用程序定义的任务。
            }
            base.Dispose(disposing);//清理基类
        }

        
        // 加#region和#endregion的作用主要是  可以将这块区域的代码折叠起来,便于查看
        // 与 #region 同一行的后面 可以跟任意文字以对该区域进行说明。
        #region Windows 窗体设计器生成的代码

        /// <summary>
        /// 设计器支持所需的方法 - 不要修改
        /// 使用代码编辑器修改此方法的内容。
        /// </summary>
        private void InitializeComponent()
        {
            this.SuspendLayout();//暂停布局更新
            // 
            // Form1
            // 
            this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F);//确定窗口和按钮的像素点,高dpi高像素点,低dpi低像素点。只和分辨率有关,与后面用户更改窗口大小无关。
            this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;//根据系统设置字体大小,更改字体、控件、窗口的大小
            this.ClientSize = new System.Drawing.Size(800, 450);
            this.Name = "Form1";
            this.Text = "Form1";
            // 添加事件处理程序,以便在窗体的Load事件发生时(也就是窗体即将出现在屏幕上时)执行。
			// Form1_Load是一个方法,当窗体加载时,会自动调用这个方法。
			// 你可以在Form1.cs文件中找到这个方法的定义,并在其中添加代码,以便在窗体加载时初始化一些设置。
            this.Load += new System.EventHandler(this.Form1_Load);
			// 恢复布局更新并应用布局更改
			// 当你动态添加或移除控件时,可能不希望每次更改后都立即更新布局,可以在所有更改完成后恢复布局更新。
			//this.ResumeLayout()是用于恢复窗体布局更新的方法,它没有任何参数。它的作用是指示窗体在调用此方法后恢复对布局的更新,并立即应用布局更改。
			//对于参数this.ResumeLayout(false),这是一个常见的误解。该方法不接受参数,所以实际上不会有true或false的选项。在不接受参数的情况下,它的行为与不提供参数时是一样的,都是恢复布局更新并应用布局更改。
            this.ResumeLayout(false);

        }

        #endregion
    }
}

为什么基类也要dispose

在面向对象编程中,基类(base class)是指其他类继承的类。也可以称为父类、超类或顶级类。基类是被继承者的通用概念,它定义了一组共享的属性和方法,被继承者可以继承这些属性和方法,并在其基础上进行扩展或特化。
当一个类继承自另一个类时,被继承的类称为基类(或父类),而继承的类称为派生类(或子类)。派生类可以访问和使用基类的属性和方法,并且还可以添加自己的特定属性和方法。
基类的作用是提供通用的功能和行为,以便被继承者可以重用和扩展这些功能。通过继承基类,派生类可以获得基类的属性、方法和行为,同时还可以添加自己的特定功能。
基类在继承层次结构中的作用类似于模板或蓝图,它为继承者定义了一些共同的行为和属性,使得代码的重复使用和扩展变得更加容易和灵活。

意思是,比如,设置了两个类,男人类和人类,人类里设置了吃饭喝水,因为人类都是这样,所以男人类里没有写也没有重写吃饭喝水,,所以当我想dispose掉男人类的时候,也要把人类dispose掉,因为我可能会调用男人类的基类人类中吃饭喝水的功能,是这样吗

是的,你的理解是正确的。如果有一个基类叫做"人类",并且在这个基类中定义了共同的行为,比如"吃饭"和"喝水"方法。然后你创建了一个派生类叫做"男人类",如果"男人类"没有对这些方法进行重写或者添加新的行为,那么在释放或者dispose掉"男人类"的实例时,也要确保基类"人类"的资源也被释放。
这是因为当你调用"男人类"的实例时,它可以使用基类"人类"中定义的方法,比如"吃饭"和"喝水"。如果你释放了"男人类"的实例却没有释放基类的资源,那么当你在释放之后再次调用"男人类"的实例去执行"吃饭"和"喝水"的功能时,可能会出现错误或者不可预料的行为。
所以,在释放或者dispose掉"男人类"的实例时,确保在释放"男人类"的资源之前,先释放基类"人类"的资源是一个很好的做法,这样可以保证程序的正确性和稳定性。

为什么要使用SuspendLayout()进行暂停布局更新

调用SuspendLayout()方法后,窗体将不再实时计算和应用布局,而是暂时保持之前的布局状态。这意味着当你对窗体进行修改时,不会立即引发布局的重新计算和应用,从而提高了窗体的响应速度和用户体验。
当你完成对窗体的修改后,可以调用ResumeLayout()方法来恢复窗体的布局逻辑。在调用ResumeLayout()方法之后,窗体将重新计算和应用布局,使之与最新的修改保持一致。
综上所述,SuspendLayout()方法用于暂停窗体的布局逻辑,而ResumeLayout()方法用于恢复窗体的布局逻辑。这样可以在修改窗体时提高性能,并保证布局的准确性。

6F,12F是准确浮点数,为什么可以用来设置窗体自动缩放比例

this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F); 中的6F和12F是用来设置窗体的自动缩放比例的。
System.Drawing.SizeF 是一个结构,用于表示对象的尺寸,其中宽度和高度可以是任意浮点数。在这个例子中,6F 和 12F 是用来表示窗体的自动缩放比例的,而不是具体的尺寸。
它的基准值是 (6F, 12F),即水平方向是 6 倍缩放,垂直方向是 12 倍缩放。
您的窗口和控件会根据当前系统DPI与设计时预设的DPI(这里假定为6F水平和12F垂直)的比例来缩放大小。在设计时DPI是96时,按钮的尺寸是100x50像素(宽x高)。那么在DPI为576的显示器上,按钮的宽度应该会放大到600像素(100像素 * 6),也就是变成600x300像素。

所以他就是初始化窗口时,根据dpi确定窗口和按钮的像素点,而和用户对窗口进行缩放后,窗口和控件的尺寸无关,对吗

是的,理解得很对。AutoScaleDimensions与DPI(点每英寸)有关,而非用户调整窗口的大小。这意味着,在.NET应用程序中,当窗口对话框初始化时,AutoScaleDimensions的设置将根据系统DPI来调整窗口和控件的尺寸。如果系统DPI设置与设计时的DPI不同,那么控件会自动缩放以适应不同的显示设置。
一旦窗口初始化并根据DPI缩放完成,用户手动对窗口的缩放通常不会影响控件的尺寸,除非开发者编写了特定的代码来响应窗口大小的改变。AutoScaleMode属性决定了控件是如何随着DPI变化而自动缩放的。例如,如果AutoScaleMode被设置为Dpi,则控件将会根据显示器的DPI变化来缩放其大小;如果设置为Font,则控件大小会根据字体大小的变化来调整。
但是,窗口内的布局和大小通常由布局管理器控制,这可能会导致窗口中的控件在窗口大小变化时重新布局。但这些行为应该是在开发过程中明确设置的,而不是自动按比例缩放到窗口的当前尺寸。所以,用户对窗口大小的更改可能会导致布局变化,但并不直接影响由AutoScaleDimensions基于DPI设置的控件尺寸。

Dpi更改窗口和控件,字体又更改窗口和控件,为什么要重复更改

他们共同工作以确保 Windows Forms 应用程序在不同的显示设置下具有一致的外观。
AutoScaleDimensions 属性设置了窗体设计时使用的显示设备的 DPI 或“点每英寸”值。这里的 SizeF(6F, 12F) 并不是实际的 DPI 值,而是设计时的缩放因子,其中的 6F 和 12F 是以“点”为单位的宽度和高度值,它们通常由 Visual Studio 在设计时基于你的系统 DPI 设置自动生成。
AutoScaleMode 属性决定了窗体在运行时如何根据用户的系统 DPI 和字体大小设置进行缩放。当它被设置为 System.Windows.Forms.AutoScaleMode.Font,意味着窗体的缩放将基于字体的大小。
当你的窗体加载时,.NET Framework 会使用这两个属性来决定是否需要对窗体和其控件进行缩放,以及缩放的比例。如果用户的 DPI 设置与设计时的 DPI 设置不一致,或者如果用户改变了系统字体的大小,.NET Framework 将自动调整窗体和控件的大小,使得其在用户的显示设置上看起来仍然是预期的大小和布局。
这不是一种“重复更改”。**AutoScaleDimensions 是设计时的基准,AutoScaleMode 决定了运行时的缩放策略。**它们共同确保了无论用户的 DPI 设置或字体大小如何变化,应用程序的界面都能保持设计时的意图不变。

从Form1启动Form2

1.先添加窗体文件:右键项目->添加->窗体(Windows窗体)
2.修改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)
		 {
		     Form2 form2 = new Form2();
		     form2.Show(); // 窗口方式显示,允许在后台运行,Form1和Form2的鼠标焦点可随意切换
		     
		 }
		 private void button2_Click(object sender, EventArgs e)
		 {
		     Form2 form2 = new Form2();
		     form2.ShowDialog(); // 对话框方式显示,不允许在后台运行,必须先关闭Form2焦点才能切换到Form1
		 }
    }
}

对话框(Dialog)是一种特殊的窗体,它通常用于显示一些需要用户输入或进行确认的信息。在Windows Forms中,使用ShowDialog()方法来以对话框方式显示一个窗体。
对话框的特点是它会阻塞用户与其他窗体的交互,直到对话框关闭。当对话框打开时,用户无法与其他窗体进行交互,除非先关闭对话框。这是因为对话框通常用于提供重要的提示、警告或需要用户输入的场景,所以它需要用户的专注和响应。如果允许对话框在后台运行,用户可能会不小心忽略对话框或忽略对话框中的某些重要信息,从而导致不正确的操作或结果。为了确保用户能够及时地处理对话框,对话框被设计为阻塞用户与其他窗体的交互。
当需要在后台运行的情况下显示窗体时,可以使用普通窗体(Form)并使用Show()方法来显示。普通窗体不会阻塞用户与其他窗体的交互,用户可以在多个窗体之间自由切换。
总之,对话框是一种特殊的窗体,它需要用户的专注和响应,因此不允许在后台运行。而普通窗体则可以在后台运行并允许用户与其他窗体进行交互。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值