Компьютерная графика, мультимедиа и игры на Visual C#

         

Проектирование заготовительных операций подготовки материала


Листинг 86.1. Расчет оптимальных параметров разрезки листа на полосы.

//Объявляем глобальные переменные:

public double d, H, Rn, s, s_sheet, C, L, rho,

      nu, El, sig_ys, sig_u, e_u, e_tot;

public int Radio;

double dH, Ha, D;

double B, a, b, t, W, F, Nbl, W_F;

double pi = Math.PI;

// Расчетные функции:

//Функции класса объектов "Полуфабрикаты":

double Allowance()

{

      //Определение техн-го припуска, например, по таблице:

      dH=5;

      //Если включен переключатель 2,

      // то обрезка припуска не нужна; при этом  Radio=1:

      if (Radio==1) dH=0;

      return dH;

}

double Semiproduct()



{

      dH=Allowance();

      //Расчет размеров полуфабриката:

      Ha = H + dH;

      return Ha;

}

//Функции класса объектов "Заготовки":

double Area1_Semiproduct()

{

      double A1 = pi*(d-2*Rn)*(d-2*Rn)/4;

      return A1; //mm*mm

}

double Area2_Semiproduct()

{

      double A2 = pi*(Rn-s/2)*(2*(Rn-s/2)+pi*(d-2*Rn)/2);

      return A2; //mm*mm

}

double Area3_Semiproduct()

{

      Ha=Semiproduct();

      double A3 = pi*(d-s)*(Ha-Rn);

      return A3; //mm*mm

}

double Area_Semiproduct()

{

      double A, A1, A2, A3;

      A1=Area1_Semiproduct();

      A2=Area2_Semiproduct();

      A3=Area3_Semiproduct(); A=A1+A2+A3;

      return A;

}

double DBlank()

{

      double A = Area_Semiproduct();

      D=Math.Sqrt(4*A/pi);

      return D;

}

//Функции класса объектов "Материалы":

double Bstrip()

{

      //Определение параметров раскроя:

      double del_st, del1, z_b;

      a=1.2; b=1.6; del_st=0.7; del1=0.4; z_b=1;

      //Шаг вырезки заготовок:

      D = DBlank(); t = D + a;

      //Расчет ширины полосы:

      B = D + 2*(b + del_st) + z_b + del1;

      return B;

}

void Cutting()

{

      //Определение параметров раскроя:

      double N_strip_1, N_strip_2, N_bl_st_1, N_bl_st_2,

            N_bl_1, N_bl_2;

      B = Bstrip();

      //Число полос из листа при продольной разрезке:


      N_strip_1 = Math.Floor(C/B);
      // Число полос из листа при поперечной разрезке:
      N_strip_2 = Math.Floor(L/B);
      //Шаг вырезки заготовок:
      D = DBlank(); t = D + a;
      //Число заготовок из полосы при продольной разрезке:
      N_bl_st_1 = Math.Floor((L - a)/t);
      //Число заготовок из полосы при поперечной разрезке:
      N_bl_st_2 = Math.Floor((C - a)/t);
      //Число заготовок из листа при продольной разрезке:
      N_bl_1 = N_bl_st_1 * N_strip_1;
      //Число заготовок из листа при поперечной разрезке:
      N_bl_2 = N_bl_st_2 * N_strip_2;
      //Проверка, при каком варианте разрезки
      // заготовок больше:
      if (N_bl_1 >= N_bl_2)
      {
            //Передача рассчитанных значений в окна TextBox:
            textBox5.Text = N_strip_1.ToString();
            W = N_strip_1 * B;
            textBox6.Text = W.ToString();
            F = C - W;
            textBox7.Text = F.ToString();
            textBox8.Text = C.ToString(); W_F = C;
            textBox9.Text = (W/W_F).ToString();
            Nbl=N_bl_1;
      }
      else
      {
            //Передача рассчитанных значений в окна TextBox:
            textBox5.Text = N_strip_2.ToString();
            W = N_strip_2 * B;
            textBox6.Text = W.ToString();
            F = L - W;
            textBox7.Text = F.ToString();
            textBox8.Text = L.ToString(); W_F = L;
            textBox9.Text = (W/W_F).ToString();
            Nbl=N_bl_2;
      }
}
Теперь для выполнения расчета и вывода результатов расчета в окна TextBox на Form3 (при помощи кнопки со знаком равенства “=”) дважды щелкаем эту кнопку. Появляется файл Form3.cs с шаблоном, в который записываем следующий код.
Листинг 86.2. Код кнопки “=” на Form3 для расчета первой операции.
//Передача размеров листа s, C, L
//из окон TextBox на Form1 в окна TextBox на Form3:
textBox1.Text = s_sheet.ToString();
textBox2.Text = C.ToString();
textBox3.Text = L.ToString();


//Расчет и передача значения ширины полосы "B"
//в окно TextBox4 на Form3:
textBox4.Text = Bstrip().ToString();
//Расчет и передача рациональных параметров
//разрезки листа на полосы в окна TextBox на Form3:
Cutting();
Листинг 86.3. Код для выполнения анимации.
bool myColor = false;
private void timer1_Tick(object sender, EventArgs e)
{
      //Вводим анимацию:
      if (myColor == false)
      {
            //Выводим красный цвет надписи элемента упр-я:
            this.button1.ForeColor = Color.Red;
            //Изменяем значение myColor на противоположное:
            myColor = true;
      }
      else
      {
            //Выводим зеленый цвет надписи элемента упр-я:             this.button1.ForeColor = Color.Green;
            //Изменяем значение myColor на противоположное:
            myColor = false;
      }
}
Щелчок по значку “x” (Close), который уже был на Form1 после создания проекта, или по кнопке Cancel, которую ввели мы (для удобства), закрывает не только данный активный вид панели, но и все последующие виды панели, которые мы вызвали после данного вида (т.е. закрываем приложение). После щелчка значка “x” (Close) или кнопки Cancel на Form3 закрывается только один этот вид панели, а все остальные панели остаются открытыми, и мы можем их анализировать или читать справку (если щелкнуть кнопку Help). Методика печати на принтере информации с панели (после щелчка кнопки Print, рис. 86.1) описана выше.
Как уже отмечалось, на практике часто ограничиваются только первой операцией разрезки листа на полосы; в этом случае следующая операция не нужна, и, соответственно, не нужна и кнопка Next>> на Form3. В нашем общем случае требуется, чтобы после щелчка кнопки Next>> выходила следующая форма (со следующим эффектом анимации), к разработке которой мы и приступаем.

Программирование портативных и карманных компьютеров


Листинг 74.1. Метод для сложения чисел.

private void button1_Click(object sender, EventArgs e)

{

    double a, b, c;

    a = Convert.ToDouble(textBox1.Text);

    b = Convert.ToDouble(textBox2.Text);

    c = a + b;

    textBox3.Text = c.ToString();

}

Листинг 74.2. Метод для построения линии.

private void Form1_Paint(object sender, PaintEventArgs e)

{

    Pen myPen = new Pen(Color.Black, 3);

    e.Graphics.DrawLine(myPen, 10, 100, 100,30);

}

Для примера, выделяем первое устройство My Computer. На экране появляется форма Form1 с прямой линией (рис. 74.10). Аналогично  можно выполнять любые другие операции, которые мы запишем в файл Form1.cs.

После запуска этого же проекта (или какого-либо нового проекта этого типа) на выполнение и выбора второго устройства Pocket PC SE Emulator появляется панель, в которую через некоторое время загружается показанный выше эмулятор  Pocket PC, который также полностью функционален.

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



Расчет и изображение


Листинг 41.1. Код выше и в теле процедуры Form1_Load.

    'Вводим функцию для поверхности z = f = f(x, y):

    Private Function f(ByVal x As Single, ByVal y As Single) _

    As Single

        f = 2 * x * x * x * x - 3 * x * x + 4 * y * y

    End Function

    'Вводим функцию для частной производной df/dx:

    Private Function df_dx(ByVal x As Single, _

    ByVal y As Single) As Single

        df_dx = 8 * x * x * x - 6 * x

    End Function

    'Вводим функцию для частной производной df/dy:

    Private Function df_dy(ByVal x As Single, _

    ByVal y As Single) As Single

        df_dy = 8 * y

    End Function

    'Задаем перо для рисования линий уровня:

    Private myPen As Pen

    'Загружаем функции для рисования линий уровня:

    Private Sub Form1_Load(ByVal sender As System.Object, _

    ByVal e As EventArgs) Handles MyBase.Load

        'Задаем цвет пера:

        myPen = New Pen(Color.Black, 0)

        'Связываем графический элемент PictureBox1

        'с объектом g класса Graphics:

        Dim bmp As New Bitmap(PictureBox1.ClientSize.Width, _

        PictureBox1.ClientSize.Height)

        Dim g As Graphics = Graphics.FromImage(bmp)

        'Определяем преобразования для масштабирования и 

        'рисования линий на PictureBox1 в интервале

        '-1.5 <= x <= 1.5, -1.5 <= y <= 1.5:

        Const x_min As Single = -1.5

        Const x_max As Single = 1.5

        Const y_min As Single = -1.5

        Const y_max As Single = 1.5

        g.ScaleTransform(bmp.Width / (x_max - x_min), _

        bmp.Height / (y_max - y_min))

        g.TranslateTransform(-x_min, -y_min, _

        System.Drawing.Drawing2D.MatrixOrder.Prepend)

        'Вызываем функцию для рисования линий уровня:

        For LevelCurves As Integer = -3 To 10

            PlotLevelCurve(g, CSng( _

            LevelCurves / 4), -4, 4, -4, 4, 0.05, 1, 1, 0.002)

        Next

        'Показываем результат рисования:

        PictureBox1.Image = bmp

    End Sub


Ниже этого кода записываем следующие вспомогательные процедуры.
Листинг 41.2.
Вспомогательные процедуры.
    'Находим точку на линии:
    Private Sub FindPointOnCurve(ByRef x As Single, _
    ByRef y As Single, ByVal LevelCurves As Single, _
    Optional ByVal start_x As Single = 0.1, _
    Optional ByVal start_y As Single = 0.2, _
    Optional ByVal tolerance As Single = 0.01, _
    Optional ByVal initial_delta As Single = 0.1)
        Dim dx As Single : Dim dy As Single
        Dim dz As Single : Dim dist As Single
        Dim delta As Single : Dim f_xy As Single
        Dim direction As Integer
        'Начальная точка:
        x = start_x : y = start_y : delta = initial_delta
        'Повторяем решение:
        Do
            f_xy = f(x, y) : dz = LevelCurves - f_xy
            If Abs(dz) < tolerance Then Exit Do
            'Анализируем направление:
            If Sign(dz) <> direction Then
                'Изменяем направление. Уменьшаем delta:
                delta = delta / 2 : direction = Sign(dz)
            End If
            'Рассчитываем градиент:
            Gradient(x, y, dx, dy)
            If Abs(dx) + Abs(dy) < 0.001 Then Exit Do
            'Перемещаемся направо:
            x = x + dx * delta * direction
            y = y + dy * delta * direction
        Loop
    End Sub
    'Рассчитываем градиент в этой точке:
    Private Sub Gradient(ByVal x As Single, _
    ByVal y As Single, ByRef dx As Single, ByRef dy As Single)
        Dim dist As Single
        dx = df_dx(x, y) : dy = df_dy(x, y)
        dist = CSng(Sqrt(dx * dx + dy * dy))
        If Abs(dist) < 0.0001 Then
            dx = 0 : dy = 0
        Else
            dx = dx / dist : dy = dy / dist
        End If
    End Sub
    'Программируем второй массив для передачи в файл:
    'Задаем границы индексов второго массива myArrayVB_2(i, j):
    Dim N_x_2 As Integer = 20000
    Dim N_y_2 As Integer = 1
    'Объявляем массив myArrayVB_2(i, j) переменных типа Single ,


    'когда i = 0,1,2,3,...,N_x; j = 0,1,2,3,...,N_y:
    Dim myArrayVB_2(20000, 1) As Single 'Автомат-ки обнуляется.
    'Значение первой границы массива myArrayVB_2:
    Dim N_1_myArrayVB_2 As Integer
    'Счетчик элементов массива:
    Dim ii As Integer = -1
    'Рисуем линию уровня f(x, y) = LevelCurves:
    Private Sub PlotLevelCurve(ByVal g As Graphics, _
    ByVal LevelCurves As Single, ByVal x_min As Single, _
    ByVal x_max As Single, ByVal y_min As Single, _
    ByVal y_max As Single, _
    Optional ByVal step_size As Single = 0.1, _
    Optional ByVal start_x As Single = 1.0, _
    Optional ByVal start_y As Single = 1.0, _
    Optional ByVal tolerance As Single = 0.02)
        'Объявляем индексы элементов всех массивов:
        Dim i, j As Integer
        'Программируем 1-й массив для рисования здесь.
        'Задаем границы индексов 1-го массива myArrayVB(i, j):
        Dim N_x As Integer = 2000
        Dim N_y As Integer = 1
        'Объявляем 1-й массив myArrayVB(i, j) переменных Single,
        'когда i = 0,1,2,3,...,N_x; j = 0,1,2,3,...,N_y:
        Dim myArrayVB(N_x, N_y) As Single 'Автомат-ки обнуляется.
        'Значение первой границы массива myArrayVB:
        Dim N_1_myArrayVB As Integer
        'Объявляем переменные для точек линий уровня:
        Dim num_points As Integer
        Dim x0 As Single : Dim y0 As Single
        Dim x1 As Single : Dim y1 As Single
        Dim x2 As Single : Dim y2 As Single
        Dim dx As Single : Dim dy As Single
        'Находим точку (x0, y0) на линии уровня LevelCurves:
        FindPointOnCurve(x0, y0, LevelCurves, _
        start_x, start_y, tolerance)
        'Начальная точка линии:
        num_points = 1
        'Следующая линия уровня LevelCurves:
        x2 = x0
        y2 = y0
        i = -1 'Задаем до цикла.
        'Начало цикла Do - Loop:
        Do
            x1 = x2
            y1 = y2
            'Находим следующую точку на линии:
            Gradient(x2, y2, dx, dy)


            If Abs(dx) + Abs(dy) < 0.001 Then Exit Do
            x2 = x2 + dy * step_size
            y2 = y2 - dx * step_size
            FindPointOnCurve(x2, y2, LevelCurves, x2, y2, _
            tolerance)
            'Можно рисовать и здесь (без массива) до этой точки:
            'g.DrawLine(myPen, x1, y1, x2, y2)
            'Записываем коорд-ты точек в 1-й массив для текущей
            ' линии уровня, которую будем рисовать здесь:
            i = i + 2
            myArrayVB(i, 0) = x1
            myArrayVB(i, 1) = y1
            myArrayVB(i + 1, 0) = x2
            myArrayVB(i + 1, 1) = y2
            N_1_myArrayVB = i + 1 'Значение границы массива.
            'Записываем координаты точек текущей линии
            'во 2-й массив, который будем экспортировать в файл:
            ii = ii + 2
            myArrayVB_2(ii, 0) = x1
            myArrayVB_2(ii, 1) = y1
            myArrayVB_2(ii + 1, 0) = x2
            myArrayVB_2(ii + 1, 1) = y2
            N_1_myArrayVB_2 = ii + 1 'Значение границы массива.
            'Задаем следующую точку:
            num_points = num_points + 1
            'Смотрим,находится ли точка вне области рисования:
            If x2 < x_min Or x2 > x_max Or _
               y2 < y_min Or y2 > y_max _
                    Then Exit Do
            'Если мы ушли более чем на 4 точки, то смотрим
            'не пришли ли мы в начало:
            If num_points >= 4 Then
                If Sqrt((x0 - x2) * (x0 - x2) + (y0 - y2) _
                * (y0 - y2)) <= step_size * 1.1 Then
                    'Можно рисовать и здесь (без массива):
                    'g.DrawLine(myPen, x2, y2, x0, y0)
                    'Записываем координаты точек в 1-й массив:
                    i = i + 2
                    myArrayVB(i, 0) = x2
                    myArrayVB(i, 1) = y2
                    myArrayVB(i + 1, 0) = x0
                    myArrayVB(i + 1, 1) = y0
                    N_1_myArrayVB = i + 1 'Граница массива.


                    'Записываем координаты точек во 2-й массив,
                    'который будем экспортировать в файл:
                    ii = ii + 2
                    myArrayVB_2(ii, 0) = x2
                    myArrayVB_2(ii, 1) = y2
                    myArrayVB_2(ii + 1, 0) = x0
                    myArrayVB_2(ii + 1, 1) = y0
                    N_1_myArrayVB_2 = ii + 1 'Граница массива.
                    Exit Do
                End If
            End If
        Loop 'Переход в начало цикла Do - Loop.
        'Начало N_first_line и конец N_last_line цикла
        ' при рисовании здесь из массива myArrayVB:
        Dim N_first_line, N_last_line As Integer
        N_first_line = 1
        N_last_line = N_1_myArrayVB
        'Передаем значения начала N_first_line
        'и конца цикла N_last_line в элементы массива
        'myArrayVB(0, 0) и myArrayVB(0, 1):
        myArrayVB(0, 0) = N_first_line
        myArrayVB(0, 1) = N_last_line
        'Рисуем при помощи массива координат myArrayVB(2000, 1):
        Dim k As Integer
        i = -1
        For k = N_first_line To N_last_line
            i = i + 2
            x1 = myArrayVB(i, 0)
            y1 = myArrayVB(i, 1)
            x2 = myArrayVB(i + 1, 0)
            y2 = myArrayVB(i + 1, 1)
            g.DrawLine(myPen, x1, y1, x2, y2)
        Next
        'Начало N_first_line_2 и конец N_last_line_2 цикла
        'при рисовании из массива myArrayVB_2 в другом проекте:
        Dim N_first_line_2, N_last_line_2 As Integer
        N_first_line_2 = 1
        N_last_line_2 = N_1_myArrayVB_2
        'Передаем значения начала N_first_line_2
        'и конца цикла N_last_line_2 в элементы массива
        'myArrayVB_2(0, 0) и myArrayVB_2(0, 1):
        myArrayVB_2(0, 0) = N_first_line_2
        myArrayVB_2(0, 1) = N_last_line_2
        'Записываем массив корд-т myArrayVB_2(20000, 1) в файл.
        'Создаем объект sw класса StreamWriter
        'для записи в файл D:\MyDocs\MyTest_LevelCurves.txt.
        'Файл автоматически "опустошается":
        Dim sw As StreamWriter = _
        New StreamWriter("D:\MyDocs\MyTest_LevelCurves.txt")
        'Каждый элемент массива myArrayVB_2(i, j) запис-м в файл
        'в виде отдельной строки при помощи процедуры WriteLine:
        For i = 0 To N_x_2
            For j = 0 To N_y_2
                sw.WriteLine(myArrayVB_2(i, j))
            Next
        Next
        sw.Close()
    End Sub
Аналогично можно записать массивы с координатами точек для нескольких геометрических изображений в несколько различных файлов на жестком диске компьютера. И далее в проекте на Visual C#, Visual C++ (или другом языке) можно считывать массивы с координатами точек и выводить эти изображения на экран монитора, а также печатать их на принтере, как будет показано в следующей главе. 

Расчет и изображение линий уровня на поверхности


Листинг 40.1. Код выше и в теле метода Form1_Load.

//Вводим функцию для поверхности z = f1 = f(x, y):

public float f(float x, float y)

{

      float f1;

      f1 = 2 * x * x * x * x - 3 * x * x + 4 * y * y;

      return f1;

}

//Вводим функцию для частной производной df/dx:

public float df_dx(float x, float y)

{

      float f2;

      f2 = 8 * x * x * x - 6 * x;

      return f2;

}

//Вводим функцию для частной производной df/dy:

public float df_dy(float x, float y)

{

      float f3;

      f3 = 8 * y;

      return f3;

}

//Объявляем перо для рисования линий уровня:

Pen myPen;

//Загружаем функции для рисования линий уровня:

private void Form1_Load_1(object sender, EventArgs e)

{

      //Создаем экземпляр пера с цветом и толщиной:

      myPen = new Pen(Color.Black, 0);

      //Связываем графический элемент PictureBox1

      //с объектом g класса Graphics:

      Bitmap bmp = new Bitmap(pictureBox1.ClientSize.Width,

                              pictureBox1.ClientSize.Height);

      Graphics g = Graphics.FromImage(bmp);

      //Определяем преобразования для масштабирования и 

      //рисования линий на PictureBox в интервале

      //-2 <= x <= 2, -1.5 <= y <= 1.5:

      float x_min = -2f;

      float x_max = 2f;

      float y_min = -1.5f;

      float y_max = 1.5f;

      g.ScaleTransform(bmp.Width / (x_max - x_min),

                       bmp.Height / (y_max - y_min));

      g.TranslateTransform(-x_min, -y_min,

      System.Drawing.Drawing2D.MatrixOrder.Prepend);

      //Вызываем функцию для рисования линий уровня:

      for (int LevelCurves = -3; LevelCurves <= 25;

      LevelCurves++)

      PlotLevelCurve(g, Convert.ToSingle(

      LevelCurves / 4),

      -4f, 4f, -4f, 4f, 0.05f, 1f, 1f, 0.002f);

      //Показываем результат рисования:

      pictureBox1.Image = bmp;

}

Ниже этого кода записываем следующие вспомогательные методы.

Листинг 40.2.

Вспомогательные методы.

//Находим точку на линии:

float initial_delta = 0.1f;


private void FindPointOnCurve( ref float x, ref float y,
float LevelCurves, float start_x, float start_y,
float tolerance)
{
      float dx = 0, dy = 0, dz, delta, f_xy;
      int direction = 0;
      //Начальная точка:
      x = start_x; y = start_y; delta = initial_delta;
      //В бесконечном цикле do-while выходим через break:
      int i = 0;
      do
      {
            f_xy = f(x, y); dz = LevelCurves - f_xy;
            if (Math.Abs(dz) < tolerance) break;
            //Анализируем направление:
            if (Math.Sign(dz) != direction)
            {
                  //Изменяем направление. Уменьшаем delta:
                  delta = delta / 2;
                  direction = Math.Sign(dz);
            }
            //Рассчитываем градиент:
            Gradient(x, y, ref dx, ref dy);
            if ((Math.Abs(dx) + Math.Abs(dy)) < 0.001) break;
            //Перемещаемся направо:
            x = x + dx * delta * (float)direction;
            y = y + dy * delta * (float)direction;
      }
      while (i < 1);
}
//Рассчитываем градиент в этой точке:
private void Gradient(float x, float y,
                               ref float dx, ref float dy)
{
      float dist = 0;
      dx = df_dx(x, y); dy = df_dy(x, y);
      dist = Convert.ToSingle(Math.Sqrt(dx * dx + dy * dy));
      if (Math.Abs(dist) < 0.0001)
      {
            dx = 0; dy = 0;
      }
      else
      {
            dx = dx / dist; dy = dy / dist;
      }
}
//Рисуем линию уровня f(x, y) = LevelCurves:
private void PlotLevelCurve(Graphics g,
float LevelCurves, float x_min, float x_max, float y_min,
float y_max, float step_size,
float start_x, float start_y,
float tolerance)
{
      int num_points = 0;
      float x0 = 0, y0 = 0, x1, y1, x2, y2, dx = 0, dy = 0;
      //Находим точку (x0, y0) на линии уровня LevelCurves:
      FindPointOnCurve(ref x0, ref y0, LevelCurves,
      start_x, start_y, tolerance);
      //Начало:
      num_points = 1;


      //Следующая линия уровня LevelCurves:
      x2 = x0; y2 = y0;
      //В бесконечном цикле do-while выходим через break:
      int i = 0;
      do
      {
            x1 = x2; y1 = y2;
            //Находим следующую точку на линии:
            Gradient(x2, y2, ref dx, ref dy);
            if ((Math.Abs(dx) + Math.Abs(dy)) < 0.001) break;
            x2 = x2 + dy * step_size;
            y2 = y2 - dx * step_size;
            FindPointOnCurve(ref x2, ref y2,
                  LevelCurves, x2, y2, tolerance);
            //Рисуем до этой точки:
            g.DrawLine(myPen, x1, y1, x2, y2);
            num_points = num_points + 1;
            //Смотрим,находится ли точка
            //вне области рисования:
            if (x2 < x_min) break;
            if (x2 > x_max) break;
            if (y2 < y_min) break;
            if (y2 > y_max) break;
            // Если мы ушли более чем на 4 точки, то смотрим
            //не пришли ли мы в начало:
            if (num_points >= 4)
            {
                  if (Math.Sqrt((x0 - x2) * (x0 - x2) +
                  (y0 - y2) * (y0 - y2)) <= step_size * 1.1)
                  {
                        g.DrawLine(myPen, x2, y2, x0, y0);
                        break;
                  }
            }
      }
      while (i < 1);
}
Таким образом, мы закончили разработку новой методологии создания графической системы на базе Visual C# для построения на экране монитора и печати на принтере линий уровня для разнообразных трехмерных поверхностей в трехмерном пространстве.
Аналогично по этой методологии можно разработать приложения для построения различных линий уровня на различных поверхностях.

Разработка мультипликации при помощи списка рисунков 


Листинг 66.1. Метод для компонента Timer.

//Объявляем глобальную переменную currentImage

//для номера текущего рисунка и приравниваем нулю:

int currentImage = 0;

private void timer1_Tick(object sender, EventArgs e)

{

      //Последовательно выводим рисунки:

      if(imageList1.Images.Empty != true)

          {

          //Центрируем рисунок внутри рамки PictureBox1:

          pictureBox1.SizeMode =

                        PictureBoxSizeMode.CenterImage;

          //Выводим рисунок с номером 'currentImage' :

          pictureBox1.Image =

                            imageList1.Images[currentImage];

          //Организовываем цикл по индексу 'currentImage' :

          currentImage = currentImage + 1;

          if (currentImage == imageList1.Images.Count)

                                           currentImage = 0;

          }

}

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

Чтобы установить значение свойства Interval компонента Timer в зависимости от свойства Value ползунка элемента управления TrackBar, дважды щелкаем элемент управления TrackBar в режиме проектирования. Появляется файл Form1.cs с шаблоном, который после записи нашего кода принимает следующий вид.

Листинг 66.2. Метод для элемента управления TrackBar.

private void trackBar1_Scroll(object sender, EventArgs e)

{

      timer1.Enabled = true;

      timer1.Interval = trackBar1.Value;

}

Согласно разработанной выше методике, чтобы иметь возможность приостановить (и запустить вновь) процесс анимации на любом рисунке при помощи кнопки Stop/Start Animation, дважды щелкаем эту кнопку в режиме проектирования (рис. 66.1). Появляется файл Form1.cs с шаблоном, который после записи нашего кода принимает такой вид.

 

Листинг 66.3. Метод для кнопки Stop/Start Animation.

bool OffOn = false;

private void button6_Click(object sender, EventArgs e)

{

      //Задаем чередование остановки и возобновления анимации


      //после каждого щелчка кнопки button:
      if (OffOn == false)
      {
          //Приостанавливаем анимацию:
          timer1.Enabled = false;
          //Изменяем значение OffOn на противоположное:
          OffOn = true;
      }
      else
      {
           //Возобновляем анимацию:
           timer1.Enabled = true;
           //Изменяем значение OffOn на противоположное:
           OffOn = false;
      }
}
Листинг 66.4. Метод для компонента PrintDocument.
private void printDocument1_PrintPage(object sender,
               System.Drawing.Printing.PrintPageEventArgs e)
{
      // Выводим рисунок, который видим на экране
      //в рамке pictureBox1, при помощи метода DrawImage:
      e.Graphics.DrawImage(pictureBox1.Image, 0, 0);
}
Теперь дважды щелкаем кнопку Print (рис. 66.1). Открывается файл Form1.cs с шаблоном, в который записываем код из приведенного выше параграфа “Методика печати изображения на принтере”.
В заключении этой главы сделаем вывод, что при разработке мультипликации при помощи компонента ImageList (Список рисунков) код программы получается короче, однако из-за того, что элемент ImageList предназначен для хранения коллекции растровых изображений небольшого размера (не более 256 на 256 пикселей), качество мультипликации из наших больших изображений (размером 880 на 988 пикселей) получается хуже, чем в предыдущей главе, где графические файлы поэтапных рисунков мы ввели непосредственно в приложение (при помощи метода FromFile). Поэтому, когда требуется спроектировать мультипликацию высокого качества из больших (по объему занимаемой памяти) рисунков в виде графических файлов любого формата, целесообразно применять методику, разработанную нами в предыдущей главе.

Разработка стандартного калькулятора


Теперь (для программирования операции сложения) дважды щелкаем кнопку “=” (рис. 11.1) и в появившийся шаблон процедуры записываем код:

      double number2, number3;

      if (i==1)

      {

            number2 = Convert.ToDouble(textBox1.Text);

            number3 = Number + number2;

            textBox1.Text = number3.ToString();

     }

При помощи оператора if сложение выполняется только после того, как предварительно мы щелкнем кнопку “+”, программа присвоит целочисленной переменной i значение 1, и далее щелкнем кнопку “=”.

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

Для вычитания чисел аналогично (как для сложения) дважды щелкаем кнопку “-” (рис. 11.1) и в появившийся шаблон новой процедуры записываем код:

      i=2;

      Number = Convert.ToDouble(textBox1.Text);

      textBox1.Text = "";

      textBox1.Focus();

Дважды щелкаем кнопку “=” (рис. 11.1) и в появившуюся ту же процедуру для этой кнопки, ниже нашего предыдущего кода, записываем следующий код:

      if (i==2)

      {

            number2 = Convert.ToDouble(textBox1.Text);

            number3 = Number - number2;

            textBox1.Text = number3.ToString();

   }

Аналогично для умножения чисел дважды щелкаем кнопку “ * ” (рис. 11.1) и в появившийся шаблон новой процедуры записываем код:

      i=3;

      Number = Convert.ToDouble(textBox1.Text);

      textBox1.Text = "";

      textBox1.Focus();

Дважды щелкаем кнопку “=” (рис. 11.1) и в появившуюся ту же процедуру для этой кнопки, ниже нашего предыдущего кода, записываем следующий код:

      if (i==3)

      {

            number2 = Convert.ToDouble(textBox1.Text);

            number3 = Number * number2;

            textBox1.Text = number3.ToString();

   }

Аналогично для деления чисел дважды щелкаем кнопку “ / ” (рис. 11.1) и в появившийся шаблон новой процедуры записываем код:


      i=4;
      Number = Convert.ToDouble(textBox1.Text);
      textBox1.Text = "";
      textBox1.Focus();
Дважды щелкаем кнопку “=” (рис. 11.1) и в появившуюся ту же процедуру, ниже нашего предыдущего кода, записываем следующий код:
      if (i==4)
      {
            number2 = Convert.ToDouble(textBox1.Text);
            number3 = Number / number2;
            textBox1.Text = number3.ToString();
   }
Наш алгоритм деления “1/x” предусматривает только один щелчок по этой одной кнопке “1/x” (рис. 11.1). Для программирования деления “1/x”, дважды щелкаем эту кнопку “1/x” (рис. 11.1) и в появившийся шаблон новой процедуры записываем код:
      double number2;
      Number = Convert.ToDouble(textBox1.Text);
      number2 = 1/Number;
   textBox1.Text = number2.ToString();
Чтобы наш калькулятор решал пять стандартных задач на проценты, дважды щелкаем эту кнопку “ % ” (рис. 11.1) и в шаблон новой процедуры записываем код:
     
      double number2, number3;
      if (i==1)
      {
            number2 = Convert.ToDouble(textBox1.Text);
            number3 = Number*(1 + number2/100);
            textBox1.Text = number3.ToString();
      }
      if (i==2)
      {
            number2 = Convert.ToDouble(textBox1.Text);
            number3 = Number*(1 - number2/100);
            textBox1.Text = number3.ToString();
      }
      if (i==3)
      {
            number2 = Convert.ToDouble(textBox1.Text);
            number3 = Number*number2/100;
            textBox1.Text = number3.ToString();
      }
      if (i==4)
      {
            number2 = Convert.ToDouble(textBox1.Text);
            number3 = Number/number2*100;
            textBox1.Text = number3.ToString();
   }
Правила вычислений процентов стандартны для нашего, настольного и Windows калькуляторов. А примеры для вычислений процентов на данном втором калькуляторе будут даны и подробно объяснены в следующей главе при создании третьего калькулятора.
Для очистки окна от числа дважды щелкаем кнопку “C” (рис. 11.1) и в появившийся шаблон новой процедуры записываем код:


      textBox1.Text = ""; textBox1.Focus();
Для обнуления памяти, дважды щелкаем кнопку “Memory clearing MC” (рис. 11.1) и в шаблоне новой процедуры обнуляем глобальную переменную Memory:
   Memory = 0;
Чтобы вызвать в окно число, сохраненное нами в памяти калькулятора, дважды щелкаем кнопку “Memory recall MR” (рис. 11.1) и в появившийся шаблон новой процедуры записываем код:
   textBox1.Text = Memory.ToString();
Чтобы занести (сохранить) в память калькулятора записанное нами в окно число, дважды щелкаем кнопку “Store to memory MS” (рис. 11.1) и в появившийся шаблон новой процедуры записываем код:
   Memory = Convert.ToDouble(textBox1.Text);
Чтобы сложить число (которое мы видим в окне) с числом, сохраненным в памяти калькулятора, дважды щелкаем кнопку “Add to memory M+” (рис. 11.1) и в появившийся шаблон новой процедуры записываем код:
      double number2, number3;
      number2 = Convert.ToDouble(textBox1.Text);
      number3 = number2 + Memory;
      textBox1.Text = number3.ToString();
Дадим очень краткие пояснения (так как основная их часть уже дана выше). В памяти калькулятора число присваивается глобальной переменной Memory, а схема применения этой переменной будет описана ниже в последующем параграфе.

Рисование линий при помощи нажатия кнопки мыши


Листинг 27.1. Объявляем глобальные переменные и записываем наш код.

    //Объявляем глобальные переменные для координат "x" и "y"

    //указателя мыши в момент 1-го и 2-го нажатий кнопки мыши:

    public int x_MouseDown_1, y_MouseDown_1,

                x_MouseDown_2, y_MouseDown_2;

    //Чтобы рисование осуществлялось только после каждого щелчка

    //кнопки,объявляем переключатель рисования

    //в виде глобальной переменной OffOn:

    bool OffOn = false;

    private void Form1_MouseDown(object sender, MouseEventArgs e)

    {

        //Объявляем объект "g" класса Graphics

        //и при помощи функции CreateGraphics

        //предоставляем ему возможность рисования

        //на this форме Form1:

        Graphics g = this.CreateGraphics();

        //Выбираем перо "myPen" красного цвета Red

        //толщиной в 3 пикселя:

        Pen myPen = new Pen(Color.Red, 3);

        //Определяем координаты "x" и "y" указателя мыши

        //в момент нажатия кнопки мыши:

        x_MouseDown_2 = e.X;

        y_MouseDown_2 = e.Y;

        //Проверяем условие для переменной OffOn:

        //Если переменная OffOn равна

        //исходному значению false,

        if (OffOn == false)

      {

            //то задаем координаты указателя мыши

            //после первого нажатия кнопки мыши:

            x_MouseDown_1 = x_MouseDown_2;

            y_MouseDown_1 = y_MouseDown_2;

            //Изменяем значение OffOn на противоположное:

            OffOn = true;

      }

        else

      {

            //Если переключатель в виде переменной OffOn

            //равен true, то рисуем линию между предыдущей

            //и последующей позицией указателя мыши

        //в момент нажатия кнопки мыши:

        g.DrawLine(myPen, x_MouseDown_1, y_MouseDown_1,

                               x_MouseDown_2, y_MouseDown_2);

            //Задаем предыдущей позиции указателя мыши

            //координаты данной позиции указателя мыши:


            x_MouseDown_1 = x_MouseDown_2;
            y_MouseDown_1 = y_MouseDown_2;
      }
    }
Чтобы удалить, в случае необходимости, то, что мы нарисовали, дважды щелкаем кнопку с надписью “Очистить панель” в режиме проектирования. Появляется шаблон функции button1_Click для обработки события в виде щелчка этой кнопки. В тело шаблона записываем код из предыдущей главы для такой же функции,  но с небольшим дополнением, как показано на следующем листинге.
Листинг 27.2. Метод  button1_Click для стирания рисунка.
private void button1_Click(object sender, EventArgs e)
{
    //Объявляем объект "g" класса Graphics:
    Graphics g = this.CreateGraphics();
    //Очищаем (Clear) клиентскую область Form1 от рисунка:
    g.Clear(BackColor);
    //Чтобы рисование осуществлялось только от позиции
    //курсора на предыдущем щелчке до позиции курсора
    //на данном щелчке кнопки мыши,задаем переключателю
    //в виде глобальной переменной OffOn
    //первоначальное значение:
    OffOn = false;
}
В режиме выполнения (Debug, Start Without Debugging) мы можем рисовать при помощи щелчков кнопки мыши любой текст или фигуру, согласно алгоритму, как в качестве примера показано на рис. 27.1. После щелчка кнопки с надписью “Очистить панель” то, что мы нарисовали, удаляется. И мы можем начать рисовать сначала.

Рисование при помощи перемещения мыши


Листинг 26.1. Объявляем глобальные переменные и записываем наш код.

    //Объявляем глобальные переменные

    //для координат "x" и "y" указателя мыши

    //в момент нажатия кнопки мыши и перемещения мыши:

    public int x_MouseDown, y_MouseDown;

    public int x_MouseMove, y_MouseMove;

    //Чтобы рисование осуществлялось

    //только после каждого щелчка кнопки,

    //объявляем переключатель рисования

    //в виде глобальной переменной OffOn:

    bool OffOn = false;

private void Form1_MouseDown(object sender, MouseEventArgs e)

{

        //Определяем координаты "x" и "y" указателя мыши

        //в момент нажатия кнопки мыши:

        x_MouseDown = e.X;

        y_MouseDown = e.Y;

        //Изменяем значение OffOn на противоположное:

        OffOn = true;

    }

Далее в панели Properties на вкладке Events дважды щелкаем имя второго события, например, MouseMove, показанное на рис. 26.4. Появляется шаблон метода Form1_MouseMove для обработки события MouseMove в виде перемещения мыши. После записи нашего кода шаблон принимает следующий вид.

Листинг 26.2. Метод Form1_MouseMove для перемещения мыши.

private void Form1_MouseMove(object sender, MouseEventArgs e)

{

        //Объявляем объект "g" класса Graphics

        //и при помощи функции CreateGraphics

        //предоставляем ему возможность рисования

        //на this Form1:

        Graphics g = this.CreateGraphics();

        //Определяем координаты "x" и "y" указателя мыши

        //в моменты перемещения мыши:

        x_MouseMove = e.X;

        y_MouseMove = e.Y;

        //Выбираем перо "myPen" красного цвета Red

        //толщиной в 3 пикселя:

        Pen myPen = new Pen(Color.Red, 3);

        //Если переключатель рисования

        //в виде переменной OffOn равен true:

        if (OffOn == true)

        {

            //после нажатия кнопки мыши и перемещения мыши

        //рисуется линия заданного цвета и толщины:


        g.DrawLine(myPen, x_MouseDown, y_MouseDown,
                               x_MouseMove, y_MouseMove);
            // Задаем предыдущей позиции указателя мыши
            //координаты данной позиции указателя мыши:
            x_MouseDown = x_MouseMove;
            y_MouseDown = y_MouseMove;
        }
    }
В панели Properties на вкладке Events дважды щелкаем имя следующего события, например, MouseUp (рис. 26.4). Появляется шаблон функции Form1_ Form1_MouseUp для обработки события MouseUp в виде освобождения кнопки мыши в исходное положение. После записи нашего кода шаблон принимает такой вид.
Листинг 26.3. Метод  Form1_MouseUp для освобождения кнопки мыши.
private void Form1_MouseUp(object sender, MouseEventArgs e)
{
        //Изменяем значение OffOn на противоположное:
        OffOn = false;
    }
Чтобы удалить, в случае необходимости, то, что мы нарисовали, дважды щелкаем кнопку с надписью “Очистить панель” в режиме проектирования. Появляется шаблон функции button1_Click для обработки события в виде щелчка кнопки. После записи нашего кода шаблон принимает следующий вид.
Листинг 26.4. Метод  button1_Click для стирания рисунка.
private void button1_Click(object sender, EventArgs e)
{
    //Объявляем объект "g" класса Graphics:
    Graphics g = this.CreateGraphics();
    //Очищаем (Clear) клиентскую область
    //Form1 от рисунка:
    g.Clear(BackColor);
}
В режиме выполнения (Debug, Start Without Debugging) мы можем рисовать мышью любой текст или фигуру, согласно алгоритму, как в качестве примера показано на рис. 26.2 (где мы написали два слова “Visual Studio”). Методы сохранения и печати нашего рисунка уже были приведены выше.

Рисование прямоугольников и эллипсов при помощи нажатия кнопки мыши


Листинг 28.1. Объявляем глобальные переменные и записываем наш код.

//Объявляем глобальные переменные для координат "x" и "y"

//указателя мыши в момент нажатия кнопки мыши:

public int x_MouseDown_1, y_MouseDown_1;

//Определяем координаты указателя в момент нажатия кнопки:

private void pictureBox1_MouseDown(object sender, MouseEventArgs e)

{

      x_MouseDown_1 = e.X;

      y_MouseDown_1 = e.Y;

}

В панели Properties для элемента управления PictureBox на вкладке Events дважды щелкаем имя второго события MouseUp. Появляется шаблон метода pictureBox1_MouseUp для обработки события MouseUp в виде отпускания кнопки мыши. После записи нашего кода шаблон принимает следующий вид.

Листинг 28.2. Метод  pictureBox1_MouseUp для обработки отпускания кнопки.

private void pictureBox1_MouseUp(object sender, MouseEventArgs e)

{

        //Выбираем перо "myPen" черного цвета Black

        //толщиной в 3 пикселя:

    Pen myPen = new Pen(Color.Black, 3);

        //Объявляем объект "g" класса Graphics и предоставляем

        //ему возможность рисования на pictureBox1:

    Graphics g = Graphics.FromHwnd(pictureBox1.Handle);

    //Рисуем прямоугольник:

    g.DrawRectangle(myPen, x_MouseDown_1, y_MouseDown_1,

                   e.X - x_MouseDown_1, e.Y - y_MouseDown_1);

}

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

Листинг 28.3. Метод button1_Click для стирания рисунка.

private void button1_Click(object sender, EventArgs e)

{

    //Объявляем объект "g" класса Graphics

    //и связываем его с pictureBox1:

    Graphics g = pictureBox1.CreateGraphics();

    //Очищаем (Clear) элемент pictureBox1 от рисунка

    //и заполняем его белым цветом:

    g.Clear(Color.White);

}

В режиме выполнения (Debug, Start Without Debugging) перемещаем указатель мыши в первую точку, нажимаем кнопку, перемещаем указатель мыши во вторую точку и отпускаем кнопку; при этом из предыдущей точки в данную точку рисуется прямоугольник. Аналогично строим еще несколько прямоугольников (рис. 28.1).

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

g.DrawEllipse(myPen, x_MouseDown_1, y_MouseDown_1,

                e.X - x_MouseDown_1, e.Y - y_MouseDown_1);

то по этому второму варианту программы можем рисовать эллипсы (рис. 28.2) согласно алгоритму. После щелчка кнопки с надписью “1. Очистить панель” (или нажатия клавиши Enter, или Alt+1) то, что мы нарисовали, удаляется. И мы можем начать рисовать сначала.



Рисование простых линий на форме или элементах управления и печать этих линий


Листинг 5.1. Код для рисования прямой линии.

private void Form1_Paint(object sender, PaintEventArgs e)

{

    //Задаем цвет и толщину пера:

    Pen myPen = new Pen(Color.Black, 3);

    //Рисуем линию:

    e.Graphics.DrawLine(myPen, 10, 15, 100, 120);

    //Высвобождаем память, выделенную объекту myPen:

    myPen.Dispose();

}

Листинг 5.2. Код для рисования кривых линий.

private void Form1_Paint(object sender, PaintEventArgs e)

{

    //Задаем цвет и толщину пера:

    Pen myPen = new Pen(Color.Black, 3);

    //Рисуем эллипс лица:

    e.Graphics.DrawEllipse(myPen, 0, 0, 200, 220);

    //Рисуем закрытый глаз как дугу:

    e.Graphics.DrawArc(myPen, 35, 35, 35, 35, 180, -180);

    //Рисуем открытый глаз как эллипс:

    e.Graphics.DrawEllipse(myPen, 120, 35, 35, 35);

    //Рисуем нос как линию (сплайн) Безье:

    e.Graphics.DrawBezier(myPen, 100, 60, 120, 100,

    90, 120, 80, 100);

    //Рисуем рот как канонический сплайн:

    Point[] apt = new Point[4];

    apt[0] = new Point(60, 140);

    apt[1] = new Point(140, 140);

    apt[2] = new Point(100, 180);

    apt[3] = new Point(60, 140);

    e.Graphics.DrawCurve(myPen, apt, 0, 3, 0.9f);

    //Высвобождаем память, выделенную объекту myPen:

    myPen.Dispose();

}

Листинг 5.3. Код на Visual C# для печати изображения на принтере.

private void button1_Click(object sender, EventArgs e)

{

    //Передаем объекту printDialog1 информацию об объекте

    //printDocument1 при помощи свойства Document:

    printDialog1.Document = printDocument1;

    //Выводим стандартную панель Print при помощи метода

    //ShowDialog() для задания параметров печати

    //и после щелчка OK на панели Print печатаем документ

    //при помощи метода Print():

    if (printDialog1.ShowDialog() == DialogResult.OK)

                                     printDocument1.Print();

}

Листинг 5.4. Код на Visual Basic для печати изображения на принтере.

    Private Sub Button3_Click(ByVal sender As System.Object, _

    ByVal e As EventArgs) Handles Button3.Click


        ' Передаем объекту PrintDialog1 информацию об объекте
        'PrintDocument1 при помощи свойства Document:
        PrintDialog1.Document = PrintDocument1
        'Выводим панель Print при помощи функции ShowDialog
        'для задания параметров и вызываем процедуру Print():
        If PrintDialog1.ShowDialog() = DialogResult.OK Then
            PrintDocument1.Print()
        End If
    End Sub
 
Листинг 5.5. Код на прежнем Visual C++ (2002-2004 годов) для печати.
private:
System::Void button3_Click(System::Object *  sender,
System::EventArgs *  e)
{
        //Передаем объекту printDialog1 информацию об объекте
        //printDocument1 при помощи свойства Document:
        printDialog1->Document = printDocument1;
         //Выводим стандартную панель Print при помощи метода
        //ShowDialog() для задания параметров печати
        //и печатаем документ после щелчка OK на панели Print
        //при помощи метода Print():
        if (printDialog1->ShowDialog() == DialogResult::OK)
            printDocument1->Print();
}
Листинг 5.6. Код на новом Visual C++ 2005 для печати изображения.
private:
System::Void button3_Click(System::Object^  sender,
System::EventArgs^  e)
{
        //Передаем объекту printDialog1 информацию об объекте
        //printDocument1 при помощи свойства Document:
        printDialog1->Document = printDocument1;
         //Выводим стандартную панель Print при помощи метода
        //ShowDialog() для задания параметров печати
        //и печатаем документ при помощи метода Print():
        printDialog1->ShowDialog();
        printDocument1->Print();
}
Если мы не желаем видеть перед печатью стандартную панель Print, то компонент PrintDialog нам не потребуется, а в шаблон обработчика щелчка по кнопке вместо кода на листинге 5.3 записываем только одну строку кода:
printDocument1.Print();
Проверяем в действии созданную нами программу для печати на принтере любых изображений. Для этого получаем на экране монитора (по описанной выше методике) заданное изображение и щелкаем кнопку Print.
Появляется стандартная панель Print (рис. 5.5), на которой мы выбираем (или оставляем по умолчанию) принтер и задаем параметры печати. Например, можно изменить ориентацию печати и вместо Portrait (Портрет) выбрать переключатель Landscape (Ландшафт). После щелчка кнопки Печать (Print) или OK принтер печатает только одно изображение без формы и элементов управления.
Таким образом, мы закончили разработку общей методики построения на экране монитора и печати на принтере разнообразных изображений.

Рисование сложных линий и печать всей формы как снимка экрана


Листинг 6.1. Код для рисования прямоугольника.

private void Form1_Paint(object sender, PaintEventArgs e)

{

    //Задаем цвет и толщину пера:

    Pen myPen1 = new Pen(Color.Black, 3);

    //Объявляем объект myRectangle и создаем экземпляр этого объекта:

    Rectangle myRectangle = new Rectangle(10, 15, 150, 200);

    //Рисуем фигуру:

    e.Graphics.DrawRectangle(myPen1, myRectangle);

    //Высвобождаем память, выделенную объекту myPen1:

    myPen1.Dispose();

}

Листинг 6.2. Код для рисования кривых линий.

private void Form1_Paint(object sender, PaintEventArgs e)

{

      //Задаем цвет и толщину перьев:

      Pen myPen1 = new Pen(Color.Black, 3);

      Pen myPen2 = new Pen(Color.Black, 1);

      //Объявляем объекты и создаем экземпляры этих объектов:

      Point myPoint1 = new Point(50, 50);

      Point myPoint2 = new Point(100, 25);

      Point myPoint3 = new Point(200, 5);

      Point myPoint4 = new Point(275, 50);

      Point myPoint5 = new Point(300, 150);

      Point myPoint6 = new Point(350, 200);

      Point myPoint7 = new Point(250, 250);

      Point[] myCurvePoints =

      {

      myPoint1,

      myPoint2,

      myPoint3,

      myPoint4,

      myPoint5,

      myPoint6,

      myPoint7

      };

      //Рисуем линии:

      e.Graphics.DrawLines(myPen1, myCurvePoints);

      e.Graphics.DrawClosedCurve(myPen2, myCurvePoints);

      //Высвобождаем память от перьев myPen1, myPen2:

      myPen1.Dispose();

      myPen2.Dispose();

}

Листинг 6.3. Метод для фотографирования клиентской области формы.

[System.Runtime.InteropServices.DllImport("gdi32.dll")]

public static extern long BitBlt(IntPtr hdcDest,

int nXDest, int nYDest, int nWidth, int nHeight,

IntPtr hdcSrc, int nXSrc, int nYSrc, int dwRop);

private Bitmap myMemoryImage;

private void myCaptureScreen()

{

      Graphics myGraphics = this.CreateGraphics();

      Size s = this.Size;

      myMemoryImage = new Bitmap(s.Width, s.Height,

                                                 myGraphics);


      Graphics myMemoryGraphics =
      Graphics.FromImage(myMemoryImage);
      IntPtr dc0 = myGraphics.GetHdc();
      IntPtr dc1 = myMemoryGraphics.GetHdc();
      BitBlt(dc1, 0, 0, this.ClientRectangle.Width,
            this.ClientRectangle.Height,
            dc0, 0, 0, 13369376);
            myGraphics.ReleaseHdc(dc0);
            myMemoryGraphics.ReleaseHdc(dc1);
}
Листинг 6.4. Код для рисования изображения.
private void printDocument1_PrintPage(object sender,
      System.Drawing.Printing.PrintPageEventArgs e)
{
      e.Graphics.DrawImage(myMemoryImage, 0, 0);
}
Теперь дважды щелкаем по кнопке Print (рис. 6.1) в режиме проектирования. Открывается файл Form1.cs с шаблоном, в который записываем сначала одну строку для вызова приведенного выше метода:
   myCaptureScreen();
а затем записываем код для кнопки из приведенного выше параграфа “Методика печати изображения на принтере”.
Листинг 6.5. Метод для фотографирования элемента управления PictureBox.
[System.Runtime.InteropServices.DllImport("gdi32.dll")]
public static extern long BitBlt(IntPtr hdcDest,
int nXDest, int nYDest, int nWidth, int nHeight,
IntPtr hdcSrc, int nXSrc, int nYSrc, int dwRop);
private Bitmap myMemoryImage;
private void myCaptureScreen()
{
      Graphics myGraphics = pictureBox1.CreateGraphics();
      myMemoryImage = new Bitmap(
            pictureBox1.Width,
            pictureBox1.Height, myGraphics);
      Graphics myMemoryGraphics =
            Graphics.FromImage(myMemoryImage);
      IntPtr dc0 = myGraphics.GetHdc();
      IntPtr dc1 = myMemoryGraphics.GetHdc();
      BitBlt(dc1, 0, 0, pictureBox1.ClientRectangle.Width,
            pictureBox1.ClientRectangle.Height,
            dc0, 0, 0, 13369376);
      myGraphics.ReleaseHdc(dc0);
      myMemoryGraphics.ReleaseHdc(dc1);
}

Рисование текста и печать текстового файла


Листинг 8.1. Код для рисования горизонтального текста.

private void Form1_Paint(object sender, PaintEventArgs e)

{

    //Объявляем переменную myString и присваиваем значение:

    string myString = "Visual Studio";

 //Объявляем объект myFont и создаем экземпляр объекта:

    Font myFont = new Font("Arial", 30);

    //Объявляем объект myBrush и создаем экземпляр объекта:

    SolidBrush myBrush = new SolidBrush(Color.Black);

    //Задаем координаты начала текста:

    float x = 5.0f;

    float y = 50.0f;

    //Рисуем горизонтальный текст кистью myBrush:

    e.Graphics.DrawString(myString, myFont, myBrush, x, y);

    //Высвобождаем память, выделенную объектам:

    myFont.Dispose();

    myBrush.Dispose();

}

Листинг 8.2. Строки для рисования вертикального текста.

 //Объявляем объект myFormat и создаем экземпляр объекта:

    StringFormat myFormat = new StringFormat(

            StringFormatFlags.DirectionVertical);

    //Рисуем вертикальный текст кистью myBrush:

    e.Graphics.DrawString(myString, myFont, myBrush,

                        x, y, myFormat);

Листинг 8.3. Считывание текстового файла.

System.IO.StreamReader myPrintFile;

Font myPrintFont;

private void button1_Click(object sender, EventArgs e)

{

      string myPrintPath = Environment.GetFolderPath(

            Environment.SpecialFolder.Desktop);

      myPrintFile =

            new System.IO.StreamReader(myPrintPath +

                                          @"\myText.txt");

      myPrintFont = new Font("Times New Roman", 12);

      printDocument1.Print();

      myPrintFile.Close();

}

Дважды щелкаем по значку для компонента PrintDocument (ниже формы в режиме проектирования). Открывается файл Form1.cs с шаблоном, который после записи кода принимает следующий вид.

Листинг 8.4. Печать текстового файла.

private void printDocument1_PrintPage(object sender,

      System.Drawing.Printing.PrintPageEventArgs e)

{

      float yPos = 0f;


      int counter = 0;
      float leftMargin = e.MarginBounds.Left;
      float topMargin = e.MarginBounds.Top;
      string line = null;
      float linesPerPage = e.MarginBounds.Height /
            myPrintFont.GetHeight(e.Graphics);
      while (counter < linesPerPage)
      {
            line = myPrintFile.ReadLine();
            if (line == null)
            {
                  break;
            }
            yPos = topMargin + counter *
            myPrintFont.GetHeight(e.Graphics);
            e.Graphics.DrawString(line, myPrintFont,
                  Brushes.Black, leftMargin, yPos,
                             new StringFormat());
            counter++;
      }
      if (line != null)
      {
            e.HasMorePages = true;
      }
}
Проверяем в действии созданную нами программу для печати на принтере текстового файла. Строим и запускаем программу: Build, Build Solution; Debug, Start Without Debugging. Мы увидим форму Form1 в режиме выполнения. Щелкаем кнопку Print. Принтер печатает заданный текстовый файл. По этой методике мы можем распечатывать из Visual Studio различные текстовые файлы с различным расширением.
Мы закончили часть книги с общими методиками проектирования различных изображений и методиками печати изображений и текстовых файлов на принтере.
 

Рисование заполненных фигур и печать всей формы с предварительным просмотром


Листинг 7.1. Код для рисования прямоугольника.

private void Form1_Paint(object sender, PaintEventArgs e)

{

    //Задаем тип и цвет кисти:

    SolidBrush myBrush =

                 new SolidBrush(System.Drawing.Color.Black);

    //Объявляем объект myRectangle и создаем экземпляр этого объекта:

    Rectangle myRectangle = new Rectangle(10, 15, 150, 200);

    //Рисуем и заполняем фигуру:

    e.Graphics.FillRectangle(myBrush, myRectangle);

    //Высвобождаем память, выделенную объекту myBrush:

    myBrush.Dispose();

}

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

Листинг 7.2. Строка для рисования эллипса.

e.Graphics.FillEllipse(myBrush, myRectangle);

Листинг 7.3. Вызов методов для захвата изображения и вывода Print preview.

private void button1_Click(object sender, EventArgs e)

{

    //Захватываем изображение:

    myCaptureScreen();

    //Выводим панель Print preview:

    printPreviewDialog1.Show();

}



Рисование заполненных прямоугольников и эллипсов при помощи нажатия кнопки мыши


Листинг 29.1. Объявляем глобальные переменные и записываем наш код.

//Объявляем глобальные переменные для координат "x" и "y"

//указателя мыши в момент нажатия кнопки мыши:

public int x_MouseDown_1, y_MouseDown_1;

//Определяем координаты указателя в момент нажатия кнопки:

private void pictureBox1_MouseDown(object sender, MouseEventArgs e)

{

      x_MouseDown_1 = e.X; y_MouseDown_1 = e.Y;

}

В панели Properties для элемента управления PictureBox на вкладке Events дважды щелкаем имя второго события MouseUp. Появляется шаблон, который после записи нашего кода принимает следующий вид.

Листинг 29.2. Метод  pictureBox1_MouseUp для обработки отпускания кнопки.

private void pictureBox1_MouseUp(object sender, MouseEventArgs e)

{

    //Объявляем объект "g" класса Graphics и предоставляем

    //ему возможность рисования на pictureBox1:

    Graphics g = Graphics.FromHwnd(pictureBox1.Handle);

    //Создаем и рисуем прямоугольник:

    Rectangle myRectangle = new Rectangle(

      new Point(x_MouseDown_1, y_MouseDown_1),

      new Size(e.X - x_MouseDown_1, e.Y - y_MouseDown_1));

      g.DrawRectangle(new Pen(Color.Transparent),

                                                myRectangle);

    //Выбираем кисть myBrush для линейного градиента

    //между белым White и черным Black цветами:

    LinearGradientBrush myBrush;

    myBrush = new LinearGradientBrush(myRectangle,

            Color.White, Color.Black,

            LinearGradientMode.Horizontal);

    //Рисуем заполненный прямоугольник:

    g.FillRectangle(myBrush, myRectangle);

}

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

Листинг 29.3. Метод button1_Click для стирания рисунка.

private void button1_Click(object sender, EventArgs e)


{
    //Объявляем объект "g" класса Graphics
    //и связываем его с pictureBox1:
    Graphics g = pictureBox1.CreateGraphics();
    //Очищаем (Clear) элемент pictureBox1 от рисунка
    //и заполняем его белым цветом:
    g.Clear(Color.White);
}
В режиме выполнения (Debug, Start Without Debugging) перемещаем указатель мыши в первую точку, нажимаем кнопку, перемещаем указатель мыши во вторую точку и отпускаем кнопку; при этом из предыдущей точки в данную точку рисуется прямоугольник, заполненный по линейному градиенту между двумя заданными цветами (белым White и черным Black). Аналогично строим еще несколько прямоугольников (рис. 29.1). Если в коде на листинге 29.2 вместо строки для прямоугольника мы запишем (g.FillEllipse(myBrush, myRectangle);), то по этому второму варианту программы можем рисовать эллипсы, заполненные по тому же линейному градиенту, рис. 29.2. После щелчка кнопки с надписью “1. Очистить панель” (или нажатия клавиши Enter, или Alt+1) то, что мы нарисовали, удаляется. И мы можем начать рисовать сначала.

Система компьютерного проектирования техпроцессов


Листинг 85.1. Код кнопки OK для передачи данных с Form1 на Form3.

//Объявляем локальные переменные:

double d, H, Rn, s, s_sheet, C, L, rho,

    nu, El, sig_ys, sig_u, e_u, e_tot;

//Считываем исходные данные из окон TextBox формы Form1:

d = Convert.ToDouble(textBox1.Text);

H = Convert.ToDouble(textBox2.Text);

Rn = Convert.ToDouble(textBox3.Text);

s = Convert.ToDouble(textBox4.Text);

s_sheet = Convert.ToDouble(textBox5.Text);

C = Convert.ToDouble(textBox6.Text);

L = Convert.ToDouble(textBox7.Text);

rho = Convert.ToDouble(textBox8.Text);

nu = Convert.ToDouble(textBox9.Text);

El = Convert.ToDouble(textBox10.Text);

sig_ys = Convert.ToDouble(textBox11.Text);

sig_u = Convert.ToDouble(textBox12.Text);

e_u = Convert.ToDouble(textBox13.Text);

e_tot = Convert.ToDouble(textBox14.Text);

//Присваиваем исходные данные другим переменным

//класса для формы Form3, но с такими же именами:

Form3 myForm3 = new Form3();

myForm3.d = d;

myForm3.H = H;

myForm3.Rn = Rn;

myForm3.s = s;

myForm3.Radio = Radio;

myForm3.s_sheet = s_sheet;

myForm3.C = C;

myForm3.L = L;

myForm3.rho = rho;

myForm3.nu = nu;

myForm3.El = El;

myForm3.sig_ys = sig_ys;

myForm3.sig_u = sig_u;

myForm3.e_u = e_u;

myForm3.e_tot = e_tot;

//Выводим следующую диалоговую форму Form3:

myForm3.Show();

Листинг 85.2. Код для выполнения анимации.

//Объявляем булеву переменную myColor со значением false:

bool myColor = false;

private void timer1_Tick(object sender, EventArgs e)

{

      //Вводим анимацию:

      if (myColor == false)

      {

            //Выводим белый цвет элемента управления:

            this.button1.BackColor = Color.White;

            //Изменяем значение myColor на противоположное:

            myColor = true;

      }

      else

      {

            //Выводим желтый цвет элемента управления:                 this.button1.BackColor = Color.Yellow;

            //Изменяем значение myColor на противоположное:

            myColor = false;

      }

}

Применительно к нашим типичным деталям типа стакана (рис. 85.1) технологический процесс их изготовления включает следующие типичные операции:

Операция 1. Разрезка листа на полосы.

Операция 2. Вырезка заготовок из полосы.

Операция 3. Изготовление полуфабриката из заготовки.

Операция 4. Обрезка технологического припуска на полуфабрикате.

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



Создание баз и наборов данных


Листинг 20.1. Объявление и создание экземпляра набора данных.

private void button1_Click(object sender, EventArgs e)

{

      DataSet ds1 = new DataSet();

}

Листинг 20.2. Метод для выполнения анимации.

//Объявляем булеву переменную myHeight со значением false:

bool myHeight = false;

private void timer1_Tick(object sender, EventArgs e)

{

    //Программируем анимацию:

    if (myHeight == false)

    {

        //Изменяем высоту формы до 500:

        this.Height = 500;

        //Изменяем значение myHeight на противоположное:

        myHeight = true;

    }

    else

    {

        //Изменяем высоту формы до 490:

        this.Height = 490;

        //Изменяем значение myHeight на противоположное:

        myHeight = false;

    }

}

В этом коде мы можем устанавливать чередование двух других значений высоты формы. Задавая в панели Properties (для компонента Timer) различные значения свойству Interval (а выше мы задали 1000 миллисекунд или 1 секунду), можно изменять частоту чередования высот панели. Методика приостановки и возобновления анимации (с примерами) дана выше.

Другой вариант создания наборов и баз данных и управления ими мы опишем в следующей главе.



Степени, корни, логарифмы и факториалы


Теперь в шаблон файла Form9.cs необходимо написать нашу часть кода для выполнения расчетов. Для возведения  числа “x” в различные степени (при помощи первой кнопки со знаком “=” на данной форме Form9) дважды щелкаем эту кнопку (рис. 13.1). Появляется файл Form9.cs с шаблоном, в который записываем:

     double x, x2, x3, x4, x5;

     x = Convert.ToDouble(textBox1.Text);

     x2 = Math.Pow(x,2);

     textBox2.Text = x2.ToString();

     x3 = Math.Pow(x,3);

     textBox3.Text = x3.ToString();

     x4 = Math.Exp(x);

     textBox4.Text = x4.ToString();

     x5 = Math.Pow(10,x);

     textBox5.Text = x5.ToString();

     textBox6.Focus();

Для вычисления степени 

 или x^y (при помощи второй кнопки со знаком “=” на данной форме Form9) дважды щелкаем эту кнопку в режиме проектирования (рис. 13.1). Появляется файл Form9.cs с шаблоном, в который записываем:

     double x, y, x2;

     x = Convert.ToDouble(textBox1.Text);

     y = Convert.ToDouble(textBox6.Text);

     x2 = Math.Pow(x,y);

     textBox7.Text = x2.ToString();

     textBox11.Focus();

Для вычисления корней (

или sqrt(x);   
 или x^(1/3);   
 или x^(1/y) при помощи третьей кнопки со знаком “=” на форме Form9, дважды щелкаем эту кнопку (рис. 13.1). Появляется файл Form9.cs с шаблоном, в который записываем:

     double x, x2, c, x3, x4, y;

     x = Convert.ToDouble(textBox1.Text);

     x2 = Math.Sqrt(x);

     textBox8.Text = x2.ToString();

     c = 1/3.0;

     x3 = Math.Pow(x,c);

     textBox9.Text = x3.ToString();

     y = Convert.ToDouble(textBox6.Text);

     if (y!=0)

     {

     c = 1/y;

     x4 = Math.Pow(x,c);

     }

     else x4 = 0;

     textBox10.Text = x4.ToString();

     textBox11.Focus();

Для вычисления корня

 или a^(x/y) при помощи четвертой кнопки со знаком “=” на форме Form9 дважды щелкаем эту кнопку (рис. 13.1). Появляется файл Form9.cs с шаблоном, в который записываем:

     double x, y, a, c, x4;

     x = Convert.ToDouble(textBox1.Text);

     y = Convert.ToDouble(textBox6.Text);


     a = Convert.ToDouble(textBox11.Text);
     if (y!=0)
     {
     c = x/y;
     x4 = Math.Pow(a,c);
     }
     else x4 = 0;
     textBox12.Text = x4.ToString();
     textBox13.Focus();
Для вычислений трех логарифмов
 или ln(x);  
 или log(x);  
 или log[y](x) при помощи пятой кнопки со знаком “=” на форме Form9, дважды щелкаем эту кнопку (рис. 13.1). Появляется файл Form9.cs с шаблоном, в который записываем:
     double x, x2, x3, x4=0, x5=1, x6, y;
     x = Convert.ToDouble(textBox1.Text);
     y = Convert.ToDouble(textBox6.Text);
     if (x!=0)
     {
     x2 = Math.Log(x);
     }
     else x2 = 0;
     textBox13.Text = x2.ToString();
     if (x!=0)
     {
     x3 = Math.Log10(x);
     }
     else x3 = 0;
     textBox14.Text = x3.ToString();
     if (x!=0) x4 = Math.Log10(x);
     if (y!=0) x5 = Math.Log10(y);
     x6 = x4/x5;
     textBox15.Text = x6.ToString();
     textBox16.Focus();
Для вычисления факториалов n!, где n – целое положительное число (при n=0, n!=1) при помощи шестой кнопки со знаком “=” на форме Form9 дважды щелкаем эту кнопку (рис. 13.1). Появляется файл Form9.cs с шаблоном, в который записываем:
     long i, n, Fac=1;
     n = Convert.ToInt64(textBox16.Text);
     for (i=2; i<=n; i++)
     Fac = Fac*i;
     textBox17.Text = Fac.ToString();
В предыдущих главах мы разработали все основные эффекты анимации, которые связаны с пошаговыми изменениями свойств самой формы. А теперь приступим к разработке эффектов анимации, которые связаны с пошаговыми изменениями свойств элементов управления, которые мы размещаем на форме. И на данной форме эффект анимации разработаем для элемента управления, который мы, как правило, первым размещаем на панели, а именно, для рамки группы GroupBox. Создадим циклическое изменение (мигание) надписи при рамке группы (когда, например, мы хотим выделить эту надпись для пользователя).
Алгоритм данной анимации формулируем так:
после появления формы на ней начинает циклически изменяться (мигать) надпись, например, “Powers, Roots, Logarithms and Factorials” при рамке группы (с заданным нами выше в панели Properties интервалом времени для  компонента Timer1).


Для программной реализации этого алгоритма (по разработанной в главе 2 методике) дважды щелкаем значок для компонента Timer ниже формы в режиме проектирования. Появляется файл с шаблоном, в который записываем:
//Объявляем булеву переменную myText со значением false:
bool myText = false;
private void timer1_Tick(object sender, EventArgs e)
{
      //Вводим анимацию:
      if (myText == false)
      {
            //Выводим название рамки:
            this.groupBox1.Text =
            "Powers, Roots, Logarithms and Factorials";
            //Изменяем значение myText на противоположное:
            myText = true;
      }
      else
      {
            //Удаляем название рамки:
            this.groupBox1.Text = "";
            //Изменяем значение myText на противоположное:
            myText = false;
      }
}
В этом коде в строке (this.groupBox1.Text = "";) между кавычками мы можем записать другой текст, который будет чередоваться с первой надписью.

Теория и алгоритмы системы


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

Главное достоинство нашей методологии заключается в том, что мы спроектируем типичные приложения для построения различных пространственных изображений только на одной открытой (последней версии) платформе Visual Studio 2005 (без использования закрытых побочных библиотек типа DirectX и OpenGL, которые к тому же очень сложны в изучении).

Чтобы на экране монитора отобразить какой-либо объект, у нас должны быть (рис. 31.1):

точка наблюдения E (E – первая буква одного из ключевых, в данной теории, английских слов Eye – глаз (наблюдателя));

объект наблюдения, который отождествлен с множеством точек; одна из этих точек P  показана на рис. 31.1 (P – это первая буква английского слова Point – точка);

экран монитора; на этом экране точку объекта P мы видим в точке экрана P’, которая находится на пересечении прямой EP с плоскостью экрана.

Отметим, что мы приводим ключевые английские слова по данной тематике с целью, чтобы далее легче было разобраться со сложными программами на Visual C#, Visual Basic и Visual C++ 2005, где имена переменных, массивов, процедур, функций, методов и других элементов программирования записаны с использованием этих ключевых слов.

В трехмерном пространстве вводим неподвижную правую прямоугольную систему координат x, y, z, а также сферическую систему координат r,

,
(рис. 31.2), в которой определяются положения и размеры точки наблюдения, объекта и экрана. Эта прямоугольная система координат в литературе называется по-разному, например, глобальной (global coordinates) или мировой (world coordinates) в отличие от локальной (local coordinates). Такую глобальную систему координат можно задать, например, в центре изображаемого объекта.

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



Управляемое вращение и перемещение фигуры


Листинг 56.1. Код проектирования и преобразования фигуры.

//Объявляем переменную 'i' для исходной позиции фигуры;

int i = 0;

//Объявляем объект нашего нового класса Animation и

//при помощи конструктора new создаем экземпляр объекта:

Animation myAnimation = new Animation();

//Вводим наш новый класс Animation:

class Animation

{

      //Объявляем и задаем шаги горизонтального offsetX

      //и вертикального offsetY перемещений фигуры

      //за один интервал времени:

      float offsetX = 6;

      float offsetY = 2;

      //Объявляем и задаем в градусах

      //шаг угла поворота фигуры:

      float step_alpha = 6;

      //Объявляем объекты класса GraphicsPath:

      GraphicsPath myGraphicsPath = new GraphicsPath();

      GraphicsPath myGraphicsPath2 = new GraphicsPath();

      //В классе Matrix объявляем

      //объекты-матрицы преобразований:

      //объект myMatrix1 - для поворота фигуры и

      //объект myMatrix2 - для перемещения фигуры:

      Matrix myMatrix1 = new Matrix();

      Matrix myMatrix2 = new Matrix();

      //Вводим конструктор нашего класса для задания фигуры

      //в виде окружности (методом AddEllipse)

      //и в виде линий (методом AddLine):

      public Animation()

      {

            myGraphicsPath.AddEllipse(70, 70, 100, 100);

            myGraphicsPath.AddLine(75, 100, 165, 100);

            myGraphicsPath.AddLine(75, 140, 165, 140);

            //При помощи клонирования

            //создаем объект myGraphicsPath2

            //как точную копию объекта myGraphicsPath:

            myGraphicsPath2 =

                       (GraphicsPath)myGraphicsPath.Clone();

      }

      //Вводим методо FigureDraw для преобразования

      //и рисования фигуры:

      public void FigureDraw(Graphics myGraphics, int j)

      {

            //Перемещаем фигуру:

            myMatrix2.Translate(offsetX, offsetY);

            //При помощи клонирования

            //создаем объект myGraphicsPath


            //как точную копию объекта myGraphicsPath2:
            myGraphicsPath =
                      (GraphicsPath)myGraphicsPath2.Clone();
            //Задаем точку, относительно которой
            //будет поворачиваться фигура:
            PointF myPointF =
                        myGraphicsPath.GetBounds().Location;
            myPointF.X = myPointF.X +
                       myGraphicsPath.GetBounds().Width / 2;
            myPointF.Y = myPointF.Y +
                      myGraphicsPath.GetBounds().Height / 2;
            //Поворачиваем фигуру по часовой стрелке
            //на один шаг step_alpha
            // при помощи метода RotateAt класса Matrix:
            myMatrix1.RotateAt(step_alpha, myPointF);
            //Применяем метод Transform класса GraphicsPath
            //для трансформирования матриц myMatrix:
            myGraphicsPath.Transform(myMatrix1);
            myGraphicsPath.Transform(myMatrix2);
          //Рисуем преобразованную фигуру:
          myGraphics.DrawPath(new Pen(Color.Red, 3),
                                            myGraphicsPath);
     }
}
В панели Properties (для PictureBox) на вкладке Events дважды щелкаем по имени события Paint. Появляется шаблон метода PictureBox_Paint, который после записи нашего кода принимает следующий вид.
Листинг 56.2.  Метод для элемента управления PictureBox.
private void pictureBox1_Paint(object sender,
                                            PaintEventArgs e)
{
    //Вызываем метод FigureDraw
    //для рисования фигуры в i-м положении:
    myAnimation.FigureDraw(e.Graphics, i);
    //Задаем следующее i-е положение фигуры:
    i = i + 1;
}
Чтобы установить значение свойства Interval компонента Timer в зависимости от свойства Value ползунка элемента управления TrackBar, дважды щелкаем элемент управления TrackBar в режиме проектирования. Появляется файл Form9.cs с шаблоном, который после записи нашего кода принимает следующий вид.
Листинг 56.3. Метод для элемента управления TrackBar.
private void trackBar1_Scroll(object sender, EventArgs e)
{
      timer1.Enabled = true;
      timer1.Interval = trackBar1.Value;
}
Чтобы подключить к работе таймер, дважды щелкаем значок для компонента Timer (ниже формы в режиме проектирования). Появляется файл Form9.cs с шаблоном, который после записи нашего кода принимает следующий вид.
Листинг 56.4. Метод для компонента Timer.
private void timer1_Tick(object sender, EventArgs e)
{
      pictureBox1.Refresh();
}

Управляемое вращение линии


Листинг 55.1. Код проектирования рисунка.

//Переменную "angle" (для угла поворота) приравниваем нулю:

int angle = 0;

private void pictureBox1_Paint(object sender,

                                            PaintEventArgs e)

{

      //Объявляем локальные переменные:

      //Радиус вращающейся линии:

      float r = 100.0F;

      //Абсцисса и ордината неподвижной граничной точки,

      //вокруг которой вращается линия (центра вращения):

      float x_centre = 100.0F;

      float y_centre = 100.0F;

      //Текущие значения абсциссы и ординаты

      //граничной вращающейся точки:

      float x, y;

      

      //Определяем текущие значения абсциссы и ординаты

      //граничной вращающейся точки

      //и преобразовываем в тип (float):

      x = x_centre + r * Convert.ToSingle(

                   Math.Cos(2 * Math.PI * angle / 360));

      y = y_centre + r * Convert.ToSingle(

                    Math.Sin(2 * Math.PI * angle / 360));

      //Выполняем процедуру DrawLine класса Graphics

      //для построения линии по двум точкам

      //с координатами (x_centre, y_centre) и (x, y):

      e.Graphics.DrawLine(new Pen(Color.Black, 3),

                             x_centre, y_centre, x, y);

      //Увеличиваем угол поворота линии,

      //на один шаг, равный 6 градусам:

      angle = angle + 6;

      //Обнуляем угол поворота линии,

      //когда линия сделает полный оборот

      //на 360 градусов:

      if (angle == 360) angle = 0;

      //Для наглядности рисуем окружность

      //(типа циферблата часов),

      //внутри которой будет вращаться линия:

      e.Graphics.DrawEllipse(new Pen(Color.Blue, 2),

                                     0, 0, 200, 200);

      //Рисуем две оси симметрии окружности,

      //горизонтальную и вертикальную:

      e.Graphics.DrawLine(new Pen(Color.Red, 1),

                                    0, 100, 200, 100);

      e.Graphics.DrawLine(new Pen(Color.Red, 1),


                                    100, 0, 100, 200);
}
Чтобы установить значение свойства Interval компонента Timer в зависимости от свойства Value ползунка элемента управления TrackBar, дважды щелкаем элемент управления TrackBar в режиме проектирования (рис. 37.2). Появляется файл Form7.cs с шаблоном, который после записи двух строк нашего кода (не считая комментариев) принимает вид следующего метода.
Листинг 55.2. Метод для элемента управления TrackBar.
private void trackBar1_Scroll(object sender,
                                         EventArgs e)
{
     //Устанавливаем свойство таймера Enabled равным true:
     timer1.Enabled = true;
     //Устанавливаем значение свойства Interval таймера
     //в зависимости от перемещения ползунка Value:
     timer1.Interval = trackBar1.Value;
}
Чтобы подключить к работе таймер, дважды щелкаем значок для компонента Timer в режиме проектирования. Появляется файл Form7.cs с шаблоном, который после записи строки нашего кода (не считая комментариев) принимает такой вид.
Листинг 55.3. Метод для компонента Timer.
private void timer1_Tick(object sender, EventArgs e)
{
    //Перерисовываем клиентскую область элемента pictureBox1
    //через каждый Interval времени:
    pictureBox1.Refresh();
}
В этом коде метод Refresh (класса Control) перерисовывает клиентскую область элемента управления PictureBox через интервал времени, заданный ползунком.

Управляемое заполнение фигур


Листинг 57.1.  Метод для элемента управления PictureBox.

//Объявляем глобальную переменную filled_height

//для текущей высоты заполнения фигуры и приравниваем нулю:

int filled_height = 0;

private void pictureBox1_Paint(object sender,

                                            PaintEventArgs e)

{

      //Задаем стиль и цвет заполняющих элементов:

      HatchBrush myHatchBrush =

               new HatchBrush(HatchStyle.Cross, Color.Blue);

      //Объявляем объект класса Graphics

      //и задаем ему свойство Graphics:

      Graphics myGraphics = e.Graphics;

      //Заполняем прямоугольник

      //на текущую высоту filled_height:

      myGraphics.FillRectangle(myHatchBrush, 0, 0,

      pictureBox1.Size.Width, filled_height);

      //Увеличиваем текущую высоту заполнения

      //на следующий шаг progressBar1.Step:

      filled_height = filled_height + progressBar1.Step;

}

Дадим краткие пояснения. В главной строке кода:

      myGraphics.FillRectangle(myHatchBrush, 0, 0,

      pictureBox1.Size.Width, filled_height);

нули (0, 0) соответствуют координатам верхнего левого угла, а последние два параметра (pictureBox1.Size.Width, filled_height) соответствуют ширине и высоте заполняемого прямоугольника в виде элемента управления PictureBox.

Чтобы установить значение свойства Interval компонента Timer в зависимости от свойства Value ползунка элемента управления TrackBar, дважды щелкаем элемент управления TrackBar в режиме проектирования. Появляется файл Form11.cs с шаблоном, который после записи нашего кода принимает такой вид.

Листинг 57.2. Метод для элемента управления TrackBar.

private void trackBar1_Scroll(object sender, EventArgs e)

{

      timer1.Enabled = true;

      timer1.Interval = trackBar1.Value;

}

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

Листинг 57.3. Метод для компонента Timer.


private void timer1_Tick(object sender, EventArgs e)
{
      //Задаем максимальное значение progressBar1.Maximum
      //индикатора процесса,
      //равное высоте заполняемой панели picturebox1.Height:
      progressBar1.Maximum = pictureBox1.Height;
      //Если текущее значение Value индикатора
      //стало больше максимального значения:
      if (progressBar1.Value >= progressBar1.Maximum)
      {
            //отключаем таймер:
            timer1.Enabled = false;
      }
        else
      {
            //Увеличиваем текущее значение Value индикатора
            //на величину шага Step:
            progressBar1.PerformStep();
            //Перерисовываем клиентскую область
            //элемента управления PictureBox
            //через каждый Interval времени:
            pictureBox1.Refresh();
      }
}
В качестве следующего примера из списка методов класса Graphics (рис. 57.1) выберем второй метод FillEllipse для заполнения фигуры в виде эллипса.  На листинге 57.1 заменим одну строку кода (с методом FillRectangle) на строку кода с методом FillEllipse:
myGraphics.FillEllipse(myHatchBrush, 0, 0, -
picturebox1.Size.Width, filled_height);
На листинге 57.1 заменим одну строку кода (с методом FillRectangle) на строку кода с методом FillPie:
myGraphics.FillPie(myHatchBrush, 0, 0,
pictureBox1.Size.Width, pictureBox1.Size.Height –
progressBar1.Height, 0, filled_height);
Если строку кода с методом FillPie записать в таком виде:
myGraphics.FillPie(myHatchBrush, 0, 0,
pictureBox1.Size.Height, pictureBox1.Size.Height –
ProgressBar1.Height, 0, filled_height);
то получим частный случай заполнения сектора в круге (рис. 57.7).

Управляемый мигающий текст


Листинг 58.1. Метод для элемента управления TrackBar.

private void trackBar1_Scroll(object sender, EventArgs e)

{

      timer1.Enabled = true;

      timer1.Interval = trackBar1.Value;

}

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

Листинг 58.2. Метод для компонента Timer.

//Объявляем булеву переменную myText со значением false:

bool myText = false;

private void timer1_Tick(object sender, EventArgs e)

{

      //Программируем анимацию:

      if (myText == false)

      {

            //Задаем чередование черного Black

            //и белого White цветов текста

            //внутри элемента label1:

            this.label1.ForeColor = Color.Black;

            //Изменяем значение myText на противоположное:

            myText = true;

      }

      else

      {

            this.label1.ForeColor = Color.White;

            //Изменяем значение myText на противоположное:

            myText = false;

      }

}

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

По этой методике можно спроектировать анимацию в виде мигания любого текста за счет чередования двух любых цветов текста из длинного списка цветов Visual Studio (рис. 58.1) из структуры Color пространства имен System.Drawing.



Установка веб-компонентов Windows для веб-программирования на основе ASP.NET


Веб-программирование заключается в создании коммуникации между клиентами и серверами в изолированной локальной (например, корпоративной) и глобальной (Интернет) сети. Под словом “клиенты” понимаются установленные на компьютеры программные продукты (например, платформа Visual Studio 2005) пользователей, которые при помощи браузера, например, Internet Explorer и веб-службы получают какую-либо информацию с сервера. Под словом “серверы” понимаются программные продукты, установленные на компьютеры провайдеров (предоставляющие услуги хостинга), которые размещают у себя приложения в виде сайтов и при помощи веб-службы посылают информацию с сайтов на браузер пользователя по его запросу.

Веб-приложение и веб-службу мы должны разрабатывать на базе известного программного продукта корпорации Microsoft, который называется Internet Information Services (IIS) - Информационные службы Интернета. Эти службы IIS поставляются в комплекте со всеми операционными системами Windows 98/2000/XP/Server 2003, однако перед работой их нужно запустить в режим Started (Работает); по умолчанию службы находятся в режиме Stopped (Отключено), о чем мы расскажем в следующем параграфе.

Чтобы веб-приложение, которое мы спроектировали, например, в наших предыдущих книгах [7, 8], работало в Интернете, на компьютере провайдера должны быть установлены службы IIS (и, как правило, большинство провайдеров в мире используют службы IIS). А чтобы мы могли разрабатывать, отлаживать и тестировать веб-приложения и веб-службы,  и на нашем компьютере службы IIS должны быть запущены в режим “Started”.

По сравнению с разработанными в предыдущих главах Windows-приложениями, веб-приложения имеют следующие преимущества:

большая часть нашего кода находится не на нашем компьютере как клиенте (и не на многих компьютерах пользователей), а на одном веб-сервере; по нашему коду сервер создает готовую веб-страницу как стандартный документ HTML (Hypertext Markup Language) и передает на браузер любого пользователя, который запросит этот документ;

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

Когда мы первый раз попытаемся создать проект веб-приложения или веб-службы и выполним построение (Build, Build Solution), то в окне Output увидим сообщение об ошибке, что на этой машине должны быть установлены службы IIS для этой программы, чтобы она функционировала правильно. Установку служб IIS на компьютер с операционной системой Windows 2000 Server мы подробно описали в нашей предыдущей книге [7]. Далее уже можно разрабатывать проекты веб-приложений и веб-служб по методике, описанной в нашей предыдущей книге [8].



Варианты часов с цифровой индикацией, индикаторами прогресса и датой


Листинг 53.1. Метод для вывода короткого времени, без секунд.

private void button5_Click(object sender, EventArgs e)

{

      statusBarPanel1.Text =

                 System.DateTime.Now.ToShortTimeString();

}

Для вывода короткой даты (одними цифрами) при помощи метода ToShortDateString дважды щелкаем вторую кнопку Start на Form3 в режиме редактирования (рис. 53.4). Появляется файл Form3.cs с шаблоном, который после записи одной строки нашего кода принимает следующий вид.

Листинг 53.2. Метод для вывода короткой даты.

private void button6_Click(object sender, EventArgs e)

{

      statusBarPanel2.Text =

                    System.DateTime.Now.ToShortDateString();

}

Тот же самый шаблон для первой кнопки Start после записи одной строки кода (с целью вывода длинного времени, с секундами, при помощи метода ToLongTimeString) принимает следующий вид.

Листинг 53.3. Метод для вывода длинного времени, с секундами.

private void button5_Click(object sender, EventArgs e)

{

      statusBarPanel1.Text =

                 System.DateTime.Now.ToLongTimeString ();

}

Листинг 53.4. Метод для вывода длинной даты.

private void button6_Click(object sender, EventArgs e)

{

      statusBarPanel2.Text =

                 System.DateTime.Now.ToLongDateString ();

}

Листинг 53.5. Метод для вывода коротких значений часов и даты.

private void timer1_Tick(object sender, EventArgs e)

{

      statusBarPanel1.Text =

                    System.DateTime.Now.ToShortTimeString();

      statusBarPanel2.Text =

                    System.DateTime.Now.ToShortDateString();

}

Листинг 53.6. Метод для вывода длинных значений часов и даты.

private void timer1_Tick(object sender, EventArgs e)

{

      statusBarPanel1.Text =

                     System.DateTime.Now.ToLongTimeString();

      statusBarPanel2.Text =

                     System.DateTime.Now.ToLongDateString();

}

Листинг 53.7. Код для вывода времени и даты по второму варианту.

label1.Text = System.DateTime.Now.ToLongTimeString();

label2.Text = System.DateTime.Now.ToLongDateString();

Листинг 53.8. Метод для вывода значений секунд, минут и часов.

private void timer1_Tick(object sender, EventArgs e)

{

      DateTime currentTime = DateTime.Now;

      int seconds = currentTime.Second;

      int minutes = currentTime.Minute;

      int hours = currentTime.Hour;

      progressBar1.Value = seconds;

      progressBar2.Value = minutes;

      progressBar3.Value = hours;

      label1.Text = seconds.ToString();

      label2.Text = minutes.ToString();

      label3.Text = hours.ToString();

}

Продолжим (в следующей главе) проектирование более сложных анимационных программ (согласно оглавлению системы).



Воспроизведение аудио файлов из приложения Visual С#


Напомним, что перед написанием любой программы в Form3.cs выше пространства имен с именем нашего проекта подключаем новое пространство имен:

using System.Diagnostics;

Главное, в файл Form3.cs необходимо написать нашу часть кода для открытия проигрывателя при помощи первой основной кнопки “Start Windows Media Player” на данной Form3 (рис. 69.1). Дважды щелкаем эту кнопку в режиме редактирования. Появляется файл Form3.cs с шаблоном, который после записи нашего кода (согласно постановке задачи для управления проигрывателем) принимает такой вид.

Листинг 69.1. Метод для открытия Windows Media.

private void button1_Click (object sender, EventArgs

e)

{

      Process.Start("wmplayer.exe");

}

Теперь в файл Form3.cs необходимо написать нашу часть кода для открытия проигрывателя Windows Media с последующим воспроизведением конкретного аудио файла при помощи второй основной кнопки “Start the audio file” на данной Form3 (рис. 69.1). Дважды щелкаем эту кнопку в режиме редактирования.

Появляется файл Form3.cs с шаблоном, который после записи нашего кода принимает такой вид.

Листинг 69.2. Метод для воспроизведения аудио файла.

private void button2_Click (object sender, EventArgs

e)

{

 //Запускаем Windows Media Player:

    //и воспроизводим конкретный аудио файл:

    Process.Start("wmplayer.exe", @"F:\Track03.cda");

}

Напомним, что для версии проигрывателя, старше 6, вместо "mplayer2.exe" надо записать "wmplayer.exe", в пути расположения звукового файла желательно убрать все пробелы, а имя этого файла записать в одной строке кода (без переносов) с предыдущей папкой. Аналогично мы записываем код для воспроизведения любого другого файла, то ли после щелчка этой кнопки, то ли после щелчка новой кнопки (которую мы должны ввести на форму).

Аналогично воспроизводим любой другой файл с компакт-диска или с жесткого диска компьютера.



Воспроизведение видео файлов из приложения Visual C#


Листинг 70.1. Метод для воспроизведения видео файла.

private void button2_Click _Click(object sender, EventArgs

e)

{

    //Запускаем Windows Media Player

    //и воспроизводим конкретный видео файл:

    //Process.Start("mplayer2.exe", @"C:\WINNT\clock.avi");

    Process.Start("wmplayer.exe", @"C:\WINNT\clock.avi");

}

Напомним, что для версии проигрывателя старше 6 в коде на листинге 70.1 вместо закомментированного файла "mplayer2.exe" записан "wmplayer.exe".

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



Вращающееся градиентное заполнение фигур цветом 


Листинг 61.1. Метод для компонента Timer1.

//Объявляем и обнуляем глобальную переменную angle:

int angle = 0;

private void timer1_Tick(object sender, EventArgs e)

{

      //Экземпляр структуры ntPtr:

      IntPtr myIntPtr = new IntPtr();

      //Свойство Handle:

      myIntPtr = this.Handle;

      //Создаем объект myGraphics класса Graphics

      //и применяем функцию FromHwnd:

      Graphics myGraphics = Graphics.FromHwnd(myIntPtr);

      //Задаем параметры прямоугольника:

      Rectangle myRectangle = new Rectangle(5, 5, 700, 400);

      //Задаем два граничных цвета Red и White

      //градиентной заливки:

      LinearGradientBrush myLinearGradientBrush =

                  new LinearGradientBrush(myRectangle,

                  Color.Red, Color.White, angle);

        //Заполняем прямоугольник цветом:

        myGraphics.FillRectangle(myLinearGradientBrush,

        myRectangle);

        //Организовываем циклический процесс вращения:

        angle = angle + 10;

        if (angle >= 360) angle = 0;

        //Высвобождаем ресурсы, выделенные объекту

        //myGraphics:

        myGraphics.Dispose();

}

Чтобы установить значение свойства Interval компонента Timer в зависимости от свойства Value ползунка элемента управления TrackBar, дважды щелкаем элемент управления TrackBar в режиме проектирования. Появляется файл Form1.cs с шаблоном, в который записываем код, приведенный в предыдущей главе.

Согласно разработанной выше методике, чтобы иметь возможность приостановить (и запустить вновь) процесс анимации при помощи кнопки Stop Animation, дважды щелкаем эту кнопку в режиме проектирования. Появляется файл Form1.cs с шаблоном, в который записываем код, приведенный в предыдущей главе.



Вращение линии


Листинг 54.1. Код проектирования рисунка.

//Объявляем глобальную переменную для угла "angle"

//и приравниваем ее нулю:

int angle = 0;

private void pictureBox1_Paint(object sender,

                                            PaintEventArgs e)

{

    //Объявляем объект myGraphicsPath класса GraphicsPath:

    GraphicsPath myGraphicsPath = new GraphicsPath();

    //На объекте myGraphicsPath выполняем процедуру

    //AddLine для построения линии по двум точкам

    //с координатами (29, 29) и (100, 100):

    myGraphicsPath.AddLine(29, 29, 100, 100);

    //В классе Matrix создаем объект myMatrix

    //в виде матицы преобразований:

    Matrix myMatrix = new Matrix(1, 0, 0, 1, 1, 1);

    //В структуре PointF создаем объект myPointF

    //с координатами точки (100, 100);,

    //вокруг которой будет вращаться линия:

    PointF myPointF = new PointF(100, 100);

    //Поворачиваем линию вокруг точки (100, 100)

    //на один шаг при помощи метода RotateAt

    //класса Matrix:

    myMatrix.RotateAt(angle, myPointF);

    //Применяем метод Transform класса GraphicsPath

    //для трансформирования матрицы myMatrix:

    myGraphicsPath.Transform(myMatrix);

    //Рисуем на экране трансформированную линию

    //черным пером толщиной 3 (Pen(Color.Black, 3)):

    e.Graphics.DrawPath(new Pen(Color.Black, 3),

                                           myGraphicsPath);

    //Увеличиваем текущий угол поворота линии

    //на один шаг, равный 6 градусам:

    angle = angle + 6;

    //Обнуляем угол поворота линии,

    //когда линия сделает полный оборот в 360 градусов:

    if (angle == 360) angle = 0;

    //Для наглядности внутри квадрата 200x200

    //рисуем окружность (типа циферблата часов)

    //синим пером толщиной 2 (Pen(Color.Blue, 2),

    //внутри которой будет вращаться линия:

    e.Graphics.DrawEllipse(new Pen(Color.Blue, 2),

                                         0, 0, 200, 200);


    //Рисуем две оси симметрии окружности,
    //горизонтальную и вертикальную:
    e.Graphics.DrawLine(new Pen(Color.Red, 1),
                                  0, 100, 200, 100);
    e.Graphics.DrawLine(new Pen(Color.Red, 1),
                                  100, 0, 100, 200);
}
Листинг 54.2. Код для анимации рисунка.
 
private void timer1_Tick(object sender, EventArgs e)
{
      // Перерисовываем клиентскую область элемента управления
      //pictureBox1 через каждый Interval времени:
      pictureBox1.Refresh();
}
Напомним, что в этом коде метод Refresh (класса Control) перерисовывает клиентскую область элемента управления (в нашем примере, элемента управления PictureBox) через каждые, заданные нами в таймере, 1000 миллисекунд (1 секунду). За счет этого мы видим поворот стрелки в динамике (во времени).
Таким образом, в этой главе мы разработали методику создания анимации (в комплексе Visual C#) на экране монитора и печати текущего положения анимации на принтере. Теперь по этой методике продолжим разработку следующих форм (согласно оглавлению системы анимации) для проектирования более сложных анимаций (в следующей главе).

Ввод в систему свойств материалов для изготовления изделий


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

Для примера, укрупнено классифицируем стальной листовой прокат, из которого изготавливают основную массу деталей (например, в промышленности).

Условно делим стальной листовой прокат на три большие группы: сталь без покрытия; сталь с покрытием; сталь, плакированная другими материалами (биметалл).

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

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

1) алюминий и его сплавы; 2) медь и ее сплавы; 3) магний и его сплавы; 4) никель и его сплавы; 5) титан и его сплавы; 6) цинк и его сплавы; 7) молибден и его сплавы; 8) ниобий и его сплавы; 9) тантал и его сплавы; 10) цирконий и его сплавы; 11) вольфрам и его сплавы; 12) рений и его сплавы; 13) ванадий и его сплавы; 14) кобальт и его сплавы; 15) бериллий и его сплавы; 16) серебро и его сплавы; 17) золото и его сплавы; 18) неметаллы.



Вычисление массы изделий при помощи формы


Листинг 77.1. Методы для расчета параметров детали.

//Объявляем переменные:

double d, H, Rn, s;

double A, V, m, D;

double rho;

double pi = Math.PI;

//Площадь поверхности детали:

double Area()

{

   double A=0, A1, A2, A3;

   A1=Area1(); A2=Area2(); A3=Area3();

   A=A1+A2+A3;

   return A;

}

//Объем детали:

double Volume()

{

   A=Area(); V=A*s;

   return V;

}

//Масса детали:

double mass()

{

   A=Area(); //mm*mm

   V=Volume(); //mm*mm*mm

   m=V*rho*1.0e-9; // kg

   return m;

}

//Диаметр плоской заготовки:

double DBlank()

{

   A=Area(); D=Math.Sqrt(4*A/pi);

   return D;

}

//Площадь круга:

double Area1()

{

   double A1 = pi*(d-2*Rn)*(d-2*Rn)/4;

   return A1; //mm*mm

}

//Площадь нижнего тора:

double Area2()

{

   double A2 = pi*(Rn-s/2)*(2*(Rn-s/2)+pi*(d-2*Rn)/2);

   return A2; //mm*mm

}

//Площадь цилиндра:

double Area3()

{

   double A3 = pi*(d-s)*(H-Rn);

   return A3; //mm*mm

}

Листинг 77.2. Метод кнопки OK для расчета параметров детали.

private void button5_Click(object sender, EventArgs e)

{

  //Считывание данных о геометрии детали

  //и плотности материала:

   d = Convert.ToDouble(textBox1.Text);

   H = Convert.ToDouble(textBox2.Text);

   Rn = Convert.ToDouble(textBox3.Text);

   s = Convert.ToDouble(textBox4.Text);

   rho = Convert.ToDouble(textBox5.Text);

   //Расчет параметров детали и вывод в окна:

   textBox6.Text = Area().ToString();

   textBox7.Text = Volume().ToString();

   textBox8.Text = mass().ToString();

   textBox9.Text = DBlank().ToString();

   textBox1.Focus(); //Курсор - в первое окно.

}

Листинг 77.3. Метод для выполнения анимации.

//Объявляем булеву переменную myColor со значением false:

bool myColor = false;

private void timer1_Tick(object sender, EventArgs e)

{

      //Вводим анимацию:

      if (myColor == false)

      {

            //Выводим белый цвет рамки pictureBox1:

            this.pictureBox1.BackColor = Color. White;

            //Изменяем значение myColor на противоположное:


            myColor = true;
      }
      else
      {
            //Выводим желтый цвет рамки pictureBox1:
            this.pictureBox1.BackColor = Color.Yellow;
            //Изменяем значение myColor на противоположное:
            myColor = false;
      }
}
Листинг 77.4. Код для печати информации с формы.
// При помощи метода DrawImage печатаем рисунок детали,
//находящийся внутри рамки pictureBox1:
e.Graphics.DrawImage(pictureBox1.Image, 0, 0);
//При помощи метода DrawString печатаем
//исходные данные: d, H, Rn, s, rho:
string msg;
msg = "d = " + textBox1.Text + " mm";
e.Graphics.DrawString(msg, this.Font, Brushes.Black, 400, 100);
msg = "H = " + textBox2.Text + " mm";
e.Graphics.DrawString(msg, this.Font, Brushes.Black, 400, 120);
msg = "Rn = " + textBox3.Text + " mm";
e.Graphics.DrawString(msg, this.Font, Brushes.Black, 400, 140);
msg = "s = " + textBox4.Text + " mm";
e.Graphics.DrawString(msg, this.Font, Brushes.Black, 400, 160);
msg = "rho = " + textBox5.Text + " kg/(m*m*m*)";
e.Graphics.DrawString(msg, this.Font, Brushes.Black, 400, 180);
//При помощи метода DrawString печатаем
//результаты расчета: A, V, m, D:
msg = "A = " + textBox6.Text + " mm*mm";
e.Graphics.DrawString(msg, this.Font, Brushes.Black, 400, 220);
msg = "V = " + textBox7.Text + " mm*mm*mm";
e.Graphics.DrawString(msg, this.Font, Brushes.Black, 400, 240);
msg = "m = " + textBox8.Text + " kg";
e.Graphics.DrawString(msg, this.Font, Brushes.Black, 400, 260);
msg = "D = " + textBox9.Text + " mm";
e.Graphics.DrawString(msg, this.Font, Brushes.Black, 400, 280);

Вычисление процентов


Теперь в шаблон файла Form7.cs необходимо написать нашу часть кода для выполнения расчетов на калькуляторе. Для решения первой задачи на проценты (при помощи первой кнопки со знаком “=” на данной форме Form7) дважды щелкаем эту кнопку (рис. 12.1). Появляется файл Form7.cs с шаблоном, в который записываем:

double mul1, mul2, mul3;

mul1 = Convert.ToDouble(textBox1.Text);

mul2 = Convert.ToDouble(textBox2.Text);

mul3 = mul1 * mul2/100;

textBox3.Text = mul3.ToString();

textBox4.Focus();

Для решения второй задачи на проценты (при помощи второй кнопки со знаком “=” на данной форме Form7) дважды щелкаем эту кнопку в режиме проектирования (рис. 12.1). Появляется файл Form7.cs с шаблоном, в который записываем:

double mul1, mul2, mul3;

mul1 = Convert.ToDouble(textBox4.Text);

mul2 = Convert.ToDouble(textBox5.Text);

mul3 = mul1/mul2*100;

textBox6.Text = mul3.ToString();

textBox7.Focus();

Для решения третьей задачи на проценты (при помощи третьей кнопки со знаком “=” на данной форме Form7) дважды щелкаем эту кнопку в режиме проектирования (рис. 12.1). Появляется файл Form7.cs с шаблоном, в который записываем:

double mul1, mul2, mul3;

mul1 = Convert.ToDouble(textBox7.Text);

mul2 = Convert.ToDouble(textBox8.Text);

mul3 = mul1/mul2*100;

textBox9.Text = mul3.ToString();

textBox10.Focus();

Для решения четвертой задачи на проценты (при помощи четвертой кнопки со знаком “=” на данной форме Form7) дважды щелкаем эту кнопку в режиме проектирования (рис. 12.1). Появляется файл Form7.cs с шаблоном, в который записываем:

double mul1, mul2, mul3;

mul1 = Convert.ToDouble(textBox10.Text);

mul2 = Convert.ToDouble(textBox11.Text);

mul3 = mul1*(1 + mul2/100);

textBox12.Text = mul3.ToString();

textBox13.Focus();

Для решения пятой задачи на проценты (при помощи пятой кнопки со знаком “=” на данной форме Form7) дважды щелкаем эту кнопку в режиме проектирования (рис. 12.1). Появляется файл Form7.cs с шаблоном, в который записываем:

double mul1, mul2, mul3;

mul1 = Convert.ToDouble(textBox13.Text);


mul2 = Convert.ToDouble(textBox14.Text);
mul3 = mul1*(1 - mul2/100);
textBox15.Text = mul3.ToString();
Аналогично (как в предыдущей главе) разработаем циклическое изменение цвета шрифта (текста) всех элементов управления, которые имеются на данной форме (например, с целью выделить эти тексты). Как сделать мигающим текст только для одного элемента управления, мы уже показали выше для переключателя и далее будем показывать (в последующих главах) для других элементов управления.
Напомним, что цвет шрифта (текста) элементов управления на форме устанавливается в панели Properties (с заголовком Form7) в свойстве BackColor и по умолчанию имеет значение Control. Алгоритм данной анимации формулируем так:
после появления формы цвет текста на всех элементах управления, которые расположены на данной форме, начинает циклически изменяться, например, с черного на белый и обратно, с заданным нами выше в панели Properties интервалом времени для  компонента Timer1.
Для программной реализации этого алгоритма дважды щелкаем значок timer1 (ниже формы в режиме проектирования). Появляется файл с шаблоном, который после записи нашего кода принимает следующий вид:
//Объявляем булеву переменную myColor со значением false:
bool myColor = false;
private void timer1_Tick(object sender, EventArgs e)
{
      //Вводим анимацию:
      if (myColor == false)
      {
            //Выводим черный цвет текста
            //для всех элементов на форме:
            this.ForeColor = System.Drawing.Color.Black;
            //Изменяем значение myColor на противоположное:
            myColor = true;
      }
      else
      {
            //Выводим белый цвет текста
            //для всех элементов на форме:
            this.ForeColor = System.Drawing.Color.White;
            //Изменяем значение myColor на противоположное:
            myColor = false;
      }
}

Вычисление сложных математических выражений


Листинг 15.1. Метод для выполнения вычислений (при помощи Excel).

private void button1_Click(object sender, EventArgs e)

{

      //Объявляем объектную переменную objectExcel:

      Excel.Application objectExcel =

                              new Excel.ApplicationClass();

      //Объявляем общие объектные переменные:

      Object Formula, Result;

      //Считываем формулу из окна textBox1

      //при помощи свойства Text:

      Formula = textBox1.Text;

      //Объектная переменная objectExcel

      //вычисляет нашу формулу Formula

      //при помощи метода “_Evaluate”:

      Result = objectExcel._Evaluate(Formula);

      //Показываем вычисленное значение Result

      //в окне textBox2:

      textBox2.Text = Result.ToString();

      //Удаляем объектную переменную objExcel

      //и освобождаем выделенную под нее память:

      objectExcel.Quit();

}

Листинг 15.2. Метод для выполнения анимации.

//Объявляем булеву переменную myVisible со значением false:

bool myVisible = false;

private void timer1_Tick(object sender, EventArgs e)

{

      //Программируем анимацию:

      if (myVisible == false)

      {

            //Делаем невидимым элемент управления:

            this.button1.Hide();

            //Изменяем значение myVisible на противоположное:

            myVisible = true;

      }

      else

      {

           //Делаем видимым элемент управления:

            this.button1.Show();

            //Изменяем значение myVisible на противоположное:

            myVisible = false;

      }

}

Листинг 15.3. Метод для создания печатаемых данных.

private void printDocument1_PrintPage(object sender,

               System.Drawing.Printing.PrintPageEventArgs e)

{

   //При помощи метода DrawString печатаем исходную формулу:

   string msg;

   msg = "Formula: " + textBox1.Text + "";

   e.Graphics.DrawString(msg, this.Font, Brushes.Black,

   200, 100);

   //При помощи метода DrawString печатаем результат расчета:


   msg = " = " + textBox2.Text + "";
   e.Graphics.DrawString(msg, this.Font, Brushes.Black,
   500, 100);
}
Теперь дважды щелкаем кнопку Print (рис. 15.2). Открывается файл Form3.cs с шаблоном, в который записываем код для вызова печатающего метода printDocument1.Print из приведенного выше параграфа “Методика печати изображения на принтере”.
Мы закончили разработку калькулятора (с использованием Excel  и эффекта анимации). Отметим, что мы не только подключили Excel к нашему приложению, но и при помощи огромных возможностей платформы Visual Studio 2005 (по визуальному программированию) упростили использование готовой программы Excel, а также расширили возможности калькулятора, созданного в комплексе Visual C# (по сравнению с возможностями Excel).
Другие варианты вычисления сложных математических выражений, численное решение уравнений, построение графиков функций, расчет экономических показателей, проверка орфографии текста при помощи Excel можно разработать по аналогии с нашей предыдущей книгой [8].
Теперь приступаем к рассмотрению интеграции Visual C# с другими платформами (с использованием других эффектов анимации).

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


Листинг 48.1. Объявление членов интерфейса и глобальных переменных.

//Объявляем персонаж Джина (Genie) и путь к его файлу:

static AgentObjects.IAgentCtlCharacterEx myGenie;

static String DATAPATH_1 = "Genie.acs";

//Объявляем персонаж Мага (Merlin) и путь к его файлу:

static AgentObjects.IAgentCtlCharacterEx myMerlin;

static String DATAPATH_2 = "Merlin.acs";

//Объявляем персонаж Попугая (Peedy) и путь к его файлу:

static AgentObjects.IAgentCtlCharacterEx myPeedy;

static String DATAPATH_3 = "Peedy.acs";

//Объявляем персонаж Робота (Robby) и путь к его файлу:

static AgentObjects.IAgentCtlCharacterEx myRobby;

static String DATAPATH_4 = "Robby.acs";

//Объявляем член интерфейса Agent:

private AgentObjects.Agent myAgentController;

//Глобальная переменная для любого текста персонажа:

static String mySpeech;

//Объявляем общую для персонажей объектную переменную:

Object myObject = null;

А в шаблон (метода Form1_Load) записываем наш код (согласно постановке задачи для всех персонажей), и метод Form1_Load принимает такой вид.

                                                       

Листинг 48.2. Загрузка персонажей в элементы управления.

private void Form1_Load(object sender, EventArgs e)

{

      //Загружаем персонаж в элемент управления axAgent1:

      axAgent1.Characters.Load("Genie", DATAPATH_1);

      myGenie = axAgent1.Characters.Character("Genie");

      //Чтобы он выполнял голосовые команды на англ. яз.:

      myGenie.LanguageID = 0x409;

      //Загружаем персонаж в элемент управления axAgent2:

      axAgent2.Characters.Load("Merlin", DATAPATH_2);

      myMerlin = axAgent2.Characters.Character("Merlin");

      //Чтобы он выполнял голосовые команды на англ. яз.:

      myMerlin.LanguageID = 0x409;

      //Загружаем персонаж в элемент управления axAgent3:

      axAgent3.Characters.Load("Peedy", DATAPATH_3);

      myPeedy = axAgent3.Characters.Character("Peedy");


      // Чтобы он выполнял голосовые команды на англ. яз.:
      myPeedy.LanguageID = 0x409;
      //Загружаем персонаж в элемент управления axAgent4:
      axAgent4.Characters.Load("Robby", DATAPATH_4);
      myRobby = axAgent4.Characters.Character("Robby");
      //Чтобы он выполнял голосовые команды на англ. яз.:
      myRobby.LanguageID = 0x409;
      //Для всех четырех персонажей добавляем
      //нашу голосовую команду, как пользователей,
      //например, команду "MoveToMouse" -
      //переместиться на место курсора мыши:
      mySpeech = "MoveToMouse";
      myGenie.Commands.Add(
            mySpeech, mySpeech, mySpeech, true, true);
      myMerlin.Commands.Add(
            mySpeech, mySpeech, mySpeech, true, true);
      myPeedy.Commands.Add(
            mySpeech, mySpeech, mySpeech, true, true);
      myRobby.Commands.Add(
            mySpeech, mySpeech, mySpeech, true, true);
      //Задаем, например, Джину выполнение еще команды,
      //для примера, голосовой команды "Merlin":
      mySpeech = "Merlin";
      myGenie.Commands.Add(
            mySpeech, mySpeech, mySpeech, true, true);
      //Задаем, например, Магу выполнение еще команды,
      //для примера, голосовой команды "Peedy":
      mySpeech = "Peedy";
      myMerlin.Commands.Add(
            mySpeech, mySpeech, mySpeech, true, true);
      //Задаем, например, Попугаю выполнение еще команды,
      //для примера, голосовой команды "Robby":
      mySpeech = "Robby";
      myPeedy.Commands.Add(
            mySpeech, mySpeech, mySpeech, true, true);
      //Задаем, например, Роботу выполнение еще команды,
      //для примера, голосовой команды "Genie":
      mySpeech = "Genie";
    myRobby.Commands.Add(
            mySpeech, mySpeech, mySpeech, true, true);
    //Добавляем имя анимации, активизируемое голосом:
    mySpeech = "Announce";


    myGenie.Commands.Add(
    mySpeech, mySpeech, mySpeech, true, true);
    //Показываем какой-либо текущий персонаж:
    //От начала координат в вехнем левом углу панели Form1
    //задаем координаты "x,y" места расположения
    //текущего персонажа, например, Genie:
    myGenie.MoveTo(
            Convert.ToInt16(this.Location.X + 400),
            Convert.ToInt16(this.Location.Y - 130), 1000);
    //Показываем персонаж в заданном месте:
    myGenie.Show(0);
    //Чтобы персонажи произносили речи через динамики,
    //задаем им следующие свойства:
    myAgentController = new AgentObjects.Agent();
    myAgentController.Connected = true;
    myAgentController.Characters.Load(
         "genie", "genie.acs");
    myGenie =
           myAgentController.Characters.Character("genie");
    myAgentController.Characters.Load(
         "merlin", "merlin.acs");
    myMerlin =
           myAgentController.Characters.Character("merlin");
    myAgentController.Characters.Load(
         "peedy", "peedy.acs");
    myPeedy =
           myAgentController.Characters.Character("peedy");
    myAgentController.Characters.Load(
         "robby", "robby.acs");
    myRobby =
           myAgentController.Characters.Character("robby");
    //Текущий персонаж произносит текст из кода
    //и показывает этот текст в виде подсказки:
    myGenie.Speak("Здравствуйте. Меня зовут Джин. " +
    "Выберите, пожалуйста, персонаж, анимацию, " +
    "запишите слова в окно и щелкните кнопку.", myObject);
    //Добавляем в окно со списком ComboBox1
    //имена CharacterID четырех персонажей:
    comboBox1.Items.Add("Genie");
    comboBox1.Items.Add("Merlin");
    comboBox1.Items.Add("Peedy");
    comboBox1.Items.Add("Robby");
}
В панели Properties выбираем заголовок comboBox1 (или щелкаем по элементу управления comboBox1) и на вкладке Events дважды щелкаем по имени события SelectedIndexChanged. Появляется файл Form1.cs с шаблоном, который после записи нашего кода (согласно алгоритму) принимает следующий вид.


Листинг 48.3. Метод для окна со списком comboBox1.
private void comboBox1_SelectedIndexChanged(
      object sender, EventArgs e)
{
    //Добавляем имена анимаций для выделенного
    //(в окне со списком comboBox1) персонажа
    //в окно со списком comboBox2:
    We_Get_AnimationNames();
}
Чтобы это добавление имен анимаций (для выделенного в окне со списком comboBox1 персонажа) в окно со списком comboBox2 можно было вставлять в другие приложения, оформим это добавление в виде отдельного метода We_Get_AnimationNames, как показано на следующем листинге.
Листинг 48.4. Метод We_Get_AnimationNames.
private void We_Get_AnimationNames()
{
    //Объявляем перечислители myEnumerator
    //интерфейса IEnumerator
    //для имен анимаций каждого персонажа:
    System.Collections.IEnumerator myEnumerator1 =
            axAgent1.Characters.Character("Genie").
            AnimationNames.GetEnumerator();
    System.Collections.IEnumerator myEnumerator2 =
            axAgent2.Characters.Character("Merlin").
            AnimationNames.GetEnumerator();
    System.Collections.IEnumerator myEnumerator3 =
            axAgent3.Characters.Character("Peedy").
            AnimationNames.GetEnumerator();
    System.Collections.IEnumerator myEnumerator4 =
            axAgent4.Characters.Character("Robby").
            AnimationNames.GetEnumerator();
    //Если в окне со списком comboBox1
    //выбран первый персонаж с индексом 0:
    if (comboBox1.SelectedIndex == 0)
    {
        //Очищаем окно со списком ComboBox2:
        comboBox2.Items.Clear();
        //Организовываем цикл:
        while (myEnumerator1.MoveNext())
                  //Добавляем имена анимаций этого персонажа
                  //в окно со списком comboBox2:
                  comboBox2.Items.Add(
                        myEnumerator1.Current);
    }
    //Если в окне со списком comboBox1
    //выбран второй персонаж с индексом 1:
    if (comboBox1.SelectedIndex == 1)


    {
        //Очищаем окно со списком ComboBox2:
        comboBox2.Items.Clear();
        //Организовываем цикл:
        while (myEnumerator2.MoveNext())
                  //Добавляем имена анимаций этого персонажа
                  //в окно со списком comboBox2:
                  comboBox2.Items.Add(
                        myEnumerator2.Current);
    }
    //Если в окне со списком comboBox1
    //выбран третий персонаж с индексом 2:
    if (comboBox1.SelectedIndex == 2)
    {
        //Очищаем окно со списком ComboBox2:
        comboBox2.Items.Clear();
        //Организовываем цикл:
        while (myEnumerator3.MoveNext())
                  //Добавляем имена анимаций этого персонажа
                  //в окно со списком comboBox2:
                  comboBox2.Items.Add(
                        myEnumerator3.Current);
    }
    //Если в окне со списком comboBox1
    //выбран четвертый персонаж с индексом 3:
    if (comboBox1.SelectedIndex == 3)
    {
        //Очищаем окно со списком ComboBox2:
        comboBox2.Items.Clear();
        //Организовываем цикл:
        while (myEnumerator4.MoveNext())
              //Добавляем имена анимаций этого персонажа
              //в окно со списком comboBox2:
              comboBox2.Items.Add(
                        myEnumerator4.Current);
      }
}
Теперь, следуя алгоритму в первом параграфе, мы записываем такой код, чтобы:
если в левом окне со списком comboBox1 из четырех персонажей (Genie, Merlin, Peedy, Robby) мы  выбираем какой-либо один персонаж,
а в правом окне со списком comboBox2 из более чем 70 анимаций мы выбираем какую-либо одну анимацию,
то на месте предыдущего персонажа появляется выбранный нами персонаж,  произносит текст и выполняет выбранную нами анимацию.
В панели Properties выбираем заголовок comboBox2 (или щелкаем по элементу управления comboBox2) и на вкладке Events дважды щелкаем по имени события SelectedIndexChanged. Появляется файл Form1.cs с шаблоном, который после записи нашего кода (согласно алгоритму) принимает следующий вид.


Листинг 48.5. Метод для окна со списком comboBox2.
private void comboBox2_SelectedIndexChanged(
      object sender, EventArgs e)
{
    //Персонаж произносит текст
    //и показывает анимацию при условии:
    //Если в окне со списком comboBox1
    //выбран новый персонаж:
    if (comboBox1.SelectedIndex == 0)
    {
        //Скрываем все другие персонажи:
        myMerlin.Hide(0);
        myPeedy.Hide(0);
        myRobby.Hide(0);
        //Останавливаем текущую анимацию:
        myGenie.StopAll(myObject);
        //От начала координат в вехнем левом углу Form1
        //задаем координаты "x, y" _
        //места расположения нового персонажа:
        myGenie.MoveTo(
            Convert.ToInt16(this.Location.X + 750),
            Convert.ToInt16(this.Location.Y + 250), 1000);
        //Показываем новый персонаж:
        myGenie.Show(0);
        //Перед анимацией персонаж произносит "Слушаюсь":
        mySpeech = "Слушаюсь.";
        myGenie.Speak(mySpeech, myObject);
        //Показываем выделенную нами анимацию персонажа:
        myGenie.Play(comboBox2.SelectedItem.ToString());
        //Показываем анимацию персонажа в покое:
        myGenie.Play("RestPose");
    }
    //Если в окне со списком comboBox1
    //выбран новый персонаж:
    if (comboBox1.SelectedIndex == 1)
    {
        //Скрываем все другие персонажи:
        myGenie.Hide(0);
        myPeedy.Hide(0);
        myRobby.Hide(0);
        //Останавливаем текущую анимацию:
        myMerlin.StopAll(myObject);
        //От начала координат в вехнем левом углу Form1
        //задаем координаты "x, y" _
        //места расположения нового персонажа:
        myMerlin.MoveTo(
            Convert.ToInt16(this.Location.X + 750),
            Convert.ToInt16(this.Location.Y + 250), 1000);
        //Показываем новый персонаж:
        myMerlin.Show(0);
        //Перед анимацией персонаж произносит "Слушаюсь":
        mySpeech = "Слушаюсь.";


            myMerlin.Speak(mySpeech, myObject);
            //Показываем выделенную нами анимацию персонажа:
        myMerlin.Play(comboBox2.SelectedItem.ToString());
        //Показываем анимацию персонажа в покое:
        myMerlin.Play("RestPose");
    }
    //Если в окне со списком comboBox1
    //выбран новый персонаж:
    if (comboBox1.SelectedIndex == 2)
    {
        //Скрываем все другие персонажи:
        myGenie.Hide(0);
        myMerlin.Hide(0);
        myRobby.Hide(0);
        //Останавливаем текущую анимацию:
        myPeedy.StopAll(myObject);
        //От начала координат в вехнем левом углу Form1
        //задаем координаты "x, y" _
        //места расположения нового персонажа:
        myPeedy.MoveTo(
            Convert.ToInt16(this.Location.X + 750),
            Convert.ToInt16(this.Location.Y + 250), 1000);
        //Показываем новый персонаж:
        myPeedy.Show(0);
        //Перед анимацией персонаж произносит "Слушаюсь":
        mySpeech = "Слушаюсь.";
        myPeedy.Speak(mySpeech, myObject);
        //Показываем выделенную нами анимацию персонажа:
        myPeedy.Play(comboBox2.SelectedItem.ToString());
        //Показываем анимацию персонажа в покое:
        myPeedy.Play("RestPose");
    }
    //Если в окне со списком comboBox1
    //выбран новый персонаж:
    if (comboBox1.SelectedIndex == 3)
    {
        //Скрываем все другие персонажи:
        myGenie.Hide(0);
        myMerlin.Hide(0);
        myPeedy.Hide(0);
        //Останавливаем текущую анимацию:
        myRobby.StopAll(myObject);
        //От начала координат в вехнем левом углу Form1
        //задаем координаты "x, y" _
        //места расположения нового персонажа:
        myRobby.MoveTo(
            Convert.ToInt16(this.Location.X + 750),
            Convert.ToInt16(this.Location.Y + 250), 1000);
        //Показываем новый персонаж:
        myRobby.Show(0);
        //Перед анимацией персонаж произносит "Слушаюсь":


        mySpeech = "Слушаюсь.";
        myRobby.Speak(mySpeech, myObject);
        //Показываем выделенную нами анимацию персонажа:
        myRobby.Play(comboBox2.SelectedItem.ToString());
        //Показываем анимацию персонажа в покое:
        myRobby.Play("RestPose");
      }
}
Теперь, следуя алгоритму в первом параграфе, мы записываем такой код, чтобы:
если мы щелкнем кнопку на форме, но ничего не запишем в окно TextBox, то персонаж попросит нас записать текст в это окно;
когда мы запишем в окно TextBox текст на русском языке и щелкнем кнопку на форме, то персонаж произнесет записанный нами текст.
Дважды щелкаем эту кнопку в режиме редактирования (или в панели Properties выбираем заголовок button1 и на вкладке Events дважды щелкаем по имени события Click). Появляется файл Form1.cs с шаблоном (метода button1_Click), который после записи нашего кода принимает следующий вид.
Листинг 48.6. Метод для кнопки.
private void button1_Click(object sender, EventArgs e)
{
      //Чтобы персонажи произносили речи через динамики,
      //задаем им следующие свойства:
      myAgentController = new AgentObjects.Agent();
      myAgentController.Connected = true;
      myAgentController.Characters.Load(
             "genie", "genie.acs");
      myGenie =
            myAgentController.Characters.Character("genie");
      myAgentController.Characters.Load(
             "merlin", "merlin.acs");
      myMerlin =
           myAgentController.Characters.Character("merlin");
      myAgentController.Characters.Load(
             "peedy", "peedy.acs");
      myPeedy =
            myAgentController.Characters.Character("peedy");
      myAgentController.Characters.Load(
             "robby", "robby.acs");
      myRobby =
            myAgentController.Characters.Character("robby");
      //Персонаж произносит текст из окна TextBox


      //при условии:
      // Если окно TextBox не заполнено:
      if (textBox1.Text == "")
      {
        if (comboBox1.SelectedIndex == 0)
        {
            mySpeech =
            "Запишите, пожалуйста, в окно слова, " +
            "которые я должен произнести.";
            myGenie.Speak(mySpeech, myObject);
        }
        if (comboBox1.SelectedIndex == 1)
        {
            mySpeech =
            "Запишите, пожалуйста, в окно слова, " +
            "которые я должен произнести.";
            myMerlin.Speak(mySpeech, myObject);
        }
        if (comboBox1.SelectedIndex == 2)
        {
            mySpeech =
            "Запишите, пожалуйста, в окно слова, " +
            "которые я должен произнести.";
            myPeedy.Speak(mySpeech, myObject);
        }
        if (comboBox1.SelectedIndex == 3)
        {
            mySpeech =
            "Запишите, пожалуйста, в окно слова, " +
            "которые я должен произнести.";
            myRobby.Speak(mySpeech, myObject);
        }
      }
      else
      //иначе, если окно TextBox заполнено,
      //персонаж произносит слова из этого TextBox:
      {
            mySpeech = textBox1.Text;
            if (comboBox1.SelectedIndex == 0)
            myGenie.Speak(mySpeech, myObject);
            if (comboBox1.SelectedIndex == 1)
            myMerlin.Speak(mySpeech, myObject);
            if (comboBox1.SelectedIndex == 2)
            myPeedy.Speak(mySpeech, myObject);
            if (comboBox1.SelectedIndex == 3)
            myRobby.Speak(mySpeech, myObject);
      }
}
В предыдущей главе мы привели методику и программу для управления персонажами при помощи наших голосовых команд: когда мы произнесем в микрофон по-английски: заданную по умолчанию команду Hide (Скрыть), персонаж удаляется с экрана; одно из заданных по умолчанию имен персонажей (Genie, Merlin, Peedy, Robby), этот озвученный персонаж сменяет предыдущий; заданную нами пользовательскую голосовую команду, например, MoveToMouse, персонаж перемещается в место нахождения курсора мыши.


По изложенной в предыдущей главе методике здесь мы продолжим разработку методов управления персонажами при помощи голосовых команд. Напомним, что на листинге 48.2 в метод Form1_Load мы добавили новую голосовую команду в виде имени анимации (это имя имеется в окне со списком сomboBox2 для любого персонажа), чтобы видимый на экране персонаж произнес поясняющий текст и выполнил эту анимацию. К примеру, на листинге 48.2 для персонажа Genie (Джин) мы добавили имя анимации Announce в следующем коде:
    //Добавляем имя анимации, активизируемое голосом:
    mySpeech = "Announce";
    myGenie.Commands.Add(
    mySpeech, mySpeech, mySpeech, true, true);
Таким образом, чтобы после произнесения в микрофон имени анимации Announce персонаж выполнил эту анимацию, в панели Properties выбираем заголовок AxAgent1 (или щелкаем по элементу управления AxAgent1) и на вкладке Events дважды щелкаем по имени события Command. Появляется файл Form1.cs с шаблоном, который после записи нашего кода (согласно алгоритму) принимает такой вид.
Листинг 48.7. Метод, чтобы персонаж выполнял наши голосовые команды.
//Объявляем глобальный объект myCommand интерфейса
static AgentObjects.IAgentCtlUserInput myCommand;
private void axAgent1_Command(object sender,
      AxAgentObjects._AgentEvents_CommandEvent e)
{
      //Связываем объект myCommand с голосом пользователя:
      myCommand = (AgentObjects.IAgentCtlUserInput)
            (e.userInput);
      //Если выше при помощи метода Add мы добавили
      //имя анимации, например, Announce
      //в качестве голосовой команды:
      if (myCommand.Voice == "Announce")
      {
          //После голосовой команды останавливаем
          //текущую анимацию:
          myGenie.StopAll(myObject);
          //Перед анимацией персонаж произносит:
          mySpeech = "Охотно покажу эту анимацию.";
          myGenie.Speak(mySpeech, myObject);
          //Показывает анимацию, имя которой
          //мы произнесли в микрофон:


          myGenie.Play("Announce");
          //Показывает анимацию в покое:
          myGenie.Play("RestPose");
      }
      //После команды голосом "MoveToMouse"
      // персонаж перемещается на место курсора мыши:
      if (myCommand.Voice == "MoveToMouse")
      {
            myGenie.MoveTo(
                        Convert.ToInt16(Cursor.Position.X),
                  Convert.ToInt16(Cursor.Position.Y), 1000);
      }
}
Поясним, что выше на листинге 48.2 в метод Form1_Load мы добавили голосовую команду MoveToMouse, поэтому в данном листинге приводим код для обработки также и этой команды (этот код подробно объяснен в предыдущей главе).
Аналогично мы можем записать код для решения любой подобной задачи согласно разработанному нами алгоритму, в том числе для выполнения любой анимации любого персонажа по нашей голосовой команде.
Cтроим программу и запускаем на выполнение обычным образом: Build, Build Solution; Debug, Start Without Debugging. В ответ Visual C# выполняет программу и на рабочий стол выводит форму Form1 в режиме выполнения.
И теперь на основании предыдущих глав разработаем методику создания мультфильма с использованием этих персонажей и их анимаций.

Запуск Word, добавление нового и открытие существующего документа


Листинг 17.1. Объектная переменная и метод для вызова Word.

//Объявляем объектную переменную objectWord

//и, тем самым, запускаем процессор Word,

//который по умолчанию невидим:

Word.Application objectWord = new Word.ApplicationClass();  

private void button6_Click(object sender, EventArgs e)

{

      //Делаем Word видимым:

      objectWord.Visible = true;

}



Этапы разработки программы для установки приложения


 

Чтобы передать пользователю (а пользователями можем быть и мы, разработчики приложения) или заказчику разработанное нами любое приложение на базе платформы Microsoft Visual Studio (на четырех основных комплексах: Visual Basic, Visual C#, Visual C++, Visual J#), необходимо выполнить следующие этапы:

создание проекта для установки приложения;

добавление (в проект установки приложения) проекта разработанного нами ранее приложения;

ввод ярлыка в меню Start (Пуск);

построение решения из двух проектов;

запуск приложения на компьютере пользователя.

Последовательно рассмотрим эти этапы.



Краткие сведения о Microsoft Agent


Продолжаем разрабатывать методологию мультимедиа на примере интеграции Visual Basic с очень популярной и перспективной технологией Microsoft Agent. Microsoft Agent – это беспрецедентная программная мультимедийная технология для более естественных путей связи человека и компьютера через создание новых диалоговых интерфейсов. Это набор программных услуг, которые дают возможность разработчикам включать интерактивные анимированные персонажи в их приложения и веб-страницы. Эти персонажи могут говорить при помощи программы (средства, механизма, инструмента, преобразователя) для перевода текста в речь (a text-to-speech engine - TTS), воспроизводить аудио и даже принимать разговорные речевые команды через механизм распознавания речи (speech recognition engine). Microsoft Agent дает возможность разработчикам расширить интерфейс пользователя за пределы распространенных сегодня взаимодействий мыши и клавиатуры. Технология Microsoft Agent может быть применима в следующих областях:

имеется огромное число ролей, которые разработчик в качестве режиссера может создать для персонажей Microsoft Agent и применить в своих программах;

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

дружественная обучающая программа с такими персонажами могла бы помогать человеку в поэтапном освоении нового материала;

персонаж мог бы представить уведомление или предупреждение, что новая электронная почта прибыла, и затем предложить ее прочитать;

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

Технология Microsoft Agent предназначена прежде всего для разработчиков, использующих языки или среды, которые поддерживают компонентную объектную модель (Component Object Model – COM) или интерфейсы управления Microsoft ActiveX. Они включают, например, Microsoft Visual Studio (Visual C#, Visual Basic, Visual FoxPro), Microsoft Office (Visual Basic for Applications), Microsoft Internet Explorer (Visual Basic Scripting Edition or Microsoft Jscript), Microsoft Windows Script Host (ActiveX Scripting Language).



Объектно-ориентированный анализ геометрии изделий


Напомним, что перед нами стоит задача: разработать методологию создания вычислительной системы из различных приложений комплекса Visual C# с использованием элементов компьютерной графики. Если в предыдущих главах мы разрабатывали приложения для математических вычислений и построения графиков функций, то с этой главы начнем разрабатывать приложения для решения практических проблем в науке и технике (например, в промышленности, строительстве, сельском хозяйстве и т.д.). Одной из самых распространенных таких проблем является определение площади поверхности, объема и массы любого изделия (вещи, продукта, детали), которое или уже изготавливается, или планируется изготавливать (выпускать). Расчет площади поверхности, объема и массы необходимо выполнять абсолютно для всех изделий (как вновь спроектированных, так и существующих, но, например, модернизированных изделий); такой расчет является самостоятельной (часто сложной) инженерной задачей, которая обычно решается приближенно с заданной точностью. Для решения этой задачи будем использовать объектно-ориентированную философию, которая (как уже отмечалось) включает три основных понятия: объектно-ориентированный анализ; объектно-ориентированное проектирование и объектно-ориентированное программирование ООП (Object Oriented Programming, OOP). С целью реализации принципов объектно-ориентированной философии сначала необходимо разработать класс объектов-изделий.

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

1. Класс объектов-изделий типа стакана.

2. Класс объектов-изделий типа втулки.

3. Класс объектов-изделий типа оси и так далее.



Описание содержимого компакт-диска и схема использования


На прилагаемом к книге компакт-диске приведены все листинги из этой книги в виде файла формата (.doc) для текстового редактора Microsoft Word любой версии, например, Word 2003.

Эти листинги можно вставлять в любую программу, например, по такой схеме.

1. В Visual Studio мы строим проект типа Visual C#, Visual Basic или Visual C++ (с новым синтаксисом) версии 2002, 2003, 2004 или 2005 года по методике, описанной в главе книги.

2. В этом проекте получаем (по описанной в главе книги схеме) шаблон метода (если это возможно), например, при помощи двойного щелчка по имени события в панели Properties на вкладке Events для формы Form1, элемента управления или компонента.

3. В текстовом редакторе Word открываем с компакт-диска файл формата (.doc) с листингами книги, щелкаем по гиперссылке с номером данной главы в оглавлении файла, находим и выделяем мышью код, который мы хотим вставить в шаблон метода, и копируем в буфер обмена (Clipboard) при помощи стандартного приема: правый щелчок по выделенному коду, Копировать (Copy).

4. Открываем файл, например, Form1.cs нашего проекта типа Visual C# и в шаблон метода вставляем (правый щелчок, Вставить – Paste) код из буфера обмена.

5. Если шаблон метода невозможно получить, то с компакт-диска аналогично копируем весь метод (методы) и вставляем в проект типа Visual C#, Visual Basic или Visual C++ 2002 – 2005 годов.

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

7. Мы не приводим проекты Visual Studio 2005, т.к. их невозможно открыть на предыдущих версиях Visual Studio 2002, 2003 и 2004 годов.

Программы с этих листингов могут быть использованы при разработке разнообразных приложений не только на базе Visual Studio 2005, но и на базе предыдущих версий Visual Studio .NET 2002, Visual Studio .NET 2003 и Visual Studio 2004.



Основные схемы интеграции


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

Если известные базовые программы написаны на том же языке, на котором мы разрабатываем проект, например, на Visual C#, то мы вставляем известные программы в наш новый проект и дорабатываем для решения конкретной задачи.

Если же базовые программы написаны, например, на Visual Basic, т.е. не на том языке, на котором мы разрабатываем проект, то при разработке новых программ на основе известных возможны три основных схемы (варианта).

Первая схема (вариант). Мы переписываем известные программы с Visual Basic на Visual C# и вставляем в новый проект. Например, приведенные в данной книге программы графической системы в двух- и трехмерном пространстве мы сначала написали на более простом языке Visual Basic и опубликовали в наших предыдущих книгах [3,4,8], а затем переписали на Visual C# и приводим в данной книге. Следовательно, методика переписывания программы с Visual Basic на Visual C# за счет изменения, главным образом, только синтаксиса языка в данной книге уже имеется, и аналогично по этой методике можно переписывать другие программы. К слову, подробные таблицы сравнения синтаксиса четырех главных (в мире программирования) языков Basic, C#, C++, J# даны в нашей книге [2].

Вторая схема (вариант). В имеющемся у нас базовом проекте, например, на Visual Basic мы организовываем программу таким образом, чтобы эта программа рассчитывала данные, например, в виде потоков или массивов координат точек геометрических изображений (например, в виде массивов координат узловых точек геометрического тела, поверхности z=f(x,y) и осей координат на плоском экране монитора). Эти массивы мы передаем в новый  проект на Visual C#.  Такую передачу данных, например, в виде массивов экранных координат точек изображений мы осуществляем в проекте на Visual Basic (по описанной ниже методике) при помощи класса StreamWriter и записи этих массивов в файлы на жестком диске компьютера (например, в текстовые файлы типа D:\MyDocs\MyTest.txt). Далее в нашем новом проекте на Visual C# (или Visual Basic, или Visual C#, или каком-либо другом языке) при помощи класса StreamReader программа считывает из файлов массивы координат и по этим координатам строит изображения при помощи какого-либо метода интерфейса Graphics Device Interface (GDI+), например, DrawLine. 

Третья схема (вариант). В этом варианте мы используем так называемую схему или  методику “компонент - клиент”.



Постановка задачи и проектирование формы


Листинг 35.1. Метод для рисования геометрических изображений.

    private void pictureBox1_Paint(object sender,

PaintEventArgs e)

    {

        //Объявляем индексы элементов всех массивов:

        int i, j, k;

        //Задаем границы индексов 1-го массива myArrayVC(i, j):

        int N_x = 201; int N_y = 2;

        //Объявляем 1-й массив myArrayVC(i, j) переменных float,

        //когда i = 0,1,2,3,...,(N_x - 1);

        //      j = 0,1,2,3,...,(N_y - 1):

        float[,] myArrayVC = new float[N_x, N_y];

        //Для считывания из файла

        //по адресу D:\\MyDocs\\MyTest3D_Graphics.txt

        //координат изображения в массив myArrayVC(201, 2)

        //создаем объект sr класса StreamReader:

        StreamReader sr =

            new StreamReader(

            @"D:\\MyDocs\\MyTest3D_Graphics.txt");

        //Считываем из файла MyTest3D_Graphics.txt

        //координаты изображения в массив myArrayVC(201, 2)

        //при помощи метода ReadLine:

        for (i = 0; i <= N_x - 1; i++)

      for (j = 0; j <= N_y - 1; j++)

               myArrayVC[i, j] =

                  Convert.ToSingle(sr.ReadLine());

        sr.Close();

        //Рисуем первое изображение по координатам из массива.

        //Объявляем координаты двух точек:

        float x1, y1, x2, y2;

        //Будем рисовать пером myPen толщиной 3:

        Pen myPen = new Pen(Color.Black, 3);

        //Объявляем переменные для начала N_first_line

        //и конца N_last_line цикла при рисовании:

        int N_first_line, N_last_line;

        //Передаем переменным для начала и конца цикла

        //значения первых двух элементов массива myArrayVC:

        N_first_line = Convert.ToInt32(myArrayVC[0, 0]);

        N_last_line = Convert.ToInt32(myArrayVC[0, 1]);

        //Рисуем изображение, начиная с точки (1,0; 1,1):

        i = -1;

        for (k = N_first_line; k <= N_last_line; k++)

        {

            i = i + 2;

            x1 = myArrayVC[i, 0];


            y1 = myArrayVC[i, 1];

            x2 = myArrayVC[i + 1, 0];

            y2 = myArrayVC[i + 1, 1];

            e.Graphics.DrawLine(myPen, x1, y1, x2, y2);

        }

        //Задаем границы индексов 2-го массива myArrayVC_2(i, j):

        int N_x_2 = 201;

        int N_y_2 = 2;

        //Объявляем 2-й массив myArrayVC_2(i, j) перем-х float,

        //когда i = 0,1,2,3,...,(N_x_2 - 1);

        //      j = 0,1,2,3,...,(N_y_2 - 1):

        float[,] myArrayVC_2 = new float[N_x_2, N_y_2];

        //Для считывания из файла

        //по адресу D:\\MyDocs\\MyTest3D_Graphics_2.txt

        //координат изображения в массив myArrayVC_2(201, 2)

        // создаем объект sr_2 класса StreamReader:

        StreamReader sr_2 = new StreamReader(

            @"D:\\MyDocs\\MyTest3D_Graphics_2.txt");

        //Считываем из файла MyTest3D_Graphics_2.txt

        //координаты изображения в массив myArrayVC_2(201, 2)

        //при помощи метода ReadLine:

        for (i = 0; i <= N_x - 1; i++)

      for (j = 0; j <= N_y - 1; j++)

                myArrayVC_2[i, j] =

                  Convert.ToSingle(sr_2.ReadLine());

        sr_2.Close();

        //Рисуем второе изображение по координатам из массива.

        //Будем рисовать пером myPen толщиной 1:

        Pen myPen_2 = new Pen(Color.Black, 1);

        //Объявляем переменные для начала N_first_line

        //и конца N_last_line цикла при рисовании:

        int N_first_line_2, N_last_line_2;

        //Передаем переменным для начала и конца цикла

        //значения первых двух элементов массива myArrayVC:

        N_first_line_2 = Convert.ToInt32(myArrayVC_2[0, 0]);

        N_last_line_2 = Convert.ToInt32(myArrayVC_2[0, 1]);

        //Рисуем изображение, начиная с точки (1,0; 1,1):

        i = -1;

        //for (k = 1; k <= 3; k++)

        for (k = N_first_line_2; k <= N_last_line_2; k++)

        {

            i = i + 2;

            x1 = myArrayVC_2[i, 0];

            y1 = myArrayVC_2[i, 1];

            x2 = myArrayVC_2[i + 1, 0];

            y2 = myArrayVC_2[i + 1, 1];

            e.Graphics.DrawLine(myPen_2, x1, y1, x2, y2);

        }

    }

Аналогично по этой методологии мы можем разработать другие приложения для построения различных пространственных изображений.


Создание проекта для установки приложения


Для создания проекта установки:

1. На стартовой странице Visual Studio 2005 щелкаем кнопку или значок New Project (или в меню выбираем File, New, Project).

2. В панели New Project:

в окне Project Types выделяем тип проекта Setup and Deployment Projects; в окне Templates выделяем шаблон Setup Project;

в окне Name оставляем заданное по умолчанию имя проекта Setup1 (рис. 90.1)  и щелкаем OK.

В ответ Visual Studio 2005 создает решение (Solution), состоящее пока из одного проекта установки приложения, и выводит следующий интерфейс этого проекта установки в виде панели File System (рис. 90.2).

В левой части этой панели File System показана файловая система компьютера, на который будет установлено приложение, а справа – содержимое выбранной папки из левой части. Пока в этих папках ничего нет, и нам необходимо их заполнить. И то, что мы сейчас видим в правом окне на рис. 90.2, будет добавлено позднее.



Создание проекта SQL Server Project


В Visual Studio 2005 существует еще несколько вариантов разработки баз данных с использованием специальных шаблонов проекта Database по следующей схеме. В VS щелкаем New Project (или File, New, Project), в панели New Project (рис. 22.1) в окне Project Types открываем папку Visual C# и выделяем Database, в окне Templates выделяем шаблон SQLServer Project; в окне Name оставляем записанное по умолчанию имя проекта SQLServerProject1, в окне Location оставляем по умолчанию (или выбираем новый) путь к папке, в которой будет расположен проект, щелкаем OK.

Появляется панель SQLServerProject1 (рис. 22.2), в окна которой мы должны записать (или выбрать из имеющихся) имена сервера и базы данных.

В данном примере видно (рис. 22.2), что на нашем компьютере имеется соединение сервера Z-1 с базой данных Northwind (которую мы уже применяли выше).

Щелкаем кнопку OK (рис. 22.2). Создается проект для базы данных.



Список литературы


Жарков В.А. Visual C# .NET в науке и технике. – М .: Жарков Пресс, 2002.

Жарков В.А. Самоучитель Жаркова по Visual Studio .NET: Visual Basic .NET, Visual C# .NET, Visual C++ .NET, Visual J# .NET. – М .: Жарков Пресс, 2002.

Жарков В.А. Самоучитель Жаркова по Visual Basic .NET. – М .: Жарков Пресс, 2002.

Жарков В.А. Самоучитель Жаркова по анимации и мультипликации в Visual Basic .NET 2003. – М .: Жарков Пресс, 2003.

Жарков В.А. Самоучитель Жаркова по анимации и мультипликации в Visual C# .NET 2003. – М .: Жарков Пресс, 2003.

Жарков В.А. Самоучитель Жаркова по анимации и мультипликации в Visual C++. – М .: Жарков Пресс, 2003.

Жарков В.А. Самоучитель Жаркова по интеграции Visual Basic .NET 2003 с другими платформами. – М .: Жарков Пресс, 2003.

Жарков В.А. Компьютерная графика, мультимедиа и игры на Visual Basic. – М.: Жарков Пресс, 2004.

Жарков В.А. Visual C++ на практике. – М.: Лаборатория Базовых Знаний, 2002.

Zharkov V.A. Theory and Practice of Deep Drawing. – London, Mechanical Engineering Publications Limited, 1995.

Гарнаев А.Ю. Самоучитель Visual Studio .NET 2003. – СПб.: БХВ-Петербург, 2003.

Stephens R. Visual Basic Graphics Programming. 2nd Edition. New York, Wiley Computer Publishing, 1999.

Microsoft Visual Studio 2005.

Microsoft DirectX 9.0 SDK Update – (Summer 2004).



Требования для установки Visual Studio


Для установки на компьютер среды разработки (платформы) Visual Studio 2005 корпорация Microsoft  формулирует системные требования в виде табл. 1.1.

Таблица 1.1.

Требования к компьютеру для инсталляции платформы Visual Studio 2005.

Processor

Minimum: 766 megahertz (MHz) Pentium processor

Recommended: 1 gigahertz (GHz) Pentium processor recommended

Operating System

 Visual Studio 2005 can be installed on any of the following systems:

 Microsoft Windows® 2003 Server

 Windows XP Professional Service Pack 1

RAM

Minimum: 128 megabytes (MB)

Recommended: 256 MB

Hard Disk

Without MSDN: 750 MB of available space required on system drive

2 gigabytes (GB) of available space required on installation drive

With MSDN: 1.1 GB of available space required on system drive

3.2 GB of available space required on installation drive

CD or DVD Drive

Required

Display

Minimum: 800 x 600 256 colors

Recommended: 1024x768 High Color — 16-bit

Smart Device Development

ActiveSync 3.7.1

Microsoft .NET Framework Version 1.1 (for Smartphone 2003 projects)

Mouse

Microsoft mouse or compatible pointing device

Все платформы Visual Studio 2005, Visual Studio 2004, Visual Studio .NET 2003 и Visual Studio .NET 2002 созданы в виде редакций: Enterprise Architect, Enterprise Developer, Professional. Каждая редакция включает такие основные языки программирования: Visual Basic, Visual C#, Visual C++, Visual J#. Установка на компьютер любой версии этой платформы подробно описана в нашей книге [1].



в мире книга по новейшей


Это первая в мире книга по новейшей версии языка Visual C# 2005 из платформы Visual Studio 2005, которую издательство “Жарков Пресс” получило непосредственно от корпорации Microsoft (США). Сразу же отметим, что все программы из данной книги прекрасно работают также и на платформах предыдущих версий Visual Studio 2004, Visual Studio .NET 203 и Visual Studio .NET 2002.
Наша основная цель – дать читателю ту информацию, которую он больше нигде не найдет. Поэтому мы не будем дублировать известные книги по языку программирования Visual C# и давать подробные объяснения по теории этого языка. Если у читателя возникнуть вопросы, он легко отыщет книгу по данному языку  (некоторые книги приведены в нашем списке литературы) и там найдет ответ, так как терминология по всем тематикам у нас общая. Мы будем давать лишь краткие пояснения, чтобы начинающий пользователь постепенно осваивал различные базовые дисциплины, по возможности не используя другие книги; опытный пользователь может пропускать эти пояснения. К достоинствам книги, рассчитанной на широкий круг новичков и опытных специалистов, мы относим практическую направленность, простоту изложения (без описания сложных теорий, но давая ссылки на книги, в которых эти сложные теории можно изучить), наличие подробных методик и пошаговых инструкций, большое количество примеров и иллюстраций.
Все программы из этой книги могут быть вставлены в самые разнообразные проекты и приложения и прекрасно работать.
На прилагаемом к книге компакт-диске приведены все листинги с программами из этой книги в виде файла формата (.doc) для текстового редактора Microsoft Word любой версии. Эти программы можно скопировать и вставить в любые приложения Visual Studio на языках Visual C#, Visual Basic и Visual C++ версий 2002, 2003, 2004 и 2005 годов (как подробно описано в конце книги).
Книга предназначена:
для всех желающих быстро изучить новейший самый современный, совершенный и перспективный  (в мире программирования) язык высокого уровня Visual C#, сразу же создавать на этом языке последних версий Visual C# 2005, Visual C# 2004, Visual C# .NET 2003 и Visual C# .NET 2002 мощные профессиональные приложения и применять их на практике в разнообразных сферах деятельности,
в том числе, книга предназначена для начинающих и опытных пользователей компьютерами, программистов различной квалификации, инженерно-технических работников, конструкторов, технологов, математиков и механиков,
а также для учащихся и слушателей курсов, студентов, аспирантов, учителей, преподавателей, научных работников и ученых.
Все вопросы, замечания и предложения можно направлять по email:
valery-zharkov@mtu-net.ru
или с сайта нашего издательства «Жарков Пресс (Zharkov Press)»:
www.zharkovpress.com
На этом же сайте можно познакомиться со всеми новыми книгами нашего издательства «Жарков Пресс» (г. Москва).

Выполнение программы


Проверяем в работе новую форму. Для этого строим программу и запускаем ее на выполнение обычным образом: Build, Build Solution; Debug, Start Without Debugging. В ответ Visual C# выполняет программу и на рабочий стол выводит первую форму (с оглавлением нашей системы) в режиме выполнения. После щелчка переключателя 1 (или кнопки Next>>, или нажатия клавиш Alt+1) появляется наша Form3, показанная выше на рис. 17.1.

После щелчка первой кнопки “Запуск Word (Starting Word)” на Form3, на экране монитора появляется рабочий стол с интерфейсом Word, при помощи которого стандартным образом можно создавать новый документ, открывать существующий документ и далее редактировать этот документ всеми средствами Word.

На форму можно ввести эффекты анимации аналогично тому, как мы это сделали выше, а также мультипликационные персонажи, как это мы сделаем ниже. Несколько вариантов проверки орфографии и расчет статистических данных о тексте при помощи Word можно разработать по аналогии с нашими книгами [7, 8].


Cтроим программу и запускаем на выполнение обычным образом: Build, Build Solution; Debug, Start Without Debugging. В ответ Visual C# запускает программу и на рабочий стол выводит форму Form1 в режиме выполнения.

После загрузки Form1 на ней начинается показ нашего маленького мультфильма в следующей последовательности эпизодов.

Автоматически появляется Джин, выполняет первую анимацию и произносит (через динамики компьютера) первый текст (при этом губы персонажа шевелятся в такт с текстом), согласно приведенному выше нашему коду:

      //Персонаж выполняет анимацию Announce:

      myGenie.Play("Announce");

      //Произносит записанную нами речь:

      mySpeech =

      "Здравствуйте, меня зовут Джин. " +

      "Спасибо за Ваше внимание ко мне.";

      myGenie.Speak(mySpeech, myObject);

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




Проверяем в работе новую форму. Для этого строим программу и запускаем ее на выполнение обычным образом: Build, Build Solution; Debug, Start Without Debugging.

В ответ Visual C# выполняет программу и на рабочий стол выводит первую форму (с оглавлением нашей системы) в режиме выполнения.

После щелчка переключателя 2 (или нажатия клавиш Alt+2, или щелчка кнопки Next>> на предыдущей Form3) появляется Form5, показанная на рис. 70.1.

После щелчка первой основной кнопки “Start Windows Media” на экране монитора появляется проигрыватель Windows Media Player соответствующей версии (показанный в предыдущей главе), в котором можно воспроизводить файлы.

После щелчка второй основной кнопки “clock.avi” появляется проигрыватель Windows Media  и начинается воспроизведение видео файла с именем, которое мы записали в код. На рис. 70.2 видны часы, на которых перемещается секундная стрелка и изменяются цифры от 1 до 12 со звуковым сигналом каждую секунду.

После окончания воспроизведения можно продолжать выполнять любые операции, поддерживаемые интерфейсом Windows Media.

Аналогично воспроизводим любой другой файл.

Мы закончили часть нашей книги по методологии интеграции (взаимодействия) комплекса Visual С# (из платформы Visual Studio 2005) с проигрывателями серии Windows Media Player корпорации Microsoft для решения широко распространенных задач по воспроизведению аудио и видео файлов.

И теперь по этой методологии мы можем постепенно дополнять эти задачи другими возможностями данной интеграции.



Выполнение расчетов


Проверяем созданный нами второй калькулятор. Для этого строим программу и запускаем ее на выполнение обычным образом: Build, Build Solution; Debug, Start Without Debugging.



На этом мы закончили данную


На этом мы закончили данную книгу и описание нашей методологии разработки компьютерной графики, мультимедиа и игр на базе самого современного, совершенного и перспективного языка программирования высокого уровня Visual C# 2005 из новейшей версии платформы Microsoft Visual Studio 2005. Эта методология может быть использована при разработке разнообразных приложений не только на базе Visual Studio 2005, но и на базе предыдущих версий Visual Studio .NET 2002, Visual Studio .NET 2003 и Visual Studio 2004.
В начальных главах мы разработали методологию создания личных или корпоративных вычислительных систем для проведения теоретических и экспериментальных исследований и получения расчетных и экспериментальных данных. В этих системах расчеты, а также проектирование мультимедиа в виде анимации и мультипликации изображений осуществлены на базе основных типов приложений Visual C#, таких как Windows Application (приложение на основе форм), Console Application (приложение на основе консольных панелей) и др. В последующих главах мы разработали методологию создания графических систем для визуализация  полученных расчетных и экспериментальных данных при помощи разнообразных двухмерных и трехмерных графиков, геометрических поверхностей и трехмерных тел.  
Впервые в мире мы привели полные тексты мощных программ для построения и управления разнообразными трехмерными телами, поверхностями и линиями уровней этих поверхностей в трехмерном пространстве на трех различных языках: Visual C#, Visual Basic и Visual C++ (с новейшим синтаксисом).
Главное достоинство данной методологии заключается в том, что для создания двухмерных и трехмерных графических систем при решении широкого круга задач нам не нужно использовать дополнительные и сложные в применении библиотеки типа DirectX и OpenGL, а нужна только одна открытая и мощная среда разработки Visual Studio последних версий (2002, 2003, 2004 или 2005 года).
Тем не менее, мы подробно описали методологию создания очень сложных анимационных двухмерных и трехмерных графических систем для решения крупных задач в проектах Visual C# при помощи очень мощной библиотеки (точнее, целой технологии) новейшей версии DirectX 9.0с.
Методику создания мультимедийных приложений и игр в проектах Visual C# мы разработали на основе известной программной технологии Microsoft Agent. Эта технология позволяет включать в Windows-приложения и веб-страницы интерактивные (основанные на диалоге, в том числе и через голосовые команды в микрофон) анимационные персонажи. Персонажи могут и сами говорить (не только на английском, но и на русском языке), и выполнять наши речевые команды (правда, пока только на английском языке) при помощи уникальных программ синтеза и распознавания речи.
Эти методики можно применять в любой практической деятельности.
О компьютерных книгах нашего издательства “Жарков Пресс (Zharkov Press)” по данным тематикам можно узнать на сайте издательства:
www.zharkovpress.com