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
- DataSourceControl.cs
- InputBinding.cs
- SafeNativeMethods.cs
- BasicCommandTreeVisitor.cs
- HMACSHA1.cs
- StrongNameMembershipCondition.cs
- VerticalAlignConverter.cs
- StaticSiteMapProvider.cs
- util.cs
- COM2FontConverter.cs
- BitmapCodecInfoInternal.cs
- clipboard.cs
- FileSystemEventArgs.cs
- StrongNamePublicKeyBlob.cs
- InboundActivityHelper.cs
- IInstanceTable.cs
- GetCardDetailsRequest.cs
- IResourceProvider.cs
- ConfigXmlText.cs
- FrameworkTextComposition.cs
- WorkflowRuntimeService.cs
- BindingMemberInfo.cs
- ServiceThrottlingBehavior.cs
- DataSourceConverter.cs
- XmlSchemaCompilationSettings.cs
- ShadowGlyph.cs
- Stream.cs
- AppDomainManager.cs
- RelationshipConverter.cs
- DataGridViewRowErrorTextNeededEventArgs.cs
- ShutDownListener.cs
- DataGridViewTextBoxCell.cs
- AttributeCollection.cs
- VarRefManager.cs
- PreviewPrintController.cs
- BuildDependencySet.cs
- DesignerActionList.cs
- ProjectedSlot.cs
- TileBrush.cs
- ListViewEditEventArgs.cs
- PackagingUtilities.cs
- _SslSessionsCache.cs
- TypeElement.cs
- FileAuthorizationModule.cs
- BamlLocalizableResource.cs
- DbFunctionCommandTree.cs
- ObjectDataSourceEventArgs.cs
- MgmtResManager.cs
- ZipPackagePart.cs
- DataRecordObjectView.cs
- SplitterEvent.cs
- BamlLocalizer.cs
- UTF32Encoding.cs
- CDSsyncETWBCLProvider.cs
- Panel.cs
- GlobalizationSection.cs
- PartialTrustVisibleAssembly.cs
- DefaultSection.cs
- Section.cs
- bidPrivateBase.cs
- ArraySet.cs
- TemplateField.cs
- SqlError.cs
- counter.cs
- ToolStripMenuItem.cs
- BuilderInfo.cs
- updateconfighost.cs
- AtomServiceDocumentSerializer.cs
- IFlowDocumentViewer.cs
- AnimationLayer.cs
- ParameterCollection.cs
- DocumentReference.cs
- BitmapSizeOptions.cs
- CollectionConverter.cs
- FrameworkName.cs
- MarshalDirectiveException.cs
- FixedSOMTableRow.cs
- BehaviorEditorPart.cs
- ArrayList.cs
- TypeReference.cs
- WhileDesigner.cs
- SrgsElement.cs
- TreeWalkHelper.cs
- ContextDataSource.cs
- SendMailErrorEventArgs.cs
- DataGridViewCellValidatingEventArgs.cs
- NamedPipeAppDomainProtocolHandler.cs
- StructuredTypeInfo.cs
- TimeSpanValidator.cs
- NameObjectCollectionBase.cs
- ConnectionProviderAttribute.cs
- ZipPackage.cs
- WebConfigurationManager.cs
- HierarchicalDataTemplate.cs
- CompModSwitches.cs
- WindowsScroll.cs
- BinarySecretKeyIdentifierClause.cs
- StorageMappingItemCollection.cs
- NamedElement.cs
- ComplexPropertyEntry.cs