在管理软件研发过程中,特别是涉及项目管理或者生产计划方面,都需要一款类似微软project的控件对项目下的分解任务进行图形展示(甘特图)。下面介绍一下在WindowsForm下如何实现类似微软project软件的甘特图?最终的效果如下所示:
1、VS2012创建一个Windows应用程序GanttChartControl,并添加甘特图控件库,结构如下:
(注:此处甘特图控件是一款开源库,源码可从网上自行下载)
2、自定义任务类和资源类,代码如下:
1 #region 自定义任务和资源类
2 ///
3 ///自定义资源
4 ///
5 [Serializable]
6 public class MyResource
7 {
8 public string Name { get; set; }
9 }
10 ///
11 /// 自定义任务类,继承 Task 接口 (可选)
12 ///
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(_mChart_TaskMouseOver);
7 _mChart.TaskMouseOut += new EventHandler(_mChart_TaskMouseOut);
8 _mChart.TaskSelected += new EventHandler(_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;
后台完整代码为:
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 ///
13 /// 甘特图控件使用演示
14 ///
15 public partial class ExampleFull : Form
16 {
17 OverlayPainter _mOverlay = new OverlayPainter();
18
19 ProjectManager _mManager = null;
20
21 ///
22 /// Example starts here
23 ///
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(_mChart_TaskMouseOver);
145 _mChart.TaskMouseOut += new EventHandler(_mChart_TaskMouseOut);
146 _mChart.TaskSelected += new EventHandler(_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 ///
191 /// UI初始化
192 ///
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 ///
290 /// 甘特图快捷键说明
291 ///
292 ///
293 ///
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 ///
438 /// An example of how to encapsulate a helper painter for painter additional features on Chart
439 ///
440 public class OverlayPainter
441 {
442 ///
443 /// Hook such a method to the chart paint event listeners
444 ///
445 ///
446 ///
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 ///
500 ///自定义资源
501 ///
502 [Serializable]
503 public class MyResource
504 {
505 public string Name { get; set; }
506 }
507 ///
508 /// 自定义任务类,继承 Task 接口 (可选)
509 ///
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 }