C#实例:多功能Windows窗体应用程序Helloworld_WinForm

有了创建一个Windows窗体应用程序的经验,就可以开始尝试运用更多的控件实现更多丰富的功能界面。以下分享我基于项目Helloworld_WinForm使用常用C#Windows窗体控件实现一些小功能。

每一节标题为所用到的控件,全文以实际制作过程为序编制。


目录

  • WinForm窗体应用程序开发步骤
  • 常用控件实例
    • MenuStrip 菜单栏
    • richTextBox富文本框
    • SaveFileDialog保存对话框
    • FontDialog字体对话框
    • richTextBox的属性WordWrap
    • ColorDialog颜色对话框
    • Timer计时器
    • PictureBox-如何加文字
    • PictureBox-画图
  • 问题与解决
    • 解决子窗体被父窗体控件挡住问题
  • 发布做好的程序


WinForm窗体应用程序开发步骤

1、创建窗体Form

项目创建时会默认创建一个窗体,默认为父窗体。
新建的其他窗体为子窗体,子窗体调用时会在父窗体中显示。
项目创建方法见:Helloworld_WinForm,本文直接基于之前创建的项目搭建功能。

2、创建控件Control

控件显示在工具箱中,通过双击或拖拽的方式显示在当前打开的设计窗口中,可在属性栏修改其属性。

3、指定布局Layout

根据应用拖动控件位置,或在属性中调整坐标等。

4、响应事件Event

事件包括双击控件、按下鼠标、向文本框输入内容等等,可以在控件属性中点击事件图标查看所有事件。
响应是指发生事件后,触发的操作,通常以代码的形式实现功能。

描述还是比较抽象,建议动手实践。

常用控件实例

MenuStrip 菜单栏

新建MenuStrip控件,修改属性如下

  • Name:tools
  • Text:工具
    在工具下,继续新建TextBox,修改它们属性的Text。

如果在子窗体中也加入Menustrip,则需在父窗体的Menustrip属性中按下图所示修改,否则子窗体菜单栏不会显示出来,默认二者菜单栏合并。
C#实例:多功能Windows窗体应用程序Helloworld_WinForm_第1张图片
父窗体:
C#实例:多功能Windows窗体应用程序Helloworld_WinForm_第2张图片
子窗体:
C#实例:多功能Windows窗体应用程序Helloworld_WinForm_第3张图片

richTextBox富文本框

参考链接
在项目中右键添加子窗体,命名Text。
Anchor属性选择“Top,Bottom,Left,Right”,这样当窗体大小改变时,RichTextBox控件的大小也会跟着改变
C#实例:多功能Windows窗体应用程序Helloworld_WinForm_第4张图片

新建 richTextBox控件。属性BackColor改为ControlLightLiight,ReadOnly改为True。修改Dock属性为Fill,使控件铺满窗口。
C#实例:多功能Windows窗体应用程序Helloworld_WinForm_第5张图片

将父窗体属性中的IsMdiContainer改为true。
并双击父窗体菜单栏的“新建”,编辑程序,使点击新建时打开子窗体。

private void toolStripTextBox3_Click(object sender, EventArgs e)
        {
            Text newMDIChild = new Helloworld_WinForm.Text();
            // Set the Parent Form of the Child window.
            newMDIChild.MdiParent = this;
            // Display the new form.
            newMDIChild.Show();
        }

SaveFileDialog保存对话框

参考链接:c#保存textbox中的字符串到txt文件中
点击记事本的【文件】→【保存】菜单项时,使用SaveFileDialog保存文件。

用程序创建SaveFileDialog及修改属性。

		// 菜单栏中的保存按钮。也可用Button
		private void 保存ToolStripMenuItem_Click(object sender, EventArgs e)
        {
        	// 新建SaveFileDialog,Name为saveFileDialog
            SaveFileDialog saveFileDialog = new SaveFileDialog();
            // 修改属性,定义保存文件类型
            saveFileDialog.Filter = "(*.txt)|*.txt|(*.*)|*.*|97-2003Word文档|*.doc";
            // 文件名是日期时间
            saveFileDialog.FileName = "D:\\text\\" + DateTime.Now.ToString("yyyyMMddHHmm") + ".txt";
            // 对话框打开
            if (saveFileDialog.ShowDialog() == DialogResult.OK)
            {
            	// 新建数据流
                StreamWriter streamWriter = new StreamWriter(saveFileDialog.FileName, true);
                // 写入数据
                streamWriter.Write(this.richTextBox1.Text);
                // 关闭当前streamWriter对象和基础流
                streamWriter.Close();
            }
        }

		// 富文本,Name为richTextBox1
        private void richTextBox1_TextChanged_1(object sender, EventArgs e)
        {

        }

上述程序启动后,点击保存,会弹出保存窗口,如下:
C#实例:多功能Windows窗体应用程序Helloworld_WinForm_第6张图片
可以选择保存为txt或doc格式。

试一试效果:
C#实例:多功能Windows窗体应用程序Helloworld_WinForm_第7张图片

FontDialog字体对话框

继续增加菜单栏选项:字体。其属性Name为字体ToolStripMenuItem。
C#实例:多功能Windows窗体应用程序Helloworld_WinForm_第8张图片
双击字体,编写代码,新建字体对话框,并将设置的字体赋给富文本中的Text。

		private void 字体ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            FontDialog fontDialog = new FontDialog();
            if(fontDialog.ShowDialog() == DialogResult.OK)
            {
                richTextBox1.SelectionFont = fontDialog.Font;
            }
        }

试一下效果:
先设置字体,再输入文本。也可在输入文本后,选中需要修改字体的文本,再点击字体修改。
C#实例:多功能Windows窗体应用程序Helloworld_WinForm_第9张图片
C#实例:多功能Windows窗体应用程序Helloworld_WinForm_第10张图片

richTextBox的属性WordWrap

增加菜单栏选项:自动换行。其Name属性为自动换行ToolStripMenuItem。

自动换行的Checked属性默认为“False”,文本内容按照文本框的宽度自动换行,否则只按段落标记换行。

可以修改富文本属性WordWrap,以决定是否默认自动换行,此处为默认自动换行:
C#实例:多功能Windows窗体应用程序Helloworld_WinForm_第11张图片
将自动换行选项的默认状态Checked改为被点击的True状态:
C#实例:多功能Windows窗体应用程序Helloworld_WinForm_第12张图片
双击自动换行,编辑代码如下:

        private void 自动换行ToolStripMenuItem_Click(object sender, EventArgs e)
        {
        	// 判断自动换行状态标记
            if(自动换行ToolStripMenuItem.Checked == false)
            {
            	// 被按下后更新状态
                自动换行ToolStripMenuItem.Checked = true;
                // 自动换行
                richTextBox1.WordWrap = true;
            }
            else
            {
            	// 被按下后更新状态
                自动换行ToolStripMenuItem.Checked = false;
                // 不自动换行
                richTextBox1.WordWrap = false;
            }
        }

实现的效果就是默认自动换行,点击自动换行后取消自动换行,再次点击则变为自动换行。

ColorDialog颜色对话框

利用ColorDialog修改字体颜色。
增加菜单栏字体颜色,其Name属性为字体颜色ToolStripMenuItem。

双击它编辑代码如下:

// 第一种
		private void 字体颜色ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            ColorDialog colorDialog = new ColorDialog();
            if (colorDialog.ShowDialog() == DialogResult.OK)
            {
                richTextBox1.SelectionColor = colorDialog.Color;
            }
        }

试一下效果:
若先设置字体颜色,再输入文本,则此前输入的文本不会变化,变更只适用于此后输入的文本。
也可在输入文本后,选中需要修改字体颜色的文本,再点击字体颜色修改,变更适用于选中的文本。
C#实例:多功能Windows窗体应用程序Helloworld_WinForm_第13张图片
修改为橙色:
C#实例:多功能Windows窗体应用程序Helloworld_WinForm_第14张图片

如果在未选中文本时修改字体颜色,要将所有文本字体颜色同时修改,则可以这样写:
选中文本再修改颜色,只会修改选中文本的颜色。

// 第二种
		private void 字体颜色ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            ColorDialog colorDialog = new ColorDialog();
            if (this.colorDialog1.ShowDialog() == DialogResult.OK)
            {
                if (this.richTextBox1.SelectedText == "") // 若未选中文本,则将设置颜色适用于所有文本
                {
                    this.richTextBox1.ForeColor = this.colorDialog1.Color;
                }
                else
                {
                    this.richTextBox1.SelectionColor = this.colorDialog1.Color;
                }
            }
        }

Timer计时器

参考链接
在项目中新建Windows窗体,命名为Clock.cs。
在父窗体中,双击菜单栏Clock,编写代码,添加子窗体Clock。属性BackColor改为ControlLightLiight,ReadOnly改为True。
代码如下:

		private void toolStripTextBox2_Click(object sender, EventArgs e)
        {
            Clock newMDIChild = new Helloworld_WinForm.Clock();
            // Set the Parent Form of the Child window.
            newMDIChild.MdiParent = this;
            // Display the new form.
            newMDIChild.Show();
        }

在Clock窗体中,拖拽Label控件,Name为label1,修改属性字体颜色为喜欢的字体。修改属性Text为yyyy-MM-dd HH:mm:ss。
C#实例:多功能Windows窗体应用程序Helloworld_WinForm_第15张图片
拖拽Timer计时器控件,Name为timer1,修改属性Enable为True,Interval为1000。使能定时,每1000ms执行一次函数timer1_Tick中的内容。
C#实例:多功能Windows窗体应用程序Helloworld_WinForm_第16张图片
双击timer1,编写代码,使其显示实时时间。

        private void timer1_Tick(object sender, EventArgs e)
        {
            label1.Text = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");  //年-月-日 小时:分钟:秒
        }

其中,HH为24小时进制,hh为12小时进制。

让Label文字居中的方法:设置Autosize的值为false,拉大这个label框的宽度,设置label属性里的TextAlign为MiddleCenter,意思是让框里的文字内容居中。
C#实例:多功能Windows窗体应用程序Helloworld_WinForm_第17张图片
启动后效果如下:每过一秒,时间更新一次。
C#实例:多功能Windows窗体应用程序Helloworld_WinForm_第18张图片

PictureBox-如何加文字

参考链接
在父窗口的菜单栏工具中添加一项:Panel。并添加子菜单 加水印 和 清屏。本节实现加水印的功能,后一节实现清屏。
C#实例:多功能Windows窗体应用程序Helloworld_WinForm_第19张图片

从工具箱拖拽一个PictureBox控件到窗口,属性Dock改为Fill。
属性BackgroundImage可以上传一个图片,使PictureBox控件区域默认显示该图片。
还有SizeMode属性选Zoom,SizeMode属性包含:

  • Normal:图片大小不变;
  • strechImage:拉伸图片适应PictureBox(图片会变形)
  • AutoSize:PictureBox适应图片;
  • CenterImage:图片居中显示;
  • Zoom:图片填充PictureBox(不变形)

双击“加水印”,编辑程序如下:实现将文字显示在对应坐标。

		private void 加水印ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            // 在pictureBox上创建画图板
            Graphics g = pictureBox1.CreateGraphics();
            // 设置字体的样式
            Font f = new Font("黑体", 24);
            // 实例化一个实心画刷,颜色是白色
            SolidBrush brush = new SolidBrush(Color.White);
            // 与左上角坐标的距离
            PointF point = new PointF(400, 300);
            // 开始绘制
            g.DrawString("From: Electrical_IT", f, brush, point);
        }

启动运行,点击加水印,效果如下:
C#实例:多功能Windows窗体应用程序Helloworld_WinForm_第20张图片

PictureBox-画图

参考链接:C#控件picturebox实现画图功能
C#控件画图方法
打开指定路径图片的方法
本部分实现鼠标在PictureBox区域中使用鼠标绘制的功能。
PictureBox控件属性设置参考上一节。菜单栏也如上一节添加。

要实现绘图功能,需要用到PictureBox的事件响应,位置在PictureBox的属性框中,点击PictureBox,点击事件图标即可看到:
C#实例:多功能Windows窗体应用程序Helloworld_WinForm_第21张图片
重命名事件MouseDown为drawstart,事件MouseMove为drawmove,事件MouseUp为drawstop。
每次命名后会自动切换到代码编辑界面。

修改代码如下:

        private void 清屏ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            Graphics g = pictureBox1.CreateGraphics();
            // 用原背景图清屏
            g.DrawImage(pictureBox1.BackgroundImage, 0, 0);
        }

        // 定义鼠标绘制的终点(起点永远是鼠标当前坐标)
        private Point endpoint;
        // 绘制标志
        private static bool drawing = false;
        private void drawstart(object sender, MouseEventArgs e)
        {
            // 创建终点
            endpoint = new Point(e.X, e.Y);
            // 鼠标按下开始绘制
            drawing = true;
        }

        private void drawstop(object sender, MouseEventArgs e)
        {
            // 鼠标松开结束绘制
            drawing = false; 
        }

        private void drawmove(object sender, MouseEventArgs e)
        {
            // 鼠标移动进行绘制,创建画布
            Graphics g = pictureBox1.CreateGraphics();
            // 显示时消除锯齿
            g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;
            // 如果鼠标按下的按钮是左键
            if(e.Button == MouseButtons.Left)
            {
                if(drawing)
                {
                    // 当前坐标
                    Point currentpoint = new Point(e.X, e.Y);
                    // 用白蓝色笔绘制连接p2和当前坐标的线
                    g.DrawLine(new Pen(Color.AliceBlue, 2), endpoint, currentpoint);
                    // 更新终点坐标
                    endpoint.X = currentpoint.X;
                    endpoint.Y = currentpoint.Y;
                }
            }
        }

用鼠标画一画,绘制效果如下:
C#实例:多功能Windows窗体应用程序Helloworld_WinForm_第22张图片
点击清屏后效果如下:(清屏也会把水印清掉)
C#实例:多功能Windows窗体应用程序Helloworld_WinForm_第23张图片
如果清屏想用白色清屏,参考以下代码:

		private void 清屏ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            Graphics g = pictureBox1.CreateGraphics();
            g.Clear(Color.White);
        }

问题与解决

解决子窗体被父窗体控件挡住问题

上述实例先创建了子窗体Hello、Clock和Text,再在父窗体中添加了控件PictureBox。
启动后,点击菜单栏Hello、Clock和文件新建时,子窗体无法显示在PictureBox控件前,原因是被父窗口的控件挡住了。

我的解决方法是在打开子窗体前,将父窗体中的控件PictureBox隐藏,点击Panel后再显示PictureBox控件。

隐藏:pictureBox1.Hide();
显示:pictureBox1.Show();

首先将HelloWorld.cs中,菜单点击事件的响应程序里添加隐藏控件的函数:

		 private void toolStripTextBox1_Click(object sender, EventArgs e)
        {
            Hello newMDIChild = new Helloworld_WinForm.Hello();
            // Set the Parent Form of the Child window.
            newMDIChild.MdiParent = this;
            // Hide the pictureBox1
            pictureBox1.Hide();
            // Display the new form.
            newMDIChild.Show();
        }

        private void toolStripTextBox3_Click(object sender, EventArgs e)
        {
            Text newMDIChild = new Helloworld_WinForm.Text();
            // Set the Parent Form of the Child window.
            newMDIChild.MdiParent = this;
            //Hide the pictureBox1
            pictureBox1.Hide();
            // Display the new form.
            newMDIChild.Show();
        }

        private void toolStripTextBox2_Click(object sender, EventArgs e)
        {
            Clock newMDIChild = new Helloworld_WinForm.Clock();
            // Set the Parent Form of the Child window.
            newMDIChild.MdiParent = this;
            //Hide the pictureBox1
            pictureBox1.Hide();
            // Display the new form.
            newMDIChild.Show();
        }

其次,在点击菜单中需要响应主窗口控件pictureBox1的程序中,增加显示控件函数:

		private void 加水印ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            // 设置字体的样式
            Font f = new Font("黑体", 24);
            // 实例化一个实心画刷,颜色是白色
            SolidBrush brush = new SolidBrush(Color.White);
            // 与左上角坐标的距离
            PointF point = new PointF(400, 300);
            // 显示pictureBox1控件
            pictureBox1.Show();
            // 在pictureBox上创建画图板
            Graphics g = pictureBox1.CreateGraphics();
            // 开始绘制
            g.DrawString("From: Electrical_IT", f, brush, point);
        }

        private void 清屏ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            // 显示pictureBox1控件
            pictureBox1.Show();
            Graphics g = pictureBox1.CreateGraphics();
            // 用原背景图清屏
            g.DrawImage(pictureBox1.BackgroundImage, 0, 0);
        }

测试后发现还一个问题:pictureBox1被隐藏后,点击菜单中的加水印,会显示pictureBox1控件背景,但不会显示水印,还需要第二次点击,才会显示水印。不清楚为什么,还希望有大神评论指点。

另外,如果主窗口中控件非常多,不建议使用这种方式,建议将主窗口的控件放在Panel控件中,使子窗口的父类设置为Panel。参考链接

发布做好的程序

如果想将程序发给朋友玩一下,就需要发布。

首先,配置设置为Release、Any CPU。
在这里插入图片描述
找到生成,点击发布。
C#实例:多功能Windows窗体应用程序Helloworld_WinForm_第24张图片
根据发布向导,指定发布的位置。
C#实例:多功能Windows窗体应用程序Helloworld_WinForm_第25张图片
选择用户下载的方式,这里选从ROM。
C#实例:多功能Windows窗体应用程序Helloworld_WinForm_第26张图片
选择不检查更新,并点击完成。
C#实例:多功能Windows窗体应用程序Helloworld_WinForm_第27张图片
等待片刻,就可以在路径里找到setup.exe安装包。双击运行,就可以得到应用配置文件夹和应用程序。双击Helloworld_WinForm.application就可以运行了。
在这里插入图片描述
如果想卸载,可以在控制面板的应用中找到并卸载它。
C#实例:多功能Windows窗体应用程序Helloworld_WinForm_第28张图片

你可能感兴趣的:(上位机,C#,c#,windows)