Реклама i
Стань нашим партнером - зарабатывай с нами!
| Правила | Регистрация | Пользователи | Сообщения за день |  Справка по форуму | Файлообменник |

Вернуться   Форум DWG.RU > Программное обеспечение > Программирование > .NET > .NET, Как передать массив в метод COM объекта?

.NET, Как передать массив в метод COM объекта?

Ответ
Поиск в этой теме
Непрочитано 17.05.2011, 13:37
.NET, Как передать массив в метод COM объекта?
RomanZonta
 
Регистрация: 25.01.2011
Сообщений: 14

Здравствуйте.

Пишу утилиту на VB.NET для Autocad для построения протяжки (EXTRUDE) по заданным параметрам. Использую позднее связывание (без подключения библиотек Autocad).
Пытаюсь использовать метод AddSolid, но этот метод требует в качестве сечения регион.
Пытаюсь создать регион:

Код:
[Выделить все]
     Public Sub drawIBeam(ByVal blockObjRef As Object, _
                         ByVal beamHeight As Single, _
                         ByVal beamCapWidth As Single, _
                         ByVal beamCapThickness As Single, _
                         ByVal beamWall As Single)
        Dim ACad As Object
        Dim ADoc As Object
        Dim MoSpace As Object
        ACad = GetObject(, "AutoCAD.Application")
        ADoc = ACad.ActiveDocument
        MoSpace = ADoc.ModelSpace

        Dim buf As Object
        Dim lines(0 To 3) As Object

        lines(0) = drawLineInObject(blockObjRef, -beamCapWidth / 2, 0, beamCapWidth, 0, "Base lines")
        lines(1) = drawLineInObject(blockObjRef, -beamCapWidth / 2, 0, 0, beamCapThickness, "Base lines")
        lines(2) = drawLineInObject(blockObjRef, beamCapWidth / 2, 0, 0, beamCapThickness, "Base linesh")
        lines(3) = drawLineInObject(blockObjRef, -beamCapWidth / 2, beamCapThickness, beamCapWidth, 0, "Base lines")

        buf = blockObjRef.AddRegion(lines)

    End Sub
При этом возникает ошибка "Invalid object array" при вызове строки.

Код:
[Выделить все]
        buf = blockObjRef.AddRegion(lines)
Функция drawLineInObject рисует линию в объекте и возвращает эту линию.

Может быть, кто-нибудь знает как решить данную проблему?
Заранее благодарен за помощь.

Последний раз редактировалось RomanZonta, 30.05.2011 в 08:20.
Просмотров: 9887
 
Непрочитано 19.05.2011, 01:09
#21
Олег (jr.)

специалист по околачиванию грушевых деревьев
 
Регистрация: 14.09.2004
Pietari, Venäjä
Сообщений: 813


Цитата:
Сообщение от Pastor Посмотреть сообщение
поскольку переменная blockObjRef объявлена, как Object, а у объекта класса Object не существует метода AddRegion(). И позднее связывание здесь не при чем. Позднее связывание осуществляется, как минимум, с использованием Type.GetTypeFromProgID(), Activator.CreateInstance() и экземплярного метода InvokeMember() класса Type.
Совершенно верно
Но это все равно не катит, по-крайней мере у меня
Глянь на досуге

Код:
[Выделить все]
   Imports System.Runtime.InteropServices
Imports System.Reflection

Public Class ReflectionCommands

    Public Shared Sub TestACAD()


        Dim appProgID As String = "Autocad.Application"
        Dim fname As String = "C:\UsedFiles\newtest.dwg"
        ' Получаем ссылку на интерфейс IDispatch
        Dim AcadType As Type = Type.GetTypeFromProgID(appProgID)

        ' Запускаем Acad
        Dim AcadApp As Object = Activator.CreateInstance(AcadType)
        Dim visargs() As Object = New Object(0) {}
        visargs(0) = True
        ' Делаем видимым окно приложения
        AcadApp.GetType().InvokeMember("Visible", BindingFlags.SetProperty, Nothing, AcadApp, visargs, Nothing)
        Dim AcadDocs As Object = AcadApp.GetType().InvokeMember( _
    "Documents", BindingFlags.GetProperty, Nothing, AcadApp, Nothing)

        ' Заносим в массив параметров имя файла
        Dim args() As Object = New Object(1) {}
        args(0) = fname
        args(1) = False 'read-only=false
        ' Пробуем открыть файл
        Dim AcDoc As Object = AcadDocs.GetType.InvokeMember( _
        "Open", BindingFlags.InvokeMethod, Nothing, AcadDocs, args, Nothing)
        Dim Util As Object = New Object
        Try
            ' Получаем ссылку на активный документ
            AcDoc = AcadApp.GetType.InvokeMember( _
        "ActiveDocument", BindingFlags.GetProperty, Nothing, AcadApp, Nothing, Nothing)
            ' Получаем ссылку на объект AcadUtility
            Util = AcDoc.GetType().InvokeMember("Utility", BindingFlags.GetProperty, Nothing, AcDoc, Nothing)
            ' Получаем ссылку на объект блока модели
            Dim oSpace As Object = _
            AcDoc.GetType.InvokeMember( _
            "ModelSpace", BindingFlags.GetProperty, Nothing, AcDoc, Nothing)
            ' Получаем ссылку на объект коллекции блоков
            Dim AcBlocks As Object = AcDoc.GetType().InvokeMember("Blocks", BindingFlags.GetProperty, Nothing, AcDoc, Nothing)

            'Проверяем наличие описания блока "myblock" в коллекции блоков документа
            Dim oBlock As Object = Nothing
            Try
                oBlock = AcBlocks.GetType().InvokeMember("Item", BindingFlags.InvokeMethod, Nothing, AcBlocks, New Object() {"myblock"})
            Catch ex As Exception
                MsgBox("Block does not exist")
                Exit Sub
            End Try

            ''добавляем объект в описание блока
            drawIBeam(oBlock, 1, 2, 0.1, 0.12)

            'Сохранение документа
            Dim closeargs() As Object = New Object(1) {}
            closeargs(0) = False
            ' Под тем же именем
            closeargs(1) = fname
            ' Пробуем закрыть документ
            '        AcDoc.GetType().InvokeMember( _
            '        "Close", BindingFlags.InvokeMethod, Nothing, AcDoc, closeargs, _
            'Nothing, System.Globalization.CultureInfo.CurrentCulture, Nothing
            ' Упрощенный синтаксис
            AcDoc.GetType().InvokeMember( _
                    "Close", BindingFlags.InvokeMethod, Nothing, AcDoc, closeargs)

            ' Пробуем закрыть приложение
            AcadApp.GetType().InvokeMember( _
            "Quit", BindingFlags.InvokeMethod, Nothing, AcadApp, Nothing)
            MsgBox("Finished")

        Catch ex As Exception
            MsgBox("Reason: " & ex.Message & vbLf & "Trace: " & ex.StackTrace)

            'AcadApp.GetType().InvokeMember( _
            '"Quit", BindingFlags.InvokeMethod, Nothing, AcadApp, Nothing)
        Finally
            'Очистка мусора

            ' Уничтожение объекта AcDoc.
            releaseObject(AcDoc)
            ' Уничтожение объекта AcadDocs.
            releaseObject(AcadDocs)
            ' Уничтожение объекта AcadApp.
            releaseObject(AcadApp)
            ' Вызываем сборщик мусора для немедленной очистки памяти
            GC.WaitForPendingFinalizers()
            GC.GetTotalMemory(True)
            GC.WaitForPendingFinalizers()
            GC.GetTotalMemory(True)

            releaseObject(AcDoc)
            ' Уничтожение объекта AcadDocs.
            releaseObject(AcadDocs)
            ' Уничтожение объекта AcadApp.
            releaseObject(AcadApp)
            ' Вызываем сборщик мусора для немедленной очистки памяти
            GC.WaitForPendingFinalizers()
            GC.GetTotalMemory(True)
            GC.WaitForPendingFinalizers()
            GC.GetTotalMemory(True)

 

        End Try

    End 

    Public Shared Sub releaseObject(ByVal obj As Object)
        Try
            System.Runtime.InteropServices.Marshal.FinalReleaseComObject(obj)
            obj = Nothing
        Catch ex As Exception
            obj = Nothing
        Finally
            GC.Collect()
        End Try
    End Sub
    Public Shared Sub drawIBeam(ByVal oSpace As Object, _
                   ByVal beamHeight As Double, _
                   ByVal beamCapWidth As Double, _
                   ByVal beamCapThickness As Double, _
                   ByVal beamWall As Single)

        Dim oLines() As Object = New Object(3) {}
        Dim oLine1 As Object = drawLineInObject(oSpace, -beamCapWidth / 2, 0, beamCapWidth, 0, "Base lines")
        oLines(0) = oLine1
        Dim oLine2 As Object = drawLineInObject(oSpace, beamCapWidth / 2, 0, 0, beamCapThickness, "Base lines") ''drawLineInObject(oSpace, -beamCapWidth / 2, 0, 0, beamCapThickness, "Base lines")
        oLines(1) = oLine2
        Dim oLine3 As Object = drawLineInObject(oSpace, -beamCapWidth / 2, 0, 0, beamCapThickness, "Base lines") ''drawLineInObject(oSpace, beamCapWidth / 2, 0, 0, beamCapThickness, "Base lines")
        oLines(2) = oLine3
        Dim oLine4 As Object = drawLineInObject(oSpace, -beamCapWidth / 2, beamCapThickness, beamCapWidth, 0, "Base lines")
        oLines(3) = oLine4

        Dim reg As Object = oSpace.GetType.InvokeMember("AddRegion", BindingFlags.Public Or BindingFlags.InvokeMethod Or BindingFlags.Static, Nothing, oSpace, oLines)
        Dim regobj As Object = CType(reg, Object())(0)
    End Sub

    Public Shared Function drawLineInObject(ByVal oBlock As Object, _
                          ByVal startX As Double, _
                          ByVal startY As Double, _
                          ByVal lenghtX As Double, _
                          ByVal lenghtY As Double, _
                          ByVal layer As String) As Object

        Dim begpRef() As Double = New Double(2) {}
        Dim endpRef() As Double = New Double(2) {}


        begpRef(0) = startX
        begpRef(1) = startY
        begpRef(2) = 0.0
        endpRef(0) = begpRef(0) + lenghtX
        endpRef(1) = begpRef(1) + lenghtY
        endpRef(2) = 0.0

        Dim pts() As Object = New Object(1) {}
        pts(0) = begpRef
        pts(1) = endpRef
        Dim oLine As Object = oBlock.GetType.InvokeMember("AddLine", BindingFlags.InvokeMethod, Nothing, oBlock, pts)
        oLine.GetType.InvokeMember("Layer", BindingFlags.SetProperty, Nothing, oLine, New Object() {layer})
        oLine.GetType.InvokeMember("Update", BindingFlags.InvokeMethod, Nothing, oLine, Nothing)

        Return oLine

    End Function

End Class
Many regards,

~'J'~
Олег (jr.) вне форума  
 
Автор темы   Непрочитано 19.05.2011, 15:11
#22
RomanZonta


 
Регистрация: 25.01.2011
Сообщений: 14


Цитата:
Сообщение от Pastor Посмотреть сообщение
Продолжаю настаивать на том, что если речь идет о VB.NET, то код функции, представленной в посте №1 не может быть скомпилирован из-за наличия строчки:
Почему же тогда функция "drawLineInObject" (см. пост №3) прекрасно работает, хотя в ней указано:

Код:
[Выделить все]
 buf = blockObjRef.AddLine(begpRef, endpRef),
а переменная "blockObjRef" объявлена как "Object"?

Цитата:
Сообщение от Олег (jr.) Посмотреть сообщение
Глянь на досуге
Спасибо за код. Не работает. На строке

Код:
[Выделить все]
Dim reg As Object = oSpace.GetType.InvokeMember("AddRegion", BindingFlags.Public Or BindingFlags.InvokeMethod Or BindingFlags.Static, Nothing, oSpace, oLines)
выдает ошибку:

"Адресат вызова создал исключение."
{"Указанное число параметров не соответствует ожидаемому числу."}

Вот здесь нашел решение на Delphi похожей проблемы с передачей массива объектов.

Может кто-нибудь сможет разобраться, как это адоптировать для vb?

Вот код решения на Delphi

Код:
[Выделить все]
procedure AddOuterLoop(Hatch,outerLoop:OleVariant);
var
  dsp,earg: Integer;
  parm: TDispParams;
  s: WideString;
  e: TExcepInfo;
  rslt: OleVariant;
begin
  s:='AppendOuterLoop';
  IDispatch(Hatch).GetIDsOfNames(GUID_NULL,@s,1,0,@dsp);
  parm.cArgs:=1;
  parm.cNamedArgs:=0;
  parm.rgvarg:=@outerLoop;
  IDispatch(Hatch).Invoke(dsp,GUID_NULL,0,DISPATCH_METHOD,Parm,@rslt,@e,@earg);
  Hatch.Evaluate;
end;

procedure TestFunctions();
var
  App,MSpace: OleVariant;
  p1,p2: OleVariant;
  h:OleVariant;
  outerLoop: OleVariant;
begin
  // Получаем IAcadApplication
  App:=GetActiveOleObject('BricscadApp.AcadApplication');
  p1:=VarArrayCreate([0,2],varDouble);
  p1[0]:=0; p1[1]:=10; p1[2]:=0;
  p2:=VarArrayCreate([0,2],varDouble);
  p2[0]:=50; p2[1]:=10; p2[2]:=0;
  MSpace:=App.ActiveDocument.ModelSpace;
  // Рисуем замкнутый контур(Окружность)
  outerLoop:=VarArrayCreate([0,0],varDispatch);
  outerLoop[0]:=MSpace.AddCircle(p1,30);
  // Создаем штриховку
  h:=MSpace.AddHatch(1,'SOLID', True);
  // вызываем AppendOuterLoop и там же Evaluate
  AddOuterLoop(h,outerLoop);
end;

Последний раз редактировалось RomanZonta, 19.05.2011 в 15:25.
RomanZonta вне форума  
 
Непрочитано 19.05.2011, 19:27
#23
Pastor

это только кличка
 
Регистрация: 22.10.2006
Москва
Сообщений: 252


Цитата:
Почему же тогда функция "drawLineInObject" (см. пост №3) прекрасно работает,
Может я зря настаиваю, не зная VB.NET. Допускаю, что вызов от имени объекта типа Object какого-либо экземплярного метода, отсутствующего в классе Object, компилятор VB.NET расценивает, как попытку вызова этого метода через рефлексию и втихаря вставляет соответствующий код? В общем, я пас.
__________________
...в шее моей жилы железные, и лоб мой - медный...

Последний раз редактировалось Pastor, 19.05.2011 в 19:59.
Pastor вне форума  
 
Автор темы   Непрочитано 30.05.2011, 08:21
#24
RomanZonta


 
Регистрация: 25.01.2011
Сообщений: 14


Решено вставкой региона из внешнего файла.
Всем спасибо за помощь.
RomanZonta вне форума  
Ответ
Вернуться   Форум DWG.RU > Программное обеспечение > Программирование > .NET > .NET, Как передать массив в метод COM объекта?

Размещение рекламы


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Порекомендуйте литературу для повышения квалификации(грунты, геотехника) acid Поиск литературы, чертежей, моделей и прочих материалов 6 13.05.2015 22:14
Где написано, что Подрядчик обязан передавать исполнительную документацию ? drill_man Разное 164 15.01.2013 15:30
Какие документы должен передать подрядчик при передаче объекта незавершенного строительства заказчику. Diokles Технология и организация строительства 1 13.10.2010 17:52
Недостатки базисно-индексного метода расчета смет (например МДС-81.35.2004) ? drill_man Прочее. Отраслевые разделы 31 22.07.2010 14:52