📄 sstate.h
字号:
// Copyright (c) 2002
// Sergey Klimov (kidd@ukr.net)
#ifndef __WTL_DW__SSTATE_H__
#define __WTL_DW__SSTATE_H__
#pragma once
#include<memory>
#include<utility>
#include<algorithm>
#include<map>
#include<cassert>
#include<limits>
#include<string>
#include<sstream>
namespace sstate{
const TCHAR ctxtGeneral[] = _T("General");
const TCHAR ctxtCXScreen[] =_T("SM_CXSCREEN");
const TCHAR ctxtCYScreen[] =_T("SM_CYSCREEN");
const TCHAR ctxtPlacement[] =_T("placement");
const TCHAR ctxtMainWindow[] =_T("Main Window");
const TCHAR ctxtVisible[] =_T("visible");
const TCHAR ctxtBand[] =_T("band");
const TCHAR ctxtStoreVer[] =_T("version");
typedef std::basic_string<TCHAR> tstring;
typedef unsigned long ID;
//i'll replace CRegKey with a abstract interface later ;)
struct IMainState
{
virtual float XRatio() const = 0;
virtual float YRatio() const = 0;
virtual CRegKey& MainKey()=0;
};
struct IState
{
virtual ~IState(){}
virtual bool Store(IMainState* /*pMState*/,CRegKey& /*key*/)=0;
virtual bool Restore(IMainState* /*pMState*/,CRegKey& /*key*/)=0;
virtual bool RestoreDefault()=0;
virtual void AddRef()=0;
virtual void Release()=0;
};
template<class T>
class CStateBase : public T
{
public:
CStateBase():m_ref(1)
{
}
virtual void AddRef()
{
m_ref++;
}
virtual void Release()
{
if(--m_ref==0)
delete this;
}
virtual ~CStateBase()
{
assert(m_ref==0);
}
protected:
unsigned long m_ref;
};
template<class T=IState>
class CStateHolder
{
typedef CStateHolder<T> thisClass;
public:
CStateHolder():m_pState(0)
{
}
CStateHolder(T* pState)
{
pState->AddRef();
m_pState=pState;
}
CStateHolder(const thisClass& sholder)
{
*this=(sholder);
}
thisClass& operator = (const thisClass& sholder)
{
m_pState=const_cast<T*>(sholder.m_pState);
if(m_pState!=0)
m_pState->AddRef();
return *this;
}
~CStateHolder()
{
if(m_pState!=0)
m_pState->Release();
}
const T* operator ->() const
{
return m_pState;
}
T* operator ->()
{
return m_pState;
}
protected:
T* m_pState;
};
class CMainState : public IMainState
{
public:
CMainState()
{
}
CMainState(LPCTSTR lpszKeyName):m_strMainKey(lpszKeyName)
{
}
CMainState(const tstring& strKeyName):m_strMainKey(strKeyName)
{
}
virtual CRegKey& MainKey()
{
assert(m_keyMain.m_hKey);
return m_keyMain;
}
virtual float XRatio() const
{
return m_xratio;
}
virtual float YRatio() const
{
return m_yratio;
}
bool Store()
{
DWORD dwDisposition;
assert(!m_strMainKey.empty());
bool bRes=(m_keyMain.Create(HKEY_CURRENT_USER,m_strMainKey.c_str(),REG_NONE,
REG_OPTION_NON_VOLATILE, KEY_WRITE|KEY_READ,
NULL,&dwDisposition)==ERROR_SUCCESS);
if(bRes)
{
CRegKey keyGeneral;
bRes=(keyGeneral.Create(m_keyMain,ctxtGeneral,REG_NONE,
REG_OPTION_NON_VOLATILE, KEY_WRITE|KEY_READ,
NULL,&dwDisposition)==ERROR_SUCCESS);
if(bRes)
{
DWORD val=::GetSystemMetrics(SM_CXSCREEN);
::RegSetValueEx(keyGeneral, ctxtCXScreen, NULL, REG_DWORD,
reinterpret_cast<BYTE*>(&val), sizeof(DWORD));
val=::GetSystemMetrics(SM_CYSCREEN);
::RegSetValueEx(keyGeneral, ctxtCYScreen, NULL, REG_DWORD,
reinterpret_cast<BYTE*>(&val), sizeof(DWORD));
/*
keyGeneral.SetValue(::GetSystemMetrics(SM_CXSCREEN),ctxtCXScreen);
keyGeneral.SetValue(::GetSystemMetrics(SM_CYSCREEN),ctxtCYScreen);
*/
}
}
return bRes;
}
bool Restore()
{
assert(!m_strMainKey.empty());
bool bRes=(m_keyMain.Open(HKEY_CURRENT_USER,m_strMainKey.c_str(),KEY_READ)==ERROR_SUCCESS);
if(bRes)
{
CRegKey keyGeneral;
bRes=(keyGeneral.Open(m_keyMain,ctxtGeneral,KEY_READ)==ERROR_SUCCESS);
{
SIZE szScreen;
DWORD dwCount = sizeof(DWORD);
m_xratio=(::RegQueryValueEx(keyGeneral,ctxtCXScreen,NULL,NULL,
reinterpret_cast<LPBYTE>(&szScreen.cx),&dwCount) ==ERROR_SUCCESS
&& (dwCount == sizeof(DWORD)))
?float(::GetSystemMetrics(SM_CXSCREEN))/szScreen.cx
:float(1.0);
dwCount = sizeof(DWORD);
m_yratio=(::RegQueryValueEx(keyGeneral,ctxtCYScreen,NULL,NULL,
reinterpret_cast<LPBYTE>(&szScreen.cy),&dwCount) ==ERROR_SUCCESS
&&(dwCount == sizeof(DWORD)))
?float(::GetSystemMetrics(SM_CYSCREEN))/szScreen.cy
:float(1.0);
/*
m_xratio=(keyGeneral.QueryValue(reinterpret_cast<DWORD&>(szScreen.cx),ctxtCXScreen)==ERROR_SUCCESS)
?float(::GetSystemMetrics(SM_CXSCREEN))/szScreen.cx
:float(1.0);
m_yratio=(keyGeneral.QueryValue(reinterpret_cast<DWORD&>(szScreen.cy),ctxtCYScreen)==ERROR_SUCCESS)
?float(::GetSystemMetrics(SM_CYSCREEN))/szScreen.cy
:float(1.0);
*/
}
}
return bRes;
}
public:
CRegKey m_keyMain;
tstring m_strMainKey;
float m_xratio;
float m_yratio;
};
class CContainerImpl : public CStateBase<IState>
{
protected:
typedef CStateHolder<IState> CItem;
typedef std::map<ID,CItem> CBunch;
class CStorer
{
public:
CStorer(IMainState* pMState,CRegKey& keyTop)
:m_pMState(pMState),m_keyTop(keyTop)
{
}
void operator() (std::pair<const ID,CItem>& x) const
{
std::basic_stringstream<TCHAR> sstrKey;
sstrKey.flags(std::ios::hex | std::ios::showbase );
sstrKey<<x.first;
CRegKey key;
DWORD dwDisposition;
LONG lRes = key.Create(m_keyTop,sstrKey.str().c_str(),REG_NONE,
REG_OPTION_NON_VOLATILE, KEY_WRITE|KEY_READ,
NULL,&dwDisposition);
if(lRes==ERROR_SUCCESS)
x.second->Store(m_pMState,key);
}
protected:
IMainState* m_pMState;
CRegKey& m_keyTop;
};
class CRestorer
{
public:
CRestorer(IMainState* pMState,CRegKey& keyTop)
:m_pMState(pMState),m_keyTop(keyTop)
{
}
void operator() (std::pair<const ID,CItem>& x) const
{
std::basic_stringstream<TCHAR> sstrKey;
sstrKey.flags(std::ios::hex | std::ios::showbase );
sstrKey<<x.first;
CRegKey key;
LONG lRes = key.Open(m_keyTop,sstrKey.str().c_str(),KEY_READ);
if(lRes==ERROR_SUCCESS)
x.second->Restore(m_pMState,key);
else
x.second->RestoreDefault();
}
protected:
IMainState* m_pMState;
CRegKey& m_keyTop;
};
struct CDefRestorer
{
void operator() (std::pair<const ID,CItem>& x) const
{
x.second->RestoreDefault();
}
};
public:
CContainerImpl():m_nextFreeID(/*std::numeric_limits<ID>::max()*/ULONG_MAX)
{
}
ID GetUniqueID() const
{
return m_nextFreeID--;
}
virtual bool Store(IMainState* pMState,CRegKey& key)
{
std::for_each(m_bunch.begin(),m_bunch.end(),CStorer(pMState,key));
return true;
}
virtual bool Restore(IMainState* pMState,CRegKey& key)
{
std::for_each(m_bunch.begin(),m_bunch.end(),CRestorer(pMState,key));
return true;
}
virtual bool RestoreDefault()
{
std::for_each(m_bunch.begin(),m_bunch.end(),CDefRestorer());
return true;
}
ID Add(IState* pState)
{
ID id=GetUniqueID();
Add(id,pState);
return id;
}
void Add(ID id,IState* pState)
{
CStateHolder<IState> h (pState);
m_bunch[id]=h;
}
void Remove(ID id)
{
assert(m_bunch.find(id)!=m_bunch.end());
m_bunch.erase(id);
}
protected:
mutable ID m_nextFreeID;
CBunch m_bunch;
};
class CWindowStateMgr
{
protected:
class CImpl : public CContainerImpl
{
typedef CContainerImpl baseClass;
public:
CImpl(HWND hWnd=NULL,int nDefCmdShow=SW_SHOWNOACTIVATE)
:m_hWnd(hWnd),m_nDefCmdShow(nDefCmdShow)
{
}
void SetWindow(HWND hWnd=NULL,int nDefCmdShow=SW_SHOWNOACTIVATE)
{
assert(::IsWindow(hWnd));
m_hWnd=hWnd;
m_nDefCmdShow=nDefCmdShow;
}
virtual bool Store(IMainState* pMState,CRegKey& key)
{
assert(IsWindow(m_hWnd));
WINDOWPLACEMENT wp;
wp.length = sizeof(WINDOWPLACEMENT);
bool bRes=false;
if (::GetWindowPlacement(m_hWnd,&wp))
{
wp.flags = 0;
if(::IsZoomed(m_hWnd))
wp.flags |= WPF_RESTORETOMAXIMIZED;
if(wp.showCmd==SW_SHOWMINIMIZED)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -