Main Page | Namespace List | Class Hierarchy | Class List | Directories | File List | Namespace Members | Class Members | File Members

SkinWindow.cpp

Go to the documentation of this file.
00001 //
00002 // SkinWindow.cpp
00003 //
00004 // Copyright (c) Shareaza Development Team, 2002-2005.
00005 // This file is part of SHAREAZA (www.shareaza.com)
00006 //
00007 // Shareaza is free software; you can redistribute it
00008 // and/or modify it under the terms of the GNU General Public License
00009 // as published by the Free Software Foundation; either version 2 of
00010 // the License, or (at your option) any later version.
00011 //
00012 // Shareaza is distributed in the hope that it will be useful,
00013 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00014 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015 // GNU General Public License for more details.
00016 //
00017 // You should have received a copy of the GNU General Public License
00018 // along with Shareaza; if not, write to the Free Software
00019 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00020 //
00021 
00022 #include "StdAfx.h"
00023 #include "Shareaza.h"
00024 #include "Settings.h"
00025 #include "CoolInterface.h"
00026 #include "SkinWindow.h"
00027 #include "XML.h"
00028 
00029 #ifdef _DEBUG
00030 #undef THIS_FILE
00031 static char THIS_FILE[]=__FILE__;
00032 #define new DEBUG_NEW
00033 #endif
00034 
00035 
00036 #define BORDER_WIDTH                    GetSystemMetrics( SM_CXSIZEFRAME )
00037 #define SIZEBOX_WIDTH                   GetSystemMetrics( SM_CXSIZE )
00038 
00039 
00041 // CSkinWindow construction
00042 
00043 CSkinWindow::CSkinWindow()
00044 {
00045         m_bPart         = new BOOL[ SKINPART_COUNT ];
00046         m_rcPart        = new CRect[ SKINPART_COUNT ];
00047         m_nPart         = new int[ SKINPART_COUNT ];
00048         m_bAnchor       = new BOOL[ SKINANCHOR_COUNT ];
00049         m_rcAnchor      = new CRect[ SKINANCHOR_COUNT ];
00050         
00051         ZeroMemory( m_bPart, sizeof(BOOL) * SKINPART_COUNT );
00052         ZeroMemory( m_nPart, sizeof(int) * SKINPART_COUNT );
00053         ZeroMemory( m_bAnchor, sizeof(BOOL) * SKINANCHOR_COUNT );
00054         
00055         m_szMinSize.cx = m_szMinSize.cy = 0;
00056         m_rcMaximise.SetRect( -1, 0, -1, -1 );
00057         m_rcResize.SetRect( BORDER_WIDTH, BORDER_WIDTH, BORDER_WIDTH, BORDER_WIDTH );
00058         
00059         m_hoSkin                        = NULL;
00060         m_bCaption                      = FALSE;
00061         m_bCaptionCaps          = FALSE;
00062         m_crCaptionFill         = CLR_NONE;
00063         m_crCaptionText         = RGB( 255, 255, 255 );
00064         m_crCaptionInactive     = RGB( 128, 128, 128 );
00065         m_crCaptionShadow       = CLR_NONE;
00066         m_crCaptionOutline      = CLR_NONE;
00067         m_nCaptionAlign         = 0;
00068         
00069         m_pRegionXML    = NULL;
00070         
00071         m_nHoverAnchor  = 0;
00072         m_nDownAnchor   = 0;
00073         m_nMirror = 0;
00074 }
00075 
00076 CSkinWindow::~CSkinWindow()
00077 {
00078         if ( m_dcSkin.m_hDC != NULL )
00079         {
00080                 if ( m_hoSkin != NULL ) m_dcSkin.SelectObject( CBitmap::FromHandle( m_hoSkin ) );
00081                 m_dcSkin.DeleteDC();
00082         }
00083         
00084         if ( m_bmSkin.m_hObject != NULL ) m_bmSkin.DeleteObject();
00085         
00086         if ( m_pRegionXML ) delete m_pRegionXML;
00087         
00088         for ( POSITION pos = m_pPartList.GetStartPosition() ; pos ; )
00089         {
00090                 CRect* pRect;
00091                 CString str;
00092                 m_pPartList.GetNextAssoc( pos, str, (void*&)pRect );
00093                 delete pRect;
00094         }
00095         
00096         for ( POSITION pos = m_pAnchorList.GetStartPosition() ; pos ; )
00097         {
00098                 CRect* pRect;
00099                 CString str;
00100                 m_pAnchorList.GetNextAssoc( pos, str, (void*&)pRect );
00101                 delete pRect;
00102         }
00103         
00104         delete [] m_bPart;
00105         delete [] m_rcPart;
00106         delete [] m_nPart;
00107         delete [] m_bAnchor;
00108         delete [] m_rcAnchor;
00109 }
00110 
00112 // CSkinWindow parse XML
00113 
00114 BOOL CSkinWindow::Parse(CXMLElement* pBase, const CString& strPath)
00115 {
00116         static LPCTSTR pszPart[] =
00117         {
00118                 _T("TopLeft"), _T("Top"), _T("TopRight"),
00119                 _T("TopLeftIA"), _T("TopIA"), _T("TopRightIA"),
00120                 _T("LeftTop"), _T("Left"), _T("LeftBottom"),
00121                 _T("RightTop"), _T("Right"), _T("RightBottom"),
00122                 _T("BottomLeft"), _T("Bottom"), _T("BottomRight"),
00123                 _T("System"), _T("SystemHover"), _T("SystemDown"),
00124                 _T("Minimise"), _T("MinimiseHover"), _T("MinimiseDown"),
00125                 _T("Maximise"), _T("MaximiseHover"), _T("MaximiseDown"),
00126                 _T("Close"), _T("CloseHover"), _T("CloseDown"),
00127                 NULL
00128         };
00129         
00130         static LPCTSTR pszAnchor[] =
00131         {
00132                 _T("Icon"), _T("System"), _T("Minimise"), _T("Maximise"), _T("Close"),
00133                 NULL
00134         };
00135         
00136         if ( ! pBase->IsNamed( _T("windowSkin") ) ) return FALSE;
00137         
00138         CString str;
00139         CRect rc;
00140         
00141         for ( POSITION pos = pBase->GetElementIterator() ; pos ; )
00142         {
00143                 CXMLElement* pGroup = pBase->GetNextElement( pos );
00144                 
00145                 if ( pGroup->IsNamed( _T("target") ) )
00146                 {
00147                         CString strTarget = pGroup->GetAttributeValue( _T("window") );
00148                         
00149                         if ( strTarget == _T("CMainTabBarCtrl") )
00150                                 strTarget = strTarget;
00151 
00152                         if ( strTarget.GetLength() )
00153                         {
00154                                 m_sTargets += '|';
00155                                 m_sTargets += strTarget;
00156                                 m_sTargets += '|';
00157                         }
00158                 }
00159                 else if ( pGroup->IsNamed( _T("parts") ) )
00160                 {
00161                         for ( POSITION posInner = pGroup->GetElementIterator() ; posInner ; )
00162                         {
00163                                 CXMLElement* pXML = pGroup->GetNextElement( posInner );
00164                                 if ( ! pXML->IsNamed( _T("part") ) ) continue;
00165                                 
00166                                 if ( ! ParseRect( pXML, &rc ) ) continue;
00167                                 if ( ! rc.Width() ) rc.right++;
00168                                 if ( ! rc.Height() ) rc.bottom++;
00169                                 
00170                                 CString strMode = pXML->GetAttributeValue( _T("mode") );
00171                                 int nMode = SKINPARTMODE_TILE;
00172                                 
00173                                 if ( strMode.CompareNoCase( _T("tile") ) == 0 )
00174                                         nMode = SKINPARTMODE_TILE;
00175                                 else if ( strMode.CompareNoCase( _T("stretch") ) == 0 )
00176                                         nMode = SKINPARTMODE_STRETCH;
00177                                 
00178                                 CString strName = pXML->GetAttributeValue( _T("name") );
00179                                 if ( strName.IsEmpty() ) continue;
00180                                 
00181                 int nPart = 0;
00182                                 for ( ; pszPart[ nPart ] ; nPart++ )
00183                                 {
00184                                         if ( _tcsicmp( strName, pszPart[ nPart ] ) == 0 )
00185                                         {
00186                                                 m_bPart[ nPart ]        = TRUE;
00187                                                 m_nPart[ nPart ]        = nMode;
00188                                                 m_rcPart[ nPart ]       = rc;
00189                                                 break;
00190                                         }
00191                                 }
00192                                 
00193                                 if ( pszPart[ nPart ] == NULL )
00194                                 {
00195                                         CRect* pRect;
00196                                         
00197                                         if ( m_pPartList.Lookup( strName, (void*&)pRect ) )
00198                                         {
00199                                                 *pRect = rc;
00200                                         }
00201                                         else
00202                                         {
00203                                                 pRect = new CRect( &rc );
00204                                                 m_pPartList.SetAt( strName, pRect );
00205                                         }
00206                                 }
00207                         }
00208                 }
00209                 else if ( pGroup->IsNamed( _T("anchors") ) )
00210                 {
00211                         for ( POSITION posInner = pGroup->GetElementIterator() ; posInner ; )
00212                         {
00213                                 CXMLElement* pXML = pGroup->GetNextElement( posInner );
00214                                 if ( ! pXML->IsNamed( _T("anchor") ) ) continue;
00215                                 
00216                                 if ( ! ParseRect( pXML, &rc ) ) continue;
00217                                 
00218                                 CString strName = pXML->GetAttributeValue( _T("name") );
00219                                 
00220                 int nAnchor = 0;
00221                                 for ( ; pszAnchor[ nAnchor ] ; nAnchor++ )
00222                                 {
00223                                         if ( _tcsicmp( strName, pszAnchor[ nAnchor ] ) == 0 )
00224                                         {
00225                                                 m_bAnchor[ nAnchor ]    = TRUE;
00226                                                 m_rcAnchor[ nAnchor ]   = rc;
00227                                                 break;
00228                                         }
00229                                 }
00230                                 
00231                                 if ( pszAnchor[ nAnchor ] == NULL )
00232                                 {
00233                                         CRect* pRect;
00234                                         if ( m_pAnchorList.Lookup( strName, (void*&)pRect ) )
00235                                         {
00236                                                 *pRect = rc;
00237                                         }
00238                                         else
00239                                         {
00240                                                 pRect = new CRect( &rc );
00241                                                 m_pAnchorList.SetAt( strName, pRect );
00242                                         }
00243                                         if ( strName == "Mirror" )
00244                                         {
00245                                                 m_nMirror = 1;
00246                                                 m_rcMirror = pRect;
00247                                         }
00248                                         if ( strName == "MirrorFull" )
00249                                         {
00250                                                 m_nMirror = 2;
00251                                                 m_rcMirror = pRect;
00252                                         }
00253                                 }
00254                         }
00255                 }
00256                 else if ( pGroup->IsNamed( _T("region") ) )
00257                 {
00258                         if ( m_pRegionXML ) delete m_pRegionXML;
00259                         m_pRegionXML = pGroup->Detach();
00260                 }
00261                 else if ( pGroup->IsNamed( _T("caption") ) )
00262                 {
00263                         m_bCaption = ParseRect( pGroup, &m_rcCaption );
00264                         
00265                         CString strFont = pGroup->GetAttributeValue( _T("fontFace") );
00266                         
00267                         if ( strFont.GetLength() )
00268                         {
00269                                 CString strSize = pGroup->GetAttributeValue( _T("fontSize") );
00270                                 CString strBold = pGroup->GetAttributeValue( _T("fontWeight") );
00271                                 
00272                                 if ( strBold.CompareNoCase( _T("bold") ) == 0 )
00273                                         strBold = _T("700");
00274                                 else if ( strBold.CompareNoCase( _T("normal") ) == 0 )
00275                                         strBold = _T("400");
00276                                 
00277                                 int nFontSize = 13, nFontWeight = FW_BOLD;
00278                                 _stscanf( strSize, _T("%i"), &nFontSize );
00279                                 _stscanf( strBold, _T("%i"), &nFontWeight );
00280                                 
00281                                 LOGFONT lf;
00282                                 ZeroMemory( &lf, sizeof(lf) );
00283                                 lf.lfHeight                     = nFontSize;
00284                                 lf.lfWeight                     = nFontWeight;
00285                                 lf.lfCharSet            = DEFAULT_CHARSET;
00286                                 lf.lfQuality            = DEFAULT_QUALITY;
00287                                 lf.lfOutPrecision       = OUT_DEFAULT_PRECIS;
00288                                 lf.lfClipPrecision      = CLIP_DEFAULT_PRECIS;
00289                                 lf.lfPitchAndFamily     = DEFAULT_PITCH|FF_DONTCARE;
00290                                 _tcscpy( lf.lfFaceName, strFont );
00291                                 
00292                                 if ( _tcsistr( strSize, _T("pt") ) != NULL )
00293                                 {
00294                                         m_fnCaption.CreatePointFontIndirect( &lf );
00295                                 }
00296                                 else
00297                                 {
00298                                         lf.lfHeight = -lf.lfHeight;
00299                                         m_fnCaption.CreateFontIndirect( &lf );
00300                                 }
00301                         }
00302                         
00303                         str = pGroup->GetAttributeValue( _T("colour") );
00304                         ParseColour( str, m_crCaptionText );
00305                         str = pGroup->GetAttributeValue( _T("inactiveColour") );
00306                         ParseColour( str, m_crCaptionInactive );
00307                         str = pGroup->GetAttributeValue( _T("fill") );
00308                         ParseColour( str, m_crCaptionFill );
00309                         str = pGroup->GetAttributeValue( _T("fillColour") );
00310                         ParseColour( str, m_crCaptionFill );
00311                         str = pGroup->GetAttributeValue( _T("shadowColour") );
00312                         ParseColour( str, m_crCaptionShadow );
00313                         str = pGroup->GetAttributeValue( _T("outlineColour") );
00314                         ParseColour( str, m_crCaptionOutline );
00315                         
00316                         str = pGroup->GetAttributeValue( _T("caps") );
00317                         m_bCaptionCaps = str.GetLength() > 0;
00318                         
00319                         str = pGroup->GetAttributeValue( _T("align") );
00320                         if ( str.CompareNoCase( _T("left") ) == 0 )
00321                                 m_nCaptionAlign = 0;
00322                         else if ( str.CompareNoCase( _T("center") ) == 0 )
00323                                 m_nCaptionAlign = 1;
00324                         else if ( str.CompareNoCase( _T("right") ) == 0 )
00325                                 m_nCaptionAlign = 2;
00326                         
00327                         if ( m_bCaption && m_fnCaption.m_hObject == NULL )
00328                         {
00329                                 NONCLIENTMETRICS pMetrics;
00330                                 pMetrics.cbSize = sizeof(pMetrics);
00331                                 SystemParametersInfo( SPI_GETNONCLIENTMETRICS, pMetrics.cbSize, &pMetrics, 0 );
00332                                 m_fnCaption.CreateFontIndirect( &pMetrics.lfCaptionFont );
00333                         }
00334                 }
00335                 else if ( pGroup->IsNamed( _T("image") ) )
00336                 {
00337                         str = pGroup->GetAttributeValue( _T("language") );
00338                         
00339                         if ( str.GetLength() > 0 )
00340                         {
00341                                 if ( str.CompareNoCase( Settings.General.Language ) != 0 ) continue;
00342                                 m_sLanguage = str;
00343                         }
00344                         
00345                         CString strRes  = pGroup->GetAttributeValue( _T("res") );
00346                         CString strFile = pGroup->GetAttributeValue( _T("path") );
00347                         HBITMAP hBitmap = NULL;
00348                         
00349                         if ( strFile.GetLength() > 0 )
00350                         {
00351                                 strFile = strPath + strFile;
00352                                 hBitmap = (HBITMAP)LoadImage( AfxGetInstanceHandle(), strFile,
00353                                         IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE );
00354                         }
00355                         else if ( strRes.GetLength() > 0 )
00356                         {
00357                                 UINT nResID = 0;
00358                                 if ( _stscanf( strRes, _T("%lu"), &nResID ) != 1 ) return FALSE;
00359                                 if ( nResID == IDB_NAVBAR_IMAGE && theApp.m_bRTL )
00360                                          nResID = IDB_NAVBAR_IMAGE_RTL;
00361                                 else if ( nResID == IDB_NAVBAR_ALPHA && theApp.m_bRTL )
00362                                          nResID = IDB_NAVBAR_ALPHA_RTL;
00363                                 hBitmap = (HBITMAP)LoadImage( AfxGetInstanceHandle(),
00364                                         MAKEINTRESOURCE(nResID), IMAGE_BITMAP, 0, 0, 0 );
00365                         }
00366                         
00367                         if ( hBitmap == NULL ) return FALSE;
00368                         
00369                         str = pGroup->GetAttributeValue( _T("type") );
00370                         CharLower( str.GetBuffer() );
00371                         str.ReleaseBuffer();
00372                         
00373                         if ( str == _T("watermark") || str == _T("water") )
00374                         {
00375                                 if ( m_bmWatermark.m_hObject != NULL ) m_bmWatermark.DeleteObject();
00376                                 m_bmWatermark.Attach( hBitmap );
00377                         }
00378                         else if ( str == _T("alpha") )
00379                         {
00380                                 if ( m_bmAlpha.m_hObject != NULL ) m_bmAlpha.DeleteObject();
00381                                 m_bmAlpha.Attach( hBitmap );
00382                         }
00383                         else
00384                         {
00385                                 if ( m_bmSkin.m_hObject != NULL ) m_bmSkin.DeleteObject();
00386                                 m_bmSkin.Attach( hBitmap );
00387                         }
00388                 }
00389                 else if ( pGroup->IsNamed( _T("maximiseCrop") ) )
00390                 {
00391                         ParseRect( pGroup, &m_rcMaximise );
00392                         m_rcMaximise.right -= m_rcMaximise.left;
00393                         m_rcMaximise.bottom -= m_rcMaximise.top;
00394                 }
00395                 else if ( pGroup->IsNamed( _T("resizeBorder") ) )
00396                 {
00397                         ParseRect( pGroup, &m_rcResize );
00398                         m_rcResize.right -= m_rcResize.left;
00399                         m_rcResize.bottom -= m_rcResize.top;
00400                 }
00401                 else if ( pGroup->IsNamed( _T("minimumSize") ) )
00402                 {
00403                         CString str = pGroup->GetAttributeValue( _T("width") );
00404                         _stscanf( str, _T("%i"), &m_szMinSize.cx );
00405                         str = pGroup->GetAttributeValue( _T("height") );
00406                         _stscanf( str, _T("%i"), &m_szMinSize.cy );
00407                 }
00408         }
00409         
00410         return ( m_bmSkin.m_hObject != NULL );
00411 }
00412 
00414 // CSkinWindow parse helpers
00415 
00416 BOOL CSkinWindow::ParseRect(CXMLElement* pXML, CRect* pRect)
00417 {
00418         CString strValue = pXML->GetAttributeValue( _T("rect") );
00419 
00420         if ( strValue.GetLength() )
00421         {
00422                 _stscanf( strValue, _T("%i,%i,%i,%i"), &pRect->left, &pRect->top,
00423                         &pRect->right, &pRect->bottom );
00424                 pRect->right += pRect->left;
00425                 pRect->bottom += pRect->top;
00426                 return TRUE;
00427         }
00428 
00429         strValue = pXML->GetAttributeValue( _T("point") );
00430 
00431         if ( strValue.GetLength() )
00432         {
00433                 _stscanf( strValue, _T("%i,%i"), &pRect->left, &pRect->top );
00434                 pRect->right = pRect->bottom = 0;
00435                 return TRUE;
00436         }
00437 
00438         return FALSE;
00439 }
00440 
00441 BOOL CSkinWindow::ParseColour(const CString& str, COLORREF& cr)
00442 {
00443         if ( str.GetLength() != 6 ) return FALSE;
00444 
00445         int nRed, nGreen, nBlue;
00446 
00447         if ( _stscanf( str.Mid( 0, 2 ), _T("%x"), &nRed ) != 1 ) return FALSE;
00448         if ( _stscanf( str.Mid( 2, 2 ), _T("%x"), &nGreen ) != 1 ) return FALSE;
00449         if ( _stscanf( str.Mid( 4, 2 ), _T("%x"), &nBlue ) != 1 ) return FALSE;
00450 
00451         cr = RGB( nRed, nGreen, nBlue );
00452 
00453         return TRUE;
00454 }
00455 
00457 // CSkinWindow window hooks
00458 
00459 void CSkinWindow::CalcWindowRect(RECT* pRect, BOOL bToClient, BOOL bZoomed)
00460 {
00461         CRect rcAdjust( 0, 0, 0, 0 );
00462 
00463         if ( m_bPart[ SKINPART_TOP_LEFT ] )
00464                 rcAdjust.top = max( rcAdjust.top, LONG(m_rcPart[ SKINPART_TOP_LEFT ].Height()) );
00465         if ( m_bPart[ SKINPART_TOP ] )
00466                 rcAdjust.top = max( rcAdjust.top, LONG(m_rcPart[ SKINPART_TOP ].Height()) );
00467         if ( m_bPart[ SKINPART_TOP_RIGHT ] )
00468                 rcAdjust.top = max( rcAdjust.top, LONG(m_rcPart[ SKINPART_TOP_RIGHT ].Height()) );
00469 
00470         if ( m_bPart[ SKINPART_LEFT ] )
00471                 rcAdjust.left = max( rcAdjust.left, LONG(m_rcPart[ SKINPART_LEFT ].Width()) );
00472         
00473         if ( m_bPart[ SKINPART_RIGHT ] )
00474                 rcAdjust.right = max( rcAdjust.right, LONG(m_rcPart[ SKINPART_RIGHT ].Width()) );
00475         
00476         if ( m_bPart[ SKINPART_BOTTOM_LEFT ] )
00477                 rcAdjust.bottom = max( rcAdjust.bottom, LONG(m_rcPart[ SKINPART_BOTTOM_LEFT ].Height()) );
00478         if ( m_bPart[ SKINPART_BOTTOM ] )
00479                 rcAdjust.bottom = max( rcAdjust.bottom, LONG(m_rcPart[ SKINPART_BOTTOM ].Height()) );
00480         if ( m_bPart[ SKINPART_BOTTOM_RIGHT ] )
00481                 rcAdjust.bottom = max( rcAdjust.bottom, LONG(m_rcPart[ SKINPART_BOTTOM_RIGHT ].Height()) );
00482 
00483         if ( bToClient )
00484         {
00485                 pRect->left             += rcAdjust.left;
00486                 pRect->top              += rcAdjust.top;
00487                 pRect->right    -= rcAdjust.right;
00488                 pRect->bottom   -= rcAdjust.bottom;
00489         }
00490         else
00491         {
00492                 pRect->left             -= rcAdjust.left;
00493                 pRect->top              -= rcAdjust.top;
00494                 pRect->right    += rcAdjust.right;
00495                 pRect->bottom   += rcAdjust.bottom;
00496         }
00497 }
00498 
00499 void CSkinWindow::OnNcCalcSize(CWnd* pWnd, BOOL bCalcValidRects, NCCALCSIZE_PARAMS FAR* lpncsp)
00500 {
00501         CalcWindowRect( &lpncsp->rgrc[0], TRUE, pWnd->IsZoomed() );
00502 }
00503 
00504 void CSkinWindow::OnGetMinMaxInfo(MINMAXINFO* lpMMI)
00505 {
00506         CRect rcWork;
00507         if ( theApp.m_pfnGetMonitorInfoA != NULL ) //If GetMonitorInfo() is available
00508         {
00509                 MONITORINFO oMonitor;
00510                 ZeroMemory( &oMonitor, sizeof(oMonitor) );
00511                 oMonitor.cbSize = sizeof(oMonitor);
00512                 theApp.m_pfnGetMonitorInfoA( theApp.m_pfnMonitorFromWindow( AfxGetMainWnd()->GetSafeHwnd(), MONITOR_DEFAULTTOPRIMARY ), &oMonitor );
00513                 
00514                 rcWork = oMonitor.rcWork;
00515         }
00516         else
00517         {
00518                 SystemParametersInfo( SPI_GETWORKAREA, 0, &rcWork, 0 );
00519         }
00520         rcWork.OffsetRect( -rcWork.left, -rcWork.top );
00521         
00522         CRect rcAdjusted( &rcWork );
00523         CalcWindowRect( &rcAdjusted, FALSE, TRUE );
00524         
00525         if ( m_rcMaximise.left < 0 )
00526                 rcWork.left = rcAdjusted.left;
00527         else
00528                 rcWork.left -= m_rcMaximise.left;
00529         
00530         if ( m_rcMaximise.top < 0 )
00531                 rcWork.top = rcAdjusted.top;
00532         else
00533                 rcWork.top -= m_rcMaximise.top;
00534         
00535         if ( m_rcMaximise.right < 0 )
00536                 rcWork.right = rcAdjusted.right;
00537         else
00538                 rcWork.right += m_rcMaximise.right;
00539         
00540         if ( m_rcMaximise.bottom < 0 )
00541                 rcWork.bottom = rcAdjusted.bottom;
00542         else
00543                 rcWork.bottom += m_rcMaximise.bottom;
00544         
00545         lpMMI->ptMaxPosition.x  = rcWork.left;
00546         lpMMI->ptMaxPosition.y  = rcWork.top;
00547         lpMMI->ptMaxSize.x              = rcWork.right;
00548         lpMMI->ptMaxSize.y              = rcWork.bottom;
00549         
00550         lpMMI->ptMinTrackSize.x = max( lpMMI->ptMinTrackSize.x, m_szMinSize.cx );
00551         lpMMI->ptMinTrackSize.y = max( lpMMI->ptMinTrackSize.y, m_szMinSize.cy );
00552 }
00553 
00554 UINT CSkinWindow::OnNcHitTest(CWnd* pWnd, CPoint point, BOOL bResizable)
00555 {
00556         CRect rc, rcAnchor;
00557         int nPointX;
00558 
00559         pWnd->GetWindowRect( &rc );
00560         if ( theApp.m_bRTL )
00561         {
00562                 nPointX = point.x;
00563                 point.x = 2 * rc.left + rc.Width() - point.x;
00564         }
00565                 
00566         if ( m_bAnchor[ SKINANCHOR_SYSTEM ] )
00567         {
00568                 ResolveAnchor( rc, rcAnchor, SKINANCHOR_SYSTEM );
00569                 if ( rcAnchor.PtInRect( point ) ) return HTSYSMENU;
00570         }
00571         
00572         if ( m_bAnchor[ SKINANCHOR_MINIMISE ] )
00573         {
00574                 ResolveAnchor( rc, rcAnchor, SKINANCHOR_MINIMISE );
00575                 if ( rcAnchor.PtInRect( point ) ) return HTREDUCE;
00576         }
00577         
00578         if ( m_bAnchor[ SKINANCHOR_MAXIMISE ] )
00579         {
00580                 ResolveAnchor( rc, rcAnchor, SKINANCHOR_MAXIMISE );
00581                 if ( rcAnchor.PtInRect( point ) ) return HTZOOM;
00582         }
00583         
00584         if ( m_bAnchor[ SKINANCHOR_CLOSE ] )
00585         {
00586                 ResolveAnchor( rc, rcAnchor, SKINANCHOR_CLOSE );
00587                 if ( rcAnchor.PtInRect( point ) ) return HTCLOSE;
00588         }
00589         
00590         if ( theApp.m_bRTL ) point.x = nPointX;
00591         if ( bResizable && ! pWnd->IsZoomed() )
00592         {
00593                 if ( point.x >= rc.right - SIZEBOX_WIDTH && point.y >= rc.bottom - SIZEBOX_WIDTH )
00594                         return HTBOTTOMRIGHT;
00595                 
00596                 if ( point.x < rc.left + m_rcResize.left )
00597                 {
00598                         if ( point.y < rc.top + m_rcResize.top ) return HTTOPLEFT;
00599                         else if ( point.y >= rc.bottom - m_rcResize.bottom ) return HTBOTTOMLEFT;
00600                         else return HTLEFT;
00601                 }
00602                 else if ( point.x >= rc.right - m_rcResize.right )
00603                 {
00604                         if ( point.y < rc.top + m_rcResize.top ) return HTTOPRIGHT;
00605                         else if ( point.y >= rc.bottom - m_rcResize.bottom ) return HTBOTTOMRIGHT;
00606                         else return HTRIGHT;
00607                 }
00608                 else if ( point.y < rc.top + m_rcResize.top )
00609                 {
00610                         if ( point.x < rc.left + m_rcResize.left ) return HTTOPLEFT;
00611                         else if ( point.x >= rc.right - m_rcResize.right ) return HTTOPRIGHT;
00612                         return HTTOP;
00613                 }
00614                 else if ( point.y >= rc.bottom - m_rcResize.bottom )
00615                 {
00616                         if ( point.x < rc.left + m_rcResize.left ) return HTBOTTOMLEFT;
00617                         else if ( point.x >= rc.right - m_rcResize.right ) return HTBOTTOMRIGHT;
00618                         return HTBOTTOM;
00619                 }
00620         }
00621         
00622         OnNcCalcSize( pWnd, FALSE, (NCCALCSIZE_PARAMS*)&rc );
00623         
00624         if ( point.y < rc.top ) return HTCAPTION;
00625         
00626         return rc.PtInRect( point ) ? HTCLIENT : HTBORDER;
00627 }
00628 
00629 void CSkinWindow::OnNcPaint(CWnd* pWnd)
00630 {
00631         CWindowDC dc( pWnd );
00632         if ( theApp.m_bRTL ) theApp.m_pfnSetLayout( dc.m_hDC, LAYOUT_RTL ); 
00633         Paint( pWnd, dc, FALSE );
00634 }
00635 
00636 BOOL CSkinWindow::OnNcActivate(CWnd* pWnd, BOOL bActive)
00637 {
00638         CWindowDC dc( pWnd );
00639         if ( theApp.m_bRTL ) theApp.m_pfnSetLayout( dc.m_hDC, LAYOUT_RTL ); 
00640         Paint( pWnd, dc, TRUE, bActive ? TS_TRUE : TS_FALSE );
00641         return FALSE;
00642 }
00643 
00644 void CSkinWindow::OnSetText(CWnd* pWnd)
00645 {
00646         CWindowDC dc( pWnd );
00647         if ( theApp.m_bRTL ) theApp.m_pfnSetLayout( dc.m_hDC, LAYOUT_RTL ); 
00648         Paint( pWnd, dc, TRUE );
00649 }
00650 
00651 void CSkinWindow::OnSize(CWnd* pWnd)
00652 {
00653         if ( pWnd->IsIconic() ) return;
00654         
00655         if ( pWnd->IsZoomed() )
00656         {
00657                 if ( theApp.m_pfnGetMonitorInfoA != NULL )
00658                 {
00659                         CRect rcWnd;
00660                         SystemParametersInfo( SPI_GETWORKAREA, 0, rcWnd, 0 );
00661                         
00662                         HMONITOR hMonitor = theApp.m_pfnMonitorFromWindow( pWnd->GetSafeHwnd(), MONITOR_DEFAULTTONEAREST );
00663                         MONITORINFO mi;
00664                         memset( &mi, 0, sizeof(MONITORINFO) );
00665                         mi.cbSize = sizeof(MONITORINFO);
00666                         VERIFY( GetMonitorInfo( hMonitor, &mi ) );
00667 
00668                         if ( mi.dwFlags & MONITORINFOF_PRIMARY )
00669                                 SetWindowPos( pWnd->m_hWnd, HWND_TOP, rcWnd.left, rcWnd.top, rcWnd.Width(), 
00670                                         rcWnd.Height(), 0 );
00671                 }
00672                 pWnd->SetWindowRgn( NULL, TRUE );
00673         }
00674         else if ( m_pRegionXML )
00675         {
00676                 SelectRegion( pWnd );
00677         }
00678         else if ( CoolInterface.IsNewWindows() )
00679         {
00680                 CRect rcWnd;
00681                 
00682                 pWnd->GetWindowRect( &rcWnd );
00683                         rcWnd.OffsetRect( -rcWnd.left, -rcWnd.top );
00684                         rcWnd.right++; rcWnd.bottom++;
00685                 
00686                 HRGN hRgn = CreateRectRgnIndirect( &rcWnd );
00687                 pWnd->SetWindowRgn( hRgn, TRUE );
00688         }
00689 }
00690 
00691 BOOL CSkinWindow::OnEraseBkgnd(CWnd* pWnd, CDC* pDC)
00692 {
00693         if ( m_bmWatermark.m_hObject == NULL ) return FALSE;
00694         
00695         if ( ! m_dcSkin.m_hDC ) m_dcSkin.CreateCompatibleDC( pDC );
00696         CBitmap* pOldImage = (CBitmap*)m_dcSkin.SelectObject( &m_bmWatermark );
00697         
00698         BITMAP pWatermark;
00699         CRect rc;
00700         
00701         pWnd->GetClientRect( &rc );
00702         m_bmWatermark.GetBitmap( &pWatermark );
00703         
00704         for ( int nY = rc.top ; nY < rc.bottom ; nY += pWatermark.bmHeight )
00705         {
00706                 for ( int nX = rc.left ; nX < rc.right ; nX += pWatermark.bmWidth )
00707                 {
00708                         pDC->BitBlt( nX, nY, pWatermark.bmWidth, pWatermark.bmHeight, &m_dcSkin, 0, 0, SRCCOPY );
00709                 }
00710         }
00711         
00712         m_dcSkin.SelectObject( pOldImage );
00713         return TRUE;
00714 }
00715 
00716 void CSkinWindow::OnNcMouseMove(CWnd* pWnd, UINT nHitTest, CPoint point)
00717 {
00718         int nAnchor = 0;
00719         if ( nHitTest == HTSYSMENU ) nAnchor = SKINANCHOR_SYSTEM;
00720         else if ( nHitTest == HTREDUCE ) nAnchor = SKINANCHOR_MINIMISE;
00721         else if ( nHitTest == HTZOOM ) nAnchor = SKINANCHOR_MAXIMISE;
00722         else if ( nHitTest == HTCLOSE ) nAnchor = SKINANCHOR_CLOSE;
00723 
00724         if ( m_nDownAnchor && m_nDownAnchor != nAnchor )
00725         {
00726                 if ( ( GetAsyncKeyState( VK_LBUTTON ) & 0x8000 ) == 0 )
00727                         m_nDownAnchor = 0;
00728                 nAnchor = 0;
00729         }
00730 
00731         if ( nAnchor != m_nHoverAnchor )
00732         {
00733                 m_nHoverAnchor = nAnchor;
00734                 CWindowDC dc( pWnd );
00735                 if ( theApp.m_bRTL ) theApp.m_pfnSetLayout( dc.m_hDC, LAYOUT_RTL ); 
00736                 Paint( pWnd, dc, TRUE );
00737         }       
00738 }
00739 
00740 BOOL CSkinWindow::OnNcLButtonDown(CWnd* pWnd, UINT nHitTest, CPoint point)
00741 {
00742         int nAnchor = 0;
00743         if ( nHitTest == HTSYSMENU ) nAnchor = SKINANCHOR_SYSTEM;
00744         else if ( nHitTest == HTREDUCE ) nAnchor = SKINANCHOR_MINIMISE;
00745         else if ( nHitTest == HTZOOM ) nAnchor = SKINANCHOR_MAXIMISE;
00746         else if ( nHitTest == HTCLOSE ) nAnchor = SKINANCHOR_CLOSE;
00747         else return FALSE;
00748 
00749         m_nHoverAnchor = m_nDownAnchor = nAnchor;
00750 
00751         if ( nAnchor == SKINANCHOR_SYSTEM )
00752         {
00753                 CRect rcWindow, rcSystem;
00754 
00755                 pWnd->GetWindowRect( &rcWindow );
00756                 ResolveAnchor( rcWindow, rcSystem, SKINANCHOR_SYSTEM );
00757                 CMenu* pPopup = pWnd->GetSystemMenu( FALSE );
00758 
00759                 CWindowDC dc( pWnd );
00760                 if ( theApp.m_bRTL ) theApp.m_pfnSetLayout( dc.m_hDC, LAYOUT_RTL );
00761                 Paint( pWnd, dc, TRUE );
00762 
00763                 DWORD nTime = GetTickCount();
00764 
00765                 UINT nCmdID = pPopup->TrackPopupMenu( TPM_LEFTALIGN|TPM_TOPALIGN|TPM_RETURNCMD,
00766                         theApp.m_bRTL ? rcWindow.right - rcSystem.left + rcWindow.left : rcSystem.left, 
00767                         rcSystem.bottom, pWnd, NULL );
00768 
00769                 m_nHoverAnchor = m_nDownAnchor = 0;
00770 
00771                 if ( nCmdID )
00772                 {
00773                         pWnd->PostMessage( WM_SYSCOMMAND, nCmdID, MAKELONG( rcSystem.left, rcSystem.bottom ) );
00774                 }
00775                 else if ( GetTickCount() - nTime < 300 )
00776                 {
00777                         GetCursorPos( &point );
00778                         if ( OnNcHitTest( pWnd, point, FALSE ) == HTSYSMENU )
00779                         {
00780                                 pWnd->PostMessage( WM_SYSCOMMAND, SC_CLOSE, MAKELONG( rcSystem.left, rcSystem.bottom ) );
00781                         }
00782                 }
00783         }
00784 
00785         CWindowDC dc( pWnd );
00786         if ( theApp.m_bRTL ) theApp.m_pfnSetLayout( dc.m_hDC, LAYOUT_RTL );
00787         Paint( pWnd, dc, TRUE );
00788 
00789         return TRUE;
00790 }
00791 
00792 BOOL CSkinWindow::OnNcLButtonUp(CWnd* pWnd, UINT nHitTest, CPoint point)
00793 {
00794         if ( ! m_nDownAnchor ) return FALSE;
00795 
00796         if ( m_nDownAnchor == m_nHoverAnchor )
00797         {
00798                 switch ( m_nDownAnchor )
00799                 {
00800                 case SKINANCHOR_MINIMISE:
00801                         pWnd->PostMessage( WM_SYSCOMMAND, SC_MINIMIZE );
00802                         break;
00803                 case SKINANCHOR_MAXIMISE:
00804                         pWnd->PostMessage( WM_SYSCOMMAND, pWnd->IsZoomed() ? SC_RESTORE : SC_MAXIMIZE );
00805                         break;
00806                 case SKINANCHOR_CLOSE:
00807                         pWnd->PostMessage( WM_SYSCOMMAND, SC_CLOSE );
00808                         break;
00809                 }
00810         }
00811 
00812         m_nHoverAnchor = 0;
00813         m_nDownAnchor = 0;
00814         
00815         CWindowDC dc( pWnd );
00816         if ( theApp.m_bRTL ) theApp.m_pfnSetLayout( dc.m_hDC, LAYOUT_RTL );
00817         Paint( pWnd, dc, TRUE );
00818 
00819         return FALSE;
00820 }
00821 
00822 BOOL CSkinWindow::OnNcLButtonDblClk(CWnd* pWnd, UINT nHitTest, CPoint point)
00823 {
00824         if ( nHitTest == HTSYSMENU )
00825         {
00826                 pWnd->PostMessage( WM_SYSCOMMAND, SC_CLOSE );
00827                 return TRUE;
00828         }
00829 
00830         return FALSE;
00831 }
00832 
00834 // CSkinWindow paint
00835 
00836 void CSkinWindow::Prepare(CDC* pDC)
00837 {
00838         if ( m_dcSkin.m_hDC == NULL )
00839                 m_dcSkin.CreateCompatibleDC( pDC );
00840         if ( m_hoSkin == NULL )
00841                 m_hoSkin = (HBITMAP)m_dcSkin.SelectObject( &m_bmSkin )->GetSafeHandle();
00842         if ( theApp.m_bRTL ) theApp.m_pfnSetLayout( m_dcSkin.m_hDC, LAYOUT_BITMAPORIENTATIONPRESERVED ); 
00843 }
00844 
00845 void CSkinWindow::Paint(CWnd* pWnd, CDC& dc, BOOL bCaption, TRISTATE bActive)
00846 {
00847         HICON hIcon = NULL;
00848         CString strCaption;
00849         CRect rc, rcItem;
00850         
00851         Prepare( &dc );
00852         
00853         pWnd->GetWindowRect( &rc );
00854         rc.OffsetRect( -rc.left, -rc.top );
00855 
00856         if ( bActive == TS_UNKNOWN )
00857         {
00858                 if ( pWnd->IsKindOf( RUNTIME_CLASS(CMDIChildWnd) ) )
00859                 {
00860                         CMDIFrameWnd* pFrame = ((CMDIChildWnd*)pWnd)->GetMDIFrame();
00861                         bActive = pFrame->MDIGetActive() == pWnd ? TS_TRUE : TS_FALSE;
00862                 }
00863                 else
00864                 {
00865                         bActive = CWnd::GetForegroundWindow() == pWnd ? TS_TRUE : TS_FALSE;
00866                 }
00867         }
00868         
00869         BOOL bZoomed = pWnd->IsZoomed();
00870         
00871         if ( m_bCaption )
00872         {
00873                 pWnd->GetWindowText( strCaption );
00874                 if ( m_bCaptionCaps )
00875                 {
00876                         CharUpper( strCaption.GetBuffer() );
00877                         strCaption.ReleaseBuffer();
00878                 }
00879         }
00880         
00881         if ( m_bAnchor[ SKINANCHOR_ICON ] )
00882         {
00883                 hIcon = pWnd->GetIcon( FALSE );
00884                 if ( hIcon == NULL ) hIcon = pWnd->GetIcon( TRUE );
00885         }
00886         int nCaptionHeight = 0;
00887         
00888         if ( m_bPart[ SKINPART_TOP_LEFT ] ) nCaptionHeight = max( nCaptionHeight, m_rcPart[ SKINPART_TOP_LEFT ].Height() );
00889         if ( m_bPart[ SKINPART_TOP ] ) nCaptionHeight = max( nCaptionHeight, m_rcPart[ SKINPART_TOP ].Height() );
00890         if ( m_bPart[ SKINPART_TOP_RIGHT ] ) nCaptionHeight = max( nCaptionHeight, m_rcPart[ SKINPART_TOP_RIGHT ].Height() );
00891         CDC* pDC = CoolInterface.GetBuffer( dc, CSize( rc.Width(), nCaptionHeight ) );
00892         
00893         for ( int nAnchor = SKINANCHOR_SYSTEM ; nAnchor <= SKINANCHOR_CLOSE ; nAnchor++ )
00894         {
00895                 if ( m_bAnchor[ nAnchor ] )
00896                 {
00897                         int nPart = ( nAnchor - SKINANCHOR_SYSTEM ) * 3 + SKINPART_SYSTEM;
00898                         
00899                         if ( m_nHoverAnchor == nAnchor )
00900                                 nPart += ( m_nDownAnchor == nAnchor ? 2 : 1 );
00901                         else
00902                                 nPart += ( m_nDownAnchor == nAnchor ? 0 : 0 );
00903                         
00904                         if ( m_bPart[ nPart ] )
00905                         {
00906                                 ResolveAnchor( rc, rcItem, nAnchor );
00907                                 // Buttons like "Close" are mirrored for RTL layout
00908                                 // Maybe <anchor name="Close" rect="-31,5,23,23" can_be_mirrored="true"/>
00909                                 // should be used instead? Small design flaws appear sometimes with the
00910                                 // current implementation if all buttons in caption are mirrored although
00911                                 // they are barely noticeable.
00912                                 if ( m_bPart[ SKINPART_TOP ] && theApp.m_bRTL && nAnchor == SKINANCHOR_CLOSE )
00913                                         pDC->StretchBlt( m_rcPart[ nPart ].Width() + rcItem.left - 1, rcItem.top,
00914                                                 -m_rcPart[ nPart ].Width(), m_rcPart[ nPart ].Height(),
00915                                                 &m_dcSkin, m_rcPart[ nPart ].left, m_rcPart[ nPart ].top,
00916                                                 m_rcPart[ nPart ].Width(), m_rcPart[ nPart ].Height(), SRCCOPY );
00917                                 else
00918                                         pDC->BitBlt( rcItem.left, rcItem.top,
00919                                                 m_rcPart[ nPart ].Width(), m_rcPart[ nPart ].Height(), &m_dcSkin,
00920                                                 m_rcPart[ nPart ].left, m_rcPart[ nPart ].top, SRCCOPY );
00921                                 pDC->ExcludeClipRect( rcItem.left, rcItem.top,
00922                                         rcItem.left + m_rcPart[ nPart ].Width(),
00923                                         rcItem.top + m_rcPart[ nPart ].Height() );
00924                         }
00925                 }
00926         }
00927         
00928         CRect rcLeft( &rc ), rcTop( &rc ), rcRight( &rc ), rcBottom( &rc );
00929         int nTotalWidth, nCaptionWidth, nSystemOffset;
00930         int nSystemWidth, nCaptionOffset, nRestOffset;
00931         nCaptionOffset = m_rcMirror.left;
00932         nCaptionWidth = m_rcMirror.top;
00933         nSystemOffset = m_rcMirror.right - m_rcMirror.left;
00934         nSystemWidth = m_rcMirror.bottom - m_rcMirror.top;
00935 
00936         if ( bActive == TS_FALSE && m_bPart[ SKINPART_IA_TOP_LEFT ] )
00937         {
00938                 pDC->BitBlt( 0, 0, m_rcPart[ SKINPART_IA_TOP_LEFT ].Width(),
00939                         m_rcPart[ SKINPART_IA_TOP_LEFT ].Height(), &m_dcSkin,
00940                         m_rcPart[ SKINPART_IA_TOP_LEFT ].left,
00941                         m_rcPart[ SKINPART_IA_TOP_LEFT ].top, SRCCOPY );
00942 
00943                 nTotalWidth = m_rcPart[ SKINPART_IA_TOP_LEFT ].Width();
00944                 nRestOffset = nTotalWidth - nSystemWidth - nSystemOffset - nCaptionWidth - nCaptionOffset;
00945 
00946                 // Inactive main window caption mirroring for RTL
00947                 if ( theApp.m_bRTL && m_sTargets == "|CMainWnd|" && m_nMirror != 0 )
00948                 {
00949                         pDC->StretchBlt( nTotalWidth - nCaptionOffset, 0, -nCaptionWidth, 
00950                                 m_rcPart[ SKINPART_IA_TOP_LEFT ].Height(), &m_dcSkin,
00951                                 m_rcPart[ SKINPART_IA_TOP_LEFT ].left + nRestOffset + nSystemWidth + nSystemOffset,
00952                                 m_rcPart[ SKINPART_IA_TOP_LEFT ].top, nCaptionWidth, 
00953                                 m_rcPart[ SKINPART_IA_TOP_LEFT ].Height(), SRCCOPY );
00954                         if ( m_nMirror == 2 )
00955                                 pDC->StretchBlt( nRestOffset + nSystemWidth, 0, -nSystemWidth,
00956                                         m_rcPart[ SKINPART_IA_TOP_LEFT ].Height(), &m_dcSkin,
00957                                         m_rcPart[ SKINPART_IA_TOP_LEFT ].left + nRestOffset,
00958                                         m_rcPart[ SKINPART_IA_TOP_LEFT ].top, nSystemWidth,
00959                                         m_rcPart[ SKINPART_IA_TOP_LEFT ].Height(), SRCCOPY );
00960                 }
00961                 rcLeft.top += m_rcPart[ SKINPART_IA_TOP_LEFT ].Height();
00962                 rcTop.left += m_rcPart[ SKINPART_IA_TOP_LEFT ].Width();
00963         }
00964         else if ( m_bPart[ SKINPART_TOP_LEFT ] )
00965         {
00966                 pDC->BitBlt( 0, 0, m_rcPart[ SKINPART_TOP_LEFT ].Width(),
00967                         m_rcPart[ SKINPART_TOP_LEFT ].Height(), &m_dcSkin,
00968                         m_rcPart[ SKINPART_TOP_LEFT ].left,
00969                         m_rcPart[ SKINPART_TOP_LEFT ].top, SRCCOPY );
00970 
00971                 // Active main window caption mirroring for RTL
00972                 if ( theApp.m_bRTL && m_sTargets == "|CMainWnd|" && m_nMirror != 0 )
00973                 {
00974                         nTotalWidth = m_rcPart[ SKINPART_TOP_LEFT ].Width();
00975                         nRestOffset = nTotalWidth - nSystemWidth - nSystemOffset - nCaptionWidth - nCaptionOffset;
00976                         pDC->StretchBlt( nTotalWidth - nCaptionOffset, 0, -nCaptionWidth, 
00977                                 m_rcPart[ SKINPART_TOP_LEFT ].Height(), &m_dcSkin,
00978                                 m_rcPart[ SKINPART_TOP_LEFT ].left + nRestOffset + nSystemWidth + nSystemOffset,
00979                                 m_rcPart[ SKINPART_TOP_LEFT ].top, nCaptionWidth, 
00980                                 m_rcPart[ SKINPART_TOP_LEFT ].Height(), SRCCOPY );
00981                         if ( m_nMirror == 2 )
00982                                 pDC->StretchBlt( nRestOffset + nSystemWidth, 0, -nSystemWidth,
00983                                         m_rcPart[ SKINPART_TOP_LEFT ].Height(), &m_dcSkin,
00984                                         m_rcPart[ SKINPART_TOP_LEFT ].left + nRestOffset,
00985                                         m_rcPart[ SKINPART_TOP_LEFT ].top, nSystemWidth,
00986                                         m_rcPart[ SKINPART_TOP_LEFT ].Height(), SRCCOPY );
00987                 }
00988                 rcLeft.top += m_rcPart[ SKINPART_TOP_LEFT ].Height();
00989                 rcTop.left += m_rcPart[ SKINPART_TOP_LEFT ].Width();
00990         }
00991         
00992         if ( bActive == TS_FALSE && m_bPart[ SKINPART_IA_TOP_RIGHT ] )
00993         {
00994                 pDC->BitBlt( rc.Width() - m_rcPart[ SKINPART_IA_TOP_RIGHT ].Width(), 0,
00995                         m_rcPart[ SKINPART_IA_TOP_RIGHT ].Width(),
00996                         m_rcPart[ SKINPART_IA_TOP_RIGHT ].Height(), &m_dcSkin,
00997                         m_rcPart[ SKINPART_IA_TOP_RIGHT ].left,
00998                         m_rcPart[ SKINPART_IA_TOP_RIGHT ].top, SRCCOPY );
00999                 rcTop.right -= m_rcPart[ SKINPART_IA_TOP_RIGHT ].Width();
01000                 rcRight.top += m_rcPart[ SKINPART_IA_TOP_RIGHT ].Height();
01001         }
01002         else if ( m_bPart[ SKINPART_TOP_RIGHT ] )
01003         {
01004                 pDC->BitBlt( rc.Width() - m_rcPart[ SKINPART_TOP_RIGHT ].Width(), 0,
01005                         m_rcPart[ SKINPART_TOP_RIGHT ].Width(),
01006                         m_rcPart[ SKINPART_TOP_RIGHT ].Height(), &m_dcSkin,
01007                         m_rcPart[ SKINPART_TOP_RIGHT ].left,
01008                         m_rcPart[ SKINPART_TOP_RIGHT ].top, SRCCOPY );
01009                 rcTop.right -= m_rcPart[ SKINPART_TOP_RIGHT ].Width();
01010                 rcRight.top += m_rcPart[ SKINPART_TOP_RIGHT ].Height();
01011         }
01012         
01013         if ( m_bPart[ SKINPART_BOTTOM_LEFT ] && ! bCaption )
01014         {
01015                 dc.BitBlt( 0, rc.Height() - m_rcPart[ SKINPART_BOTTOM_LEFT ].Height(),
01016                         m_rcPart[ SKINPART_BOTTOM_LEFT ].Width(),
01017                         m_rcPart[ SKINPART_BOTTOM_LEFT ].Height(), &m_dcSkin,
01018                         m_rcPart[ SKINPART_BOTTOM_LEFT ].left,
01019                         m_rcPart[ SKINPART_BOTTOM_LEFT ].top, SRCCOPY );
01020                 rcBottom.left += m_rcPart[ SKINPART_BOTTOM_LEFT ].Width();
01021                 rcLeft.bottom -= m_rcPart[ SKINPART_BOTTOM_LEFT ].Height();
01022         }
01023         
01024         if ( m_bPart[ SKINPART_BOTTOM_RIGHT ] && ! bCaption )
01025         {
01026                 dc.BitBlt( rc.Width() - m_rcPart[ SKINPART_BOTTOM_RIGHT ].Width(),
01027                         rc.Height() - m_rcPart[ SKINPART_BOTTOM_RIGHT ].Height(),
01028                         m_rcPart[ SKINPART_BOTTOM_RIGHT ].Width(),
01029                         m_rcPart[ SKINPART_BOTTOM_RIGHT ].Height(), &m_dcSkin,
01030                         m_rcPart[ SKINPART_BOTTOM_RIGHT ].left,
01031                         m_rcPart[ SKINPART_BOTTOM_RIGHT ].top, SRCCOPY );
01032                 rcRight.bottom -= m_rcPart[ SKINPART_BOTTOM_RIGHT ].Height();
01033                 rcBottom.right -= m_rcPart[ SKINPART_BOTTOM_RIGHT ].Width();
01034         }
01035         
01036         if ( m_bPart[ SKINPART_LEFT_TOP ] && ! bCaption )
01037         {
01038                 dc.BitBlt( 0, rcLeft.top, m_rcPart[ SKINPART_LEFT_TOP ].Width(),
01039                         m_rcPart[ SKINPART_LEFT_TOP ].Height(), &m_dcSkin,
01040                         m_rcPart[ SKINPART_LEFT_TOP ].left,
01041                         m_rcPart[ SKINPART_LEFT_TOP ].top, SRCCOPY );
01042                 rcLeft.top += m_rcPart[ SKINPART_LEFT_TOP ].Height();
01043         }
01044         
01045         if ( m_bPart[ SKINPART_LEFT_BOTTOM ] && ! bCaption )
01046         {
01047                 dc.BitBlt( 0, rcLeft.bottom - m_rcPart[ SKINPART_LEFT_BOTTOM ].Height(),
01048                         m_rcPart[ SKINPART_LEFT_BOTTOM ].Width(),
01049                         m_rcPart[ SKINPART_LEFT_BOTTOM ].Height(), &m_dcSkin,
01050                         m_rcPart[ SKINPART_LEFT_BOTTOM ].left,
01051                         m_rcPart[ SKINPART_LEFT_BOTTOM ].top, SRCCOPY );
01052                 rcLeft.bottom -= m_rcPart[ SKINPART_LEFT_BOTTOM ].Height();
01053         }
01054         
01055         if ( m_bPart[ SKINPART_RIGHT_TOP ] && ! bCaption )
01056         {
01057                 dc.BitBlt( rcRight.right - m_rcPart[ SKINPART_RIGHT_TOP ].Width(),
01058                         rcRight.top, m_rcPart[ SKINPART_RIGHT_TOP ].Width(),
01059                         m_rcPart[ SKINPART_RIGHT_TOP ].Height(), &m_dcSkin,
01060                         m_rcPart[ SKINPART_RIGHT_TOP ].left,
01061                         m_rcPart[ SKINPART_RIGHT_TOP ].top, SRCCOPY );
01062                 rcRight.top += m_rcPart[ SKINPART_RIGHT_TOP ].Height();
01063         }
01064         
01065         if ( m_bPart[ SKINPART_RIGHT_BOTTOM ] && ! bCaption )
01066         {
01067                 dc.BitBlt( rcRight.right - m_rcPart[ SKINPART_RIGHT_BOTTOM ].Width(),
01068                         rcRight.bottom - m_rcPart[ SKINPART_RIGHT_BOTTOM ].Height(),
01069                         m_rcPart[ SKINPART_RIGHT_BOTTOM ].Width(),
01070                         m_rcPart[ SKINPART_RIGHT_BOTTOM ].Height(), &m_dcSkin,
01071                         m_rcPart[ SKINPART_RIGHT_BOTTOM ].left,
01072                         m_rcPart[ SKINPART_RIGHT_BOTTOM ].top, SRCCOPY );
01073                 rcRight.bottom -= m_rcPart[ SKINPART_RIGHT_BOTTOM ].Height();
01074         }
01075         
01076         if ( m_bPart[ SKINPART_LEFT ] && rcLeft.top < rcLeft.bottom && ! bCaption )
01077         {
01078                 CRect* pRect = &m_rcPart[ SKINPART_LEFT ];
01079                 
01080                 if ( m_nPart[ SKINPART_LEFT ] == SKINPARTMODE_STRETCH )
01081                 {
01082                         dc.SetStretchBltMode( STRETCH_DELETESCANS );
01083                         dc.StretchBlt( 0, rcLeft.top, pRect->Width(), rcLeft.Height(),
01084                                 &m_dcSkin, pRect->left, pRect->top,
01085                                 pRect->Width(), pRect->Height(), SRCCOPY );
01086                 }
01087                 else
01088                 {
01089                         for ( int nY = rcLeft.top ; nY < rcLeft.bottom ; nY += pRect->Height() )
01090                         {
01091                                 dc.BitBlt( 0, nY, pRect->Width(), min( pRect->Height(), int(rcLeft.bottom - nY) ),
01092                                         &m_dcSkin, pRect->left, pRect->top, SRCCOPY );
01093                         }
01094                 }
01095         }
01096         
01097         if ( bActive == TS_FALSE && m_bPart[ SKINPART_IA_TOP ] && rcTop.left < rcTop.right )
01098         {
01099                 CRect* pRect = &m_rcPart[ SKINPART_IA_TOP ];
01100                 
01101                 if ( m_nPart[ SKINPART_IA_TOP ] == SKINPARTMODE_STRETCH )
01102                 {
01103                         pDC->SetStretchBltMode( STRETCH_DELETESCANS );
01104                         pDC->StretchBlt( rcTop.left, 0, rcTop.Width(), pRect->Height(),
01105                                 &m_dcSkin, pRect->left, pRect->top,
01106                                 pRect->Width(), pRect->Height(), SRCCOPY );
01107                 }
01108                 else
01109                 {
01110                         for ( int nX = rcTop.left ; nX < rcTop.right ; nX += pRect->Width() )
01111                         {
01112                                 pDC->BitBlt( nX, 0, min( pRect->Width(), int(rcTop.right - nX) ),
01113                                         pRect->Height(), &m_dcSkin, pRect->left, pRect->top, SRCCOPY );
01114                         }
01115                 }
01116         }
01117         else if ( m_bPart[ SKINPART_TOP ] && rcTop.left < rcTop.right )
01118         {
01119                 CRect* pRect = &m_rcPart[ SKINPART_TOP ];
01120 
01121                 if ( m_nPart[ SKINPART_TOP ] == SKINPARTMODE_STRETCH )
01122                 {
01123                         pDC->SetStretchBltMode( STRETCH_DELETESCANS );
01124                         pDC->StretchBlt( rcTop.left, 0, rcTop.Width(), pRect->Height(),
01125                                 &m_dcSkin, pRect->left, pRect->top,
01126                                 pRect->Width(), pRect->Height(), SRCCOPY );
01127                 }
01128                 else
01129                 {
01130                         for ( int nX = rcTop.left ; nX < rcTop.right ; nX += pRect->Width() )
01131                         {
01132                                 pDC->BitBlt( nX, 0, min( pRect->Width(), int(rcTop.right - nX) ),
01133                                         pRect->Height(), &m_dcSkin, pRect->left, pRect->top, SRCCOPY );
01134                         }
01135                 }
01136         }
01137         
01138         if ( m_bPart[ SKINPART_RIGHT ] && rcRight.top < rcRight.bottom && ! bCaption )
01139         {
01140                 CRect* pRect = &m_rcPart[ SKINPART_RIGHT ];
01141                 
01142                 if ( m_nPart[ SKINPART_RIGHT ] == SKINPARTMODE_STRETCH )
01143                 {
01144                         dc.SetStretchBltMode( STRETCH_DELETESCANS );
01145                         dc.StretchBlt( rc.right - pRect->Width(), rcRight.top, pRect->Width(),
01146                                 rcRight.Height(), &m_dcSkin, pRect->left, pRect->top,
01147                                 pRect->Width(), pRect->Height(), SRCCOPY );
01148                 }
01149                 else
01150                 {
01151                         for ( int nY = rcRight.top ; nY < rcRight.bottom ; nY += pRect->Height() )
01152                         {
01153                                 dc.BitBlt( rc.right - pRect->Width(), nY, pRect->Width(),
01154                                         min( pRect->Height(), int(rcRight.bottom - nY) ),
01155                                         &m_dcSkin,      pRect->left, pRect->top, SRCCOPY );
01156                         }
01157                 }
01158         }
01159         
01160         if ( m_bPart[ SKINPART_BOTTOM ] && rcTop.left < rcTop.right && ! bCaption )
01161         {
01162                 CRect* pRect = &m_rcPart[ SKINPART_BOTTOM ];
01163                 
01164                 if ( m_nPart[ SKINPART_TOP ] == SKINPARTMODE_STRETCH )
01165                 {
01166                         dc.SetStretchBltMode( STRETCH_DELETESCANS );
01167                         dc.StretchBlt( rcBottom.left, rc.bottom - pRect->Height(),
01168                                 rcBottom.Width(), pRect->Height(),
01169                                 &m_dcSkin, pRect->left, pRect->top,
01170                                 pRect->Width(), pRect->Height(), SRCCOPY );
01171                 }
01172                 else
01173                 {
01174                         for ( int nX = rcBottom.left ; nX < rcBottom.right ; nX += pRect->Width() )
01175                         {
01176                                 dc.BitBlt( nX, rc.bottom - pRect->Height(),
01177                                         min( pRect->Width(), int(rcBottom.right - nX) ), pRect->Height(),
01178                                         &m_dcSkin, pRect->left, pRect->top, SRCCOPY );
01179                         }
01180                 }
01181         }
01182         
01183         if ( hIcon != NULL )
01184         {
01185                 ResolveAnchor( rc, rcItem, SKINANCHOR_ICON );
01186                 DrawIconEx( pDC->GetSafeHdc(), rcItem.left, rcItem.top, hIcon, 16, 16, 0, NULL, DI_NORMAL );
01187         }
01188         
01189         if ( m_bCaption && strCaption.GetLength() )
01190         {
01191                 CFont* pOldFont = (CFont*)pDC->SelectObject( &m_fnCaption );
01192                 CSize sz                = pDC->GetTextExtent( strCaption );
01193                 CPoint ptCap;
01194                 
01195                 rcItem.left             = m_rcCaption.left + ( m_rcCaption.left >= 0 ? rc.left : rc.right );
01196                 rcItem.right    = m_rcCaption.Width() + ( m_rcCaption.Width() >= 0 ? rc.left : rc.right );
01197                 rcItem.top              = rc.top + m_rcCaption.top;
01198                 rcItem.bottom   = rc.top + m_rcCaption.bottom;
01199                 
01200                 switch ( m_nCaptionAlign )
01201                 {
01202                 case 0:
01203                         ptCap.x = rcItem.left + 1;
01204                         break;
01205                 case 1:
01206                         ptCap.x = ( rcItem.left + rcItem.right ) / 2 - sz.cx / 2;
01207                         ptCap.x = max( ptCap.x, rcItem.left + 1 );
01208                         break;
01209                 case 2:
01210                         ptCap.x = rcItem.right - sz.cx - 1;
01211                         ptCap.x = max( ptCap.x, rcItem.left + 1 );
01212                         break;
01213                 }
01214                 
01215                 ptCap.y = ( rcItem.top + rcItem.bottom ) / 2 - sz.cy / 2;
01216                 
01217                 pDC->SetBkMode( TRANSPARENT );
01218                 
01219                 if ( m_crCaptionShadow != CLR_NONE )
01220                 {
01221                         pDC->SetTextColor( m_crCaptionShadow );
01222                         pDC->ExtTextOut( ptCap.x + 1, ptCap.y + 1, ETO_CLIPPED, &rcItem, strCaption, NULL );
01223                 }
01224                 else if ( m_crCaptionOutline != CLR_NONE )
01225                 {
01226                         pDC->SetTextColor( m_crCaptionOutline );
01227                         pDC->ExtTextOut( ptCap.x - 1, ptCap.y - 1, ETO_CLIPPED, &rcItem, strCaption, NULL );
01228                         pDC->ExtTextOut( ptCap.x, ptCap.y - 1, ETO_CLIPPED, &rcItem, strCaption, NULL );
01229                         pDC->ExtTextOut( ptCap.x + 1, ptCap.y - 1, ETO_CLIPPED, &rcItem, strCaption, NULL );
01230                         pDC->ExtTextOut( ptCap.x - 1, ptCap.y, ETO_CLIPPED, &rcItem, strCaption, NULL );
01231                         pDC->ExtTextOut( ptCap.x + 1, ptCap.y, ETO_CLIPPED, &rcItem, strCaption, NULL );
01232                         pDC->ExtTextOut( ptCap.x - 1, ptCap.y + 1, ETO_CLIPPED, &rcItem, strCaption, NULL );
01233                         pDC->ExtTextOut( ptCap.x, ptCap.y + 1, ETO_CLIPPED, &rcItem, strCaption, NULL );
01234                         pDC->ExtTextOut( ptCap.x + 1, ptCap.y + 1, ETO_CLIPPED, &rcItem, strCaption, NULL );
01235                 }
01236                 
01237                 pDC->SetTextColor( bActive == TS_TRUE ? m_crCaptionText : m_crCaptionInactive );
01238                 pDC->ExtTextOut( ptCap.x, ptCap.y, ETO_CLIPPED, &rcItem, strCaption, NULL );
01239                 pDC->SelectObject( pOldFont );
01240         }
01241         
01242         dc.BitBlt( 0, 0, rc.Width(), nCaptionHeight, pDC, 0, 0, SRCCOPY );
01243         pDC->SelectClipRgn( NULL );
01244         
01245         dc.SetTextColor( 0 );
01246 }
01247 
01249 // CSkinWindow part and anchor access
01250 
01251 BOOL CSkinWindow::GetPart(LPCTSTR pszName, CRect& rcPart)
01252 {
01253         CRect* pRect;
01254         if ( ! m_pPartList.Lookup( pszName, (void*&)pRect ) ) return FALSE;
01255         rcPart = *pRect;
01256         return TRUE;
01257 }
01258 
01259 BOOL CSkinWindow::GetAnchor(LPCTSTR pszName, CRect& rcAnchor)
01260 {
01261         CRect* pRect;
01262         if ( ! m_pAnchorList.Lookup( pszName, (void*&)pRect ) ) return FALSE;
01263         rcAnchor = *pRect;
01264         return TRUE;
01265 }
01266 
01267 BOOL CSkinWindow::GetAnchor(LPCTSTR pszName, const CRect& rcClient, CRect& rcAnchor)
01268 {
01269         CRect* pRect;
01270         if ( ! m_pAnchorList.Lookup( pszName, (void*&)pRect ) ) return FALSE;
01271         rcAnchor = *pRect;
01272         rcAnchor.OffsetRect( rcAnchor.left < 0 ? rcClient.right : rcClient.left, 0 );
01273         rcAnchor.OffsetRect( 0, rcAnchor.top < 0 ? rcClient.bottom : rcClient.top );
01274         return TRUE;
01275 }
01276 
01277 BOOL CSkinWindow::PaintPartOnAnchor(CDC* pDC, const CRect& rcClient, LPCTSTR pszPart, LPCTSTR pszAnchor)
01278 {
01279         CRect rcPart, rcAnchor;
01280         
01281         if ( ! GetPart( pszPart, rcPart ) ) return FALSE;
01282         if ( ! GetAnchor( pszAnchor, rcClient, rcAnchor ) ) return FALSE;
01283         if ( m_dcSkin.m_hDC == NULL ) Prepare( pDC );
01284         
01285         pDC->BitBlt( rcAnchor.left, rcAnchor.top, rcPart.Width(), rcPart.Height(),
01286                 &m_dcSkin, rcPart.left, rcPart.top, SRCCOPY );
01287         pDC->ExcludeClipRect( &rcAnchor );
01288         
01289         return TRUE;
01290 }
01291 
01292 void CSkinWindow::ResolveAnchor(const CRect& rcClient, CRect& rcAnchor, int nAnchor)
01293 {
01294         rcAnchor = m_rcAnchor[ nAnchor ];
01295         rcAnchor.OffsetRect( rcAnchor.left < 0 ? rcClient.right : rcClient.left, 0 );
01296         rcAnchor.OffsetRect( 0, rcAnchor.top < 0 ? rcClient.bottom : rcClient.top );
01297 }
01298 
01300 // CSkinWindow region builder
01301 
01302 void CSkinWindow::SelectRegion(CWnd* pWnd)
01303 {
01304         CRect rcWnd, rcPart;
01305         HRGN hRgn = NULL;
01306 
01307         pWnd->GetWindowRect( &rcWnd );
01308         rcWnd.OffsetRect( -rcWnd.left, -rcWnd.top );
01309         rcWnd.right++; rcWnd.bottom++;
01310 
01311         for ( POSITION pos = m_pRegionXML->GetElementIterator() ; pos ; )
01312         {
01313                 CXMLElement* pXML = m_pRegionXML->GetNextElement( pos );
01314                 if ( ! pXML->IsNamed( _T("shape") ) ) continue;
01315 
01316                 if ( ParseRect( pXML, &rcPart ) )
01317                 {
01318                         rcPart.right    -= rcPart.left;
01319                         rcPart.bottom   -= rcPart.top;
01320                         rcPart.left             += rcPart.left >= 0 ? rcWnd.left : rcWnd.right + 1;
01321                         rcPart.top              += rcPart.top >= 0 ? rcWnd.top : rcWnd.bottom + 1;
01322                         rcPart.right    += rcPart.right >= 0 ? rcWnd.left : rcWnd.right + 1;
01323                         rcPart.bottom   += rcPart.bottom >= 0 ? rcWnd.top : rcWnd.bottom + 1;
01324                 }
01325                 else
01326                 {
01327                         rcPart.CopyRect( &rcWnd );
01328                 }
01329                 
01330                 CString strType = pXML->GetAttributeValue( _T("type") );
01331                 HRGN hPart = NULL;
01332 
01333                 if ( strType.CompareNoCase( _T("rectangle") ) == 0 )
01334                 {
01335                         hPart = CreateRectRgnIndirect( &rcPart );
01336                 }
01337                 else if ( strType.CompareNoCase( _T("ellipse") ) == 0 )
01338                 {
01339                         hPart = CreateEllipticRgnIndirect( &rcPart );
01340                 }
01341                 else if ( strType.CompareNoCase( _T("roundRect") ) == 0 )
01342                 {
01343                         int nWidth, nHeight;
01344                         _stscanf( pXML->GetAttributeValue( _T("size") ), _T("%i,%i"), &nWidth, &nHeight );
01345                         hPart = CreateRoundRectRgn( rcPart.left, rcPart.top, rcPart.right, rcPart.bottom,
01346                                 nWidth, nHeight );
01347                 }
01348                 else
01349                 {
01350                         continue;
01351                 }
01352 
01353                 if ( hPart == NULL )
01354                 {
01355                         if ( hRgn ) DeleteObject( hRgn );
01356                         pWnd->SetWindowRgn( NULL, TRUE );
01357                         return;
01358                 }
01359 
01360                 if ( hRgn )
01361                 {
01362                         strType = pXML->GetAttributeValue( _T("combine") );
01363 
01364                         if ( strType.CompareNoCase( _T("and") ) == 0 )
01365                         {
01366                                 CombineRgn( hRgn, hPart, hRgn, RGN_AND );
01367                         }
01368                         else if ( strType.CompareNoCase( _T("copy") ) == 0 )
01369                         {
01370                                 CombineRgn( hRgn, hPart, hRgn, RGN_COPY );
01371                         }
01372                         else if ( strType.CompareNoCase( _T("diff") ) == 0 )
01373                         {
01374                                 CombineRgn( hRgn, hRgn, hPart, RGN_DIFF );
01375                         }
01376                         else if ( strType.CompareNoCase( _T("or") ) == 0 )
01377                         {
01378                                 CombineRgn( hRgn, hPart, hRgn, RGN_OR );
01379                         }
01380                         else if ( strType.CompareNoCase( _T("xor") ) == 0 )
01381                         {
01382                                 CombineRgn( hRgn, hPart, hRgn, RGN_XOR );
01383                         }
01384 
01385                         DeleteObject( hPart );
01386                 }
01387                 else
01388                 {
01389                         hRgn = hPart;
01390                 }
01391         }
01392 
01393         if ( hRgn ) pWnd->SetWindowRgn( hRgn, TRUE );
01394 }
01395 
01396 CSize CSkinWindow::GetRegionSize()
01397 {
01398         if ( ! m_pRegionXML ) return CSize( 0, 0 );
01399 
01400         CRect rcTotal( 0, 0, 0, 0 );
01401 
01402         for ( POSITION pos = m_pRegionXML->GetElementIterator() ; pos ; )
01403         {
01404                 CXMLElement* pXML = m_pRegionXML->GetNextElement( pos );
01405                 CRect rcPart;
01406 
01407                 if ( pXML->IsNamed( _T("shape") ) && ParseRect( pXML, &rcPart ) )
01408                 {
01409                         rcTotal.UnionRect( &rcTotal, &rcPart );
01410                 }
01411         }
01412 
01413         return rcTotal.Size();
01414 }
01415 
01417 // CSkinWindow pre-blend
01418 
01419 BOOL CSkinWindow::PreBlend(CBitmap* pbmTarget, const CRect& rcTarget, const CRect& rcSource)
01420 {
01421         BITMAPINFO pTargeInfo, pImageInfo, pAlphaInfo;
01422         
01423         ZeroMemory( &pTargeInfo, sizeof(pTargeInfo) );
01424         ZeroMemory( &pImageInfo, sizeof(pImageInfo) );
01425         ZeroMemory( &pAlphaInfo, sizeof(pAlphaInfo) );
01426         
01427         pTargeInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
01428         pImageInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
01429         pAlphaInfo.bmiHeader.biSize     = sizeof(BITMAPINFOHEADER);
01430         
01431         HDC hDC = ::GetDC( 0 );
01432         if ( theApp.m_bRTL ) theApp.m_pfnSetLayout( hDC, LAYOUT_BITMAPORIENTATIONPRESERVED );
01433         
01434         if ( 0 == GetDIBits( hDC, m_bmSkin, 0, 0, NULL, &pImageInfo, DIB_RGB_COLORS ) ||
01435                  0 == GetDIBits( hDC, *pbmTarget, 0, 0, NULL, &pTargeInfo, DIB_RGB_COLORS ) )
01436         {
01437                 ::ReleaseDC( 0, hDC );
01438                 return FALSE;
01439         }
01440         
01441         BOOL bAlpha = ( 0 != GetDIBits( hDC, m_bmAlpha, 0, 0, NULL, &pAlphaInfo, DIB_RGB_COLORS ) );
01442         if ( ! bAlpha ) CopyMemory( &pAlphaInfo, &pImageInfo, sizeof(pAlphaInfo) );
01443         
01444         int nTargePitch = ( ( pTargeInfo.bmiHeader.biWidth * 3 ) + 3 ) & ~3;
01445         int nImagePitch = ( ( pImageInfo.bmiHeader.biWidth * 3 ) + 3 ) & ~3;
01446         int nAlphaPitch = ( ( pAlphaInfo.bmiHeader.biWidth * 3 ) + 3 ) & ~3;
01447         
01448         pTargeInfo.bmiHeader.biHeight           = -abs( pTargeInfo.bmiHeader.biHeight );
01449         pTargeInfo.bmiHeader.biBitCount         = 24;
01450         pTargeInfo.bmiHeader.biCompression      = BI_RGB;
01451         pTargeInfo.bmiHeader.biSizeImage        = -pTargeInfo.bmiHeader.biHeight * nTargePitch;
01452         pImageInfo.bmiHeader.biHeight           = -abs( pImageInfo.bmiHeader.biHeight );
01453         pImageInfo.bmiHeader.biBitCount         = 24;
01454         pImageInfo.bmiHeader.biCompression      = BI_RGB;
01455         pImageInfo.bmiHeader.biSizeImage        = -pImageInfo.bmiHeader.biHeight * nImagePitch;
01456         pAlphaInfo.bmiHeader.biHeight           = -abs( pAlphaInfo.bmiHeader.biHeight );
01457         pAlphaInfo.bmiHeader.biBitCount         = 24;
01458         pAlphaInfo.bmiHeader.biCompression      = BI_RGB;
01459         pAlphaInfo.bmiHeader.biSizeImage        = -pAlphaInfo.bmiHeader.biHeight * nAlphaPitch;
01460         
01461         BYTE* pTargeData = new BYTE[ pTargeInfo.bmiHeader.biSizeImage ];
01462         BYTE* pImageData = new BYTE[ pImageInfo.bmiHeader.biSizeImage ];
01463         BYTE* pAlphaData = bAlpha ? new BYTE[ pAlphaInfo.bmiHeader.biSizeImage ] : NULL;
01464         
01465         GetDIBits( hDC, *pbmTarget, 0, -pTargeInfo.bmiHeader.biHeight, pTargeData, &pTargeInfo, DIB_RGB_COLORS );
01466         GetDIBits( hDC, m_bmSkin, 0, -pImageInfo.bmiHeader.biHeight, pImageData, &pImageInfo, DIB_RGB_COLORS );
01467         if ( bAlpha ) GetDIBits( hDC, m_bmAlpha, 0, -pAlphaInfo.bmiHeader.biHeight, pAlphaData, &pAlphaInfo, DIB_RGB_COLORS );
01468         
01469         int nSrcY = rcSource.top, nSrcLeft = rcSource.left * 3;
01470         int nDstY = rcTarget.top, nDstLeft = rcTarget.left * 3;
01471         
01472         int nWidth = min( rcSource.Width(), rcTarget.Width() );
01473         nWidth = min( nWidth, int(pTargeInfo.bmiHeader.biWidth - rcTarget.left) );
01474         nWidth = min( nWidth, int(pImageInfo.bmiHeader.biWidth - rcSource.left) );
01475         nWidth = min( nWidth, int(pAlphaInfo.bmiHeader.biWidth - rcSource.left) );
01476         
01477         for ( int nY = min( rcTarget.Height(), rcSource.Height() ) ; nY ; nY--, nSrcY++, nDstY++ )
01478         {
01479                 BYTE* pTargePtr = pTargeData + nDstY * nTargePitch + nDstLeft;
01480                 BYTE* pImagePtr = pImageData + nSrcY * nImagePitch + nSrcLeft;
01481                 BYTE* pAlphaPtr = pAlphaData + nSrcY * nAlphaPitch + nSrcLeft;
01482                 
01483                 if ( nDstY < 0 || nDstY >= -pTargeInfo.bmiHeader.biHeight )
01484                 {
01485                         // Out of bounds on destination
01486                 }
01487                 else if ( nSrcY < 0 || nSrcY >= -pImageInfo.bmiHeader.biHeight )
01488                 {
01489                         // Out of bounds on source
01490                 }
01491                 else if ( bAlpha && nSrcY < -pAlphaInfo.bmiHeader.biHeight )
01492                 {
01493                         for ( int nX = nWidth ; nX ; nX-- )
01494                         {
01495                                 register BYTE nAlpha = *pAlphaPtr; pAlphaPtr += 3;
01496                                 *pTargePtr = (BYTE)( ( (DWORD)(*pTargePtr) * ( 255 - nAlpha ) + (*pImagePtr) * nAlpha ) / 255 );
01497                                 pTargePtr++; pImagePtr++;
01498                                 *pTargePtr = (BYTE)( ( (DWORD)(*pTargePtr) * ( 255 - nAlpha ) + (*pImagePtr) * nAlpha ) / 255 );
01499                                 pTargePtr++; pImagePtr++;
01500                                 *pTargePtr = (BYTE)( ( (DWORD)(*pTargePtr) * ( 255 - nAlpha ) + (*pImagePtr) * nAlpha ) / 255 );
01501                                 pTargePtr++; pImagePtr++;
01502                         }
01503                 }
01504                 else
01505                 {
01506                         CopyMemory( pTargePtr, pImagePtr, nWidth * 3 );
01507                 }
01508         }
01509         
01510         SetDIBits( hDC, *pbmTarget, 0, -pTargeInfo.bmiHeader.biHeight, pTargeData,
01511                 &pTargeInfo, DIB_RGB_COLORS );
01512         
01513         if ( bAlpha ) delete [] pAlphaData;
01514         delete [] pImageData;
01515         delete [] pTargeData;
01516         
01517         ::ReleaseDC( 0, hDC );
01518         
01519         return TRUE;
01520 }

Generated on Thu Dec 15 10:39:50 2005 for Shareaza 2.2.1.0 by  doxygen 1.4.2