000151. Запуск другой формы из основной, ListBox, MenuStrip
Last updated
Last updated
Запуск другой формы из основной, ListBox, MenuStrip||wmysterio|wmysterio|wmysterio@yandex.ru|/||Всем осветительный привет! Мы продолжаем изучать формы Windows и сегодня мы будем учится запускать новую форму из окна основной, а также рассмотрим такие элементы, как ListBox и MenuStrip. Начнём с того, что будем создавать обычное меню, которое можно наблюдать в стандартных окнах. Для этого найдите компонент MenuStrip и переместите его в макет программы: По-умолчанию меню выводится сверху, как видно на рисунке выше. Это визуальный редактор меню. В поле "Вводить здесь" нам предлагают ввести имя ячейки каждого пункта нашей навигации. При нажатии на элемент в нас выскакивают дополнительные места для будущих команд: Соответственно всё, что будет написано справа будет горизонтальной навигацией, а что внизу - подпункты выделенной категории. Для начала создадим 3 пункта меню: "Файл", "Команды" и "Справка". В меню файл создадим 2 пункта: "Сохранить HTML" и "Выход": В меню "Команды" добавим только 1 пункт - "История", а в Справку закинем "Об авторе" и "О программе". Наше меню готово, осталось только написать логику этих пунктов. Но прежде всего предлагаю сместить объект кнопка, браузер и ТекстБокс на небольшое расстояние от панели меню. Если это сделать, то получится эффект, когда меню частично закрывает кнопку и поле ввода, что намекает на криворукость программиста Думаю при компиляции без изменений сразу будет видим этот эффект. Ваша задача - подкорректировать элементы макета под более удобный вид. В этом уроке мы рассмотрим выполнение 2-х функций - "Выход" и "История". Знаю, что выйти с программы можно и нажав красный крестик, но я предлагаю сделать это программно, вдруг кому-то пригодится Мы должны сделать обработчик события "Клик" по пункту меню. Два раза нажимаем ЛКМ по нужной ячейке меню, чтобы компилятор автоматически создал подписку и обработчик события: и в обработчике пишем всего одну команду:
Кодprivate void выходToolStripMenuItem_Click( object sender, EventArgs e ) {
Application.Exit();
}С историей посещённый сайтов немного сложнее. Здесь есть куда разный вариантов. Я предлагаю немного усовершенствовать библиотеку, которую мы создали в предыдущем уроке.
Заходим в проект BrowserLib и нажимаем комбинацию CTRL+SHIFT+A, и добавляем новую форму, назвав её, например, History:
Теперь мы можем визуализировать нашу новую форму. Предлагаю эту форму сделать фиксированной, размером 400х350, режим авто-размера: GrowAndShrink. Добавим туда новый компонент - ListBox и разместим его на форме. Добавим ещё 2 кнопки: "удалить запись", "очистить". Если пользователь нажмёт 2 раза ЛКМ по элементу списка, то браузер перейдёт по сохранённой ссылке. Кроме этого создадим лейбл, который будет иметь имя "Нет". Этот компонент будет отображать дату записи, которую мы указали в момент добавления записи лога. В итоге мы должны получить такое окно:
ListBox сам-по-себе не очень сложный в освоении, и очень поход на обычные списки, только в визуальном оформлении. Прежде всего нужно заполнить список информацией. По-задумке, в форму будет передан некий массив строк с которых будет формироваться список. Перейдём в режим редактирования(клавиша F7). В конструктор впишем аргумент - string[] LINKS. Чтобы мы могли выводить дату, мы должны хранить её где-нить, по-этому предлагаю добавить private поле со списком:
Кодprivate List<string> DATE = new List<string>();Так, как одна из функций данного окна является переход по ссылке, мы должны вернуть эту ссылку в виде строки. Пишем:
Кодpublic string retLink = "";Дальше уже идёт процесс заполнения. После процедуры InitializeComponent() добавим следующий код:
Кодpublic History( string[] LINKS ) {
InitializeComponent();
if ( LINKS == null ) {
button1.Enabled = false;
button2.Enabled = false;
return;
}
foreach ( string Temp in LINKS ) {
string[] s = Temp.Split( '|' );
DATE.Add(s[0]);
listBox1.Items.Add(s[1]);
}
}Рассмотрим первый блок. По логике, если нам передали пустой или несуществующий массив, то значит никаких ссылок в логе у нас нет. По этому все действия будут бесполезны, по этому зададим активность наших кнопок в режим "спячки" и сражу же выходим с конструктора с помощи return. Если массив всё-таки существует и имеет записи, то условие не выполняется и идёт второй блок. Мы в цикле обходим все строки в массиве. Каждую строчку мы разделяем сепаратором Split( '|' ). Суть этого метода в том, что он берёт каждую подстроку и записывает в массив, каждая строка является новым элементом. То есть если у нас есть строка "111|222|333|444|555", то на выходе мы получим массив с элементами:
КодArrey
[0]111
[1]222
[2]333
[3]444
[4]555Символ '|' является сепаратором и в массив не входит. Так как наша строка имеет всего один символ сепаратора, то на выходе мы получим массив с 2-х элементов: даты и ссылки. Нулевой элемент мы запишем в список DATE, а первый в ListBox.
Процесс заполнения окончен.Дальше уже идёт реализация. Создадим обработчик события для кнопки "Удалить запись". Прежде всего нам необходимо узнать текущий выбранный элемент:
КодlistBox1.SelectedIndexА потом его удалить командой:
КодlistBox1.Items.RemoveAt( INDEX );Так, как мы должны удалить и в списке дат элемент, то более оптимально будет вынести индекс в переменную, чтобы не делать лишних запросов:
Кодint Index = listBox1.SelectedIndex;
listBox1.Items.RemoveAt( Index );
DATE.RemoveAt( Index );
listBox1.SelectedIndex = 0;Однако есть исключение - нельзя отнимать несуществующие элементы, по этому мы должны поставить условия, что если к-во элементов списка больше нуля, то удалять, иначе отключим кнопки:
Кодprivate void button2_Click( object sender, EventArgs e ) {
if ( listBox1.Items.Count > 0 ) {
int Index = listBox1.SelectedIndex;
listBox1.Items.RemoveAt( Index );
DATE.RemoveAt(Index);
if ( 1 > listBox1.Items.Count ) {
button1.Enabled = false;
button2.Enabled = false;
}
} else {
button1.Enabled = false;
button2.Enabled = false;
}
}Процесс очистки всех элементов ещё проще. Можно конечно было бы делать циклы и тому подобное, но Майкрософт уже сделали это за нас, создав отличный метод очистки:
Кодprivate void button1_Click( object sender, EventArgs e ) {
listBox1.Items.Clear();
DATE.Clear();
button1.Enabled = false;
button2.Enabled = false;
}Итак, мы научили список удалятся 2-мя способами: по одному и всё вместе. Он умеет получать данные из вне. Теперь разберёмся с датами. Здесь проще простого. Выбираем наш список в макете программы и ищем событие SelectedIndexChanged, жмём 2 раза на поле и получаем обработчик события:
Этот блок рекомендую брать в блок try, так как индекс после удаления очищается.
Кодprivate void listBox1_SelectedIndexChanged( object sender, EventArgs e ) {
try {
label1.Text = DATE[ listBox1.SelectedIndex ].ToString();
} catch {
label1.Text = "НЕТ";
}
}Итак, у нас теперь теперь осталась одна задача - переход на ссылке по двойному клику в списке. Здесь тоже нет ничего сложного - наша форма этого делать не будет, это осуществит dll-библиотека, а мы должны только передадим нужное значение. Опять переходим в события ЛистБокса и выбираем событие "DoubleClick". В обработчике пишем следующий текст:
Кодprivate void listBox1_DoubleClick( object sender, EventArgs e ) {
retLink = listBox1.Items[ listBox1.SelectedIndex ].ToString();
Close();
}Суть в том, что мы передаём через публичную переменную ссылку а затем просто закрываем форму, используя процедуру Close().
Казалось весь функционал формы уже сделан, но есть один интересный факт: удаляли мы только со списка, но не с файла. Нам нужно осуществить перезапись файла. Это делается не очень сложно. Для начала зайдём в события самой формы и выбираем "FormClosing". Это событие возникает перед самим закрытием формы, а не после, дающий возможности воспользоваться данными формы:
Кодprivate void History_FormClosing( object sender, FormClosingEventArgs e ) {
string text = "";
int j = DATE.Count;
if ( j > 0 ) {
for ( int i = 0; i < j; i++ ) {
text += DATE[ i ].ToString() + "|" + listBox1.Items[ i ].ToString() + "\r\n";
}
}
File.WriteAllText( "log.txt", text );
}Если к-во элементов списка больше нуля, то идёт цикл, который прибавляет строку с нужным форматом к переменной text. Дальше идёт переход к записи файла. Если есть записи, то запишутся все. Если нет, то файл будет только пустым.
На этом мы завершаем проектировать форму и переходим к dll-ке. Добавим новый статический метод:
Кодpublic static string DysplayHistory() {
// Здесь будет код
}Чтобы открыть новую форму, нам понадобится подключить библиотеку:
Кодusing System.Windows.Forms;Дальше нужно объявить переменную - нашу форму. Делается это так:
КодНАЗВАНИЕ_ФОРМЫ переменная = new НАЗВАНИЕ_ФОРМЫ(атрибуты);Так как форму я завал History, то конструктор будет следующим:
КодHistory frm = new History( GetMessages() );В качестве параметра я передаю массив строк, который получаю ранее записанным методом GetMessages. Дальше нам нужно вызвать форму на экран. Есть 2 способа:
1) Вызов модального окна - форма будет поверх всех окон, а остальные будут недоступны(напоминает MessageBox).
2) Обычный вызов окна - будет создано окно, но мы может осуществлять и другие действия в проекте, вне создаваемой формы.
Я предпочитаю модальный способ:
Кодfrm.ShowDialog();Для обычного:
Кодfrm.Show();Итак, окно открылось, пользователь сделал какие-то действия и закрыл его. Наша процедура возвращает строку, но какую? Так как в окне истории мы предполагали, что пользователь может нажать дабл-клик по списку, то будет переход на тот сайт. Так вот эту стоку метод будет возвращать. Весь метод будет выглядеть так:
Кодpublic static string DysplayHistory() {
History frm = new History( GetMessages() );
frm.ShowDialog();
return frm.retLink;
}Мы крутые! Форма и библиотека полностью функциональна! Теперь нам остался последний штрих! вызвать эту процедуру с главного окна программы. Для этого дважды кликнем на шаблон ячейки меню "История" и добавим следующий код:
Кодprivate void историяToolStripMenuItem_Click( object sender, EventArgs e ) {
string a = BrowserLog.DysplayHistory();
}Делаем тест:
Наша задача выполнена. наш браузер научился хранить историю! :)
Теперь сделаем одну махинацию, чтобы легче и экономнее было использовать наш браузер, а именно создать процедуру, которая будет принимать 1 строковый параметр а сама выполнять переход в браузер:
Кодpublic void FollowLink( string URL ) {
try {
webBrowser1.Url = new Uri( URL );
BrowserLog.AddMessage( URL );
label1.Text = "";
} catch {
label1.Text = "Неверное имя ссылки!";
}
}И использовать эту функцию в обработчике кнопки:
Кодprivate void button1_Click( object sender, EventArgs e ) {
FollowLink( textBox1.Text );
}Теперь мы можем воспользоваться этой процедурой и в обработчике кнопки меню "История":
Кодprivate void историяToolStripMenuItem_Click( object sender, EventArgs e ) {
string a = BrowserLog.DysplayHistory();
if ( a.Length > 0 ) {
FollowLink( a );
}
}Таким образом мы осуществили такое действие: пользователь дважды нажал на ссылку в списке и осуществился переход на эту ссылку.
Ну и чтобы Вас окончательно утомить, давайте осуществим просьбу одного пользователя - чтобы префикс "http://" автоматически приклеивался, а то постоянно вводить адрес как-то непривычно и не функционально. Реализовать такое просто.Достаточно написать условие:
Кодif ( str.ToLower().IndexOf( "http://" ) == -1 ) {
str = "http://" + str;
}а метод FollowLink будет иметь вид:
Кодpublic void FollowLink( string URL ) {
try {
if ( URL.ToLower().IndexOf( "http://" ) == -1 ) {
URL = "http://" + URL;
}
webBrowser1.Url = new Uri( URL );
BrowserLog.AddMessage( URL );
label1.Text = "";
} catch {
label1.Text = "Неверное имя ссылки!";
}
}Суть условия проста. Ищем в строке подстроку "http://". Если такая не нашлась(результат вернул -1), то просто дописываем эту приставку к строке. Чтобы поиск был корректным, нужно перевести строку в нижний регистр, чем мы воспользовались: ToLower().
Итак, из этого урока вы извлекли:
- Вызов формы из другой формы;
- Применили основные команды ListBox и также List;
- Научились передавать данные между формой и библиотекой(этот вариант катит и при обмене с другими формами, классами и.т.п.);
- Узнали некоторые методы работы со строками Split, ToLower, IndexOf;
- Узнали о понятии меню и как писать команды при нажатия кнопки;
На этом, окончательно, урок окончен. Спасибо за внимание ;)
|3469|1|0|81769077png
581160
400110\|74422300
png235
96|96864589png
18093\|53095560
png320
168|75561017png
587189
400128\|29877193
png416
367400
352|10715290png
561356
400253\|42902911
png600
450400
300||zapusk_drugoj_formy_iz_osnovnoj_listbox_menustrip|1399455340