Click here to Skip to main content
15,885,978 members
Articles / Desktop Programming / MFC

The SBJ MVC Framework - The Model, from Abstraction to Realization

Rate me:
Please Sign up or sign in to vote.
5.00/5 (19 votes)
20 Mar 2009CPOL19 min read 109.2K   1.3K   51  
A Model-View-Controller Framework that integrates with the MFC Doc/View architecture
//------------------------------------------------------------------------------
// $Workfile: Profile.h $
// $Header: /DevNet/SbjCore/SbjCore/Sys/Profile.h 7     2/13/08 10:27a Steve $
//
//	Copyright � 2006 Tartus, Inc.
// All rights reserved.
//
// The information contained herein is confidential, proprietary to
// Tartus, Inc., and considered a trade secret as defined
// in section 499C of the penal code of the State of California.  Use
// of this information by anyone other than authorized employees of
// Tartus, Inc. is granted only under a written non-disclosure
// agreement, which expressly prescribes the scope and manner of such
// use.
//
// *** Authors ***
//	 Neal O'Hara
//	 John La Porta
//	 Zhimin Lin
//	 Andreas Christmann
//	 Steve Johnson
//	 Frankie Jefferson
//	 Tartus, Inc.
//
// $Revision: 7 $
//
//-----------------------------------------------------------------------------

#pragma once

#include "StringUtils.h"

namespace SbjCore
{
	namespace Sys
	{
		/* SetSharedProfileState switches to Sharable Profile (i.e. Software\Company\App 
			becomes Software\Company\Shared\App) if bIsShareable is true. switches back
			on destruction.
		*/	
		struct SetSharedProfileStateImpl;
	
		class AFX_EXT_CLASS SetSharedProfileState 
		{
		public:
			SetSharedProfileState(bool bIsShareable);
			virtual ~SetSharedProfileState();
		private:
			struct SetSharedProfileStateImpl* const m_pImpl;
			
		};

		/////////////////////////////////////////////////////////////////////////////////////////////
		
		/* SetAlternateProfile switches to an alternate Profile section (i.e. Software\Company\App 
		becomes Software\Company\<AltProfile>). Switches back on destruction.
		*/	
		struct SetAlternateProfileImpl;

		class AFX_EXT_CLASS SetAlternateProfile 
		{
		public:
			SetAlternateProfile(LPCTSTR lpszAltProfile = NULL);
			virtual ~SetAlternateProfile();
		private:
			struct SetAlternateProfileImpl* const m_pImpl;

		};
		
		// CString specific /////////////////////////////////////////////////////////////////////////	

		const CString AFX_EXT_API GetProfileValue(
			LPCTSTR lpszSection, 
			LPCTSTR lpszEntry, 
			LPCTSTR lpszValue,
			bool bCreateEntry = true,
			bool bIsShareable = false);

		BOOL AFX_EXT_API WriteProfileValue(
			LPCTSTR lpszSection, 
			LPCTSTR lpszEntry, 
			LPCTSTR lpszValue,
			bool bIsShareable = false);


		// Template specific /////////////////////////////////////////////////////////////////////////	

		/** GetProfileValue gets a template value from the profile registry of CWinApp, uses stl to provide localization.
		
			\param T_VALUE any basic type or construct that implements the << stream operator.
		*/
		template <class T_VALUE> const T_VALUE GetProfileValue(
			LPCTSTR	lpszSection,									///< registry section
			LPCTSTR	lpszEntry,										///< registry entry
			const T_VALUE& nValue,									///< default value
			bool bCreateEntry = true,
			bool bIsShareable = false)								///< true to create missing entry in registry
		{
			CWinApp* pApp = ::AfxGetApp();

			if (pApp == NULL)
			{
				return nValue;
			}
			
			SetSharedProfileState theState(bIsShareable);
			
			CString sDefault(SbjCore::Utils::STR::ValueToStr(nValue));

			CString sVal(pApp->GetProfileString(lpszSection, lpszEntry, sDefault));

			if (bCreateEntry)
			{
				if (!pApp->WriteProfileString(lpszSection, lpszEntry, sVal))
				{
					TRACE(_T("Unable to write profile string: %s [%s] [%s]\n"), lpszSection, lpszEntry, (LPCTSTR) sVal);
				}
			}
			
			T_VALUE tValue = SbjCore::Utils::STR::StrToValue<T_VALUE>(sVal);

			return tValue;
		}


		/** WriteProfileValue writes a template value to the profile registry of CWinApp, uses stl to provide localization.
		
			\param T_VALUE any basic type or construct that implements the >> stream operator.
		*/
		template <class T_VALUE> BOOL WriteProfileValue(
			LPCTSTR lpszSection,								   ///< registry section
			LPCTSTR lpszEntry,									   ///< registry entry
			const T_VALUE& dValue,
			bool bIsShareable = false)								   ///< default value
		{
			CWinApp* pApp = ::AfxGetApp();

			if (pApp == NULL)
			{
				return FALSE;
			}

			SetSharedProfileState theState(bIsShareable);

			return pApp->WriteProfileString(lpszSection, lpszEntry, SbjCore::Utils::STR::ValueToStr(dValue));
		}

		/** The Persist class persists a template value to the profile registry of CWinApp. It reads 
			the value when initialized and writes when destructed
			
			\param T_VALUE any basic type or construct that implements the << and >> stream operators.
		*/
		template < class T_VALUE > 
		class ProfilePersist
		{
		protected:
			CString sSection;
			CString sEntry;
			bool bShareable;
		public:
			T_VALUE value;

			/// default ctor
			ProfilePersist()
			{
			}

			/// ctor - calls Init to read the persisted value from the registry				
			ProfilePersist(LPCTSTR lpszSection,			///< registry section
				LPCTSTR lpszEntry,						///< registry entry
				T_VALUE val,							///< default value
				bool bCreateEntry = true,
				bool bIsShareable = false)				///< true to create missing entry in registry
			{
				Init(lpszSection, lpszEntry, val, bCreateEntry, bIsShareable);
			}

			void Init(LPCTSTR lpszSection,				///< registry section
				LPCTSTR lpszEntry,						///< registry entry
				T_VALUE val,							///< default value
				bool bCreateEntry = true,
				bool bIsShareable = false)				///< true to create missing entry in registry
			{
				sSection = lpszSection;
				sEntry = lpszEntry;
				bShareable = bIsShareable;
				
				value = GetProfileValue(sSection, sEntry, val, bCreateEntry, bShareable);
			}

			/// dtor - calls Write() to write the persisted value to the registry
			virtual ~ProfilePersist()
			{
				Write();
			}
			
			/// Write writes the persisted value to the registry
			void Write()
			{
				WriteProfileValue(sSection, sEntry, value, bShareable);				
			}

		};
		

		///////////////////////////////////////////////////////////////////////

#pragma warning(disable:4700) // uninitialized local variable 'x' used			
		
		template<typename xtype>
		class Profile
		{
		public:
			Profile()
			{
			}
			
			Profile(LPCTSTR lpszSection, LPCTSTR lpszEntry, bool bIsShareable) : 
				sTheSection(lpszSection), 
				sTheEntry(lpszEntry), 
				bShareable(bIsShareable)
			{
			} 
			
			LPCTSTR GetSection() 
			{ 
				return sTheSection; 
			} 
			LPCTSTR GetEntry() 
			{ 
				return sTheEntry; 
			} 
			
			bool IsShareable()
			{
				return bShareable;
			}

		public:
					
			xtype GetProfile()
			{
				return OnGetProfile();
			}

			xtype GetDefault()
			{
				return OnGetDefault();
			}

			void ResetToDefault()
			{
				OnResetToDefault();
			}
			
			void WriteProfile(xtype aValue)
			{
				OnWriteProfile(aValue);
			}
			
		protected:
			CString sTheEntry;
			CString sTheSection;
			bool bShareable;
		private:
			virtual xtype OnGetProfile()
			{
				return xtype();
			}
			virtual xtype OnGetDefault()
			{
				return xtype();
			}
			virtual void OnResetToDefault() {};
			virtual void OnWriteProfile(xtype aType) { aType; };
		};
		
#pragma warning(default:4700)				
		
#define DECLARE_PROFILE_CLASS(tclass, ttype, tsection, tentry, tdefault, tshareable, tAltProfile) \
		template<typename xtype = ttype> \
		class tclass##T : public SbjCore::Sys::Profile<xtype> \
		{ \
		public: \
			tclass##T() : \
				SbjCore::Sys::Profile<xtype>(tsection, tentry, tshareable) \
			{ \
				SetDefault(tdefault);\
				ReadProfile(); \
			} \
			LPCTSTR GetSection() \
			{ \
				return sTheSection; \
			} \
			LPCTSTR GetEntry() \
			{ \
				return sTheEntry; \
			} \
		private: \
			void SetDefault(xtype aDefault) \
			{ \
				theDefault = aDefault; \
			} \
			void ReadProfile() \
			{ \
				if (!bBeenRead) \
				{ \
					bBeenRead = true; \
					SbjCore::Sys::SetAlternateProfile theAltProfile(tAltProfile); \
					theCurValue = SbjCore::Sys::GetProfileValue(GetSection(), GetEntry(), theDefault, true, bShareable); \
				} \
			} \
			virtual void OnWriteProfile(xtype aValue) \
			{ \
				SbjCore::Sys::SetAlternateProfile theAltProfile(tAltProfile); \
				theCurValue = aValue; \
				SbjCore::Sys::WriteProfileValue(sTheSection, sTheEntry, theCurValue, bShareable); \
			} \
			virtual xtype OnGetProfile() \
			{ \
				return theCurValue; \
			} \
			virtual xtype OnGetDefault() \
			{ \
				return theDefault; \
			} \
			virtual void OnResetToDefault() \
			{ \
  				SbjCore::Sys::SetAlternateProfile theAltProfile(tAltProfile); \
				theCurValue = theDefault; \
				SbjCore::Sys::WriteProfileValue(sTheSection, sTheEntry, theCurValue, bShareable); \
			} \
			private: \
				static xtype theDefault; \
				static xtype theCurValue; \
				static bool bBeenRead; \
		}; \
		template<typename xttype> \
		typename xttype tclass##T<xttype>::theDefault; \
		template<typename xttype> \
		typename xttype tclass##T<xttype>::theCurValue; \
		template<typename xttype> \
		typename bool tclass##T<xttype>::bBeenRead = false; \
		typedef tclass##T<> tclass; \

	}
}



//*** Modification History ***
// $Log: /DevNet/SbjCore/SbjCore/Sys/Profile.h $
// 
// 7     2/13/08 10:27a Steve
// Added Named Colors to ColorProp, Bold and Italics to Fonts and error
// checking to ProfiledFileProperty
// 
// 6     2/01/08 1:18p Steve
// 
// 5     1/25/08 5:51p Steve
// TTP 6463 BCF - Tools>Options View Settings - "Default" button shows
// current color, instead of default color.
// TTP 6465 BCF - Tools>Options View Settings - "Default" button is set to
// white for all items in Plan View Colors.
// 
// 4     11/09/07 2:40p Builder
// Adjusted Path for StringUtilsd.h
// 
// 3     11/09/07 1:40p Steve
// Revamped the Profile and Property code for Shared Profiles
// 
// 2     7/12/07 12:42a John
// Adjusted include path to start from SbjCore
// 
// 1     4/02/07 4:56p Steve
// 
// 4     1/04/07 1:02p Steve
// After dev box crash
// 
// 3     11/21/06 2:24p Steve
// 
// 2     4/24/06 3:32p Steve

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
SBJ
United States United States
Real name is Steve Johnson. Programming since 1979. Started on a Heathkit Micro with a DEC LSI-11 and UCSD Pascal. Moved to PCs & DOS as soon as Turbo Pascal became available. Did some Assembly, ISR, TSR etc. All this while working for a Manufacturing Co. for 8 years. Had my own solo Co. doing barcode labeling software for 4 years (terrible business man, all I wanted to do was code). Since then working for various software companies. Moved to Windows around the time of 3.1 with Borland C then C++. Then on to VC++ and MFC, and just about anything I could get my hands on or had to learn for my job, and been at it ever since. Of course recently I've been playing with .NET, ASP, C#, WPF etc.

Comments and Discussions