5

chrome または firefox の Scrollbas にはハンドルがありません。それらはハンドル コントロールですが、システムの既定のスクロールバーと同じ外観と動作を共有します。このことから、これらのブラウザーは、DrawThemeBackground などの Windows テーマ API を使用してスクロールバーを描画していると推測できます。

ただし、DrawThemeBackground などの API は GDI であり、chrome/firefox は skia/cario を使用してキャンバス全体をレンダリングします。私の問題は、彼らがこの 2 種類の技術をどのように組み合わせるかということです。

擬似コード:

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

ファイアフォックス

実はカイロには、カイロ表面から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 キャンバスから 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. ただし、ビジュアル スタイルが無効になっている場合 (クラシック モードは 1 つ)、DrawFrameControlコントロールの描画に使用されます。

于 2013-03-24T07:59:53.990 に答える