Add project files.

This commit is contained in:
CreepyCrafter24 2019-12-01 19:33:28 +01:00
parent 5d00c879ee
commit 705d6be07f
17 changed files with 2248 additions and 0 deletions

25
GradeCalc.sln Normal file
View File

@ -0,0 +1,25 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 16
VisualStudioVersion = 16.0.29519.87
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GradeCalc", "GradeCalc\GradeCalc.csproj", "{D5948BBB-1F03-497A-A2BA-DD1E6F54A2A8}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{D5948BBB-1F03-497A-A2BA-DD1E6F54A2A8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{D5948BBB-1F03-497A-A2BA-DD1E6F54A2A8}.Debug|Any CPU.Build.0 = Debug|Any CPU
{D5948BBB-1F03-497A-A2BA-DD1E6F54A2A8}.Release|Any CPU.ActiveCfg = Release|Any CPU
{D5948BBB-1F03-497A-A2BA-DD1E6F54A2A8}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {C07FE5E3-2DEC-4911-9938-CC630D9B3B4E}
EndGlobalSection
EndGlobal

6
GradeCalc/App.config Normal file
View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6.1"/>
</startup>
</configuration>

View File

@ -0,0 +1,774 @@
using System;
using System.ComponentModel;
using System.Diagnostics;
using System.Drawing;
using System.Globalization;
using System.Windows.Forms;
namespace GradeCalc
{
public class DataGridViewNumericUpDownCell : DataGridViewTextBoxCell
{
// Used in KeyEntersEditMode function
[System.Runtime.InteropServices.DllImport("USER32.DLL", CharSet = System.Runtime.InteropServices.CharSet.Auto)]
private static extern short VkKeyScan(char key);
// Used in TranslateAlignment function
private static readonly DataGridViewContentAlignment anyRight = DataGridViewContentAlignment.TopRight |
DataGridViewContentAlignment.MiddleRight |
DataGridViewContentAlignment.BottomRight;
private static readonly DataGridViewContentAlignment anyCenter = DataGridViewContentAlignment.TopCenter |
DataGridViewContentAlignment.MiddleCenter |
DataGridViewContentAlignment.BottomCenter;
// Default dimensions of the static rendering bitmap used for the painting of the non-edited cells
private const int DATAGRIDVIEWNUMERICUPDOWNCELL_defaultRenderingBitmapWidth = 100;
private const int DATAGRIDVIEWNUMERICUPDOWNCELL_defaultRenderingBitmapHeight = 22;
// Default value of the DecimalPlaces property
internal const int DATAGRIDVIEWNUMERICUPDOWNCELL_defaultDecimalPlaces = 0;
// Default value of the Increment property
internal const decimal DATAGRIDVIEWNUMERICUPDOWNCELL_defaultIncrement = decimal.One;
// Default value of the Maximum property
internal const decimal DATAGRIDVIEWNUMERICUPDOWNCELL_defaultMaximum = (decimal)100.0;
// Default value of the Minimum property
internal const decimal DATAGRIDVIEWNUMERICUPDOWNCELL_defaultMinimum = decimal.Zero;
// Default value of the ThousandsSeparator property
internal const bool DATAGRIDVIEWNUMERICUPDOWNCELL_defaultThousandsSeparator = false;
// Type of this cell's editing control
private static Type defaultEditType = typeof(DataGridViewNumericUpDownEditingControl);
// Type of this cell's value. The formatted value type is string, the same as the base class DataGridViewTextBoxCell
private static Type defaultValueType = typeof(decimal);
// The bitmap used to paint the non-edited cells via a call to NumericUpDown.DrawToBitmap
[ThreadStatic]
private static Bitmap renderingBitmap;
// The NumericUpDown control used to paint the non-edited cells via a call to NumericUpDown.DrawToBitmap
[ThreadStatic]
private static NumericUpDown paintingNumericUpDown;
private int decimalPlaces; // Caches the value of the DecimalPlaces property
private decimal increment; // Caches the value of the Increment property
private decimal minimum; // Caches the value of the Minimum property
private decimal maximum; // Caches the value of the Maximum property
private bool thousandsSeparator; // Caches the value of the ThousandsSeparator property
/// <summary>
/// Constructor for the DataGridViewNumericUpDownCell cell type
/// </summary>
public DataGridViewNumericUpDownCell()
{
// Create a thread specific bitmap used for the painting of the non-edited cells
if (renderingBitmap == null)
{
renderingBitmap = new Bitmap(DATAGRIDVIEWNUMERICUPDOWNCELL_defaultRenderingBitmapWidth, DATAGRIDVIEWNUMERICUPDOWNCELL_defaultRenderingBitmapHeight);
}
// Create a thread specific NumericUpDown control used for the painting of the non-edited cells
if (paintingNumericUpDown == null)
{
paintingNumericUpDown = new NumericUpDown();
// Some properties only need to be set once for the lifetime of the control:
paintingNumericUpDown.BorderStyle = BorderStyle.None;
paintingNumericUpDown.Maximum = decimal.MaxValue / 10;
paintingNumericUpDown.Minimum = decimal.MinValue / 10;
}
// Set the default values of the properties:
decimalPlaces = DATAGRIDVIEWNUMERICUPDOWNCELL_defaultDecimalPlaces;
increment = DATAGRIDVIEWNUMERICUPDOWNCELL_defaultIncrement;
minimum = DATAGRIDVIEWNUMERICUPDOWNCELL_defaultMinimum;
maximum = DATAGRIDVIEWNUMERICUPDOWNCELL_defaultMaximum;
thousandsSeparator = DATAGRIDVIEWNUMERICUPDOWNCELL_defaultThousandsSeparator;
}
/// <summary>
/// The DecimalPlaces property replicates the one from the NumericUpDown control
/// </summary>
[
DefaultValue(DATAGRIDVIEWNUMERICUPDOWNCELL_defaultDecimalPlaces)
]
public int DecimalPlaces
{
get {
return decimalPlaces;
}
set {
if (value < 0 || value > 99)
{
throw new ArgumentOutOfRangeException("The DecimalPlaces property cannot be smaller than 0 or larger than 99.");
}
if (decimalPlaces != value)
{
SetDecimalPlaces(RowIndex, value);
OnCommonChange(); // Assure that the cell or column gets repainted and autosized if needed
}
}
}
/// <summary>
/// Returns the current DataGridView EditingControl as a DataGridViewNumericUpDownEditingControl control
/// </summary>
private DataGridViewNumericUpDownEditingControl EditingNumericUpDown
{
get {
return DataGridView.EditingControl as DataGridViewNumericUpDownEditingControl;
}
}
/// <summary>
/// Define the type of the cell's editing control
/// </summary>
public override Type EditType
{
get {
return defaultEditType; // the type is DataGridViewNumericUpDownEditingControl
}
}
/// <summary>
/// The Increment property replicates the one from the NumericUpDown control
/// </summary>
public decimal Increment
{
get {
return increment;
}
set {
if (value < (decimal)0.0)
{
throw new ArgumentOutOfRangeException("The Increment property cannot be smaller than 0.");
}
SetIncrement(RowIndex, value);
// No call to OnCommonChange is needed since the increment value does not affect the rendering of the cell.
}
}
/// <summary>
/// The Maximum property replicates the one from the NumericUpDown control
/// </summary>
public decimal Maximum
{
get {
return maximum;
}
set {
if (maximum != value)
{
SetMaximum(RowIndex, value);
OnCommonChange();
}
}
}
/// <summary>
/// The Minimum property replicates the one from the NumericUpDown control
/// </summary>
public decimal Minimum
{
get {
return minimum;
}
set {
if (minimum != value)
{
SetMinimum(RowIndex, value);
OnCommonChange();
}
}
}
/// <summary>
/// The ThousandsSeparator property replicates the one from the NumericUpDown control
/// </summary>
[
DefaultValue(DATAGRIDVIEWNUMERICUPDOWNCELL_defaultThousandsSeparator)
]
public bool ThousandsSeparator
{
get {
return thousandsSeparator;
}
set {
if (thousandsSeparator != value)
{
SetThousandsSeparator(RowIndex, value);
OnCommonChange();
}
}
}
/// <summary>
/// Returns the type of the cell's Value property
/// </summary>
public override Type ValueType
{
get {
Type valueType = base.ValueType;
if (valueType != null)
{
return valueType;
}
return defaultValueType;
}
}
/// <summary>
/// Clones a DataGridViewNumericUpDownCell cell, copies all the custom properties.
/// </summary>
public override object Clone()
{
DataGridViewNumericUpDownCell dataGridViewCell = base.Clone() as DataGridViewNumericUpDownCell;
if (dataGridViewCell != null)
{
dataGridViewCell.DecimalPlaces = DecimalPlaces;
dataGridViewCell.Increment = Increment;
dataGridViewCell.Maximum = Maximum;
dataGridViewCell.Minimum = Minimum;
dataGridViewCell.ThousandsSeparator = ThousandsSeparator;
}
return dataGridViewCell;
}
/// <summary>
/// Returns the provided value constrained to be within the min and max.
/// </summary>
private decimal Constrain(decimal value)
{
Debug.Assert(minimum <= maximum);
if (value < minimum)
{
value = minimum;
}
if (value > maximum)
{
value = maximum;
}
return value;
}
/// <summary>
/// DetachEditingControl gets called by the DataGridView control when the editing session is ending
/// </summary>
[
EditorBrowsable(EditorBrowsableState.Advanced)
]
public override void DetachEditingControl()
{
DataGridView dataGridView = DataGridView;
if (dataGridView == null || dataGridView.EditingControl == null)
{
throw new InvalidOperationException("Cell is detached or its grid has no editing control.");
}
NumericUpDown numericUpDown = dataGridView.EditingControl as NumericUpDown;
if (numericUpDown != null)
{
// Editing controls get recycled. Indeed, when a DataGridViewNumericUpDownCell cell gets edited
// after another DataGridViewNumericUpDownCell cell, the same editing control gets reused for
// performance reasons (to avoid an unnecessary control destruction and creation).
// Here the undo buffer of the TextBox inside the NumericUpDown control gets cleared to avoid
// interferences between the editing sessions.
TextBox textBox = numericUpDown.Controls[1] as TextBox;
if (textBox != null)
{
textBox.ClearUndo();
}
}
base.DetachEditingControl();
}
/// <summary>
/// Adjusts the location and size of the editing control given the alignment characteristics of the cell
/// </summary>
private Rectangle GetAdjustedEditingControlBounds(Rectangle editingControlBounds, DataGridViewCellStyle cellStyle)
{
// Add a 1 pixel padding on the left and right of the editing control
editingControlBounds.X += 1;
editingControlBounds.Width = Math.Max(0, editingControlBounds.Width - 2);
// Adjust the vertical location of the editing control:
int preferredHeight = cellStyle.Font.Height + 3;
if (preferredHeight < editingControlBounds.Height)
{
switch (cellStyle.Alignment)
{
case DataGridViewContentAlignment.MiddleLeft:
case DataGridViewContentAlignment.MiddleCenter:
case DataGridViewContentAlignment.MiddleRight:
editingControlBounds.Y += (editingControlBounds.Height - preferredHeight) / 2;
break;
case DataGridViewContentAlignment.BottomLeft:
case DataGridViewContentAlignment.BottomCenter:
case DataGridViewContentAlignment.BottomRight:
editingControlBounds.Y += editingControlBounds.Height - preferredHeight;
break;
}
}
return editingControlBounds;
}
/// <summary>
/// Customized implementation of the GetErrorIconBounds function in order to draw the potential
/// error icon next to the up/down buttons and not on top of them.
/// </summary>
protected override Rectangle GetErrorIconBounds(Graphics graphics, DataGridViewCellStyle cellStyle, int rowIndex)
{
const int ButtonsWidth = 16;
Rectangle errorIconBounds = base.GetErrorIconBounds(graphics, cellStyle, rowIndex);
if (DataGridView.RightToLeft == RightToLeft.Yes)
{
errorIconBounds.X = errorIconBounds.Left + ButtonsWidth;
}
else
{
errorIconBounds.X = errorIconBounds.Left - ButtonsWidth;
}
return errorIconBounds;
}
/// <summary>
/// Customized implementation of the GetFormattedValue function in order to include the decimal and thousand separator
/// characters in the formatted representation of the cell value.
/// </summary>
protected override object GetFormattedValue(object value,
int rowIndex,
ref DataGridViewCellStyle cellStyle,
TypeConverter valueTypeConverter,
TypeConverter formattedValueTypeConverter,
DataGridViewDataErrorContexts context)
{
// By default, the base implementation converts the Decimal 1234.5 into the string "1234.5"
object formattedValue = base.GetFormattedValue(value, rowIndex, ref cellStyle, valueTypeConverter, formattedValueTypeConverter, context);
string formattedNumber = formattedValue as string;
if (!string.IsNullOrEmpty(formattedNumber) && value != null)
{
decimal unformattedDecimal = Convert.ToDecimal(value);
decimal formattedDecimal = Convert.ToDecimal(formattedNumber);
if (unformattedDecimal == formattedDecimal)
{
// The base implementation of GetFormattedValue (which triggers the CellFormatting event) did nothing else than
// the typical 1234.5 to "1234.5" conversion. But depending on the values of ThousandsSeparator and DecimalPlaces,
// this may not be the actual string displayed. The real formatted value may be "1,234.500"
return formattedDecimal.ToString((ThousandsSeparator ? "N" : "F") + DecimalPlaces.ToString());
}
}
return formattedValue;
}
/// <summary>
/// Custom implementation of the GetPreferredSize function. This implementation uses the preferred size of the base
/// DataGridViewTextBoxCell cell and adds room for the up/down buttons.
/// </summary>
protected override Size GetPreferredSize(Graphics graphics, DataGridViewCellStyle cellStyle, int rowIndex, Size constraintSize)
{
if (DataGridView == null)
{
return new Size(-1, -1);
}
Size preferredSize = base.GetPreferredSize(graphics, cellStyle, rowIndex, constraintSize);
if (constraintSize.Width == 0)
{
const int ButtonsWidth = 16; // Account for the width of the up/down buttons.
const int ButtonMargin = 8; // Account for some blank pixels between the text and buttons.
preferredSize.Width += ButtonsWidth + ButtonMargin;
}
return preferredSize;
}
/// <summary>
/// Custom implementation of the InitializeEditingControl function. This function is called by the DataGridView control
/// at the beginning of an editing session. It makes sure that the properties of the NumericUpDown editing control are
/// set according to the cell properties.
/// </summary>
public override void InitializeEditingControl(int rowIndex, object initialFormattedValue, DataGridViewCellStyle dataGridViewCellStyle)
{
base.InitializeEditingControl(rowIndex, initialFormattedValue, dataGridViewCellStyle);
NumericUpDown numericUpDown = DataGridView.EditingControl as NumericUpDown;
if (numericUpDown != null)
{
numericUpDown.BorderStyle = BorderStyle.None;
numericUpDown.DecimalPlaces = DecimalPlaces;
numericUpDown.Increment = Increment;
numericUpDown.Maximum = Maximum;
numericUpDown.Minimum = Minimum;
numericUpDown.ThousandsSeparator = ThousandsSeparator;
string initialFormattedValueStr = initialFormattedValue as string;
if (initialFormattedValueStr == null)
{
numericUpDown.Text = string.Empty;
}
else
{
numericUpDown.Text = initialFormattedValueStr;
}
}
}
/// <summary>
/// Custom implementation of the KeyEntersEditMode function. This function is called by the DataGridView control
/// to decide whether a keystroke must start an editing session or not. In this case, a new session is started when
/// a digit or negative sign key is hit.
/// </summary>
public override bool KeyEntersEditMode(KeyEventArgs e)
{
NumberFormatInfo numberFormatInfo = CultureInfo.CurrentCulture.NumberFormat;
Keys negativeSignKey = Keys.None;
string negativeSignStr = numberFormatInfo.NegativeSign;
if (!string.IsNullOrEmpty(negativeSignStr) && negativeSignStr.Length == 1)
{
negativeSignKey = (Keys)VkKeyScan(negativeSignStr[0]);
}
if ((char.IsDigit((char)e.KeyCode) ||
e.KeyCode >= Keys.NumPad0 && e.KeyCode <= Keys.NumPad9 ||
negativeSignKey == e.KeyCode ||
Keys.Subtract == e.KeyCode) &&
!e.Shift && !e.Alt && !e.Control)
{
return true;
}
return false;
}
/// <summary>
/// Called when a cell characteristic that affects its rendering and/or preferred size has changed.
/// This implementation only takes care of repainting the cells. The DataGridView's autosizing methods
/// also need to be called in cases where some grid elements autosize.
/// </summary>
private void OnCommonChange()
{
if (DataGridView != null && !DataGridView.IsDisposed && !DataGridView.Disposing)
{
if (RowIndex == -1)
{
// Invalidate and autosize column
DataGridView.InvalidateColumn(ColumnIndex);
// TODO: Add code to autosize the cell's column, the rows, the column headers
// and the row headers depending on their autosize settings.
// The DataGridView control does not expose a public method that takes care of this.
}
else
{
// The DataGridView control exposes a public method called UpdateCellValue
// that invalidates the cell so that it gets repainted and also triggers all
// the necessary autosizing: the cell's column and/or row, the column headers
// and the row headers are autosized depending on their autosize settings.
DataGridView.UpdateCellValue(ColumnIndex, RowIndex);
}
}
}
/// <summary>
/// Determines whether this cell, at the given row index, shows the grid's editing control or not.
/// The row index needs to be provided as a parameter because this cell may be shared among multiple rows.
/// </summary>
private bool OwnsEditingNumericUpDown(int rowIndex)
{
if (rowIndex == -1 || DataGridView == null)
{
return false;
}
DataGridViewNumericUpDownEditingControl numericUpDownEditingControl = DataGridView.EditingControl as DataGridViewNumericUpDownEditingControl;
return numericUpDownEditingControl != null && rowIndex == ((IDataGridViewEditingControl)numericUpDownEditingControl).EditingControlRowIndex;
}
/// <summary>
/// Custom paints the cell. The base implementation of the DataGridViewTextBoxCell type is called first,
/// dropping the icon error and content foreground parts. Those two parts are painted by this custom implementation.
/// In this sample, the non-edited NumericUpDown control is painted by using a call to Control.DrawToBitmap. This is
/// an easy solution for painting controls but it's not necessarily the most performant. An alternative would be to paint
/// the NumericUpDown control piece by piece (text and up/down buttons).
/// </summary>
protected override void Paint(Graphics graphics, Rectangle clipBounds, Rectangle cellBounds, int rowIndex, DataGridViewElementStates cellState,
object value, object formattedValue, string errorText, DataGridViewCellStyle cellStyle,
DataGridViewAdvancedBorderStyle advancedBorderStyle, DataGridViewPaintParts paintParts)
{
if (DataGridView == null)
{
return;
}
// First paint the borders and background of the cell.
base.Paint(graphics, clipBounds, cellBounds, rowIndex, cellState, value, formattedValue, errorText, cellStyle, advancedBorderStyle,
paintParts & ~(DataGridViewPaintParts.ErrorIcon | DataGridViewPaintParts.ContentForeground));
Point ptCurrentCell = DataGridView.CurrentCellAddress;
bool cellCurrent = ptCurrentCell.X == ColumnIndex && ptCurrentCell.Y == rowIndex;
bool cellEdited = cellCurrent && DataGridView.EditingControl != null;
// If the cell is in editing mode, there is nothing else to paint
if (!cellEdited)
{
if (PartPainted(paintParts, DataGridViewPaintParts.ContentForeground))
{
// Paint a NumericUpDown control
// Take the borders into account
Rectangle borderWidths = BorderWidths(advancedBorderStyle);
Rectangle valBounds = cellBounds;
valBounds.Offset(borderWidths.X, borderWidths.Y);
valBounds.Width -= borderWidths.Right;
valBounds.Height -= borderWidths.Bottom;
// Also take the padding into account
if (cellStyle.Padding != Padding.Empty)
{
if (DataGridView.RightToLeft == RightToLeft.Yes)
{
valBounds.Offset(cellStyle.Padding.Right, cellStyle.Padding.Top);
}
else
{
valBounds.Offset(cellStyle.Padding.Left, cellStyle.Padding.Top);
}
valBounds.Width -= cellStyle.Padding.Horizontal;
valBounds.Height -= cellStyle.Padding.Vertical;
}
// Determine the NumericUpDown control location
valBounds = GetAdjustedEditingControlBounds(valBounds, cellStyle);
bool cellSelected = (cellState & DataGridViewElementStates.Selected) != 0;
if (renderingBitmap.Width < valBounds.Width ||
renderingBitmap.Height < valBounds.Height)
{
// The static bitmap is too small, a bigger one needs to be allocated.
renderingBitmap.Dispose();
renderingBitmap = new Bitmap(valBounds.Width, valBounds.Height);
}
// Make sure the NumericUpDown control is parented to a visible control
if (paintingNumericUpDown.Parent == null || !paintingNumericUpDown.Parent.Visible)
{
paintingNumericUpDown.Parent = DataGridView;
}
// Set all the relevant properties
paintingNumericUpDown.TextAlign = TranslateAlignment(cellStyle.Alignment);
paintingNumericUpDown.DecimalPlaces = DecimalPlaces;
paintingNumericUpDown.ThousandsSeparator = ThousandsSeparator;
paintingNumericUpDown.Font = cellStyle.Font;
paintingNumericUpDown.Width = valBounds.Width;
paintingNumericUpDown.Height = valBounds.Height;
paintingNumericUpDown.RightToLeft = DataGridView.RightToLeft;
paintingNumericUpDown.Location = new Point(0, -paintingNumericUpDown.Height - 100);
paintingNumericUpDown.Text = formattedValue as string;
Color backColor;
if (PartPainted(paintParts, DataGridViewPaintParts.SelectionBackground) && cellSelected)
{
backColor = cellStyle.SelectionBackColor;
}
else
{
backColor = cellStyle.BackColor;
}
if (PartPainted(paintParts, DataGridViewPaintParts.Background))
{
if (backColor.A < 255)
{
// The NumericUpDown control does not support transparent back colors
backColor = Color.FromArgb(255, backColor);
}
paintingNumericUpDown.BackColor = backColor;
}
// Finally paint the NumericUpDown control
Rectangle srcRect = new Rectangle(0, 0, valBounds.Width, valBounds.Height);
if (srcRect.Width > 0 && srcRect.Height > 0)
{
paintingNumericUpDown.DrawToBitmap(renderingBitmap, srcRect);
graphics.DrawImage(renderingBitmap, new Rectangle(valBounds.Location, valBounds.Size),
srcRect, GraphicsUnit.Pixel);
}
}
if (PartPainted(paintParts, DataGridViewPaintParts.ErrorIcon))
{
// Paint the potential error icon on top of the NumericUpDown control
base.Paint(graphics, clipBounds, cellBounds, rowIndex, cellState, value, formattedValue, errorText,
cellStyle, advancedBorderStyle, DataGridViewPaintParts.ErrorIcon);
}
}
}
/// <summary>
/// Little utility function called by the Paint function to see if a particular part needs to be painted.
/// </summary>
private static bool PartPainted(DataGridViewPaintParts paintParts, DataGridViewPaintParts paintPart)
{
return (paintParts & paintPart) != 0;
}
/// <summary>
/// Custom implementation of the PositionEditingControl method called by the DataGridView control when it
/// needs to relocate and/or resize the editing control.
/// </summary>
public override void PositionEditingControl(bool setLocation,
bool setSize,
Rectangle cellBounds,
Rectangle cellClip,
DataGridViewCellStyle cellStyle,
bool singleVerticalBorderAdded,
bool singleHorizontalBorderAdded,
bool isFirstDisplayedColumn,
bool isFirstDisplayedRow)
{
Rectangle editingControlBounds = PositionEditingPanel(cellBounds,
cellClip,
cellStyle,
singleVerticalBorderAdded,
singleHorizontalBorderAdded,
isFirstDisplayedColumn,
isFirstDisplayedRow);
editingControlBounds = GetAdjustedEditingControlBounds(editingControlBounds, cellStyle);
DataGridView.EditingControl.Location = new Point(editingControlBounds.X, editingControlBounds.Y);
DataGridView.EditingControl.Size = new Size(editingControlBounds.Width, editingControlBounds.Height);
}
/// <summary>
/// Utility function that sets a new value for the DecimalPlaces property of the cell. This function is used by
/// the cell and column DecimalPlaces property. The column uses this method instead of the DecimalPlaces
/// property for performance reasons. This way the column can invalidate the entire column at once instead of
/// invalidating each cell of the column individually. A row index needs to be provided as a parameter because
/// this cell may be shared among multiple rows.
/// </summary>
internal void SetDecimalPlaces(int rowIndex, int value)
{
Debug.Assert(value >= 0 && value <= 99);
decimalPlaces = value;
if (OwnsEditingNumericUpDown(rowIndex))
{
EditingNumericUpDown.DecimalPlaces = value;
}
}
/// Utility function that sets a new value for the Increment property of the cell. This function is used by
/// the cell and column Increment property. A row index needs to be provided as a parameter because
/// this cell may be shared among multiple rows.
internal void SetIncrement(int rowIndex, decimal value)
{
Debug.Assert(value >= (decimal)0.0);
increment = value;
if (OwnsEditingNumericUpDown(rowIndex))
{
EditingNumericUpDown.Increment = value;
}
}
/// Utility function that sets a new value for the Maximum property of the cell. This function is used by
/// the cell and column Maximum property. The column uses this method instead of the Maximum
/// property for performance reasons. This way the column can invalidate the entire column at once instead of
/// invalidating each cell of the column individually. A row index needs to be provided as a parameter because
/// this cell may be shared among multiple rows.
internal void SetMaximum(int rowIndex, decimal value)
{
maximum = value;
if (minimum > maximum)
{
minimum = maximum;
}
object cellValue = GetValue(rowIndex);
if (cellValue != null)
{
decimal currentValue = Convert.ToDecimal(cellValue);
decimal constrainedValue = Constrain(currentValue);
if (constrainedValue != currentValue)
{
SetValue(rowIndex, constrainedValue);
}
}
Debug.Assert(maximum == value);
if (OwnsEditingNumericUpDown(rowIndex))
{
EditingNumericUpDown.Maximum = value;
}
}
/// Utility function that sets a new value for the Minimum property of the cell. This function is used by
/// the cell and column Minimum property. The column uses this method instead of the Minimum
/// property for performance reasons. This way the column can invalidate the entire column at once instead of
/// invalidating each cell of the column individually. A row index needs to be provided as a parameter because
/// this cell may be shared among multiple rows.
internal void SetMinimum(int rowIndex, decimal value)
{
minimum = value;
if (minimum > maximum)
{
maximum = value;
}
object cellValue = GetValue(rowIndex);
if (cellValue != null)
{
decimal currentValue = Convert.ToDecimal(cellValue);
decimal constrainedValue = Constrain(currentValue);
if (constrainedValue != currentValue)
{
SetValue(rowIndex, constrainedValue);
}
}
Debug.Assert(minimum == value);
if (OwnsEditingNumericUpDown(rowIndex))
{
EditingNumericUpDown.Minimum = value;
}
}
/// Utility function that sets a new value for the ThousandsSeparator property of the cell. This function is used by
/// the cell and column ThousandsSeparator property. The column uses this method instead of the ThousandsSeparator
/// property for performance reasons. This way the column can invalidate the entire column at once instead of
/// invalidating each cell of the column individually. A row index needs to be provided as a parameter because
/// this cell may be shared among multiple rows.
internal void SetThousandsSeparator(int rowIndex, bool value)
{
thousandsSeparator = value;
if (OwnsEditingNumericUpDown(rowIndex))
{
EditingNumericUpDown.ThousandsSeparator = value;
}
}
/// <summary>
/// Returns a standard textual representation of the cell.
/// </summary>
public override string ToString()
{
return "DataGridViewNumericUpDownCell { ColumnIndex=" + ColumnIndex.ToString(CultureInfo.CurrentCulture) + ", RowIndex=" + RowIndex.ToString(CultureInfo.CurrentCulture) + " }";
}
/// <summary>
/// Little utility function used by both the cell and column types to translate a DataGridViewContentAlignment value into
/// a HorizontalAlignment value.
/// </summary>
internal static HorizontalAlignment TranslateAlignment(DataGridViewContentAlignment align)
{
if ((align & anyRight) != 0)
{
return HorizontalAlignment.Right;
}
else if ((align & anyCenter) != 0)
{
return HorizontalAlignment.Center;
}
else
{
return HorizontalAlignment.Left;
}
}
}
}

View File

@ -0,0 +1,304 @@
using System;
using System.ComponentModel;
using System.Globalization;
using System.Text;
using System.Windows.Forms;
namespace GradeCalc
{
/// <summary>
/// Custom column type dedicated to the DataGridViewNumericUpDownCell cell type.
/// </summary>
public class DataGridViewNumericUpDownColumn : DataGridViewColumn
{
/// <summary>
/// Constructor for the DataGridViewNumericUpDownColumn class.
/// </summary>
public DataGridViewNumericUpDownColumn() : base(new DataGridViewNumericUpDownCell())
{
}
/// <summary>
/// Represents the implicit cell that gets cloned when adding rows to the grid.
/// </summary>
[
Browsable(false),
DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)
]
public override DataGridViewCell CellTemplate
{
get {
return base.CellTemplate;
}
set {
DataGridViewNumericUpDownCell dataGridViewNumericUpDownCell = value as DataGridViewNumericUpDownCell;
if (value != null && dataGridViewNumericUpDownCell == null)
{
throw new InvalidCastException("Value provided for CellTemplate must be of type DataGridViewNumericUpDownElements.DataGridViewNumericUpDownCell or derive from it.");
}
base.CellTemplate = value;
}
}
/// <summary>
/// Replicates the DecimalPlaces property of the DataGridViewNumericUpDownCell cell type.
/// </summary>
[
Category("Appearance"),
DefaultValue(DataGridViewNumericUpDownCell.DATAGRIDVIEWNUMERICUPDOWNCELL_defaultDecimalPlaces),
Description("Indicates the number of decimal places to display.")
]
public int DecimalPlaces
{
get {
if (NumericUpDownCellTemplate == null)
{
throw new InvalidOperationException("Operation cannot be completed because this DataGridViewColumn does not have a CellTemplate.");
}
return NumericUpDownCellTemplate.DecimalPlaces;
}
set {
if (NumericUpDownCellTemplate == null)
{
throw new InvalidOperationException("Operation cannot be completed because this DataGridViewColumn does not have a CellTemplate.");
}
// Update the template cell so that subsequent cloned cells use the new value.
NumericUpDownCellTemplate.DecimalPlaces = value;
if (DataGridView != null)
{
// Update all the existing DataGridViewNumericUpDownCell cells in the column accordingly.
DataGridViewRowCollection dataGridViewRows = DataGridView.Rows;
int rowCount = dataGridViewRows.Count;
for (int rowIndex = 0; rowIndex < rowCount; rowIndex++)
{
// Be careful not to unshare rows unnecessarily.
// This could have severe performance repercussions.
DataGridViewRow dataGridViewRow = dataGridViewRows.SharedRow(rowIndex);
DataGridViewNumericUpDownCell dataGridViewCell = dataGridViewRow.Cells[Index] as DataGridViewNumericUpDownCell;
if (dataGridViewCell != null)
{
// Call the internal SetDecimalPlaces method instead of the property to avoid invalidation
// of each cell. The whole column is invalidated later in a single operation for better performance.
dataGridViewCell.SetDecimalPlaces(rowIndex, value);
}
}
DataGridView.InvalidateColumn(Index);
// TODO: Call the grid's autosizing methods to autosize the column, rows, column headers / row headers as needed.
}
}
}
/// <summary>
/// Replicates the Increment property of the DataGridViewNumericUpDownCell cell type.
/// </summary>
[
Category("Data"),
Description("Indicates the amount to increment or decrement on each button click.")
]
public decimal Increment
{
get {
if (NumericUpDownCellTemplate == null)
{
throw new InvalidOperationException("Operation cannot be completed because this DataGridViewColumn does not have a CellTemplate.");
}
return NumericUpDownCellTemplate.Increment;
}
set {
if (NumericUpDownCellTemplate == null)
{
throw new InvalidOperationException("Operation cannot be completed because this DataGridViewColumn does not have a CellTemplate.");
}
NumericUpDownCellTemplate.Increment = value;
if (DataGridView != null)
{
DataGridViewRowCollection dataGridViewRows = DataGridView.Rows;
int rowCount = dataGridViewRows.Count;
for (int rowIndex = 0; rowIndex < rowCount; rowIndex++)
{
DataGridViewRow dataGridViewRow = dataGridViewRows.SharedRow(rowIndex);
DataGridViewNumericUpDownCell dataGridViewCell = dataGridViewRow.Cells[Index] as DataGridViewNumericUpDownCell;
if (dataGridViewCell != null)
{
dataGridViewCell.SetIncrement(rowIndex, value);
}
}
}
}
}
/// Indicates whether the Increment property should be persisted.
private bool ShouldSerializeIncrement()
{
return !Increment.Equals(DataGridViewNumericUpDownCell.DATAGRIDVIEWNUMERICUPDOWNCELL_defaultIncrement);
}
/// <summary>
/// Replicates the Maximum property of the DataGridViewNumericUpDownCell cell type.
/// </summary>
[
Category("Data"),
Description("Indicates the maximum value for the numeric up-down cells."),
RefreshProperties(RefreshProperties.All)
]
public decimal Maximum
{
get {
if (NumericUpDownCellTemplate == null)
{
throw new InvalidOperationException("Operation cannot be completed because this DataGridViewColumn does not have a CellTemplate.");
}
return NumericUpDownCellTemplate.Maximum;
}
set {
if (NumericUpDownCellTemplate == null)
{
throw new InvalidOperationException("Operation cannot be completed because this DataGridViewColumn does not have a CellTemplate.");
}
NumericUpDownCellTemplate.Maximum = value;
if (DataGridView != null)
{
DataGridViewRowCollection dataGridViewRows = DataGridView.Rows;
int rowCount = dataGridViewRows.Count;
for (int rowIndex = 0; rowIndex < rowCount; rowIndex++)
{
DataGridViewRow dataGridViewRow = dataGridViewRows.SharedRow(rowIndex);
DataGridViewNumericUpDownCell dataGridViewCell = dataGridViewRow.Cells[Index] as DataGridViewNumericUpDownCell;
if (dataGridViewCell != null)
{
dataGridViewCell.SetMaximum(rowIndex, value);
}
}
DataGridView.InvalidateColumn(Index);
// TODO: This column and/or grid rows may need to be autosized depending on their
// autosize settings. Call the autosizing methods to autosize the column, rows,
// column headers / row headers as needed.
}
}
}
/// Indicates whether the Maximum property should be persisted.
private bool ShouldSerializeMaximum()
{
return !Maximum.Equals(DataGridViewNumericUpDownCell.DATAGRIDVIEWNUMERICUPDOWNCELL_defaultMaximum);
}
/// <summary>
/// Replicates the Minimum property of the DataGridViewNumericUpDownCell cell type.
/// </summary>
[
Category("Data"),
Description("Indicates the minimum value for the numeric up-down cells."),
RefreshProperties(RefreshProperties.All)
]
public decimal Minimum
{
get {
if (NumericUpDownCellTemplate == null)
{
throw new InvalidOperationException("Operation cannot be completed because this DataGridViewColumn does not have a CellTemplate.");
}
return NumericUpDownCellTemplate.Minimum;
}
set {
if (NumericUpDownCellTemplate == null)
{
throw new InvalidOperationException("Operation cannot be completed because this DataGridViewColumn does not have a CellTemplate.");
}
NumericUpDownCellTemplate.Minimum = value;
if (DataGridView != null)
{
DataGridViewRowCollection dataGridViewRows = DataGridView.Rows;
int rowCount = dataGridViewRows.Count;
for (int rowIndex = 0; rowIndex < rowCount; rowIndex++)
{
DataGridViewRow dataGridViewRow = dataGridViewRows.SharedRow(rowIndex);
DataGridViewNumericUpDownCell dataGridViewCell = dataGridViewRow.Cells[Index] as DataGridViewNumericUpDownCell;
if (dataGridViewCell != null)
{
dataGridViewCell.SetMinimum(rowIndex, value);
}
}
DataGridView.InvalidateColumn(Index);
// TODO: This column and/or grid rows may need to be autosized depending on their
// autosize settings. Call the autosizing methods to autosize the column, rows,
// column headers / row headers as needed.
}
}
}
/// Indicates whether the Maximum property should be persisted.
private bool ShouldSerializeMinimum()
{
return !Minimum.Equals(DataGridViewNumericUpDownCell.DATAGRIDVIEWNUMERICUPDOWNCELL_defaultMinimum);
}
/// <summary>
/// Replicates the ThousandsSeparator property of the DataGridViewNumericUpDownCell cell type.
/// </summary>
[
Category("Data"),
DefaultValue(DataGridViewNumericUpDownCell.DATAGRIDVIEWNUMERICUPDOWNCELL_defaultThousandsSeparator),
Description("Indicates whether the thousands separator will be inserted between every three decimal digits.")
]
public bool ThousandsSeparator
{
get {
if (NumericUpDownCellTemplate == null)
{
throw new InvalidOperationException("Operation cannot be completed because this DataGridViewColumn does not have a CellTemplate.");
}
return NumericUpDownCellTemplate.ThousandsSeparator;
}
set {
if (NumericUpDownCellTemplate == null)
{
throw new InvalidOperationException("Operation cannot be completed because this DataGridViewColumn does not have a CellTemplate.");
}
NumericUpDownCellTemplate.ThousandsSeparator = value;
if (DataGridView != null)
{
DataGridViewRowCollection dataGridViewRows = DataGridView.Rows;
int rowCount = dataGridViewRows.Count;
for (int rowIndex = 0; rowIndex < rowCount; rowIndex++)
{
DataGridViewRow dataGridViewRow = dataGridViewRows.SharedRow(rowIndex);
DataGridViewNumericUpDownCell dataGridViewCell = dataGridViewRow.Cells[Index] as DataGridViewNumericUpDownCell;
if (dataGridViewCell != null)
{
dataGridViewCell.SetThousandsSeparator(rowIndex, value);
}
}
DataGridView.InvalidateColumn(Index);
// TODO: This column and/or grid rows may need to be autosized depending on their
// autosize settings. Call the autosizing methods to autosize the column, rows,
// column headers / row headers as needed.
}
}
}
/// <summary>
/// Small utility function that returns the template cell as a DataGridViewNumericUpDownCell
/// </summary>
private DataGridViewNumericUpDownCell NumericUpDownCellTemplate
{
get {
return (DataGridViewNumericUpDownCell)CellTemplate;
}
}
/// <summary>
/// Returns a standard compact string representation of the column.
/// </summary>
public override string ToString()
{
StringBuilder sb = new StringBuilder(100);
sb.Append("DataGridViewNumericUpDownColumn { Name=");
sb.Append(Name);
sb.Append(", Index=");
sb.Append(Index.ToString(CultureInfo.CurrentCulture));
sb.Append(" }");
return sb.ToString();
}
}
}

View File

@ -0,0 +1,352 @@
using System;
using System.Drawing;
using System.Windows.Forms;
namespace GradeCalc
{
/// <summary>
/// Defines the editing control for the DataGridViewNumericUpDownCell custom cell type.
/// </summary>
internal class DataGridViewNumericUpDownEditingControl : NumericUpDown, IDataGridViewEditingControl
{
// Needed to forward keyboard messages to the child TextBox control.
[System.Runtime.InteropServices.DllImport("USER32.DLL", CharSet = System.Runtime.InteropServices.CharSet.Auto)]
private static extern IntPtr SendMessage(IntPtr hWnd, int msg, IntPtr wParam, IntPtr lParam);
// The grid that owns this editing control
private DataGridView dataGridView;
// Stores whether the editing control's value has changed or not
private bool valueChanged;
// Stores the row index in which the editing control resides
private int rowIndex;
/// <summary>
/// Constructor of the editing control class
/// </summary>
public DataGridViewNumericUpDownEditingControl()
{
// The editing control must not be part of the tabbing loop
TabStop = false;
}
// Beginning of the IDataGridViewEditingControl interface implementation
/// <summary>
/// Property which caches the grid that uses this editing control
/// </summary>
public virtual DataGridView EditingControlDataGridView
{
get {
return dataGridView;
}
set {
dataGridView = value;
}
}
/// <summary>
/// Property which represents the current formatted value of the editing control
/// </summary>
public virtual object EditingControlFormattedValue
{
get {
return GetEditingControlFormattedValue(DataGridViewDataErrorContexts.Formatting);
}
set {
Text = (string)value;
}
}
/// <summary>
/// Property which represents the row in which the editing control resides
/// </summary>
public virtual int EditingControlRowIndex
{
get {
return rowIndex;
}
set {
rowIndex = value;
}
}
/// <summary>
/// Property which indicates whether the value of the editing control has changed or not
/// </summary>
public virtual bool EditingControlValueChanged
{
get {
return valueChanged;
}
set {
valueChanged = value;
}
}
/// <summary>
/// Property which determines which cursor must be used for the editing panel,
/// i.e. the parent of the editing control.
/// </summary>
public virtual Cursor EditingPanelCursor
{
get {
return Cursors.Default;
}
}
/// <summary>
/// Property which indicates whether the editing control needs to be repositioned
/// when its value changes.
/// </summary>
public virtual bool RepositionEditingControlOnValueChange
{
get {
return false;
}
}
/// <summary>
/// Method called by the grid before the editing control is shown so it can adapt to the
/// provided cell style.
/// </summary>
public virtual void ApplyCellStyleToEditingControl(DataGridViewCellStyle dataGridViewCellStyle)
{
Font = dataGridViewCellStyle.Font;
if (dataGridViewCellStyle.BackColor.A < 255)
{
// The NumericUpDown control does not support transparent back colors
Color opaqueBackColor = Color.FromArgb(255, dataGridViewCellStyle.BackColor);
BackColor = opaqueBackColor;
dataGridView.EditingPanel.BackColor = opaqueBackColor;
}
else
{
BackColor = dataGridViewCellStyle.BackColor;
}
ForeColor = dataGridViewCellStyle.ForeColor;
TextAlign = DataGridViewNumericUpDownCell.TranslateAlignment(dataGridViewCellStyle.Alignment);
}
/// <summary>
/// Method called by the grid on keystrokes to determine if the editing control is
/// interested in the key or not.
/// </summary>
public virtual bool EditingControlWantsInputKey(Keys keyData, bool dataGridViewWantsInputKey)
{
switch (keyData & Keys.KeyCode)
{
case Keys.Right:
{
TextBox textBox = Controls[1] as TextBox;
if (textBox != null)
{
// If the end of the selection is at the end of the string,
// let the DataGridView treat the key message
if (RightToLeft == RightToLeft.No && !(textBox.SelectionLength == 0 && textBox.SelectionStart == textBox.Text.Length) ||
RightToLeft == RightToLeft.Yes && !(textBox.SelectionLength == 0 && textBox.SelectionStart == 0))
{
return true;
}
}
break;
}
case Keys.Left:
{
TextBox textBox = Controls[1] as TextBox;
if (textBox != null)
{
// If the end of the selection is at the begining of the string
// or if the entire text is selected and we did not start editing,
// send this character to the dataGridView, else process the key message
if (RightToLeft == RightToLeft.No && !(textBox.SelectionLength == 0 && textBox.SelectionStart == 0) ||
RightToLeft == RightToLeft.Yes && !(textBox.SelectionLength == 0 && textBox.SelectionStart == textBox.Text.Length))
{
return true;
}
}
break;
}
case Keys.Down:
// If the current value hasn't reached its minimum yet, handle the key. Otherwise let
// the grid handle it.
if (Value > Minimum)
{
return true;
}
break;
case Keys.Up:
// If the current value hasn't reached its maximum yet, handle the key. Otherwise let
// the grid handle it.
if (Value < Maximum)
{
return true;
}
break;
case Keys.Home:
case Keys.End:
{
// Let the grid handle the key if the entire text is selected.
TextBox textBox = Controls[1] as TextBox;
if (textBox != null)
{
if (textBox.SelectionLength != textBox.Text.Length)
{
return true;
}
}
break;
}
case Keys.Delete:
{
// Let the grid handle the key if the carret is at the end of the text.
TextBox textBox = Controls[1] as TextBox;
if (textBox != null)
{
if (textBox.SelectionLength > 0 ||
textBox.SelectionStart < textBox.Text.Length)
{
return true;
}
}
break;
}
}
return !dataGridViewWantsInputKey;
}
/// <summary>
/// Returns the current value of the editing control.
/// </summary>
public virtual object GetEditingControlFormattedValue(DataGridViewDataErrorContexts context)
{
bool userEdit = UserEdit;
try
{
// Prevent the Value from being set to Maximum or Minimum when the cell is being painted.
UserEdit = (context & DataGridViewDataErrorContexts.Display) == 0;
return Value.ToString((ThousandsSeparator ? "N" : "F") + DecimalPlaces.ToString());
}
finally
{
UserEdit = userEdit;
}
}
/// <summary>
/// Called by the grid to give the editing control a chance to prepare itself for
/// the editing session.
/// </summary>
public virtual void PrepareEditingControlForEdit(bool selectAll)
{
TextBox textBox = Controls[1] as TextBox;
if (textBox != null)
{
if (selectAll)
{
textBox.SelectAll();
}
else
{
// Do not select all the text, but
// position the caret at the end of the text
textBox.SelectionStart = textBox.Text.Length;
}
}
}
// End of the IDataGridViewEditingControl interface implementation
/// <summary>
/// Small utility function that updates the local dirty state and
/// notifies the grid of the value change.
/// </summary>
private void NotifyDataGridViewOfValueChange()
{
if (!valueChanged)
{
valueChanged = true;
dataGridView.NotifyCurrentCellDirty(true);
}
}
/// <summary>
/// Listen to the KeyPress notification to know when the value changed, and
/// notify the grid of the change.
/// </summary>
protected override void OnKeyPress(KeyPressEventArgs e)
{
base.OnKeyPress(e);
// The value changes when a digit, the decimal separator, the group separator or
// the negative sign is pressed.
bool notifyValueChange = false;
if (char.IsDigit(e.KeyChar))
{
notifyValueChange = true;
}
else
{
System.Globalization.NumberFormatInfo numberFormatInfo = System.Globalization.CultureInfo.CurrentCulture.NumberFormat;
string decimalSeparatorStr = numberFormatInfo.NumberDecimalSeparator;
string groupSeparatorStr = numberFormatInfo.NumberGroupSeparator;
string negativeSignStr = numberFormatInfo.NegativeSign;
if (!string.IsNullOrEmpty(decimalSeparatorStr) && decimalSeparatorStr.Length == 1)
{
notifyValueChange = decimalSeparatorStr[0] == e.KeyChar;
}
if (!notifyValueChange && !string.IsNullOrEmpty(groupSeparatorStr) && groupSeparatorStr.Length == 1)
{
notifyValueChange = groupSeparatorStr[0] == e.KeyChar;
}
if (!notifyValueChange && !string.IsNullOrEmpty(negativeSignStr) && negativeSignStr.Length == 1)
{
notifyValueChange = negativeSignStr[0] == e.KeyChar;
}
}
if (notifyValueChange)
{
// Let the DataGridView know about the value change
NotifyDataGridViewOfValueChange();
}
}
/// <summary>
/// Listen to the ValueChanged notification to forward the change to the grid.
/// </summary>
protected override void OnValueChanged(EventArgs e)
{
base.OnValueChanged(e);
if (Focused)
{
// Let the DataGridView know about the value change
NotifyDataGridViewOfValueChange();
}
}
/// <summary>
/// A few keyboard messages need to be forwarded to the inner textbox of the
/// NumericUpDown control so that the first character pressed appears in it.
/// </summary>
protected override bool ProcessKeyEventArgs(ref Message m)
{
TextBox textBox = Controls[1] as TextBox;
if (textBox != null)
{
SendMessage(textBox.Handle, m.Msg, m.WParam, m.LParam);
return true;
}
else
{
return base.ProcessKeyEventArgs(ref m);
}
}
}
}

109
GradeCalc/GradeCalc.csproj Normal file
View File

@ -0,0 +1,109 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="..\packages\Antlr4.CodeGenerator.4.6.4\build\Antlr4.CodeGenerator.props" Condition="Exists('..\packages\Antlr4.CodeGenerator.4.6.4\build\Antlr4.CodeGenerator.props')" />
<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>{D5948BBB-1F03-497A-A2BA-DD1E6F54A2A8}</ProjectGuid>
<OutputType>WinExe</OutputType>
<RootNamespace>GradeCalc</RootNamespace>
<AssemblyName>GradeCalc</AssemblyName>
<TargetFrameworkVersion>v4.6.1</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
<Deterministic>true</Deterministic>
<NuGetPackageImportStamp>
</NuGetPackageImportStamp>
<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>
</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>
</PropertyGroup>
<ItemGroup>
<Reference Include="Antlr4.Runtime, Version=4.6.0.0, Culture=neutral, PublicKeyToken=09abb75b9ed49849, processorArchitecture=MSIL">
<HintPath>..\packages\Antlr4.Runtime.4.6.4\lib\net45\Antlr4.Runtime.dll</HintPath>
</Reference>
<Reference Include="NCalc2, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\NCalc2.2.1.0\lib\net46\NCalc2.dll</HintPath>
</Reference>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Data" />
<Reference Include="System.Deployment" />
<Reference Include="System.Drawing" />
<Reference Include="System.Net.Http" />
<Reference Include="System.Windows.Forms" />
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="DataGridViewNumericUpDownCell.cs" />
<Compile Include="DataGridViewNumericUpDownColumn.cs" />
<Compile Include="DataGridViewNumericUpDownEditingControl.cs">
<SubType>Component</SubType>
</Compile>
<Compile Include="MainForm.cs">
<SubType>Form</SubType>
</Compile>
<Compile Include="MainForm.Designer.cs">
<DependentUpon>MainForm.cs</DependentUpon>
</Compile>
<Compile Include="NCalcDoubleParser.cs" />
<Compile Include="Program.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<EmbeddedResource Include="MainForm.resx">
<DependentUpon>MainForm.cs</DependentUpon>
</EmbeddedResource>
<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="packages.config" />
<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>
<None Include="App.config" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
<PropertyGroup>
<ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
</PropertyGroup>
<Error Condition="!Exists('..\packages\Antlr4.CodeGenerator.4.6.4\build\Antlr4.CodeGenerator.props')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Antlr4.CodeGenerator.4.6.4\build\Antlr4.CodeGenerator.props'))" />
<Error Condition="!Exists('..\packages\Antlr4.CodeGenerator.4.6.4\build\Antlr4.CodeGenerator.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Antlr4.CodeGenerator.4.6.4\build\Antlr4.CodeGenerator.targets'))" />
</Target>
<Import Project="..\packages\Antlr4.CodeGenerator.4.6.4\build\Antlr4.CodeGenerator.targets" Condition="Exists('..\packages\Antlr4.CodeGenerator.4.6.4\build\Antlr4.CodeGenerator.targets')" />
</Project>

162
GradeCalc/MainForm.Designer.cs generated Normal file
View File

@ -0,0 +1,162 @@
namespace GradeCalc
{
partial class MainForm
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.dataGridView = new System.Windows.Forms.DataGridView();
this.calcButton = new System.Windows.Forms.Button();
this.configPanel = new System.Windows.Forms.Panel();
this.algorithmBox = new System.Windows.Forms.ComboBox();
this.tasksNum = new System.Windows.Forms.NumericUpDown();
this.tasksLabel = new System.Windows.Forms.Label();
this.algorithmLabel = new System.Windows.Forms.Label();
((System.ComponentModel.ISupportInitialize)(this.dataGridView)).BeginInit();
this.configPanel.SuspendLayout();
((System.ComponentModel.ISupportInitialize)(this.tasksNum)).BeginInit();
this.SuspendLayout();
//
// dataGridView
//
this.dataGridView.ColumnHeadersHeightSizeMode = System.Windows.Forms.DataGridViewColumnHeadersHeightSizeMode.AutoSize;
this.dataGridView.Dock = System.Windows.Forms.DockStyle.Fill;
this.dataGridView.Location = new System.Drawing.Point(0, 0);
this.dataGridView.Name = "dataGridView";
this.dataGridView.Size = new System.Drawing.Size(891, 352);
this.dataGridView.TabIndex = 0;
//
// calcButton
//
this.calcButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
this.calcButton.Location = new System.Drawing.Point(12, 6);
this.calcButton.Name = "calcButton";
this.calcButton.Size = new System.Drawing.Size(100, 23);
this.calcButton.TabIndex = 1;
this.calcButton.Text = "Calculate Grades";
this.calcButton.UseVisualStyleBackColor = true;
this.calcButton.Click += new System.EventHandler(this.calcButton_Click);
//
// configPanel
//
this.configPanel.Controls.Add(this.algorithmLabel);
this.configPanel.Controls.Add(this.tasksLabel);
this.configPanel.Controls.Add(this.algorithmBox);
this.configPanel.Controls.Add(this.tasksNum);
this.configPanel.Controls.Add(this.calcButton);
this.configPanel.Dock = System.Windows.Forms.DockStyle.Bottom;
this.configPanel.Location = new System.Drawing.Point(0, 352);
this.configPanel.Name = "configPanel";
this.configPanel.Size = new System.Drawing.Size(891, 37);
this.configPanel.TabIndex = 2;
//
// algorithmBox
//
this.algorithmBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.algorithmBox.FormattingEnabled = true;
this.algorithmBox.Items.AddRange(new object[] {
"totalScore / maxScore"});
this.algorithmBox.Location = new System.Drawing.Point(357, 8);
this.algorithmBox.Name = "algorithmBox";
this.algorithmBox.Size = new System.Drawing.Size(180, 21);
this.algorithmBox.TabIndex = 3;
this.algorithmBox.Text = "totalScore / maxScore";
//
// tasksNum
//
this.tasksNum.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
this.tasksNum.Location = new System.Drawing.Point(163, 9);
this.tasksNum.Maximum = new decimal(new int[] {
50,
0,
0,
0});
this.tasksNum.Minimum = new decimal(new int[] {
1,
0,
0,
0});
this.tasksNum.Name = "tasksNum";
this.tasksNum.Size = new System.Drawing.Size(120, 20);
this.tasksNum.TabIndex = 2;
this.tasksNum.Value = new decimal(new int[] {
1,
0,
0,
0});
this.tasksNum.ValueChanged += new System.EventHandler(this.tasksNum_ValueChanged);
//
// tasksLabel
//
this.tasksLabel.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
this.tasksLabel.AutoSize = true;
this.tasksLabel.Location = new System.Drawing.Point(118, 11);
this.tasksLabel.Name = "tasksLabel";
this.tasksLabel.Size = new System.Drawing.Size(39, 13);
this.tasksLabel.TabIndex = 4;
this.tasksLabel.Text = "Tasks:";
//
// algorithmLabel
//
this.algorithmLabel.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
this.algorithmLabel.AutoSize = true;
this.algorithmLabel.Location = new System.Drawing.Point(298, 11);
this.algorithmLabel.Name = "algorithmLabel";
this.algorithmLabel.Size = new System.Drawing.Size(53, 13);
this.algorithmLabel.TabIndex = 5;
this.algorithmLabel.Text = "Algorithm:";
//
// MainForm
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(891, 389);
this.Controls.Add(this.dataGridView);
this.Controls.Add(this.configPanel);
this.MinimumSize = new System.Drawing.Size(504, 156);
this.Name = "MainForm";
this.Text = "GradeCalc";
((System.ComponentModel.ISupportInitialize)(this.dataGridView)).EndInit();
this.configPanel.ResumeLayout(false);
this.configPanel.PerformLayout();
((System.ComponentModel.ISupportInitialize)(this.tasksNum)).EndInit();
this.ResumeLayout(false);
}
#endregion
private System.Windows.Forms.DataGridView dataGridView;
private System.Windows.Forms.Button calcButton;
private System.Windows.Forms.Panel configPanel;
private System.Windows.Forms.NumericUpDown tasksNum;
private System.Windows.Forms.ComboBox algorithmBox;
private System.Windows.Forms.Label tasksLabel;
private System.Windows.Forms.Label algorithmLabel;
}
}

83
GradeCalc/MainForm.cs Normal file
View File

@ -0,0 +1,83 @@
using NCalc2;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Windows.Forms;
namespace GradeCalc
{
public partial class MainForm : Form
{
private List<DataGridViewNumericUpDownColumn> taskColumns = new List<DataGridViewNumericUpDownColumn>();
private DataGridViewTextBoxColumn nameColumn;
private DataGridViewTextBoxColumn gradeColumn;
public MainForm()
{
InitializeComponent();
nameColumn = new DataGridViewTextBoxColumn();
nameColumn.HeaderText = "Name";
nameColumn.Name = "Name";
dataGridView.Columns.Add(nameColumn);
gradeColumn = new DataGridViewTextBoxColumn();
gradeColumn.HeaderText = "Grade";
gradeColumn.Name = "Grade";
gradeColumn.ReadOnly = true;
dataGridView.Columns.Add(gradeColumn);
tasksNum_ValueChanged(null, null);
}
private void calcButton_Click(object sender, EventArgs e)
{
foreach (DataGridViewRow row in dataGridView.Rows)
{
decimal maxScore = 0;
decimal totalScore = 0;
taskColumns.ForEach(s =>
{
DataGridViewNumericUpDownCell cell = (DataGridViewNumericUpDownCell)row.Cells[s.Name];
if (!string.IsNullOrWhiteSpace((string)cell.FormattedValue))
{
maxScore += cell.Maximum;
totalScore += decimal.Parse((string)cell.FormattedValue);
}
});
Expression ex = new Expression(algorithmBox.Text);
ex.Parameters["score"] = (double)totalScore;
ex.Parameters["maxScore"] = (double)maxScore;
//double gradeVal = (double)totalScore / (double)maxScore;
double grade = 6 - (NCalcDoubleParser.Parse(ex.Evaluate()) * 5);
((DataGridViewTextBoxCell)row.Cells[gradeColumn.Name]).Value = (grade.ToString().Length > 13 ? grade.ToString().Remove(13) : grade.ToString()) + " " + texGrade(grade);
}
dataGridView.Sort(nameColumn, ListSortDirection.Ascending);
}
private void tasksNum_ValueChanged(object sender, EventArgs e)
{
while (tasksNum.Value < taskColumns.Count)
{
DataGridViewNumericUpDownColumn col = taskColumns[taskColumns.Count - 1];
dataGridView.Columns.Remove(col);
taskColumns.Remove(col);
col.Dispose();
}
while (tasksNum.Value > taskColumns.Count)
{
DataGridViewNumericUpDownColumn clm = new DataGridViewNumericUpDownColumn();
clm.Minimum = 0;
clm.Maximum = 10;
clm.Name = "Task " + (taskColumns.Count + 1).ToString();
dataGridView.Columns.Add(clm);
taskColumns.Add(clm);
}
gradeColumn.DisplayIndex = dataGridView.Columns.Count - 1;
}
private string texGrade(double g)
{
double gGrade = (new double[] { -0.5, 0, 0.5 }).OrderBy(x => Math.Abs(x - (g - (int)Math.Round(g)))).First();
return ((char)('A' + (int)Math.Round(g) - 1)).ToString() + ((g == 1 || gGrade == -0.5) ? "+" : (g == 6 || gGrade == 0.5) ? "-" : "");
}
}
}

120
GradeCalc/MainForm.resx Normal file
View File

@ -0,0 +1,120 @@
<?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.Runtime.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:import namespace="http://www.w3.org/XML/1998/namespace" />
<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" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</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" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</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=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
</root>

View File

@ -0,0 +1,40 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace GradeCalc
{
static class NCalcDoubleParser
{
public static double Parse(object NCalcOutput)
{
if (NCalcOutput.GetType() == typeof(bool))
return (bool)NCalcOutput ? 1 : 0;
else if (NCalcOutput.GetType() == typeof(byte))
return (byte)NCalcOutput;
else if (NCalcOutput.GetType() == typeof(sbyte))
return (sbyte)NCalcOutput;
else if (NCalcOutput.GetType() == typeof(short))
return (short)NCalcOutput;
else if (NCalcOutput.GetType() == typeof(ushort))
return (ushort)NCalcOutput;
else if (NCalcOutput.GetType() == typeof(int))
return (int)NCalcOutput;
else if (NCalcOutput.GetType() == typeof(uint))
return (uint)NCalcOutput;
else if (NCalcOutput.GetType() == typeof(long))
return (long)NCalcOutput;
else if (NCalcOutput.GetType() == typeof(ulong))
return (ulong)NCalcOutput;
else if (NCalcOutput.GetType() == typeof(float))
return (float)NCalcOutput;
else if (NCalcOutput.GetType() == typeof(double))
return (double)NCalcOutput;
else if (NCalcOutput.GetType() == typeof(decimal))
return (double)(decimal)NCalcOutput;
throw new ArgumentException("Type mismatch! (" + NCalcOutput.GetType().ToString() + ")");
}
}
}

16
GradeCalc/Program.cs Normal file
View File

@ -0,0 +1,16 @@
using System;
using System.Windows.Forms;
namespace GradeCalc
{
internal static class Program
{
[STAThread]
private static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new MainForm());
}
}
}

View File

@ -0,0 +1,35 @@
using System.Reflection;
using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("GradeCalc")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("GradeCalc")]
[assembly: AssemblyCopyright("Copyright © 2019")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]
// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("d5948bbb-1f03-497a-a2ba-dd1e6f54a2a8")]
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]

View File

@ -0,0 +1,63 @@
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
// Runtime Version:4.0.30319.42000
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
namespace GradeCalc.Properties {
using System;
/// <summary>
/// A strongly-typed resource class, for looking up localized strings, etc.
/// </summary>
// This class was auto-generated by the StronglyTypedResourceBuilder
// class via a tool like ResGen or Visual Studio.
// To add or remove a member, edit your .ResX file then rerun ResGen
// with the /str option, or rebuild your VS project.
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "16.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>
/// Returns the cached ResourceManager instance used by this class.
/// </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("GradeCalc.Properties.Resources", typeof(Resources).Assembly);
resourceMan = temp;
}
return resourceMan;
}
}
/// <summary>
/// Overrides the current thread's CurrentUICulture property for all
/// resource lookups using this strongly typed resource class.
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Globalization.CultureInfo Culture {
get {
return resourceCulture;
}
set {
resourceCulture = value;
}
}
}
}

View File

@ -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>

View File

@ -0,0 +1,26 @@
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
// Runtime Version:4.0.30319.42000
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
namespace GradeCalc.Properties {
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "16.3.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;
}
}
}
}

View File

@ -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>

View File

@ -0,0 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="Antlr4" version="4.6.4" targetFramework="net48" developmentDependency="true" />
<package id="Antlr4.CodeGenerator" version="4.6.4" targetFramework="net48" developmentDependency="true" />
<package id="Antlr4.Runtime" version="4.6.4" targetFramework="net48" />
<package id="Microsoft.CSharp" version="4.4.1" targetFramework="net48" />
<package id="NCalc2" version="2.1.0" targetFramework="net48" />
<package id="System.Dynamic.Runtime" version="4.3.0" targetFramework="net48" />
</packages>