5.7 开发工作流图形定义工具
5.7.1 开发图形工具界面
1、设置绘图工具主界面
打开Visual Studio.NET开发工具(这里用的是2003版本),创建基于C#项目的Windows应用程序,输入项目名称如WorkFlowTools后点击确定,开发工具将自动生成程序框架及一个Windows主界面(窗体)程序Form1.cs(包含一个同名的Windows窗体类Form1,当然也可以在窗体属性页中通过编辑Name属性修改类名称。这里沿用默认名称Form1),可以编辑界面的Text属性(Windows界面的标题文字,默认为Form1。运行程序时将显示),如可以修改为“WorkFlow Drawing Tools”。
设置窗体Form1的大小,如800,620;设置背景颜色,可以选择web颜色“azure”。使用工具箱,为窗体添加主菜单MainMenu,为MainMenu编辑一级菜单,如“文件”,在一级菜单下添加二级菜单,如“新建流程”、“保存流程”等,双击相应菜单(如“保存流程”,也可以编辑相应菜单的事件属性)可以添加菜单命令处理方法。设置Form1的Menu属性为刚创建的主菜单。
为Form1窗体界面添加ContextMenu(右键菜单),设置菜单命令,如“删除节点”、“编辑节点”等;设置Form1的ContextMenu属性为刚创建的右键菜单;双击右键的菜单命令可以添加对应的命令处理方法,如对应“编辑节点”命令的EditMenu方法:
private void EditMenu(object sender, System.EventArgs e)
{
//测试代码
MessageBox.Show("节点任务名称不能为空!");
}
2、设置工作流图形元素按钮
为Form1窗体添加工具条ToolBar,设置其dock属性为Left(工具条位于界面左侧),设置工具条Size属性(宽度、高度,如100,600),设置其Buttonsize属性(按钮尺寸,如100,30)。如图5.5所示:

图5.5 设置左侧工具条
使用绘图工具绘制多个按钮图形,分别对应开始节点、结束节点、任务节点及过程逻辑节点等,以便为工具条添加按钮。
从工具箱中选择ImageList(图片列表)并添加到Form1窗体,设置其ImageSize(图片尺寸,要对应于工具条宽度,如100,30)属性,设置其Images属性,为其添加已绘制的按钮图片。如图5.6所示:

图5.6 为ImageList添加图片
设置ToolBar的imagelist属性(选择刚添加的ImageList),编辑ToolBar的Buttons属性,为工具条添加节点图形按钮,设置按钮方式为PushButton,编辑ImageIndex属性,选择按钮图片(即ImageList中的图片)。如图5.7所示:

图5.7 为ToolsBar添加按钮
双击ToolBar添加工具条点击事件处理方法,在方法中添加如下测试代码:
switch(toolBar1.Buttons.IndexOf(e.Button))
{
case 0:
MessageBox.Show("1成功!");
break;
case 1:
MessageBox.Show("2成功!");
break;
}
以上代码只是为了方便测试,实际上,按钮点击事件处理方法的作用是记录所选择的图形元素类型。这样,根据Form1中记录图形元素类型的变量值,在绘图面板中(通过鼠标点击等事件处理方法)就可以绘制不同的节点、迁移等工作流图形元素。
3、为绘图工具主窗体Form1添加绘图面板
从工具箱选择Panel为Form窗体添加绘图面板panel1。编辑其dock属性,选择Form的中间编辑区位置。设置AutoScroll属性为true,设置AutoScrollMinsize属性(如1200,1000。面板小于多少尺寸下将显示滚动条);添加panel1的MouseDown事件处理方法。示例代码如下:
private void panel1_MouseDown(object sender, System.Windows.Forms.MouseEventArgs e)
{
//左键按下
if(e.Button == MouseButtons.Left)
{
//绘制填充矩形
Graphics g=panel1.CreateGraphics();
g.DrawRectangle(new Pen(new SolidBrush(Color.LightPink),3),e.X,e.Y,60,26);
g.FillRectangle(new SolidBrush(Color.FromArgb(128,255,255)),e.X,e.Y,60,26);
}
}
为了在拖动滚动条时重新绘制图形,编辑panel1的重绘图形事件Paint,添加重绘事件处理方法。示例代码如下:
private void panel1_Paint(object sender, System.Windows.Forms.PaintEventArgs e)
{
repaint();
}
//自定义图形重绘方法
private void repaint()
{
//具体代码在后续章节将详细介绍
......
}
4、添加节点属性编辑窗体
在绘制工作流过程节点时需要编辑节点名称等节点属性,因此还需要添加一个编辑节点属性的新窗体。
在解决方案管理器中选择项目,在右键菜单中选择新建窗体,编辑窗体文件名称,如EditNode。
如图5.8所示,为窗体添加任务名称编辑框。

图5.8 节点属性编辑窗体
在EditNode.cs窗体代码文件中添加记录任务名称的公共属性nodename等。EditNode.cs示例代码如下:
......
public class EditNode : System.Windows.Forms.Form
{
private System.Windows.Forms.TextBox textBox1;
private System.Windows.Forms.Label label1;
private System.Windows.Forms.Button button1;
......
//公共变量,用于返回节点名程等
public string nodename;
//窗体类构造函数
public EditNode()
{
InitializeComponent();
}
//设置任务名称编辑框的默认值
public void setNameText(string str)
{
textBox1.Text=str;
return;
}
......
//确定按钮
private void button1_Click(object sender, System.EventArgs e)
{
//设置任务名称属性为文本编辑框的输入值
if(textBox1.Text != "")
nodename=textBox1.Text.Trim();
this.Close();
return;
}
......
}
在前面提到的Form1右键菜单命令处理方法EditMenu方法中添加如下测试代码:
private void EditMenu(object sender, System.EventArgs e)
{
//实际代码要复杂得多,如判断右键选择的节点,获取节点任务的原名称等
......
//初始化节点编辑窗体对象
EditNode editnode=new EditNode();
//设置窗体编辑控件属性
editnode.setNameText("节点任务的原名称");
//显示编辑窗体
editnode.ShowDialog();
//显示从窗体中用户输入的任务名称
if(editnode.nodename == "")
MessageBox.Show("节点名称不能为空!");
else
MessageBox.Show(editnode.nodename);
}
实际的节点属性编辑代码在后续章节详细介绍。
5、添加编辑和保存过程属性的窗体
在绘制过程图形(以及编辑节点名称等属性)完成后,就可以点击Form1的主菜单“保存流程”,并在弹出的过程保存窗体中输入过程名称、选择流程中要编辑的业务数据表等,完成工作流过程定义工作。编辑和保存过程属性的窗体如图5.9所示:
图5.9 保存流程的窗体
保存流程的窗体代码如下:
using System;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
using System.Data;
using System.Data.SqlClient;
namespace drawtaskbytoolbar
{
public class ProcessForm : System.Windows.Forms.Form
{
private System.Windows.Forms.TextBox textBox1;
private System.Windows.Forms.ComboBox comboBox1;
private System.Windows.Forms.TextBox textBox2;
......
public string processDes="";//记录流程名称的公共属性
public string relatedTableName="";//关联业务表名称(包含创建表的数据库用户名)
public string tableAlias;//业务表中文名
public string duedate;//业务办理承诺期限
public ProcessForm()
{
InitializeComponent();
//获取关联业务表列表,在列表中选择与流程关联的业务表
string strSql="select Description,(Ower+'.'+TableName) as newtablename
from RelatedTables";
DataSet ds=new DataAccess().SQLExeDataSet(strSql);
comboBox1.DataSource=ds.Tables[0];
comboBox1.DisplayMember="Description";
comboBox1.ValueMember="newtablename";
}
......
private void button1_Click(object sender, System.EventArgs e)
{
processDes=textBox1.Text.Trim();
relatedTableName=comboBox1.SelectedValue.ToString();
tableAlias=comboBox1.Text;
duedate=textBox2.Text.Trim();
this.Close();
return;
}
}
}