Сообщество программистов Autodesk в СНГ

ADN Club => AutoCAD .NET API => Тема начата: JohnJ от 21-10-2014, 11:57:10

Название: Переключение на другой лист в другом открытом документе
Отправлено: JohnJ от 21-10-2014, 11:57:10
Добрый день! Открыто несколько документов, нужно сделать лист одного из документов активным.
Использую для этого следующий код:
Код - C# [Выбрать]
  1. if (DocumentActivate(doc_name)) {
  2.     LayoutManager.Current.CurrentLayout = layout_name;
  3. }
  4.  
где
Код - C# [Выбрать]
  1. public bool DocumentActivate(string doc_name) {
  2.             try {
  3.                 if (DocumentManager.MdiActiveDocument.Name == doc_name) return true;
  4.                 var document = DocumentManager.Cast<Document>().First(doc => doc.Name == doc_name);
  5.                 if (document == null) return false;
  6.                 using (DocumentManager.MdiActiveDocument.LockDocument()) {
  7.                     DocumentManager.MdiActiveDocument = document;
  8.                 }
  9.                 return true;
  10.             } catch (Exception exception) {
  11.                 MessageBox.Show(exception.Message);
  12.             }
  13.             return false;
  14.         }
  15.  
c# autocad 2012

На строке LayoutManager.Current.CurrentLayout = layout_name; выскакивает ошибка: eSetFailed. Подозреваю, что связана она с тем, что текущий документ ещё не стал текущим. Если вписать перед этой строкой return (прервать выполнение метода), то автокад ждёт бесконечно долго. Если закрыть окно моего плагина - документ в автокаде тут же переключится на указанный ранее в программе. Как сделать, что бы документ переключался сразу, а моя программа получила управление для продолжения действий по завершению переключения?
Я уже пробовал и DoEvents() и Editor.Update и даже Editor.Regenerate и AcApplication.UpdateScreen(). Ничего не помогло что-то...
Название: Re: Переключение на другой лист в другом открытом документе
Отправлено: Александр Ривилис от 21-10-2014, 11:59:20
Ты этот код выполняешь в команде?
Название: Re: Переключение на другой лист в другом открытом документе
Отправлено: JohnJ от 21-10-2014, 12:01:05
командой запускается окно (через ShowDialog, хотя пробовал уже и Show просто), на окне нажимается кнопка, которая выполняет этот код.
У команды указан флаг CommandFlags.Session
Название: Re: Переключение на другой лист в другом открытом документе
Отправлено: Александр Ривилис от 21-10-2014, 12:07:22
Попробуй перед выполнением DocumentActivate вызвать
Код - C# [Выбрать]
  1. DocumentManager.DocumentActivationEnabled = true;
Я не могу понять зачем вот это у тебя в коде:
Код - C# [Выбрать]
  1.                 using (DocumentManager.MdiActiveDocument.LockDocument()) {
  2.                     DocumentManager.MdiActiveDocument = document;
  3.                 }
Зачем блокировать старый активный документ при переключении в новый?
Название: Re: Переключение на другой лист в другом открытом документе
Отправлено: JohnJ от 21-10-2014, 12:13:06
чуть подправил метод  DocumentActivate - исправил неточность с return true и false.
Блокировка старого документа осталась от экспериментов, пока я не узнал про CommandFlags.Session
Если это не требуется, я сейчас попробую убрать лишнее действие.
Теперь метод стал таким:
Код - C# [Выбрать]
  1.         public bool DocumentActivate(string doc_name) {
  2.             try {
  3.                 if (DocumentManager.MdiActiveDocument.Name == doc_name) return true;
  4.                 DocumentManager.DocumentActivationEnabled = true;
  5.                 var document = DocumentManager.Cast<Document>().First(doc => doc.Name == doc_name);
  6.                 if (document == null) return false;
  7.                 DocumentManager.MdiActiveDocument = document;
  8.                 return true;
  9.             } catch (Exception exception) {
  10.                 MessageBox.Show(exception.Message);
  11.             }
  12.             return false;
  13.         }
  14.  

Но реакция не изменилась - та же ошибка в том же месте.
Название: Re: Переключение на другой лист в другом открытом документе
Отправлено: JohnJ от 21-10-2014, 12:16:01
Сейчас перечитал ваш совет: убрал DocumentManager.DocumentActivationEnabled = true; из метода и перенёс перед его вызовом. В результате ошибка eInvalidContext на этой строке. Это свойство перед выполнением этой строки уже имеет значение true, возможно поэтому выдаётся ошибка?
Название: Re: Переключение на другой лист в другом открытом документе
Отправлено: Александр Ривилис от 21-10-2014, 12:16:51
Тебе вообще-то нужно блокировать новый документ, а не старый.
Название: Re: Переключение на другой лист в другом открытом документе
Отправлено: Александр Ривилис от 21-10-2014, 12:18:23
Сейчас перечитал ваш совет: убрал DocumentManager.DocumentActivationEnabled = true; из метода и перенёс перед его вызовом. В результате ошибка eInvalidContext на этой строке
Нужно сначала проверить состояние DocumentActivationEnabled, и если оно false переключить на true.
Название: Re: Переключение на другой лист в другом открытом документе
Отправлено: Александр Ривилис от 21-10-2014, 12:23:20
Кстати, а почему ShowDialog, а не Application.ShowModalDialog ???
Название: Re: Переключение на другой лист в другом открытом документе
Отправлено: JohnJ от 21-10-2014, 12:27:42
всегда использовал такой способ: (new MyForm()).ShowDialog();
Сейчас попробую сделать как вы сказали.
Итог: в случае ShowModalDialog DocumentActivationEnabled была false.
Ошибка eSetFailed осталась.
Название: Re: Переключение на другой лист в другом открытом документе
Отправлено: Александр Ривилис от 21-10-2014, 12:30:12
всегда использовал такой способ: (new MyForm()).ShowDialog();
Неправильно. В AutoCAD нужно использовать Application.ShowModalDialog.
Ошибка eSetFailed осталась.
Вполне возможно, что в этом контексте нельзя переключится на другой лист. А зачем тебе это нужно?
Название: Re: Переключение на другой лист в другом открытом документе
Отправлено: JohnJ от 21-10-2014, 12:43:15
нужно использовать Application.ShowModalDialog
Спасибо! Буду теперь использовать такой подход.

Возможно как-то можно с помощью Interop?
Моя форма содержит список листов всех открытых документов, нужно что бы выбранный лист экспортировался в модель. В рамках одного документа программа работает, а вот при двух уже не может переключиться на другой документ как мне необходимо.
Экспорт работает только для активного листа и выдаёт ошибку, если лист экспортируется до его активации.
Название: Re: Переключение на другой лист в другом открытом документе
Отправлено: Александр Ривилис от 21-10-2014, 13:01:23
Если закрыть окно моего плагина - документ в автокаде тут же переключится на указанный ранее в программе.
Ну попробуй тогда закрывать окно, переключаться и снова запускать окно.
Название: Re: Переключение на другой лист в другом открытом документе
Отправлено: JohnJ от 21-10-2014, 13:05:34
а как отследить, что документ уже поменялся и можно снова запускаться?
Название: Re: Переключение на другой лист в другом открытом документе
Отправлено: Александр Ривилис от 21-10-2014, 13:11:40
а как отследить, что документ уже поменялся и можно снова запускаться?
Вообще-то по событию DocumentCollection.DocumentActivated
Давай попробуем еще одну вещь:
1) После вызова DocumentActivate() переключи HostApplicationServices.WorkingDatabase на новую базу
2) Блокируй новую базу
3) Вызывай LayoutManager.Current.CurrentLayout = layout_name;
Название: Re: Переключение на другой лист в другом открытом документе
Отправлено: JohnJ от 21-10-2014, 13:49:36
Так ошибка не вылетает, однако документ визуально по прежнему не меняется, а после закрытия программы меняется, но в нём становится активна модель, причём забавно так ведёт себя - выглядит как лист, но рисунок на нём меньше, чем нужно, раз в 20-30. При перемещении взгляда мышкой по модели она двигается лишь немного, по сравнению с тем, как должна.
При переключении на лист и обратно ничего хорошего - фон становится чёрный. но изображения в модели не видно и оно не появляется по двойному щелчку колёсика мышки.
Название: Re: Переключение на другой лист в другом открытом документе
Отправлено: JohnJ от 21-10-2014, 13:55:03
Интересно, что если вызвать команду DocumentManager.Open(doc_name), то документ откроется и обновится окно так, как и ожидается. Возможно, это можно использовать как обходной манёвр. Тем более, что в будущем всё-равно предполагается, что работа будет идти с не открытыми ещё документами, которые будут открываться в Автокаде для выполнения экспорта...
Название: Re: Переключение на другой лист в другом открытом документе
Отправлено: JohnJ от 21-10-2014, 14:14:35
Бестолку, MdiActiveDocument всё-равно не меняется, даже после Open
Название: Re: Переключение на другой лист в другом открытом документе
Отправлено: Александр Ривилис от 21-10-2014, 14:16:34
Начнем с начала. Какая версия AutoCAD? Какое значение системной переменной FIBERWORLD?
Название: Re: Переключение на другой лист в другом открытом документе
Отправлено: JohnJ от 21-10-2014, 14:20:06
автокад 2012 (в первом сообщении писал).
Если нужно подробнее, то в "О программе" Версия продукта: F.51.0.0
64битный

FIBERWORLD = 0 (только чтение)
Название: Re: Переключение на другой лист в другом открытом документе
Отправлено: Александр Ривилис от 21-10-2014, 14:22:45
NEXTFIBERWORLD в 1 и перезапусти AutoCAD. Потом продолжай тестировать.
Название: Re: Переключение на другой лист в другом открытом документе
Отправлено: JohnJ от 21-10-2014, 14:29:23
Переключение сработало! :)
Я вспомнил, что ставил эту переменную в 0, так как с ней не работала отладка (где-то в интернете нашёл рецепт). Сейчас вроде сработала и отладка тоже, только странно как-то (после нажатия на кнопку на моей форме сначала завис автокад, потом я нажал на паузу в VS, оказался на строке Application.ShowModalDialog(new MyForm()); нажал Продолжить и оказался в нужной точке останова). Буду ещё проверять.
Название: Re: Переключение на другой лист в другом открытом документе
Отправлено: Александр Ривилис от 21-10-2014, 14:35:26
оказался на строке Application.ShowModalDialog(new MyForm()); нажал Продолжить и оказался в нужной точке останова).
С отладкой у тебя будут проблемы.
С FIBERWORLD == 1 плохо работает отладка (исправляется только переключением FIBERWORLD на 0)
С FIBERWORLD == 0 очень плохо работает Лента (Ribbon), переключение документов и еще что-то...
Так что выбирай из двух зол меньшее.
Название: Re: Переключение на другой лист в другом открытом документе
Отправлено: JohnJ от 21-10-2014, 14:37:30
понятно, спасибо огромное!
Такие проблемы с отладкой, как я понял, сохранились и в Autocad2014, а в 2015 они есть, или эту проблему решили в новых версиях?
Название: Re: Переключение на другой лист в другом открытом документе
Отправлено: Александр Ривилис от 21-10-2014, 14:43:13
Такие проблемы с отладкой, как я понял, сохранились и в Autocad2014, а в 2015 они есть, или эту проблему решили в новых версиях?
В 2014 тоже самое, т.к. для него нормальный режим работы FIBERWORLD == 1, а в 2015 этой проблемы нет, т.к. в нём в нормальном состоянии FIBERWORLD == 0.
Это скорее проблема Microsoft (отладчика VS), чем Autodesk. Насколько я помню до VS 2005 включительно отладчик нормально работал с FIBERWORLD == 1 (точнее в тех версиях AutoCAD нельзя было переключится на FIBERWORLD == 0)
Название: Re: Переключение на другой лист в другом открытом документе
Отправлено: JohnJ от 21-10-2014, 14:46:03
спасибо ещё раз! даже не знаю, какое сообщение выбрать как ответ, видимо про FIBER... Всё-таки в этом оказалась причина.