📄 skinwindow.cpp
字号:
}
if ( m_bPart[ SKINPART_RIGHT_TOP ] && ! bCaption )
{
dc.BitBlt( rcRight.right - m_rcPart[ SKINPART_RIGHT_TOP ].Width(),
rcRight.top, m_rcPart[ SKINPART_RIGHT_TOP ].Width(),
m_rcPart[ SKINPART_RIGHT_TOP ].Height(), &m_dcSkin,
m_rcPart[ SKINPART_RIGHT_TOP ].left,
m_rcPart[ SKINPART_RIGHT_TOP ].top, SRCCOPY );
rcRight.top += m_rcPart[ SKINPART_RIGHT_TOP ].Height();
}
if ( m_bPart[ SKINPART_RIGHT_BOTTOM ] && ! bCaption )
{
dc.BitBlt( rcRight.right - m_rcPart[ SKINPART_RIGHT_BOTTOM ].Width(),
rcRight.bottom - m_rcPart[ SKINPART_RIGHT_BOTTOM ].Height(),
m_rcPart[ SKINPART_RIGHT_BOTTOM ].Width(),
m_rcPart[ SKINPART_RIGHT_BOTTOM ].Height(), &m_dcSkin,
m_rcPart[ SKINPART_RIGHT_BOTTOM ].left,
m_rcPart[ SKINPART_RIGHT_BOTTOM ].top, SRCCOPY );
rcRight.bottom -= m_rcPart[ SKINPART_RIGHT_BOTTOM ].Height();
}
if ( m_bPart[ SKINPART_LEFT ] && rcLeft.top < rcLeft.bottom && ! bCaption )
{
CRect* pRect = &m_rcPart[ SKINPART_LEFT ];
if ( m_nPart[ SKINPART_LEFT ] == SKINPARTMODE_STRETCH )
{
dc.SetStretchBltMode( STRETCH_DELETESCANS );
dc.StretchBlt( 0, rcLeft.top, pRect->Width(), rcLeft.Height(),
&m_dcSkin, pRect->left, pRect->top,
pRect->Width(), pRect->Height(), SRCCOPY );
}
else
{
for ( int nY = rcLeft.top ; nY < rcLeft.bottom ; nY += pRect->Height() )
{
dc.BitBlt( 0, nY, pRect->Width(), min( pRect->Height(), rcLeft.bottom - nY ),
&m_dcSkin, pRect->left, pRect->top, SRCCOPY );
}
}
}
if ( bActive == TS_FALSE && m_bPart[ SKINPART_IA_TOP ] && rcTop.left < rcTop.right )
{
CRect* pRect = &m_rcPart[ SKINPART_IA_TOP ];
if ( m_nPart[ SKINPART_IA_TOP ] == SKINPARTMODE_STRETCH )
{
pDC->SetStretchBltMode( STRETCH_DELETESCANS );
pDC->StretchBlt( rcTop.left, 0, rcTop.Width(), pRect->Height(),
&m_dcSkin, pRect->left, pRect->top,
pRect->Width(), pRect->Height(), SRCCOPY );
}
else
{
for ( int nX = rcTop.left ; nX < rcTop.right ; nX += pRect->Width() )
{
pDC->BitBlt( nX, 0, min( pRect->Width(), rcTop.right - nX ),
pRect->Height(), &m_dcSkin, pRect->left, pRect->top, SRCCOPY );
}
}
}
else if ( m_bPart[ SKINPART_TOP ] && rcTop.left < rcTop.right )
{
CRect* pRect = &m_rcPart[ SKINPART_TOP ];
if ( m_nPart[ SKINPART_TOP ] == SKINPARTMODE_STRETCH )
{
pDC->SetStretchBltMode( STRETCH_DELETESCANS );
pDC->StretchBlt( rcTop.left, 0, rcTop.Width(), pRect->Height(),
&m_dcSkin, pRect->left, pRect->top,
pRect->Width(), pRect->Height(), SRCCOPY );
}
else
{
for ( int nX = rcTop.left ; nX < rcTop.right ; nX += pRect->Width() )
{
pDC->BitBlt( nX, 0, min( pRect->Width(), rcTop.right - nX ),
pRect->Height(), &m_dcSkin, pRect->left, pRect->top, SRCCOPY );
}
}
}
if ( m_bPart[ SKINPART_RIGHT ] && rcRight.top < rcRight.bottom && ! bCaption )
{
CRect* pRect = &m_rcPart[ SKINPART_RIGHT ];
if ( m_nPart[ SKINPART_RIGHT ] == SKINPARTMODE_STRETCH )
{
dc.SetStretchBltMode( STRETCH_DELETESCANS );
dc.StretchBlt( rc.right - pRect->Width(), rcRight.top, pRect->Width(),
rcRight.Height(), &m_dcSkin, pRect->left, pRect->top,
pRect->Width(), pRect->Height(), SRCCOPY );
}
else
{
for ( int nY = rcRight.top ; nY < rcRight.bottom ; nY += pRect->Height() )
{
dc.BitBlt( rc.right - pRect->Width(), nY, pRect->Width(),
min( pRect->Height(), rcRight.bottom - nY ),
&m_dcSkin, pRect->left, pRect->top, SRCCOPY );
}
}
}
if ( m_bPart[ SKINPART_BOTTOM ] && rcTop.left < rcTop.right && ! bCaption )
{
CRect* pRect = &m_rcPart[ SKINPART_BOTTOM ];
if ( m_nPart[ SKINPART_TOP ] == SKINPARTMODE_STRETCH )
{
dc.SetStretchBltMode( STRETCH_DELETESCANS );
dc.StretchBlt( rcBottom.left, rc.bottom - pRect->Height(),
rcBottom.Width(), pRect->Height(),
&m_dcSkin, pRect->left, pRect->top,
pRect->Width(), pRect->Height(), SRCCOPY );
}
else
{
for ( int nX = rcBottom.left ; nX < rcBottom.right ; nX += pRect->Width() )
{
dc.BitBlt( nX, rc.bottom - pRect->Height(),
min( pRect->Width(), rcBottom.right - nX ), pRect->Height(),
&m_dcSkin, pRect->left, pRect->top, SRCCOPY );
}
}
}
if ( hIcon != NULL )
{
ResolveAnchor( rc, rcItem, SKINANCHOR_ICON );
DrawIconEx( pDC->GetSafeHdc(), rcItem.left, rcItem.top, hIcon, 16, 16, 0, NULL, DI_NORMAL );
}
if ( m_bCaption && strCaption.GetLength() )
{
CFont* pOldFont = (CFont*)pDC->SelectObject( &m_fnCaption );
CSize sz = pDC->GetTextExtent( strCaption );
CPoint ptCap;
rcItem.left = m_rcCaption.left + ( m_rcCaption.left >= 0 ? rc.left : rc.right );
rcItem.right = m_rcCaption.Width() + ( m_rcCaption.Width() >= 0 ? rc.left : rc.right );
rcItem.top = rc.top + m_rcCaption.top;
rcItem.bottom = rc.top + m_rcCaption.bottom;
switch ( m_nCaptionAlign )
{
case 0:
ptCap.x = rcItem.left + 1;
break;
case 1:
ptCap.x = ( rcItem.left + rcItem.right ) / 2 - sz.cx / 2;
ptCap.x = max( ptCap.x, rcItem.left + 1 );
break;
case 2:
ptCap.x = rcItem.right - sz.cx - 1;
ptCap.x = max( ptCap.x, rcItem.left + 1 );
break;
}
ptCap.y = ( rcItem.top + rcItem.bottom ) / 2 - sz.cy / 2;
pDC->SetBkMode( TRANSPARENT );
if ( m_crCaptionShadow != CLR_NONE )
{
pDC->SetTextColor( m_crCaptionShadow );
pDC->ExtTextOut( ptCap.x + 1, ptCap.y + 1, ETO_CLIPPED, &rcItem, strCaption, NULL );
}
else if ( m_crCaptionOutline != CLR_NONE )
{
pDC->SetTextColor( m_crCaptionOutline );
pDC->ExtTextOut( ptCap.x - 1, ptCap.y - 1, ETO_CLIPPED, &rcItem, strCaption, NULL );
pDC->ExtTextOut( ptCap.x, ptCap.y - 1, ETO_CLIPPED, &rcItem, strCaption, NULL );
pDC->ExtTextOut( ptCap.x + 1, ptCap.y - 1, ETO_CLIPPED, &rcItem, strCaption, NULL );
pDC->ExtTextOut( ptCap.x - 1, ptCap.y, ETO_CLIPPED, &rcItem, strCaption, NULL );
pDC->ExtTextOut( ptCap.x + 1, ptCap.y, ETO_CLIPPED, &rcItem, strCaption, NULL );
pDC->ExtTextOut( ptCap.x - 1, ptCap.y + 1, ETO_CLIPPED, &rcItem, strCaption, NULL );
pDC->ExtTextOut( ptCap.x, ptCap.y + 1, ETO_CLIPPED, &rcItem, strCaption, NULL );
pDC->ExtTextOut( ptCap.x + 1, ptCap.y + 1, ETO_CLIPPED, &rcItem, strCaption, NULL );
}
pDC->SetTextColor( bActive == TS_TRUE ? m_crCaptionText : m_crCaptionInactive );
pDC->ExtTextOut( ptCap.x, ptCap.y, ETO_CLIPPED, &rcItem, strCaption, NULL );
pDC->SelectObject( pOldFont );
}
dc.BitBlt( 0, 0, rc.Width(), nCaptionHeight, pDC, 0, 0, SRCCOPY );
pDC->SelectClipRgn( NULL );
dc.SetTextColor( 0 );
}
//////////////////////////////////////////////////////////////////////
// CSkinWindow part and anchor access
BOOL CSkinWindow::GetPart(LPCTSTR pszName, CRect& rcPart)
{
CRect* pRect;
if ( ! m_pPartList.Lookup( pszName, (void*&)pRect ) ) return FALSE;
rcPart = *pRect;
return TRUE;
}
BOOL CSkinWindow::GetAnchor(LPCTSTR pszName, CRect& rcAnchor)
{
CRect* pRect;
if ( ! m_pAnchorList.Lookup( pszName, (void*&)pRect ) ) return FALSE;
rcAnchor = *pRect;
return TRUE;
}
BOOL CSkinWindow::GetAnchor(LPCTSTR pszName, const CRect& rcClient, CRect& rcAnchor)
{
CRect* pRect;
if ( ! m_pAnchorList.Lookup( pszName, (void*&)pRect ) ) return FALSE;
rcAnchor = *pRect;
rcAnchor.OffsetRect( rcAnchor.left < 0 ? rcClient.right : rcClient.left, 0 );
rcAnchor.OffsetRect( 0, rcAnchor.top < 0 ? rcClient.bottom : rcClient.top );
return TRUE;
}
BOOL CSkinWindow::PaintPartOnAnchor(CDC* pDC, const CRect& rcClient, LPCTSTR pszPart, LPCTSTR pszAnchor)
{
CRect rcPart, rcAnchor;
if ( ! GetPart( pszPart, rcPart ) ) return FALSE;
if ( ! GetAnchor( pszAnchor, rcClient, rcAnchor ) ) return FALSE;
if ( m_dcSkin.m_hDC == NULL ) Prepare( pDC );
pDC->BitBlt( rcAnchor.left, rcAnchor.top, rcPart.Width(), rcPart.Height(),
&m_dcSkin, rcPart.left, rcPart.top, SRCCOPY );
pDC->ExcludeClipRect( &rcAnchor );
return TRUE;
}
void CSkinWindow::ResolveAnchor(const CRect& rcClient, CRect& rcAnchor, int nAnchor)
{
rcAnchor = m_rcAnchor[ nAnchor ];
rcAnchor.OffsetRect( rcAnchor.left < 0 ? rcClient.right : rcClient.left, 0 );
rcAnchor.OffsetRect( 0, rcAnchor.top < 0 ? rcClient.bottom : rcClient.top );
}
//////////////////////////////////////////////////////////////////////
// CSkinWindow region builder
void CSkinWindow::SelectRegion(CWnd* pWnd)
{
CRect rcWnd, rcPart;
HRGN hRgn = NULL;
pWnd->GetWindowRect( &rcWnd );
rcWnd.OffsetRect( -rcWnd.left, -rcWnd.top );
rcWnd.right++; rcWnd.bottom++;
for ( POSITION pos = m_pRegionXML->GetElementIterator() ; pos ; )
{
CXMLElement* pXML = m_pRegionXML->GetNextElement( pos );
if ( ! pXML->IsNamed( _T("shape") ) ) continue;
if ( ParseRect( pXML, &rcPart ) )
{
rcPart.right -= rcPart.left;
rcPart.bottom -= rcPart.top;
rcPart.left += rcPart.left >= 0 ? rcWnd.left : rcWnd.right + 1;
rcPart.top += rcPart.top >= 0 ? rcWnd.top : rcWnd.bottom + 1;
rcPart.right += rcPart.right >= 0 ? rcWnd.left : rcWnd.right + 1;
rcPart.bottom += rcPart.bottom >= 0 ? rcWnd.top : rcWnd.bottom + 1;
}
else
{
rcPart.CopyRect( &rcWnd );
}
CString strType = pXML->GetAttributeValue( _T("type") );
HRGN hPart = NULL;
if ( strType.CompareNoCase( _T("rectangle") ) == 0 )
{
hPart = CreateRectRgnIndirect( &rcPart );
}
else if ( strType.CompareNoCase( _T("ellipse") ) == 0 )
{
hPart = CreateEllipticRgnIndirect( &rcPart );
}
else if ( strType.CompareNoCase( _T("roundRect") ) == 0 )
{
int nWidth, nHeight;
_stscanf( pXML->GetAttributeValue( _T("size") ), _T("%i,%i"), &nWidth, &nHeight );
hPart = CreateRoundRectRgn( rcPart.left, rcPart.top, rcPart.right, rcPart.bottom,
nWidth, nHeight );
}
else
{
continue;
}
if ( hPart == NULL )
{
if ( hRgn ) DeleteObject( hRgn );
pWnd->SetWindowRgn( NULL, TRUE );
return;
}
if ( hRgn )
{
strType = pXML->GetAttributeValue( _T("combine") );
if ( strType.CompareNoCase( _T("and") ) == 0 )
{
CombineRgn( hRgn, hPart, hRgn, RGN_AND );
}
else if ( strType.CompareNoCase( _T("copy") ) == 0 )
{
CombineRgn( hRgn, hPart, hRgn, RGN_COPY );
}
else if ( strType.CompareNoCase( _T("diff") ) == 0 )
{
CombineRgn( hRgn, hRgn, hPart, RGN_DIFF );
}
else if ( strType.CompareNoCase( _T("or") ) == 0 )
{
CombineRgn( hRgn, hPart, hRgn, RGN_OR );
}
else if ( strType.CompareNoCase( _T("xor") ) == 0 )
{
CombineRgn( hRgn, hPart, hRgn, RGN_XOR );
}
DeleteObject( hPart );
}
else
{
hRgn = hPart;
}
}
if ( hRgn ) pWnd->SetWindowRgn( hRgn, TRUE );
}
CSize CSkinWindow::GetRegionSize()
{
if ( ! m_pRegionXML ) return CSize( 0, 0 );
CRect rcTotal( 0, 0, 0, 0 );
for ( POSITION pos = m_pRegionXML->GetElementIterator() ; pos ; )
{
CXMLElement* pXML = m_pRegionXML->GetNextElement( pos );
CRect rcPart;
if ( pXML->IsNamed( _T("shape") ) && ParseRect( pXML, &rcPart ) )
{
rcTotal.UnionRect( &rcTotal, &rcPart );
}
}
return rcTotal.Size();
}
//////////////////////////////////////////////////////////////////////
// CSkinWindow pre-blend
BOOL CSkinWindow::PreBlend(CBitmap* pbmTarget, const CRect& rcTarget, const CRect& rcSource)
{
BITMAPINFO pTargeInfo, pImageInfo, pAlphaInfo;
ZeroMemory( &pTargeInfo, sizeof(pTargeInfo) );
ZeroMemory( &pImageInfo, sizeof(pImageInfo) );
ZeroMemory( &pAlphaInfo, sizeof(pAlphaInfo) );
pTargeInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
pImageInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
pAlphaInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
HDC hDC = ::GetDC( 0 );
if ( 0 == GetDIBits( hDC, m_bmSkin, 0, 0, NULL, &pImageInfo, DIB_RGB_COLORS ) ||
0 == GetDIBits( hDC, *pbmTarget, 0, 0, NULL, &pTargeInfo, DIB_RGB_COLORS ) )
{
::ReleaseDC( 0, hDC );
return FALSE;
}
BOOL bAlpha = ( 0 != GetDIBits( hDC, m_bmAlpha, 0, 0, NULL, &pAlphaInfo, DIB_RGB_COLORS ) );
if ( ! bAlpha ) CopyMemory( &pAlphaInfo, &pImageInfo, sizeof(pAlphaInfo) );
int nTargePitch = ( ( pTargeInfo.bmiHeader.biWidth * 3 ) + 3 ) & ~3;
int nImagePitch = ( ( pImageInfo.bmiHeader.biWidth * 3 ) + 3 ) & ~3;
int nAlphaPitch = ( ( pAlphaInfo.bmiHeader.biWidth * 3 ) + 3 ) & ~3;
pTargeInfo.bmiHeader.biHeight = -abs( pTargeInfo.bmiHeader.biHeight );
pTargeInfo.bmiHeader.biBitCount = 24;
pTargeInfo.bmiHeader.biCompression = BI_RGB;
pTargeInfo.bmiHeader.biSizeImage = -pTargeInfo.bmiHeader.biHeight * nTargePitch;
pImageInfo.bmiHeader.biHeight = -abs( pImageInfo.bmiHeader.biHeight );
pImageInfo.bmiHeader.biBitCount = 24;
pImageInfo.bmiHeader.biCompression = BI_RGB;
pImageInfo.bmiHeader.biSizeImage = -pImageInfo.bmiHeader.biHeight * nImagePitch;
pAlphaInfo.bmiHeader.biHeight = -abs( pAlphaInfo.bmiHeader.biHeight );
pAlphaInfo.bmiHeader.biBitCount = 24;
pAlphaInfo.bmiHeader.biCompression = BI_RGB;
pAlphaInfo.bmiHeader.biSizeImage = -pAlphaInfo.bmiHeader.biHeight * nAlphaPitch;
BYTE* pTargeData = new BYTE[ pTargeInfo.bmiHeader.biSizeImage ];
BYTE* pImageData = new BYTE[ pImageInfo.bmiHeader.biSizeImage ];
BYTE* pAlphaData = bAlpha ? new BYTE[ pAlphaInfo.bmiHeader.biSizeImage ] : NULL;
GetDIBits( hDC, *pbmTarget, 0, -pTargeInfo.bmiHeader.biHeight, pTargeData, &pTargeInfo, DIB_RGB_COLORS );
GetDIBits( hDC, m_bmSkin, 0, -pImageInfo.bmiHeader.biHeight, pImageData, &pImageInfo, DIB_RGB_COLORS );
if ( bAlpha ) GetDIBits( hDC, m_bmAlpha, 0, -pAlphaInfo.bmiHeader.biHeight, pAlphaData, &pAlphaInfo, DIB_RGB_COLORS );
int nSrcY = rcSource.top, nSrcLeft = rcSource.left * 3;
int nDstY = rcTarget.top, nDstLeft = rcTarget.left * 3;
int nWidth = min( rcSource.Width(), rcTarget.Width() );
nWidth = min( nWidth, pTargeInfo.bmiHeader.biWidth - rcTarget.left );
nWidth = min( nWidth, pImageInfo.bmiHeader.biWidth - rcSource.left );
nWidth = min( nWidth, pAlphaInfo.bmiHeader.biWidth - rcSource.left );
for ( int nY = min( rcTarget.Height(), rcSource.Height() ) ; nY ; nY--, nSrcY++, nDstY++ )
{
BYTE* pTargePtr = pTargeData + nDstY * nTargePitch + nDstLeft;
BYTE* pImagePtr = pImageData + nSrcY * nImagePitch + nSrcLeft;
BYTE* pAlphaPtr = pAlphaData + nSrcY * nAlphaPitch + nSrcLeft;
if ( nDstY < 0 || nDstY >= -pTargeInfo.bmiHeader.biHeight )
{
// Out of bounds on destination
}
else if ( nSrcY < 0 || nSrcY >= -pImageInfo.bmiHeader.biHeight )
{
// Out of bounds on source
}
else if ( bAlpha && nSrcY < -pAlphaInfo.bmiHeader.biHeight )
{
for ( int nX = nWidth ; nX ; nX-- )
{
register BYTE nAlpha = *pAlphaPtr; pAlphaPtr += 3;
*pTargePtr = (BYTE)( ( (DWORD)(*pTargePtr) * ( 255 - nAlpha ) + (*pImagePtr) * nAlpha ) / 255 );
pTargePtr++; pImagePtr++;
*pTargePtr = (BYTE)( ( (DWORD)(*pTargePtr) * ( 255 - nAlpha ) + (*pImagePtr) * nAlpha ) / 255 );
pTargePtr++; pImagePtr++;
*pTargePtr = (BYTE)( ( (DWORD)(*pTargePtr) * ( 255 - nAlpha ) + (*pImagePtr) * nAlpha ) / 255 );
pTargePtr++; pImagePtr++;
}
}
else
{
CopyMemory( pTargePtr, pImagePtr, nWidth * 3 );
}
}
SetDIBits( hDC, *pbmTarget, 0, -pTargeInfo.bmiHeader.biHeight, pTargeData,
&pTargeInfo, DIB_RGB_COLORS );
if ( bAlpha ) delete [] pAlphaData;
delete [] pImageData;
delete [] pTargeData;
::ReleaseDC( 0, hDC );
return TRUE;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -