65.9K
CodeProject is changing. Read more.
Home

Stream like operations for the registry

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.11/5 (3 votes)

Jan 25, 2001

viewsIcon

36949

downloadIcon

823

Use the operators >> and to extract/insert registry entries.

  • Download source files - 8 Kb
  • Download demo project - 11 Kb
  • Introduction

    cout <<  "Birthday: " << dt << "; Height: " <<  d; 
    

    is better than the equivalent printf statement. It is easier to remember than the printf format specifiers, less error prone and the operators << and >> can be used for different streams ( cout,files,CArchive). This article presents stream operations for the registry. The above example would be written to the registry by:

    regStream << RegVal("Birthday",dt) << RegVal("Height",d);
    

    All arithmetic data types and the MFC value types CPoint, CSize, CRect, CSize, COleDateTime and CFont are supported. This article merely presents a new interface to an already existing CRegistry class by Robert Pittenger, which can be found on this site.

    Two stream variants are supported. CRegStream<CRegBaseHumanReadable> stores all registry entries as human readable strings. The second stream variant supported is CRegStream<CRegBaseGeneral>. It uses all the registry datatypes that are also used by Robert Pittenger's class. The first interface is mainly intended for the application settings in which users of your software prefer readable registry entries over encoded ones.

    Interface

    Registry entries are Name/Value pairs. Each operand of an inserter or extractor >> must be a Name/Value pair. The function RegVar(LPCTSTR lpszEntry,T& t,const T& defaultVal= T()) returns a Name/Value pair as an operand of >>, whereas RegVal(LPCTSTR lpszEntry,const T& t) returns a Name/Value pair which is suitable for the operand . The macros RVAR and RVAL allow you to leave out the lpszEntry parameter. This is because the Name is constructed from the C++ variable name supplied to the macro.

    /* functions which construct Name/Value pairs for the  and >> operators */
    template<class T>
    RegVariable<T> RegVar(LPCTSTR lpszEntry,T& t,const T& defaultVal= T())
    {   return RegVariable<T>(lpszEntry,t,defaultVal);}
    
    template<class T>
    RegValue<T> RegVal(LPCTSTR lpszEntry,const T& t)
    {   return RegValue<T>(lpszEntry,t); }
    
    /* Macros, which construct an lpszEntry from the C++ variable name */
    #define RVAL(v)         RegVal(RegTrim(#v),v)
    #define RVAR(v)         RegVar(RegTrim(#v),v)
    #define RVAR1(v)        RegVar(RegTrim(#v),v,defaultVal)
    
    template<class CRegBase>
    class CRegStream   : public CRegBase
    {
    public:
    	CRegStream(HKEY hKey=0):m_bSuccess(true)
    	{ if( hKey!=0 ){ SetRootKey(hKey);}}
    
    	bool    Success() //indicates whether last operation was successful
    	{   return m_bSuccess;}
    
    	//  and >> operator functions 
    	//....
    };
    class CRegBaseGeneral : public CRegistry
    {	
    	// directly interfacing to Robert Pittenger's <code>CRegistry class.
    	// ...
    };
    class CRegBaseHumanReadable : public CRegistry
    {
    	// this class writes human readable strings into the registry. e.g. "{3,5}" for a point.
    	// ....
    };
    

    Example Usage

    In the following example, human readable register entries are written to the HKEY_CURRENT_USER registry part and encoded register entries are written to the HKEY_LOCAL_MACHINE registry part. Afterwards the entries are read from both parts and checked for equality.

    int main(int argc,TCHAR* argv[])
    {
        float           fFloatEps= FLT_EPSILON;             CString strTitle=  "Sir";
        COleDateTime    dtBirthday(1970,10,10,10,15,30);    CPoint pt;
        BOOL bOk;
        CRegStream<CRegBaseHumanReadable> reg_user(HKEY_CURRENT_USER);
        if( bOk=reg_user.SetKey("Software\\RegStreamDemo\\Settings",TRUE) ){
            reg_user    << RVAL(fFloatEps)  <<  RVAL(strTitle)  <<  RVAL(dtBirthday) 
                        << RegVal(_T("$-Point"),CPoint(3,5));
        }
        CRegStream<CRegBaseGeneral> reg_machine(HKEY_LOCAL_MACHINE);
        if( bOk&& (bOk=reg_machine.SetKey("Software\\RegStreamDemo\\Settings",TRUE)) ){
            reg_machine <<  RVAL(fFloatEps) <<  RVAL(strTitle)  <<  RVAL(dtBirthday)
                        <<  RegVal(_T("$-Point"),CPoint(3,5));
        }
        if( bOk ){
            reg_user    >>  RVAR(fFloatEps) >>  RVAR(strTitle)  >> RVAR(dtBirthday)
                        >>  RegVar(_T("$-Point"),pt);
            float floatEps1; CString strTitle1; CPoint pt1;
            reg_machine >>  RegVar(_T("FloatEps"),floatEps1)    >>  RegVar(_T("Title"),strTitle1)
                        >>  RegVar(_T("$-Point"),pt1);
            ASSERT(fFloatEps==floatEps1 && strTitle==strTitle1 && pt==pt1);
        }
    }
    

    Implementation Details

    The implementation resides entirely in the header file "RegStream.h". It consists of template types and functions. It's the first time that I used member template functions. They helped a lot in reducing the coding task. The resulting code is remarkably uniform, easy to understand and read.