大家都知道如果你想用一個好看的按鈕,你通常的做法是兩種:1 映射按鈕變量 2 .h定義
CExButton m_btn;然後m_btn.SubclassDlgItem 。這兩種做法對於小程序,小工程沒有問題但是當工程一大,做起來特別費勁而且容易出錯,如果你想去掉這些換一種界面無疑是一場噩夢!下面介紹方法原理簡單,實用而且方便。
首先:
添加一個輔助類CLxpSkin
class CXPButton;
class CEditEx;
class CLineStatic;
class CFlatComboBox;
class CExCheckBox;
class CExGroupBox;
class CLxpSkin
{
public:
CLxpSkin(HWND hDlg); //一個類的實例對應一個對話框
~CLxpSkin();
public:
CList<CXPButton*,CXPButton *>m_btnList;//對應一個窗口下面所有的 button 鏈表
CList<CEditEx *,CEditEx *>m_edtList;//對應一個窗口下面所有的 edit 鏈表
CList<CLineStatic *,CLineStatic *>m_lineList;//對應一個窗口下面所有 static 鏈表
CList<CFlatComboBox *,CFlatComboBox *>m_cmbList;//對應一個窗口下面所有 ComboBox 鏈表
CList<CExCheckBox *,CExCheckBox *>m_chkList;//對應一個窗口下面所有 CheckBox 鏈表
CList<CExGroupBox *,CExGroupBox *>m_grpList;//對應一個窗口下面所有 CheckBox 鏈表
private: HWND m_hDlg;
public:
//記錄系統中所有每一個對話框窗口和其對應的LxpSkin類
static CMap< HWND, HWND, CLxpSkin* , CLxpSkin*>m_mapSkin;
static BOOL InstallSkin(HWND hDlg);
static void UnInstallSkin(HWND hDlg);
};
使用方法如下:
當做完上面的類之後你要做的就是在每個Dialog的OnInitDialog裡面寫上:CLxpSkin::InstallSkin(
m_hWnd)
在OnDestroy()裡面寫上CLxpSkin::UnInstallSkin(m_hWnd);
對應的Cpp文件如下:
CMap< HWND, HWND, CLxpSkin*, CLxpSkin*>CLxpSkin::m_mapSkin;
CLxpSkin::CLxpSkin(HWND hDlg):m_btnList(10),m_hDlg(hDlg)
{
}
CLxpSkin::~CLxpSkin()
{
POSITION pos=m_btnList.GetHeadPosition();
while(pos != NULL)
{
delete m_btnList.GetNext(pos);
}
pos=m_edtList.GetHeadPosition();
while(pos != NULL)
{
delete m_edtList.GetNext(pos);
}
pos=m_lineList.GetHeadPosition();
while(pos != NULL)
{
delete m_lineList.GetNext(pos);
}
pos=m_cmbList.GetHeadPosition();
while(pos != NULL)
{
delete m_cmbList.GetNext(pos);
}
pos=m_chkList.GetHeadPosition();
while(pos != NULL)
{
delete m_chkList.GetNext(pos);
}
pos=m_grpList.GetHeadPosition();
while(pos != NULL)
{
delete m_grpList.GetNext(pos);
}
}
BOOL CLxpSkin::InstallSkin(HWND hDlg)
{
ASSERT(::IsWindow(hDlg));
TCHAR szBuf[256];
HWND hWnd;
int nIdFirst;
DWORD dwStyle;
CLxpSkin * pSkin=new CLxpSkin(hDlg);
//將每一個對話框的句柄和每一個類實例映射起來
if(pSkin != NULL)
m_mapSkin.SetAt(hDlg,pSkin);
hWnd=GetWindow(hDlg,GW_CHILD);
if(hWnd == NULL || !::IsWindow(hWnd))
return FALSE;
nIdFirst=GetDlgCtrlID(hWnd);
do
{
GetClassName(hWnd,szBuf,256);
//Edit子類化
if( _tcsicmp(szBuf,_T("Edit")) == 0)
{
//驗證是否已經被永久映射
if(CWnd::FromHandlePermanent(hWnd) ==
NULL)
{
CEditEx *pEdit=new CEditEx();
if(pEdit == NULL)
return FALSE;
pSkin->m_edtList.AddTail(pEdit);
//子類化此窗口
pEdit->SubclassWindow(hWnd);
}
}
//button子類化
if(_tcsicmp(szBuf,_T("Button")) == 0)
{
dwStyle = GetWindowLong(hWnd,GWL_STYLE);
if((dwStyle & SS_TYPEMASK) == BS_DEFPUSHBUTTON)
dwStyle = BS_PUSHBUTTON;
if((dwStyle & SS_TYPEMASK) == BS_AUTOCHECKBOX)
dwStyle = BS_CHECKBOX;
TCHAR szBuf[256];
GetWindowText(hWnd,szBuf,256);
//PushButton子類化
if( (dwStyle & SS_TYPEMASK) == BS_PUSHBUTTON)
{
if(CWnd::FromHandlePermanent(hWnd) == NULL)
{
CXPButton *pBtn=new CXPButton();
if(pBtn == NULL)
return FALSE;
pSkin->m_btnList.AddTail(pBtn);
pBtn->SubclassWindow(hWnd);
}
}
//Checkbox子類化
else if( (dwStyle & SS_TYPEMASK) == BS_CHECKBOX
)
{
if(CWnd::FromHandlePermanent(hWnd) == NULL)
{
CExCheckBox *pChk=new CExCheckBox();
if(pChk == NULL)
return FALSE;
pSkin->m_chkList.AddTail(pChk);
pChk->SubclassWindow(hWnd);
}
}
else if( ( dwStyle & SS_TYPEMASK) == BS_GROUPBOX)
{
if(CWnd::FromHandlePermanent(hWnd) == NULL)
{
CExGroupBox *pGrp=new CExGroupBox();
if(pGrp == NULL)
return FALSE;
pSkin->m_grpList.AddTail(pGrp);
pGrp->SubclassWindow(hWnd);
}
}
}
//static子類化
if( (_tcsicmp(szBuf,_T("Static")) == 0)
&& (GetWindowLong(hWnd,GWL_STYLE) & SS_ETCHEDHORZ)
==
SS_ETCHEDHORZ)
{
if(CWnd::FromHandlePermanent(hWnd) == NULL)
{
CLineStatic * pLine=new CLineStatic();
if(pLine == NULL)
return FALSE;
pSkin->m_lineList.AddTail(pLine);
pLine->SubclassWindow(hWnd);
}
}
//ComboBox子類化
if( _tcsicmp(szBuf,_T("ComboBox")) == 0)
{
if(CWnd::FromHandlePermanent(hWnd) == NULL)
{
CFlatComboBox *pCmb=new CFlatComboBox();
if(pCmb == NULL)
return FALSE;
pSkin->m_cmbList.AddTail(pCmb);
pCmb->SubclassWindow(hWnd);
}
}
//etc
hWnd=GetWindow(hWnd,GW_HWNDNEXT);
if(!::IsWindow(hWnd) || hWnd==NULL)
break;
}while(nIdFirst != GetDlgCtrlID(hWnd));
return TRUE;
}
void CLxpSkin::UnInstallSkin(HWND hDlg)
{
CLxpSkin * pSkin=NULL;
if(m_mapSkin.Lookup(hDlg,pSkin))
{
delete pSkin;
pSkin=NULL;
}
return;
}
優點:這個類不僅僅可以換界面還可以將工程當中的某些控件功能輕易的改變和還原.