1 // TortoiseSVN - a Windows shell extension for easy version control
3 // Copyright (C) 2003-2011 - TortoiseSVN
5 // This program is free software; you can redistribute it and/or
6 // modify it under the terms of the GNU General Public License
7 // as published by the Free Software Foundation; either version 2
8 // of the License, or (at your option) any later version.
10 // This program is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 // GNU General Public License for more details.
15 // You should have received a copy of the GNU General Public License
16 // along with this program; if not, write to the Free Software Foundation,
17 // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
24 #include "auto_buffer.h"
25 #include "FormatMessageWrapper.h"
33 * Base class for the registry classes.
36 * - win98 or later, win2k or later, win95 with IE4 or later, winNT4 with IE4 or later
37 * - import library Shlwapi.lib
46 * String type specific operations.
49 virtual LPCTSTR
GetPlainString (const S
& s
) const = 0;
50 virtual DWORD
GetLength (const S
& s
) const = 0;
54 /** Default constructor.
59 * \param key the path to the key, including the key. example: "Software\\Company\\SubKey\\MyValue"
60 * \param force set to TRUE if no cache should be used, i.e. always read and write directly from/to registry
61 * \param base a predefined base key like HKEY_LOCAL_MACHINE. see the SDK documentation for more information.
63 CRegBaseCommon(const S
& key
, bool force
, HKEY base
= HKEY_CURRENT_USER
, REGSAM sam
= 0);
66 * Removes the whole registry key including all values. So if you set the registry
67 * entry to be HKCU\Software\Company\Product\key\value there will only be
68 * HKCU\Software\Company\Product key in the registry.
69 * \return ERROR_SUCCESS or an nonzero error code. Use FormatMessage() to get an error description.
73 * Removes the value of the registry object. If you set the registry entry to
74 * be HKCU\Software\Company\Product\key\value there will only be
75 * HKCU\Software\Company\Product\key\ in the registry.
76 * \return ERROR_SUCCESS or an nonzero error code. Use FormatMessage() to get an error description.
81 * Returns the string of the last error occurred.
83 virtual S
getErrorString()
85 CFormatMessageWrapper
errorMessage(LastError
);
86 S
result ((LPCTSTR
)errorMessage
);
90 /// get failure info for last operation
92 LONG
GetLastError() const
97 /// used in subclass templates to specify the correct string type
104 HKEY m_base
; ///< handle to the registry base
105 S m_key
; ///< the name of the value
106 S m_path
; ///< the path to the key
107 LONG LastError
; ///< the value of the last error occurred
108 REGSAM m_sam
; ///< the security attributes to pass to the registry command
110 bool m_read
; ///< indicates if the value has already been read from the registry
111 bool m_force
; ///< indicates if no cache should be used, i.e. always read and write directly from registry
112 bool m_exists
; ///< true, if the registry actually exists
115 // implement CRegBaseCommon<> members
118 CRegBaseCommon
<S
>::CRegBaseCommon()
119 : m_base (HKEY_CURRENT_USER
)
122 , LastError (ERROR_SUCCESS
)
131 CRegBaseCommon
<S
>::CRegBaseCommon (const S
& key
, bool force
, HKEY base
, REGSAM sam
)
135 , LastError (ERROR_SUCCESS
)
144 DWORD CRegBaseCommon
<S
>::removeKey()
150 RegOpenKeyEx (m_base
, GetPlainString (m_path
), 0, KEY_WRITE
|m_sam
, &hKey
);
151 return SHDeleteKey(m_base
, GetPlainString (m_path
));
155 LONG CRegBaseCommon
<S
>::removeValue()
161 RegOpenKeyEx(m_base
, GetPlainString (m_path
), 0, KEY_WRITE
|m_sam
, &hKey
);
162 return RegDeleteValue(hKey
, GetPlainString (m_key
));
167 * Base class for MFC type registry classes.
170 #ifdef __CSTRINGT_H__
171 class CRegBase
: public CRegBaseCommon
<CString
>
176 * String type specific operations.
179 virtual LPCTSTR
GetPlainString (const CString
& s
) const {return (LPCTSTR
)s
;}
180 virtual DWORD
GetLength (const CString
& s
) const {return s
.GetLength();}
184 /** Default constructor.
189 * \param key the path to the key, including the key. example: "Software\\Company\\SubKey\\MyValue"
190 * \param force set to TRUE if no cache should be used, i.e. always read and write directly from/to registry
191 * \param base a predefined base key like HKEY_LOCAL_MACHINE. see the SDK documentation for more information.
193 CRegBase(const CString
& key
, bool force
, HKEY base
= HKEY_CURRENT_USER
, REGSAM sam
= 0);
196 * Returns the string of the last error occurred.
198 CString
getErrorString()
200 CString error
= CRegBaseCommon
<CString
>::getErrorString();
201 #if defined IDS_REG_ERROR
203 sTemp
.FormatMessage(IDS_REG_ERROR
, (LPCTSTR
)m_key
, (LPCTSTR
)error
);
216 * Base class for STL string type registry classes.
219 class CRegStdBase
: public CRegBaseCommon
<tstring
>
224 * String type specific operations.
227 virtual LPCTSTR
GetPlainString (const tstring
& s
) const {return s
.c_str();}
228 virtual DWORD
GetLength (const tstring
& s
) const {return static_cast<DWORD
>(s
.size());}
232 /** Default constructor.
237 * \param key the path to the key, including the key. example: "Software\\Company\\SubKey\\MyValue"
238 * \param force set to TRUE if no cache should be used, i.e. always read and write directly from/to registry
239 * \param base a predefined base key like HKEY_LOCAL_MACHINE. see the SDK documentation for more information.
241 CRegStdBase(const tstring
& key
, bool force
, HKEY base
= HKEY_CURRENT_USER
, REGSAM sam
= 0);
246 * DWORD value in registry. with this class you can use DWORD values in registry
247 * like normal DWORD variables in your program.
249 * in your header file, declare your registry DWORD variable:
251 * CRegDWORD regvalue;
253 * next initialize the variable e.g. in the constructor of your class:
255 * regvalue = CRegDWORD("Software\\Company\\SubKey\\MyValue", 100);
257 * this will set the registry value "MyValue" under HKEY_CURRENT_USER with path
258 * "Software\Company\SubKey" to the variable. If the key does not yet exist or
259 * an error occurred during read from the registry, a default
260 * value of 100 is used when accessing the variable.
261 * now the variable can be used like any other DWORD variable:
263 * regvalue = 200; //stores the value 200 in the registry
264 * int temp = regvalue + 300; //temp has value 500 now
265 * regvalue += 300; //now the registry has the value 500 too
267 * to avoid too much access to the registry the value is cached inside the object.
268 * once the value is read, no more read accesses to the registry will be made.
269 * this means the variable will contain a wrong value if the corresponding registry
270 * entry is changed by anything else than this variable! If you think that could happen
275 * to force a refresh of the variable with the registry.
276 * a write to the registry is only made if the new value assigned with the variable
277 * is different than the last assigned value.
278 * to force a write use the method write();
279 * another option to force reads and writes to the registry is to specify TRUE as the
280 * third parameter in the constructor.
282 template<class T
, class Base
>
283 class CRegTypedBase
: public Base
287 T m_value
; ///< the cached value of the registry
288 T m_defaultvalue
; ///< the default value to use
291 * time stamp of the last registry lookup, i.e \ref read() call
297 * \ref read() will be called, if \ref lastRead differs from the
298 * current time stamp by more than this.
299 * (DWORD)(-1) -> no automatic refresh.
302 DWORD lookupInterval
;
305 * Check time stamps etc.
306 * If the current data is out-dated, reset the \ref m_read flag.
309 void HandleAutoRefresh();
312 * sub-classes must provide type-specific code to extract data from
313 * and write data to an open registry key.
316 virtual void InternalRead (HKEY hKey
, T
& value
) = 0;
317 virtual void InternalWrite (HKEY hKey
, const T
& value
) = 0;
322 * Make the value type accessible to others.
329 * We use this instead of a default constructor because not all
330 * data types may provide an adequate default constructor.
332 CRegTypedBase(const T
& def
);
336 * \param key the path to the key, including the key. example: "Software\\Company\\SubKey\\MyValue"
337 * \param def the default value used when the key does not exist or a read error occurred
338 * \param force set to TRUE if no cache should be used, i.e. always read and write directly from/to registry
339 * \param base a predefined base key like HKEY_LOCAL_MACHINE. see the SDK documentation for more information.
341 CRegTypedBase(const typename
Base::StringT
& key
, const T
& def
, bool force
= FALSE
, HKEY base
= HKEY_CURRENT_USER
, REGSAM sam
= 0);
345 * \param updateInterval time in msec between registry lookups caused by operator const T&
346 * \param key the path to the key, including the key. example: "Software\\Company\\SubKey\\MyValue"
347 * \param def the default value used when the key does not exist or a read error occurred
348 * \param force set to TRUE if no cache should be used, i.e. always read and write directly from/to registry
349 * \param base a predefined base key like HKEY_LOCAL_MACHINE. see the SDK documentation for more information.
351 CRegTypedBase(DWORD updateInterval
, const typename
Base::StringT
& key
, const T
& def
, bool force
= FALSE
, HKEY base
= HKEY_CURRENT_USER
, REGSAM sam
= 0);
354 * reads the assigned value from the registry. Use this method only if you think the registry
355 * value could have been altered without using the CRegDWORD object.
356 * \return the read value
358 void read(); ///< reads the value from the registry
359 void write(); ///< writes the value to the registry
361 bool exists(); ///< test whether registry entry exits
362 const T
& defaultValue() const; ///< return the default passed to the constructor
369 CRegTypedBase
<T
,Base
>& operator=(const T
& rhs
);
372 // implement CRegTypedBase<> members
374 template<class T
, class Base
>
375 void CRegTypedBase
<T
, Base
>::HandleAutoRefresh()
377 if (m_read
&& (lookupInterval
!= (DWORD
)(-1)))
379 DWORD currentTime
= GetTickCount();
380 if ( (currentTime
< lastRead
)
381 || (currentTime
> lastRead
+ lookupInterval
))
388 template<class T
, class Base
>
389 CRegTypedBase
<T
, Base
>::CRegTypedBase (const T
& def
)
391 , m_defaultvalue (def
)
393 , lookupInterval ((DWORD
)-1)
397 template<class T
, class Base
>
398 CRegTypedBase
<T
, Base
>::CRegTypedBase (const typename
Base::StringT
& key
, const T
& def
, bool force
, HKEY base
, REGSAM sam
)
399 : Base (key
, force
, base
, sam
)
401 , m_defaultvalue (def
)
403 , lookupInterval ((DWORD
)-1)
407 template<class T
, class Base
>
408 CRegTypedBase
<T
, Base
>::CRegTypedBase (DWORD lookupInterval
, const typename
Base::StringT
& key
, const T
& def
, bool force
, HKEY base
, REGSAM sam
)
409 : Base (key
, force
, base
, sam
)
411 , m_defaultvalue (def
)
413 , lookupInterval (lookupInterval
)
417 template<class T
, class Base
>
418 void CRegTypedBase
<T
, Base
>::read()
420 m_value
= m_defaultvalue
;
424 if ((LastError
= RegOpenKeyEx (m_base
, GetPlainString (m_path
), 0, STANDARD_RIGHTS_READ
|KEY_QUERY_VALUE
|m_sam
, &hKey
))==ERROR_SUCCESS
)
428 T value
= m_defaultvalue
;
429 InternalRead (hKey
, value
);
431 if (LastError
==ERROR_SUCCESS
)
437 LastError
= RegCloseKey(hKey
);
440 lastRead
= GetTickCount();
443 template<class T
, class Base
>
444 void CRegTypedBase
<T
, Base
>::write()
449 if ((LastError
= RegCreateKeyEx(m_base
, GetPlainString (m_path
), 0, _T(""), REG_OPTION_NON_VOLATILE
, KEY_WRITE
|m_sam
, NULL
, &hKey
, &disp
))!=ERROR_SUCCESS
)
454 InternalWrite (hKey
, m_value
);
455 if (LastError
==ERROR_SUCCESS
)
460 LastError
= RegCloseKey(hKey
);
462 lastRead
= GetTickCount();
465 template<class T
, class Base
>
466 bool CRegTypedBase
<T
, Base
>::exists()
468 if (!m_read
&& (LastError
== ERROR_SUCCESS
))
474 template<class T
, class Base
>
475 const T
& CRegTypedBase
<T
, Base
>::defaultValue() const
477 return m_defaultvalue
;
480 template<class T
, class Base
>
481 CRegTypedBase
<T
, Base
>::operator const T
&()
484 if ((m_read
)&&(!m_force
))
486 LastError
= ERROR_SUCCESS
;
496 template<class T
, class Base
>
497 CRegTypedBase
<T
, Base
>& CRegTypedBase
<T
, Base
>::operator =(const T
& d
)
499 if (m_read
&& (d
== m_value
) && !m_force
)
501 //no write to the registry required, its the same value
502 LastError
= ERROR_SUCCESS
;
512 * DWORD value in registry. with this class you can use DWORD values in registry
513 * like normal DWORD variables in your program.
515 * in your header file, declare your registry DWORD variable:
517 * CRegDWORD regvalue;
519 * next initialize the variable e.g. in the constructor of your class:
521 * regvalue = CRegDWORD("Software\\Company\\SubKey\\MyValue", 100);
523 * this will set the registry value "MyValue" under HKEY_CURRENT_USER with path
524 * "Software\Company\SubKey" to the variable. If the key does not yet exist or
525 * an error occurred during read from the registry, a default
526 * value of 100 is used when accessing the variable.
527 * now the variable can be used like any other DWORD variable:
529 * regvalue = 200; //stores the value 200 in the registry
530 * int temp = regvalue + 300; //temp has value 500 now
531 * regvalue += 300; //now the registry has the value 500 too
533 * to avoid too much access to the registry the value is cached inside the object.
534 * once the value is read, no more read accesses to the registry will be made.
535 * this means the variable will contain a wrong value if the corresponding registry
536 * entry is changed by anything else than this variable! If you think that could happen
541 * to force a refresh of the variable with the registry.
542 * a write to the registry is only made if the new value assigned with the variable
543 * is different than the last assigned value.
544 * to force a write use the method write();
545 * another option to force reads and writes to the registry is to specify TRUE as the
546 * third parameter in the constructor.
549 class CRegDWORDCommon
: public CRegTypedBase
<DWORD
,Base
>
554 * provide type-specific code to extract data from and write data to an open registry key.
557 virtual void InternalRead (HKEY hKey
, DWORD
& value
);
558 virtual void InternalWrite (HKEY hKey
, const DWORD
& value
);
562 CRegDWORDCommon(void);
565 * \param key the path to the key, including the key. example: "Software\\Company\\SubKey\\MyValue"
566 * \param def the default value used when the key does not exist or a read error occurred
567 * \param force set to TRUE if no cache should be used, i.e. always read and write directly from/to registry
568 * \param base a predefined base key like HKEY_LOCAL_MACHINE. see the SDK documentation for more information.
570 CRegDWORDCommon(const typename
Base::StringT
& key
, DWORD def
= 0, bool force
= false, HKEY base
= HKEY_CURRENT_USER
, REGSAM sam
= 0);
571 CRegDWORDCommon(DWORD lookupInterval
, const typename
Base::StringT
& key
, DWORD def
= 0, bool force
= false, HKEY base
= HKEY_CURRENT_USER
, REGSAM sam
= 0);
573 CRegDWORDCommon
& operator=(DWORD rhs
) {CRegTypedBase
<DWORD
, Base
>::operator =(rhs
); return *this;}
574 CRegDWORDCommon
& operator+=(DWORD d
) { return *this = *this + d
;}
575 CRegDWORDCommon
& operator-=(DWORD d
) { return *this = *this - d
;}
576 CRegDWORDCommon
& operator*=(DWORD d
) { return *this = *this * d
;}
577 CRegDWORDCommon
& operator/=(DWORD d
) { return *this = *this / d
;}
578 CRegDWORDCommon
& operator%=(DWORD d
) { return *this = *this % d
;}
579 CRegDWORDCommon
& operator<<=(DWORD d
) { return *this = *this << d
;}
580 CRegDWORDCommon
& operator>>=(DWORD d
) { return *this = *this >> d
;}
581 CRegDWORDCommon
& operator&=(DWORD d
) { return *this = *this & d
;}
582 CRegDWORDCommon
& operator|=(DWORD d
) { return *this = *this | d
;}
583 CRegDWORDCommon
& operator^=(DWORD d
) { return *this = *this ^ d
;}
586 // implement CRegDWORDCommon<> methods
589 CRegDWORDCommon
<Base
>::CRegDWORDCommon(void)
590 : CRegTypedBase
<DWORD
, Base
>(0)
595 CRegDWORDCommon
<Base
>::CRegDWORDCommon(const typename
Base::StringT
& key
, DWORD def
, bool force
, HKEY base
, REGSAM sam
)
596 : CRegTypedBase
<DWORD
, Base
> (key
, def
, force
, base
, sam
)
601 CRegDWORDCommon
<Base
>::CRegDWORDCommon(DWORD lookupInterval
, const typename
Base::StringT
& key
, DWORD def
, bool force
, HKEY base
, REGSAM sam
)
602 : CRegTypedBase
<DWORD
, Base
> (lookupInterval
, key
, def
, force
, base
, sam
)
607 void CRegDWORDCommon
<Base
>::InternalRead (HKEY hKey
, DWORD
& value
)
609 DWORD size
= sizeof(value
);
611 if ((LastError
= RegQueryValueEx(hKey
, GetPlainString (m_key
), NULL
, &type
, (BYTE
*) &value
, &size
))==ERROR_SUCCESS
)
613 ASSERT(type
==REG_DWORD
);
618 void CRegDWORDCommon
<Base
>::InternalWrite (HKEY hKey
, const DWORD
& value
)
620 LastError
= RegSetValueEx (hKey
, GetPlainString (m_key
), 0, REG_DWORD
,(const BYTE
*) &value
, sizeof(value
));
625 * CString value in registry. with this class you can use CString values in registry
626 * almost like normal CString variables in your program.
628 * in your header file, declare your registry CString variable:
630 * CRegString regvalue;
632 * next initialize the variable e.g. in the constructor of your class:
634 * regvalue = CRegString("Software\\Company\\SubKey\\MyValue", "default");
636 * this will set the registry value "MyValue" under HKEY_CURRENT_USER with path
637 * "Software\Company\SubKey" to the variable. If the key does not yet exist or
638 * an error occurred during read from the registry, a default
639 * value of "default" is used when accessing the variable.
640 * now the variable can be used like any other CString variable:
642 * regvalue = "some string"; //stores the value "some string" in the registry
643 * CString temp = regvalue + "!!"; //temp has value "some string!!" now
645 * to use the normal methods of the CString class, just typecast the CRegString to a CString
646 * and do whatever you want with the string:
648 * ((CString)regvalue).GetLength();
649 * ((CString)regvalue).Trim();
651 * please be aware that in the second line the change in the string won't be written
652 * to the registry! To force a write use the write() method. A write() is only needed
653 * if you change the String with Methods not overloaded by CRegString.
654 * to avoid too much access to the registry the value is cached inside the object.
655 * once the value is read, no more read accesses to the registry will be made.
656 * this means the variable will contain a wrong value if the corresponding registry
657 * entry is changed by anything else than this variable! If you think that could happen
662 * to force a refresh of the variable with the registry.
663 * a write to the registry is only made if the new value assigned with the variable
664 * is different than the last assigned value.
665 * to force a write use the method write();
666 * another option to force reads and writes to the registry is to specify TRUE as the
667 * third parameter in the constructor.
670 class CRegStringCommon
: public CRegTypedBase
<typename
Base::StringT
, Base
>
675 * provide type-specific code to extract data from and write data to an open registry key.
678 virtual void InternalRead (HKEY hKey
, typename
Base::StringT
& value
);
679 virtual void InternalWrite (HKEY hKey
, const typename
Base::StringT
& value
);
685 * \param key the path to the key, including the key. example: "Software\\Company\\SubKey\\MyValue"
686 * \param def the default value used when the key does not exist or a read error occurred
687 * \param force set to TRUE if no cache should be used, i.e. always read and write directly from/to registry
688 * \param base a predefined base key like HKEY_LOCAL_MACHINE. see the SDK documentation for more information.
690 CRegStringCommon(const typename
Base::StringT
& key
, const typename
Base::StringT
& def
= _T(""), bool force
= false, HKEY base
= HKEY_CURRENT_USER
, REGSAM sam
= 0);
691 CRegStringCommon(DWORD lookupInterval
, const typename
Base::StringT
& key
, const typename
Base::StringT
& def
= _T(""), bool force
= false, HKEY base
= HKEY_CURRENT_USER
, REGSAM sam
= 0);
693 CRegStringCommon
& operator=(const typename
Base::StringT
& rhs
) {CRegTypedBase
<StringT
, Base
>::operator =(rhs
); return *this;}
694 CRegStringCommon
& operator+=(const typename
Base::StringT
& s
) { return *this = (typename
Base::StringT
)*this + s
; }
697 // implement CRegDWORD<> methods
700 CRegStringCommon
<Base
>::CRegStringCommon(void)
701 : CRegTypedBase
<typename
Base::StringT
, Base
>(typename
Base::StringT())
706 CRegStringCommon
<Base
>::CRegStringCommon(const typename
Base::StringT
& key
, const typename
Base::StringT
& def
, bool force
, HKEY base
, REGSAM sam
)
707 : CRegTypedBase
<typename
Base::StringT
, Base
> (key
, def
, force
, base
, sam
)
712 CRegStringCommon
<Base
>::CRegStringCommon(DWORD lookupInterval
, const typename
Base::StringT
& key
, const typename
Base::StringT
& def
, bool force
, HKEY base
, REGSAM sam
)
713 : CRegTypedBase
<typename
Base::StringT
, Base
> (lookupInterval
, key
, def
, force
, base
, sam
)
718 void CRegStringCommon
<Base
>::InternalRead (HKEY hKey
, typename
Base::StringT
& value
)
722 LastError
= RegQueryValueEx(hKey
, GetPlainString (m_key
), NULL
, &type
, NULL
, &size
);
724 if (LastError
== ERROR_SUCCESS
)
726 auto_buffer
<TCHAR
> pStr (size
);
727 if ((LastError
= RegQueryValueEx(hKey
, GetPlainString (m_key
), NULL
, &type
, (BYTE
*) pStr
.get(), &size
))==ERROR_SUCCESS
)
729 ASSERT(type
==REG_SZ
|| type
==REG_EXPAND_SZ
);
730 value
= StringT (pStr
.get());
736 void CRegStringCommon
<Base
>::InternalWrite (HKEY hKey
, const typename
Base::StringT
& value
)
738 LastError
= RegSetValueEx(hKey
, GetPlainString (m_key
), 0, REG_SZ
, (BYTE
*)GetPlainString (value
), (GetLength(value
)+1)*sizeof (TCHAR
));
743 * CRect value in registry. with this class you can use CRect values in registry
744 * almost like normal CRect variables in your program.
746 * in your header file, declare your registry CString variable:
750 * next initialize the variable e.g. in the constructor of your class:
752 * regvalue = CRegRect("Software\\Company\\SubKey\\MyValue", CRect(100,100,200,200));
754 * this will set the registry value "MyValue" under HKEY_CURRENT_USER with path
755 * "Software\Company\SubKey" to the variable. If the key does not yet exist or
756 * an error occurred during read from the registry, a default
757 * value of 100,100,200,200 is used when accessing the variable.
758 * now the variable can be used like any other CRect variable:
760 * regvalue = CRect(40,20,300,500); //stores the value in the registry
761 * CRect temp = regvalue + CPoint(1,1);
762 * temp |= CSize(5,5);
764 * to use the normal methods of the CRect class, just typecast the CRegRect to a CRect
765 * and do whatever you want with the rect:
767 * ((CRect)regvalue).MoveToX(100);
768 * ((CRect)regvalue).DeflateRect(10,10);
770 * please be aware that in the second line the change in the CRect won't be written
771 * to the registry! To force a write use the write() method. A write() is only needed
772 * if you change the CRect with Methods not overloaded by CRegRect.
773 * to avoid too much access to the registry the value is cached inside the object.
774 * once the value is read, no more read accesses to the registry will be made.
775 * this means the variable will contain a wrong value if the corresponding registry
776 * entry is changed by anything else than this variable! If you think that could happen
781 * to force a refresh of the variable with the registry.
782 * a write to the registry is only made if the new value assigned with the variable
783 * is different than the last assigned value.
784 * to force a write use the method write();
785 * another option to force reads and writes to the registry is to specify TRUE as the
786 * third parameter in the constructor.
789 #ifdef __ATLTYPES_H__ // defines CRect
790 class CRegRect
: public CRegTypedBase
<CRect
, CRegBase
>
795 * provide type-specific code to extract data from and write data to an open registry key.
798 virtual void InternalRead (HKEY hKey
, CRect
& value
);
799 virtual void InternalWrite (HKEY hKey
, const CRect
& value
);
805 * \param key the path to the key, including the key. example: "Software\\Company\\SubKey\\MyValue"
806 * \param def the default value used when the key does not exist or a read error occurred
807 * \param force set to TRUE if no cache should be used, i.e. always read and write directly from/to registry
808 * \param base a predefined base key like HKEY_LOCAL_MACHINE. see the SDK documentation for more information.
810 CRegRect(const CString
& key
, const CRect
& def
= CRect(), bool force
= false, HKEY base
= HKEY_CURRENT_USER
, REGSAM sam
= 0);
813 CRegRect
& operator=(const CRect
& rhs
) {CRegTypedBase
<CRect
, CRegBase
>::operator =(rhs
); return *this;}
814 operator LPCRECT() { return (LPCRECT
)(CRect
)*this; }
815 operator LPRECT() { return (LPRECT
)(CRect
)*this; }
816 CRegRect
& operator+=(POINT r
) { return *this = (CRect
)*this + r
;}
817 CRegRect
& operator+=(SIZE r
) { return *this = (CRect
)*this + r
;}
818 CRegRect
& operator+=(LPCRECT r
) { return *this = (CRect
)*this + r
;}
819 CRegRect
& operator-=(POINT r
) { return *this = (CRect
)*this - r
;}
820 CRegRect
& operator-=(SIZE r
) { return *this = (CRect
)*this - r
;}
821 CRegRect
& operator-=(LPCRECT r
) { return *this = (CRect
)*this - r
;}
823 CRegRect
& operator&=(CRect r
) { return *this = r
& *this;}
824 CRegRect
& operator|=(CRect r
) { return *this = r
| *this;}
830 * CPoint value in registry. with this class you can use CPoint values in registry
831 * almost like normal CPoint variables in your program.
833 * in your header file, declare your registry CPoint variable:
835 * CRegPoint regvalue;
837 * next initialize the variable e.g. in the constructor of your class:
839 * regvalue = CRegPoint("Software\\Company\\SubKey\\MyValue", CPoint(100,100));
841 * this will set the registry value "MyValue" under HKEY_CURRENT_USER with path
842 * "Software\Company\SubKey" to the variable. If the key does not yet exist or
843 * an error occurred during read from the registry, a default
844 * value of 100,100 is used when accessing the variable.
845 * now the variable can be used like any other CPoint variable:
847 * regvalue = CPoint(40,20); //stores the value in the registry
848 * CPoint temp = regvalue + CPoint(1,1);
849 * temp += CSize(5,5);
851 * to use the normal methods of the CPoint class, just typecast the CRegPoint to a CPoint
852 * and do whatever you want with the point:
854 * ((CRect)regvalue).Offset(100,10);
856 * please be aware that in the above example the change in the CPoint won't be written
857 * to the registry! To force a write use the write() method. A write() is only needed
858 * if you change the CPoint with Methods not overloaded by CRegPoint.
859 * to avoid too much access to the registry the value is cached inside the object.
860 * once the value is read, no more read accesses to the registry will be made.
861 * this means the variable will contain a wrong value if the corresponding registry
862 * entry is changed by anything else than this variable! If you think that could happen
867 * to force a refresh of the variable with the registry.
868 * a write to the registry is only made if the new value assigned with the variable
869 * is different than the last assigned value.
870 * to force a write use the method write();
871 * another option to force reads and writes to the registry is to specify TRUE as the
872 * third parameter in the constructor.
875 #ifdef __ATLTYPES_H__ // defines CPoint
876 class CRegPoint
: public CRegTypedBase
<CPoint
, CRegBase
>
881 * provide type-specific code to extract data from and write data to an open registry key.
884 virtual void InternalRead (HKEY hKey
, CPoint
& value
);
885 virtual void InternalWrite (HKEY hKey
, const CPoint
& value
);
891 * \param key the path to the key, including the key. example: "Software\\Company\\SubKey\\MyValue"
892 * \param def the default value used when the key does not exist or a read error occurred
893 * \param force set to TRUE if no cache should be used, i.e. always read and write directly from/to registry
894 * \param base a predefined base key like HKEY_LOCAL_MACHINE. see the SDK documentation for more information.
896 CRegPoint(const CString
& key
, const CPoint
& def
= CPoint(), bool force
= false, HKEY base
= HKEY_CURRENT_USER
, REGSAM sam
= 0);
899 CRegPoint
& operator=(const CPoint
& rhs
) {CRegTypedBase
<CPoint
, CRegBase
>::operator =(rhs
); return *this;}
900 CRegPoint
& operator+=(CPoint p
) { return *this = p
+ *this; }
901 CRegPoint
& operator-=(CPoint p
) { return *this = p
- *this; }
907 * Manages a registry key (not a value). Provides methods to create and remove the
908 * key and to query the list of values and sub keys.
911 #ifdef __AFXCOLL_H__ // defines CStringList
917 * \param key the path to the key, including the key. example: "Software\\Company\\SubKey"
918 * \param base a predefined base key like HKEY_LOCAL_MACHINE. see the SDK documentation for more information.
920 CRegistryKey(const CString
& key
, HKEY base
= HKEY_CURRENT_USER
, REGSAM sam
= 0);
924 * Creates the registry key if it does not already exist.
925 * \return ERROR_SUCCESS or an nonzero error code. Use FormatMessage() to get an error description.
929 * Removes the whole registry key including all values. So if you set the registry
930 * entry to be HKCU\Software\Company\Product\key there will only be
931 * HKCU\Software\Company\Product key in the registry.
932 * \return ERROR_SUCCESS or an nonzero error code. Use FormatMessage() to get an error description.
936 bool getValues(CStringList
& values
); ///< returns the list of values
937 bool getSubKeys(CStringList
& subkeys
); ///< returns the list of sub keys
940 HKEY m_base
; ///< handle to the registry base
941 HKEY m_hKey
; ///< handle to the open registry key
942 REGSAM m_sam
; ///< the security attributes to pass to the registry command
943 CString m_path
; ///< the path to the key
953 /// constructor parameters
955 typename
T::StringT key
;
956 typename
T::ValueT defaultValue
;
959 /// per-index defaults
961 typedef std::map
<int, typename
T::ValueT
> TDefaults
;
964 /// the indices accessed so far
966 typedef std::map
<int, T
*> TElements
;
967 mutable TElements elements
;
971 const typename
T::ValueT
& GetDefault (int index
) const;
972 T
& GetAt (int index
) const;
978 CKeyList (const typename
T::StringT
& key
, const typename
T::ValueT
& defaultValue
, HKEY base
= HKEY_CURRENT_USER
)
980 , defaultValue (defaultValue
)
985 /// destruction: delete all elements
989 for ( TElements::iterator iter
= elements
.begin()
990 , end
= elements
.end()
1000 const T
& operator[] (int index
) const
1002 return GetAt (index
);
1005 T
& operator[] (int index
)
1007 return GetAt (index
);
1010 const TDefaults
& GetDefaults() const
1015 TDefaults
& GetDefaults()
1020 const typename
T::ValueT
& GetDefault() const
1022 return defaultValue
;
1029 const typename
T::ValueT
& CKeyList
<T
>::GetDefault (int index
) const
1031 TDefaults::const_iterator iter
= defaults
.find (index
);
1032 return iter
== defaults
.end() ? defaultValue
: iter
->second
;
1036 T
& CKeyList
<T
>::GetAt (int index
) const
1038 TElements::iterator iter
= elements
.find (index
);
1039 if (iter
== elements
.end())
1042 _itot_s (index
, buffer
, 10);
1043 typename
T::StringT indexKey
= key
+ _T ('\\') + buffer
;
1045 T
* newElement
= new T (indexKey
, GetDefault (index
), false, base
);
1046 iter
= elements
.insert (std::make_pair (index
, newElement
)).first
;
1049 return *iter
->second
;
1055 * Instantiate templates for common (data type, string type) combinations.
1058 #ifdef __CSTRINGT_H__
1059 CRegDWORDCommon
<CRegBase
>;
1060 typedef CRegDWORDCommon
<CRegBase
> CRegDWORD
;
1061 CRegStringCommon
<CRegBase
>;
1062 typedef CRegStringCommon
<CRegBase
> CRegString
;
1065 CKeyList
<CRegDWORD
>;
1066 typedef CKeyList
<CRegDWORD
> CRegDWORDList
;
1067 CKeyList
<CRegString
>;
1068 typedef CKeyList
<CRegString
> CRegStringList
;
1072 CRegDWORDCommon
<CRegStdBase
>;
1073 typedef CRegDWORDCommon
<CRegStdBase
> CRegStdDWORD
;
1074 CRegStringCommon
<CRegStdBase
>;
1075 typedef CRegStringCommon
<CRegStdBase
> CRegStdString
;
1078 CKeyList
<CRegStdDWORD
>;
1079 typedef CKeyList
<CRegStdDWORD
> CRegStdDWORDList
;
1080 CKeyList
<CRegStdString
>;
1081 typedef CKeyList
<CRegStdString
> CRegStdStringList
;