Процесс (как в 2д процессе указать объект к которому применить команду)

Автор Wargin39, 10.01.25, 08:44:57

« назад - далее »

0 Пользователи и 1 гость просматривают эту тему.

Wargin39

Всех приветствую!
Подскажите, как в "процессе" указывать курсором 2д объекты к которым нужно применить данную команду?  В самом Компасе данная механика реализована повсеместно во многих стандартных командах. к примеру: "Выравнивание размеров";"построение параллельных и перпендикулярных прямых";"Эквидистанта"; "Скругление" и т.п. Меня интересует как реализовать подобную функцию в своем процессе с помощью Компас API?

Если важно, то моя задумка заключается в том, чтобы написать команду которая добавляет текст в линейный размер. Сейчас я реализую это с помощью функции: SelectionManager, однако это по моему как-то дико! (сейчас логика моей программы такова: я включаю команду и в "бесконечном" цикле проверяю есть ли выбранные объекты, если я выбираю размерную линию, то программа добавляет в нее нужный текст. После выключения команды, цикл останавливается. Это работает, но хочется это реализовать как в функции "выравнивание размеров", плюс там выполняется предварительное подсвечивание объектов на котором находится курсор)
Буду благодарен если вы мне поможете!

Vi2

Мы используем UserGetPlacementAndEntity. где в функции filter(entity) указывается подходит ли нам объект (если подходит, то он подсвечивается. если не подходит, то не подсвечивается), а в функции select(entity,request) обрабатывается подсвеченный объект, на котором уже нажали мышкой.

UU

Цитата: Vi2 от 10.01.25, 20:58:59Мы используем UserGetPlacementAndEntity. где в функции filter(entity) указывается подходит ли нам объект (если подходит, то он подсвечивается. если не подходит, то не подсвечивается), а в функции select(entity,request) обрабатывается подсвеченный объект, на котором уже нажали мышкой.
Для 2D?
ksPlacement или ksCursor.

Vi2

Цитата: UU от 11.01.25, 03:33:29Для 2D?
В 3Д - рёбра эскизов и граней, грани, тела и системы координат. Всё, что может участвовать в обработке.

PS
В 2Д наше приложение не появляется. Видимо, так определено, но и в 2Д, наверное, тоже можно использовать - модель объектов ведь одна и та же.

UU

Цитата: Vi2 от 11.01.25, 21:39:36В 3Д - рёбра эскизов и граней, грани, тела и системы координат. Всё, что может участвовать в обработке.

PS
В 2Д наше приложение не появляется. Видимо, так определено, но и в 2Д, наверное, тоже можно использовать - модель объектов ведь одна и та же.

Что?

Lemieux

Цитата: Vi2 от 11.01.25, 21:39:36В 3Д - рёбра эскизов и граней, грани, тела и системы координат. Всё, что может участвовать в обработке.

PS
В 2Д наше приложение не появляется. Видимо, так определено, но и в 2Д, наверное, тоже можно использовать - модель объектов ведь одна и та же.

Сурово  :w: :-)))

Vi2

Цитата: Lemieux от 12.01.25, 08:50:33Сурово  :w: :-)))
Что-то я не понял: сказал что-то не то? Или оверскил какой-то от моего предложения?

Lemieux

Цитата: Vi2 от 12.01.25, 14:43:21Что-то я не понял: сказал что-то не то? Или оверскил какой-то от моего предложения?
Так это я записываю за мастерами и смеюсь над своим лоускилом  :um:

Wargin39


ВСЕМ ПРИВЕТ! мне удалось используя данный метод koord=ksDocument2D.ksCursorEx(requestInfo, 0, 0, фантом,procParam) запустить процесс и добавить к нему функции обратной связи для процесса Cursor, ниже привожу немного кода и ссылку откуда я это взял. Однако рано радоваться, есть проблема!! я пока не знаю как обработать нажатие кнопки мыши и остановить процесс. я также не знаю как в в функции обратной связи отслеживать нажатие мыши!
таким образом вопрос следующий: как подписаться на событие, я нахожу много инфы в SDK, но в ней отсутствует взаимосвязанности, я не понимаю что у кого брать.... :`(   буду рад любой помощи! 
Как получить интерфейс ksProcess2DNotify? приведите код если кто знает.
requestInfo = self.api5.GetParamStruct(10)
requestInfo.Init()
requestInfo.prompt = u'Укажите место вставки текста' #подсказка
requestInfo.title="команда №1"
requestInfo.dynamic=1
ocx = Dispatch("******тут_название_COM*****")
ocx.Init(self.api5)
requestInfo.SetCallBackCEx(u"fun777",0,ocx)
см. https://forum.ascon.ru/index.php?topic=37629.msg305788#msg305788


Цитата: UU от 11.01.25, 03:33:29ksPlacement или ksCursor.
да, можно и так запустить процесс! но как в нем начать отслеживать нажатие мыши?
+ Благодарностей: 1

UU


Wargin39

я сделал так, чтобы получать объект по нажатию на него мышкой. Ниже привожу архив с исходным кодом.
Для запуска программы, нужно первым  запустить файл:  registr COM obj.py (Это нужно сделать один раз, и больше не потребуется.)
Затем просто запустите файл: Компас.py
Чуть ниже, отдельно выложу код обоих файлов....
Аналогичный метод описан:  https://forum.ascon.ru/index.php?topic=31276.msg249587#quickreply_anchor

Wargin39

Код файла: registr COM obj.py 


import pythoncom
from win32com.client import Dispatch, gencache
module =  gencache.EnsureModule("{0422828C-F174-495E-AC5D-D31014DBBE87}", 0, 1, 0)  #модуль компас3д

clsid=pythoncom.CreateGuid()  #это CLSID  (генерируем CLSID....)
print("CLSID: ",clsid)

class Tverd_777:
    _reg_clsid_ =clsid    #CLSID объекта COM
    _reg_progid_= "Serv_COM" #"Идентификатор программы" или Имя COM-сервера. Это имя, которое пользователь обычно использует для создания экземпляра объекта
    _public_methods_ = [u'fun777',u'Init']  #Список всех имен методов, доступных удаленным клиентам COM
    #_public_attrs_ =  #Список всех имен атрибутов, доступных удаленным клиентам COM
    _readonly_attrs_ = ['doc','ref'] #Список всех атрибутов, к которым можно получить доступ, но которые нельзя задать.

    def __init__(self):
       self.kompas = None
       self.kompasObject  = None
       self.doc = None
       self.lov = None  #ловушка курсора
       self.ref = 0

    def Init(self, kompas):
        self.kompas = kompas
        self.kompasObject = module.KompasObject(self.kompas.QueryInterface(module.KompasObject.CLSID, pythoncom.IID_IDispatch))
        self.doc = self.kompasObject.ActiveDocument2D()
        self.lov=self.doc.ksGetCursorLimit()   #ловушка курсора
    def fun777(self,com, x, y, info, phantom, dynamic):   #данные аргументы определены Компас3д, менять их не нужно!
        info= module.ksRequestInfo(info.QueryInterface(module.ksRequestInfo.CLSID, pythoncom.IID_IDispatch))
        info.cursorId=0xFFFC    #устанавливаем нужный нам курсор
        info.SetCursorText("Укажи объект")   #устанавливаем текст курсора

        ref = self.doc.ksFindObj(x,y, self.lov) #получаем указатель объекта на который наведен курсор
        if self.ref!=ref:
            if ref!=0 and self.doc.ksExistObj(ref)==1: #выделяем цветом
                self.doc.ksLightObj(ref, 1)
            if self.ref!=0:
                self.doc.ksLightObj(self.ref, 0)  #снимаем выделение
            self.ref=ref

        if dynamic == 0:
            if com == -1:
                self.doc.ksLightObj(self.ref, 0)     #снимаем выделение
                return 1, print(f"#1, {self.ref}")    #Если указать в return "0", то функция закроется, а если "1", то функция будет воспроизводится многократно после нажатия на мышь
            else:
                return 0, print("#2")        #Если указать в return "0", то функция закроется, а если "1", то функция будет воспроизводится многократно после нажатия на мышь
        return 1, print(f"координаты курсора: {x} : {y} ")


if __name__=='__main__':
    import win32com.server.register
    win32com.server.register.UseCommandLine(Tverd_777) #производим регистрацию класса  "Tverd_777" в системе
    print("завершено!")

Wargin39

код файла:Компас.py  (но помните, что перед его запуском, нужно запустить один раз код: registr COM obj.py) смотри выше.....
from tkinter import *
import pythoncom
from win32com.client import Dispatch, gencache
import psutil

class Компас_старт:
    def __init__(self):
        self.конст5= gencache.EnsureModule("{75C9F5D0-B5B8-4526-8681-9903C567D2ED}", 0, 1, 0).constants
        self.модуль5 = gencache.EnsureModule("{0422828C-F174-495E-AC5D-D31014DBBE87}", 0, 1, 0)
        self.модуль7 = gencache.EnsureModule("{69AC2981-37C0-4379-84FD-5DD2F3C0A520}", 0, 1, 0)
        self.api5 = self.модуль5.KompasObject(Dispatch("Kompas.Application.5")._oleobj_.QueryInterface(self.модуль5.KompasObject.CLSID, pythoncom.IID_IDispatch))
        self.api7 = self.модуль7.IKompasAPIObject(Dispatch("Kompas.Application.7")._oleobj_.QueryInterface(self.модуль7.IKompasAPIObject.CLSID,pythoncom.IID_IDispatch))
        self.app7 = self.api7.Application

    def указать_место(self):
        iDocument = self.app7.ActiveDocument
        if iDocument.DocumentType not in (1, 2): #проверяем тип документа, если не 2д, то функция закроется
            return
        ksDocument2D = self.api5.ActiveDocument2D()
        requestInfo = self.api5.GetParamStruct(10)
        requestInfo.Init()
        requestInfo.cursorId=0xFFFC   #указываем курсор
        requestInfo.prompt = u'Укажите место вставки текста'
        requestInfo.title="команда №1"
        requestInfo.SetCursorText("Укажи объект")
        requestInfo.dynamic=1

        procParam = self.app7.CreateProcessParam()
        procParam.SpecToolbar = self.конст5.pnEnterEscHelp  #тип панели(есть и другие, но меня устроила эта)
        procParam.Caption = "Моя команда 12.01.2025"         #заголовок
        procParam.AutoReduce = True              # завершить процесс автоматом при задании всех параметров
        propTabs = procParam.PropertyTabs        #Коллекция вкладок Панели свойств
        вкладка1=propTabs.SystemTab              #делаем системную вкладку невидимой
        вкладка1.Visible=0                       #скрывам пнтерфейс базовой точки, он мне не нужен!

        propTab = propTabs.Add("Первая закладка")
        Controls = propTab.PropertyControls   #Коллекция элементов управленияна вкладке
        propTab.Visible = True
        propTab.Active = True
        propTab.Expanded = True
        # Добавляем строку в которой пишем "Укажите объект"
        строка1 = self.модуль7.IPropertyPreviewText(Controls.Add(self.конст5.ksControlEditStr))
        строка1.Name = "Объект"
        строка1.NameVisibility = True
        строка1.Enable = 0
        строка1.Value = "Укажите объект"
        строка1.Visible = True

        фантом= self.api5.GetParamStruct(6)   # создаем фантом, назначаем ему группу и тип.
        фантом.Init()
        фантом.phantom=0      #просто вставляет группу без смещения
        g=фантом.GetPhantomParam()

        ocx = Dispatch("Serv_COM")    #подключаемся к нашему классу из файла: "registr COM obj.py"
        ocx.Init(self.api5)
        requestInfo.SetCallBackCEx(u"fun777",0,ocx)    #устанавливаем в качестве функции обратной связи "fun777" из нашего  "registr COM obj.py"

        ловушка=ksDocument2D.ksGetCursorLimit()    #радиус ловушки курсора
        koord=ksDocument2D.ksCursorEx(requestInfo, 0, 0, фантом,procParam)     #запускаем процесс указания точки

#///////////////////////////////////////////////////////////////////////////////////////////////////
#/////////////////////////////////////ЭТОТ КОД УЖЕ НЕ ОБЯЗАТЕЛЕН////////////////////////////////////
        print(koord[1],koord[2])
        reference_obj = ksDocument2D.ksFindObj(koord[1], koord[2], ловушка)
        if ksDocument2D.ksExistObj(reference_obj)==1:
            ksDocument2D.ksLightObj(reference_obj, 1)
#///////////////////////////////////////////////////////////////////////////////////////////////////
#///////////////////////////////////////////////////////////////////////////////////////////////////

экз1=Компас_старт() #запускаем наш класс
def функция999():
    экз1.указать_место()
root = Tk()
root.title("METANIT.COM")
root.attributes("-topmost", True)
root.attributes('-toolwindow', True)
button1 = Button(text="проверка", command=функция999)
button1.grid(column=0, row=0)
root.mainloop()

Wargin39

теперь меня интересует: события панели свойств. Как с ней работать? как получать значения из поля ввода? Если встречался код на данную тему, скиньте пж :`( !!!


Wargin39

Цитата: UU от 13.01.25, 09:44:47Step12.
там нет примера, как из панели свойств получить значения "Value" элементов управления из функции обратной связи "SetCallBackC" или для этого нужно обязательно выйти из функции обратной связи? но тогда вопрос как получить выходное значение функции SetCallBackC (итоговое имею в виду)?

UU

Функции обратной связи Step4.
Просто прочитать свойство Value у нужного компонента, желательно по событию.
https://help.ascon.ru/KOMPAS_SDK/23/ru-RU/controltypeenum.html
Цитата: Wargin39 от 16.01.25, 08:10:51там нет примера, как из панели свойств получить значения "Value" элементов управления из функции обратной связи "SetCallBackC" или для этого нужно обязательно выйти из функции обратной связи? но тогда вопрос как получить выходное значение функции SetCallBackC (итоговое имею в виду)?
Тут его читаете.

Wargin39

Всем привет.
Дописал функцию обратной связи, теперь не только можно подсветить объект но получать доступ к его интерфейсам. т.е. теперь можно указать объект к которому  вы хотите применить свои действия (в 2д чертеже)

второй файл остался без изменений!
инструкцию по запуску кода читайте выше!
код обратной функции :

import pythoncom
from win32com.client import Dispatch, gencache
module =  gencache.EnsureModule("{0422828C-F174-495E-AC5D-D31014DBBE87}", 0, 1, 0)  #модуль компас3д
module7 = gencache.EnsureModule("{69AC2981-37C0-4379-84FD-5DD2F3C0A520}", 0, 1, 0)

clsid=pythoncom.CreateGuid()  #это CLSID  (генерируем CLSID....)
print("CLSID: ",clsid)

def int_r(num):
    num = int(num + (0.5 if num > 0 else -0.5))
    return num

class Tverd_777:
    _reg_clsid_ =clsid    #CLSID объекта COM
    _reg_progid_= "Serv_COM" #"Идентификатор программы" или Имя COM-сервера. Это имя, которое пользователь обычно использует для создания экземпляра объекта
    _public_methods_ = [u'fun777',u'Init']  #Список всех имен методов, доступных удаленным клиентам COM
    #_public_attrs_ =  #Список всех имен атрибутов, доступных удаленным клиентам COM
    _readonly_attrs_ = ['doc','ref'] #Список всех атрибутов, к которым можно получить доступ, но которые нельзя задать.

    def __init__(self):
       self.kompas = None
       self.kompasObject  = None
       self.doc = None
       self.lov = None  #ловушка курсора
       self.ref = 0

    def Init(self, kompas):
        self.kompas = kompas
        self.kompasObject = module.KompasObject(self.kompas.QueryInterface(module.KompasObject.CLSID, pythoncom.IID_IDispatch))
        self.doc = self.kompasObject.ActiveDocument2D()
        self.lov=self.doc.ksGetCursorLimit()   #ловушка курсора

    def fun777(self,com, x, y, info, phantom, dynamic):   #данные аргументы определены Компас3д, менять их не нужно!
        info= module.ksRequestInfo(info.QueryInterface(module.ksRequestInfo.CLSID, pythoncom.IID_IDispatch))
        info.cursorId=0xFFFC    #устанавливаем нужный нам курсор

        ref = self.doc.ksFindObj(x,y, self.lov) #получаем указатель объекта на который наведен курсор
        if self.ref!=ref:
            if ref!=0 and self.doc.ksExistObj(ref)==1: #выделяем цветом
                self.doc.ksLightObj(ref, 1)
            if self.ref!=0:
                self.doc.ksLightObj(self.ref, 0)  #снимаем выделение
            self.ref=ref

        if dynamic == 0:
            if com == -1:
                self.doc.ksLightObj(self.ref, 0)     #снимаем выделение
                obgkt=self.kompasObject.TransferReference(self.ref, 0) #получить обект по его идентификатору
                if obgkt!=None:
                    if obgkt.Type==13041:
                        driv=module7.IDrawingObject(obgkt)
                        vl=module7.IDimensionText(driv)
                        vl.Accuracy=0   #знаков после запятой
                        vl.Prefix.Str="" #удаляем прошлое содержимое
                        razmer=vl.NominalValue   #размер
                        r1=int_r(razmer)+1
                        vl.Suffix.Str="±2("+str(r1)+")"
                        obgkt.Update()

                return 1, print(f"#1, {self.ref}")    #Если указать в return "0", то функция закроется, а если "1", то функция будет воспроизводится многократно после нажатия на мышь    **
            else:
                return 0, print("#2")        #Если указать в return "0", то функция закроется, а если "1", то функция будет воспроизводится многократно после нажатия на мышь
        return 1, print(f"координаты курсора: {x} : {y} ")


if __name__=='__main__':
    import win32com.server.register
    win32com.server.register.UseCommandLine(Tverd_777) #производим регистрацию класса  "Tverd_777" в системе
    print("завершено!")

+ Благодарностей: 1

Wargin39

полезные ссылки по созданию своей панели инструментов:
https://forum.ascon.ru/index.php?topic=35696.msg285296#msg285284 
https://forum.ascon.ru/index.php?topic=29310.msg224669#msg224669
в SKD Создание прикладных библиотек  > Оформление прикладных библиотек типа DLL  > Функции
Пример использования функций оформления библиотеки