具有透明客户端区域的窗口

window with transparent client area

本文关键字:窗口 区域 客户端 透明      更新时间:2023-10-16

我像这样注册窗口类:

WNDCLASSEX wctt;
wctt.cbSize        = sizeof(WNDCLASSEX);
wctt.style         = CS_DBLCLKS;
wctt.lpfnWndProc   = WndProcTooltip;
wctt.cbClsExtra    = 0;
wctt.cbWndExtra    = 0;
wctt.hInstance     = m_hAppInstance;
wctt.hIcon         = NULL;
wctt.hCursor       = LoadCursor(NULL, IDC_SIZE);
wctt.hbrBackground = NULL;
wctt.lpszMenuName  = NULL;
wctt.lpszClassName = _T("myWindow");
wctt.hIconSm       = NULL;
RegisterClassEx(&wctt)

你可以看到我使用wctt.hbrBackground = NULL;所以它没有背景。

窗口是这样创建的:

::CreateWindowEx(WS_EX_TOPMOST | WS_EX_TOOLWINDOW,
_T("myWindow"),
NULL,
WS_VISIBLE | WS_POPUP,
50,
50,
150,
100,
NULL,
NULL,
m_hAppInstance,
NULL);

在paint部分,我在窗口上画了一个图标:

PAINTSTRUCT     ps;
HDC             hdc;
BITMAP          bitmap;
ICONINFO        iconinfo;
hdc = ::BeginPaint(hWnd, &ps);
::SetBkMode(hdc,TRANSPARENT);
::GetIconInfo(localIcon, &iconinfo);
::GetObject(iconinfo.hbmColor, sizeof(bitmap), &bitmap);
::DeleteObject(iconinfo.hbmColor);
::DeleteObject(iconinfo.hbmMask);
::DrawIconEx(hdc, 0,0, localIcon, bitmap.bmWidth, bitmap.bmHeight, 0, NULL, DI_NORMAL);

图标的大小小于窗口的大小,我在背景上得到当前视图的窗口下面的弹出。

但是现在,当我移动窗口(或最小化窗口下方的弹出)的背景没有改变。

我试图做一个计时器,每次做流动:

RECT rcClient;
GetClientRect(hWnd, &rcClient);
InvalidateRect(hWnd,&rcClient,TRUE);

这将使打印函数再次运行,但图标的背景不会改变。

我应该在WM_ERASEBKGND中做些什么吗?
有人知道怎么让它工作吗?

谢谢,家伙

仅仅让背景保持不上色是不够的;你还需要让下面的窗口在必要时重新粉刷自己。

如果窗口是同一层次结构的一部分,由同一线程创建,它足以给你的窗口WS_EX_TRANSPARENT扩展样式。这将导致下面的窗口首先绘制自己,因此背景始终是最新的。

否则你需要使用SetWindowRgn,这样你的窗口实际上不存在于你想画的边界之外。

查看分层窗口。此功能允许创建不同形状的半透明窗口。

在你的窗口类中添加WS_EX_LAYERED扩展属性

你可以用下面两个函数来控制窗口的透明度:

  1. SetLayeredWindowAttributes:

    1. bAlpha控制整个窗口的不透明度,如果你在dwFlags中传递LWA_ALPHA

      当alpha为0时,窗口是完全透明的。当alpha值为255时,该窗口是不透明的。

    2. crKey设置透明的颜色。

      窗口绘制的所有像素都是透明的。

  2. UpdateLayeredWindow给你精确的控制窗口透明度,你可以给窗口的不同部分不同的透明度水平。

如果您试图创建一个非矩形窗口,这是不够的。设置"no background"仅仅意味着背景不会被绘制,你会看到内存中那个位置发生了什么。

要创建一个非矩形窗口,请看SetWindowRgn函数