View Issue Details
ID | Project | Category | View Status | Date Submitted | Last Update |
---|---|---|---|---|---|
0005060 | JEDI VCL | 00 JVCL Components | public | 2009-12-21 17:30 | 2012-09-10 14:15 |
Reporter | SteffenSchm | Assigned To | obones | ||
Priority | normal | Severity | major | Reproducibility | always |
Status | resolved | Resolution | fixed | ||
Product Version | 3.39 | ||||
Target Version | Fixed in Version | 3.46 | |||
Summary | 0005060: Wrong Display and Return of Float Values by TJvValidateEdit | ||||
Description | TJvValidateEdit converts Float to String by using the normal Delphi function StrToFloat. This function uses ThousandSeparator and DecimalSeparator loaded from SysUtils by calling: GetLocalChar(GetThreadLocale,....) To convert from String to Float TJvValidateEdit calls JvSafeStrToFloat from the JVCL unit JvJCLUtils. This function loads own Chars for ThousandSeparator and DecimalSeparator by calling: GetLocalChar(LOCALE_SYSTEM_DEFAULT,....) Not for all but for some of our computers the ThousandSeparator and DecimalSeparator used for Float to String conversion are different from these used for String to Float conversion. This causes a lot of trouble and makes the component unusable. | ||||
Additional Information | I changed the function JvSafeStrToFloat to use the ThousandSeparator and DecimalSeparator from SysUtils. This solves my problem. | ||||
Tags | No tags attached. | ||||
related to | 0005385 | resolved | obones | TJvValidateEdit has a bug in DecimalSeparator handling. |
has duplicate | 0005774 | resolved | obones | Values by TJvValidateEdit multiplied by 10^NumberOfDecimals |
related to | 0005579 | resolved | obones | TJvValidateEdit: Issues with DisplayFormat of dfFloat with DecimalPlaces on x64 PT |
|
Do you happen to change the value of ThousandSeparator and DecimalSeparator while the program is running? |
|
No I did not change any of these values while the program is running |
|
Could you please provide the zipped sources of a sample application showing this? |
2010-07-26 18:08
|
JvValidateEdit Bug.zip (8,768 bytes) |
|
I can confirm the bug. My PC is a Windows 7 English (U.S.) installation, so GetLocalChar(LOCALE_SYSTEM_DEFAULT,....) returns English (U.S.) settings. I set my per-user locale to Portuguese (Brazil) while testing an internationalization problem for one of our customers, so the LOCALE_USER_DEFAULT and GetThreadLocale return Portuguese (Brazil) settings. (In response to your earlier question, this change was NOT made while the program was running.) The result is that, as SteffenSchm reported, TJvValidateEdit sometimes tries to use commas and sometimes tries to use decimals. In my sample project, if I assign a value of 500 to JvValidateEdit1->Value, it's formatted as 500,0000, then the comma is discarded because it doesn't match LOCALE_SYSTEM_DEFAULT, so JvValidateEdit1->Value ends up being 5000000,0000. |
2010-08-20 16:05
|
Project2.zip (5,152 bytes) |
2010-08-20 16:05
|
|
2010-08-20 16:06
|
|
|
Please find enclosed the source code of a asmple application. But the error can not be reproduced at any computer. At one of my two laptops GetLocalChars returns different results depending on which parameters is used (LOCALE_SYSTEM_DEFAULT, GetThreadLocale or GetSystemDefaultLCID. This is shown on Pic1.jpg. By pressung the Button1 in the sample application the values in all JvValidateEdits are read and rewritten by the following code: JvValidateEdit1.Value:=JvValidateEdit1.Value; This results in wrong values shown in Pic2.jpg. This is exactly the reaction described also by jkelley. I solved the problem for my project by changing the following lines in the function _JvSafeStrToFloat of the unit JvJCLUtils FormatSettings.ThousandSeparator := GetLocaleChar(LOCALE_SYSTEM_DEFAULT, LOCALE_STHOUSAND, '.'); FormatSettings.DecimalSeparator := GetLocaleChar(LOCALE_SYSTEM_DEFAULT, LOCALE_SDECIMAL, '.'); by the following: FormatSettings.ThousandSeparator:= ThousandSeparator; FormatSettings.DecimalSeparator := DecimalSeparator; This can also be used to fix the problem generally. |
|
Changing this has other consequences on codes that use JvSafeStrToFloat. Wouldn't it be cleaner to have always the same function be called, and preferably the JVCL one? If yes, could you propose the changes here? |
|
Any news? |
|
As I mentioned on 0005579, I didn't touch on _JvSafeStrToFloat. Instead, just passing the third argument of JvSafeStrToFloatDef as {$IFDEF RTL220_UP}FormatSettings.{$ENDIF RTL220_UP}DecimalSeparator did solve it. That seems the most correct usage of that function. |
|
JvJCLUtils.pas, line 7013: {$IFDEF RTL150_UP} FormatSettings.ThousandSeparator := GetLocaleChar(LOCALE_SYSTEM_DEFAULT, LOCALE_STHOUSAND, '.'); FormatSettings.DecimalSeparator := GetLocaleChar(LOCALE_SYSTEM_DEFAULT, LOCALE_SDECIMAL, '.'); {$ELSE} FormatSettings.DecimalSeparator := DecimalSeparator; {$ENDIF RTL150_UP} The above code will load the default decimal and thousand separators for the current system. If the user changed these settings the conversion will fail. This prevents JvValidateEdit from working correctly. Proposed fix: replace "LOCALE_SYSTEM_DEFAULT" with "GetThreadLocale" to load the currently used decimal and thousand separators. I tested a number of scenarios and everything worked fine. |
|
Have you seen this: http://stackoverflow.com/questions/1767946/getthreadlocale-returns-different-value-than-getuserdefaultlcid Seems like GetThreadLocale is not such a good idea after all |
|
We are able to reproduce the Problem on Windows Vista Business 32 and Windows 7 Business 64. The screenshots below show the dialogs used to change these settings. Steps: - Change your format settings to "German (Germany)" http://1.bp.blogspot.com/-05cWKX7SVUE/Ti7hPCJfI7I/AAAAAAAAAEg/gBcS-u7l3eQ/s1600/Changing+Time+Format+Windows+7.png - Change your system locale to "English (USA)" (http://www.sisulizer.de/_img/codepage-problems/w7-region-and-language-administrative.jpg) Your DecimalSeparator will now be "," according to Windows. Entering floating point numbers in TJvValidateEdit will now fail. E.g entering "1,23" will be converted into "123,00". Notice how you can enter "," bot not ".". The underlying problem seems to be that JvValidateEdit uses different methods of obtaining DecimalSeparator. (1) TJvCustomValidateEdit.IsValidChar in JvValidateEdit.pas uses "{$IFDEF RTL220_UP}FormatSettings.{$ENDIF RTL220_UP}DecimalSeparator". (2) Several other methods in this unit use JvSafeStrToFloatDef from JvJCLUtils.pas which calls _JvSafeStrToFloat in JvJCLUtils.pas. Ultimately "GetLocaleChar(LOCALE_USER_DEFAULT, LOCALE_SDECIMAL, '.')" is called. (1) always returned the correct value in our tests. In the above scenario "," is returned which corresponds the chosen format setting "German (Germany)". (2) seems to return values corresponding to chosen system locale. In the above scenario this is "." for "English (USA)". Obviously both can't be right at the same time. Windows seems to give precedence to format settings which are per user settings. (2) can be changed to return these user settings rather than the system settings. Proposed fix: replace "LOCALE_SYSTEM_DEFAULT" with "LOCALE_USER_DEFAULT" in JvJCLUtils.pas (lines 7014 and 7015). This also avoids using "GetThreadLocale" which seems to have problems of its own. |
|
Sorry, the parenthesis broke the second link. Here is a working link: http://www.sisulizer.de/_img/codepage-problems/w7-region-and-language-administrative.jpg |
|
Fair enough, thanks for the pointers |
|
Please change in JvJCLUtils the function _JvSafeStrToFloat() the next lines ----------------------------------------------------------------------- { Locale Handling logic October 2008 supercedes former StrToFloatUS functionality. } {$IFDEF RTL150_UP} LocalFormatSettings.ThousandSeparator := GetLocaleChar(LOCALE_SYSTEM_DEFAULT, LOCALE_STHOUSAND, '.'); LocalFormatSettings.DecimalSeparator := GetLocaleChar(LOCALE_SYSTEM_DEFAULT, LOCALE_SDECIMAL, '.'); {$ELSE} ----------------------------------------------------------------------- to these lines: ----------------------------------------------------------------------- { Locale Handling logic October 2008 supercedes former StrToFloatUS functionality. } {$IFDEF RTL150_UP} LocalFormatSettings.ThousandSeparator := GetLocaleChar(LOCALE_USER_DEFAULT, LOCALE_STHOUSAND, '.'); LocalFormatSettings.DecimalSeparator := GetLocaleChar(LOCALE_USER_DEFAULT, LOCALE_SDECIMAL, '.'); {$ELSE} ----------------------------------------------------------------------- This fucking bug caused us a headache and lot of time, because in our application the values were multiplied by 10^x (where x = number of decimals) everywhere the TJvValidateEdit is used. You can image which dramatic effects this has :( Mainly on Terminal Systems we see this, because the DecimalSeparator in LOCALE_SYSTEM_DEFAULT is totally different from the LOCALE_USER_DEFAULT one. |
|
Arno, I've come with a different fix that didn't touched JvJCLUtils, just check case 0005579. |
|
@cguser, I see your fix more as a workaround, i think the JvSafeStrToFloat() should behave correctly for the users regional settings. Probably this function is also used by other components/functions and will fail therefor also. |
|
Arno, Likely so. I do not have the details fresh on my memory anymore, so I won't comment on the technical details. It does puzzle me, however, that for such a serious (and visible) issue, no clean solution has been applied after this long. I still need to mind to manually patch this each and every time Jedi components are updated. Every now and then, some coleague gets bitten by this. |
|
I see indeed this issue is hurting many people already since 2009/2010. We upgraded recently to latest version, because we slowly start migrating everything to Delphi XE2. While we were using a very old version we were not bitten by it earlier. HOW CAN IT BE THIS BUG IS STILL ALIVE?? Please, somebody with commit rights fix this. |
|
I started this topic in 2009 and solved the problem for my application by the fix descriped 2010-08-10. I am not a advanced programmer and do not understand in common why the jvl needs to read the chars for Decimal and ThousandSeparator again. Why not using the constants already defined by Delphi? |
|
This is now fixed in SVN |
Date Modified | Username | Field | Change |
---|---|---|---|
2009-12-21 17:30 | SteffenSchm | New Issue | |
2009-12-28 16:42 | obones | Note Added: 0017033 | |
2009-12-28 16:42 | obones | Status | new => feedback |
2009-12-29 12:58 | SteffenSchm | Note Added: 0017044 | |
2010-06-07 13:54 | obones | Note Added: 0017460 | |
2010-07-26 18:08 | jkelley | File Added: JvValidateEdit Bug.zip | |
2010-07-26 18:12 | jkelley | Note Added: 0017542 | |
2010-08-20 16:05 | SteffenSchm | File Added: Project2.zip | |
2010-08-20 16:05 | SteffenSchm | File Added: Pic1.JPG | |
2010-08-20 16:06 | SteffenSchm | File Added: Pic2.JPG | |
2010-08-20 16:18 | SteffenSchm | Note Added: 0017612 | |
2010-10-08 16:23 | obones | Note Added: 0017820 | |
2011-06-07 17:25 | obones | Note Added: 0018568 | |
2011-06-07 18:01 | obones | Relationship added | related to 0005579 |
2011-06-07 18:01 | obones | Relationship added | related to 0005385 |
2011-06-07 18:13 | cguser | Note Added: 0018642 | |
2011-09-16 14:44 | ThomasC | Note Added: 0018894 | |
2011-09-21 14:46 | obones | Note Added: 0018960 | |
2011-09-21 16:35 | ThomasC | Note Added: 0018965 | |
2011-09-21 16:39 | ThomasC | Note Added: 0018967 | |
2011-09-22 11:34 | obones | Note Added: 0018971 | |
2011-09-22 11:34 | obones | Status | feedback => acknowledged |
2012-01-19 16:07 | ArnoBrinkman | Note Added: 0019319 | |
2012-01-19 16:32 | cguser | Note Added: 0019320 | |
2012-01-19 17:29 | ArnoBrinkman | Note Added: 0019321 | |
2012-01-19 17:43 | cguser | Note Added: 0019322 | |
2012-01-19 18:26 | ArnoBrinkman | Note Added: 0019323 | |
2012-01-19 18:35 | SteffenSchm | Note Added: 0019324 | |
2012-02-24 11:56 | obones | Note Added: 0019528 | |
2012-02-24 11:56 | obones | Status | acknowledged => resolved |
2012-02-24 11:56 | obones | Fixed in Version | => Daily / SVN |
2012-02-24 11:56 | obones | Resolution | open => fixed |
2012-02-24 11:56 | obones | Assigned To | => obones |
2012-02-24 17:37 | obones | Relationship added | related to 0005774 |
2012-02-24 17:37 | obones | Relationship replaced | has duplicate 0005774 |
2012-09-10 14:15 | obones | Fixed in Version | Daily / SVN => 3.46 |