C# для профессионалов. Том II
Шрифт:
Однако посмотрим теперь, что происходит, если действительно воспользоваться одной из панелей прокрутки и сместить немного изображение вниз:
Очевидно, что-то происходит неправильно.
Фактически неправильное поведение связано с тем, что не было принято во внимание положение панелей прокрутки в коде метода
Фигуры
Прежде чем перейти к решению этой проблемы, рассмотрим, что происходит на снимках экрана. Это поможет точно понять, как выполняется рисование в присутствии панелей прокрутки, и в то же время будет хорошей практикой. Если начать использовать GDI+, то рано или поздно встретится ситуация со странными рисунками, такая, как одна из приведенных выше, что потребует определить, что же происходит неправильно.
Посмотрим сначала на последний снимок экрана, с которым проще иметь дело. Пример
Теперь посмотрим на более ранний снимок экрана — сразу после прокрутки изображения вниз. Мы замечаем, что здесь верхние две трети окна выглядят нормально. Это связано с тем, что они были нарисованы, когда приложение запускалось в первый раз. При прокрутке окна Windows не просит приложение перерисовать то, что уже было на экране. Система Windows достаточно разумна, чтобы самостоятельно определить, какие биты из изображаемых в данный момент на экране могут плавно переместиться, чтобы соответствовать текущему положению панели прокрутки. Это значительно более эффективный процесс, так как он может использовать некоторые аппаратные средства ускорения. Часть этого изображения экрана, которая выглядит неправильно, составляет нижнюю треть окна. Эта часть окна не была нарисована, когда приложение появилось на экране впервые, так как до начала прокрутки она находилась вне клиентской области. Значит, система Windows просит приложение
Один из способов решения проблемы состоит в следующем. Мы в данный момент задаем координаты относительно верхнего левого угла начала "документа", а нам необходимо преобразовать их, чтобы задать относительно верхнего левого угла клиентской области. Рисунок должен это четко показать. На нем тонкие прямоугольники отмечают границы области экрана и всего документа (чтобы сделать рисунок понятнее, документ на самом деле расширен вниз и вправо за границы экрана, но это не изменяет рассуждения. Мы также предполагаем небольшую горизонтальную и вертикальную прокрутки). Толстые линии отмечают прямоугольник и эллипс, которые мы пытаемся нарисовать. Некоторая произвольно нарисованная точка Р будет служить в качестве примера. При вызове методов рисования мы предоставляем экземпляр объекта
Проблема в том, что неизвестно, каким будет вектор из А в Р. Мы знаем, какой будет вектор из В в Р, это просто координаты Р относительно верхнего левого угла документа, позиция, где мы хотим нарисовать в документе точку Р. Мы знаем также, какой будет вектор из В в А — это величина, на которую была выполнена прокрутка; она хранится в свойстве класса
Однако все выполняется проще. Весь процесс был расписан подробно, чтобы показать, что происходит на самом деле, но класс
После всех этих объяснений осталось только добавить следующую строку кода в код рисования
Фактически в нашем примере это происходит немного сложнее, так как мы по отдельности контролируем область вырезания, проверяя, нужно ли делать какое-либо рисование. Мы должны настроить эту проверку с учетом положения прокрутки, после чего весь код рисования для этого примера (загружаемый с web-сайта Wrox Press как
Теперь код прокрутки работает прекрасно, мы можем, наконец, получить правильно прокрученный снимок экрана.
Координаты мировые, страницы и устройства