4

I have a control on my app that can be resized by the user, it has some button anchored to the top-right side and also a scrollbar.
The problem is that when the control is resized, the controls anchored to the right also changes the position, and only after a few ms the controls goes into the right place. So it looks like the child controls "shakes" while the parent control is resized.

I already tried all kind of things, like using SuspendLayout and ResumeLayout on the parent control, setting double buffering and other styles on each control to true, setting WS_EX_COMPOSITED bit, but nothing seems to make this issue go away.
This issue is present on other apps too, and is pretty annoying.

So is there anyway to fix that on .net?
Maybe making it render everything to a backbuffer, and then when everything is finished render it to screen?

Joe White
  • 94,807
  • 60
  • 220
  • 330
sleepydog
  • 63
  • 4
  • As far as I can tell, it's not a delay in the rendering process. It has to do with the resize events being called a bit later. If you could post a sample code with the control hierarchy where this happens, it'd help me investigate further – Rakshith Ravi Jun 28 '15 at 17:09
  • How deep are the controls nested? – TaW Jun 28 '15 at 17:26
  • I would say 5 levels deep. there is a scroll bar control, then a list that uses this scrollbar, then another control that uses that list and have some buttons anchored on left/right, this control goes inside a control that is basically a window that goes inside a docking control, where those "windows" controls can be moved and resized. The code is a bit complex, but Ill try to make a simplified version and attach to the question. – sleepydog Jun 28 '15 at 18:36
  • 1
    I would create a new event that fires after resize is done, using a little timer magic stopping and starting a timer with an interval about 50ish ms on each resize event you can create this fake ResizeEnd kind of event. On the first resize event I would stop the drawing of the UI using the dllimport call (dont recall which it was) to stop drawing the contents of your window or control. Then when the resize is done, enable drawing again using the same dllimport call. The effect would be that it will only redraw itself after resize is done or every 50ms if you pause while resizing. – Wolf5 Jun 29 '15 at 03:54
  • ResizeEnd event: http://stackoverflow.com/questions/3083146/winforms-action-after-resize-event/30398501#30398501 – Wolf5 Jun 29 '15 at 03:57
  • Suspend drawing: http://stackoverflow.com/questions/487661/how-do-i-suspend-painting-for-a-control-and-its-children – Wolf5 Jun 29 '15 at 03:59
  • @Wolf5 Thanks for the tip, I implemented this method on my parent control, and I call SuspendDrawing before changing the control position/size, and then call ResumeDrawing after the layout has been setup. It worked good, "shaky" effect is gone, but the only problem now is that sometimes garbage is left on the form background (parts of the control at the old position) – sleepydog Jun 29 '15 at 17:52
  • I fixed the "garbage" problem by Refreshing the form too, now everything is OK! Thanks again. I guess you can put this as an awser so I can mark it as a solution for this question. – sleepydog Jun 29 '15 at 18:00
  • Thanks. I use the same tactics on a newly created nested control that had the similar issues. Now there is no more stuttering. – Wolf5 Jun 29 '15 at 21:37

2 Answers2

2

I would create a new event that fires after resize is done, using a little timer magic stopping and starting a timer with an interval about 50ish ms on each resize event you can create this fake ResizeEnd kind of event.

On the first resize event I would stop the drawing of the UI using the dllimport call (dont recall which it was) to stop drawing the contents of your window or control. Then when the resize is done, enable drawing again using the same dllimport call.

The effect would be that it will only redraw itself after resize is done or every 50ms if you pause while resizing.

ResizeEnd: WinForms - action after resize event

SuspendDrawing: How do I suspend painting for a control and its children?

Community
  • 1
  • 1
Wolf5
  • 16,600
  • 12
  • 59
  • 58
  • Just a side note, I used it on the form calling `SuspendDrawing();` on ResizeBegin event, `ResumeDrawing(); SuspendDrawing();` on Resize event and `ResumeDrawing();` on ResizeEnd and it worked great, so the timer is not really necessary. – sleepydog Jun 29 '15 at 22:00
  • The timer is only needed for creating a ResizeEnd event unless your control already had it :) – Wolf5 Jun 29 '15 at 22:13
0

override the below virtual method from namespace using System.Drawing;

  protected override Point ScrollToControl(Control activeControl)
    {
        return AutoScrollPosition;
    }

should solve the problem !

Jaydeep Shil
  • 1,894
  • 22
  • 21