Hello, I am creating a custom control using C# GDI+.

Quick explanation...the control will be say 500 pixels on screen but will contain perhaps 500000 pixels of information. So although i'm only showing 500px at a time i need to obviously scroll in the horizontal plane (left & right). The tricky part is that each 500px chunk of bitmap takes a while (between 100ms - 1000ms) to render.

So my plan is to maintain a 1500px bitmap in memory. i.e. the 500px visible part and 500px either side of the visible area and draw the off-screen parts asynchronously as the user scrolls.

I would like some feedback, advice, criticism or examples of code to help me achieve this. It seems fairly straight forward but after a few initial test attempts its proving more difficult than one would imagine.



The effectiveness of this approach depends on, amongst other things, the amount of moving around the user will do. If the user is making small movement, then stopping to consider the new information, this could work. However, if the user is whizzing back and forth, you'll still have an issue.

Does your application lend itself to gradually improving the quality of the image - i.e. providing a quick usable image and then improving it as the user stops to consider it?

Unfortunately the control is displaying medical trend data so it does not really lend itself to gradually improving the quality. Also, it is possible and likely that users may scroll from left to right fairly rapidly as well as slowing paging.
+1  A: 

I had a similar problem a few years back. As dommer mentions, if you're processing chunks of the image before displaying them you're best off showing something and improving it later. If you're having problems blitting the original image, you've got something wrong with your method. GDI+ is very particular about pixel depth (you want 32bpp with alpha).

In our case, we processed in 500px tiles and padded out a tile around the visible view Ff the user scrolled outside the area we'd processed we blitted bits of the original image with a dark semi-opaque rectangle super-imposed on them. These chunks were queued for processing. As we processed chunks of the image (centre-out) they semi-opaque rectangles would disappear.

It worked reasonably well, was very responsive and very fast. It's very fast to blit the original bitmap onto the screen, and in our case the processing was usually very close behind. The effect of the tiles getting lighter was actually quite pretty.

Steve Mc
Don't suppose you have any chopped down code you code let me have?

Draw only the visible area. Build a method

Bitmap DrawGraph(leftMargin, rightMargin) {...}

and then in OnPaint() do

Bitmap bmp = new Bitmap(e.ClipRectangle.Width, e.ClipRectangle.Height);
bmp = DrawGraph(e.ClipRectangle.Left, e.ClipRectangle.Right);

e.Graphics.DrawImageUnscaled(bmp, e.ClipRectangle.Location);