|
Программирование >> Вывод графики
protected override void OnMouseDown(MouseEventArgs e) base.OnMouseDown(e); mouseDoubleClickPosition = new Point(e.X, e.Y); Теперь взглянем на переопределение OnDoubleClick() . Здесь работы побольше: protected override void OnDoubleClick(EventArgs e) int i = PageCoordinatesToLineIndex(mouseDoubleClickPosition); if (i >= 0) TextLineInformation lineToBeChanged = (TextLineInformation)documentLines[i]; lineToBeChanged.Text = lineToBeChanged.Text.ToUpper(); Graphics dc = CreateGraphics(); uint newWidth =(uint)dc.MeasureString(lineToBeChanged.Text, mainFont).Width; if (newWidth > lineToBeChanged.Width) lineToBeChanged.Width = newWidth; if (newWidth+2*margin > this.documentSize.Width) documentSize.Width = (int)newWidth; AutoScrollMinSize = this.documentSize; Rectangle changedRectangle = new Rectangle( LineIndexToPageCoordinates(i), new Size((int)newWidth, (int)this.lineHeight)); this.Invalidate(changedRectangle); base.OnDoubleClick(e); Здесь мы начинаем с вызова PageCoordinatesToLineIndex() , чтобы определить, на какой строке текста находился указатель мыши в момент двойного щелчка. Если этот вызов вернет -1, значит, указатель был вне пределов текста, и потому ничего делать не нужно, за исключением, конечно, вызова OnDoubleClick() базового класса, чтобы позволить Windows выполнить обработку по умолчанию. Предположим, мы идентифицировали строку текста. Тогда можно применить метод string.ToUpper() , чтобы преобразовать ее в верхний регистр. Это - простая часть работы. Сложная часть заключается в том, чтобы определить, что и где должно быть перерисовано. К счастью, поскольку этот пример прост, комбинаций не так много. Можно предположить, что преобразование строки в верхний регистр всегда либо оставит длину строки неизменной, либо увеличит ее. Заглавные буквы крупнее прописных, а потому ширина никогда не станет меньше. Также нам известно, что поскольку перенос строк не выполняется, наша строка текста не перейдет на следующую и не вытолкнет остальные вниз. Значит, преобразование в верхний регистр не изменит местоположения никаких других элементов. Это значительно упрощает задачу! Следующее, что делает наш код - он использует Graphics.MeasureString() для того, чтобы вычислить новую ширину текста. И здесь возникают две описанных ниже возможности. □ Новая ширина строки может сделать ее самой длинной в тексте, что увеличит ширину всего документа. В этом случае придется установить AutoScrollMinSize новое значение, чтобы правильно работали линейки прокрутки. □ Размер документа может остаться прежним. В любом случае потребуется перерисовать экран, вызвав Invalidate() . Но изменилась только одна строка, а потому нам не нужно перерисовывать весь документ. Вместо этого необходимо найти границы прямоугольной области, содержащей модифицированную строку, чтобы их можно было передать Invalidate() , обеспечивая перерисовку только измененной строки. И это именно то, что делает показанный ранее код. Наш вызов Invalidate() инициирует вызов OnPaint() , когда обработчик события мыши возвращает управление. Памятуя о ранее приведенных предупреждениях относительно сложности установки отладочных точек прерывания внутри OnPaint() , мы запускаем пример и устанавливаем точку прерывания в OnPaint() , чтобы перехватить результирующее действие перерисовки, в результате чего обнаруживаем, что параметр PaintEventArgs метода OnPaint() действительно содержит область отсечения, соответствующую указанному прямоугольнику с измененной строкой. И поскольку мы переопределили OnPaint() так, что он тщательно принимает во внимание область отсечения, подлежащую перерисовке, то как раз одна измененная строка и будет перерисована. Печать До сих пор в этой главе мы сосредоточили свое внимание исключительно на рисовании на экране. Тем не менее, однажды вам понадобится получить твердую копию данных. Это и есть тема настоящего раздела. Мы расширим пример CapsEditor, добавив возможность предварительно просмотра копии для печати и собственно печати редактируемого документа. К сожалению, у нас нет достаточного места, чтобы рассмотреть тему печати очень подробно, поэтому мы реализуем в примере лишь самую базовую функциональность печати. Обычно, реализуя возможность печати данных в приложении, необходимо добавить три команды в главное меню приложения File (Файл): □ Page Setup (Параметры страницы) - для выбора опций печати, например, какие страницы печатать, какой принтер использовать и тому подобное; □ Print Preview (Предварительный просмотр) - для открытия новой формы, демонстрирующей внешний вид макета для печати; □ Print (Печать) - для отправки документа на устройство печати. Пока для простоты мы не будем реализовывать команду меню Page Setup. Печать будет выполняться только с установками по умолчанию. Однако отметим, что если вы пожелаете реализовать Page Setup, то для вас Microsoft подготовила класс диалогового окна настройки печати - System.Windows.Forms.PrintDialog. Вы можете написать обработчик события меню, который отобразит эту форму и сохранит выбранные пользователем настройки. Во многих отношениях печать - это то же самое, что отображение на экране. Вы используете контекст устройства (экземпляр Graphics) и вызываете обычные команды отображения с этим экземпляром. В Microsoft разработали множество классов, призванных помочь в этом. Вот два главных класса, которые вам для этого понадобятся: □ System.Drawing.Printing.PrintDocument □ System.Drawing.Printing.PrintPreviewDialog Эти два класса берут на себя обеспечение доставки команд рисования нужному контексту устройств для выполнения печати, избавляя разработчика от рутины и позволяя сосредоточиться на логике того, что необходимо напечатать. Несмотря на эти сложности, сам процесс печати довольно прост. Необходимые шаги программного характера, которые для этого нужно выполнить, сводятся к описанным ниже. □ Печать. Вы создаете экземпляр объекта PrintDocument и вызываете его метод Print() . Этот метод посылает событие PrintPage для печати первой страницы. PrintPage принимает параметр PrintPageEventArgs, который содержит информацию относительно размера бумаги и настроек, а также объект Graphics, используемый для команд рисования. Таким образом, вам нужно написать обработчик для этого события и реализовать его для печати страницы. Этот обработчик также должен устанавливать свойство PrintPageEventArgs булевского типа под названием HasMorePages в true или false, для указания того, есть ли еще страницы для печати. Метод PrintDocument.Print() выполняет повторяющуюся инициализацию события PrintPage до тех пор, пока не увидит, что HasMorePages установлено в false. □ Предварительный просмотр. В этом случае создаются экземпляры объектов PrintDocument и PrintPreviewDialog. Экземпляр PrintDocument присоединяется к PrintPreviewDialog (через свойство PrintPreviewDialog.Document), после чего вызывается метод диалога ShowDialog() . Этот метод модально отображает диалоговое окно, которое представляет собой стандартную форму Windows для предварительного просмотра печати с загруженными в нее страницами документа. Внутренне страницы отображаются последовательной генерацией события PrintPage до тех пор, пока свойство HasMorePages не станет равно false. При этом нет необходимости писать отдельный обработчик событий для этого; используется тот же обработчик, что служит для печати каждой страницы, поскольку код рисования в обоих случаях идентичен (в конце концов, предварительный просмотр печати должен показывать в точности то, что будет напечатано). Реализация команд меню Print и Print Preview Теперь, когда мы в общих чертах описали этот процесс, в данном разделе посмотрим, как это выглядит в исходном коде. Исходный код примера доступен в виде проекта PrintingCapsEdit на прилагаемом компакт-диске. Он состоит из проекта CapsEditor с дополнениями, выделенными в приведенном ниже фрагменте. Начнем с использования представления конструктора интегрированной среды разработки Visual Studio 2008, добавив две новых команды в меню File (Файл), а именно: Print (Печать) и Print Preview (Предварительный просмотр). С помощью окна свойств переименуем их в menuFilePrint и menuFilePrintPreview, а также сделаем их неактивными при запуске приложения (нельзя ничего печатать, пока документ не открыт). Эти команды меню сделаем активными, добавив следующий код в метод LoadFile() главной формы, который отвечает за загрузку файла в приложение CapsEditor: private void LoadFile(string FileName) StreamReader sr = new StreamReader(FileName); string nextLine; documentLines.Clear(); nLines = 0; TextLineInformation nextLineInfo; while ((nextLine = sr.ReadLine()) I= null) nextLineInfo = new TextLineInformation(); nextLineInfo.Text = nextLine;
|
© 2006 - 2024 pmbk.ru. Генерация страницы: 0
При копировании материалов приветствуются ссылки. |