Требуется извлечь объекты из которых состоит сборка, для дальнейшей работы с ними.
Подскажите пожалуйста, как это можно сделать.
IPart7.PartsEx - Массив SAFEARRAY компонентов.
Sabahs, можно чуть более развёрнутый ответ? Я не нашёл внятного описания описания IPart7.
Воспользуйтесь поиском, да и в справке вроде подробно расписано.
http://forum.ascon.ru/index.php/topic,3771.msg20448.html#msg20448
Sabahs, у меня совсем глупый вопрос - если я хочу нарисовать, скажем, квадрат средствами API КОМПАСа в среде MVS, то что мне для этого нужно сделать.
Смотрите пример Step3 и Step3a в SDK.
Sabahs, насколько я понял, любое приложение использующее API КОМПАСа должно получить указатель на базовый интерфейс KompasObject? Так ли это? Я смотрел примеры на С++ и С#, в частности step2. В С++ не происходит получение указателя на KompasObjec. Тогда как в C# это есть.
void ExternalRunCommand([In] short command, [In] short mode, [In, MarshalAs(UnmanagedType.IDispatch)] object kompas_).
Вот это строчка не понятна - MarshalAs(UnmanagedType.IDispatch) Не могли бы вы прокаментировать её.
Так почитайте в SDK пункт "Оформление прикладных библиотек типа ActiveX", там подробно расписано про ExternalRunCommand.
Собственно там идёт приведение интерфейса к одному из интерфейсов API5 или API7, в зависимости от того, что будут указан в функции IsOnApplication7.
Если Вы имеете ввиду пример c:\Program Files\ASCON\KOMPAS-3D V15\SDK\C++\Visualc\step2\, то там используются экспортные функции из LibTool - из kAPI2D5.dll.
PS. Могу и ошибаться, т.к. я на Си не программирую.
Sabahs, если у меня в приложении используется API5, в частности, KompasObject и ksDocument3d то существует ли способ к этим объектам использовать API7 ?
Вы в DLL можете использовать API5, API7 и экспортные функции из LibTool, как всё это получить есть в примерах SDK.
Sabahs, из сборки можно вытащить имена файлов, в которых лежат компоненты? Причём вытащить нужно в иерархическом порядке, т.е провести декомпозиция сборки на компоненты, и из компоненты узнать имя файла.
IPart7.FileName - Имя файла компонента.
Sabahs, можно как нибудь извлечь данные в иерархическом порядке?
Из того, что есть сейчас вот:
public void AssemblyDecomposition()
{
if (doc != null)
{
//получить интерфейс на верхний компонент
IPart7 TopComponent = doc.TopPart;
if (TopComponent != null)
{
//получить интерфейс на коллекцию компонентов
IParts7 comCollection = TopComponent.Parts;
if (comCollection != null)
{
foreach (IPart7 element in comCollection)
{
//если элемент деталь, то получаем имя детали
if (element.Detail)
{
string fileName = element.FileName;
Console.WriteLine(fileName);
}
//иначе если элемент сборка
else
{
//формируем коллекцию элементов сборки
IParts7 NewCollection = element.Parts;
foreach (IPart7 item in comCollection)
{
string fileName = element.FileName;
Console.WriteLine(fileName);
}
}
}
}
}
}
Вроде должна возвращать всё, вроде и иерархия сохраняется, хотя нужно проверять.
http://forum.ascon.ru/index.php/topic,27478.msg205429.html#msg205429
Sabahs, вы не знаете, как использовать SAFEARRAY в C# ?
Смотрите пример:
c:\Program Files\ASCON\KOMPAS-3D V16\SDK\C#\Automation\Step3_API7_2D\Step3_API7_2D.cs
И всё же я не понимаю, какое значение(тип) мне должно вернуться, после использования PartsEx
Делаю так:
IKompasDocument3D doc;
IPart7 TopComponent = doc.TopPart;
TopComponent.PartsEx( ksPart7CollectionTypeEnum.ksAllParts);
Пример не судьба посмотреть, я в C# полный ноль, но если верить примеру, то должно быть так:
Array arr = (Array)TopComponent.PartsEx( ksPart7CollectionTypeEnum.ksAllParts);
Sabahs, если делать через PartsEx - всё хорошо(почти). Иерархия есть, компоненты сборки есть, файлы, в которых лежат компоненты есть(почти). Нет компонентов, которые в сборку должны входять, но физически не присутствую. Например, на компьютере нет файлов, в которых эти компоненты присутсвуют.
Как это исправить?
Из святого духа создать.
Sabahs, если делать так, то будут все компоненты. но, без иерархии.
public void AssemblyDecomposition()
{
if (doc != null)
{
//получить интерфейс на верхний компонент
IPart7 TopComponent = doc.TopPart;
if (TopComponent != null)
{
//получить интерфейс на коллекцию компонентов
IParts7 comCollection = TopComponent.Parts;
if (comCollection != null)
{
foreach (IPart7 element in comCollection)
{
//если элемент деталь, то получаем имя детали
if (element.Detail)
{
string fileName = element.FileName;
Console.WriteLine(fileName);
}
//иначе если элемент сборка
else
{
//формируем коллекцию элементов сборки
IParts7 NewCollection = element.Parts;
foreach (IPart7 item in comCollection)
{
string fileName = item.FileName;
Console.WriteLine(fileName);
}
}
}
}
}
}
Каким образом будут все компоненты, если их физически нет на компьютере?
Я так понял Вам нужны все компоненты кроме копий из операций копирования, то тогда так получите массив.
Array arr = (Array)TopComponent.PartsEx( ksPart7CollectionTypeEnum.ksUniqueParts);
Каким образом будут все компоненты, если их физически нет на компьютере?
Они могут лежать в БД удалённо. Но если нет соединения с сетью, то такие компоненты могут быть недоступны.Насколько я понимаю, то в роли такой БД выступает ЛОЦМАН.
Я так понял Вам нужны все компоненты кроме копий из операций копирования
Нет, мне нужно получить файлы(путь к ним), в которых лежат компоненты сборки в иерархическом порядке.
Если есть сборка, в который отсутствует компоненты, то в дереве модели, такие компоненты помечаются красным кружочком. Но Компас откуда то пытается "подтянуть" эти файлы! У него есть что-то вроде ссылок на эти файлы. Если файлы лежат на локальном компьютере, то условная ссылка - путь к файлу. Если файлы лежат удалённо, это что другое.
Как получить эту условную ссылку?
Давайте в картинках, что имеем, что получаем.
ЦитироватьДавайте в картинках, что имеем, что получаем.
уже ненужно.
Как разобрать сборку, если в ней есть ещё "подсборки"? Я пытался это сделать используя обход в глубину, но таким способом получается разобрать только саму "подсборку". Как быть, если в самой "подсборк"е может быть ещё n сборок?
Использовать рекурсию.
ЦитироватьИспользовать рекурсию.
Это уже получилось.
Если использовать интерфейс IFeature7 нельзя ли получить компоненты в иерархическом порядке?
Добрый день!
Имею в настоящий момент такую-же задачку: перебрать все элементы из сборки и ее подсборок. Писать пробую на c#.
appl = (IApplication)kompas.ksGetApplication7();
if (appl == null) return;
doc1 = (IKompasDocument3D)appl.ActiveDocument;
if (doc1 != null)
{
IPart7 TopComponent = doc1.TopPart;
if (TopComponent != null)
{
listBox1.Items.Add(TopComponent.Name); //------------здесь выдает в listbox имя сборки, все ок
IParts7 comCollection = TopComponent.Parts;
if (comCollection != null)
{
listBox1.Items.Add(comCollection.Count); // а здесь выдает 0, хотя в сборке есть куча объектов...
foreach (IPart7 element in comCollection)
{
if (element.Detail)
{
string fileName = element.Name;
listBox1.Items.Add(fileName);
}
else
{
IParts7 NewCollection = element.Parts;
foreach (IPart7 item in comCollection); // до этой строки не доходит, т.к. не видит объекты...
{
string fileName = element.Name;
listBox1.Items.Add(fileName);
}
}
}
}
}
}
что я делаю не так и как сделать, что бы получить хотя бы имена объектов внутри подсборки?
голову сломал, но в объектной модели не разобрался... Помогите люди добрые! :`(
http://forum.ascon.ru/index.php/topic,27478.msg205429.html#msg205429
Цитата: s_sergey от 29.03.15, 11:23:08
как сделать, что бы получить хотя бы имена объектов внутри подсборки?
голову сломал, но в объектной модели не разобрался... Помогите люди добрые! :`(
Если у вас в именах файлов Спецификаций содержатся номера документов, то я такую стратегию могу посоветовать :)
Сам делаю так, ибо иного пока не освоил в аду API7 и авгиевых конюшнях SDK... Да и не гонят никуда...
Парсю "нулевую" Спецификацию на номера документов, а потом рекурсивно их обхожу :)
получаю var rows = IKompasDocument.SpecificationRows[0]
foreach(SpecificationColumn cell in rows[n])
{
if(cell.Type = ksRowNumber)
var number = cell.Text.Str;
}
А дальше ищу в той же папке файлы с такими номерами и... собственно, рекурсивно их обхожу, получая всё что мне надо и формируя иерархию уже в своей программе. А дальше работаю со своим представлением.
Если нужны подробности - спрашивайте :)
Если всё ещё актуально...
Моя задача была чуть сложней. Необходимо было не просто пройтись по элементам сборки, но и вытащить их в иерархическом порядке.
Решение такое - создадим класс Assembly. Класс имеет три параметра - имя сборки, путь к файлу в которой лежит сборка, тип, позволяющий понять является ли элемент сборкой или нет, а также список, в котором храним элементы сборки.
public class Assembly
{
public string Name { get; set; }
public string File { get; set; }
public int asmType { get; set; }
public List<Assembly> Subassembly { get; set; }
public Assembly ( )
{List = new ObservableCollection<Assembly> ( ); }
}
Сам алгоритм разбора тривиален - обход графа в глубину.
public void AssemblyDecomposition()
{
if (doc != null)
{
// берём верхний компонент
IPart7 TopComponent = doc.TopPart;
if (TopComponent != null)
{
assembly.File = TopComponent.FileName;
assembly.Name = TopComponent.Name;
//признак, что компонент сборка
assembly.asmType = 1;
//получаем массив компонентов сборки
arrComponent = (Array)TopComponent.PartsEx[ksPart7CollectionTypeEnum.ksUniqueParts];
foreach (var i in arrComponent)
{
Decomposition((IPart7)i, assembly);
}
}
}
}
private void Decomposition(IPart7 component, Assembly assembly)
{
Assembly tmp = new Assembly();
if (component.Detail)
{
tmp.Name = component.Name;
tmp.File = component.FileName;
//признак, что деталь
tmp.asmType = 0;
//добавляем деталь в сборку
assembly.Subassembly.Add(tmp);
}
else
{
//иначе если подсборка, то разложить её на составные части
Array arrSubComponent = (Array)component.PartsEx[ksPart7CollectionTypeEnum.ksUniqueParts];
tmp.Name = component.Name;
tmp.File = component.FileName;
tmp.asmType = 1;
//добвим её в "большую сборку"
assembly.Subassembly.Add(tmp);
foreach (IPart7 newComponent in arrSubComponent)
{
//будем "собирать" компоненты "подсборки"
Decomposition(newComponent, tmp);
}
}
}
Код не идеален - есть дублирование кода, да и вообще.. но работает.