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

ADN Club => AutoCAD .NET API => Тема начата: JohnLennin от 19-11-2013, 23:55:09

Название: Работа с графикой и интерфейсная форма
Отправлено: JohnLennin от 19-11-2013, 23:55:09
Коллеги!

Честно скажу - где-то я про это читал, но к сожалению не могу теперь найти на просторах интернета где именно, может подскажете. :'(
Проблема следующая - чего-то накодил, все работает нормально, когда команды вызваются из командной строки автокада.
Однако, необходимо, чтобы они вызвались из формы с кнопочками, списками, которые генерятся из СУБД и т.п.
Форму слава богу нарисовал и даже вызываю ее, она показывается, кнопочки нажимаются, списки заполняются, однако, когда на форме нажимаю кнопочку вставить объект в чертеж и вызываю команду этой самой вставки - необходимо точку вставки вместе с объектом выбрать на чертеже и тут вываливается ошибка eLockViolation.
При этом если эту команду вызвать руками например из командной строки или отдельно компильнуть без формы - все замечатльно работает.
Где-то я что-то читал по поводу того, что надо что-то с формой делать и штуки типа Form1.ActiveForm.Show() Form1.ActiveForm.Hide() недостаточно чтобы все нормально заработало, но к сожалению, сейчас не могу найти где именно это было написано с подробностями и как с этим бороться.
Ошибка вываливается на строке (4) в котрой делаю запись в таблицу с блоками.
Код - vb.net [Выбрать]
  1. If sampstatus = "OK" Then
  2.    Using myT As Transaction = tm.StartTransaction()
  3.      Dim bt As BlockTable = DirectCast(tm.GetObject(db.BlockTableId, OpenMode.ForRead, False), BlockTable)
  4.      Dim btr As BlockTableRecord = DirectCast(tm.GetObject(bt(BlockTableRecord.ModelSpace), OpenMode.ForWrite, False), BlockTableRecord)
  5.      btr.AppendEntity(mvb)
  6.      tm.AddNewlyCreatedDBObject(mvb, True)
  7.      myT.Commit()
  8.    End Using
  9. End If

UPD: Нашел где это было
http://forums.autodesk.com/t5/NET/eLockViolation-when-trying-to-draw-from-a-command-on-a-form/td-p/1348038 (http://forums.autodesk.com/t5/NET/eLockViolation-when-trying-to-draw-from-a-command-on-a-form/td-p/1348038)
Исправляется путем Lock'а активного документа, перед всем этим безобразием надо написать:
Код - vb.net [Выбрать]
  1.  Dim doc1 As Document = Application.DocumentManager.MdiActiveDocument
  2.  Dim dl As DocumentLock = doc1.LockDocument
И тогда все заработало.
Стоит оставить эту тему, т.к. с этим часто все кто начинает писать в таблицы через интерфейсные формы сталкивается.
Название: Re: Работа с графикой и интерфейсная форма
Отправлено: Александр Ривилис от 20-11-2013, 01:59:30
Правильнее было бы использовать такой код:
Код - vb.net [Выбрать]
  1. Dim doc As Document = Application.DocumentManager.MdiActiveDocument
  2. Using acLckDoc As DocumentLock = doc.LockDocument()
  3.  '  здесь код который модифицирует документ
  4. End Using
Этот код гарантирует то, что документ будет разблокирован даже если возникнет исключение.

P.S.: Кстати на нашем сайте есть такая переводная статья: В каких случаях следует блокировать документ (http://adn-cis.org/v-kakix-sluchayax-sleduet-blokirovat-dokument.html)
Название: Re: Работа с графикой и интерфейсная форма
Отправлено: JohnLennin от 20-11-2013, 08:41:39
Спасибо Александр!
Действительно так будет вернее. И за ссылку на статью спасибо!
Скорее всего я ее и читал когда-то, просто голова в последнее время совсем дырявая стала, слишком много в ней приходится держать оперативной информации, а времени чтобы систематизировать и структурировать долгосрочные знания как всегда не хватает. Все приходится делать "галопом по Европам". Вот и выпадают фрагменты из памяти  :o
Название: Re: Работа с графикой и интерфейсная форма
Отправлено: JohnLennin от 20-11-2013, 10:46:45
И еще такой вопросик - как обычно принято делать переключение между диалоговым окном и рабочим пространством autocad? В том смысле, чтобы диалоговое окно не мешало тыкать мышкой в пространство модели.
Просто сворачивать? а если например надо поменять какие-то параметры в диалоговом окне - его опять разворачивать?
Может тупо  Autodesk.AutoCAD.Internal.Utils.SetFocusToDwgView()?
Название: Re: Работа с графикой и интерфейсная форма
Отправлено: Александр Ривилис от 20-11-2013, 12:52:35
Обычно принято (на этом форуме) один вопрос - одна тема.  :)
А если серьезно, то всё зависит от того какая форма и что от неё требуется. Если форма модальная, то она должна быть закрыта в любом случае. Если форма немодальная и небольшая, то может оставаться на экране. Если большая, то нужно скрывать/восстанавливать, так как она будет закрывать кусок рабочего пространства.
Может тупо  Autodesk.AutoCAD.Internal.Utils.SetFocusToDwgView()?
Вопрос только где это делать? Нужно же оставить возможность переключиться на эту форму.
Название: Re: Работа с графикой и интерфейсная форма
Отправлено: Anton от 22-01-2014, 12:32:59
Присоединяюсь ко второй части вопроса про Autodesk.AutoCAD.Internal.Utils.SetFocusToDwgView.
Как вернуть фокус обратно на форму?
Смысл примерно такой-же - есть форма, в ней произвели какие-то манипуляции, дальше вызываем команду Autodesk.AutoCAD.Internal.Utils.SetFocusToDwgView, опять производим манипуляции, а затем надо сделать фокус обратно на форму, вопрос какой командой?
Название: Re: Работа с графикой и интерфейсная форма
Отправлено: Дмитрий Загорулькин от 22-01-2014, 12:45:05
http://adndevblog.typepad.com/autocad/2012/05/taking-mouse-inputs-from-a-modal-dialog-box.html
Название: Re: Работа с графикой и интерфейсная форма
Отправлено: Anton от 22-01-2014, 15:33:48
Спасибо большое Дмитрий за линк. Эта штука в принципе мне подходит, хотя и работает только с модальными формами. Вполне допускаю что переделать немного интерфейс и сделать вызывающее окно модальным будет правильнее.
Выделю здесь основные моменты, чтобы другим времени зря не терять

Код - vb.net [Выбрать]
  1.         Dim doc As Autodesk.AutoCAD.ApplicationServices.Document = _
  2.                   Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument
  3.         Dim ed As Autodesk.AutoCAD.EditorInput.Editor = doc.Editor
  4.         ' Активируем editor
  5.         Using UI As Autodesk.AutoCAD.EditorInput.EditorUserInteraction = ed.StartUserInteraction(Me)
  6.              ' Здесь производим все необходимые нам манипуляции в редакторе AutoCAD
  7.          End Using ' возвращаемся обратно в модальное окно
  8.  
Да еще, при миграции на 2013-2014 надо в 5 строке Me дополнить Me.Handle
Код - vb.net [Выбрать]
  1. Using UI As Autodesk.AutoCAD.EditorInput.EditorUserInteraction = ed.StartUserInteraction(Me.Handle)
  2.  
Напеределали они в 2013 немного, часть функционала перекидали в accoremgd.dll, чтобы не скучно жить было, а то расслабились понимаешь с 2007 версии никаких кардинальных изменений  ;)
Название: Re: Работа с графикой и интерфейсная форма
Отправлено: Александр Ривилис от 22-01-2014, 22:37:58
Как вернуть фокус обратно на форму?
Смысл примерно такой-же - есть форма, в ней произвели какие-то манипуляции, дальше вызываем команду Autodesk.AutoCAD.Internal.Utils.SetFocusToDwgView, опять производим манипуляции, а затем надо сделать фокус обратно на форму, вопрос какой командой?
1. http://www.pinvoke.net/default.aspx/user32.setfocus - это как записать P/Invoke для функции SetFocus из Windows API. Ей требуется один параметр - HWND формы.
2. Чтобы найти HWND для твоей формы используй метод Form.Handle
Название: Re: Работа с графикой и интерфейсная форма
Отправлено: Андрей Бушман от 29-01-2014, 11:36:41
P.S.: Кстати на нашем сайте есть такая переводная статья: В каких случаях следует блокировать документ (http://adn-cis.org/v-kakix-sluchayax-sleduet-blokirovat-dokument.html)
Такой момент: предположим, что изначально метод был написан со значением Session (помимо прочих) в атрибуте, и в коде использовалась блокировка (LockDocument в блоке using) некоторого документа, с которым выполнялась работа.

Позднее разработчик вдруг решает, мол пусть этот метод будет работать лишь с текущим документом и изменил код так, что работа ведётся в MdiActiveDocument. В свете оного программист убирает в атрибуте значение Session, но забывает удалить обозначенный выше блок кода, который на некоторое время блокирует документ. Получается, что автокад сам блокирует документ, а тут ещё и программист пытается сделать то же самое, т.е. блокировать уже блокированный документ... В подобной ситуации я бы ожидал генерации исключения (Exception) , но оно не происходит и код, на котором я моделировал обозначенную ситуацию, работает как нужно.

Могут ли в обозначенной мною ситуации всё же возникать какие-либо проблемы?

Небольшое замечания по ссылке (http://adn-cis.org/v-kakix-sluchayax-sleduet-blokirovat-dokument.html).
Цитата: Александр Ривилис
// изменим значение 'TILEMODE ' одного из документов
Не "одного", а всех кроме текущего (комментарий не соответствует коду).
Название: Re: Работа с графикой и интерфейсная форма
Отправлено: Александр Ривилис от 29-01-2014, 18:44:41
Небольшое замечания по ссылке.
Цитата: Александр Ривилис

    // изменим значение 'TILEMODE ' одного из документов

Не "одного", а всех кроме текущего (комментарий не соответствует коду).
Согласен. Исправил. В оригинальной статье таже неточность.
Название: Re: Работа с графикой и интерфейсная форма
Отправлено: Александр Ривилис от 29-01-2014, 19:10:08
Позднее разработчик вдруг решает, мол пусть этот метод будет работать лишь с текущим документом и изменил код так, что работа ведётся в MdiActiveDocument. В свете оного программист убирает в атрибуте значение Session, но забывает удалить обозначенный выше блок кода, который на некоторое время блокирует документ. Получается, что автокад сам блокирует документ, а тут ещё и программист пытается сделать то же самое, т.е. блокировать уже блокированный документ... В подобной ситуации я бы ожидал генерации исключения (Exception) , но оно не происходит и код, на котором я моделировал обозначенную ситуацию, работает как нужно.

Могут ли в обозначенной мною ситуации всё же возникать какие-либо проблемы?

Никаких проблем. Просто если в команде нет атрибута Session, то она выполняется в контексте документа и Application.DocumentManager.MdiActiveDocument.LockDocument просто игнорируется.
Название: Re: Работа с графикой и интерфейсная форма
Отправлено: Андрей Бушман от 29-01-2014, 19:14:23
Значит можно везде писать блокировку документа на всякий случай, чтобы если в будущем вдруг потребуется работать в контексте приложения,  то не приходилось бы судорожно перелопачивать код и добавлять необходимые юзинги. Можно будет просто добавлять атрибут и не беспокоиться о том, что у юзера "вдруг" всё встанет на уши.
Название: Re: Работа с графикой и интерфейсная форма
Отправлено: Александр Ривилис от 29-01-2014, 19:19:32
Да. Во всяком случае во всех существующих версиях AutoCAD .NET API "лишний" вызов LockDocument в контексте документа не приводит ни к каким отрицательным последствиям.