Details
There are a number of classes for working with the Windows Registry on The Code Project site, including:
All of these are helpful in one way or another, but using the Registry was still more work than it should be. To remedy this, I've come up with CPJRegistry
, which makes it much easier to save your MFC application settings.
Examples
Example 1: Load from the Registry
CPJRegistry Reg((CWinApp*)this, TRUE);
Reg.Section("Settings");
Reg.Profile("StartDate", m_StartDate);
Reg.Profile("UserName", m_strUserName);
Example 2: Save to the Registry
CPJRegistry Reg((CWinApp*)this, FALSE);
Reg.Section("Settings");
Reg.Profile("StartDate", m_StartDate);
Reg.Profile("UserName", m_strUserName);
Example 3: Load and save to the Registry
int CMyApp::GetPutRegistryData(BOOL bIsGet)
{
CPJRegistry Reg((CWinApp*)this, bIsGet);
Reg.Section("Settings");
Reg.Profile("StartDate", m_StartDate);
Reg.Profile("UserName", m_strUserName);
return 0;
}
Example 4: Load and save to the Registry, using the HKEY_LOCAL_MACHINE base key
int CMyApp::GetPutRegistryData(BOOL bIsGet)
{
CPJRegistry Reg((CWinApp*)this, bIsGet);
Reg.SetRoot(HKEY_LOCAL_MACHINE);
Reg.Section("Settings");
Reg.Profile("StartDate", m_StartDate);
Reg.Profile("UserName", m_strUserName);
return 0;
}
The final two examples show that separate code for loading and saving to the Registry isn't required. The following comments from the class header file describe and demonstrate how this class fits into a typical MFC application:
CMyApp::CMyApp()
{
m_nUseCount = 0;
m_bMadeSummary = FALSE;
m_strUserName = "";
m_StartDate = GetCurrentTime();
m_LastUsed = GetCurrentTime();
m_rcMainWindow = CRect(50, 50, 650, 450);
...
}
#include "PJRegistry.h"
#define GET_REGISTRY TRUE
#define PUT_REGISTRY FALSE
int CMyApp::GetPutRegistryData(BOOL bIsGet)
{
CPJRegistry Reg((CWinApp*)this, bIsGet);
Reg.RootKey(HKEY_LOCAL_MACHINE);
Reg.Section("Settings");
Reg.Profile("UseCount", m_nUseCount);
Reg.Profile("MadeSummary", m_bMadeSummary);
Reg.RootKey(HKEY_CURRENT_USER);
Reg.Section("Settings");
Reg.Profile("UserName", m_strUserName);
Reg.Profile("StartDate", m_StartDate);
Reg.Profile("LastUsed", m_LastUsed);
Reg.Section("MainWindow");
Reg.Profile("Position", m_rcMainWindow);
if (bIsGet)
{
if (m_LastUsed < m_StartDate)
m_StartDate = m_LastUsed;
}
return 0;
}
BOOL CMyApp::InitInstance()
{
...
LoadStdProfileSettings();
GetPutRegistryData(GET_REGISTRY);
...
}
int CMyApp::ExitInstance()
{
GetPutRegistryData(PUT_REGISTRY);
return CWinApp::ExitInstance();
}
On to the CPJRegistry
class definition.
class CPJRegistry
{
public:
CPJRegistry(CWinApp* pApp, BOOL bIsGet);
virtual ~CPJRegistry();
BOOL RootKey(HKEY hRootKey);
void Section(CString strSection);
long Profile(LPCTSTR lpszEntry, int& nValue);
long Profile(LPCTSTR lpszEntry, WORD& nValue);
long Profile(LPCTSTR lpszEntry, DWORD& dwValue);
long Profile(LPCTSTR lpszEntry, long& lValue);
long Profile(LPCTSTR lpszEntry, double& dValue);
long Profile(LPCTSTR lpszEntry, CString& strValue);
long Profile(LPCTSTR lpszEntry, CPoint& PointValue);
long Profile(LPCTSTR lpszEntry, CSize& Size);
long Profile(LPCTSTR lpszEntry, COleDateTime& DateTime);
long Profile(LPCTSTR lpszEntry, CRect& rcValue);
long Profile(LPCTSTR lpszEntry, LPBYTE pData, UINT& nBytes);
private:
CWinApp* m_pApp;
BOOL m_bGet;
CString m_strSection;
HKEY m_hRootKey;
HKEY m_hAppKey;
HKEY m_hSectionKey;
BOOL m_bDirty;
CString m_strCompanyName;
CString m_strAppName;
HKEY GetAppRegistryKey();
};
The overloaded routine Profile
accepts most common types, and will read and write to the Registry depending on the bIsGet
parameter passed on CPJRegistry
creation. If it fails, the passed variable retains it's initialized value. Profile
, and settings up your own GetPutRegistryData
routine, are the keys to making Registry use simple. Instead of separate Registry reading and writing routines, your GetPutRegistryData
routine does the work of both. Once you have written that, you need to call it in your InitInstance
to load, call it again in your ExitInstance
to save. Just a single line of code in your GetPutRegistryData
routine is required for each variable you want in the Registry.
One final note, UINT Profile(LPCTSTR lpszEntry, LPBYTE pData, UINT nBytes);
allows you to read/write binary data to the Registry. But, if you try and write a structure that contains pointers or classes you're going to have problems. Save the parts individually instead.
History
- May 15, 2001 -
CPJRegistry 2.0
has been re-written to support HKEY_LOCAL_MACHINE
, via the SetRoot
call.