Лучшая практика для пользовательского контроля рисования в Winforms? - PullRequest
7 голосов
/ 12 ноября 2009

Обычно, когда я переопределяю метод OnPaint, я создаю внутри него перья, кисти и т. Д., А затем располагаю их.

Я также где-то читал, что вместо того, чтобы воссоздавать эти ручки и кисти и т. Д., Создать их один раз как статические элементы, а затем утилизировать их один раз, когда форма закрыта, и т. Д.

Это лучшая практика?

Есть ли лучший способ для этого?

Я могу предположить, что поскольку OnPaint вызывается 1000 раз (?), Это создаст много работы для GC по сравнению с созданием их только один раз.

Ответы [ 5 ]

8 голосов
/ 12 ноября 2009

Если кисти и ручки не меняются, то, безусловно, лучше создать их один раз и использовать их повторно. Обратите внимание, однако, что если ваш элемент управления может использоваться в нескольких потоках (что очень маловероятно), вы должны либо сделать их ThreadStatic (и инициализировать при первом использовании для каждого потока), либо сделать их экземплярами-членами (и разместить их в вашем Dispose переопределить); в противном случае вы получите невоспроизводимые ошибки GDI +, поскольку объекты GDI + нельзя использовать одновременно в нескольких потоках. То же самое относится и к изображениям.

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

Заметьте, кстати, что если вы используете нормальные цвета, вы можете использовать статические Brushes и Pens классы, которые содержат статические кисти и ручки для всех встроенных цветов .Net и SystemBrushes и SystemPens для системных цветов.

2 голосов
/ 11 октября 2010

В прошлом месяце я прочитал интересную статью , в которой предлагалось сделать всю вашу живопись на отдельном объекте BufferedGraphics, и у метода on_paint была прямая копия этого объекта в графический объект вашего элемента управления.

Таким образом, нанесение краски происходит быстрее, и вы обновляете BufferedGraphics только тогда, когда что-то существенно изменяется (то есть линия перемещается или изменяется текст).

1 голос
/ 11 октября 2010

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

Убедитесь, что вы Dispose() все, что вам нужно в вашей графике. Ручки, кисти, регионы, шрифты. Все они являются объектами GDI и связаны с системой дескрипторами GDI.

Если вам нужна графика, которая каким-то образом анимируется или будет меняться во времени без щелчка пользователем, подготовьте все свои графические объекты впереди и используйте их как можно чаще. Здесь можно применить правило, которое заключается в том, что лучше тратить память, чем миллисекунды при рисовании каждого кадра анимации.

И, наконец, по крайней мере, для этого поста - не забудьте использовать двойную буферизацию, либо в автоматическом режиме в .net Control, либо в стиле «сворачивайте свой собственный задний план».

Развлекайся GDI-ing:)

1 голос
/ 12 ноября 2009

Я бы использовал кисти и ручки в качестве элементов пользовательского элемента управления, а затем утилизировал их при утилизации элемента управления. Таким образом, вы повторно используете одну и ту же кисть / перо при каждом вызове OnPaint.

Я бы не объявил их static, потому что вы не сможете знать, когда сможете избавиться от своих объектов. Но, как уже упоминалось в SLaks, если в памяти одновременно имеется много экземпляров элемента управления, может быть хорошей идеей создавать кисти и перья как статические, чтобы у вас был только один экземпляр каждого объекта, созданный за время существования вашего приложения. .

0 голосов
/ 12 ноября 2009

Рекомендуется использовать системные ручки и кисти, так как они оптимизированы для минимального потребления ресурсов.

...