Почему PaintEventArgs.Graphics отличается от Control.CreateGraphics? - PullRequest
0 голосов
/ 26 ноября 2011

Я написал метод обработчика событий и прикрепил его к событию Paint для Form (только главное окно). Это событие отправляет PaintEventArgs, содержащее свойство с именем Graphics, которое является экземпляром System.Drawing.Graphics.

Вот код, который я использую:

private void Form1_Paint(object sender, PaintEventArgs e) {

    Bitmap bm = new Bitmap("fruit-dealer-full.jpg");

    Graphics g1 = this.CreateGraphics();
    Graphics g2 = e.Graphics;

    // g1.DrawImage(bm, 0, 0, this.Width, this.Height);
    // g1.DrawRectangle(
    //       Pens.White, 10.0f, 10.0f, this.Width - 200, this.Height - 200);

    g2.DrawImage(bm, 0, 0, this.Width, this.Height);
    g2.DrawRectangle(
           Pens.White, 10.0f, 10.0f, this.Width - 200, this.Height - 200);

}

В конечном итоге я просто хочу лучше понять, что здесь происходит, но, в частности, у меня есть три вопроса:

  1. Почему g1 перерисовывает изображение во всем окне, тогда как g2 рисует только новую часть, даже если я вызываю g2.Clear() перед рисованием?
  2. Почему с любым объектом Graphics изображение перерисовывается только при увеличении размера окна, а не при уменьшении его размера?
  3. Если PaintEventArgs.Graphics не может (или не должен) использоваться для рисования, для чего он используется? Я полагаю, что это просто предотвращает необходимость создания нового экземпляра Graphics, если форму не нужно перерисовывать; что еще я пропускаю?

Ответы [ 2 ]

3 голосов
/ 26 ноября 2011

Вы .NET WinForms дети действительно должны изучить Win32 API. Получи копию Petzold уже!

Почему g1 перерисовывает изображение во всем окне, а g2 рисует только новую часть, даже если я вызываю g2.Clear () перед рисованием?

Предположительно g2 - это оболочка для контекста устройства, полученная от BeginPaint. Я представляю себе обертки WinForms PAINTSTRUCT::rcPaint для вас - эта переменная описывает область, которую нужно нарисовать. Это ожидаемое поведение - вместо того, чтобы сжигать циклы ЦП, перерисовывая все окно каждый раз, когда другое окно перекрывает его всего на один пиксель, вы можете перерисовать ... только один пиксель!

g2.Clear предположительно ограничено rcPaint.

g1 - это, вероятно, GetDC для окна, которое дает вам всю поверхность для рисования.

Почему при использовании любого графического объекта изображение перерисовывается только при увеличении размера окна, а не при уменьшении его размера?

Базовый класс окна, вероятно, не имеет CS_HREDRAW или CS_VREDRAW стилей окна. Без них нет повода для поведения по умолчанию запрашивать перерисовку окна, когда оно становится меньше: Windows знает, как выглядит все окно, она может удалить ненужные фрагменты. В отличие от этого, когда окно становится больше, оно не знает, что рисовать в новой области.

Если PaintEventArgs.Graphics не может (или не должен) использоваться для рисования, для чего он используется? Я полагаю, что это просто предотвращает создание нового экземпляра Graphics, если форму не нужно перерисовывать; есть что-то еще, что я пропускаю?

Используется для рисования. Если у вас нет сложных требований к рисованию, вы можете использовать PaintEventArgs.Graphics, чтобы минимизировать количество рисования, которое идет к вашему окну. (Как указано выше - это огромная экономия циклов ЦП и, вероятно, это простая оболочка над BeginPaint и EndPaint - то есть способ выполнения рисования в клиентской области .)

1 голос
/ 26 ноября 2011
  1. Почему g1 перерисовывает изображение во всем окне, а g2 рисует только новую часть, даже если я вызываю g2.Clear () перед рисованием?
    Я не могу понять этот момент, Вы рисуете полную форму в обоих случаях. Таким образом, оба должны нарисовать всю форму, возможно, у вас было такое поведение в другом коде

  2. Почему при использовании любого графического объекта изображение перерисовывается только при увеличении размера окна, а не при уменьшении его размера?
    Поскольку вы должны вызывать Invalidate () в событии Form.Resize, чтобы инициировать перерисовку

  3. Если PaintEventArgs.Graphics не может (или не должен) использоваться для рисования, для чего он используется? Я полагаю, что это просто предотвращает создание нового экземпляра Graphics, если форму не нужно перерисовывать; есть ли что-то еще, что я скучаю?
    Они разные, CreateGraphics - это временный объект, который должен быть размещен сразу после использования (или использован внутри блока), Он используется для простых задач, не требующих рисования, таких как MeasureString, или для получения информации контекста. Для рисования вы всегда должны использовать PaintEventArgs.Graphics. Хороший сценарий, в котором разница будет очевидной, - это использование двойной буферизации. Если вы получите объект Graphics с помощью CreateGraphics, вы получите объект Graphics для элемента управления, а при получении его из PaintEventArgs вы получите растровое изображение буферизации.
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...