5

chrome 或 firefox 中的 Scrollbas 没有句柄。它们是无句柄控件,但它们确实与系统默认滚动条具有相同的外观和行为。由此,我们可以推断出这些浏览器使用了windows主题API,比如DrawThemeBackground,来绘制滚动条。

然而,DrawThemeBackground 等 API 是 GDI,chrome/firefox 使用skia/cario 来渲染整个画布。我的问题是他们如何结合这两种技术?

伪代码:

WM_PAINT:
    prepare canvas;
    draw the canvas with skia/cario;
    bitblt to the dc;
    draw the theme-related handless control;(???)
    bitblt to the dc or directly draw to the dc;(???)

过程和上面的一样吗?

4

1 回答 1

5

火狐

实际上 cairo 具有从 cairo 表面获取 DC 的功能。示例代码:

VOID OnPaint(HWND hwnd, HDC hdc)
{
    RECT rc;
    ::GetClientRect(hwnd, &rc);
    //draw one line
    cairo_surface_t* surface = cairo_win32_surface_create(hdc);
    cairo_t* cr = cairo_create(surface);
    cairo_set_source_rgb(cr, 0xff, 0, 0);
    cairo_set_line_width(cr, 1);
    cairo_move_to(cr, 0, 0);
    cairo_line_to(cr, rc.right, rc.bottom);
    cairo_stroke(cr);
    cairo_destroy(cr);

    //draw the theme background
    HDC hdcNew = cairo_win32_surface_get_dc(surface);
    HTHEME hTheme = OpenThemeData(NULL, L"SCROLLBAR");
    RECT rcArrow;
    SetRect(&rcArrow, 30, 30, 45, 45);
    DrawThemeBackground(hTheme, hdcNew, SBP_ARROWBTN, ABS_DOWNDISABLED, &rcArrow, NULL);
    cairo_surface_destroy(surface);
}

gfxWindowsNativeDrawing::BeginNativeDrawing()最后打电话HDC gfxWindowsSurface::GetDCWithClip(gfxContext *ctx)给cairo win32。

铬合金

Skia 不提供从skia canvas 到hdc 的转换功能,但是项目chrome 为skia 添加了一个扩展并实现了这个功能。

在skia/ext/bitmap_platform_device_win.cc:

HDC BitmapPlatformDevice::BitmapPlatformDeviceData::GetBitmapDC() {
}

它从画布内部位图创建一个内存 dc。

因此,在绘画时,您是否需要使用原生 dc 或一般的 cairo/skia 画布不再重要。

示例代码:

void TestChromeExt(HWND hwnd, HDC hdc)
{
    RECT rc;
    GetClientRect(hwnd, &rc);
    skia::BitmapPlatformDevice* pBmpDevice = skia::BitmapPlatformDevice::Create(rc.right, rc.bottom, true);
    skia::PlatformCanvas *pCanvas = new skia::PlatformCanvas(pBmpDevice);
    pCanvas->clear(SK_ColorWHITE);
    SkPaint paint;
    paint.setColor(SK_ColorRED);
    paint.setStrokeWidth(3);
    paint.setStyle(SkPaint::kStroke_Style);
    pCanvas->drawLine(0, 0, rc.right, rc.bottom, paint);
    HDC memdc = skia::BeginPlatformPaint(pCanvas);
    RECT rcArrow;
    SetRect(&rcArrow, 100, 200, 120, 220);
    DrawThemeBackground(OpenThemeData(NULL, L"SCROLLBAR"), memdc, SBP_ARROWBTN, ABS_DOWNDISABLED, &rcArrow, NULL);
    skia::EndPlatformPaint(pCanvas);
    skia::DrawToNativeContext(pCanvas, hdc, 0, 0, &rc);
}

对于 Windows,为确保原生外观,当启用视觉样式时,这些浏览器将使用DrawThemeBackground. 但是,当视觉样式被禁用时(经典模式为一种),它们将用于DrawFrameControl绘制控件。

于 2013-03-24T07:59:53.990 回答