【问题标题】:window with transparent client area具有透明客户区的窗口
【发布时间】:2012-12-26 17:24:47
【问题描述】:

我这样注册窗口类:

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

在绘画部分,我在窗口上绘制图标:

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做些什么吗?
有没有人知道如何让它工作?

谢谢, 伙计

【问题讨论】:

  • 请注意,如果您调用InvalidateRect 并使用NULL 作为rect,它会使整个客户端rect 无效
  • 是的,我知道,我希望所有的客户区都失效……这不就是这样做的吗?
  • 这个:InvalidateRect(hWnd, NULL, TRUE) 相当于这个:RECT rcClient; GetClientRect(hWnd, &rcClient); InvalidateRect(hWnd,&rcClient,TRUE);。没有一个是错的,两者都做同样的事情......

标签: c++ winapi background window


【解决方案1】:

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

如果窗口是同一层次结构的一部分,由同一线程创建,则为您的窗口提供WS_EX_TRANSPARENT 扩展样式就足够了。这会导致下面的窗口首先自行绘制,因此背景始终是最新的。

否则,您需要使用SetWindowRgn,以便您的窗口实际上不存在于您要绘制的边框之外。

【讨论】:

  • 它看起来不错...我会在它上面做更多的工作。谢谢你:)
【解决方案2】:

看看Layered Window。此功能允许创建不同形状的半透明窗口。

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

您可以使用以下两个功能控制窗口的透明度:

  1. SetLayeredWindowAttributes:

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

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

    2. crKey 设置透明的颜色。

      窗口以这种颜色绘制的所有像素都是透明的。

  2. UpdateLayeredWindow 让您可以精确控制窗口的透明度,您可以为窗口的不同部分赋予不同的透明度。

【讨论】:

  • 我总是忘记分层窗口。而且我从来没有意识到它们是在 Windows 2000 中一直引入的。
  • 当我使用带有crKey的WS_EX_LAYERED窗口时,图像的边界和透明区域不清晰,并且我们有一些透明颜色的残留物。
  • @guymininberg 你能发一个屏幕截图吗?当您使用crKey 时,只有以这种精确颜色绘制的区域才会被渲染为透明。如果你的图标有半透明区域,并且你想保留它们,那么你必须使用UpdateLayeredWindow
【解决方案3】:

如果您尝试创建一个非矩形窗口,这还不够。设置“无背景”只是意味着不会绘制背景,您会看到该位置内存中发生的任何事情。

要创建非矩形窗口,请查看SetWindowRgn 函数。

【讨论】:

  • 什么时候调用这个函数?
  • 创建窗口后只需一次。
  • 我应该制作一个与我加载的图像兼容的 Rgn 吗?
猜你喜欢
  • 2011-06-16
  • 2011-01-16
  • 2012-05-03
  • 2012-05-04
  • 2016-03-03
  • 2012-07-06
  • 1970-01-01
  • 1970-01-01
  • 2013-02-21
相关资源
最近更新 更多