Code:
/ FX-1434 / FX-1434 / 1.0 / untmp / whidbey / REDBITS / ndp / fx / src / WinForms / Managed / System / WinForms / NumericUpDown.cs / 1 / NumericUpDown.cs
//------------------------------------------------------------------------------ //// Copyright (c) Microsoft Corporation. All rights reserved. // //----------------------------------------------------------------------------- namespace System.Windows.Forms { using Microsoft.Win32; using System; using System.ComponentModel; using System.ComponentModel.Design; using System.Diagnostics; using System.Diagnostics.CodeAnalysis; using System.Drawing; using System.Windows.Forms.Internal; using System.Globalization; using System.Runtime.InteropServices; using System.Security.Permissions; using System.Windows.Forms.Layout; ////// /// [ ComVisible(true), ClassInterface(ClassInterfaceType.AutoDispatch), DefaultProperty("Value"), DefaultEvent("ValueChanged"), DefaultBindingProperty("Value"), SRDescription(SR.DescriptionNumericUpDown) ] public class NumericUpDown : UpDownBase, ISupportInitialize { private static readonly Decimal DefaultValue = Decimal.Zero; private static readonly Decimal DefaultMinimum = Decimal.Zero; private static readonly Decimal DefaultMaximum = (Decimal)100.0; private const int DefaultDecimalPlaces = 0; private static readonly Decimal DefaultIncrement = Decimal.One; private const bool DefaultThousandsSeparator = false; private const bool DefaultHexadecimal = false; private const int InvalidValue = -1; ////////////////////////////////////////////////////////////// // Member variables // ////////////////////////////////////////////////////////////// ///Represents a Windows up-down control that displays numeric values. ////// The number of decimal places to display. /// private int decimalPlaces = DefaultDecimalPlaces; ////// The amount to increment by. /// private Decimal increment = DefaultIncrement; // Display the thousands separator? private bool thousandsSeparator = DefaultThousandsSeparator; // Minimum and maximum values private Decimal minimum = DefaultMinimum; private Decimal maximum = DefaultMaximum; // Hexadecimal private bool hexadecimal = DefaultHexadecimal; // Internal storage of the current value private Decimal currentValue = DefaultValue; private bool currentValueChanged; // Event handler for the onValueChanged event private EventHandler onValueChanged = null; // Disable value range checking while initializing the control private bool initializing = false; // Provides for finer acceleration behavior. private NumericUpDownAccelerationCollection accelerations; // the current NumericUpDownAcceleration object. private int accelerationsCurrentIndex; // Used to calculate the time elapsed since the up/down button was pressed, // to know when to get the next entry in the accelaration table. private long buttonPressedStartTime; ////// /// [ SuppressMessage("Microsoft.Globalization", "CA1303:DoNotPassLiteralsAsLocalizedParameters") // "0" is the default value for numeric up down. // So we don't have to localize it. ] public NumericUpDown() : base() { // this class overrides GetPreferredSizeCore, let Control automatically cache the result SetState2(STATE2_USEPREFERREDSIZECACHE, true); Text = "0"; StopAcceleration(); } ////////////////////////////////////////////////////////////// // Properties // ////////////////////////////////////////////////////////////// ///[To be supplied.] ////// Specifies the acceleration information. /// [ Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden) ] public NumericUpDownAccelerationCollection Accelerations { get { if( this.accelerations == null ){ this.accelerations = new NumericUpDownAccelerationCollection(); } return this.accelerations; } } ////// /// [ SRCategory(SR.CatData), DefaultValue(NumericUpDown.DefaultDecimalPlaces), SRDescription(SR.NumericUpDownDecimalPlacesDescr) ] public int DecimalPlaces { get { return decimalPlaces; } set { if (value < 0 || value > 99) { throw new ArgumentOutOfRangeException("DecimalPlaces", SR.GetString(SR.InvalidBoundArgument, "DecimalPlaces", value.ToString(CultureInfo.CurrentCulture), (0).ToString(CultureInfo.CurrentCulture), "99")); } decimalPlaces = value; UpdateEditText(); } } ///Gets or sets the number of decimal places to display in the up-down control. ////// /// [ SRCategory(SR.CatAppearance), DefaultValue(NumericUpDown.DefaultHexadecimal), SRDescription(SR.NumericUpDownHexadecimalDescr) ] public bool Hexadecimal { get { return hexadecimal; } set { hexadecimal = value; UpdateEditText(); } } ///Gets or /// sets a value indicating whether the up-down control should /// display the value it contains in hexadecimal format. ////// /// [ SRCategory(SR.CatData), SRDescription(SR.NumericUpDownIncrementDescr) ] public Decimal Increment { get { if (this.accelerationsCurrentIndex != InvalidValue) { return this.Accelerations[this.accelerationsCurrentIndex].Increment; } return this.increment; } set { if (value < (Decimal)0.0) { throw new ArgumentOutOfRangeException("Increment", SR.GetString(SR.InvalidArgument, "Increment", value.ToString(CultureInfo.CurrentCulture))); } else { this.increment = value; } } } ///Gets or sets the value /// to increment or /// decrement the up-down control when the up or down buttons are clicked. ////// /// [ SRCategory(SR.CatData), RefreshProperties(RefreshProperties.All), SRDescription(SR.NumericUpDownMaximumDescr) ] public Decimal Maximum { get { return maximum; } set { maximum = value; if (minimum > maximum) { minimum = maximum; } Value = Constrain(currentValue); Debug.Assert(maximum == value, "Maximum != what we just set it to!"); } } ///Gets or sets the maximum value for the up-down control. ////// /// [ SRCategory(SR.CatData), RefreshProperties(RefreshProperties.All), SRDescription(SR.NumericUpDownMinimumDescr) ] public Decimal Minimum { get { return minimum; } set { minimum = value; if (minimum > maximum) { maximum = value; } Value = Constrain(currentValue); Debug.Assert(minimum.Equals(value), "Minimum != what we just set it to!"); } } ///Gets or sets the minimum allowed value for the up-down control. ////// /// [ Browsable(false), EditorBrowsable(EditorBrowsableState.Never), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden) ] public new Padding Padding { get { return base.Padding; } set { base.Padding = value;} } [ Browsable(false), EditorBrowsable(EditorBrowsableState.Never) ] new public event EventHandler PaddingChanged { add { base.PaddingChanged += value; } remove { base.PaddingChanged -= value; } } ////// ///[To be supplied.] ////// Determines whether the UpDownButtons have been pressed for enough time to activate acceleration. /// private bool Spinning { get{ return this.accelerations != null && this.buttonPressedStartTime != InvalidValue; } } ////// /// /// [ Browsable(false), EditorBrowsable(EditorBrowsableState.Never), Bindable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden) ] // We're just overriding this to make it non-browsable. public override string Text { get { return base.Text; } set { base.Text = value; } } ////// The text displayed in the control. /// ////// [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)] new public event EventHandler TextChanged { add { base.TextChanged += value; } remove { base.TextChanged -= value; } } /// /// /// [ SRCategory(SR.CatData), DefaultValue(NumericUpDown.DefaultThousandsSeparator), Localizable(true), SRDescription(SR.NumericUpDownThousandsSeparatorDescr) ] public bool ThousandsSeparator { get { return thousandsSeparator; } set { thousandsSeparator = value; UpdateEditText(); } } /* * The current value of the control */ ///Gets or sets a value indicating whether a thousands /// separator is displayed in the up-down control when appropriate. ////// /// [ SRCategory(SR.CatAppearance), Bindable(true), SRDescription(SR.NumericUpDownValueDescr) ] public Decimal Value { get { if (UserEdit) { ValidateEditText(); } return currentValue; } set { if (value != currentValue) { if (!initializing && ((value < minimum) || (value > maximum))) { throw new ArgumentOutOfRangeException("Value", SR.GetString(SR.InvalidBoundArgument, "Value", value.ToString(CultureInfo.CurrentCulture), "'Minimum'", "'Maximum'")); } else { currentValue = value; OnValueChanged(EventArgs.Empty); currentValueChanged = true; UpdateEditText(); } } } } ////////////////////////////////////////////////////////////// // Methods // ////////////////////////////////////////////////////////////// ///Gets or sets the value /// assigned to the up-down control. ////// /// [SRCategory(SR.CatAction), SRDescription(SR.NumericUpDownOnValueChangedDescr)] public event EventHandler ValueChanged { add { onValueChanged += value; } remove { onValueChanged -= value; } } ////// Occurs when the ///property has been changed in some way. /// /// /// /// Handles tasks required when the control is being initialized. /// public void BeginInit() { initializing = true; } // // Returns the provided value constrained to be within the min and max. // private Decimal Constrain(Decimal value) { Debug.Assert(minimum <= maximum, "minimum > maximum"); if (value < minimum) { value = minimum; } if (value > maximum) { value = maximum; } return value; } ///protected override AccessibleObject CreateAccessibilityInstance() { return new NumericUpDownAccessibleObject(this); } /// /// /// public override void DownButton() { SetNextAcceleration(); if (UserEdit) { ParseEditText(); } Decimal newValue = currentValue; // Operations on Decimals can throw OverflowException. // try{ newValue -= this.Increment; if (newValue < minimum){ newValue = minimum; if( this.Spinning){ StopAcceleration(); } } } catch( OverflowException ){ newValue = minimum; } Value = newValue; } ////// Decrements the value of the up-down control. /// ////// /// /// public void EndInit() { initializing = false; Value = Constrain(currentValue); UpdateEditText(); } ////// Called when initialization of the control is complete. /// ////// Overridden to set/reset acceleration variables. /// protected override void OnKeyDown(KeyEventArgs e) { if (base.InterceptArrowKeys && (e.KeyCode == Keys.Up || e.KeyCode == Keys.Down) && !this.Spinning) { StartAcceleration(); } base.OnKeyDown(e); } ////// Overridden to set/reset acceleration variables. /// protected override void OnKeyUp(KeyEventArgs e) { if (base.InterceptArrowKeys && (e.KeyCode == Keys.Up || e.KeyCode == Keys.Down)) { StopAcceleration(); } base.OnKeyUp(e); } ////// /// /// protected override void OnTextBoxKeyPress(object source, KeyPressEventArgs e) { base.OnTextBoxKeyPress(source, e); NumberFormatInfo numberFormatInfo = System.Globalization.CultureInfo.CurrentCulture.NumberFormat; string decimalSeparator = numberFormatInfo.NumberDecimalSeparator; string groupSeparator = numberFormatInfo.NumberGroupSeparator; string negativeSign = numberFormatInfo.NegativeSign; string keyInput = e.KeyChar.ToString(); if (Char.IsDigit(e.KeyChar)) { // Digits are OK } else if (keyInput.Equals(decimalSeparator) || keyInput.Equals(groupSeparator) || keyInput.Equals(negativeSign)) { // Decimal separator is OK } else if (e.KeyChar == '\b') { // Backspace key is OK } else if (Hexadecimal && ((e.KeyChar >= 'a' && e.KeyChar <= 'f') || e.KeyChar >= 'A' && e.KeyChar <= 'F')) { // Hexadecimal digits are OK } else if ((ModifierKeys & (Keys.Control | Keys.Alt)) != 0) { // Let the edit control handle control and alt key combinations } else { // Eat this invalid key and beep e.Handled = true; SafeNativeMethods.MessageBeep(0); } } ////// Restricts the entry of characters to digits (including hex), the negative sign, /// the decimal point, and editing keystrokes (backspace). /// ////// /// protected virtual void OnValueChanged(EventArgs e) { // Call the event handler if (onValueChanged != null) { onValueChanged(this, e); } } ///Raises the ///event. protected override void OnLostFocus(EventArgs e) { base.OnLostFocus(e); if (UserEdit) { UpdateEditText(); } } /// /// Overridden to start/end acceleration. /// internal override void OnStartTimer() { StartAcceleration(); } ////// Overridden to start/end acceleration. /// internal override void OnStopTimer() { StopAcceleration(); } ////// /// protected void ParseEditText() { Debug.Assert(UserEdit == true, "ParseEditText() - UserEdit == false"); try { // VSWhidbey 173332: Verify that the user is not starting the string with a "-" // before attempting to set the Value property since a "-" is a valid character with // which to start a string representing a negative number. if (!string.IsNullOrEmpty(Text) && !(Text.Length == 1 && Text == "-")) { if (Hexadecimal) { Value = Constrain(Convert.ToDecimal(Convert.ToInt32(Text, 16))); } else { Value = Constrain(Decimal.Parse(Text, CultureInfo.CurrentCulture)); } } } catch { // Leave value as it is } finally { UserEdit = false; } } ////// Converts the text displayed in the up-down control to a /// numeric value and evaluates it. /// ////// Updates the index of the UpDownNumericAcceleration entry to use (if needed). /// private void SetNextAcceleration() { // Spinning will check if accelerations is null. if(this.Spinning && this.accelerationsCurrentIndex < (this.accelerations.Count - 1)) { // if index not the last entry ... // Ticks are in 100-nanoseconds (1E-7 seconds). long nowTicks = DateTime.Now.Ticks; long buttonPressedElapsedTime = nowTicks - this.buttonPressedStartTime; long accelerationInterval = 10000000L * this.accelerations[this.accelerationsCurrentIndex + 1].Seconds; // next entry. // If Up/Down button pressed for more than the current acceleration entry interval, get next entry in the accel table. if( buttonPressedElapsedTime > accelerationInterval ) { this.buttonPressedStartTime = nowTicks; this.accelerationsCurrentIndex++; } } } private void ResetIncrement() { Increment = DefaultIncrement; } private void ResetMaximum() { Maximum = DefaultMaximum; } private void ResetMinimum() { Minimum = DefaultMinimum; } private void ResetValue() { Value = DefaultValue; } ////// private bool ShouldSerializeIncrement() { return !Increment.Equals(NumericUpDown.DefaultIncrement); } ///Indicates whether the ///property should be /// persisted. /// private bool ShouldSerializeMaximum() { return !Maximum.Equals(NumericUpDown.DefaultMaximum); } ///Indicates whether the ///property should be persisted. /// private bool ShouldSerializeMinimum() { return !Minimum.Equals(NumericUpDown.DefaultMinimum); } ///Indicates whether the ///property should be persisted. /// private bool ShouldSerializeValue() { return !Value.Equals(NumericUpDown.DefaultValue); } ///Indicates whether the ///property should be persisted. /// Records when UpDownButtons are pressed to enable acceleration. /// private void StartAcceleration() { this.buttonPressedStartTime = DateTime.Now.Ticks; } ////// Reset when UpDownButtons are pressed. /// private void StopAcceleration() { this.accelerationsCurrentIndex = InvalidValue; this.buttonPressedStartTime = InvalidValue; } ////// /// Provides some interesting info about this control in String form. /// ///public override string ToString() { string s = base.ToString(); s += ", Minimum = " + Minimum.ToString(CultureInfo.CurrentCulture) + ", Maximum = " + Maximum.ToString(CultureInfo.CurrentCulture); return s; } /// /// /// public override void UpButton() { SetNextAcceleration(); if (UserEdit) { ParseEditText(); } Decimal newValue = currentValue; // Operations on Decimals can throw OverflowException. // try{ newValue += this.Increment; if (newValue > maximum){ newValue = maximum; if( this.Spinning){ StopAcceleration(); } } } catch( OverflowException ){ newValue = maximum; } Value = newValue; } private string GetNumberText(decimal num) { string text; if (Hexadecimal) { text = ((Int64)num).ToString("X", CultureInfo.InvariantCulture); Debug.Assert(text == text.ToUpper(CultureInfo.InvariantCulture), "GetPreferredSize assumes hex digits to be uppercase."); } else { text = num.ToString((ThousandsSeparator ? "N" : "F") + DecimalPlaces.ToString(CultureInfo.CurrentCulture), CultureInfo.CurrentCulture); } return text; } ////// Increments the value of the up-down control. /// ////// /// protected override void UpdateEditText() { // If we're initializing, we don't want to update the edit text yet, // just in case the value is invalid. if (initializing) { return; } // If the current value is user-edited, then parse this value before reformatting if (UserEdit) { ParseEditText(); } // VSWhidbey 173332: Verify that the user is not starting the string with a "-" // before attempting to set the Value property since a "-" is a valid character with // which to start a string representing a negative number. if (currentValueChanged || (!string.IsNullOrEmpty(Text) && !(Text.Length == 1 && Text == "-"))) { currentValueChanged = false; ChangingText = true; // Make sure the current value is within the min/max Debug.Assert(minimum <= currentValue && currentValue <= maximum, "DecimalValue lies outside of [minimum, maximum]"); Text = GetNumberText(currentValue); Debug.Assert(ChangingText == false, "ChangingText should have been set to false"); } } ////// Displays the current value of the up-down control in the appropriate format. /// ////// /// protected override void ValidateEditText() { // See if the edit text parses to a valid decimal ParseEditText(); UpdateEditText(); } // This is not a breaking change -- Even though this control previously autosized to hieght, // it didn't actually have an AutoSize property. The new AutoSize property enables the // smarter behavior. internal override Size GetPreferredSizeCore(Size proposedConstraints) { int height = PreferredHeight; int baseSize = Hexadecimal ? 16 : 10; int digit = GetLargestDigit(0, baseSize); // The floor of log is intentionally 1 less than the number of digits. We initialize // testNumber to account for the missing digit. int numDigits = (int)Math.Floor(Math.Log(Math.Max(-(double)Minimum, (double)Maximum), baseSize)); decimal testNumber; // preinitialize testNumber with the leading digit if(digit != 0 || numDigits == 1) { testNumber = digit; } else { // zero can not be the leading digit if we need more than // one digit. (0*baseSize = 0 in the loop below) testNumber = GetLargestDigit(1, baseSize); } // e.g., if the lagest digit is 7, and we can have 3 digits, the widest string would be "777" for(int i = 0; i < numDigits; i++) { testNumber = testNumber * baseSize + digit; } int textWidth = TextRenderer.MeasureText(GetNumberText(testNumber), this.Font).Width; // Call AdjuctWindowRect to add space for the borders int width = SizeFromClientSize(textWidth, height).Width + upDownButtons.Width; return new Size(width, height) + Padding.Size; } private int GetLargestDigit(int start, int end) { int largestDigit = -1; int digitWidth = -1; for(int i = start; i < end; i++) { char ch; if(i < 10) { ch = i.ToString(CultureInfo.InvariantCulture)[0]; } else { ch = (char)('A' + (i - 10)); } Size digitSize = TextRenderer.MeasureText(ch.ToString(), this.Font); if(digitSize.Width >= digitWidth) { digitWidth = digitSize.Width; largestDigit = i; } } Debug.Assert(largestDigit != -1 && digitWidth != -1, "Failed to find largest digit."); return largestDigit; } [System.Runtime.InteropServices.ComVisible(true)] internal class NumericUpDownAccessibleObject : ControlAccessibleObject { public NumericUpDownAccessibleObject(NumericUpDown owner) : base(owner) { } public override AccessibleRole Role { get { AccessibleRole role = Owner.AccessibleRole; if (role != AccessibleRole.Default) { return role; } return AccessibleRole.ComboBox; } } public override AccessibleObject GetChild(int index) { if (index >= 0 && index < GetChildCount()) { // TextBox child // if (index == 0) { return ((UpDownBase)Owner).TextBox.AccessibilityObject.Parent; } // Up/down buttons // if (index == 1) { return ((UpDownBase)Owner).UpDownButtonsInternal.AccessibilityObject.Parent; } } return null; } public override int GetChildCount() { return 2; } } } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007. // Copyright (c) Microsoft Corporation. All rights reserved./// Validates and updates /// the text displayed in the up-down control. /// ///
Link Menu

This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- SymDocumentType.cs
- ProfileGroupSettings.cs
- XPathDocumentNavigator.cs
- SiteMapProvider.cs
- TableLayoutSettingsTypeConverter.cs
- CodeArrayCreateExpression.cs
- MetaChildrenColumn.cs
- Int32Converter.cs
- HtmlAnchor.cs
- DataGridParentRows.cs
- HashCodeCombiner.cs
- SqlClientMetaDataCollectionNames.cs
- MimeObjectFactory.cs
- DataReaderContainer.cs
- SubqueryTrackingVisitor.cs
- EditorZoneDesigner.cs
- GacUtil.cs
- HttpClientChannel.cs
- ContentPresenter.cs
- HtmlValidatorAdapter.cs
- Registry.cs
- DuplicateWaitObjectException.cs
- BindingsCollection.cs
- XmlUrlResolver.cs
- DataGridViewAdvancedBorderStyle.cs
- ClassImporter.cs
- ImportContext.cs
- TransportContext.cs
- SlipBehavior.cs
- TransactionTable.cs
- HashRepartitionEnumerator.cs
- RemotingAttributes.cs
- BindingList.cs
- XmlCharCheckingReader.cs
- ProcessInfo.cs
- FilterRepeater.cs
- Light.cs
- CompilerGlobalScopeAttribute.cs
- Rethrow.cs
- PageAsyncTaskManager.cs
- SourceLineInfo.cs
- SqlServices.cs
- FontWeights.cs
- CachedBitmap.cs
- TimeEnumHelper.cs
- GeneralTransform3D.cs
- WebPartDisplayModeCollection.cs
- InputLanguageProfileNotifySink.cs
- Vector3D.cs
- VisualStyleInformation.cs
- TraceContextRecord.cs
- XmlSerializerAssemblyAttribute.cs
- linebase.cs
- SafeTokenHandle.cs
- BuildResult.cs
- PolyQuadraticBezierSegment.cs
- CodeAttachEventStatement.cs
- RMEnrollmentPage3.cs
- ResXFileRef.cs
- ClientSideQueueItem.cs
- ProfileSettings.cs
- InlinedLocationReference.cs
- TreeNodeStyle.cs
- RegistrySecurity.cs
- DeclaredTypeValidator.cs
- GetPageNumberCompletedEventArgs.cs
- WindowsTitleBar.cs
- XPathScanner.cs
- XmlSerializerSection.cs
- SqlRowUpdatingEvent.cs
- ColumnClickEvent.cs
- TrackPointCollection.cs
- XmlSerializerVersionAttribute.cs
- ExtractCollection.cs
- DesignerUtils.cs
- SelectionGlyph.cs
- SqlMetaData.cs
- Margins.cs
- MetadataException.cs
- SystemBrushes.cs
- CrossContextChannel.cs
- MaterialGroup.cs
- ArrayList.cs
- SspiHelper.cs
- ToolStripButton.cs
- JsonSerializer.cs
- BasicCellRelation.cs
- DoubleAnimationUsingKeyFrames.cs
- Serializer.cs
- RuntimeCompatibilityAttribute.cs
- MachineKeySection.cs
- TrackingMemoryStreamFactory.cs
- PasswordBoxAutomationPeer.cs
- BrowserDefinitionCollection.cs
- AppDomain.cs
- IPEndPoint.cs
- BaseEntityWrapper.cs
- CfgRule.cs
- DomNameTable.cs
- VerificationException.cs