Как правильно использовать OnPaint в приложениях.Net?

Иногда мне нужен внешний вид элемента управления. Или сделайте много заказной живописи. Я знаю, что могу сделать это с OnPaint (см.: http://msdn.microsoft.com/en-us/library/system.windows.forms.control.onpaint.aspx)

Как правильно рисовать вещи в приложении.net, используя OnPaint? Есть ли какие-то правила, которые я должен соблюдать, чтобы оптимизировать свое приложение и минимизировать время рендеринга?

Примечание: время от времени я видел и испытывал много неэффективного использования OnPaint, поэтому я создал этот вопрос и ответ.

1 ответ

Решение

Использовать OnPaint для того, чтобы эффективно вы знали пару вещей:

  • OnPaint контроля, например, Form1, выполняется каждый раз, когда элемент управления окрашен (дух...)
  • OnPaint из Form1 выполняется каждый раз, когда дочерний элемент управления Form1 нарисован. Например, если вы рисуете точку в правом верхнем углу Form1 с использованием OnPaint из Form1 в то время как у вас есть 150 дочерних элементов управления Form1, точка будет нарисована не менее 150 раз! Это значительно увеличивает время рендеринга. Особенно, если вы делаете много пользовательских чертежей и расчетов в OnPaint,
    • Так что, как правило, вы никогда не должны иметь никакой логики в OnPaint элемента управления, когда этот элемент управления имеет один или несколько дочерних элементов управления. Вместо этого вы должны создать собственный элемент управления, в котором больше нет дочерних элементов управления, который выполняет рисование. И поместите его в качестве дочернего элемента управления в родительский элемент управления в том месте, где требуется пользовательский чертеж.
    • Всякий раз, когда элемент управления добавляется к родителю, родитель перерисовывается. Если вы поместите много элементов управления на другой элемент управления, например, большой набор результатов с флажками на Form1, вы должны использовать Form1.SuspendLayout() (см. http://msdn.microsoft.com/en-us/library/system.windows.forms.control.suspendlayout.aspx) перед добавлением дочерних элементов управления. А также Form1.ResumeLayout() когда вы закончите добавлять элементы управления. Это временно подавляет OnPaint событие, и уменьшает время рендеринга.
    • Прозрачные пленки всегда увеличивают время рендеринга.
    • Размещение компонентов таким образом, что между ними нет фона, уменьшает количество OnPaint события в родительском контроле. Например, поместите 4 текстовых поля ниже друг друга, чтобы они касались друг друга. Таким образом, между ними нет фона, а все элементы управления нарисованы в одном OnPaint событие вместо 4 OnPaint События. Конечно, это не всегда возможно, так как вы не хотите склеивать все свои компоненты рядом. Но это стоит делать, если производительность важнее, чем внешний вид, например, в большой пользовательской "сетке данных" какого-то рода.
    • НИКОГДА не меняйте расположение или размер элемента управления в OnPaint событие, так как это вызывает новые OnPaint События. Если вы должны переместить / изменить размеры элементов управления, вам придется добавить это где-то еще в вашем коде, до OnPaint вызывается. Например, поместите код перемещения / изменения размера в OnLayout или же OnResize или подобные события. Если вы все еще думаете, что вы должны поместить этот код перемещения / изменения размера в OnPaint Событие для того, чтобы ваше приложение работало, чем вы не правы, и вам нужно пересмотреть логику вашего кода.
    • Подумайте System.Math.Pow(2, 2), прежде чем вызывать Refresh() для элемента управления вне его собственного класса. Если у вас есть желание вызвать Refresh, вам, вероятно, нужны новые события и обработчики событий, чтобы синхронизироваться с тем, что вы хотите отобразить. Это также относится и к Invalidate().
    • Чтобы проверить, насколько хорошо вы рисуете, вы можете сделать следующее. 1. Откройте ваше приложение. 2. Поместите точку торможения на OnPaint в верхней части списка. 3. Максимизируйте окно, чтобы оно охватывало ваше приложение. 4. Сверните окно снова, и ваше приложение перерисовает элемент управления. Если вещи нарисованы дважды, вы допустили ошибку в логике вашего приложения.

Ну, вот и все, если что-то придет в голову, что я забыл, я обновлю этот вопрос и ответ. Если я что-то забыл или допустил ошибку, я был бы рад принять это к сведению!

Надеюсь, это даст кому-то преимущество в использовании пользовательских инструментов рисования в.Net, поскольку я искал эту информацию некоторое время назад.

Другие вопросы по тегам