Обновление изменений в Layout

Автор Тема: Обновление изменений в Layout  (Прочитано 8148 раз)

0 Пользователей и 2 Гостей просматривают эту тему.

Оффлайн pavka_97Автор темы

  • ADN OPEN
  • ***
  • Сообщений: 150
  • Карма: 3
Уже третий раз сталкиваюсь с ситуацией, когда для обновления изменений в пространстве листа требуется его попереключать на другие листы или модель. Зачастую это не только неудобно, но и порождает доп.ошибки. Существуют ли еще методы обновления (ну кроме ed.Regen, UpdateDisplay) изменений в листе без переключений?

Пример 1. Удаляем все на текущем листе, вставляем блок. Без переключений возникает ошибка eNullObjectId.
Код - C# [Выбрать]
  1. using Autodesk.AutoCAD.Runtime;
  2. using Autodesk.AutoCAD.ApplicationServices;
  3. using Autodesk.AutoCAD.DatabaseServices;
  4. using Autodesk.AutoCAD.EditorInput;
  5. using Autodesk.AutoCAD.Geometry;
  6.  
  7. namespace pavli
  8. {
  9.     public class pavli
  10.     {
  11.         [CommandMethod("PAVPLTEST")]
  12.         public void PAVLI()
  13.         {
  14.             Document doc = Application.DocumentManager.MdiActiveDocument;
  15.             Editor ed = doc.Editor;
  16.             Database db = doc.Database;
  17.             LayoutManager layMng = LayoutManager.Current;
  18.             string curLayoutName = layMng.CurrentLayout;
  19.  
  20.             //Копируем определение блока из др.файла
  21.  
  22.             ObjectIdCollection ids = new ObjectIdCollection();
  23.             using (Database newDB = new Database(false, false))
  24.             {
  25.                 newDB.ReadDwgFile(@"D:\1.dwg", System.IO.FileShare.Read, false, string.Empty);
  26.                 newDB.CloseInput(true);
  27.                 using (BlockTable bt = newDB.BlockTableId.Open(OpenMode.ForRead) as BlockTable)
  28.                 {
  29.                     if (bt.Has("Штсcc")) ids.Add(bt["Штсcc"]);
  30.  
  31.                     else return;
  32.                 }
  33.                 if (ids.Count > 0)
  34.                 {
  35.                     IdMapping iMap = new IdMapping();
  36.                     {
  37.                         using (DocumentLock dl = doc.LockDocument())
  38.                         {
  39.                             db.WblockCloneObjects(ids, db.BlockTableId, iMap, DuplicateRecordCloning.Ignore, false);
  40.  
  41.                         }
  42.                     }
  43.                 }
  44.             }
  45.  
  46.             //Выбираем все примитивы текущего пространства листа и удаляем их
  47.  
  48.             TypedValue[] acTypValAr = new TypedValue[1];
  49.             acTypValAr.SetValue(new TypedValue(410, curLayoutName), 0);
  50.             SelectionFilter acSelFtr = new SelectionFilter(acTypValAr);
  51.             PromptSelectionResult acSSPrompt = ed.SelectAll(acSelFtr);
  52.             SelectionSet acSSet = acSSPrompt.Value;
  53.             ObjectIdCollection acObjIdColl = new ObjectIdCollection(acSSet.GetObjectIds());
  54.  
  55.             using (Transaction tr = db.TransactionManager.StartTransaction())
  56.             {
  57.  
  58.                 foreach (ObjectId id in acObjIdColl)
  59.                 {
  60.                     var objObject = tr.GetObject(id, OpenMode.ForWrite);
  61.                     objObject.Erase();
  62.                 }
  63.                 tr.Commit();
  64.             }//тут программно переключаем на др/лист модель и обратно, без этого ошибка.
  65.  
  66.  
  67.             //Вставляем блок на лист
  68.  
  69.             ObjectId psid = db.CurrentSpaceId;
  70.  
  71.             using (Transaction tr2 = db.TransactionManager.StartTransaction())
  72.             {
  73.                 BlockTable bt = tr2.GetObject(db.BlockTableId, OpenMode.ForRead) as BlockTable;
  74.                 BlockTableRecord btr = tr2.GetObject(bt["Штсcc"], OpenMode.ForWrite) as BlockTableRecord;
  75.                 BlockTableRecord cs = tr2.GetObject(psid, OpenMode.ForWrite) as BlockTableRecord; //Ошибка тут eNullObjectId
  76.                 Point3d pins = new Point3d(0, 0, 0);
  77.                 BlockReference blRefTest = new BlockReference(pins, bt["Штсcc"]);
  78.                 ObjectId bRefId = cs.AppendEntity(blRefTest);
  79.                 tr2.AddNewlyCreatedDBObject(blRefTest, true);
  80.             }
  81.         }
  82.     }
  83. }
  84.  
Пример 2. Меняем настройки печати на листе на Extents. Код работает,но не со всеми листами. Для правильного графического отображения границ печати нужно переключится на др. лист/модель и обратно.
Код - C# [Выбрать]
  1. using Autodesk.AutoCAD.Runtime;
  2. using Autodesk.AutoCAD.ApplicationServices;
  3. using Autodesk.AutoCAD.DatabaseServices;
  4. using Autodesk.AutoCAD.EditorInput;
  5. using Autodesk.AutoCAD.PlottingServices;
  6.  
  7. namespace pavli
  8. {
  9.     public class pavli
  10.     {
  11.         [CommandMethod("PAVPLTEST2")]
  12.         public void PAVLI2()
  13.         {
  14.             Document doc = Application.DocumentManager.MdiActiveDocument;
  15.             Editor ed = doc.Editor;
  16.             Database db = doc.Database;
  17.             LayoutManager layMng = LayoutManager.Current;
  18.        
  19.             using (Transaction acTrans = db.TransactionManager.StartTransaction())
  20.             {
  21.                 Layout acLayout = acTrans.GetObject(layMng.GetLayoutId(layMng.CurrentLayout), OpenMode.ForRead) as Layout;
  22.                 PlotInfo acPlInfo = new PlotInfo();
  23.                 acPlInfo.Layout = acLayout.ObjectId;
  24.                 PlotSettings acPlSet = new PlotSettings(acLayout.ModelType);
  25.                 acPlSet.CopyFrom(acLayout);
  26.                 PlotSettingsValidator acPlSetVdr = PlotSettingsValidator.Current;
  27.                 PlotConfig plotConfig = PlotConfigManager.SetCurrentConfig(acLayout.PlotConfigurationName);
  28.                 acPlSetVdr.SetPlotType(acPlSet, Autodesk.AutoCAD.DatabaseServices.PlotType.Extents);
  29.                 acPlSetVdr.SetPlotConfigurationName(acPlSet, "Canon785sss.pc3", "User4401");
  30.                 acPlSetVdr.SetUseStandardScale(acPlSet, true);
  31.                 acPlSetVdr.SetStdScaleType(acPlSet, StdScaleType.ScaleToFit);
  32.                 acPlSetVdr.SetPlotCentered(acPlSet, true);
  33.                 PlotRotation Rot = PlotRotation.Degrees090;
  34.                 acPlSetVdr.SetPlotRotation(acPlSet, Rot);
  35.                 var ssl = acPlSetVdr.GetPlotStyleSheetList();
  36.                 if (ssl.Contains("monochromesss.ctb"))
  37.                 {
  38.                     acPlSetVdr.SetCurrentStyleSheet(acPlSet, "monochromesss.ctb");
  39.                 }
  40.                 acLayout.UpgradeOpen();
  41.                 acLayout.CopyFrom(acPlSet);
  42.                 acTrans.Commit();
  43.             }
  44.             ed.Regen();
  45.         }
  46.     }
  47. }
  48.  

Оффлайн Александр Ривилис

  • Administrator
  • *****
  • Сообщений: 13829
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Re: Обновление изменений в Layout
« Ответ #1 : 20-05-2019, 19:35:47 »
pavka_97,
Думаю, что к обновлению Layout это не имеет никакого отношения. Если ты пытаешься открыть открыть db.CurrentSpaceId и получаешь eNullObjectId, то у тебя уже что-то ненормальное с базой данных.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн pavka_97Автор темы

  • ADN OPEN
  • ***
  • Сообщений: 150
  • Карма: 3
Re: Обновление изменений в Layout
« Ответ #2 : 20-05-2019, 20:07:47 »
то у тебя уже что-то ненормальное с базой данных.
В базе нового чистого файла, в который я копирую блок, ошибка?

Вот так работает в чистом файле, если db.CurrentSpaceId инициализируем пораньше. Но этот способ не работает в "грязном" файле.
Код - C# [Выбрать]
  1. using Autodesk.AutoCAD.Runtime;
  2. using Autodesk.AutoCAD.ApplicationServices;
  3. using Autodesk.AutoCAD.DatabaseServices;
  4. using Autodesk.AutoCAD.EditorInput;
  5. using Autodesk.AutoCAD.Geometry;
  6.  
  7. namespace pavli
  8. {
  9.     public class pavli
  10.     {
  11.         [CommandMethod("PAVPLTEST")]
  12.         public void PAVLI()
  13.         {
  14.             Document doc = Application.DocumentManager.MdiActiveDocument;
  15.             Editor ed = doc.Editor;
  16.             Database db = doc.Database;
  17.  
  18.             //LayoutManager layMng = LayoutManager.Current;
  19.             //string curLayoutName = layMng.CurrentLayout;
  20.             ObjectId psid = db.CurrentSpaceId;
  21.             string curLayoutName = LayoutManager.Current.CurrentLayout;
  22.             string msLayoutName = "";
  23.             using (Transaction tr = db.TransactionManager.StartTransaction())
  24.             {
  25.                 // BlockTableRecord для текущего пространства
  26.                 BlockTableRecord btr = tr.GetObject(db.CurrentSpaceId, OpenMode.ForRead) as BlockTableRecord;
  27.                 BlockTableRecord btrMS = tr.GetObject(SymbolUtilityServices.GetBlockModelSpaceId(db), OpenMode.ForRead) as BlockTableRecord;
  28.                 // Текущий лист
  29.                 Layout layout = tr.GetObject(btr.LayoutId, OpenMode.ForRead) as Layout;
  30.                 // Лист модели
  31.                 Layout layoutMS = tr.GetObject(btrMS.LayoutId, OpenMode.ForRead) as Layout;
  32.                 msLayoutName = layoutMS.LayoutName;
  33.                 tr.Commit();
  34.             }
  35.                 //Копируем определение блока из др.файла
  36.  
  37.                 ObjectIdCollection ids = new ObjectIdCollection();
  38.             using (Database newDB = new Database(false, false))
  39.             {
  40.                 newDB.ReadDwgFile(@"D:\1.dwg", System.IO.FileShare.Read, false, string.Empty);
  41.                 newDB.CloseInput(true);
  42.                 using (BlockTable bt = newDB.BlockTableId.Open(OpenMode.ForRead) as BlockTable)
  43.                 {
  44.                     if (bt.Has("Штсcc")) ids.Add(bt["Штсcc"]);
  45.  
  46.                     else return;
  47.                 }
  48.                 if (ids.Count > 0)
  49.                 {
  50.                     IdMapping iMap = new IdMapping();
  51.                     {
  52.                         using (DocumentLock dl = doc.LockDocument())
  53.                         {
  54.                             db.WblockCloneObjects(ids, db.BlockTableId, iMap, DuplicateRecordCloning.Ignore, false);
  55.  
  56.                         }
  57.                     }
  58.                 }
  59.             }
  60.  
  61.             //Выбираем все примитивы текущего пространства листа и удаляем их
  62.  
  63.             TypedValue[] acTypValAr = new TypedValue[1];
  64.             acTypValAr.SetValue(new TypedValue(410, curLayoutName), 0);
  65.             SelectionFilter acSelFtr = new SelectionFilter(acTypValAr);
  66.             PromptSelectionResult acSSPrompt = ed.SelectAll(acSelFtr);
  67.             SelectionSet acSSet = acSSPrompt.Value;
  68.             ObjectIdCollection acObjIdColl = new ObjectIdCollection(acSSet.GetObjectIds());
  69.  
  70.             using (Transaction tr = db.TransactionManager.StartTransaction())
  71.             {
  72.  
  73.                 foreach (ObjectId id in acObjIdColl)
  74.                 {
  75.                     var objObject = tr.GetObject(id, OpenMode.ForWrite);
  76.                     objObject.Erase();
  77.                 }
  78.                 tr.Commit();
  79.             }
  80.  
  81.             //Как альтернатива - рабочий вариант№2 с переключением
  82.             //LayoutManager.Current.CurrentLayout = msLayoutName;
  83.             //LayoutManager.Current.CurrentLayout = curLayoutName;
  84.  
  85.             //Вставляем блок на лист
  86.  
  87.            
  88.  
  89.             using (Transaction tr2 = db.TransactionManager.StartTransaction())
  90.             {
  91.                 BlockTable bt = tr2.GetObject(db.BlockTableId, OpenMode.ForRead) as BlockTable;
  92.                 BlockTableRecord btr = tr2.GetObject(bt["Штсcc"], OpenMode.ForWrite) as BlockTableRecord;
  93.                 BlockTableRecord cs = tr2.GetObject(psid, OpenMode.ForWrite) as BlockTableRecord; //Ошибка тут eNullObjectId
  94.                 Point3d pins = new Point3d(0, 0, 0);
  95.                 BlockReference blRefTest = new BlockReference(pins, bt["Штсcc"]);
  96.                 ObjectId bRefId = cs.AppendEntity(blRefTest);
  97.                 tr2.AddNewlyCreatedDBObject(blRefTest, true);
  98.                 tr2.Commit();
  99.             }
  100.             ed.Regen();
  101.         }
  102.     }
  103. }
  104.  
  105.  

А вот способ номер два с переключением на модель и обратно работает в "грязном", но он мне не совсем подходит.

Оффлайн Александр Ривилис

  • Administrator
  • *****
  • Сообщений: 13829
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Re: Обновление изменений в Layout
« Ответ #3 : 20-05-2019, 20:11:09 »
В базе нового чистого файла, в который я копирую блок, ошибка?
Видимо после копирования. В любом случае db.CurrentSpaceId не может быть null
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн Александр Ривилис

  • Administrator
  • *****
  • Сообщений: 13829
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Re: Обновление изменений в Layout
« Ответ #4 : 20-05-2019, 20:16:33 »
Выложи свой 1.dwg и укажи в какой версии AutoCAD ты тестируешь.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн Александр Ривилис

  • Administrator
  • *****
  • Сообщений: 13829
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Re: Обновление изменений в Layout
« Ответ #5 : 20-05-2019, 20:19:18 »
Вот так работает в чистом файле, если db.CurrentSpaceId инициализируем пораньше. Но этот способ не работает в "грязном" файле.
Что такое грязный и чистый файлы???
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн pavka_97Автор темы

  • ADN OPEN
  • ***
  • Сообщений: 150
  • Карма: 3
Re: Обновление изменений в Layout
« Ответ #6 : 20-05-2019, 20:30:13 »
Блок любой, хоть круг. Чистый файл- только созданный, новый. Грязный файл - заполненный различными примитивами.  Eng2016x64

Оффлайн Александр Ривилис

  • Administrator
  • *****
  • Сообщений: 13829
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Re: Обновление изменений в Layout
« Ответ #7 : 20-05-2019, 20:33:42 »
Блок любой, хоть круг. Чистый файл- только созданный, новый. Грязный файл - заполненный различными примитивами.  Eng2016x64
Код запускаешь в Модели или в Листе?
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн pavka_97Автор темы

  • ADN OPEN
  • ***
  • Сообщений: 150
  • Карма: 3
Re: Обновление изменений в Layout
« Ответ #8 : 20-05-2019, 20:40:12 »
В листе

Оффлайн Александр Ривилис

  • Administrator
  • *****
  • Сообщений: 13829
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Re: Обновление изменений в Layout
« Ответ #9 : 20-05-2019, 20:45:44 »
pavka_97,
Проверил твой код у себя в "грязном" файле (нарисовал на текущем листе несколько кругов) - всё работает без ошибок. Блок нормально вставляется.
Только заменил
Код - C# [Выбрать]
  1. BlockTableRecord btr = tr2.GetObject(bt["Штсcc"], OpenMode.ForWrite) as BlockTableRecord;
на
Код - C# [Выбрать]
  1. BlockTableRecord btr = tr2.GetObject(bt["Штсcc"], OpenMode.ForRead) as BlockTableRecord;
Есть подозрение, что твой код кроме примитивов на листе может стирать и видовые экраны.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн pavka_97Автор темы

  • ADN OPEN
  • ***
  • Сообщений: 150
  • Карма: 3
Re: Обновление изменений в Layout
« Ответ #10 : 20-05-2019, 20:57:43 »
всё работает без ошибок
Исключений не выдает?Код из 1-го поста?

Оффлайн Александр Ривилис

  • Administrator
  • *****
  • Сообщений: 13829
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Re: Обновление изменений в Layout
« Ответ #11 : 20-05-2019, 21:50:01 »
всё работает без ошибок
Исключений не выдает?Код из 1-го поста?

Код отсюда: http://adn-cis.org/forum/index.php?topic=9274.msg38551#msg38551
Никаких исключений. Как я сказал, проверял на "грязном" чертеже.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн Александр Ривилис

  • Administrator
  • *****
  • Сообщений: 13829
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Re: Обновление изменений в Layout
« Ответ #12 : 20-05-2019, 22:58:58 »
всё работает без ошибок
Исключений не выдает?Код из 1-го поста?

Проверил и код из первого поста - всё работает без исключений. Хотя в нём не хватает tr2.Commit()
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн pavka_97Автор темы

  • ADN OPEN
  • ***
  • Сообщений: 150
  • Карма: 3
Re: Обновление изменений в Layout
« Ответ #13 : 20-05-2019, 23:51:25 »
Проверил в eng2013x86 код из первого поста с tr2.Commit(). Файл блока- новый,чистый, круг. Файл, куда копируем-новый, чистый,прямоугольник в пространстве листа, вызываем из этого листа. Исключение -75 строка,eNullObjectId .


Оффлайн Александр Ривилис

  • Administrator
  • *****
  • Сообщений: 13829
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Re: Обновление изменений в Layout
« Ответ #14 : 21-05-2019, 00:21:15 »
pavka_97,
Код - C# [Выбрать]
  1. using Autodesk.AutoCAD.Runtime;
  2. using Autodesk.AutoCAD.ApplicationServices;
  3. using Autodesk.AutoCAD.DatabaseServices;
  4. using Autodesk.AutoCAD.EditorInput;
  5. using Autodesk.AutoCAD.Geometry;
  6.  
  7. namespace pavli
  8. {
  9.   public class pavli
  10.   {
  11.     [CommandMethod("PAVPLTEST")]
  12.     public void PAVLI()
  13.     {
  14.       Document doc = Application.DocumentManager.MdiActiveDocument;
  15.       Editor ed = doc.Editor;
  16.       Database db = doc.Database;
  17.       LayoutManager layMng = LayoutManager.Current;
  18.       string curLayoutName = layMng.CurrentLayout;
  19.  
  20.       //Копируем определение блока из др.файла
  21.  
  22.       ObjectIdCollection ids = new ObjectIdCollection();
  23.       using (Database newDB = new Database(false, false))
  24.       {
  25.         newDB.ReadDwgFile(@"D:\1.dwg", System.IO.FileShare.Read, false, string.Empty);
  26.         newDB.CloseInput(true);
  27.         using (BlockTable bt = newDB.BlockTableId.Open(OpenMode.ForRead) as BlockTable)
  28.         {
  29.           if (bt.Has("Штсcc")) ids.Add(bt["Штсcc"]);
  30.  
  31.           else return;
  32.         }
  33.         if (ids.Count > 0)
  34.         {
  35.           IdMapping iMap = new IdMapping();
  36.           {
  37.             using (DocumentLock dl = doc.LockDocument())
  38.             {
  39.               newDB.WblockCloneObjects(ids, db.BlockTableId, iMap, DuplicateRecordCloning.Ignore, false);
  40.  
  41.             }
  42.           }
  43.         }
  44.       }
  45.  
  46.       //Выбираем все примитивы текущего пространства листа и удаляем их
  47.  
  48.       TypedValue[] acTypValAr = new TypedValue[1];
  49.       acTypValAr.SetValue(new TypedValue(410, curLayoutName), 0);
  50.       SelectionFilter acSelFtr = new SelectionFilter(acTypValAr);
  51.       PromptSelectionResult acSSPrompt = ed.SelectAll(acSelFtr);
  52.       SelectionSet acSSet = acSSPrompt.Value;
  53.       ObjectIdCollection acObjIdColl = new ObjectIdCollection(acSSet.GetObjectIds());
  54.  
  55.       using (Transaction tr = db.TransactionManager.StartTransaction())
  56.       {
  57.  
  58.         foreach (ObjectId id in acObjIdColl)
  59.         {
  60.           var objObject = tr.GetObject(id, OpenMode.ForWrite);
  61.           // Не нужно удалять все видовые экраны
  62.           if (!(objObject is Viewport)) objObject.Erase();
  63.         }
  64.         tr.Commit();
  65.       }//тут программно переключаем на др/лист модель и обратно, без этого ошибка.
  66.  
  67.  
  68.       //Вставляем блок на лист
  69.  
  70.       ObjectId psid = db.CurrentSpaceId;
  71.  
  72.       using (Transaction tr2 = db.TransactionManager.StartTransaction())
  73.       {
  74.         BlockTable bt = tr2.GetObject(db.BlockTableId, OpenMode.ForRead) as BlockTable;
  75.         BlockTableRecord btr = tr2.GetObject(bt["Штсcc"], OpenMode.ForRead) as BlockTableRecord;
  76.         BlockTableRecord cs = tr2.GetObject(psid, OpenMode.ForWrite) as BlockTableRecord; //Ошибка тут eNullObjectId
  77.         Point3d pins = new Point3d(0, 0, 0);
  78.         BlockReference blRefTest = new BlockReference(pins, bt["Штсcc"]);
  79.         ObjectId bRefId = cs.AppendEntity(blRefTest);
  80.         tr2.AddNewlyCreatedDBObject(blRefTest, true);
  81.         tr2.Commit();
  82.       }
  83.     }
  84.   }
  85. }

Сравни со своим кодом и проверь.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение