Stream like operations for the registry






4.11/5 (3 votes)
Jan 25, 2001

36949

823
Use the operators >> and to extract/insert registry entries.
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.