Вопрос: Как не закрывая "отдать" взятый в обработку документ

Автор Akew, 30.03.16, 19:56:49

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

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

Akew

Добрый вечер!

В окне КОМПАС открыта 3D модель. Получаю к ней доступ:
ksDocument3DPtr doc3D = MyKompasObject->ActiveDocument3D();
if( doc3D != NULL ) {

IKompasDocument3DPtr kompasDoc3D( IUnknownPtr( ksTransferInterface( doc3D, ksAPI7Dual, 0), false) );
if( kompasDoc3D != NULL ) {

IPart7Ptr part7 = kompasDoc3D->TopPart;
if( part7 != NULL ) {

// Обработка компонент

}
}
}


Проблема состоит в том, что блок "Обработка компонент" кроме чисто программных методов обработки имеет операции КОМПАСа, которые интерактивно вызывает пользователь (с панелей инструментов КОМПАСа).
Например, редактирование операции "Удалить грани"; после возобновления автоматической обработки программа определяет изменения в этой операции (т.е., находит, какие грани были удалены/восстановлены, по ним находит стыкующиеся грани и удаляет эти грани из массива операции "Удалить грани", и др.).
Взаимодействие с пользователем реализовано на выдаче немодального сообщения; работа программы приостанавливается, пока пользователь не проведет свою операцию и не закроет это сообщение (кнопка "OK").

В связи с этим, вопрос: должна ли программа каким-то образом возвращать текущий документ, перед тем как пользователь будет редактировать операцию "Удалить грани"? Я полагаю, что должна. Только пока не нашел подходящего способа; есть только метод close(), но мне хотелось бы, чтобы документ оставался открытым в окне КОМПАСа (не открывать его снова всякий раз).

Спасибо.


Akew

ЦитироватьОна у Вас, что отдельным потоком работает?
Нет, вряд ли (во всяком случае, я ничего не организовывал). И с таким понятием, поток, пока не сталкивался.


Akew

Цитировать
Цитата: Sabahs от 30.03.16, 21:06:39
Тогда, я не понимаю сути проблемы.
Я подозреваю, что, когда программа (в том виде, в каком она реализована сейчас) "отдает управление" пользователю, то редактируемая 3D модель, уже "занятая" программой, пользователю передается, как бы, не в полном объеме (как это было бы в случае, если пользователь с самого начала редактировал ее вручную, без использования программы). Например, при ручном редактировании операции "Удалить грани" (при работе с программой) не всегда показывается кол-во удаленных граней в окошке свойств этой операции (сами грани при этом отбираются нормально); нельзя построить кривую пересечения двух поверхностей и т.д.. Эти ситуации похожи на те, когда, не закончив редактирование одной операции (например, забыв закончить), пользователь начинает работать с другой (при "ручной" работе с КОМПАС).

Мне нужен способ отдачи пользователю полного управления над редактируемой моделью от программы, и получения его обратно, когда он закончит свои действия (не закрывая при этом программы, и без повторного закрывания-открывания редактируемой модели в окне КОМПАСа).

Что делает пользователь, можно контролировать. Без кода тут бессмысленно разговаривать, я не могу понять, зачем закрывать программу, а также закрывать и открывать деталь?

Akew

Цитата: Sabahs от 30.03.16, 22:03:31
Без кода тут бессмысленно разговаривать
Вот, извольте.
В программе реализован интерактивный цикл (функция RunInteractiveCycle()).
//------------------------------------------------------------------------------
// Запустить интерактивный цикл
// ---
void RunInteractiveCycle() {
CString title_dialog = _T( "Функция RunInteractiveCycle" );

// Проверить, открыта ли модель, получить к ней доступ
ksDocument3DPtr thisDocument3D( MyKompasObject->ActiveDocument3D() );
if ( !thisDocument3D ) {
MessageBox( NULL, _T("thisDocument3D не получен (1)"), title_dialog, MB_OK|MB_ICONERROR ); return;
}

IKompasDocument3DPtr thisKompasDocument3D = IUnknownPtr( ksTransferInterface( thisDocument3D, ksAPI7Dual, 0), false);
if ( !thisKompasDocument3D ) {
MessageBox( NULL, _T("thisKompasDocument3D не получен (5)"), title_dialog, MB_OK|MB_ICONERROR ); return;
}

IPart7Ptr topPart7 = thisKompasDocument3D->TopPart;
if ( !topPart7 ) {
MessageBox( NULL, _T("topPart7 не получен (6)"), title_dialog, MB_OK|MB_ICONERROR ); return;
}

// Интерактивный цикл, пока пользователь его не остановит в диалоге-запросе
while(1) {
// 1. Выдать первый диалог (немодальный), чтобы пользователь провел операции с открытой моделью в КОМПАСе
MessageBox( NULL, _T("Работа программы приостановлена\n\nПроведите манипуляцию с моделью, вернитесь к этому сообщению и нажмите OK"), title_dialog, MB_OK|MB_ICONINFORMATION );

// 2. Программа возобновляет работу, определяет сделанные пользователем изменения с моделью и проводит с ней определенные действия

// 3. Выдать второй диалог (модальный) с запросом, продолжать ли интерактивный цикл; получить отклик
if ( MessageBox( ::GetActiveWindow(), _T("Закончить интерактивный цикл?"),
_T("Вопрос"), MB_ICONQUESTION | MB_YESNO ) == IDYES ) break;

}
// Конец работы с интерактивным циклом

MessageBox( NULL, _T("Работа цикла закончена"), title_dialog, MB_OK|MB_ICONINFORMATION );

}

Это бесконечный while с двумя диалогами-сообщениями.
Первый - для организации пользовательской паузы, во время которой пользователь выполняет те или иные операции в КОМПАС (редактирует открытую модель).
Пауза прерывается нажанием OK в этом диалоге.
Второй - с вопросом, продолжать ли интерактивный цикл. Если нет, то - выход из него.

Предположим, что пользователь должен построить кривые пересечения поверхностей (в панели инструментов "Пространственные кривые"), а программа - "отловить" эти кривые, и выполнить с ними какие-то действия (этот блок опущен, как не имеющий прямого отношения к рассматриваемой проблеме). Эти действия (указание пользователем кривых и их программная обработка) могут быть выполнены несколько раз.

В отсутствие программы - кривые строятся без проблем.
При запуске этого цикла - те же самые кривые не создаются. Наборы поверхностей - указываются, - и образ будущей кривой пересечения вроде бы появляется. Однако, кнопка "Создать объект" панели свойств остается неактивной.
Кроме того, в окошках наборов поверхностей иногда не появляются названия поверхностей, которые были указаны как исходные.

Эта проблема, как оказалось, серьезнее, чем представлялась вначале. А именно, если изначально модель в КОМПАСе не открывать, а в функции RunInteractiveCycle() убрать проверку наличия открытой модели, а во время пользовательской паузы открыть ту же модель, то построить кривую пересечения двух поверхностей тоже не удастся, - хотя, казалось бы, пользователь получает непосредственный доступ к модели. Таким образом, манипуляции с закрыванием-открыванием открытой модели не помогли бы.
В связи с этим, мой вопрос нужно сформулировать иначе: "Как получить доступ к моделям из интерактивного цикла?".

Прилагаю полный проект и образец модели, на которой наблюдал описанные феномены (Windows XP, Visual C++ 2005, КОМПАС v14).
В качестве первого набора поверхностей нужно указать плоскость ZX, второго - самые большие грани "кирпича" или шар (возможны и иные варианты). Как образец, одна такая кривая уже построена (на шаре).

P.S. Вы написали, что "Что делает пользователь, можно контролировать".
Как в приведенном интерактивном цикле можно проконтролировать, что пользователь завершил операцию "Кривая пересечения поверхностей", т.е., нажал "Создать объект" или "Прервать команду" (если этот вопрос не является отдельной темой)?

Т.е. Вы хотите сказать, что - MessageBox, штука не модальная?
По моему, проще сделать не модальную форму, кинуть на неё кнопку, по нажатию которой библиотека получит доступ к документу и сделает свои манипуляции, а наличие крестика поможет отключить библиотеку.
http://forum.ascon.ru/index.php/topic,22654.msg155743.html#msg155743

Akew

Цитата: Sabahs от 01.04.16, 06:05:25
Т.е. Вы хотите сказать, что - MessageBox, штука не модальная?
Насколько я знаю, все зависит от 1-го аргумента, указателя на родителя.
Если это будет реальный родитель, т.е.,::GetActiveWindow(), то MessageBox будет модальным.
Если NULL, то - не модальным.

ЦитироватьПо моему, проще сделать не модальную форму, кинуть на неё кнопку, по нажатию которой библиотека получит доступ к документу и сделает свои манипуляции, а наличие крестика поможет отключить библиотеку.
Поясните, пожалуйста:
1. Чем Ваша реализация будет отличаться от моей представленной? У моей формы, в MessageBox (тот, что первый), тоже есть кнопка, OK, после нажатия которой управление получает программа.
2. Не понял, для чего нужно отключать библиотеку (по "крестику"): в общем случае, после окончания работы с циклом пользователь должен иметь возможность продолжить работу с другими функциями библиотеки (включая и эту, с циклом).

Прием использования нескольких окон интересный, только пока не понял, как его приспособить к моей задаче.

И, все-таки, можно ли, используя мой способ, получить требуемый результат (в интерактивном цикле построить кривую пересечения двух поверхностей)?

Спасибо.

Вы свой результат уже получили, иногда мелочи, которых Вы не показываете, играют немаловажную роль.
PS. Я показывал просто вариант и кое какие, мелочи - это не означает,  что надо делать так, а не иначе.

Akew

Цитата: Sabahs от 01.04.16, 21:19:22
Вы свой результат уже получили, иногда мелочи, которых Вы не показываете, играют немаловажную роль.
Нужного результата, построение пользователем кривых в интерактивном цикле, нет.

Какие мелочи я не показал? Блок, который обрабатывает ("отлавливает") отстроенные пользователем кривые? А для решения данной вопроса он и не нужен, т.к. проблема в том, что пользователь не может построить эти кривые до этого блока, - сейчас у меня проблема только в этом.

Однако, если Вам нужна дополнительная информация ("мелочи"), то, пожалуйста, уточните, что именно, - представлю. Пока не понятно, что требуется (код - есть, модель - тоже, проблему описал, надеюсь, достаточно подробно).

Я считаю, что такая реализация, как сделана у Вас, является неправильной, где Вы передали управление из Вашего цикла, Компасу?
Оптимальный вариант смотреть в сторону событий Компаса, тем более там уже эти циклы присутствуют, перейдите по ссылке ниже, там есть кино, где показано, как это работает в отладчике.
http://forum.ascon.ru/index.php/topic,29269.msg224103.html#msg224103