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

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

Как через COM интерфейс Автокада прочесть значение переменной?

Ответ
Поиск в этой теме
Непрочитано 14.12.2009, 19:32 #1
Как через COM интерфейс Автокада прочесть значение переменной?
Supermax
 
Руководитель фирмы
 
Москва
Регистрация: 28.03.2007
Сообщений: 1,831

У меня есть переменная, в ней записана строка. Мне надо прочесть эту строку через COM интерфейс AutoCAD.Application как?
Я могу через SendCommand создавать любые переменные, а прочесть - нет.
Может кто поможет?
Просмотров: 6758
 
Непрочитано 14.12.2009, 20:23
#2
Елпанов Евгений

программист
 
Регистрация: 20.12.2005
Москва
Сообщений: 1,439
Отправить сообщение для Елпанов Евгений с помощью Skype™


а откуда у тебя берется строка в переменной?
Может проще эту строку засунуть в другое место, откуда ее легко взять из других прог...
Как пример, переменная окружения:
Код:
[Выделить все]
(setenv "my_data" "my_string")
далее, используя любую программу, читаем реестр:
Код:
[Выделить все]
(VL-REGISTRY-READ "HKEY_CURRENT_USER\\Software\\Autodesk\\AutoCAD\\R17.1\\ACAD-6001:409\\FixedProfile\\General" "my_data")
В данном примере, путь к ветке реестра моего акада, но никто не мешает создать свою ветку для своего приложения.


Другой метод - переменные приложения
USERI1...USERI5 - целые числа
USERR1...USERR5 - реальные числа
USERS1...USERS5 - строки

Код будет выглядеть:
Код:
[Выделить все]
(setvar "USERS1" "my_string1")
(vlax-variant-value(vla-GetVariable (vla-get-ActiveDocument(vlax-get-acad-object))"USERS1"))
ps. можно придумать еще кучу мест, например писать в файл или мой любимый - в базу данных...
__________________
Чем гениальнее ваш план, тем меньше людей с ним будут согласны.
/Сунь Цзы/
Елпанов Евгений вне форума  
 
Автор темы   Непрочитано 14.12.2009, 20:38
#3
Supermax

Руководитель фирмы
 
Регистрация: 28.03.2007
Москва
Сообщений: 1,831
Отправить сообщение для Supermax с помощью Skype™


А доступа к переменным среды типа через
Autodesk.AutoCAD.ApplicationServices
или через
Autodesk.AutoCAD.Runtime
только для сторонних прог нет?
Supermax вне форума  
 
Непрочитано 14.12.2009, 20:49
#4
Елпанов Евгений

программист
 
Регистрация: 20.12.2005
Москва
Сообщений: 1,439
Отправить сообщение для Елпанов Евгений с помощью Skype™


а зачем это, если можно напрямую прочесть из реестра?
Кстати, внутри акада можно прочесть переменные через дизель:
Код:
[Выделить все]
(MENUCMD "M=$(getenv, my_data)")
__________________
Чем гениальнее ваш план, тем меньше людей с ним будут согласны.
/Сунь Цзы/
Елпанов Евгений вне форума  
 
Автор темы   Непрочитано 14.12.2009, 21:24
#5
Supermax

Руководитель фирмы
 
Регистрация: 28.03.2007
Москва
Сообщений: 1,831
Отправить сообщение для Supermax с помощью Skype™


Понимаешь, я хочу сделать интерфейс на AutoIT.
Как на картинке. Мне надо все названия блоков перегнать в дерево и рядом будет окно со свойствами и атрибутами. Выделяешь блок на дереве, а рядом его свойства и атрибуты появляются.
Я хочу, чтобы это дерево само расширялось и сужалось. Сделал блок - он там появился, убил - он и там исчез.
Реестр тут совсем не катит.
С системной переменной тоже как-то криво. Это надо каждый список поштучно туда загонять. Бр-р-р.
Миниатюры
Нажмите на изображение для увеличения
Название: проба.JPG
Просмотров: 115
Размер:	23.2 Кб
ID:	30548  
Supermax вне форума  
 
Непрочитано 14.12.2009, 21:33
#6
Елпанов Евгений

программист
 
Регистрация: 20.12.2005
Москва
Сообщений: 1,439
Отправить сообщение для Елпанов Евгений с помощью Skype™


для такого меню, можно сразу генерировать xml файл или если сложно, просто текстовый файл с необходимыми тебе разделителями вложенности строк итд...
__________________
Чем гениальнее ваш план, тем меньше людей с ним будут согласны.
/Сунь Цзы/
Елпанов Евгений вне форума  
 
Непрочитано 14.12.2009, 21:48
#7
Vov.Ka


 
Регистрация: 21.07.2008
Луцьк
Сообщений: 179


Код:
[Выделить все]
VERSION 1.0 CLASS
BEGIN
  MultiUse = -1  'True
END
Attribute VB_Name = "VLAX"
Attribute VB_GlobalNameSpace = False
Attribute VB_Creatable = False
Attribute VB_PredeclaredId = False
Attribute VB_Exposed = False
' VLAX.CLS v1.4 (Last updated 8/27/2001)
' Copyright 1999-2001 by Frank Oquendo
'
' Permission to use, copy, modify, and distribute this software
' for any purpose and without fee is hereby granted, provided
' that the above copyright notice appears in all copies and
' that both that copyright notice and the limited warranty and
' restricted rights notice below appear in all supporting
' documentation.
'
' FRANK OQUENDO (THE AUTHOR) PROVIDES THIS PROGRAM "AS IS" AND WITH
' ALL FAULTS. THE AUTHOR SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTY
' OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR USE.  THE AUTHOR
' DOES NOT WARRANT THAT THE OPERATION OF THE PROGRAM WILL BE
' UNINTERRUPTED OR ERROR FREE.
'
' Use, duplication, or disclosure by the U.S. Government is subject to
' restrictions set forth in FAR 52.227-19 (Commercial Computer
' Software - Restricted Rights) and DFAR 252.227-7013(c)(1)(ii)
' (Rights in Technical Data and Computer Software), as applicable.
'
' VLAX.cls allows developers to evaluate AutoLISP expressions from
' Visual Basic or VBA
'
' Notes:
' All code for this class module is publicly available througout various posts
' at news://discussion.autodesk.com/autodesk.autocad.customization.vba. I do not
' claim copyright or authorship on code presented in these posts, only on this
' compilation of that code. In addition, a great big "Thank you!" to Cyrille Fauvel
' demonstrating the use of the VisualLISP ActiveX Module.
'
' Dependencies:
' Use of this class module requires the following application:
' 1. VisualLISP

Private VL As Object
Private VLF As Object

Private Sub Class_Initialize()

    Set VL = ThisDrawing.Application.GetInterfaceObject("VL.Application.1")
    Set VLF = VL.ActiveDocument.Functions

End Sub

Private Sub Class_Terminate()

    Set VLF = Nothing
    Set VL = Nothing

End Sub

Public Function EvalLispExpression(lispStatement As String)

    Dim sym As Object, ret As Object, retval
    
    Set sym = VLF.Item("read").funcall(lispStatement)
    On Error Resume Next
    retval = VLF.Item("eval").funcall(sym)
    If Err Then
        EvalLispExpression = ""
    Else
        EvalLispExpression = retval
    End If

End Function

Public Sub SetLispSymbol(symbolName As String, value)

    Dim sym As Object, ret, symValue
    
    symValue = value
    Set sym = VLF.Item("read").funcall(symbolName)
    ret = VLF.Item("set").funcall(sym, symValue)
    EvalLispExpression "(defun translate-variant (data) (cond ((= (type data) 'list) (mapcar 'translate-variant data)) ((= (type data) 'variant) (translate-variant (vlax-variant-value data))) ((= (type data) 'safearray) (mapcar 'translate-variant (vlax-safearray->list data))) (t data)))"
    EvalLispExpression "(setq " & symbolName & "(translate-variant " & symbolName & "))"
    EvalLispExpression "(setq translate-variant nil)"

End Sub

Public Function GetLispSymbol(symbolName As String)

    Dim sym As Object, ret, symValue
    
    symValue = value
    Set sym = VLF.Item("read").funcall(symbolName)
    GetLispSymbol = VLF.Item("eval").funcall(sym)

End Function

Public Function GetLispList(symbolName As String) As Variant

   Dim sym As Object, list As Object
   Dim Count, elements(), i As Long
   
   Set sym = VLF.Item("read").funcall(symbolName)
   Set list = VLF.Item("eval").funcall(sym)
   
   Count = VLF.Item("length").funcall(list)
   
   ReDim elements(0 To Count - 1) As Variant
   
   For i = 0 To Count - 1
        elements(i) = VLF.Item("nth").funcall(i, list)
   Next
   
   GetLispList = elements
   
End Function

Public Sub NullifySymbol(ParamArray symbolName())

    Dim i As Integer
    
    For i = LBound(symbolName) To UBound(symbolName)
        EvalLispExpression "(setq " & CStr(symbolName(i)) & " nil)"
    Next

End Sub
Vov.Ka вне форума  
 
Автор темы   Непрочитано 14.12.2009, 21:52
#8
Supermax

Руководитель фирмы
 
Регистрация: 28.03.2007
Москва
Сообщений: 1,831
Отправить сообщение для Supermax с помощью Skype™


У меня есть два метода в COM-е AutoIT
; ClipGet () Вернуть текущий текст буфера обмена.
; ClipPut (1) Записать текст в буфер обмена.

Придется все превращать в текст и перегонять через буфер.
Стремно как-то.
А через файлы не катит. Моя панель завязана на события Автокада и когда просходит изменение базы рисунка должна обновлять содержимое панели. Через файлы будет сбоить, пути искать, долго писать и вообще не известно как это все синхронизировать.

А может кто специальный COM сварганит? Всего пару методов. Записать и прочесть. Вот было бы здорово.

Vov.Ka, спасибо за замечательный материал, только в VBA я не силен и есть пару вопросов.
Код:
[Выделить все]
Private VL As Object
Private VLF As Object
Ну, это понятно, дали определение переменным VL и VLF


Код:
[Выделить все]
Private Sub Class_Initialize()

    Set VL = ThisDrawing.Application.GetInterfaceObject("VL.Application.1")
    Set VLF = VL.ActiveDocument.Functions

End Sub
Тут де-юре понятно, а де-факто нет. В частности ("VL.Application.1") я хоть убей не понимаю, как можно давать значение переменной (Set VL = ....) и на нее же ссылаться? Если бы она раньше была уже со значением - понятно, но она же еще пуста.
Есть у меня метод GetInterfaceObject, но что ему совать - не пойму. Как мне добраться до Functions?

Все, добрался до Functions
Код:
[Выделить все]
(setq vl (vla-GetInterfaceObject (vlax-get-acad-object) "VL.Application.16"))
(setq vlactdoc (vla-get-ActiveDocument vl))
(setq vlf (vlax-get-property vlactdoc "Functions" ))
(setq vlitemread (vlax-get-property vlf "Item" "read"))
(setq vlitemreadname (vlax-get-property vlitemread "Name"))
(setq sum (vlax-invoke-method vlitemread 'funcall "????????"))
Только в последней строчке не хочет глотать имена переменных.

Set sym = VLF.Item("read").funcall(symbolName)
Я создал в рисунке переменную (setq A1 "123")
Я уже и "\"A1\"" и сяк - никак
; error: too few actual parameters

Последний раз редактировалось Supermax, 15.12.2009 в 13:15.
Supermax вне форума  
 
Непрочитано 15.12.2009, 13:18
#9
Сергей Дубина


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


А если попробовать не переменные а коллекцию BlockReference
__________________
КазнитьØнельзяØпомиловать:eek:
Сергей Дубина вне форума  
 
Автор темы   Непрочитано 15.12.2009, 16:32
#10
Supermax

Руководитель фирмы
 
Регистрация: 28.03.2007
Москва
Сообщений: 1,831
Отправить сообщение для Supermax с помощью Skype™


Ничего не получается..
Я нашел у себя в реестре "VL.Application.16"
Вот его дамп:

Код:
[Выделить все]
Command: (setq vl (vlax-get-or-create-object "VL.Application.16"))
#<VLA-OBJECT DVlApplication 0d544048>
Command: (vlax-dump-object vl T)
; DVlApplication: Dispatch interface for VL Application
; Property values:
;   ActiveDocument (RO) = ...Indexed contents not shown...
;   Documents (RO) = ...Indexed contents not shown...
;   Name (RO) = ...Indexed contents not shown...
; No methods
T
К сожалению, чтение Documents дает 0, то есть этот СОМ не видит никаких документов, в том числе и ActiveDocument
тоже не имеет доступа к пространству имен.

Строка
Код:
[Выделить все]
Set VL = ThisDrawing.Application.GetInterfaceObject("VL.Application.1")
Покрыта тайной своего происхождения, поскольку ThisDrawing остался за кадром.

Применение метода GetInterfaceObject к AutoCAD.Application дает то же самое, что и просто
(vlax-get-or-create-object "VL.Application.16"). У него как небыло доступа, к пространству имен, так и нет.
Вот поэтому я и не могу получить данные о переменной. Ее просто нет в VL.Application.16.
Но все функции Автолиспа - есть.

Задаю прямой вопрос: Что это за СОМ VL.Application.16 ???????
Supermax вне форума  
 
Непрочитано 15.12.2009, 17:01
#11
VVA

Инженер LISP
 
Регистрация: 11.05.2005
Минск
Сообщений: 6,992


Цитата:
Сообщение от Supermax Посмотреть сообщение
Я могу через SendCommand создавать любые переменные, а прочесть - нет.
Пошли через Sendcommand лисп выражение
Код:
[Выделить все]
(setvar "USERS1" Имя_Твоей_ЛИСП_Переменной)
С помощью метода GetVariable прочитай значение переменной USERS1
Похожий пример
__________________
Как использовать код на Лиспе читаем здесь
VVA вне форума  
 
Автор темы   Непрочитано 15.12.2009, 17:39
#12
Supermax

Руководитель фирмы
 
Регистрация: 28.03.2007
Москва
Сообщений: 1,831
Отправить сообщение для Supermax с помощью Skype™


Да мне уже это советовали.
Цитата:
USERI1...USERI5 - целые числа
USERR1...USERR5 - реальные числа
USERS1...USERS5 - строки
Наверное придется все значения свойств блоков переводить в строки и писать функции.
А про "VL.Application.16" всеж интересно.

Я попробовал пойти от обратного и немного продвинулся.
Я решил не читать значение переменной, а записать в переменную что-нибудь.

Код:
[Выделить все]
(setq vl (vla-GetInterfaceObject (vlax-get-acad-object) "VL.Application.16"))
(setq vlactdoc (vla-get-ActiveDocument vl))
(setq vlf (vlax-get-property vlactdoc "Functions" ))
(setq vlitemset (vlax-get-property vlf "Item" "set"))
(setq sum (vlax-invoke-method vlitemset "funcall" 'A1 1))
Ругнулось
; error: lisp value has no coercion to VARIANT with this type: A1

Ага думаю и стал перебирать все vlax-make-variant, но не тут-то было.
Есть целые числа, длинные и не очень, есть строки, есть массивы и пустышки - ничего не катит. Хочет только символ.
А варианта с символом-то и нема. И где его взять?
Может из-за этого не мог прочесть?

Первая удача!
Код:
[Выделить все]
(setq vlitemstrcat (vlax-get-property vlf "Item" "strcat"))
(setq sum (vlax-invoke-method vlitemstrcat "funcall" "A1" "1"))
Вернуло #<variant 8 A11>

А с eval, setq, vl-symbol-value и пр.
Цитата:
The requested action with this object has failed
Запрошенная акция с этим объектом терпела неудачу
И догадываетесь почему? Да, да. Нет связи с активным документом! А именно там и создаются переменные.

Последний раз редактировалось Supermax, 15.12.2009 в 19:12.
Supermax вне форума  
 
Непрочитано 15.12.2009, 19:12
#13
Елпанов Евгений

программист
 
Регистрация: 20.12.2005
Москва
Сообщений: 1,439
Отправить сообщение для Елпанов Евгений с помощью Skype™


Supermax, тогда, много проще идти через словари...
Они гарантированно имеют доступ через СОМ и удобны в использовании.
просто создавай свой словарь, в нем объекты, в объектах данные.

Цитата:
Первая удача!
Код:
(setq vlitemstrcat (vlax-get-property vlf "Item" "strcat"))
(setq sum (vlax-invoke-method vlitemstrcat "funcall" "A1" "1"))
у меня вернуло:
Код:
[Выделить все]
; error: Automation Error. Member not found: funcall
_$
__________________
Чем гениальнее ваш план, тем меньше людей с ним будут согласны.
/Сунь Цзы/
Елпанов Евгений вне форума  
 
Автор темы   Непрочитано 15.12.2009, 19:27
#14
Supermax

Руководитель фирмы
 
Регистрация: 28.03.2007
Москва
Сообщений: 1,831
Отправить сообщение для Supermax с помощью Skype™


Со словарями, это уже теплее, хотя тоже через ... черный вход.
А ты вот так попробуй:

Код:
[Выделить все]
(setq vl (vla-GetInterfaceObject (vlax-get-acad-object) "VL.Application.16"))
(setq vlactdoc (vla-get-ActiveDocument vl))
(setq vlf (vlax-get-property vlactdoc "Functions" ))
(setq vlitemstrcat (vlax-get-property vlf "Item" "strcat"))
(setq sum (vlax-invoke-method vlitemstrcat "funcall" "A1" "1"))
Supermax вне форума  
 
Непрочитано 15.12.2009, 19:30
#15
VVA

Инженер LISP
 
Регистрация: 11.05.2005
Минск
Сообщений: 6,992


Может эти ссылки как-то помогут
Код:
[Выделить все]
Public Function LispVariable(Name As String, Optional Value As Variant) As Variant
Dim VLisp As Object
Dim VLispFunc As Object
Dim VLispVar As Variant

' Access the Lisp ActiveX control.
Set VLisp = Application.GetInterfaceObject("VL.Application.16")
' Access the Lisp Functions defined for the active document.
Set VLispFunc = VLisp.ActiveDocument.functions

' Return the value of the Lisp Function.
LispVariable = VLispFunc.Item("eval").funcall(VLispFunc.Item("read").funcall(Name))

End Function
http://discussion.autodesk.com/forum...hreadID=434750
__________________
Как использовать код на Лиспе читаем здесь
VVA вне форума  
 
Автор темы   Непрочитано 15.12.2009, 19:42
#16
Supermax

Руководитель фирмы
 
Регистрация: 28.03.2007
Москва
Сообщений: 1,831
Отправить сообщение для Supermax с помощью Skype™


Спасибо VVA, но все это я уже перепробовал.
Интересно, а на VBA удается вот так читать переменные?
Тут все VBA-шные примеры мелькают, а как на счет их проверить?
Читают эти функции переменные или нет?
Если читают, то почему я не могу?

К стати все арифметические функции работают. Тоже варианты возвращает с результатом.
Чего-то не хватает...

А,
Код:
[Выделить все]
(setq vlitemobj (vlax-get-property vlf "Item" "vlax-get-acad-object"))
#<VLA-OBJECT DVlFunction 0d5c21d8>
(setq sum (vlax-invoke-method vlitemobj "funcall")) 
; error: too few actual parameters
У vlax-get-acad-object вообще нет параметров, а все равно не катит. То катит, то не катит, странно.

Последний раз редактировалось Supermax, 15.12.2009 в 20:00.
Supermax вне форума  
 
Непрочитано 15.12.2009, 20:12
#17
Елпанов Евгений

программист
 
Регистрация: 20.12.2005
Москва
Сообщений: 1,439
Отправить сообщение для Елпанов Евгений с помощью Skype™


Цитата:
Сообщение от Supermax Посмотреть сообщение
А ты вот так попробуй:
Код:
[Выделить все]
#<VLA-OBJECT DVlApplication 0b323048> 
#<VLA-OBJECT DVlDocument 0b3230e8> 
#<VLA-OBJECT DVlFunctions 0b323138> 
#<VLA-OBJECT DVlFunction 0b323188> 
; error: Automation Error. Member not found: funcall
_$
__________________
Чем гениальнее ваш план, тем меньше людей с ним будут согласны.
/Сунь Цзы/
Елпанов Евгений вне форума  
 
Автор темы   Непрочитано 15.12.2009, 20:19
#18
Supermax

Руководитель фирмы
 
Регистрация: 28.03.2007
Москва
Сообщений: 1,831
Отправить сообщение для Supermax с помощью Skype™


Попробуй с +
Код:
[Выделить все]
(setq vlitem+ (vlax-get-property vlf "Item" "+"))
(setq sum (vlax-invoke-method vlitem+ "funcall" 2 7))
У меня вернуло
#<variant 3 9>

Ну и как в словарь строки и списки записывать?
Там только объекты тулятся, или я не прав?

Последний раз редактировалось Supermax, 15.12.2009 в 21:29.
Supermax вне форума  
 
Непрочитано 15.12.2009, 22:01
#19
Елпанов Евгений

программист
 
Регистрация: 20.12.2005
Москва
Сообщений: 1,439
Отправить сообщение для Елпанов Евгений с помощью Skype™


Цитата:
Сообщение от Supermax Посмотреть сообщение
У меня вернуло
#<variant 3 9>
#<VLA-OBJECT DVlFunction 0b323098>
; error: Automation Error. Member not found: funcall
проверяю в autocad 2008 (en) sp1
__________________
Чем гениальнее ваш план, тем меньше людей с ним будут согласны.
/Сунь Цзы/
Елпанов Евгений вне форума  
 
Непрочитано 15.12.2009, 22:33
#20
Кулик Алексей aka kpblc
Moderator

LISP, C# (ACAD 200[9,12,13,14])
 
Регистрация: 25.08.2003
С.-Петербург
Сообщений: 39,848


Supermax, скажи, а зачем вообще использовать Lisp-функции, если ты работаешь со сторонним скриптовым языком?
__________________
Моя библиотека lisp-функций
---
Обращение ко мне - на "ты".
Все, что сказано - личное мнение.
Кулик Алексей aka kpblc вне форума  
Ответ
Вернуться   Форум DWG.RU > Программное обеспечение > Программирование > Как через COM интерфейс Автокада прочесть значение переменной?

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


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Сейсмозащита и сейсмоизоляция существующих, построенных зд. IANationalInformAgentstvo Прочее. Архитектура и строительство 216 20.01.2015 16:51
Как оптом сохранить все чертежи в формате 14-го автокада? Соня AutoCAD 26 20.03.2011 14:59
как изменить интерфейс Autocad 2009 Electra AutoCAD 2 15.06.2009 00:16
Мониторы LCD CRT Разное 94 17.06.2008 10:51
как задать тип переменной Александер Программирование 5 17.10.2005 15:32