【问题标题】:Make parent window transparent and child window opaque with CEF使用 CEF 使父窗口透明而子窗口不透明
【发布时间】:2019-04-24 11:57:10
【问题描述】:

在 Windows 上,我正在尝试使用 CEF(Chromium Embedded Framework)创建一个窗口应用程序,其父窗口是透明的,其子窗口是不透明的(我想要一个圆角和一个指向子窗口中的状态栏)。类似于:

我尝试使用SetLayeredWindowAttributes 使父窗口透明,但它也使子窗口透明。有没有办法在 Windows 上实现这一点?

【问题讨论】:

  • 如果您愿意牺牲一些性能(取决于您的应用,可能是最低限度),您可以使用屏幕外渲染将外星人控件作为您真实窗口中的浏览器视图。

标签: windows window adobe chromium-embedded


【解决方案1】:

SetLayeredWindowAttributes 需要一种颜色来实现透明度。确保子窗口不使用透明度颜色。您可以选择一种随机颜色,例如 RGB(255, 0, 254) 并假设子窗口没有使用它。

如果您无法控制子窗口,并且无法确定它可能使用什么颜色,那么SetWindowRgn 是创建非矩形窗口的另一种选择。

下面的示例显示了如何设置区域,使角为圆形,顶部为三角形。

您可以使用 GDI+ 获得更大的灵活性来绘制区域,并获得抗锯齿效果,使边框看起来更平滑。

#include <Windows.h>

int triangle_height = 30;
int corner_size = 20;
int caption_height = 60;

LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
{
    switch(msg)
    {
    case WM_CREATE:
    {
        //create a child button for testing
        CreateWindowW(L"BUTTON", L"Close", WS_CHILD | WS_VISIBLE,
            10, caption_height + 10, 100, 30,
            hwnd, HMENU(100), GetModuleHandle(NULL), NULL);

        RECT rc;
        GetClientRect(hwnd, &rc);

        //create a triangle region
        int w = rc.right;
        int h = rc.bottom;
        int z = triangle_height;
        POINT pt[3];
        pt[0] = { w / 2, 0 };
        pt[1] = { w / 2 - z, z };
        pt[2] = { w / 2 + z, z };
        HRGN htri = CreatePolygonRgn(pt, 3, WINDING);

        //create a round rectangle region
        HRGN hrgn = CreateRoundRectRgn(0, z, w, h - z, corner_size, corner_size);

        //combine the triangle with round rectangle
        CombineRgn(hrgn, htri, hrgn, RGN_OR);

        //set the new region
        SetWindowRgn(hwnd, hrgn, TRUE);

        DeleteObject(htri);
        DeleteObject(hrgn);
        return 0;
    }

    case WM_PAINT:
    {
        PAINTSTRUCT ps;
        HDC hdc = BeginPaint(hwnd, &ps);
        RECT rc = ps.rcPaint;

        //we don't have a standard title bar, paint one here:
        rc.bottom = caption_height;
        SetDCBrushColor(hdc, RGB(80, 80, 80));
        FillRect(hdc, &rc, (HBRUSH)GetStockObject(DC_BRUSH));

        //paint the background
        rc = ps.rcPaint;
        rc.top = caption_height;
        SetDCBrushColor(hdc, RGB(240, 240, 240));
        FillRect(hdc, &rc, (HBRUSH)GetStockObject(DC_BRUSH));

        //use FrameRgn to paint a border around the region
        HRGN hrgn = CreateRectRgn(0, 0, 0, 0);
        GetWindowRgn(hwnd, hrgn);
        SetDCBrushColor(hdc, RGB(128, 128, 128));
        FrameRgn(hdc, hrgn, (HBRUSH)GetStockObject(DC_BRUSH), 1, 1);
        DeleteObject(hrgn);

        EndPaint(hwnd, &ps);

        return 0;
    }

    case WM_NCHITTEST:
    {
        //we don't have a standard title-bar
        //respond to our custome title-bar manually:
        POINT pt;
        GetCursorPos(&pt);
        ScreenToClient(hwnd, &pt);
        if(pt.y < caption_height)
            return HTCAPTION;
        break;
    }

    case WM_COMMAND:
        if(HIWORD(wparam) == BN_CLICKED)
            if(LOWORD(wparam) == 100)
                SendMessage(hwnd, WM_CLOSE, 0, 0);
        break;

    case WM_DESTROY:
        PostQuitMessage(0);
        return 0;
    }

    return DefWindowProc(hwnd, msg, wparam, lparam);
}

int APIENTRY wWinMain(HINSTANCE hInstance, HINSTANCE, LPTSTR, int)
{
    WNDCLASSEXW wcex = { sizeof(wcex) };
    wcex.style = CS_DROPSHADOW;
    wcex.lpfnWndProc = WndProc;
    wcex.hInstance = hInstance;
    wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
    wcex.hbrBackground = NULL;
    wcex.lpszClassName = L"classname";
    RegisterClassExW(&wcex);

    CreateWindowW(wcex.lpszClassName, L"Test", WS_VISIBLE | WS_POPUP,
        200, 200, 600, 400, 0, 0, hInstance, 0);

    MSG msg;
    while(GetMessage(&msg, NULL, 0, 0))
    {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }

    return (int)msg.wParam;
}

【讨论】:

  • 嗨 Barmak:您的解决方案有效。我按原样测试了它,我看到了带有箭头的圆角框。我花了一段时间来确保它也适用于 CEF 窗口的父窗口。最后,这也有效。谢谢你。我给你赏金!
  • 欢迎您@trungdinhtrong。顺便说一句,您可以为这些类型的问题添加 [winapi] 标签以获得更多关注。更新:用FrameRgn在区域周围添加了一个细边框
猜你喜欢
  • 2013-02-21
  • 2010-10-21
  • 1970-01-01
  • 2015-08-15
  • 1970-01-01
  • 2011-05-31
  • 1970-01-01
  • 2012-11-14
  • 2012-08-04
相关资源
最近更新 更多