程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> VC >> VC++ >> 不用Hook也能實現方便快捷的換膚功能

不用Hook也能實現方便快捷的換膚功能

編輯:VC++

  大家都知道如果你想用一個好看的按鈕,你通常的做法是兩種: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;
  }

  優點:這個類不僅僅可以換界面還可以將工程當中的某些控件功能輕易的改變和還原.

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved