最经工作需要用.Net做winform程序,以前因为个人对windows的东西不太感冒,就接触很少,但是为了生活也没办法,多学习一样技术也没坏处。
C#语法跟C++和java非常类似,从变量定义、语句、循环、名字空间、异常处理等都很相似,有一定编程基础的只需要稍微了解一下就可以上手。我刚接触C#和VS没几天,几乎没学什么语法,通过百度(google上不去啊)一边查一边做,基本上可以做出一个简单的winform小程序来。微软把几乎所有的东西都封装好了,我只需要大致了解一下windows编程的思路,通过拖动控件和添加事件处理,就能做一个最基础的小软件。
下面就随手记录最近零星学的东西,以防以后忘记。
1、从vs上新建一个winform工程后,默认导入system、system.windows.forms、system.text等包,这叫做工程的引用,主要需要关注From1.cs, From1.Designer.cs, Program.cs三个文件,Program.cs是程序的入口,代码如下:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows.Forms;
namespace WindowsFormsApplication1
{
static class Program
{
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Form1());
}
}
}
核心就是Application.Run(new Form1())这行代码,表示开启了一个winform的主事件循环,From1是主窗口,循环等待并响应外部事件。
From1.Designer.cs是定义了主窗体的一些控件属性,在程序开始就生成这些控件,vs建议不要直接编辑这里的代码,如果要添加控件或者注册事件最好是通过“设计”页面来处理。
From1.cs是需要主要编辑的文件,用于添加事件处理。
2、在windows上编写GUI程序都是基于windows的消息机制,简单来说就是操作系统为每个应用程序维护一个消息队列,操作系统接收来自鼠标、键盘传来的事件,封装成一种叫消息的数据结构,然后传给对应的应用程序窗体,通过委托调用事件方法进行处理。
在C#中,windows消息都进行了面向对象封装,叫event(事件)。在定义event的时候指定了一个委托,然后注册事件处理的时候需要调用这个委托。
public delegate void EventHandler(object sender,EventArgs e); 定义了一个事件处理的委托
public event EventHandler MouseClick; 定义一个事件
在From1.Designer.cs中需要添加下面一行:
this.button1.MouseClick+= new System.EventHandler(this.button1_Click);
表示为按钮button1添加一个MouseClick事件,对应的事件处理函数时this.button1_Click,我们需要再Form1.cs中实现这个处理方法.
当然,如果只是简单应用,我们不需要自己定义event,.Net已经为我们定义绝大部分可能遇到的事件,我们要做的就是注册事件、处理事件。
3、GUI编程一个重点就是对异步和线程的使用,Application.Run(new Form1())表示开始一个主线程,启动Form1为主窗口,它不断循环等待事件的发生。当发生一个鼠标Click事件,一种方式使用同步调用,我们暂停主线程等待鼠标Click事件处理完毕然后继续运行,这样整个主窗体会处于“假死”状态,如果事件处理需要花很长时间,程序将完全卡死不能动。我前几天实现的winform程序是后台调用一个外部程序,要执行很长时间,解决的方法就是另外开启一个线程:
首先引用名字空间
using System.Threading; 导入线程相关的类
然后在事件函数中添加一个线程
Thread ts = new Thread(new ParameterizedThreadStart(work));
ts.Start(this);
或者
Thread ts = new Thread(new ThreadStart(work));
ts.Start();
两种添加线程方法的区别就是,第一个可以传入一个object参数,一般都是传进主窗体的this,这样方便我们在线程中操作主窗体的属性。
work方法中就是线程的代码,我需要在事件运行的时候,不断获取外部程序的标准输出和标准错误输出,所以可以线程中进行处理
4、调用外部程序使用Process类,在线程中可以用waitforexit方法等待进程执行完毕而不用担心会阻塞主线程。
Process调外部程序需要注意几点:
(1)在WaitForExit后使用Process.ExitCode 获取返回值,以此来判断外部程序是否执行成功
(2)外部程序可能出异常一直没有返回值,需要使用WaitForExit的一个重载设置最长等待时间
(3)子进程执行完毕后,使用Dispose和Close释放相关资源并关闭;子进程执行异常后,通过Kill杀死