Студопедия

Главная страница Случайная страница

Разделы сайта

АвтомобилиАстрономияБиологияГеографияДом и садДругие языкиДругоеИнформатикаИсторияКультураЛитератураЛогикаМатематикаМедицинаМеталлургияМеханикаОбразованиеОхрана трудаПедагогикаПолитикаПравоПсихологияРелигияРиторикаСоциологияСпортСтроительствоТехнологияТуризмФизикаФилософияФинансыХимияЧерчениеЭкологияЭкономикаЭлектроника






Благодарности 23 страница






SqlDataReader myReader;
sqlConnection1.Open();

Дальнейшая работа выполняется внутри блока try-catch, в задачу которого входит перехват и обработка исключений.

Прежде всего, необходимо убедиться, что удаляемый узел не имеет дочерних узлов. Наше приложение позволяет удалять из дерева только такие узлы.

Для поиска всех дочерних узлов выделенного пользователем узла метод DeleteNode использует команду sqlFindChildsCommand.

Вот текст этой команды, который нужно записать в свойство CommandText объекта sqlFindChildsCommand:

SELECT id FROM dbo.Tree WHERE (parent_id = @parent_id)

Через параметр @parent_id мы передаем этой команде идентификатор удаляемого узла:

sqlFindChildsCommand.Parameters[" @parent_id" ].Value = id;
myReader = sqlFindChildsCommand.ExecuteReader();

Если в таблице Tree есть строки, в столбце parent_id которых содержится идентификатор удаляемого узла, значит, такой узле удалять нельзя. Вот соответствующая проверка, выполняемая методом DeleteNode:

if(! myReader.Read())
{
// Удаление узла

}

В том случае, когда удаляемый узел не имеет дочерних узлов, нам нужно удалить строку, описывающую этот узел, из таблицы Tree, а затем удалить соответствующую статью из таблицы Document.

Для удаления строки из таблицы Tree мы используем команду sqlDeleteRowCommand1, предварительно закрыв объект myReader:

myReader.Close();

sqlDeleteRowCommand1.Parameters[" @id" ].Value = id;
sqlDeleteRowCommand1.ExecuteNonQuery();

Свойство объекта sqlDeleteRowCommand1 должно содержать следующий текст команды SQL:

DELETE FROM dbo.Tree WHERE (id = @id)

Идентификатор удаляемого узла передается команде sqlDeleteRowCommand1 в качестве единственного параметра.

Для удаления текста статьи мы использовали другой подход — сформировали исходный текст команды SQL в памяти при помощи метода String.Format:

string strCmd = String.Format(
" DELETE FROM Documents WHERE tree_id = {0}", id);

SqlCommand cmd = new SqlCommand(strCmd, sqlConnection1);
cmd.ExecuteNonQuery();

Полученная в результате этих действий команда исполняется методом ExecuteNonQuery.

И, наконец, последнее, что делает метод DeleteNode после удаления информации из базы данных, это очистка окна элемента управления RichEdit, отображающего содержимое текущего документа, выделенного пользователем в окне дерева:

richTextBox1.Text = " ";

О том, как текст выделенного документа попадает в это окно, мы расскажем в следующем разделе.

Отслеживание перемещений по дереву

Последнее, что нам нужно сделать при подготовке приложения ArticlesApp, это обеспечить просмотр содержимого статьи, заголовок которой пользователь выделил в окне дерева. Для этого нам необходимо снабдить элемент управления treeView1 обработчиком события AfterSelect:

private void treeView1_AfterSelect(object sender,
System.Windows.Forms.TreeViewEventArgs e)
{
int id = (int)treeView1.SelectedNode.Tag;

sqlConnection1.Open();
try
{
SqlDataReader myReader;

string strCmd = String.Format(
" SELECT document FROM Documents WHERE tree_id = {0}", id);

SqlCommand cmd = new SqlCommand(strCmd, sqlConnection1);
myReader = cmd.ExecuteReader();

if(myReader.Read())
{
richTextBox1.Text = myReader.GetString(0).ToString();
}
myReader.Close();
}
catch(Exception ex)
{
MessageBox.Show(ex.Message, " Ошибка");
}

sqlConnection1.Close();
}

Этот обработчик будет получать управление всякий раз, когда пользователь выделяет в окне дерева новый заголовок статьи.

Что делает наш обработчик события treeView1_AfterSelect?

Прежде всего, он получает идентификатор узла, выделенного пользователем, считывая его из свойства treeView1.SelectedNode.Tag:

int id = (int)treeView1.SelectedNode.Tag;

Зная этот идентификатор, мы можем получить текст статьи из таблицы Document, чтобы отобразить его в правой части главного окна нашего приложения.

Для того чтобы получить текст статьи, мы открываем соединение с базой данных. Операция выполняется в блоке try-catch, после чего соединение закрывается:

sqlConnection1.Open();
try
{

}
catch(Exception ex)
{
MessageBox.Show(ex.Message, " Ошибка");
}
sqlConnection1.Close();

Чтобы извлечь текст статьи из таблицы Documents, мы формируем строку в памяти, пользуясь методом String.Format:

string strCmd = String.Format(
" SELECT document FROM Documents WHERE tree_id = {0}", id);

SqlCommand cmd = new SqlCommand(strCmd, sqlConnection1);

Для запуска команды мы создаем объект myReader класса SqlDataReader, а затем вызываем метод ExecuteReader:

SqlDataReader myReader;
myReader = cmd.ExecuteReader();

Результат выполнения команды записывается в свойство richTextBox1.Text, после чего текст статьи появляется в правой части главного окна нашего приложения:

if(myReader.Read())
{
richTextBox1.Text = myReader.GetString(0).ToString();
}

Необходимое финальное действие — закрытие ненужного больше объекта myReader:

myReader.Close();

Разумеется, для чтения текста статьи Вы можете использовать хранимые процедуры сервера Microsoft SQL Server. Использование хранимых процедур дает дополнительные преимущества при создании приложений с базами данных. В частности, разработчик может настраивать права доступа к таким процедурам. Кроме того, хранимые процедуры можно готовить и отлаживать вне контекста приложения. Эту работу можно поручить специалисту по серверу Microsoft SQL Server, который знает все о базах данных, но ничего о создании приложений на языке программирования C#.

Визуальное проектирование приложений C#


А.В. Фролов, Г.В. Фролов

Глава 10. Графический интерфейс GDI+. 2

Основные понятия.. 2

Независимость от аппаратуры.. 2

Контекст отображения. 3

Класс Graphics. 4

Приложение GraphicsApp. 4

Отслеживание состояния клавиш мыши. 5

Отслеживание перемещения курсора мыши. 5

Идентификатор окна Handle и объект Graphics. 6

Кисть для рисования. 6

Рисование точки. 6

Рисование в окне элемента управления. 7

Событие Paint.. 8

Рисование в окнах приложений Microsoft Windows. 8

Сообщение WM_PAINT. 9

Пример обработки события Paint 10

Перерисовка окон элементов управления. 12

Методы и свойства класса Graphics. 12

Рисование геометрических фигур. 12

Линия. 12

Набор линий. 13

Прямоугольник. 16

Набор прямоугольников. 16

Многоугольник. 17

Эллипс. 18

Сегмент эллипса. 18

Кривые Безье. 19

Канонические сплайны.. 20

Замкнутый сегмент эллипса. 22

Закрашенные фигуры.. 23

Рисование изображений. 23

Немного о ресурсах приложения. 24

Значки. 24

Растровые и векторные изображения. 26

Использование класса Image. 27

Режим буксировки. 27

События при буксировке. 28

Обработка события DragOver 28

Обработка события DragDrop. 29

Загрузка изображения. 29

Рисование загруженного изображения. 30

Рисование текста. 32

Инструменты для рисования.. 32

Перья. 33

Кисти. 36

Кисть для сплошной закраски. 37

Кисти типа HatchBrush. 37

Кисти типа TextureBrush. 40

Градиентные кисти. 41

Шрифты.. 42

Классификация шрифтов. 42

Шрифты TrueType. 42

Шрифты OpenType. 44

Выбор шрифта. 46

Конструкторы класса Font 46

Тип шрифта FontStyle. 47

Единицы измерения размера шрифта. 47

Семейство шрифта FontFamily. 48

Приложение FontApp. 48

 

Глава 10. Графический интерфейс GDI+

Мы изучили многочисленные аспекты визуального создания приложений C# с графическим интерфейсом, однако так и не познакомились непосредственно с реализацией самого графического интерфейса библиотеки классов Microsoft.NET Framework.

Действительно, все приложения, рассмотренные ранее в предыдущих главах этой книги, не осуществляли непосредственный вывод графических изображений или текста в окна приложения. Мы абстрагировались от деталей графического интерфейса, возложив все операции по рисованию в окнах на такие элементы управления, как текстовые поля, поля редактирования, списки, деревья и пр.

Вместе с тем рано или поздно наступает момент, когда набор стандартных элементов управления перестает удовлетворять разработчика приложений. Иногда возникают задачи, требующие функций и методов, позволяющих программе рисовать в окнах приложения произвольные графические изображения или отображать текст нестандартным способом. Типичный пример — построение всякого рода графиков и диаграмм, а также создание анимационных изображений.

Графический интерфейс приложений C#, как и других приложений, предназначенных для работы в рамках Microsoft.NET Framework, состоит из набора классов. Эти классы инкапсулируют поведение объектов и инструментов, предназначенных для рисования. Однако прежде чем приступить к описанию этих классов, нам необходимо познакомиться с основными понятиями интерфейса графических устройств.

Заметим, что графический интерфейс GDI+ настолько обширный, что ему можно посвятить отдельную книгу или даже несколько книг. Поэтому в рамках одной главы мы изложим только наиболее существенные аспекты применения GDI+. Тех из Вас, кому будет интересно познакомиться с возможностями GDI+ глубже, мы адресуем к [10].

Основные понятия

Если Вы когда-либо создавали программы для операционной системы MS-DOS и ее аналогов, то помните, что такие программы могут работать в текстовом или графическом режиме.

Использование текстового режима обычно не вызывает затруднений. Программы выводят текстовые строки на экран консоли, обращаясь к системным функциям ОС или к функциям базовой системы ввода-вывода BIOS. Что же касается графического режима, то его использование приводило к необходимости выполнять в программах прямое обращение к аппаратуре видеоадаптера.

С учетом того обстоятельства, что компьютеры могут быть оснащены видеоадаптерами самого разного типа, создание графических программ MS-DOS, способных работать на любых компьютерах, превращалось в непростую задачу. В самом деле, прежде чем выводить что-то на экран монитора в графическом режиме, программа должна была определить тип видеоадаптера и его возможности, переключить видеоадаптер в нужный видеорежим, а затем выполнять вывод изображения с учетом особенностей этого видеорежима. Всех, кого интересуют подробности программирования видеоадаптеров на уровне аппаратуры, мы адресуем к нашей книге [7], посвященной этому вопросу.

Независимость от аппаратуры

При создании ОС Microsoft Windows компания Microsoft избавила программистов от необходимости учитывать аппаратные особенности видеоадаптеров, переложив эту задачу на драйверы видеоадаптеров. Эти драйверы создаются разработчиками видеоадаптеров и наилучшим образом реализуют возможности аппаратуры.

Что же касается приложений, то для них в составе ОС Microsoft Windows был предусмотрен набор системных функций, реализующих интерфейс графических устройств (Graphics Device Interface, GDI). Применительно к приложениям Microsoft Windows мы рассмотрели этот интерфейс в [8]. Что же касается этой книги, то здесь мы расскажем о работе с усовершенствованным интерфейсом GDI+, доступным приложениям Microsoft.NET Framework.

Интерфейс графических устройств GDI, как это можно предположить из названия, предназначен для взаимодействия приложений Microsoft Windows с графическими устройствами, такими как видеоадаптер, принтер или плоттер.

Когда приложения обращаются к GDI для выполнения операции вывода графического изображения, они работают не с реальными (физическими) устройствами вывода, а с логическими устройствами. Приложения Microsoft Windows не определяют тип видеоадаптера (EGA, VGA, SVGA и т.п.), а работают с логическим видеоадаптером, имеющим феноменальные характеристики: способность отображать практически любой цвет, имеющим огромное разрешение и т. д.

Выполняя запрос приложения, GDI обращается к драйверу соответствующего устройства вывода, работающему, в свою очередь, непосредственно с физическим устройством вывода. В процессе выполнения запроса GDI (или драйвер) учитывает ограниченные возможности видеоадаптера и его аппаратные особенности, делая необходимые приближения.

Например, приложение может указать для цвета линии любой из примерно 16 млн. цветов, однако не всякое устройство обладает таким цветовым разрешением (ограничения на количество одновременно отображаемых цветов присутствуют, например, в карманных компьютерах). В зависимости от типа физического устройства, используемого для вывода, GDI может выбрать для отображения цвет, наиболее соответствующий запрошенному цвету, и допустимый для устройства.

Например, если устройство вывода монохромное, вместо различных цветов могут использоваться градации серого цвета. Поэтому приложение может запросить для вывода любой цвет, но для рисования будет использован только такой, который может использовать данное физическое устройство.

Такая ситуация, когда приложение запрашивает у ОС Microsoft Windows одно, а получает другое, возникает не только при работе с цветом. Приложение может запросить для вывода шрифт, описав его характеристики. Интерфейс GDI подберет для вывода наиболее подходящий (с его точки зрения) шрифт, соответствующий описанию, и предоставит его приложению.

На первый взгляд, этот подход обескураживает, особенно тех программистов, кто имеет опыт создания графических программ для MS-DOS и привык получать от системы точно то, что требуется. Однако такой подход удобен для обеспечения аппаратной независимости.

Составляя программы для MS-DOS, Вы работали с видеоадаптерами, указывая конкретные цвета и загружая в его память конкретные шрифты из отдельных файлов. Поэтому программы MS-DOS были крепко «привязаны» к аппаратуре. Для использования новых возможностей требовалось вносить изменения в программы. Приложения Microsoft Windows способны работать в неизменном виде на любом оборудовании, лишь бы был соответствующий драйвер. Чем лучше используемая аппаратура, чем большими возможностями она обладает, тем ближе будут параметры полученного шрифта и цвета соответствовать запрошенным.

Поэтому даже если сейчас в Вашем распоряжении есть только видеоадаптер с ограниченным количеством отображаемых цветов, при разработке приложений Microsoft Windows Вы можете не ограничивать себя дюжиной цветов. Ваше приложение должно быть сделано так, чтобы оно могло использовать любой цвет. Со временем, когда у Вас появится современный видеоадаптер, окно Вашего приложения засветится всеми цветами радуги, причем для этого не придется вносить никаких изменений в само приложение.

Контекст отображения

С точки зрения приложений, интерфейс GDI состоит из контекста отображения и инструментов, предназначенных для рисования.

Контекст отображения можно сравнить с листом бумаги, на котором приложение рисует то или иное графическое изображение, а также пишет текст. Инструменты для рисования — это перья, кисти (а также шрифты и даже целые графические изображения), с помощью которых создается изображение.

Кроме контекста отображения и инструментов для рисования, приложениям доступны десятки функций программного интерфейса GDI, предназначенные для работы с контекстом отображения и инструментами. Что же касается приложений Microsoft.NET Framework, то они реализуют возможности интерфейса GDI+ с помощью набора соответствующих классов и интерфейсов.

В терминах ОС Microsoft Windows контекст отображения (display context) представляет собой структуру данных, описывающую устройство отображения. В этой структуре хранятся различные характеристики устройства и набор инструментов для рисования, выбранный по умолчанию. Приложение может выбирать в контекст отображения различные инструменты (например, перья различной толщины и цвета, с различными «наконечниками»). Поэтому если Вам надо нарисовать линию красного или зеленого цвета, перед выполнением операции следует выбрать в контекст отображения соответствующее перо.

Заметим, что функции рисования GDI, входящие в программный интерфейс Win32 API, не имеют параметров, указывающих цвет или толщину линии. Такие параметры хранятся в контексте отображения.

Приложение может создать контекст отображения не только для окна приложения, но и для любого другого графического устройства вывода, например, для принтера. В последнем случае оно может рисовать на принтере различные изображения, используя те же функции, что и для рисования в окне приложения.

Можно создать контекст отображения для метафайла. Метафайл — это обычный файл или файл в памяти, в котором хранятся последовательности команд интерфейса GDI. Приложение может выполнять графический вывод в метафайл как в обычное устройство вывода, а затем «проигрывать» метафайл на реальном устройстве вывода.

Контекст устройства в терминах ОС Microsoft Windows выступает в роли связующего звена между приложением и драйвером устройства (рис. 10-1) и представляет собой структуру данных размером примерно 800 байт. Эта структура данных содержит информацию о том, как нужно выполнять операции вывода на данном устройстве (цвет и толщину линии, тип системы координат и т. д.).

Рис. 10-1. Вывод данных через контекст устройства

Если приложение получает или создает контекст для устройства отображения, такой контекст называется контекстом отображения (display context). Поэтому когда, например, приложение получает контекст для отображения в одном из своих окон, такой контекст называется контекстом отображения. Если же ему требуется выполнять операцию вывода для устройства (для принтера или для экрана дисплея), приложение должно получить или создать контекст устройства (device context).

Следует понимать, что контексты устройства и отображения содержат описания одних и тех же характеристик и имеют одинаковую структуру. Название контекста определяется только тем, относится ли контекст к окну отображения или устройству вывода.

Класс Graphics

Концепция графического интерфейса GDI+ несколько отличается от концепции «классического» графического интерфейса GDI, с которым привыкли иметь дело разработчики приложений Microsoft Windows. Те из Вас, кто создавал приложения Java с графическим интерфейсом на базе классов Abstract Window Toolkit (AWT), найдут, что эти классы имеют много общего с классами GDI+.

Прежде всего, это касается класса Graphics, реализующего в себе как свойства контекста отображения, так и инструменты, предназначенные для рисования в этом контексте.

Для того чтобы приложение могло что-нибудь нарисовать в окне, оно должно, прежде всего, получить или создать для этого окна объект класса Graphics. Далее, пользуясь свойствами и методами этого объекта, приложение может рисовать в окне различные фигуры или текстовые строки.

Приложение GraphicsApp

Проще всего объяснить назначение и принципы использования класса Graphics на конкретном примере. Давайте создадим приложение GraphicsApp, в окне которого можно рисовать мышью (рис. 10-2).

Рис. 10-2. Рисунок в окне приложения GraphicsApp

Создайте проект приложения GraphicsApp при помощи мастера проектов, а затем установите белый цвет фона для формы этого приложения Form1. Изменить цвет фона можно, отредактировав свойство BackColor.

Отслеживание состояния клавиш мыши

Нам нужно сделать так, чтобы пользователь мог рисовать в окне при нажатой левой клавише мыши. Поэтому нам придется отслеживать в нашем приложении события, связанные с нажатием и отжатием этой клавиши. Кроме того, необходимо отслеживать перемещения курсора мыши.

Текущее состояние мыши будет храниться в поле doDraw типа bool. Вам нужно добавить это поле в класс Form1, проинициализировав его следующим образом:

bool doDraw = false;

Создайте два обработчика событий MouseDown и MouseUp для формы Form1:

private void Form1_MouseDown(object sender,
System.Windows.Forms.MouseEventArgs e)
{
doDraw = true;
}

private void Form1_MouseUp(object sender,
System.Windows.Forms.MouseEventArgs e)
{
doDraw = false;
}

Чтобы создать эти обработчики событий, откройте окно визуального проектирования формы, а затем на вкладке событий щелкните дважды события MouseDown и MouseUp. Мы показали это окно на рис. 10-3, добавив обработчик события MouseMove, необходимый для отслеживания перемещений мыши.

Рис. 10-3. Добавление обработчиков событий

Когда пользователь нажимает левую клавишу мыши, управление передается обработчику событий Form1_MouseDown. Этот обработчик записывает в поле doDraw значение true, отмечая таким способом тот факт, что пользователь приступил к процедуре рисования.

Нарисовав линию, пользователь отпускает левую клавишу мыши. При этом управление передается обработчику событий Form1_MouseUp, записывающему в поле doDraw значение false. Это означает завершение процедуры рисования.

Отслеживание перемещения курсора мыши

Для того чтобы наделить наше приложение возможностью рисования, добавьте обработчик события Form1_MouseMove:

private void Form1_MouseMove(object sender,
System.Windows.Forms.MouseEventArgs e)
{
if(doDraw)
{
Graphics g = Graphics.FromHwnd(this.Handle);
SolidBrush redBrush = new SolidBrush(Color.Red);
g.FillRectangle(redBrush, e.X, e.Y, 1, 1);
}
}

Этот обработчик будет получать управление при всяком перемещении курсора мыши, причем свойства e.X и e.Y будут содержать новые координаты курсора.

Мы воспользуемся этим обстоятельством, нарисовав в месте нового расположения курсора квадрат, с шириной стороны в один пиксел. На экране такой квадрат будет выглядеть как точка. Рисование должно выполняться только в том случае, если в поле doDraw хранится значение true.

Идентификатор окна Handle и объект Graphics

Как мы уже говорили, прежде чем мы сможем что-нибудь нарисовать в окне нашего приложения, мы должны получить для этого окна объект класса Graphics. В случае приложения GraphicsApp нам нужно получить такой объект для окна формы Form1.

Как это сделать?

Те из Вас, кто создавал приложения для ОС Microsoft Windows, знают, что каждое окно имеет свой идентификатор (handle). Зная идентификатор окна, можно легко получить связанный с этим окном контекст отображения.

Приложения Microsoft.NET Framework могут получить идентификатор формы или любого другого элемента управления при помощи свойства Handle. В частности, наше приложение получает идентификатор окна формы Form1 с помощью свойства this.Handle.

Зная идентификатор окна, с помощью метода Graphics.FromHwnd нетрудно получить нужный нам объект класса Graphics:

Graphics g = Graphics.FromHwnd(this.Handle);

Позже Вы узнаете и о других способах получения этого объекта.

Кисть для рисования

Для того чтобы рисовать, художнику нужна кисть. Программист, создающий приложение GDI+, тоже нуждается в инструментах для рисования. Мы создадим кисть как объект класса SolidBrush:

SolidBrush redBrush = new SolidBrush(Color.Red);

С помощью этой кисти можно рисовать замкнутые геометрические фигуры, закрашенные заданным цветом. Через единственный параметр мы передаем конструктору класса SolidBrush цвет кисти Color.Red. Таким образом, мы будем рисовать кистью красного цвета.

Позже мы познакомимся с перьями класса Pen, а также с другими кистями.

Рисование точки

В классе Graphics имеется множество различных методов, предназначенных для рисования самых разных геометрических фигур, таких как линии, прямоугольники, овалы и окружности, многоугольники, кривые Безье и т.д.

Но вот чего в этом классе нет, так это метода, с помощью которого можно было бы нарисовать одну единственную точку. Заметим, однако, что вместо точки мы можем нарисовать закрашенный квадрат с шириной стороны, равным 1 пикселу. Эта задача выполняется при помощи метода FillRectangle:

g.FillRectangle(redBrush, e.X, e.Y, 1, 1);

Обратите внимание на то, что метод FillRectangle вызывается для объекта g класса Graphics, созданного нами для окна формы Form1. Поэтому квадрат будет нарисован в окне этой формы.

В качестве первого параметра методу FillRectangle передается кисть redBrush, которую нужно использовать для рисования. Кисть нужна и для других методов класса Graphics, предназначенных для рисования геометрических фигур.

Второй и третий параметры метода FillRectangle задают координаты, в которых будет нарисован квадрат.

Начало системы координат при этом находится в левом верхнем углу окна, для которого был получен объект Graphics. В нашем случае это левый верхний угол внутренней области окна формы Form1. Ось X в этой системе координат, принятой по умолчанию, направлена слева направо, а ось Y — сверху вниз (рис. 10-4).

Рис. 10-4. Система координат по умолчанию

И, наконец, последние два параметра метода FillRectangle задают, соответственно, ширину и высоту прямоугольника.

В процессе перемещения мыши, при нажатой левой клавише, происходит многократный вызов обработчика событий Form1_MouseMove. Как результат, в окне нашего приложения появляется рисунок, состоящий из отдельных точек (рис. 10-2).

Рисование в окне элемента управления

В приложении GraphicsApp мы получили контекст отображения (в виде объекта класса Graphics) для всего окна формы Form1. Однако формы реальных приложений создаются с использованием различных элементов управления, о которых мы рассказывали в предыдущих главах нашей книги. Что же касается непосредственного рисования, то оно чаще всего выполняется не во всем окне приложения, а только в его некоторой части.

На рис. 10-5 мы показали главное окно приложения GraphicsApp1, внутри которого находится элемент управления класса Panel.

Рис. 10-5. Рисование в окне элемента управления Panel

С помощью мыши пользователь может рисовать внутри окна панели Panel, однако остальная часть главного окна приложения для рисования недоступна.

Создайте проект приложения GraphicsApp1 и перетащите из панели Toolbox системы Microsoft Visual Studio в форму Form1 значок элемента управления Panel.

Далее создайте в классе Form1 поле doDraw и обработчики событий, создаваемых мышью. Обработчики должны создаваться для объекта Panel, а не для формы Form1, как это было в предыдущем приложении:

bool doDraw = false;

private void panel1_MouseDown(object sender,
System.Windows.Forms.MouseEventArgs e)
{
doDraw = true;
}

private void panel1_MouseUp(object sender,
System.Windows.Forms.MouseEventArgs e)
{
doDraw = false;
}

private void panel1_MouseMove(object sender,
System.Windows.Forms.MouseEventArgs e)
{
if(doDraw)
{
Graphics g = Graphics.FromHwnd(panel1.Handle);
SolidBrush redBrush = new SolidBrush(Color.Red);
g.FillEllipse(redBrush, e.X, e.Y, 10, 10);
}
}

Этот код почти аналогичен коду, который мы использовали в предыдущем приложении GraphicsApp, однако в обработчиках событий имеются важные отличия.

Прежде всего, мы создали обработчики событий для панели panel1, а не для формы Form1. В результате они будут получать управление только в том случае, когда пользователь щелкает левую кнопку мыши и перемещает ее курсор внутри панели.

Второе важное отличие в методе panel1_MouseMove. Этот метод получает контекст отображения не для всего окна формы, а только для окна панели panel1. С этой целью он передает методу Graphics.FromHwnd идентификатор окна панели, извлеченный из свойства panel1.Handle:

Graphics g = Graphics.FromHwnd(panel1.Handle);

В результате последующая операция рисования будет выполнена в системе координат, связанной с окном панели, а не с окном формы.

Третье отличие от предыдущего приложения не соль существенно. Вместо метода FillRectangle для рисования мы применили метод FillEllipse:

g.FillEllipse(redBrush, e.X, e.Y, 10, 10);

Назначение параметров метода FillEllipse, предназначенного для рисования закрашенных эллипсов, аналогично назначению параметров метода FillRectangle. При этом два последних параметра задают, соответственно, ширину и высоту прямоугольной области, занимаемой эллипсом.

Событие Paint

Проверяя работу приложения GraphicsApp1, описанного в предыдущем разделе этой главы, Вы наверняка заметите одну неприятную особенность — при изменении размеров окна часть нарисованного изображения или все изображение пропадает. Аналогичная неприятность происходит и в том случае, когда окно приложения GraphicsApp1 перекрывается окном другого приложения.






© 2023 :: MyLektsii.ru :: Мои Лекции
Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав.
Копирование текстов разрешено только с указанием индексируемой ссылки на источник.