Paul,
1. Minor Point: When I insert a new FireTextBox control, the font is always "Tahoma 8" and not the default font specified in "Tools->Environment Options->Visual Designer->Fonts->Default font for new control; could be easy to fix I presume.
2. Nice to have: On my PC, I use the comma (,) as the decimal separator; when I use a FireTextBox control with a Numeric mask style, I can't use the decimal point (.) from the numeric keypad as a decimal separator, I've to use the comma (,) on the normal keyboard; in Excel by example, I can use the decimal point from the numeric keypad as a decimal separator and the decimal point is automatically transformed in a coma (,) in the excel sheet; I don't know if it could be possible to implement such a feature with the FireTextBox.
3. Important point to be aware: I started to replace some TextBoxes by FireTextBoxes on some of my project; theses boxes were used to fill in Numeric value.
To extract the value from TextBox, I usually used this code:
Local lValue As Double
lValue = Val(FF_TextBox_GetText(HWND_FORM1_TEXT1))
So at first I used the same code with FireTextBoxe:
Local lValue As Double
lValue = Val(FF_TextBox_GetText(HWND_FORM1_FIRETEXTBOX1))
But the returned value was not exactly the same; here are the results when the user fill the value 12345.67
Quote
lValue with TextBox=12345.67
lValue with FireTextBox=12345
So I understand very quickly that the val() function doesn't evaluate correctly the decimal value due to the comma (,) instead of a decimal point (.); so to make it work I add a replace command in my code:
Local lValue As Double
Local lStringFireTextBox As String
lStringFireTextBox = FF_TextBox_GetText(HWND_FORM1_FIRETEXTBOX1)
Replace "," With "." In lStringFireTextBox
lValue = Val(lStringFireTextBox)Now I get the right value, but then I have a question:
If my program is used on another computer with other option for the decimal point, how can I ensure "portability" of my software on this new PC ?
Here is my question: can you provide some standard function that extract the numeric value from the FireTextBox control that take into account dynamically the
decimal separator and the
group separator used by the computer; I was thinking of functions like :
FF_FireTextBox_GetSingleNumeric()
FF_FireTextBox_GetDoubleNumeric()
FF_FireTextBox_GetExtendedNumeric()
...
Does it make sense ?
Thanks,
Jean-Pierre
Thanks Jean-Pierre, I'll have to think about this a bit more. Regional settings for the various
Quote from: Jean-Pierre Leroy on January 21, 2010, 06:17:54 PM
Paul,
1. Minor Point: When I insert a new FireTextBox control, the font is always "Tahoma 8" and not the default font specified in "Tools->Environment Options->Visual Designer->Fonts->Default font for new control; could be easy to fix I presume.
That setting seems to be working okay for me. I'll check again tomorrow, but when I changed the default control font then all new FireTextBoxes and FireLink's that I created used that new default font.
Quote
2. Nice to have: On my PC, I use the comma (,) as the decimal separator; when I use a FireTextBox control with a Numeric mask style, I can't use the decimal point (.) from the numeric keypad as a decimal separator, I've to use the comma (,) on the normal keyboard; in Excel by example, I can use the decimal point from the numeric keypad as a decimal separator and the decimal point is automatically transformed in a coma (,) in the excel sheet; I don't know if it could be possible to implement such a feature with the FireTextBox.
That's pretty interesting. I assume that Excel itself must do some type remapping or internal conversions of all periods to commas. Very interesting. I could see such a feature being built into the FireTextBox code.
Quote
But the returned value was not exactly the same; here are the results when the user fill the value 12345.67
Quote
lValue with TextBox=12345.67
lValue with FireTextBox=12345
It returns perfectly for me. I mean all you are doing is converting "12345.67". I don't see any commas in the code you are using?
Quote
So I understand very quickly that the val() function doesn't evaluate correctly the decimal value due to the comma (,) instead of a decimal point (.); so to make it work I add a replace command in my code:
Yes, you're right. PB's help for VAL specifically says:
"The string argument should not contain any commas, as VAL terminates processing if a comma is encountered."Quote
If my program is used on another computer with other option for the decimal point, how can I ensure "portability" of my software on this new PC ?
I think that your application would have to test for the Local. Check out the code that I use in the FireTextBox.inc source code for determining the default symbols:
Quote
Function FF_FilterNumeric_GetSymbols( ByVal ed As FIRETEXTBOX_DATA Ptr, _
ByRef sNumbers As String, _
ByRef sPrefix As String, _
ByRef sThousands As String, _
ByRef sDecimal As String, _
ByRef sNegative As String _
) As Long
Local zBuffer As Asciiz * 10
sNumbers = "0123456789"
sNegative = "-"
If @ed.fCurrencyPrefix Then
sPrefix = "$"
If GetLocaleInfo(%LOCALE_USER_DEFAULT, %LOCALE_SCURRENCY, zBuffer, SizeOf(zBuffer)) Then
sPrefix = zBuffer
End If
End If
If @ed.fDecimalPoint Then
sDecimal = "."
If GetLocaleInfo(%LOCALE_USER_DEFAULT, %LOCALE_SMONDECIMALSEP, zBuffer, SizeOf(zBuffer)) Then
sDecimal = zBuffer
End If
End If
If @ed.fGroupSeparator Then
sThousands = ","
If GetLocaleInfo(%LOCALE_USER_DEFAULT, %LOCALE_SMONTHOUSANDSEP, zBuffer, SizeOf(zBuffer)) Then
sThousands = zBuffer
End If
End If
End Function
Quote
Here is my question: can you provide some standard function that extract the numeric value from the FireTextBox control that take into account dynamically the decimal separator and the group separator used by the computer; I was thinking of functions like :
FF_FireTextBox_GetSingleNumeric()
FF_FireTextBox_GetDoubleNumeric()
FF_FireTextBox_GetExtendedNumeric()
Possibly. I guess it could become a part of the basic source code of the FireTextBox.inc itself. I'll see what I can do over the next few days.
I will have to check what the FireTextBox can mean for me. I had the same problem as Jean-Pierre (not typically FF, nor typically PowerBasic) and always checked for the settings of the user:
Function GetDecPointChar$()
Dim cchData As Long
Dim LCType As Long
Dim Locale As Long
Dim lpLCData As Asciiz*51
Dim Tmp As Long
Locale = GetUserDefaultLCID
LCType = %LOCALE_SDECIMAL
lpLCData = Space$(50)
cchData = Len(lpLCData)
Tmp = GetLocaleInfo(Locale, LCType, lpLCData, cchData)
GetDecPointChar$ = Left$(lpLCData, Tmp- 1)
End Function
That retrieved the decimal point character for the user (not PC-dependent but user-dependent) but may be the FireTextBox is better.
I added functions like SafeVal where any comma's were transformed into "." before applying the VAL-statement, similar to your solution.
Wilko
Paul,
I have written 3 functions FF_FireTextBox_GetSingle(), FF_FireTextBox_GetDouble and FF_FireTextBox_GetExtended; these functions can retrieve the numeric value of a FireTextBox control (with a numeric mask style) regardless of the regional settings of the PC (decimal separator and thousands separator).
Perhaps there is a more elegant way to write these functions; at least for the time being it solved my issue.
I would like to warn other FireFly users not to use directly the VAL() function on the result of the FF_TextBox_GetText() in order to evaluate the numeric value of a FireTextBox control (with a numeric mask style) like below :
Local lValue As Double
lValue = Val(FF_TextBox_GetText(HWND_FORM1_FIRETEXTBOX1))
Due to the fact that the FireTextBox control uses the regional settings to display the decimal separator and the thousands separator (which is indeed a good idea) a direct evaluation could lead to different results depending on the regional settings of the PC (decimal separator and thousands separator).
Hope that helps.
Jean-Pierre
Function FF_FireTextBox_GetSingle(ByVal hWndControl As Dword) As Single
' to evaluate the FireTextBox
Local lFireTextBox As String
' to retrieve locale windows settings
Local lBuffer As Asciiz * 10
Local lDecimal As String
Local lThousands As String
' Do a check to ensure that this is actually a window handle
If IsWindow(hWndControl) Then
' retrieve the "Decimal Separator"
If GetLocaleInfo(%LOCALE_USER_DEFAULT, %LOCALE_SMONDECIMALSEP, lBuffer, SizeOf(lBuffer)) Then
lDecimal = lBuffer
End If
' retrieve the "Thousands Separator"
If GetLocaleInfo(%LOCALE_USER_DEFAULT, %LOCALE_SMONTHOUSANDSEP, lBuffer, SizeOf(lBuffer)) Then
lThousands = lBuffer
End If
' retrieve the string value from the FireTextBox control
lFireTextBox = FF_TextBox_GetText(hWndControl)
' replace the "Decimal Separator" by a point (.) if necessary
If lDecimal <> "." Then Replace lDecimal With "." In lFireTextBox
' remove the "Thousands Separator"
lFireTextBox = Remove$(lFireTextBox, lThousands)
' return the numeric value
Function = Val(lFireTextBox)
End If
End Function
Function FF_FireTextBox_GetDouble(ByVal hWndControl As Dword) As Double
' to evaluate the FireTextBox
Local lFireTextBox As String
' to retrieve locale windows settings
Local lBuffer As Asciiz * 10
Local lDecimal As String
Local lThousands As String
' Do a check to ensure that this is actually a window handle
If IsWindow(hWndControl) Then
' retrieve the "Decimal Separator"
If GetLocaleInfo(%LOCALE_USER_DEFAULT, %LOCALE_SMONDECIMALSEP, lBuffer, SizeOf(lBuffer)) Then
lDecimal = lBuffer
End If
' retrieve the "Thousands Separator"
If GetLocaleInfo(%LOCALE_USER_DEFAULT, %LOCALE_SMONTHOUSANDSEP, lBuffer, SizeOf(lBuffer)) Then
lThousands = lBuffer
End If
' retrieve the string value from the FireTextBox control
lFireTextBox = FF_TextBox_GetText(hWndControl)
' replace the "Decimal Separator" by a point (.) if necessary
If lDecimal <> "." Then Replace lDecimal With "." In lFireTextBox
' remove the "Thousands Separator"
lFireTextBox = Remove$(lFireTextBox, lThousands)
' return the numeric value
Function = Val(lFireTextBox)
End If
End Function
Function FF_FireTextBox_GetExtended(ByVal hWndControl As Dword) As Extended
' to evaluate the FireTextBox
Local lFireTextBox As String
' to retrieve locale windows settings
Local lBuffer As Asciiz * 10
Local lDecimal As String
Local lThousands As String
' Do a check to ensure that this is actually a window handle
If IsWindow(hWndControl) Then
' retrieve the "Decimal Separator"
If GetLocaleInfo(%LOCALE_USER_DEFAULT, %LOCALE_SMONDECIMALSEP, lBuffer, SizeOf(lBuffer)) Then
lDecimal = lBuffer
End If
' retrieve the "Thousands Separator"
If GetLocaleInfo(%LOCALE_USER_DEFAULT, %LOCALE_SMONTHOUSANDSEP, lBuffer, SizeOf(lBuffer)) Then
lThousands = lBuffer
End If
' retrieve the string value from the FireTextBox control
lFireTextBox = FF_TextBox_GetText(hWndControl)
' replace the "Decimal Separator" by a point (.) if necessary
If lDecimal <> "." Then Replace lDecimal With "." In lFireTextBox
' remove the "Thousands Separator"
lFireTextBox = Remove$(lFireTextBox, lThousands)
' return the numeric value
Function = Val(lFireTextBox)
End If
End Function
Thanks Jean-Pierre,
That is certainly a big help and has saved me a bit of work ;)
I am curious as to why 3 separate functions are necessary. Why not just use one function to return the value as a Double and allow PB to automatically cast the value to fit the variable it is being assigned to?
Local myValue As Currency
myValue = FF_FireTextBox_GetDouble( HWND_FORM1_FIRETEXTBOX1 )
I would think that Double would have more than digit holders that someone entering or displaying the value in the textbox would never exceed it.
Paul,
You're right it is useless to have 3 separate functions; so my suggestions are:
1. To use one function called FF_FireTextBox_GetNumeric() in order to mimic the "Mask style" mentioned in the FireTextBox control.
2. To return the value as Extended as it seems that extended-precision are the basis of computation in PowerBASIC; from the doc:
QuoteExtended-precision numbers are the basis of computation in PowerBASIC. The type-specifier character for an Extended-precision floating-point is: ##. In PowerBASIC, all floating point calculations are performed in extended precision for maximum accuracy. Extended-precision has also been provided as a declarable variable type, so you can take advantage of its extra exponent range and precision.
Here is the latest version of the proposed FF_FireTextBox_GetNumeric() function:
Function FF_FireTextBox_GetNumeric(ByVal hWndControl As Dword) As Extended
' to evaluate the FireTextBox
Local lFireTextBox As String
' to retrieve locale windows settings
Local lBuffer As Asciiz * 10
Local lDecimal As String
Local lThousands As String
' Do a check to ensure that this is actually a window handle
If IsWindow(hWndControl) Then
' retrieve the "Decimal Separator"
If GetLocaleInfo(%LOCALE_USER_DEFAULT, %LOCALE_SMONDECIMALSEP, lBuffer, SizeOf(lBuffer)) Then
lDecimal = lBuffer
End If
' retrieve the "Thousands Separator"
If GetLocaleInfo(%LOCALE_USER_DEFAULT, %LOCALE_SMONTHOUSANDSEP, lBuffer, SizeOf(lBuffer)) Then
lThousands = lBuffer
End If
' retrieve the string value from the FireTextBox control
lFireTextBox = FF_TextBox_GetText(hWndControl)
' replace the "Decimal Separator" by a point (.) if necessary
If lDecimal <> "." Then Replace lDecimal With "." In lFireTextBox
' remove the "Thousands Separator"
lFireTextBox = Remove$(lFireTextBox, lThousands)
' return the numeric value
Function = Val(lFireTextBox)
End If
End Function
Tell me if it makes sense,
Regards,
Jean-Pierre
Thanks Jean-Pierre, I have added your function to the standard list of FF Functions that ship with FF3.
Paul,
Thank you for added the function FF_FireTextBox_GetNumeric() to the standard list of FF Functions that ship with FF3.
Today I had a similar issue when I tried to refresh back a FireTextBox control with the result of a computation; if I update directly the FireTextBox control with the function FF_TextBox_SetText the decimal separator is not displayed.
So I created a new sub that I called FF_FireTextBox_SetNumeric() to set a numeric value in a FireTextBox control.
Here is the source code of the proposed FF_FireTextBox_SetNumeric() function:
Sub FF_FireTextBox_SetNumeric(ByVal hWndControl As Dword, ByVal pNumeric As Extended)
' the string that will contain the numeric value
Local lFireTextBox As String
' to retrieve locale windows settings
Local lBuffer As Asciiz * 10
Local lDecimal As String
' Do a check to ensure that this is actually a window handle
If IsWindow(hWndControl) Then
' retrieve the "Decimal Separator"
If GetLocaleInfo(%LOCALE_USER_DEFAULT, %LOCALE_SMONDECIMALSEP, lBuffer, SizeOf(lBuffer)) Then
lDecimal = lBuffer
End If
' convert the numeric value in string
lFireTextBox = LTrim$(Str$(pNumeric))
' replace the "." by the "Decimal Separator" if necessary
If lDecimal <> "." Then Replace "." With lDecimal In lFireTextBox
' set the numeric value in the FireTextBox control
FF_TextBox_SetText(hWndControl, lFireTextBox)
End If
End Sub
Everything works fine except a small issue; when I update the FireTextBox control the number of decimal places is not respected; on the enclosed example we can see 3 decimal places even if the control is defined with 2 decimal places.
Regards,
Jean-Pierre
This is corrected now. The control would not format the number when it was initially set in the control. It would only format the trailing zeros when the focus left the control (ie. on WM_KILLFOCUS).