OSDN Git Service

Remove unnecessary file
[tortoisegit/TortoiseGitJp.git] / src / Utils / registry.h
1 // TortoiseSVN - a Windows shell extension for easy version control\r
2 \r
3 // Copyright (C) 2003-2008 - TortoiseSVN\r
4 \r
5 // This program is free software; you can redistribute it and/or\r
6 // modify it under the terms of the GNU General Public License\r
7 // as published by the Free Software Foundation; either version 2\r
8 // of the License, or (at your option) any later version.\r
9 \r
10 // This program is distributed in the hope that it will be useful,\r
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of\r
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
13 // GNU General Public License for more details.\r
14 \r
15 // You should have received a copy of the GNU General Public License\r
16 // along with this program; if not, write to the Free Software Foundation,\r
17 // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\r
18 //\r
19 #pragma once\r
20 #include <string>\r
21 #include <memory>\r
22 #include "shlwapi.h"\r
23 \r
24 #ifndef ASSERT\r
25 #define ASSERT(x)\r
26 #endif\r
27 \r
28 /**\r
29  * \ingroup Utils\r
30  * Base class for the registry classes.\r
31  *\r
32  * \par requirements \r
33  * - win98 or later, win2k or later, win95 with IE4 or later, winNT4 with IE4 or later\r
34  * - import library Shlwapi.lib\r
35  */\r
36 \r
37 template<class S>\r
38 class CRegBaseCommon\r
39 {\r
40 protected:\r
41 \r
42     /**\r
43      * String type specific operations.\r
44      */\r
45 \r
46     virtual LPCTSTR GetPlainString (const S& s) const = 0;\r
47     virtual DWORD GetLength (const S& s) const = 0;\r
48 \r
49 public: //methods\r
50 \r
51     /** Default constructor.\r
52      */\r
53     CRegBaseCommon();\r
54         /**\r
55          * Constructor.\r
56          * \param key the path to the key, including the key. example: "Software\\Company\\SubKey\\MyValue"\r
57          * \param force set to TRUE if no cache should be used, i.e. always read and write directly from/to registry\r
58          * \param base a predefined base key like HKEY_LOCAL_MACHINE. see the SDK documentation for more information.\r
59          */\r
60         CRegBaseCommon(const S& key, bool force, HKEY base = HKEY_CURRENT_USER);\r
61 \r
62         /**\r
63          * Removes the whole registry key including all values. So if you set the registry\r
64          * entry to be HKCU\Software\Company\Product\key\value there will only be\r
65          * HKCU\Software\Company\Product key in the registry.\r
66          * \return ERROR_SUCCESS or an nonzero error code. Use FormatMessage() to get an error description.\r
67          */\r
68         DWORD removeKey();\r
69         /**\r
70          * Removes the value of the registry object. If you set the registry entry to\r
71          * be HKCU\Software\Company\Product\key\value there will only be\r
72          * HKCU\Software\Company\Product\key\ in the registry.\r
73          * \return ERROR_SUCCESS or an nonzero error code. Use FormatMessage() to get an error description.\r
74          */\r
75         LONG removeValue();\r
76 \r
77         /**\r
78          * Returns the string of the last error occurred.\r
79          */\r
80         virtual S getErrorString()\r
81         {\r
82                 LPVOID lpMsgBuf;\r
83 \r
84                 FormatMessage(\r
85                         FORMAT_MESSAGE_ALLOCATE_BUFFER | \r
86                         FORMAT_MESSAGE_FROM_SYSTEM |\r
87                         FORMAT_MESSAGE_IGNORE_INSERTS,\r
88                         NULL,\r
89                         LastError,\r
90                         MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),\r
91                         (LPTSTR) &lpMsgBuf,\r
92                         0, NULL );\r
93 \r
94                 return (LPCTSTR)lpMsgBuf;\r
95         };\r
96 \r
97 public: \r
98     \r
99     typedef S StringT;  ///< used in subclass templates to specify the correct string type\r
100 \r
101     //members\r
102         HKEY m_base;            ///< handle to the registry base\r
103         S m_key;                    ///< the name of the value\r
104         S m_path;                   ///< the path to the key\r
105         LONG LastError;         ///< the value of the last error occurred\r
106 \r
107         bool m_read;            ///< indicates if the value has already been read from the registry\r
108         bool m_force;           ///< indicates if no cache should be used, i.e. always read and write directly from registry\r
109     bool m_exists;      ///< true, if the registry actually exists\r
110 };\r
111 \r
112 // implement CRegBaseCommon<> members\r
113 \r
114 template<class S>\r
115 CRegBaseCommon<S>::CRegBaseCommon()\r
116     : m_base (HKEY_CURRENT_USER)\r
117     , m_key()\r
118     , m_path()\r
119     , LastError (ERROR_SUCCESS)\r
120     , m_read (false)\r
121     , m_force (false)\r
122     , m_exists (false)\r
123 {\r
124 }\r
125 \r
126 template<class S>\r
127 CRegBaseCommon<S>::CRegBaseCommon (const S& key, bool force, HKEY base)\r
128     : m_base (base)\r
129         , m_key (key)\r
130     , m_path()\r
131     , LastError (ERROR_SUCCESS)\r
132     , m_read (false)\r
133     , m_force (force)\r
134     , m_exists (false)\r
135 {\r
136 }\r
137 \r
138 template<class S>\r
139 DWORD CRegBaseCommon<S>::removeKey() \r
140\r
141     m_exists = false;\r
142     m_read = true;\r
143 \r
144     HKEY hKey = NULL;\r
145     RegOpenKeyEx (m_base, GetPlainString (m_path), 0, KEY_WRITE, &hKey); \r
146     return SHDeleteKey(m_base, GetPlainString (m_path)); \r
147 }\r
148 \r
149 template<class S>\r
150 LONG CRegBaseCommon<S>::removeValue() \r
151\r
152     m_exists = false;\r
153     m_read = true;\r
154 \r
155     HKEY hKey = NULL;\r
156     RegOpenKeyEx(m_base, GetPlainString (m_path), 0, KEY_WRITE, &hKey); \r
157     return RegDeleteValue(hKey, GetPlainString (m_key)); \r
158 }\r
159 \r
160 /**\r
161  * \ingroup Utils\r
162  * Base class for MFC type registry classes.\r
163  */\r
164 \r
165 #ifdef __CSTRINGT_H__\r
166 class CRegBase : public CRegBaseCommon<CString>\r
167 {\r
168 protected:\r
169 \r
170     /**\r
171      * String type specific operations.\r
172      */\r
173 \r
174     virtual LPCTSTR GetPlainString (const CString& s) const {return (LPCTSTR)s;}\r
175     virtual DWORD GetLength (const CString& s) const {return s.GetLength();}\r
176 \r
177 public: //methods\r
178 \r
179     /** Default constructor.\r
180      */\r
181     CRegBase();\r
182         /**\r
183          * Constructor.\r
184          * \param key the path to the key, including the key. example: "Software\\Company\\SubKey\\MyValue"\r
185          * \param force set to TRUE if no cache should be used, i.e. always read and write directly from/to registry\r
186          * \param base a predefined base key like HKEY_LOCAL_MACHINE. see the SDK documentation for more information.\r
187          */\r
188         CRegBase(const CString& key, bool force, HKEY base = HKEY_CURRENT_USER);\r
189 \r
190         /**\r
191          * Returns the string of the last error occurred.\r
192          */\r
193         CString getErrorString()\r
194         {\r
195         CString error = CRegBaseCommon<CString>::getErrorString();\r
196 #if defined IDS_REG_ERROR\r
197                 CString sTemp;\r
198                 sTemp.Format(IDS_REG_ERROR, (LPCTSTR)m_key, (LPCTSTR)error);\r
199                 return sTemp;\r
200 #else\r
201                 return error;\r
202 #endif\r
203         };\r
204 };\r
205 #endif\r
206 \r
207 typedef std::wstring wide_string;\r
208 #ifndef stdstring\r
209 #       ifdef UNICODE\r
210 #               define stdstring wide_string\r
211 #       else\r
212 #               define stdstring std::string\r
213 #       endif\r
214 #endif\r
215 \r
216 /**\r
217  * \ingroup Utils\r
218  * Base class for STL string type registry classes.\r
219  */\r
220 \r
221 class CRegStdBase : public CRegBaseCommon<stdstring>\r
222 {\r
223 protected:\r
224 \r
225     /**\r
226      * String type specific operations.\r
227      */\r
228 \r
229     virtual LPCTSTR GetPlainString (const stdstring& s) const {return s.c_str();}\r
230     virtual DWORD GetLength (const stdstring& s) const {return static_cast<DWORD>(s.size());}\r
231 \r
232 public: //methods\r
233 \r
234     /** Default constructor.\r
235      */\r
236     CRegStdBase();\r
237         /**\r
238          * Constructor.\r
239          * \param key the path to the key, including the key. example: "Software\\Company\\SubKey\\MyValue"\r
240          * \param force set to TRUE if no cache should be used, i.e. always read and write directly from/to registry\r
241          * \param base a predefined base key like HKEY_LOCAL_MACHINE. see the SDK documentation for more information.\r
242          */\r
243         CRegStdBase(const stdstring& key, bool force, HKEY base = HKEY_CURRENT_USER);\r
244 };\r
245 \r
246 /**\r
247  * \ingroup Utils\r
248  * DWORD value in registry. with this class you can use DWORD values in registry\r
249  * like normal DWORD variables in your program.\r
250  * Usage:\r
251  * in your header file, declare your registry DWORD variable:\r
252  * \code\r
253  * CRegDWORD regvalue;\r
254  * \endcode\r
255  * next initialize the variable e.g. in the constructor of your class:\r
256  * \code\r
257  * regvalue = CRegDWORD("Software\\Company\\SubKey\\MyValue", 100);\r
258  * \endcode\r
259  * this will set the registry value "MyValue" under HKEY_CURRENT_USER with path \r
260  * "Software\Company\SubKey" to the variable. If the key does not yet exist or\r
261  * an error occurred during read from the registry, a default\r
262  * value of 100 is used when accessing the variable.\r
263  * now the variable can be used like any other DWORD variable:\r
264  * \code\r
265  * regvalue = 200;                                              //stores the value 200 in the registry\r
266  * int temp = regvalue + 300;                   //temp has value 500 now\r
267  * regvalue += 300;                                             //now the registry has the value 500 too\r
268  * \endcode\r
269  * to avoid too much access to the registry the value is cached inside the object.\r
270  * once the value is read, no more read accesses to the registry will be made.\r
271  * this means the variable will contain a wrong value if the corresponding registry\r
272  * entry is changed by anything else than this variable! If you think that could happen\r
273  * then use \r
274  * \code\r
275  * regvalue.read();\r
276  * \endcode\r
277  * to force a refresh of the variable with the registry.\r
278  * a write to the registry is only made if the new value assigned with the variable\r
279  * is different than the last assigned value.\r
280  * to force a write use the method write();\r
281  * another option to force reads and writes to the registry is to specify TRUE as the\r
282  * third parameter in the constructor.\r
283  */\r
284 template<class T, class Base>\r
285 class CRegTypedBase : public Base\r
286 {\r
287 private:\r
288 \r
289         T m_value;                                      ///< the cached value of the registry\r
290         T m_defaultvalue;                       ///< the default value to use\r
291 \r
292     /**\r
293      * sub-classes must provide type-specific code to extract data from\r
294      * and write data to an open registry key.\r
295      */\r
296 \r
297     virtual void InternalRead (HKEY hKey, T& value) = 0;\r
298     virtual void InternalWrite (HKEY hKey, const T& value) = 0;\r
299 \r
300 public:\r
301 \r
302     /**\r
303      * We use this instead of a default constructor because not all \r
304      * data types may provide an adequate default constructor.\r
305      */\r
306         CRegTypedBase(const T& def);\r
307 \r
308         /**\r
309          * Constructor.\r
310          * \param key the path to the key, including the key. example: "Software\\Company\\SubKey\\MyValue"\r
311          * \param def the default value used when the key does not exist or a read error occurred\r
312          * \param force set to TRUE if no cache should be used, i.e. always read and write directly from/to registry\r
313          * \param base a predefined base key like HKEY_LOCAL_MACHINE. see the SDK documentation for more information.\r
314          */\r
315     CRegTypedBase(const typename Base::StringT& key, const T& def, bool force = FALSE, HKEY base = HKEY_CURRENT_USER);\r
316 \r
317         /**\r
318          * reads the assigned value from the registry. Use this method only if you think the registry\r
319          * value could have been altered without using the CRegDWORD object.\r
320          * \return the read value\r
321          */\r
322         void    read();                                         ///< reads the value from the registry\r
323         void    write();                                        ///< writes the value to the registry\r
324 \r
325     /**\r
326      * Data access.\r
327      */\r
328 \r
329     operator const T&();\r
330         CRegTypedBase<T,Base>& operator=(const T& rhs);\r
331 };\r
332 \r
333 // implement CRegTypedBase<> members\r
334 \r
335 template<class T, class Base>\r
336 CRegTypedBase<T, Base>::CRegTypedBase (const T& def)\r
337     : m_value (def)\r
338     , m_defaultvalue (def)\r
339 {\r
340 }\r
341 \r
342 template<class T, class Base>\r
343 CRegTypedBase<T, Base>::CRegTypedBase (const typename Base::StringT& key, const T& def, bool force, HKEY base)\r
344     : Base (key, force, base)\r
345     , m_value (def)\r
346     , m_defaultvalue (def)\r
347 {\r
348 }\r
349 \r
350 template<class T, class Base>\r
351 void CRegTypedBase<T, Base>::read()\r
352 {\r
353         m_value = m_defaultvalue;\r
354     m_exists = false;\r
355 \r
356     HKEY hKey = NULL;\r
357         if ((LastError = RegOpenKeyEx (m_base, GetPlainString (m_path), 0, KEY_EXECUTE, &hKey))==ERROR_SUCCESS)\r
358         {\r
359                 m_read = true;\r
360 \r
361         T value = m_defaultvalue;\r
362         InternalRead (hKey, value);\r
363 \r
364                 if (LastError ==ERROR_SUCCESS)\r
365                 {\r
366             m_exists = true;\r
367                         m_value = value;\r
368                 }\r
369 \r
370         LastError = RegCloseKey(hKey);\r
371         }\r
372 }\r
373 \r
374 template<class T, class Base>\r
375 void CRegTypedBase<T, Base>::write()\r
376 {\r
377     HKEY hKey = NULL;\r
378 \r
379     DWORD disp = 0;\r
380         if ((LastError = RegCreateKeyEx(m_base, GetPlainString (m_path), 0, _T(""), REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &hKey, &disp))!=ERROR_SUCCESS)\r
381         {\r
382                 return;\r
383         }\r
384 \r
385     InternalWrite (hKey, m_value);\r
386         if (LastError ==ERROR_SUCCESS)\r
387         {\r
388                 m_read = true;\r
389         m_exists = true;\r
390         }\r
391         LastError = RegCloseKey(hKey);\r
392 }\r
393 \r
394 \r
395 template<class T, class Base>\r
396 CRegTypedBase<T, Base>::operator const T&()\r
397 {\r
398         if ((m_read)&&(!m_force))\r
399         {\r
400                 LastError = 0;\r
401         }\r
402         else\r
403         {\r
404                 read();\r
405         }\r
406 \r
407         return m_value;\r
408 }\r
409 \r
410 template<class T, class Base>\r
411 CRegTypedBase<T, Base>& CRegTypedBase<T, Base>::operator =(const T& d)\r
412 {\r
413         if ((d==m_value)&&(!m_force))\r
414         {\r
415                 //no write to the registry required, its the same value\r
416                 LastError = 0;\r
417                 return *this;\r
418         }\r
419         m_value = d;\r
420         write();\r
421         return *this;\r
422 }\r
423 \r
424 /**\r
425  * \ingroup Utils\r
426  * DWORD value in registry. with this class you can use DWORD values in registry\r
427  * like normal DWORD variables in your program.\r
428  * Usage:\r
429  * in your header file, declare your registry DWORD variable:\r
430  * \code\r
431  * CRegDWORD regvalue;\r
432  * \endcode\r
433  * next initialize the variable e.g. in the constructor of your class:\r
434  * \code\r
435  * regvalue = CRegDWORD("Software\\Company\\SubKey\\MyValue", 100);\r
436  * \endcode\r
437  * this will set the registry value "MyValue" under HKEY_CURRENT_USER with path \r
438  * "Software\Company\SubKey" to the variable. If the key does not yet exist or\r
439  * an error occurred during read from the registry, a default\r
440  * value of 100 is used when accessing the variable.\r
441  * now the variable can be used like any other DWORD variable:\r
442  * \code\r
443  * regvalue = 200;                                              //stores the value 200 in the registry\r
444  * int temp = regvalue + 300;                   //temp has value 500 now\r
445  * regvalue += 300;                                             //now the registry has the value 500 too\r
446  * \endcode\r
447  * to avoid too much access to the registry the value is cached inside the object.\r
448  * once the value is read, no more read accesses to the registry will be made.\r
449  * this means the variable will contain a wrong value if the corresponding registry\r
450  * entry is changed by anything else than this variable! If you think that could happen\r
451  * then use \r
452  * \code\r
453  * regvalue.read();\r
454  * \endcode\r
455  * to force a refresh of the variable with the registry.\r
456  * a write to the registry is only made if the new value assigned with the variable\r
457  * is different than the last assigned value.\r
458  * to force a write use the method write();\r
459  * another option to force reads and writes to the registry is to specify TRUE as the\r
460  * third parameter in the constructor.\r
461  */\r
462 template<class Base>\r
463 class CRegDWORDCommon : public CRegTypedBase<DWORD,Base>\r
464 {\r
465 private:\r
466 \r
467     /**\r
468      * provide type-specific code to extract data from and write data to an open registry key.\r
469      */\r
470 \r
471     virtual void InternalRead (HKEY hKey, DWORD& value);\r
472     virtual void InternalWrite (HKEY hKey, const DWORD& value);\r
473 \r
474 public:\r
475 \r
476         CRegDWORDCommon(void);\r
477         /**\r
478          * Constructor.\r
479          * \param key the path to the key, including the key. example: "Software\\Company\\SubKey\\MyValue"\r
480          * \param def the default value used when the key does not exist or a read error occurred\r
481          * \param force set to TRUE if no cache should be used, i.e. always read and write directly from/to registry\r
482          * \param base a predefined base key like HKEY_LOCAL_MACHINE. see the SDK documentation for more information.\r
483          */\r
484     CRegDWORDCommon(const typename Base::StringT& key, DWORD def = 0, bool force = false, HKEY base = HKEY_CURRENT_USER);\r
485 \r
486     CRegDWORDCommon& operator=(DWORD rhs) {CRegTypedBase<DWORD, Base>::operator =(rhs); return *this;}\r
487         CRegDWORDCommon& operator+=(DWORD d) { return *this = *this + d;}\r
488         CRegDWORDCommon& operator-=(DWORD d) { return *this = *this - d;}\r
489         CRegDWORDCommon& operator*=(DWORD d) { return *this = *this * d;}\r
490         CRegDWORDCommon& operator/=(DWORD d) { return *this = *this / d;}\r
491         CRegDWORDCommon& operator%=(DWORD d) { return *this = *this % d;}\r
492         CRegDWORDCommon& operator<<=(DWORD d) { return *this = *this << d;}\r
493         CRegDWORDCommon& operator>>=(DWORD d) { return *this = *this >> d;}\r
494         CRegDWORDCommon& operator&=(DWORD d) { return *this = *this & d;}\r
495         CRegDWORDCommon& operator|=(DWORD d) { return *this = *this | d;}\r
496         CRegDWORDCommon& operator^=(DWORD d) { return *this = *this ^ d;}\r
497 };\r
498 \r
499 // implement CRegDWORDCommon<> methods\r
500 \r
501 template<class Base>\r
502 CRegDWORDCommon<Base>::CRegDWORDCommon(void)\r
503     : CRegTypedBase<DWORD, Base>(0)\r
504 {\r
505 }\r
506 \r
507 template<class Base>\r
508 CRegDWORDCommon<Base>::CRegDWORDCommon(const typename Base::StringT& key, DWORD def, bool force, HKEY base)\r
509     : CRegTypedBase<DWORD, Base> (key, def, force, base)\r
510 {\r
511         read();\r
512 }\r
513 \r
514 template<class Base>\r
515 void CRegDWORDCommon<Base>::InternalRead (HKEY hKey, DWORD& value)\r
516 {\r
517     DWORD size = sizeof(value);\r
518         DWORD type = 0;\r
519         if ((LastError = RegQueryValueEx(hKey, GetPlainString (m_key), NULL, &type, (BYTE*) &value, &size))==ERROR_SUCCESS)\r
520     {\r
521                 ASSERT(type==REG_DWORD);\r
522     }\r
523 }\r
524 \r
525 template<class Base>\r
526 void CRegDWORDCommon<Base>::InternalWrite (HKEY hKey, const DWORD& value)\r
527 {\r
528         LastError = RegSetValueEx (hKey, GetPlainString (m_key), 0, REG_DWORD,(const BYTE*) &value, sizeof(value));\r
529 }\r
530 \r
531 /**\r
532  * \ingroup Utils\r
533  * CString value in registry. with this class you can use CString values in registry\r
534  * almost like normal CString variables in your program.\r
535  * Usage:\r
536  * in your header file, declare your registry CString variable:\r
537  * \code\r
538  * CRegString regvalue;\r
539  * \endcode\r
540  * next initialize the variable e.g. in the constructor of your class:\r
541  * \code\r
542  * regvalue = CRegString("Software\\Company\\SubKey\\MyValue", "default");\r
543  * \endcode\r
544  * this will set the registry value "MyValue" under HKEY_CURRENT_USER with path \r
545  * "Software\Company\SubKey" to the variable. If the key does not yet exist or\r
546  * an error occurred during read from the registry, a default\r
547  * value of "default" is used when accessing the variable.\r
548  * now the variable can be used like any other CString variable:\r
549  * \code\r
550  * regvalue = "some string";                    //stores the value "some string" in the registry\r
551  * CString temp = regvalue + "!!";              //temp has value "some string!!" now\r
552  * \endcode\r
553  * to use the normal methods of the CString class, just typecast the CRegString to a CString\r
554  * and do whatever you want with the string:\r
555  * \code\r
556  * ((CString)regvalue).GetLength();\r
557  * ((CString)regvalue).Trim();\r
558  * \endcode\r
559  * please be aware that in the second line the change in the string won't be written\r
560  * to the registry! To force a write use the write() method. A write() is only needed\r
561  * if you change the String with Methods not overloaded by CRegString.\r
562  * to avoid too much access to the registry the value is cached inside the object.\r
563  * once the value is read, no more read accesses to the registry will be made.\r
564  * this means the variable will contain a wrong value if the corresponding registry\r
565  * entry is changed by anything else than this variable! If you think that could happen\r
566  * then use \r
567  * \code\r
568  * regvalue.read();\r
569  * \endcode\r
570  * to force a refresh of the variable with the registry.\r
571  * a write to the registry is only made if the new value assigned with the variable\r
572  * is different than the last assigned value.\r
573  * to force a write use the method write();\r
574  * another option to force reads and writes to the registry is to specify TRUE as the\r
575  * third parameter in the constructor.\r
576  */\r
577 template<class Base>\r
578 class CRegStringCommon : public CRegTypedBase<typename Base::StringT, Base>\r
579 {\r
580 private:\r
581 \r
582     /**\r
583      * provide type-specific code to extract data from and write data to an open registry key.\r
584      */\r
585 \r
586     virtual void InternalRead (HKEY hKey, typename Base::StringT& value);\r
587     virtual void InternalWrite (HKEY hKey, const typename Base::StringT& value);\r
588 \r
589 public:\r
590         CRegStringCommon();\r
591         /**\r
592          * Constructor.\r
593          * \param key the path to the key, including the key. example: "Software\\Company\\SubKey\\MyValue"\r
594          * \param def the default value used when the key does not exist or a read error occurred\r
595          * \param force set to TRUE if no cache should be used, i.e. always read and write directly from/to registry\r
596          * \param base a predefined base key like HKEY_LOCAL_MACHINE. see the SDK documentation for more information.\r
597          */\r
598     CRegStringCommon(const typename Base::StringT& key, const typename Base::StringT& def = _T(""), bool force = false, HKEY base = HKEY_CURRENT_USER);\r
599         \r
600     CRegStringCommon& operator=(const typename Base::StringT& rhs) {CRegTypedBase<StringT, Base>::operator =(rhs); return *this;}\r
601         CRegStringCommon& operator+=(const typename Base::StringT& s) { return *this = (typename Base::StringT)*this + s; }\r
602 };\r
603 \r
604 // implement CRegDWORD<> methods\r
605 \r
606 template<class Base>\r
607 CRegStringCommon<Base>::CRegStringCommon(void)\r
608     : CRegTypedBase<typename Base::StringT, Base>(typename Base::StringT())\r
609 {\r
610 }\r
611 \r
612 template<class Base>\r
613 CRegStringCommon<Base>::CRegStringCommon(const typename Base::StringT& key, const typename Base::StringT& def, bool force, HKEY base)\r
614     : CRegTypedBase<typename Base::StringT, Base> (key, def, force, base)\r
615 {\r
616         read();\r
617 }\r
618 \r
619 template<class Base>\r
620 void CRegStringCommon<Base>::InternalRead (HKEY hKey, typename Base::StringT& value)\r
621 {\r
622         DWORD size = 0;\r
623         DWORD type = 0;\r
624         LastError = RegQueryValueEx(hKey, GetPlainString (m_key), NULL, &type, NULL, &size);\r
625 \r
626     std::auto_ptr<TCHAR> pStr (new TCHAR[size]);\r
627         if ((LastError = RegQueryValueEx(hKey, GetPlainString (m_key), NULL, &type, (BYTE*) pStr.get(), &size))==ERROR_SUCCESS)\r
628     {\r
629         ASSERT(type==REG_SZ || type==REG_EXPAND_SZ);\r
630         value = StringT (pStr.get());\r
631     }\r
632 }\r
633 \r
634 template<class Base>\r
635 void CRegStringCommon<Base>::InternalWrite (HKEY hKey, const typename Base::StringT& value)\r
636 {\r
637         LastError = RegSetValueEx(hKey, GetPlainString (m_key), 0, REG_SZ, (BYTE *)GetPlainString (value), (GetLength(value)+1)*sizeof (TCHAR));\r
638 }\r
639 \r
640 /**\r
641  * \ingroup Utils\r
642  * CRect value in registry. with this class you can use CRect values in registry\r
643  * almost like normal CRect variables in your program.\r
644  * Usage:\r
645  * in your header file, declare your registry CString variable:\r
646  * \code\r
647  * CRegRect regvalue;\r
648  * \endcode\r
649  * next initialize the variable e.g. in the constructor of your class:\r
650  * \code\r
651  * regvalue = CRegRect("Software\\Company\\SubKey\\MyValue", CRect(100,100,200,200));\r
652  * \endcode\r
653  * this will set the registry value "MyValue" under HKEY_CURRENT_USER with path \r
654  * "Software\Company\SubKey" to the variable. If the key does not yet exist or\r
655  * an error occurred during read from the registry, a default\r
656  * value of 100,100,200,200 is used when accessing the variable.\r
657  * now the variable can be used like any other CRect variable:\r
658  * \code\r
659  * regvalue = CRect(40,20,300,500);                             //stores the value in the registry\r
660  * CRect temp = regvalue + CPoint(1,1);\r
661  * temp |= CSize(5,5);\r
662  * \endcode\r
663  * to use the normal methods of the CRect class, just typecast the CRegRect to a CRect\r
664  * and do whatever you want with the rect:\r
665  * \code\r
666  * ((CRect)regvalue).MoveToX(100);\r
667  * ((CRect)regvalue).DeflateRect(10,10);\r
668  * \endcode\r
669  * please be aware that in the second line the change in the CRect won't be written\r
670  * to the registry! To force a write use the write() method. A write() is only needed\r
671  * if you change the CRect with Methods not overloaded by CRegRect.\r
672  * to avoid too much access to the registry the value is cached inside the object.\r
673  * once the value is read, no more read accesses to the registry will be made.\r
674  * this means the variable will contain a wrong value if the corresponding registry\r
675  * entry is changed by anything else than this variable! If you think that could happen\r
676  * then use \r
677  * \code\r
678  * regvalue.read();\r
679  * \endcode\r
680  * to force a refresh of the variable with the registry.\r
681  * a write to the registry is only made if the new value assigned with the variable\r
682  * is different than the last assigned value.\r
683  * to force a write use the method write();\r
684  * another option to force reads and writes to the registry is to specify TRUE as the\r
685  * third parameter in the constructor.\r
686  */\r
687 \r
688 #ifdef __ATLTYPES_H__   // defines CRect \r
689 class CRegRect : public CRegTypedBase<CRect, CRegBase>\r
690 {\r
691 private:\r
692 \r
693     /**\r
694      * provide type-specific code to extract data from and write data to an open registry key.\r
695      */\r
696 \r
697     virtual void InternalRead (HKEY hKey, CRect& value);\r
698     virtual void InternalWrite (HKEY hKey, const CRect& value);\r
699 \r
700 public:\r
701         CRegRect();\r
702         /**\r
703          * Constructor.\r
704          * \param key the path to the key, including the key. example: "Software\\Company\\SubKey\\MyValue"\r
705          * \param def the default value used when the key does not exist or a read error occurred\r
706          * \param force set to TRUE if no cache should be used, i.e. always read and write directly from/to registry\r
707          * \param base a predefined base key like HKEY_LOCAL_MACHINE. see the SDK documentation for more information.\r
708          */\r
709         CRegRect(const CString& key, const CRect& def = CRect(), bool force = false, HKEY base = HKEY_CURRENT_USER);\r
710         ~CRegRect(void);\r
711         \r
712     CRegRect& operator=(const CRect& rhs) {CRegTypedBase<CRect, CRegBase>::operator =(rhs); return *this;}\r
713         operator LPCRECT() { return (LPCRECT)(CRect)*this; }\r
714         operator LPRECT() { return (LPRECT)(CRect)*this; }\r
715         CRegRect& operator+=(POINT r) { return *this = (CRect)*this + r;}\r
716         CRegRect& operator+=(SIZE r) { return *this = (CRect)*this + r;}\r
717         CRegRect& operator+=(LPCRECT  r) { return *this = (CRect)*this + r;}\r
718         CRegRect& operator-=(POINT r) { return *this = (CRect)*this - r;}\r
719         CRegRect& operator-=(SIZE r) { return *this = (CRect)*this - r;}\r
720         CRegRect& operator-=(LPCRECT  r) { return *this = (CRect)*this - r;}\r
721         \r
722         CRegRect& operator&=(CRect r) { return *this = r & *this;}\r
723         CRegRect& operator|=(CRect r) { return *this = r | *this;}\r
724 };\r
725 #endif\r
726 \r
727 /**\r
728  * \ingroup Utils\r
729  * CPoint value in registry. with this class you can use CPoint values in registry\r
730  * almost like normal CPoint variables in your program.\r
731  * Usage:\r
732  * in your header file, declare your registry CPoint variable:\r
733  * \code\r
734  * CRegPoint regvalue;\r
735  * \endcode\r
736  * next initialize the variable e.g. in the constructor of your class:\r
737  * \code\r
738  * regvalue = CRegPoint("Software\\Company\\SubKey\\MyValue", CPoint(100,100));\r
739  * \endcode\r
740  * this will set the registry value "MyValue" under HKEY_CURRENT_USER with path \r
741  * "Software\Company\SubKey" to the variable. If the key does not yet exist or\r
742  * an error occurred during read from the registry, a default\r
743  * value of 100,100 is used when accessing the variable.\r
744  * now the variable can be used like any other CPoint variable:\r
745  * \code\r
746  * regvalue = CPoint(40,20);                                    //stores the value in the registry\r
747  * CPoint temp = regvalue + CPoint(1,1);\r
748  * temp += CSize(5,5);\r
749  * \endcode\r
750  * to use the normal methods of the CPoint class, just typecast the CRegPoint to a CPoint\r
751  * and do whatever you want with the point:\r
752  * \code\r
753  * ((CRect)regvalue).Offset(100,10);\r
754  * \endcode\r
755  * please be aware that in the above example the change in the CPoint won't be written\r
756  * to the registry! To force a write use the write() method. A write() is only needed\r
757  * if you change the CPoint with Methods not overloaded by CRegPoint.\r
758  * to avoid too much access to the registry the value is cached inside the object.\r
759  * once the value is read, no more read accesses to the registry will be made.\r
760  * this means the variable will contain a wrong value if the corresponding registry\r
761  * entry is changed by anything else than this variable! If you think that could happen\r
762  * then use \r
763  * \code\r
764  * regvalue.read();\r
765  * \endcode\r
766  * to force a refresh of the variable with the registry.\r
767  * a write to the registry is only made if the new value assigned with the variable\r
768  * is different than the last assigned value.\r
769  * to force a write use the method write();\r
770  * another option to force reads and writes to the registry is to specify TRUE as the\r
771  * third parameter in the constructor.\r
772  */\r
773 \r
774 #ifdef __ATLTYPES_H__   // defines CPoint \r
775 class CRegPoint : public CRegTypedBase<CPoint, CRegBase>\r
776 {\r
777 private:\r
778 \r
779     /**\r
780      * provide type-specific code to extract data from and write data to an open registry key.\r
781      */\r
782 \r
783     virtual void InternalRead (HKEY hKey, CPoint& value);\r
784     virtual void InternalWrite (HKEY hKey, const CPoint& value);\r
785 \r
786 public:\r
787         CRegPoint();\r
788         /**\r
789          * Constructor.\r
790          * \param key the path to the key, including the key. example: "Software\\Company\\SubKey\\MyValue"\r
791          * \param def the default value used when the key does not exist or a read error occurred\r
792          * \param force set to TRUE if no cache should be used, i.e. always read and write directly from/to registry\r
793          * \param base a predefined base key like HKEY_LOCAL_MACHINE. see the SDK documentation for more information.\r
794          */\r
795         CRegPoint(const CString& key, const CPoint& def = CPoint(), bool force = false, HKEY base = HKEY_CURRENT_USER);\r
796         ~CRegPoint(void);\r
797         \r
798     CRegPoint& operator=(const CPoint& rhs) {CRegTypedBase<CPoint, CRegBase>::operator =(rhs); return *this;}\r
799         CRegPoint& operator+=(CPoint p) { return *this = p + *this; }\r
800         CRegPoint& operator-=(CPoint p) { return *this = p - *this; }\r
801 };\r
802 #endif\r
803 \r
804 /**\r
805  * \ingroup Utils\r
806  * Manages a registry key (not a value). Provides methods to create and remove the\r
807  * key and to query the list of values and sub keys.\r
808  */\r
809 \r
810 #ifdef __AFXCOLL_H__   // defines CStringList \r
811 class CRegistryKey\r
812 {\r
813 public: //methods\r
814         /**\r
815          * Constructor.\r
816          * \param key the path to the key, including the key. example: "Software\\Company\\SubKey"\r
817          * \param base a predefined base key like HKEY_LOCAL_MACHINE. see the SDK documentation for more information.\r
818          */\r
819         CRegistryKey(const CString& key, HKEY base = HKEY_CURRENT_USER);\r
820         ~CRegistryKey();\r
821 \r
822         /**\r
823          * Creates the registry key if it does not already exist.\r
824          * \return ERROR_SUCCESS or an nonzero error code. Use FormatMessage() to get an error description.\r
825          */\r
826         DWORD createKey();\r
827         /**\r
828          * Removes the whole registry key including all values. So if you set the registry\r
829          * entry to be HKCU\Software\Company\Product\key there will only be\r
830          * HKCU\Software\Company\Product key in the registry.\r
831          * \return ERROR_SUCCESS or an nonzero error code. Use FormatMessage() to get an error description.\r
832          */\r
833         DWORD removeKey();\r
834 \r
835         bool getValues(CStringList& values);            ///< returns the list of values\r
836         bool getSubKeys(CStringList& subkeys);          ///< returns the list of sub keys\r
837 \r
838 public: //members\r
839         HKEY m_base;            ///< handle to the registry base\r
840         HKEY m_hKey;            ///< handle to the open registry key\r
841         CString m_path;         ///< the path to the key\r
842 };\r
843 #endif\r
844 \r
845 /**\r
846  * Instantiate templates for common (data type, string type) combinations.\r
847  */\r
848 \r
849 #ifdef __CSTRINGT_H__\r
850 CRegDWORDCommon<CRegBase>;\r
851 typedef CRegDWORDCommon<CRegBase> CRegDWORD;\r
852 CRegStringCommon<CRegBase>;\r
853 typedef CRegStringCommon<CRegBase> CRegString;\r
854 #endif\r
855 \r
856 CRegDWORDCommon<CRegStdBase>;\r
857 typedef CRegDWORDCommon<CRegStdBase> CRegStdWORD;\r
858 CRegStringCommon<CRegStdBase>;\r
859 typedef CRegStringCommon<CRegStdBase> CRegStdString;\r
860 \r
861 \r