在管理软件研发过程中,特别是涉及项目管理或者生产计划方面,都需要一款类似微软project的控件对项目下的分解任务进行图形展示(甘特图)。下面介绍一下在WindowsForm下如何实现类似微软project软件的甘特图?最终的效果如下所示:

1、VS2012创建一个Windows应用程序GanttChartControl,并添加甘特图控件库,结构如下:

(注:此处甘特图控件是一款开源库,源码可从网上自行下载)

2、自定义任务类和资源类,代码如下:

 1  #region 自定义任务和资源类
 2     /// <summary>
 3     ///自定义资源
 4     /// </summary>
 5     [Serializable]
 6     public class MyResource
 7     {
 8         public string Name { get; set; }
 9     }
10     /// <summary>
11     /// 自定义任务类,继承 Task 接口 (可选)
12     /// </summary>
13     [Serializable]
14     public class MyTask : Task
15     {
16         public MyTask(ProjectManager manager) : base()
17         {
18             Manager = manager;
19         }
20
21         private ProjectManager Manager { get; set; }
22
23         public new int Start { get { return base.Start; } set { Manager.SetStart(this, value); } }
24         public new int End { get { return base.End; } set { Manager.SetEnd(this, value); } }
25         public new int Duration { get { return base.Duration; } set { Manager.SetDuration(this, value); } }
26         public new float Complete { get { return base.Complete; } set { Manager.SetComplete(this, value); } }
27     }
28     #endregion 

为了能够保存甘特图信息,需要将任务类和资源类标志为[Serializable]。自定义任务类需要继承Task接口。
3、创建项目和任务,代码如下:

 1             // 创建项目和任务
 2             _mManager = new ProjectManager();
 3             var p项目= new MyTask(_mManager) { Name = "项目" };
 4             _mManager.Add(p项目);
 5             var t售前任务组 = new MyTask(_mManager) { Name = "售前阶段" };
 6             var t项目启动 = new MyTask(_mManager) { Name = "项目启动会" };
 7             var t需求调研 = new MyTask(_mManager) { Name = "需求调研" };
 8             var t方案撰写 = new MyTask(_mManager) { Name = "方案撰写" };
 9             var t方案确认 = new MyTask(_mManager) { Name = "方案确认" };
10             // 用ProjectManager类Add方法添加任务
11             _mManager.Add(t售前任务组);
12             _mManager.Add(t项目启动);
13             _mManager.Add(t需求调研);
14             _mManager.Add(t方案撰写);
15             _mManager.Add(t方案确认);

首先需要用 ProjectManager  _mManager = new ProjectManager();创建一个ProjectManager,后续所有的任务都需要添加到此类Add方法添加任务进行管理。

任务的其他属性用下述代码进行设置:

 1          // 用ProjectManager类SetDuration方法设置任务工期
 2             _mManager.SetDuration(t项目启动, 3);
 3             _mManager.SetDuration(t需求调研, 5);
 4             _mManager.SetDuration(t方案撰写, 7);
 5             _mManager.SetDuration(t方案确认, 4);
 6             _mManager.SetDuration(tUI设计, 3);
 7             _mManager.SetDuration(t数据库设计, 5);
 8
 9             //用ProjectManager类Split方法对任务进行分段
10             _mManager.Split(t数据库设计, new MyTask(_mManager), new MyTask(_mManager), 2);
11
12             // 设置任务的完成率
13             t项目启动.Complete = 0.9f;
14             t需求调研.Complete = 0.5f;
15             t方案撰写.Complete = 0.4f;

4、任务分组和任务衔接关系定义

有了任务后,可以对任务的上下关系(分组)和接替关系进行定义,代码如下:

 1 // 给任务分组
 2             _mManager.Group(p项目, t售前任务组);
 3             _mManager.Group(p项目, t开发阶段);
 4             _mManager.Group(p项目, t实施阶段);
 5
 6
 7             _mManager.Group(t售前任务组, t项目启动);
 8             _mManager.Group(t售前任务组, t需求调研);
 9             _mManager.Group(t售前任务组, t方案撰写);
10             _mManager.Group(t售前任务组, t方案确认);
11             //任务衔接关系设置,不支持类型
12             _mManager.Relate(t项目启动, t需求调研);
13             _mManager.Relate(t需求调研, t方案撰写);
14             _mManager.Relate(t方案撰写, t方案确认);
15
16
17             _mManager.Group(t开发阶段, tUI设计);
18             _mManager.Group(t开发阶段, t数据库设计);
19             _mManager.Group(t开发阶段, t编码);
20             _mManager.Group(t开发阶段, t测试);
21
22             _mManager.Relate(t方案确认, tUI设计);
23
24             _mManager.Relate(tUI设计, t数据库设计);
25             _mManager.Relate(t数据库设计, t编码);
26             _mManager.Relate(t编码, t测试);
27
28             _mManager.Group(t实施阶段, t系统安装和初始化);
29             _mManager.Group(t实施阶段, t系统培训);
30             _mManager.Group(t实施阶段, t系统验收);
31             _mManager.Group(t实施阶段, t结项);
32
33             _mManager.Relate(t测试, t系统安装和初始化);
34             _mManager.Relate(t系统安装和初始化, t系统培训);
35             _mManager.Relate(t系统培训, t系统验收);
36             _mManager.Relate(t系统验收, t结项);

5、资源分配

 1           // 创建并设置任务资源(人、材料、设备等),任务资源可自定义
 2             var jake = new MyResource() { Name = "Jake" };
 3             var peter = new MyResource() { Name = "Peter" };
 4             var john = new MyResource() { Name = "John" };
 5             var lucas = new MyResource() { Name = "Lucas" };
 6             var james = new MyResource() { Name = "James" };
 7             var mary = new MyResource() { Name = "Mary" };
 8             // 给任务分配资源
 9             _mManager.Assign(t项目启动, jake);
10             _mManager.Assign(t项目启动, peter);
11             _mManager.Assign(t项目启动, john);
12             _mManager.Assign(t需求调研, jake);
13             _mManager.Assign(t需求调研, james);
14             _mManager.Assign(t数据库设计, james);
15             _mManager.Assign(t数据库设计, lucas);
16             _mManager.Assign(t方案撰写, mary);
17             _mManager.Assign(t方案撰写, lucas);
18             _mManager.Assign(t方案撰写, john);

6、甘特图初始化

 1             //甘特图初始化并创建任务代理
 2             _mChart.Init(_mManager);
 3             _mChart.CreateTaskDelegate = delegate() { return new MyTask(_mManager); };
 4
 5             // 任务事件监听
 6             _mChart.TaskMouseOver += new EventHandler<TaskMouseEventArgs>(_mChart_TaskMouseOver);
 7             _mChart.TaskMouseOut += new EventHandler<TaskMouseEventArgs>(_mChart_TaskMouseOut);
 8             _mChart.TaskSelected += new EventHandler<TaskMouseEventArgs>(_mChart_TaskSelected);
 9             _mChart.PaintOverlay += _mOverlay.ChartOverlayPainter;
10             //允许任务拖拽
11             _mChart.AllowTaskDragDrop = true;
12
13             // 设置任务提示内容,可自定义
14             _mChart.SetToolTip(t项目启动, string.Join(", ", _mManager.ResourcesOf(t项目启动).Select(x => (x as MyResource).Name)));
15             _mChart.SetToolTip(t需求调研, string.Join(", ", _mManager.ResourcesOf(t需求调研).Select(x => (x as MyResource).Name)));
16             _mChart.SetToolTip(t数据库设计, string.Join(", ", _mManager.ResourcesOf(t数据库设计).Select(x => (x as MyResource).Name)));
17             _mChart.SetToolTip(t方案撰写, string.Join(", ", _mManager.ResourcesOf(t方案撰写).Select(x => (x as MyResource).Name)));
18
19             //设置图形日期信息
20             _mManager.TimeScale = TimeScale.Day;
21             var span = DateTime.Today - _mManager.Start;
22             _mManager.Now = (int)Math.Round(span.TotalDays);
23             // 设置图形标题显示日期格式
24             _mChart.TimeScaleDisplay = TimeScaleDisplay.DayOfWeek; 

7、完成后的界面为:

后台完整代码为:

  1 using System;
  2 using System.Collections.Generic;
  3 using System.ComponentModel;
  4 using System.Data;
  5 using System.Drawing;
  6 using System.Linq;
  7 using System.Text;
  8 using System.Windows.Forms;
  9 using Braincase.GanttChart;
 10 namespace GanttChartControl
 11 {
 12     /// <summary>
 13     /// 甘特图控件使用演示
 14     /// </summary>
 15     public partial class ExampleFull : Form
 16     {
 17         OverlayPainter _mOverlay = new OverlayPainter();
 18
 19         ProjectManager _mManager = null;
 20
 21         /// <summary>
 22         /// Example starts here
 23         /// </summary>
 24         public ExampleFull()
 25         {
 26             InitializeComponent();
 27
 28             // 创建项目和任务
 29             _mManager = new ProjectManager();
 30             var p项目= new MyTask(_mManager) { Name = "项目" };
 31             _mManager.Add(p项目);
 32             var t售前任务组 = new MyTask(_mManager) { Name = "售前阶段" };
 33             var t项目启动 = new MyTask(_mManager) { Name = "项目启动会" };
 34             var t需求调研 = new MyTask(_mManager) { Name = "需求调研" };
 35             var t方案撰写 = new MyTask(_mManager) { Name = "方案撰写" };
 36             var t方案确认 = new MyTask(_mManager) { Name = "方案确认" };
 37             // 用ProjectManager类Add方法添加任务
 38             _mManager.Add(t售前任务组);
 39             _mManager.Add(t项目启动);
 40             _mManager.Add(t需求调研);
 41             _mManager.Add(t方案撰写);
 42             _mManager.Add(t方案确认);
 43             var t开发阶段 = new MyTask(_mManager) { Name = "开发阶段" };
 44             var tUI设计 = new MyTask(_mManager) { Name = "UI设计" };
 45             var t数据库设计 = new MyTask(_mManager) { Name = "数据库设计" };
 46             var t编码 = new MyTask(_mManager) { Name = "编码" };
 47             var t测试 = new MyTask(_mManager) { Name = "测试" };
 48             _mManager.Add(t开发阶段);
 49             _mManager.Add(tUI设计);
 50             _mManager.Add(t数据库设计);
 51             _mManager.Add(t编码);
 52             _mManager.Add(t测试);
 53             var t实施阶段 = new MyTask(_mManager) { Name = "实施阶段" };
 54             var t系统安装和初始化 = new MyTask(_mManager) { Name = "系统安装和初始化" };
 55             var t系统培训 = new MyTask(_mManager) { Name = "系统培训" };
 56             var t系统验收 = new MyTask(_mManager) { Name = "系统验收" };
 57             var t结项 = new MyTask(_mManager) { Name = "结项" };
 58             _mManager.Add(t实施阶段);
 59             _mManager.Add(t系统安装和初始化);
 60             _mManager.Add(t系统培训);
 61             _mManager.Add(t系统验收);
 62             _mManager.Add(t结项);
 63
 64
 65             // 用ProjectManager类SetDuration方法设置任务工期
 66             _mManager.SetDuration(t项目启动, 3);
 67             _mManager.SetDuration(t需求调研, 5);
 68             _mManager.SetDuration(t方案撰写, 7);
 69             _mManager.SetDuration(t方案确认, 4);
 70             _mManager.SetDuration(tUI设计, 3);
 71             _mManager.SetDuration(t数据库设计, 5);
 72
 73             //用ProjectManager类Split方法对任务进行分段
 74             _mManager.Split(t数据库设计, new MyTask(_mManager), new MyTask(_mManager), 2);
 75
 76             // 设置任务的完成率
 77             t项目启动.Complete = 0.9f;
 78             t需求调研.Complete = 0.5f;
 79             t方案撰写.Complete = 0.4f;
 80
 81             // 给任务分组
 82             _mManager.Group(p项目, t售前任务组);
 83             _mManager.Group(p项目, t开发阶段);
 84             _mManager.Group(p项目, t实施阶段);
 85
 86
 87             _mManager.Group(t售前任务组, t项目启动);
 88             _mManager.Group(t售前任务组, t需求调研);
 89             _mManager.Group(t售前任务组, t方案撰写);
 90             _mManager.Group(t售前任务组, t方案确认);
 91             //任务衔接关系设置,不支持类型
 92             _mManager.Relate(t项目启动, t需求调研);
 93             _mManager.Relate(t需求调研, t方案撰写);
 94             _mManager.Relate(t方案撰写, t方案确认);
 95
 96
 97             _mManager.Group(t开发阶段, tUI设计);
 98             _mManager.Group(t开发阶段, t数据库设计);
 99             _mManager.Group(t开发阶段, t编码);
100             _mManager.Group(t开发阶段, t测试);
101
102             _mManager.Relate(t方案确认, tUI设计);
103
104             _mManager.Relate(tUI设计, t数据库设计);
105             _mManager.Relate(t数据库设计, t编码);
106             _mManager.Relate(t编码, t测试);
107
108             _mManager.Group(t实施阶段, t系统安装和初始化);
109             _mManager.Group(t实施阶段, t系统培训);
110             _mManager.Group(t实施阶段, t系统验收);
111             _mManager.Group(t实施阶段, t结项);
112
113             _mManager.Relate(t测试, t系统安装和初始化);
114             _mManager.Relate(t系统安装和初始化, t系统培训);
115             _mManager.Relate(t系统培训, t系统验收);
116             _mManager.Relate(t系统验收, t结项);
117
118
119
120             // 创建并设置任务资源(人、材料、设备等),任务资源可自定义
121             var jake = new MyResource() { Name = "Jake" };
122             var peter = new MyResource() { Name = "Peter" };
123             var john = new MyResource() { Name = "John" };
124             var lucas = new MyResource() { Name = "Lucas" };
125             var james = new MyResource() { Name = "James" };
126             var mary = new MyResource() { Name = "Mary" };
127             // 给任务分配资源
128             _mManager.Assign(t项目启动, jake);
129             _mManager.Assign(t项目启动, peter);
130             _mManager.Assign(t项目启动, john);
131             _mManager.Assign(t需求调研, jake);
132             _mManager.Assign(t需求调研, james);
133             _mManager.Assign(t数据库设计, james);
134             _mManager.Assign(t数据库设计, lucas);
135             _mManager.Assign(t方案撰写, mary);
136             _mManager.Assign(t方案撰写, lucas);
137             _mManager.Assign(t方案撰写, john);
138
139             //甘特图初始化并创建任务代理
140             _mChart.Init(_mManager);
141             _mChart.CreateTaskDelegate = delegate() { return new MyTask(_mManager); };
142
143             // 任务事件监听
144             _mChart.TaskMouseOver += new EventHandler<TaskMouseEventArgs>(_mChart_TaskMouseOver);
145             _mChart.TaskMouseOut += new EventHandler<TaskMouseEventArgs>(_mChart_TaskMouseOut);
146             _mChart.TaskSelected += new EventHandler<TaskMouseEventArgs>(_mChart_TaskSelected);
147             _mChart.PaintOverlay += _mOverlay.ChartOverlayPainter;
148             //允许任务拖拽
149             _mChart.AllowTaskDragDrop = true;
150
151             // 设置任务提示内容,可自定义
152             _mChart.SetToolTip(t项目启动, string.Join(", ", _mManager.ResourcesOf(t项目启动).Select(x => (x as MyResource).Name)));
153             _mChart.SetToolTip(t需求调研, string.Join(", ", _mManager.ResourcesOf(t需求调研).Select(x => (x as MyResource).Name)));
154             _mChart.SetToolTip(t数据库设计, string.Join(", ", _mManager.ResourcesOf(t数据库设计).Select(x => (x as MyResource).Name)));
155             _mChart.SetToolTip(t方案撰写, string.Join(", ", _mManager.ResourcesOf(t方案撰写).Select(x => (x as MyResource).Name)));
156
157             //设置图形日期信息
158             _mManager.TimeScale = TimeScale.Day;
159             var span = DateTime.Today - _mManager.Start;
160             _mManager.Now = (int)Math.Round(span.TotalDays);
161             // 设置图形标题显示日期格式
162             _mChart.TimeScaleDisplay = TimeScaleDisplay.DayOfWeek;
163
164             // UI初始化
165             _InitExampleUI();
166             //隐藏说明(打印模式隐藏)
167             _mOverlay.PrintMode = true;
168
169
170         }
171
172         void _mChart_TaskSelected(object sender, TaskMouseEventArgs e)
173         {
174             _mTaskGrid.SelectedObjects = _mChart.SelectedTasks.Select(x => _mManager.IsPart(x) ? _mManager.SplitTaskOf(x) : x).ToArray();
175             _mResourceGrid.Items.Clear();
176             _mResourceGrid.Items.AddRange(_mManager.ResourcesOf(e.Task).Select(x => new ListViewItem(((MyResource)x).Name)).ToArray());
177         }
178
179         void _mChart_TaskMouseOut(object sender, TaskMouseEventArgs e)
180         {
181             lblStatus.Text = "";
182             _mChart.Invalidate();
183         }
184
185         void _mChart_TaskMouseOver(object sender, TaskMouseEventArgs e)
186         {
187             lblStatus.Text = string.Format("{0} to {1}", _mManager.GetDateTime(e.Task.Start).ToLongDateString(), _mManager.GetDateTime(e.Task.End).ToLongDateString());
188             _mChart.Invalidate();
189         }
190         /// <summary>
191         /// UI初始化
192         /// </summary>
193         private void _InitExampleUI()
194         {
195             //设置数据源
196             TaskGridView.DataSource = new BindingSource(_mManager.Tasks, null);
197             mnuFilePrint200.Click += (s, e) => _PrintDocument(2.0f);
198             mnuFilePrint150.Click += (s, e) => _PrintDocument(1.5f);
199             mnuFilePrint100.Click += (s, e) => _PrintDocument(1.0f);
200             mnuFilePrint80.Click += (s, e) => _PrintDocument(0.8f);
201             mnuFilePrint50.Click += (s, e) => _PrintDocument(0.5f);
202             mnuFilePrint25.Click += (s, e) => _PrintDocument(0.25f);
203             mnuFilePrint10.Click += (s, e) => _PrintDocument(0.1f);
204
205             mnuFileImgPrint100.Click += (s, e) => _PrintImage(1.0f);
206             mnuFileImgPrint50.Click += (s, e) => _PrintImage(0.5f);
207             mnuFileImgPrint10.Click += (s, e) => _PrintImage(0.1f);
208         }
209
210         #region 菜单设置
211
212         private void mnuFileSave_Click(object sender, EventArgs e)
213         {
214             using (var dialog = new SaveFileDialog())
215             {
216                 dialog.InitialDirectory = System.IO.Path.GetDirectoryName(Application.ExecutablePath);
217                 if (dialog.ShowDialog() == System.Windows.Forms.DialogResult.OK)
218                 {
219                     using (var fs = System.IO.File.OpenWrite(dialog.FileName))
220                     {
221                         System.Runtime.Serialization.Formatters.Binary.BinaryFormatter bf = new System.Runtime.Serialization.Formatters.Binary.BinaryFormatter();
222                        //序列化
223                         bf.Serialize(fs, _mManager);
224                     }
225                 }
226             }
227         }
228
229         private void mnuFileOpen_Click(object sender, EventArgs e)
230         {
231             using (var dialog = new OpenFileDialog())
232             {
233                 dialog.InitialDirectory = System.IO.Path.GetDirectoryName(Application.ExecutablePath);
234                 if (dialog.ShowDialog() == System.Windows.Forms.DialogResult.OK)
235                 {
236                     using (var fs = System.IO.File.OpenRead(dialog.FileName))
237                     {
238                         System.Runtime.Serialization.Formatters.Binary.BinaryFormatter bf = new System.Runtime.Serialization.Formatters.Binary.BinaryFormatter();
239                         //反序列化
240                         _mManager = bf.Deserialize(fs) as ProjectManager;
241                         if (_mManager == null)
242                         {
243                             MessageBox.Show("Unable to load ProjectManager. Data structure might have changed from previous verions", "Gantt Chart", MessageBoxButtons.OK, MessageBoxIcon.Error);
244                         }
245                         else
246                         {
247                             _mChart.Init(_mManager);
248                             _mChart.Invalidate();
249                         }
250                     }
251                 }
252             }
253         }
254
255         private void mnuFileExit_Click(object sender, EventArgs e)
256         {
257             this.Close();
258         }
259
260         private void mnuViewDaysDayOfWeek_Click(object sender, EventArgs e)
261         {
262             _mManager.TimeScale = TimeScale.Day;
263             _mChart.TimeScaleDisplay = TimeScaleDisplay.DayOfWeek;
264             _mChart.Invalidate();
265         }
266
267         private void mnuFileNew_Click(object sender, EventArgs e)
268         {
269             // start a new Project and init the chart with the project
270             _mManager = new ProjectManager();
271             _mManager.Add(new Task() { Name = "New Task" });
272             _mChart.Init(_mManager);
273             _mChart.Invalidate();
274         }
275
276
277
278         private void mnuViewRelationships_Click(object sender, EventArgs e)
279         {
280             _mChart.ShowRelations = mnuViewRelationships.Checked = !mnuViewRelationships.Checked;
281             _mChart.Invalidate();
282         }
283
284         private void mnuViewSlack_Click(object sender, EventArgs e)
285         {
286             _mChart.ShowSlack = mnuViewSlack.Checked = !mnuViewSlack.Checked;
287             _mChart.Invalidate();
288         }
289         /// <summary>
290         /// 甘特图快捷键说明
291         /// </summary>
292         /// <param name="sender"></param>
293         /// <param name="e"></param>
294         private void mnuViewIntructions_Click(object sender, EventArgs e)
295         {
296             _mOverlay.PrintMode = !(mnuViewIntructions.Checked = !mnuViewIntructions.Checked);
297             _mChart.Invalidate();
298         }
299
300         #region Timescale Views
301         private void mnuViewDays_Click(object sender, EventArgs e)
302         {
303             _mManager.TimeScale = TimeScale.Day;
304             mnuViewDays.Checked = true;
305             mnuViewWeek.Checked = false;
306             _mChart.Invalidate();
307         }
308
309         private void mnuViewWeek_Click(object sender, EventArgs e)
310         {
311             _mManager.TimeScale = TimeScale.Week;
312             mnuViewDays.Checked = false;
313             mnuViewWeek.Checked = true;
314             _mChart.Invalidate();
315         }
316
317         private void mnuViewDayOfWeek_Click(object sender, EventArgs e)
318         {
319             _mChart.TimeScaleDisplay = TimeScaleDisplay.DayOfWeek;
320             mnuViewDayOfWeek.Checked = true;
321             mnuViewDayOfMonth.Checked = false;
322             mnuViewWeekOfYear.Checked = false;
323             _mChart.Invalidate();
324         }
325
326         private void mnuViewDayOfMonth_Click(object sender, EventArgs e)
327         {
328             _mChart.TimeScaleDisplay = TimeScaleDisplay.DayOfMonth;
329             mnuViewDayOfWeek.Checked = false;
330             mnuViewDayOfMonth.Checked = true;
331             mnuViewWeekOfYear.Checked = false;
332             _mChart.Invalidate();
333         }
334
335         private void mnuViewWeekOfYear_Click(object sender, EventArgs e)
336         {
337             _mChart.TimeScaleDisplay = TimeScaleDisplay.WeekOfYear;
338             mnuViewDayOfWeek.Checked = false;
339             mnuViewDayOfMonth.Checked = false;
340             mnuViewWeekOfYear.Checked = true;
341             _mChart.Invalidate();
342         }
343         #endregion Timescale Views
344
345         #endregion Main Menu
346
347         #region Sidebar
348
349         private void _mDateTimePicker_ValueChanged(object sender, EventArgs e)
350         {
351             _mManager.Start = _mStartDatePicker.Value;
352             var span = DateTime.Today - _mManager.Start;
353             _mManager.Now = (int)Math.Round(span.TotalDays);
354             if (_mManager.TimeScale == TimeScale.Week) _mManager.Now = (_mManager.Now % 7) * 7;
355             _mChart.Invalidate();
356         }
357
358         private void _mPropertyGrid_SelectedGridItemChanged(object sender, SelectedGridItemChangedEventArgs e)
359         {
360             _mChart.Invalidate();
361         }
362
363         private void _mNowDatePicker_ValueChanged(object sender, EventArgs e)
364         {
365             TimeSpan span = _mNowDatePicker.Value - _mStartDatePicker.Value;
366             _mManager.Now = span.Days + 1;
367             if (_mManager.TimeScale == TimeScale.Week) _mManager.Now = _mManager.Now / 7 + (_mManager.Now % 7 > 0 ? 1 : 0);
368             _mChart.Invalidate();
369         }
370
371         private void _mScrollDatePicker_ValueChanged(object sender, EventArgs e)
372         {
373             _mChart.ScrollTo(_mScrollDatePicker.Value);
374             _mChart.Invalidate();
375         }
376
377         private void _mTaskGridView_SelectionChanged(object sender, EventArgs e)
378         {
379             if (TaskGridView.SelectedRows.Count > 0)
380             {
381                 var task = TaskGridView.SelectedRows[0].DataBoundItem as Task;
382                 _mChart.ScrollTo(task);
383             }
384         }
385
386         #endregion Sidebar
387
388         #region 打印设置
389
390         private void _PrintDocument(float scale)
391         {
392             using (var dialog = new PrintDialog())
393             {
394                 dialog.Document = new System.Drawing.Printing.PrintDocument();
395                 if (dialog.ShowDialog() == System.Windows.Forms.DialogResult.OK)
396                 {
397                     // set the print mode for the custom overlay painter so that we skip printing instructions
398                     dialog.Document.BeginPrint += (s, arg) => _mOverlay.PrintMode = true;
399                     dialog.Document.EndPrint += (s, arg) => _mOverlay.PrintMode = false;
400
401                     // tell chart to print to the document at the specified scale
402                     _mChart.Print(dialog.Document, scale);
403                 }
404             }
405         }
406
407         private void _PrintImage(float scale)
408         {
409             using (var dialog = new SaveFileDialog())
410             {
411                 dialog.Filter = "Bitmap (*.bmp) | *.bmp";
412                 if (dialog.ShowDialog() == System.Windows.Forms.DialogResult.OK)
413                 {
414                     // set the print mode for the custom overlay painter so that we skip printing instructions
415                     _mOverlay.PrintMode = true;
416                     // tell chart to print to the document at the specified scale
417
418                     var bitmap = _mChart.Print(scale);
419                     _mOverlay.PrintMode = false; // restore printing overlays
420
421                     bitmap.Save(dialog.FileName, System.Drawing.Imaging.ImageFormat.Bmp);
422                 }
423             }
424         }
425
426         #endregion Print
427
428         private void ExampleFull_Load(object sender, EventArgs e)
429         {
430
431         }
432
433
434     }
435
436     #region overlay painter
437     /// <summary>
438     /// An example of how to encapsulate a helper painter for painter additional features on Chart
439     /// </summary>
440     public class OverlayPainter
441     {
442         /// <summary>
443         /// Hook such a method to the chart paint event listeners
444         /// </summary>
445         /// <param name="sender"></param>
446         /// <param name="e"></param>
447         public void ChartOverlayPainter(object sender, ChartPaintEventArgs e)
448         {
449             // Don't want to print instructions to file
450             if (this.PrintMode) return;
451
452             var g = e.Graphics;
453             var chart = e.Chart;
454
455             // Demo: Static billboards begin -----------------------------------
456             // Demonstrate how to draw static billboards
457             // "push matrix" -- save our transformation matrix
458             e.Chart.BeginBillboardMode(e.Graphics);
459
460             // draw mouse command instructions
461             int margin = 300;
462             int left = 20;
463             var color = chart.HeaderFormat.Color;
464             StringBuilder builder = new StringBuilder();
465             builder.AppendLine("THIS IS DRAWN BY A CUSTOM OVERLAY PAINTER TO SHOW DEFAULT MOUSE COMMANDS.");
466             builder.AppendLine("*******************************************************************************************************");
467             builder.AppendLine("Left Click - Select task and display properties in PropertyGrid");
468             builder.AppendLine("Left Mouse Drag - Change task starting point");
469             builder.AppendLine("Right Mouse Drag - Change task duration");
470             builder.AppendLine("Middle Mouse Drag - Change task complete percentage");
471             builder.AppendLine("Left Doubleclick - Toggle collaspe on task group");
472             builder.AppendLine("Right Doubleclick - Split task into task parts");
473             builder.AppendLine("Left Mouse Dragdrop onto another task - Group drag task under drop task");
474             builder.AppendLine("Right Mouse Dragdrop onto another task part - Join task parts");
475             builder.AppendLine("SHIFT + Left Mouse Dragdrop onto another task - Make drop task precedent of drag task");
476             builder.AppendLine("ALT + Left Dragdrop onto another task - Ungroup drag task from drop task / Remove drop task from drag task precedent list");
477             builder.AppendLine("SHIFT + Left Mouse Dragdrop - Order tasks");
478             builder.AppendLine("SHIFT + Middle Click - Create new task");
479             builder.AppendLine("ALT + Middle Click - Delete task");
480             builder.AppendLine("Left Doubleclick - Toggle collaspe on task group");
481             var size = g.MeasureString(builder.ToString(), e.Chart.Font);
482             var background = new Rectangle(left, chart.Height - margin, (int)size.Width, (int)size.Height);
483             background.Inflate(10, 10);
484             g.FillRectangle(new System.Drawing.Drawing2D.LinearGradientBrush(background, Color.LightYellow, Color.Transparent, System.Drawing.Drawing2D.LinearGradientMode.Vertical), background);
485             g.DrawRectangle(Pens.Brown, background);
486             g.DrawString(builder.ToString(), chart.Font, color, new PointF(left, chart.Height - margin));
487
488
489             // "pop matrix" -- restore the previous matrix
490             e.Chart.EndBillboardMode(e.Graphics);
491             // Demo: Static billboards end -----------------------------------
492         }
493
494         public bool PrintMode { get; set; }
495     }
496     #endregion overlay painter
497
498     #region 自定义任务和资源类
499     /// <summary>
500     ///自定义资源
501     /// </summary>
502     [Serializable]
503     public class MyResource
504     {
505         public string Name { get; set; }
506     }
507     /// <summary>
508     /// 自定义任务类,继承 Task 接口 (可选)
509     /// </summary>
510     [Serializable]
511     public class MyTask : Task
512     {
513         public MyTask(ProjectManager manager) : base()
514         {
515             Manager = manager;
516         }
517
518         private ProjectManager Manager { get; set; }
519
520         public new int Start { get { return base.Start; } set { Manager.SetStart(this, value); } }
521         public new int End { get { return base.End; } set { Manager.SetEnd(this, value); } }
522         public new int Duration { get { return base.Duration; } set { Manager.SetDuration(this, value); } }
523         public new float Complete { get { return base.Complete; } set { Manager.SetComplete(this, value); } }
524     }
525     #endregion
526 }

WindowsForm如何实现类似微软project软件的甘特图?相关推荐

  1. 在Project软件的甘特图中添加横线和竖线

    出于各种原因,我们有时候想在Project软件的甘特图区域添加横线或竖线. 比如爱美,想让计划显示的更漂亮一些. 比如眼神不好,怕左边的任务名称和右边的横道图看串行(我是认真的). 比如好奇,看到人家 ...

  2. 中国版类似Google Earth软件问世(组图)

    软件的启动画面和Google Earth非常类似 画面可三维显示 北京郊区的水库清晰可见 2006年9月5日我国第一套三维全息电子沙盘在北京国际会议中心对外展示,该系统在功能上与Google Eart ...

  3. Java使用mpxj导入.mpp格式的Project文件(甘特图)

    最近换工作了,主要的项目都是企业内部为支撑的管理平台,刚入入职没多久,遇到了一个需求,就是导入微软的Project文件,踩过不少坑,所以记录一下,后续还有从数据库导出Project引导文件,也就是xm ...

  4. wps里有project吗_甘特图是什么?-如何用WPS表格做甘特图

    甘特图(Gantt Chart)又称横道图,由亨利.甘特于1910年开发的,它通过图示形象地表示特定项目的活动顺序与持续时间.其中横轴表示时间,纵轴表示活动(项目).线条表示在整个期间上计划和实际的活 ...

  5. java 读取project_java 导入读取.mpp project文件(甘特图)

    写这个的思路是:将.mpp文件中的内容读取出来,我只需要他的一级和二级目录,一级目录.二级目录各一张表,二级目录表存一级目录的主键id,这点和网上其他的方法不太一样,大多数都是一张表就完事的,因为表不 ...

  6. invalid project description._[Project教程] 在Project软件中如何处理加班工时

    在微软Project软件中有处理加班工时的功能,但是我在系统课程中没有讲,为什么呢?就像Project软件中的[进度线]功能,这个功能还不够完善,所以暂时不建议大家使用.加班工时这个问题也是如此,总体 ...

  7. 分享几个常做甘特图的软件

    因为现在做的工作是项目运营,所以平时在部署活动的时候需要跟进活动的执行情况,那活动的执行进度就要活动相关的甘特图.如果没有一款合适的软件去做甘特图会特别麻烦,一方面要处理数据另一方面要保证图型的美观, ...

  8. java生成XML格式文件,导入MS Project生成甘特图

    公司需求需要生成如如下图所示的project甘特图,开发语言是java,网上找了很久也没有找到可以利用java生成这种甘特图的方案.退而求其次,改变需求生成可以导入project的xml文件. 首先用 ...

  9. 电脑端甘特图软件推荐,十分好用

    现在的办公软件层出不穷,各种各样的啥都有,但是真真在用心做软件的团队却没几个.因为本人从事软件需求分析,所以对这些五花八门的软件了解的比较多,最近接触比较多的就是绘图软件的调研,顺便来分享分享我的调研 ...

最新文章

  1. django模板的导入
  2. 架构师之路 — API 经济 — RESTful API
  3. php如何防止超发,PHP+redis实现的限制抢购防止商品超发功能详解
  4. [翻译-ASP.NET MVC]Contact Manager开发之旅
  5. android竖直和横向,如何在android中为纵向和横向模式定义不同的控件
  6. 安卓逆向_5 --- Android 学习
  7. jenkins集成tomcat
  8. 服务器摆放需要预留U位么_卧室系列 | 选床+摆放新姿势,提升睡眠品质小技巧...
  9. ofo在北京上线有桩模式,违规最高罚20元
  10. Intelj IDEA的pom.xml显示错误can not reconnect
  11. 使用 FFmpeg 工具合并本地多个.ts文件为单个.MP4
  12. win10解压文件时,出错:不能创建符号链接 你可能需要以管理员权限运行Winrar 客户端没有所需的特权
  13. AHRS算法代码:磁力计+加计+陀螺版
  14. 串口工具Kermit
  15. java脱机是什么意思_java获取本地打印机,以及判断打印机是否脱机状态
  16. 自学编程,10个程序员学习必收藏的编程网站,你知道几个?
  17. 对APP强制更新的思考
  18. mysql正则表达式中括号单汉字_正则表达式中(括号) [方括号] {大括号}的区别
  19. 《天外世界》游戏体验报告
  20. React使用百度地图实现驾车路线规划

热门文章

  1. mysql 时间语句【集锦】
  2. Mongodb性能监控
  3. SpringSecurity应用(二)
  4. Google IO 2017为我们带来了什么
  5. 《机器人学经典教程》——2.1 控制理论
  6. 利用zabbix API进行管理
  7. 修改UCenter用户名长度限制的方法php程序和数据库修改
  8. Software Switching优化
  9. jquery 验证email
  10. 通过一个对数据的存储和分析的简单实例初识Hadoop