Код автоматически созданный конструктором форм windows

В этом уроке Вы узнаете где находится программный код проекта, как открыть редактор кода. Повторим операторы, которые используются для записи линейных алгоритмов.

Просмотров 1.1к. Обновлено 11 октября 2019

Урок из серии «Программирование на Visual Basic.Net для школьников«.

В предыдущем уроке вы создали свой первый проект. Познакомились со всеми этапами создания проекта.

В этом уроке мы остановимся на программном кода проекта более подробно, повторим операторы, которые используются  для записи линейного алгоритма.

Вы узнаете где находится программный код проекта, как открыть редактор кода.

Повторим оператор объявления переменных, оператор присваивания, познакомимся  с функциями InputBox и MsgBox, которые используются для  ввода/вывода данных.

Содержание

  1. Программный код проекта и редактор кода
  2. Объявление переменных
  3. Присваивание переменным значений
  4. Функция ввода данных
  5. Функция вывода данных
  6. Проект «Переменные»

Программный код проекта и редактор кода

Связанный с формой Form1 программный код находится в файле Form1.vb. Открыть редактор кода можно тремя способами:

  • выбрать команду Посмотреть код  в контекстном меню формы;
  • выполнить щелчок на соответствующей кнопке в обозревателе решений;
  • щелкнуть вкладку  Form1.vb.

Урок 4. Программный код проекта

1. Список объектов

2. Список событий для выбранного объекта

3. Заготовка для обработки события щелчок на кнопке

В верхней части окна редактора кода располагаются два раскрывающихся списка. Левый список содержит все объекты, имеющиеся на форме.

Раскрывающийся список справа содержит список событий, связанных с выбранным объектом, на которые программы может реагировать. Первоначально в этом списке выбрано основное, самое «естественное»  событие  для этого объекта.

В окне редактора кода находится свернутый код, автоматически созданный конструктором форм Windows.

Он генерируется автоматически, если вы добавляете на форму кнопку или какой-то другой элемент управления.

Далее располагается код, который вы пишите собственноручно.

Тот код,  который вы пишите вручную, в большинстве случаев находится в обработчиках событий элементов управления формы.

Чтобы написать программный код для обработчика события, которое идет по умолчанию для элемента управления формы, нужно выбрать  этот элемент на форме и выполните по нему двойной щелчок. Откроется окно редактора кода, и создастся заготовка процедуры обработчика события (пустая процедура, содержащая заголовок и оператор, обозначающий конец процедуры), готовая для редактирования.

Обработчики других событий можно выбрать из выпадающего списка в верхнем правом углу окна редактора кода.

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

В программном коде будем использовать те же алгоритмические конструкции, что и в языке QBasic. Мы их будем постепенно вводить по ходу решения задач.

Первые наши проекты будут содержать программный код, реализующий линейные алгоритмы.  Для записи таких алгоритмов будут необходимы: оператор объявления переменных, функции для ввода и вывода данных   и оператор присваивания.

Объявление переменных

Для использования переменной необходимо выполнить три действия:

  1. Объявить переменную. Сообщить программе имя и тип переменной, которую требуется использовать.
  2. Присвоить переменной значение. Передать переменной значение для хранения.
  3. Непосредственно использовать переменную. Извлечь значение, содержащееся в переменной, и использовать его в программе.

При объявлении переменной необходимо решить, как она будет называться, и какой тип данных будет ей присвоен.

Для объявления переменных используется оператор  Dim.

Синтаксис этого оператора:

Dim

 Имя_переменной

As

 Тип_переменной

Основные типы переменных:

String (текстовые строки);

Integer (целые числа);

Single (дробные числа);

Boolean (True или False).

Пример.

Эта строка кода сообщает программе, что требуется использовать переменную с именем aNumber, и что она должна хранить целые числа (тип данных Integer).

При объявлении нескольких переменных можно перечислять их через запятую:

Dim a As Byte,
    b As String,
    с As Boolean

Присваивание переменным значений

Значение переменной присваивается при помощи знака =, называемого оператором присваивания, как показано в следующем примере.

Эта строка кода берет значение 42 и сохраняет его в ранее объявленной переменной с именем aNumber.

Как показано выше, можно объявить переменную в одной строке кода и присвоить ей значение позже, в другой строке. Это может вызвать ошибку при попытке использовать переменную до присвоения ей значения.

По этой причине рекомендуется объявлять переменные и присваивать им значения в одной и той же строке. Даже если будущее значение переменной пока неизвестно, ей можно присвоить значение по умолчанию. В этом случае код для объявления и присвоения значений тем же самым переменным будет выглядеть так, как показано ниже.

Dim anInteger As Integer = 42 
Dim aSingle As Single = 42.5 
Dim aString As String = "I like candy" 
Dim aBoolean As Boolean = True

При этом далее в коде по-прежнему можно присваивать переменным другие значения.

Функция ввода данных

InputBox() – функция для ввода данных с помощью диалогового окна ввода.

Аргументами этой функции являются две строки, а значением функции – строка, введенная пользователем.

Общий вид функции:

<Переменная> = InputBox(«Подсказка», «Заголовок окна» [, «Значение по умолчанию»])

Здесь:

Подсказка – строка для отображения в диалоговом окне подсказки относительно вводимого значения;

Заголовок – строковое значение, задающее название окна в строке заголовка. Если аргумент Заголовок опущен, то в строку заголовка помещается имя приложения.

Значение по умолчанию — строковое значение, отображаемое в качестве ответного сообщения по умолчанию, если ничего не было введено.
Если параметр Значение по умолчанию опущен, то в текстовом поле ничего не отображается.

Если какие-либо аргументы пропускаются, то нужно оставить разделяющие их запятые.

В процессе выполнения этой функции появляется диалоговое окно с текстовым полем для ввода данных.

Функция InputBox

Если пользователь щелкнет ОК, то значением функции станет строка, введенная пользователем.

Если щелкнет по кнопке Cancel, то значением функции станет строка «Значение по молчанию».

Функция вывода данных

MsgBox() – функция выводит сообщение в специальное окно сообщений, в котором можно разместить определенный набор кнопок и информационный значок о типе сообщения.

Общий вид функции: MsgBox(«Сообщение» [,ЧисКод1+ЧисКод2] [,»Заголовок»])

Здесь:

Сообщение – это сообщение, которое выводиться в окно сообщений;

ЧисКод1+ЧисКод2 – аргумент, определяющий внешний вид окна, значение ЧисКод1 определяет вид пиктограммы, которая помещается на окно сообщения, а значение ЧисКод2 – набор кнопок, размещаемых в окне;

Заголовок – аргумент, определяющий заголовок окна.

Параметры для MsgBox

Например, для функции MsgBox («Сообщение»,48+3,»Заголовок») будет выведено окно сообщений, показанное ниже:

Пример применения функции MsgBox

Проект «Переменные»

В этом проекте будет написана короткая программа, которая создает четыре переменные, присваивает им значения, а затем отображает каждое значение в окне, называемом окном сообщения.

  1. Создайте проект, в котором будет храниться код. Для этого:
    • Загрузите Visual Basic из меню Windows Пуск, если он еще не загружен.
    • В меню файл выберите создать проект.
    • В поле имя введите «Переменные», выберите свою папку для расположения проекта и нажмите кнопку OK. Visual Basic создаст файлы для программы и откроет конструктор формы.
  2. Для создания переменных и отображения их значений дважды щелкните форму, чтобы открыть редактор кода.
    Редактор кода откроется на процедуре  с именем Form1_Load. Код, который записан в этой процедуре,  будет выполнен при первой загрузке формы в память.
  3. В процедуру Form1_Load добавьте следующий код:
    Dim anInteger As Integer = 42 
    Dim aSingle As Single = 39.5 
    Dim aString As String = "I like candy" 
    Dim aBoolean As Boolean = True

    Этот код объявляет четыре переменные и присваивает им значения по умолчанию. Эти четыре переменные являются переменными типов Integer, Single, String и Boolean.

    Примечание. Значения для переменных типа String (текстовые строки)  необходимо заключать  в кавычки (» «). Эта инструкция сообщает программе, что текст нужно интерпретировать именно как фактический текст, а не как имя переменной.

    При присвоении переменной типа Boolean значения True или False не нужно заключать эти слова в кавычки, потому что True и False являются ключевыми словами Visual Basic, имеющими специальное значение.

  4. После кода, написанного на предыдущем этапе, введите следующий код.
    MsgBox(anInteger)
    MsgBox(aSingle)
    MsgBox(aString)
    MsgBox(aBoolean)

    Этот код нужен для вывода новых значений переменных  в диалоговом окне с помощью функции MsgBox.

  5. Нажмите клавишу F5 для запуска приложения.
  6. Нажмите кнопку OK в каждом окне сообщения при их появлении.
  7. Можно закрыть форму, нажав кнопку со знаком «x» в правом верхнем углу формы.
  8. После завершения программы можно вернуться назад и изменить значения, которые присваиваются переменным в коде — вы увидите, что при следующем запуске программы отображаются новые значения.

В этом уроке вы узнали как писать программный код проекта, повторили операторы, которые используются  для записи линейного алгоритма. Оператор присваивания использовали для изменения значений простых переменных.
В следующем уроке будет рассказано о применении оператора присваивания для изменения значений свойств элементов управления.

Следующее занятие: Присваивание значений свойствам в коде

Урок понравился? Отзывы и замечания можно оставить в форме для комментариев, расположенной в нижней части страницы.

Permalink

Cannot retrieve contributors at this time


This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters

Show hidden characters

namespace AppCSharp
{
partial class Form1
{
/// <summary>
/// Обязательная переменная конструктора.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Освободить все используемые ресурсы.
/// </summary>
/// <param name=«disposing«>истинно, если управляемый ресурс должен быть удален; иначе ложно.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Код, автоматически созданный конструктором форм Windows
/// <summary>
/// Требуемый метод для поддержки конструктора — не изменяйте
/// содержимое этого метода с помощью редактора кода.
/// </summary>
private void InitializeComponent()
{
this.label1 = new System.Windows.Forms.Label();
this.buttonPlay = new System.Windows.Forms.Button();
this.SuspendLayout();
//
// label1
//
this.label1.AutoSize = true;
this.label1.Location = new System.Drawing.Point(631, 13);
this.label1.Name = «label1«;
this.label1.Size = new System.Drawing.Size(35, 13);
this.label1.TabIndex = 9;
this.label1.Text = «label1«;
//
// buttonPlay
//
this.buttonPlay.Location = new System.Drawing.Point(634, 170);
this.buttonPlay.Name = «buttonPlay«;
this.buttonPlay.Size = new System.Drawing.Size(164, 23);
this.buttonPlay.TabIndex = 10;
this.buttonPlay.Text = «Сброс процесса«;
this.buttonPlay.UseVisualStyleBackColor = true;
this.buttonPlay.Click += new System.EventHandler(this.buttonPlay_Click);
//
// Form1
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(810, 646);
this.Controls.Add(this.buttonPlay);
this.Controls.Add(this.label1);
this.Name = «Form1«;
this.Text = «Form1«;
this.ResumeLayout(false);
this.PerformLayout();
}
#endregion
private System.Windows.Forms.Label label1;
private System.Windows.Forms.Button buttonPlay;
}
}

Помогите решить проблему, при запуске у меня не запускается форма Form1. в чем может быть проблема?
form1.designer

    /// <summary>
    /// Освободить все используемые ресурсы.
    /// </summary>
    /// <param name="disposing">истинно, если управляемый ресурс должен быть удален; иначе ложно.</param>
    protected override void Dispose(bool disposing)
    {
        if (disposing && (components != null))
        {
            components.Dispose();
        }
        base.Dispose(disposing);
    }

    #region Код, автоматически созданный конструктором форм Windows

    /// <summary>
    /// Обязательный метод для поддержки конструктора - не изменяйте
    /// содержимое данного метода при помощи редактора кода.
    /// </summary>
    private void InitializeComponent()
    {
        this.textBox1 = new System.Windows.Forms.TextBox();
        this.HostButton = new System.Windows.Forms.Button();
        this.ConnectButton = new System.Windows.Forms.Button();
        this.SuspendLayout();
        // 
        // textBox1
        // 
        this.textBox1.Location = new System.Drawing.Point(11, 15);
        this.textBox1.Name = "textBox1";
        this.textBox1.Size = new System.Drawing.Size(128, 20);
        this.textBox1.TabIndex = 0;
        // 
        // HostButton
        // 
        this.HostButton.Location = new System.Drawing.Point(11, 43);
        this.HostButton.Name = "HostButton";
        this.HostButton.Size = new System.Drawing.Size(128, 29);
        this.HostButton.TabIndex = 1;
        this.HostButton.Text = "Host";
        this.HostButton.UseVisualStyleBackColor = true;
        this.HostButton.Click += new System.EventHandler(this.HostButton_Click);
        // 
        // ConnectButton
        // 
        this.ConnectButton.Location = new System.Drawing.Point(11, 78);
        this.ConnectButton.Name = "ConnectButton";
        this.ConnectButton.Size = new System.Drawing.Size(128, 29);
        this.ConnectButton.TabIndex = 2;
        this.ConnectButton.Text = "Connect";
        this.ConnectButton.UseVisualStyleBackColor = true;
        this.ConnectButton.Click += new System.EventHandler(this.ConnectButton_Click);
        // 
        // Form1
        // 
        this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
        this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
        this.ClientSize = new System.Drawing.Size(146, 121);
        this.Controls.Add(this.ConnectButton);
        this.Controls.Add(this.HostButton);
        this.Controls.Add(this.textBox1);
        this.Name = "Form1";
        this.Text = "Easy Chat";
        this.ResumeLayout(false);
        this.PerformLayout();

    }

    #endregion

    private System.Windows.Forms.TextBox textBox1;
    private System.Windows.Forms.Button HostButton;
    private System.Windows.Forms.Button ConnectButton;
}

form1

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Net;

namespace easy_chat
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
            Form1 form = new Form1();
            form.Show();
        }


        private void HostButton_Click(object sender, EventArgs e)
        {
            Form1 form1 = new Form1();
            Chat form = new Chat();
            form.StartServer();
            form.Show();
            form1.Close();
        }

        private void ConnectButton_Click(object sender, EventArgs e)
        {
            Form1 form1 = new Form1();
            Chat form = new Chat();
            IPAddress ip;
            bool isipaddr = IPAddress.TryParse(textBox1.Text,out ip);
            if (isipaddr)
            {
                form.StartClient(ip);
                form.Show();
                form1.Close();
            }
            else
            {
                MessageBox.Show("Incorrect Ip");
            }
        }
    }
}

Program.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace easy_chat
{
    static class Program
    {
        /// <summary>
        /// Главная точка входа для приложения.
        /// </summary>
        [STAThread]
        static void Main()
        {
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            Application.Run(new Form1());
        }
    }
}

Следующий шаг: отображение текущей позиции записи

В дополнение к предоставлению в вашей форме базовых инструментов для навигации вы можете предоставить некую индикацию текущего номера записи, а также общего числа записей в наборе данных. Вы можете сделать это, создав в форме объект метки, который будет отображать текущую позицию. Значение текущей позиции хранится в свойстве Position объекта BindingContext. Если вы хотите обновлять текущую позицию каждый раз, когда используются кнопки навигации, создайте в верхней части кода программы формы процедуру, которая будет определять текущую позицию и отображать ее в форме.

В следующем упражнении вы создадите процедуру с именем Count, которая объявляет две переменные, хранящие общее число записей и номер текущей записи, а затем отображает эту информацию с помощью свойства Text новой метки с именем lblCount.

Создание процедуры Count для отображения информации о текущей записи

  1. Отобразите форму, а затем используйте элемент управления Label и нарисуйте прямо под текстовым полем широкую метку.
  2. Установите свойство Name этой метки равным «lblCount».
  3. Установите свойство Text этой метки равным «Запись 0 из 0».
  4. Чтобы открыть Редактор кода, щелкните в Обозревателе решений на кнопке View Code (Просмотреть код).
  5. Прокрутите окно Редактор кода в самый верх и поместите курсор под тeгом «Windows Form Designer generated code» («Код, автоматически созданный конструктором форм Windows»). Когда мы размещаем процедуру в классе Form, ее можно вызвать из любого места кода формы.
  6. Введите в процедуре Count следующий код программы. Обратите внимание, что Visual Basic автоматически добавляет оператор End Sub.

    Private Sub Count()
    	Dim Records, Current As Integer
    	Records = Me.BindingContext( _
    	DsInstructors1, "Instructors").Count
    	Current = Me.BindingContext( _
    	DsInstructors1, "Instructors").Position + 1
    	lblCount.Text = "Запись " & Current.ToString & " из " & _
    	Records.ToString
    End Sub

    Процедура Count присваивает значение свойства Count целочисленной переменной Records, а значение свойства Position плюс 1 присваивает целочисленной переменной Current. К значению Position добавляется 1 из-за того, что список записей нумеруется с 0 (как массивы и коллекции) — интересный момент для программистов, но не имеющий смысла для пользователя. Наконец, переменные Records и Current преобразуются в строки и вместе с форматирующей информацией копируются в свойство Text объекта lblCount. Текст в этой метке будет иметь следующий формат: «Запись x из y», где x — это значение переменной Current, а y — это значение переменной Records. Теперь в каждую из пяти процедур событий кнопок программы ADO Form добавьте вызов процедуры Count. Это важно, так как каждая кнопка выполняет действие, связанное с навигацией, поэтому метку следует обновлять каждый раз, когда меняется значение свойства Position.

  7. Прокрутите окно вниз до процедуры события btnFirst_Click, добавьте в верхней части процедуры пустую строку и введите следующий вызов процедуры:

    Ваша процедура события будет теперь выглядеть так (хотя первая строка может быть не разделена на две):

    Private Sub btnFirst_Click(ByVal sender As System.Object, _
    	ByVal e As System.EventArgs) Handles btnFirst.Click
    	Me.BindingContext(DsInstructors1, "Instructors").Position = 0
    	Count()
    End Sub
  8. Повторите этот шаг, добавив вызов процедуры Count в каждую из следующих процедур событий вашей программы: btnLast_Click, btnPrev_Click, btnNext_Click и btnLoad_Click. Теперь запустите программу и посмотрите, как работает статистика текущей записи.
  9. Чтобы запустить программу, щелкните на кнопке Start (Начать).

    Примечание. Готовая программа ADO Form лежит в папке c:vbnet03sbsГл.19ado form.

  10. Щелкните на кнопке Загрузка данных. Форма заполнится данными и появится имя первого инструктора. В дополнение к этому под текстовым полем в только что созданной вами новой метке появится текст Запись 1 из 9. Ваша форма должна выглядеть примерно так.

  11. Чтобы посмотреть, как меняется статистика текущей записи при просмотре записей инструкторов из набора данных, щелкните несколько раз на кнопке Следующая запись.
  12. Щелкните на кнопках Предыдущая запись, Первая запись и Последняя запись, чтобы убедиться, что процедура Count работает также и для этих навигационных кнопок.
  13. Чтобы остановить приложение ADO Form, щелкните на кнопке Закрыть в строке заголовка программы.

Вы написали на Visual Basic и ADO.NET вашу первую оболочку для базы данных. В этом примере вы использовали базу данных Microsoft Access. Однако вы обнаружите, что базовые методики доступа к данным других типов, включая базы данных SQL Server и базы данных, хранящихся в удаленных хранилищах, очень похожи на эту. Причина этой одинаковости заключается в распределенной архитектуре ADO.NET, которая использует один и тот же механизм для установления соединения, настройки адаптеров данных и создания наборов данных.

Хотя для установки базового соединения и настройки в сессии ADO.NET требуется выполнить несколько шагов, преимущество этой предварительной работы состоит в том, что манипуляции с информацией из базы данных становятся универсальным процессом. Это верно даже тогда, когда используемые вами данные получаются из удаленного источника или являются результатом объединения различных таблиц базы данных или форматов данных. В
«Представление данных с помощью элемента управления DataGrid»
вы продолжите работать с информацией из базы данных, и научитесь как использовать элемент управления DataGrid для одновременной работы с несколькими записями базы данных.

Доступ к данным в среде веб-форм

Техники доступа к данным, обсуждаемые в этой лекции, были разработаны для использования в среде форм Windows — базовой среде Visual Studio, которую вы использовали для создания большинства программ из этой книги. Однако вы также можете использовать техники программирования ADO.NET в среде веб-форм, что позволяет совместно использовать источники данных из интернета и писать оболочки для баз данных, которые доступны через веб-браузер. Большинство различий между средами форм Windows и веб-форм описано в
«Использование веб-форм для создания интерактивных веб-приложений»
. За дополнительной информацией по написанию приложений баз данных в среде веб-форм обратитесь к справочной системе Visual Basic.

Краткая справка по лекции 19

Чтобы Сделайте следующее
Установить соединение с базой данных Щелкните на команде Server Explorer (Обозреватель серверов) в меню View (Вид), далее на кнопке Connect To Database (Подключиться к базе данных) и с помощью диалогового окна Data Link Properties (Свойства соединения с данными) укажите базу данных, к которой вы хотите открыть доступ.
Создать адаптер данных Щелкните на закладке Data (Данные) в окне Toolbox (Область элементов), перетащите в форму элемент управления OleDbDataAdapter или элемент управления SqlDataAdapter, а затем укажите в Data Adapter Configuration Wizard (Мастере конфигурации адаптера данных) информацию о базе данных, которую вы хотите использовать.
Создать набор данных Щелкните на команде Generate Dataset (Создать dataset) в меню Data (Данные), укажите имя набора данных, а затем убедитесь, что установлен флажок Add This Dataset To The Designer (Добавить этот dataset в конструктор).
Связать элемент управления формы Windows с активным набором данных Добавьте в форму подходящий элемент управления, откройте окно Properties (Свойства), а затем установите свойства категории DataBinding этого элемента управления равными требуемому полю (столбцу) из набора данных. (Одним из наиболее полезных свойств категории DataBinding является Text.)
Заполнить набор данных данными и вывести их в связанном элементе управления в форме Windows

Поместите в процедуру события, которая должна заполнять элементы управления формы, следующий оператор программы. (Замените имена адаптера и набора данных вашими собственными.)

OleDbDataAdapter1.Fill(DsInstructors1)
Добавить в форму Windows элементы управления для навигации

Создайте в форме объекты кнопок и добавьте в каждую из их процедур события Click операторы, которые обновляют свойство Position объекта BindingContext. Например, следующий оператор программы отображает следующую запись из таблицы с именем Instructors, находящейся в наборе данных DsInstructors1:

Me.BindingContext(DsInstructors1, _
	"Instructors").Position += 1

olegall

0 / 0 / 0

Регистрация: 27.01.2014

Сообщений: 116

1

27.01.2014, 11:38. Показов 8212. Ответов 31

Метки нет (Все метки)


Привет. Возникает ошибка «необработанное исключение типа System.StackOverflowException»

На этой строке: Form1 Control = new Form1();

Я обращаюсь к контролам в своём классе из Form1.Designer.cs

Коды классов:

C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
namespace PC_Atmega161
{
class Common
{
 
    Form1 Control = new Form1();
    UART UART_copy = new UART();
 
    public void init()
    {
        // Настройка кнопки отправки запроса
        //buttonSend.Width = dataGridView1.Width;
 
        // Настройка ComboBox
        string[] ComPortNames = SerialPort.GetPortNames();
 
        for (int i = 0; i < ComPortNames.Length; i++)
        {
            Control.comboBox1.Items.Add(ComPortNames[i]);
        }
    }
 
    public void ShowInMessage()
    {
        Console.WriteLine("RowCount" + Control.dataGridView2.RowCount);
        for (int i = Control.dataGridView2.RowCount; i >= 1; i--)
        {
            Console.WriteLine("i: " + i);
            if (i == 1)
            {
                break;
            }
            Control.dataGridView2.Rows[i - 1].Cells[0].Value = Control.dataGridView2.Rows[i - 2].Cells[0].Value;
        }
 
        Control.dataGridView2.Rows[0].Cells[0].Value = UART_copy.InMessage[0].ToString("x");
        Control.dataGridView2.Rows[0].Cells[1].Value = UART_copy.InMessage[1].ToString("x");
        Control.dataGridView2.Rows[0].Cells[2].Value = UART_copy.InMessage[2].ToString("x");
        Control.dataGridView2.Rows[0].Cells[3].Value = UART_copy.InMessage[3].ToString("x");
        Control.dataGridView2.Rows[0].Cells[4].Value = UART_copy.InMessage[4].ToString("x");
        Control.dataGridView2.Rows[0].Cells[5].Value = "0" + UART_copy.InMessage[5].ToString("x");
        Control.dataGridView2.Rows[0].Cells[6].Value = "0" + UART_copy.InMessage[6].ToString("x");
    }
 
}
}
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
using System;
using System.Data;
using System.Data.SqlClient;
using System.Windows.Forms;
using System.Runtime.InteropServices;
using System.IO.Ports;
using System.IO;
using System.Globalization;
using System.Threading;
using System.Collections.Generic;
using System.ComponentModel;
 
namespace PC_Atmega161
{
    partial class Form1
    {
 
        /// <summary>
        /// Требуется переменная конструктора.
        /// </summary>
        private System.ComponentModel.IContainer components = null;
 
        /// <summary>
        /// Освободить все используемые ресурсы.
        /// </summary>
        /// <param name="disposing">истинно, если управляемый ресурс должен быть удален; иначе ложно.</param>
        protected override void Dispose(bool disposing)
        {
            if (disposing && (components != null))
            {
                components.Dispose();
            }
            base.Dispose(disposing);
        }
 
        #region Код, автоматически созданный конструктором форм Windows
 
 
        //private DataGridView dataGridView1 = new DataGridView();
 
        //this.DataGridView1.AllowUserToAddRows = false;
        
 
        /// <summary>
        /// Обязательный метод для поддержки конструктора - не изменяйте
        /// содержимое данного метода при помощи редактора кода.
        /// </summary>
        public void InitializeComponent()
        {
            this.buttonSend = new System.Windows.Forms.Button();
            this.dataGridView1 = new System.Windows.Forms.DataGridView();
            this.label1 = new System.Windows.Forms.Label();
            this.LabelDebug = new System.Windows.Forms.Label();
            this.ButtonDebug = new System.Windows.Forms.Button();
            this.dataGridView2 = new System.Windows.Forms.DataGridView();
            this.label2 = new System.Windows.Forms.Label();
            this.LabelDebug2 = new System.Windows.Forms.Label();
            this.LabelDebug3 = new System.Windows.Forms.Label();
            this.comboBox1 = new System.Windows.Forms.ComboBox();
            this.label3 = new System.Windows.Forms.Label();
            this.button1 = new System.Windows.Forms.Button();
            this.label4 = new System.Windows.Forms.Label();
            this.label5 = new System.Windows.Forms.Label();
            this.label7 = new System.Windows.Forms.Label();
            this.label6 = new System.Windows.Forms.Label();
            this.label8 = new System.Windows.Forms.Label();
            this.button2 = new System.Windows.Forms.Button();
            this.button3 = new System.Windows.Forms.Button();
            ((System.ComponentModel.ISupportInitialize)(this.dataGridView1)).BeginInit();
            ((System.ComponentModel.ISupportInitialize)(this.dataGridView2)).BeginInit();
            this.SuspendLayout();
 
            
            // 
            // buttonSend
            // 
            this.buttonSend.Location = new System.Drawing.Point(64, 207);
            this.buttonSend.Name = "buttonSend";
            this.buttonSend.Size = new System.Drawing.Size(168, 50);
            this.buttonSend.TabIndex = 0;
            this.buttonSend.Text = "Зондировать линию Dir_1";
            this.buttonSend.UseVisualStyleBackColor = true;
            this.buttonSend.Click += new System.EventHandler(this.buttonSend_Click);
            // 
            // dataGridView1
            // 
            // Настройка поля запроса
            this.dataGridView1.AllowUserToAddRows = false;
            this.dataGridView1.AutoSizeColumnsMode = System.Windows.Forms.DataGridViewAutoSizeColumnsMode.AllCells;
            this.dataGridView1.ColumnHeadersHeightSizeMode = System.Windows.Forms.DataGridViewColumnHeadersHeightSizeMode.AutoSize;
            this.dataGridView1.Location = new System.Drawing.Point(64, 87);
            this.dataGridView1.Name = "dataGridView1";
            this.dataGridView1.Size = new System.Drawing.Size(457, 114);
            this.dataGridView1.TabIndex = 1;
            //this.dataGridView1.CellContentClick += new System.Windows.Forms.DataGridViewCellEventHandler(this.dataGridView1_CellContentClick);
 
            this.dataGridView1.RowCount = 1;
            this.dataGridView1.ColumnCount = 4;
            this.dataGridView1.ColumnHeadersVisible = true;
            this.dataGridView1.RowHeadersVisible = false;
 
            this.dataGridView1.Columns[0].Name = "Признак начала ':'";
            this.dataGridView1.Columns[1].Name = "Команда: 0x01, 0x02 или 0x03";
            this.dataGridView1.Columns[2].Name = "Старший байт LRC";
            this.dataGridView1.Columns[3].Name = "Младший байт LRC";
 
 
            this.dataGridView1.Rows[0].Cells[0].Value = "3a";        // Стартовый байт 
            this.dataGridView1.Rows[0].Cells[1].Value = "";          // Команда по умолчанию
            this.dataGridView1.Rows[0].Cells[2].Value = "";          // LRC старший
            this.dataGridView1.Rows[0].Cells[3].Value = "";          // LRC младший
 
            //dataGridView1.Width = 470;
            this.dataGridView1.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.AllCells;
 
            // 
            // label1
            // 
            this.label1.AutoSize = true;
            this.label1.Font = new System.Drawing.Font("Microsoft Sans Serif", 15.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(204)));
            this.label1.Location = new System.Drawing.Point(414, 43);
            this.label1.Name = "label1";
            this.label1.Size = new System.Drawing.Size(84, 25);
            this.label1.TabIndex = 2;
            this.label1.Text = "Запрос";
            
            // 
            // LabelDebug
            // 
            this.LabelDebug.AutoSize = true;
            this.LabelDebug.Location = new System.Drawing.Point(61, 42);
            this.LabelDebug.Name = "LabelDebug";
            this.LabelDebug.Size = new System.Drawing.Size(50, 13);
            this.LabelDebug.TabIndex = 3;
            this.LabelDebug.Text = "Отладка";
            // 
            // ButtonDebug
            // 
            this.ButtonDebug.Location = new System.Drawing.Point(64, 12);
            this.ButtonDebug.Name = "ButtonDebug";
            this.ButtonDebug.Size = new System.Drawing.Size(127, 23);
            this.ButtonDebug.TabIndex = 4;
            this.ButtonDebug.Text = "Кнопка для отладки";
            this.ButtonDebug.UseVisualStyleBackColor = true;
            this.ButtonDebug.Click += new System.EventHandler(this.ButtonDebug_Click);
            // 
            // dataGridView2
            // 
            this.dataGridView2.ColumnHeadersHeightSizeMode = System.Windows.Forms.DataGridViewColumnHeadersHeightSizeMode.AutoSize;
            this.dataGridView2.Location = new System.Drawing.Point(64, 392);
            this.dataGridView2.Name = "dataGridView2";
            this.dataGridView2.Size = new System.Drawing.Size(971, 254);
            this.dataGridView2.TabIndex = 5;
 
            // Настройка поля приёма ответа
            this.dataGridView2.RowCount = 10;
            this.dataGridView2.ColumnCount = 7;
            this.dataGridView2.ColumnHeadersVisible = true;
            this.dataGridView2.RowHeadersVisible = false;
 
            this.dataGridView2.Columns[0].Name = "Признак начала ':'";
            this.dataGridView2.Columns[1].Name = "Данные, t0";
            this.dataGridView2.Columns[2].Name = "Признак «норма/авария» на линии Dir_1";
            this.dataGridView2.Columns[3].Name = "Данные, t1";
            this.dataGridView2.Columns[4].Name = "Признак «норма/авария» на линии Dir_2";
            this.dataGridView2.Columns[5].Name = "Старший байт LRC";
            this.dataGridView2.Columns[6].Name = "Младший байт LRC";
            this.dataGridView2.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.AllCells;
            // 
            // label2
            // 
            this.label2.AutoSize = true;
            this.label2.Font = new System.Drawing.Font("Microsoft Sans Serif", 15.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(204)));
            this.label2.Location = new System.Drawing.Point(414, 352);
            this.label2.Name = "label2";
            this.label2.Size = new System.Drawing.Size(71, 25);
            this.label2.TabIndex = 6;
            this.label2.Text = "Ответ";
            
            // 
            // LabelDebug2
            // 
            this.LabelDebug2.AutoSize = true;
            this.LabelDebug2.Location = new System.Drawing.Point(141, 52);
            this.LabelDebug2.Name = "LabelDebug2";
            this.LabelDebug2.Size = new System.Drawing.Size(50, 13);
            this.LabelDebug2.TabIndex = 7;
            this.LabelDebug2.Text = "Отладка";
            // 
            // LabelDebug3
            // 
            this.LabelDebug3.AutoSize = true;
            this.LabelDebug3.Location = new System.Drawing.Point(231, 53);
            this.LabelDebug3.Name = "LabelDebug3";
            this.LabelDebug3.Size = new System.Drawing.Size(50, 13);
            this.LabelDebug3.TabIndex = 8;
            this.LabelDebug3.Text = "Отладка";
            // 
            // comboBox1
            // 
            this.comboBox1.FormattingEnabled = true;
            this.comboBox1.Location = new System.Drawing.Point(833, 5);
            this.comboBox1.Name = "comboBox1";
            this.comboBox1.Size = new System.Drawing.Size(121, 21);
            this.comboBox1.TabIndex = 9;
            // 
            // label3
            // 
            this.label3.AutoSize = true;
            this.label3.Location = new System.Drawing.Point(731, 9);
            this.label3.Name = "label3";
            this.label3.Size = new System.Drawing.Size(101, 13);
            this.label3.TabIndex = 10;
            this.label3.Text = "Доступные порты:";
            // 
            // button1
            // 
            this.button1.Location = new System.Drawing.Point(960, 4);
            this.button1.Name = "button1";
            this.button1.Size = new System.Drawing.Size(75, 23);
            this.button1.TabIndex = 11;
            this.button1.Text = "Открыть";
            this.button1.UseVisualStyleBackColor = true;
            this.button1.Click += new System.EventHandler(this.button1_Click);
            // 
            // label4
            // 
            this.label4.AutoSize = true;
            this.label4.Location = new System.Drawing.Point(832, 40);
            this.label4.Name = "label4";
            this.label4.Size = new System.Drawing.Size(35, 13);
            this.label4.TabIndex = 12;
            this.label4.Text = "label4";
            // 
            // label5
            // 
            this.label5.AutoSize = true;
            this.label5.Font = new System.Drawing.Font("Microsoft Sans Serif", 15.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(204)));
            this.label5.Location = new System.Drawing.Point(59, 300);
            this.label5.Name = "label5";
            this.label5.Size = new System.Drawing.Size(36, 25);
            this.label5.TabIndex = 13;
            this.label5.Text = "t0:";
            // 
            // label7
            // 
            this.label7.AutoSize = true;
            this.label7.Font = new System.Drawing.Font("Microsoft Sans Serif", 15.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(204)));
            this.label7.Location = new System.Drawing.Point(414, 300);
            this.label7.Name = "label7";
            this.label7.Size = new System.Drawing.Size(36, 25);
            this.label7.TabIndex = 15;
            this.label7.Text = "t1:";
            // 
            // label6
            // 
            this.label6.AutoSize = true;
            this.label6.Font = new System.Drawing.Font("Microsoft Sans Serif", 15.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(204)));
            this.label6.Location = new System.Drawing.Point(163, 300);
            this.label6.Name = "label6";
            this.label6.Size = new System.Drawing.Size(69, 25);
            this.label6.TabIndex = 16;
            this.label6.Text = "Dir_1:";
            // 
            // label8
            // 
            this.label8.AutoSize = true;
            this.label8.Font = new System.Drawing.Font("Microsoft Sans Serif", 15.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(204)));
            this.label8.Location = new System.Drawing.Point(546, 300);
            this.label8.Name = "label8";
            this.label8.Size = new System.Drawing.Size(190, 25);
            this.label8.TabIndex = 17;
            this.label8.Text = "Признак на Dir_2:";
            // 
            // button2
            // 
            this.button2.Location = new System.Drawing.Point(282, 207);
            this.button2.Name = "button2";
            this.button2.Size = new System.Drawing.Size(168, 50);
            this.button2.TabIndex = 18;
            this.button2.Text = "Зондировать линию Dir_2";
            this.button2.UseVisualStyleBackColor = true;
            this.button2.Click += new System.EventHandler(this.button2_Click);
            // 
            // button3
            // 
            this.button3.Location = new System.Drawing.Point(485, 207);
            this.button3.Name = "button3";
            this.button3.Size = new System.Drawing.Size(181, 50);
            this.button3.TabIndex = 19;
            this.button3.Text = "Зондировать линии Dir_1, Dir_2";
            this.button3.UseVisualStyleBackColor = true;
            this.button3.Click += new System.EventHandler(this.button3_Click);
            // 
            // Form1
            // 
            this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
            this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
            this.BackColor = System.Drawing.SystemColors.Control;
            this.ClientSize = new System.Drawing.Size(1184, 658);
            this.Controls.Add(this.button3);
            this.Controls.Add(this.button2);
            this.Controls.Add(this.label8);
            this.Controls.Add(this.label6);
            this.Controls.Add(this.label7);
            this.Controls.Add(this.label5);
            this.Controls.Add(this.label4);
            this.Controls.Add(this.button1);
            this.Controls.Add(this.label3);
            this.Controls.Add(this.comboBox1);
            this.Controls.Add(this.LabelDebug3);
            this.Controls.Add(this.LabelDebug2);
            this.Controls.Add(this.label2);
            this.Controls.Add(this.dataGridView2);
            this.Controls.Add(this.ButtonDebug);
            this.Controls.Add(this.LabelDebug);
            this.Controls.Add(this.label1);
            this.Controls.Add(this.dataGridView1);
            this.Controls.Add(this.buttonSend);
            this.Name = "Form1";
            this.Text = "Form1";
            //this.Load += new System.EventHandler(this.Form1_Load);
            ((System.ComponentModel.ISupportInitialize)(this.dataGridView1)).EndInit();
            ((System.ComponentModel.ISupportInitialize)(this.dataGridView2)).EndInit();
            this.ResumeLayout(false);
            this.PerformLayout();
 
        }
 
 
        #endregion
 
        public System.Windows.Forms.Button buttonSend;
        public Label label1;
        public Label LabelDebug;
        public Button ButtonDebug;
        public DataGridView dataGridView2;
        public DataGridView dataGridView1;
        public Label label2;
        public Label LabelDebug2;
        public Label LabelDebug3;
        public ComboBox comboBox1;
        public Label label3;
        public Button button1;
        public Label label4;
        public Label label5;
        public Label label7;
        public Label label6;
        public Label label8;
        public Button button2;
        public Button button3;
    }
}

__________________
Помощь в написании контрольных, курсовых и дипломных работ, диссертаций здесь



0



1448 / 1120 / 345

Регистрация: 11.04.2011

Сообщений: 2,615

27.01.2014, 12:23

2

Цитата
Сообщение от olegall
Посмотреть сообщение

Я обращаюсь к контролам в своём классе из Form1.Designer.cs

В файлы, которые заканчиваются на Designer.cs вообще лезть не надо своими шаловливыми ручками. Особенно, когда знания языка стремятся к нулю. Пишите свой код в файле Form1.cs.



0



0 / 0 / 0

Регистрация: 27.01.2014

Сообщений: 116

27.01.2014, 12:45

 [ТС]

3

Допустим. Что с ответом на мой вопрос?



0



1448 / 1120 / 345

Регистрация: 11.04.2011

Сообщений: 2,615

27.01.2014, 12:50

4

olegall, Вы предлагаете мне порытся среди кучи автоматически сгенерированного кода, чтобы найти пару строк кривонаписанного вашего? Ну уж нет …



0



olegall

0 / 0 / 0

Регистрация: 27.01.2014

Сообщений: 116

27.01.2014, 12:56

 [ТС]

5

Убрал свои добавления в дизайнере

C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
using System;
using System.Data;
using System.Data.SqlClient;
using System.Windows.Forms;
using System.Runtime.InteropServices;
using System.IO.Ports;
using System.IO;
using System.Globalization;
using System.Threading;
using System.Collections.Generic;
using System.ComponentModel;
 
namespace PC_Atmega161
{
    partial class Form1
    {
 
        /// <summary>
        /// Требуется переменная конструктора.
        /// </summary>
        private System.ComponentModel.IContainer components = null;
 
        /// <summary>
        /// Освободить все используемые ресурсы.
        /// </summary>
        /// <param name="disposing">истинно, если управляемый ресурс должен быть удален; иначе ложно.</param>
        protected override void Dispose(bool disposing)
        {
            if (disposing && (components != null))
            {
                components.Dispose();
            }
            base.Dispose(disposing);
        }
 
        #region Код, автоматически созданный конструктором форм Windows
 
 
        //private DataGridView dataGridView1 = new DataGridView();
 
        //this.DataGridView1.AllowUserToAddRows = false;
        
 
        /// <summary>
        /// Обязательный метод для поддержки конструктора - не изменяйте
        /// содержимое данного метода при помощи редактора кода.
        /// </summary>
        public void InitializeComponent()
        {
            this.buttonSend = new System.Windows.Forms.Button();
            this.dataGridView1 = new System.Windows.Forms.DataGridView();
            this.label1 = new System.Windows.Forms.Label();
            this.LabelDebug = new System.Windows.Forms.Label();
            this.ButtonDebug = new System.Windows.Forms.Button();
            this.dataGridView2 = new System.Windows.Forms.DataGridView();
            this.label2 = new System.Windows.Forms.Label();
            this.LabelDebug2 = new System.Windows.Forms.Label();
            this.LabelDebug3 = new System.Windows.Forms.Label();
            this.comboBox1 = new System.Windows.Forms.ComboBox();
            this.label3 = new System.Windows.Forms.Label();
            this.button1 = new System.Windows.Forms.Button();
            this.label4 = new System.Windows.Forms.Label();
            this.label5 = new System.Windows.Forms.Label();
            this.label7 = new System.Windows.Forms.Label();
            this.label6 = new System.Windows.Forms.Label();
            this.label8 = new System.Windows.Forms.Label();
            this.button2 = new System.Windows.Forms.Button();
            this.button3 = new System.Windows.Forms.Button();
            ((System.ComponentModel.ISupportInitialize)(this.dataGridView1)).BeginInit();
            ((System.ComponentModel.ISupportInitialize)(this.dataGridView2)).BeginInit();
            this.SuspendLayout();
 
            
            // 
            // buttonSend
            // 
            this.buttonSend.Location = new System.Drawing.Point(64, 207);
            this.buttonSend.Name = "buttonSend";
            this.buttonSend.Size = new System.Drawing.Size(168, 50);
            this.buttonSend.TabIndex = 0;
            this.buttonSend.Text = "Зондировать линию Dir_1";
            this.buttonSend.UseVisualStyleBackColor = true;
            this.buttonSend.Click += new System.EventHandler(this.buttonSend_Click);
            // 
            // dataGridView1
            // 
            // Настройка поля запроса
            this.dataGridView1.AllowUserToAddRows = false;
            this.dataGridView1.AutoSizeColumnsMode = System.Windows.Forms.DataGridViewAutoSizeColumnsMode.AllCells;
            this.dataGridView1.ColumnHeadersHeightSizeMode = System.Windows.Forms.DataGridViewColumnHeadersHeightSizeMode.AutoSize;
            this.dataGridView1.Location = new System.Drawing.Point(64, 87);
            this.dataGridView1.Name = "dataGridView1";
            this.dataGridView1.Size = new System.Drawing.Size(457, 114);
            this.dataGridView1.TabIndex = 1;
            //this.dataGridView1.CellContentClick += new System.Windows.Forms.DataGridViewCellEventHandler(this.dataGridView1_CellContentClick);
 
 
            /*
            this.dataGridView1.RowCount = 1;
            this.dataGridView1.ColumnCount = 4;
            this.dataGridView1.ColumnHeadersVisible = true;
            this.dataGridView1.RowHeadersVisible = false;
 
            this.dataGridView1.Columns[0].Name = "Признак начала ':'";
            this.dataGridView1.Columns[1].Name = "Команда: 0x01, 0x02 или 0x03";
            this.dataGridView1.Columns[2].Name = "Старший байт LRC";
            this.dataGridView1.Columns[3].Name = "Младший байт LRC";
 
 
            this.dataGridView1.Rows[0].Cells[0].Value = "3a";        // Стартовый байт 
            this.dataGridView1.Rows[0].Cells[1].Value = "";          // Команда по умолчанию
            this.dataGridView1.Rows[0].Cells[2].Value = "";          // LRC старший
            this.dataGridView1.Rows[0].Cells[3].Value = "";          // LRC младший
            */
            //dataGridView1.Width = 470;
            this.dataGridView1.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.AllCells;
 
            // 
            // label1
            // 
            this.label1.AutoSize = true;
            this.label1.Font = new System.Drawing.Font("Microsoft Sans Serif", 15.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(204)));
            this.label1.Location = new System.Drawing.Point(414, 43);
            this.label1.Name = "label1";
            this.label1.Size = new System.Drawing.Size(84, 25);
            this.label1.TabIndex = 2;
            this.label1.Text = "Запрос";
            
            // 
            // LabelDebug
            // 
            this.LabelDebug.AutoSize = true;
            this.LabelDebug.Location = new System.Drawing.Point(61, 42);
            this.LabelDebug.Name = "LabelDebug";
            this.LabelDebug.Size = new System.Drawing.Size(50, 13);
            this.LabelDebug.TabIndex = 3;
            this.LabelDebug.Text = "Отладка";
            // 
            // ButtonDebug
            // 
            this.ButtonDebug.Location = new System.Drawing.Point(64, 12);
            this.ButtonDebug.Name = "ButtonDebug";
            this.ButtonDebug.Size = new System.Drawing.Size(127, 23);
            this.ButtonDebug.TabIndex = 4;
            this.ButtonDebug.Text = "Кнопка для отладки";
            this.ButtonDebug.UseVisualStyleBackColor = true;
            this.ButtonDebug.Click += new System.EventHandler(this.ButtonDebug_Click);
            // 
            // dataGridView2
            // 
            this.dataGridView2.ColumnHeadersHeightSizeMode = System.Windows.Forms.DataGridViewColumnHeadersHeightSizeMode.AutoSize;
            this.dataGridView2.Location = new System.Drawing.Point(64, 392);
            this.dataGridView2.Name = "dataGridView2";
            this.dataGridView2.Size = new System.Drawing.Size(971, 254);
            this.dataGridView2.TabIndex = 5;
 
 
            /*
            // Настройка поля приёма ответа
            this.dataGridView2.RowCount = 10;
            this.dataGridView2.ColumnCount = 7;
            this.dataGridView2.ColumnHeadersVisible = true;
            this.dataGridView2.RowHeadersVisible = false;
 
            this.dataGridView2.Columns[0].Name = "Признак начала ':'";
            this.dataGridView2.Columns[1].Name = "Данные, t0";
            this.dataGridView2.Columns[2].Name = "Признак «норма/авария» на линии Dir_1";
            this.dataGridView2.Columns[3].Name = "Данные, t1";
            this.dataGridView2.Columns[4].Name = "Признак «норма/авария» на линии Dir_2";
            this.dataGridView2.Columns[5].Name = "Старший байт LRC";
            this.dataGridView2.Columns[6].Name = "Младший байт LRC";
            this.dataGridView2.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.AllCells;
            */
            // 
            // label2
            // 
            this.label2.AutoSize = true;
            this.label2.Font = new System.Drawing.Font("Microsoft Sans Serif", 15.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(204)));
            this.label2.Location = new System.Drawing.Point(414, 352);
            this.label2.Name = "label2";
            this.label2.Size = new System.Drawing.Size(71, 25);
            this.label2.TabIndex = 6;
            this.label2.Text = "Ответ";
            
            // 
            // LabelDebug2
            // 
            this.LabelDebug2.AutoSize = true;
            this.LabelDebug2.Location = new System.Drawing.Point(141, 52);
            this.LabelDebug2.Name = "LabelDebug2";
            this.LabelDebug2.Size = new System.Drawing.Size(50, 13);
            this.LabelDebug2.TabIndex = 7;
            this.LabelDebug2.Text = "Отладка";
            // 
            // LabelDebug3
            // 
            this.LabelDebug3.AutoSize = true;
            this.LabelDebug3.Location = new System.Drawing.Point(231, 53);
            this.LabelDebug3.Name = "LabelDebug3";
            this.LabelDebug3.Size = new System.Drawing.Size(50, 13);
            this.LabelDebug3.TabIndex = 8;
            this.LabelDebug3.Text = "Отладка";
            // 
            // comboBox1
            // 
            this.comboBox1.FormattingEnabled = true;
            this.comboBox1.Location = new System.Drawing.Point(833, 5);
            this.comboBox1.Name = "comboBox1";
            this.comboBox1.Size = new System.Drawing.Size(121, 21);
            this.comboBox1.TabIndex = 9;
            // 
            // label3
            // 
            this.label3.AutoSize = true;
            this.label3.Location = new System.Drawing.Point(731, 9);
            this.label3.Name = "label3";
            this.label3.Size = new System.Drawing.Size(101, 13);
            this.label3.TabIndex = 10;
            this.label3.Text = "Доступные порты:";
            // 
            // button1
            // 
            this.button1.Location = new System.Drawing.Point(960, 4);
            this.button1.Name = "button1";
            this.button1.Size = new System.Drawing.Size(75, 23);
            this.button1.TabIndex = 11;
            this.button1.Text = "Открыть";
            this.button1.UseVisualStyleBackColor = true;
            this.button1.Click += new System.EventHandler(this.button1_Click);
            // 
            // label4
            // 
            this.label4.AutoSize = true;
            this.label4.Location = new System.Drawing.Point(832, 40);
            this.label4.Name = "label4";
            this.label4.Size = new System.Drawing.Size(35, 13);
            this.label4.TabIndex = 12;
            this.label4.Text = "label4";
            // 
            // label5
            // 
            this.label5.AutoSize = true;
            this.label5.Font = new System.Drawing.Font("Microsoft Sans Serif", 15.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(204)));
            this.label5.Location = new System.Drawing.Point(59, 300);
            this.label5.Name = "label5";
            this.label5.Size = new System.Drawing.Size(36, 25);
            this.label5.TabIndex = 13;
            this.label5.Text = "t0:";
            // 
            // label7
            // 
            this.label7.AutoSize = true;
            this.label7.Font = new System.Drawing.Font("Microsoft Sans Serif", 15.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(204)));
            this.label7.Location = new System.Drawing.Point(414, 300);
            this.label7.Name = "label7";
            this.label7.Size = new System.Drawing.Size(36, 25);
            this.label7.TabIndex = 15;
            this.label7.Text = "t1:";
            // 
            // label6
            // 
            this.label6.AutoSize = true;
            this.label6.Font = new System.Drawing.Font("Microsoft Sans Serif", 15.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(204)));
            this.label6.Location = new System.Drawing.Point(163, 300);
            this.label6.Name = "label6";
            this.label6.Size = new System.Drawing.Size(69, 25);
            this.label6.TabIndex = 16;
            this.label6.Text = "Dir_1:";
            // 
            // label8
            // 
            this.label8.AutoSize = true;
            this.label8.Font = new System.Drawing.Font("Microsoft Sans Serif", 15.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(204)));
            this.label8.Location = new System.Drawing.Point(546, 300);
            this.label8.Name = "label8";
            this.label8.Size = new System.Drawing.Size(190, 25);
            this.label8.TabIndex = 17;
            this.label8.Text = "Признак на Dir_2:";
            // 
            // button2
            // 
            this.button2.Location = new System.Drawing.Point(282, 207);
            this.button2.Name = "button2";
            this.button2.Size = new System.Drawing.Size(168, 50);
            this.button2.TabIndex = 18;
            this.button2.Text = "Зондировать линию Dir_2";
            this.button2.UseVisualStyleBackColor = true;
            this.button2.Click += new System.EventHandler(this.button2_Click);
            // 
            // button3
            // 
            this.button3.Location = new System.Drawing.Point(485, 207);
            this.button3.Name = "button3";
            this.button3.Size = new System.Drawing.Size(181, 50);
            this.button3.TabIndex = 19;
            this.button3.Text = "Зондировать линии Dir_1, Dir_2";
            this.button3.UseVisualStyleBackColor = true;
            this.button3.Click += new System.EventHandler(this.button3_Click);
            // 
            // Form1
            // 
            this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
            this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
            this.BackColor = System.Drawing.SystemColors.Control;
            this.ClientSize = new System.Drawing.Size(1184, 658);
            this.Controls.Add(this.button3);
            this.Controls.Add(this.button2);
            this.Controls.Add(this.label8);
            this.Controls.Add(this.label6);
            this.Controls.Add(this.label7);
            this.Controls.Add(this.label5);
            this.Controls.Add(this.label4);
            this.Controls.Add(this.button1);
            this.Controls.Add(this.label3);
            this.Controls.Add(this.comboBox1);
            this.Controls.Add(this.LabelDebug3);
            this.Controls.Add(this.LabelDebug2);
            this.Controls.Add(this.label2);
            this.Controls.Add(this.dataGridView2);
            this.Controls.Add(this.ButtonDebug);
            this.Controls.Add(this.LabelDebug);
            this.Controls.Add(this.label1);
            this.Controls.Add(this.dataGridView1);
            this.Controls.Add(this.buttonSend);
            this.Name = "Form1";
            this.Text = "Form1";
            //this.Load += new System.EventHandler(this.Form1_Load);
            ((System.ComponentModel.ISupportInitialize)(this.dataGridView1)).EndInit();
            ((System.ComponentModel.ISupportInitialize)(this.dataGridView2)).EndInit();
            this.ResumeLayout(false);
            this.PerformLayout();
 
        }
 
 
        #endregion
 
        public System.Windows.Forms.Button buttonSend;
        public Label label1;
        public Label LabelDebug;
        public Button ButtonDebug;
        public DataGridView dataGridView2;
        public DataGridView dataGridView1;
        public Label label2;
        public Label LabelDebug2;
        public Label LabelDebug3;
        public ComboBox comboBox1;
        public Label label3;
        public Button button1;
        public Label label4;
        public Label label5;
        public Label label7;
        public Label label6;
        public Label label8;
        public Button button2;
        public Button button3;
        
        
        
    }
 
}



0



Эксперт .NET

5459 / 4232 / 1208

Регистрация: 12.10.2013

Сообщений: 12,223

Записей в блоге: 2

27.01.2014, 13:01

6

А что вот эта строка значит: Form1 Control = new Form1()? Вы хотите получить коллекцию всех элементов управления на основной форме?



0



745 / 486 / 187

Регистрация: 30.12.2012

Сообщений: 1,278

Записей в блоге: 2

27.01.2014, 13:01

7

olegall, покажите код обработчиков событий нажатия на кнопки



0



olegall

0 / 0 / 0

Регистрация: 27.01.2014

Сообщений: 116

27.01.2014, 13:23

 [ТС]

8

Цитата
Сообщение от insite2012
Посмотреть сообщение

А что вот эта строка значит: Form1 Control = new Form1()? Вы хотите получить коллекцию всех элементов управления на основной форме?

Да именно так. Создаю экземпляр формы, чтобы через него обращаться к контролам из своего класса. Если есть лучшее решение — скажите

Добавлено через 11 минут

Цитата
Сообщение от Tsin
Посмотреть сообщение

olegall, покажите код обработчиков событий нажатия на кнопки

C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.IO.Ports;
 
 
namespace PC_Atmega161
{
    public partial class Form1 : Form
    {
        Common CommonCopy = new Common();
        UART UART_copy = new UART();
 
 
 
        
        public Form1()
        {
            Console.WriteLine("|||||" + " Hey " + "|||||");
        }
        
        private void ButtonDebug_Click(object sender, EventArgs e)
        {
            string[] ports = SerialPort.GetPortNames();
            LabelDebug.Text = ports[0];
        }
 
        private void buttonSend_Click(object sender, EventArgs e)
        {
 
            //CommonCopy.FillRequest(buttonSend.Text);
            UART_copy.SerialPort1.Write(UART_copy.Request, 0, UART_copy.Request.Length);
        }
        private void button2_Click(object sender, EventArgs e)
        {
            //CommonCopy.FillRequest(button2.Text);
            UART_copy.SerialPort1.Write(UART_copy.Request, 0, UART_copy.Request.Length);
        }
        private void button3_Click(object sender, EventArgs e)
        {
            //CommonCopy.FillRequest(button3.Text);
            UART_copy.SerialPort1.Write(UART_copy.Request, 0, UART_copy.Request.Length);
        }
 
        // Открыть COM порт
        private void button1_Click(object sender, EventArgs e)
        {
            //CommonCopy.OpenCloseChosenPort();
        }
       
    }
}



0



647 / 582 / 170

Регистрация: 17.07.2012

Сообщений: 1,649

Записей в блоге: 1

27.01.2014, 13:28

9

У вас при создании экземпляра формы создается объект Common, а при создании Common — объект формы.



0



0 / 0 / 0

Регистрация: 27.01.2014

Сообщений: 116

27.01.2014, 13:52

 [ТС]

10

Ну а мне так нужно — что же делать? У меня есть несколько классов и мне надо, чтобы из любого класса я обратился к данным любого другого класса. Или так нельзя?



0



647 / 582 / 170

Регистрация: 17.07.2012

Сообщений: 1,649

Записей в блоге: 1

27.01.2014, 14:24

11

У вас рекурсивно создаются объекты вплоть до переполнения стека.

Я не могу подсказать как вам нужно сделать, ибо я не совсем понимаю что вы хотите.



0



0 / 0 / 0

Регистрация: 27.01.2014

Сообщений: 116

27.01.2014, 14:43

 [ТС]

12

Конкретно — у меня есть 2 класса: UART.cs и common.cs. Из любого из этих классов я хочу обращаться (изменять) данные другого класса, а также обращаться к элементам формы из файла Form1.Designer.cs



0



insite2012

Эксперт .NET

5459 / 4232 / 1208

Регистрация: 12.10.2013

Сообщений: 12,223

Записей в блоге: 2

27.01.2014, 15:28

13

Не пойму, зачем обращаться из класса к элементам управления формы, никакой инкапсуляции…
А серьезно — скажите точнее, что требуется. Из класса, после создания экземпляра этого класса, все что угодно можно вывести на форму. Ведь то, что будет выводиться, все равно в самом классе формируется, так ведь? Ну вот и выводите. В классе private поля, public свойства, возвращающие значения полей и все.

Добавлено через 8 минут
Вот самый элементарный пример, когда экземпляр класса меняет надпись на метке основной формы.

C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
 
namespace WindowsFormsApplication1
{
    public partial class Form1 : Form
    {
        public List<Control> controls;
        public Form1()
        {
            InitializeComponent();
            this.Load+=new EventHandler(Form1_Load);
        }
        private void Form1_Load(object sender, EventArgs e)
        {
            My m = new My();
            label1.Text = m.prop;
        }
    }
  
    class My
    {
        private string myString;
 
        public My()
        {
            myString = "This is label on the Form1";
        }
        public string prop
        {
            get
            {
                return myString;
            }
        }
       
    }
}



0



olegall

0 / 0 / 0

Регистрация: 27.01.2014

Сообщений: 116

27.01.2014, 15:46

 [ТС]

14

Я спроектировал приложение так: Есть класс, относящийся к COM порту, UART. Там методы парсинга посылки, чтения байт и т.п. Есть класс общего назначения, не знал как его назвать — назвал Common. Есть класс Form1 в файле Form1.Designer.cs — созданный си шарпом.

Из кода видно, что, например, методы Common обращаются к данным из Form1 и UART. Ну и так далее. По моей затее методы какого-либо класса могут обращаться к данным любого класса, свободно. Получается конфликт и переполнение стека. Как же мне сделать?

Зачем я так делаю? Что поделить код на логические порции (классы) и уменьшить длину листингов. Если я неправильно спроектировал — буду рад услышать правильные мысли

C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.IO.Ports;
 
 
namespace PC_Atmega161
{
    public partial class Form1 : Form
    {
        Common CommonCopy = new Common();
        UART UART_copy = new UART();
 
 
 
        
        public Form1()
        {
            Console.WriteLine("|||||" + " Hey " + "|||||");
        }
        
        private void ButtonDebug_Click(object sender, EventArgs e)
        {
            string[] ports = SerialPort.GetPortNames();
            LabelDebug.Text = ports[0];
        }
 
        private void buttonSend_Click(object sender, EventArgs e)
        {
 
            //CommonCopy.FillRequest(buttonSend.Text);
            UART_copy.SerialPort1.Write(UART_copy.Request, 0, UART_copy.Request.Length);
        }
        private void button2_Click(object sender, EventArgs e)
        {
            //CommonCopy.FillRequest(button2.Text);
            UART_copy.SerialPort1.Write(UART_copy.Request, 0, UART_copy.Request.Length);
        }
        private void button3_Click(object sender, EventArgs e)
        {
            //CommonCopy.FillRequest(button3.Text);
            UART_copy.SerialPort1.Write(UART_copy.Request, 0, UART_copy.Request.Length);
        }
 
        // Открыть COM порт
        private void button1_Click(object sender, EventArgs e)
        {
            //CommonCopy.OpenCloseChosenPort();
        }
       
    }
}

C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
using System;
using System.Data;
using System.Data.SqlClient;
using System.Windows.Forms;
using System.Runtime.InteropServices;
using System.IO.Ports;
using System.IO;
using System.Globalization;
using System.Threading;
using System.Collections.Generic;
using System.ComponentModel;
 
namespace PC_Atmega161
{
    class Common
    {
        /*
        Form1 form;
         
        Common( Form1 reference)
        {
               form = reference;
        }*/
 
        Form1 Control = new Form1();
        UART UART_copy = new UART();        
        
        public void init()
        {
            // Настройка кнопки отправки запроса
            //buttonSend.Width = dataGridView1.Width;
 
            // Настройка ComboBox
            string[] ComPortNames = SerialPort.GetPortNames();
 
            for (int i = 0; i < ComPortNames.Length; i++)
            {
                Control.comboBox1.Items.Add(ComPortNames[i]);
            }
        }
 
        public void OpenCloseChosenPort()
        {
                  
            //Control.rrr = 1;
            
            if (Control.button1.Text == "Открыть")
            {
                UART_copy.SerialPort1.PortName = Control.comboBox1.SelectedItem.ToString();
                UART_copy.SerialPort1.Open();
                if (UART_copy.SerialPort1.IsOpen)
                {
                    Control.label4.Text = "Порт " + Control.comboBox1.SelectedItem.ToString() + " успешно открыт";
                    Control.button1.Text = "Закрыть";
                }
                else
                {
                    Control.label4.Text = "Порт " + Control.comboBox1.SelectedItem.ToString() + " открыть не удалось";
                }
            }
            else
                if (Control.button1.Text == "Закрыть")
                {
                    UART_copy.SerialPort1.Close();
                    Control.label4.Text = "Порт " + Control.comboBox1.SelectedItem.ToString() + " закрыт";
                    Control.button1.Text = "Открыть";
                }
        }
 
        public void AnalyzeLinesStatus()
        {
            
            Control.label6.Text += " норма";
            switch (UART_copy.InMessage[5])
            {
                case 0x81:
                    Control.label6.Text += " норма";
                    break;
                case 0x01:
                    Control.label6.Text += " АВАРИЯ";
                    break;
                case 0x82:
                    Control.label8.Text += " норма";
                    break;
                case 0x02:
                    Control.label8.Text += " АВАРИЯ";
                    break;
            }
 
 
            switch (UART_copy.InMessage[5])
            {
                case 0x81:
 
                        ushort MeasuredTimeDir1OK = (ushort)((UART_copy.InMessage[3] << 8 | UART_copy.InMessage[4] << 0) * 1.1);  // 1.1 - 1.1 мс - дискрет (см. расчёты к прошивке)
                        Control.label5.Text = "t1: " + MeasuredTimeDir1OK + " мкс";
                        Control.label6.Text += " норма";
                    break;
 
                case 0x01:
 
                    ushort MeasuredTimeDir1Danger = (ushort)(UART_copy.InMessage[3] << 8 | UART_copy.InMessage[4] << 0);
                        Control.label5.Text = "t1: " + MeasuredTimeDir1Danger + " мкс";
                        Control.label6.Text = "Dir1: АВАРИЯ";
                    break;
            }
 
            switch (UART_copy.InMessage[10])
            {
                case 0x82:
 
                        ushort MeasuredTimeDir2OK = (ushort)((UART_copy.InMessage[8] << 8 | UART_copy.InMessage[9] << 0) * 1.1);  // 1.1 - 1.1 мс - дискрет (см. расчёты к прошивке)
                        Control.label7.Text = "t2: " + MeasuredTimeDir2OK + " мкс";
                        Control.label8.Text += " норма";
                    break;
                case 0x02:
 
                    ushort MeasuredTimeDir2Danger = (ushort)(UART_copy.InMessage[8] << 8 | UART_copy.InMessage[9] << 0);
                        Control.label7.Text = "t2: " + MeasuredTimeDir2Danger + " мкс";
                        Control.label8.Text = "Dir2: АВАРИЯ";
                    break;
            }
            if (UART_copy.Request[1] == 0x01)
            {
                Control.label7.Text = "";
                Control.label8.Text = "";
            }
            if (UART_copy.Request[1] == 0x02)
            {
                Control.label5.Text = "";
                Control.label6.Text = "";
            }
        }
 
        public void ShowInMessage()
        {
            Console.WriteLine("RowCount" + Control.dataGridView2.RowCount);
            for (int i = Control.dataGridView2.RowCount; i >= 1; i--)
            {
                Console.WriteLine("i: " + i);
                if (i == 1)
                {
                    break;
                }
                Control.dataGridView2.Rows[i - 1].Cells[0].Value = Control.dataGridView2.Rows[i - 2].Cells[0].Value;
            }
 
            Control.dataGridView2.Rows[0].Cells[0].Value = UART_copy.InMessage[0].ToString("x");
            Control.dataGridView2.Rows[0].Cells[1].Value = UART_copy.InMessage[1].ToString("x");
            Control.dataGridView2.Rows[0].Cells[2].Value = UART_copy.InMessage[2].ToString("x");
            Control.dataGridView2.Rows[0].Cells[3].Value = UART_copy.InMessage[3].ToString("x");
            Control.dataGridView2.Rows[0].Cells[4].Value = UART_copy.InMessage[4].ToString("x");
            Control.dataGridView2.Rows[0].Cells[5].Value = "0" + UART_copy.InMessage[5].ToString("x");
            Control.dataGridView2.Rows[0].Cells[6].Value = "0" + UART_copy.InMessage[6].ToString("x");
        }
 
 
        public void FillRequest(string ButtonText)
        {
            // Заполнение элементов массива
            UART_copy.StartSign = Control.dataGridView1.Rows[0].Cells[0].Value.ToString();
            UART_copy.Request[0] = Convert.ToByte(UART_copy.StartSign, 16);
 
            //LabelDebug.Text = "|||||||||||||||||||||||||||||||||||||   " + ButtonText;    
            switch (ButtonText)
            {
                case "Зондировать линию Dir_1":
                    Control.dataGridView1.Rows[0].Cells[1].Value = "01";
                    break;
 
                case "Зондировать линию Dir_2":
                    Control.dataGridView1.Rows[0].Cells[1].Value = "02";
                    break;
 
                case "Зондировать линии Dir_1, Dir_2":
                    Control.dataGridView1.Rows[0].Cells[1].Value = "03";
                    break;
            }
            UART_copy.Command = Control.dataGridView1.Rows[0].Cells[1].Value.ToString();
            UART_copy.Request[1] = Convert.ToByte(UART_copy.Command, 16);
 
            ushort LRC = 0;
            LRC = UART_copy.GetLRC(UART_copy.Request);
 
            UART_copy.Request[2] = (byte)((LRC >> 8) & 0xFF);
            Control.dataGridView1.Rows[0].Cells[2].Value = UART_copy.Request[2].ToString("x");
 
            UART_copy.Request[3] = (byte)(LRC & 0xFF);
            Control.dataGridView1.Rows[0].Cells[3].Value = UART_copy.Request[3].ToString("x");
        }
        
    }
}

C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
using System;
using System.Data;
using System.Data.SqlClient;
using System.Windows.Forms;
using System.Runtime.InteropServices;
using System.IO.Ports;
using System.IO;
using System.Globalization;
using System.Threading;
using System.Collections.Generic;
using System.ComponentModel;
 
 
 
 
namespace PC_Atmega161
{
    public class UART
    {
        public int temp = 0;
        public string StartSign, Command, FunctionByte, CRC16HighByte,
                      CRC16LowByte, CRByte, LFByte;
        public System.IO.Ports.SerialPort SerialPort1;
        public byte InMessageL;                      // Длина принятого сообщения
        public AutoResetEvent EventInMessageReady;   // Событие, показывающее, что сообщение принято
        public byte[] InMessage = new byte[100];     // длина - как минимум 2 байт (без данных, CRC и признаков конца)
        public byte[] Request = new byte[4];
    
        // Стадии приёма посылки
        const byte WAITING_START = 0;
        const byte WAITING_T0 = 1;
        const byte WAITING_FLAG_DIR1 = 5;
        const byte WAITING_T1 = 6;
        const byte WAITING_FLAG_DIR2 = 10;
        const byte WAITING_LRC_HIGH = 11;
        const byte WAITING_LRC_LOW = 12;
 
        // Константы приёма/передачи данных
        const byte START = 0x3A;
        const byte ADDRESS_PC = 0x01;
        const byte ADDRESS_ATmega161 = 0x01;
        const byte FUNCTION = 0x04;
        const byte CR = 0x0D;
        const byte LF = 0x0A;
 
        uint RxStage = 0;
 
        Common CommonCopy = new Common();
        
        public void Init()
        {
            // Настройка COM порта
            SerialPort1 = new SerialPort();
            SerialPort1.BaudRate = 57600;
            SerialPort1.Parity = System.IO.Ports.Parity.None;
            SerialPort1.StopBits = System.IO.Ports.StopBits.One;
            SerialPort1.DataReceived += DataReceived; // Подключить обработчик принятых данных
        }
 
        // Обработчик по приему данных
        public void DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)
        {
            byte B;
 
            while (SerialPort1.BytesToRead > 0)
            {
                B = (byte)SerialPort1.ReadByte();
                Console.WriteLine("|||||" + B + "|||||");
                AnalyseByte(B);  // Обработать запрос
            }
        }
 
        void AnalyseByte(byte ReceivedByte)
        {
            if (RxStage == WAITING_START)
            {
                InMessage[RxStage] = ReceivedByte;
            }
            else
            //if (RxStage <= WAITING_DATA)
            if (RxStage >= 1 && RxStage <= 10)
            {
                InMessage[RxStage] = ReceivedByte;
            }
            else
            if (RxStage == WAITING_LRC_HIGH)
            {
                InMessage[RxStage] = ReceivedByte;
                Console.WriteLine("||||| ok" + RxStage + "|||||");
            }
            else
            if (RxStage == WAITING_LRC_LOW)
            {
                InMessage[RxStage] = ReceivedByte;
                Console.WriteLine("||||| ok" + RxStage + "|||||");
                RxStage = 0;
                //CommonCopy.AnalyzeLinesStatus();
                return;
            }
            RxStage++;
        }
 
        // Вычисление LRC
        public ushort GetLRC(byte[] array)
        {
            ushort lrc = 0;
            for (int i = 0; i < array.Length - 2; i++)
            {                       // вычисление LRC
                lrc += array[i];
            }
            return lrc;
        }
        
    }
}
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
using System;
using System.Data;
using System.Data.SqlClient;
using System.Windows.Forms;
using System.Runtime.InteropServices;
using System.IO.Ports;
using System.IO;
using System.Globalization;
using System.Threading;
using System.Collections.Generic;
using System.ComponentModel;
 
namespace PC_Atmega161
{
    partial class Form1
    {
 
        /// <summary>
        /// Требуется переменная конструктора.
        /// </summary>
        private System.ComponentModel.IContainer components = null;
 
        /// <summary>
        /// Освободить все используемые ресурсы.
        /// </summary>
        /// <param name="disposing">истинно, если управляемый ресурс должен быть удален; иначе ложно.</param>
        protected override void Dispose(bool disposing)
        {
            if (disposing && (components != null))
            {
                components.Dispose();
            }
            base.Dispose(disposing);
        }
 
        #region Код, автоматически созданный конструктором форм Windows
 
 
        //private DataGridView dataGridView1 = new DataGridView();
 
        //this.DataGridView1.AllowUserToAddRows = false;
        
 
        /// <summary>
        /// Обязательный метод для поддержки конструктора - не изменяйте
        /// содержимое данного метода при помощи редактора кода.
        /// </summary>
        public void InitializeComponent()
        {
            this.buttonSend = new System.Windows.Forms.Button();
            this.dataGridView1 = new System.Windows.Forms.DataGridView();
            this.label1 = new System.Windows.Forms.Label();
            this.LabelDebug = new System.Windows.Forms.Label();
            this.ButtonDebug = new System.Windows.Forms.Button();
            this.dataGridView2 = new System.Windows.Forms.DataGridView();
            this.label2 = new System.Windows.Forms.Label();
            this.LabelDebug2 = new System.Windows.Forms.Label();
            this.LabelDebug3 = new System.Windows.Forms.Label();
            this.comboBox1 = new System.Windows.Forms.ComboBox();
            this.label3 = new System.Windows.Forms.Label();
            this.button1 = new System.Windows.Forms.Button();
            this.label4 = new System.Windows.Forms.Label();
            this.label5 = new System.Windows.Forms.Label();
            this.label7 = new System.Windows.Forms.Label();
            this.label6 = new System.Windows.Forms.Label();
            this.label8 = new System.Windows.Forms.Label();
            this.button2 = new System.Windows.Forms.Button();
            this.button3 = new System.Windows.Forms.Button();
            ((System.ComponentModel.ISupportInitialize)(this.dataGridView1)).BeginInit();
            ((System.ComponentModel.ISupportInitialize)(this.dataGridView2)).BeginInit();
            this.SuspendLayout();
 
            
            // 
            // buttonSend
            // 
            this.buttonSend.Location = new System.Drawing.Point(64, 207);
            this.buttonSend.Name = "buttonSend";
            this.buttonSend.Size = new System.Drawing.Size(168, 50);
            this.buttonSend.TabIndex = 0;
            this.buttonSend.Text = "Зондировать линию Dir_1";
            this.buttonSend.UseVisualStyleBackColor = true;
            this.buttonSend.Click += new System.EventHandler(this.buttonSend_Click);
            // 
            // dataGridView1
            // 
            // Настройка поля запроса
            this.dataGridView1.AllowUserToAddRows = false;
            this.dataGridView1.AutoSizeColumnsMode = System.Windows.Forms.DataGridViewAutoSizeColumnsMode.AllCells;
            this.dataGridView1.ColumnHeadersHeightSizeMode = System.Windows.Forms.DataGridViewColumnHeadersHeightSizeMode.AutoSize;
            this.dataGridView1.Location = new System.Drawing.Point(64, 87);
            this.dataGridView1.Name = "dataGridView1";
            this.dataGridView1.Size = new System.Drawing.Size(457, 114);
            this.dataGridView1.TabIndex = 1;
            //this.dataGridView1.CellContentClick += new System.Windows.Forms.DataGridViewCellEventHandler(this.dataGridView1_CellContentClick);
 
 
            /*
            this.dataGridView1.RowCount = 1;
            this.dataGridView1.ColumnCount = 4;
            this.dataGridView1.ColumnHeadersVisible = true;
            this.dataGridView1.RowHeadersVisible = false;
 
            this.dataGridView1.Columns[0].Name = "Признак начала ':'";
            this.dataGridView1.Columns[1].Name = "Команда: 0x01, 0x02 или 0x03";
            this.dataGridView1.Columns[2].Name = "Старший байт LRC";
            this.dataGridView1.Columns[3].Name = "Младший байт LRC";
 
 
            this.dataGridView1.Rows[0].Cells[0].Value = "3a";        // Стартовый байт 
            this.dataGridView1.Rows[0].Cells[1].Value = "";          // Команда по умолчанию
            this.dataGridView1.Rows[0].Cells[2].Value = "";          // LRC старший
            this.dataGridView1.Rows[0].Cells[3].Value = "";          // LRC младший
            */
            //dataGridView1.Width = 470;
            this.dataGridView1.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.AllCells;
 
            // 
            // label1
            // 
            this.label1.AutoSize = true;
            this.label1.Font = new System.Drawing.Font("Microsoft Sans Serif", 15.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(204)));
            this.label1.Location = new System.Drawing.Point(414, 43);
            this.label1.Name = "label1";
            this.label1.Size = new System.Drawing.Size(84, 25);
            this.label1.TabIndex = 2;
            this.label1.Text = "Запрос";
            
            // 
            // LabelDebug
            // 
            this.LabelDebug.AutoSize = true;
            this.LabelDebug.Location = new System.Drawing.Point(61, 42);
            this.LabelDebug.Name = "LabelDebug";
            this.LabelDebug.Size = new System.Drawing.Size(50, 13);
            this.LabelDebug.TabIndex = 3;
            this.LabelDebug.Text = "Отладка";
            // 
            // ButtonDebug
            // 
            this.ButtonDebug.Location = new System.Drawing.Point(64, 12);
            this.ButtonDebug.Name = "ButtonDebug";
            this.ButtonDebug.Size = new System.Drawing.Size(127, 23);
            this.ButtonDebug.TabIndex = 4;
            this.ButtonDebug.Text = "Кнопка для отладки";
            this.ButtonDebug.UseVisualStyleBackColor = true;
            this.ButtonDebug.Click += new System.EventHandler(this.ButtonDebug_Click);
            // 
            // dataGridView2
            // 
            this.dataGridView2.ColumnHeadersHeightSizeMode = System.Windows.Forms.DataGridViewColumnHeadersHeightSizeMode.AutoSize;
            this.dataGridView2.Location = new System.Drawing.Point(64, 392);
            this.dataGridView2.Name = "dataGridView2";
            this.dataGridView2.Size = new System.Drawing.Size(971, 254);
            this.dataGridView2.TabIndex = 5;
 
 
            /*
            // Настройка поля приёма ответа
            this.dataGridView2.RowCount = 10;
            this.dataGridView2.ColumnCount = 7;
            this.dataGridView2.ColumnHeadersVisible = true;
            this.dataGridView2.RowHeadersVisible = false;
 
            this.dataGridView2.Columns[0].Name = "Признак начала ':'";
            this.dataGridView2.Columns[1].Name = "Данные, t0";
            this.dataGridView2.Columns[2].Name = "Признак «норма/авария» на линии Dir_1";
            this.dataGridView2.Columns[3].Name = "Данные, t1";
            this.dataGridView2.Columns[4].Name = "Признак «норма/авария» на линии Dir_2";
            this.dataGridView2.Columns[5].Name = "Старший байт LRC";
            this.dataGridView2.Columns[6].Name = "Младший байт LRC";
            this.dataGridView2.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.AllCells;
            */
            // 
            // label2
            // 
            this.label2.AutoSize = true;
            this.label2.Font = new System.Drawing.Font("Microsoft Sans Serif", 15.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(204)));
            this.label2.Location = new System.Drawing.Point(414, 352);
            this.label2.Name = "label2";
            this.label2.Size = new System.Drawing.Size(71, 25);
            this.label2.TabIndex = 6;
            this.label2.Text = "Ответ";
            
            // 
            // LabelDebug2
            // 
            this.LabelDebug2.AutoSize = true;
            this.LabelDebug2.Location = new System.Drawing.Point(141, 52);
            this.LabelDebug2.Name = "LabelDebug2";
            this.LabelDebug2.Size = new System.Drawing.Size(50, 13);
            this.LabelDebug2.TabIndex = 7;
            this.LabelDebug2.Text = "Отладка";
            // 
            // LabelDebug3
            // 
            this.LabelDebug3.AutoSize = true;
            this.LabelDebug3.Location = new System.Drawing.Point(231, 53);
            this.LabelDebug3.Name = "LabelDebug3";
            this.LabelDebug3.Size = new System.Drawing.Size(50, 13);
            this.LabelDebug3.TabIndex = 8;
            this.LabelDebug3.Text = "Отладка";
            // 
            // comboBox1
            // 
            this.comboBox1.FormattingEnabled = true;
            this.comboBox1.Location = new System.Drawing.Point(833, 5);
            this.comboBox1.Name = "comboBox1";
            this.comboBox1.Size = new System.Drawing.Size(121, 21);
            this.comboBox1.TabIndex = 9;
            // 
            // label3
            // 
            this.label3.AutoSize = true;
            this.label3.Location = new System.Drawing.Point(731, 9);
            this.label3.Name = "label3";
            this.label3.Size = new System.Drawing.Size(101, 13);
            this.label3.TabIndex = 10;
            this.label3.Text = "Доступные порты:";
            // 
            // button1
            // 
            this.button1.Location = new System.Drawing.Point(960, 4);
            this.button1.Name = "button1";
            this.button1.Size = new System.Drawing.Size(75, 23);
            this.button1.TabIndex = 11;
            this.button1.Text = "Открыть";
            this.button1.UseVisualStyleBackColor = true;
            this.button1.Click += new System.EventHandler(this.button1_Click);
            // 
            // label4
            // 
            this.label4.AutoSize = true;
            this.label4.Location = new System.Drawing.Point(832, 40);
            this.label4.Name = "label4";
            this.label4.Size = new System.Drawing.Size(35, 13);
            this.label4.TabIndex = 12;
            this.label4.Text = "label4";
            // 
            // label5
            // 
            this.label5.AutoSize = true;
            this.label5.Font = new System.Drawing.Font("Microsoft Sans Serif", 15.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(204)));
            this.label5.Location = new System.Drawing.Point(59, 300);
            this.label5.Name = "label5";
            this.label5.Size = new System.Drawing.Size(36, 25);
            this.label5.TabIndex = 13;
            this.label5.Text = "t0:";
            // 
            // label7
            // 
            this.label7.AutoSize = true;
            this.label7.Font = new System.Drawing.Font("Microsoft Sans Serif", 15.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(204)));
            this.label7.Location = new System.Drawing.Point(414, 300);
            this.label7.Name = "label7";
            this.label7.Size = new System.Drawing.Size(36, 25);
            this.label7.TabIndex = 15;
            this.label7.Text = "t1:";
            // 
            // label6
            // 
            this.label6.AutoSize = true;
            this.label6.Font = new System.Drawing.Font("Microsoft Sans Serif", 15.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(204)));
            this.label6.Location = new System.Drawing.Point(163, 300);
            this.label6.Name = "label6";
            this.label6.Size = new System.Drawing.Size(69, 25);
            this.label6.TabIndex = 16;
            this.label6.Text = "Dir_1:";
            // 
            // label8
            // 
            this.label8.AutoSize = true;
            this.label8.Font = new System.Drawing.Font("Microsoft Sans Serif", 15.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(204)));
            this.label8.Location = new System.Drawing.Point(546, 300);
            this.label8.Name = "label8";
            this.label8.Size = new System.Drawing.Size(190, 25);
            this.label8.TabIndex = 17;
            this.label8.Text = "Признак на Dir_2:";
            // 
            // button2
            // 
            this.button2.Location = new System.Drawing.Point(282, 207);
            this.button2.Name = "button2";
            this.button2.Size = new System.Drawing.Size(168, 50);
            this.button2.TabIndex = 18;
            this.button2.Text = "Зондировать линию Dir_2";
            this.button2.UseVisualStyleBackColor = true;
            this.button2.Click += new System.EventHandler(this.button2_Click);
            // 
            // button3
            // 
            this.button3.Location = new System.Drawing.Point(485, 207);
            this.button3.Name = "button3";
            this.button3.Size = new System.Drawing.Size(181, 50);
            this.button3.TabIndex = 19;
            this.button3.Text = "Зондировать линии Dir_1, Dir_2";
            this.button3.UseVisualStyleBackColor = true;
            this.button3.Click += new System.EventHandler(this.button3_Click);
            // 
            // Form1
            // 
            this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
            this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
            this.BackColor = System.Drawing.SystemColors.Control;
            this.ClientSize = new System.Drawing.Size(1184, 658);
            this.Controls.Add(this.button3);
            this.Controls.Add(this.button2);
            this.Controls.Add(this.label8);
            this.Controls.Add(this.label6);
            this.Controls.Add(this.label7);
            this.Controls.Add(this.label5);
            this.Controls.Add(this.label4);
            this.Controls.Add(this.button1);
            this.Controls.Add(this.label3);
            this.Controls.Add(this.comboBox1);
            this.Controls.Add(this.LabelDebug3);
            this.Controls.Add(this.LabelDebug2);
            this.Controls.Add(this.label2);
            this.Controls.Add(this.dataGridView2);
            this.Controls.Add(this.ButtonDebug);
            this.Controls.Add(this.LabelDebug);
            this.Controls.Add(this.label1);
            this.Controls.Add(this.dataGridView1);
            this.Controls.Add(this.buttonSend);
            this.Name = "Form1";
            this.Text = "Form1";
            //this.Load += new System.EventHandler(this.Form1_Load);
            ((System.ComponentModel.ISupportInitialize)(this.dataGridView1)).EndInit();
            ((System.ComponentModel.ISupportInitialize)(this.dataGridView2)).EndInit();
            this.ResumeLayout(false);
            this.PerformLayout();
 
        }
 
 
        #endregion
 
        public System.Windows.Forms.Button buttonSend;
        public Label label1;
        public Label LabelDebug;
        public Button ButtonDebug;
        public DataGridView dataGridView2;
        public DataGridView dataGridView1;
        public Label label2;
        public Label LabelDebug2;
        public Label LabelDebug3;
        public ComboBox comboBox1;
        public Label label3;
        public Button button1;
        public Label label4;
        public Label label5;
        public Label label7;
        public Label label6;
        public Label label8;
        public Button button2;
        public Button button3;
        
        
        
    }
 
}



0



Эксперт .NET

5459 / 4232 / 1208

Регистрация: 12.10.2013

Сообщений: 12,223

Записей в блоге: 2

27.01.2014, 15:49

15

Сложно у Вас как-то все… Сейчас приведу пример моей работы с портом… Там тоже запись в порт и прием из порта…



0



Nalale

3 / 3 / 1

Регистрация: 19.03.2013

Сообщений: 34

27.01.2014, 15:55

16

olegall, у вас файл Program.cs имеется? он имеет такой вид?

C#
1
2
3
4
5
6
7
8
9
10
11
12
13
static class Program
    {
        /// <summary>
        /// The main entry point for the application.
        /// </summary>
        
        [STAThread]
        static void Main()
        {            
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            Application.Run(new Form1());                       
        }



0



insite2012

Эксперт .NET

5459 / 4232 / 1208

Регистрация: 12.10.2013

Сообщений: 12,223

Записей в блоге: 2

27.01.2014, 15:56

17

Вот. Это класс записи в порт посылок и приема необходимых данных. И потом вывод данных на основную форму через свойства.

C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO.Ports;
using System.Windows.Forms;
 
namespace EVO_2_Csharp
{
    class ReadClass
    {
        private string Model;         //Модель
        private string SerialNumber;  //Серийный номер
        private string ProductNumber; //Продуктовый номер
        private int realChecksum;     //Просчитанная КС
        private int fileChecksum;     //Прописанная КС
        private List<byte> errList = new List<byte>();//Массив для блока ошибок и статистики
        private SerialPort Port=new SerialPort(); //Экземпляр порта
        private delegate List<byte> ReadDelegate(int count);  //Делегат асинхронного чтения
 
        //Конструктор
        public ReadClass()
        {
        }
 
        //Стандартная функция чтения
       public List<byte> ReadModuleEVO_2(string PortName, byte Address, int Size)
        {
           //Переменные функции
            byte[] DataAsc = { 0xa5, 0xee, 0x2, 0x91, 0x30, 0x5, Address, 0x0, 0x0, 0x7f, 0x0, 0x0 };
            List<byte>tempList=new List<byte>();
            List<byte>outList=new List<byte>();
            int checksum = 0;
            
           //Установки порта
            Port.PortName = PortName;
            Port.BaudRate = 38400;
            Port.ReadTimeout = 500;
           ReadDelegate readDelegate=new ReadDelegate(ReadData);
           
 
            using (Port)
            {
                Port.Open();
                //Основной цикл чтения
                int I = 0;
                for (I= 0; I <= Size - 1; I++)
                {
                    //Цикл просчета КС запроса
                    checksum = 0;
                    DataAsc[11] = 0;
                    for (int j = 0; j < DataAsc.GetUpperBound(0); j++)
                    {
                        checksum += DataAsc[j];
                    }
                    DataAsc[11] = Convert.ToByte(checksum & 0xff);
 
                    //Отправка запроса в СОМ порт
                    for (int n = 0; n <= DataAsc.GetUpperBound(0); n++)
                    {
                        Port.Write(DataAsc, n, 1);
                    }
 
                    //Aсинхронное считывание данных из СОМ порта
                    IAsyncResult result = readDelegate.BeginInvoke(264, null, null);
                    tempList.AddRange(readDelegate.EndInvoke(result));
 
                    //Фильтрация и копирование в выходной массив
                    tempList.RemoveRange(0, 7);
                    tempList.RemoveAt(tempList.Count - 1);
                    outList.AddRange(tempList);
                    tempList.Clear();
 
                    //Подстановка адресов в запрос
                    if(((I+1)%2)==0)
                    {
                    DataAsc[7] = 0x0;
                    DataAsc[9] = 0x7F;
                    DataAsc[8] = Convert.ToByte((DataAsc[8]+1) & 0xff);
                    DataAsc[10] = DataAsc[8];
                    }
                    else
                    {
                    DataAsc[7] = 0x80;
                    DataAsc[9] = 0xFF;
                    }  
                }
            }
            //Обработка сообщений
            Application.DoEvents();
 
           //Возврат данных
            return outList;
        }
        //Функция получения информации о подключенном модуле
       public bool GetInfo(string PortName)
       {
           //Локальные переменные
           byte[] DataAsc = { 0xa5, 0xee, 0x2, 0x91, 0x30, 0x5, 0xa0, 0x0, 0x0, 0xf, 0x0, 0x0 };
           List<byte> tempList = new List<byte>();
           List<byte> vectorList = new List<byte>();
           IAsyncResult result;
           int checksum = 0;
 
           //Установки порта
           Port.PortName = PortName;
           Port.BaudRate = 38400;
           Port.ReadTimeout = 500;
           ReadDelegate readDelegate = new ReadDelegate(ReadData);
 
           using (Port)
           {
               Port.Open();
 
               //Цикл просчета КС запроса
               checksum = 0;
               DataAsc[11] = 0;
               for (int j = 0; j < DataAsc.GetUpperBound(0); j++)
               {
                   checksum += DataAsc[j];
               }
               DataAsc[11] = Convert.ToByte(checksum & 0xff);
 
               //Цикл посылки запросов
               for (int i = 0; i <= 5; i++)
               {
                   //Запрос в порт
                   for (int q = 0; q <= DataAsc.GetUpperBound(0); q++)//Цикл записи запроса в порт
                   {
                       Port.Write(DataAsc, q, 1);
                   }
                   System.Threading.Thread.Sleep(500);
                   if ((Port.BytesToRead != 0))
                   {
                       //Aсинхронное считывание данных из СОМ порта
                        result = readDelegate.BeginInvoke(40, null, null);
                        vectorList.AddRange(readDelegate.EndInvoke(result));
                       break;
                   }
                   //Условие выхода с возвратом False (устр-во не отвечает)
                   else if ((Port.BytesToRead == 0) && (i == 5))
                   {
                       return false;
                   }
               }
               //Фильтрация принятых данных
               vectorList.RemoveRange(0, 7);
               vectorList.RemoveAt(vectorList.Count - 1);
 
               //Подстановка адресов в запрос
               DataAsc[7] = vectorList[0];
               DataAsc[8] = vectorList[1];
               DataAsc[9] = vectorList[2];
               DataAsc[10] = vectorList[3];
 
               //Цикл просчета КС запроса
               checksum = 0;
               DataAsc[11] = 0;
               for (int j = 0; j < DataAsc.GetUpperBound(0); j++)
               {
                   checksum += DataAsc[j];
               }
               DataAsc[11] = Convert.ToByte(checksum & 0xff);
 
               //Запрос в порт
               for (int q = 0; q <= DataAsc.GetUpperBound(0); q++)//Цикл записи запроса в порт
               {
                   Port.Write(DataAsc, q, 1);
               }
 
               //Aсинхронное считывание данных из СОМ порта
               result = readDelegate.BeginInvoke(44, null, null);
               tempList.AddRange(readDelegate.EndInvoke(result));
 
               //Фильтрация и переворот байтов в мaссиве
               tempList.RemoveRange(0, 7);
               tempList.RemoveAt(tempList.Count - 1);
               tempList = statMethods.EepToBin(tempList);
 
               //Поиск маркера 030609101111 в полученном блоке данных
               string index="";
               for(int i=0;i<=5;i++)
               {
                   index += tempList[i].ToString("X2");
               }
               if (index != "030609101111")
                   //При отсутствии маркера-возврат со значением false
                   return false;
               else
               {
                   //Получение серийного номера
                   for (int s = 0; s <= 5; s++)
                   {
                       SerialNumber += tempList[s + 6].ToString("X2");
                   }
                   SerialNumber = SerialNumber.Substring(0, 9);
 
                   //Получение продуктового номера
                   for (int p = 0; p <= 5; p++)
                   {
                       ProductNumber += tempList[p + 12].ToString("X2");
                   }
                   ProductNumber = ProductNumber.Substring(0, 11);
 
                   //Получение имени модели
                   for(int m=0;m<=13;m++)
                   {
                       Model += Convert.ToChar(tempList[m + 18]);
                   }  
               }
 
               tempList.Clear();
               //Подстановка адресов в запрос
               DataAsc[7] = vectorList[12];
               DataAsc[8] = vectorList[13];
               DataAsc[9] = vectorList[14];
               DataAsc[10] = vectorList[15];
 
               //Формирование размера блока ошибок
               int errBlockLength = (((vectorList[15]) * 0x100 + vectorList[14]) 
                             - ((vectorList[13]) * 0x100 + vectorList[12])) * 2;
 
               //Цикл просчета КС запроса
               checksum = 0;
               DataAsc[11] = 0;
               for (int j = 0; j < DataAsc.GetUpperBound(0); j++)
               {
                   checksum += DataAsc[j];
               }
               DataAsc[11] = Convert.ToByte(checksum & 0xff);
 
               //Запрос в порт
               for (int q = 0; q <= DataAsc.GetUpperBound(0); q++)//Цикл записи запроса в порт
               {
                   Port.Write(DataAsc, q, 1);
               }
 
               //Aсинхронное считывание данных из СОМ порта
               result = readDelegate.BeginInvoke(errBlockLength+8, null, null);
               errList.AddRange(readDelegate.EndInvoke(result));
               errList.RemoveRange(0, 7);
               errList.RemoveAt(errList.Count - 1);
 
               return true;
           }
       }
        //Функция проверки корректности загруженного файла
       public  bool fileCheck(List<byte> list)
       {
           //Переворот eep>>bin
           list = statMethods.EepToBin(list);
 
           //Проверка размера файла
           if ((list.Count - 1 >= 0x2000) && (list.Count - 1 < 0x40))
               return false;
 
           //Вектор маркера
           int checkVector = Convert.ToInt32((list[0]*0x100+list[1])*2);
           string marker = "";
           for (int i = 0; i <= 5; i++)
           {
               marker += list[checkVector + i].ToString("X2");
           }
           //Проверка через маркер
           if (marker != "030609101111")
               return false;
 
           //Проверка через совпадение контрольных сумм
           realChecksum = 0;//Прописанная КС
           fileChecksum = 0;//Просчитанная КС
           int checksumVector = Convert.ToInt32((list[18] * 0x100 + list[19]) * 2);//Вектор КС
           fileChecksum = Convert.ToInt32(list[checksumVector] * 0x100 + list[checksumVector + 1]);
 
           //Просчет КС
           for (int j = 0; j <= checksumVector-1; j++)
           {
               realChecksum += Convert.ToInt32(list[j]) & 0xffff;
           }
           realChecksum = realChecksum & 0xffff;
           if (fileChecksum != realChecksum)
               return false;
 
           int index = checkVector + 6;
           //Получение сер.номера
           for (int i = 0; i <= 5; i++)
           {
               SerialNumber += list[index + i].ToString("X2");
           }
           SerialNumber = SerialNumber.Substring(0, 9);
           //Получение прод.номера
           for (int j = 0; j <= 5; j++)
           {
               ProductNumber += list[index + 6 + j].ToString("X2");
           }
           ProductNumber = ProductNumber.Substring(0, 11);
 
           //Получение имени модели
           for (int m = 0; m <= 13; m++)
           {
               Model += Convert.ToChar(list[index + 12+m]);
           }  
 
           return true;
       }
       
 
        //Функция для асинхронного чтения данных из СОМ порта
       private List<byte> ReadData(int count)
       {
           List<byte> outList = new List<byte>();
           {
               for (int i = 0; i < count; i++)
                   outList.Add(Convert.ToByte(Port.ReadByte()));
           }
           return outList;
       }
       #region Properties
 
       //Своство для модели
       public  string ModelVal
       {
           get
           {
               return Model;
           }
       }
        //Свойство для серийного номера
       public  string SerialNumberVal
       {
           get
           {
               return SerialNumber;
           }
       }
        //Свойство для продуктового номера
       public  string ProdNumberVal
       {
           get
           {
               return ProductNumber;
           }
       }
        //Свойство для блока ошибок
       public List<byte> errLIstVal
       {
           get
           {
               return errList;
           }
       }
        //Свойство для просчитанной КС
       public  int realChecksumVal
       {
           get
           {
               return realChecksum;
           }
       }
        //Свойство для прописанной КС
       public int fileChecksumVal
       {
           get
           {
               return fileChecksum;
           }
       }
       #endregion
    }
}



0



olegall

0 / 0 / 0

Регистрация: 27.01.2014

Сообщений: 116

27.01.2014, 16:03

 [ТС]

18

Цитата
Сообщение от Nalale
Посмотреть сообщение

olegall, у вас файл Program.cs имеется? он имеет такой вид?

C#
1
2
3
4
5
6
7
8
9
10
11
12
13
static class Program
    {
        /// <summary>
        /// The main entry point for the application.
        /// </summary>
        
        [STAThread]
        static void Main()
        {            
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            Application.Run(new Form1());                       
        }

вот:

C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using System.Windows.Forms;
 
namespace PC_Atmega161
{
    static class Program
    {
        /// <summary>
        /// Главная точка входа для приложения.
        /// </summary>
        [STAThread]
        static void Main()
        {
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            Application.Run(new Form1());
        }
    }
}



0



Nalale

3 / 3 / 1

Регистрация: 19.03.2013

Сообщений: 34

27.01.2014, 16:36

19

olegall, тогда в обработчике загрузке формы Form1 передавай ее в качесте параметра при создании объекта класса Common, т.е

C#
1
2
3
4
5
6
7
8
public partial class Form1 : Form
    {
        Common CommonCopy;
        private void Form1_Load(object sender, EventArgs e)
        {
              CommonCopy = new Common(this);
        }
    }

далее удали строчку создания экземпляра класса Form1 в классе Common и в конструкторе этого класса сделай так

C#
1
2
3
4
5
6
7
class Common
    {
       Form1 form1;
       public Common(Form1 parent)
       {
               form1 = parent;
       }

и обращайся к элементам класса Form1 из класса Common так

C#
1
2
3
4
5
if (UART_copy.SerialPort1.IsOpen)
                {
                    form1.label4.Text = "Порт " + form1.comboBox1.SelectedItem.ToString() + " успешно открыт";
                    form1.button1.Text = "Закрыть";
                }

Но, как было сказано, это нарушает правила ООП, поэтому можно это реализовать более легко и правильно



0



0 / 0 / 0

Регистрация: 27.01.2014

Сообщений: 116

27.01.2014, 16:42

 [ТС]

20

Спасибо, завтра попробую.
Можете написать как? И вообще правильно ли я мыслил при создании классов? Я пишу под контроллеры на с, С# использую редко и ООП не применяю в общем то.



0



Лабораторная работа №2

Создание приложения Windows Form. Стандартные элементы управления и компоненты.

1. Цель

изучить методы создания приложений с использованием Windows Form. Также изучить стандартные компоненты и научиться их применять на практике.

2.Методические указания

1.При изучении языка программирования С# будет использоваться интегрированная среда разработки программного обеспечения Microsoft Visual Studio Express 2013 для Windows Desktop. Будут использованы основные элементы .NET Framework и связь С# с элементами платформы .NET.

2.По окончанию работы сохраните все созданные файлы на своих носителях.

3.Защита лабораторной работы производится только при наличии электронного варианта работающего скрипта.

3.Теоретические сведения

Первое, что необходимо сделать — создать приложение Windows Forms. Для примера создадим пустую форму, и отобразим ее на экране.

using System;

using System.Windows.Forms; namespace NotepadForms

{

public class MyForm : System.Windows.Forms.Form

{

public MyForm()

{

}

[STAThread]

static void Main()

{

Application.Run(new MyForm());

}

}

}

Когда мы скомпилируем и запустим этот пример, то получим маленькую пустую форму без заголовка. Никаких реальных функций, но это — Windows Forms. В приведенном коде заслуживают внимания две вещи. Первая — тот факт, что при создании класса MyForm используется наследование. Следующая строка объявляет MyForm как наследника

System.Windows.Forms.Form:

public class MyForm : System.Windows.Forms.Form

Класс Form — один из главных классов в пространстве имен System.Windows.Forms. Следующий фрагмент кода стоит рассмотреть более подробно:

[STAThread] static void Main()

{

Application.Run(new MyForm());

}

Main — точка входа по умолчанию в любое клиентское приложение на C#. Как правило, в более крупных приложениях метод Main() не будет находиться в классе формы, а скорее в классе, отвечающем за процесс запуска. В данном случае вы должны установить имя такого запускающего класса в диалоговом окне свойств проекта. Обратите внимание на атрибут *STAThread+. Он устанавливает модель многопоточности COM в STA (однопоточный апартамент). Модель многопоточности STA требуется для взаимодействия с COM и устанавливается по умолчанию в каждом проекте Windows Forms.

Метод Application.Run() отвечает за запуск стандартного цикла сообщений приложения. Application.Run() имеет три перегрузки.

Первая из них не принимает параметров; вторая принимает в качестве параметра объект ApplicationContext. В нашем примере объект MyForm становится главной формой приложения. Это означает, что когда форма закрывается, то приложение завершается. Используя класс ApplicationContext, можно в большей степени контролировать завершение главного цикла сообщений и выход из приложения.

Класс Applicationсодержит в себе очень полезную функциональность. Он предоставляет группу статических методов и свойств для управления процессом запуска

и останова приложения, а также обеспечивает доступ к сообщениям Windows, обрабатываемым приложением. В табл. 2.1 перечислены некоторые из этих наиболее полезных методов и свойств.

Таблица 2.1. Некоторые полезные методы и свойства класса Application

А теперь как будет выглядеть это приложение, если его сгенерировать в Visual Studio 2010? Первое, что следует отметить — будет создано два файла. Причина в том, что Visual Studio 2010 использует возможность частичных (partial) классов и выделяет весь код, сгенерированный визуальным дизайнером, в отдельный файл. Если используется имя по умолчанию — Form1, то эти два файла будет называться Form1.cs и Form1.Designer.cs. Если только у вас не включена опция Show All Files (Показать все файлы) в меню Project (Проект), то вы не увидите в проводнике Solution Explorer файла Form1.Designer.cs. Ниже показан код этих двух файлов, сгенерированных Visual Studio.

Сначала — Form1.cs:

using System;

using System.Collections.Generic; using System.ComponentModel; using System.Data;

using System.Drawing; using System.Linq; using System.Text;

using System.Threading.Tasks; using System.Windows.Forms;

namespace MyForm

{

public partial class Form1 : Form

{

public Form1()

{

InitializeComponent();

}

}

}

Здесь мы видим только операторы using и простой конструктор. А вот код Form1. Designer.cs:

namespace MyForm

{

partial class Form1

{

///<summary>

///Требуется переменная конструктора.

///</summary>

private System.ComponentModel.IContainer components = null;

///<summary>

///Освободить все используемые ресурсы.

///</summary>

///<param name=»disposing»>истинно, если управляемый ресурс должен быть удален; иначе ложно.</param>

protected override void Dispose(bool disposing)

{

if (disposing && (components != null))

{

components.Dispose();

}

base.Dispose(disposing);

}

#region Код, автоматически созданный конструктором форм Windows

///<summary>

///Обязательный метод для поддержки конструктора — не изменяйте

///содержимое данного метода при помощи редактора кода.

/// </summary>

private void InitializeComponent()

{

this.SuspendLayout();

//

// Form1

//

this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; this.ClientSize = new System.Drawing.Size(383, 335); this.Name = «Form1»;

this.Text = «Form1»; this.ResumeLayout(false);

}

#endregion

}

}

Файл, сгенерированный дизайнером форм, редко подвергается ручному редактированию. Единственным исключением может быть случай, когда необходима специальная обработка в методе Dispose(). Метод InitializeComponent мы обсудим позднее в этой главе. Если взглянуть на этот код примера приложения в целом, то мы увидим, что он намного длиннее, чем простой пример командной строки. Здесь перед началом класса присутствует несколько операторов using, и большинство из них в данном примере не нужны. Однако их присутствие ничем не мешает. Класс Form1 наследуется от

System.Windows.Forms.Form, как и в предыдущем, введенном примере, но в этой точке начинаются расхождения. Во-первых, в файле Form1.Designer появляется строка:

private System.ComponentModel.IContainer components = null;

В данном примере эта строка кода ничего не делает. Но, добавляя компонент в форму, вы можете также добавить его в объект components, который представляет собой контейнер. Причина добавления этого контейнера — в необходимости правильной обработки уничтожения формы. Класс формы поддерживает интерфейс IDisposable, потому что он реализован в классе Component. Когда компонент добавляется в контейнер, то этот контейнер должен позаботиться о корректном уничтожении своего содержимого при закрытии формы. Это можно увидеть в методе Dispose нашего примера:

protected override void Dispose(bool disposing)

{

if (disposing && (components != null))

{

components.Dispose();

}

base.Dispose(disposing);

}

Здесь мы видим, что когда вызывается метод Dispose формы, то также вызывается

метод Dispose объекта components, поскольку он содержит в себе другие компоненты, которые также должны быть корректно удалены.

Конструктор класса Form1, находящийся в файле Form1.cs, выглядит так:

public Form1()

{

InitializeComponent();

}

Обратите внимание на вызов InitializeComponent().

Метод InitializeComponent() находится в файле Form1.Designer.cs и делает то, что следует из его наименования — инициализирует все элементы управления, которые могут быть добавлены к форме. Он также инициализирует свойства формы. В нашем примере метод InitializeComponent() выглядит следующим образом:

private void InitializeComponent()

{

this.SuspendLayout();

this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; this.ClientSize = new System.Drawing.Size(383, 335); this.Name = «Form1»;

this.Text = «Form1»; this.ResumeLayout(false);

}

Как видите, здесь присутствует лишь базовый код инициализации. Этот метод связан с визуальным дизайнером Visual Studio. Когда в форму вносятся изменения в дизайнере, они отражаются на InitializeComponent(). Если вы вносите любые изменения в InitializeComponent(),

то следующий раз после того, как что-то будет изменено в дизайнере, эти ручные изменения будут утеряны. InitializeComponent() повторно генерируется после каждого изменения дизайна формы. Если возникает необходимость добавить некоторый дополнительный код для формы или элементов управления и компонентов формы, это должно быть сделано после вызова InitializeComponent(). Этот метод также отвечает за создание экземпляров элементов управления, поэтому любой вызов, ссылающийся на них, выполненный до InitializeComponent(), завершится возбуждением исключения нулевой ссылки.

Чтобы добавить элемент управления или компонент в форму, нажмите комбинацию клавиш <Ctrl+Alt+X> или выберите пункт меню View — Toolbox (Вид — Панель инструментов) в среде Visual Studio .NET. Щелкните правой кнопкой мыши на Form1.cs в проводнике Solution Explorer и в появившемся контекстном меню выберите пункт View Designer (Показать дизайнер). Выберите элемент управления Button и перетащите на поверхность формы в визуальном дизайнере. Можно также дважды щелкнуть на выбранном элементе управления, и он будет добавлен в форму. То же самое следует проделать с элементом TextBox рис. 1.1. Теперь, после добавления этих двух элементов управления на форму, метод InitializeComponent() расширяется и содержит такой код:

private void InitializeComponent()

{

this.button1 = new System.Windows.Forms.Button(); this.textBox1 = new System.Windows.Forms.TextBox(); this.SuspendLayout();

//

//button1

this.button1.Location = new System.Drawing.Point(166, 44); this.button1.Name = «button1»;

this.button1.Size = new System.Drawing.Size(75, 23); this.button1.TabIndex = 0;

this.button1.Text = «button1»; this.button1.UseVisualStyleBackColor = true;

//textBox1

//

this.textBox1.Location = new System.Drawing.Point(43, 44); this.textBox1.Name = «textBox1»;

this.textBox1.Size = new System.Drawing.Size(100, 20); this.textBox1.TabIndex = 1;

//

// Form1

//

this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; this.ClientSize = new System.Drawing.Size(383, 335); this.Controls.Add(this.textBox1); this.Controls.Add(this.button1);

this.Name = «Form1»; this.Text = «Form1»; this.ResumeLayout(false); this.PerformLayout();

}

Рис. 1.1. Расположение элементов на форме

Если посмотреть на первые три строки кода этого метода, мы увидим в них создание экземпляров элементов управления Button и TextBox. Обратите внимание на имена, присвоенные им — textBox1и button1. По умолчанию дизайнер в качестве имен использует имя класса элемента управления, дополненное целым числом. Когда вы добавляете следующую кнопку, дизайнер называет ее button2 и т.д. Следующая строка — часть пары

SuspendLayout/ResumeLayout. Метод SuspendLayout() временно приостанавливает события размещения, которые имеют место при первоначальной инициализации элемента управления. В конце метода вызывается ResumeLayout(), чтобы вернуть все в норму. В сложной форме с множеством элементов управления метод InitializeComponent() может стать достаточно большим.

Чтобы изменить значения свойств элемента управления, нужно либо нажать <F4>,

либо выбрать пункт меню View-Properties Window (Вид — Окно свойств). Это окно позволяет модифицировать большинство свойств элемента управления или компонента. При внесении изменений в окне свойств метод InitializeComponent() автоматически переписывается с тем, чтобы отразить новые значения свойств. Например, изменив свойство Text на My Button в окне свойств, получим следующий код в InitializeComponent():

//

// button1

//

this.button1.Location = new System.Drawing.Point(34, 33); this.button1.Name = «button1»;

this.button1.Size = new System.Drawing.Size(75, 23); this.button1.TabIndex = 0;

this.button1.Text = «My Button «; this.button1.UseVisualStyleBackColor = true;

Иерархия классов

Важность понимания иерархии становится очевидной в процессе проектирования и конструирования пользовательских элементов управления. Если такой элемент управления унаследован от конкретного библиотечного элемента управления, например, когда создается текстовое поле с некоторыми дополнительными методами и свойствами, то имеет смысл унаследовать его от обычного текстового поля и затем переопределить и добавить необходимые методы. Однако если приходится создавать элемент управления, который не соответствует ни одному из существующих в .NET Framework, то его придется унаследовать от одного из базовых классов: Control или ScrollableControl, если нужны возможности прокрутки, либо ContainerControl, если он должен служить контейнером для других элементов управления.

Класс Control

Пространство имен System.Windows.Forms включает один класс, который является базовым почти для всех элементов управления и форм — System.Windows.Forms.Control. Он реализует основную функциональность для создания экранов, которые видит пользователь. Класс Control

унаследован от System.ComponentModel.Component. Класс Component обеспечивает классу

Control инфраструктуру, необходимую для того, чтобы его можно было перетаскивать и помещать на поле дизайнера, а также, чтобы он мог включать в себя другие элементы управления. Класс Control предлагает огромный объем функциональности классам, наследуемым от него. Этот список слишком большой, чтобы приводить его здесь, поэтому в данном разделе мы рассмотрим только наиболее важные возможности, предоставляемые классом Control.

Размер и местоположение

Размер и местоположение элементов управления определяются свойствами Height, Width, Top, Bottom, Left и Right, вместе с дополняющими их Size и Location. Отличие состоит в том, что Height, Width, Top, Bottom, Leftи Right принимают одно целое значение. Size принимает значение структуры Size, а Location — значение структуры Point. Структуры Size и Point включают в себя координаты X, Y. Point обычно описывает местоположение, а Size— высоту и ширину объекта. Size и Point определены в пространстве имен System.Drawing. Обе структуры очень похожи в том, что представляют пары координат X, Y, но, кроме того — переопределенные операции, упрощающие сравнения и преобразования. Вы можете, например, складывать вместе две структуры Size. В случае структуры Point операция сложения переопределена таким образом, что можно прибавить к Point структуру Size и получить в результате Point. Это дает эффект прибавления расстояния к местоположению, чтобы получить новое местоположение, что очень удобно для динамического создания форм и элементов управления.

Свойство Bounds возвращает объект Rectangle, представляющий экранную область, занятую элементом управления. Эта область включает полосы прокрутки и заголовка. Rectangle также относится к пространству имен System.Drawing. Свойство ClientSize — структура Size, представляющая клиентскую область элемента управления за вычетом полос прокрутки и заголовка.

Методы PointToClient и PointToScreen— удобные методы преобразования, которые принимают Point и возвращают Point. Метод PointToClient принимает структуру Point, представляющую экранные координаты, и транслирует их в координаты текущего клиентского объекта. Это удобно для операций перетаскивания. Метод PointToScreen выполняет обратную операцию — принимает координаты в клиентском объекте и транслирует их в экранные координаты.

Методы RectangleToScreen и ScreenToRectangle выполняют те же операции, но со структурами Rectangle вместо Point.

Свойство Dock определяет, к какой грани родительского элемента управления должен пристыковываться данный элемент. Перечисление DockStyle задает возможные значения этого свойства. Они могут быть такими: Top, Bottom, Right, Left, Fill и None. Значение Fill

устанавливает размер данного элемента управления равным размеру родительского.

Свойство Anchor(якорь) прикрепляет грань данного элемента управления к грани родительского элемента управления. Это отличается от стыковки (docking) тем, что не устанавливает грань дочернего элемента управления точно на грань родительского, а просто выдерживает постоянное расстояние между ними. Например, если якорь правой грани элемента управления установлен на правую грань родительского элемента, и если родитель изменяет размер, то правая грань данного элемента сохраняет постоянную дистанцию от правой грани родителя — т.е. он изменяет размер вместе с родителем. Свойство Anchor принимает значения из перечисления AnchorStyle, а именно: Top, Bottom, Left, Right и None. Устанавливая эти значения, можно заставить элемент управления изменять свой размер динамически вместе с родителем. Таким образом, кнопки и текстовые поля не будут усечены или скрыты при изменении размеров формы пользователем.

Свойства Dock и Anchor применяются в сочетании с компоновками элементов управления Flow и Table они позволяют создавать очень сложные пользовательские окна. Изменение размеров окна может оказаться достаточно непростой задачей для сложных форм с множеством элементов управления. Эти инструменты существенно облегчают задачу.

Внешний вид

Свойства, имеющие отношение к внешнему виду элемента управления — это BackColor и ForeColor, которые принимают объект System.Drawing.Color в качестве значения. Свойство BackGroundImage принимает объект графического образа как значение. Класс System.Drawing.Image — абстрактный класс, служащий в качестве базового для классов Bitmap

и Metafile. Свойство BackgroundImageLayout использует перечисление ImageLayout для определения способа отображения графического образа в элементе управления. Допустимые значения таковы: Center, Tile, Stretch, Zoom или None.

Свойства Font и Text работают с надписями. Чтобы изменить Font, необходимо создать объект Font. При создании этого объекта указывается имя, стиль и размер шрифта.

Взаимодействие с пользователем

Взаимодействие с пользователем лучше всего описывается серией событий, которые генерирует элемент управления и на которые он реагирует. Некоторые из наиболее часто используемых событий: Click, DoubleClick, KeyDown, KeyPress, Validatingи Paint. События, связанные с мышью — Click, DoubleClick, MouseDown, MouseUp, MouseEnter, MouseLeave и

MouseHover— описывают взаимодействие мыши и экранного элемента управления. Если вы обрабатываете оба события — Click и DoubleClick— то всякий раз, когда перехватывается событие DoubleClick, также возбуждается и событие Click. Это может привести к нежелательным последствиям при неправильной обработке. К тому же и Click, и DoubleClick принимают в качестве аргумента EventArgs, в то время как события MouseDown и MouseUp принимают MouseEventArgs. Структура MouseEventArgs содержит несколько частей полезной информации — например, о кнопке, на которой был выполнен щелчок, количестве щелчков на

кнопке, количестве щелчков колесика мыши, текущих координатах X и Y указателя мыши. Если нужен доступ к любой подобной информации, то вместо событий Click или DoubleClick потребуется обрабатывать события MouseDown и MouseUp. События клавиатуры работают подобным образом. Объем необходимой информации определяет выбор обрабатываемых событий. Для простейших случаев событие KeyPress принимает KeyPressEventArgs. Эта структура включает KeyChar, представляющий символ нажатой клавиши. Свойство Handled используется для определения того, было ли событие обработано. Установив значение Handled в true, можно добиться того, что событие не будет передано операционной системе для совершения стандартной обработки. Если необходима дополнительная информация о нажатой клавише, то больше подойдут события KeyDown или KeyUp. Оба принимают структуру KeyEventArgs. Свойства KeyEventArgs включают признак одновременного состояния клавиш <Ctrl>, <Alt> или <Shift>. Свойство KeyCode возвращает значение типа перечисления Keys, идентифицирующее нажатую клавишу. В отличие от свойства KeyPressEventArgs. KeyChar, свойство KeyCode сообщает о каждой клавише клавиатуры, а не только о буквенно-цифровых клавишах. Свойство KeyData возвращает значение типа Keys, а также устанавливает модификатор. Значение модификатора сопровождает значение клавиши, объединяясь с ним двоичной логической операцией “ИЛИ”. Таким образом, можно получить информацию о том, была ли одновременно нажата клавиша <Shift>или <Ctrl>. Свойство KeyValue— целое значение из перечисления Keys. Свойство Modifiers содержит значение типа Keys, представляющее нажатые модифицирующие клавиши. Если было нажато более одной такой клавиши, их значения объединяются операцией “ИЛИ”. События клавиш поступают в следующем порядке:

1.KeyDown

2.KeyPress

3.KeyUp

События Validating, Validated, Enter, Leave, GotFocusи LostFocus имеют отношение к получению фокуса элементами управления (т.е. когда становятся активными) и утере его. Это случается, когда пользователь нажатием клавиши <Tab> переходит к данному элементу управления либо выбирает его мышью. Может показаться, что события Enter, Leave, GotFocusи LostFocus очень похожи в том, что они делают. События GotFocus и LostFocus относятся к низкоуровневым, и связаны с событиями Windows WM_SETFOCUS и WM_KILLFOCUS. Обычно когда возможно, лучше использовать события Enter и Leave. События Validatin gи Validated возбуждаются при проверке данных в элементе управления. Эти события принимают аргумент CancelEventArgs. С его помощью можно отменить последующие события, установив свойство Cancel в true. Если вы разрабатываете собственный проверочный код, и проверка завершается неудачно, то в этом случае можно установить Cancel в true — тогда элемент управления не

утратит фокус. Validating происходит во время проверки, а Validated — после нее. Порядок

возникновения событий следующий:

1.Enter

2.GotFocus

3.Leave

4.Validating

5.Validated

6.LostFocus

Понимание последовательности этих событий важно, чтобы избежать рекурсивных ситуаций. Например, попытка установить фокус элемента управления внутри обработчика события LostFocus создает ситуацию взаимоблокировки в цикле событий, и приложение перестает реагировать на внешние воздействия.

Стандартные элементы управления и компоненты

Рассмотрим различные стандартные элементы управления, поставляемые в составе .NET Framework, и объясним, какую дополнительную функциональность они предлагают.

Форма frmControls, содержит многие элементы управления с базовой функциональностью. На рис. 2.2 показан ее внешний вид.

Рис. 2.2 Форма с основными элементами

Button

Класс Button представляет простую командную кнопку и наследуется от ButtonBase. Чаще всего требует написания кода обработки события Click. Следующий фрагмент кода реализует обработчик события Click. Когда выполняется щелчок на кнопке, появляется окно сообщения, отображающее имя кнопки.

private void button1_Click(object sender, EventArgs e)

{

MessageBox.Show(«Выполнен щелчок на » + ((Button)sender).Name + «.»);

}

С помощью метода PerformClick можно эмулировать событие Click кнопки без необходимости действительного выполнения щелчка пользователем. Метод NotifyDefault принимает в параметре значение булевского типа и сообщает кнопке, чтобы она отобразила себя как кнопку по умолчанию. Обычно кнопка по умолчанию на форме имеет слегка утолщенную рамку. Чтобы идентифицировать кнопку как кнопку по умолчанию, потребуется установить свойство AcceptButton формы равным ссылке на эту кнопку. После этого, если пользователь нажмет клавишу <Enter>, сгенерируется событие Click этой кнопки по умолчанию. На рис. 2.3 Кнопка с меткой Default (По умолчанию) является кнопкой по умолчанию (обратите внимание на темную рамку). Кнопки могут содержать на своей поверхности как текст, так и графическое изображение. Изображения доступны для кнопок через объект ImageList или свойство Image.

Рис. 2.3 Кнопка с меткой Default

  • Sample solution demonstrating different IDisposable-behavior of components with different constructors — 15.6 Kb

MainForm from the sample solution.

Introduction

A couple of days ago, I’ve got an email from a fellow developer with a rather interesting question concerning the Visual Studio .NET Windows Forms designer. The guy asked about the meaning of the components member generated by the designer and why it is not used in most of the Forms he designed.

The components member is generated as part of the «Windows Forms Designer generated code» region, which is part of every Form created and managed by means of the Visual Studio .NET Windows Forms designer:

#Region " Windows Form Designer generated code "
 ..
  
  Protected Overloads Overrides Sub Dispose(ByVal disposing As Boolean)

    If disposing Then
      If Not (components Is Nothing) Then
        components.Dispose()
      End If
    End If
    MyBase.Dispose(disposing)
  End Sub

  
  Private components As System.ComponentModel.IContainer
...
#End Region

The code and the comments indicate that the components member is used by the Form to hold the list of components in order to be able to dispose the components as part of the Form.Dispose call.

I’ve checked the designer-generated code in all my .NET Windows Forms projects and I’ve realized that the components member is actually used only when a component having a specific constructor is placed onto a Form.

You might recall that a component is a class that implements the System.ComponentModel.IComponent interface (either directly or by deriving from a class that already implements the interface, such as System.ComponentModel.Component). If the component exposes a constructor with the specific signature Public Sub New(ByVal c As IContainer), then the components Form member is instantiated and passed to the component’s constructor:

#Region " Windows Form Designer generated code "
 ..
<System.Diagnostics.DebuggerStepThrough()> _
Private Sub InitializeComponent()
  Me.components = New System.ComponentModel.Container
  ...
  Me.ImageList1 = _
    New System.Windows.Forms.ImageList(Me.components)
...
#End Region

Within the New(ByVal c As IContainer) constructor, the component adds itself to the container by calling the IContainer.Add method. Within the Form.Dispose method, the components.Dispose method is called ensuring that all the resources held by the Form‘s components are correctly released.

At this point, it started to make sense, although I still wondered how are components without the New(IContainer) constructor disposed off? I’ve found several such components in the System.Windows.Forms namespace having only the default (parameterless) constructor, for example:

System.Windows.Forms.ColumnHeader
System.Windows.Forms.DataGridTableStyle
System.Windows.Forms.ColorDialog
System.Windows.Forms.FontDialog
System.Windows.Forms.OpenFileDialog
System.Windows.Forms.SaveFileDialog
...

Regarding their «dispose» behavior, the classes can be roughly divided into two groups:

The classes in the first group are always contained within a parent component (or control), so they are disposed along with their container. For instance, System.Windows.Forms.ColumnHeader instances are contained within the System.Windows.Forms.ListView.Columns collection. The System.Windows.Forms.DataGridTableStyle instances are contained within the System.Windows.Forms.DataGrid.TableStyles collection.

The classes in the second group (represented by the System.Windows.Forms.*Dialog classes above) are NOT disposed as part of their owning Form disposal. I can only guess that the classes either don’t hold onto any unmanaged resources during their lifetime, or there are some other mechanisms for releasing their resources (Windows messages come to mind, for example).

In order to verify the above-mentioned disposable behavior, I’ve created a Windows Application project implementing two components (you can download the solution here). The SimpleComponent class was created WITHOUT the New(IContainer) constructor. The ContainedComponent class was created WITH the New(IContainer) constructor:

Public Class SimpleComponent
  Inherits System.ComponentModel.Component

  Public Sub New()
    MyBase.New()
  End Sub

  Protected Overloads Overrides Sub Dispose(ByVal disposing As Boolean)
    Debug.WriteLine(String.Format("{0}({1})", _ 
                 Me.GetType().FullName, disposing))
    MyBase.Dispose(disposing)
  End Sub

End Class


Public Class ContainedComponent
  Inherits System.ComponentModel.Component

  Public Sub New()
    MyBase.New()
  End Sub

  Public Sub New(ByVal Container As System.ComponentModel.IContainer)
    Me.New()
    Container.Add(Me)
  End Sub

  Protected Overloads Overrides Sub Dispose( _
    ByVal disposing As Boolean)

    Debug.WriteLine(String.Format("{0}({1})", _ 
                Me.GetType().FullName, disposing))
    MyBase.Dispose(disposing)
  End Sub

End Class

After recompiling the solution, I was able to add the two components to the Visual Studio .NET toolbox and I’ve dropped both of the components onto a DialogForm form class. Here is the instantiation code that the Windows Forms designer generated for the two components:

#Region " Windows Form Designer generated code "
 ..
  Me.components = New System.ComponentModel.Container
  Me.SimpleComponent1 = New DisposableComponents.SimpleComponent
  Me.ContainedComponent2 = _ 
    New DisposableComponents.ContainedComponent(Me.components)
...
#End Region

Because the ContainedComponent class exposes the New(IContainer) constructor, the designer generated code to call this constructor instead of the default one. In the constructor, the ContainedComponent instance adds itself to the Form.components container, so it is automatically disposed when the Form‘s Dispose(Boolean) method is called.

In contrast, the SimpleComponent instance does not really know when the owning Form is disposed, so it remains alive until it becomes garbage-collected eventually.

In the application’s main form, the following code is used to display the DialogForm containing the two components:

Private Sub ShowDialogButton_Click(...)
  Dim Dialog As DialogForm
  Try
    Dialog = New DialogForm
    Dialog.ShowDialog(Me)
  Catch ex As Exception
    Trace.WriteLine(ex.ToString())
    MsgBox(ex.Message, MsgBoxStyle.Exclamation)
  Finally
    If Not Dialog Is Nothing Then
      Dialog.Dispose()
    End If
  End Try
End Sub

When you run the application and click the ShowDialogButton button, the DialogForm instance is displayed. If you dismiss the dialog, the DialogForm.Dispose method is called and you’ll see in the Output window that the ContainedComponent.Dispose method has been called as well.

In contrast, the SimpleComponent instance is NOT disposed until after the application is ended or until garbage collection takes place. (It might happen if you create and destroy several instances of the DialogForm so enough memory is allocated that a threshold for the garbage collection is reached. Just press and hold the ENTER key and you’ll reach the threshold quickly.)

After looking at how the Windows Forms designer handles components, I think it might be useful to have a quick look at how Controls are handled with regards to IDisposable.

Every Windows Forms control derives from the System.Windows.Forms.Control base class, which exposes the Controls property:

Public ReadOnly Property Controls() As ControlCollection

The implementation of the Control.Dispose(Boolean) is overridden in such a way that it iterates through the Controls collection calling the Dispose method for each member of the collection. The Windows Forms Designer «knows» this and the code it generates for Control-derived classes always adds controls to the Control.Controls collection that the Form class inherits from the Control class:

#Region " Windows Form Designer generated code "
 ..
<System.Diagnostics.DebuggerStepThrough()> Private Sub InitializeComponent()
  Me.TextBox1 = New System.Windows.Forms.TextBox
  ...
  Me.Controls.Add(Me.TextBox1)
End Sub
...
#End Region

This way, when the Form is being disposed, the contained controls are disposed automatically as well.

I don’t really know why the Component containment support is not built into the Form class just like the Control containment represented by the Form.Controls collection. It would have been more consistent and also it would make the generated code smaller and more elegant. For example, it wouldn’t have been necessary to neither generate the components member declaration, nor the Dispose(Boolean) method override. If someone is able to explain the reasoning behind this inconsistency, please let me know — I’m really curious about that.

This leads me to an important recommendation:

If you’ve been designing a component that allocates UNMANAGED resources, please double check that you:

  1. Implement the specific Public New(IContainer) constructor and add your component instance to the container by calling the IContainer.Add(Me) method in the constructor. (If you create your component using the Visual Studio .NET ‘Component Class’ template, it generates the specific constructor for you properly.)
  2. Implement the IDisposable design pattern properly meaning that you do release the unmanaged resources and also that you do that exactly once.

Please, take a look here if you’d like to see an alternate IDisposable design pattern — more robust and elegant than its .NET counterpart, IMHO.

History

February 1, 2004

Published.

I live in Slovakia with my wife, two sons and two daughters. I’ve been doing Microsoft Windows development since 1988; primarily in VB. I’m a big fan of the MS .NET framework, publisher of the www.vbinfozine.com ezine and the author of components found at www.lamarvin.com.

  • Sample solution demonstrating different IDisposable-behavior of components with different constructors — 15.6 Kb

MainForm from the sample solution.

Introduction

A couple of days ago, I’ve got an email from a fellow developer with a rather interesting question concerning the Visual Studio .NET Windows Forms designer. The guy asked about the meaning of the components member generated by the designer and why it is not used in most of the Forms he designed.

The components member is generated as part of the «Windows Forms Designer generated code» region, which is part of every Form created and managed by means of the Visual Studio .NET Windows Forms designer:

#Region " Windows Form Designer generated code "
 ..
  
  Protected Overloads Overrides Sub Dispose(ByVal disposing As Boolean)

    If disposing Then
      If Not (components Is Nothing) Then
        components.Dispose()
      End If
    End If
    MyBase.Dispose(disposing)
  End Sub

  
  Private components As System.ComponentModel.IContainer
...
#End Region

The code and the comments indicate that the components member is used by the Form to hold the list of components in order to be able to dispose the components as part of the Form.Dispose call.

I’ve checked the designer-generated code in all my .NET Windows Forms projects and I’ve realized that the components member is actually used only when a component having a specific constructor is placed onto a Form.

You might recall that a component is a class that implements the System.ComponentModel.IComponent interface (either directly or by deriving from a class that already implements the interface, such as System.ComponentModel.Component). If the component exposes a constructor with the specific signature Public Sub New(ByVal c As IContainer), then the components Form member is instantiated and passed to the component’s constructor:

#Region " Windows Form Designer generated code "
 ..
<System.Diagnostics.DebuggerStepThrough()> _
Private Sub InitializeComponent()
  Me.components = New System.ComponentModel.Container
  ...
  Me.ImageList1 = _
    New System.Windows.Forms.ImageList(Me.components)
...
#End Region

Within the New(ByVal c As IContainer) constructor, the component adds itself to the container by calling the IContainer.Add method. Within the Form.Dispose method, the components.Dispose method is called ensuring that all the resources held by the Form‘s components are correctly released.

At this point, it started to make sense, although I still wondered how are components without the New(IContainer) constructor disposed off? I’ve found several such components in the System.Windows.Forms namespace having only the default (parameterless) constructor, for example:

System.Windows.Forms.ColumnHeader
System.Windows.Forms.DataGridTableStyle
System.Windows.Forms.ColorDialog
System.Windows.Forms.FontDialog
System.Windows.Forms.OpenFileDialog
System.Windows.Forms.SaveFileDialog
...

Regarding their «dispose» behavior, the classes can be roughly divided into two groups:

The classes in the first group are always contained within a parent component (or control), so they are disposed along with their container. For instance, System.Windows.Forms.ColumnHeader instances are contained within the System.Windows.Forms.ListView.Columns collection. The System.Windows.Forms.DataGridTableStyle instances are contained within the System.Windows.Forms.DataGrid.TableStyles collection.

The classes in the second group (represented by the System.Windows.Forms.*Dialog classes above) are NOT disposed as part of their owning Form disposal. I can only guess that the classes either don’t hold onto any unmanaged resources during their lifetime, or there are some other mechanisms for releasing their resources (Windows messages come to mind, for example).

In order to verify the above-mentioned disposable behavior, I’ve created a Windows Application project implementing two components (you can download the solution here). The SimpleComponent class was created WITHOUT the New(IContainer) constructor. The ContainedComponent class was created WITH the New(IContainer) constructor:

Public Class SimpleComponent
  Inherits System.ComponentModel.Component

  Public Sub New()
    MyBase.New()
  End Sub

  Protected Overloads Overrides Sub Dispose(ByVal disposing As Boolean)
    Debug.WriteLine(String.Format("{0}({1})", _ 
                 Me.GetType().FullName, disposing))
    MyBase.Dispose(disposing)
  End Sub

End Class


Public Class ContainedComponent
  Inherits System.ComponentModel.Component

  Public Sub New()
    MyBase.New()
  End Sub

  Public Sub New(ByVal Container As System.ComponentModel.IContainer)
    Me.New()
    Container.Add(Me)
  End Sub

  Protected Overloads Overrides Sub Dispose( _
    ByVal disposing As Boolean)

    Debug.WriteLine(String.Format("{0}({1})", _ 
                Me.GetType().FullName, disposing))
    MyBase.Dispose(disposing)
  End Sub

End Class

After recompiling the solution, I was able to add the two components to the Visual Studio .NET toolbox and I’ve dropped both of the components onto a DialogForm form class. Here is the instantiation code that the Windows Forms designer generated for the two components:

#Region " Windows Form Designer generated code "
 ..
  Me.components = New System.ComponentModel.Container
  Me.SimpleComponent1 = New DisposableComponents.SimpleComponent
  Me.ContainedComponent2 = _ 
    New DisposableComponents.ContainedComponent(Me.components)
...
#End Region

Because the ContainedComponent class exposes the New(IContainer) constructor, the designer generated code to call this constructor instead of the default one. In the constructor, the ContainedComponent instance adds itself to the Form.components container, so it is automatically disposed when the Form‘s Dispose(Boolean) method is called.

In contrast, the SimpleComponent instance does not really know when the owning Form is disposed, so it remains alive until it becomes garbage-collected eventually.

In the application’s main form, the following code is used to display the DialogForm containing the two components:

Private Sub ShowDialogButton_Click(...)
  Dim Dialog As DialogForm
  Try
    Dialog = New DialogForm
    Dialog.ShowDialog(Me)
  Catch ex As Exception
    Trace.WriteLine(ex.ToString())
    MsgBox(ex.Message, MsgBoxStyle.Exclamation)
  Finally
    If Not Dialog Is Nothing Then
      Dialog.Dispose()
    End If
  End Try
End Sub

When you run the application and click the ShowDialogButton button, the DialogForm instance is displayed. If you dismiss the dialog, the DialogForm.Dispose method is called and you’ll see in the Output window that the ContainedComponent.Dispose method has been called as well.

In contrast, the SimpleComponent instance is NOT disposed until after the application is ended or until garbage collection takes place. (It might happen if you create and destroy several instances of the DialogForm so enough memory is allocated that a threshold for the garbage collection is reached. Just press and hold the ENTER key and you’ll reach the threshold quickly.)

After looking at how the Windows Forms designer handles components, I think it might be useful to have a quick look at how Controls are handled with regards to IDisposable.

Every Windows Forms control derives from the System.Windows.Forms.Control base class, which exposes the Controls property:

Public ReadOnly Property Controls() As ControlCollection

The implementation of the Control.Dispose(Boolean) is overridden in such a way that it iterates through the Controls collection calling the Dispose method for each member of the collection. The Windows Forms Designer «knows» this and the code it generates for Control-derived classes always adds controls to the Control.Controls collection that the Form class inherits from the Control class:

#Region " Windows Form Designer generated code "
 ..
<System.Diagnostics.DebuggerStepThrough()> Private Sub InitializeComponent()
  Me.TextBox1 = New System.Windows.Forms.TextBox
  ...
  Me.Controls.Add(Me.TextBox1)
End Sub
...
#End Region

This way, when the Form is being disposed, the contained controls are disposed automatically as well.

I don’t really know why the Component containment support is not built into the Form class just like the Control containment represented by the Form.Controls collection. It would have been more consistent and also it would make the generated code smaller and more elegant. For example, it wouldn’t have been necessary to neither generate the components member declaration, nor the Dispose(Boolean) method override. If someone is able to explain the reasoning behind this inconsistency, please let me know — I’m really curious about that.

This leads me to an important recommendation:

If you’ve been designing a component that allocates UNMANAGED resources, please double check that you:

  1. Implement the specific Public New(IContainer) constructor and add your component instance to the container by calling the IContainer.Add(Me) method in the constructor. (If you create your component using the Visual Studio .NET ‘Component Class’ template, it generates the specific constructor for you properly.)
  2. Implement the IDisposable design pattern properly meaning that you do release the unmanaged resources and also that you do that exactly once.

Please, take a look here if you’d like to see an alternate IDisposable design pattern — more robust and elegant than its .NET counterpart, IMHO.

History

February 1, 2004

Published.

I live in Slovakia with my wife, two sons and two daughters. I’ve been doing Microsoft Windows development since 1988; primarily in VB. I’m a big fan of the MS .NET framework, publisher of the www.vbinfozine.com ezine and the author of components found at www.lamarvin.com.

Понравилась статья? Поделить с друзьями:
  • Код для установки windows xp sp3
  • Код активации windows 7 максимальная 64 bit бесплатно
  • Код а97 произошла неизвестная ошибка windows update
  • Код для установки windows 10 home
  • Код активации windows 7 корпоративная сборка 7601