Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I get rid of jerkiness in WinForms scrolling animation?

I'm writing a simple control in C# that works like a picture box, except the image is constantly scrolling upwards (and re-appearing from the bottom). The animation effect is driven by a timer (System.Threading.Timer) which copies from the cached image (in two parts) to a hidden buffer, which is then drawn to the control's surface in its Paint event.

The problem is that this scrolling animation effect is slightly jerky when run at a high frame rate of 20+ frames per second (at lower frame rates the effect is too small to be perceived). I suspect that this jerkiness is because the animation is not synchronized in any way with my monitor's refresh rate, which means that each frame stays on the screen for a variable length of time instead of for exactly 25 milliseconds.

Is there any way I can get this animation to scroll smoothly?

You can download a sample application here (run it and click "start"), and the source code is here. It doesn't look horribly jerky, but if you look at it closely you can see the hiccups.

WARNING: this animation produces a pretty weird optical illusion effect which might make you a little sick. If you watch it for awhile and then turn it off, it will look as if your screen is stretching itself vertically.

UPDATE: as an experiment, I tried creating an AVI file with my scrolling bitmaps. The result was less jerky than my WinForms animation, but still unacceptable (and it still made me sick to my stomach to watch it for too long). I think I'm running into a fundamental problem of not being synced with the refresh rate, so I may have to stick to making people sick with my looks and personality.

like image 407
MusiGenesis Avatar asked Jun 04 '09 12:06

MusiGenesis


1 Answers

You would need to wait for a VSYNC before you draw the buffered image.

There is a CodeProject article that suggests using a multimedia timer and DirectX' method IDirectDraw::GetScanLine().

I'm quite sure you can use that method via Managed DirectX from C#.

EDIT:

After some more research and googling I come to the conclusion that drawing via GDI doesn't happen in realtime and even if you're drawing in the exact right moment it might actually happen too late and you will have tearing.

So, with GDI this seems not to be possible.

like image 102
VVS Avatar answered Nov 03 '22 00:11

VVS