У меня есть контроль, который я должен сделать большие изменения. Я хотел бы полностью предотвратить его перерисовку, пока я делаю это - SuspendLayout и ResumeLayout недостаточно. Как приостановить рисование для элемента управления и его дочерних элементов?
184
Ответы:
На моей предыдущей работе мы изо всех сил пытались заставить наше богатое приложение пользовательского интерфейса рисовать быстро и плавно. Мы использовали стандартные элементы управления .Net, пользовательские элементы управления и элементы управления devexpress.
После долгих поисков и использования рефлектора я наткнулся на сообщение win32 WM_SETREDRAW. Это действительно останавливает рисование элементов управления, пока вы обновляете их, и может применяться IIRC к родительской / содержащей панели.
Это очень простой класс, демонстрирующий, как использовать это сообщение:
Есть более полные обсуждения по этому вопросу - Google для C # и WM_SETREDRAW, например
C # джиттер
Приостановка макетов
И к кому это может относиться, это аналогичный пример в VB:
источник
Control
базовый класс для всех элементов управления WinForms уже делает дляBeginUpdate
иEndUpdate
методов. Самостоятельная отправка сообщения не лучше, чем использование этих методов для тяжелой работы за вас, и, конечно, не может привести к другим результатам.Control.Handle
заставит создать дескриптор окна и может повлиять на производительность. Например, если вы перемещали элемент управления в форме до ее отображения, если вы вызываете этоSuspendDrawing
заранее, ваш ход будет медленнее. Вероятно, должны иметьif (!parent.IsHandleCreated) return
проверки в обоих методах.Следующее является тем же решением ng5000, но не использует P / Invoke.
источник
Message
и гдеNativeWindow
; поиск документации по названному классуMessage
не так уж интересен.Invalidate()
не работает так же хорошо, какRefresh()
если бы не последовал один в любом случае.Я обычно использую немного измененную версию ответа ngLink .
Это позволяет приостановить / возобновить вызовы, чтобы быть вложенными. Вы должны убедиться, что соответствует каждому
SuspendDrawing
сResumeDrawing
. Следовательно, было бы неплохо сделать их публичными.источник
SuspendDrawing(); try { DrawSomething(); } finally { ResumeDrawing(); }
. Другой вариант - реализовать это вIDisposable
классе и заключить чертежную часть вusing
-словие. Дескриптор будет передан конструктору, который приостановит рисование.DllImport
DECLARE ,wParam
какbool
?Чтобы помочь не забыть включить рисунок:
использование:
источник
action()
выдает исключение? (Используйте попытку / наконец-то)Хорошее решение без использования взаимодействия:
Как всегда, просто включите DoubleBuffered = true в CustomControl. Затем, если у вас есть какие-либо контейнеры, такие как FlowLayoutPanel или TableLayoutPanel, выведите класс из каждого из этих типов, а в конструкторах включите двойную буферизацию. Теперь просто используйте ваши производные контейнеры вместо контейнеров Windows.Forms.
источник
Исходя из ответа ng5000, мне нравится использовать это расширение:
Использование:
источник
Вот комбинация ceztko и ng5000, чтобы принести версию расширений VB, которая не использует pinvoke
источник
Я знаю, что это старый вопрос, на который уже дан ответ, но вот мое мнение об этом; Я реорганизовал приостановку обновлений в IDisposable - таким образом я могу заключить операторы, которые я хочу запустить, в
using
оператор.источник
Это даже проще и, может быть, хакерски - поскольку я вижу много мышц GDI в этой теме , и, очевидно, подходит только для определенных сценариев. YMMV
В моем сценарии я использую то, что я буду называть «Родительским» UserControl - и во время
Load
события я просто удаляю элемент управления, которым нужно манипулировать, из.Controls
коллекции Родителя и Родителя.OnPaint
заботится о полной покраске дочернего элемента. контролировать каким-либо особым образом .. полностью отключить возможности рисования ребенка в автономном режиме.Теперь я передаю свою дочернюю процедуру рисования методу расширения, основанному на этой концепции от Майка Голда, для печати оконных форм .
Здесь мне нужен поднабор меток для рендеринга перпендикулярно макету:
Затем я освобождаю дочерний элемент управления от рисования с помощью этого кода в
ParentUserControl.Load
обработчике событий:Затем в том же ParentUserControl мы рисуем элемент управления, которым нужно манипулировать с нуля:
Когда вы размещаете ParentUserControl где-нибудь, например, Windows Form - я обнаружил, что моя Visual Studio 2015 правильно отображает форму во время разработки, а также во время выполнения:
Теперь, так как мои особые манипуляции поворачивают дочерний элемент управления на 90 градусов, я уверен, что все горячие точки и интерактивность были уничтожены в этом регионе - но проблема, которую я решал, заключалась в том, чтобы наклеить этикетку на упаковку, которую нужно было предварительно просмотреть и напечатать, который работал хорошо для меня.
Если есть способы восстановить «горячие точки» и контроль для моего намеренно осиротевшего контроля - я бы с радостью узнал об этом когда-нибудь (конечно, не для этого сценария, но… просто для изучения). Конечно, WPF поддерживает такое сумасшествие ... OOTB ... но ... эй ... WinForms так весело, правда?
источник
Или просто используйте
Control.SuspendLayout()
иControl.ResumeLayout()
.источник