本篇是系列文章,专门介绍如何用C#上实现窗口和界面程序。值得注意的是,与VC++不同之处在于,VC是纯粹的面向对象,而C#是基于COM接口的编程方法,因此,按照VC++面向对象的MFC的思想无法理解C#,需要建立接口的概念。本篇将实现实验展示,并叙述接口思想。
假定已经安装好VS2019,然后建立C#的窗口程序。
1 创建新项目
2 选择C#窗口工程
3 给项目起名
然后进入创建窗口,点击【创建】按钮,就可以了。
在 Visual Studio 中创建新表单时,设计器会在 .Designer.cs 文件中生成以下代码:
- /// <summary>
- /// Required designer variable.
- /// </summary>
- private System.ComponentModel.IContainer components = null;
-
- /// <summary>
- /// Clean up any resources being used.
- /// </summary>
- /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
- protected override void Dispose(bool disposing)
- {
- if (disposing && (components != null))
- {
- components.Dispose();
- }
- base.Dispose(disposing);
- }
private System.ComponentModel.IContainer components = null;
它是窗体设计器自动生成的代码,作为组件的容器。当窗体上没有组建时,把它删掉, 删了也“无所谓”当窗体上有组件时就不能删了,删了会出现错误的。
也就是:他是管理组件的一个容器。
为了深刻理解,举个例子:
1.新建个窗体,删除了componment,这时没问题的
2.再往窗体拖拽个Timer组件,再看是不是有自动生成了个componment?回答是肯定的。
3.再把componment删了,看看还有没“所谓”,出错了吧!
4.这时其实componment已经不是null了,它已经被new了:this.components = new System.ComponentModel.Container();
components 变量的用途是什么?我的理论是,我应该将它用于我在 Designer 之外创建的表单拥有的任何 IDisposable 类(因为 Dispose 已经由 Designer 实现)。
因此,例如,如果我的表单拥有一种字体,我可以通过将其添加到这样的组件来确保它被处理:
- public partial class Form1 : Form
- {
- Font coolFont;
-
- public Form1()
- {
- InitializeComponent();
- this.coolFont = new Font("Comic Sans", 12);
- components.Add(this.coolFont);
- }
- }
当您向表单添加非 UI 组件(例如 Timer 组件)时,组件将成为这些组件的父级。设计器文件中的代码确保在处置表单时处置这些组件。如果您没有在设计时将任何此类组件添加到表单中,则组件将为空。
由于组件是设计器生成的,并且如果您在表单上没有非 UI 组件(在设计时),它将为空,我个人会选择以其他方式管理这些组件,将它们放置在表单关闭或类似的东西上。
我试图更深入地理解这一点。我曾尝试在设计时添加组件,但组件实例变量仍然始终为空。如果组件实例变量设置为 null 以外的值,我在哪里可以找到设置它的代码?
我通过添加来自设计器的 SerialPort 组件,在设计器生成的代码中设置组件实例变量。所以我现在明白了。我希望它在不使用时不会生成组件和 Dispose 代码,这样可以避免混淆并减少代码,但是 whatchucando
components 变量等效于表单的 Controls 变量。它跟踪表单上的所有控件。使一个窗体在关闭时可以自动处理所有控件,这是一项非常重要的清理工作。
表单类没有等效的成员来跟踪在设计时放置在其上的所有组件,因此设计人员会自动处理它。
请注意,将 Dispose() 方法从 Designer.cs 文件移动到主表单源代码文件是完全可以接受的。我强烈建议您这样做,没有理由以任何方式使 Form 类“特别”,它只是一个像其他任何类一样的托管类。在 base.Dispose 调用之前添加 Dispose() 调用以根据需要处理成员。
我们建立一个基本窗口,该窗口可以打开一个图片文件并显示;而且,可以保存成其它文件名称。如下:
1)首先按照第二节中建立空的窗口。
2)进入UI设计,并从IDE开发环境选【工具】菜单
3)选择三个按钮,改外观后,双击,自动引入空程序代码。
4)填充代码如下:
- 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 sharpC_first
- {
- public partial class Form1 : Form
- {
- public Form1()
- {
- InitializeComponent();
- }
- private string pathname = string.Empty;
- private void button1_Click(object sender, EventArgs e)
- {
- OpenFileDialog file = new OpenFileDialog();
- file.InitialDirectory = ".";
- file.Filter = "所有文件(*.*)|*.*";
- file.ShowDialog();
- if (file.FileName != string.Empty)
- {
- try
- {
- pathname = file.FileName; //获得文件的绝对路径
- this.pictureBox1.Load(pathname);
- }
- catch (Exception ex)
- {
- MessageBox.Show(ex.Message);
- }
- }
- }
-
- private void button2_Click(object sender, EventArgs e)
- {
- SaveFileDialog save = new SaveFileDialog();
- save.ShowDialog();
- if (save.FileName != string.Empty)
- {
- pictureBox1.Image.Save(save.FileName);
- }
- }
-
- private void button3_Click(object sender, EventArgs e)
- {
- this.Close();
- }
- }
- }
执行(不调试)菜单的选项,可以执行程序。如下:
1 点击【打开】:出现文件读入对话框。
2 显示如下
我们将以棋盘为例,实现一个可以对弈的象棋程序。下篇博文我们继续实现。