Читать «ЯЗЫК ПРОГРАММИРОВАНИЯ С# 2005 И ПЛАТФОРМА .NET 2.0. 3-е издание» онлайн - страница 487
Эндрю Троелсен
Обновление области клиента формы
В ходе выполнения приложения GDI+ может возникнуть необходимость в явном вызове события Paint вместо ожидания того, что окно станет "естественно грязным". Например, вы создаете программу, которая позволяет пользователю выбрать подходящий рисунок из набора точечных изображений в пользовательском диалоговом окне. После закрытия диалогового окна нужна отобразить выбранный пользователем рисунок в области клиента формж. Очевидно, если ждать, когда окно станет "естественно грязным", пользователь не увидит изменений до того, как изменятся размеры окна или его часть откроется из-под другого окна. Чтобы вызвать перерисовку окна программно, просто вызовите наследуемый метод Invalidate().
public partial class MainForm: Form {
…
private void MainForm_Paint(object sender, PaintEventArgs e) {
Graphics g = e.Graphics;
// Здесь выполняется визуализация изображения.
}
private void GetNewBitmap() {
// Отображение диалогового окна и получение нового образа.
// Перерисовка клиентской области.
Invalidate();
}
}
Метод Invalidate() является перегруженным, чтобы вы могли указать прямоугольную область для перерисовки, а не перерисовывать все области клиента (что делается до умолчанию). Чтобы обновить только заданный прямоугольник слева вверху области клиента, вы можете использовать следующее.
// Перерисовка прямоугольной части формы.
private void UpdateUpperArea() {
Rectangle myRect = new Rectangle(0, 0, 75, 150);
Invalidate(myRect);
}
Доступ к объекту 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.