C#Windows窗体界面设计_07_多窗体设计

binzhouweichao@163.com

2013-10-20

需要在前面的项目上进行较大的修改。

前面的项目:

http://yunpan.cn/QbDEYRhANkiHk

本节的内容是:添加一个子窗口,用于设置绘图点数POINTCNT和放大倍数。同时,在状态栏添加两个显示点数和放大倍数的文本标签。


1. 为项目添加子窗体

打开项目TriPaint_20131013,右键,添加,Windows窗体:


将新的窗体命名为Settings.cs。



2. 为新窗体Settings添加控件

添加两个Label文本标签,用于显示提示;添加两个TextBox文本框,用于填写修改的点数和放大倍数;添加两个Button按钮,用于确定修改和取消。

打开Settings.cs[设计]文件,对新窗体Settings默认的属性不做修改。

打开左侧工具箱,分别添加上述所述的控件。

把第一个Label显示的文本修改为“Point Counts Setting:”,下面紧跟着一个TextBox,默认显示文本为“50”,也就是默认的点数为50。

把第二个Label显示的文本修改为“Scale Settings:”,下面紧跟着第二个TextBox,默认显示文本为“30”,也就是放大30倍。

再下面并排两个按钮Button,一个显示为OK,用于确认,另一个显示为Cancel,用于取消。

好吧。。。还是一个一个的截图修改吧、、

初始添加的控件如下:


选中label1,在右下角属性窗口中,修改其显示文本属性Text为:Point Count Setting:


然后修改其名称属性(Name)为:pointCntLabel


同理,修改label2,Text为Scale Setting:,(Name)为scaleLabel。


修改第一个TextBox(紧挨着lable1的那个)的名称(Name)为:pointCntText,显示文本Text为:50。


修改第二个TextBox(紧挨着label2)的名称(Name)为:scaleText,显示文本Text为:30。


修改第一个按钮button1的名称(Name)为:settingsOkButton,显示文本(Text)为:OK。


修改第二个按钮button2的名称(Name)为:settingsCancelButton,显示文本Text为:Cancel。



修改后的Settings窗体样式为:



3. 为主窗体TriPaint添加控件

在菜单栏添加一个调出子窗体Settings的菜单,名为Settings。在状态栏添加两个状态标签,分别用于显示当前设置的绘图点数和放大倍数。

打开TriPaint.cs[设计]文件,选中menuStrip1,在菜单栏添加Settings菜单:



选中statusStrip1,添加两个标签StatusLabel:


将toolStripStatusLabel2的文本属性Text改为:50,用于显示当前的绘图点数,将toolStripStatusLabel3的文本属性Text改为30,用于显示当前的放大倍数。修改后的TriPaint窗体界面为:



5. 完善代码

5.1 为TriPaint窗体的Settings菜单添加功能

功能为:点击Settings菜单调出子窗体Settings。

为了实现调出子窗体功能,需要在全局变量中,将子窗体Settings实例化。

打开GlobalVars.cs,在其尾部添加实例化Settings的代码:

        //创建子窗体Settings的静态实例对象
        private static Settings settings = new Settings();
        public static Settings SettingS
        {
            get { return settings; }
            set { settings = value; }
        }

在TriPaint.cs[设计]文件中,双击菜单Settings,自动生成settingsToolStripMenuItem_Click()函数,并关联Settings的Click事件,添加代码:

        private void settingsToolStripMenuItem_Click(object sender, EventArgs e)
        {
            GlobalVars.SettingS.Show();//调出子窗体Settings,也就是让其实例SettingS显示
        }

5.2 设置子窗体Settings类中按钮控件的功能

主要是设置OK按钮。

点击OK按钮实现的功能为:

a. 关闭子窗体Settings

b. 根据Settings窗体中两个文本中重置的数据,对绘图进行重新操作,主要是

b1. 由pointCntText的数值,重新构建绘图数据数组data。

b2. 由scaleText的数值,重新设置画布的坐标系的放大倍数,并重新绘图


打开Settings.cs[设计]文件,双击OK按钮,自动生成settingsOkButton_Click()事件函数,并自动关联OK按钮的Click事件。

a. 首先添加关闭窗体Settings的代码:

            this.Hide();//关闭子窗体Settings

由于是在该窗体类的内部进行,所以使用this指针来操作该类即可。


b. 

b1. 其次,对绘图数据data的重新构建。

因为data已经被定义为静态数组,也就是在程序运行时,已经确定好了数组的大小,并分配了内存。所以如果想要重新设置大小,只能重新对其赋值为一个新的对象。

这样,对构建Data数据的所有全局变量,都需要做一番修改,比如POINTCNT,比如xInternal等等。

打开GlobalVars.cs,将其中对POINTCNT定义赋值的部分修改为:

        //public const int POINTCNT = 50;//点数,POINTCNT <= XMAX - XMIN  
        private static int pointcnt = 50;
        public static int POINTCNT
        {
            set { pointcnt = value; }
            get { return pointcnt; }
        }

将xInterval定义赋值部分修改为:

        //public float xInterval = (XMAX - XMIN) / (POINTCNT - 1);//i增量对应的data.X增量
        private static float xinterval = (XMAX - XMIN) / (POINTCNT - 1);
        public static float xInterval
        {
            get { return xinterval; }
            set { xinterval = value; }
        }

这样,就可以在Settings中对data重建了。

回到Settings.cs中对OK按钮的Click事件的响应函数settingsOkButton_Click()。

首先,更改点数的全局变量为pointCntText的值:

            GlobalVars.POINTCNT = int.Parse(pointCntText.Text);//修改点数为textbox1的值

其次,修改x关于i的增量xInterval:

            GlobalVars.xInterval = (GlobalVars.XMAX - GlobalVars.XMIN) / (GlobalVars.POINTCNT - 1);//根据点数重新设置x关于i的增量

然后,新建data的实例,然后赋值:

            GlobalVars.Data = new PointF[GlobalVars.POINTCNT];//重置data的实例对象
            for (int i = 0; i < GlobalVars.POINTCNT; i++)
            {
                GlobalVars.Data[i].X = i * GlobalVars.xInterval;
                GlobalVars.Data[i].Y = (float)(Math.Sin(GlobalVars.Data[i].X));
            }

b2. 再然后,销毁原先的位图b,根据新设置的放大倍数,调整坐标系,重建位图b。

这需要设置一个放大倍数全局变量。在GlobalVars.cs中添加:

        //放大倍数
        private static int scaleNum = 30;
        public static int ScaleNum
        {
            set { scaleNum = value; }
            get { return scaleNum; }
        }

再回到Settings.cs中,重建位图b,并在pictureBox1中重新绘制,并显示:

            //重建位图b
            GlobalVars.ScaleNum = int.Parse(scaleText.Text);//获取放大倍数
            GlobalVars.B = new Bitmap(GlobalVars.triPaint.PicW, GlobalVars.triPaint.PicH);//重建位图b实例,如果不加此条,则在原图上叠加
            Graphics g = Graphics.FromImage(GlobalVars.B);//图像画布添加绘图

            //坐标系平移镜像
            g.TranslateTransform(0, GlobalVars.triPaint.PicH / 2);//先平移,原点平移到左边框中点
            g.ScaleTransform(1, -1);//关于x轴对称
            g.ScaleTransform(GlobalVars.ScaleNum, GlobalVars.ScaleNum);//放大30倍,x与y等同放大
            
            Pen p = new Pen(Color.Blue, 1 / GlobalVars.ScaleNum);//画笔缩放30倍

            g.DrawLines(p, GlobalVars.Data);//多点绘图,直线连接

            //释放绘图所占用资源
            p.Dispose();
            g.Dispose();

            //显示重绘的图像
            MyFunctions.ShowImage();

为了使得重绘后的点数和放大倍数在状态栏显示,需要在主窗体TriPaint类中,在绘图事件函数pictureBox1_Paint()中添加代码:

            this.toolStripStatusLabel2.Text = GlobalVars.POINTCNT.ToString();//更新状态栏显示的点数
            this.toolStripStatusLabel3.Text = GlobalVars.ScaleNum.ToString();//更新状态栏显示的放大倍数

这样,OK按钮的功能就都实现了。

下面再添加Cancel按钮的功能。

功能很简单,只关闭子窗体Settings,并将修改的值还原成上次生效的值,在下次打开Settings时,两个文本框的值还原。

在Settings.cs[设计]文件中,选中Cancel按钮,双击,自动生成代码settingsCancelButton_Click(),并自动关联Cancel按钮的Click事件。添加代码:

            this.Hide();//子窗体Settings隐藏

上次生效的值已经缓存在了状态栏的文本标签上,所以,只需要将状态栏的后两个标签开放,供子窗体Settings使用即可。

在主窗体TriPaint的类中(即TriPaint.cs),开放控件toolStripStatusLabel2和toolStripStatusLabel3的文本Text的只读属性:

        //公开toolStripStatusLabel2和toolStripStatusLabel2的Text的只读属性,共Settings读取
        public string statusPointCntText
        {
            get { return toolStripStatusLabel2.Text; }
        }
        public string statusScaleText
        {
            get { return toolStripStatusLabel3.Text; }
        }

回到Settings的Cancel按钮,添加还原文本框数值的代码:

            this.pointCntText.Text = GlobalVars.triPaint.statusPointCntText;//还原点数文本框
            this.scaleText.Text = GlobalVars.triPaint.statusScaleText;//还原放大倍数文本框


总体上,代码已经修改完成。

其中有一个bug,就是如果关掉Settings窗体时,使用的是窗体右上角的x,而不是OK或Cancel按钮的话,下次再点Settings菜单,想要弹出Settings窗体,是会报错的,错误原因是当前的对象已经释放,也就是通过窗体的x,已经将初始化时实例化的对象SettingS释放掉了。所以,一种方法是在关闭子窗体时不释放资源,另一种方法是禁用子窗体Settings的右上角的关闭x。

我们采用第二种方法,经用子窗体的关闭x。

打开Settings.cs[设计]文件,在右下方属性窗口中,选择事件视图,找到FormClosing事件


该事件的释义为:

FormClosing :在窗体关闭时,FormClosing 事件发生。窗体关闭时,此事件会得到处理,从而释放与此窗体关联的所有资源。如果取消此事件,则该窗体保持打开状态。
若要取消窗体的关闭操作,请将传递给事件处理程序的 FormClosingEventArgs 的 Cancel 属性设置为 true。

参考:http://wenku.baidu.com/view/a735ba65011ca300a6c39010.html

双击FormClosing事件,在Settings中自动生成Settings_FormClosing()事件函数,自动关联FormClosing事件,在里面添加禁止关闭的代码:

        private void Settings_FormClosing(object sender, FormClosingEventArgs e)
        {
            e.Cancel = true;
        }

至此,所有修改过的代码的终稿如下:

TriPaint.cs

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace TriPaint_20131013
{
    public partial class TriPaint : Form
    {


        public TriPaint()
        {
            InitializeComponent();
            //在这里添加代码
            //对数据进行处理  
            /* 
            for (int i = 0; i < GlobalVars.POINTCNT; i++) 
            { 
                GlobalVars.Data[i].X = (int)(i * GlobalVars.xInterval);//i对应的data.X 
                GlobalVars.Data[i].Y = (int)(GlobalVars.times * Math.Sin(GlobalVars.Data[i].X / GlobalVars.times));//sin函数求值 
                GlobalVars.Data[i].Y = (int)(GlobalVars.Data[i].Y + GlobalVars.times * 1);//Y轴向正向平移1,即1*times,令最高点(也就是3π/2对应的-1点)的值为0 
            } 
             * */
            //直接运算,倍数及平移稍后处理  
            for (int i = 0; i < GlobalVars.POINTCNT; i++)
            {
                GlobalVars.Data[i].X = i * GlobalVars.xInterval;
                GlobalVars.Data[i].Y = (float)(Math.Sin(GlobalVars.Data[i].X));
            }  

        }

        //公开pictureBox1的Width和Height属性,仅供读取
        public int PicW
        {
            get { return pictureBox1.Width; }
        }
        public int PicH
        {
            get { return pictureBox1.Height; }
        }

        //公开statusLabel的Text属性,供读写
        public string StatusText
        {
            get { return toolStripStatusLabel1.Text; }
            set { toolStripStatusLabel1.Text = value; }
        }

        //公开pictureBox1的Image属性,供读写
        public Image PicImage
        {
            get { return pictureBox1.Image; }
            set { pictureBox1.Image = value; }
        }

        //公开pictureBox1的私有方法Refresh()
        public void PicRefresh()
        {
            pictureBox1.Refresh();
        }

        //公开toolStripStatusLabel2和toolStripStatusLabel2的Text的只读属性,共Settings读取
        public string statusPointCntText
        {
            get { return toolStripStatusLabel2.Text; }
        }
        public string statusScaleText
        {
            get { return toolStripStatusLabel3.Text; }
        }

        private void TriPaint_Load(object sender, EventArgs e)
        {
            //Graphics g = this.CreateGraphics();//画板
            //this.Show();//显示
            //Bitmap b = new Bitmap(pictureBox1.Width, pictureBox1.Height);//新建图像画布
            Graphics g = Graphics.FromImage(GlobalVars.B);//图像画布添加绘图

            //坐标系平移镜像
            //g.TranslateTransform(0, 100);//向y正向平移300
            //g.ScaleTransform(1, -1);//关于x轴镜像
            g.TranslateTransform(0, pictureBox1.Height / 2);//先平移,原点平移到左边框中点
            g.ScaleTransform(1, -1);//关于x轴对称
            g.ScaleTransform(30, 30);//放大30倍,x与y等同放大

            //Pen p = new Pen(Color.Blue, 1);//画笔
            Pen p = new Pen(Color.Blue, 1 / 30);//画笔缩放30倍

            g.DrawLines(p, GlobalVars.Data);//多点绘图,直线连接

            //pictureBox1.Image = b;//图像框的图像为上述绘图生成的图像

            //释放绘图所占用资源
            p.Dispose();
            g.Dispose();
            //b.Dispose();
        }

        //自定义显示图片函数
        public void showImage()
        {
            pictureBox1.Image = GlobalVars.B;//显示图像b
            pictureBox1.Refresh();//刷新图片框
        }
        //自定义隐藏图片函数
        public void hideImage()
        {
            pictureBox1.Image = null;//图片置空
            pictureBox1.Refresh();//刷新图片框
        }

        private void button1_Click(object sender, EventArgs e)
        {
            //pictureBox1.Image = GlobalVars.B;//显示图像b
            //pictureBox1.Refresh();//刷新图片框
            //showImage();//显示图片
            MyFunctions.ShowImage();
        }

        private void button2_Click(object sender, EventArgs e)
        {
            //pictureBox1.Image = null;//对Image的值置空,刷新后图像就消失了
            //pictureBox1.Refresh();
            //hideImage();//隐藏图片
            MyFunctions.HideImage();
        }

        private void showToolStripMenuItem_Click(object sender, EventArgs e)
        {
            //pictureBox1.Image = GlobalVars.B;//显示图像b
            //pictureBox1.Refresh();//刷新图片框
            //showImage();//显示图片
            MyFunctions.ShowImage();
        }

        private void hideToolStripMenuItem_Click(object sender, EventArgs e)
        {
            //pictureBox1.Image = null;//对Image的值置空,刷新后图像就消失了
            //pictureBox1.Refresh();
            //hideImage();//隐藏图片
            MyFunctions.HideImage();
        }

        private void toolStripButton1_Click(object sender, EventArgs e)
        {
            //pictureBox1.Image = GlobalVars.B;//显示图像b
            //pictureBox1.Refresh();//刷新图片框
            //showImage();//显示图片
            MyFunctions.ShowImage();
        }

        private void toolStripButton2_Click(object sender, EventArgs e)
        {
            //pictureBox1.Image = null;//对Image的值置空,刷新后图像就消失了
            //pictureBox1.Refresh();
            //hideImage();//隐藏图片
            MyFunctions.HideImage();
        }

        private void pictureBox1_Paint(object sender, PaintEventArgs e)
        {
            if (pictureBox1.Image == null)//如果图像为空
            {
                //toolStripStatusLabel1.Text = "Hide";//则显示Hide
                GlobalVars.StatusText = "Hide";
            }
            else//否则,即图像不为空,有具体的BMP位图
            {
                //toolStripStatusLabel1.Text = "Show";//则显示Show
                GlobalVars.StatusText = "Show";
            }

            this.toolStripStatusLabel2.Text = GlobalVars.POINTCNT.ToString();//更新状态栏显示的点数
            this.toolStripStatusLabel3.Text = GlobalVars.ScaleNum.ToString();//更新状态栏显示的放大倍数
        }

        private void settingsToolStripMenuItem_Click(object sender, EventArgs e)
        {
            GlobalVars.SettingS.Hide();
            GlobalVars.SettingS.Show();//调出子窗体Settings,也就是让其实例SettingS显示
        }

    }
}

Settings.cs

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace TriPaint_20131013
{
    public partial class Settings : Form
    {
        public Settings()
        {
            InitializeComponent();
        }

        private void settingsOkButton_Click(object sender, EventArgs e)
        {
            this.Hide();//关闭子窗体Settings

            //重新构建绘图数据
            GlobalVars.POINTCNT = int.Parse(pointCntText.Text);//修改点数为textbox1的值
            GlobalVars.xInterval = (GlobalVars.XMAX - GlobalVars.XMIN) / (GlobalVars.POINTCNT - 1);//根据点数重新设置x关于i的增量
            GlobalVars.Data = new PointF[GlobalVars.POINTCNT];//重置data的实例对象
            for (int i = 0; i < GlobalVars.POINTCNT; i++)
            {
                GlobalVars.Data[i].X = i * GlobalVars.xInterval;
                GlobalVars.Data[i].Y = (float)(Math.Sin(GlobalVars.Data[i].X));
            }

            //重建位图b
            GlobalVars.ScaleNum = int.Parse(scaleText.Text);//获取放大倍数
            GlobalVars.B = new Bitmap(GlobalVars.triPaint.PicW, GlobalVars.triPaint.PicH);//重建位图b实例,如果不加此条,则在原图上叠加
            Graphics g = Graphics.FromImage(GlobalVars.B);//图像画布添加绘图

            //坐标系平移镜像
            g.TranslateTransform(0, GlobalVars.triPaint.PicH / 2);//先平移,原点平移到左边框中点
            g.ScaleTransform(1, -1);//关于x轴对称
            g.ScaleTransform(GlobalVars.ScaleNum, GlobalVars.ScaleNum);//放大30倍,x与y等同放大
            
            Pen p = new Pen(Color.Blue, 1 / GlobalVars.ScaleNum);//画笔缩放30倍

            g.DrawLines(p, GlobalVars.Data);//多点绘图,直线连接

            //释放绘图所占用资源
            p.Dispose();
            g.Dispose();

            //显示重绘的图像
            MyFunctions.ShowImage();

        }

        private void settingsCancelButton_Click(object sender, EventArgs e)
        {
            this.Hide();//子窗体Settings隐藏
            this.pointCntText.Text = GlobalVars.triPaint.statusPointCntText;//还原点数文本框
            this.scaleText.Text = GlobalVars.triPaint.statusScaleText;//还原放大倍数文本框
        }

        private void Settings_FormClosing(object sender, FormClosingEventArgs e)
        {
            e.Cancel = true;
        }
        
    }
}

GlobalVars.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;

namespace TriPaint_20131013
{
    //修改这里
    static class GlobalVars
    {
        //类似于#define宏定义,设置三个常量
        //public const int POINTCNT = 50;//点数,POINTCNT <= XMAX - XMIN  
        private static int pointcnt = 50;
        public static int POINTCNT
        {
            set { pointcnt = value; }
            get { return pointcnt; }
        }
        //public const int XMAX = 200;//X轴最大值,也就是2π对应的值    
        //public const int XMIN = 0;//X轴最小值  
        //public const double times = (XMAX - XMIN) / (2 * Math.PI - 0);//放大倍数  
        public const float XMAX = (float)(2 * Math.PI);//不放大情况下的x的最大值  
        public const float XMIN = 0F;//不放大情况下x的最小值  
        //public float xInterval = (XMAX - XMIN) / (POINTCNT - 1);//i增量对应的data.X增量
        private static float xinterval = (XMAX - XMIN) / (POINTCNT - 1);
        public static float xInterval
        {
            get { return xinterval; }
            set { xinterval = value; }
        }
        //类似于全局变量,可以重新赋值  
        /* 
        //坐标点变量 
        private static Point[] data = new Point[POINTCNT]; 
        public static Point[] Data 
        { 
            get { return data; } 
            set { data = value; } 
        } 
         * */
        //使用调整坐标系Scale的方法调整视图,对原始数据运算不做处理  
        private static PointF[] data = new PointF[POINTCNT];
        public static PointF[] Data
        {
            get { return data; }
            set { data = value; }
        }  

        //位图b,为pictureBox1.Image使用的值
        //private static Bitmap b = new Bitmap(250, 250);
        //private static Bitmap b = new Bitmap(new TriPaint().PicW, new TriPaint().PicH);
        //创建主窗体TriPaint类的静态实例
        private static TriPaint tripaint = new TriPaint();
        public static TriPaint triPaint
        {
            get { return tripaint; }
            set { tripaint = value; }
        }
        private static Bitmap b = new Bitmap(triPaint.PicW, triPaint.PicH);
        public static Bitmap B
        {
            get { return b; }
            set { b = value; }
        }

        //创建StatusText全局变量,通过实例triPaint进行传递
        public static string StatusText
        {
            get { return triPaint.StatusText; }
            set { triPaint.StatusText = value; }
        }

        //创建子窗体Settings的静态实例对象
        private static Settings settings = new Settings();
        public static Settings SettingS
        {
            get { return settings; }
            set { settings = value; }
        }

        //放大倍数
        private static int scaleNum = 30;
        public static int ScaleNum
        {
            set { scaleNum = value; }
            get { return scaleNum; }
        }
    }
}


结果图:


注:点数应该大于1,当然,等于1也不会报错,但是因为1个点没法连线,所以图像上什么都不显示。放大倍数应该为正值。负值在左边框的左侧,图像上无法显示。

这两个只都为数字,不能使用字母,虽然程序中没有做限制。。


项目终稿代码:

http://yunpan.cn/QbpeYiaBEUATu

C#Windows窗体界面设计到此结束。以后进行实际的项目,如果有时间会同步更新。


展开阅读全文

没有更多推荐了,返回首页