Saturday, August 21, 2010

C++ .Net Flickering Control?

Hi, i have a control in C++ using .Net, i am drawing a filled Elipse in the OnPaint function however when ever i resize the control it flickers whilst the resize if happeneing.





I have tried setting double buffers however this makes things worse. I have tried setting several of the different control syles but they make no difference. Any suggestions?





Here is my code:





void HyperbolicDiscView::OnResize( EventArgs ^ e )


{


Invalidate();


}





//////////////////////////////////////鈥?br>




void HyperbolicDiscView::OnPaint( PaintEventArgs ^ e )


{


Control::OnPaint( e );


Graphics ^ pGraph = Graphics::FromHwnd( this-%26gt;Handle );


pGraph-%26gt;SmoothingMode::set( System::Drawing::Drawing2D::SmoothingMod鈥?);


pGraph-%26gt;DrawEllipse( gcnew Pen( Drawing::Color::Black, 2 ), *m_pDiscArea );


pGraph-%26gt;FillEllipse( Drawing::Brushes::Red, *m_pDiscArea );


}C++ .Net Flickering Control?
Sync display dosen't really apply to Windows, imagine you had 20 controls in a dialog, you synced before painting each control and your monitor was running at 60 hz. It would take a third of a second to redraw your dialog! I think there's a better answer.





The problem maybe that Windows is clearing the background of the window, the background of your control and then telling you to paint it. The paint message could come quite a while after clearing the background, thats where the flicker comes in.





Firstly, make sure the windows with the control on has the WS_CLIP_SIBLINGS style. This tells windows not to paint behind a control window.





Next make sure your control is not responding to WM_ERASEBKGND. That means its window class need to have 0 for the handle to its background brush.





Finally, fill the background when you paint the control. If the Ellipse function is too slow so that you still see a flicker, use buffering (as you suggested) by rendering to a memory DC and blitting to the screen.





When you call invalidate, try to make sure you it will redraw without erasing the background. I use RedrawWindow rather than InvalidateRect as it offers more control (I program the API directly).





If you are resizing lots of controls its better to use DeferWindowPos. This makes a list of controls that will be resized then processes them quickly. This reduces delays between resize and paint when moving many windows.





Paint message are low priority, they are moved down the message queue by sizing, timers, mouse, keyboards, so you have to apply some control to them. Mail me if you're still stuck.C++ .Net Flickering Control?
You need to sync the display by setting a small delay

No comments:

Post a Comment