The right way to create transparent buttons in WINAPI

I tried Google, but could not find the final answer.

How to make a button with redefined WM_PAINT transparent. So that you can see the shape through it in all places except when something is drawn. Avoid flickering at the same time.

I saw examples with SetBkMode (HDC, TRANSPARENT) using NULL_BRUSH, examples with CompatibleDC and BitBlts, but I'm not quite sure if this is the right way, or how it behaves when WM_CLIPCHILDREN is set to the parent window. Most of the experiments that I had also had some kind of strange behavior. Cannot find good documentation on WM_ERASEBKGND / WM_CTLCOLOR / WM_PAINT / WS_EX_COMPOSITED / WS_CLIPCHILDREN / etc internal relations on MSDN in general.

Does anyone know where I could read about this topic with all gotchas related?

+3
source share
1 answer

mmm, I never found anything close to an authoritative document on this topic.

This is just my random memory dump, trying to make the controls β€œplay well” when they are animated, in a window that was either skin-like (a normal non-client area with a raster background), and layered (to get a window with custom edges without a client with effects shadow shadow) or with advanced Aero Glass effects (via DwmExtendFrameIntoClient).

  • SetBKMode (... TRANSPARENT) simply ensures that text rendering does not fill the text background with the current color bk.
  • WS_EX_COMPOSITED causes the windows to draw the parent and all child windows in the back buffer when the parent flag is invalid, and then draw the back buffer. This is flickering, but NT 6.0 introduced a desktop window manager that does not comply with WS_EX_COMPOSITED.
  • WS_CLIPCHILDREN forbids child windows and the parent window to draw the same area twice. But contra is indicated if you need to use group fields or tab controls.
  • WS_CLIPSIBLING can be useful if child windows overlap and cause flickering. again, this style is useless if you need to use group boxes or tab controls.
  • Another problem with WS_CLIPCHILDREN is that you cannot paint the background in the parent window of the proc window and rely on the NULL brush to open the skin. You can return the brush from WM_CTLCOLORxxx messages to force some standard controls to paint their background using a bitmap on your computer.
  • WS_EX_LAYERED is another style that causes windows to buffer the painting of your parent window. But a layered window artist does not draw child windows at all, so you need to manually draw child windows by sending WM_PRINTCLIENT messages. Not all controls support this message.
  • WPF turns out to be the lack of back buffering and alpha support, without creating real child windows for its buttons.

The final situation:

With a little work, you can easily get a skin behind most of the standard controls. WS_CLIPCHILDREN, and the background image on the parent will not simulate flickering. WM_CTLCOLORxxx knob to fill the background on the controls.

If you use Group Boxes or TabControls to place other controls, you absolutely must get the correct Z-order if you use WS_CLIPSIBLINGS.

By sending WM_PRINTCLIENT control messages and some subclasses, you can get standard DIBSection controls for drawing, which you can manually (or use the DWM working functions) edit the alpha channel and then draw in a multi-level window, or a window with an extended spray. This even flickers, but controls that do not support WM_PRINTCLIENT, or often update themselves outside of WM_PAINT, will not display correctly.

+6
source

Source: https://habr.com/ru/post/1346886/


All Articles