sc 10 months ago
parent
commit
959f3fd243
  1. BIN
      GanttChart/GanttChart.bmp
  2. 105
      GanttChart/GanttChart.csproj
  3. 197
      GanttChart/GanttChartBrushes.cs
  4. 71
      GanttChart/GanttChartCollection.cs
  5. 26
      GanttChart/GanttChartItemClickEventArgs.cs
  6. 26
      GanttChart/GanttChartItemDoubleClickEventArgs.cs
  7. 32
      GanttChart/GanttChartPropertyChangeEventArgs.cs
  8. 35
      GanttChart/GanttChartRangeSelectedEventArgs.cs
  9. 26
      GanttChart/GanttChartRowSelectedEventArgs.cs
  10. 410
      GanttChart/GanttChartView.Events.cs
  11. 217
      GanttChart/GanttChartView.Logic.cs
  12. 756
      GanttChart/GanttChartView.Properties.cs
  13. 409
      GanttChart/GanttChartView.Render.cs
  14. 137
      GanttChart/GanttChartView.cs
  15. 11
      GanttChart/GanttChartViewColumn.cs
  16. 11
      GanttChart/GanttChartViewColumnGroup.cs
  17. 42
      GanttChart/GanttChartViewItem.cs
  18. 30
      GanttChart/GanttChartViewItemBlockType.cs
  19. 30
      GanttChart/GanttChartViewRow.cs
  20. 36
      GanttChart/Properties/AssemblyInfo.cs
  21. 63
      GanttChart/Properties/Resources.Designer.cs
  22. 117
      GanttChart/Properties/Resources.resx
  23. 26
      GanttChart/Properties/Settings.Designer.cs
  24. 7
      GanttChart/Properties/Settings.settings
  25. 30
      GanttChart/TimeRange.cs
  26. 6
      SunlightCentralizedControlManagement(SCCM).sln
  27. 1
      View/ProductionPlanningView.xaml
  28. 4
      View/ProductionPlanningView.xaml.cs

BIN
GanttChart/GanttChart.bmp

Binary file not shown.

After

Width:  |  Height:  |  Size: 822 B

105
GanttChart/GanttChart.csproj

@ -0,0 +1,105 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{DEA91CB9-1011-4EE7-B8E1-72428F731789}</ProjectGuid>
<OutputType>Library</OutputType>
<RootNamespace>GanttChart</RootNamespace>
<AssemblyName>GanttChart</AssemblyName>
<TargetFrameworkVersion>v4.7.2</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<Deterministic>true</Deterministic>
<TargetFrameworkProfile />
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<Prefer32Bit>false</Prefer32Bit>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<Prefer32Bit>false</Prefer32Bit>
</PropertyGroup>
<PropertyGroup>
<StartupObject />
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="System.Data" />
<Reference Include="System.Deployment" />
<Reference Include="System.Drawing" />
<Reference Include="System.Windows.Forms" />
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="GanttChartBrushes.cs" />
<Compile Include="GanttChartItemClickEventArgs.cs" />
<Compile Include="GanttChartItemDoubleClickEventArgs.cs" />
<Compile Include="GanttChartPropertyChangeEventArgs.cs" />
<Compile Include="GanttChartRangeSelectedEventArgs.cs" />
<Compile Include="GanttChartRowSelectedEventArgs.cs" />
<Compile Include="GanttChartView.cs">
<SubType>Component</SubType>
</Compile>
<Compile Include="GanttChartView.Events.cs">
<SubType>Component</SubType>
</Compile>
<Compile Include="GanttChartView.Logic.cs">
<SubType>Component</SubType>
</Compile>
<Compile Include="GanttChartView.Properties.cs">
<SubType>Component</SubType>
</Compile>
<Compile Include="GanttChartView.Render.cs">
<SubType>Component</SubType>
</Compile>
<Compile Include="GanttChartViewColumn.cs" />
<Compile Include="GanttChartViewColumnGroup.cs" />
<Compile Include="GanttChartViewItem.cs" />
<Compile Include="GanttChartCollection.cs" />
<Compile Include="GanttChartViewItemBlockType.cs" />
<Compile Include="GanttChartViewRow.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="TimeRange.cs" />
<EmbeddedResource Include="Properties\Resources.resx">
<Generator>ResXFileCodeGenerator</Generator>
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
<SubType>Designer</SubType>
</EmbeddedResource>
<Compile Include="Properties\Resources.Designer.cs">
<AutoGen>True</AutoGen>
<DependentUpon>Resources.resx</DependentUpon>
<DesignTime>True</DesignTime>
</Compile>
<None Include="Properties\Settings.settings">
<Generator>SettingsSingleFileGenerator</Generator>
<LastGenOutput>Settings.Designer.cs</LastGenOutput>
</None>
<Compile Include="Properties\Settings.Designer.cs">
<AutoGen>True</AutoGen>
<DependentUpon>Settings.settings</DependentUpon>
<DesignTimeSharedInput>True</DesignTimeSharedInput>
</Compile>
</ItemGroup>
<ItemGroup>
<EmbeddedResource Include="GanttChart.bmp" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
</Project>

197
GanttChart/GanttChartBrushes.cs

@ -0,0 +1,197 @@
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Text;
namespace GanttChart
{
/// <summary>
/// 甘特图笔刷
/// </summary>
class GanttChartBrushes: IDisposable
{
GanttChartView View { get; set; }
public GanttChartBrushes(GanttChartView view)
{
View = view;
this.GridBrush = new SolidBrush(view.GridColor);
this.ColumnDateTextBrush = new SolidBrush(view.ColumnDateTextColor);
this.ColumnHourTextBrush = new SolidBrush(view.ColumnHourTextColor);
this.HeaderBackBrush = new SolidBrush(view.HeaderBackColor);
this.BackBrush = new SolidBrush(view.BackColor);
this.ContentBackBrush = new SolidBrush(view.ContentBackColor);
this.CurrentTimeLineBrush = new SolidBrush(view.CurrentTimeLineColor);
this.ItemTextBrush = new SolidBrush(view.ItemTextColor);
this.ItemBackBrush = new SolidBrush(view.ItemBackColor);
this.ItemBorderBrush = new SolidBrush(view.ItemBorderColor);
this.ItemStartFlagBrush = new SolidBrush(view.ItemStartFlagColor);
this.ItemSubRangeBackBrush = new SolidBrush(view.ItemSubRangeBackColor);
this.ItemSelectionTextBrush = new SolidBrush(view.ItemSelectionTextColor);
this.ItemSelectionBackBrush = new SolidBrush(view.ItemSelectionBackColor);
this.ItemSelectionBorderBrush = new SolidBrush(view.ItemSelectionBorderColor);
this.ItemSelectionSubRangeBackBrush = new SolidBrush(view.ItemSelectionSubRangeBackColor);
this.ItemWarnningTextBrush = new SolidBrush(view.ItemWarnningTextColor);
this.RowHeaderTextBrush = new SolidBrush(view.RowHeaderTextColor);
this.RowSelectionHeaderTextBrush = new SolidBrush(view.RowSelectionHeaderTextColor);
this.RowSelectionBorderBrush = new SolidBrush(view.RowSelectionBorderColor);
this.RowSelectionHeaderBackBrush = new SolidBrush(view.RowSelectionHeaderBackColor);
this.RowSelectionContentBackBrush = new SolidBrush(view.RowSelectionContentBackColor);
this.TooltipTextBrush = new SolidBrush(view.TooltipTextColor);
this.TooltipBorderBrush = new SolidBrush(view.TooltipBorderColor);
this.TooltipBackBrush = new SolidBrush(view.TooltipBackColor);
this.TimeRangeSelecetionBackBrush = new SolidBrush(view.TimeRangeSelecetionBackColor);
this.SelectionRectangleBackBrush = new SolidBrush(view.SelectionRectangleBackColor);
this.GridPen = new Pen(this.GridBrush, 1);
this.CurrentTimeLinePen = new Pen(this.CurrentTimeLineBrush, 1);
this.ItemBorderPen = new Pen(this.ItemBorderBrush, 1);
this.ItemBackPen = new Pen(this.ItemBackBrush, 1);
this.ItemSelectionBorderPen = new Pen(this.ItemSelectionBorderBrush, 1);
this.RowSelectionBorderPen = new Pen(this.RowSelectionBorderBrush, 1);
this.TooltipBorderPen = new Pen(this.TooltipBorderBrush, 1);
this.ItemStartFlagPen = new Pen(this.ItemStartFlagBrush, 2);
this.ItemSubRangeBackPen = new Pen(this.ItemSubRangeBackBrush, 1);
this.ItemSelectionSubRangeBackPen = new Pen(this.ItemSelectionSubRangeBackBrush, 1);
}
public SolidBrush GridBrush { get; set; }
public SolidBrush ColumnDateTextBrush { get; set; }
public SolidBrush ColumnHourTextBrush { get; set; }
public SolidBrush HeaderBackBrush { get; set; }
public SolidBrush BackBrush { get; set; }
public SolidBrush ContentBackBrush { get; set; }
public SolidBrush CurrentTimeLineBrush { get; set; }
public SolidBrush ItemTextBrush { get; set; }
public SolidBrush ItemBackBrush { get; set; }
public SolidBrush ItemBorderBrush { get; set; }
public SolidBrush ItemStartFlagBrush { get; set; }
public SolidBrush ItemSubRangeBackBrush { get; set; }
public SolidBrush ItemSelectionTextBrush { get; set; }
public SolidBrush ItemSelectionBackBrush { get; set; }
public SolidBrush ItemSelectionBorderBrush { get; set; }
public SolidBrush ItemSelectionSubRangeBackBrush { get; set; }
public SolidBrush ItemWarnningTextBrush { get; set; }
public SolidBrush RowHeaderTextBrush { get; set; }
public SolidBrush RowSelectionHeaderTextBrush { get; set; }
public SolidBrush RowSelectionBorderBrush { get; set; }
public SolidBrush RowSelectionHeaderBackBrush { get; set; }
public SolidBrush RowSelectionContentBackBrush { get; set; }
public SolidBrush TooltipTextBrush { get; set; }
public SolidBrush TooltipBorderBrush { get; set; }
public SolidBrush TooltipBackBrush { get; set; }
public SolidBrush TimeRangeSelecetionBackBrush { get; set; }
public SolidBrush SelectionRectangleBackBrush { get; set; }
public Pen GridPen { get; }
public Pen CurrentTimeLinePen { get; }
public Pen ItemBorderPen { get; }
public Pen ItemBackPen { get; }
public Pen ItemSelectionBorderPen { get; }
public Pen RowSelectionBorderPen { get; }
public Pen TooltipBorderPen { get; }
public Pen ItemStartFlagPen { get; }
public Pen ItemSubRangeBackPen { get; }
public Pen ItemSelectionSubRangeBackPen { get; }
public void Refresh()
{
this.GridBrush.Color = View.GridColor;
this.ColumnDateTextBrush.Color = View.ColumnDateTextColor;
this.ColumnHourTextBrush.Color = View.ColumnHourTextColor;
this.HeaderBackBrush.Color = View.HeaderBackColor;
this.ContentBackBrush.Color = View.ContentBackColor;
this.CurrentTimeLineBrush.Color = View.CurrentTimeLineColor;
this.ItemTextBrush.Color = View.ItemTextColor;
this.ItemBackBrush.Color = View.ItemBackColor;
this.ItemBorderBrush.Color = View.ItemBorderColor;
this.ItemStartFlagBrush.Color = View.ItemStartFlagColor;
this.ItemSubRangeBackBrush.Color = View.ItemSubRangeBackColor;
this.ItemSelectionTextBrush.Color = View.ItemSelectionTextColor;
this.ItemSelectionBackBrush.Color = View.ItemSelectionBackColor;
this.ItemSelectionBorderBrush.Color = View.ItemSelectionBorderColor;
this.ItemSelectionSubRangeBackBrush.Color = View.ItemSelectionSubRangeBackColor;
this.ItemWarnningTextBrush.Color = View.ItemWarnningTextColor;
this.RowHeaderTextBrush.Color = View.RowHeaderTextColor;
this.RowSelectionHeaderTextBrush.Color = View.RowSelectionHeaderTextColor;
this.RowSelectionBorderBrush.Color = View.RowSelectionBorderColor;
this.RowSelectionHeaderBackBrush.Color = View.RowSelectionHeaderBackColor;
this.RowSelectionContentBackBrush.Color = View.RowSelectionContentBackColor;
this.TooltipTextBrush.Color = View.TooltipTextColor;
this.TooltipBorderBrush.Color = View.TooltipBorderColor;
this.TooltipBackBrush.Color = View.TooltipBackColor;
this.TimeRangeSelecetionBackBrush.Color = View.TimeRangeSelecetionBackColor;
this.SelectionRectangleBackBrush.Color = View.SelectionRectangleBackColor;
}
public void Dispose()
{
this.GridPen.Dispose();
this.CurrentTimeLinePen.Dispose();
this.ItemBorderPen.Dispose();
this.ItemBackPen.Dispose();
this.ItemSelectionBorderPen.Dispose();
this.RowSelectionBorderPen.Dispose();
this.TooltipBorderPen.Dispose();
this.ItemStartFlagPen.Dispose();
this.ItemSubRangeBackPen.Dispose();
this.ItemSelectionSubRangeBackPen.Dispose();
this.BackBrush.Dispose();
this.GridBrush.Dispose();
this.ColumnDateTextBrush.Dispose();
this.ColumnHourTextBrush.Dispose();
this.HeaderBackBrush.Dispose();
this.ContentBackBrush.Dispose();
this.CurrentTimeLineBrush.Dispose();
this.ItemTextBrush.Dispose();
this.ItemBackBrush.Dispose();
this.ItemBorderBrush.Dispose();
this.ItemStartFlagBrush.Dispose();
this.ItemSubRangeBackBrush.Dispose();
this.ItemSelectionTextBrush.Dispose();
this.ItemSelectionBackBrush.Dispose();
this.ItemSelectionBorderBrush.Dispose();
this.ItemSelectionSubRangeBackBrush.Dispose();
this.ItemWarnningTextBrush.Dispose();
this.RowHeaderTextBrush.Dispose();
this.RowSelectionHeaderTextBrush.Dispose();
this.RowSelectionBorderBrush.Dispose();
this.RowSelectionHeaderBackBrush.Dispose();
this.RowSelectionContentBackBrush.Dispose();
this.TooltipTextBrush.Dispose();
this.TooltipBorderBrush.Dispose();
this.TooltipBackBrush.Dispose();
this.TimeRangeSelecetionBackBrush.Dispose();
this.SelectionRectangleBackBrush.Dispose();
}
}
}

71
GanttChart/GanttChartCollection.cs

@ -0,0 +1,71 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace GanttChart
{
/// <summary>
/// 甘特图像集合
/// </summary>
/// <typeparam name="T"></typeparam>
public class GanttChartCollection<T> : ICollection<T>
{
private List<T> Items;
internal bool IsChanged { get; set; }
internal DateTime StartDate { get; set; }
public GanttChartCollection()
{
Items = new List<T>();
}
public GanttChartCollection(ICollection<T> items):this()
{
Items.AddRange(items);
IsChanged = true;
}
public int Count => Items.Count;
bool ICollection<T>.IsReadOnly => false;
public void Add(T item)
{
Items.Add(item);
IsChanged = true;
}
public void Clear()
{
Items.Clear();
IsChanged = false;
}
public bool Contains(T item) => Items.Contains(item);
public void CopyTo(T[] array, int arrayIndex) => Items.CopyTo(array, arrayIndex);
public IEnumerator<T> GetEnumerator() => Items.GetEnumerator();
public bool Remove(T item)
{
if (Items.Remove(item))
{
IsChanged = true;
return true;
}
return false;
}
IEnumerator IEnumerable.GetEnumerator()
{
return Items.GetEnumerator();
}
public T this[int index]
{
get
{
return Items[index];
}
}
}
}

26
GanttChart/GanttChartItemClickEventArgs.cs

@ -0,0 +1,26 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace GanttChart
{
/// <summary>
/// 甘特图项单击事件参数
/// </summary>
public class GanttChartItemClickEventArgs : EventArgs
{
/// <summary>
/// 项
/// </summary>
public GanttChartViewItem Item { get; private set; }
/// <summary>
/// 初始化
/// </summary>
/// <param name="item"></param>
public GanttChartItemClickEventArgs(GanttChartViewItem item)
{
Item = item;
}
}
}

26
GanttChart/GanttChartItemDoubleClickEventArgs.cs

@ -0,0 +1,26 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace GanttChart
{
/// <summary>
/// 甘特图项双击事件参数
/// </summary>
public class GanttChartItemDoubleClickEventArgs : EventArgs
{
/// <summary>
/// 项
/// </summary>
public GanttChartViewItem Item { get; private set; }
/// <summary>
/// 初始化
/// </summary>
/// <param name="item"></param>
public GanttChartItemDoubleClickEventArgs(GanttChartViewItem item)
{
Item = item;
}
}
}

32
GanttChart/GanttChartPropertyChangeEventArgs.cs

@ -0,0 +1,32 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace GanttChart
{
/// <summary>
/// 甘特图属性改变事件参数
/// </summary>
public class GanttChartPropertyChangeEventArgs : EventArgs
{
/// <summary>
/// 初始化
/// </summary>
/// <param name="name"></param>
/// <param name="value"></param>
public GanttChartPropertyChangeEventArgs(string name, object value)
{
PropertyName = name;
PropertyValue = value;
}
/// <summary>
/// 属性名
/// </summary>
public string PropertyName { get; set; }
/// <summary>
/// 属性值
/// </summary>
public object PropertyValue { get; set; }
}
}

35
GanttChart/GanttChartRangeSelectedEventArgs.cs

@ -0,0 +1,35 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace GanttChart
{
/// <summary>
/// 甘特图范围选择事件参数
/// </summary>
public class GanttChartRangeSelectedEventArgs : EventArgs
{
/// <summary>
/// 事件范围
/// </summary>
public TimeRange Range { get; private set; }
/// <summary>
/// 初始化
/// </summary>
/// <param name="range"></param>
public GanttChartRangeSelectedEventArgs(TimeRange range)
{
Range = range;
}
/// <summary>
/// 初始化
/// </summary>
/// <param name="startTime"></param>
/// <param name="endTime"></param>
public GanttChartRangeSelectedEventArgs(DateTime startTime, DateTime endTime)
{
Range = new TimeRange { StartTime = startTime, EndTime = endTime };
}
}
}

26
GanttChart/GanttChartRowSelectedEventArgs.cs

@ -0,0 +1,26 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace GanttChart
{
/// <summary>
/// 甘特图行选中事件参数
/// </summary>
public class GanttChartRowSelectedEventArgs : EventArgs
{
/// <summary>
/// 行
/// </summary>
public GanttChartViewRow Row { get; private set; }
/// <summary>
/// 初始化
/// </summary>
/// <param name="row"></param>
public GanttChartRowSelectedEventArgs(GanttChartViewRow row)
{
Row = row;
}
}
}

410
GanttChart/GanttChartView.Events.cs

@ -0,0 +1,410 @@
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace GanttChart
{
/// <summary>
/// 甘特图控件
/// 该部分类主要处理事件
/// </summary>
public partial class GanttChartView
{
private bool _IsShiftPress = false;
private bool _IsCtrlPress = false;
private bool _IsAltPress = false;
private bool _IsMouseDown = false;
private bool _IsAjustSize = false;
private bool _IsDragItem = false;
private bool _IsShowTooltip = false;
private Point _DragStartLocation = Point.Empty;
private Point _DragEndLocation = Point.Empty;
private Point _ShowTooltipPoint = Point.Empty;
private Rectangle _SelectionRange = Rectangle.Empty;
private GanttChartViewItem _DragItem = null;
private GanttChartViewItem _ShowTooltipItem = null;
public event EventHandler<GanttChartPropertyChangeEventArgs> PropertyChanged;
public event EventHandler<GanttChartItemClickEventArgs> ItemClick;
public event EventHandler<GanttChartItemDoubleClickEventArgs> ItemDoubleClick;
public event EventHandler<GanttChartRowSelectedEventArgs> RowSelected;
public event EventHandler<GanttChartRangeSelectedEventArgs> RangeSelected;
/// <summary>
/// 初始化事件
/// </summary>
protected void InitEvent()
{
_VScrollBar.Scroll += new ScrollEventHandler(VScrollBar_Scroll);
_HScrollBar.Scroll += new ScrollEventHandler(HScrollBar_Scroll);
_ContentControl.Paint += OnContentControlPaint;
_ContentControl.MouseDown += OnMouseDown;
_ContentControl.MouseUp += OnMouseUp;
_ContentControl.MouseMove += OnMouseMove;
_ContentControl.MouseClick += OnMouseClick;
_ContentControl.MouseDoubleClick += OnMouseDoubleClick;
}
/// <summary>
/// 销毁事件
/// </summary>
protected void DisposeEvent()
{
}
/// <summary>
/// 键盘按下事件
/// </summary>
/// <param name="e"></param>
protected override void OnKeyDown(KeyEventArgs e)
{
_IsShiftPress = e.Shift;
_IsCtrlPress = e.Control;
_IsAltPress = e.Alt;
base.OnKeyDown(e);
}
/// <summary>
/// 键盘弹起事件
/// </summary>
/// <param name="e"></param>
protected override void OnKeyUp(KeyEventArgs e)
{
_IsShiftPress = e.Shift;
_IsCtrlPress = e.Control;
_IsAltPress = e.Alt;
base.OnKeyUp(e);
}
/// <summary>
/// 鼠标单击事件
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
protected void OnMouseClick(object sender, MouseEventArgs e)
{
if (_DragStartLocation != Point.Empty && e.X != _DragStartLocation.X && _DragStartLocation.Y != e.Y)
{
return;
}
if (IsHoverRowHeader(e.Location) || IsHoverRow(e.Location))
{
_SelectionRow = GetRow(e.Location);
Invalidate();
RowSelected?.Invoke(this, new GanttChartRowSelectedEventArgs(_SelectionRow));
}
if (IsHoverItem(e.Location))
{
_SelectionItem = GetItem(e.Location);
Invalidate();
ItemClick?.Invoke(this, new GanttChartItemClickEventArgs(_SelectionItem));
}
}
/// <summary>
/// 鼠标双击事件
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
protected void OnMouseDoubleClick(object sender, MouseEventArgs e)
{
if (IsHoverItem(e.Location))
{
_SelectionItem = GetItem(e.Location);
Invalidate();
if(ItemDoubleClick != null)
{
if (_IsShowTooltip)
{
_IsShowTooltip = false;
_ShowTooltipItem = null;
_ShowTooltipPoint = Point.Empty;
}
ItemDoubleClick(this, new GanttChartItemDoubleClickEventArgs(_SelectionItem));
}
}
}
/// <summary>
/// 鼠标滚动事件
/// </summary>
/// <param name="e"></param>
protected override void OnMouseWheel(MouseEventArgs e)
{
if (_IsShowTooltip)
{
_IsShowTooltip = false;
_ShowTooltipItem = null;
_ShowTooltipPoint = Point.Empty;
}
//int i = e.Delta > 0 ? -1 : 1;
var scrollbar = _IsShiftPress ? _HScrollBar : (ScrollBar)_VScrollBar;
var h = scrollbar.Value - (int)(e.Delta * MouseWheelSensitivity);
if (h > scrollbar.Maximum)
{
h = scrollbar.Maximum;
}
if (h < scrollbar.Minimum)
{
h = scrollbar.Minimum;
}
scrollbar.Value = h;
Invalidate();
base.OnMouseWheel(e);
}
/// <summary>
/// 鼠标按下事件
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
protected void OnMouseDown(object sender, MouseEventArgs e)
{
if (_SelectionRow != null || _SelectionItem != null || _DragItem != null)
{
_SelectionRow = null;
_SelectionItem = null;
_DragItem = null;
Invalidate();
}
_IsMouseDown = e.Button == MouseButtons.Left && true;
if (_IsMouseDown)
{
_SelectionRange = Rectangle.Empty;
_SelectionTimeRange = null;
_DragStartLocation = e.Location;
if (IsHoverDateSplitLine(e.Location) && !IsHoverItem(e.Location))
{
_IsAjustSize = true;
}
else if (IsHoverItem(e.Location))
{
_IsDragItem = true;
_DragItem = GetItem(e.Location);
}
}
}
/// <summary>
/// 控件创建事件
/// </summary>
protected override void OnCreateControl()
{
this.Brushes = new GanttChartBrushes(this);
_HScrollBar.Width = this.Width - VScrollWidth;
_VScrollBar.Height = this.Height - HScrollHeight;
AdjustScrollbar();
base.OnCreateControl();
}
/// <summary>
/// 控件大小变化事件
/// </summary>
/// <param name="e"></param>
protected override void OnSizeChanged(EventArgs e)
{
_HScrollBar.Width = this.Width - VScrollWidth;
_VScrollBar.Height = this.Height - HScrollHeight;
AdjustScrollbar();
Invalidate();
base.OnSizeChanged(e);
}
/// <summary>
/// 控件绘制事件
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void OnContentControlPaint(object sender, PaintEventArgs e)
{
int bottom = ColumnHeight + ItemHeight + RowSpacing * 2;
if (Rows != null && Rows.Any())
{
var last = Rows.Last();
bottom = last.Bottom;
}
DrawBack(e.Graphics, bottom);
e.Graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;
DrawHeader(e.Graphics, bottom);
DrawColumnHeader(e.Graphics);
DrawTimeLine(e.Graphics, bottom);
DrawSelectingRectangle(e.Graphics);
DrawSelectionRange(e.Graphics);
DrawRows(e.Graphics, bottom);
DrawItemTooltip(e.Graphics);
}
/// <summary>
/// 鼠标弹起事件
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
protected void OnMouseUp(object sender, MouseEventArgs e)
{
if (_IsMouseDown)
{
if (_IsAjustSize)
{
_IsAjustSize = false;
var w = e.X - _DragStartLocation.X + DateWidth;
if (w < MinDateWidth)
{
DateWidth = MinDateWidth;
}
else
{
DateWidth = (w / 48 + (w % 48 == 0 ? 0 : 1)) * 48;
}
if(Rows != null)
{
Rows.IsChanged = true;
}
AdjustScrollbar();
Invalidate();
}
else if (_IsDragItem)
{
_IsDragItem = false;
//TODO:触发Drag事件
Invalidate();
}
else if(!_DragStartLocation.IsEmpty && e.X != _DragStartLocation.X && e.Y != _DragStartLocation.Y && _DragStartLocation.X > RowHeaderWidth && _DragStartLocation.Y > ColumnHeight)
{
_DragEndLocation = e.Location;
var row = GetRow(_DragStartLocation);
if (row != null)
{
var width = Math.Abs(_DragEndLocation.X - _DragStartLocation.X);
if (_DragEndLocation.X < RowHeaderWidth)
{
width -= RowHeaderWidth - _DragEndLocation.X;
}
else if (_DragEndLocation.X > ((int)(EndDate.Date - StartDate.Date).TotalDays + 1) * DateWidth + RowHeaderWidth - _HScrollBar.Value)
{
width = ((int)(EndDate.Date - StartDate.Date).TotalDays + 1) * DateWidth + RowHeaderWidth - _HScrollBar.Value - _DragStartLocation.X;
}
var start = new Point(Math.Min(_DragStartLocation.X, Math.Max(_DragEndLocation.X, RowHeaderWidth)), row.Top + 1);
_SelectionRange = new Rectangle(start, new Size(width, row.Bottom - row.Top - 2));
Invalidate();
var mw = DateWidth / 24f / 60f;
var ts = StartDate.AddMinutes((int)((_DragStartLocation.X - RowHeaderWidth + _HScrollBar.Value) / mw));
var te = StartDate.AddMinutes((int)((_DragEndLocation.X - RowHeaderWidth + _HScrollBar.Value) / mw));
if (te < ts)
{
var tt = te;
te = ts;
ts = tt;
}
_SelectionTimeRange = new TimeRange { StartTime = ts, EndTime = te };
RangeSelected?.Invoke(this, new GanttChartRangeSelectedEventArgs(ts, te));
}
}
}
_IsMouseDown = false;
_DragStartLocation = Point.Empty;
_DragEndLocation = Point.Empty;
}
/// <summary>
/// 鼠标移动事件
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
protected void OnMouseMove(object sender, MouseEventArgs e)
{
if (_IsMouseDown)
{
if (_IsShowTooltip)
{
_IsShowTooltip = false;
_ShowTooltipItem = null;
_ShowTooltipPoint = Point.Empty;
Invalidate();
}
if (_IsDragItem)
{
}
else if (_DragStartLocation.X > RowHeaderWidth && _DragStartLocation.Y > ColumnHeight)
{
//TODO: 画选择框
_DragEndLocation = e.Location;
Invalidate();
}
return;
}
else if (IsHoverDateSplitLine(e.Location) && !IsHoverItem(e.Location))
{
Cursor = Cursors.VSplit;
}
//else if (IsHoverRowHeader(e))
//{
// Cursor = DefaultCursor;
//}
else if (IsHoverItem(e.Location))
{
Cursor = Cursors.Hand;
//TODO:显示Tooltip
if (!_IsShowTooltip || GetItem(e.Location) != _ShowTooltipItem)
{
_IsShowTooltip = true;
_ShowTooltipItem = GetItem(e.Location);
_ShowTooltipPoint = ComputeTooltipLocation(e.Location);
Invalidate();
return;
}
else
{
return;
}
}
else
{
Cursor = DefaultCursor;
}
if (_IsShowTooltip)
{
_IsShowTooltip = false;
_ShowTooltipItem = null;
_ShowTooltipPoint = Point.Empty;
Invalidate();
}
}
/// <summary>
/// 横向滚动事件
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void HScrollBar_Scroll(object sender, ScrollEventArgs e)
{
Invalidate();
}
/// <summary>
/// 纵向滚动事件
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void VScrollBar_Scroll(object sender, ScrollEventArgs e)
{
Invalidate();
}
/// <summary>
/// 属性改变事件
/// </summary>
/// <param name="name"></param>
/// <param name="value"></param>
private void OnPropertyChanged(string name, object value)
{
this.Brushes?.Refresh();
var args = new GanttChartPropertyChangeEventArgs(name, value);
PropertyChanged?.Invoke(this, args);
if(name == nameof(BlockType))
{
Rows.IsChanged = true;
}
AdjustScrollbar();
Invalidate();
}
}
}

217
GanttChart/GanttChartView.Logic.cs

@ -0,0 +1,217 @@
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace GanttChart
{
/// <summary>
/// 甘特图控件
/// 该部分类处理甘特图逻辑
/// </summary>
public partial class GanttChartView
{
/// <summary>
/// 鼠标是否经过日分割线
/// </summary>
/// <param name="e"></param>
/// <returns></returns>
private bool IsHoverDateSplitLine(Point e)
{
var t = (e.X + _HScrollBar.Value - RowHeaderWidth + this.DateWidth) % this.DateWidth;
return e.X > this.RowHeaderWidth + 3 && e.X < ((EndDate.Date - StartDate.Date).TotalDays + 1) * DateWidth + RowHeaderWidth - _HScrollBar.Value && (this.DateWidth - 2 <= t || t <= 1);
}
/// <summary>
/// 鼠标是否经过行标题
/// </summary>
/// <param name="e"></param>
/// <returns></returns>
private bool IsHoverRowHeader(Point e)
{
return e.X <= this.RowHeaderWidth && e.Y > this.ColumnHeight;
}
/// <summary>
/// 鼠标是否经过行
/// </summary>
/// <param name="e"></param>
/// <returns></returns>
private bool IsHoverRow(Point e)
{
var y = e.Y + _VScrollBar.Value;
return e.X < ((EndDate.Date - StartDate.Date).TotalDays + 1) * DateWidth + RowHeaderWidth - _HScrollBar.Value && e.Y > this.ColumnHeight && Rows != null ? Rows.Any(r=>r.Top <= y && r.Bottom >= y) : false;
}
/// <summary>
/// 鼠标是否经过项
/// </summary>
/// <param name="e"></param>
/// <returns></returns>
private bool IsHoverItem(Point e)
{
if(e.X > this.RowHeaderWidth && e.Y > this.ColumnHeight && Rows != null)
{
var row = GetRow(e);
if (row != null && row.Items != null && row.Items.Any())
{
var x = e.X + _HScrollBar.Value;
var y = e.Y + _VScrollBar.Value;
return row.Items.Any(r=>r.Left<=x && x <= r.Left + Math.Max(r.Width, r.TextWidth) && r.Top <= y && y <= r.Top + ItemHeight);
}
}
return false;
}
/// <summary>
/// 获取项
/// </summary>
/// <param name="e"></param>
/// <returns></returns>
private GanttChartViewItem GetItem(Point e)
{
if (e.X > this.RowHeaderWidth && e.X < ((EndDate.Date - StartDate.Date).TotalDays + 1) * DateWidth + RowHeaderWidth - _HScrollBar.Value && e.Y > this.ColumnHeight && Rows != null)
{
var row = GetRow(e);
if (row != null && row.Items != null && row.Items.Any())
{
var x = e.X + _HScrollBar.Value;
var y = e.Y + _VScrollBar.Value;
return row.Items.OrderBy(r=>r.Left).LastOrDefault(r => r.Left <= x && x <= r.Left + Math.Max(r.Width, r.TextWidth) && r.Top <= y && y <= r.Top + ItemHeight);
}
}
return null;
}
/// <summary>
/// 获取行
/// </summary>
/// <param name="e"></param>
/// <returns></returns>
private GanttChartViewRow GetRow(Point e)
{
if (e.X < ((EndDate.Date - StartDate.Date).TotalDays + 1) * DateWidth + RowHeaderWidth - _HScrollBar.Value && e.Y > this.ColumnHeight && e.Y + _VScrollBar.Value < (Rows == null || !Rows.Any() ? 0 : Rows.Max(r=>r.Bottom)) && Rows != null)
{
var y = e.Y + _VScrollBar.Value;
return Rows.FirstOrDefault(r => r.Top <= y && r.Bottom >= y);
}
return null;
}
/// <summary>
/// 计算所有行和项的大小
/// </summary>
private void ComputeRowsAndItemsSize()
{
var minuteWidth = DateWidth / 24f / 60f;
var currentRowY = ColumnHeight;
foreach (var row in Rows)
{
row.Top = currentRowY;
var currentItemY = currentRowY + RowSpacing;
row.Bottom = currentRowY;
if(row.Items != null)
{
var beforeTop = row.Top + RowSpacing;
var beforeRight = 0;
var items = row.Items.OrderBy(r => r.StartTime).ToList();
for ( int i = 0; i < items.Count; i++)
{
var item = items[i];
if (item.EndTime >= StartTime && item.StartTime <= EndTime && item.EndTime >= item.StartTime)
{
item.Left = (int)((item.StartTime - StartTime).TotalMinutes * minuteWidth) + RowHeaderWidth;
item.Width = (int)((item.EndTime - item.StartTime).TotalMinutes * minuteWidth);
item.TextWidth = TextRenderer.MeasureText(item.Title, ItemTextFont, System.Drawing.Size.Empty).Width;
if (item.Left < beforeRight || BlockType == GanttChartViewItemBlockType.Block && i > 0)
{
var its = items.Take(i).GroupBy(r=>r.Top).Select(r=>r.OrderByDescending(p => p.Left + p.TextWidth).First());
if(BlockType == GanttChartViewItemBlockType.Return && its.Any(r=>r.Left + r.TextWidth < item.Left))
{
var it = its.First(r => r.Left + r.TextWidth < item.Left);
item.Top = it.Top;
beforeTop = it.Top;
}
else
{
if(BlockType == GanttChartViewItemBlockType.Return && its.Any())
{
beforeTop = its.Max(r => r.Top);
}
item.Top = beforeTop + ItemHeight + ItemSpacing;
beforeTop += ItemHeight + ItemSpacing;
}
}
else
{
if (i > 0)
{
if (BlockType == GanttChartViewItemBlockType.Return && beforeTop != row.Top + RowSpacing)
{
beforeTop = row.Top + RowSpacing;
}
}
item.Top = beforeTop;
}
if (BlockType == GanttChartViewItemBlockType.Compact)
{
beforeRight = item.Left + item.Width;
}
else
{
beforeRight = item.Left + Math.Max(item.TextWidth, item.Width);
}
if (item.Ranges != null && item.Ranges.Any())
{
var subs = item.Ranges.OrderBy(r => r.StartTime);
foreach (var sub in subs)
{
sub.Left = item.Left + (int)((sub.StartTime - item.StartTime).TotalMinutes * minuteWidth);
sub.Width = (int)((sub.EndTime - sub.StartTime).TotalMinutes * minuteWidth);
}
}
}
else
{
//row.Items.Remove(item);
//i--;
}
}
}
if (row.Items == null || !row.Items.Any(r=>r.Left > 0))
{
row.Bottom = row.Top + ItemHeight + RowSpacing * 2;
}
else
{
row.Bottom = Math.Max(row.Items.Max(r => r.Top), ColumnHeight + RowSpacing) + ItemHeight + RowSpacing;
}
currentRowY = row.Bottom;
}
}
/// <summary>
/// 计算提示框的位置
/// </summary>
/// <param name="e"></param>
/// <returns></returns>
private Point ComputeTooltipLocation(Point e)
{
var size = TooltipOuterSize;
var x = e.X;
if (e.X + size.Width > _ContentControl.Width)
{
var t = e.X - size.Width;
if (t < 0 && 0 - t < (e.X + size.Width) - _ContentControl.Width || t >= 0)
{
x = t;
}
}
var y = _ShowTooltipItem.Top - _VScrollBar.Value + ItemHeight + ItemSpacing;
if(y + size.Height > _ContentControl.Height)
{
var t = _ShowTooltipItem.Top - _VScrollBar.Value - ItemSpacing - size.Height;
if (t < 0 && 0 - t < (y + size.Height) - _ContentControl.Height || t >= 0)
{
y = t;
}
}
return new Point(x, y);
}
}
}

756
GanttChart/GanttChartView.Properties.cs

@ -0,0 +1,756 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace GanttChart
{
/// <summary>
/// 甘特图控件
/// 该部分类主要是甘特图的属性
/// </summary>
public partial class GanttChartView
{
#region Fonts
private Font _ColumnDateTextFont = DefaultFont;
/// <summary>
/// 日期字体
/// </summary>
public Font ColumnDateTextFont
{
get { return _ColumnDateTextFont; }
set { _ColumnDateTextFont = value; OnPropertyChanged(nameof(ColumnDateTextFont), value); }
}
private Font _ColumnHourTextFont = DefaultFont;
/// <summary>
/// 时间字体
/// </summary>
public Font ColumnHourTextFont
{
get { return _ColumnHourTextFont; }
set { _ColumnHourTextFont = value; OnPropertyChanged(nameof(ColumnHourTextFont), value); }
}
private Font _RowHeaderTextFont = DefaultFont;
/// <summary>
/// 行标题字体
/// </summary>
public Font RowHeaderTextFont
{
get { return _RowHeaderTextFont; }
set { _RowHeaderTextFont = value; OnPropertyChanged(nameof(RowHeaderTextFont), value); }
}
private Font _ItemTextFont = DefaultFont;
/// <summary>
/// 项字体
/// </summary>
public Font ItemTextFont
{
get { return _ItemTextFont; }
set { _ItemTextFont = value; OnPropertyChanged(nameof(ItemTextFont), value); }
}
private Font _TooltipTextFont = DefaultFont;
/// <summary>
/// 提示文字字体
/// </summary>
public Font TooltipTextFont
{
get { return _TooltipTextFont; }
set { _TooltipTextFont = value; OnPropertyChanged(nameof(TooltipTextFont), value); }
}
#endregion
#region Colors
private Color _GridColor = Color.FromArgb(210, 210, 210);
/// <summary>
/// 网格颜色
/// </summary>
public Color GridColor
{
get { return _GridColor; }
set { _GridColor = value; OnPropertyChanged(nameof(GridColor), value); }
}
private Color _ColumnDateTextColor = Color.FromArgb(102, 102, 102);
/// <summary>
/// 日期文字颜色
/// </summary>
public Color ColumnDateTextColor
{
get { return _ColumnDateTextColor; }
set { _ColumnDateTextColor = value; OnPropertyChanged(nameof(ColumnDateTextColor), value); }
}
private Color _ColumnHourTextColor = Color.FromArgb(102, 102, 102);
/// <summary>
/// 小时文字颜色
/// </summary>
public Color ColumnHourTextColor
{
get { return _ColumnHourTextColor; }
set { _ColumnHourTextColor = value; OnPropertyChanged(nameof(ColumnHourTextColor), value); }
}
private Color _HeaderBackColor = Color.FromArgb(247, 247, 247);
/// <summary>
/// 标题背景颜色
/// </summary>
public Color HeaderBackColor
{
get { return _HeaderBackColor; }
set { _HeaderBackColor = value; OnPropertyChanged(nameof(HeaderBackColor), value); }
}
private Color _ContentBackColor = Color.White;
/// <summary>
/// 内容背景颜色
/// </summary>
public Color ContentBackColor
{
get { return _ContentBackColor; }
set { _ContentBackColor = value; OnPropertyChanged(nameof(ContentBackColor), value); }
}
private Color _CurrentTimeLineColor = Color.Red;
/// <summary>
/// 当前时间线颜色
/// </summary>
public Color CurrentTimeLineColor
{
get { return _CurrentTimeLineColor; }
set { _CurrentTimeLineColor = value; OnPropertyChanged(nameof(CurrentTimeLineColor), value); }
}
private Color _ItemTextColor = Color.FromArgb(51, 51, 51);
/// <summary>
/// 项文字颜色
/// </summary>
public Color ItemTextColor
{
get { return _ItemTextColor; }
set { _ItemTextColor = value; OnPropertyChanged(nameof(ItemTextColor), value); }
}
private Color _ItemBackColor = Color.FromArgb(190, 190, 190);
/// <summary>
/// 项背景颜色
/// </summary>
public Color ItemBackColor
{
get { return _ItemBackColor; }
set { _ItemBackColor = value; OnPropertyChanged(nameof(ItemBackColor), value); }
}
private Color _ItemBorderColor = Color.FromArgb(18, 170, 11);
/// <summary>
/// 项边框颜色
/// </summary>
public Color ItemBorderColor
{
get { return _ItemBorderColor; }
set { _ItemBorderColor = value; OnPropertyChanged(nameof(ItemBorderColor), value); }
}
private Color _ItemStartFlagColor = Color.Red;
/// <summary>
/// 项首标志颜色
/// </summary>
public Color ItemStartFlagColor
{
get { return _ItemStartFlagColor; }
set { _ItemStartFlagColor = value; OnPropertyChanged(nameof(ItemStartFlagColor), value); }
}
private Color _ItemSubRangeBackColor = Color.FromArgb(153, 201, 255);
/// <summary>
/// 项时间范围背景颜色
/// </summary>
public Color ItemSubRangeBackColor
{
get { return _ItemSubRangeBackColor; }
set { _ItemSubRangeBackColor = value; OnPropertyChanged(nameof(ItemSubRangeBackColor), value); }
}
private Color _ItemSelectionTextColor = Color.FromArgb(18, 170, 11);
/// <summary>
/// 选中项文字颜色
/// </summary>
public Color ItemSelectionTextColor
{
get { return _ItemSelectionTextColor; }
set { _ItemSelectionTextColor = value; OnPropertyChanged(nameof(ItemSelectionTextColor), value); }
}
private Color _ItemSelectionBackColor = Color.FromArgb(229, 249, 229);
/// <summary>
/// 选中项背景颜色
/// </summary>
public Color ItemSelectionBackColor
{
get { return _ItemSelectionBackColor; }
set { _ItemSelectionBackColor = value; OnPropertyChanged(nameof(ItemSelectionBackColor), value); }
}
private Color _ItemSelectionBorderColor = Color.FromArgb(18, 170, 11);
/// <summary>
/// 选中项边框颜色
/// </summary>
public Color ItemSelectionBorderColor
{
get { return _ItemSelectionBorderColor; }
set { _ItemSelectionBorderColor = value; OnPropertyChanged(nameof(ItemSelectionBorderColor), value); }
}
private Color _ItemSelectionSubRangeBackColor = Color.FromArgb(153, 201, 255);
/// <summary>
/// 选中项时间范围背景颜色
/// </summary>
public Color ItemSelectionSubRangeBackColor
{
get { return _ItemSelectionSubRangeBackColor; }
set { _ItemSelectionSubRangeBackColor = value; OnPropertyChanged(nameof(ItemSelectionSubRangeBackColor), value); }
}
private Color _RowHeaderTextColor = Color.FromArgb(102, 102, 102);
/// <summary>
/// 行标题文字颜色
/// </summary>
public Color RowHeaderTextColor
{
get { return _RowHeaderTextColor; }
set { _RowHeaderTextColor = value; OnPropertyChanged(nameof(RowHeaderTextColor), value); }
}
private Color _RowSelectionHeaderTextColor = Color.FromArgb(102, 102, 102);
/// <summary>
/// 选中行标题文字颜色
/// </summary>
public Color RowSelectionHeaderTextColor
{
get { return _RowSelectionHeaderTextColor; }
set { _RowSelectionHeaderTextColor = value; OnPropertyChanged(nameof(RowSelectionHeaderTextColor), value); }
}
private Color _RowSelectionBorderColor = Color.FromArgb(247, 247, 247);
/// <summary>
/// 选中行边框颜色
/// </summary>
public Color RowSelectionBorderColor
{
get { return _RowSelectionBorderColor; }
set { _RowSelectionBorderColor = value; OnPropertyChanged(nameof(RowSelectionBorderColor), value); }
}
private Color _RowSelectionHeaderBackColor = Color.FromArgb(247, 247, 247);
/// <summary>
/// 选中行标题背景颜色
/// </summary>
public Color RowSelectionHeaderBackColor
{
get { return _RowSelectionHeaderBackColor; }
set { _RowSelectionHeaderBackColor = value; OnPropertyChanged(nameof(RowSelectionHeaderBackColor), value); }
}
private Color _RowSelectionContentBackColor = Color.FromArgb(247, 247, 247);
/// <summary>
/// 选中行内容背景颜色
/// </summary>
public Color RowSelectionContentBackColor
{
get { return _RowSelectionContentBackColor; }
set { _RowSelectionContentBackColor = value; OnPropertyChanged(nameof(RowSelectionContentBackColor), value); }
}
private Color _TooltipTextColor = Color.FromArgb(237, 237, 237);
/// <summary>
/// 提示文字颜色
/// </summary>
public Color TooltipTextColor
{
get { return _TooltipTextColor; }
set { _TooltipTextColor = value; OnPropertyChanged(nameof(TooltipTextColor), value); }
}
private Color _TooltipBorderColor = Color.FromArgb(102, 0, 0, 0);
/// <summary>
/// 提示边框颜色
/// </summary>
public Color TooltipBorderColor
{
get { return _TooltipBorderColor; }
set { _TooltipBorderColor = value; OnPropertyChanged(nameof(TooltipBorderColor), value); }
}
private Color _TooltipBackColor = Color.FromArgb(102, 0, 0, 0);
/// <summary>
/// 提示背景颜色
/// </summary>
public Color TooltipBackColor
{
get { return _TooltipBackColor; }
set { _TooltipBackColor = value; OnPropertyChanged(nameof(TooltipBackColor), value); }
}
private Color _TimeRangeSelecetionBackColor = Color.FromArgb(153, 201, 255);
/// <summary>
/// 选中时间范围背景颜色
/// </summary>
public Color TimeRangeSelecetionBackColor
{
get { return _TimeRangeSelecetionBackColor; }
set { _TimeRangeSelecetionBackColor = value; OnPropertyChanged(nameof(TimeRangeSelecetionBackColor), value); }
}
private Color _SelectionRectangleBackColor = Color.FromArgb(80, 210, 210, 210);
/// <summary>
/// 选择框背景颜色
/// </summary>
public Color SelectionRectangleBackColor
{
get { return _SelectionRectangleBackColor; }
set { _SelectionRectangleBackColor = value; OnPropertyChanged(nameof(SelectionRectangleBackColor), value); }
}
private Color _ItemWarnningTextColor = Color.Red;
/// <summary>
/// 项警告文字颜色
/// </summary>
public Color ItemWarnningTextColor
{
get { return _ItemWarnningTextColor; }
set { _ItemWarnningTextColor = value; OnPropertyChanged(nameof(ItemWarnningTextColor), value); }
}
#endregion
#region Mouse
private float _MouseWheelSensitivity = 0.5f;
/// <summary>
/// 鼠标滚轮灵敏度
/// </summary>
[DefaultValue(0.5f)]
public float MouseWheelSensitivity
{
get { return _MouseWheelSensitivity; }
set { _MouseWheelSensitivity = value; OnPropertyChanged(nameof(MouseWheelSensitivity), value); }
}
#endregion
#region Size
private int _ItemHeight = 30;
/// <summary>
/// 项高度
/// </summary>
[DefaultValue(30)]
public int ItemHeight
{
get { return _ItemHeight; }
set { _ItemHeight = value; OnPropertyChanged(nameof(ItemHeight), value); }
}
private int _RowHeaderWidth = 150;
/// <summary>
/// 行标题宽度
/// </summary>
[DefaultValue(150)]
public int RowHeaderWidth
{
get { return _RowHeaderWidth; }
set { _RowHeaderWidth = value; OnPropertyChanged(nameof(RowHeaderWidth), value); }
}
private int _RowHeight = 100;
/// <summary>
/// 行高
/// </summary>
[DefaultValue(100)]
public int RowHeight
{
get { return _RowHeight; }
set { _RowHeight = value; OnPropertyChanged(nameof(RowHeight), value); }
}
private int _ColumnDateHeight = 30;
/// <summary>
/// 日期高度
/// </summary>
[DefaultValue(30)]
public int ColumnDateHeight
{
get { return _ColumnDateHeight; }
set { _ColumnDateHeight = value; OnPropertyChanged(nameof(ColumnDateHeight), value); }
}
private int _ColumnHourHeight = 30;
/// <summary>
/// 小时高度
/// </summary>
[DefaultValue(30)]
public int ColumnHourHeight
{
get { return _ColumnHourHeight; }
set { _ColumnHourHeight = value; OnPropertyChanged(nameof(ColumnHourHeight), value); }
}
private int _DateWidth = MinDateWidth;
/// <summary>
/// 日期宽度
/// </summary>
[DefaultValue(MinDateWidth)]
public int DateWidth
{
get { return _DateWidth; }
set { _DateWidth = value; OnPropertyChanged(nameof(DateWidth), value); }
}
private int _HScrollHeight = 15;
/// <summary>
/// 横向滚动条高度
/// </summary>
[DefaultValue(15)]
public int HScrollHeight
{
get { return _HScrollHeight; }
set { _HScrollHeight = value; OnPropertyChanged(nameof(HScrollHeight), value); }
}
private int _VScrollWidth = 15;
/// <summary>
/// 纵向滚动条宽度
/// </summary>
[DefaultValue(15)]
public int VScrollWidth
{
get { return _VScrollWidth; }
set { _VScrollWidth = value; OnPropertyChanged(nameof(VScrollWidth), value); }
}
private int _ItemSpacing = 2;
/// <summary>
/// 项的行间距
/// </summary>
[DefaultValue(2)]
public int ItemSpacing
{
get { return _ItemSpacing; }
set { _ItemSpacing = value; OnPropertyChanged(nameof(ItemSpacing), value); }
}
private int _RowSpacing = 5;
/// <summary>
/// 行间距
/// </summary>
[DefaultValue(5)]
public int RowSpacing
{
get { return _RowSpacing; }
set { _RowSpacing = value; OnPropertyChanged(nameof(RowSpacing), value); }
}
#endregion
#region Control
private bool _IsFixedRowHeight = false;
/// <summary>
/// 是否固定行高
/// </summary>
[DefaultValue(false)]
public bool IsFixedRowHeight
{
get { return _IsFixedRowHeight; }
set { _IsFixedRowHeight = value; OnPropertyChanged(nameof(IsFixedRowHeight), value); }
}
private bool _EnableEdit = false;
/// <summary>
/// 启用编辑
/// </summary>
[DefaultValue(false)]
public bool EnableEdit
{
get { return _EnableEdit; }
set { _EnableEdit = value; OnPropertyChanged(nameof(EnableEdit), value); }
}
private bool _AllowItemNotWrap = true;
/// <summary>
/// 允许项文字换行
/// </summary>
[DefaultValue(true)]
public bool AllowItemNotWrap
{
get { return _AllowItemNotWrap; }
set { _AllowItemNotWrap = value; OnPropertyChanged(nameof(AllowItemNotWrap), value); }
}
private bool _IsShowItemBorder = false;
/// <summary>
/// 是否显示项边框
/// </summary>
[DefaultValue(false)]
public bool IsShowItemBorder
{
get { return _IsShowItemBorder; }
set { _IsShowItemBorder = value; OnPropertyChanged(nameof(IsShowItemBorder), value); }
}
private bool _AllowHeaderNotWrap = true;
/// <summary>
/// 允许行标题文字换行
/// </summary>
[DefaultValue(true)]
public bool AllowHeaderNotWrap
{
get { return _AllowHeaderNotWrap; }
set { _AllowHeaderNotWrap = value; OnPropertyChanged(nameof(AllowHeaderNotWrap), value); }
}
private GanttChartViewItemBlockType _BlockType = GanttChartViewItemBlockType.TextOverBlock;
/// <summary>
/// 项换行模式
/// </summary>
public GanttChartViewItemBlockType BlockType
{
get { return _BlockType; }
set { _BlockType = value; OnPropertyChanged(nameof(BlockType), value); }
}
private bool _IsShowSelectionBorder = false;
/// <summary>
/// 显示行选中高亮边框
/// </summary>
[DefaultValue(false)]
public bool IsShowSelectionBorder
{
get { return _IsShowSelectionBorder; }
set { _IsShowSelectionBorder = value; OnPropertyChanged(nameof(IsShowSelectionBorder), value); }
}
private bool _AllowSelectRange = false;
/// <summary>
/// 允许选中时间范围
/// </summary>
[DefaultValue(false)]
public bool AllowSelectRange
{
get { return _AllowSelectRange; }
set { _AllowSelectRange = value; OnPropertyChanged(nameof(AllowSelectRange), value); }
}
private Func<GanttChartViewItem, GanttChartViewItem, bool> _SelectionItemSameComparator = null;
/// <summary>
/// 选择项的同类项比较器
/// </summary>
public Func<GanttChartViewItem, GanttChartViewItem, bool> SelectionItemSameComparator
{
get { return _SelectionItemSameComparator; }
set { _SelectionItemSameComparator = value; }
}
#endregion
#region DataSource
private DateTime _StartDate = DateTime.Today;
/// <summary>
/// 开始日期
/// </summary>
public DateTime StartDate
{
get { return _StartDate; }
set { _StartDate = value; OnPropertyChanged(nameof(StartDate), value); }
}
private DateTime _EndDate = DateTime.Today.AddDays(1);
/// <summary>
/// 结束日期
/// </summary>
public DateTime EndDate
{
get { return _EndDate; }
set { _EndDate = value; OnPropertyChanged(nameof(EndDate), value); }
}
private GanttChartCollection<GanttChartViewRow> _Rows = new GanttChartCollection<GanttChartViewRow>();
/// <summary>
/// 行集合
/// </summary>
public GanttChartCollection<GanttChartViewRow> Rows
{
get { return _Rows; }
set { _Rows = value; OnPropertyChanged(nameof(Rows), value); }
}
private GanttChartViewRow _SelectionRow = null;
/// <summary>
/// 选中的行
/// </summary>
public GanttChartViewRow SelectionRow
{
get { return _SelectionRow; }
set { _SelectionRow = value; OnPropertyChanged(nameof(SelectionRow), value); }
}
private GanttChartViewItem _SelectionItem = null;
/// <summary>
/// 选中的项
/// </summary>
public GanttChartViewItem SelectionItem
{
get { return _SelectionItem; }
set { _SelectionItem = value; OnPropertyChanged(nameof(SelectionItem), value); }
}
private TimeRange _SelectionTimeRange = null;
/// <summary>
/// 选中的时间范围
/// </summary>
public TimeRange SelectionTimeRange
{
get { return _SelectionTimeRange; }
set { _SelectionTimeRange = value; OnPropertyChanged(nameof(SelectionTimeRange), value); }
}
private DateTime _DateSplitTime = DateTime.MinValue;
/// <summary>
/// 日分割时间
/// </summary>
public DateTime DateSplitTime
{
get { return _DateSplitTime; }
set { _DateSplitTime = value; OnPropertyChanged(nameof(DateSplitTime), value); }
}
private string _DateTimeShowText = "时间";
/// <summary>
/// 时间显示文本
/// </summary>
[DefaultValue("时间")]
public string DateTimeShowText
{
get { return _DateTimeShowText; }
set { _DateTimeShowText = value; OnPropertyChanged(nameof(DateTimeShowText), value); }
}
private string _RowTitleShowText = "资源";
/// <summary>
/// 行头显示文本
/// </summary>
[DefaultValue("资源")]
public string RowTitleShowText
{
get { return _RowTitleShowText; }
set { _RowTitleShowText = value; OnPropertyChanged(nameof(RowTitleShowText), value); }
}
#endregion
#region ReadOnly
public int ColumnHeight
{
get { return ColumnDateHeight + ColumnHourHeight; }
}
public int TotalDays
{
get
{
return (int)(EndDate.Date - StartDate.Date).TotalDays + 1;
}
}
public DateTime StartTime
{
get
{
return StartDate.Date.Add(DateSplitTime - DateSplitTime.Date);
}
}
public DateTime EndTime
{
get
{
return EndDate.Date.Add(DateSplitTime - DateSplitTime.Date);
}
}
private Size TooltipSize
{
get
{
var size = TextRenderer.MeasureText(_ShowTooltipItem.Tooltip, TooltipTextFont, Size.Empty);
size.Height = size.Height + (int)((_ShowTooltipItem.Tooltip.Split(new string[] { Environment.NewLine }, StringSplitOptions.None).Length - 1) * 1.7);
return size;
}
}
private Size TooltipOuterSize
{
get
{
var size = TooltipSize;
size.Width += RowSpacing * 2;
size.Height += RowSpacing * 2;
return size;
}
}
#endregion
#region Const
private const int MinDateWidth = 3 * 48;
#endregion
}
}

409
GanttChart/GanttChartView.Render.cs

@ -0,0 +1,409 @@
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace GanttChart
{
/// <summary>
/// 甘特图控件
/// 该部分类用于处理甘特图的绘制渲染
/// </summary>
public partial class GanttChartView
{
/// <summary>
/// 画背景
/// </summary>
/// <param name="graphics"></param>
/// <param name="bottom"></param>
protected virtual void DrawBack(Graphics graphics, int bottom)
{
graphics.FillRectangle(this.Brushes.BackBrush, _ContentControl.DisplayRectangle);
var range = new RectangleF(new PointF(0, 0), new SizeF(TotalDays * DateWidth + RowHeaderWidth - _HScrollBar.Value, bottom - _VScrollBar.Value));
graphics.SetClip(range);
graphics.FillRectangle(this.Brushes.HeaderBackBrush, range);
range = new RectangleF(new PointF(0, ColumnHeight), new SizeF(TotalDays * DateWidth + RowHeaderWidth - _HScrollBar.Value, bottom - ColumnHeight - _VScrollBar.Value));
graphics.FillRectangle(this.Brushes.ContentBackBrush, range);
if (_SelectionRow != null)
{
var selectionHeader = new Rectangle(1, _SelectionRow.Top + 1 - _VScrollBar.Value, RowHeaderWidth - 2, (int)(_SelectionRow.Bottom - _SelectionRow.Top - 1));
var selectionContent = new Rectangle(RowHeaderWidth, _SelectionRow.Top + 1 - _VScrollBar.Value, (int)(TotalDays * DateWidth - _HScrollBar.Value - 1), selectionHeader.Height);
graphics.FillRectangle(this.Brushes.RowSelectionHeaderBackBrush, selectionHeader);
graphics.FillRectangle(this.Brushes.RowSelectionContentBackBrush, selectionContent);
}
graphics.ResetClip();
}
/// <summary>
/// 画没有数据
/// </summary>
/// <param name="graphics"></param>
/// <param name="bottom"></param>
protected virtual void DrawNonData(Graphics graphics, int bottom)
{
}
/// <summary>
/// 画提示框
/// </summary>
/// <param name="graphics"></param>
protected virtual void DrawItemTooltip(Graphics graphics)
{
if (!_IsShowTooltip) return;
var size = TooltipSize;
var border = new Rectangle(_ShowTooltipPoint, new Size(size.Width + RowSpacing * 2, size.Height + RowSpacing * 2));
var content = new Point(_ShowTooltipPoint.X + RowSpacing, _ShowTooltipPoint.Y + RowSpacing);
graphics.FillRectangle(this.Brushes.TooltipBackBrush, border);
graphics.DrawRectangle(this.Brushes.TooltipBorderPen, border);
graphics.DrawString(_ShowTooltipItem.Tooltip, TooltipTextFont, this.Brushes.TooltipTextBrush, content);
//TextRenderer.DrawText(graphics, _ShowTooltipItem.Tooltip, TooltipTextFont, content, TooltipTextColor);
}
/// <summary>
/// 画选中范围
/// </summary>
/// <param name="graphics"></param>
protected virtual void DrawSelectionRange(Graphics graphics)
{
if (!AllowSelectRange || _SelectionRange.IsEmpty) return;
graphics.FillRectangle(this.Brushes.TimeRangeSelecetionBackBrush, _SelectionRange);
}
/// <summary>
/// 画选中的矩形
/// </summary>
/// <param name="graphics"></param>
protected virtual void DrawSelectingRectangle(Graphics graphics)
{
if (!AllowSelectRange || _DragStartLocation.IsEmpty || _DragEndLocation.IsEmpty || _DragStartLocation == _DragEndLocation || _DragStartLocation.X <= RowHeaderWidth || _DragStartLocation.Y <= ColumnHeight) return;
var row = GetRow(_DragStartLocation);
if (row == null) return;
var start = new Point(Math.Min(_DragStartLocation.X, Math.Max(_DragEndLocation.X, RowHeaderWidth)), Math.Min(_DragStartLocation.Y, Math.Max(_DragEndLocation.Y, row.Top)));
var height = Math.Abs(Math.Min(_DragEndLocation.Y, row.Bottom - _VScrollBar.Value) - _DragStartLocation.Y);
var width = Math.Abs(_DragEndLocation.X - _DragStartLocation.X);
if (_DragEndLocation.Y < row.Top)
{
height -= row.Top - _DragEndLocation.Y;
}
if (_DragEndLocation.X < RowHeaderWidth)
{
width -= RowHeaderWidth - _DragEndLocation.X;
}
else if(_DragEndLocation.X > TotalDays * DateWidth + RowHeaderWidth - _HScrollBar.Value)
{
width = TotalDays * DateWidth + RowHeaderWidth - _HScrollBar.Value - _DragStartLocation.X;
}
var rect = new RectangleF(start, new SizeF(width, height));
graphics.FillRectangle(this.Brushes.SelectionRectangleBackBrush, rect);
}
/// <summary>
/// 画项的时间范围
/// </summary>
/// <param name="graphics"></param>
/// <param name="item"></param>
/// <param name="sub"></param>
protected virtual void DrawItemTimeRange(Graphics graphics, GanttChartViewItem item, TimeRange sub)
{
var width = sub.Width;
var right = sub.Left + sub.Width;
if (right == item.Left + item.Width)
{
width = width - 2;
if(width < 1)
{
return;
}
}
if (item == _SelectionItem)
{
graphics.FillRectangle(this.Brushes.ItemSelectionSubRangeBackBrush, sub.Left - _HScrollBar.Value, item.Top - _VScrollBar.Value, width, ItemHeight);
graphics.DrawRectangle(this.Brushes.ItemSelectionSubRangeBackPen, sub.Left - _HScrollBar.Value, item.Top - _VScrollBar.Value, width, ItemHeight);
}
else
{
graphics.FillRectangle(this.Brushes.ItemSubRangeBackBrush, sub.Left - _HScrollBar.Value, item.Top - _VScrollBar.Value, width, ItemHeight);
graphics.DrawRectangle(this.Brushes.ItemSubRangeBackPen, sub.Left - _HScrollBar.Value, item.Top - _VScrollBar.Value, width, ItemHeight);
}
}
/// <summary>
/// 画项
/// </summary>
/// <param name="graphics"></param>
/// <param name="titleFormat"></param>
/// <param name="item"></param>
/// <param name="range"></param>
protected virtual void DrawItem(Graphics graphics, StringFormat titleFormat, GanttChartViewItem item, RectangleF range)
{
var clip = new RectangleF(range.X, (range.Y < ColumnHeight ? ColumnHeight : range.Y) + 1, range.Width, (range.Y < ColumnHeight ? (range.Height - (ColumnHeight - range.Y)) : range.Height) - 2);
graphics.SetClip(clip);
if (item.Ranges != null && item.Ranges.Any())
{
graphics.FillRectangle(this.Brushes.ItemBackBrush, item.Left - _HScrollBar.Value, item.Top - _VScrollBar.Value, Math.Max(item.Width - 2, 2), ItemHeight);
graphics.DrawRectangle(this.Brushes.ItemBackPen, item.Left - _HScrollBar.Value, item.Top - _VScrollBar.Value, Math.Max(item.Width - 2, 2), ItemHeight);
var subs = item.Ranges.OrderBy(r => r.StartTime);
foreach (var sub in subs)
{
DrawItemTimeRange(graphics, item, sub);
}
}
else
{
graphics.FillRectangle(this.Brushes.ItemSubRangeBackBrush, item.Left - _HScrollBar.Value, item.Top - _VScrollBar.Value, Math.Max(item.Width - 2, 2), ItemHeight);
graphics.DrawRectangle(this.Brushes.ItemSubRangeBackPen, item.Left - _HScrollBar.Value, item.Top - _VScrollBar.Value, Math.Max(item.Width - 2, 2), ItemHeight);
}
if (item == _SelectionItem)
{
var textBrush = item.IsWarnning ? this.Brushes.ItemWarnningTextBrush : this.Brushes.ItemSelectionTextBrush;
graphics.DrawLine(this.Brushes.ItemStartFlagPen, item.Left - _HScrollBar.Value + 1, item.Top - _VScrollBar.Value + ItemHeight / 2, item.Left - _HScrollBar.Value + 1, item.Top - _VScrollBar.Value + ItemHeight);
graphics.DrawRectangle(this.Brushes.ItemSelectionBorderPen, item.Left - _HScrollBar.Value, item.Top - _VScrollBar.Value, Math.Max(item.Width - 2, 2), ItemHeight);
graphics.DrawString(item.Title, ItemTextFont, textBrush, new RectangleF(item.Left - _HScrollBar.Value + 2, item.Top - _VScrollBar.Value + 1, 0, ItemHeight - 2), titleFormat);
}
else if(_SelectionItem != null && SelectionItemSameComparator != null && SelectionItemSameComparator(item, _SelectionItem))
{
var textBrush = item.IsWarnning ? this.Brushes.ItemWarnningTextBrush : this.Brushes.ItemSelectionTextBrush;
graphics.DrawLine(this.Brushes.ItemStartFlagPen, item.Left - _HScrollBar.Value + 1, item.Top - _VScrollBar.Value + ItemHeight / 2, item.Left - _HScrollBar.Value + 1, item.Top - _VScrollBar.Value + ItemHeight);
if (IsShowItemBorder)
graphics.DrawRectangle(this.Brushes.ItemBorderPen, item.Left - _HScrollBar.Value, item.Top - _VScrollBar.Value, Math.Max(item.Width - 2, 2), ItemHeight);
graphics.DrawString(item.Title, ItemTextFont, textBrush, new RectangleF(item.Left - _HScrollBar.Value + 2, item.Top - _VScrollBar.Value + 1, 0, ItemHeight - 2), titleFormat);
}
else
{
var textBrush = item.IsWarnning ? this.Brushes.ItemWarnningTextBrush : this.Brushes.ItemTextBrush;
graphics.DrawLine(this.Brushes.ItemStartFlagPen, item.Left - _HScrollBar.Value + 1, item.Top - _VScrollBar.Value + ItemHeight / 2, item.Left - _HScrollBar.Value + 1, item.Top - _VScrollBar.Value + ItemHeight);
if (IsShowItemBorder)
graphics.DrawRectangle(this.Brushes.ItemBorderPen, item.Left - _HScrollBar.Value, item.Top - _VScrollBar.Value, Math.Max(item.Width - 2, 2), ItemHeight);
graphics.DrawString(item.Title, ItemTextFont, textBrush, new RectangleF(item.Left - _HScrollBar.Value + 2, item.Top - _VScrollBar.Value + 1, 0, ItemHeight - 2), titleFormat);
}
graphics.ResetClip();
}
/// <summary>
/// 画行
/// </summary>
/// <param name="graphics"></param>
/// <param name="headerFormat"></param>
/// <param name="titleFormat"></param>
/// <param name="row"></param>
/// <param name="range"></param>
/// <param name="rowRect"></param>
protected virtual void DrawRow(Graphics graphics, StringFormat headerFormat, StringFormat titleFormat, GanttChartViewRow row, RectangleF range, RectangleF rowRect)
{
graphics.SetClip(range);
var drawY = rowRect.Y + RowSpacing;
var drawHeight = rowRect.Height - RowSpacing * 2;
if (drawHeight > (_ContentControl.Height - ColumnHeight) / 4)
{
drawY = Math.Max(rowRect.Y, ColumnHeight);
drawHeight = Math.Min(rowRect.Bottom - RowSpacing, _ContentControl.Height) - drawY;
}
graphics.DrawString(row.Title, RowHeaderTextFont, this.Brushes.RowHeaderTextBrush, new RectangleF(rowRect.X + RowSpacing, drawY, RowHeaderWidth - RowSpacing * 2, drawHeight), headerFormat);
graphics.ResetClip();
if(row.Items != null)
{
var items = row.Items.OrderBy(r=>r.StartTime);
foreach (var item in items)
{
if (item.Left + item.Width - _HScrollBar.Value > RowHeaderWidth)
{
if (item.Left - _HScrollBar.Value < range.Right)
{
DrawItem(graphics, titleFormat, item, new RectangleF(RowHeaderWidth + 1, rowRect.Y + 1, rowRect.Width - RowHeaderWidth - 2, rowRect.Height - 2));
}
}
}
}
graphics.SetClip(range);
graphics.DrawLine(this.Brushes.GridPen, 0, row.Bottom - _VScrollBar.Value, rowRect.Width, row.Bottom - _VScrollBar.Value);
if (_SelectionRow == row && IsShowSelectionBorder)
{
var selectionRect = new Rectangle(1, row.Top + 1, (int)(range.Width - 3), (int)(row.Bottom - row.Top - 2));
graphics.DrawRectangle(this.Brushes.RowSelectionBorderPen, selectionRect);
}
graphics.ResetClip();
}
/// <summary>
/// 画所有行
/// </summary>
/// <param name="graphics"></param>
/// <param name="bottom"></param>
protected virtual void DrawRows(Graphics graphics, int bottom)
{
var range = new RectangleF(0, ColumnHeight, RowHeaderWidth + TotalDays * DateWidth - _HScrollBar.Value, bottom - _VScrollBar.Value + 1);
graphics.DrawLine(this.Brushes.GridPen, RowHeaderWidth, ColumnDateHeight, range.Width - 1, ColumnDateHeight);
graphics.SetClip(range);
graphics.DrawLine(this.Brushes.GridPen, 0, ColumnHeight, range.Width - 1, ColumnHeight);
if (Rows == null || !Rows.Any())
{
DrawNonData(graphics, bottom);
graphics.DrawLine(this.Brushes.GridPen, 0, bottom, range.Width - 1, bottom);
return;
}
graphics.ResetClip();
var headerFormat = new StringFormat();
headerFormat.Alignment = StringAlignment.Near;
headerFormat.LineAlignment = StringAlignment.Center;
var titleFormat = new StringFormat();
titleFormat.Alignment = StringAlignment.Near;
titleFormat.LineAlignment = StringAlignment.Center;
titleFormat.FormatFlags = BlockType == GanttChartViewItemBlockType.Compact ? StringFormatFlags.LineLimit : StringFormatFlags.NoWrap;
foreach (var row in Rows)
{
if (row.Bottom - _VScrollBar.Value > ColumnHeight)
{
var rowRect = new RectangleF(new PointF(0, row.Top - _VScrollBar.Value), new SizeF(range.Width, row.Bottom - row.Top + 1));
if (!range.IntersectsWith(rowRect)) break;
DrawRow(graphics, headerFormat, titleFormat, row, range, rowRect);
}
}
}
/// <summary>
/// 画列
/// </summary>
/// <param name="graphics"></param>
/// <param name="format"></param>
/// <param name="date"></param>
/// <param name="range"></param>
/// <param name="startX"></param>
/// <param name="width"></param>
/// <param name="cellHour"></param>
protected virtual void DrawColumn(Graphics graphics, StringFormat format, DateTime date, RectangleF range, int startX, int width, int cellHour)
{
var offsetMinutes = (int)(DateSplitTime - DateSplitTime.Date).TotalMinutes % (60 * cellHour);
var offset = (int)(offsetMinutes / 60f * width);
startX = startX - offset;
var dt = date.AddMinutes(-offsetMinutes);
for (DateTime i = dt; i < dt.AddDays(1); i = i.AddHours(cellHour))
{
var rectangle = new RectangleF(startX, ColumnDateHeight + 1, 0, ColumnHourHeight - 2);
if (range.IntersectsWith(rectangle) && (offset != 0 || date.Hour != i.Hour))
{
graphics.DrawString(i.Hour == 0 ? "0" : i.Hour.ToString("##00"), ColumnDateTextFont, this.Brushes.ColumnHourTextBrush, rectangle, format);
//graphics.DrawLine(this.Brushes.GridPen, rectangle.X, ColumnDateHeight, rectangle.X, ColumnDateHeight + ColumnHourHeight / 5);
graphics.DrawLine(this.Brushes.GridPen, rectangle.X, ColumnDateHeight + ColumnHourHeight / 5 * 4, rectangle.X, ColumnDateHeight + ColumnHourHeight - 1);
}
startX += width * cellHour;
}
}
/// <summary>
/// 画列头
/// </summary>
/// <param name="graphics"></param>
protected virtual void DrawColumnHeader(Graphics graphics)
{
var range = new RectangleF(new PointF(RowHeaderWidth + 1, 1), new SizeF(TotalDays * DateWidth - 1, _ContentControl.Height - 2));
graphics.SetClip(range);
int cellHour = GetCellHours();
var format = new StringFormat();
format.Alignment = StringAlignment.Center;
format.LineAlignment = StringAlignment.Center;
format.FormatFlags = StringFormatFlags.LineLimit;
var x = RowHeaderWidth;
for (var i = StartTime; i <= EndTime; i = i.AddDays(1))
{
var dx = x - _HScrollBar.Value;
var rectangle = new RectangleF(dx + 1, 1, DateWidth - 1, ColumnDateHeight - 2);
if (rectangle.Right > RowHeaderWidth)
{
if (!range.IntersectsWith(rectangle))
{
x += DateWidth;
continue;
}
graphics.DrawString(i.ToString("yyyy-MM-dd") + " 星期" + ("日一二三四五六"[(int)i.DayOfWeek]), ColumnDateTextFont, this.Brushes.ColumnDateTextBrush, rectangle, format);
DrawColumn(graphics, format, i, range, (int)rectangle.X - 1, DateWidth / 24, cellHour);
}
x += DateWidth;
}
graphics.ResetClip();
}
/// <summary>
/// 画行头
/// </summary>
/// <param name="graphics"></param>
/// <param name="bottom"></param>
protected virtual void DrawHeader(Graphics graphics, int bottom)
{
var range = new RectangleF(new PointF(0, 0), new SizeF(RowHeaderWidth + TotalDays * DateWidth, bottom - _VScrollBar.Value));
graphics.SetClip(range);
graphics.DrawLine(this.Brushes.GridPen, range.X, range.Y, range.X + RowHeaderWidth, range.Y + ColumnHeight);
graphics.DrawString(this.DateTimeShowText, this.ColumnDateTextFont, this.Brushes.ColumnDateTextBrush,
new Rectangle(0, 0, RowHeaderWidth - RowSpacing, ColumnDateHeight),
new StringFormat { Alignment = StringAlignment.Far, LineAlignment = StringAlignment.Center });
graphics.DrawString(this.RowTitleShowText, this.RowHeaderTextFont, this.Brushes.RowHeaderTextBrush,
new Rectangle(RowSpacing, ColumnDateHeight, RowHeaderWidth - RowSpacing, ColumnHourHeight - RowSpacing),
new StringFormat { Alignment = StringAlignment.Near, LineAlignment = StringAlignment.Far });
graphics.ResetClip();
}
/// <summary>
/// 画时间线
/// </summary>
/// <param name="graphics"></param>
/// <param name="bottom"></param>
protected virtual void DrawTimeLine(Graphics graphics, int bottom)
{
var range = new RectangleF(new PointF(0, 0), new SizeF(RowHeaderWidth + TotalDays * DateWidth, bottom - _VScrollBar.Value));
graphics.SetClip(range);
graphics.DrawRectangle(this.Brushes.GridPen, _ContentControl.DisplayRectangle);
var x = RowHeaderWidth - 1;
if(StartTime == DateTime.Today.Add(DateSplitTime - DateSplitTime.Date))
{
graphics.DrawLine(this.Brushes.CurrentTimeLinePen, x, 0, x, _ContentControl.Height);
}
else
{
graphics.DrawLine(this.Brushes.GridPen, x, 0, x, _ContentControl.Height);
}
for (var i = StartTime; i <= EndTime; i = i.AddDays(1))
{
x += DateWidth;
var dx = x - _HScrollBar.Value;
if (dx + 1 > RowHeaderWidth)
{
if (dx + 1 > _ContentControl.Width) break;
if(i.AddDays(1) == DateTime.Today.Add(DateSplitTime - DateSplitTime.Date))
{
graphics.DrawLine(this.Brushes.CurrentTimeLinePen, dx, 0, dx, _ContentControl.Height);
}
else
{
graphics.DrawLine(this.Brushes.GridPen, dx, 0, dx, _ContentControl.Height);
}
}
}
graphics.ResetClip();
}
/// <summary>
/// 计算单元格小时
/// </summary>
/// <returns></returns>
private int GetCellHours()
{
var halfHourWidth = DateWidth / 48;
int cellHour;
if (halfHourWidth >= 12)
{
cellHour = 1;
}
else if (halfHourWidth >= 6)
{
cellHour = 2;
}
else if (halfHourWidth >= 4)
{
cellHour = 3;
}
else if (halfHourWidth >= 3)
{
cellHour = 4;
}
else if (halfHourWidth >= 2)
{
cellHour = 6;
}
else
{
cellHour = 12;
}
return cellHour;
}
}
}

137
GanttChart/GanttChartView.cs

@ -0,0 +1,137 @@
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace GanttChart
{
/// <summary>
/// 甘特图控件
/// </summary>
[ToolboxBitmap(typeof(GanttChartView), "GanttChart.GanttChartView.bmp")]
public partial class GanttChartView: Control
{
#region Private Members
private HScrollBar _HScrollBar;
private VScrollBar _VScrollBar;
private TableLayoutPanel _Table;
private Control _ContentControl;
private GanttChartBrushes Brushes;
#endregion
#region ctor
public GanttChartView()
{
_Table = new TableLayoutPanel();
_Table.ColumnCount = 2;
_Table.RowCount = 2;
_Table.ColumnStyles.Add(new ColumnStyle(SizeType.AutoSize));
_Table.ColumnStyles.Add(new ColumnStyle(SizeType.Absolute, VScrollWidth));
_Table.RowStyles.Add(new RowStyle(SizeType.AutoSize));
_Table.RowStyles.Add(new RowStyle(SizeType.Absolute, HScrollHeight));
_ContentControl = new GanttChartCanvas();
_ContentControl.Dock = DockStyle.Fill;
_ContentControl.Margin = new Padding(0);
_Table.Controls.Add(_ContentControl, 0, 0);
_HScrollBar = new HScrollBar();
_HScrollBar.Value = 0;
_HScrollBar.Height = HScrollHeight;
_HScrollBar.SmallChange = 1;
_HScrollBar.LargeChange = 2;
//_HScrollBar.Dock = DockStyle.Fill;
_HScrollBar.Visible = true;
_Table.Controls.Add(_HScrollBar, 0, 1);
_VScrollBar = new VScrollBar();
_VScrollBar.Value = 0;
_VScrollBar.Width = VScrollWidth;
_VScrollBar.SmallChange = 1;
_VScrollBar.LargeChange = 2;
//_VScrollBar.Dock = DockStyle.Fill;
_VScrollBar.Visible = true;
_Table.Controls.Add(_VScrollBar, 1, 0);
_Table.Dock = DockStyle.Fill;
Controls.Add(_Table);
InitEvent();
}
#endregion
/// <summary>
/// 调整滚动条
/// </summary>
private void AdjustScrollbar()
{
var bottom = ItemHeight + RowSpacing * 2;
if (Rows != null && Rows.Any())
{
if (StartDate != Rows.StartDate || Rows.IsChanged)
{
ComputeRowsAndItemsSize();
Rows.IsChanged = false;
Rows.StartDate = StartDate;
}
var last = Rows.Last();
bottom = last.Bottom;
}
if (IsFixedRowHeight)
{
var h = ColumnHeight + (Rows?.Count ?? 0) * RowHeight + 200;
if(h > Height - HScrollHeight)
{
_VScrollBar.Maximum = h - Height + HScrollHeight + 1;
}
else
{
_VScrollBar.Maximum = 0;
}
}
else
{
_VScrollBar.Maximum = bottom - Height + HScrollHeight + 1 + 200;
}
_VScrollBar.Minimum = 0;
_HScrollBar.Maximum = ((int)(EndDate.Date - StartDate.Date).TotalDays + 1) * DateWidth - Width + RowHeaderWidth + VScrollWidth + 1 + 200;
_HScrollBar.Minimum = 0;
_VScrollBar.Enabled = _VScrollBar.Maximum > 0;
_HScrollBar.Enabled = _HScrollBar.Maximum > 0;
}
/// <summary>
/// 重绘
/// </summary>
public new void Invalidate()
{
base.Invalidate();
_ContentControl.Invalidate();
}
/// <summary>
/// 销毁
/// </summary>
/// <param name="disposing"></param>
protected override void Dispose(bool disposing)
{
this.Brushes?.Dispose();
base.Dispose(disposing);
}
class GanttChartCanvas : Control
{
public GanttChartCanvas()
{
SetStyle(ControlStyles.OptimizedDoubleBuffer, true);
SetStyle(ControlStyles.ResizeRedraw, true);
SetStyle(ControlStyles.Selectable, true);
}
protected override void OnPaintBackground(PaintEventArgs pevent) { }
}
}
}

11
GanttChart/GanttChartViewColumn.cs

@ -0,0 +1,11 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace GanttChart
{
public class GanttChartViewColumn
{
}
}

11
GanttChart/GanttChartViewColumnGroup.cs

@ -0,0 +1,11 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace GanttChart
{
public class GanttChartViewColumnGroup
{
}
}

42
GanttChart/GanttChartViewItem.cs

@ -0,0 +1,42 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace GanttChart
{
/// <summary>
/// 甘特图项
/// </summary>
public class GanttChartViewItem : TimeRange
{
/// <summary>
/// 项的时间范围集合
/// </summary>
public ICollection<TimeRange> Ranges { get; set; }
/// <summary>
/// 标题
/// </summary>
public string Title { get; set; }
/// <summary>
/// 提示内容
/// </summary>
public string Tooltip { get; set; }
/// <summary>
/// 顶部位置
/// </summary>
internal int Top { get; set; }
/// <summary>
/// 文本宽度
/// </summary>
internal int TextWidth { get; set; }
/// <summary>
/// 数据
/// </summary>
public object Data { get; set; }
/// <summary>
/// 是否警告
/// </summary>
public bool IsWarnning { get; set; }
}
}

30
GanttChart/GanttChartViewItemBlockType.cs

@ -0,0 +1,30 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace GanttChart
{
/// <summary>
/// 甘特图项的换行模式
/// </summary>
public enum GanttChartViewItemBlockType
{
/// <summary>
/// 紧凑
/// </summary>
Compact,
/// <summary>
/// 文字超过换行
/// </summary>
TextOverBlock,
/// <summary>
/// 强制换行
/// </summary>
Block,
/// <summary>
/// 回归
/// </summary>
Return
}
}

30
GanttChart/GanttChartViewRow.cs

@ -0,0 +1,30 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace GanttChart
{
/// <summary>
/// 甘特图行
/// </summary>
public class GanttChartViewRow
{
/// <summary>
/// 标题
/// </summary>
public string Title { get; set; }
/// <summary>
/// 顶部
/// </summary>
internal int Top { get; set; }
/// <summary>
/// 按钮
/// </summary>
internal int Bottom { get; set; }
/// <summary>
/// 项集合
/// </summary>
public List<GanttChartViewItem> Items { get; set; }
}
}

36
GanttChart/Properties/AssemblyInfo.cs

@ -0,0 +1,36 @@
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
// 有关程序集的一般信息由以下
// 控制。更改这些特性值可修改
// 与程序集关联的信息。
[assembly: AssemblyTitle("GanttChart")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("GanttChart")]
[assembly: AssemblyCopyright("Copyright © 2019")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// 将 ComVisible 设置为 false 会使此程序集中的类型
//对 COM 组件不可见。如果需要从 COM 访问此程序集中的类型
//请将此类型的 ComVisible 特性设置为 true。
[assembly: ComVisible(false)]
// 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID
[assembly: Guid("dea91cb9-1011-4ee7-b8e1-72428f731789")]
// 程序集的版本信息由下列四个值组成:
//
// 主版本
// 次版本
// 生成号
// 修订号
//
//可以指定所有这些值,也可以使用“生成号”和“修订号”的默认值
//通过使用 "*",如下所示:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]

63
GanttChart/Properties/Resources.Designer.cs

@ -0,0 +1,63 @@
//------------------------------------------------------------------------------
// <auto-generated>
// 此代码由工具生成。
// 运行时版本:4.0.30319.42000
//
// 对此文件的更改可能会导致不正确的行为,并且如果
// 重新生成代码,这些更改将会丢失。
// </auto-generated>
//------------------------------------------------------------------------------
namespace GanttChart.Properties {
using System;
/// <summary>
/// 一个强类型的资源类,用于查找本地化的字符串等。
/// </summary>
// 此类是由 StronglyTypedResourceBuilder
// 类通过类似于 ResGen 或 Visual Studio 的工具自动生成的。
// 若要添加或移除成员,请编辑 .ResX 文件,然后重新运行 ResGen
// (以 /str 作为命令选项),或重新生成 VS 项目。
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
internal class Resources {
private static global::System.Resources.ResourceManager resourceMan;
private static global::System.Globalization.CultureInfo resourceCulture;
[global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
internal Resources() {
}
/// <summary>
/// 返回此类使用的缓存的 ResourceManager 实例。
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Resources.ResourceManager ResourceManager {
get {
if (object.ReferenceEquals(resourceMan, null)) {
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("GanttChart.Properties.Resources", typeof(Resources).Assembly);
resourceMan = temp;
}
return resourceMan;
}
}
/// <summary>
/// 重写当前线程的 CurrentUICulture 属性,对
/// 使用此强类型资源类的所有资源查找执行重写。
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Globalization.CultureInfo Culture {
get {
return resourceCulture;
}
set {
resourceCulture = value;
}
}
}
}

117
GanttChart/Properties/Resources.resx

@ -0,0 +1,117 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
</root>

26
GanttChart/Properties/Settings.Designer.cs

@ -0,0 +1,26 @@
//------------------------------------------------------------------------------
// <auto-generated>
// 此代码由工具生成。
// 运行时版本:4.0.30319.42000
//
// 对此文件的更改可能会导致不正确的行为,并且如果
// 重新生成代码,这些更改将会丢失。
// </auto-generated>
//------------------------------------------------------------------------------
namespace GanttChart.Properties {
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "17.12.0.0")]
internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase {
private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
public static Settings Default {
get {
return defaultInstance;
}
}
}
}

7
GanttChart/Properties/Settings.settings

@ -0,0 +1,7 @@
<?xml version='1.0' encoding='utf-8'?>
<SettingsFile xmlns="http://schemas.microsoft.com/VisualStudio/2004/01/settings" CurrentProfile="(Default)">
<Profiles>
<Profile Name="(Default)" />
</Profiles>
<Settings />
</SettingsFile>

30
GanttChart/TimeRange.cs

@ -0,0 +1,30 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace GanttChart
{
/// <summary>
/// 时间范围
/// </summary>
public class TimeRange
{
/// <summary>
/// 开始时间
/// </summary>
public DateTime StartTime { get; set; }
/// <summary>
/// 结束时间
/// </summary>
public DateTime EndTime { get; set; }
/// <summary>
/// 左边
/// </summary>
internal int Left { get; set; }
/// <summary>
/// 宽度
/// </summary>
internal int Width { get; set; }
}
}

6
SunlightCentralizedControlManagement(SCCM).sln

@ -5,6 +5,8 @@ VisualStudioVersion = 17.11.35312.102
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SunlightCentralizedControlManagement_SCCM_", "SunlightCentralizedControlManagement_SCCM_.csproj", "{2CFE8A79-C7DC-47AC-8D0C-2E03010E2458}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GanttChart", "GanttChart\GanttChart.csproj", "{DEA91CB9-1011-4EE7-B8E1-72428F731789}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@ -15,6 +17,10 @@ Global
{2CFE8A79-C7DC-47AC-8D0C-2E03010E2458}.Debug|Any CPU.Build.0 = Debug|Any CPU
{2CFE8A79-C7DC-47AC-8D0C-2E03010E2458}.Release|Any CPU.ActiveCfg = Release|Any CPU
{2CFE8A79-C7DC-47AC-8D0C-2E03010E2458}.Release|Any CPU.Build.0 = Release|Any CPU
{DEA91CB9-1011-4EE7-B8E1-72428F731789}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{DEA91CB9-1011-4EE7-B8E1-72428F731789}.Debug|Any CPU.Build.0 = Debug|Any CPU
{DEA91CB9-1011-4EE7-B8E1-72428F731789}.Release|Any CPU.ActiveCfg = Release|Any CPU
{DEA91CB9-1011-4EE7-B8E1-72428F731789}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE

1
View/ProductionPlanningView.xaml

@ -22,6 +22,7 @@
</Grid.RowDefinitions>
<Grid Grid.Row="0">
<WebBrowser Name="webBrowser" />
<lvc:PieChart/>
</Grid>
<StackPanel x:Name="scr" Grid.Row="1" Height="60" Background="#FF00204E" Orientation="Horizontal">
<ListView ScrollViewer.HorizontalScrollBarVisibility="Disabled" Foreground="#FF1368BD">

4
View/ProductionPlanningView.xaml.cs

@ -30,6 +30,8 @@ using static SunlightCentralizedControlManagement_SCCM_.UserClass.SqliteHelper;
using static SunlightCentralizedControlManagement_SCCM_.WindowsView.ViewStep;
using static System.Windows.Forms.VisualStyles.VisualStyleElement;
using SunlightCentralizedControlManagement_SCCM_.ViewModel;
using LiveChartsCore.SkiaSharpView.WPF;
using System.Data.Entity.Core.Common.CommandTrees.ExpressionBuilder;
namespace SunlightCentralizedControlManagement_SCCM_.View
{
@ -64,8 +66,6 @@ namespace SunlightCentralizedControlManagement_SCCM_.View
webBrowser.NavigateToString(html);
}
private void ListViewItem_Quit(object sender, System.Windows.Input.MouseButtonEventArgs e)//退出事件

Loading…
Cancel
Save