在WINAPI中执行透明按钮的正确方法

时间:2011-01-04 15:57:52

标签: winapi

尝试谷歌,但无法找到明确的答案。

如何使覆盖WM_PAINT的按钮透明。这样你就可以在所有地方看到它的形式,除非画出一些东西。同时避免闪烁。

我看到了SetBkMode(HDC,TRANSPARENT)的示例,使用了NULL_BRUSH,带有CompatibleDC和BitBlts的示例,但我不太确定哪个是正确的方法,以及它在WM_CLIPCHILDREN设置时的行为方式父窗口。我做的大多数实验也有一些奇怪的行为。在MSDN上找不到关于WM_ERASEBKGND / WM_CTLCOLOR / WM_PAINT / WS_EX_COMPOSITED / WS_CLIPCHILDREN / etc内部关系的好文档。

有没有人知道我在哪里可以阅读关于这个主题的所有问题?

1 个答案:

答案 0 :(得分:6)

嗯,我从来没有找到任何关于这个主题的权威文件。

这只是作为我的相当随机的内存转储尝试让控件“玩得很好”,当动画时,在一个被剥皮的窗口(具有位图背景的普通非客户区域),分层(以获得一个窗口带有投影效果的自定义非客户端边缘)或扩展的Aero Glass(通过DwmExtendFrameIntoClient)效果。

  • SetBKMode(... TRANSPARENT)只是确保文本渲染不会填充当前bk颜色的文本背景。
  • WS_EX_COMPOSITED导致窗口在父项失效时将父窗口和所有子窗口绘制到后台缓冲区,然后绘制后台缓冲区。这是无闪烁的,但是NT 6.0引入了不支持WS_EX_COMPOSITED的桌面窗口管理器。
  • WS_CLIPCHILDREN可防止子窗口和父窗口两次绘制相同区域。但如果您需要使用组框或标签控件,则表示反对。
  • 如果子窗口重叠并导致闪烁,则WS_CLIPSIBLING可能很有用。如果你需要使用组框或标签控件,这种风格也是无用的。
  • WS_CLIPCHILDREN的另一个问题是你无法在父widnows窗口proc中绘制背景并依赖于NULL画笔来显示皮肤。您可以从WM_CTLCOLORxxx消息中返回一个画笔,强制使用一些标准控件,用皮肤位图绘制背景。
  • WS_EX_LAYERED是另一种使窗口缓冲父窗口绘制的样式。但是分层的窗口画家根本不绘制子窗口,因此您需要通过发送WM_PRINTCLIENT消息手动绘制子窗口。并非所有控件都支持此消息。
  • WPF通过不为其按钮创建实际的子窗口来解决缺少背缓冲绘画和alpha支持的问题。

最后的情况:

通过一些工作,您可以轻松获得大多数标准控件背后的皮肤。 WS_CLIPCHILDREN并且父级上没有背景绘制将最小化闪烁。处理WM_CTLCOLORxxx以填充控件的背景。

如果您正在使用Group Boxes或TabControls来构建其他控件,那么在使用WS_CLIPSIBLINGS时,绝对必须使Z顺序正确。

通过发送控件WM_PRINTCLIENT消息和一些子类,您可以获得绘制到DIBSection上的标准控件,然后您可以手动(或使用DWM工作器函数)修复Alpha通道,然后绘制到分层窗口,或带有扩展航空玻璃的窗户。这甚至是无闪烁的,但是不支持WM_PRINTCLIENT或经常在WM_PAINT之外自行更新的控件将无法正确显示。