672 lines
21 KiB
C++
672 lines
21 KiB
C++
//---------------------------------------------------------------------------
|
|
// BorderFill.cpp - implements the drawing API for bgtype = BorderFill
|
|
//---------------------------------------------------------------------------
|
|
#include "stdafx.h"
|
|
#include "Render.h"
|
|
#include "Utils.h"
|
|
#include "gradient.h"
|
|
#include "tmutils.h"
|
|
#include "rgn.h"
|
|
#include "BorderFill.h"
|
|
#include "CacheList.h"
|
|
#include "gradient.h"
|
|
#include "drawhelp.h"
|
|
//---------------------------------------------------------------------------
|
|
HRESULT CBorderFill::PackProperties(CRenderObj *pRender, BOOL fNoDraw, int iPartId, int iStateId)
|
|
{
|
|
memset(this, 0, sizeof(CBorderFill)); // allowed because we have no vtable
|
|
_eBgType = BT_BORDERFILL;
|
|
|
|
//---- save off partid, stateid for debugging ----
|
|
_iSourcePartId = iPartId;
|
|
_iSourceStateId = iStateId;
|
|
|
|
if (fNoDraw)
|
|
{
|
|
//---- this is used to fake a bgtype=none object ----
|
|
_fNoDraw = TRUE;
|
|
}
|
|
else
|
|
{
|
|
//---- get border type ----
|
|
if (FAILED(pRender->GetEnumValue(iPartId, iStateId, TMT_BORDERTYPE, (int *)&_eBorderType)))
|
|
_eBorderType = BT_RECT; // TODO: Make Zero the default when no bordertype is specified.
|
|
|
|
//---- get border color ----
|
|
if (FAILED(pRender->GetColor(iPartId, iStateId, TMT_BORDERCOLOR, &_crBorder)))
|
|
_crBorder = RGB(0, 0, 0);
|
|
|
|
//---- get border size ----
|
|
if (FAILED(pRender->GetInt(iPartId, iStateId, TMT_BORDERSIZE, &_iBorderSize)))
|
|
_iBorderSize = 1; // TODO: Make Zero the default when no bordersize is specified.
|
|
|
|
if (_eBorderType == BT_ROUNDRECT)
|
|
{
|
|
//---- get round rect width ----
|
|
if (FAILED(pRender->GetInt(iPartId, iStateId, TMT_ROUNDCORNERWIDTH, &_iRoundCornerWidth)))
|
|
_iRoundCornerWidth = 80;
|
|
|
|
//---- get round rect height ----
|
|
if (FAILED(pRender->GetInt(iPartId, iStateId, TMT_ROUNDCORNERHEIGHT, &_iRoundCornerHeight)))
|
|
_iRoundCornerHeight = 80;
|
|
}
|
|
|
|
//---- get fill type ----
|
|
if (FAILED(pRender->GetEnumValue(iPartId, iStateId, TMT_FILLTYPE, (int *)&_eFillType)))
|
|
_eFillType = FT_SOLID;
|
|
|
|
if (_eFillType == FT_SOLID)
|
|
{
|
|
//---- get fill color ----
|
|
if (FAILED(pRender->GetColor(iPartId, iStateId, TMT_FILLCOLOR, &_crFill)))
|
|
_crFill = RGB(255, 255, 255);
|
|
}
|
|
else if (_eFillType == FT_TILEIMAGE)
|
|
{
|
|
_iDibOffset = pRender->GetValueIndex(iPartId, iStateId, TMT_DIBDATA);
|
|
|
|
if (_iDibOffset == -1) // not found
|
|
_iDibOffset = 0;
|
|
}
|
|
else // one of the graident filltypes
|
|
{
|
|
_iGradientPartCount = 0;
|
|
GRADIENTPART gpParts[5]; // max is 5 for now
|
|
|
|
for (int i=0; i < ARRAYSIZE(gpParts); i++)
|
|
{
|
|
COLORREF crPart;
|
|
if (FAILED(pRender->GetColor(iPartId, iStateId, TMT_GRADIENTCOLOR1+i, &crPart)))
|
|
break;
|
|
|
|
int iPartRatio;
|
|
if (FAILED(pRender->GetInt(iPartId, iStateId, TMT_GRADIENTRATIO1+i, &iPartRatio)))
|
|
iPartRatio = 0;
|
|
|
|
_crGradientColors[_iGradientPartCount] = crPart;
|
|
_iGradientRatios[_iGradientPartCount] = iPartRatio;
|
|
|
|
_iGradientPartCount++;
|
|
}
|
|
}
|
|
|
|
//---- ContentMargins ----
|
|
if (FAILED(pRender->GetMargins(NULL, iPartId, iStateId, TMT_CONTENTMARGINS, NULL,
|
|
&_ContentMargins)))
|
|
{
|
|
_ContentMargins.cxLeftWidth = _iBorderSize;
|
|
_ContentMargins.cxRightWidth = _iBorderSize;
|
|
_ContentMargins.cyTopHeight = _iBorderSize;
|
|
_ContentMargins.cyBottomHeight = _iBorderSize;
|
|
}
|
|
}
|
|
|
|
return S_OK;
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
BOOL CBorderFill::KeyProperty(int iPropId)
|
|
{
|
|
BOOL fKey = FALSE;
|
|
|
|
switch (iPropId)
|
|
{
|
|
case TMT_BGTYPE:
|
|
case TMT_BORDERSIZE:
|
|
case TMT_ROUNDCORNERWIDTH:
|
|
case TMT_ROUNDCORNERHEIGHT:
|
|
case TMT_GRADIENTRATIO1:
|
|
case TMT_GRADIENTRATIO2:
|
|
case TMT_GRADIENTRATIO3:
|
|
case TMT_GRADIENTRATIO4:
|
|
case TMT_GRADIENTRATIO5:
|
|
//case TMT_IMAGEFILE: // borrowed from imagefile
|
|
case TMT_CONTENTMARGINS:
|
|
case TMT_BORDERCOLOR:
|
|
case TMT_FILLCOLOR:
|
|
case TMT_GRADIENTCOLOR1:
|
|
case TMT_GRADIENTCOLOR2:
|
|
case TMT_GRADIENTCOLOR3:
|
|
case TMT_GRADIENTCOLOR4:
|
|
case TMT_GRADIENTCOLOR5:
|
|
case TMT_BORDERTYPE:
|
|
case TMT_FILLTYPE:
|
|
fKey = TRUE;
|
|
break;
|
|
}
|
|
|
|
return fKey;
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
void CBorderFill::DumpProperties(CSimpleFile *pFile, BYTE *pbThemeData, BOOL fFullInfo)
|
|
{
|
|
if (fFullInfo)
|
|
pFile->OutLine(L"Dump of CBorderFill at offset=0x%x", (BYTE *)this - pbThemeData);
|
|
else
|
|
pFile->OutLine(L"Dump of CBorderFill");
|
|
|
|
pFile->OutLine(L" _eBgType=%d, _fNoDraw=%d", _eBgType, _fNoDraw);
|
|
|
|
pFile->OutLine(L" _eBorderType=%d, _iBorderSize=%d, _crBorder=0x%08x",
|
|
_eBorderType, _iBorderSize, _crBorder);
|
|
|
|
pFile->OutLine(L" _iRoundCornerWidth=%d, _iRoundCornerHeight=%d",
|
|
_iRoundCornerWidth, _iRoundCornerHeight);
|
|
|
|
if (fFullInfo)
|
|
{
|
|
pFile->OutLine(L" _eFillType=%d, _iDibOffset=%d, _crFill=0x%08x",
|
|
_eFillType, _iDibOffset, _crFill);
|
|
}
|
|
else
|
|
{
|
|
pFile->OutLine(L" _eFillType=%d, _crFill=0x%08x",
|
|
_eFillType, _crFill);
|
|
}
|
|
|
|
pFile->OutLine(L" _ContentMargins=%d, %d, %d, %d",
|
|
_ContentMargins.cxLeftWidth, _ContentMargins.cxRightWidth,
|
|
_ContentMargins.cyTopHeight, _ContentMargins.cyBottomHeight);
|
|
|
|
pFile->OutLine(L" _iGradientPartCount=%d", _iGradientPartCount);
|
|
|
|
for (int i=0; i < _iGradientPartCount; i++)
|
|
{
|
|
pFile->OutLine(L" _crGradientColors[%d]=0x%08x, _iGradientRatios[%d]=%d",
|
|
i, _iGradientRatios[i], i, _iGradientRatios[i]);
|
|
}
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
HRESULT CBorderFill::DrawComplexBackground(CRenderObj *pRender, HDC hdcOrig,
|
|
const RECT *pRect, BOOL fGettingRegion, BOOL fBorder, BOOL fContent,
|
|
OPTIONAL const RECT *pClipRect)
|
|
{
|
|
CSaveClipRegion scrOrig;
|
|
HRESULT hr = S_OK;
|
|
|
|
bool fGradient = false;
|
|
int iWidth;
|
|
int iHeight;
|
|
|
|
//---- pen & brush should proceed hdc so auto-delete happens in correct order ----
|
|
CAutoGDI<HPEN> hPen;
|
|
CAutoGDI<HBRUSH> hBrush;
|
|
CAutoDC hdc(hdcOrig);
|
|
|
|
CMemoryDC memoryDC;
|
|
|
|
//---- draw border first (along with simple fills) ----
|
|
BOOL fHavePath = FALSE;
|
|
|
|
int width = WIDTH(*pRect);
|
|
int height = HEIGHT(*pRect);
|
|
|
|
if (pClipRect) // use GDI clipping for complex cases
|
|
{
|
|
//---- get previous clipping region (for restoring at end) ----
|
|
hr = scrOrig.Save(hdc);
|
|
if (FAILED(hr))
|
|
goto exit;
|
|
|
|
//---- add "pClipRect" to the GDI clipping region ----
|
|
int iRetVal = IntersectClipRect(hdc, pClipRect->left, pClipRect->top,
|
|
pClipRect->right, pClipRect->bottom);
|
|
if (iRetVal == ERROR)
|
|
{
|
|
hr = MakeErrorLast();
|
|
goto exit;
|
|
}
|
|
}
|
|
|
|
if ((fBorder) && (_iBorderSize))
|
|
{
|
|
hPen = CreatePen(PS_SOLID | PS_INSIDEFRAME, _iBorderSize, _crBorder);
|
|
if (! hPen)
|
|
{
|
|
hr = MakeErrorLast();
|
|
goto exit;
|
|
}
|
|
}
|
|
|
|
|
|
if (fContent)
|
|
{
|
|
if (_eFillType == FT_SOLID)
|
|
{
|
|
hBrush = CreateSolidBrush(_crFill);
|
|
if (! hBrush)
|
|
{
|
|
hr = MakeErrorLast();
|
|
goto exit;
|
|
}
|
|
}
|
|
else if (_eFillType == FT_TILEIMAGE)
|
|
{
|
|
#if 0
|
|
HBITMAP hBitmap = NULL;
|
|
|
|
|
|
//---- don't return on error - will default to NULL brush below ----
|
|
HRESULT hr = pRender->GetBitmap(hdc, _iImageFileOffset, iPartId, iStateId, &hBitmap);
|
|
if (FAILED(hr))
|
|
goto exit;
|
|
|
|
//Log("TileImage: GetBitmap() returns hr=0x%x, hBitmap=0x%x", hr, hBitmap);
|
|
|
|
hBrush = CreatePatternBrush(hBitmap);
|
|
Log(LOG_TM, L"TileImage: CreatePatternBrush() returns hBrush=0x%x, Error=0x%x", hBrush, GetLastError());
|
|
|
|
pRender->ReturnBitmap(hBitmap);
|
|
if (! hBrush)
|
|
{
|
|
hr = MakeErrorLast();
|
|
goto exit;
|
|
}
|
|
#endif
|
|
}
|
|
else
|
|
fGradient = true;
|
|
}
|
|
|
|
if (fGettingRegion)
|
|
fGradient = false;
|
|
|
|
if (! hBrush) // no brush wanted
|
|
hBrush = (HBRUSH)GetStockObject(NULL_BRUSH);
|
|
|
|
if (! hPen) // no pen wanted
|
|
hPen = (HPEN)GetStockObject(NULL_PEN);
|
|
|
|
hdc.SelectPen(hPen);
|
|
hdc.SelectBrush(hBrush);
|
|
|
|
if (_eBorderType == BT_RECT)
|
|
{
|
|
if (_iBorderSize > 0)
|
|
{
|
|
//---- no need to create a path for region in this case ----
|
|
Rectangle(hdc, pRect->left, pRect->top, pRect->right, pRect->bottom);
|
|
}
|
|
else
|
|
{
|
|
FillRect(hdc, pRect, hBrush);
|
|
}
|
|
}
|
|
else if (_eBorderType == BT_ROUNDRECT)
|
|
{
|
|
int iEllipHeight = (_iRoundCornerHeight*height)/100;
|
|
int iEllipWidth = (_iRoundCornerWidth*width)/100;
|
|
|
|
RoundRect(hdc, pRect->left, pRect->top, pRect->right, pRect->bottom,
|
|
iEllipHeight, iEllipWidth);
|
|
|
|
if (fGradient) // create a path of the border
|
|
{
|
|
BeginPath(hdc);
|
|
RoundRect(hdc, pRect->left, pRect->top, pRect->right, pRect->bottom,
|
|
iEllipHeight, iEllipWidth);
|
|
EndPath(hdc);
|
|
|
|
fHavePath = TRUE;
|
|
}
|
|
}
|
|
else // if (_eBorderType == BT_ELLIPSE)
|
|
{
|
|
Ellipse(hdc, pRect->left, pRect->top, pRect->right, pRect->bottom);
|
|
|
|
if (fGradient) // create a path of the border
|
|
{
|
|
BeginPath(hdc);
|
|
Ellipse(hdc, pRect->left, pRect->top, pRect->right, pRect->bottom);
|
|
EndPath(hdc);
|
|
|
|
fHavePath = TRUE;
|
|
}
|
|
}
|
|
|
|
if (! fGradient) // we're done
|
|
goto exit;
|
|
|
|
//---- draw gradient fill within the border drawn above ----
|
|
|
|
//---- shrink rect to subtract border ----
|
|
RECT rect;
|
|
SetRect(&rect, pRect->left, pRect->top, pRect->right, pRect->bottom);
|
|
|
|
rect.left += _iBorderSize;
|
|
rect.top += _iBorderSize;
|
|
|
|
rect.right -= _iBorderSize;
|
|
rect.bottom -= _iBorderSize;
|
|
|
|
iWidth = WIDTH(rect);
|
|
iHeight = HEIGHT(rect);
|
|
|
|
hr = memoryDC.OpenDC(hdc, iWidth, iHeight);
|
|
if (FAILED(hr))
|
|
goto exit;
|
|
|
|
//---- paint our bounding rect into dcBitmap with our gradient ----
|
|
RECT rect2;
|
|
SetRect(&rect2, 0, 0, iWidth, iHeight);
|
|
|
|
GRADIENTPART gpParts[5]; // max is 5 for now
|
|
|
|
//---- get gradient colors & ratios ----
|
|
for (int i=0; i < _iGradientPartCount; i++)
|
|
{
|
|
COLORREF crPart = _crGradientColors[i];
|
|
|
|
gpParts[i].Color.bRed = RED(crPart);
|
|
gpParts[i].Color.bGreen = GREEN(crPart);
|
|
gpParts[i].Color.bBlue = BLUE(crPart);
|
|
gpParts[i].Color.bAlpha = 255;
|
|
|
|
gpParts[i].Ratio = (BYTE)_iGradientRatios[i];
|
|
};
|
|
|
|
if (_eFillType == FT_RADIALGRADIENT)
|
|
{
|
|
PaintGradientRadialRect(memoryDC, rect2, _iGradientPartCount, gpParts);
|
|
}
|
|
else if (_eFillType == FT_VERTGRADIENT)
|
|
{
|
|
PaintVertGradient(memoryDC, rect2, _iGradientPartCount, gpParts);
|
|
}
|
|
else // if (_eFillType == FT_HORZGRADIENT)
|
|
{
|
|
PaintHorzGradient(memoryDC, rect2, _iGradientPartCount, gpParts);
|
|
}
|
|
|
|
|
|
if (fHavePath)
|
|
{
|
|
CSaveClipRegion scrCurrent;
|
|
hr = scrCurrent.Save(hdc); // save current clip region
|
|
if (FAILED(hr))
|
|
goto exit;
|
|
|
|
//---- select our shape as the clipping region in normal hdc ----
|
|
SelectClipPath(hdc, RGN_AND);
|
|
|
|
//---- blt our gradient into the shape-clipped rect into the normal hdc ----
|
|
BitBlt(hdc, rect.left, rect.top, iWidth, iHeight, memoryDC, 0, 0, SRCCOPY);
|
|
|
|
scrCurrent.Restore(hdc); // restore current clip region
|
|
}
|
|
else
|
|
{
|
|
//---- blt our gradient into the shape-clipped rect into the normal hdc ----
|
|
BitBlt(hdc, rect.left, rect.top, iWidth, iHeight, memoryDC, 0, 0, SRCCOPY);
|
|
}
|
|
|
|
exit:
|
|
scrOrig.Restore(hdc); // restore clipping region
|
|
|
|
return hr;
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
HRESULT CBorderFill::DrawBackground(CRenderObj *pRender, HDC hdcOrig,
|
|
const RECT *pRect, OPTIONAL const DTBGOPTS *pOptions)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
//---- options ----
|
|
DWORD dwOptionFlags = 0;
|
|
BOOL fBorder = TRUE;
|
|
BOOL fContent = TRUE;
|
|
BOOL fGettingRegion = FALSE;
|
|
const RECT *pClipRect = NULL;
|
|
|
|
if (pOptions)
|
|
{
|
|
dwOptionFlags = pOptions->dwFlags;
|
|
|
|
if (dwOptionFlags & DTBG_CLIPRECT)
|
|
pClipRect = &pOptions->rcClip;
|
|
|
|
if (dwOptionFlags & DTBG_OMITBORDER)
|
|
fBorder = FALSE;
|
|
|
|
if (dwOptionFlags & DTBG_OMITCONTENT)
|
|
fContent = FALSE;
|
|
|
|
if (dwOptionFlags & DTBG_COMPUTINGREGION)
|
|
fGettingRegion = TRUE;
|
|
}
|
|
|
|
//---- optimize for perf-sensitive paths thru here ----
|
|
if (_fNoDraw)
|
|
{
|
|
//---- nothing to do ----
|
|
}
|
|
else if ((_eFillType == FT_SOLID) && (_eBorderType == BT_RECT)) // solid rectangle
|
|
{
|
|
if (! _iBorderSize) // no border case
|
|
{
|
|
if (fContent)
|
|
{
|
|
//---- clip, if needed ----
|
|
RECT rcContent = *pRect;
|
|
if (pClipRect)
|
|
IntersectRect(&rcContent, &rcContent, pClipRect);
|
|
|
|
//---- fastest solid rect ----
|
|
COLORREF crOld = SetBkColor(hdcOrig, _crFill);
|
|
ExtTextOut(hdcOrig, 0, 0, ETO_OPAQUE, &rcContent, NULL, 0, NULL);
|
|
|
|
//---- restore old color ----
|
|
SetBkColor(hdcOrig, crOld);
|
|
}
|
|
}
|
|
else // border case
|
|
{
|
|
COLORREF crOld = GetBkColor(hdcOrig);
|
|
|
|
//---- draw clipped borders ----
|
|
if (fBorder)
|
|
{
|
|
RECT rcLine;
|
|
|
|
SetBkColor(hdcOrig, _crBorder);
|
|
|
|
//---- draw LEFT line ----
|
|
SetRect(&rcLine, pRect->left, pRect->top, pRect->left+_iBorderSize,
|
|
pRect->bottom);
|
|
|
|
if (pClipRect)
|
|
IntersectRect(&rcLine, &rcLine, pClipRect);
|
|
|
|
ExtTextOut(hdcOrig, 0, 0, ETO_OPAQUE, &rcLine, NULL, 0, NULL);
|
|
|
|
//---- draw RIGHT line ----
|
|
SetRect(&rcLine, pRect->right-_iBorderSize, pRect->top, pRect->right,
|
|
pRect->bottom);
|
|
|
|
if (pClipRect)
|
|
IntersectRect(&rcLine, &rcLine, pClipRect);
|
|
|
|
ExtTextOut(hdcOrig, 0, 0, ETO_OPAQUE, &rcLine, NULL, 0, NULL);
|
|
|
|
//---- draw TOP line ----
|
|
SetRect(&rcLine, pRect->left, pRect->top, pRect->right,
|
|
pRect->top+_iBorderSize);
|
|
|
|
if (pClipRect)
|
|
IntersectRect(&rcLine, &rcLine, pClipRect);
|
|
|
|
ExtTextOut(hdcOrig, 0, 0, ETO_OPAQUE, &rcLine, NULL, 0, NULL);
|
|
|
|
//---- draw BOTTOM line ----
|
|
SetRect(&rcLine, pRect->left, pRect->bottom-_iBorderSize, pRect->right,
|
|
pRect->bottom);
|
|
|
|
if (pClipRect)
|
|
IntersectRect(&rcLine, &rcLine, pClipRect);
|
|
|
|
ExtTextOut(hdcOrig, 0, 0, ETO_OPAQUE, &rcLine, NULL, 0, NULL);
|
|
}
|
|
|
|
//---- remove borders from rect to draw content ----
|
|
if (fContent)
|
|
{
|
|
RECT rcContent = *pRect;
|
|
rcContent.left += _iBorderSize;
|
|
rcContent.right -= _iBorderSize;
|
|
rcContent.top += _iBorderSize;
|
|
rcContent.bottom -= _iBorderSize;
|
|
|
|
if (pClipRect)
|
|
IntersectRect(&rcContent, &rcContent, pClipRect);
|
|
|
|
//---- fastest solid rect ----
|
|
SetBkColor(hdcOrig, _crFill);
|
|
ExtTextOut(hdcOrig, 0, 0, ETO_OPAQUE, &rcContent, NULL, 0, NULL);
|
|
}
|
|
|
|
//---- restore old color ----
|
|
SetBkColor(hdcOrig, crOld);
|
|
}
|
|
}
|
|
else // all other cases
|
|
{
|
|
hr = DrawComplexBackground(pRender, hdcOrig, pRect, fGettingRegion,
|
|
fBorder, fContent, pClipRect);
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
HRESULT CBorderFill::GetBackgroundRegion(CRenderObj *pRender, OPTIONAL HDC hdc,
|
|
const RECT *pRect, HRGN *pRegion)
|
|
{
|
|
HRESULT hr;
|
|
|
|
//---- see if it even has a transparent part ----
|
|
if (! IsBackgroundPartiallyTransparent())
|
|
{
|
|
//---- return the bounding rect as the region ----
|
|
HRGN hrgn = CreateRectRgn(pRect->left, pRect->top,
|
|
pRect->right, pRect->bottom);
|
|
|
|
if (! hrgn)
|
|
return MakeErrorLast();
|
|
|
|
*pRegion = hrgn;
|
|
return S_OK;
|
|
}
|
|
|
|
//---- create a memory dc/bitmap to draw info ----
|
|
CMemoryDC hdcMemory;
|
|
|
|
//---- use maximum drawing values as size of DC ----
|
|
hr = hdcMemory.OpenDC(NULL, RECTWIDTH(pRect), RECTHEIGHT(pRect));
|
|
if (FAILED(hr))
|
|
return hr;
|
|
|
|
BOOL fOK = BeginPath(hdcMemory);
|
|
if (! fOK)
|
|
return MakeErrorLast();
|
|
|
|
DTBGOPTS Opts = {sizeof(Opts), DTBG_COMPUTINGREGION};
|
|
|
|
hr = DrawBackground(pRender, hdcMemory, pRect, &Opts);
|
|
if (FAILED(hr))
|
|
return hr;
|
|
|
|
fOK = EndPath(hdcMemory);
|
|
if (! fOK)
|
|
return MakeErrorLast();
|
|
|
|
HRGN hrgn = PathToRegion(hdcMemory);
|
|
if (! hrgn)
|
|
return MakeErrorLast();
|
|
|
|
*pRegion = hrgn;
|
|
return S_OK;
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
BOOL CBorderFill::IsBackgroundPartiallyTransparent()
|
|
{
|
|
return ((_eBorderType != BT_RECT) || _fNoDraw);
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
HRESULT CBorderFill::HitTestBackground(CRenderObj *pRender, OPTIONAL HDC hdc,
|
|
DWORD dwHTFlags, const RECT *pRect, HRGN hrgn, POINT ptTest, OUT WORD *pwHitCode)
|
|
{
|
|
MARGINS margins;
|
|
GetContentMargins(pRender, hdc, &margins);
|
|
*pwHitCode = HitTestRect( dwHTFlags, pRect, margins, ptTest );
|
|
return S_OK;
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
void CBorderFill::GetContentMargins(CRenderObj *pRender, OPTIONAL HDC hdc, MARGINS *pMargins)
|
|
{
|
|
*pMargins = _ContentMargins;
|
|
|
|
//---- adjust for DPI scaling ----
|
|
#if 0
|
|
int iDcDpi;
|
|
|
|
if (DpiDiff(hdc, &iDcDpi)))
|
|
{
|
|
pMargins->cxLeftWidth = DpiScale(pMargins->cxLeftWidth, iDcDpi);
|
|
pMargins->cxRightWidth = DpiScale(pMargins->cxRightWidth, iDcDpi);
|
|
pMargins->cyTopHeight = DpiScale(pMargins->cyTopHeight, iDcDpi);
|
|
pMargins->cyBottomHeight = DpiScale(pMargins->cyBottomHeight, iDcDpi);
|
|
}
|
|
#endif
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
HRESULT CBorderFill::GetBackgroundContentRect(CRenderObj *pRender, OPTIONAL HDC hdc,
|
|
const RECT *pBoundingRect, RECT *pContentRect)
|
|
{
|
|
MARGINS margins;
|
|
GetContentMargins(pRender, hdc, &margins);
|
|
|
|
pContentRect->left = pBoundingRect->left + margins.cxLeftWidth;
|
|
pContentRect->top = pBoundingRect->top + margins.cyTopHeight;
|
|
|
|
pContentRect->right = pBoundingRect->right - margins.cxRightWidth;
|
|
pContentRect->bottom = pBoundingRect->bottom - margins.cyBottomHeight;
|
|
|
|
return S_OK;
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
HRESULT CBorderFill::GetBackgroundExtent(CRenderObj *pRender, OPTIONAL HDC hdc,
|
|
const RECT *pContentRect, RECT *pExtentRect)
|
|
{
|
|
MARGINS margins;
|
|
GetContentMargins(pRender, hdc, &margins);
|
|
|
|
pExtentRect->left = pContentRect->left - margins.cxLeftWidth;
|
|
pExtentRect->top = pContentRect->top-+ margins.cyTopHeight;
|
|
|
|
pExtentRect->right = pContentRect->right + margins.cxRightWidth;
|
|
pExtentRect->bottom = pContentRect->bottom + margins.cyBottomHeight;
|
|
|
|
return S_OK;
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
HRESULT CBorderFill::GetPartSize(HDC hdc, THEMESIZE eSize, SIZE *psz)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
if (eSize == TS_MIN)
|
|
{
|
|
psz->cx = max(1, _iBorderSize*2);
|
|
psz->cy = max(1, _iBorderSize*2);
|
|
}
|
|
else if (eSize == TS_TRUE)
|
|
{
|
|
psz->cx = _iBorderSize*2 + 1;
|
|
psz->cy = _iBorderSize*2 + 1;
|
|
}
|
|
else
|
|
{
|
|
hr = MakeError32(E_INVALIDARG);
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
//---------------------------------------------------------------------------
|