Click here to Skip to main content
15,895,799 members
Articles / Programming Languages / C++

Windows SetThreadLocale and CRT setlocale

Rate me:
Please Sign up or sign in to vote.
4.85/5 (12 votes)
15 Feb 2005Public Domain4 min read 108.5K   2.4K   39  
Keeps CRT locale status in synch with Windows thread locale.
#pragma once

#include <comdef.h>
#include <locale.h>

/* This class saves the current CRT locale state and restores it when the object
   goes out of scope.

   This class was kept separate from CTempLocale because it may be useful on
   it's own.
*/
class CCrtLocaleSwitch {
public:
	//Constructor.  Optionally switches to a new LCID.
	CCrtLocaleSwitch(LCID lcNew=0);
	//Desstructor.  Restores original locale settings.
	virtual ~CCrtLocaleSwitch(){
		restore();
	}
	//Loads a _bstr_t with a string compatible with CRT setlocale function.
	static LPCTSTR loadLocaleId(LCID lcid, _bstr_t& bstrRetBuf);
	//Set the locale for the CRT using a Windows LCID.
	static bool setLocale(LCID lcNew);
	//Restores the locale set at the time the class instantiated.
	bool restore(){
		return setlocale(LC_ALL, _strLocale) ? true : false;
	}

protected:
	_bstr_t		_strLocale;
};

/*	This class saves the current thread's LCID and CRT state, then restores
	it when it goes out of scope.
*/
class CTempLocale {
public:
	CTempLocale(LCID lcid=0) : _crt(0)
	{
		_lcOrig = GetThreadLocale();
		if( lcid != _lcOrig ){
			SetThreadLocale(lcid);
			_crt.setLocale(lcid);
		}
	}

	//Restores the LCID before instantiation
	virtual ~CTempLocale(){
		restore();
	}

	//Set the thread's locale and CRT state back to what it was
	void restore(){
		if( _lcOrig != GetThreadLocale() )
			SetThreadLocale(_lcOrig);
		_crt.restore();
	}

	//Changes the locale.  Does not affect the LCID set by restore().
	void setLocale(LCID lcid){
		if( lcid == GetThreadLocale() )
			return;

		restore();
		SetThreadLocale(lcid);
		_crt.setLocale(lcid);
	}
	//Writes a double to a string in the current locale with nPrec decimal
	//places.  Stores an LCID identifier at the end of the string.
	LPCTSTR packDouble(double dbl, int nPrec, _bstr_t& bstrBufRes);
	//Reads a double based on LCID information at the end of string, if present.
	bool readDouble(LPCTSTR lpszText, double& dblRes);
	//Reads a double and returns a default upon failure.
	double readDoubleDef(LPCTSTR lpszText, double defVal){
		double dRes;
		if( readDouble(lpszText, dRes) )
			return dRes;
		return defVal;
	}
	LPCTSTR packLong(LONG lVal, _bstr_t& bstrBufRes);
	bool readLong(LPCTSTR lpszText, LONG& lRes);
	LONG readLongDef(LPCTSTR lpszText, LONG lDef){
		LONG lRes;
		if( readLong(lpszText, lRes) )
			return lRes;
		return lDef;
	}
	//Trims LCID information from the end of a packed long or double string.
	static LPCTSTR trimLcid(LPCTSTR lpszNum, _bstr_t& bstrRetBuf);

	//Utilities

	//Gets the LCID's language name in English
	static bool getLangName(LCID lcid, OUT _bstr_t& bstrLanguage);
	//Gets the LCID's two letter language identifier
	static bool getShortLangName(LCID lcid, OUT _bstr_t& bstrLanguage);
	//Gets the LCID's region name in English
	static bool getRegionName(LCID lcid, OUT _bstr_t& bstrLanguage);
	//Gets the LCID's two letter region identifier
	static bool getShortRegionName(LCID lcid, OUT _bstr_t& bstrLanguage);

protected:
	LCID	_lcOrig;
	CCrtLocaleSwitch	_crt;
};

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under A Public Domain dedication


Written By
Software Developer (Senior) CDK Global, LLC
United States United States
Director of Software Engineering for a startup software/hardware solution provider based in Silicon Valley. Currently in search of a new position with another company.

Comments and Discussions