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.