Тема: SendCommand для динамической вставки блоков + обработка

Для юзверей очень нужно было отображать вставку блоков динамически, как из самого автокада. Методом InsertBlock добиться отображения при вставке не получилось никак :(
А с SendCommand'ом творились просто ужасные вещи. Проект уже к атрибутам обращается, а блок еще не вставлен и т.п. ...
В итоге функция получилась корявая, но она РАБОТАЕТ и при этом возвращает AcadBlockReference )))
Теперь очень бы хотелось узнать, как грамотно выйти из функции по нажатию “Esc”.)
И как можно оптимизировать процесс?

Function DrawBlockRef(entBlock As AcadBlock) As AcadBlockReference
With ThisDrawing
[i]'   рисуем вхождение блока
'   методом посыла строковых команд прямо в автокад,
'   т.к. в этом случае вхождение блока отображается динамически на экране
'перед этим вставим в пространство модели "контрольную точку"
'для обхода сбоев в работе SendCommand [/i]
Dim tPoint As AcadPoint
Dim ip(2) As Double
ip(0) = 0: ip(1) = 0: ip(2) = 0
Set tPoint = .ModelSpace.AddPoint(ip)
[i]'теперь рисуем сам блок при помощи SendCommand[/i]
LetsDoItAgain:
ThisDrawing.SendCommand _
    "-i" & vbCr & _
    entBlock.Name & vbCr & _
    "S" & vbCr & _
      1 & vbCr & _
    "R" & vbCr & _
    "0" & vbCr
[i]'проверяем выполнение процедуры SendCommand
'Если блок еще не вставлен, то отправляем команды снова
'Если блок вставлен - удаляем "контрольную точку" и идем дальше[/i]
If .ModelSpace(.ModelSpace.Count - 1).ObjectName = "AcDbPoint" Then
    GoTo LetsDoItAgain
Else
    .ModelSpace(.ModelSpace.Count - 2).Delete
End If
Update
[i]'запишем вхождение блока, которое сейчас вставили
'в переменную для возврата функции[/i]
Dim tblref As AcadBlockReference
Set tblref = .ModelSpace(.ModelSpace.Count - 1)
[i]'возвращаем значение[/i]
Set DrawBlockRef = tblref
End With
End Function

Re: SendCommand для динамической вставки блоков + обработка

На лиспе интересует вариант решения?

Re: SendCommand для динамической вставки блоков + обработка

Попробуй так:

Function DrawBlockRef(entBlock As AcadBlock) As AcadBlockReference
With ThisDrawing
Dim tPoint As AcadPoint
Dim ip(2) As Double
ip(0) = 0: ip(1) = 0: ip(2) = 0
Set tPoint = .ModelSpace.AddPoint(ip)
ThisDrawing.SendCommand _
    "-i" & vbCr & _
    entBlock.Name & vbCr & _
    "S" & vbCr & _
      1 & vbCr & _
    "R" & vbCr & _
    "0" & vbCr
[b]
Do While .GetVariable("CMDACTIVE") <> 0
Loop
[/b]
Dim tblref As AcadBlockReference
If .ModelSpace(.ModelSpace.Count - 1).ObjectName = "AcDbPoint" Then
   .ModelSpace(.ModelSpace.Count - 1).Delete
Else
   .ModelSpace(.ModelSpace.Count - 2).Delete
   Set tblref = .ModelSpace(.ModelSpace.Count - 1)
   Set DrawBlockRef = tblref
End If
Update
End With
End Function

Re: SendCommand для динамической вставки блоков + обработка

> StudentCM
Чистый VBA не имеет методов реализации отображения
блока при вставке, одно из решений - применение
функций Автолиспа как в этом случае,
поэтому нужно придерживаться правил чужого
монастыря, то бишь Автолиспа, а проще сказать
манипулировать системными переменными, чтобы
у метода SendCommand было меньше поводов
глючить
(Не забудь включить кнопку в Опциях: Break on Unhandled Errors)
Как пример (хотя и не идеальный тоже):

Option Explicit
'~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~'
Function IsBlockExist(bName As String) As Boolean
   Dim oBlock As AcadBlock
   IsBlockExist = False
   For Each oBlock In ThisDrawing.Blocks
   If StrComp(oBlock.Name, bName, vbTextCompare) = 0 Then
   IsBlockExist = True
   End If
   Next
End Function
'~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~'
Function IsLayerExist(lName As String) As Boolean
   Dim oLayer As AcadLayer
   IsLayerExist = False
   For Each oLayer In ThisDrawing.Layers
   If StrComp(oLayer.Name, lName, vbTextCompare) = 0 Then
   IsLayerExist = True
   End If
   Next
End Function
'~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~'
Sub InsertWithGhostImage()
     Dim blkName As String, layName As String
     Dim osm, clr, pt
     Dim strPt As String, comStr As String
     blkName = InputBox(vbCrLf & "Block name to be insert:", "Insert Block")
     If blkName = vbNullString Then Exit Sub
     If Not IsBlockExist(blkName) Then
     MsgBox "Block " & Chr(34) & blkName & Chr(34) & " does not exist"
     Exit Sub
     End If
     layName = InputBox(vbCrLf & "Layer name to insert block on:", "Insert Block", "0")
     If Not IsLayerExist(layName) Then
     MsgBox "Layer " & Chr(34) & layName & Chr(34) & " does not exist"
     Exit Sub
     End If
     With ThisDrawing
          On Error GoTo Err_Control
          osm = .GetVariable("OSMODE")
          clr = .GetVariable("CLAYER")
          .Utility.Prompt vbCrLf & "   Specify insertion point of block  >>"
          .SetVariable "CLAYER", layName     '<-- layer name you need
          .SetVariable "EXPERT", 2     '<-- suppress any prompts in the command line
          .SetVariable "FILEDIA", 0     '<-- suppress display file dialog box if block is drawing
          .SetVariable "ATTDIA", 0     '<-- suppress attribute dialog
          .SetVariable "ATTREQ", 0     '<-- suppress prompt to verify attribute value
          .SetVariable "OSMODE", 0     '<-- turn snap mode off
          .SetVariable "CMDECHO", 0     '<-- suppress command echo
          comStr = "(command " & _
                   Chr(34) & "._-insert" & Chr(34) & _
                   vbCr & Chr(34) & blkName & _
                   Chr(34) & " pause" & vbCr & _
                   Chr(34) & "1" & Chr(34) & _
                   vbCr & Chr(34) & "1" & Chr(34) & _
                   vbCr & Chr(34) & "0" & Chr(34) & ")"
                   .SendCommand comStr & vbCr
          DoEvents
          Dim oSpace As AcadBlock
          Dim oblkRef As AcadBlockReference
          If .ActiveSpace = acModelSpace Then
               Set oSpace = .ModelSpace
          Else
               Set oSpace = .PaperSpace
          End If
          Set oblkRef = oSpace.Item(oSpace.Count - 1)
          '///Debug.Print oblkRef.EffectiveName '/// debug only
     End With
Exit_Here:
     With ThisDrawing
          .SetVariable "CLAYER", clr
          .SetVariable "EXPERT", 0
          .SetVariable "FILEDIA", 1
          .SetVariable "ATTDIA", 1
          .SetVariable "ATTREQ", 1
          .SetVariable "OSMODE", osm
          .SetVariable "CMDECHO", 1
     End With
     Exit Sub
Err_Control:
     MsgBox Err.Description
     Resume Exit_Here
End Sub
'~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~'

~'J'~

Re: SendCommand для динамической вставки блоков + обработка

> Gogi
Попробуй так:
- - - - - - - - - - - - -
Do While .GetVariable("CMDACTIVE") <> 0
Loop

- - - - - - - - - - - - -
А сам то пробовал?
Совет рискованный...

Re: SendCommand для динамической вставки блоков + обработка

Я не спец по VBA, поэтому только общая идея: если работа только в 2Д, то вставить блок "вне зоны видимости" (системные переменные, по-моему, vsmin или vsmax), а потом применить _.change. Для работы в 3Д надо будет поступать по другому, пример приводил ShaggyDoc здесь.

Re: SendCommand для динамической вставки блоков + обработка

Fatty правильно написал, что визуализация (например, вставки блока) в VBA (и вообще объектными методами) невозможна в принципе. Это всё равно придется делать в LISP.
Но и незачем из VBA устанавливать переменные и делать прочие манипуляции. Типа послать стандартную функцию command.
Надо просто иметь отлаженную отработанную и загруженную LISP функцию, и через SendCommand посылать строку с вызовом этой функции. Разумеется, с вычисленными в VBA и подставленными значениями аргументов (например, имени блока). В том числе в отправляемой строке может быть и загрузка самой функции вставки.

Re: SendCommand для динамической вставки блоков + обработка

После тщательной проверки выяснилось, что моя функция порой дает серьезные сбои... после "взрыва" блока с его состовляющими творится чушь... либо их не выбрать (при Regen All они исчезают, но в базе чертежа все равно остаются!!) либо вообще скачут на другой слой. звучит как бред. думаю, это из-за извращений с ModelSpace'ом...
Отчаялся найти решения на VBA. ShaggyDoc, не напишите ли функцию функцию на LISP'е?

Re: SendCommand для динамической вставки блоков + обработка

> ShaggyDoc
Tем не менее работает сквозняком начиная с 2000
по 2008 включительно, мил-человек
Проверить бы надо прежде чем...
IMO
~'J'~

Re: SendCommand для динамической вставки блоков + обработка

> Fatty
Разве я написал, что код не работает? Я обращаю внимание на принцип - "лиспу - лиспово, бейсику - бейсиково".

> StudentCM
Ссылка на разные варианты прямо в этой ветке.