Программирование >>  Вывод графики 

1 ... 14 15 16 [ 17 ] 18 19


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;



1 ... 14 15 16 [ 17 ] 18 19

© 2006 - 2024 pmbk.ru. Генерация страницы: 0.001
При копировании материалов приветствуются ссылки.
Яндекс.Метрика