висновок графіки

У той момент, коли будь-яка частина вікна ховається, приховані пікселі губляться, тому що Windows звільняє пам'ять, яку вони займали. Однак вона запам'ятовує, що частина вікна була прихована, і коли виявляє, що ця частина вікна знову відкрита, то запитує у додатки, що володіє вікном, перерисовку його вмісту. Є кілька винятків з цього правила - зазвичай, коли мова йде про приховування дуже невеликих частин вікон на короткий час (хорошим прикладом може служити вибір елемента головного меню, коли з нього випадає підменю, тимчасово накриваючи частина вікна). Зазвичай же можна очікувати, що якщо частина вікна була прихована, то ваш додаток має перемалювати його.

Саме це є причиною проблеми з нашим прикладом додатки. Ми помістили код малювання в конструктор Form1, який викликається тільки один раз при запуску програми, і ми не можемо викликати цей конструктор знову, щоб перемалювати наші фігури, коли це знадобиться пізніше.

При роботі з елементами управління Windows Forms немає необхідності знати що-небудь про те, як ними вирішується це завдання. Справа в тому, що стандартні елементи управління досить складні, і вони знають, як їм слід перемальовувати себе в будь-який момент, коли Windows попросить їх про це. Це пояснює, чому програмуючи елементи управління, нам взагалі не доводиться турбуватися про реальний процес з малювання. Якщо ж ми беремо на себе відповідальність за відображення екрану свого застосування, то треба також подбати про те, щоб додаток коректно відповідало на запити Windows, що стосуються перемальовування всіх частин його вікна. У наступному розділі ми внесемо необхідні зміни, щоб зробити це.

Малювання контурів з використанням OnPaint ()

Не турбуйтеся, якщо попередні пояснення створили у вас враження, що малювання власного користувальницького інтерфейсу виглядає жахливо складним завданням. Змусити додаток перемалювати себе, коли це необхідно, насправді досить просто.

Windows повідомляє додаток про те, що потрібна деяка перерисовка, збуджуючи подія Paint. Цікаво, що клас Form вже має реалізований обробник цієї події, тому нам не доведеться додавати його самостійно. Оброблювач Form1 події Paint міститься в віртуальному методі OnPaint (). якому передається єдиний параметр PaintEventArgs. Це означає, що все, що нам необхідно зробити - це перевизначити OnPaint (). щоб він виконував необхідну нам малювання.

В даному розділі створимо нове Windows-додаток під назвою DrwShapes. Як і раніше, встановимо білий колір фону, використовуючи вікно властивостей. Крім того, змінимо текст вікна на DrawShapes Sample. Після цього додамо наступний фрагмент до згенеровані коду класу Form1.

protected override void OnPaint (PaintEventArgs e)

Graphics dc = e.Graphics;

Pen bluePen = new Pen (Color.Blue, 3);

Pen redPen = new Pen (Color.Red, 2);

dc.DrawEllipse (redPen, 0, 50, 80, 60);

Зверніть увагу, що метод OnPaint () оголошений як protected, оскільки зазвичай він використовується всередині класу, тому немає причин будь-якого коду поза класом знати про його існування.

PaintEventArgs - це спадкоємець класу EventArgs, який зазвичай використовується для передачі інформації про події. PaintEventArgs має два додаткових властивості, більш важливе з яких - це екземпляр Graphics, вже підготовлений і оптимізований для малювання потрібної області вікна. Це означає, що нам не доведеться в методі OnPaint () викликати CreateGraphics (), щоб отримати DC - нам його вже передали. Друге додаткове властивість ми незабаром також розглянемо; воно містить більш деталізовану інформацію про те, яка область вікна дійсно потребує перемальовуванні.

В нашій реалізації OnPaint () насамперед ми отримуємо посилання на об'єкт Graphics з PaintEventArgs, потім малюємо наші фігури точно так, як робили це раніше. І в кінці викликаємо метод OnPaint () базового класу. Цей крок важливий. Ми переопределили OnPaint () для виконання нашого власного малювання, але, можливо, що Windows може мати деяку додаткову роботу, яку необхідно виконати в процесі малювання - вся ця робота буде виконана в методі OnPaint () одного з базових класів .NET.

У цьому прикладі, якщо прибрати вріз OnPaint () базового класу, то ми не побачимо ніякого особливого ефекту. Однак не слід піддаватися спокусі відмовитися від цього виклику. Це може порушити нормальну роботу Windows, і результати можуть бути непредсказуемсмі.

Метод OnPaint () також викликається при першому запуску додатка, коли наше вікно вперше відображається на екрані. У в'язі з цим немає необхідності дублювати код малювання в конструкторі.


висновок графіки

Мал. 33.2. Результат виконання прикладу DrawShapes при перекритті форми іншим вікном

Запуск цього коду спочатку дасть той же результат, що і попередній приклад, за винятком того, що тепер наше додаток поводиться правильно при мінімізації вікна або приховуванні його частини.

Використання області відсікання

Приклад програми DrawShapes з попереднього розділу ілюструє головні принципи, що стосуються малювання в вікнах, хоча він і не дуже ефективний. Причина пов'язана зі спробою малювати все в вікні, незалежно від того, наскільки багато в дійсності елементів повинно бути перерисовано. На рис. 33.2 показаний результат виконання прикладу DrawShapes з подальшим відкриттям іншого вікна і переміщенням його над формою DrawShapes так, що частина його перекривається.

Поки все добре. Однак коли ми зрушимо перекривши вікно так, що вікно DrawShapes знову буде повністю мабуть, Windows, як зазвичай, пошле нашій формі подія Paint, запитуючи її перерисовку. Прямокутник і еліпс знаходяться в лівому верхньому кутку клієнтської області, а тому залишалися видимими весь час. Таким чином, насправді не було необхідності їх весь час перемальовувати на додачу до перемальовуванні білого фону вікна. Однак Windows не знає про це, а тому думає, що повинна згенерувати подія Paint, що призводить до виклику нашої реалізації OnPaint (). І ця реалізація виконує абсолютно зайву перерисовку прямокутника і еліпса.

В результаті всього цього запит до примірника Graphics виконати якесь малювання поза недійсною області майже напевно призведе до зайвих витрат процесорного часу і сповільнить додаток. У добре спроектованому додатку код повинен допомагати контексту пристрою, виконуючи кілька простих перевірок, щоб переконатися, що не буде зроблено зайвих спроб виклику методів екземпляра Graphics. У цьому розділі ми закодируем новий приклад DrawShapesWithClipping, модифікувавши попередній DisplayShapes. У коді OnPaint () будуть виконані прості перевірки, щоб переконатися, що недійсна область перетинається з областю, в якій потрібно малювати, і тільки в разі, якщо це так, малювання буде виконано.

По-перше, нам потрібно отримати інформацію про область відсікання. Для цього нам знадобиться нова властивість ClipRectangle класу PaintEventArgs. Властивість ClipRectangle містить координати перемальовувати області, оформлені у вигляді примірника структури System.Drawing.Rectangle. Це досить проста структура - вона містить чотири властивості, які нас цікавлять: Top, Bottom,

Схожі статті