Изображение к статье создано при помощи нейросети Kandinsky
Пожалуй, ни для кого ни секрет, что в современных реалиях для сохранения безопасности ваших данных необходимо использовать пароли к различным приложениям и сервисам. И от того, насколько надёжный пароль вы будете использовать к этим приложениям и сервисам, напрямую зависит защищённость вашего аккаунта и данных. Наверное, сегодня каждый знает и понимает, что крайне не рекомендуется использовать слишком простые пароли, состоящие только из цифр (вроде дат или годов рождения) или целых слов или словосочетаний, которые бы представляли собой комбинации, легко подбираемые злоумышленниками, желающими получить доступ к вашему аккаунту в том или ином приложении или сервисе. Поэтому для сохранности ваших данных вам всегда нужен надёжный пароль.
Чтобы облегчить задачу и не придумывать каждый раз новый пароль из головы, на сегодняшний день уже существуют всевозможные программы и онлайн-сервисы для генерации надёжных паролей, которые мы можем использовать для обеспечения защиты наших данных. Механизмы генерации качественных паролей встроены и в современные браузеры, чтобы помочь нам быстро получить хороший и надёжный пароль.
В этой статье в практических целях мы также посмотрим с вами на пример написания несложного генератора паролей, используя язык программирования C# и Windows Forms.
Итак, мы по шагам напишем с вами приложение на C#, которое:
- будет генерировать пароль заданной длины от 5 до 30 символов
- сможет использовать для генерации пароля цифры (от 0 до 9), строчные и прописные латинские символы (a-z, A-Z), а также спецсимволы (#, $, %, ! и другие)
- будет автоматически копировать сгенерированный пароль в буфер обмена для его дальнейшего использования в каком-то приложении/сервисе
- будет выдавать рекомендацию по генерации надёжного пароля, если посчитает, что выставленные настройки приведут к генерации слишком простого пароля.
- поддержит кнопку очистки сгенерированного пароля
- сможет сохранять выставленные пользователем настройки генерации пароля и использовать их при следующем запуске приложения
Мы разберём код такого приложения и посмотрим на то, как оно работает изнутри. Как всегда в конце статьи вы сможете скачать архив с готовым проектом для среды Microsoft Visual Studio и изучить код самостоятельно, если не планируете писать приложение по представленным шагам с нуля. Однако, если вы только начинаете изучать разработку на C# и хотите получить больше практики при разработке приложений на C#, я бы рекомендовал пройти по шагам статьи и разработать приложение по уроку, а затем при желании сравнить с тем готовым проектом, который мы предлагаем к скачиванию в конце статьи.
Приложение будет содержать одну главную форму и будет выглядеть следующим образом:
Ну что же, давайте приступим.
Создание нового проекта в среде Microsoft Visual Studio
Откройте среду разработки Microsoft Visual Studio и создайте новый проект с типом Приложение Windows Forms (.NET Framework), как показано ниже:
В качестве имени нового проекта задайте PasswordGenerator и выберите местоположение, куда будут сохранены файлы нового проекта (здесь я обычно оставляю все настройки по умолчанию и рекомендую сделать то же самое, просто запомните каталог, указанный в поле "Расположение", чтобы затем открывать его в Проводнике):
Переименование главной формы приложения
После создания проекта будет создана главная форма по умолчанию с именем Form1 и соответствующий ей класс Form1.cs.
Выберем в окне "Обозреватель решений" эту форму и в окне "Свойства" изменим название класса для формы на FrmPasswordGenerator.cs.
В диалоговом окне, запрашивающем подтверждение переименования класса формы и связанных с ней файлов, соглашаемся.
В итоге должно получиться следующее - в окне "Обозреватель решений" форма и зависящие от неё файлы будут переименованы:
А так должно выглядеть окно "Свойства":
Настройка главной формы приложения и её элементов
Теперь нам нужно изменить размеры и свойства главной формы и расположить все нужные нам элементы управления.
Выберите форму, чтобы она появилась в представлении конструктора и установите для формы следующие свойства и их значения:
- FormBorderStyle - FixedSingle
- Text - [Allineed.Ru] - Генератор паролей
- Size - 600; 358
- StartPosition - CenterScreen
- Name - FrmPasswordGenerator
- MaximizeBox - False
- MinimizeBox - False
Часть свойств нашей главной формы мы ещё изменим чуть позже, когда на ней будут присутствовать кнопки и остальные элементы.
Теперь нужно расположить на главной форме требуемые элементы. Для этого в левой части Microsoft Visual Studio находим "Панель элементов" и последовательно перетаскиваем с неё на нашу главную форму следующие элементы, а также устанавливаем им описанные ниже свойства:
1) Один элемент GroupBox и его дочерние элементы
Перетаскиваем на форму элемент GroupBox и устанавливаем ему следующие свойства:
- Text - Параметры генерации пароля:
- Location - 12; 12
- Size - 560; 171
- Name - GroupBoxGenerationParams
Теперь внутрь этого элемента GroupBox перетаскиваем по очереди:
- 4 элемента CheckBox
- 1 элемент TrackBar
- 2 элемента Label
Элементам CheckBox устанавливаем последовательно следующие свойства:
1-й:
- Text - Использовать специальные символы: # ! $ ; _ ? && ^ % @ * ( ) { } [ ]
- Location - 9; 20
- Name - CheckBoxUseSpecialSymbols
2-й:
- Text - Использовать цифры: 0 - 9
- Location - 9; 43
- Name - CheckBoxUseDigits
3-й:
- Text - Использовать строчные латинские буквы: a - z
- Location - 9; 66
- Name - CheckBoxUseLowercaseLetters
4-й:
- Text - Использовать прописные латинские буквы: A - Z
- Location - 9; 89
- Name - CheckBoxUseUppercaseLetters
Элементу TrackBar устанавливаем свойства:
- Location - 184; 112
- Size - 368; 45
- Maximum - 30
- Minimum - 5
- Value - 5
- Name - TrackBarPasswordLength
Оставшимся двум элементам Label также устанавливаем следующие свойства:
1-й:
- Text - Длина пароля (символов):
- Location - 6; 118
- Name - LabelPasswordLength
2-й:
- Font - Microsoft Sans Serif; 8,25pt; style=Bold
- Text - ##
- Location - 143; 118
- Name - LabelPasswordLengthValue
Теперь в остальных пунктах ниже все элементы управления будем перетаскивать на форму за пределами этого элемента GroupBox:
2) Три кнопки Button
Перетаскиваем на форму три кнопки (Button) и устанавливаем их свойства:
1-я:
- Text - &Сгенерировать пароль
- Location - 12; 199
- Size - 138; 23
- Name - ButtonGeneratePassword
2-я:
- Text - &Выход
- Location - 461; 269
- Size - 111; 23
- Name - ButtonExit
3-я:
- Text - <пусто, т.е. стереть текст по умолчанию>
- Location - 539; 194
- Size - 33; 33
- Name - ButtonClearPassword
3) Четыре элемента Label
Перетаскиваем на форму четыре метки (Label) и устанавливаем их свойства:
1-я:
- Text - Сгенерированный пароль:
- Location - 156; 204
- Name - LabelGeneratedPassword
2-я:
- Font - Microsoft Sans Serif; 8,25pt; style=Bold
- ForeColor - Green (значение нужно выбрать из всплывающей палитры на вкладке "Интернет")
- Text - Пароль скопирован в буфер обмена
- Location - 300; 224
- Name - LabelPasswordCopiedToClipboard
3-я:
- Font - Microsoft Sans Serif; 8,25pt; style=Bold
- ForeColor - 192; 0; 0
- Text - Рекомендации для генерации надёжного пароля:
- Location - 12; 251
- Name - LabelWarningMessageTitle
4-я:
- ForeColor - 192; 0; 0
- Text - длина от 8 символов и более, с использованием спецсимволов, цифр, строчных и прописных латинских букв
- AutoSize - False
- Location - 12; 269
- Size - 416; 36
- Name - LabelWarningMessage
4) Один элемент TextBox
Перетаскиваем на форму элемент TextBox и устанавливаем ему свойства:
- Location - 303; 201
- Size - 230; 20
- Name - TextBoxGeneratedPassword
5) Один элемент Timer
Перетаскиваем на форму элемент Timer и устанавливаем ему свойства:
- Interval - 2000
- Name - TimerShowLabelCopiedToClipboard
6) Один элемент ImageList
Перетаскиваем на форму элемент ImageList и устанавливаем ему свойства:
- ColorDepth - Depth32Bit
- ImageSize - 24; 24
- Name - ImageListDefault
7) Один элемент ToolTip
Перетаскиваем на форму элемент ToolTip и устанавливаем ему свойства:
- Name - ToolTipForControl
Теперь все основные элементы расположены на нашей главной форме, и им установлены ключевые начальные значения свойств.
Установка дополнительных свойств форме и её элементам
Однако, как мы и говорили ранее, нужно будет выполнить дополнительную настройку некоторых свойств формы и её элементов, когда на форме будут присутствовать все элементы. Давайте сделаем это.
Выбираем главную форму в представлении конструктора и выставим дополнительно следующие её свойства:
- AcceptButton - ButtonGeneratePassword (выбираем из выпадающего списка)
- CancelButton - ButtonExit (выбираем из выпадающего списка)
Теперь выберем последовательно наши кнопки (Button) и установим им дополнительно свойства:
Для кнопки "Сгенерировать пароль" (ButtonGeneratePassword):
- ToolTip на ToolTipForControl - Сгенерировать надёжный пароль с заданной длинной и используемыми символами
Для кнопки без текста с именем ButtonClearPassword:
- ToolTip на ToolTipForControl - Очистить поле
Для кнопки "Выход" (ButtonExit):
- ToolTip на ToolTipForControl - Выйти из программы
Программирование логики главной формы и её элементов
Теперь, когда все элементы главной формы расположены на своих местах, мы перейдем к самой интересной части - разработке логики нашего приложения.
Дважды кликнем на коде формы из представления конструктора, чтобы открыть редактор кода формы.
В самом начале класса нашей формы зададим 4 строковых массива, которые будут содержать те символы, из которых будет генерироваться пароль, а также определим 4 целочисленные константы, которые будут соответствовать этим массивам и использоваться для определения, из какого именно массива мы будем брать очередной генерируемый символ пароля:
public partial class FrmPasswordGenerator : Form {
public string[] digits = new string[] { "0", "1", "2", "3", "4", "5", "6", "7", "8", "9" };
public string[] lowercaseLetters = new string[] { "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z" };
public string[] uppercaseLetters = new string[] { "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z" };
public string[] specialSymbols = new string[] { "#", "!", "$", ";", "_", "&", "^", "%", "&", "*", "(", ")", "{", "}", "[", "]" };
public const int USE_DIGITS = 1;
public const int USE_LOWERCASE_LETTERS = 2;
public const int USE_UPPERCASE_LETTERS = 3;
public const int USE_SPECIAL_SYMBOLS = 4;
// ... остальной код формы ...
}
Теперь давайте напишем метод, который будет проверять некоторую условную силу/надёжность нашего пароля и назовём его CheckPasswordStrength(). Задача метода - проверить, что значение в элементе TrackBar с именем TrackBarPasswordLength больше 7 (т.к. мы будем рекомендовать длину пароля от 8 и более символов), а также что выставлены значения для всех элементов CheckBox на форме, что означает, что мы рекомендуем генерацию такого пароля, где используются все 4 ранее определённых массива и символы из них - спецсимволы, строчные/прописные латинские буквы и цифры. Если же пользователь пожелает снизить количество символов в генерируемом пароле или снимет хотя бы один флажок, то мы будем считать пароль не очень надёжным и делать видимым предупреждающее сообщение:
/// <summary>
/// [RU] Опеределяет силу/надёжность пароля, и если пароль не соответствует рекомендациям, выводит предупреждающее сообщение
/// [EN] Checks strength/robustness of the password and in case password does not meet recommendations, shows a warning message
/// </summary>
private void CheckPasswordStrength() {
bool isLengthGreaterThan7Symbols = TrackBarPasswordLength.Value >= 8;
bool isUsedAllSymbols = CheckBoxUseDigits.Checked && CheckBoxUseSpecialSymbols.Checked && CheckBoxUseLowercaseLetters.Checked && CheckBoxUseUppercaseLetters.Checked;
bool isStrongPassword = isLengthGreaterThan7Symbols && isUsedAllSymbols;
LabelWarningMessageTitle.Visible = !isStrongPassword;
LabelWarningMessage.Visible = !isStrongPassword;
}
Также давайте добавим в код формы новый метод EnableDisableGeneratePasswordButton(), который будет делать доступной/недоступной кнопку "Сгенерировать пароль", в зависимости от состояния элементов CheckBox на форме. Мы будем запрещать генерацию пароля, если ни один флажок не выставлен (поскольку в этом случае ни один из 4-х массивов символов не используется, и нам попросту не из чего генерировать пароль). Также в этом новом методе будем вызывать наш метод CheckPasswordStrength(), который мы уже написали:
private void EnableDisableGeneratePasswordButton() {
ButtonGeneratePassword.Enabled = CheckBoxUseDigits.Checked || CheckBoxUseLowercaseLetters.Checked || CheckBoxUseUppercaseLetters.Checked || CheckBoxUseSpecialSymbols.Checked;
CheckPasswordStrength();
}
Далее сделаем так, чтобы при клике на каждом из флажков вызывался наш новый метод EnableDisableGeneratePasswordButton(). Для этого переходим на главную форму в представление конструктора и дважды кликаем по первому флажку. В результате для него будет сгенерирован метод-обработчик события CheckChanged, которое происходит при смене состояния флажка. Нужно проделать аналогичное действие для каждого из наших 4-х флажков, чтобы в коде формы сгенерировались их соответствующие обработчики. Теперь в тело каждого обработчика добавляем вызов вышеупомянутого метода, и должно получиться примерно следующее:
private void CheckBoxUseSpecialSymbols_CheckedChanged(object sender, EventArgs e) {
EnableDisableGeneratePasswordButton();
}
private void CheckBoxUseDigits_CheckedChanged(object sender, EventArgs e) {
EnableDisableGeneratePasswordButton();
}
private void CheckBoxUseLowercaseLetters_CheckedChanged(object sender, EventArgs e) {
EnableDisableGeneratePasswordButton();
}
private void CheckBoxUseUppercaseLetters_CheckedChanged(object sender, EventArgs e) {
EnableDisableGeneratePasswordButton();
}
Теперь давайте напишем метод для генерации пароля. Назовём его GetGeneratedPassword(int passwordLength), и пусть он возвращает тип string, т.е. он будет возвращать у нас строку, содержащую сгенерированный пароль. Ниже полный код этого метода:
private string GetGeneratedPassword(int passwordLength) {
StringBuilder sbPassword = new StringBuilder();
Random random = new Random();
for (int i = 0; i < passwordLength; i++) {
int randomArrayNumber;
do {
randomArrayNumber = random.Next(1, 5);
} while (IsNeedToSkip(randomArrayNumber));
switch (randomArrayNumber) {
case USE_DIGITS:
int randomDigitIndex = random.Next(0, digits.Length);
sbPassword.Append(digits[randomDigitIndex]);
break;
case USE_LOWERCASE_LETTERS:
int randomLowercaseLetterIndex = random.Next(0, lowercaseLetters.Length);
sbPassword.Append(lowercaseLetters[randomLowercaseLetterIndex]);
break;
case USE_UPPERCASE_LETTERS:
int randomUppercaseLetterIndex = random.Next(0, uppercaseLetters.Length);
sbPassword.Append(uppercaseLetters[randomUppercaseLetterIndex]);
break;
case USE_SPECIAL_SYMBOLS:
int randomSpecialSymbolIndex = random.Next(0, specialSymbols.Length);
sbPassword.Append(specialSymbols[randomSpecialSymbolIndex]);
break;
}
}
return sbPassword.ToString();
}
Вы можете заметить, что метода с именем IsNeedToSkip ещё не существует в коде формы, поэтому компилятор выдаст соответствующую ошибку. Не переживайте, мы добавим метод IsNeedToSkip немного позже, а пока давайте разберём, как же работает сам алгоритм генерации пароля.
Итак, в начале метода мы определяем строковый буфер - переменную с типом StringBuilder и именем sbPassword. Нетрудно догадаться, что она и будет хранить наш сгенерированный пароль, а наша задача - в цикле добавлять к паролю по одному символу, беря этот символ из одного из наших 4-х массивов. Для того, чтобы генерировать случайные числа мы используем класс Random и в начале метода объявляем переменную random. Количество итераций цикла соответствует длине пароля, который мы получаем во входном параметре метода - passwordLength.
В цикле мы присваиваем переменной randomArrayNumber произвольное значение от 1 до 4. Тут стоит отметить, что специфика метода Next() в классе Random заключается в том, что второй его аргумент исключён из возможных генерируемых значений, в отличие от первого, т.е. значение 5 мы никогда не получим. Так вот, это значение от 1 до 4 указывает на один из наших строковых массивов, а именно на тот, из которого нам и нужно будет взять какой-то произвольный символ для пароля. Обратите внимание, что мы делаем это в цикле do ... while, каждый раз проверяя значение метода IsNeedToSkip. Что же будет делать этот метод? Он лишь проверит, что произвольное значение от 1 до 4 относится к массиву, который мы в принципе можем использовать для генерации - поскольку мы можем флажками на форме запрещать использование каких-то массивов и символов из них. Т.е. фактически мы в цикле do ... while крутимся до тех пор, пока не получим произвольный номер массива, разрешённого к использованию, исходя из текущего состояние флажков в нашей программе.
А дальше всё довольно просто - у нас есть оператор switch, каждая развилка case которого "нацелена" на все 4 допустимых массива. И для каждого случая мы снова с помощью random сгенерируем произвольное число, но в этот раз уже соответствующее индексу элемента в пределах выбранного массива. И добавим символ из выбранного массива к нашему паролю.
Наконец, по выходу из основного цикла for мы уже имеем сформированный пароль в буфере sbPassword и возвращаем его как строку в качестве результата метода.
Давайте теперь напишем метод IsNeedToSkip, чтобы компилятор не "ругался" ошибкой. В свободном месте кода для формы добавляем такой код метода:
private bool IsNeedToSkip(int arrayNumber) {
if (arrayNumber == USE_DIGITS && !CheckBoxUseDigits.Checked) {
return true;
} else if (arrayNumber == USE_LOWERCASE_LETTERS && !CheckBoxUseLowercaseLetters.Checked) {
return true;
} else if (arrayNumber == USE_UPPERCASE_LETTERS && !CheckBoxUseUppercaseLetters.Checked) {
return true;
} else if (arrayNumber == USE_SPECIAL_SYMBOLS && !CheckBoxUseSpecialSymbols.Checked) {
return true;
}
return false;
}
Как видно из кода этого метода, он сверяет значение в аргументе arrayNumber с фактическим состоянием флага на форме. И если этот флаг выключен, то IsNeedToSkip будет возвращать true, в противном случае - он вернёт false, и это будет означать, что мы можем использовать массив для взятия из него символов и добавлять их к генерируемому паролю.
Теперь вернёмся на форму приложения и дважды кликнем на кнопке ButtonClearPassword, чтобы сгенерировать обработчик нажатия на кнопку. Эта кнопка будет очищать текстовое поле, стирая из него сгенерированный пароль. В обработчике пишем простейший код для очистки поля:
private void ButtonClearPassword_Click(object sender, EventArgs e) {
TextBoxGeneratedPassword.Text = "";
}
Снова вернёмся на форму приложения и теперь дважды кликнем по таймеру с именем TimerShowLabelCopiedToClipboard. В результате сгенерируется обработчик события Tick для таймера, куда мы добавим следующий код:
private void TimerShowLabelCopiedToClipboard_Tick(object sender, EventArgs e) {
LabelPasswordCopiedToClipboard.Hide();
TimerShowLabelCopiedToClipboard.Stop();
}
Что делает этот код? Когда таймер сработает, то вызовется его событие Tick, и метка с текстом "Пароль скопирован в буфер обмена" будет скрыта, при этом сам таймер будет снова остановлен. Это нужно, чтобы обеспечить эффект пропадания метки, т.к. пользователю программы нужно лишь кратковременно дать понять, что пароль скопировался в буфер обмена.
Давайте теперь напишем обработчик для главной кнопки на форме - "Сгенерировать пароль". Снова возвращаемся в представление конструктора и дважды кликаем на кнопке. В сгенерированном обработчике события щелчка по кнопке, напишем код:
private void ButtonGeneratePassword_Click(object sender, EventArgs e) {
LabelPasswordCopiedToClipboard.Hide();
TimerShowLabelCopiedToClipboard.Stop();
int passwordLength = TrackBarPasswordLength.Value;
TextBoxGeneratedPassword.Text = GetGeneratedPassword(passwordLength);
Clipboard.SetText(TextBoxGeneratedPassword.Text);
LabelPasswordCopiedToClipboard.Show();
TimerShowLabelCopiedToClipboard.Start();
}
Что происходит при клике на кнопку "Сгенерировать пароль"? Во-первых, мы скрываем метку "Пароль скопирован в буфер обмена", если вдруг она видима, а также останавливаем таймер.
Во-вторых, мы получаем значение длины генерируемого пароля из элемента TrackBar в переменную passwordLength. Далее мы вызываем наш уже готовый метод GetGeneratedPassword для генерации пароля, передавая ему указанную длину пароля. Возвращённый методом сгенерированный пароль мы устанавливаем в качестве значения в текстовое поле формы.
Наконец, с помощью класса Clipboard и его метода SetText мы копируем также сгенерированный пароль в буфер обмена. И напоследок - мы показываем вновь метку "Пароль скопирован в буфер обмена" и запускаем таймер - чтобы когда таймер сработает через 2 секунды (значение Interval нашего таймера выставлено 2000, что означает 2000 миллисекунд, или 2 секунды), он снова скроет метку и выключится.
Настройки программы. Программируем загрузку и сохранение настроек программы
Согласитесь, было бы здорово, если бы наша программа умела "запоминать" все настройки, с которыми мы её каждый раз будем завершать. Это удобно, если нам не хочется каждый раз выставлять предпочтительную длину генерируемого пароля, а также каждый раз флажками регулировать, какие же символы можно использовать в пароле.
Давайте же поддержим необходимые настройки в нашей программы и свяжем их с элементами на главной форме приложения.
Для этого перейдите к окну "Обозреватель решений", раскройте узел "Properties" с изображением гаечного ключа, как показано на рисунке:
Дважды кликните на узле Settings.settings, в результате чего откроется окно параметров нашей программы и таблица. В таблице нам необходимо ввести данные для каждой настройки и заполнить поля следующим образом:
Ниже дано объяснение настройкам, которые мы вводим для нашей программы:
- IsUseDigits - флаг (bool) со значением по умолчанию True. Обозначает, что флажок "Использовать цифры: 0 - 9" по умолчанию будет выставлен при старте программы
- IsUseUppercaseLetters - флаг (bool) со значением по умолчанию True. Обозначает, что флажок "Использовать прописные латинские буквы: A - Z" по умолчанию будет выставлен при старте программы
- IsUseLowercaseLetters - флаг (bool) со значением по умолчанию True. Обозначает, что флажок "Использовать строчные латинские буквы: a - z" по умолчанию будет выставлен при старте программы
- IsUseSpecialSymbols - флаг (bool) со значением по умолчанию True. Обозначает, что флажок "Использовать специальные символы: # ! $ ; _ ? && ^ % @ * ( ) { } [ ]" по умолчанию будет выставлен при старте программы
- PasswordLength - целое число (int) со значением по умолчанию 5. Обозначает длину пароля, которая будет выставлена в элементе TrackBar при загрузке программы
Теперь для нашей программы определены различные нужные параметры, и мы сможем запоминать её состояние перед каждым выходом, а при старте - загружать ранее сохраненные значения.
Давайте теперь реализуем сохранение/загрузку настроек программы.
Прежде всего нужно перейти обратно в редактор кода и в самом верху кода для формы прописать директиву:
using PasswordGenerator.Properties;
Это позволит нам получить доступ к параметрам приложения и стандартному классу Settings, используемому для считывания настроек и их сохранения.
Добавим в код формы новый метод LoadSettings(), который мы далее будем вызывать при открытии нашей главной формы. Метод считывает параметры приложения и устанавливает соответствующее состояние элементов на форме:
/// <summary>
/// [RU] Загрузка настроек программы и обновление элементов на форме
/// [EN] Loads program settings and updates form controls
/// </summary>
private void LoadSettings() {
CheckBoxUseDigits.Checked = Settings.Default.IsUseDigits;
CheckBoxUseSpecialSymbols.Checked = Settings.Default.IsUseSpecialSymbols;
CheckBoxUseUppercaseLetters.Checked = Settings.Default.IsUseUppercaseLetters;
CheckBoxUseLowercaseLetters.Checked = Settings.Default.IsUseLowercaseLetters;
TrackBarPasswordLength.Value = Settings.Default.PasswordLength;
UpdatePasswordLengthValue();
}
Добавим также код метода UpdatePasswordLengthValue(), который просто обновляет метку со значением длины пароля, регулируемым через элемент TrackBar:
/// <summary>
/// [RU] Обновляет длину пароля для генерации после изменения значения в элементе TrackBar
/// [EN] Updates the length for generation the password after changing the value of TrackBar element
/// </summary>
private void UpdatePasswordLengthValue() {
LabelPasswordLengthValue.Text = TrackBarPasswordLength.Value.ToString();
}
Теперь нам нужен также метод по сохранению всех настроек программы. По сути он делает обратное действие методу LoadSettings() - записывает в параметры текущее состояние элементов на форме, а в конце для сохранения настроек вызывает Settings.Default.Save():
/// <summary>
/// [RU] Сохранение настроек программы
/// [EN] Saves program settings
/// </summary>
private void SaveSettings() {
Settings.Default.IsUseDigits = CheckBoxUseDigits.Checked;
Settings.Default.IsUseSpecialSymbols = CheckBoxUseSpecialSymbols.Checked;
Settings.Default.IsUseUppercaseLetters = CheckBoxUseUppercaseLetters.Checked;
Settings.Default.IsUseLowercaseLetters = CheckBoxUseLowercaseLetters.Checked;
Settings.Default.PasswordLength = TrackBarPasswordLength.Value;
Settings.Default.Save();
}
Мы практически завершили написание нашего генератора паролей.
Осталась самая малость. В методе-обработчике загрузки нашей формы добавляем следующий код:
private void FrmPasswordGenerator_Load(object sender, EventArgs e) {
LoadSettings();
EnableDisableGeneratePasswordButton();
CheckPasswordStrength();
}
Как видим, при загрузке формы мы делаем 3 вещи: загружаем настройки программы и обновляем состояние элементов формы, регулируем доступность кнопки "Сгенерировать пароль", а также вызываем метод CheckPasswordStrength(), чтобы показать/скрыть метку с рекомендацией о силе/надёжности генерируемого пароля.
Добавим в код формы следующий новый метод:
private void SaveSettingsAndExitApp() {
SaveSettings();
Application.Exit();
}
Этот метод будет сохранять все настройки и выходить из программы. Теперь переходим в представление конструктора и дважды кликаем по кнопке "Выход", чтобы сгенерировать обработчик нажатия на кнопку. Добавляем в обработчик вызов этого нового метода:
private void ButtonExit_Click(object sender, EventArgs e) {
SaveSettingsAndExitApp();
}
Снова возвращаемся в представление конструктора формы, выбираем главную форму и в окне "Свойства" кликаем на иконку "молнии" и находим для формы событие FormClosing. Дважды кликаем напротив названия этого события. В результате в код формы будет добавлен обработчик события закрытия формы (например, оно будет вызываться при закрытии формы нажатием на "крестик" в правом верхнем углу, а нам нужно также сохранять все настройки программы в этом случае). Пишем в обработчике следующий код:
private void FrmPasswordGenerator_FormClosing(object sender, FormClosingEventArgs e) {
SaveSettingsAndExitApp();
}
Далее мы хотим, чтобы доступность кнопки, которая очищает текстовое поле с паролем менялась, в зависимости от наличия/отсутствия текста в текстовом поле. Из представления конструктора дважды кликнем по текстовому полю и добавим в обработчик события TextChanged следующий код:
private void TextBoxGeneratedPassword_TextChanged(object sender, EventArgs e) {
ButtonClearPassword.Enabled = TextBoxGeneratedPassword.TextLength > 0;
}
На этом наша программа полностью написана и работоспособна!
Попробуйте запустить её из среды разработки, нажав на кнопку "Пуск" в виде зелёного треугольника. Теперь можно генерировать пароли с заданными настройками.
Тем не менее, осталось несколько финальных штрихов, связанных с иконками для программы.
Последние штрихи для программы
Несмотря на то, что код программы полностью готов, и ей уже можно пользоваться, нам потребуется настроить ещё пару вещей - задать иконку для приложения, чтобы исполняемый .exe файл нашей программы имел законченный вид, а также добавить в элемент ImageListDefault формы изображение "корзины" и установить его кнопке ButtonClearPassword, которая у нас не имеет текста.
Файл с изображением корзины вы найдете в архиве в конце этой статьи. Вам нужно будет скачать и распаковать архив, после чего взять оттуда файл с именем 2638315_bin_delete_dust_erace_garbage_icon.png и поместить в тот же каталог вашего проекта, где располагается файл формы FrmPasswordGenerator.cs.
Далее выберите элемент ImageListDefault на форме и в окне "Свойства" нажмите на его свойство Images и в открывшемся редакторе коллекции изображений нажмите кнопку "Добавить", после чего найдите изображение корзины и добавьте его в элемент ImageList. Эти действия представлены по шагам ниже:
Теперь выберите на форме кнопку ButtonClearPassword и установите для неё следующие свойства:
- ImageList - ImageListDefault
- ImageAlign - TopLeft
- ImageIndex - 0
Это придаст кнопке очистки текстового поля вид с изображением корзины.
Теперь установим иконку для главной формы нашего приложения. Возьмите ещё один файл из архива с примером - 9021590_password_bold_icon.ico и разместите его в том же каталоге, что и изображение корзины.
Далее выполните два шага:
1. Для главной формы установите свойство Icon, указав путь к этой иконке
2. В главном меню Microsoft Visual Studio выберите "Проект" → "Свойства: PasswordGenerator" и в открывшемся окне в блоке "Ресурсы" / "Значок и манифест" укажите путь к файлу иконки.
Ссылки на авторов и иконки, которые мы использовали при написании нашего приложения:
- https://www.iconfinder.com/phosphor-icons (Лицензия: https://creativecommons.org/licenses/by/4.0/)
- https://www.iconfinder.com/popcic (Лицензия: https://creativecommons.org/licenses/by/3.0/)
Ссылка на архив с готовым проектом для Microsoft Visual Studio и исполняемые файлы для сборок Debug/Release:
На этом всё, спасибо за внимание. Делитесь своими комментариями и мыслями внизу статьи и не забудьте поставить лайк, если статья вам понравилась. Удачи!