Книга: ЯЗЫК ПРОГРАММИРОВАНИЯ С# 2005 И ПЛАТФОРМА .NET 2.0. 3-е издание

Доступ к объекту Graphics вне обработчика Paint

Доступ к объекту Graphics вне обработчика Paint

В некоторых редких случаях может понадобиться доступ к объекту Graphics вне контекста обработчика события Paint. Предположим, например, что нужно перерисовать небольшой круг с центром в точке (х, у), где был выполнен щелчок кнопки мыши. Чтобы получить действительный объект Graphics в рамках контекста обработчика событий MouseDown, можно, например, вызвать статический метод Graphics.FromHwnd(). Имея опыт использования Win32, вы можете знать, что HWND является структурой данных, представляющей окно Win32. В рамках платформы .NET наследуемое свойство Handle извлекает соответствующую структуру HWND, которую затем можно использовать в качестве параметра для Graphics. FromHwnd().

private void MainForm_MouseDown(object sender, MouseEventArgs e) {
 // Получение объекта Graphics через Hwnd.
 Graphics g = Graphics.FromHwnd(this.Handle);
 // Рисование круга 10*10 по щелчку мыши.
 g.FillEllipse(Brushes.Firebrick, e.X, e.Y, 10, 10);
 // Освобождение объектов Graphic, созданных напрямую.
 g.Dispose();
}

Эта логика отображает круг за пределами обработчика OnPaint(), но очень важно понимать, что когда выполняется обновление формы, все такие круги стираются! Это разумно, поскольку соответствующая визуализация выполнялась в контексте события MouseDown. Значительно лучшим подходом Является создание в обработчике события MouseDown нового типа Point, который добавляется к некоторой внутренней коллекции (например, List‹T›), и только затем вызывается Invalidate(). Тогда обработчик события Раint может просто "пройти" по коллекции и перерисовать каждый Point.

public partial class MainForm: Form {
 // Используется для хранения всех Point.
 private List‹Point› myPts = new List‹Point›();
 publiс MainForm() {
  …
  this.MouseDown += new MouseEventHandler(MainForm_MouseDown);
 }
 private void MainForm_MouseDown(object sender, MouseEventArgs e) {
  // Добавление в коллекцию.
  myPts.Add(new Point(e.X, e.Y));
  Invalidate();
 }
 private void MainForm_Paint(object sender, PaintEventArgs e) {
  Graphics g = e.Graphics;
  g.DrawString("Привет GDI+", new Font("Times New Roman", 20), new SolidBrush(Color.Black), 0, 0);
  foreach(Point p in myPts) g.FillEllipse(Brushes.Firebrick, p.X, p.Y, 10, 10);
 }
}

При таком подходе уже отображенные круги будут оставаться на месте, поскольку графическая визуализация обрабатывается в рамках события Paint. На рис. 20.1 показано окно тестового запуска этого приложения.


Рис 20.1. Простое графическое приложение

Исходный код. Проект BasiсPaintForm размещен в подкаталоге, соответствующем главе 20.

Оглавление книги


Генерация: 1.136. Запросов К БД/Cache: 3 / 1
поделиться
Вверх Вниз