1 // TortoiseGit - 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 "FormatMessageWrapper.h"
32 * Base class for the registry classes.
35 * - win98 or later, win2k or later, win95 with IE4 or later, winNT4 with IE4 or later
36 * - import library Shlwapi.lib
45 * String type specific operations.
48 virtual LPCTSTR
GetPlainString (const S
& s
) const = 0;
49 virtual DWORD
GetLength (const S
& s
) const = 0;
53 /** Default constructor.
58 * \param key the path to the key, including the key. example: "Software\\Company\\SubKey\\MyValue"
59 * \param force set to TRUE if no cache should be used, i.e. always read and write directly from/to registry
60 * \param base a predefined base key like HKEY_LOCAL_MACHINE. see the SDK documentation for more information.
62 CRegBaseCommon(const S
& key
, bool force
, HKEY base
= HKEY_CURRENT_USER
, REGSAM sam
= 0);
65 * Removes the whole registry key including all values. So if you set the registry
66 * entry to be HKCU\Software\Company\Product\key\value there will only be
67 * HKCU\Software\Company\Product key in the registry.
68 * \return ERROR_SUCCESS or an nonzero error code. Use FormatMessage() to get an error description.
72 * Removes the value of the registry object. If you set the registry entry to
73 * be HKCU\Software\Company\Product\key\value there will only be
74 * HKCU\Software\Company\Product\key\ in the registry.
75 * \return ERROR_SUCCESS or an nonzero error code. Use FormatMessage() to get an error description.
80 * Returns the string of the last error occurred.
82 virtual S
getErrorString()
84 CFormatMessageWrapper
errorMessage(LastError
);
85 S
result ((LPCTSTR
)errorMessage
);
89 /// get failure info for last operation
91 LONG
GetLastError() const
96 /// used in subclass templates to specify the correct string type
103 HKEY m_base
; ///< handle to the registry base
104 S m_key
; ///< the name of the value
105 S m_path
; ///< the path to the key
106 LONG LastError
; ///< the value of the last error occurred
107 REGSAM m_sam
; ///< the security attributes to pass to the registry command
109 bool m_read
; ///< indicates if the value has already been read from the registry
110 bool m_force
; ///< indicates if no cache should be used, i.e. always read and write directly from registry
111 bool m_exists
; ///< true, if the registry actually exists
114 // implement CRegBaseCommon<> members
117 CRegBaseCommon
<S
>::CRegBaseCommon()
118 : m_base (HKEY_CURRENT_USER
)
121 , LastError (ERROR_SUCCESS
)
130 CRegBaseCommon
<S
>::CRegBaseCommon (const S
& key
, bool force
, HKEY base
, REGSAM sam
)
134 , LastError (ERROR_SUCCESS
)
143 DWORD CRegBaseCommon
<S
>::removeKey()
149 RegOpenKeyEx (m_base
, GetPlainString (m_path
), 0, KEY_WRITE
|m_sam
, &hKey
);
150 return SHDeleteKey(m_base
, GetPlainString (m_path
));
154 LONG CRegBaseCommon
<S
>::removeValue()
160 RegOpenKeyEx(m_base
, GetPlainString (m_path
), 0, KEY_WRITE
|m_sam
, &hKey
);
161 return RegDeleteValue(hKey
, GetPlainString (m_key
));
166 * Base class for MFC type registry classes.
169 #ifdef __CSTRINGT_H__
170 class CRegBase
: public CRegBaseCommon
<CString
>
175 * String type specific operations.
178 virtual LPCTSTR
GetPlainString (const CString
& s
) const {return (LPCTSTR
)s
;}
179 virtual DWORD
GetLength (const CString
& s
) const {return s
.GetLength();}
183 /** Default constructor.
188 * \param key the path to the key, including the key. example: "Software\\Company\\SubKey\\MyValue"
189 * \param force set to TRUE if no cache should be used, i.e. always read and write directly from/to registry
190 * \param base a predefined base key like HKEY_LOCAL_MACHINE. see the SDK documentation for more information.
192 CRegBase(const CString
& key
, bool force
, HKEY base
= HKEY_CURRENT_USER
, REGSAM sam
= 0);
195 * Returns the string of the last error occurred.
197 CString
getErrorString()
199 CString error
= CRegBaseCommon
<CString
>::getErrorString();
200 #if defined IDS_REG_ERROR
202 sTemp
.FormatMessage(IDS_REG_ERROR
, (LPCTSTR
)m_key
, (LPCTSTR
)error
);
215 * Base class for STL string type registry classes.
218 class CRegStdBase
: public CRegBaseCommon
<tstring
>
223 * String type specific operations.
226 virtual LPCTSTR
GetPlainString (const tstring
& s
) const {return s
.c_str();}
227 virtual DWORD
GetLength (const tstring
& s
) const {return static_cast<DWORD
>(s
.size());}
231 /** Default constructor.
236 * \param key the path to the key, including the key. example: "Software\\Company\\SubKey\\MyValue"
237 * \param force set to TRUE if no cache should be used, i.e. always read and write directly from/to registry
238 * \param base a predefined base key like HKEY_LOCAL_MACHINE. see the SDK documentation for more information.
240 CRegStdBase(const tstring
& key
, bool force
, HKEY base
= HKEY_CURRENT_USER
, REGSAM sam
= 0);
245 * DWORD value in registry. with this class you can use DWORD values in registry
246 * like normal DWORD variables in your program.
248 * in your header file, declare your registry DWORD variable:
250 * CRegDWORD regvalue;
252 * next initialize the variable e.g. in the constructor of your class:
254 * regvalue = CRegDWORD("Software\\Company\\SubKey\\MyValue", 100);
256 * this will set the registry value "MyValue" under HKEY_CURRENT_USER with path
257 * "Software\Company\SubKey" to the variable. If the key does not yet exist or
258 * an error occurred during read from the registry, a default
259 * value of 100 is used when accessing the variable.
260 * now the variable can be used like any other DWORD variable:
262 * regvalue = 200; //stores the value 200 in the registry
263 * int temp = regvalue + 300; //temp has value 500 now
264 * regvalue += 300; //now the registry has the value 500 too
266 * to avoid too much access to the registry the value is cached inside the object.
267 * once the value is read, no more read accesses to the registry will be made.
268 * this means the variable will contain a wrong value if the corresponding registry
269 * entry is changed by anything else than this variable! If you think that could happen
274 * to force a refresh of the variable with the registry.
275 * a write to the registry is only made if the new value assigned with the variable
276 * is different than the last assigned value.
277 * to force a write use the method write();
278 * another option to force reads and writes to the registry is to specify TRUE as the
279 * third parameter in the constructor.
281 template<class T
, class Base
>
282 class CRegTypedBase
: public Base
286 T m_value
; ///< the cached value of the registry
287 T m_defaultvalue
; ///< the default value to use
290 * time stamp of the last registry lookup, i.e \ref read() call
296 * \ref read() will be called, if \ref lastRead differs from the
297 * current time stamp by more than this.
298 * (DWORD)(-1) -> no automatic refresh.
301 DWORD lookupInterval
;
304 * Check time stamps etc.
305 * If the current data is out-dated, reset the \ref m_read flag.
308 void HandleAutoRefresh();
311 * sub-classes must provide type-specific code to extract data from
312 * and write data to an open registry key.
315 virtual void InternalRead (HKEY hKey
, T
& value
) = 0;
316 virtual void InternalWrite (HKEY hKey
, const T
& value
) = 0;
321 * Make the value type accessible to others.
328 * We use this instead of a default constructor because not all
329 * data types may provide an adequate default constructor.
331 CRegTypedBase(const T
& def
);
335 * \param key the path to the key, including the key. example: "Software\\Company\\SubKey\\MyValue"
336 * \param def the default value used when the key does not exist or a read error occurred
337 * \param force set to TRUE if no cache should be used, i.e. always read and write directly from/to registry
338 * \param base a predefined base key like HKEY_LOCAL_MACHINE. see the SDK documentation for more information.
340 CRegTypedBase(const typename
Base::StringT
& key
, const T
& def
, bool force
= FALSE
, HKEY base
= HKEY_CURRENT_USER
, REGSAM sam
= 0);
344 * \param updateInterval time in msec between registry lookups caused by operator const T&
345 * \param key the path to the key, including the key. example: "Software\\Company\\SubKey\\MyValue"
346 * \param def the default value used when the key does not exist or a read error occurred
347 * \param force set to TRUE if no cache should be used, i.e. always read and write directly from/to registry
348 * \param base a predefined base key like HKEY_LOCAL_MACHINE. see the SDK documentation for more information.
350 CRegTypedBase(DWORD updateInterval
, const typename
Base::StringT
& key
, const T
& def
, bool force
= FALSE
, HKEY base
= HKEY_CURRENT_USER
, REGSAM sam
= 0);
353 * reads the assigned value from the registry. Use this method only if you think the registry
354 * value could have been altered without using the CRegDWORD object.
355 * \return the read value
357 void read(); ///< reads the value from the registry
358 void write(); ///< writes the value to the registry
360 bool exists(); ///< test whether registry entry exits
361 const T
& defaultValue() const; ///< return the default passed to the constructor
368 CRegTypedBase
<T
,Base
>& operator=(const T
& rhs
);
371 // implement CRegTypedBase<> members
373 template<class T
, class Base
>
374 void CRegTypedBase
<T
, Base
>::HandleAutoRefresh()
376 if (m_read
&& (lookupInterval
!= (DWORD
)(-1)))
378 DWORD currentTime
= GetTickCount();
379 if ( (currentTime
< lastRead
)
380 || (currentTime
> lastRead
+ lookupInterval
))
387 template<class T
, class Base
>
388 CRegTypedBase
<T
, Base
>::CRegTypedBase (const T
& def
)
390 , m_defaultvalue (def
)
392 , lookupInterval ((DWORD
)-1)
396 template<class T
, class Base
>
397 CRegTypedBase
<T
, Base
>::CRegTypedBase (const typename
Base::StringT
& key
, const T
& def
, bool force
, HKEY base
, REGSAM sam
)
398 : Base (key
, force
, base
, sam
)
400 , m_defaultvalue (def
)
402 , lookupInterval ((DWORD
)-1)
406 template<class T
, class Base
>
407 CRegTypedBase
<T
, Base
>::CRegTypedBase (DWORD lookupInterval
, const typename
Base::StringT
& key
, const T
& def
, bool force
, HKEY base
, REGSAM sam
)
408 : Base (key
, force
, base
, sam
)
410 , m_defaultvalue (def
)
412 , lookupInterval (lookupInterval
)
416 template<class T
, class Base
>
417 void CRegTypedBase
<T
, Base
>::read()
419 m_value
= m_defaultvalue
;
423 if ((LastError
= RegOpenKeyEx (m_base
, GetPlainString (m_path
), 0, STANDARD_RIGHTS_READ
|KEY_QUERY_VALUE
|m_sam
, &hKey
))==ERROR_SUCCESS
)
426 T value
= m_defaultvalue
;
427 InternalRead (hKey
, value
);
429 if (LastError
==ERROR_SUCCESS
)
435 LastError
= RegCloseKey(hKey
);
439 lastRead
= GetTickCount();
442 template<class T
, class Base
>
443 void CRegTypedBase
<T
, Base
>::write()
448 if ((LastError
= RegCreateKeyEx(m_base
, GetPlainString (m_path
), 0, _T(""), REG_OPTION_NON_VOLATILE
, KEY_WRITE
|m_sam
, NULL
, &hKey
, &disp
))!=ERROR_SUCCESS
)
453 InternalWrite (hKey
, m_value
);
454 if (LastError
==ERROR_SUCCESS
)
459 LastError
= RegCloseKey(hKey
);
461 lastRead
= GetTickCount();
464 template<class T
, class Base
>
465 bool CRegTypedBase
<T
, Base
>::exists()
467 if (!m_read
&& (LastError
== ERROR_SUCCESS
))
473 template<class T
, class Base
>
474 const T
& CRegTypedBase
<T
, Base
>::defaultValue() const
476 return m_defaultvalue
;
479 template<class T
, class Base
>
480 CRegTypedBase
<T
, Base
>::operator const T
&()
483 if ((m_read
)&&(!m_force
))
485 LastError
= ERROR_SUCCESS
;
495 template<class T
, class Base
>
496 CRegTypedBase
<T
, Base
>& CRegTypedBase
<T
, Base
>::operator =(const T
& d
)
498 if (m_read
&& (d
== m_value
) && !m_force
)
500 //no write to the registry required, its the same value
501 LastError
= ERROR_SUCCESS
;
511 * DWORD value in registry. with this class you can use DWORD values in registry
512 * like normal DWORD variables in your program.
514 * in your header file, declare your registry DWORD variable:
516 * CRegDWORD regvalue;
518 * next initialize the variable e.g. in the constructor of your class:
520 * regvalue = CRegDWORD("Software\\Company\\SubKey\\MyValue", 100);
522 * this will set the registry value "MyValue" under HKEY_CURRENT_USER with path
523 * "Software\Company\SubKey" to the variable. If the key does not yet exist or
524 * an error occurred during read from the registry, a default
525 * value of 100 is used when accessing the variable.
526 * now the variable can be used like any other DWORD variable:
528 * regvalue = 200; //stores the value 200 in the registry
529 * int temp = regvalue + 300; //temp has value 500 now
530 * regvalue += 300; //now the registry has the value 500 too
532 * to avoid too much access to the registry the value is cached inside the object.
533 * once the value is read, no more read accesses to the registry will be made.
534 * this means the variable will contain a wrong value if the corresponding registry
535 * entry is changed by anything else than this variable! If you think that could happen
540 * to force a refresh of the variable with the registry.
541 * a write to the registry is only made if the new value assigned with the variable
542 * is different than the last assigned value.
543 * to force a write use the method write();
544 * another option to force reads and writes to the registry is to specify TRUE as the
545 * third parameter in the constructor.
548 class CRegDWORDCommon
: public CRegTypedBase
<DWORD
,Base
>
553 * provide type-specific code to extract data from and write data to an open registry key.
556 virtual void InternalRead (HKEY hKey
, DWORD
& value
);
557 virtual void InternalWrite (HKEY hKey
, const DWORD
& value
);
561 CRegDWORDCommon(void);
564 * \param key the path to the key, including the key. example: "Software\\Company\\SubKey\\MyValue"
565 * \param def the default value used when the key does not exist or a read error occurred
566 * \param force set to TRUE if no cache should be used, i.e. always read and write directly from/to registry
567 * \param base a predefined base key like HKEY_LOCAL_MACHINE. see the SDK documentation for more information.
569 CRegDWORDCommon(const typename
Base::StringT
& key
, DWORD def
= 0, bool force
= false, HKEY base
= HKEY_CURRENT_USER
, REGSAM sam
= 0);
570 CRegDWORDCommon(DWORD lookupInterval
, const typename
Base::StringT
& key
, DWORD def
= 0, bool force
= false, HKEY base
= HKEY_CURRENT_USER
, REGSAM sam
= 0);
572 CRegDWORDCommon
& operator=(DWORD rhs
) {CRegTypedBase
<DWORD
, Base
>::operator =(rhs
); return *this;}
573 CRegDWORDCommon
& operator+=(DWORD d
) { return *this = *this + d
;}
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
;}
585 // implement CRegDWORDCommon<> methods
588 CRegDWORDCommon
<Base
>::CRegDWORDCommon(void)
589 : CRegTypedBase
<DWORD
, Base
>(0)
594 CRegDWORDCommon
<Base
>::CRegDWORDCommon(const typename
Base::StringT
& key
, DWORD def
, bool force
, HKEY base
, REGSAM sam
)
595 : CRegTypedBase
<DWORD
, Base
> (key
, def
, force
, base
, sam
)
600 CRegDWORDCommon
<Base
>::CRegDWORDCommon(DWORD lookupInterval
, const typename
Base::StringT
& key
, DWORD def
, bool force
, HKEY base
, REGSAM sam
)
601 : CRegTypedBase
<DWORD
, Base
> (lookupInterval
, key
, def
, force
, base
, sam
)
606 void CRegDWORDCommon
<Base
>::InternalRead (HKEY hKey
, DWORD
& value
)
608 DWORD size
= sizeof(value
);
610 if ((LastError
= RegQueryValueEx(hKey
, GetPlainString (m_key
), NULL
, &type
, (BYTE
*) &value
, &size
))==ERROR_SUCCESS
)
612 ASSERT(type
==REG_DWORD
);
617 void CRegDWORDCommon
<Base
>::InternalWrite (HKEY hKey
, const DWORD
& value
)
619 LastError
= RegSetValueEx (hKey
, GetPlainString (m_key
), 0, REG_DWORD
,(const BYTE
*) &value
, sizeof(value
));
624 * CString value in registry. with this class you can use CString values in registry
625 * almost like normal CString variables in your program.
627 * in your header file, declare your registry CString variable:
629 * CRegString regvalue;
631 * next initialize the variable e.g. in the constructor of your class:
633 * regvalue = CRegString("Software\\Company\\SubKey\\MyValue", "default");
635 * this will set the registry value "MyValue" under HKEY_CURRENT_USER with path
636 * "Software\Company\SubKey" to the variable. If the key does not yet exist or
637 * an error occurred during read from the registry, a default
638 * value of "default" is used when accessing the variable.
639 * now the variable can be used like any other CString variable:
641 * regvalue = "some string"; //stores the value "some string" in the registry
642 * CString temp = regvalue + "!!"; //temp has value "some string!!" now
644 * to use the normal methods of the CString class, just typecast the CRegString to a CString
645 * and do whatever you want with the string:
647 * ((CString)regvalue).GetLength();
648 * ((CString)regvalue).Trim();
650 * please be aware that in the second line the change in the string won't be written
651 * to the registry! To force a write use the write() method. A write() is only needed
652 * if you change the String with Methods not overloaded by CRegString.
653 * to avoid too much access to the registry the value is cached inside the object.
654 * once the value is read, no more read accesses to the registry will be made.
655 * this means the variable will contain a wrong value if the corresponding registry
656 * entry is changed by anything else than this variable! If you think that could happen
661 * to force a refresh of the variable with the registry.
662 * a write to the registry is only made if the new value assigned with the variable
663 * is different than the last assigned value.
664 * to force a write use the method write();
665 * another option to force reads and writes to the registry is to specify TRUE as the
666 * third parameter in the constructor.
669 class CRegStringCommon
: public CRegTypedBase
<typename
Base::StringT
, Base
>
674 * provide type-specific code to extract data from and write data to an open registry key.
677 virtual void InternalRead (HKEY hKey
, typename
Base::StringT
& value
);
678 virtual void InternalWrite (HKEY hKey
, const typename
Base::StringT
& value
);
684 * \param key the path to the key, including the key. example: "Software\\Company\\SubKey\\MyValue"
685 * \param def the default value used when the key does not exist or a read error occurred
686 * \param force set to TRUE if no cache should be used, i.e. always read and write directly from/to registry
687 * \param base a predefined base key like HKEY_LOCAL_MACHINE. see the SDK documentation for more information.
689 CRegStringCommon(const typename
Base::StringT
& key
, const typename
Base::StringT
& def
= _T(""), bool force
= false, HKEY base
= HKEY_CURRENT_USER
, REGSAM sam
= 0);
690 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);
692 CRegStringCommon
& operator=(const typename
Base::StringT
& rhs
) {CRegTypedBase
<StringT
, Base
>::operator =(rhs
); return *this;}
693 CRegStringCommon
& operator+=(const typename
Base::StringT
& s
) { return *this = (typename
Base::StringT
)*this + s
; }
696 // implement CRegDWORD<> methods
699 CRegStringCommon
<Base
>::CRegStringCommon(void)
700 : CRegTypedBase
<typename
Base::StringT
, Base
>(typename
Base::StringT())
705 CRegStringCommon
<Base
>::CRegStringCommon(const typename
Base::StringT
& key
, const typename
Base::StringT
& def
, bool force
, HKEY base
, REGSAM sam
)
706 : CRegTypedBase
<typename
Base::StringT
, Base
> (key
, def
, force
, base
, sam
)
711 CRegStringCommon
<Base
>::CRegStringCommon(DWORD lookupInterval
, const typename
Base::StringT
& key
, const typename
Base::StringT
& def
, bool force
, HKEY base
, REGSAM sam
)
712 : CRegTypedBase
<typename
Base::StringT
, Base
> (lookupInterval
, key
, def
, force
, base
, sam
)
717 void CRegStringCommon
<Base
>::InternalRead (HKEY hKey
, typename
Base::StringT
& value
)
721 LastError
= RegQueryValueEx(hKey
, GetPlainString (m_key
), NULL
, &type
, NULL
, &size
);
723 if (LastError
== ERROR_SUCCESS
)
725 std::unique_ptr
<TCHAR
[]> pStr (new TCHAR
[size
]);
726 if ((LastError
= RegQueryValueEx(hKey
, GetPlainString (m_key
), NULL
, &type
, (BYTE
*) pStr
.get(), &size
))==ERROR_SUCCESS
)
728 ASSERT(type
==REG_SZ
|| type
==REG_EXPAND_SZ
);
729 value
= StringT (pStr
.get());
735 void CRegStringCommon
<Base
>::InternalWrite (HKEY hKey
, const typename
Base::StringT
& value
)
737 LastError
= RegSetValueEx(hKey
, GetPlainString (m_key
), 0, REG_SZ
, (BYTE
*)GetPlainString (value
), (GetLength(value
)+1)*sizeof (TCHAR
));
742 * CRect value in registry. with this class you can use CRect values in registry
743 * almost like normal CRect variables in your program.
745 * in your header file, declare your registry CString variable:
749 * next initialize the variable e.g. in the constructor of your class:
751 * regvalue = CRegRect("Software\\Company\\SubKey\\MyValue", CRect(100,100,200,200));
753 * this will set the registry value "MyValue" under HKEY_CURRENT_USER with path
754 * "Software\Company\SubKey" to the variable. If the key does not yet exist or
755 * an error occurred during read from the registry, a default
756 * value of 100,100,200,200 is used when accessing the variable.
757 * now the variable can be used like any other CRect variable:
759 * regvalue = CRect(40,20,300,500); //stores the value in the registry
760 * CRect temp = regvalue + CPoint(1,1);
761 * temp |= CSize(5,5);
763 * to use the normal methods of the CRect class, just typecast the CRegRect to a CRect
764 * and do whatever you want with the rect:
766 * ((CRect)regvalue).MoveToX(100);
767 * ((CRect)regvalue).DeflateRect(10,10);
769 * please be aware that in the second line the change in the CRect won't be written
770 * to the registry! To force a write use the write() method. A write() is only needed
771 * if you change the CRect with Methods not overloaded by CRegRect.
772 * to avoid too much access to the registry the value is cached inside the object.
773 * once the value is read, no more read accesses to the registry will be made.
774 * this means the variable will contain a wrong value if the corresponding registry
775 * entry is changed by anything else than this variable! If you think that could happen
780 * to force a refresh of the variable with the registry.
781 * a write to the registry is only made if the new value assigned with the variable
782 * is different than the last assigned value.
783 * to force a write use the method write();
784 * another option to force reads and writes to the registry is to specify TRUE as the
785 * third parameter in the constructor.
788 #ifdef __ATLTYPES_H__ // defines CRect
789 class CRegRect
: public CRegTypedBase
<CRect
, CRegBase
>
794 * provide type-specific code to extract data from and write data to an open registry key.
797 virtual void InternalRead (HKEY hKey
, CRect
& value
);
798 virtual void InternalWrite (HKEY hKey
, const CRect
& value
);
804 * \param key the path to the key, including the key. example: "Software\\Company\\SubKey\\MyValue"
805 * \param def the default value used when the key does not exist or a read error occurred
806 * \param force set to TRUE if no cache should be used, i.e. always read and write directly from/to registry
807 * \param base a predefined base key like HKEY_LOCAL_MACHINE. see the SDK documentation for more information.
809 CRegRect(const CString
& key
, const CRect
& def
= CRect(), bool force
= false, HKEY base
= HKEY_CURRENT_USER
, REGSAM sam
= 0);
812 CRegRect
& operator=(const CRect
& rhs
) {CRegTypedBase
<CRect
, CRegBase
>::operator =(rhs
); return *this;}
813 operator LPCRECT() { return (LPCRECT
)(CRect
)*this; }
814 operator LPRECT() { return (LPRECT
)(CRect
)*this; }
815 CRegRect
& operator+=(POINT r
) { return *this = (CRect
)*this + r
;}
816 CRegRect
& operator+=(SIZE r
) { return *this = (CRect
)*this + r
;}
817 CRegRect
& operator+=(LPCRECT r
) { return *this = (CRect
)*this + r
;}
818 CRegRect
& operator-=(POINT r
) { return *this = (CRect
)*this - r
;}
819 CRegRect
& operator-=(SIZE r
) { return *this = (CRect
)*this - r
;}
820 CRegRect
& operator-=(LPCRECT r
) { return *this = (CRect
)*this - r
;}
822 CRegRect
& operator&=(CRect r
) { return *this = r
& *this;}
823 CRegRect
& operator|=(CRect r
) { return *this = r
| *this;}
829 * CPoint value in registry. with this class you can use CPoint values in registry
830 * almost like normal CPoint variables in your program.
832 * in your header file, declare your registry CPoint variable:
834 * CRegPoint regvalue;
836 * next initialize the variable e.g. in the constructor of your class:
838 * regvalue = CRegPoint("Software\\Company\\SubKey\\MyValue", CPoint(100,100));
840 * this will set the registry value "MyValue" under HKEY_CURRENT_USER with path
841 * "Software\Company\SubKey" to the variable. If the key does not yet exist or
842 * an error occurred during read from the registry, a default
843 * value of 100,100 is used when accessing the variable.
844 * now the variable can be used like any other CPoint variable:
846 * regvalue = CPoint(40,20); //stores the value in the registry
847 * CPoint temp = regvalue + CPoint(1,1);
848 * temp += CSize(5,5);
850 * to use the normal methods of the CPoint class, just typecast the CRegPoint to a CPoint
851 * and do whatever you want with the point:
853 * ((CRect)regvalue).Offset(100,10);
855 * please be aware that in the above example the change in the CPoint won't be written
856 * to the registry! To force a write use the write() method. A write() is only needed
857 * if you change the CPoint with Methods not overloaded by CRegPoint.
858 * to avoid too much access to the registry the value is cached inside the object.
859 * once the value is read, no more read accesses to the registry will be made.
860 * this means the variable will contain a wrong value if the corresponding registry
861 * entry is changed by anything else than this variable! If you think that could happen
866 * to force a refresh of the variable with the registry.
867 * a write to the registry is only made if the new value assigned with the variable
868 * is different than the last assigned value.
869 * to force a write use the method write();
870 * another option to force reads and writes to the registry is to specify TRUE as the
871 * third parameter in the constructor.
874 #ifdef __ATLTYPES_H__ // defines CPoint
875 class CRegPoint
: public CRegTypedBase
<CPoint
, CRegBase
>
880 * provide type-specific code to extract data from and write data to an open registry key.
883 virtual void InternalRead (HKEY hKey
, CPoint
& value
);
884 virtual void InternalWrite (HKEY hKey
, const CPoint
& value
);
890 * \param key the path to the key, including the key. example: "Software\\Company\\SubKey\\MyValue"
891 * \param def the default value used when the key does not exist or a read error occurred
892 * \param force set to TRUE if no cache should be used, i.e. always read and write directly from/to registry
893 * \param base a predefined base key like HKEY_LOCAL_MACHINE. see the SDK documentation for more information.
895 CRegPoint(const CString
& key
, const CPoint
& def
= CPoint(), bool force
= false, HKEY base
= HKEY_CURRENT_USER
, REGSAM sam
= 0);
898 CRegPoint
& operator=(const CPoint
& rhs
) {CRegTypedBase
<CPoint
, CRegBase
>::operator =(rhs
); return *this;}
899 CRegPoint
& operator+=(CPoint p
) { return *this = p
+ *this; }
900 CRegPoint
& operator-=(CPoint p
) { return *this = p
- *this; }
906 * Manages a registry key (not a value). Provides methods to create and remove the
907 * key and to query the list of values and sub keys.
910 #ifdef __AFXCOLL_H__ // defines CStringList
916 * \param key the path to the key, including the key. example: "Software\\Company\\SubKey"
917 * \param base a predefined base key like HKEY_LOCAL_MACHINE. see the SDK documentation for more information.
919 CRegistryKey(const CString
& key
, HKEY base
= HKEY_CURRENT_USER
, REGSAM sam
= 0);
923 * Creates the registry key if it does not already exist.
924 * \return ERROR_SUCCESS or an nonzero error code. Use FormatMessage() to get an error description.
928 * Removes the whole registry key including all values. So if you set the registry
929 * entry to be HKCU\Software\Company\Product\key there will only be
930 * HKCU\Software\Company\Product key in the registry.
931 * \return ERROR_SUCCESS or an nonzero error code. Use FormatMessage() to get an error description.
935 bool getValues(CStringList
& values
); ///< returns the list of values
936 bool getSubKeys(CStringList
& subkeys
); ///< returns the list of sub keys
939 HKEY m_base
; ///< handle to the registry base
940 HKEY m_hKey
; ///< handle to the open registry key
941 REGSAM m_sam
; ///< the security attributes to pass to the registry command
942 CString m_path
; ///< the path to the key
952 /// constructor parameters
954 typename
T::StringT key
;
955 typename
T::ValueT defaultValue
;
958 /// per-index defaults
960 typedef std::map
<int, typename
T::ValueT
> TDefaults
;
963 /// the indices accessed so far
965 typedef std::map
<int, T
*> TElements
;
966 mutable TElements elements
;
970 const typename
T::ValueT
& GetDefault (int index
) const;
971 T
& GetAt (int index
) const;
977 CKeyList (const typename
T::StringT
& key
, const typename
T::ValueT
& defaultValue
, HKEY base
= HKEY_CURRENT_USER
)
979 , defaultValue (defaultValue
)
984 /// destruction: delete all elements
988 for ( TElements::iterator iter
= elements
.begin()
989 , end
= elements
.end()
999 const T
& operator[] (int index
) const
1001 return GetAt (index
);
1004 T
& operator[] (int index
)
1006 return GetAt (index
);
1009 const TDefaults
& GetDefaults() const
1014 TDefaults
& GetDefaults()
1019 const typename
T::ValueT
& GetDefault() const
1021 return defaultValue
;
1028 const typename
T::ValueT
& CKeyList
<T
>::GetDefault (int index
) const
1030 TDefaults::const_iterator iter
= defaults
.find (index
);
1031 return iter
== defaults
.end() ? defaultValue
: iter
->second
;
1035 T
& CKeyList
<T
>::GetAt (int index
) const
1037 TElements::iterator iter
= elements
.find (index
);
1038 if (iter
== elements
.end())
1041 _itot_s (index
, buffer
, 10);
1042 typename
T::StringT indexKey
= key
+ _T ('\\') + buffer
;
1044 T
* newElement
= new T (indexKey
, GetDefault (index
), false, base
);
1045 iter
= elements
.insert (std::make_pair (index
, newElement
)).first
;
1048 return *iter
->second
;
1054 * Instantiate templates for common (data type, string type) combinations.
1057 #ifdef __CSTRINGT_H__
1058 CRegDWORDCommon
<CRegBase
>;
1059 typedef CRegDWORDCommon
<CRegBase
> CRegDWORD
;
1060 CRegStringCommon
<CRegBase
>;
1061 typedef CRegStringCommon
<CRegBase
> CRegString
;
1064 CKeyList
<CRegDWORD
>;
1065 typedef CKeyList
<CRegDWORD
> CRegDWORDList
;
1066 CKeyList
<CRegString
>;
1067 typedef CKeyList
<CRegString
> CRegStringList
;
1071 CRegDWORDCommon
<CRegStdBase
>;
1072 typedef CRegDWORDCommon
<CRegStdBase
> CRegStdDWORD
;
1073 CRegStringCommon
<CRegStdBase
>;
1074 typedef CRegStringCommon
<CRegStdBase
> CRegStdString
;
1077 CKeyList
<CRegStdDWORD
>;
1078 typedef CKeyList
<CRegStdDWORD
> CRegStdDWORDList
;
1079 CKeyList
<CRegStdString
>;
1080 typedef CKeyList
<CRegStdString
> CRegStdStringList
;