Автозапуск кода в каждом новом документе nanoCAD

На форуме nanocad возник вопрос: "А как запустить lsp внутри каждого документа?"

В ACAD-то все просто: код будет грузиться в каждый документ (как эта загрузка обеспечивается - вопрос отдельный). А если в коде добавить самовызов, то он и сработает нормально.

Но в nanoCAD такого счастья уже нет. Хотя бы потому, что коды - даже lsp - грузятся в приложение, а не в документ. Понятие реакторов* в nanoCAD 23 (ну, по крайней мере на момент написания статьи) не реализованы. Складываем это вместе - и получается, что код ни разу не в курсе, в каком документе он выполняется. И отследить момент перехода в другой документ шансов практически нет.

Уточнение: на лиспе. Если делать через NET, то все становится достаточно простым.

Много кода
Общая идея: подписаться на несколько событий:

  • DocumentActivated
  • DocumentCreateStarted
  • DocumentBecameCurrent
  • DocumentCreated
  • DocumentDestroyed

И посмотреть, что получится в результате. Ну и за компанию – на событие начала и окончания команды:

  • CommandWillStart
  • CommandEnded

Чтобы особо не заморачиваться, результаты буду выводить в текстовый лог:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
    internal static class LogService
    {
        public static void LogMessage(string DocumentName, [CallerMemberName] string Message = null)
        {
            if (!Directory.Exists(Path.GetDirectoryName(_logFileName)))
            {
                Directory.CreateDirectory(Path.GetDirectoryName(_logFileName));
            }

            try
            {
                using (StreamWriter writer = new StreamWriter(_logFileName, true, Encoding.UTF8))
                {
                    writer.WriteLine(DateTime.Now.ToString("yyyy.MM.dd HH:mm:ss.fff")
                        + (DocumentName == null ? "Без имени документа" : DocumentName)
                        + "\t:\t"
                        + (Message == null ? "Нет сообщения" : Message));
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.ToString());
            }
        }

        private static string _logFileName =
            Path.Combine(Environment.GetEnvironmentVariable("appdata"), @"KpblcNCadEvents\KpblcNCadEvents.Log");
    }

Ну и сама подписка на события:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
    public class ExtensionApplication : IExtensionApplication
    {
        public void Initialize()
        {
            Application.DocumentManager.DocumentActivated += OnDocumentActivated;
            Application.DocumentManager.DocumentCreateStarted += OnDocumentStarted;
            Application.DocumentManager.DocumentBecameCurrent += OnDocumentBecameCurrent;
            Application.DocumentManager.DocumentCreated += OnDocumentCreated;
            Application.DocumentManager.DocumentDestroyed += OnDocumentDestroyed;
            Application.DocumentManager.CurrentDocument.CommandWillStart += OnCommandStart;
            Application.DocumentManager.CurrentDocument.CommandEnded += OnCommandEnd;
        }

        private void OnCommandEnd(object sender, CommandEventArgs e)
        {
            Document doc = Application.DocumentManager.MdiActiveDocument;
            LogService.LogMessage(doc == null ? null : doc.Name);
        }

        private void OnCommandStart(object sender, CommandEventArgs e)
        {
            Document doc = Application.DocumentManager.MdiActiveDocument;
            LogService.LogMessage(doc == null ? null : doc.Name);
        }

        private void OnDocumentDestroyed(object sender, DocumentDestroyedEventArgs e)
        {
            Document doc = Application.DocumentManager.MdiActiveDocument;
            LogService.LogMessage(doc == null ? null : doc.Name);
        }

        private void OnDocumentCreated(object sender, DocumentCollectionEventArgs e)
        {
            Document doc = Application.DocumentManager.MdiActiveDocument;
            LogService.LogMessage(doc == null ? null : doc.Name);
        }

        private void OnDocumentBecameCurrent(object sender, DocumentCollectionEventArgs e)
        {
            Document doc = Application.DocumentManager.MdiActiveDocument;
            LogService.LogMessage(doc == null ? null : doc.Name);
        }

        private void OnDocumentStarted(object sender, DocumentCollectionEventArgs e)
        {
            Document doc = Application.DocumentManager.MdiActiveDocument;
            LogService.LogMessage(doc == null ? null : doc.Name);
        }

        private void OnDocumentActivationChanged(object sender, DocumentActivationChangedEventArgs e)
        {
           Document doc = Application.DocumentManager.MdiActiveDocument;
            LogService.LogMessage(doc == null ? null : doc.Name);
        }

        private void OnDocumentActivated(object sender, DocumentCollectionEventArgs e)
        {
            Document doc = Application.DocumentManager.MdiActiveDocument;
            LogService.LogMessage(doc == null ? null : doc.Name);
        }

        public void Terminate() { }
       
    }

Заодно создаю ярлык вызова nanoCAD с принудительной загрузкой скомпилированной сборки:

1
"C:\Program Files\Nanosoft\nanoCAD x64 23.0\nCad.exe" -g "C:\Users\kpblc\Source\Repos\KpblcNCadEvents\KpblcNCadEvents\bin\Debug\net6.0-windows\KpblcNCadEvents.dll"

При старте nanoCAD в логе получаю:

1
2
3
4
5
6
7
2023.05.22 20:21:23.828Без имени0 : OnCommandEnd
2023.05.22 20:21:23.833Без имени0 : OnCommandStart
2023.05.22 20:21:23.842Без имени0 : OnCommandEnd
2023.05.22 20:21:23.981Без имени0 : OnCommandStart
2023.05.22 20:21:29.730Без имени0 : OnCommandEnd
2023.05.22 20:21:29.818Без имени0 : OnCommandStart
2023.05.22 20:21:29.820Без имени0 : OnCommandEnd

Полагаю, что сначала создается документ, потом обрабатываются ключи вызова, а потом уже стандартные команды типа _new, _toolpalettes etc.
Жму Ctrl+N:

1
2
3
4
5
6
2023.05.22 20:23:58.732Без имени0 : OnCommandStart
2023.05.22 20:23:58.812Без имени0 : OnDocumentStarted
2023.05.22 20:23:59.403Без имени1 : OnDocumentCreated
2023.05.22 20:23:59.515Без имени1 : OnDocumentActivated
2023.05.22 20:23:59.517Без имени1 : OnDocumentBecameCurrent
2023.05.22 20:23:59.658Без имени1 : OnCommandEnd

Получается, что команда начинается в одном документе, а заканчивается в другом :) Прикол аднака ;)

Но вот тут уже срабатывают привязки к событиям документов.

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

Если я ошибаюсь - милости прошу, поправляйте :)

P.S. Исходный код, ориентированный на nanoCAD23, болтается на гитхабе.
---
* имеются в виду командные реакторы

Размещено в .NET, nanoCAD, Разное · Метки: , , , ,



Поделитесь своим мнением


Я не робот.