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

Cod*_*der 3 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内部关系的好文档.

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

Chr*_*cke 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是另一种使Windows缓冲父窗口绘制的样式.但是分层的窗口画家根本不绘制子窗口,因此您需要通过发送WM_PRINTCLIENT消息手动绘制子窗口.并非所有控件都支持此消息.
  • WPF通过不为其按钮创建实际的子窗口来解决缺少背缓冲绘画和alpha支持的问题.

最后的情况:

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

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

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