Рисование с помощью Winforms - PullRequest
2 голосов
/ 25 января 2012

Я хочу получить немного знаний о WinForm Graphics, поэтому я переписываю свой небольшой 2D-редактор с XNA на WinForm Graphics-only.

Теперь я создал новый UserControl для набора плиток, но, как я видел, метод Paint вызывается только при инициализации элемента управления. Поскольку я хочу перекрасить свой элемент управления постоянно (или, по крайней мере, с помощью события MouseOver, чтобы сэкономить немного производительности), я слышал, что метод Invalidate() заставляет элемент управления перерисовывать себя, но это тоже way unperformant.

Можно ли как-нибудь позволить моему UserControl рисовать себя с помощью кода, без проблем с производительностью?

1 Ответ

3 голосов
/ 25 января 2012

Метод Paint не вызывается только при инициализации элемента управления.Он вызывается каждый раз, когда необходимо перекрасить элемент управления.Это, конечно, происходит, когда элемент управления создается впервые.Это также происходит, когда ваше приложение свернуто, а затем восстановлено, когда другое приложение перемещается поверх вашего приложения, которое затемняет его содержимое, а затем удаляется и так далее.Это также происходит, когда вы делаете недействительной клиентскую область элемента управления, используя метод Invalidate или его эквиваленты.Это было сделано на ранних стадиях разработки Windows как оптимизация производительности - нет необходимости перекрашивать что-то, что не изменилось!

Если вы хотите принудительно перерисовать элемент управления, вам следует вызвать Invalidate метод и укажите конкретную область клиентской области, которую нужно перекрасить.

Я понятия не имею, что вы имеете в виду по поводу "это способ слишком несоответствующий".Метод Invalidate не может быть медленным.Все, что он делает, это устанавливает флаг, который сообщает Windows, что ваш элемент управления должен перерисовываться всякий раз, когда он находится в режиме ожидания (без обработки каких-либо других сообщений).

Если вы хотите заставить Windows перекрасить ваш элемент управления немедленно (не дожидаясь его простоя; еще одна оптимизация производительности, встроенная в Windows с самого начала), вызовите метод Update , который вызывает немедленное перерисовывание всех недействительных областей.

Единственный способ, которым это может быть медленным, - это если ваш рисунок код медленный внутри метода обработчика событий Paint.И, очевидно, я не могу рассказать вам, как оптимизировать этот код, не увидев его первым.


Можно ли как-нибудь позволить моему UserControl рисовать себя через код, не имея таких проблем с производительностью?

Событие Paint - это именно то, как и где элементы управления должны рисовать себя.Вот почему он есть.

Если вы не рисуете в событии Paint, все, что вы рисуете, будет удалено при следующей перерисовке элемента управления (который, как уже упоминалось,ранее, может произойти в ответ на любое количество ожидаемых и неожиданных явлений).

Иногда, однако, имеет смысл рисовать временные объекты в клиентской области элемента управления (например, отображать прямоугольник перетаскивания в ответ на событие MouseDown).В этом случае вы можете в любое время получить экземпляр класса Graphics (который обычно передается в качестве аргумента вашему методу-обработчику Paint и для которого вы вызываете методы для рисования).Вы делаете это, вызывая CreateGraphics метод на вашем контроле, который возвращает объект Graphics.Затем вы рисуете в / на Graphics объект, полученный так же, как в методе обработки событий Paint.

Очевидно, что это не может / не будет быстрее, чем код рисования внутриPaint метод обработчика событий (если это действительно виновник), но он заставит экран обновляться немедленно , а не всякий раз, когда элемент управления простаивает и не обрабатывает никаких других сообщений.

Я еще раз повторю, что этот подход следует использовать только для немедленного предоставления и временную обратную связь, поскольку все, что вы рисуете, будет стерто в следующий раз, когда элемент управленияперерисован.Когда это происходит, возникает событие Paint, и запускается ваш код внутри этого обработчика метода, который ничего не знает о том, что вы нарисовали в другой разовый случай.Вот почему все должно происходить внутри метода обработчика событий Paint, и вы должны вызывать Invalidate (и, возможно, хотя и не всегда, Update), когда какое-то другое событие требует перерисовки.

...