On Windows, I'm trying to use CEF (Chromium Embedded Framework) to create a window application with parent window to be transparent and its child window to be opaque (I want to have a rounded corner and an arrow pointing to the status bar in the child window). Something similar to:
I tried to use SetLayeredWindowAttributes
to make the parent window transparent but it also makes the child window transparent. Is there a way to make this happen on Windows?
SetLayeredWindowAttributes
needs a color for transparency. Make sure the transparency color is not used by the child window. You can pick a random color, for example RGB(255, 0, 254)
and assume the child window is not using it.
If you have no control over the child window, and you can't be sure what colors it might use, then SetWindowRgn
is another option to create non-rectangular windows.
The example below shows how to set the region such that the corners are round with a triangle on top.
You can use GDI+ to gain more flexibility for drawing the region, and for anti-aliasing effect so that the borders look more smooth.
#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;
}