📄 draw.c
字号:
if (!UXTHEME_Blt (hdcDst, xOfs, yOfs, bltWidth, bltHeight,
hdcSrc, nXOriginSrc, nYOriginSrc,
transparent, transcolor))
return FALSE;
xOfs += nWidthSrc;
xRemaining -= nWidthSrc;
}
yOfs += nHeightSrc;
yRemaining -= nHeightSrc;
}
return TRUE;
}
else
{
return UXTHEME_StretchBlt (hdcDst, nXOriginDst, nYOriginDst, nWidthDst, nHeightDst,
hdcSrc, nXOriginSrc, nYOriginSrc, nWidthSrc, nHeightSrc,
transparent, transcolor);
}
}
/* Get transparency parameters passed to UXTHEME_StretchBlt() - the parameters
* depend on whether the image has full alpha or whether it is
* color-transparent or just opaque. */
static inline void get_transparency (HTHEME hTheme, int iPartId, int iStateId,
BOOL hasImageAlpha, INT* transparent,
COLORREF* transparentcolor, BOOL glyph)
{
if (hasImageAlpha)
{
*transparent = ALPHABLEND_FULL;
*transparentcolor = RGB (255, 0, 255);
}
else
{
BOOL trans = FALSE;
GetThemeBool(hTheme, iPartId, iStateId,
glyph ? TMT_GLYPHTRANSPARENT : TMT_TRANSPARENT, &trans);
if(trans) {
*transparent = ALPHABLEND_BINARY;
if(FAILED(GetThemeColor(hTheme, iPartId, iStateId,
glyph ? TMT_GLYPHTRANSPARENTCOLOR : TMT_TRANSPARENTCOLOR,
transparentcolor))) {
/* If image is transparent, but no color was specified, use magenta */
*transparentcolor = RGB(255, 0, 255);
}
}
else
*transparent = ALPHABLEND_NONE;
}
}
/***********************************************************************
* UXTHEME_DrawImageGlyph
*
* Draw an imagefile glyph
*/
static HRESULT UXTHEME_DrawImageGlyph(HTHEME hTheme, HDC hdc, int iPartId,
int iStateId, RECT *pRect,
const DTBGOPTS *pOptions)
{
HRESULT hr;
HBITMAP bmpSrc = NULL;
HDC hdcSrc = NULL;
HGDIOBJ oldSrc = NULL;
RECT rcSrc;
INT transparent = FALSE;
COLORREF transparentcolor;
int valign = VA_CENTER;
int halign = HA_CENTER;
POINT dstSize;
POINT srcSize;
POINT topleft;
BOOL hasAlpha;
hr = UXTHEME_LoadImage(hTheme, hdc, iPartId, iStateId, pRect, TRUE,
&bmpSrc, &rcSrc, &hasAlpha);
if(FAILED(hr)) return hr;
hdcSrc = CreateCompatibleDC(hdc);
if(!hdcSrc) {
hr = HRESULT_FROM_WIN32(GetLastError());
return hr;
}
oldSrc = SelectObject(hdcSrc, bmpSrc);
dstSize.x = pRect->right-pRect->left;
dstSize.y = pRect->bottom-pRect->top;
srcSize.x = rcSrc.right-rcSrc.left;
srcSize.y = rcSrc.bottom-rcSrc.top;
get_transparency (hTheme, iPartId, iStateId, hasAlpha, &transparent,
&transparentcolor, TRUE);
GetThemeEnumValue(hTheme, iPartId, iStateId, TMT_VALIGN, &valign);
GetThemeEnumValue(hTheme, iPartId, iStateId, TMT_HALIGN, &halign);
topleft.x = pRect->left;
topleft.y = pRect->top;
if(halign == HA_CENTER) topleft.x += (dstSize.x/2)-(srcSize.x/2);
else if(halign == HA_RIGHT) topleft.x += dstSize.x-srcSize.x;
if(valign == VA_CENTER) topleft.y += (dstSize.y/2)-(srcSize.y/2);
else if(valign == VA_BOTTOM) topleft.y += dstSize.y-srcSize.y;
if(!UXTHEME_Blt(hdc, topleft.x, topleft.y, srcSize.x, srcSize.y,
hdcSrc, rcSrc.left, rcSrc.top,
transparent, transparentcolor)) {
hr = HRESULT_FROM_WIN32(GetLastError());
}
SelectObject(hdcSrc, oldSrc);
DeleteDC(hdcSrc);
return hr;
}
/***********************************************************************
* UXTHEME_DrawImageGlyph
*
* Draw glyph on top of background, if appropriate
*/
static HRESULT UXTHEME_DrawGlyph(HTHEME hTheme, HDC hdc, int iPartId,
int iStateId, RECT *pRect,
const DTBGOPTS *pOptions)
{
int glyphtype = GT_NONE;
GetThemeEnumValue(hTheme, iPartId, iStateId, TMT_GLYPHTYPE, &glyphtype);
if(glyphtype == GT_IMAGEGLYPH) {
return UXTHEME_DrawImageGlyph(hTheme, hdc, iPartId, iStateId, pRect, pOptions);
}
else if(glyphtype == GT_FONTGLYPH) {
/* I don't know what a font glyph is, I've never seen it used in any themes */
FIXME("Font glyph\n");
}
return S_OK;
}
/***********************************************************************
* get_image_part_size
*
* Used by GetThemePartSize and UXTHEME_DrawImageBackground
*/
static HRESULT get_image_part_size (HTHEME hTheme, HDC hdc, int iPartId,
int iStateId, RECT *prc, THEMESIZE eSize,
POINT *psz)
{
HRESULT hr = S_OK;
HBITMAP bmpSrc;
RECT rcSrc;
BOOL hasAlpha;
hr = UXTHEME_LoadImage(hTheme, hdc, iPartId, iStateId, prc, FALSE,
&bmpSrc, &rcSrc, &hasAlpha);
if (FAILED(hr)) return hr;
switch (eSize)
{
case TS_DRAW:
if (prc != NULL)
{
RECT rcDst;
POINT dstSize;
POINT srcSize;
int sizingtype = ST_STRETCH;
BOOL uniformsizing = FALSE;
CopyRect(&rcDst, prc);
dstSize.x = rcDst.right-rcDst.left;
dstSize.y = rcDst.bottom-rcDst.top;
srcSize.x = rcSrc.right-rcSrc.left;
srcSize.y = rcSrc.bottom-rcSrc.top;
GetThemeBool(hTheme, iPartId, iStateId, TMT_UNIFORMSIZING, &uniformsizing);
if(uniformsizing) {
/* Scale height and width equally */
if (dstSize.x*srcSize.y < dstSize.y*srcSize.x)
{
dstSize.y = MulDiv (srcSize.y, dstSize.x, srcSize.x);
rcDst.bottom = rcDst.top + dstSize.y;
}
else
{
dstSize.x = MulDiv (srcSize.x, dstSize.y, srcSize.y);
rcDst.right = rcDst.left + dstSize.x;
}
}
GetThemeEnumValue(hTheme, iPartId, iStateId, TMT_SIZINGTYPE, &sizingtype);
if(sizingtype == ST_TRUESIZE) {
int truesizestretchmark = 100;
if(dstSize.x < 0 || dstSize.y < 0) {
BOOL mirrorimage = TRUE;
GetThemeBool(hTheme, iPartId, iStateId, TMT_MIRRORIMAGE, &mirrorimage);
if(mirrorimage) {
if(dstSize.x < 0) {
rcDst.left += dstSize.x;
rcDst.right += dstSize.x;
}
if(dstSize.y < 0) {
rcDst.top += dstSize.y;
rcDst.bottom += dstSize.y;
}
}
}
/* Whatever TrueSizeStretchMark does - it does not seem to
* be what's outlined below. It appears as if native
* uxtheme always stretches if dest is smaller than source
* (ie as if TrueSizeStretchMark==100 with the code below) */
#if 0
/* Only stretch when target exceeds source by truesizestretchmark percent */
GetThemeInt(hTheme, iPartId, iStateId, TMT_TRUESIZESTRETCHMARK, &truesizestretchmark);
#endif
if(dstSize.x < 0 || dstSize.y < 0 ||
(MulDiv(srcSize.x, 100, dstSize.x) > truesizestretchmark &&
MulDiv(srcSize.y, 100, dstSize.y) > truesizestretchmark)) {
memcpy (psz, &dstSize, sizeof (SIZE));
}
else {
memcpy (psz, &srcSize, sizeof (SIZE));
}
}
else
{
psz->x = abs(dstSize.x);
psz->y = abs(dstSize.y);
}
break;
}
/* else fall through */
case TS_MIN:
/* FIXME: couldn't figure how native uxtheme computes min size */
case TS_TRUE:
psz->x = rcSrc.right - rcSrc.left;
psz->y = rcSrc.bottom - rcSrc.top;
break;
}
return hr;
}
/***********************************************************************
* UXTHEME_DrawImageBackground
*
* Draw an imagefile background
*/
static HRESULT UXTHEME_DrawImageBackground(HTHEME hTheme, HDC hdc, int iPartId,
int iStateId, RECT *pRect,
const DTBGOPTS *pOptions)
{
HRESULT hr = S_OK;
HBITMAP bmpSrc;
HGDIOBJ oldSrc;
HDC hdcSrc;
RECT rcSrc;
RECT rcDst;
POINT dstSize;
POINT srcSize;
POINT drawSize;
int sizingtype = ST_STRETCH;
INT transparent;
COLORREF transparentcolor = 0;
BOOL hasAlpha;
hr = UXTHEME_LoadImage(hTheme, hdc, iPartId, iStateId, pRect, FALSE,
&bmpSrc, &rcSrc, &hasAlpha);
if(FAILED(hr)) return hr;
hdcSrc = CreateCompatibleDC(hdc);
if(!hdcSrc) {
hr = HRESULT_FROM_WIN32(GetLastError());
return hr;
}
oldSrc = SelectObject(hdcSrc, bmpSrc);
CopyRect(&rcDst, pRect);
get_transparency (hTheme, iPartId, iStateId, hasAlpha, &transparent,
&transparentcolor, FALSE);
dstSize.x = rcDst.right-rcDst.left;
dstSize.y = rcDst.bottom-rcDst.top;
srcSize.x = rcSrc.right-rcSrc.left;
srcSize.y = rcSrc.bottom-rcSrc.top;
GetThemeEnumValue(hTheme, iPartId, iStateId, TMT_SIZINGTYPE, &sizingtype);
if(sizingtype == ST_TRUESIZE) {
int valign = VA_CENTER, halign = HA_CENTER;
get_image_part_size (hTheme, hdc, iPartId, iStateId, pRect, TS_DRAW, &drawSize);
GetThemeEnumValue(hTheme, iPartId, iStateId, TMT_VALIGN, &valign);
GetThemeEnumValue(hTheme, iPartId, iStateId, TMT_HALIGN, &halign);
if (halign == HA_CENTER)
rcDst.left += (dstSize.x/2)-(drawSize.x/2);
else if (halign == HA_RIGHT)
rcDst.left = rcDst.right - drawSize.x;
if (valign == VA_CENTER)
rcDst.top += (dstSize.y/2)-(drawSize.y/2);
else if (valign == VA_BOTTOM)
rcDst.top = rcDst.bottom - drawSize.y;
rcDst.right = rcDst.left + drawSize.x;
rcDst.bottom = rcDst.top + drawSize.y;
if(!UXTHEME_StretchBlt(hdc, rcDst.left, rcDst.top, drawSize.x, drawSize.y,
hdcSrc, rcSrc.left, rcSrc.top, srcSize.x, srcSize.y,
transparent, transparentcolor))
hr = HRESULT_FROM_WIN32(GetLastError());
}
else {
HDC hdcDst = NULL;
MARGINS sm;
POINT org;
dstSize.x = abs(dstSize.x);
dstSize.y = abs(dstSize.y);
GetThemeMargins(hTheme, hdc, iPartId, iStateId, TMT_SIZINGMARGINS, NULL, &sm);
hdcDst = hdc;
OffsetViewportOrgEx(hdcDst, rcDst.left, rcDst.top, &org);
/* Upper left corner */
if(!UXTHEME_Blt(hdcDst, 0, 0, sm.cxLeftWidth, sm.cyTopHeight,
hdcSrc, rcSrc.left, rcSrc.top,
transparent, transparentcolor)) {
hr = HRESULT_FROM_WIN32(GetLastError());
goto draw_error;
}
/* Upper right corner */
if(!UXTHEME_Blt (hdcDst, dstSize.x-sm.cxRightWidth, 0,
sm.cxRightWidth, sm.cyTopHeight,
hdcSrc, rcSrc.right-sm.cxRightWidth, rcSrc.top,
transparent, transparentcolor)) {
hr = HRESULT_FROM_WIN32(GetLastError());
goto draw_error;
}
/* Lower left corner */
if(!UXTHEME_Blt (hdcDst, 0, dstSize.y-sm.cyBottomHeight,
sm.cxLeftWidth, sm.cyBottomHeight,
hdcSrc, rcSrc.left, rcSrc.bottom-sm.cyBottomHeight,
transparent, transparentcolor)) {
hr = HRESULT_FROM_WIN32(GetLastError());
goto draw_error;
}
/* Lower right corner */
if(!UXTHEME_Blt (hdcDst, dstSize.x-sm.cxRightWidth, dstSize.y-sm.cyBottomHeight,
sm.cxRightWidth, sm.cyBottomHeight,
hdcSrc, rcSrc.right-sm.cxRightWidth, rcSrc.bottom-sm.cyBottomHeight,
transparent, transparentcolor)) {
hr = HRESULT_FROM_WIN32(GetLastError());
goto draw_error;
}
if ((sizingtype == ST_STRETCH) || (sizingtype == ST_TILE)) {
int destCenterWidth = dstSize.x - (sm.cxLeftWidth + sm.cxRightWidth);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -