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

ADN Club => AutoCAD .NET API => Тема начата: trir от 14-05-2015, 12:43:43

Название: Открыть .dwg на нужном листе
Отправлено: trir от 14-05-2015, 12:43:43
тут (http://forum.dwg.ru/showthread.php?t=60781) есть пример, как сделать гиперссылку на лист в dwg
Цитировать
C:\Папка\файл.dwg#,Лист5
Хочу повторить для wpf Hyperlink, но ничего не получается  :-\
так открывается файл:
Код - C# [Выбрать]
  1.         private void OnRequestNavigate(object sender, RequestNavigateEventArgs e)
  2.         {            
  3.             System.Diagnostics.Process.Start(e.Uri.LocalPath);
  4.         }
а как открыть на нужном листе?
Название: Re: Открыть .dwg на нужном листе
Отправлено: Александр Ривилис от 14-05-2015, 13:08:26
Так я думаю и не получится. То, что AutoCAD понимает такой вид ссылок, не означает что и Windows их понимает.
Название: Re: Открыть .dwg на нужном листе
Отправлено: Александр Ривилис от 14-05-2015, 13:22:01
Я вижу пока только один вариант - запуск acad.exe с ключом /b, указывающим scr-файл, в котором содержится:
Код - INI [Выбрать]
  1. _layout
  2. _set
  3. Лист5
Название: Re: Открыть .dwg на нужном листе
Отправлено: Андрей Бушман от 14-05-2015, 13:40:13
А ключ /v как работает? Я ожидал, что с его помощью можно указать пользовательский именованный вид, при назначении которого автоматом происходит переключение на соответствующий лист. Однако по факту вижу, что текущим он не становится:
Код - C# [Выбрать]
  1. Process proc = new Process();
  2. ProcessStartInfo info = new ProcessStartInfo(
  3.   @"C:\Program Files\Autodesk\AutoCAD 2009\acad.exe",
  4.   "\"\\\\Aleph\\Обмен\\Бушман\\123.dwg\" /v \"111\" /nologo");
  5. proc.StartInfo = info;
  6. proc.Start();
В консоли вижу сообщение:
Цитировать
Can't restore initial Paper space view 111 in Model Tab.Regenerating model.
Не срабатывает и в AutoCAD 2016. Если вручную указать именованный вид, то переключение на его Layout происходит.
Название: Re: Открыть .dwg на нужном листе
Отправлено: Александр Ривилис от 14-05-2015, 13:53:55
Этот вариант я тоже рассматривал, хотя сразу понимал, что он не сработает.
Название: Re: Открыть .dwg на нужном листе
Отправлено: Андрей Бушман от 14-05-2015, 14:07:02
Вы проигнорировали мой вопрос относительно магнитофона. И на основании чего вы "сразу понимали"? Насколько я вижу, /v работает, если именованный вид находится на вкладке Model, а вот при размещении на листах - не хочет.
Название: Re: Открыть .dwg на нужном листе
Отправлено: Александр Ривилис от 14-05-2015, 14:11:07
Вы проигнорировали мой вопрос относительно магнитофона.
Этот:
А ключ /v как работает?
?
Я так понял, что ты уже сам разобрался. Если именованный вид - Layout View и в сохраненном dwg-файле текущий один из Layout, то этот вид для него устанавливается. Если в сохраненном dwg-файле текущий - модель, то показывает сообщение о невозможности установить этот вид.
Ключ /v в любом случае не переключает листы, а пытается применить указанный вид к текущему листу/модели.
Название: Re: Открыть .dwg на нужном листе
Отправлено: Андрей Бушман от 14-05-2015, 14:14:16
Я клоню к тому, что если /v предназначен для установки текущим указанного вида, то не важно, где этот вид размещён (в модели или на листе) - он просто должен быть активирован. Если при этом потребуется переключиться на лист - это должно быть сделано. Короче - это баг (имхо).
Название: Re: Открыть .dwg на нужном листе
Отправлено: Александр Ривилис от 14-05-2015, 14:17:01
Короче - это баг (имхо).
Нет. Это By Design. Так было всегда - еще тогда, когда в AutoCAD не было ни одного Layout вообще, а всё было Model, но виды уже тогда были.
Название: Re: Открыть .dwg на нужном листе
Отправлено: Андрей Бушман от 14-05-2015, 14:27:31
Нет. Это By Design. Так было всегда - еще тогда, когда в AutoCAD не было ни одного Layout вообще, а всё было Model, но виды уже тогда были.
От версии к версии Autodesk развивает изменяет API. Каждые три года меняет формат DWG. Если теперь документ может содержать много листов, то и этот самый "By Design" должен это учитывать. В противном случае получаем несоответствие функционала с текущим форматом документа и возможностями приложения, доступными пользователю через его "ручки". Я помню и про кривую работу свойства, указывающего наличие/отсутствие атрибутов у динамического блока - тоже "By Design"... Называть это можно как угодно, однако, если заявленный функционал не работает в соответствии со своим заявлением - то это баг. Смотрим описание ключа здесь (http://knowledge.autodesk.com/support/autocad/troubleshooting/caas/sfdcarticles/sfdcarticles/Startup-switches-for-AutoCAD.html):
Цитировать
/v - View name
Никаких "но", "если" и т.п. не обозначено. Я воспринимаю информацию именно так, как она написана. Текущее описание не соответствует реальному поведению (т.е. не каждый видовой экран будет корректно обработан).
Название: Re: Открыть .dwg на нужном листе
Отправлено: Александр Ривилис от 14-05-2015, 14:42:48
Называть это можно как угодно, однако, если заявленный функционал не работает в соответствии со своим заявлением - то это баг. Смотрим описание ключа здесь:

А если нельзя установить вид без переключения Layout?

Короче говоря. Это тянет в лушем случае на Wish List. Ну и учти про Что такое ‘business case’ и как с ним бороться? (http://adn-cis.org/forum/index.php?topic=2640.0)
Я специально порылся в интернете и не нашел ни одного вопроса по переключению Layout при помощи ключа /v. Это значит, что число тех, кому это необходимо стремится к 0. Кому это нужно - или переключат вручную, или напишут пару строк в scr-файл:
Код - INI [Выбрать]
  1. _-view
  2. _restory
  3. <имя вида>
Ну или вообще напишут программу.
Название: Re: Открыть .dwg на нужном листе
Отправлено: Андрей Бушман от 15-05-2015, 10:25:41
Как вариант. Проверял в AutoCAD 2016 Enu x64.
Код - C# [Выбрать]
  1. /* © Andrey Bushman, 2015
  2.  * This code adds capability to point additional key with its argument to
  3.  * acad.exe. This key allows set current necessary Layout (or Model) tab:
  4.  * Its signature: /layout "LayoutName"
  5.  *
  6.  * WARNING: It are to place AFTER your DWG file name.
  7.  *
  8.  * For example, you can use it in the BAT-file:
  9.  * call "%ProgramFiles%\Autodesk\AutoCAD 2016\acad.exe" /nologo "C:\public\data\test.dwg"  /layout "My Some Layout"
  10.  *
  11.  * ExtensionApplication.cs
  12.  */
  13. using System;
  14. using System.Collections.Generic;
  15. using System.Linq;
  16.  
  17. #if AUTOCAD
  18. using cad = Autodesk.AutoCAD.ApplicationServices.Application;
  19. using Autodesk.AutoCAD.ApplicationServices;
  20. using Autodesk.AutoCAD.DatabaseServices;
  21. using Autodesk.AutoCAD.EditorInput;
  22. using Autodesk.AutoCAD.Runtime;
  23. #endif
  24.  
  25. [assembly: ExtensionApplication(typeof(LayoutSwitchingSample.ExtensionApplication))]
  26.  
  27. namespace LayoutSwitchingSample {
  28.  
  29.   public sealed class ExtensionApplication : IExtensionApplication {
  30.     public void Initialize() {
  31.       Document doc = cad.DocumentManager.MdiActiveDocument;
  32.       if (null == doc)
  33.         return;
  34.  
  35.       Database db = doc.Database;
  36.       Editor ed = doc.Editor;
  37.       using (doc.LockDocument()) {
  38.         using (Transaction tr = db.TransactionManager.StartTransaction()) {
  39.           ed.WriteMessage("\nThe \"{0}\" assembly successfully loaded.\n",
  40.             this.GetType().Assembly.Location);
  41.  
  42.           String[] args = Environment.GetCommandLineArgs().Select(n =>
  43.             n.ToLower()).ToArray();
  44.           const String key = "/layout";
  45.           String layoutName = String.Empty;
  46.           layoutName = GetLayoutName(args, key);
  47.           if (!String.IsNullOrEmpty(layoutName)) {
  48.             cad.SetSystemVariable("CTAB", layoutName);
  49.           }
  50.  
  51.           tr.Commit();
  52.         }
  53.       }
  54.     }
  55.  
  56.     private string GetLayoutName(string[] args, String key) {
  57.       if (null == args) {
  58.         return null;
  59.       }
  60.       Int32 index = Array.IndexOf(args, key);
  61.       if (args.GetLowerBound(0) - 1 == index || index == args.Length - 1) {
  62.         return null;
  63.       }
  64.       String layoutName = args[index + 1];
  65.       return layoutName;
  66.     }
  67.  
  68.     public void Terminate() {
  69.       // Nothing is here
  70.     }
  71.   }
  72. }
Название: Re: Открыть .dwg на нужном листе
Отправлено: Александр Ривилис от 15-05-2015, 13:21:22
В качестве идеи работы со строкой запуска AutoCAD - очень хорошо. Но сразу возникает несколько вопросов:
1) Потребуется как минимум несколько сборок для поддержки различных версий AutoCAD, которые должны быть зарегистрированы в системе для автоматической загрузки в AutoCAD. В зависимости от версии потребуются различные методы загрузки.
2) Метод Initialize() может быть вызван до того, как dwg-файл будет полностью загружен. Даже чтение информации из dwg-файла в этом методе является рискованным, а изменение её и подавно. Так что этот код следовало бы как-то модифицировать.
Название: Re: Открыть .dwg на нужном листе
Отправлено: Андрей Бушман от 15-05-2015, 14:01:43
1) Потребуется как минимум несколько сборок для поддержки различных версий AutoCAD, которые должны быть зарегистрированы в системе для автоматической загрузки в AutoCAD.
Обычно я автоматически компилирую три сборки: под 2009, 2013 и 2015. Диапазон их применения: AutoCAD 2009-2016. Кроме того, создаю единую точку входа (http://bushman-andrey.blogspot.ru/2014/06/dll-autocad.html), которую и регистрирую в автозагрузку для каждой интересной мне версии AutoCAD.
В зависимости от версии потребуются различные методы загрузки.
О каких "различных методах загрузки" речь и какое отношение это имеет к коду? Регистрация в реестре работает во всех версиях AutoCAD. Использовать не доведённый до ума механизм Bundle пакетов вместо регистрации в реестре можно по своему усмотрению. Текущее его состояние я не проверял, но мне достаточно того, что отсутствие внятной и корректной его спецификации преподносится компанией автодеск как "благо" для программистов (даже комментировать это не хочу) и то, что формат конфиг-файла может автодеском произвольно меняться как перчатки (уже спотыкался об это).

Например, помнится нельзя было отключить автозагрузку Bundle пакета, т.к. соответствующая настройка в конфиг-файле пакета попросту игнорировалась данным механизмом. В качестве решения проблемы автодеск предлагала временно переименовывать каталог (вместо суффикса ".bundle" набирать абракадабру).
Цитировать
2) Метод Initialize() может быть вызван до того, как dwg-файл будет полностью загружен. Даже чтение информации из dwg-файла в этом методе является рискованным, а изменение её и подавно. Так что этот код следовало бы как-то модифицировать.
В моих тестах этого не происходило. Если такая опасность существует то, конечно же, её следует обойти. ПредлОжите способ получения извещения о завершении инициализации документа? Что автодеск рекомендует по данному вопросу? :)
Название: Re: Открыть .dwg на нужном листе
Отправлено: Александр Ривилис от 15-05-2015, 14:22:16
ПредлОжите способ получения извещения о завершении инициализации документа?
Думаю что достаточно будет выполнить твой код из главного потока: http://adn-cis.org/ispolzovanie-potokov-dlya-fonovoj-obrabotki.html
По поводу того каким образом реализовывать автозагрузку. Я тоже предпочитаю использовать реестр. Этот способ более универсальный.
Название: Re: Открыть .dwg на нужном листе
Отправлено: Андрей Бушман от 15-05-2015, 15:46:17
Думаю что достаточно будет выполнить твой код из главного потока: http://adn-cis.org/ispolzovanie-potokov-dlya-fonovoj-obrabotki.html
В обозначенной по ссылке статье используется костыль из WinForm контрола, но возможно есть иной, более простой путь (предлагаемый вариант обозначен ниже)... Кроме того, перевод не корректен: задача и поток - это четыре совершенно разных человека.

Применительно к запуску в основном потоке: ну так можно методы Initialize() и Terminate() просто пометить атрибутом STAThread (https://msdn.microsoft.com/ru-ru/library/system.stathreadattribute%28v=vs.110%29.aspx) и будут они вызываться в основном потоке (поправьте меня, если я не прав). Ведь методы main приложений WinForms и WPF именно этим атрибутом и помечены. Или считаете, что этого будет не достаточно и нужно обязательно лепить костыль с контролом WinForms, обозначенный в статье?

И, откровенно говоря, я не понимаю, какое отношение потоки имеют к данному вопросу с кодом в методе Initialize(), ведь я не запрашивал создание дополнительного фонового потока.
Название: Re: Открыть .dwg на нужном листе
Отправлено: Александр Ривилис от 15-05-2015, 18:21:06
Кроме того, перевод не корректен: задача и поток - это четыре совершенно разных человека.
У слова "поток" в русском языке есть несколько значений. Правильнее было бы тогда переводить как "поток выполнения", но это слишком длинно. Классический же перевод для "thread" в контексте языков программирования, которому уже лет тридцать - "задача".
Название: Re: Открыть .dwg на нужном листе
Отправлено: Александр Ривилис от 15-05-2015, 18:22:55
Применительно к запуску в основном потоке: ну так можно методы Initialize() и Terminate() просто пометить атрибутом STAThread и будут они вызываться в основном потоке (поправьте меня, если я не прав).
Не прав. Если бы это было так просто, то достаточно было бы пометить все необходимые методы этим атрибутом и тогда AutoCAD сразу же стал бы многозадачным (точнее стал бы поддерживать многозадачное обращение к своим объектам, в том числе и Database). :)
Название: Re: Открыть .dwg на нужном листе
Отправлено: Александр Ривилис от 15-05-2015, 18:36:48
Еще один из вариантов для проверки того, что чертеж уже полностью открыт - событие Database.DwgFileOpened
Но тут могут быть нюансы, так как если чертеж уже открыт до вызова метода Initialize(), то события Database.DwgFileOpened для уже открытого чертежа мы не дождёмся.
Название: Re: Открыть .dwg на нужном листе
Отправлено: Александр Ривилис от 16-05-2015, 13:17:28
Здесь (http://forums.autodesk.com/t5/net/is-it-safe-to-use-database-in-the-initialize-method/td-p/5636779) тебе напомнили еще один вариант - использование события Application.Idle. А я бы для надежности объединил бы его с указанным выше мной методом Control.Invoke
Название: Re: Открыть .dwg на нужном листе
Отправлено: Андрей Бушман от 18-05-2015, 10:48:43
Цитата: Александр Ривилис
Здесь тебе напомнили еще один вариант - использование события Application.Idle.
Спасибо. Нужно будет в блоге себе шпаргалку нацарапать - не в первый раз уже забываю эту информацию (об Application.Idle).

если чертеж уже открыт до вызова метода Initialize(), то события Database.DwgFileOpened для уже открытого чертежа мы не дождёмся.
Это я помню, поэтому данное событие не использую.
Название: Re: Открыть .dwg на нужном листе
Отправлено: Андрей Бушман от 18-05-2015, 11:02:41
Классический же перевод для "thread" в контексте языков программирования, которому уже лет тридцать - "задача".
Классика, говорите...

1. Джеффри Рихтер "CLR via C#. Программирование на платформе Microsoft .NET Framework 4.0 на языке C#", глава 25 "Потоки исполнения". В обозначенной главе везде "Thread" переводится как "поток". Не вижу "задачу".

2. Энтони Уильямс "Параллельное программирование на C++ в действии. Практика разработки многопоточных программ". В обозначенной книге слово "Thread" так же везде переводится как "поток".

3. Чарльз Петцольд "Программирование с использованием Microsoft Windows Forms. Новые возможности технологии Windows Forms". Стр 22 (описание атрибута STAThread) - и снова "thread" переводится как "поток".

4. Мэтью Мак-Дональю "WPF Windows Presentation Foundation в .NET 3.0 для профессионалов." Стр. 98, раздел "Многопоточная обработка". Та же самая картина: слово "Thread" везде переводится как "поток".

Обозначенные выше книги - это однозначно классика. Не знаю, откуда вы свою "классику" берёте... Я согласен с тем, что одинаковый перевод слов Stream и Thread - это очень плохо, но в книгах обычно вижу именно это.
Название: Re: Открыть .dwg на нужном листе
Отправлено: Александр Ривилис от 18-05-2015, 14:14:37
Я опираюсь на значительно более раннюю терминологию. Например, "Программирование для Windows NT", А.В. Фролов, Г.В.Фролов (серия БСП, "Диалог-МИФИ"), 1996г.
Название: Re: Открыть .dwg на нужном листе
Отправлено: Дима_ от 18-05-2015, 19:39:05
В старых лисп книжках тоже вперемешку "потоки вычислений" и "задачи". Но, там, сей термин имеет более общее значение - если выражаться .Net языком то любая последовательность (IEnumerable), даже,например, "строка" - string тоже может быть представлена как поток вычислений. Просто задачей ее обзывать уж совсем "абстрактно" получается.