📄 skin.cpp
字号:
//
// Skin.cpp
//
// Copyright (c) Shareaza Development Team, 2002-2004.
// This file is part of SHAREAZA (www.shareaza.com)
//
// Shareaza is free software; you can redistribute it
// and/or modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2 of
// the License, or (at your option) any later version.
//
// Shareaza is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Shareaza; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
#include "StdAfx.h"
#include "Shareaza.h"
#include "Settings.h"
#include "CoolInterface.h"
#include "CoolMenu.h"
#include "CtrlCoolBar.h"
#include "Skin.h"
#include "SkinWindow.h"
#include "ImageServices.h"
#include "ImageFile.h"
#include "Plugins.h"
#include "XML.h"
#include "WndChild.h"
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif
CSkin Skin;
//////////////////////////////////////////////////////////////////////
// CSkin construction
CSkin::CSkin()
{
}
CSkin::~CSkin()
{
Clear();
}
//////////////////////////////////////////////////////////////////////
// CSkin apply
void CSkin::Apply()
{
CreateDefault();
ApplyRecursive( NULL );
Finalise();
}
//////////////////////////////////////////////////////////////////////
// CSkin clear
void CSkin::Clear()
{
CString strName;
POSITION pos;
for ( pos = m_pMenus.GetStartPosition() ; pos ; )
{
CMenu* pMenu;
m_pMenus.GetNextAssoc( pos, strName, (void*&)pMenu );
delete pMenu;
}
for ( pos = m_pToolbars.GetStartPosition() ; pos ; )
{
CCoolBarCtrl* pBar;
m_pToolbars.GetNextAssoc( pos, strName, (void*&)pBar );
delete pBar;
}
for ( pos = m_pDialogs.GetStartPosition() ; pos ; )
{
CXMLElement* pXML;
m_pDialogs.GetNextAssoc( pos, strName, (void*&)pXML );
delete pXML;
}
for ( pos = m_pDocuments.GetStartPosition() ; pos ; )
{
CXMLElement* pXML;
m_pDocuments.GetNextAssoc( pos, strName, (void*&)pXML );
delete pXML;
}
for ( pos = m_pSkins.GetHeadPosition() ; pos ; )
{
delete (CSkinWindow*)m_pSkins.GetNext( pos );
}
for ( pos = m_pFontPaths.GetHeadPosition() ; pos ; )
{
RemoveFontResource( m_pFontPaths.GetNext( pos ) );
}
m_pStrings.RemoveAll();
m_pMenus.RemoveAll();
m_pToolbars.RemoveAll();
m_pDocuments.RemoveAll();
m_pWatermarks.RemoveAll();
m_pLists.RemoveAll();
m_pDialogs.RemoveAll();
m_pSkins.RemoveAll();
m_pFontPaths.RemoveAll();
if ( m_brDialog.m_hObject != NULL ) m_brDialog.DeleteObject();
if ( m_bmPanelMark.m_hObject != NULL ) m_bmPanelMark.DeleteObject();
}
//////////////////////////////////////////////////////////////////////
// CSkin caption selector
BOOL CSkin::SelectCaption(CWnd* pWnd, int nIndex)
{
CString strCaption;
pWnd->GetWindowText( strCaption );
if ( SelectCaption( strCaption, nIndex ) )
{
pWnd->SetWindowText( strCaption );
return TRUE;
}
return FALSE;
}
BOOL CSkin::SelectCaption(CString& strCaption, int nIndex)
{
for ( strCaption += '|' ; ; nIndex-- )
{
CString strSection = strCaption.SpanExcluding( _T("|") );
strCaption = strCaption.Mid( strSection.GetLength() + 1 );
if ( strSection.IsEmpty() ) break;
if ( nIndex <= 0 )
{
strCaption = strSection;
return TRUE;
}
}
return FALSE;
}
//////////////////////////////////////////////////////////////////////
// CSkin recursive folder applicator
void CSkin::ApplyRecursive(LPCTSTR pszPath)
{
WIN32_FIND_DATA pFind;
CString strPath;
HANDLE hSearch;
strPath.Format( _T("%s\\Skins\\%s*.*"), (LPCTSTR)Settings.General.Path,
pszPath ? pszPath : _T("") );
hSearch = FindFirstFile( strPath, &pFind );
if ( hSearch != INVALID_HANDLE_VALUE )
{
do
{
if ( pFind.cFileName[0] == '.' ) continue;
if ( pFind.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY )
{
strPath.Format( _T("%s%s\\"),
pszPath ? pszPath : _T(""), pFind.cFileName );
ApplyRecursive( strPath );
}
else if ( _tcsistr( pFind.cFileName, _T(".xml") ) != NULL &&
_tcsicmp( pFind.cFileName, _T("Definitions.xml") ) )
{
strPath.Format( _T("%s%s"),
pszPath ? pszPath : _T(""), pFind.cFileName );
if ( theApp.GetProfileInt( _T("Skins"), strPath, FALSE ) )
{
LoadFromFile( Settings.General.Path + _T("\\Skins\\") + strPath );
}
}
}
while ( FindNextFile( hSearch, &pFind ) );
FindClose( hSearch );
}
}
//////////////////////////////////////////////////////////////////////
// CSkin root load
BOOL CSkin::LoadFromFile(LPCTSTR pszFile)
{
CXMLElement* pXML = CXMLElement::FromFile( pszFile );
if ( pXML == NULL ) return FALSE;
CString strPath = pszFile;
int nSlash = strPath.ReverseFind( '\\' );
if ( nSlash >= 0 ) strPath = strPath.Left( nSlash + 1 );
BOOL bResult = LoadFromXML( pXML, strPath );
delete pXML;
return bResult;
}
BOOL CSkin::LoadFromResource(HINSTANCE hInstance, UINT nResourceID)
{
HMODULE hModule = hInstance != NULL ? (HMODULE)hInstance : GetModuleHandle( NULL );
HRSRC hRes = FindResource( hModule, MAKEINTRESOURCE( nResourceID ), MAKEINTRESOURCE( 23 ) );
if ( hRes == NULL ) return FALSE;
CString strBody;
DWORD nSize = SizeofResource( hModule, hRes );
HGLOBAL hMemory = ::LoadResource( hModule, hRes );
LPTSTR pszOutput = strBody.GetBuffer( nSize + 1 );
LPCSTR pszInput = (LPCSTR)LockResource( hMemory );
while ( nSize-- ) *pszOutput++ = *pszInput++;
*pszOutput++ = 0;
strBody.ReleaseBuffer();
CString strPath;
strPath.Format( _T("%lu$"), (DWORD)hModule );
return LoadFromString( strBody, strPath );
}
BOOL CSkin::LoadFromString(const CString& strXML, const CString& strPath)
{
CXMLElement* pXML = CXMLElement::FromString( strXML, TRUE );
if ( pXML == NULL ) return FALSE;
BOOL bSuccess = LoadFromXML( pXML, strPath );
delete pXML;
return bSuccess;
}
BOOL CSkin::LoadFromXML(CXMLElement* pXML, const CString& strPath)
{
if ( ! pXML->IsNamed( _T("skin") ) ) return FALSE;
BOOL bSuccess = FALSE;
for ( POSITION pos = pXML->GetElementIterator() ; pos ; )
{
CXMLElement* pSub = pXML->GetNextElement( pos );
bSuccess = FALSE;
if ( pSub->IsNamed( _T("commandImages") ) )
{
if ( ! LoadCommandImages( pSub, strPath ) ) break;
}
else if ( pSub->IsNamed( _T("watermarks" ) ) )
{
if ( ! LoadWatermarks( pSub, strPath ) ) break;
}
else if ( pSub->IsNamed( _T("windowSkins" ) ) )
{
if ( ! LoadWindowSkins( pSub, strPath ) ) break;
}
else if ( pSub->IsNamed( _T("menus") ) )
{
if ( ! LoadMenus( pSub ) ) break;
}
else if ( pSub->IsNamed( _T("toolbars") ) )
{
if ( ! LoadToolbars( pSub ) ) break;
}
else if ( pSub->IsNamed( _T("dialogs") ) )
{
if ( ! LoadDialogs( pSub ) ) break;
}
else if ( pSub->IsNamed( _T("strings") ) || pSub->IsNamed( _T("commandTips") ) )
{
if ( ! LoadStrings( pSub ) ) break;
}
else if ( pSub->IsNamed( _T("fonts" ) ) )
{
if ( ! LoadFonts( pSub, strPath ) ) break;
}
else if ( pSub->IsNamed( _T("colourScheme") ) )
{
if ( ! LoadColourScheme( pSub ) ) break;
}
else if ( pSub->IsNamed( _T("listColumns") ) )
{
if ( ! LoadListColumns( pSub ) ) break;
}
else if ( pSub->IsNamed( _T("commandMap") ) )
{
if ( ! LoadCommandMap( pSub ) ) break;
}
else if ( pSub->IsNamed( _T("documents" ) ) )
{
if ( ! LoadDocuments( pSub ) ) break;
}
else if ( pSub->IsNamed( _T("manifest") ) )
{
CString strType = pSub->GetAttributeValue( _T("type") );
strType.MakeLower();
if ( strType == _T("language") )
{
Settings.General.Language = pSub->GetAttributeValue( _T("language"), _T("en") );
}
}
bSuccess = TRUE;
}
return bSuccess;
}
//////////////////////////////////////////////////////////////////////
// CSkin strings
BOOL CSkin::LoadString(CString& str, UINT nStringID)
{
if ( m_pStrings.Lookup( nStringID, str ) ) return TRUE;
if ( str.LoadString( nStringID ) ) return TRUE;
str.Empty();
return FALSE;
}
BOOL CSkin::LoadStrings(CXMLElement* pBase)
{
for ( POSITION pos = pBase->GetElementIterator() ; pos ; )
{
CXMLElement* pXML = pBase->GetNextElement( pos );
if ( pXML->IsNamed( _T("string") ) )
{
if ( UINT nID = LookupCommandID( pXML ) )
{
CString strValue = pXML->GetAttributeValue( _T("value") );
while ( TRUE )
{
int nPos = strValue.Find( _T("\\n") );
if ( nPos < 0 ) break;
strValue = strValue.Left( nPos ) + _T("\n") + strValue.Mid( nPos + 2 );
}
// Hack for I64 compliance
if ( nID == IDS_DOWNLOAD_FRAGMENT_REQUEST || nID == IDS_DOWNLOAD_USEFUL_RANGE ||
nID == IDS_UPLOAD_CONTENT || nID == IDS_UPLOAD_PARTIAL_CONTENT ||
nID == IDS_DOWNLOAD_VERIFY_DROP )
{
Replace( strValue, _T("%lu"), _T("%I64i") );
}
m_pStrings.SetAt( nID, strValue );
}
}
else if ( pXML->IsNamed( _T("tip") ) )
{
if ( UINT nID = LookupCommandID( pXML ) )
{
CString strMessage = pXML->GetAttributeValue( _T("message") );
CString strTip = pXML->GetAttributeValue( _T("tip") );
if ( strTip.GetLength() ) strMessage += '\n' + strTip;
m_pStrings.SetAt( nID, strMessage );
}
}
}
return TRUE;
}
//////////////////////////////////////////////////////////////////////
// CSkin menus
CMenu* CSkin::GetMenu(LPCTSTR pszName)
{
LPCTSTR* pszModeSuffix = m_pszModeSuffix[ Settings.General.GUIMode ];
CString strName( pszName );
CMenu* pMenu = NULL;
for ( int nModeTry = 0 ; pszModeSuffix[ nModeTry ] ; nModeTry++ )
{
if ( m_pMenus.Lookup( strName + pszModeSuffix[ nModeTry ], (void*&)pMenu ) )
return pMenu;
for ( UINT nItem = 0 ; nItem < m_mnuDefault.GetMenuItemCount() ; nItem++ )
{
CString strItem;
m_mnuDefault.GetMenuString( nItem, strItem, MF_BYPOSITION );
if ( strItem.CompareNoCase( strName + pszModeSuffix[ nModeTry ] ) == 0 )
{
return m_mnuDefault.GetSubMenu( nItem );
}
}
}
return NULL;
}
BOOL CSkin::LoadMenus(CXMLElement* pBase)
{
for ( POSITION pos = pBase->GetElementIterator() ; pos ; )
{
CXMLElement* pXML = pBase->GetNextElement( pos );
if ( pXML->IsNamed( _T("menu") ) && ! LoadMenu( pXML ) ) return FALSE;
}
return TRUE;
}
BOOL CSkin::LoadMenu(CXMLElement* pXML)
{
CString strName = pXML->GetAttributeValue( _T("name") );
if ( strName.IsEmpty() ) return FALSE;
CMenu* pMenu = NULL;
if ( m_pMenus.Lookup( strName, (void*&)pMenu ) )
{
delete pMenu;
m_pMenus.RemoveKey( strName );
}
pMenu = new CMenu();
if ( pXML->GetAttributeValue( _T("type"), _T("popup") ).CompareNoCase( _T("bar") ) == 0 )
{
pMenu->CreateMenu();
}
else
{
pMenu->CreatePopupMenu();
}
if ( CreateMenu( pXML, pMenu->GetSafeHmenu() ) )
{
m_pMenus.SetAt( strName, pMenu );
return TRUE;
}
else
{
delete pMenu;
return FALSE;
}
}
BOOL CSkin::CreateMenu(CXMLElement* pRoot, HMENU hMenu)
{
for ( POSITION pos = pRoot->GetElementIterator() ; pos ; )
{
CXMLElement* pXML = pRoot->GetNextElement( pos );
CString strText = pXML->GetAttributeValue( _T("text") );
int nAmp = strText.Find( '_' );
if ( nAmp >= 0 ) strText.SetAt( nAmp, '&' );
if ( pXML->IsNamed( _T("item") ) )
{
if ( UINT nID = LookupCommandID( pXML ) )
{
CString strKeys = pXML->GetAttributeValue( _T("shortcut") );
if ( strKeys.GetLength() ) strText += '\t' + strKeys;
AppendMenu( hMenu, MF_STRING, nID, strText );
}
}
else if ( pXML->IsNamed( _T("menu") ) )
{
HMENU hSubMenu = CreatePopupMenu();
if ( ! CreateMenu( pXML, hSubMenu ) )
{
DestroyMenu( hSubMenu );
return FALSE;
}
AppendMenu( hMenu, MF_STRING|MF_POPUP, (UINT)hSubMenu, strText );
}
else if ( pXML->IsNamed( _T("separator") ) )
{
AppendMenu( hMenu, MF_SEPARATOR, ID_SEPARATOR, NULL );
}
}
return TRUE;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -