使用CEF使父窗口透明而子窗口不透明

时间:2018-11-21 20:37:02

标签: windows window adobe chromium-embedded

在Windows上,我尝试使用CEF(铬嵌入式框架)创建一个窗口应用程序,其父窗口是透明的,其子窗口是不透明的(我想有一个圆角和一个箭头,指向子窗口中的状态栏)。类似于:

enter image description here

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

1 个答案:

答案 0 :(得分:2)

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;
}