Form. Load Событие
Некоторые сведения относятся к предварительной версии продукта, в которую до выпуска могут быть внесены существенные изменения. Майкрософт не предоставляет никаких гарантий, явных или подразумеваемых, относительно приведенных здесь сведений.
Происходит до первоначального отображения формы.
public: event EventHandler ^ Load;
public event EventHandler Load;
public event EventHandler? Load;
member this.Load : EventHandler
Public Custom Event Load As EventHandler
Тип события
Примеры
В следующем примере показано, как использовать SetDesktopLocationчлены , Load, Activatedи Activate . Чтобы выполнить пример, вставьте следующий код в форму с именем Form1 , содержащую вызываемую Button1 Button и два Label элемента управления с именем Label1 и Label2 .
static int x = 200; static int y = 200; void Button1_Click( System::Object^ sender, System::EventArgs^ e ) < // Create a new Form1 and set its Visible property to true. Form1^ form2 = gcnew Form1; form2->Visible = true; // Set the new form's desktop location so it // appears below and to the right of the current form. form2->SetDesktopLocation( x, y ); x += 30; y += 30; // Keep the current form active by calling the Activate // method. this->Activate(); this->Button1->Enabled = false; > // Updates the label text to reflect the current values of x // and y, which was were incremented in the Button1 control's // click event. void Form1_Activated( Object^ sender, System::EventArgs^ e ) < Label1->Text = String::Format( "x: y: ", x, y ); Label2->Text = String::Format( "Number of forms currently open: ", count ); > static int count = 0; void Form1_Closed( Object^ sender, System::EventArgs^ e ) < count -= 1; >void Form1_Load( Object^ sender, System::EventArgs^ e )
static int x = 200; static int y = 200; private void Button1_Click(System.Object sender, System.EventArgs e) < // Create a new Form1 and set its Visible property to true. Form1 form2 = new Form1(); form2.Visible = true; // Set the new form's desktop location so it // appears below and to the right of the current form. form2.SetDesktopLocation(x, y); x += 30; y += 30; // Keep the current form active by calling the Activate // method. this.Activate(); this.Button1.Enabled = false; >// Updates the label text to reflect the current values of x // and y, which was were incremented in the Button1 control's // click event. private void Form1_Activated(object sender, System.EventArgs e) < Label1.Text = "x: "+x+" y: "+y; Label2.Text = "Number of forms currently open: "+count; >static int count = 0; private void Form1_Closed(object sender, System.EventArgs e) < count -= 1; >private void Form1_Load(object sender, System.EventArgs e)
Shared x As Integer = 200 Shared y As Integer = 200 Private Sub Button1_Click(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles Button1.Click ' Create a new Form1 and set its Visible property to true. Dim form2 As New Form1 form2.Visible = True ' Set the new form's desktop location so it appears below and ' to the right of the current form. form2.SetDesktopLocation(x, y) x += 30 y += 30 ' Keep the current form active by calling the Activate method. Me.Activate() Me.Button1.Enabled = False End Sub ' Updates the label text to reflect the current values of x and y, ' which was were incremented in the Button1 control's click event. Private Sub Form1_Activated(ByVal sender As Object, _ ByVal e As System.EventArgs) Handles MyBase.Activated Label1.Text = "x: " & x & " y: " & y Label2.Text = "Number of forms currently open: " & count End Sub Shared count As Integer = 0 Private Sub Form1_Closed(ByVal sender As Object, _ ByVal e As System.EventArgs) Handles MyBase.Closed count -= 1 End Sub Private Sub Form1_Load(ByVal sender As Object, _ ByVal e As System.EventArgs) Handles MyBase.Load count += 1 End Sub
Комментарии
Это событие можно использовать для выполнения таких задач, как выделение ресурсов, используемых формой.
Дополнительные сведения об обработке событий см. в разделе Обработка и вызов событий.
Использование Visual C# для выполнения простого операций ввода-вывода файлов
В этой статье описывается выполнение базового операций ввода-вывода файлов в Visual C#, а также приведен пример кода, демонстрирующий выполнение этой задачи.
Исходная версия продукта: Visual C #
Оригинальный номер базы знаний: 304430
Аннотация
- Версию Visual Basic .NET этой статьи см. в статье Как выполнить базовый файловый ввод-вывод в Visual Basic 2005 или в Visual Basic .NET.
- Сведения о версии .NET для Visual C++ этой статьи см. в статье Как выполнять базовый файловый ввод-вывод в Visual C++ или в Visual C++ .NET.
- В этой статье рассматриваются пространства System.IO имен библиотеки классов Microsoft платформа .NET Framework и System.Collections .
В этой пошаговой статье показано, как выполнить шесть основных операций ввода-вывода файлов в Visual C#. Если вы не знакомы с платформа .NET Framework, вы увидите, что объектная модель для операций с файлами в .NET похожа на FileSystemObject модель (FSO), которая пользуется популярностью у многих разработчиков Visual Studio 6.0. Чтобы упростить переход, функциональность, показанная в статье Использование FileSystemObject с Visual Basic.
Вы по-прежнему FileSystemObject можете использовать в .NET. FileSystemObject Так как является компонентом COM, для .NET требуется, чтобы доступ к объекту проходил через слой взаимодействия. Microsoft .NET создает оболочку для компонента, если вы хотите его использовать. File Однако классы , FileInfo , Directory , DirectoryInfo и другие связанные классы в платформа .NET Framework предоставляют функциональные возможности, недоступные при FSO, без накладных расходов на уровень взаимодействия.
Демонстрация операций ввода-вывода файлов
В примерах в этой статье описываются основные операции ввода-вывода файлов. В разделе Пошаговый пример описывается создание примера программы, демонстрирующей следующие операции ввода-вывода файлов:
- Чтение текстового файла
- Запись текстового файла
- Просмотр сведений о файлах
- Вывод списка дисков
- Список папок
- Вывод списка файлов
Если вы хотите использовать следующие примеры кода напрямую, имейте в виду следующее:
-
System.IO Включите пространство имен следующим образом:
using System.IO;
string winDir=System.Environment.GetEnvironmentVariable("windir");
private void addListItem(string value)
Вместо объявления и использования addListItem функции можно напрямую использовать следующую инструкцию:
this.listBox1.Items.Add(value);
Чтение текстового файла
В следующем примере кода для чтения файлаSystem.ini используется StreamReader класс . Содержимое файла добавляется в элемент управления ListBox. Блок try. catch используется для оповещения программы, если файл пуст. Существует множество способов определить, когда достигается конец файла. В этом примере метод используется Peek для изучения следующей строки перед ее чтением.
StreamReader reader=new StreamReader(winDir + "\\system.ini"); try < do < addListItem(reader.ReadLine()); >while(reader.Peek()!= -1); > catch < addListItem("File is empty"); >finally
Запись текстового файла
Этот пример кода использует класс для StreamWriter создания и записи в файл. Если у вас есть существующий файл, его можно открыть таким же образом.
StreamWriter writer = new StreamWriter("c:\\KBTest.txt"); writer.WriteLine("File created using StreamWriter class."); writer.Close(); this.listbox1.Items.Clear(); addListItem("File Written to C:\\KBTest.txt");
Просмотр сведений о файлах
Этот пример кода использует FileInfo объект для доступа к свойствам файла. в этом примере используется Notepad.exe. Свойства отображаются в элементе управления ListBox.
FileInfo FileProps =new FileInfo(winDir + "\\notepad.exe"); addListItem("File Name = " + FileProps.FullName); addListItem("Creation Time = " + FileProps.CreationTime); addListItem("Last Access Time = " + FileProps.LastAccessTime); addListItem("Last Write TIme = " + FileProps.LastWriteTime); addListItem("Size = " + FileProps.Length); FileProps = null;
Вывод списка дисков
В этом примере кода классы и Drive используются Directory для вывода списка логических дисков в системе. В этом примере результаты отображаются в элементе управления ListBox.
string[] drives = Directory.GetLogicalDrives(); foreach(string drive in drives)
Вывод списка вложенных папок
В этом примере кода метод класса используется GetDirectories Directory для получения списка папок.
string[] dirs = Directory.GetDirectories(winDir); foreach(string dir in dirs)
Вывод списка файлов
В этом примере кода используется GetFiles метод класса для Directory получения списка файлов.
string[] files= Directory.GetFiles(winDir); foreach (string i in files)
Многие вещи могут пойти не так, когда пользователь получает доступ к файлам. Файлы могут не существовать, файлы могут использоваться или пользователи могут не иметь прав на файлы или папки, к которым они пытаются получить доступ. Важно учитывать эти возможности при написании кода и обработке исключений, которые могут быть созданы.
Пошаговый пример
- В Visual C# создайте новое приложение Windows Forms. По умолчанию создается Form1 .
- Откройте окно кода для Form1 (Form1.cs).
- Удалите весь код в Файле Form1.cs.
- Вставьте следующий код в окно редактора кода программной части .
using System.Windows.Forms; using System.IO; namespace fso_cs < public partial class Form1 : Form < string winDir = System.Environment.GetEnvironmentVariable("windir"); public Form1() < InitializeComponent(); >private void button1_Click(object sender, System.EventArgs e) < //How to read a text file. //try. catch is to deal with a 0 byte file. this.listBox1.Items.Clear(); StreamReader reader = new StreamReader(winDir + "\\system.ini"); try < do < addListItem(reader.ReadLine()); >while (reader.Peek()!= -1); > catch < addListItem("File is empty"); >finally < reader.Close(); >> private void button2_Click(object sender, System.EventArgs e) < //Demonstrates how to create and write to a text file. StreamWriter writer = new StreamWriter("c:\\KBTest.txt"); writer.WriteLine("File created using StreamWriter class."); writer.Close(); this.listBox1.Items.Clear(); addListItem("File Written to C:\\KBTest.txt"); >private void button3_Click(object sender, System.EventArgs e) < //How to retrieve file properties (example uses Notepad.exe). this.listBox1.Items.Clear(); FileInfo FileProps = new FileInfo(winDir + "\\notepad.exe"); addListItem("File Name = " + FileProps.FullName); addListItem("Creation Time = " + FileProps.CreationTime); addListItem("Last Access Time = " + FileProps.LastAccessTime); addListItem("Last Write TIme = " + FileProps.LastWriteTime); addListItem("Size = " + FileProps.Length); FileProps = null; >private void button4_Click(object sender, System.EventArgs e) < //Demonstrates how to obtain a list of disk drives. this.listBox1.Items.Clear(); string[] drives = Directory.GetLogicalDrives(); foreach (string drive in drives) < addListItem(drive); >> private void button5_Click(object sender, System.EventArgs e) < //How to get a list of folders (example uses Windows folder). this.listBox1.Items.Clear(); string[] dirs = Directory.GetDirectories(winDir); foreach (string dir in dirs) < addListItem(dir); >> private void button6_Click(object sender, System.EventArgs e) < //How to obtain list of files (example uses Windows folder). this.listBox1.Items.Clear(); string[] files = Directory.GetFiles(winDir); foreach (string i in files) < addListItem(i); >> private void Form1_Load(object sender, System.EventArgs e) < this.button1.Text = "Read Text File"; this.button2.Text = "Write Text File"; this.button3.Text = "View File Information"; this.button4.Text = "List Drives"; this.button5.Text = "List Subfolders"; this.button6.Text = "List Files"; >private void addListItem(string value) < this.listBox1.Items.Add(value); >> >
namespace fso_cs < partial class Form1 < /// /// Required designer variable. /// private System.ComponentModel.IContainer components = null; /// /// Clean up any resources being used. /// /// true if managed resources should be disposed; otherwise, false. protected override void Dispose(bool disposing) < if (disposing && (components != null)) < components.Dispose(); >base.Dispose(disposing); > #region Windows Form Designer generated code /// /// Required method for Designer support - do not modify /// the contents of this method with the code editor. /// private void InitializeComponent() < this.button1 = new System.Windows.Forms.Button(); this.button2 = new System.Windows.Forms.Button(); this.button3 = new System.Windows.Forms.Button(); this.button4 = new System.Windows.Forms.Button(); this.button5 = new System.Windows.Forms.Button(); this.button6 = new System.Windows.Forms.Button(); this.listBox1 = new System.Windows.Forms.ListBox(); this.SuspendLayout(); // button1 this.button1.Location = new System.Drawing.Point(53, 30); this.button1.Name = "button1"; this.button1.Size = new System.Drawing.Size(112, 23); this.button1.TabIndex = 1; this.button1.Text = "button1"; this.button1.Click += new System.EventHandler(this.button1_Click); // button2 this.button2.Location = new System.Drawing.Point(53, 62); this.button2.Name = "button2"; this.button2.Size = new System.Drawing.Size(112, 23); this.button2.TabIndex = 2; this.button2.Text = "button2"; this.button2.Click += new System.EventHandler(this.button2_Click); // button3 this.button3.Location = new System.Drawing.Point(53, 94); this.button3.Name = "button3"; this.button3.Size = new System.Drawing.Size(112, 23); this.button3.TabIndex = 3; this.button3.Text = "button3"; this.button3.Click += new System.EventHandler(this.button3_Click); // button4 this.button4.Location = new System.Drawing.Point(53, 126); this.button4.Name = "button4"; this.button4.Size = new System.Drawing.Size(112, 23); this.button4.TabIndex = 4; this.button4.Text = "button4"; this.button4.Click += new System.EventHandler(this.button4_Click); // button5 this.button5.Location = new System.Drawing.Point(53, 158); this.button5.Name = "button5"; this.button5.Size = new System.Drawing.Size(112, 23); this.button5.TabIndex = 5; this.button5.Text = "button5"; this.button5.Click += new System.EventHandler(this.button5_Click); // button6 this.button6.Location = new System.Drawing.Point(53, 190); this.button6.Name = "button6"; this.button6.Size = new System.Drawing.Size(112, 23); this.button6.TabIndex = 6; this.button6.Text = "button6"; this.button6.Click += new System.EventHandler(this.button6_Click); // listBox1 this.listBox1.FormattingEnabled = true; this.listBox1.Location = new System.Drawing.Point(204, 30); this.listBox1.Name = "listBox1"; this.listBox1.Size = new System.Drawing.Size(270, 199); this.listBox1.TabIndex = 7; // Form1 this.AutoScaleBaseSize = new System.Drawing.Size(5, 13); this.ClientSize = new System.Drawing.Size(525, 273); this.Controls.Add(this.button6); this.Controls.Add(this.button5); this.Controls.Add(this.button4); this.Controls.Add(this.button3); this.Controls.Add(this.button2); this.Controls.Add(this.button1); this.Controls.Add(this.listBox1); this.Name = "Form1"; this.Text = "Form1"; this.Load += new System.EventHandler(this.Form1_Load); this.ResumeLayout(false); >#endregion private System.Windows.Forms.Button button1; private System.Windows.Forms.Button button2; private System.Windows.Forms.Button button3; private System.Windows.Forms.Button button4; private System.Windows.Forms.Button button5; private System.Windows.Forms.Button button6; private System.Windows.Forms.ListBox listBox1; > >
Обратная связь
Были ли сведения на этой странице полезными?
Form1 load в c что это
Загружай VB, и в путь.При этом очень советуем иметь ПРОГРАММНЫЕ МИНИАТЮРЫ, которые можно заказать по aavov@yandex.ru.Они просто необходимы,когда придется читать текст повторно, без лирики. Итак, создаем первый “Стандартный EXE” (как в Главе 1). На экране имеем примерно такую картинку:
Теперь мы найдем место, куда будем заносить собственно программу. Для этого в верхнем ряду окна нажимаем кнопку “Вид”. В выпавшем меню первая строка и есть та, которая нам нужна: “Код”. Показано на рисунке 3.
У нас поверх окна формы Проект1 – Form1 (Форма) появится окно Проект1 – Form1 (Код). Вверху этого окна у нас имеется два выпадающих списка. Слева — список доступных объектов, справа – события для этих объектов. Объектов у нас сейчас два: (General) и Form. Выбираем строку Form. В поле окна кода появились две строки. Что это значит. Первая строка:
Private Sub Form_Load()
говорит о том, что мыначинаем подпрограмму (Private Sub) или правильней процедуру, которая будет выполняться при загрузке (_Load) нашей формы (Form). Загрузка — это возникающее событие, на которое и отреагирует эта процедура. Последняя строка
просто говорит о том, что этой строкой процедура Form_Load завершается.
Вот только выполнять-то пока нечего. В теле процедуры у нас нет ничего. А поэтому мы сейчас туда чего-нибудь напихаем. Первым делом, выведем на нашу форму какой-нибудь текст. По идиотской традиции, самая первая программа должна выводить на экран надпись типа “Hello, world” («Здравствуй, мир»). Мы же, из чувства противоречия, напишем “Я стану программистом”. Для этого вписываем между двух уже имеющихся у нас строк еще одну. У нас получится вот такая процедура:
Private Sub Form_Load()
Form1 .Print «Я стану программистом»
Строка, которую мы только что вписали в процедуру, представляет собой оператор, в котором первое слово Form1 представляет собой объект с которым мы работаем (не даром Visual Basic — это объектно-ориентированный язык). В нашем случае объект — это форма. Второе слово после точки (Print) представляет собой метод, который мы используем, для того чтобы работать с нашим объектом (формой). Наш метод позволит напечатать на объекте данные, которые следуют далее. Так как строка «Я стану программистом» — текстовая, то она взята в кавычки. Таковы правила языка Visual Basic — то бишь синтаксис.
Теперь можно бы посмотреть как это работает, только ни черта у нас не выйдет. Чтобы эта надпись появилась в форме, надо залезть в окно “Свойства – Form1”. На рис. 2 (см. выше) оно подписано как “Свойства выделенного объекта”. Затем в левой колонке найти строчку со свойством “AutoRedraw”. В этой строке только в правой колонке из выпадающего списка выбрать “True”. Теперь окно перерисуется вместе с нашим чудесным текстом и мы сможем увидеть изменения формы после выполнения программой нашего оператора. Нажмем кнопочку со стрелочкой для запуска нашей программы (показано на рис.4) и наслаждаемся ее работой.
Свойство перерисовки, как и всякое другое можно задавать программно. Это намного правильней, так как в ходе выполнения программы часто приходится менять свойства объектов. Перед нашей строчкой добавим еще одну:
Form1.AutoRedraw = True
А в свойствах формы вернем состояние свойства AutoRedraw с True (Истина) на False (Ложь). Запустим программу. Она работает совершенно также. Аналогично можно менять другие свойства формы. В дальнейшем по мере необходимости мы будем обращаться к ним.
Ясное дело, форму можно растягивать. Можно также менять ее положение на экране, двигая квадратик в окне “Размещение формы”.
Еще одно. Можно создавать несколько форм и управлять объектами одной из другой. Для этого в меню выберите “Проект – Добавить форму – Открыть”.
Только если после этого запустить программу, второй формы не увидишь. Чтобы сделать ее видимой, надо прописать в Form1 такой код:
Теперь наш проект надо сохранить. Выбери “Файл – Сохранить проект” или нажми на изображение дискетки. Появиться окно сохранения проекта, которое обычно предлагает путь «C:\Program Files\Microsoft Visual Studio\VB98». Но туда сохранять ни в коем случае не надо, иначе файлы твоего проекта перпутаются с файлами Visual Basic. Лучше создать отдельную папочку с названием, которое отражает суть проекта и сохранить проект в ней. Так надо поступать с каждым проектом. Мы будем сохранять файлы под теми же именами, которые предлагает VB, хотя их, конечно, можно задавать какие угодно.
Последний этап – создание выполняемого (т.е. EXE) файла, то ради чего мы это все делали. Нажми “Файл – Создать Проект1.exe…”, сохраняй и готово. Теперь ты можешь закрыть VB и запускать свой EXE-файл. Поздравляю! Ты создал первую программу на Visual Basic. Вариант этой программы, только несколько расширенный, я привожу ниже. В ней показано изменение некоторых свойств формы. Скопируй ее в тело подпрограммы и поэкспериментируй с ней. Обрати внимание на комментарии. Они выделяются зеленым цветом и пишутся после апострофа. Нужны они только для пояснений, не компилируются и программой не выполняются.
‘******вот некоторые возможности работы с формой*****
Private Sub Form_Load()
Form1.AutoRedraw = True ‘включает перерисовку формы 1
Form1.BackColor = vbBlack ‘меняет цвет формы 1 на черный
Form1.ForeColor = &HFF& ‘меняет цвет текста формы 1 на красный
Form1.BorderStyle = 3 ‘меняет рамку (бордюр) формы 1 на неизменяемую
Form1.Font.Size = 18 ‘меняет размер шрифта формы 1 на 18
Form1.Font.Underline = True ‘подчеркивает текст в форме 1
Form1.Caption = «Моя первая программа» ‘устанавливает заголовок формы 1
Form1. Print «Я стану программистом» ‘выводит текст на форму 1
Form2.Show ‘делает видимой форму 2
Form2.Width = 9000 ‘устанавливает ширину формы 2 равной 9000 твипов
Form2.WindowState = 1 ‘сворачивает форму 2
End Sub
Скачать код можно вверху страницы.
C#. Windows Forms. Практика. Пример, который демонстрирует создание пятиугольной формы
По данному примеру можно научиться разрабатывать Windows Forms приложения, основная форма которых имеет произвольный вид.
Поиск на других Web-ресурсах:
Условие задачи
Разработать приложение Windows Forms, в котором форма есть пятиугольной. На форме разместить кнопку закрытия формы. Рекомендованные координаты в пикселах (x; y) пятиугольника формы: (0; 150), (50; 300), (420; 300), (650; 150), (400; 0).
⇑
Инструкция
1. Создать новый проект по шаблону Windows Forms
Более подробно процесс создания новой формы описывается здесь . После создания форма имеет имя Form1 по умолчанию.
⇑
2. Настройка формы Form1
В окне Properties нужно настроить следующие свойства формы Form1 :
- свойство FormBorderStyle = None ;
- свойство BackColor = Blue (рисунок 1). Чтобы найти цвет Blue нужно перейти на вкладку Web .

Рисунок 1. Установка свойства BackColor
⇑
3. Размещение и настройка кнопки Close на форме
С помощью панели инструментов Toolbox разместить на форме кнопку. В результате система создаст компонент кнопки с именем button1 .
Для кнопки button1 нужно установить следующие свойства:
- Text = «Close» ;
- Location = (150, 200).
⇑
4. Программирование обработчика события клика на кнопке button1
Для программирования события нужно выполнить следующие действия (рисунок 2):
- выделить кнопку button1 ( Close )
- в окне Properties перейти на вкладку Events ;
- в перечне обработчиков событий сделать двойной клик в области события Click . В результате откроется код обработчика этого события. Другой способ вызова кода обработчика события Click – двойной клик мышкой на кнопке, которая размещена на форме.

Рисунок 2. Событие Click компонента button1 в окне Properties
В текст обработчика события нужно добавить следующий код
this.Close();
Вышеприведенная строка с помощью this обращается к экземпляру формы Form1 . Метод Close() формы закрывает форму, таким образом что происходит выход из программы.
⇑
5. Программирование обработчика события Form_Load()
В соответствии с условием задачи, нужно чтобы после запуска форма отображалась в виде пятиугольника. Для этого нужно запрограммировать обработчик события Load формы Form1 . Событие Load вызывается в начале выполнения программы, когда форма появляется на экране (загружается).
Для вызова обработчика события Load нужно выполнить следующие действия (рисунок 3):
- с помощью мышки активировать форму Form1 ;
- в окне Properties во вкладке событий Events сделать двойной клик мышкой в поле события Load . В результате отобразится обработчик события Form1_Load() .

Рисунок 3. Событие Load формы Form1
В обработчике события Load() нужно ввести следующий код
// Обработчик события Form1_Load private void Form1_Load(object sender, EventArgs e) < // 1. Объявить экземпляр типа GraphicsPath - класс библиотеки .NET Framework, // который устанавливает последовательность соединенных линий и кривых. System.Drawing.Drawing2D.GraphicsPath gp = new System.Drawing.Drawing2D.GraphicsPath(); // 2. Создать массив точек, соответствующих координатам // пятиугольника, образовывающего форму. // 2.1. Объявить экземпляр типа "массив точек Point[]". // Point - это класс, который описывает точку на экране. Point[] mp = new Point[5]; // 2.2. Выделить память для каждой точки и заполнить // ее значениями. mp[0] = new Point(0, 150); mp[1] = new Point(50, 300); mp[2] = new Point(420, 300); mp[3] = new Point(650, 150); mp[4] = new Point(400, 0); // 3. Добавить массив точек Point[] в экземпляр gp gp.AddPolygon(mp); // 4. Создать область (Region) на основе последовательности точек gp Region rg = new Region(gp); // 5. Установить область формы this.Region // в новое значение rg this.Region = rg; >
⇑
6. Запуск программы. Результаты
Результат выполнения программы изображен на рисунке 4.

Рисунок 4. Пятиугольная форма