Add project files.
This commit is contained in:
parent
5d00c879ee
commit
705d6be07f
|
@ -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
|
|
@ -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>
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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>
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
@ -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) ? "-" : "");
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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>
|
|
@ -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() + ")");
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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());
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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")]
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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>
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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>
|
|
@ -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>
|
Reference in New Issue