views:

208

answers:

1

Is there a preferred, fast method of scrolling within a user control in GDI+?

I've created a control that graphically renders a horizontally scrollable data plot.

Currently, my control operates by converting the position of a horizontal scroll bar into an offset into the data. The control then renders the data that exists between this starting point and an end point calculated based on the width of the control.

This method works, but is very slow. I do not wish to have to manually redraw the entire control surface upon each scroll event. Rather, I'd like to initialize the control by painting the entirety (or some portion) of the graphical data to an offscreen surface, and then virtually scroll the control surface by causing it to read the pre-rendered graphic data starting at the offset calculated by the position of the horizontal scroll bar.

Is BitBlt the only way to do this? Do I really have to manually copy graphics data from one surface to another? Can't I just take over the Paint event and cause it to read the data from the offscreen surface as it renders? This way, the copy and render action are one in the same.

Or, should I do something hokey like paint directly to a Panel control and then just literally scroll the panel itself from left to right?

CLARIFICATION: Essentially, I want to know the correct way to scroll pre-rendered data. How does one scroll graphical data within a control? Redrawing the pre-rendered graphic is NOT a correct option.

+3  A: 

Yes, I would try double-buffering. If you render to an off-screen bitmap, you can just scroll the bitmap around.

You can try rendering the entire graph to one big bitmap and let the scroll bars move it around. However, if your graph is extremely large, then you'll need to limit the size of the bitmap to the visible area, paint just what is visible to it, and handle scrolling virtually as you are now.

Testing on 32-bit Windows XP, I found the limitation is somewhere around 237.9 million pixels. That is certainly plenty for most controls, but it may not be enough for your application.

For the curious, here is the maximum Windows bitmap sizes we were able to create and use:

Width   Height    Area (pixels)
======   ======    ===========
32,767    7,261 237,921,187
25,000    9,517 237,925,000
23,792   10,000 237,920,000
20,000   11,896 237,920,000
15,861   15,000 237,915,000
15,000   15,861 237,915,000
11,896   20,000 237,920,000
10,000   23,792 237,920,000
 9,517   25,000 237,925,000
 7,261   32,767 237,921,187
Paul Williams
How does one "just scroll the bitmap around?" By maually copying areas of the off-screen bitmap to the on-screen bitmap? By passing in a reference and scroll offset into a certain GDI+ function?
James
In C#, there are several Graphics.DrawImage overrides that let you draw part of an image to a specified location. You could build a Bitmap, then draw the rectangle starting at the scroll location and the size of the control's visible area.
Paul Williams