Тема: Обработка предварительного выбора.

Доброго времени суток всем!
Подскажите, как обработать предварительный выбор в VBA.
Задача вкратце такая - необходимо, чтобы макрос сам распознавал выбран ли уже(до запуска макроса) нужный примитив или нет.
Если уже выбран:
  Работать с выбранными примитивами.
Если нет, то как обычно:
  ThisDrawing.utility.GetEntity

Re: Обработка предварительного выбора.

При запуске макроса с кнопки осуществить это чистым VBA почти невозможно.

Re: Обработка предварительного выбора.

попробовать проанализировать PickFirstSelectionSet и ActiveSelectionSet. Подробнее не скажу, увы мне, увы...

Re: Обработка предварительного выбора.

> kpblc
Внутри макроса, запущенного с кнопки, PickFirstSelectionSet всегда пустой. Проанализировать идентичность ActiveSelectionSet до и после запуска макроса изнутри этого макроса тоже нельзя.
Над этой задачей бился несколько дней и придумал таки только один более-менее удобоваримый способ узнать, - были ли выбраны объекты до запуска макроса. Больше не смог.

Re: Обработка предварительного выбора.

Чтобы узнать выбрано ли что-либо до запуска программы на VBA, можно программу VBA запускать через Lisp файл, в котором есть строки:
(if (ssget "I") (setq issel "T") (setq issel "F"))
........
(command "-vbarun" путь-к-файлу.dvb!имя-модуля  issel)
в модуле VBA:
........
isset = ThisDrawing.Utility.GetString(False)  'получить из lisp
If isset = "F" Then isselblk = False          'перед запуском не было выделения
If isset = "T" Then isselblk = True           'перед запуском было выделение

Re: Обработка предварительного выбора.

...PickFirstSelectionSet всегда пустой.

Как говорил один мой знакомый - "вот падласт". Действительно - при запуске макроса выделение с объектов снимается. А как бы было красиво.
Вобщем пока я вижу только одно решение этого вопроса. Проверять наличие предварительного выбора так, как сказал Анатолий, а далее применять ActiveSelectionSet. Код в басике поолучился такой (вроде всё работает как надо):

Sub Example_PickfirstSelectionSet()
    Dim isset As String
    isset = ThisDrawing.Utility.GetString(False)   'получить из lisp
    'проверим наличие предварительного выбора
    If isset = "T" Then
        Dim pfSS As AcadSelectionSet
        Dim ssobject As AcadEntity
        Dim msg As String
        msg = vbCrLf
        'пролистаем набор выделенных примитивов
        Set pfSS = ThisDrawing.ActiveSelectionSet
        For Each ssobject In pfSS
            msg = msg & vbCrLf & ssobject.ObjectName
        Next ssobject
        MsgBox "The Pickfirst selection set contains: " & msg
    End If
End Sub

Спасибо, вы все мне очень помогли!

Re: Обработка предварительного выбора.

> Гонтарски
Если обходиться без лиспа, то как вариант:
1. Вешаем на кнопку команду использующую PFSS (например _stretch ^C^C-vbarun MacroName)
2. Пишем Event на запуск команды _stretch, который создает и заполняет именованный SelectionSet в случае, если PFSS при запуске этой команды не пустой (в events-ах PFSS, к счастью, таки виден)
3. В основной программе используем этот именованный SelectionSet как PFSS, - если пустой, значит не было предварительного выбора, если не пустой - был.
Побочные действия: при обычном вызове _stretch в чертеже будет создаваться и заполняться некий SelectionSet. Но этого никто не увидит:)
Не так красиво, зато принципиально без лиспа!:)

Re: Обработка предварительного выбора.

Просмотрев весь форум по данной теме, к сожалению так ни чего приемлемого
для своих целей и не нашёл. Поэтому пошёл своим путём. А то что получилось
предлагаю на суд професионалов.
Данный метод имеет следующие преимущества:
-позволяет, в момент загрузки VBA приложения, запускать необходимый
макрос, для инициализации всех необходимых параметров.(Тоже что
делает файл acad.dvb с макросом AcadStartup, только к именам вы не
как не привязаны.)
-позволяет запускать необходимый код, в работу, непосредственно по
вашим собственным командам, без всяких загрузок макросов.
-позволяет работать напрямую с набором PickfirstSelectionSet и определяет
былли выбор в ActiveSelectionSet, или был выход без выбора.
Алгоритм следующий:
1. В момент загрузки нашего VBA приложения, запускается макрос
   VBAProject_Initialize, в котором выставляются все необходимые для
   работы приложения параметры. В данном случае создаём нашу собственную
   команду MYCMD.
2. Вводим команду в командной строке MYCMD. Перехватываем её и запускаем
   макрос Begin_Select. В данном макросе делаем проверку на метод выбора
   объектов. Если объекты были выбраны заранее на экране, то запускаем
   макрос обработки объектов SelObjsManipulations.
   Если объекты выбраны не были, то запускаем команду SELECT для выбора
   объектов.
3. Перехватываем выход из команды SELECT и проверяем был ли выбор объектов,
   или был отказ от выбора. Если был отказ, то прекращаем работу. Если объекты
   были выбраны, то запускаем макрос обработки объектов SelObjsManipulations.
Если код отработал успешно, то макрос SelObjsManipulations выдаст сообщение
о количестве выбранных объектов.

Модуль AutoCAD Objects
-> ThisDrawing
Private Sub AcadDocument_BeginCommand(ByVal CommandName As String)
   On Error GoTo OnErr
   If ProgRuning = False Then VBAProject_Initialize
   Select Case CommandName
    Case "MYCMD": Begin_Select: Exit Sub
    Case "SELECT"
      If CmdEndOnCancel = True Then _
         CmdEndOnCancel = False: CmdMyCmd = False _
       Else: CmdEndOnCancel = True
   End Select
OnErr:
   If Err.Number <> 0 Then Err.Clear
End Sub
Private Sub AcadDocument_EndCommand(ByVal CommandName As String)
Dim SelSet As AcadSelectionSet
Dim I As Long
   On Error Resume Next
   If ProgRuning = False Then VBAProject_Initialize
   Select Case CommandName
    Case "SELECT"
      If CmdMyCmd = True Then
         CmdMyCmd = False: CmdEndOnCancel = False
         CommandName = "MYCMD"
         With ActiveDocument
            If .ActiveSelectionSet.Count <> 0 Then
               Set SelSet = .SelectionSets("$OLDACTIVESELOBJS_0A1H2F3B")
               If .ActiveSelectionSet.Count = SelSet.Count Then
                  For I = 0 To .ActiveSelectionSet.Count - 1
                     If .ActiveSelectionSet(I) Is SelSet(I) = False Then GoTo NewSel
                  Next I
                  SelSet.Delete: Set SelSet = Nothing
                  Exit Sub
NewSel:
               End If
               SelSet.Delete: Set SelSet = Nothing
               SelObjsManipulations
            End If
         End With
      End If
   End Select
End Sub
Private Sub AcadDocument_BeginSave(ByVal FileName As String)
Dim SelSet As AcadSelectionSet
   For Each SelSet In ActiveDocument.SelectionSets
      If SelSet.Name = "$EXPOLDACTSELOBJS_0A1H2F3B" Then SelSet.Delete: Exit For
   Next SelSet
   Set SelSet = Nothing
End Sub
Модуль
-> SelectObjects
Public ProgRuning As Boolean
Public CmdEndOnCancel As Boolean, CmdMyCmd As Boolean
Sub VBAProject_Initialize()
   On Error Resume Next
   ActiveDocument.SendCommand _
     "(vl-load-com)" & _
     "(defun MYCMD()())" & _
     "(vlax-add-cmd ""MYCMD"" 'MYCMD)" & _
     "(princ)" & vbCr
   DoEvents
   ProgRuning = True
У данного Lisp кода есть одна особенность. Все Lisp функции загруженные через
командную строку видны, только когда активен файл в котором они были загружены.
Поэтому, если в момент ввода нашей команды будет активен другой файл, то
AutoCAD выдаст, в командной строке, сообщение об ошибке. Для нашего VBA кода
это не имеет ни какого значения, главное что перехват команды отрабатывается чётко.
Если для кого-то это критично, то данный Lisp код необходимо сохранить
в файле *.lsp или в коде *.vlx и вместо приведёного выше кода, ввести
Lisp код загрузки вашего *.lsp или *.vlx файла, через специальную VLisp команду.
End Sub
Sub Begin_Select()
Dim AcadObj As AcadObject
Dim ArrayObj(0) As AcadObject
Dim SelSet As AcadSelectionSet
   On Error GoTo OnErr
   With ActiveDocument
      If .PickfirstSelectionSet.Count <> 0 Then
         SelObjsManipulations
         Exit Sub
      Else
         For Each SelSet In .SelectionSets
            If SelSet.Name = "$OLDACTIVESELOBJS_0A1H2F3B" Then SelSet.Clear: GoTo Sel_NoAdd
         Next SelSet
         Set SelSet = .SelectionSets.Add("$OLDACTIVESELOBJS_0A1H2F3B")
Sel_NoAdd:
         For Each AcadObj In .ActiveSelectionSet
            Set ArrayObj(0) = AcadObj
            SelSet.AddItems ArrayObj
         Next AcadObj
         Set SelSet = Nothing: Set AcadObj = Nothing
         CmdMyCmd = True: CmdEndOnCancel = False
         .SendCommand "_SELECT" & vbCr
      End If
   End With
OnErr:
   If Err.Number <> 0 Then Err.Clear
End Sub
Sub SelObjsManipulations()
Dim SelectionSet As AcadSelectionSet
   With ActiveDocument
      If .PickfirstSelectionSet.Count <> 0 Then
         Set SelectionSet = .PickfirstSelectionSet
       ElseIf .ActiveSelectionSet.Count <> 0 Then
         Set SelectionSet = .ActiveSelectionSet
       Else: Exit Sub
      End If
   End With
   MsgBox "Выбрано: " & SelectionSet.Count & " объектов." & (Chr(13) & Chr(10)) & _
     "Выбранные объекты в наборе - SelectionSet", vbInformation
End Sub