Drawing with Winforms

后端 未结 1 426
广开言路
广开言路 2021-01-07 05:42

I want to get myself a bit of WinForm Graphics knowledge, so I\'m rewriting my small 2D editor from XNA to WinForm Graphics-only.

Now, I made myself a new UserContro

相关标签:
1条回答
  • 2021-01-07 06:02

    The Paint method is not only called at the initialization of the control. It is called every time that the control needs to be repainted. This, of course, happens when the control is first created. It also happens when your application is minimized then restored, when another window is moved over your app that obscures its contents and then removed, and so on. It also happens when you invalidate the control's client area using the Invalidate method or equivalents. This was done early in the development of Windows as a performance optimization—there's no need to repaint something that hasn't changed!

    If you want to force the control to be repainted, you should call the Invalidate method and specify a particular region of the client area to be repainted.

    I have no idea what you mean about "that is way too unperformant". It's impossible for the Invalidate method to be slow. All it does is set a flag that tells Windows your control needs to be redrawn whenever it is idle (not processing any other messages).

    If you want to force Windows to repaint your control immediately (without waiting for it to be idle; another performance optimization built into Windows from the early days), call the Update method, which forces an immediate redraw of all invalidated regions.

    The only way it could be slow is if your drawing code is slow inside of the Paint event handler method. And obviously I can't tell you how to optimize that code without seeing it first.


    Is there anyway to let my UserControl paint itself via code, without having these performance-issues?

    The Paint event is precisely how and where controls should paint themselves. That's why it's there.

    If you don't paint in the Paint event, anything that you paint will be erased the next time that the control is repainted (which, as mentioned earlier, can happen in response to any number of expected and unexpected occurrences).

    Sometimes, though, it makes sense to paint temporary objects into the control's client area (such as showing a drag rectangle in response to a MouseDown event). In that case, you can obtain an instance of the Graphics class (which is typically passed as an argument to your Paint event handler method, and on which you call methods to do your drawing) at any time. You do this by calling the CreateGraphics method on your control, which returns a Graphics object. You then draw into/onto the Graphics object obtained just as you would inside of the Paint event handler method.

    Obviously this can't/won't be any faster than the drawing code inside of the Paint event handler method (if that is in fact the culprit), but it will cause the screen to be updated immediately rather than whenever the control is idle and not processing any other messages.

    I'll reiterate again that this approach should be used only to provide immediately and temporary feedback, as everything you draw will be erased the next time that the control is redrawn. When that happens, the Paint event is raised, and your code inside that method handler runs, which doesn't know anything about what you drew on some other one-off occasion. That's why everything should happen inside of the Paint event handler method, and you should call Invalidate (and perhaps, though not usually, Update) when some other event makes it necessary to repaint.

    0 讨论(0)
提交回复
热议问题