在管理软件研发过程中,特别是涉及项目管理或者生产计划方面,都需要一款类似微软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 }
时间: 2024-12-24 11:43:00