Share via


Can someone explain WS_EX_COMPOSITED

Question

Tuesday, July 20, 2010 4:13 PM | 1 vote

I have created a skinned dialog by setting a background brush on the dialog. I return this brush in response to WM_CTLCOLORDLG, WM_CTLCOLORSTATIC and WM_CTLCOLORBTN.

The first message ensures that the dialg uses my brush for painting its background, the next two ensure that buttons, radio boxes, check boxes, static controls etc all have the brush as their background.

Now, dialogs are not typically created with WS_CLIPCHILDREN so there is a lot of flicker caused by the dialogs brush painting first, then the controls.

Rather than add the WS_CLIPxxx styles, I added WS_EX_COMPOSITED style, which I thought should solve the problem - As it composits ALL painting for the window, background brush, parent, and child painting.

I still sometimes get some flicker however, that makes we wonder just exactly where and how WX_EX_COMPOSITED is implemented.

As I understood window's painting logic, basically, GetMessage would notice that there are no actual messages, so it would examine each of the windows owned by the current thread to see if any of them had a non null invalid region.

If/when it finds a non null invalid region it then SENDS (not Posts) a synchronous patch of WM_PAINT messages to the parent, and then all the child windows that intersect the invalid region.

I would have thought that WS_EX_COMPOSITED would mean that this entire process would be bracketed and rendered onto a composited surface, but the flicker I'm getting implies not.

How does painting actually work in modern versions of Windows?

 

All replies (6)

Wednesday, August 11, 2010 4:40 PM ✅Answered | 1 vote

Hi:

The description of painting logic you give is essentially correct with the addition that WS_EX_LAYERED windows and all windows when DWM is enabled are rendered into an offscreen buffer and that buffer is then rendered to the screen.  WM_PAINT messages can be skipped to update the onscreen buffer so long as the offscreen buffer is valid.

 

WS_EX_COMPOSITED works by forcing child windows to draw back to front and by double buffering them; however, the double buffering used by WS_EX_COMPOSITED for the child windows conflicts with the double buffering used by WS_EX_LAYERED windows and DWM so it does not remove the flicker in those contexts.

 

Unfortunately, this means that your composited test application flickers with DWM turned on but not with DWM turned off.

 

Narrowing the area invalidated to the minimum necessary and using WS_CLIPCHILDREN and WS_CLIPSIBLINGS appropriately can help reduce the amount of flicker.  Since the dialog has intentional overlap with the groupbox and groupboxes don't by default erase their background, the app would need to subclass the groupbox to erase its background.

 

All applications (e.g. Office) and frameworks (e.g. WPF) which I am aware of which perform complex flicker-free animations use windowless controls rather than child windows so they can control their own buffering. 

 

As far as the WM_CTLCOLOR* messages are concerned, themed controls generally bypass the simple pens and brushes set by these messages in order to draw the more complicated visual styles with DrawThemeBackground, DrawThemeText, etc.

Wendell


Wednesday, July 21, 2010 3:28 AM

Hi Farproc,

 

I think this question is related to a previous question you have asked here.

http://social.msdn.microsoft.com/Forums/en-US/vcgeneral/thread/3aa76a5a-6f04-4f85-b2ce-f1c6d8d341b8/

 

At first I guess it is an MFC project. But now I think I guess wrong. I don’t know what your skinned dialog project is. MFC handle message doesn’t like the way you have shown in that piece of code. If it is a Win32 project, please post complete code or share a simple project. You can upload it to the skydrive.live.com. I need it to reproduce the issue locally.

 

Sincerely,

Kira Qian

MSDN Subscriber Support in Forum

If you have any feedback on our support, please contact msdnmg@microsoft.comPlease remember to mark the replies as answers if they help and unmark them if they provide no help.
Welcome to the All-In-One Code Framework!


Wednesday, July 21, 2010 8:03 AM

The questions are related, but different. The other question is about controlling the color of standard windows controls with common controls 6. This question is a general question of how to use the new windows APIs to draw a window, with child controls, flicker free. On the .NET side of things there is a lot of support for creating very compelling UIs by animating controls in various ways instead of simply showing/hiding them or drawing them a different size. I'm trying to get these animation effects into a ... not managed environment using standard windows controls, and, as soon as I understand window's painting logic a bit more: try and integrate some aero glass effects.

There is however a dearth of documentation explaining the actual painting model used by DWM - when its apporpriate to use WS_EX_LAYERED, WS_EX_TRANSPARENT, WS_EX_COMPOSITED, BeginPaint / BeginBufferedPaint and so on, and how these all interact with child windows.

Ive seen blog posts from MSs own developers explaining the grief they went through to get a flicker free volume control, so the native windows painting model is really simply not well understood by anyone at the moment.

If I understand how skydrive works, this should be a link to a VS2008 version of the project.

http://cid-a342d2faed3d238e.office.live.com/self.aspx/.Documents/SkinDialog.zip

In its default configuration it will run with common controls 6 enabled. so run it on a PC with Aero Glass to see the dialog first. It is invalidating itself on a timer to simulate animations forcing redraws on the window.

There are two things happening on the dialog that confuse me: The controls are flickering, AND the text next to the radio box and check box is black.

Now, assuming you are running the app on XP, or Windows Vista or 7 with Aero enabled, stop the app, edit line 4 of SkinDialogApp.cpp to comment out the #include, and clean and rebuild and re-run.

 

This won't fix the flickering: But the dialog should now be using the classic square grey buttons (the kind that are drawn with DrawEdge) - notice that the radio box and check box now have the color I set in the WM_CTLCOLOR* handler: white.

 


Thursday, July 22, 2010 2:34 AM

Thank you for sharing me the project. I can run it on my side and did see serious flicker on the dialog. Here are 2 points.

 

1. The uElapse value for the SetTimer function is very low. That causes the InvalidateRect being called too frequently.

 

2. I didn’t see what you were going to animate in your project. I guessed you want to animate the background image. Did I guess right? If so, I change your code to let the dialog change background image per second. You can download the modified project here.

http://cid-ee362b84156dcc82.office.live.com/self.aspx/MSDN/Solution/%5E52010.7.22%5E6SkinDialog.zip

 

If I misunderstood you, please feel free to tell me.

 

Sincerely,

Kira Qian

MSDN Subscriber Support in Forum

If you have any feedback on our support, please contact msdnmg@microsoft.comPlease remember to mark the replies as answers if they help and unmark them if they provide no help.
Welcome to the All-In-One Code Framework!


Thursday, July 22, 2010 5:33 AM

What the project animates was irrelevent. The invalidation was there to simulate the effects of animation causing frequent repaints so I can understand how to control the flicker. thats also why the timer rate is unnaturally high. If I can eliminate flicker with a high repaint rate then when I put the actual low rate animations I can be sure that all the flicker s gone.

The other question I still have with that project is, why is the text color on the radio, and checkbox, not white? If you comment out the "#include "Common/UseComCtl6.h" from the main cpp file and rebuild you should see all the text colored correctly - but with ugly control styling.

How do I get the "pretty" Aero controls AND still control the color of the text elements on the dialog?


Thursday, August 12, 2010 10:43 AM

Hi:

The description of painting logic you give is essentially correct with the addition that WS_EX_LAYERED windows and all windows when DWM is enabled are rendered into an offscreen buffer and that buffer is then rendered to the screen.  WM_PAINT messages can be skipped to update the onscreen buffer so long as the offscreen buffer is valid.

 

WS_EX_COMPOSITED works by forcing child windows to draw back to front and by double buffering them; however, the double buffering used by WS_EX_COMPOSITED for the child windows conflicts with the double buffering used by WS_EX_LAYERED windows and DWM so it does not remove the flicker in those contexts.

 

Unfortunately, this means that your composited test application flickers with DWM turned on but not with DWM turned off.

 

Narrowing the area invalidated to the minimum necessary and using WS_CLIPCHILDREN and WS_CLIPSIBLINGS appropriately can help reduce the amount of flicker.  Since the dialog has intentional overlap with the groupbox and groupboxes don't by default erase their background, the app would need to subclass the groupbox to erase its background.

 

All applications (e.g. Office) and frameworks (e.g. WPF) which I am aware of which perform complex flicker-free animations use windowless controls rather than child windows so they can control their own buffering. 

 

As far as the WM_CTLCOLOR* messages are concerned, themed controls generally bypass the simple pens and brushes set by these messages in order to draw the more complicated visual styles with DrawThemeBackground, DrawThemeText, etc.

Wendell

To summarize: controls implemented as non managed child window's are deprecated. Support to draw them flicker free has been effectively removed. there is no intention to make them alpha aware so they can't be used on layered windows or windows with extended aero glass, and the uxtheme ones can't be used on a skinned app as they ignore the messages that allowed us to provide the brush to be used to paint the area outside the control.