Сообщество программистов Autodesk в СНГ

ADN Club => AutoCAD .NET API => Тема начата: Пашин Евгений от 25-08-2015, 15:22:14

Название: Как указать рамку видовому экрану на листе область объекта
Отправлено: Пашин Евгений от 25-08-2015, 15:22:14
Как указать рамку видовому экрану на листе область объекта в пространстве модели.

То есть:
1. Имеется объект в пространстве модели (прямоугольный)
2. Создаем лист с видовым экраном
3. Видовой экран настраиваем так, чтобы рамки видового экрана "обжимали" объект из пространства модели!

Должно получиться как-то так:

(https://adn-cis.org/forum/proxy.php?request=http%3A%2F%2Fs15.postimg.org%2Feg8n024rr%2Fimage.jpg&hash=78a80a9b25a845d6a44e6eaa571b2507) (http://postimg.org/image/eg8n024rr/)

Код - vb.net [Выбрать]
  1. Imports System.Runtime.InteropServices
  2. Imports Autodesk.AutoCAD.Runtime
  3. Imports Autodesk.AutoCAD.ApplicationServices
  4. Imports Autodesk.AutoCAD.DatabaseServices
  5. Imports Autodesk.AutoCAD.Geometry
  6.  
  7. Public Class CreateVP
  8.  
  9.     <DllImport("acad.exe", CallingConvention:=CallingConvention.Cdecl, _
  10.     EntryPoint:="?acedSetCurrentVPort@@YA?AW4ErrorStatus@Acad@@PBVAcDbViewport@@@Z")> _
  11.     Public Shared Function acedSetCurrentVPort(ByVal AcDbVport As IntPtr) As IntPtr
  12.     End Function
  13.     <CommandMethod("CreateFloatingViewport")> _
  14.     Public Sub CreateFloatingViewport()
  15.         '' Get the current document and database, and start a transaction
  16.         Dim acDoc As Document = Application.DocumentManager.MdiActiveDocument
  17.         Dim acCurDb As Database = acDoc.Database
  18.         Using acTrans As Transaction = acCurDb.TransactionManager.StartTransaction()
  19.             '' Open the Block table for read
  20.             Dim acBlkTbl As BlockTable
  21.             acBlkTbl = acTrans.GetObject(acCurDb.BlockTableId, _
  22.                                               OpenMode.ForRead)
  23.             '' Open the Block table record Paper space for write
  24.             Dim acBlkTblRec As BlockTableRecord
  25.             acBlkTblRec = acTrans.GetObject(acBlkTbl(BlockTableRecord.PaperSpace), _
  26.                                                  OpenMode.ForWrite)
  27.             '' Switch to the previous Paper space layout
  28.             Application.SetSystemVariable("TILEMODE", 0)
  29.  
  30.             acDoc.Editor.SwitchToPaperSpace()
  31.             '' Create a Viewport
  32.             Dim acVport As Viewport = New Viewport()
  33.             acVport.SetDatabaseDefaults()
  34.             acVport.CenterPoint = New Point3d(3.25, 3, 0)
  35.             acVport.Width = 6
  36.             acVport.Height = 5
  37.             '' Add the new object to the block table record and the transaction
  38.             acBlkTblRec.AppendEntity(acVport)
  39.             acTrans.AddNewlyCreatedDBObject(acVport, True)
  40.             '' Change the view direction
  41.             acVport.ViewDirection = New Vector3d(1, 1, 1)
  42.             '' Enable the viewport
  43.             acVport.On = True
  44.             '' Activate model space in the viewport
  45.             acDoc.Editor.SwitchToModelSpace()
  46.             '' Set the new viewport current via an imported ObjectARX function
  47.             acedSetCurrentVPort(acVport.UnmanagedObject)
  48.             '' Save the new objects to the database
  49.             acTrans.Commit()
  50.         End Using
  51.     End Sub
  52. End Class

Есть такой вот пример создания видового экрана, но я не понимаю как этот код работает! Вернее даже сказать - ОН У МЕНЯ НЕ СРАБОТАЛ!

Может кто-нибудь подсказать более изящное решение?
Название: Re: Как указать рамку видовому экрану на листе область объекта
Отправлено: Александр Ривилис от 25-08-2015, 15:40:38
1. Всегда указывай ссылку на то место, где берёшь код
2. Этот код похоже написан для AutoCAD 2012 или более раннего и x86. Тебе же как я понимаю нужен для x64 и 2014...2016
Замени строки:
Код - vb.net [Выбрать]
  1. <DllImport("acad.exe", CallingConvention:=CallingConvention.Cdecl, _
  2. EntryPoint:="?acedSetCurrentVPort@@YA?AW4ErrorStatus@Acad@@PBVAcDbViewport@@@Z")> _
на
Код - vb.net [Выбрать]
  1. <DllImport("accore.dll", CallingConvention:=CallingConvention.Cdecl, _
  2. EntryPoint:="?acedSetCurrentVPort@@YA?AW4ErrorStatus@Acad@@PEBVAcDbViewport@@@Z")> _
Сам код я не смотрел.
Название: Re: Как указать рамку видовому экрану на листе область объекта
Отправлено: Пашин Евгений от 25-08-2015, 15:47:27
Код - vb.net [Выбрать]
  1. <DllImport("accore.dll", CallingConvention:=CallingConvention.Cdecl, _
  2. EntryPoint:="?acedSetCurrentVPort@@YA?AW4ErrorStatus@Acad@@PEBVAcDbViewport@@@Z")> _

Хотел бы я узнать, а что это вообще за фигня такая?
Название: Re: Как указать рамку видовому экрану на листе область объекта
Отправлено: Пашин Евгений от 25-08-2015, 15:49:52
Та же самая ошибка

(https://adn-cis.org/forum/proxy.php?request=http%3A%2F%2Fs29.postimg.org%2Fv5o3b36fn%2Fimage.jpg&hash=fe35d70eb90fa776616ba9c551ecf57b) (http://postimg.org/image/v5o3b36fn/)

Я даже не пытаюсь понять этот код и эту ошибку - от одного его вида хочется сбежать...
Название: Re: Как указать рамку видовому экрану на листе область объекта
Отправлено: Александр Ривилис от 25-08-2015, 15:50:24
Хотел бы я узнать, а что это вообще за фигня такая?
Это тебе еще учиться и учиться. В .NET это называется P/Invoke: https://msdn.microsoft.com/ru-ru/library/eyzhw3s8%28v=vs.120%29.aspx
Название: Re: Как указать рамку видовому экрану на листе область объекта
Отправлено: Пашин Евгений от 25-08-2015, 15:52:55
Застрелиться от этого можно! Можно по-человечески (тьфу ты, по-ламерски) объяснить что-то это значит?
Название: Re: Как указать рамку видовому экрану на листе область объекта
Отправлено: Александр Ривилис от 25-08-2015, 15:54:26
Можно по-человечески (тьфу ты, по-ламерски) объяснить что-то это значит?
Это вызов из .NET функций, находящихся в dll/exe-файлах и написанных с использованием неуправляемого кода (обычно на C/C++)
Название: Re: Как указать рамку видовому экрану на листе область объекта
Отправлено: Владимир Шу от 25-08-2015, 16:17:39
Может кто-нибудь подсказать более изящное решение?
Этот код писал давно и знаний тогда было маловато, но вдруг поможет.
тут больше подробностей: http://experement.spb.ru/wiki/doku.php?id=vport_pp (http://experement.spb.ru/wiki/doku.php?id=vport_pp)

Извините, вам запрещён просмотр содержимого спойлеров.
Название: Re: Как указать рамку видовому экрану на листе область объекта
Отправлено: Пашин Евгений от 25-08-2015, 16:40:12
Код - vb.net [Выбрать]
  1. Это вызов из .NET функций, находящихся в dll/exe-файлах и написанных с использованием неуправляемого кода (обычно на C/C++)

Как я это понял: Я подключаюсь к библиотеке динамически (сама она не NET), вызываю из нее функцию! Верно? Что может быть причиной ошибки, если все хорошо? Я же просто скопировал пример отсюда:
http://docs.autodesk.com/ACD/2011/ESP/filesMDG/WS1a9193826455f5ff2566ffd511ff6f8c7ca-343a.htm
Название: Re: Как указать рамку видовому экрану на листе область объекта
Отправлено: Александр Ривилис от 25-08-2015, 16:56:32
Я подключаюсь к библиотеке динамически (сама она не NET), вызываю из нее функцию! Верно?
Да.
Что может быть причиной ошибки, если все хорошо?
Во-первых, код был написан, как я уже писал под AutoCAD версии <= 2012, во вторых, под x86.
Уточни версию и разрядность AutoCAD, под которыми ты проверяешь.
Название: Re: Как указать рамку видовому экрану на листе область объекта
Отправлено: Александр Ривилис от 25-08-2015, 17:23:33
Что-то подобное описано здесь: http://www.theswamp.org/index.php?topic=47761.0
Посмотри и попробуй.
Название: Re: Как указать рамку видовому экрану на листе область объекта
Отправлено: Windcastle от 25-08-2015, 19:57:42
Уточни версию и разрядность AutoCAD, под которыми ты проверяешь.

1. На работе - AutoCAD 2014 (x64) - Windows 8.1 (x64)
    Виртуальная машина №1 - AutoCAD 2014 (x64) - Windows XP (x64)
    Виртуальная машина №2 - AutoCAD Electrical 2014 (x32) - Windows XP (x32)
    Виртуальная машина №3 - AutoCAD Civil3D 2014 (x64) - Windows 8.1 (x64)

2. Дома - AutoCAD 2016 (x64) - Windows 7 Professional (x64)

Что-то подобное описано здесь: http://www.theswamp.org/index.php?topic=47761.0

Да, здесь те же проблемы...
Название: Re: Как указать рамку видовому экрану на листе область объекта
Отправлено: Александр Ривилис от 25-08-2015, 21:04:09
Только что проверил этот код:
Код - vb.net [Выбрать]
  1. Imports System
  2. Imports System.Runtime.InteropServices
  3. Imports Autodesk.AutoCAD.Runtime
  4. Imports Autodesk.AutoCAD.ApplicationServices
  5. Imports Autodesk.AutoCAD.DatabaseServices
  6. Imports Autodesk.AutoCAD.Geometry
  7. Imports Autodesk.AutoCAD.EditorInput
  8.  
  9. <Assembly: CommandClass(GetType(Rivilis.CreateViewport))>
  10. Namespace Rivilis
  11.     Public Class CreateViewport
  12.         <DllImport("accore.dll", CallingConvention:=CallingConvention.Cdecl, _
  13.         EntryPoint:="?acedSetCurrentVPort@@YA?AW4ErrorStatus@Acad@@PBVAcDbViewport@@@Z")> _
  14.         Public Shared Function acedSetCurrentVPort32(ByVal AcDbVport As IntPtr) As IntPtr
  15.         End Function
  16.         <DllImport("accore.dll", CallingConvention:=CallingConvention.Cdecl, _
  17.         EntryPoint:="?acedSetCurrentVPort@@YA?AW4ErrorStatus@Acad@@PEBVAcDbViewport@@@Z")> _
  18.         Public Shared Function acedSetCurrentVPort64(ByVal AcDbVport As IntPtr) As IntPtr
  19.         End Function
  20.         Public Function acedSetCurrentVPort(ByVal vport As IntPtr) As IntPtr
  21.             If (IntPtr.Size = 4) Then
  22.                 Return acedSetCurrentVPort32(vport)
  23.             Else
  24.                 Return acedSetCurrentVPort64(vport)
  25.             End If
  26.         End Function
  27.  
  28.         <CommandMethod("CreateVP")> _
  29.         Public Sub CreateFloatingViewport()
  30.             '' Get the current document and database, and start a transaction
  31.             Dim acDoc As Document = Application.DocumentManager.MdiActiveDocument
  32.             Dim acCurDb As Database = acDoc.Database
  33.             Using acTrans As Transaction = acCurDb.TransactionManager.StartTransaction()
  34.                 '' Open the Block table for read
  35.                 Dim acBlkTbl As BlockTable
  36.                 acBlkTbl = acTrans.GetObject(acCurDb.BlockTableId, _
  37.                                                   OpenMode.ForRead)
  38.                 '' Open the Block table record Paper space for write
  39.                 Dim acBlkTblRec As BlockTableRecord
  40.                 acBlkTblRec = acTrans.GetObject(acBlkTbl(BlockTableRecord.PaperSpace), _
  41.                                                      OpenMode.ForWrite)
  42.                 '' Switch to the previous Paper space layout
  43.                 Application.SetSystemVariable("TILEMODE", 0)
  44.  
  45.                 acDoc.Editor.SwitchToPaperSpace()
  46.                 '' Create a Viewport
  47.                 Dim vp As Viewport = New Viewport()
  48.                 vp.SetDatabaseDefaults()
  49.                 vp.CenterPoint = New Point3d(50, 50, 0)
  50.                 vp.Width = 100
  51.                 vp.Height = 100
  52.                 '' Add the new object to the block table record and the transaction
  53.                 acBlkTblRec.AppendEntity(vp)
  54.                 acTrans.AddNewlyCreatedDBObject(vp, True)
  55.                 '' Change the view direction
  56.                 vp.ViewDirection = New Vector3d(0, 0, 1)
  57.                 '' Enable the viewport
  58.                 vp.On = True
  59.                 '' Activate model space in the viewport
  60.                 acDoc.Editor.SwitchToModelSpace()
  61.                 '' Set the new viewport current via an imported ObjectARX function
  62.                 acedSetCurrentVPort(vp.UnmanagedObject)
  63.                 '' Save the new objects to the database
  64.                 Dim mScrRatio As Double
  65.                 mScrRatio = (vp.Width / vp.Height)
  66.  
  67.                 Dim mMaxExt As Point3d : mMaxExt = acCurDb.Extmax
  68.                 Dim mMinExt As Point3d : mMinExt = acCurDb.Extmin
  69.  
  70.                 Dim mExtents As Extents3d = New Extents3d()
  71.                 mExtents.Set(mMinExt, mMaxExt)
  72.                 '' prepare Matrix for DCS to WCS transformation
  73.  
  74.                 Dim matWCS2DCS As Matrix3d
  75.  
  76.                 matWCS2DCS = Matrix3d.PlaneToWorld(vp.ViewDirection)
  77.  
  78.                 matWCS2DCS = Matrix3d.Displacement(vp.ViewTarget - Point3d.Origin) * matWCS2DCS
  79.  
  80.                 matWCS2DCS = Matrix3d.Rotation(-vp.TwistAngle, vp.ViewDirection, vp.ViewTarget) * matWCS2DCS
  81.  
  82.                 matWCS2DCS = matWCS2DCS.Inverse()
  83.                 '' tranform the extents to the DCS
  84.                 '' defined by the viewdir
  85.  
  86.                 mExtents.TransformBy(matWCS2DCS)
  87.  
  88.                 '' width of the extents in current view
  89.  
  90.                 Dim mWidth As Double
  91.  
  92.                 mWidth = (mExtents.MaxPoint.X - mExtents.MinPoint.X)
  93.  
  94.                 '' height of the extents in current view
  95.  
  96.                 Dim mHeight As Double
  97.  
  98.                 mHeight = (mExtents.MaxPoint.Y - mExtents.MinPoint.Y)
  99.  
  100.  
  101.                 '' get the view center point
  102.                 Dim mCentPt As Point2d
  103.  
  104.  
  105.                 mCentPt = New Point2d( _
  106.                    ((mExtents.MaxPoint.X + mExtents.MinPoint.X) * 0.5), _
  107.                    ((mExtents.MaxPoint.Y + mExtents.MinPoint.Y) * 0.5) _
  108.                  )
  109.  
  110.                 '' check if the width 'fits' in current window,
  111.                 '' if not then get the new height as
  112.                 '' per the viewports aspect ratio
  113.                 If (mWidth > (mHeight * mScrRatio)) Then
  114.                     mHeight = mWidth / mScrRatio
  115.                 End If
  116.  
  117.  
  118.                 '' set the viewport parameters
  119.  
  120.                 vp.UpgradeOpen()
  121.  
  122.                 '' set the view height - adjusted by 1%
  123.  
  124.                 vp.ViewHeight = mHeight * 1.01
  125.  
  126.                 '' set the view center
  127.  
  128.                 vp.ViewCenter = mCentPt
  129.  
  130.                 vp.Visible = True
  131.                 vp.On = True
  132.                 vp.UpdateDisplay()
  133.                 acDoc.Editor.SwitchToModelSpace()
  134.                 Application.SetSystemVariable("CVPORT", vp.Number)
  135.                 acTrans.Commit()
  136.             End Using
  137.         End Sub
  138.     End Class
  139.  
  140. End Namespace

Работает в AutoCAD 2014...2016 x64. Должен работать и в 2014...2016 x86

Вот видео:


Никаких ошибок, как у тебя на картинке не даёт.
Название: Re: Как указать рамку видовому экрану на листе область объекта
Отправлено: Пашин Евгений от 26-08-2015, 08:33:15
Да, это то, что надо! Обязательно испробую!

Подскажите, чем видео-презентации пишете? Чтобы по-возможности я мог тоже самое делать. Autodesk ScreenCAST?
Название: Re: Как указать рамку видовому экрану на листе область объекта
Отправлено: Александр Ривилис от 26-08-2015, 11:47:37
Подскажите, чем видео-презентации пишете? Чтобы по-возможности я мог тоже самое делать. Autodesk ScreenCAST?
Да. Прочитай у меня в подписи Добавление Autodesk Screencast видео в сообщение на форуме (http://adn-cis.org/forum/index.php?topic=2813)
Название: Re: Как указать рамку видовому экрану на листе область объекта
Отправлено: Windcastle от 28-08-2015, 19:22:34
Подскажите для чего нужно указывать непонятную строку
EntryPoint:="?acedSetCurrentVPort@@YA?AW4ErrorStatus@Acad@@PBVAcDbViewport@@@Z"
при обращении к библиотеке ?
Что она означает? Можно ли обходить стороной ее использование?
Название: Re: Как указать рамку видовому экрану на листе область объекта
Отправлено: Александр Ривилис от 28-08-2015, 20:26:24
Начни с этой статьи: http://adn-cis.org/vnutrennie-imena-funkczij-v-utilite-dependencywalker.html
Можно ли обходить стороной ее использование?
Нет.
Название: Re: Как указать рамку видовому экрану на листе область объекта
Отправлено: Windcastle от 28-08-2015, 20:36:49
О боже...  :o
Мне что еще и C++ изучать надо?
Название: Re: Как указать рамку видовому экрану на листе область объекта
Отправлено: Александр Ривилис от 28-08-2015, 21:15:14
Мне что еще и C++ изучать надо?
Зачем? За тебя уже всё сделали. Кстати C++ и C# очень родственные языки. Они даже ближе чем VBA и VB.NET
Название: Re: Как указать рамку видовому экрану на листе область объекта
Отправлено: Windcastle от 28-08-2015, 21:24:43
Надо на чем-то остановиться. Попробую просто с чтения C#... если пойму, что прет, тогда разовью это направление. Если нет, тогда буду развивать то, что уже умею.