Рейтинг - 4.5 (4)

Всем осветительный привет! Мы продолжаем изучать формы Windows и сегодня мы будем учится запускать новую форму из окна основной, а также рассмотрим такие элементы, как ListBox и MenuStrip.

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

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

Соответственно всё, что будет написано справа будет горизонтальной навигацией, а что внизу - подпункты выделенной категории. Для начала создадим 3 пункта меню: "Файл", "Команды" и "Справка". В меню файл создадим 2 пункта: "Сохранить HTML" и "Выход":

В меню "Команды" добавим только 1 пункт - "История", а в Справку закинем "Об авторе" и "О программе".

Наше меню готово, осталось только написать логику этих пунктов. Но прежде всего предлагаю сместить объект кнопка, браузер и ТекстБокс на небольшое расстояние от панели меню. Если это сделать, то получится эффект, когда меню частично закрывает кнопку и поле ввода, что намекает на криворукость программиста smile Думаю при компиляции без изменений сразу будет видим этот эффект. Ваша задача - подкорректировать элементы макета под более удобный вид. 

В этом уроке мы рассмотрим выполнение 2-х функций - "Выход" и "История". Знаю, что выйти с программы можно и нажав красный крестик, но я предлагаю сделать это программно, вдруг кому-то пригодится smile Мы должны сделать обработчик события "Клик" по пункту меню. Два раза нажимаем ЛКМ по нужной ячейке меню, чтобы компилятор автоматически создал подписку и обработчик события:

и в обработчике пишем всего одну команду:
Код
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;
- Узнали о понятии меню и как писать команды при нажатия кнопки;

На этом, окончательно, урок окончен. Спасибо за внимание ;)

Теги: ListBox, Запуск другой формы из основной, MenuStrip

SanKing   (05.11.13 13:52)
Благодарю за урок и за "http://"!
Вход на сайт

Поиск
Категории раздела
Мини-чат
Пожалуйста, все вопросы по скриптингу задавать на форуме!
Наш опрос
Какая GTA Вам понравилась больше всего?
Всего ответов: 7
Активность на сайте
Пожертвования
Кошельки WebMoney:
U859420971000
R407741810602
Z331072372430
E314272616890
Друзья сайта
Полезные ресурсы
Статистика

Онлайн всего: 1
Гостей: 1
Пользователей: 0

Сегодня нас посетили:
Реклама