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

ADN Club => AutoCAD .NET API => Тема начата: neopentan от 19-12-2014, 15:26:06

Название: Как отключить регенерацию вида
Отправлено: neopentan от 19-12-2014, 15:26:06
Подскажите пожалуйста, как можно с помощью .NET отключить обновление (регенерацию) вида?
Название: Re: Как отключить регенерацию вида
Отправлено: Александр Ривилис от 19-12-2014, 19:56:24
Подскажите пожалуйста, как можно с помощью .NET отключить обновление (регенерацию) вида?
Уточни что ты имеешь в виду. Отключить регенерацию при переключении между листами?  Тогда системная переменная LAYOUTREGENCTL (http://exchange.autodesk.com/autocadmep/rus/online-help/BLDSYS/2012/RUS/pages/WS1a9193826455f5ffa23ce210c4a30acaf-4f78.htm) Если речь идет вообще о перерисовке в AutoCAD во время работы твоего кода, то это можно сделать при помощи P/Invoke следующих функций из ObjectARX:
Код - C++ [Выбрать]
  1. acedUpdateDisplayPause(true); // Запрещаем отображение на экране изменений
  2. //... Здесь твой код, который изменяет что-либо на экране
  3. acedUpdateDisplayPause(false); // Разрешаем отображение на экране изменений
  4. acedUpdateDisplay(); // Выполняем обновление графического окна AutoCAD
Название: Re: Как отключить регенерацию вида
Отправлено: neopentan от 19-12-2014, 22:20:03
Александр, большое спасибо за ответ. Речь идет именно об отключении перерисовки графики на время работы кода. Пока что удавалось обходиться без использования ObjectARX, видимо сейчас придется начать, раз нет альтернативы в .NET
Название: Re: Как отключить регенерацию вида
Отправлено: Александр Ривилис от 19-12-2014, 22:42:15
Пока что удавалось обходиться без использования ObjectARX, видимо сейчас придется начать, раз нет альтернативы в .NET
Я же сказал про P/Invoke из .NET, т.е. нет необходимости писать на C++ с использованием ObjectARX.
Название: Re: Как отключить регенерацию вида
Отправлено: Александр Ривилис от 20-12-2014, 01:21:09
Вот пример того, как это могло бы выглядеть. Проверял только в AutoCAD 2012 и 2014 SP1 x64.
Код - C# [Выбрать]
  1. using System;
  2. using System.Runtime.InteropServices;
  3. using System.Reflection;
  4. using Autodesk.AutoCAD.Runtime;
  5. using Autodesk.AutoCAD.ApplicationServices;
  6. using Autodesk.AutoCAD.DatabaseServices;
  7. using Autodesk.AutoCAD.Geometry;
  8. using Autodesk.AutoCAD.EditorInput;
  9. using AcRx = Autodesk.AutoCAD.Runtime;
  10. using AcAp = Autodesk.AutoCAD.ApplicationServices;
  11. using AcDb = Autodesk.AutoCAD.DatabaseServices;
  12. using AcGe = Autodesk.AutoCAD.Geometry;
  13. using AcEd = Autodesk.AutoCAD.EditorInput;
  14.  
  15.  
  16. [assembly: CommandClass(typeof(Rivilis.MyCommands))]
  17.  
  18. namespace Rivilis
  19. {
  20.   public class SuppressUpdateDisplay : IDisposable
  21.   {
  22.     [DllImport("accore.dll", EntryPoint = "?acedIsUpdateDisplayPaused@@YA_NXZ",
  23.       CallingConvention = CallingConvention.Cdecl)]
  24.     [return: MarshalAs(UnmanagedType.I1)]
  25.     private static extern bool acedIsUpdateDisplayPaused13();
  26.     [DllImport("acad.exe", EntryPoint = "?acedIsUpdateDisplayPaused@@YA_NXZ",
  27.       CallingConvention = CallingConvention.Cdecl)]
  28.     [return: MarshalAs(UnmanagedType.I1)]
  29.     private static extern bool acedIsUpdateDisplayPaused12();
  30.     [DllImport("accore.dll", EntryPoint = "?acedUpdateDisplay@@YAXXZ",
  31.       CallingConvention = CallingConvention.Cdecl)]
  32.     private static extern void acedUpdateDisplay13();
  33.     [DllImport("acad.exe", EntryPoint = "?acedUpdateDisplay@@YAXXZ",
  34.       CallingConvention = CallingConvention.Cdecl)]
  35.     private static extern void acedUpdateDisplay12();
  36.     [DllImport("accore.dll", EntryPoint = "?acedUpdateDisplayPause@@YAX_N@Z",
  37.       CallingConvention = CallingConvention.Cdecl)]
  38.     private static extern void acedUpdateDisplayPause13(
  39.       [MarshalAs(UnmanagedType.I1)] bool bPaused);
  40.     [DllImport("acad.exe", EntryPoint = "?acedUpdateDisplayPause@@YAX_N@Z",
  41.       CallingConvention = CallingConvention.Cdecl)]
  42.     private static extern void acedUpdateDisplayPause12(
  43.       [MarshalAs(UnmanagedType.I1)] bool bPaused);
  44.     public static bool acedIsUpdateDisplayPaused()
  45.     {
  46.       if (Application.Version.Major > 18)
  47.         return acedIsUpdateDisplayPaused13();
  48.       else
  49.         return acedIsUpdateDisplayPaused12();
  50.     }
  51.     public static void acedUpdateDisplayPause(bool bPaused)
  52.     {
  53.       if (Application.Version.Major > 18)
  54.         acedUpdateDisplayPause13(bPaused);
  55.       else
  56.         acedUpdateDisplayPause12(bPaused);
  57.     }
  58.  
  59.     public static void acedUpdateDisplay()
  60.     {
  61.       if (Application.Version.Major > 18)
  62.         acedUpdateDisplay13();
  63.       else
  64.         acedUpdateDisplay12();
  65.     }
  66.  
  67.     public SuppressUpdateDisplay()
  68.     {
  69.       bWasPaused = acedIsUpdateDisplayPaused();
  70.       acedUpdateDisplayPause(true);
  71.     }
  72.     public void Dispose()
  73.     {
  74.       acedUpdateDisplay();
  75.       acedUpdateDisplayPause(bWasPaused);
  76.     }
  77.     private bool bWasPaused;
  78.   }
  79.  
  80.   public class MyCommands
  81.   {
  82.     /// <summary>
  83.     /// Пример для проверки использования класса
  84.     /// SuppressUpdateDisplay
  85.     /// </summary>
  86.     [CommandMethod("TestSuppress")]
  87.     public void TestSuppress()
  88.     {
  89.       using (SuppressUpdateDisplay UI = new SuppressUpdateDisplay())
  90.       {
  91.         AcAp.Document doc = AcAp.Application.DocumentManager.MdiActiveDocument;
  92.         AcDb.Database db = doc.Database;
  93.         AcGe.Point3d center = (AcGe.Point3d)Application.GetSystemVariable("VIEWCTR");
  94.         center = center.TransformBy(doc.Editor.CurrentUserCoordinateSystem);
  95.         double radius = (double)Application.GetSystemVariable("VIEWSIZE") * 0.3;
  96.  
  97.         using (AcDb.BlockTableRecord curSpace =
  98.           db.CurrentSpaceId.Open(AcDb.OpenMode.ForWrite) as AcDb.BlockTableRecord)
  99.         {
  100.           using (AcDb.Circle circle = new AcDb.Circle(center, AcGe.Vector3d.ZAxis, radius))
  101.           {
  102.             circle.SetDatabaseDefaults(db);
  103.             curSpace.AppendEntity(circle);
  104.           }
  105.         }
  106.         doc.Editor.GetString("\nНажмите ENTER для появления окружности.");
  107.       }
  108.     }
  109.     [CommandMethod("UpdatePause")]
  110.     public void UpdatePause()
  111.     {
  112.       SuppressUpdateDisplay.acedUpdateDisplayPause(true);
  113.     }
  114.     [CommandMethod("UpdateNoPause")]
  115.     public void UpdateNoPause()
  116.     {
  117.       SuppressUpdateDisplay.acedUpdateDisplayPause(false);
  118.       SuppressUpdateDisplay.acedUpdateDisplay();
  119.     }
  120.   }
  121. }
  122.  
Название: Re: Как отключить регенерацию вида
Отправлено: neopentan от 24-12-2014, 09:53:52
Огромное спасибо, в AutoCAD 2013 все заработало.
Название: Re: Как отключить регенерацию вида
Отправлено: T72 от 26-12-2014, 09:06:58
Достаточно полезный класс. Но есть пара замечаний.
Для AutoCAD 2012 нужно исправить все
Код - C# [Выбрать]
  1. if (Application.Version.Major > 18/*12*/)
Код - C# [Выбрать]
  1. //и отключить паузу, иначе будут жуткие тормоза
  2. public void Dispose()
  3. {
  4.     acedUpdateDisplay();
  5.     acedUpdateDisplayPause(!bWasPaused);
  6. }
Название: Re: Как отключить регенерацию вида
Отправлено: Андрей Бушман от 26-12-2014, 09:11:46
Для AutoCAD 2012 нужно исправить все
Я предполагаю, что А.Н. не просто так указал 12 в качестве значения. Видимо предполагалось, что код может быть использовать и в более ранних версиях, но не старее чем R12.0. Твоя поправка автоматом накрывает медным тазом работу кода для более старых версий акада. Странно, что А.Н. многократно использует "магические числа", вместо того, чтобы оформить их в виде констант.
Название: Re: Как отключить регенерацию вида
Отправлено: T72 от 26-12-2014, 09:31:51
Для AutoCAD 2012 нужно исправить все
Я предполагаю, что А.Н. не просто так указал 12 в качестве значения. Видимо предполагалось, что код может быть использовать и в более ранних версиях, но не старее чем R12.0. Твоя поправка автоматом накрывает медным тазом работу кода для более старых версий акада. Странно, что А.Н. многократно использует "магические числа", вместо того, чтобы оформить их в виде констант.

Александ, потрудитесь прочитать код и поймете, что она не накрывает ничего, а исправляет. 12 - скорее всего имелось ввиду AutoCAD 2012 который имеет Major = 18 т.к. "accore.dll" появился с R19.
Название: Re: Как отключить регенерацию вида
Отправлено: Александр Ривилис от 26-12-2014, 13:08:41
Для AutoCAD 2012 нужно исправить все
Да. Это моя опечатка. Ночная работа сказывается. Исправлю.
//и отключить паузу, иначе будут жуткие тормоза
А вот тут извините. Я восстанавливаю паузу в то состояние, которое было до того как код запустили. Так что если была пауза, то она и должна остаться.

P.S.: Перевёл методы acedIsUpdateDisplayPaused, acedUpdateDisplay, acedUpdateDisplayPause в разряд public static, чтобы ими можно было пользоваться отдельно.
Название: Re: Как отключить регенерацию вида
Отправлено: Александр Ривилис от 26-12-2014, 13:18:04
T72,
Александ, потрудитесь прочитать код и поймете, что она не накрывает ничего, а исправляет. 12 - скорее всего имелось ввиду AutoCAD 2012 который имеет Major = 18 т.к. "accore.dll" появился с R19.
Александ - это что-то среднее между Андрей и Александр? :D Уточняю, что я еще не успел ответить на тот момент, так что полемика была с Андреем. 
Название: Re: Как отключить регенерацию вида
Отправлено: T72 от 26-12-2014, 14:12:55
Александ - это что-то среднее между Андрей и Александр? :D Уточняю, что я еще не успел ответить на тот момент, так что полемика была с Андреем. 
Это я виновен, не на того сослался.

давайте уточним:
bWasPaused = acedIsUpdateDisplayPaused(); - в простое возвращает true (по крайней мере в 2012), видать потому как ничего в данный момент не рисуется.

и в деструкторе опять паузить acedUpdateDisplayPause(bWasPaused = true); (http://docs.autodesk.com/ACDMAC/2015/ENU/Mac_Lightsaber_Dev_Help/Reference_machtml/index.html?frmname=topic&frmfile=_AcEd_Global_Functions_14_Functions.html)? С вашей точкой зрения я согласен она логична. Но как быть тогда с 2012?

Название: Re: Как отключить регенерацию вида
Отправлено: Александр Ривилис от 26-12-2014, 14:14:50
bWasPaused = acedIsUpdateDisplayPaused(); - в простое возвращает true
"Простой" - это что? Возвращать true должно только если приостановлен вывод на экран.
Название: Re: Как отключить регенерацию вида
Отправлено: T72 от 26-12-2014, 14:21:26
Простой" - это что? Возвращать true должно только если приостановлен вывод на экран.
Я хотел сказать, что когда никаких команд не выполняется. Посмотрите видео (http://file.sngp.ru/fileshare/d6c74f11-da50-4316-9da8-7d448806806f)
Название: Re: Как отключить регенерацию вида
Отправлено: Александр Ривилис от 26-12-2014, 14:41:26
Похоже это баг AutoCAD 2012. В 2014 всё нормально (т.е. bWasPaused в конструкторе == false в обычных ситуациях).
Название: Re: Как отключить регенерацию вида
Отправлено: Александр Ривилис от 26-12-2014, 14:42:19
Я хотел сказать, что когда никаких команд не выполняется.
Нет никакой связи между acedIsUpdateDisplayPaused и выполняются или не выполняются команды.
Название: Re: Как отключить регенерацию вида
Отправлено: Александр Ривилис от 26-12-2014, 14:51:07
Так. Проверил в AutoCAD 2012 в чистом ObjectARX:
Код - C++ [Выбрать]
  1.   static void ArxProject1MyCommand1(void)
  2.   {
  3.     acutPrintf(_T("\nacedIsUpdateDisplayPaused = %s"),acedIsUpdateDisplayPaused()? _T("Да") : _T("Нет"));
  4.   }
  5.  
Возвращает "Нет". Похоже какая-то проблема с P/Invoke.
Название: Re: Как отключить регенерацию вида
Отправлено: Александр Ривилис от 26-12-2014, 15:10:31
Проблему похоже идентифицировал. Вместо UnmanagedType.Bool нужно использовать UnmanagedType.I1. Интересно почему это работало в AutoCAD 2014. ;) Код исправил и проверил в AutoCAD 2012 и 2014 x64.
Название: Re: Как отключить регенерацию вида
Отправлено: T72 от 26-12-2014, 15:15:24
    Я хотел сказать, что когда никаких команд не выполняется.

Нет никакой связи между acedIsUpdateDisplayPaused и выполняются или не выполняются команды.
Буду иметь ввиду, просто я дилетант в данных вопросах и не всегда могу верно выразить свои мысли в данной предметной области.
Название: Re: Как отключить регенерацию вида
Отправлено: T72 от 26-12-2014, 15:17:32
Проблему похоже идентифицировал. Вместо UnmanagedType.Bool нужно использовать UnmanagedType.I1. Интересно почему это работало в AutoCAD 2014. ;) Код исправил и проверил в AutoCAD 2012 и 2014 x64.
Подтверждаю, у меня все сработало.
Название: Re: Как отключить регенерацию вида
Отправлено: Александр Ривилис от 26-12-2014, 15:20:07
Подтверждаю, у меня все сработало.
Итого ты:
1) Нашел ошибку с 12/18
2) Вывел на ошибку с  UnmanagedType
Так что двойное спасибо! :)