⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 draw.c

📁 这是一个开放源代码的与WINNT/WIN2K/WIN2003兼容的操作系统
💻 C
📖 第 1 页 / 共 5 页
字号:
            int srcCenterWidth   = srcSize.x - (sm.cxLeftWidth + sm.cxRightWidth);
            int destCenterHeight = dstSize.y - (sm.cyTopHeight + sm.cyBottomHeight);
            int srcCenterHeight  = srcSize.y - (sm.cyTopHeight + sm.cyBottomHeight);

            if(destCenterWidth > 0) {
                /* Center top */
                if(!UXTHEME_SizedBlt (hdcDst, sm.cxLeftWidth, 0, 
                                      destCenterWidth, sm.cyTopHeight,
                                      hdcSrc, rcSrc.left+sm.cxLeftWidth, rcSrc.top, 
                                      srcCenterWidth, sm.cyTopHeight, 
                                      sizingtype, transparent, transparentcolor)) {
                    hr = HRESULT_FROM_WIN32(GetLastError());
                    goto draw_error; 
                }
                /* Center bottom */
                if(!UXTHEME_SizedBlt (hdcDst, sm.cxLeftWidth, dstSize.y-sm.cyBottomHeight, 
                                      destCenterWidth, sm.cyBottomHeight,
                                      hdcSrc, rcSrc.left+sm.cxLeftWidth, rcSrc.bottom-sm.cyBottomHeight, 
                                      srcCenterWidth, sm.cyBottomHeight, 
                                      sizingtype, transparent, transparentcolor)) {
                    hr = HRESULT_FROM_WIN32(GetLastError());
                    goto draw_error; 
                }
            }
            if(destCenterHeight > 0) {
                /* Left center */
                if(!UXTHEME_SizedBlt (hdcDst, 0, sm.cyTopHeight, 
                                      sm.cxLeftWidth, destCenterHeight,
                                      hdcSrc, rcSrc.left, rcSrc.top+sm.cyTopHeight, 
                                      sm.cxLeftWidth, srcCenterHeight, 
                                      sizingtype, 
                                      transparent, transparentcolor)) {
                    hr = HRESULT_FROM_WIN32(GetLastError());
                    goto draw_error; 
                }
                /* Right center */
                if(!UXTHEME_SizedBlt (hdcDst, dstSize.x-sm.cxRightWidth, sm.cyTopHeight, 
                                      sm.cxRightWidth, destCenterHeight,
                                      hdcSrc, rcSrc.right-sm.cxRightWidth, rcSrc.top+sm.cyTopHeight, 
                                      sm.cxRightWidth, srcCenterHeight, 
                                      sizingtype, transparent, transparentcolor)) {
                    hr = HRESULT_FROM_WIN32(GetLastError());
                    goto draw_error; 
                }
            }
            if(destCenterHeight > 0 && destCenterWidth > 0) {
                BOOL borderonly = FALSE;
                GetThemeBool(hTheme, iPartId, iStateId, TMT_BORDERONLY, &borderonly);
                if(!borderonly) {
                    /* Center */
                    if(!UXTHEME_SizedBlt (hdcDst, sm.cxLeftWidth, sm.cyTopHeight, 
                                          destCenterWidth, destCenterHeight,
                                          hdcSrc, rcSrc.left+sm.cxLeftWidth, rcSrc.top+sm.cyTopHeight, 
                                          srcCenterWidth, srcCenterHeight, 
                                          sizingtype, transparent, transparentcolor)) {
                        hr = HRESULT_FROM_WIN32(GetLastError());
                        goto draw_error; 
                    }
                }
            }
        }

draw_error:
        SetViewportOrgEx (hdcDst, org.x, org.y, NULL);
    }
    SelectObject(hdcSrc, oldSrc);
    DeleteDC(hdcSrc);
    CopyRect(pRect, &rcDst);
    return hr;
}

/***********************************************************************
 *      UXTHEME_DrawBorderRectangle
 *
 * Draw the bounding rectangle for a borderfill background
 */
static HRESULT UXTHEME_DrawBorderRectangle(HTHEME hTheme, HDC hdc, int iPartId,
                                    int iStateId, RECT *pRect,
                                    const DTBGOPTS *pOptions)
{
    HRESULT hr = S_OK;
    HPEN hPen;
    HGDIOBJ oldPen;
    COLORREF bordercolor = RGB(0,0,0);
    int bordersize = 1;

    GetThemeInt(hTheme, iPartId, iStateId, TMT_BORDERSIZE, &bordersize);
    if(bordersize > 0) {
        POINT ptCorners[5];
        ptCorners[0].x = pRect->left;
        ptCorners[0].y = pRect->top;
        ptCorners[1].x = pRect->right-1;
        ptCorners[1].y = pRect->top;
        ptCorners[2].x = pRect->right-1;
        ptCorners[2].y = pRect->bottom-1;
        ptCorners[3].x = pRect->left;
        ptCorners[3].y = pRect->bottom-1;
        ptCorners[4].x = pRect->left;
        ptCorners[4].y = pRect->top;

        InflateRect(pRect, -bordersize, -bordersize);
        if(pOptions->dwFlags & DTBG_OMITBORDER)
            return S_OK;
        GetThemeColor(hTheme, iPartId, iStateId, TMT_BORDERCOLOR, &bordercolor);
        hPen = CreatePen(PS_SOLID, bordersize, bordercolor);
        if(!hPen)
            return HRESULT_FROM_WIN32(GetLastError());
        oldPen = SelectObject(hdc, hPen);

        if(!Polyline(hdc, ptCorners, 5))
            hr = HRESULT_FROM_WIN32(GetLastError());

        SelectObject(hdc, oldPen);
        DeleteObject(hPen);
    }
    return hr;
}

/***********************************************************************
 *      UXTHEME_DrawBackgroundFill
 *
 * Fill a borderfill background rectangle
 */
static HRESULT UXTHEME_DrawBackgroundFill(HTHEME hTheme, HDC hdc, int iPartId,
                                   int iStateId, RECT *pRect,
                                   const DTBGOPTS *pOptions)
{
    HRESULT hr = S_OK;
    int filltype = FT_SOLID;

    TRACE("(%d,%d,%d)\n", iPartId, iStateId, pOptions->dwFlags);

    if(pOptions->dwFlags & DTBG_OMITCONTENT)
        return S_OK;

    GetThemeEnumValue(hTheme, iPartId, iStateId, TMT_FILLTYPE, &filltype);

    if(filltype == FT_SOLID) {
        HBRUSH hBrush;
        COLORREF fillcolor = RGB(255,255,255);

        GetThemeColor(hTheme, iPartId, iStateId, TMT_FILLCOLOR, &fillcolor);
        hBrush = CreateSolidBrush(fillcolor);
        if(!FillRect(hdc, pRect, hBrush))
            hr = HRESULT_FROM_WIN32(GetLastError());
        DeleteObject(hBrush);
    }
    else if(filltype == FT_VERTGRADIENT || filltype == FT_HORZGRADIENT) {
        /* FIXME: This only accounts for 2 gradient colors (out of 5) and ignores
            the gradient ratios (no idea how those work)
            Few themes use this, and the ones I've seen only use 2 colors with
            a gradient ratio of 0 and 255 respectivly
        */

        COLORREF gradient1 = RGB(0,0,0);
        COLORREF gradient2 = RGB(255,255,255);
        TRIVERTEX vert[2];
        GRADIENT_RECT gRect;

        FIXME("Gradient implementation not complete\n");

        GetThemeColor(hTheme, iPartId, iStateId, TMT_GRADIENTCOLOR1, &gradient1);
        GetThemeColor(hTheme, iPartId, iStateId, TMT_GRADIENTCOLOR2, &gradient2);

        vert[0].x     = pRect->left;
        vert[0].y     = pRect->top;
        vert[0].Red   = GetRValue(gradient1) << 8;
        vert[0].Green = GetGValue(gradient1) << 8;
        vert[0].Blue  = GetBValue(gradient1) << 8;
        vert[0].Alpha = 0x0000;

        vert[1].x     = pRect->right;
        vert[1].y     = pRect->bottom;
        vert[1].Red   = GetRValue(gradient2) << 8;
        vert[1].Green = GetGValue(gradient2) << 8;
        vert[1].Blue  = GetBValue(gradient2) << 8;
        vert[1].Alpha = 0x0000;

        gRect.UpperLeft  = 0;
        gRect.LowerRight = 1;
        GradientFill(hdc,vert,2,&gRect,1,filltype==FT_HORZGRADIENT?GRADIENT_FILL_RECT_H:GRADIENT_FILL_RECT_V);
    }
    else if(filltype == FT_RADIALGRADIENT) {
        /* I've never seen this used in a theme */
        FIXME("Radial gradient\n");
    }
    else if(filltype == FT_TILEIMAGE) {
        /* I've never seen this used in a theme */
        FIXME("Tile image\n");
    }
    return hr;
}

/***********************************************************************
 *      UXTHEME_DrawBorderBackground
 *
 * Draw an imagefile background
 */
static HRESULT UXTHEME_DrawBorderBackground(HTHEME hTheme, HDC hdc, int iPartId,
                                     int iStateId, const RECT *pRect,
                                     const DTBGOPTS *pOptions)
{
    HRESULT hr;
    RECT rt;

    CopyRect(&rt, pRect);

    hr = UXTHEME_DrawBorderRectangle(hTheme, hdc, iPartId, iStateId, &rt, pOptions);
    if(FAILED(hr))
        return hr;
    return UXTHEME_DrawBackgroundFill(hTheme, hdc, iPartId, iStateId, &rt, pOptions);
}

/***********************************************************************
 *      DrawThemeBackgroundEx                               (UXTHEME.@)
 */
HRESULT WINAPI DrawThemeBackgroundEx(HTHEME hTheme, HDC hdc, int iPartId,
                                     int iStateId, const RECT *pRect,
                                     const DTBGOPTS *pOptions)
{
    HRESULT hr;
    const DTBGOPTS defaultOpts = {sizeof(DTBGOPTS), 0, {0,0,0,0}};
    const DTBGOPTS *opts;
    HRGN clip = NULL;
    int hasClip = -1;
    int bgtype = BT_BORDERFILL;
    RECT rt;

    TRACE("(%p,%p,%d,%d,%d,%d)\n", hTheme, hdc, iPartId, iStateId,pRect->left,pRect->top);
    if(!hTheme)
        return E_HANDLE;

    GetThemeEnumValue(hTheme, iPartId, iStateId, TMT_BGTYPE, &bgtype);
    if (bgtype == BT_NONE) return S_OK;

    /* Ensure we have a DTBGOPTS structure available, simplifies some of the code */
    opts = pOptions;
    if(!opts) opts = &defaultOpts;

    if(opts->dwFlags & DTBG_CLIPRECT) {
        clip = CreateRectRgn(0,0,1,1);
        hasClip = GetClipRgn(hdc, clip);
        if(hasClip == -1)
            TRACE("Failed to get original clipping region\n");
        else
            IntersectClipRect(hdc, opts->rcClip.left, opts->rcClip.top, opts->rcClip.right, opts->rcClip.bottom);
    }
    CopyRect(&rt, pRect);

    if(bgtype == BT_IMAGEFILE)
        hr = UXTHEME_DrawImageBackground(hTheme, hdc, iPartId, iStateId, &rt, opts);
    else if(bgtype == BT_BORDERFILL)
        hr = UXTHEME_DrawBorderBackground(hTheme, hdc, iPartId, iStateId, pRect, opts);
    else {
        FIXME("Unknown background type\n");
        /* This should never happen, and hence I don't know what to return */
        hr = E_FAIL;
    }
    if(SUCCEEDED(hr))
        hr = UXTHEME_DrawGlyph(hTheme, hdc, iPartId, iStateId, &rt, opts);
    if(opts->dwFlags & DTBG_CLIPRECT) {
        if(hasClip == 0)
            SelectClipRgn(hdc, NULL);
        else if(hasClip == 1)
            SelectClipRgn(hdc, clip);
        DeleteObject(clip);
    }
    return hr;
}

/*
 * DrawThemeEdge() implementation
 *
 * Since it basically is DrawEdge() with different colors, I copied its code
 * from user32's uitools.c.
 */

enum
{
    EDGE_LIGHT,
    EDGE_HIGHLIGHT,
    EDGE_SHADOW,
    EDGE_DARKSHADOW,
    EDGE_FILL,

    EDGE_WINDOW,
    EDGE_WINDOWFRAME,

    EDGE_NUMCOLORS
};

static const struct 
{
    int themeProp;
    int sysColor;
} EdgeColorMap[EDGE_NUMCOLORS] = {
    {TMT_EDGELIGHTCOLOR,                  COLOR_3DLIGHT},
    {TMT_EDGEHIGHLIGHTCOLOR,              COLOR_BTNHIGHLIGHT},
    {TMT_EDGESHADOWCOLOR,                 COLOR_BTNSHADOW},
    {TMT_EDGEDKSHADOWCOLOR,               COLOR_3DDKSHADOW},
    {TMT_EDGEFILLCOLOR,                   COLOR_BTNFACE},
    {-1,                                  COLOR_WINDOW},
    {-1,                                  COLOR_WINDOWFRAME}
};

static const signed char LTInnerNormal[] = {
    -1,           -1,                 -1,                 -1,
    -1,           EDGE_HIGHLIGHT,     EDGE_HIGHLIGHT,     -1,
    -1,           EDGE_DARKSHADOW,    EDGE_DARKSHADOW,    -1,
    -1,           -1,                 -1,                 -1
};

static const signed char LTOuterNormal[] = {
    -1,                 EDGE_LIGHT,     EDGE_SHADOW, -1,
    EDGE_HIGHLIGHT,     EDGE_LIGHT,     EDGE_SHADOW, -1,
    EDGE_DARKSHADOW,    EDGE_LIGHT,     EDGE_SHADOW, -1,
    -1,                 EDGE_LIGHT,     EDGE_SHADOW, -1
};

static const signed char RBInnerNormal[] = {
    -1,           -1,                 -1,               -1,
    -1,           EDGE_SHADOW,        EDGE_SHADOW,      -1,
    -1,           EDGE_LIGHT,         EDGE_LIGHT,       -1,
    -1,           -1,                 -1,               -1
};

static const signed char RBOuterNormal[] = {
    -1,               EDGE_DARKSHADOW,  EDGE_HIGHLIGHT, -1,
    EDGE_SHADOW,      EDGE_DARKSHADOW,  EDGE_HIGHLIGHT, -1,
    EDGE_LIGHT,       EDGE_DARKSHADOW,  EDGE_HIGHLIGHT, -1,
    -1,               EDGE_DARKSHADOW,  EDGE_HIGHLIGHT, -1
};

static const signed char LTInnerSoft[] = {
    -1,                  -1,                -1,               -1,
    -1,                  EDGE_LIGHT,        EDGE_LIGHT,       -1,
    -1,                  EDGE_SHADOW,       EDGE_SHADOW,      -1,
    -1,                  -1,                -1,               -1
};

static const signed char LTOuterSoft[] = {
    -1,               EDGE_HIGHLIGHT, EDGE_DARKSHADOW, -1,
    EDGE_LIGHT,       EDGE_HIGHLIGHT, EDGE_DARKSHADOW, -1,
    EDGE_SHADOW,      EDGE_HIGHLIGHT, EDGE_DARKSHADOW, -1,
    -1,               EDGE_HIGHLIGHT, EDGE_DARKSHADOW, -1
};

#define RBInnerSoft RBInnerNormal   /* These are the same */
#define RBOuterSoft RBOuterNormal

static const signed char LTRBOuterMono[] = {
    -1,           EDGE_WINDOWFRAME, EDGE_WINDOWFRAME, EDGE_WINDOWFRAME,

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -