Тема: Вставка блока через Sendcommand > fatal error.

После выбора блока из списка - UserForm.hide , после вставки блока - UserForm.show. Все работает нормально, если не вклинивается прозрачная команда '_pan при нажатии колеса мыши,
управление возвращается к коду ...UserForm.show до окончания действия команды вставки блока, как следствие acad вылетает (что интересно, зумирование тем же колесом к таким последствиям не приводит). Обошел проблему, проверяя значение CMDACTIVE (если >1 то exit sub), но как вернуть форму на экран?
Может, грамотнее использовать .InsertBlock, но в этом случае пользователь не видит силуэт вставляемого блока.

Re: Вставка блока через Sendcommand > fatal error.

Может проверку CMDACTIVE организовать как-то так:

Option Explicit
'InsertEnd = DoEvents.
'здесь InsertEnd — формальный параметр помогающий корректно вписать в код функцию DoEvents.
Public Declare Sub Sleep Lib "KERNEL32" (ByVal dwMilliseconds As Long)
Sub cmdTest()
    Dim InsertEnd As Integer
    Dim k As Integer
    On Error Resume Next
    ThisDrawing.SendCommand "_find "
    Do
        InsertEnd = DoEvents
        Sleep 100 'pause 0.1 sec
        k = ThisDrawing.GetVariable("CMDACTIVE")
    Loop While (k > 0)
    MsgBox "Exit successful!"
End Sub

Хотя я все равно не понимаю, как у тебя получается:"после вставки блока — UserForm.show"?

Re: Вставка блока через Sendcommand > fatal error.

У меня было что-то вроде этого:

Private Sub CommandButton3_Click()
...
  Dim varCMDACTIVE As Variant
  UserForm1.Hide
  SendCommand (name)
  varCMDACTIVE = ThisDrawing.GetVariable("CMDACTIVE")
  If varCMDACTIVE <> 0 Then Exit Sub
  UserForm1.Show Fmodal
End Sub
....
Sub SendCommand(str as string )
 Select Case ComboBox19.Value
     Case "Указать на чертеже"
         ThisDrawing.SendCommand "._-insert" & vbCr & str & vbCr _
                                & "Масштаб" & vbCr & "1" & vbCr
     Case Else
         ThisDrawing.SendCommand "._-insert" & vbCr & str & vbCr _
                                 & "Масштаб" & vbCr & "1" & vbCr _
                                 & "ПОворот" & vbCr & ComboBox19.Value & vbCr
 End Select
End Sub

(Acad русский, программа для себя и коллег по отделу)
Если организовать проверку CMDACTIVE в цикле Do...While, программа просто виснет.

Re: Вставка блока через Sendcommand > fatal error.

В качестве предположения - а форма модальная? Может, попробовать сделать ее немодальной?
P.S. Как удерживать фокус внутри формы - не спрашивайте, не знаю.

Re: Вставка блока через Sendcommand > fatal error.

Модальная или немодальная - программа ведет себя одинаково.(Модальность меняется в зависимости от нажатия кнопки на форме). Вобщем-то, форма в случае

If varCMDACTIVE <> 0 Then Exit Sub

в памяти сохраняется, и нажатие на кнопку с макросом выводит ее на экран в том же состоянии, что было в момент .hide.
Но интересно, почему зумирование не влияет на работу программы, а панорамирование приводит к выходу из Sub SendCommand(str)?

Re: Вставка блока через Sendcommand > fatal error.

Попробовал такой вариант:

Private Sub AcadDocument_EndCommand(ByVal CommandName As String)
If Prov_End_Command = 1 Then
   UserForm1.Show
End If
End Sub

Prov_End_Command объявил глобальной переменной, перед UserForm1.Hide присваиваю ей "1", перед
UserForm1.Show - "0". Только "Option Explicit" для AcadDocument пришлось убрать, иначе при неактивном макросе любая команда Acadа будет приводить к ошибке.
Вроде работает, хотя, чую, глючное решение.

Re: Вставка блока через Sendcommand > fatal error.

Не знаю почему, но у меня все и без проверок работает. Даю ссылку на архив с .frm и .frx, посмотрите. Внешние по отношению к форме библиотеки, понятно, обрублены.
http://webfile.ru/1628467

Re: Вставка блока через Sendcommand > fatal error.

P.S. Смотреть CommandButton3.

Re: Вставка блока через Sendcommand > fatal error.

> Александр Бауск
Но вы в своем примере SendCommand и не используете, там у вас .InsertBlock, а я уже писал, что хотелось бы видеть при вставке на курсоре силуэт блока.

Re: Вставка блока через Sendcommand > fatal error.

> AlexV
Попробуй так

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
     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 > fatal error.

Fatty (2007-12-06 01:51:04)

UserForm1.Hide
InsertWithGhostImage
UserForm1.Show

Ну, от fatal error ваш код избавляет, но все равно нажатие колеса мыши во время вставки блока приводит к возвращению формы на экран до завершения ._-insert.

Re: Вставка блока через Sendcommand > fatal error.

> AlexV
Проверил еще раз и из модуля формы из
редактора и из скомпилированного проекта
Работает с колесом тоже.
Может корявый Автокад?
~'J'~

Re: Вставка блока через Sendcommand > fatal error.

> Fatty
... "вопросы функционирования "корявого" ПО на данном форуме не обсуждаются";) Никаких корявостей до данного момента не замечал, Acad работает как часы. В принципе, если форму сделать немодальной, то пример работает, форма на экране (после PAN колесом) появляется до завершения ._-insert, но ввиду своей "немодальности" позволяет завершить вставку блока.

Re: Вставка блока через Sendcommand > fatal error.

> AlexV
Я так и думал, что дело в форме
~'J'~

Re: Вставка блока через Sendcommand > fatal error.

> Кулик Алексей aka kpblc
При немодальной форме Acad вылетал, если до окончания SendCommand произвести какие-либо манипуляции с объектами формы. Скопировал кое-что из кода Fatty, и проблема решилась.

Re: Вставка блока через Sendcommand > fatal error.

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

Re: Вставка блока через Sendcommand > fatal error.

Установить ATTREQ в 0

Re: Вставка блока через Sendcommand > fatal error.

Ага спасибо! не знал про такую переменную.

Re: Вставка блока через Sendcommand > fatal error.

А как прописать в аттрибут свое значение до вставки?

Re: Вставка блока через Sendcommand > fatal error.

Сделал так: вычислил последний вставленный объект и в нем исправил.

Dim varAttributes As Variant
Dim count As Integer
count = ThisDrawing.ModelSpace.count
ReDim ACADObject(count) As AcadEntity
Set ACADObject(count) = ThisDrawing.ModelSpace.Item(count - 1)
varAttributes = ACADObject(count).GetAttributes
varAttributes(0).TextString = TextBox1.value

Будет стабильно работать? или возможен путь попроще?
Еще такой вопрос: Если всталяем блок через Sendcommand, угол при этом указывается на чертеже, как значение этого угла получить?

Re: Вставка блока через Sendcommand > fatal error.

блин, я по-моему сам же на свой вопрос и ответил... Лучше такой вопрос:
При установке через Sendcommand виден силуэт. Этот силуэт всегда отображается с поворотом 0 градусов. Как сделать так, чтоб я на форме задал угол и при вставке силуэт был повернут на этот угол?

Re: Вставка блока через Sendcommand > fatal error.

Я использую такую процедуру:

Sub SendCommand(str)
  Select Case ComboBox19.value
     Case "Указать"
         ThisDrawing.SendCommand "._-insert" & vbCr & str & vbCr & "Масштаб" & vbCr & "1" & vbCr
    Case Else
       ThisDrawing.SendCommand "._-insert" & vbCr & str & vbCr & "Масштаб" & vbCr & "1" & vbCr & "ПОворот" & vbCr & ComboBox19.value & vbCr
  End Select
Prov_End_Command = 0
End Sub

Имя блока передается в str, угол поворота- ComboBox19.value
Если значение ComboBox19 - "Указать", то угол запрашивается при вставке, в остальных случаях блок висит на курсоре уже повернутый на нужный угол. В английском Acadе, ессно, ключевые слова
"Масштаб" и т.д. д.б. на англицком.

Re: Вставка блока через Sendcommand > fatal error.

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

InsertCommand = "(command " & _
        Chr(34) & "._-insert" & Chr(34) & _
        vbCr & Chr(34) & BlockName & Chr(34) & _
        Chr(34) & "PScale" & Chr(34) & vbCr & Chr(34) & BlockScale & Chr(34) & _
        " pause" & vbCr & _
        Chr(34) & BlockScale & Chr(34) & vbCr & _
        Chr(34) & BlockScale & Chr(34) & _
         ")"
ThisDrawing.SendCommand InsertCommand & vbCr

Т.е. в момент выполнения ThisDrawing.SendCommand, ожидается указание точки вставки (работает pause), при нажатии на среднюю кнопку программа, видимо, считает, что строка ThisDrawing.SendCommand выполнилась и идет дальше...
Как сделать, чтоб параномирование не влиял на ThisDrawing.SendCommand?

Re: Вставка блока через Sendcommand > fatal error.

Me.Hide
Избавляемся от ошибки и открытия формы до вставки блока.
Dim count As Integer
count = ThisDrawing.ModelSpace.count - 1
Set blk = ThisDrawing.ModelSpace.Item(count)
HandleBlock = blk.Handle
vst:
   ThisDrawing.SendCommand "._-insert" & vbCr & blkname & vbCr & "Масштаб" & vbCr & "1" & vbCr & "Поворот" & vbCr & 0 & vbCr
'находим handle последнего вставленного блока
    count = ThisDrawing.ModelSpace.count - 1
    Set blk = ThisDrawing.ModelSpace.Item(count)
    If blk.Handle = HandleBlock Then
       SendKeys "{ESC}"
       Me.Hide
       GoTo vst
    Else
       MsgBox "Блок вставлен"
    End If
Me.Show