I have 3 data graphs that are painted via the their paint events. When I have data that I need to insert into the graph I call the controls invalidate() command.
The first control's paint event actually creates a bitmap buffer for the other 2 graphs to avoid repeating a long loop.
So the invalidate commands are in a specific order (1,2,3). This works well, however when the graphed data reaches t开发者_JAVA百科he end of the graph window (PictureBox) where the data would normally start scrolling, the paint events begin firing in the wrong order (2,3,1).
has anyone came across this before? why might this be happening?
Change your code so that before calling Invalidate
on any of the three controls, you create the one shared bitmap buffer (conceivably as a static member of your control class), and then call Invalidate
on each of the controls. Within the control's Paint
event you can then use the static bitmap buffer, and it won't matter in which order the Paint
events fire.
When you call Invalidate
on a control, you're basically telling the OS to send a WM_PAINT message to that control. Because it's a Windows message, it's guaranteed to be delivered whenever Windows gets around to doing it. In your case, they're usually delivered in the order received, but sometimes they just won't be.
One other thing to consider with your code: when you place relatively complex drawing code inside your control's Paint
event handler (or inside a method called directly from the Paint
event handler), this code will execute whenever the control is invalidated for any reason, meaning that the code will run when you call Invalidate
, but it will also run whenever another window is dragged over the control.
For complex, time-consuming graphics, it's always best to perform the complex rendering on a hidden buffer (a Bitmap
or an invisible PictureBox
or whatever), and then in the control's Paint
event do a simple copy from the hidden buffer to the visible window (using Graphics.DrawImage
or BitBlt
or whatever).
This approach also allows you to avoid flicker, if you add a second buffer in between the buffer you draw on and the visible window (hence "double buffering"). After you complete drawing on the main buffer, you copy it onto the second buffer. In the control's Paint
event, you copy from the second buffer onto the visible window.
Because calling Invalidate()
on a control essentially asks the operating system to schedule the control for redraw, there is no guarantee that this is done in a specific order.
Since you attempt to call Invalidate()
in a specific order, I assume that you have a single method which does this. You could add code just before these calls to draw the bitmap buffer which is then used by the invalidated controls. I don't know if this may ever occur, but this also gives you the freedom to not invalidate a control when it's data doesn't change. Furthermore, controls can be invalidated at any time. For example, moving a form across Control 1 causes it to invalidate, and in your current setup, recalculate the buffer bitmap while that is not required. Therefore, you should separate this functionality.
精彩评论