- Implements TSpinEditEx and TFloatSpinEditEx, which allow a NullValue and provide behaviors applied when the text for the control is not a valid number. -
-- Initial implementation: 2016 by Bart Broersma. Revised in August 2020. -
-- TNullValueBehaviour is an enumerated type with values that control the behavior in TSpinEditEx or TFloatSpinEditEx when their value is not a valid number, or not within the Min and Max value for the control. -
-- TSpinEditExBase is a generic class type, and a descendant of TCustomAbstractGroupedEdit. TSpinEditExBase specifies the base class for the extended spin edit controls including TSpinEditEx and TFloatSpinEditEx. TSpinEditExBase must be specialized in a descendent class for a specific data type. The specialization type is used to implement properties including: Increment, MinValue, MaxValue, NullValue, and Value. -
-- The return value is True when MaxValue is larger than MinValue. IsLimited is used in the implementation of the IsOutOfLimits method. -
-- UpdateControl is a method used to update members in the class instance to reflect the state for the control. It is called when a new value is assigned to properties in the class instance. It is called when editing has been completed using the Edit for the grouped editing control. It is also called when the handle is allocated for the control in InitializeWnd. -
-- UpdateControl ensures that values in MinValue and MaxValue are valid. If MaxValue is not larger than MinValue, the value in MinValue is used in both properties. -
-- NullValueBehaviour is used to determine whether Value is adjusted to ensure that it is in the range specified by MinValue and MaxValue. A value other than nvbShowTextHint causes GetLimitedValue to be called to get the adjusted Value. -
-- No additional actions are performed in the method when a handle has not been allocated for the control, or at design-time. -
-- When NullValueBehaviour is set to nvbShowTextHint, an invalid numeric value entered in Text causes Text to be set to an empty string. This allows the TextHint for the control to be displayed. -
-- When Value is a valid number, and in the required range, it is converted to its String representation and assigned to the Text for the control. -
-- No actions are performed in the handler when ReadOnly is set to True. -
-- When Direction is updUp, the SpinUpDown method is called using True as an argument. Otherwise, SpinUpDown is called using False as an argument. -
-- Calls the BuddyClick method for the grouped edit control. -
-- DoEnter is an overridden method in TSpinEditExBase, and calls the inherited method on entry. The inherited methods handle the change in control focus, and signal the OnEnter event handler (when assigned). DoEnter ensures that the initial Value for the control is stored internally for use with the NullValueBehaviour used for the control instance. -
-- RealGetText is an overridden TCaption function in TSpinEditExBase used to get the text displayed for the control. RealGetText checks whether a handle has been allocated for the control in the widget set class. When a handle is assigned, the inherited method is called to the Text for the Edit in the grouped edit control. Otherwise, ValueToStr is called to get the string representation for the control Value. -
-- Reset is an overridden method in TSpinEditExBase used to revert changes made to the Value for the control. The IsMasked property is used to determine if an editing mask is in use in the Edit for the grouped edit control. When set to True, the inherited method is called to revert any changes made in Edit. When an editing mask is not in use, the initial value for the control (captured when it received focus) is restored in the Value property. -
-- Reset is used in the implementation of the EditKeyDown event handler assigned to Edit. It is called when the Escape key (VK_Escape) is pressed in the Edit control. -
-- Calls the inherited method and performs no additional actions. -
-- EditKeyDown is an overridden method in TSpinEditExBase which implements the KeyDown event handler for the Edit control. It calls the inherited method which signals the OnEditKeyDown event handler (when assigned). It also ensures that any keys explicitly handled in the grouped edit control are discarded by setting Key to 0 (zero). This includes the following virtual key codes and their associated actions: -
-- EditMouseWheelUp is the handler signalled when a Mouse Wheel Up message occurs in the Edit for the control. EditMouseWheelUp is overridden in TSpinEditExBase, and calls the inherited method. Handled is set to True if the mouse wheel message was handled in the ancestor class. When set to False, the SpinUpDown method is called to increment the value in the control. -
-- EditMouseWheelDown is the handler signalled when a Mouse Wheel Down message occurs in the Edit for the control. EditMouseWheelDown is overridden in TSpinEditExBase, and calls the inherited method. Handled is set to True if the mouse wheel message was handled in the ancestor class. When set to False, the SpinUpDown method is called to decrement the value in the control. -
-- SafeInc is a function used to increase the specified value by the Increment for the control. SafeInc ensures that the incremented value is valid for a given data type. It is an abstract virtual method, and must be implemented in a descendent class to use the specific data type for the specialization. -
-- AValue contains the type with the numeric value to be incremented. -
-- The return value contains the numeric value for the type after the value in Increment has been added. The return value is constrained when the incremented value is too large for the data type. -
-- SafeInc is used in the implementation of the SpinUpDown method. -
-- SafeDec is a function used to decrease the specified value by the Increment for the control. SafeDec ensures that the decremented value is valid for a given data type. It is an abstract virtual method, and must be implemented in a descendent class to use the specific data type for the specialization. -
-- AValue contains the type with the numeric value to be decremented. -
-- The return value contains the numeric value for the type after the value in Increment has been subtracted. The return value is constrained when the incremented value is too large for the data type. -
-- SafeDec is used in the implementation of the SpinUpDown method. -
-- TextIsNumber is an abstract virtual Boolean function which indicates the value specified in S represents a valid number. ANumber is an output parameter where the numeric value for the data type is stored. -
-- TextIsNumber must be implemented in a descendent class using the data type for the specialization. -
-- InitializeWnd is an overridden method used to perform actions needed when the handle is allocated for the control, and before child controls are created. InitializeWnd calls the inherited method on entry. -
-- InitializeWnd calls UpdateControl to validate and update members in the class instance. -
-- Loaded is an overridden method in TSpinEditExBase, and calls the inherited method on entry. Loaded corrects an undesirable behavior in the ancestor class; it sends a CM_PARENTFONTCHANGED message which also alters the color in the grouped edit control. Loaded calls UpdateSpacing prior to restoring the initial color assigned to the edit control. -
-- ArrowKeys is a Boolean property which indicates if cursor keys can be used to navigate content in the Edit for the control. -
-- When set to True, the Up (VK_UP) and Down (VK_Down) arrow keys can be used to increase or decrease the Value for the control. The key events are handled in the EditKeyDown event handler assigned to Edit. When set to False, the Up and Down keys are ignored in Edit. -
-- The default value for the property is True. -
-- Use UpDown to access the TUpDown instance used in the grouped edit control. -
-- Edit a read-only TGEEdit property which contains the editor for the grouped edit control. Edit is used to perform direct input of a new Value for the control. Edit allows use of the Up and Down cursor keys to increment or decrement the value when ArrowKeys is enabled. -
-- UpDown is the TUpDown instance used to increment and decrement the value for the grouped edit control using mouse clicks. -
-- UpDown is a read-only property which contains the TUpDown instance used to increment or decrement the Value for the grouped edit control. Click on the buttons in UpDown to increase or decrease the Value for the control by the amount specified in the Increment property. -
-- Edit is used to perform direct input of the value for the grouped edit control. -
-- UpDownVisible is a Boolean property which indicates if UpDown in the grouped edit control is visible. It is a convenience property; read and write access for the value are redirected to the Visible property in the TUpDown instance in UpDown. The default value for the property is True. -
-- MinRepeatValue contains the repeat interval used for the UpDown control in the grouped edit. The default value for the property is defined in the DefMinRepeatValue constant. -
-- Changing the value for the property causes the MinRepeatInterval property in UpDown to be updated with the new value. -
-- Create is the overridden constructor for the class instance, and calls the inherited constructor on entry. Create sets the default values for properties, including: -
-- Create configures the Edit and UpDown instances used in the grouped edit control. Edit is configured to use right alignment for its text (since it is a numeric value). UpDown is configured to include the flags needed in its ControlStyle property. The OnChangingEx and OnClick event handlers for UpDown are also set in the method. -
-- Internal members needed in the class instance are also initialized. -
-- Create calls SetInitialBounds to set the size for the control to the default values returned from GetControlClassDefaultSize. -
-- GetLimitedValue is used in the implementation of UpdateControl, SpinUpDown, and StrToValue methods. It is also called from the ValueToStr method in TCustomFloatSpinEditEx. -
-- GetLimitedValue ensures that the value for the type specified in AValue is constrained to the range specified in the MinValue and MaxValue properties. AValue is the type with the numeric value examined in the method. -
-- The return value contains the original value after it has been range adjusted. When AValue is smaller than MinValue, MinValue is assigned to the return value. When AValue is larger than MaxValue, MaxValue is assigned to the return value. -
-- ValueToStr is an abstract virtual String function used to convert the value specified in AValue to its representation as a String data type. ValueToStr must be implemented in a descendent class to use the data type and formatting needed for the specialization. -
-- StrToValue is a function which returns a generic type with the numeric value for the specified String. TextIsNumber is used to determine if S contains a valid numeric value. If S is not a valid number, the NullValueBehaviour property is used to determine the return value for the method. -
-- EditEditingDone is an overridden method in TSpinEditExBase. It calls the inherited method on entry to signal the OnEditingDone event handler (when assigned). -
-- EditEditingDone updates the Value for the control from the Text in the Edit. UpdateControl is called to ensure that members in the property are updated and validated after a change to the Value property. -
-- Increment is a property which defines the value added to or subtracted from the control Value when the UpDown control is clicked. It is also used when ArrowKeys are enable in the Edit for the grouped edit control. -
-- Increment uses the generic type for the class instance. There is no default value for the control in TSpinEditExBase, but it may be re-specified in a descendent class specialized for a given data type. -
-- MinValue is a property used to specify the minimum numeric value allowed in the Value property. MinValue uses the type specified for the generic class. Changing the property value causes UpdateControl to be called to range check and update members in the control. -
-- MinValue is used in the implementation of methods such as IsLimited, IsOutOfLimits, SpinUpDown, and GetLimitedValue. It also influences the value stored in the control when a NullValueBehaviour is applied. -
-- Use MaxValue to specify the maximum value allowed in the control. -
-- MaxValue is a property which contains the largest numeric value allowed in the Value property. MaxValue uses the type specified for the generic class. Changing the property value causes UpdateControl to be called to range check and update members in the control. -
-- MaxValue is used in the implementation of methods such as IsLimited, IsOutOfLimits, SpinUpDown, and GetLimitedValue. It also influences the value stored in the control when a NullValueBehaviour is applied. -
-- Use MinValue to specify the smallest value allowed in the control. -
-- NullValue contains the numeric value used when the text for the control does not represent a valid number. NullValue is assigned to Value when the NullValueBehaviour property is set to nvbLimitedNullValue or nvbShowTextHint. -
-- NullValueBehaviour is a TNullValueBehaviour property which contains the logic applied when the text for the control does not represent a valid numeric value. The default value for the property is nvbMinValue, and indicates that the value in MinValue is stored in the Value property when an invalid number is detected. -
-- See TNullValueBehaviour for more information about values in the enumeration and their meanings. -
-- NullValueBehaviour is used in the implementation of the UpdateControl and StrToValue methods. -
-- Value is a property which contains the numeric value for the grouped edit control. Value used the data type specified for the generic class. -
-- Read access to the property value checks for an allocated handle in the control. If the handle has not been allocated, the StrToValue method is called to get the property value. When the handle exists, the value stored in the internal member is used. -
-- Write access to the property value ensures that text assigned directly to Edit contains a valid number for the data type. This is done by calling TextIsNumber. If the new value is the same as the stored property value, no actions are performed. -
-- When the value for the property is changed, the UpdateControl method is called to range check, validate, and update members in the class instance. -
-- Use MinValue and MaxValue to control the minimum and maximum values allowed in the control. Use Increment to control the amount applied to the control value when a button in the UpDown control is clicked. Use NullValue and NullValueBehaviour to control the logic applied with an invalid numeric value is stored in the control. -
-
- TCustomFloatSpinEditEx defines an extended spin edit control with an editor for the numeric value, and buttons to increment or decrement the control value.It is a TSpinEditExBase descendant which specializes the generic ancestor for the
- Do not create instances of TCustomFloatSpinEditEx; use the TFloatSpinEditEx descendant which sets the visibility and default values for properties in the class. -
-- EditKeyPress is an overridden method in TCustomFloatSpinEditEx used to ensure that the specified character is valid for the Edit in the control. Key contains the character examined in the method. The allowed values in Key include the following characters: -
-- EditKeyPress calls the inherited method to signal the OnEditKeyPress event handler (when assigned). -
-- Any character which is not allowed in the floating point value is set to #0 to discard the character value. -
-- TextIsNumber is an overridden Boolean function used to determine if the specified string contains a valid representation for the numeric data type in the control. TextIsNumber re-implements the inherited method to use the Double data type, and does not call the method in the ancestor class. -
-- TextIsNumber calls TryStrToFloat using the local format settings for the control to convert the value in S to a floating point value. An exception raised by TryStrToFloat is handled in the method. The converted numeric value is stored in the ANumber argument on success. ANumber should be considered "undefined" when the conversion fails due to an exception. -
-- The return value is True when the value in S can be converted to the Double data type. It is False when an exception was raised and handled in the method. -
-- TextIsNumber is used in the implementation of methods like UpdateControl, SpinUpDown, and StrToValue. It is also called when setting a new value in the Value property. -
-- Set values in the MinValue, MaxValue, NullValue, and NullValueBehaviour properties to control the actions performed when TextIsNumber returns False. -
-- SafeInc is an overridden function in TCustomFloatSpinEditEx used to increase the specified value by the Increment for the control. SafeInc ensures that the incremented value is valid for the Double data type. SafeInc does not call the inherited method. -
-- AValue contains the type with the numeric value to be incremented. -
-- The return value contains the numeric value after the value in Increment has been added. The return value is constrained when the incremented value is too large for the Double data type. The upper limit for the value in the data type is defined in the MaxDouble constant. -
-- SafeInc is used in the implementation of the SpinUpDown method. -
-- SafeDec is used to decrement a specified Double value. -
-- SafeDec is an overridden function in TCustomFloatSpinEditEx used to decrease the specified value by the Increment for the control. SafeDec ensures that the decremented value is valid for the Double data type. SafeDec does not call the inherited method. -
-- AValue contains the type with the numeric value to be decremented. -
-- The return value contains the numeric value after the value in Increment has been subtracted. The return value is constrained when the decremented value is too small for the Double data type. The lower limit for the value in the data type is defined as -1 * MaxDouble. -
-- SafeDec is used in the implementation of the SpinUpDown method. -
-- SafeInc is used to increment a specified Double value. -
-- DisplayMode is a TDisplayMode property which specifies the formatting used to edit and display the Value for the control. The default value for the property is dmFixed, and indicates that fixed precision and decimals are used when formatting the control value. - - See TDisplayMode for more information about the values and meanings in the enumeration. -
-- Changing the value in DisplayMode causes the Value for the control to be updated. It also forces UpdateControl to be called to validate and normalize members in the class instance. -
-- DisplayMode is used in the implementation of the ValueToStr method which generates the string representation for the Value in the control, and is assigned to the Text property in the Edit for the grouped edit control. -
-- ExponentialFormatLimitPos is an Integer property which contains the maximum exponent allowed before a positive Value in the control must be represented using exponential notation. The default value for the property is 6 (six) and indicates that Value must exceed 10^6 before exponential notation is required for a positive number. -
-- Setting a new value for the property causes Value to be updated, and calls the UpdateControl method to validate and normalize members in the class instance. -
-- ExponentialFormatLimitPos is used in the ValueToStr method when DisplayMode contains the value dmAuto and Value has a non-zero floating point value. -
-- Use ExponentialFormatLimitNeg to specify the maximum exponent allowed before using exponential notation for a negative value in the control. -
-- Use Precision to specify the total number of digits used for a number in scientific notation. Use ExponentDigits to specify the number of exponent digits used for a number in scientific notation. -
-- ExponentialFormatLimitNeg is an Integer property which contains the exponent value at which use of scientific notation is triggered for a negative Value in the control. The default value for the property is -6, and indicates that scientific notation is required when Value is smaller than 10^-6. -
-- Changing the value for the property causes GetValue and UpdateControl to be called. -
-- ExponentialFormatLimitNeg is used in the ValueToStr method when DisplayMode is dmAuto and the Value is not 0.0. -
-- Use ExponentialFormatLimitPos to specify the exponent value which triggers use of scientific notation for a positive value. -
-- Use Precision to specify the total number of digits used for a number in scientific notation. Use ExponentDigits to specify the number of exponent digits used for a number in scientific notation. -
-- Precision is an Integer property which specifies the number of digits of precision used after the decimal point for a floating point value in scientific notation. It is the value used as the precision argument for the FloatToStrF routine in RTL. The default value for the property is 6. The maximum precision for the data type is 15. -
-- Changing the value for the property causes the GetValue and UpdateControl methods to be called. -
-- Precision is used in the ValueToStr method when DisplayMode is dmScientific or dmAuto. -
-- ExponentDigits is an Integer property which contains the number of digits used before the decimal point when using scientific notation. The default value for the property is 2. -
-- Changing the value for the property causes the GetValue and UpdateControl methods to be called. -
-- ExponentDigits is used in the ValueToStr method when the DisplayMode is dmScientific or dmAuto. -
-- Use Precision to specify the number of digits after the decimal point in a floating point value using scientific notation. -
-- Create is the overridden constructor for the class instance, and calls the inherited constructor on entry. -
-- Create makes an internal copy of the default format settings for the platform. This allows the value in DecimalSeparator to be specified and stored independent of the value in DefaultFormatSettings. The local copy is modified to used the value in the DefDecimalSeparator constant as the default value for DecimalSeparator. -
-- Create sets the default values for properties, including: -
-- DecimalSeparator is a Char property which contains the character used as the decimal point in a floating point value. Read and write access for the property value are redirected to the local TFormatSetting stored in the class instance. This allows the control to set the decimal separator independent of the format settings for the platform or operating system. -
-- The default value for the property is defined in the DefDecimalSeparator constant. Changing the value for the property updates the local format settings, and calls UpdateControl to validate and update members in the class instance. -
-- DecimalSeparator is used in EditKeyPress to validate characters entered in the Edit for the control. It is also used in ValueToStr to format the value in the control for the selected DisplayMode. -
-- DecimalPlaces is an Integer property which indicates the number of decimal places used when formatting the Value for the control. It must contain a positive integer value or 0 (zero). The default value for the property is defined in the DefDecimals constant. Changing the value for the property causes the Value property to be updated, and calls UpdateControl to validate and update other members in the class instance. -
-- DecimalPlaces is used in ValueToStr to format the value in the control for the selected DisplayMode. -
-- TFloatSpinEditEx is a TCustomFloatSpinEditEx descendant which implements a spin edit control for a value using the Double data type. TFloatSpinEditEx sets the visibility for properties defined in ancestor classes. -
-
- TFloatSpinEditEx defines an extended spin edit control with an editor for the numeric value, and buttons to increment or decrement the control value. It specializes the generic ancestor for the
- TCustomSpinEditEx is a specialization of the generic TSpinEditExBase class for the Int64 data type. In addition to implementing the Int64 data type, it provides additional properties and methods used to validate, format, and display the numeric value. -
-- Use the ThousandSeparator to set the UTF-8-encoded value used as the decimal point in the control value. -
-- Set Increment to the value by which the control is increased or decreased when the UpDown button is clicked. -
-- Use ValueToStr to get the string representation for the numeric value. -
-- Do not create instances of TCustomSpinEditEx; use TSpinEditEx, which sets the visibility for properties, instead. -
-- Use TFloatSpinEditEx to edit a floating point value using fixed or scientific notation. -
-- EditKeyPress is an overridden method in TCustomSpinEditEx, and calls the inherited method on entry. The OnEditKeyPress event handler is signalled (when assigned) by the inherited method. -
-- EditKeyPress ensures that the value in Key is valid for the control. An invalid value is discarded by setting Key to the #0 character (Decimal 0). Valid characters include numeric digits ('0'..'9'), the value in ThousandSeparator, and the negative sign indicator ('-'). -
-- Please note: The sign indicator will be disallowed when a positive non-zero value is specified in the MinValue property. -
-- Tab, BackSpace, Cut, Paste, Copy, and Undo key presses are passed to the inherited method. -
-- SafeInc is a function used to increase AValue by the amount specified in the Increment property. SafeInc is overridden in TCustomSpinEditEx to ensure that the incremented value is valid for the Int64 data type. -
-- AValue contains the the numeric value to be incremented. -
-- The return value contains the Int64 value after Increment has been added. The return value is constrained when the incremented value is too large for the Int64 data type; its value is set to High(Int64). -
-- SafeInc is used in the implementation of the SpinUpDown method in the ancestor class. -
-- SafeDec is a function used to decrease the specified value by the amount specified in the Increment property. SafeDec is overridden in TCustomSpinEditEx to ensure that the decremented value is valid for the Int64 data type. -
-- AValue contains the numeric value to be decremented. -
-- The return value contains the Int64 value after Increment has been subtracted. The return value is constrained when the decremented value is too small for the Int64 data type; its value is set to Low(Int64). -
-- SafeDec is used in the implementation of the SpinUpDown method in the ancestor class. -
-- TextIsNumber is an overridden Boolean function which indicates if the value specified in S represents a valid number for the Int64 data type. -
-- ANumber is an output parameter where the numeric value from the conversion from the is stored. -
-- The return value is a Boolean type which contains True when the text in S is successfully converted to an Int64 value and stored i the N argument. If the conversion raises an exception, it is handled in the method and the return value is set to False. The value in N should be considered as "undefined" in this scenario. -
-- ValueToStr is an overridden String function used to convert the value specified in AValue to its representation as a String data type. AValue is an Int64 type. -
-- ValueToStr calls IntToStr to convert the integer value to the String used as the return value for the method. When ThousandSeparator has been assigned, the InsertThousandSeparator routine is called to apply the display formatting to the return value. -
-- ValueToStr is used in the implementation of both the UpdateControl and RealGetText methods in the ancestor class. -
-- Increment is an Int64 property in TCustomSpinEditEx, and represents the amount by which the control value is increased or decreased when the UpDown button is clicked. The default value for the property is 1. -
-- Increment is used in the implementation of the SafeInc and SafeDec methods. -
-- ThousandSeparator is a String property which contains the character used as the thousands separator in the control. It is implemented as a String type to allow use of UTF-8-encoded characters in the property value. When it is unassigned (contains an empty string), the separator is not used to format the string value for the control. -
-- Changing the value in ThousandSeparator causes the UpdateControl method to be called to update the display for the control. -
-- ThousandSeparator is used in methods like EditKeyPress, TextIsNumber, and ValueToStr. -
-- TSpinEditEx is a TCustomSpinEditEx descendant which implements a spin edit control using an Int64 value. TSpinEditEx sets the visibility for properties defined in ancestor classes. -
-- Use the ThousandSeparator to set the UTF-8-encoded value used as the decimal point in the control value. -
-- Set Increment to the value by which the control is increased or decreased when the UpDown button is clicked. -
-- Use ValueToStr to get the string representation for the numeric value. -
-- DbgS is an overloaded String function used to get information displayed in the Debugger. This variant of the routine accepts a TNullValueBehaviour argument, an converts the specified value to its string representation, -
-
- The
- This introduction will discuss the problems the design of the controls, and the problems they are intended to eliminate. -
-- Why another SpinEdit or FloatSpinEdit control? -
-- The standard controls, TSpinEdit and TFloatSpinEdit, do not support a NullValue mechanism. Also, their implementations are widgetset dependent. While this provides a control that has the look and feel native to the widgetset, the behavior also depends on the widgetset. This is especially important when the text for the control contains an invalid numeric value (otherwise not a number). In such a case, when querying the control for it's Value, the results are not consistent for the various platforms. The difference in behavior between widgetsets also prevents implementation of the NullValue mechanism, especially the possibility to leave the control empty or to display informative text inside the control about the condition. -
-- TSpinEditEx handles Int64 values, while TSpinEdit is limited to LongInt values. This is because TSpinEdit inherits from TCustomFloatSpinEdit and the internal member for the Value is stored using the Double type, and Double does not have enough significant digits to handle the range for the Int64 type. -
-- In addition, TFloatSpinEditEx can set the value for its DecimalSeparator property independent of the value in the DefaultFormatSettings for the platform or operating system. Note: Unlike T(Float)SpinEdit, the GetValue method is always derived from the actual text in the control. This is by design, and it should not be altered. -
-- Why not simply associate a TUpDown with a TEdit instead? -
-- Using TEdit with a TUpDown control has several disadvantages: -
-- While both TSpinEditEx and TFloatSpinEditEx use a TUpDown control in their implementations, they do not use the Associate property in TUpDown. The two controls (the edit and the up/down button) are embedded in a TCustomControl (much like TEditButton) to provide proper alignment and anchoring behavior. -
-+ Implements TSpinEditEx and TFloatSpinEditEx, which allow a NullValue and provide behaviors applied when the text for the control is not a valid number. +
++ Initial implementation: 2016 by Bart Broersma. Revised in August 2020. +
++ TNullValueBehaviour is an enumerated type with values that control the behavior in TSpinEditEx or TFloatSpinEditEx when their value is not a valid number, or not within the Min and Max value for the control. +
++ TSpinEditExBase is a generic class type, and a descendant of TCustomAbstractGroupedEdit. TSpinEditExBase specifies the base class for the extended spin edit controls including TSpinEditEx and TFloatSpinEditEx. TSpinEditExBase must be specialized in a descendent class for a specific data type. The specialization type is used to implement properties including: Increment, MinValue, MaxValue, NullValue, and Value. +
++ The return value is True when MaxValue is larger than MinValue. IsLimited is used in the implementation of the IsOutOfLimits method. +
++ UpdateControl is a method used to update members in the class instance to reflect the state for the control. It is called when a new value is assigned to properties in the class instance. It is called when editing has been completed using the Edit for the grouped editing control. It is also called when the handle is allocated for the control in InitializeWnd. +
++ UpdateControl ensures that values in MinValue and MaxValue are valid. If MaxValue is not larger than MinValue, the value in MinValue is used in both properties. +
++ NullValueBehaviour is used to determine whether Value is adjusted to ensure that it is in the range specified by MinValue and MaxValue. A value other than nvbShowTextHint causes GetLimitedValue to be called to get the adjusted Value. +
++ No additional actions are performed in the method when a handle has not been allocated for the control, or at design-time. +
++ When NullValueBehaviour is set to nvbShowTextHint, an invalid numeric value entered in Text causes Text to be set to an empty string. This allows the TextHint for the control to be displayed. +
++ When Value is a valid number, and in the required range, it is converted to its String representation and assigned to the Text for the control. +
++ No actions are performed in the handler when ReadOnly is set to True. +
++ When Direction is updUp, the SpinUpDown method is called using True as an argument. Otherwise, SpinUpDown is called using False as an argument. +
++ Calls the BuddyClick method for the grouped edit control. +
++ DoEnter is an overridden method in TSpinEditExBase, and calls the inherited method on entry. The inherited methods handle the change in control focus, and signal the OnEnter event handler (when assigned). DoEnter ensures that the initial Value for the control is stored internally for use with the NullValueBehaviour used for the control instance. +
++ RealGetText is an overridden TCaption function in TSpinEditExBase used to get the text displayed for the control. RealGetText checks whether a handle has been allocated for the control in the widget set class. When a handle is assigned, the inherited method is called to the Text for the Edit in the grouped edit control. Otherwise, ValueToStr is called to get the string representation for the control Value. +
++ Reset is an overridden method in TSpinEditExBase used to revert changes made to the Value for the control. The IsMasked property is used to determine if an editing mask is in use in the Edit for the grouped edit control. When set to True, the inherited method is called to revert any changes made in Edit. When an editing mask is not in use, the initial value for the control (captured when it received focus) is restored in the Value property. +
++ Reset is used in the implementation of the EditKeyDown event handler assigned to Edit. It is called when the Escape key (VK_Escape) is pressed in the Edit control. +
++ Calls the inherited method and performs no additional actions. +
++ EditKeyDown is an overridden method in TSpinEditExBase which implements the KeyDown event handler for the Edit control. It calls the inherited method which signals the OnEditKeyDown event handler (when assigned). It also ensures that any keys explicitly handled in the grouped edit control are discarded by setting Key to 0 (zero). This includes the following virtual key codes and their associated actions: +
++ EditMouseWheelUp is the handler signalled when a Mouse Wheel Up message occurs in the Edit for the control. EditMouseWheelUp is overridden in TSpinEditExBase, and calls the inherited method. Handled is set to True if the mouse wheel message was handled in the ancestor class. When set to False, the SpinUpDown method is called to increment the value in the control. +
++ EditMouseWheelDown is the handler signalled when a Mouse Wheel Down message occurs in the Edit for the control. EditMouseWheelDown is overridden in TSpinEditExBase, and calls the inherited method. Handled is set to True if the mouse wheel message was handled in the ancestor class. When set to False, the SpinUpDown method is called to decrement the value in the control. +
++ SafeInc is a function used to increase the specified value by the Increment for the control. SafeInc ensures that the incremented value is valid for a given data type. It is an abstract virtual method, and must be implemented in a descendent class to use the specific data type for the specialization. +
++ AValue contains the type with the numeric value to be incremented. +
++ The return value contains the numeric value for the type after the value in Increment has been added. The return value is constrained when the incremented value is too large for the data type. +
++ SafeInc is used in the implementation of the SpinUpDown method. +
++ SafeDec is a function used to decrease the specified value by the Increment for the control. SafeDec ensures that the decremented value is valid for a given data type. It is an abstract virtual method, and must be implemented in a descendent class to use the specific data type for the specialization. +
++ AValue contains the type with the numeric value to be decremented. +
++ The return value contains the numeric value for the type after the value in Increment has been subtracted. The return value is constrained when the incremented value is too large for the data type. +
++ SafeDec is used in the implementation of the SpinUpDown method. +
++ TextIsNumber is an abstract virtual Boolean function which indicates the value specified in S represents a valid number. ANumber is an output parameter where the numeric value for the data type is stored. +
++ TextIsNumber must be implemented in a descendent class using the data type for the specialization. +
++ InitializeWnd is an overridden method used to perform actions needed when the handle is allocated for the control, and before child controls are created. InitializeWnd calls the inherited method on entry. +
++ InitializeWnd calls UpdateControl to validate and update members in the class instance. +
++ Loaded is an overridden method in TSpinEditExBase, and calls the inherited method on entry. Loaded corrects an undesirable behavior in the ancestor class; it sends a CM_PARENTFONTCHANGED message which also alters the color in the grouped edit control. Loaded calls UpdateSpacing prior to restoring the initial color assigned to the edit control. +
++ ArrowKeys is a Boolean property which indicates if cursor keys can be used to navigate content in the Edit for the control. +
++ When set to True, the Up (VK_UP) and Down (VK_Down) arrow keys can be used to increase or decrease the Value for the control. The key events are handled in the EditKeyDown event handler assigned to Edit. When set to False, the Up and Down keys are ignored in Edit. +
++ The default value for the property is True. +
++ Use UpDown to access the TUpDown instance used in the grouped edit control. +
++ Edit a read-only TGEEdit property which contains the editor for the grouped edit control. Edit is used to perform direct input of a new Value for the control. Edit allows use of the Up and Down cursor keys to increment or decrement the value when ArrowKeys is enabled. +
++ UpDown is the TUpDown instance used to increment and decrement the value for the grouped edit control using mouse clicks. +
++ UpDown is a read-only property which contains the TUpDown instance used to increment or decrement the Value for the grouped edit control. Click on the buttons in UpDown to increase or decrease the Value for the control by the amount specified in the Increment property. +
++ Edit is used to perform direct input of the value for the grouped edit control. +
++ UpDownVisible is a Boolean property which indicates if UpDown in the grouped edit control is visible. It is a convenience property; read and write access for the value are redirected to the Visible property in the TUpDown instance in UpDown. The default value for the property is True. +
++ MinRepeatValue contains the repeat interval used for the UpDown control in the grouped edit. The default value for the property is defined in the DefMinRepeatValue constant. +
++ Changing the value for the property causes the MinRepeatInterval property in UpDown to be updated with the new value. +
++ Create is the overridden constructor for the class instance, and calls the inherited constructor on entry. Create sets the default values for properties, including: +
++ Create configures the Edit and UpDown instances used in the grouped edit control. Edit is configured to use right alignment for its text (since it is a numeric value). UpDown is configured to include the flags needed in its ControlStyle property. The OnChangingEx and OnClick event handlers for UpDown are also set in the method. +
++ Internal members needed in the class instance are also initialized. +
++ Create calls SetInitialBounds to set the size for the control to the default values returned from GetControlClassDefaultSize. +
++ GetLimitedValue is used in the implementation of UpdateControl, SpinUpDown, and StrToValue methods. It is also called from the ValueToStr method in TCustomFloatSpinEditEx. +
++ GetLimitedValue ensures that the value for the type specified in AValue is constrained to the range specified in the MinValue and MaxValue properties. AValue is the type with the numeric value examined in the method. +
++ The return value contains the original value after it has been range adjusted. When AValue is smaller than MinValue, MinValue is assigned to the return value. When AValue is larger than MaxValue, MaxValue is assigned to the return value. +
++ ValueToStr is an abstract virtual String function used to convert the value specified in AValue to its representation as a String data type. ValueToStr must be implemented in a descendent class to use the data type and formatting needed for the specialization. +
++ StrToValue is a function which returns a generic type with the numeric value for the specified String. TextIsNumber is used to determine if S contains a valid numeric value. If S is not a valid number, the NullValueBehaviour property is used to determine the return value for the method. +
++ EditEditingDone is an overridden method in TSpinEditExBase. It calls the inherited method on entry to signal the OnEditingDone event handler (when assigned). +
++ EditEditingDone updates the Value for the control from the Text in the Edit. UpdateControl is called to ensure that members in the property are updated and validated after a change to the Value property. +
++ Increment is a property which defines the value added to or subtracted from the control Value when the UpDown control is clicked. It is also used when ArrowKeys are enable in the Edit for the grouped edit control. +
++ Increment uses the generic type for the class instance. There is no default value for the control in TSpinEditExBase, but it may be re-specified in a descendent class specialized for a given data type. +
++ MinValue is a property used to specify the minimum numeric value allowed in the Value property. MinValue uses the type specified for the generic class. Changing the property value causes UpdateControl to be called to range check and update members in the control. +
++ MinValue is used in the implementation of methods such as IsLimited, IsOutOfLimits, SpinUpDown, and GetLimitedValue. It also influences the value stored in the control when a NullValueBehaviour is applied. +
++ Use MaxValue to specify the maximum value allowed in the control. +
++ MaxValue is a property which contains the largest numeric value allowed in the Value property. MaxValue uses the type specified for the generic class. Changing the property value causes UpdateControl to be called to range check and update members in the control. +
++ MaxValue is used in the implementation of methods such as IsLimited, IsOutOfLimits, SpinUpDown, and GetLimitedValue. It also influences the value stored in the control when a NullValueBehaviour is applied. +
++ Use MinValue to specify the smallest value allowed in the control. +
++ NullValue contains the numeric value used when the text for the control does not represent a valid number. NullValue is assigned to Value when the NullValueBehaviour property is set to nvbLimitedNullValue or nvbShowTextHint. +
++ NullValueBehaviour is a TNullValueBehaviour property which contains the logic applied when the text for the control does not represent a valid numeric value. The default value for the property is nvbMinValue, and indicates that the value in MinValue is stored in the Value property when an invalid number is detected. +
++ See TNullValueBehaviour for more information about values in the enumeration and their meanings. +
++ NullValueBehaviour is used in the implementation of the UpdateControl and StrToValue methods. +
++ Value is a property which contains the numeric value for the grouped edit control. Value used the data type specified for the generic class. +
++ Read access to the property value checks for an allocated handle in the control. If the handle has not been allocated, the StrToValue method is called to get the property value. When the handle exists, the value stored in the internal member is used. +
++ Write access to the property value ensures that text assigned directly to Edit contains a valid number for the data type. This is done by calling TextIsNumber. If the new value is the same as the stored property value, no actions are performed. +
++ When the value for the property is changed, the UpdateControl method is called to range check, validate, and update members in the class instance. +
++ Use MinValue and MaxValue to control the minimum and maximum values allowed in the control. Use Increment to control the amount applied to the control value when a button in the UpDown control is clicked. Use NullValue and NullValueBehaviour to control the logic applied with an invalid numeric value is stored in the control. +
+
+ TCustomFloatSpinEditEx defines an extended spin edit control with an editor for the numeric value, and buttons to increment or decrement the control value.It is a TSpinEditExBase descendant which specializes the generic ancestor for the
+ Do not create instances of TCustomFloatSpinEditEx; use the TFloatSpinEditEx descendant which sets the visibility and default values for properties in the class. +
++ EditKeyPress is an overridden method in TCustomFloatSpinEditEx used to ensure that the specified character is valid for the Edit in the control. Key contains the character examined in the method. The allowed values in Key include the following characters: +
++ EditKeyPress calls the inherited method to signal the OnEditKeyPress event handler (when assigned). +
++ Any character which is not allowed in the floating point value is set to #0 to discard the character value. +
++ TextIsNumber is an overridden Boolean function used to determine if the specified string contains a valid representation for the numeric data type in the control. TextIsNumber re-implements the inherited method to use the Double data type, and does not call the method in the ancestor class. +
++ TextIsNumber calls TryStrToFloat using the local format settings for the control to convert the value in S to a floating point value. An exception raised by TryStrToFloat is handled in the method. The converted numeric value is stored in the ANumber argument on success. ANumber should be considered "undefined" when the conversion fails due to an exception. +
++ The return value is True when the value in S can be converted to the Double data type. It is False when an exception was raised and handled in the method. +
++ TextIsNumber is used in the implementation of methods like UpdateControl, SpinUpDown, and StrToValue. It is also called when setting a new value in the Value property. +
++ Set values in the MinValue, MaxValue, NullValue, and NullValueBehaviour properties to control the actions performed when TextIsNumber returns False. +
++ SafeInc is an overridden function in TCustomFloatSpinEditEx used to increase the specified value by the Increment for the control. SafeInc ensures that the incremented value is valid for the Double data type. SafeInc does not call the inherited method. +
++ AValue contains the type with the numeric value to be incremented. +
++ The return value contains the numeric value after the value in Increment has been added. The return value is constrained when the incremented value is too large for the Double data type. The upper limit for the value in the data type is defined in the MaxDouble constant. +
++ SafeInc is used in the implementation of the SpinUpDown method. +
++ SafeDec is used to decrement a specified Double value. +
++ SafeDec is an overridden function in TCustomFloatSpinEditEx used to decrease the specified value by the Increment for the control. SafeDec ensures that the decremented value is valid for the Double data type. SafeDec does not call the inherited method. +
++ AValue contains the type with the numeric value to be decremented. +
++ The return value contains the numeric value after the value in Increment has been subtracted. The return value is constrained when the decremented value is too small for the Double data type. The lower limit for the value in the data type is defined as -1 * MaxDouble. +
++ SafeDec is used in the implementation of the SpinUpDown method. +
++ SafeInc is used to increment a specified Double value. +
++ DisplayMode is a TDisplayMode property which specifies the formatting used to edit and display the Value for the control. The default value for the property is dmFixed, and indicates that fixed precision and decimals are used when formatting the control value. + + See TDisplayMode for more information about the values and meanings in the enumeration. +
++ Changing the value in DisplayMode causes the Value for the control to be updated. It also forces UpdateControl to be called to validate and normalize members in the class instance. +
++ DisplayMode is used in the implementation of the ValueToStr method which generates the string representation for the Value in the control, and is assigned to the Text property in the Edit for the grouped edit control. +
++ ExponentialFormatLimitPos is an Integer property which contains the maximum exponent allowed before a positive Value in the control must be represented using exponential notation. The default value for the property is 6 (six) and indicates that Value must exceed 10^6 before exponential notation is required for a positive number. +
++ Setting a new value for the property causes Value to be updated, and calls the UpdateControl method to validate and normalize members in the class instance. +
++ ExponentialFormatLimitPos is used in the ValueToStr method when DisplayMode contains the value dmAuto and Value has a non-zero floating point value. +
++ Use ExponentialFormatLimitNeg to specify the maximum exponent allowed before using exponential notation for a negative value in the control. +
++ Use Precision to specify the total number of digits used for a number in scientific notation. Use ExponentDigits to specify the number of exponent digits used for a number in scientific notation. +
++ ExponentialFormatLimitNeg is an Integer property which contains the exponent value at which use of scientific notation is triggered for a negative Value in the control. The default value for the property is -6, and indicates that scientific notation is required when Value is smaller than 10^-6. +
++ Changing the value for the property causes GetValue and UpdateControl to be called. +
++ ExponentialFormatLimitNeg is used in the ValueToStr method when DisplayMode is dmAuto and the Value is not 0.0. +
++ Use ExponentialFormatLimitPos to specify the exponent value which triggers use of scientific notation for a positive value. +
++ Use Precision to specify the total number of digits used for a number in scientific notation. Use ExponentDigits to specify the number of exponent digits used for a number in scientific notation. +
++ Precision is an Integer property which specifies the number of digits of precision used after the decimal point for a floating point value in scientific notation. It is the value used as the precision argument for the FloatToStrF routine in RTL. The default value for the property is 6. The maximum precision for the data type is 15. +
++ Changing the value for the property causes the GetValue and UpdateControl methods to be called. +
++ Precision is used in the ValueToStr method when DisplayMode is dmScientific or dmAuto. +
++ ExponentDigits is an Integer property which contains the number of digits used before the decimal point when using scientific notation. The default value for the property is 2. +
++ Changing the value for the property causes the GetValue and UpdateControl methods to be called. +
++ ExponentDigits is used in the ValueToStr method when the DisplayMode is dmScientific or dmAuto. +
++ Use Precision to specify the number of digits after the decimal point in a floating point value using scientific notation. +
++ Create is the overridden constructor for the class instance, and calls the inherited constructor on entry. +
++ Create makes an internal copy of the default format settings for the platform. This allows the value in DecimalSeparator to be specified and stored independent of the value in DefaultFormatSettings. The local copy is modified to used the value in the DefDecimalSeparator constant as the default value for DecimalSeparator. +
++ Create sets the default values for properties, including: +
++ DecimalSeparator is a Char property which contains the character used as the decimal point in a floating point value. Read and write access for the property value are redirected to the local TFormatSetting stored in the class instance. This allows the control to set the decimal separator independent of the format settings for the platform or operating system. +
++ The default value for the property is defined in the DefDecimalSeparator constant. Changing the value for the property updates the local format settings, and calls UpdateControl to validate and update members in the class instance. +
++ DecimalSeparator is used in EditKeyPress to validate characters entered in the Edit for the control. It is also used in ValueToStr to format the value in the control for the selected DisplayMode. +
++ DecimalPlaces is an Integer property which indicates the number of decimal places used when formatting the Value for the control. It must contain a positive integer value or 0 (zero). The default value for the property is defined in the DefDecimals constant. Changing the value for the property causes the Value property to be updated, and calls UpdateControl to validate and update other members in the class instance. +
++ DecimalPlaces is used in ValueToStr to format the value in the control for the selected DisplayMode. +
++ TFloatSpinEditEx is a TCustomFloatSpinEditEx descendant which implements a spin edit control for a value using the Double data type. TFloatSpinEditEx sets the visibility for properties defined in ancestor classes. +
+
+ TFloatSpinEditEx defines an extended spin edit control with an editor for the numeric value, and buttons to increment or decrement the control value. It specializes the generic ancestor for the
+ TCustomSpinEditEx is a specialization of the generic TSpinEditExBase class for the Int64 data type. In addition to implementing the Int64 data type, it provides additional properties and methods used to validate, format, and display the numeric value. +
++ Use the ThousandSeparator to set the UTF-8-encoded value used as the decimal point in the control value. +
++ Set Increment to the value by which the control is increased or decreased when the UpDown button is clicked. +
++ Use ValueToStr to get the string representation for the numeric value. +
++ Do not create instances of TCustomSpinEditEx; use TSpinEditEx, which sets the visibility for properties, instead. +
++ Use TFloatSpinEditEx to edit a floating point value using fixed or scientific notation. +
++ EditKeyPress is an overridden method in TCustomSpinEditEx, and calls the inherited method on entry. The OnEditKeyPress event handler is signalled (when assigned) by the inherited method. +
++ EditKeyPress ensures that the value in Key is valid for the control. An invalid value is discarded by setting Key to the #0 character (Decimal 0). Valid characters include numeric digits ('0'..'9'), the value in ThousandSeparator, and the negative sign indicator ('-'). +
++ Please note: The sign indicator will be disallowed when a positive non-zero value is specified in the MinValue property. +
++ Tab, BackSpace, Cut, Paste, Copy, and Undo key presses are passed to the inherited method. +
++ SafeInc is a function used to increase AValue by the amount specified in the Increment property. SafeInc is overridden in TCustomSpinEditEx to ensure that the incremented value is valid for the Int64 data type. +
++ AValue contains the the numeric value to be incremented. +
++ The return value contains the Int64 value after Increment has been added. The return value is constrained when the incremented value is too large for the Int64 data type; its value is set to High(Int64). +
++ SafeInc is used in the implementation of the SpinUpDown method in the ancestor class. +
++ SafeDec is a function used to decrease the specified value by the amount specified in the Increment property. SafeDec is overridden in TCustomSpinEditEx to ensure that the decremented value is valid for the Int64 data type. +
++ AValue contains the numeric value to be decremented. +
++ The return value contains the Int64 value after Increment has been subtracted. The return value is constrained when the decremented value is too small for the Int64 data type; its value is set to Low(Int64). +
++ SafeDec is used in the implementation of the SpinUpDown method in the ancestor class. +
++ TextIsNumber is an overridden Boolean function which indicates if the value specified in S represents a valid number for the Int64 data type. +
++ ANumber is an output parameter where the numeric value from the conversion from the is stored. +
++ The return value is a Boolean type which contains True when the text in S is successfully converted to an Int64 value and stored i the N argument. If the conversion raises an exception, it is handled in the method and the return value is set to False. The value in N should be considered as "undefined" in this scenario. +
++ ValueToStr is an overridden String function used to convert the value specified in AValue to its representation as a String data type. AValue is an Int64 type. +
++ ValueToStr calls IntToStr to convert the integer value to the String used as the return value for the method. When ThousandSeparator has been assigned, the InsertThousandSeparator routine is called to apply the display formatting to the return value. +
++ ValueToStr is used in the implementation of both the UpdateControl and RealGetText methods in the ancestor class. +
++ Increment is an Int64 property in TCustomSpinEditEx, and represents the amount by which the control value is increased or decreased when the UpDown button is clicked. The default value for the property is 1. +
++ Increment is used in the implementation of the SafeInc and SafeDec methods. +
++ ThousandSeparator is a String property which contains the character used as the thousands separator in the control. It is implemented as a String type to allow use of UTF-8-encoded characters in the property value. When it is unassigned (contains an empty string), the separator is not used to format the string value for the control. +
++ Changing the value in ThousandSeparator causes the UpdateControl method to be called to update the display for the control. +
++ ThousandSeparator is used in methods like EditKeyPress, TextIsNumber, and ValueToStr. +
++ TSpinEditEx is a TCustomSpinEditEx descendant which implements a spin edit control using an Int64 value. TSpinEditEx sets the visibility for properties defined in ancestor classes. +
++ Use the ThousandSeparator to set the UTF-8-encoded value used as the decimal point in the control value. +
++ Set Increment to the value by which the control is increased or decreased when the UpDown button is clicked. +
++ Use ValueToStr to get the string representation for the numeric value. +
++ DbgS is an overloaded String function used to get information displayed in the Debugger. This variant of the routine accepts a TNullValueBehaviour argument, an converts the specified value to its string representation, +
+
+ The
+ This introduction will discuss the problems the design of the controls, and the problems they are intended to eliminate. +
++ Why another SpinEdit or FloatSpinEdit control? +
++ The standard controls, TSpinEdit and TFloatSpinEdit, do not support a NullValue mechanism. Also, their implementations are widgetset dependent. While this provides a control that has the look and feel native to the widgetset, the behavior also depends on the widgetset. This is especially important when the text for the control contains an invalid numeric value (otherwise not a number). In such a case, when querying the control for it's Value, the results are not consistent for the various platforms. The difference in behavior between widgetsets also prevents implementation of the NullValue mechanism, especially the possibility to leave the control empty or to display informative text inside the control about the condition. +
++ TSpinEditEx handles Int64 values, while TSpinEdit is limited to LongInt values. This is because TSpinEdit inherits from TCustomFloatSpinEdit and the internal member for the Value is stored using the Double type, and Double does not have enough significant digits to handle the range for the Int64 type. +
++ In addition, TFloatSpinEditEx can set the value for its DecimalSeparator property independent of the value in the DefaultFormatSettings for the platform or operating system. Note: Unlike T(Float)SpinEdit, the GetValue method is always derived from the actual text in the control. This is by design, and it should not be altered. +
++ Why not simply associate a TUpDown with a TEdit instead? +
++ Using TEdit with a TUpDown control has several disadvantages: +
++ While both TSpinEditEx and TFloatSpinEditEx use a TUpDown control in their implementations, they do not use the Associate property in TUpDown. The two controls (the edit and the up/down button) are embedded in a TCustomControl (much like TEditButton) to provide proper alignment and anchoring behavior. +
+