2009-06-04 2 views

ответ

37

Метод Invalidate() вызовет перерисовку. будет поднят

MSDN Link

4

Вызов control.invalidate и событие краски.

+1

частная пустота Form1_Paint (объект отправителя, System.Windows.Forms.PaintEventArgs е) { System.Drawing.Graphics графика = this.CreateGraphics(); System.Drawing.Rectangle rectangle = новый System.Drawing.Rectangle (0, 0, 50, 50); graphics.DrawEllipse (System.Drawing.Pens.Black, прямоугольник); graphics.DrawRectangle (System.Drawing.Pens.Red, прямоугольник); } Когда этот метод краски вызван, чтобы перерисовать форму. Он перерисовывает форму, не так ли. –

5

Думаю, что вы также можете позвонить Refresh().

+0

Спасибо, Брайан. Отлично. –

77

В способе вашей формы или элемента управления, у вас есть 3 варианта:

this.Invalidate(); // request a delayed Repaint by the normal MessageLoop system  
this.Update();  // forces Repaint of invalidated area 
this.Refresh();  // Combines Invalidate() and Update() 

Обычно, вы бы просто позвонить Invalidate() и позволить системе объединить, что с другими обновлениями экрана. Если вы спешите, вы должны позвонить Refresh(), но затем вы рискуете, что он будет перекрашен несколько раз подряд из-за других элементов управления (особенно родителя).

Обычный способ Windows (Win32 и WinForms.Net) обрабатывает это, чтобы ждать, пока MessageQueue будет запущен пустым, а затем обработать все недействительные области экрана. Это эффективно, потому что когда что-то меняется, как правило, каскадируется и на другие вещи (элементы управления), которые изменяются.

Наиболее распространенный сценарий для Update() - это когда вы изменяете свойство (скажем, label1.Text, что приведет к аннулированию метки) в цикле for, и этот цикл временно блокирует Message-Loop. Всякий раз, когда вы его используете, вы должны спросить себя, не следует ли вместо этого использовать Thread. Но ответ всегда есть.

+8

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

+0

Обратите внимание, что может быть огромная разница в производительности процессора в зависимости от того, какой метод вы используете. 'this.Invalidate()' требует наименьших ресурсов ЦП, поскольку вы не заставляете вещи за пределами стандартного цикла сообщений, и это особенно верно, если вы можете вызывать 'this.Invalidate (false)', поэтому вы вызываете только 'OnPaint ') 'на основной элемент управления/формы, а не на дочерние элементы управления. Для одного из моих UserControls, переместившись с 'this.Update()' на 'this.Invalidate (false)' уменьшила нагрузку на процессор в 4 раза. –

3

Refresh, вероятно, также сделает для гораздо более читаемого кода, в зависимости от контекста.

6

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

this.Paint += this.OnPaint; 

Этот обработчик вызывает обычную процедуру, которая выполняет фактическую картину.

private void OnPaint(object sender, PaintEventArgs e) 
{ 
    this.DrawFrame(e.Graphics); 
} 

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

private void RedrawFrame() 
{ 
    var r = new Rectangle(
     0, 0, this.Width, this.Height); 

    this.Invalidate(r); 
    this.Update(); 
} 

Контрольные прокручивается в порядке, но мерцает далеко за пределами любого удобного уровня. Поэтому я решил вместо того, чтобы перекрашивать элемент управления, вызвать мой метод DrawFrame() непосредственно после обработки события MouseMove. Это создавало гладкую прокрутку без мерцания.

private void RedrawFrame() 
{ 
    var g = Graphics.FromHwnd(this.Handle); 
    this.DrawFrame(g); 
} 

Этот подход может быть неприменим ко всем ситуациям, но до сих пор он мне подходит.

+0

+1 для 'this.Invalidate (r)' –

+1

Будьте осторожны, я подумайте, что результат FromHwnd() должен быть удален снова (поместите его в 'using() {}') –

+3

Используйте двойную буферизацию, чтобы избавиться от мерцания. – TheRealChx101

0

использование Control.InvokePaint вы можете также использовать его для ручной двойной буферизации

Смежные вопросы