Поскольку многие люди просматривают этот вопрос, я продолжу и отвечу на него, насколько мне известно.
Класс Graphics, поставляемый с PaintEventArgs, всегда жестко обрезается запросом на аннулирование. Обычно это делается операционной системой, но это может быть сделано вашим кодом.
Вы не можете сбросить этот клип или выйти за эти границы клипа, но вам это не нужно. Во время рисования вам, как правило, не нужно заботиться о том, как оно обрезается, если вам не нужно отчаянно максимизировать производительность.
Графический класс использует стек контейнеров для применения отсечения и преобразований. Вы можете расширить этот стек самостоятельно, используя Graphics.BeginContainer и Graphics.EndContainer. Каждый раз, когда вы начинаете контейнер, любые изменения, которые вы вносите в Transform или Clip, являются временными и применяются после любого предыдущего Transform или Clip, который был настроен до BeginContainer. По сути, когда вы получаете событие OnPaint, оно уже обрезано, и вы находитесь в новом контейнере, поэтому вы не можете видеть клип (ваш регион Clip или ClipRect будет отображаться как бесконечный), и вы не сможете вырваться из него. границы клипа.
Когда состояние ваших визуальных объектов изменяется (например, при событиях мыши или клавиатуры или при реагировании на изменения данных), обычно достаточно просто вызвать Invalidate (), который перекрасит весь элемент управления. Windows будет вызывать OnPaint в моменты низкой загрузки процессора. Каждый вызов Invalidate () обычно не всегда соответствует событию OnPaint. Invalidate может быть вызван несколько раз до следующего рисования. Таким образом, если 10 свойств в вашей модели данных изменяются одновременно, вы можете безопасно вызывать Invalidate 10 раз при каждом изменении свойств, и вы, скорее всего, вызовете только одно событие OnPaint.
Я заметил, что вы должны быть осторожны с использованием Update () и Refresh (). Это сразу вызывает синхронную OnPaint. Они полезны для рисования во время однопоточной операции (возможно, обновление индикатора выполнения), но использование их в неподходящее время может привести к чрезмерному и ненужному рисованию.
Если вы хотите использовать прямоугольники клипа для улучшения производительности при перерисовке сцены, вам не нужно самостоятельно отслеживать агрегированную область клипа. Windows сделает это за вас. Просто аннулируйте прямоугольник или область, которая требует аннулирования, и раскрасьте как обычно. Например, если объект, который вы рисуете, перемещается, каждый раз, когда вы хотите сделать недействительными его старые и новые границы, вы перекрашиваете фон в том виде, в котором он был изначально, в дополнение к рисованию в новом месте. Вы также должны учитывать размеры хода пера и т. Д.
И, как упоминал Ганс Пассант, всегда используйте 32bppPArgb в качестве растрового формата для изображений с высоким разрешением. Вот фрагмент кода о том, как загрузить изображение с «высокой производительностью»:
public static Bitmap GetHighPerformanceBitmap(Image original)
{
Bitmap bitmap;
bitmap = new Bitmap(original.Width, original.Height, PixelFormat.Format32bppPArgb);
bitmap.SetResolution(original.HorizontalResolution, original.VerticalResolution);
using (Graphics g = Graphics.FromImage(bitmap))
{
g.DrawImage(original, new Rectangle(new Point(0, 0), bitmap.Size), new Rectangle(new Point(0, 0), bitmap.Size), GraphicsUnit.Pixel);
}
return bitmap;
}