Урок 3. Первый взгляд на код

Урок 3: Первый взгляд на код

Наступила пора рассмотреть подробнее Inventor API.  На первом занятии вы ввели текст программы в окно кода формы и видели, как этот код менял видимость компонентов сборки.  На втором занятии вы создали приложение Windows Forms и подключили к проекту ссылку на Inventor API.  Сейчас мы продолжим работу над проектом, чтобы добавить в него способность создавать новый сеанс Inventor или подключаться к существующему сеансу, а также пошагово рассмотрим работу программы.

В Приложении вы найдете важную информацию об объектно-ориентированном программировании (ООП) и концепции классов

Обратная связь: напишите нам об этом занятии или о курсе «Моя первая программа»: myfirstplugin@autodesk.com
Скачать файлы Inventor для урока 3
lesson3_visualstudio_visualexpress.zip (zip - 18Kb)
Добавим в проект занятия 2 новый код

На втором занятии был создан проект со ссылкой на Autodesk.Inventor.Interop.dll,  которая дает программе возможность использовать Inventor API.  Следующим шагом будет получение доступа к объекту API самого верхнего уровня — Inventor.Application.

  1. Откроем проект из урока 2:
    Откройте проект из предыдущего урока и окно кода формы Form1.  Окно кода формы можно открыть правым кликом на Form1.vb  в Обозревателе решений, выбрав в контекстном меню пункт Перейти к коду.  Чтобы освободить место для новых строк, поставьте курсор в начале строки с текстом Public Class Form1 и нажмите несколько раз клавишу Enter. В результате получите несколько пустых строк в верхней части окна.
    Теперь над строкой Public Class Form1 введите следующие строки:
    Imports System
    Imports System.Type
    Imports System.Activator
    Imports System.Runtime.InteropServices
    Imports Inventor
    
    Ключевые слова
    Первое, что сразу бросается в глаза, это цветовое выделение введенного текста.   Visual Basic изменяет цвет некоторых слов для облегчения восприятия программного текста.  Синим выделяются ключевые слова, которые могут применяться лишь в определенных ситуациях.  Например, вам не удастся создать собственную переменную с именем Imports, поскольку это слово зарезервировано для служебных целей.

    Пространства имен
    Первые несколько строк кода начинаются с ключевого слова Imports.  При работе в проекте Visual Basic с различными API и компонентами вполне вероятны случайные совпадения имен. Для исключения подобных конфликтов .NET предлагает вам концепцию пространства имен.  Пространство имен — способ организации взаимосвязанных классов в группы, которые облегчают идентификацию нужных классов.

    Предположим для примера, что по соседству проживают два мальчика по имени Джон.  Одним из способов однозначной идентификации конкретного Джона может быть использование его фамилии.  Но если и фамилии вдруг окажутся одинаковыми, скажем, Смит, то однозначной идентификации не получится.  Придется в этом случае воспользоваться дополнительной информацией, например, указанием школы, в которой каждый из них учится.  С использованием синтаксиса VB.NET одного из ребят можно именовать SchoolA.Smith.John, другого — SchoolB.Smith.John.

    Точно таким же образом вы можете идентифицировать любой конкретный класс в VB.NET.  Ключевое слово Imports обеспечивает прямой доступ к классам, включенным в пространство имен, что избавляет все от необходимости вводить полные длинные имена классов в тексте программы.  Сервис IntelliSense использует информацию о классах пространства имен при формировании своих подсказок. Ключевое слово Imports диктует компилятору VB.NET обеспечить доступ к классам указанного пространства имен из кода в данном файле.
    С момента добавления ссылки на Autodesk.Inventor.Interop.dll в вашем проекте становится доступным пространство имен Inventor, после чего его можно указывать в директиве Imports
  1. Классы
    Следующая строка программы определяет класс:
    Public Class Form1
    

    Это стандартное объявление класса, оно было создано мастером Visual Studio в момент создания проекта.  Вы можете рассматривать класс как определение типа, которое может быть использовано для описания любого объекта этого типа.  Класс можно рассматривать и как своего рода шаблон, описывающий характеристики конкретных объектов и который может быть использован для создания подобных объектов.  Класс может помочь в определении общих характеристик объектов своего типа: атрибутов (свойств) объектов и их поведения (методов).  Более подробно эти вопросы рассмотрены в Приложении.

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

     

  2.  Добавим переменные
    После объявления класса можно ввести в программу несколько переменных.
        Dim _invApp As Inventor.Application
        Dim _started As Boolean = False
    

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

    Начнем с создания переменной _invApp.  Вы можете дать переменной практически любое имя, коль скоро это имя является уникальным в пределах текущей области кода и не является зарезервированным (как, например, уже упомянутое выше слово “Imports”).  Разумеется, вы можете присвоить этой переменной и более осмысленное имя типа “theInventorApplication”.  Символ подчеркивания в начале имени переменной — дань соглашению именовать так переменные класса, они доступны из любых процедур и функций этого класса. 

    Для объявления переменной используется ключевое слово Dim, за которым следует имя переменной _invApp.  Тип переменной указывается после ключевого слова As, в данном случае это Inventor.Application.

    Вслед за объявлением переменной _invApp, которая будет использоваться для быстрого доступа к объекту Inventor Application, вы объявите еще одну переменную с именем _started типа Boolean (логический). Это означает, что данная переменная может принимать лишь два значения — True (истина) или False (ложь).  Объявление переменных резервирует область памяти для хранения данных, размер выделяемой памяти зависит от размера сохраняемого типа или класса.  Примечание:
    Обратите внимание, несмотря на подключение пространства имен Inventor директивой Imports, вы по-прежнему вынуждены полностью специфицировать имя Inventor.Application. Дело в том, использование просто Application приведет к конфликту с пространством имен System.Windows.Forms, где тоже имеется объект Application.

  3. Процедуры
    Теперь мы приступим к созданию процедуры Sub (от англ. Sub-routine – подпрограмма).  Sub представляет собой блок кода, который выполняется при заданных вами условиях. Например, вы можете пожелать выполнять процедуру при каждом нажатии конкретной кнопки в диалоговом окне.

    Сочетание ключевых слов Public и Sub перед именем процедуры задает область видимости этой процедуры. Конец процедуры задается ключевыми словами End Sub.  Добавить процедуру можно и с использованием выпадающего меню, что находится в верхней части окна кода.  Создаваемые с помощью этого меню процедуры предусмотрены по умолчанию для класса, код которого вы в этот момент редактируете. В вашем случае это класс Form.  Для него характерна, например, процедура Sub New.  Эта процедура автоматически вызывается в момент создания формы (в данном приложении это происходит при старте приложения).  Она вам пригодится, чтобы создать новый сеанс Inventor или подключиться к уже существующему сеансу, если он будет обнаружен.

    Процедура должна располагаться в пределах кода класса.  Давайте создадим процедуру “Sub” в классе Form1.  Сделайте сначала активным окно кода формы Form1.  Это можно сделать, если правым кликом на имени проекта в Обозревателе решений открыть контекстное меню и выбрать в нем пункт «Перейти к коду».  Далее в верхних выпадающих меню выберите Form1 в левом и New в правом меню.



    Теперь процедура Sub New должна быть добавлена в класс Form1.  Эта процедура вызывается при старте приложения Windows Form, т.е. начальным действием по умолчанию такого приложения является  создание объекта типа Form1 и отображение его на экране (это можно контролировать через свойства проекта).

    Вашему приложению для работы необходим сеанс Inventor.  В принципе вы можете многократно подключаться к Inventor в моменты, когда требуется выполнить в нем какие-либо действия. В данном же случае вы реализуете более простой подход — подключение к сеансу Inventor будет производиться один раз при старте вашего приложения.
       Public Sub New()
     
       ' Этот вызов является обязательным для конструктора.
       InitializeComponent()
     
       ' здесь размещается любой инициализирующий код.
     
    End Sub
    

  4. Создание или подключение к сеансу Inventor:
    Введите приведенный ниже код после вызова метода InitializeComponent().  Вызов InitializeComponent вставляется в конструктор Sub New автоматически и помогает настроить поведение формы.  Если вам хочется взглянуть на код метода,  правым кликом на имени метода откройте контекстное меню и выберите в нем пункт «Перейти к определению».  Убедитесь, что вы не изменили код метода InitializeComponent – редактировать его не требуется, поскольку этот код будет изменяться автоматически по мере ведения в форму новых элементов управления.

        ' здесь размещается любой инициализирующий код.
    Try
     _invApp = Marshal.GetActiveObject("Inventor.Application")
      
    Catch ex As Exception
       Try
         Dim invAppType As Type = _
         GetTypeFromProgID("Inventor.Application")
     
         _invApp = CreateInstance(invAppType)
         _invApp.Visible = True
     
        'Примечаниеstarted :
        'Данная логическая переменная служит индикатором,
        'был ли данный сеанс Inventor создан нашей программой
        'и требуется ли принудительное завершение сеанса
        'по окончании работы нашего приложения.
         _started = True
     
       Catch ex2 As Exception
         MsgBox(ex2.ToString())
         MsgBox("Не удалось ни найти, ни создать сеанс Inventor")
       End Try
    End Try
    

    Обратите внимание, что для присвоения значения объектной переменной _invApp используется знак равенства:
    _invApp = Marshal.GetActiveObject("Inventor.Application")
    
    После выполнения этой строки переменная _invApp будет содержать ссылку на объект типа Inventor.Application.  Обратите внимание также на то, что объявление переменных класса _invApp и _started было сделано с использованием ключевого слова Dim вне какой-либо процедуры Sub.  Это сделало их глобальными, общедоступными в пределах класса, т.е. вы можете обращаться к этим переменным из любой процедуры данного класса.  Это сделано для того, чтобы воспользоваться обеими переменными в процедуре обработчика события FormClosed, которая будет добавлена на следующем шаге.

    Исключения
    Функция GetActiveObject помогает нам найти существующий сеанс Inventor.  Переданная в аргументе строка «Inventor.Application», известная как ProgID, указывает функции GetActiveObject тип объекта, который следует искать.  Блок Try-Catch, в который мы заключили вызов GetActiveObject, отслеживает возможные исключения, т.е. ошибки в .NET коде.  Это сделано специально, поскольку мы точно знаем, что функция GetActiveObject сгенерирует ошибку (“throw” an exception), если не найдет сеанс Inventor.  Если такое случится, будет выполнен код, размещенный после ключевого слова Catch. Этот код попытается создать новый сеанс Inventor.

  5. События
    Рассмотрим реакцию программы на событие FormClosed.  События представляют собой нечто такое, о чем вы получаете уведомления и на что вы можете реагировать в вашем программном коде.  Получение уведомления о событии FormClosed означает, что форма Form1 закрывается, и вам следует выполнить предусмотренные завершающие операции.  Если вы запустили новый сеанс Inventor в вашем конструкторе Sub New, вам следует завершить этот сеанс.  Именно по этой причине была введена логическая переменная _started, которая в таком случае имеет значение True.  Вы можете проверить значение этой переменной при закрытии формы, и если значение равно True, закрыть сеанс Inventor.  Чтобы создать процедуру–обработчик события FormClosed, выделите в левом выпадающем меню пункт «(События Form1)», а потом выберите пункт FormClosed в выпадающем меню справа.



    После этого обработчик события “Form1_FormClosed” будет добавлен в класс Form1.  Эта процедура Sub будет вызываться всякий раз при закрытии формы.

    Private Sub Form1_FormClosed(ByVal sender As Object, ByVal e As 
    System.Windows.Forms.FormClosedEventArgs) Handles Me.FormClosed
    
    End Sub
    

  6. Добавить код к форме
    Введите следующие строки кода в процедуру обработки события Form1_FormClosed:
    ' Закроем сеанс Inventor, если он был создан при создании формы
      If _started Then
        _invApp.Quit()
      End If
     
      _invApp = Nothing
    

    Здесь вы закрываете Inventor, если значение переменной _started равно True (т.е. если сеанс Inventor был создан вашей программой, поскольку активного сеанса в момент ее старта найти не удалось).

  7. Выполнение приложения Windows Form
    Запустите выполнение приложения нажатием клавиши F5.  Если к этому моменту Inventor не был запущен, будет создан новый сеанс.

    Отлично!  Вы дошли до конца урока, насыщенного важной информацией.Вы познакомились с рядом новых тем, включая некоторые основы объектно-ориентированного программирования — что такое класс и что такое объект, получили представление об основах языка VB.NET и впервые рассмотрели важные элементы приложения для Inventor.  Мы увидели также главные классы Inventor API и увидели, как их можно использовать в коде урока 1.
Дополнительные темы

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

Чтобы справиться с проблемой высокой сложности программ, было разработано объектно-ориентированное программирование (ООП). ООП позволило совершенно по иному структурировать программный код и открыло новые возможности для компонентного представления программных систем и создания условий для многократного использования разработанного кода. 

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

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

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

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

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

Использование схемы объектной модели для поиска классов Inventor API

Изучая объектную модель Inventor API можно видеть, что многие классы Inventor API ассоциированы с основными типами документов Inventor — деталями (Part), сборками (Assembly), чертежами (Drawing).  Другие части API используются для создания элементов пользовательского интерфейса и прочих объектов, не связанных с конкретным типом документа.  Вы можете загрузить файл PDF со структурной схемой объектной модели Inventor API со страницы Центра разработки приложений (Inventor Developer Center) http://www.autodesk.com/developinventor,  где вы найдете и другие полезные материалы по Inventor API.

Схема объектной модели в графической форме отображает структуру взаимных связей классов в Inventor API.  На вершине иерархии классов располагается класс Application.  Одним из классов, который доступен из класса Application, является класс Documents.  Из него можно добраться до классов документов конкретных типов: PartDocument, AssemblyDocument и DrawingDocument.  Ниже приведен фрагмент схемы, где видна связь между классами Application, Documents и DrawingDocument.  Обратите внимание, данная иерархическая схема дает представление о том, какие классы доступны из конкретного класса, а из каких доступен он сам.

Попробуем провести аналогию между схемой объектной модели Inventor API и организационной структурой корпорации.  На вершине ее управленческой пирамиды находится президент, под ним могут быть несколько вице-президентов, у каждого из которых есть директора, руководители отделов и еще ниже — сотрудники и т.д.  В терминах Inventor API вы должны пройти президента (Application), затем вице-президента (Documents) и далее вниз по иерархии вплоть до конкретного сотрудника (скажем, DrawingDocument), который может выполнить требуемое действие, например, сохранить документ чертежа.

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

На схеме объектной модели можно заметить, что некоторые прямоугольники имеют скругленные вершины.  Так на схеме обозначаются коллекции объектов. Обычно имена коллекций заканчиваются на “s”,что  указывает на множественное число хранимых объектов конкретного класса.  Например, коллекция Documents будет содержать один или несколько объектов типа Document.  Коллекции имеют собственные методы, например, метод Add служит для добавления в коллекцию нового объекта. Новые документы создаются методом Documents.Add().

PDF файл со схемой объектной модели Inventor API входит в состав Inventor SDK (Software Development Kit).  После установки Inventor  вы можете найти его в папке 
C:\Program Files\Autodesk\Inventor 201x\SDK\DeveloperTools\Docs

SDK входит в состав поставки Inventor в виде двух самостоятельных дистрибутивов DeveloperTools.msi и UserTools.msi, которые следует проинсталлировать вручную. DeveloperTools содержит примеры программ и утилиты для разработчиков приложений. User Tools.msi устанавливает приложения, которые представляют интерес не только для программистов, но и для конечных пользователей, поскольку автоматизируют задачи для которых пока нет адекватного функционала в пользовательском интерфейсе Inventor.

Инсталляционные файлы расположены в следующих папках на вашем жестом диске:

  • Windows XP: C:\Program Files\Autodesk\Inventor 201x\SDK\DeveloperTools.msi
  • Windows Vista or 7: C:\Users\Public\Documents\Autodesk\Inventor 201x\SDK\DeveloperTools.msi

Подробная информация о составе SDK приведена в файле
C:\Program Files\Autodesk\Inventor 201x \SDK\SDK_Readme.htm