Currency and Number Formats

Just as date and time formats vary from locale to locale, so do currency and number formats. As the following list of LCTYPEs associated with currency and numbers indicates, reformatting a number based on a different locale involves more than changing the currency symbol or the decimal separator.

LOCALE_ICURRDIGITS LOCALE_IPOSSYMPRECEDES
LOCALE_ICURRENCY LOCALE_SCURRENCY
LOCALE_IDIGITS LOCALE_SDECIMAL
LOCALE_IINTLCURRDIGITS LOCALE_SGROUPING
LOCALE_ILZERO LOCALE_SINTLSYMBOL
LOCALE_IMEASURE LOCALE_SLIST
LOCALE_INEGCURR LOCALE_SMONDECIMALSEP
LOCALE_INEGNUMBER LOCALE_SMONGROUPING
LOCALE_INEGSEPBYSPACE LOCALE_SMONTHOUSANDSEP
LOCALE_INEGSIGNPOSN LOCALE_SNATIVEDIGITS
LOCALE_INEGSYMPRECEDES LOCALE_SNEGATIVESIGN
LOCALE_IPOSSEPBYSPACE LOCALE_SPOSITIVESIGN
LOCALE_IPOSSIGNPOSN LOCALE_STHOUSAND


A currency symbol might come before or after the numeric quantity, it might be separated from the number by spaces, and it might be composed of one character or more than one character. In addition, if a currency amount is negative, the system might format it in one of 16 different ways. The predefined structures for numbers and currencies are as follows:

struct tagNUMBERFMT {
UINT NumDigits; // number of decimal places
// (LOCALE_IDIGITS)
UINT LeadingZero; // whether to use leading zeros for
// decimal fields (LOCALE_ILZERO)
UINT Grouping; // size of each group of digits to
// the left of the decimal (0 - 9)
LPTSTR lpDecimalSep; // pointer to a buffer containing
// the decimal separator string
LPTSTR lpThousandSep; // pointer to a buffer containing
// the thousand separator string
UINT NegativeOrder; // negative number mode
// (LOCALE_INEGNUMBER)
} NUMBERFMT, *LPNUMBERFMT;

struct tagCURRENCYFMT {
UINT NumDigits; // number of decimal places
// (LOCALE_ICURRDIGITS)
UINT LeadingZero; // whether to use leading zeros in
// decimal fields (LOCALE_ILZERO)
UINT Grouping; // size of each group of digits to the
// left of the decimal (0 - 9)
LPTSTR lpDecimalSep; // pointer to a buffer containing the
// decimal separator string
LPTSTR lpThousandSep; // pointer to a buffer containing the
// thousand separator string
UINT NegativeOrder; // negative currency mode
// (LOCALE_INEGCURR)
UINT PositiveOrder; // positive currency mode
// (LOCALE_ICURRENCY)
LPTSTR lpCurrencySymbol; // pointer to a buffer containing the
// currency symbol string
} CURRENCYFMT, *LPCURRENCYFMT;

You can create a customized number format or currency format by filling in a NUMBERFMT or CURRENCYFMT structure and passing it to the appropriate API function—GetNumberFormat or GetCurrencyFormat. If you pass in a null pointer as the lpFormat parameter, the system will format the number or currency according to the rules of the specified locale. As with dates and times, you can retrieve specific formatting information for any locale by calling GetLocaleInfo.

int size = GetLocaleInfo(lcid, LOCALE_SCURRENCY, NULL, 0);
HLOCAL hlocal = LocalAlloc(LPTR, size);
PVOID lpBuf = LocalLock(hlocal);
int rc = GetLocaleInfo(lcid, LOCALE_SCURRENCY, lpBuf, size);