лекция. Зиборов. Справочник для опытных и как пособие для начинающих программистов. Компактдиск содержит исходные коды примеров из книги
Скачать 7.39 Mb.
|
alt="Двойной щелчок возвращает в исходный размер" onclick="this.src='poryv.png’;this.height=200;this.width=200" ondblclick="this.src='poryv.png’;this.height=100;this.width=100" /> html> На самом деле вводить придется лишь разметку между тегами <body> и body>. Остальной код управляющая среда сгенерировала сама. В приведенной разметке в качестве атрибутов тега <img>, размечающего изображение, записаны две обработки событий onclick (щелчок мышью на изображении) и ondbiclick (двойной щелчок) на JavaScript. Теперь для просмотра этой страницы в браузере мы можем нажать клавишу <F5> или непосредственно открыть файл HTMLPage1.htm, например, в Internet Explorer. При этом мы увидим следующее (рис. 14.11). Рис. 14.11. Щелчок мышью увеличивает изображение Теперь решим эту же задачу программированием на Visual С# 2010. Для этого добавим в текущий проект новую Web-форму. В пункте меню Project выполним соманду Add New Item и в появившемся окне выберем шаблон Web Form. На вкладке конструктора формы перетащим из панели Tollbox (эту панель можно вызвать, например, используя комбинацию клавиш <Ctrl>+<Alt>+<X>) из раздела Standard элемент управления изображения Image, а на вкладке программного кода VebForm1.aspx.cs напишем текст, представленный в листинге 14.5. Листинг 14.5. Увеличение изображения в Web-форме (Visual С# 2010-код) // На странице имеем изображение - файл poryv.png, при щелчке мышью на нем // изображение увеличивается вдвое без перезагрузки Web-страницы using System; // Другие директивы using удалены, поскольку они не используются // в данной программе namespace Web_изoбpaжeниe { public partial class WebForm1 : Systern.Web.UI.Page { protected void Page_Load(object sender, EventArgs e) { Page.Title = "Щелкнуть мышью для увеличения"; // Указываем виртуальный путь к файлу изображения Image1.ImageUrl = Request.ApplicationPath + "poryv.png"; // Получаем URL, который используется в браузере string адрес = ResolveClientUrl(Image1.ImageUrl); // Добавляем атрибут Alt Image1.AlternateText = "Двойной щелчок возвращает в исходный размер"; // Добавляем два события JavaScript Image1.Attributes.Add("onclick", "this.src="' + адрес + "';this.height=200;this.width=200"); Image1.Attributes.Add("ondbiclick", "this.src="' + адрес + "’;this.height=100;this.width=100"); } } } Как видно из программного кода, кроме двух очевидных свойств ImageUrl и AlternateText объекта Image1 свойство Attributes добавляет объекту Image1 два события JavaScript. Нам пришлось включать таким образом события JavaScript, поскольку объект Image1 не имеет событий мыши. Поставим другую, более интересную задачу. На Web-странице имеем изображение, например, мужчины. Это изображение используем для ссылки на другую Web-страницу, скажем, на WebForm1.aspx. Причем при наведении на него указатетеля мыши происходит смена изображения на изображение женщины. Для решения этой задачи добавим в текущий проект еще одну HTML-страницу на вкладке разметки HTMLPage2.htm напишем текст, приведенный в листинге 14.6. Листинг 14.6. Смена изображения в Web-форме (HTML-код) "http://www.w3.оrg/TR/xhtml1/DTD/xhtml1-transitional.dtd"> alt="Щелкните, чтобы перейти на HTMLPage1.htm" src="m.jpg" border="0" /> Здесь тег <a> обеспечивает гиперссылку на другую Web-страницу HTMLPage1.htm, причем в качестве гиперссылки используется изображение m.jpg (изображение мужчины). Это изображение меняется на изображение женщины (файл g.jpg) при наведении на него указателя мыши (JavaScript-событие onmouseover) и возвращается в исходное, когда указатель мыши покидает элемент (событие onmouseout). Установим в качестве стартовой страницы проекта файл HTMLPage2.htm. Для этого в контекстном меню окна Solution Explorer для этого файла укажем Set As Start Page. Внешний вид данной Web-страницы в браузере показан на рис. 14.12. Рис. 14.12. Смена изображения при наведении указателя мыши Для решения этой же задачи с помощью Visual Studio 2010 в текущий проект дозаявим новую Web-форму — WebForm2.aspx. В конструкторе формы из раздела Standard панели Tollbox добавим элемент управления ImageButton, отображающий изображение и отвечающий на нажатия на нем кнопки мыши. На вкладке программного кода этой формы напишем текст программы, приведенной в листинге 14.7. Листинг 14.7. Смена изображения в Web-форме (Visual С# 2010-код) //На Web-странице имеем изображение, например мужчины, - файл m.jpg. Это изображение используем для ссылки // на другую Web-страницу, например; на WebForm1.aspx. Причем при наведении на него указателя мыши происходит // смена изображения на изображение женщины - файл g.jpg using System; //Другие директивы using удалены, поскольку они не используются вданной программе namespace Web_изoбpaжeниe { public partial class WebForm2 : System.Web.UI.Page { protected void Page_Load(object sender, EventArgs e) { // Элемент управления ImageButton отображает изображение и отвечает за нажатия на нем указателя мыши ImageButton1.PostBackUrl = "WebForml.aspx"; // Указываем виртуальный путь к файлу изображения ImageButton1.ImageUrl = Request.ApplicationPath + "m.jpg"; // Задаем альтернативный текст ImageButton1.AlternateText = "Щелкните, чтобы перейти на WebForml.aspx"; // Добавляем два события JavaScript ImageButton1.Attributes.Add("onmouseover", "this.src='g.jpg’"); ImageButton1.Attributes.Add("onmouseout", "this.src='m.jpg’")! } } } Как видно из программного кода, мы использовали те же приемы, что и в предыдущей задаче. Убедиться в работоспособности Web-страниц, рассмотренных в данном разделе, можно, открыв соответствующее решение в папке Web_ изображение. Пример 106. Формирование изображения методами класса Graphics и вывод его в Web-форму При создании Web-страниц часто бывает удобно сначала создать изображение, что-либо на нем нарисовать, например, график какой-нибудь зависимости, актуальной именно в момент загрузки страницы, затем это изображение записать на диск сервера и вывести его клиенту в обозреватель. Таким графиком может быть, скажем, график статистики посещений сайта по месяцам, по неделям, по дням. Задача, решаемая в данном разделе, состоит в следующем. Во время загрузки Web-страницы создать изображение, методами класса Graphics вывести на это изображение текстовую строку, представляющую текущую дату. С целью демонстрации возможностей методов Graphics развернуть данную строку на некоторые угол относительно горизонта. Далее сохранить рисунок в текущем каталоге сервера и вывести его на Web-страницу. Для решения этой задачи запустим Visual Studio 2010, закажем новый проект-шаблона Empty ASP.NET Web Application. Добавим Web-форму, для этого в пункте меню Project выберем команду Add New Item, в появившемся окне укажем шаблон Web Form и добавим его к нашему проекту. На вкладке дизайнера формы WebForm1.aspx добавим элемент управления Image. А на вкладке Web. Forml.aspx.cs введем программный код, представленный в листинге 14.8. Листинг 14.8. Формирование изображения и вывод его в Web-форму // Web-страница формирует файл изображения методами класса Graphics. На изображение выводится текстовая // строка, наклоненная к горизонту на 356 градусов (наклон вверх). Далее этот файл изображения отображается в форме using System; // Добавляем данное пространство имен для сокращения программного кода: using System.Drawing; // Другие директивы using удалены, поскольку они не используются в данной программе namespace ТекстНаклWeb { public partial class WebForm1 : System.Web.UI.Page { protected void Page_Load(object sender, EventArgs e) { // Создаем точечное изображение размером 215 х 35 точек с глубиной цвета 24 Bitmap Рисунок = new Bitmap(215, 35, System.Drawing.Imaging.PixelFormat.Format24bppRgb); // Создаем новый объект класса Graphics из изображения РАСТР Graphics Графика = Graphics.Fromlmage(Рисунок); // Теперь становятся доступными методы класса Graphics! // Заливка поверхности указанным цветом Графика.Clear(Color.AliceBlue); // или Графика.Clear(ColorTranslator.FromHtml("#ECECFF")); // Вывод в строку полной даты: string Дата = string.Format("Сегодня {0:D}", DateTime.Now); // Разворачиваем мир на 356 градусов по часовой стрелке Графика.RotateTrans form(356.OF); // Выводим на изображение текстовую строку Дата, // х=5, у=15 - координаты левого верхнего угла строки Графика.Drawstring(Дата, new Font("Times New Roman", 14, FontStyle.Regular), Brushes.Red, 5, 15); // Определяем физический путь файла для текущего Web-узла, // сохраняем изображение в файле risunok.jpg каталога Web-узла Рисунок.Save(Request.PhysicalApplicationPath + "risunok.jpg", System. Drawing. Imaging. ImageFormat. Jpeg) ; // Возможность вывода изображения в исходящий поток ответа HTTP: // Рисунок.Save(Response.OutputStream, System.Drawing. // Imaging.ImageFormat.Jpeg); // Цвет и ширина рамки рисунка: Image1.BorderColor = Color.Red; Imagel.BorderWidth = 2; // Указываем виртуальный путь к файлу изображения Image1.ImageUrl = Request.ApplicationPath + "risunok.jpg"; // Освобождение ресурсов Рисунок.Dispose(); Графика.Dispose(); } } } Рис. 14.13. Вывод в форму изображения, сформированного программно Как видно из программного кода, при загрузке страницы создаем точечное изображение указанного размера, формат Format24bppRgb указывает, что отводится 24 бита на точку: по 8 бит на красный, зеленый и синий каналы. Данное изображение позволяет создать новый объект класса Graphics методом Fromlmage. Теперь разворачиваем поверхность рисования на 356° методом RotateTransform и выводим на поверхность рисования текстовую строку с текущей датой. Задавая физический путь файла изображения, методом Save сохраняем его в каталоге Web-узла в формате JPEG. В комментарии приведена возможность вывода рисунка в исходящий поток ответа HTTP, при этом изображение не будет записываться на диск, но пользователь будет видеть его в браузере. Далее элементу управления Image1 указываем виртуальный путь к файлу изображения. Замечу, что физический путь не должен отправляться клиенту, поскольку он может использоваться злоумышлениками для получения сведений о приложении. На рис. 14.13 показан фрагмент работы программы. Убедиться в работоспособности Web-страницы, рассмотренной в данном примере, можно, открыв соответствующее решение в папке TeкстHaклWeb. Пример 107. Гостевая книга Допустим, на своем сайте вы обсуждаете какую-либо тему и хотите, чтобы посетители сайта оставляли свои мнения, впечатления, пожелания, замечания, адресованные владельцу или будущим посетителям. Причем так, чтобы сообщения, написанные посетителями, были бы тут же отображены и сохранены, и тем самым стимулировали желание новых посетителей написать свое сообщение. Такое программное обеспечение называют гостевой книгой сайта. В гостевой книге следует предусмотреть поля для ввода имени посетителя, адреса его электронной почты, а также поле для непосредственного сообщения. Все записи, оставленные посетителями сайта, будем сохранять в текстовом файле kniga.txt на винчестере сервера, предоставляющего Web-хостинг. Впрочем, вместо текстового файла можно воспользоваться какой-либо базой данных. Рис. 14.14. Размещение элементов управления в конструкторе формы Для программирования гостевой книги запустим Visual Studio 2010, в окне New Project выберем шаблон Empty ASP.NET Web Application, в поле Name укажем имя нового решения ГостеваяКнига и щелкнем на кнопке ОК. Теперь добавим к текущему проекту Web-форму. Для этого в пункте меню Project выберем команду Аdd New Item, в появившемся окне укажем шаблон Web Form и щелкнем на кнопке Add. На вкладке конструктора формы в панели элементов раздела Standard нам понадобятся четыре метки Label, три текстовых поля TextBox, соответственно, для имени пользователя, его электронной почты и сообщения, одна командная кнопка Вutton с надписью "Добавить сообщение"'и сетка данных GridView из раздела Data для отображения всех вводимых записей. Кроме того, возле каждого текстового поля разместим валидатор RequiredFieldValidator (раздел Validation), проверяющий факт заполнения текстовых полей. Правильность заполнения проверять не будем, поскольку в данной ситуации если мы будем слишком "принципиальничать" по поводу вводимых данных, то посетитель потеряет терпение и уйдет на другой ресурс (не наш!). Не забываем, что мы гораздо больше заинтересованы во всех новых сообщениях, чем посетители их написать. С другой стороны (другая крайность), если мы вовсе не будем контролировать заполнения текстовых полей, то у недобросовестного пользователя появится соблазн нажимать кнопку Добавить ообщение без заполнения полей и заполнять таблицу сетки данных пустыми строками, что будет вовсе дискредитацией замысла гостевой книги. В конструкторе формы разместим выбранные элементы управления так, как показано на рис. 14.14. После размещения в конструкторе необходимых элементов управления переходим на вкладку программного кода. Текст программы представлен в листинге 14.9. Листинг 14.9. Гостевая книга //Данная Web-страница приглашает посетителя оставить какие-либо записи, которые могут прочитать другие // посетители страницы. Записи сохраняются в текстовом файле kniga.txt. Записи отображаются на Web-странице // с помощью сетки данных GridView using System; using System.Web.UI.WebControls; // Добавляем эти две директивы для сокращения программного кода: using System.Data; ing System. IO; // Другие директивы using удалены, поскольку они не используются в данной программе namespace ГостеваяКнига { public partial class WebForm1 : System.Web.UI.Page { DataTable Таблица = new DataTable(); StreamReader Читатель; StreamWriter Писатель; protected void Page_Load(object sender, EventArgs e) { Label1.Text = "ВЫ МОЖЕТЕ НАПИСАТЬ КАКОЕ-НИБУДЬ " + "СООБЩЕНИЕ В НАШЕЙ ГОСТЕВОЙ КНИГЕ"; Label2.Text = "Ваше имя:"; Label3.Text = "Ваш E-mail:"; Label4.Text = "Ваше сообщение:"; Button1.Text = "Добавить сообщение"; // Разрешаем многострочие: TextBox3.TextMode = TextBoxMode.MultiLine; // Контролируем обязательность заполнения всех полей: RequiredFieldValidator1.ErrorMessage = "* Следует заполнить это текстовое поле"; RequiredFieldValidator1.ControlToValidate = "TextBox1"; RequiredFieldValidator2.ErrorMessage = "* Следует заполнить это текстовое поле"; RequiredFieldValidator2.ControlToValidate = "TextBox2"; RequiredFieldValidator3.ErrorMessage = "* Следует заполнить это текстовое поле"; RequiredFieldValidator3.ControlToValidate = "TextBox3"; Таблица.Columns.Add("Дата"); Таблица.Columns.Add("Имя"); Таблица.Columns.Add("E-mail"); Таблица.Columns.Add("Сообщение"); GridView1.BorderWidth = Unit.Pixel(2); GridView1.BorderColor = System.Drawing.Color.Gray; // Расстояние между содержимым ячейки и ее границей: GridView1.CellPadding = 3; GridView1.Caption = "Записи гостевой книги"; GridView1.CaptionAlign = TableCaptionAlign.Right; ЗaпoлнитьGridView(); } public void ЗaпoлнитьGridView() { // Эта процедура читает файл kniga.txt (если его нет, то создает), разбивает каждую строку файла на четыре части // (дата, имя, e-mail и сообщение) и заполняет этими частями строки таблицы. Затем записывает эту таблицу в // // сетку данных GridView. // // Открываем файл kniga.txt, а если его нет, то его создаем: var Открыватель = new FileStream(Request.PhysicalApplicationPath +"kniga.txt", FileMode.OpenOrCreate); // Открываем поток для чтения всех записей из файла Читатель = new StreamReader(Открыватель); //В качестве разделителя частей строки файла выбираем Tab, поскольку Tab невозможно ввести в текстовое //поле. После нажатия клавиши <ТаЬ> происходит переход в следующее текстовое поле char[] Разделитель = new char[] { '\t' }; // - массив string[] Массив_частей_строки; while (Читатель.EndOfStream == false) { string Одна_строка = Читатель.ReadLine(); // Функция Split делит строку на четыре части и присваивает каждую часть элементам массива Массив_частей_строки = Одна_строка.Split(Разделитель); // Загружаем, т. е. заполняем одну строку таблицы Таблица.LoadDataRow(Maccив_частей_строки, true); } GridView1.DataSource = Таблица; // Обновление сетки данных: GridView1.DataBind(); Таблица.Clear(); Читатель.Close(); Открыватель.Close(); } protected void Button1_Click(object sender, EventArgs e) { // Щелчок на кнопке "Добавить". // Открываем поток для добавления данных в конец файла Писатель = new StreamWriter(Request.PhysicalApplicationPath + "kniga.txt", true); // true означает разрешить добавление строк в файл. // Записываем в файл новое сообщение, между полями - символ табуляции Писатель.WriteLine("{0:D} \t{1} \t{2} \t{3}", DateTime.Now, TextBox1.Text, TextBox2.Text, TextBox3.Text); // Очищаем поля и закрываем поток TextBox1.Text = string.Empty; TextBox2.Text = string.Empty; TextBox3.Text = string.Empty; Писатель.Close(); ЗaпoлнитьGridView(); } } } Как видно из программного кода, вначале создаем таблицу данных класса DataTable и два потока данных для чтения и записи файлов так, чтобы они были видны из всех процедур класса. При обработке события загрузки формы организуем контроль обязательности заполнения текстовых полей формы, задаем "шапку" таблицы (т. е. названия колонок таблицы), а последней командой вызываем процедуру ЗаполнитьGridView. Эта процедура в цикле while читает строки текстового файла kniga.txt и заполняет ими строки таблицы данных методом LoadDataRow(). Далее заполненную таблицу данных указываем в качестве источника данных (DataSource) для сетки данных GridView1, предназначенной для визуализации (отображения) таблицы форме. После этого важно очистить таблицу данных методом Сlear (). Рис. 14.15. Интерфейс гостевой книги При обработке события "щелчок на кнопке" открываем поток данных Писатель длядобавления данных в конец файла kniga.txt и записываем в этот файл текстовую строку, содержащую текущую дату, имя посетителя Web-страницы, его e-mail и непосредственно его сообщение. Причем в качестве разделителя между этими текстовыми строками мы используем управляющий символ Tab, поскольку его невозможно ввести в текстовое поле, т. к. после нажатия клавиши <ТаЬ> предусмотрен переход в следующее текстовое поле. После закрытия потока данных Писатель вызываем процедуру 3aполнитьGridView, которая как бы начинает опять "с чистого листа": снова открывает поток для чтения файла и опять заполняет таблицу данных, которая, как мы помним, была очищена от предыдущих данных. Именно поэтому строки (команды) процедуры 3aполнитьGridView были оформлены в отдельную процедуру, поскольку заполнение таблицы и ее визуализация происходят дважды: один раз при загрузке формы, а другой при добавлении новой записи. Фрагмент работы гостевой книги представлен на рис. 14.15. Убедиться в работоспособности данной программы можно, открыв соответствующее решение в папке ГостеваяКнига. Пример 108. Программирование капча Слово Capcha —- это английская аббревиатура выражения "Completely Automated Public Turing test to tell Computers and Humans Apart", которое можно перевести, как "полностью автоматический публичный тест Тьюринга для различия компьютеров и людей". Другими словами, это компьютерное тестирование, используемое в каком-либо пользовательском интерфейсе для того, чтобы определить, кем является пользователь системы: человеком или компьютером. Процедура капча чаще всего используется при необходимости предотвратить вредоносное использование интернет-сервисов ботами (программами-роботами). В частности для предотвращения автоматических (без участия человека) отправок сообщений, регистрации, скачивании файлов, массовых рассылок, мошенничества, сетевых атак и т. п. Как вы понимаете, бот (или робот, или интернет-робот) — это специальная программа, выполняющая автоматически какие-либо действия через те же интерфейсы, что и обычный пользователь-человек. Для противодействия таким автоматическим действиям интернет-роботов сейчас довольно-таки широко применяется обсуждаемая в данном разделе капча. Основной замысел тестирования с помощью капча в том, чтобы предложить пользователю такую задачу, которую очень легко тот может решить, но которую несоизмеримо сложно предоставить для решения компьютеру. В основном это задачи на распознавание символов. Это весьма актуальная задача; автор заметил на сайте оффшорного программирования www.rentacoder.com (это сайт-посредник между работодателем и программистом), что имеет место спрос на процедуру капча. Итак, для решения этой задачи запустим Visual Studio 2010, закажем новый проект из шаблона Empty ASP.NET Web Application, укажем в поле Name имя Капча и щелкнем на кнопке ОК. К текущему проекту добавим Web-форму. Для этого в меню Project выберем команду Add New Item и в появившемся окне дважды щелкнем на шаблоне Web Form. Теперь в конструкторе формы на вкладке WebForm1.aspx из раздела Standard панели Toolbox перенесем в форму элементы управления: изображение Image, текстовое поле TextBox, командную кнопку Button, метку Label и гиперссылку HyperLink. Расположим их в форме, как показано на рис. 14.16. На вкладке файла программной поддержки WebForm1.aspx.cs введем код, дставленный в листинге 14.10. Листинг 14.10. Программирование капча //Программа тестирует пользователя на "человечность", предлагает распознать искаженную строку символов using System; using System.Drawing; using System. Drawing. Imaging; // Другие директивы using удалены, поскольку они не используются в данной программе namespace Капча { public partial class WebForm1 : System.Web.UI.Page { protected void Page_Load(object sender, EventArgs e) { Page.Title = "Капча"; // При повторной отправке данных оставляем все как есть: if (Page.IsPostBack == true) return; // Получить сгенерированный рисунок: Bitmap РАСТР = Генерировать Рисунок(); // Сохранить сгенерированный рисунок: // bmp.Save(Response.OutputStream, ImageFormat.Jpeg); РАСТР.Save(Request.PhysicalApplicationPath + "risunok.jpg", ImageFormat.Jpeg); РАСТР.Dispose(); // Указываем виртуальный путь к файлу изображения: Image1.ImageUrl = Request.ApplicationPath + "risunok.jpg"; Label1.Text = "Введите символы, изображенные на картинке"; Button1.Text = "Регистрация"; TextBox1.Focus(); TextBox1.Font.Size = 18; HyperLink1.Text = "Обновить картинку"; // При обновлении картинки отправляем на загрузку самой себя: HyperLink1.NavigateUrl = "WebForm1.aspx"; } private Bitmap ГенерироватьРисунок() { // Эта функция генерирует рисунок и возвращает его в формате Bitmap Color ЦветПера = Color.Black; Brush ЦветФона = Brushes.White, ЦветРисования = Brushes.Black; // Генератор псевдослучайных чисел: Random Случай = new Random(); // Выбор цвета случайным образом из двух вариантов: ВыборЦвета(Случай, ref ЦветПера, ref ЦветФона, ref ЦветРисования); // Размеры изображения в точках: int Width = 136; int Height = 40; // Создаем точечный рисунок: Bitmap РАСТР = new Bitmap(Width, Height, PixelFormat.Format32bppArgb); // Создаем экземпляр класса Graphics из точечного рисунка: Graphics Графика = Graphics.Fromlmage(РАСТР); // Рисуем прямоугольник, заполненный цветом фона: Графика.FillRectangle(ЦветФона, 0, 0, Width, Height); // Искажаем рисунок сеткой линий и случайно разбросанными точками: Сетка_и_точки(Графика, ЦветПера, ЦветРисования, Случай, Width, Height); // В прямоугольнике рисуем шесть случайно выбранных символов: РисованиеСимволов(Графика, ЦветРисования); Графика.Dispose(); return РАСТР; } private void ВыборЦвета(Random Случай, ref Color ЦветПера, ref Brush ЦветФона, ref Brush ЦветРисования) { // Выбираем случайным образом "комплект" цветов из двух вариантов //и передаем их как параметры по -ссылке reference int R = Случай.Next(100); // Определяем, является ли случайное число R четным или нечетным: if (Четное(R) == true) { // Первый вариант: ЦветПера = Color.Black; ЦветФона = Brushes.White; ЦветРисования = Brushes.Black; } else // Если R - нечетно: { // Второй вариант: ЦветПера = Color.White; ЦветФона = Brushes.Black; ЦветРисования = Brushes.White; } } private bool Четное(int k) { // Функция определяет, число К является четным или нечетным: if (К % 2 == 0) return true; // Оператор % возвращает целочисленный остаток от деления return false; } private void Сетка_и_точки(Graphics Графика, Color ЦветПера, Brush ЦветРисования, Random Случай, int Width, int Height) { // Искажаем рисунок сеткой линий и случайно разбросанными точками. // Создание пера для рисования им фигур: Pen Перо = new Pen (ЦветПера, 1F); // Рисование сетки линий на рисунке: for (int х = 0; х <= Height; х += 15) Графика.DrawLine(Перо, 0, х, Width, х); for (int х = 0; х <= Width; х += 15) Графика.DrawLine(Перо, х, 0, х, Height); // Рисование случайно расположенных точек, их плотность равна одной точке на 10 квадратных пикселов: int Кол_во_точек = (int)Math.Round((decimal)(Width * Height / 10), 0); for (int i = 0; i < Кол_во_точек; i++) { int x1 = Случай.Next(Width); int y1 = Случай.Next(Height); // Ширина эллипса - 1 пиксел, а его высота - 2 пиксела: Графика.FillEllipse(ЦветРисования, x1, y1, 1, 2); } } private void РисованиеСимволов(Graphics Графика, Brush Цвет_Рис) { //В прямоугольнике рисуем шесть случайно выбранных символов. // Задаем строку из шести случайно выбранных символов: string СтрокаШести = СлучайнаяСтрока(); // Запоминаем эту строку на время текущей сессии: Page. Session .Add ("Символы", СтрокаШести); // Копируем символы из строки в массив символов: char[] МассивШести = СтрокаШести.ToCharArray(); // Задаем два шрифта: один обычный, а другой - наклонный (Italic): Font Шрифт1 = new Font("Arial", 20); // 20 - это размер самой широкой буквы Font Шрифт2 = new Font(“Arial", 20, FontStyle.Italic); // Размер массива равен шести: int len = СтрокаШести.Length; // Цикл по каждой букве (их шесть): for (int i = 0; i < len; i++) { // Point - координаты левого верхнего угла прямоугольника: Rectangle Прямоугольник = new Rectangle(new Point(i * 22, 2), new Size(24, 36)); // Размер прямямоугольника - Size(24 x 36) string ОдинСимвол = МассивШести[i].ToString(); // Рисую один символ из тех самых шести символов: if (Четное(i) == true) Графика .Drawstring (ОдинСимвол, Шрифт1, Цвет_Рис, Прямоугольник); Else Графика.Drawstring(ОдинСимвол, Шрифт2, Цвет_Рис, Прямоугольник); } Шрифт1.Dispose(); Шрифт2.Dispose(); } private string СлучайнаяСтрока() { // Эта функция возвращает строку с шестью случайно выбранными // символами из набора "СтрокаСимволов": string СтрокаСимволов = "23456789ERYUPADFHKZXVBNM"; // В этом наборе нет ни нуля, ни буквы "0"("Q"), ни единицы, ни буквы "I", чтобы их не путать char[] МассивСимволов = СтрокаСимволов.ToCharArray(); // Генератор псевдослучайных чисел: Random Случай = new Random(); // SS - строка, сформированная случайным образом: string SS = string.Empty; // Цикл от 0 до 5 заполняет строку SS шестью случайно выбранными символами из массива "МассивСимволов": for (int i = 0; i <= 5; i++) SS = SS + МассивСимволов[Случай.Next(МассивСимволов.Length)]; return SS; } protected void Buttonl_Click(object sender, EventArgs e) { // Вспоминаем строку из шести случайно выбранных символов, записанную в текущую сессию: string СтрокаШести = (Page.Session["Символы"]).ToString(); // Удаление всех пробелов и невидимых управляющих символов: TextBox1.Text = TextBox1.Text.Trim(); if (TextBox1.Text == СтрокаШести) { Label1.Text = "Верно"; Label1.ForeColor = Color.Black; } Else { Label1.Text = "Попробуйте еще раз"; Label1.ForeColor = Color.Red; } } } } Как видно из программного кода, в процедуре загрузки страницы Page_Load происходит вызов ключевой функции Генерировать Рисунок только при первичной загрузке страницы, т. е. когда IsPostBack = false. Эта функция возвращает растровый рисунок в формате Bitmap, который мы сохраняем (Save) на сервере. Далее для элемента управления Image1 указываем виртуальный путь к сохраненному рисунку. Функция Генерировать Рисунок создает объект класса Graphics из точечного рисунка формата Bitmap, с помощью функции ВыборЦвета выбирает случайным образом из двух вариантов цвет фона и цвет рисования. Затем рисует заполненный цветом фона прямоугольник, который мы искажаем сеткой линий и случайно разбросанными точками, и выводит в этот прямоугольник шесть случайно выбранных символов, которые подлежат распознаванию пользователем. Как видно, программа имеет иерархическую структуру с большой глубиной вложенности. Заслуживает обсуждения функция СлучайнаяСтрока. В ней мы задaем набор символов в строковой переменной СтрокаСимволов. В этом наборе отсутствуют цифра "1", буквы "I", "J", "Т", поскольку их начертание похоже, а это может затруднять пользователю их распознавание. По этой же причине в наборе отсутст вуют цифра "0", буквы "О", "Q", "G", "С". Данную строку символов с помощью функции ToCharArray преобразуем в массив символов. Пользуясь этим массивом, в цикле легко заполнить строку шестью случайно выбранными символами. Рис. 14.16. Тестирование с помощью капча Теперь нам требуется запомнить строку с шестью выбранными символами, чтобы ее сравнить со строкой тестового поля TextBox1, которое заполнит пользователь. Воспользоваться внешними переменными мы не можем, поскольку они стираются из оперативной памяти при перезагрузке страницы. Для этой цели воспользуемся объектом Page.Session. В технологии ASP.NET каждое Web-приложение при обращении к нему пользователя (клиента) создает объект Page.Session, этот объект называют сессией или сеансом пользователя. Объект Session содержит в себе методы для создания коллекции данных. Причем созданная коллекция данных на одной странице Web-приложения оказывается доступной на любой другой странице данного приложения. Даже если пользователь перешел на другое Web-приложение (на другой Web-узел), а затем вернулся в текущее приложение, то исходная коллекция данных сессии будет сохранена. Она будет сохранена до тех пор, пока пользователь не закрыл свой Web-браузер. Однако время жизни (лимит времени) сессии все же ограничено параметром Timeout. По умолчанию время жизни равно 20 минутам, его можно регулировать в файле программной поддержки свойством объекта Session.Timeout или прямо в тексте программы. Таким образом, в процедуре РисованиеСимволов запоминаем строку с шестью выбранными символами, используя объект Page.session. При щелчке пользователем на кнопке Регистрация читаем строку с шестью выбранными символами из объекта Page.session. Теперь мы можем сравнить ее со строкой символов, полученной от пользователя в текстовом поле TextBox1. Фрагмент работы капча представлен на рис. 14,16. Убедиться в работоспособности данной программы можно, открыв соответствующее решение в папке Капча. Пример 109. Отображение времени в Web-форме с использованием технологии AJAX Мы уже обсуждали вопрос отображения времени в Windows-приложении (см. пример 86 в главе 12). Тогда для того чтобы время обновлялось каждую секунду, нами был использован элемент управления Timer. При обработке события Tick (события, когда прошел заданный интервал времени Interval, равный 1000 миллисекунд, т. е. 1 с) элемента управления Timer в метку Label копировалось новое значение времени, при этом изображение формы обновлялось (перерисовывалось). Когда речь вдет о Web-форме, технология ASP.NET предполагает операции обратной отправки данных. Когда пользователь щелкает на кнопке или делает выбор в окне списка с включенной функцией AutoPostBack, серверу отсылается соответствующий запрос, после чего с него обратно клиенту передается целая страница. Если такое обращение к серверу будет происходить каждую секунду, то возрастет объем сетевого трафика и вследствие инерции Сети пользователь будет ощущать дискомфорт. Кроме того, если на этой странице предусмотрено заполнение пользователем полей, то серверу будет отсылаться страница с частично заполненными полями. Решение этой проблемы состоит в использовании технологии AJAX, которая обеспечивает возможность выполнения частичного визуального обновления страницы посредством поддерживаемой ASP.NET AJAX-операции обратной отправки. продемонстрируем возможность технологии AJAX на примере, когда мы имеем метку Label в Web-форме. На эту метку каждую секунду копируем новое время, но обновляем при этом не всю форму, а только метку с помощью технологии AJAX. Решая эту задачу, запустим Visual Studio 2010 и закажем новый проект из шаблона Empty ASP.NET Web Application, укажем имя Name — AjaxTimer. К текущему проекту добавим Web-форму. Для этого в пункте меню Project выберем команду Add New Item и в появившемся окне дважды щелкнем по шаблону Web Form. Далее, попав на вкладку конструктора Web-формы, перетащим в форму из раздела AJAX Extensions панели ToolBox элементы управления ScriptManager, UpdatePanel. Затем на вкладке файла программной поддержки WebForm1.aspx.cs напишем программный код, приведенный в листинге 14.11. Листинг 14.11. Отображение времени в Web-форме // Web-страница демонстрирует время на текстовой метке Labell. На эту метку каждую секунду копируем новое время, //но обновляем при этом не всю форму, а только метку с помощью технологии AJAX using System; // Другие директивы using удалены, поскольку они не используются в данной программе namespace AjaxTimer { public partial class WebForm1 : System.Web.UI.Page { protected void Page_Load(object sender, EventArgs e) { Timer1.Interval = 1000; // 1000 миллисекунд = 1 секунда Label1.Text = "Текущее время: " + DateTime.Now.ToLongTimeString(); } protected void Timer1_Tick(object sender, EventArgs e) { // Обновление содержимого метки каждую секунду: Label1.Text = "Текущее время: " + DateTime.Now.ToLongTimeString(); } } } Как видно из программного кода, при загрузке страницы задаем интервал времени, равный одной секунде. При обработке события Tick — события, когда прошел заданный интервал времени, в метку Label1 копируется новое значение времени. При этом благодаря использованию технологии AJAX обновляется не вся Web-форма, а только те элементы, которые расположены на элементе UpdatePanel. Фрагмент работы программы показан на рис. 14.17. Рис. 14.17. В форме обновляется только AJAX-элемент UpdatePanel Убедиться в работоспособности Web–страницы можно открыв решение AjaxTimer.sln в папке AjaxTimer. |