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

Posted

技术标签:

【中文标题】在WINAPI中做透明按钮的正确方法【英文标题】:Correct way to do transparent buttons in WINAPI 【发布时间】:2011-01-04 15:57:52 【问题描述】:

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

如何使覆盖 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】:

嗯,我从来没有找到任何与此主题相关的权威文档。

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

SetBKMode(... TRANSPARENT) 只是确保文本渲染不会用当前的 bk 颜色填充文本的背景。 WS_EX_COMPOSITED 导致窗口在父窗口无效时将父窗口和所有子窗口绘制到后台缓冲区,然后绘制后台缓冲区。这是无闪烁的,但 NT 6.0 引入了不支持 WS_EX_COMPOSITED 的桌面窗口管理器。 WS_CLIPCHILDREN 防止子窗口和父窗口在同一区域绘制两次。但如果您需要使用分组框或选项卡控件,则相反。 如果子窗口重叠并导致闪烁,WS_CLIPSIBLINGs 可能很有用。如果您需要使用分组框或选项卡控件,这种样式也毫无用处。 WS_CLIPCHILDREN 的另一个问题是您不能在父窗口进程中绘制背景,而只能依靠 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 之外更新自身的控件将无法正确显示。

【讨论】:

WS_CLIPSIBLINGS 在您描述的情况下是可以的,只要您的 Z 顺序正确。很容易做到。 那么如果你设置了 WS_CLIPCHILDREN,你如何让按钮的背景填充表单颜色呢? WS_CLIPCHILDREN 将使子控件占用的部分未绘制,因此我被卡住了。我需要用我不知道的颜色填充SolidRect... 如果您使用的是 WS_CLIPCHILDREN,那么您可以通过让其父窗口响应大多数标准控件支持的 WM_CTLCOLORxxx 消息来提供控件的背景。 WS_EX_COMPOSITED 文档强烈暗示,如果没有 WS_EX_COMPOSITED,发送到重叠子窗口的 WM_PAINT 消息的顺序未定义为自下而上。由于必须通过按顺序处理父窗口上的子控件来确定性地定义绘制 dc 的剪辑区域,因此如果子控件重叠,则必须确实需要 WS_CLIPSIBLINS 才能获得一致的绘制。

以上是关于在WINAPI中做透明按钮的正确方法的主要内容,如果未能解决你的问题,请参考以下文章

Winapi检测按钮悬停

winapi - 如何正确使用 LayeredWindows

WinAPI 的 Groupbox 字体问题

winapi中的多行按钮

如何在标准按钮 WinApi 上绘图

WinAPI 在按钮单击时没有任何反应