在管理軟件研發過程中,特別是涉及項目管理或者生產計划方面,都需要一款類似微軟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 }