Не удаётся создать Subsection (раздел в реестре) для настроек PaletteSet

Автор Тема: Не удаётся создать Subsection (раздел в реестре) для настроек PaletteSet  (Прочитано 17319 раз)

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

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

  • Administrator
  • *****
  • Сообщений: 13829
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Попробуй объявить класс как static.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн Андрей БушманАвтор темы

  • ADN Club
  • *****
  • Сообщений: 2000
  • Карма: 163
  • Пишу программки...
    • Блог
  • Skype: Compositum78
Попробуй объявить класс как static.
я попробую, только что лежит в основе этого предположения? переменная, с которой я работаю в коде и так является статической. Неужто этого мало и требуется static class? В этом случае лесом пойдёт реализация интерфейса IExtensionApplication...

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

  • Administrator
  • *****
  • Сообщений: 13829
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
что лежит в основе этого предположения?
В основе этого предположения то, что для событий уровня DocumentCollection очень(!!!) желательны статические методы, т.к. в противном случае на каждый документ создаётся свой экземпляр класса и какой обработчик будет использоваться не ясно.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн Андрей БушманАвтор темы

  • ADN Club
  • *****
  • Сообщений: 2000
  • Карма: 163
  • Пишу программки...
    • Блог
  • Skype: Compositum78
Мне нравится исключение с сообщением "Операция завершена успешно."
Однако в xml файле нужные изменения не появляются. Т.о. я не знаю, что в этом сообщении подразумевается под "успехом"...

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

  • Administrator
  • *****
  • Сообщений: 13829
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Однако в xml файле нужные изменения не появляются.
1. try/catch поставил?
2. класс уже статический?
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн Андрей БушманАвтор темы

  • ADN Club
  • *****
  • Сообщений: 2000
  • Карма: 163
  • Пишу программки...
    • Блог
  • Skype: Compositum78
Попробуй объявить класс как static.
Без особой надежды попробовал. Те же самые сообщения об ошибках.

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

  • Administrator
  • *****
  • Сообщений: 13829
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
1. try/catch поставил?
И проверь subsection равно ли null после этого
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн Андрей БушманАвтор темы

  • ADN Club
  • *****
  • Сообщений: 2000
  • Карма: 163
  • Пишу программки...
    • Блог
  • Skype: Compositum78
1. try/catch поставил?
И проверь subsection равно ли null после этого
Проверял. subsection по прежнему равен null (после возникновения исключения). Вот код:
Код - C# [Выбрать]
  1. // © Andrey Bushman, 2013
  2. using System;
  3. using Microsoft.Win32;
  4. using System.IO;
  5.  
  6. using cad = Autodesk.AutoCAD.ApplicationServices.Application;
  7. using App = Autodesk.AutoCAD.ApplicationServices;
  8. using Db = Autodesk.AutoCAD.DatabaseServices;
  9. using Ed = Autodesk.AutoCAD.EditorInput;
  10. using Rtm = Autodesk.AutoCAD.Runtime;
  11. using Win = Autodesk.AutoCAD.Windows;
  12.  
  13. [assembly: Rtm.CommandClass(typeof(Bushman.CAD.Problems.Commands))]
  14.  
  15. namespace Bushman.CAD.Problems {
  16.  
  17.         public static class Commands {
  18.  
  19.                 internal static Win.PaletteSet palette_set = null;
  20.  
  21.                 [Rtm.CommandMethod("cmd_3", Rtm.CommandFlags.Modal)]
  22.                 public static void Command_3() {
  23.                         Ed.Editor ed = cad.DocumentManager.MdiActiveDocument.Editor;
  24.                         if (palette_set == null) {
  25.                                 // This settings will be saved into the
  26.                                 // %AppData%\Autodesk\AutoCAD 2014\R19.1\enu\Support\Profiles\Unnamed Profile\Profile.aws
  27.                                 // if the current profile is <<Unnamed Profile>>.
  28.                                 palette_set = new Win.PaletteSet("My Palette",
  29.                                         new Guid("{49DBC66F-21BE-4D9F-A5A9-BA750543042E}"));
  30.                                 palette_set.Load += new Win.PalettePersistEventHandler(palette_set_Load);
  31.                                 cad.DocumentManager.DocumentToBeDestroyed += new App.DocumentCollectionEventHandler(
  32.                                         DocumentManager_DocumentToBeDestroyed);
  33.                         }
  34.  
  35.                         palette_set.KeepFocus = true;
  36.                         palette_set.Visible = true;
  37.                 }
  38.  
  39.                 static void DocumentManager_DocumentToBeDestroyed(object sender, App.DocumentCollectionEventArgs e) {
  40.                         palette_set_Save(null, _palette_set);
  41.                 }
  42.  
  43.                 static App.IConfigurationSection _palette_set = null;
  44.  
  45.                 // This names can't to contain the spaces!
  46.                 const String name = "AAA";
  47.                 const String name2 = "BBB";
  48.                 const String val_1_name = "Value_1";
  49.                 const String val_2_name = "Value_2";
  50.  
  51.                 static void palette_set_Load(object sender, Win.PalettePersistEventArgs e) {
  52.                         App.IConfigurationSection section = _palette_set = e.ConfigurationSection;
  53.                         App.IConfigurationSection subsection = null;
  54.                         App.IConfigurationSection subsection2 = null;
  55.  
  56.                         if (!section.IsReadOnly) {
  57.                                 subsection = section.ContainsSubsection(name) ?
  58.                                 section.OpenSubsection(name) : section.CreateSubsection(name);
  59.  
  60.                                 if (!subsection.IsReadOnly) {
  61.                                         subsection2 = subsection.ContainsSubsection(name2) ?
  62.                                         subsection.OpenSubsection(name2) : subsection.CreateSubsection(name2);
  63.                                 }
  64.  
  65.                                 Int32 val_1 = (Int32)subsection2.ReadProperty(val_1_name, 100);
  66.                                 Int32 val_2 = (Int32)subsection2.ReadProperty(val_2_name, 200);
  67.                         }
  68.                 }
  69.  
  70.                 static void palette_set_Save(object sender, App.IConfigurationSection section) {
  71.                         if (section == null || section.IsReadOnly)
  72.                                 return;
  73.                         App.IConfigurationSection subsection = null;
  74.                         App.IConfigurationSection subsection2 = null;
  75.                         try {
  76.                                 // TODO: The problem is here!!!
  77.                                 // Here execution of code interrupts... Maybe IConfigurationSection is disposed already...
  78.                                 subsection = section.ContainsSubsection(name) ?
  79.                                 section.OpenSubsection(name) : section.CreateSubsection(name);
  80.                         }
  81.                         catch { } // Exception occured. The subsection is null.
  82.                         if (subsection != null && !subsection.IsReadOnly) {
  83.                                 subsection2 = subsection.ContainsSubsection(name2) ?
  84.                                 subsection.OpenSubsection(name2) : subsection.CreateSubsection(name2);
  85.                         }
  86.                         if (subsection2 != null && !subsection2.IsReadOnly) {
  87.                                 subsection2.WriteProperty(val_1_name, 700);
  88.                                 subsection2.WriteProperty(val_2_name, 800);
  89.                         }
  90.                 }
  91.         }
  92. }

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

  • Administrator
  • *****
  • Сообщений: 13829
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Давай разделим код внутри try/catch чтобы было понятно на какой операции вылет, т.е. отдельно
Код - C# [Выбрать]
  1. bool b = section.ContainsSubsection(name);
отдельно
Код - C# [Выбрать]
  1. section.OpenSubsection(name);
отдельно
Код - C# [Выбрать]
  1. subsection.CreateSubsection(name2);
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн Андрей БушманАвтор темы

  • ADN Club
  • *****
  • Сообщений: 2000
  • Карма: 163
  • Пишу программки...
    • Блог
  • Skype: Compositum78
Сделал. Обнаружил странный результат... Сначала подправленный код:

Код - C# [Выбрать]
  1. // © Andrey Bushman, 2013
  2. // AutoCAD 2014 x64 SP1 Enu
  3. using System;
  4. using Microsoft.Win32;
  5.  
  6. using cad = Autodesk.AutoCAD.ApplicationServices.Application;
  7. using App = Autodesk.AutoCAD.ApplicationServices;
  8. using Db = Autodesk.AutoCAD.DatabaseServices;
  9. using Ed = Autodesk.AutoCAD.EditorInput;
  10. using Rtm = Autodesk.AutoCAD.Runtime;
  11. using Win = Autodesk.AutoCAD.Windows;
  12.  
  13. [assembly: Rtm.CommandClass(typeof(Bushman.CAD.Problems.Commands))]
  14.  
  15. namespace Bushman.CAD.Problems {
  16.  
  17.     public static class Commands {
  18.  
  19.         internal static Win.PaletteSet palette_set = null;
  20.  
  21.         [Rtm.CommandMethod("cmd_3", Rtm.CommandFlags.Modal)]
  22.         public static void Command_3() {
  23.             Ed.Editor ed = cad.DocumentManager.MdiActiveDocument.Editor;
  24.             if (palette_set == null) {
  25.                 // This settings will be saved into the
  26.                 // %AppData%\Autodesk\AutoCAD 2014\R19.1\enu\Support\Profiles\Unnamed Profile\Profile.aws
  27.                 // if the current profile is <<Unnamed Profile>>.
  28.                 palette_set = new Win.PaletteSet("My Palette",
  29.                         new Guid("{49DBC66F-21BE-4D9F-A5A9-BA750543042E}"));
  30.                 palette_set.Load += new Win.PalettePersistEventHandler(palette_set_Load);
  31.             }
  32.  
  33.             palette_set.KeepFocus = true;
  34.             palette_set.Visible = true;
  35.         }
  36.  
  37.         [Rtm.CommandMethod("cmd_4", Rtm.CommandFlags.Modal)]
  38.         public static void Command_4() {
  39.             palette_set_Save(section);
  40.         }
  41.  
  42.         static App.IConfigurationSection section = null;
  43.  
  44.         // This names can't to contain the spaces!
  45.         const String name = "AAA";
  46.         const String name2 = "BBB";
  47.         const String val_1_name = "Value_1";
  48.         const String val_2_name = "Value_2";
  49.  
  50.         static void palette_set_Load(object sender, Win.PalettePersistEventArgs e) {
  51.             section = e.ConfigurationSection;
  52.             App.IConfigurationSection subsection = null;
  53.             App.IConfigurationSection subsection2 = null;
  54.  
  55.             if (!section.IsReadOnly) {
  56.                 Boolean n = section.ContainsSubsection(name); // True
  57.                 if (n)
  58.                     subsection = section.OpenSubsection(name);
  59.                 else
  60.                     subsection = section.CreateSubsection(name);
  61.  
  62.                 if (!subsection.IsReadOnly) {
  63.                     Boolean b = subsection.ContainsSubsection(name2); // True
  64.                     if (b)
  65.                         subsection2 = subsection.OpenSubsection(name2);
  66.                     else
  67.                         subsection2 = subsection.CreateSubsection(name2);
  68.                 }
  69.  
  70.                 Int32 val_1 = (Int32)subsection2.ReadProperty(val_1_name, 100);
  71.                 Int32 val_2 = (Int32)subsection2.ReadProperty(val_2_name, 200);
  72.             }
  73.         }
  74.  
  75.         static void palette_set_Save(App.IConfigurationSection section) {
  76.             if (section == null || section.IsReadOnly)
  77.                 return;
  78.             App.IConfigurationSection subsection = null;
  79.             App.IConfigurationSection subsection2 = null;
  80.             try {
  81.                 Boolean b = section.ContainsSubsection(name); // False... Why???                                
  82.                 if (b)
  83.                     subsection = section.OpenSubsection(name);
  84.                 else
  85.                     subsection = section.CreateSubsection(name); // Exception is here
  86.             }
  87.             catch { } // Exception occured. The subsection is null.
  88.             if (subsection != null && !subsection.IsReadOnly) {
  89.                 Boolean n = subsection.ContainsSubsection(name2);
  90.                 if (n)
  91.                     subsection2 = subsection.OpenSubsection(name2);
  92.                 else
  93.                     subsection2 = subsection.CreateSubsection(name2);
  94.             }
  95.             if (subsection2 != null && !subsection2.IsReadOnly) {
  96.                 subsection2.WriteProperty(val_1_name, 700);
  97.                 subsection2.WriteProperty(val_2_name, 800);
  98.             }
  99.         }
  100.     }
  101. }

Операцию сохранения я даже вынес в отдельную команду cmd_4, дабы иметь возможность вызвать её самостоятельно.Обратите внимание на то, что все логические проверки, выполняемые в методе palette_set_Load, возвращают в качестве значения True, т.е. все подразделы обнаружены (они и в самом деле присутствуют в файле Profile.aws). Однако в коде метода palette_set_Save такая проверка возвращает False, хотя работа идёт с одним и тем же статическим объектом:

Код - C# [Выбрать]
  1. static App.IConfigurationSection section

Затем идёт попытка создания подраздела, в результате чего и генерируется исключение.

Вопрос: Почему логическая проверка в методе palette_set_Save возвращает False, а не True?

Я вот смотрю на эти строки кода:

Код - C# [Выбрать]
  1. static void palette_set_Load(object sender, Win.PalettePersistEventArgs e) {
  2.     section = e.ConfigurationSection;

Может быть по выходу из метода  palette_set_Load AutoCAD вызывает метод e.ConfigurationSection.Dispose(), в виду чего IConfigurationSection section становится некорректным и в то же время не равным null?


Спасибо.
« Последнее редактирование: 06-12-2013, 08:38:19 от Андрей Бушман »

Оффлайн Андрей БушманАвтор темы

  • ADN Club
  • *****
  • Сообщений: 2000
  • Карма: 163
  • Пишу программки...
    • Блог
  • Skype: Compositum78
Проблема решена. Даже правильней сказать так: экспериментальным образом я обнаружил мягко говоря странные вещи, влияющие на обработку событий в AutoCAD. Возможно это будет интересно ещё кому-то... Итак, на данный момент, на руках я имею следующие факты:
  • Если палитра создаётся при помощи конструктора, вторым параметром которого указан GUID, то настройки свойств такой палитры AutoCAD автоматически сам будет сохранять в AWS файл, расположенный в перемещаемом пользовательском профиле Windows. При этом не следует путать настройки свойств самой палитры (её расположение на экране, размеры и т.п.) с настройками размещённых вами на ней пользовательских элементов графического интерфейса, т.к. сохранение этих настроек - это уже ваша головная боль (как программиста).
  • При помощи IConfigurationSection вы можете сохранять в том же AWS файле и настройки своих пользовательских контролов, "хостящихся" на вашей палитре. Эти настройки можно группировать как угодно, создавая произвольный уровень вложенности (на ваше усмотрение). Важный момент: имена создаваемых вами разделов, подразделов и свойств должны соответствовать правилам, предъявляемым XML к наименованию своих элементов и их атрибутов.
  • Если вы создаёте палитру, указанным в п.1 способом, то будьте готовы к тому, что сразу после первого создания такой палитры AutoCAD не будет генерировать событие PaletteSet.Load, в виду того, что в AWS файле ещё нет информации по данной палитре. Т. о. код, который будет зарегистрирован на это событие, не будет выполнен при первом открытии палитры, созданном способом, обозначенным в п.1. Но после того, как AutoCAD внесёт в AWS файл запись о палитре, обозначенное выше событие будет происходить (начиная со следующей сессии работы AutoCAD).
  • Такие события как PaletteSet.Load и PaletteSet.Save регистрируют делегаты, вторым параметром которых передаётся объект PalettePersistEventArgs. Этот объект, в свою очередь имеет свойство PalettePersistEventArgs.ConfigurationSection, посредством которого вы получаете доступ к экземпляру IConfigurationSection. Этот экземпляр даёт вам доступ к сохраняемым в AWS файле настройкам палитры и размещённых не ней ваших пользовательских элементов. Используя этот объект вы можете управлять сохранением своих пользовательских настроек.
  • Нет смысла ссылку на объект IConfigurationSection, переданный AutoCAD'ом в качестве второго параметра (см. предыдущий пункт), сохранять во внешнюю переменную уровня экземпляра или класса. Дело в том, что по выходу из блока кода, который вы регистрировали на нужное вам событие, AutoCAD выполняет дополнительные действия с этим объектом: скорее всего освобождает некоторые неуправляемые ресурсы, может быть даже вызывая для этого  экземплярный метод Dispose. Если вы, в последствии, выполните проверку на null для такого объекта, то получите false, но корректно работать этот объект уже не будет.
  • Из предыдущего пункта следует, что править настройки (посредством IConfigurationSection) следует только в коде, зарегистрированном на определённые события PaletteSet.
  • Код, сохраняющий настройки ваших пользовательских элементов, "хостящихся" на палитре, следует регистрировать на событие PaletteSet.Save.
  • К сожалению, AutoCAD не генерирует событие PaletteSet.Save, если вы дополнительно не зарегистрировались и на свойство PaletteSet.Saving (даже если оно вам и не нужно). Вам придётся зарегистрировать на PaletteSet.Saving хотя бы "пустышку" (метод, в котором ничего нет). Это баг.
  • Нет никакой необходимости делать ваш класс статическим, или же делать статическими его команды, работающие с палитрами - экземплярных методов вполне достаточно.

Ну а теперь, собственно, работающий код, в котором учтены все обозначенные мною выше пункты:

Код - C# [Выбрать]
  1. /* © Andrey Bushman, 2013
  2.  * AutoCAD 2014 x64 SP1
  3.  * The sample, how to save the some settings of your custom controls into the AWS file.
  4.  * I showed the feature of the "IConfigurationSection.Save" event's registration.
  5.  */
  6.  
  7. using System;
  8. using Microsoft.Win32;
  9.  
  10. using cad = Autodesk.AutoCAD.ApplicationServices.Application;
  11. using App = Autodesk.AutoCAD.ApplicationServices;
  12. using Db = Autodesk.AutoCAD.DatabaseServices;
  13. using Ed = Autodesk.AutoCAD.EditorInput;
  14. using Rtm = Autodesk.AutoCAD.Runtime;
  15. using Win = Autodesk.AutoCAD.Windows;
  16.  
  17. [assembly: Rtm.CommandClass(typeof(Bushman.CAD.Problems.Commands))]
  18.  
  19. namespace Bushman.CAD.Problems {
  20.  
  21.         public class Commands {
  22.  
  23.                 [Rtm.CommandMethod("cmd_4", Rtm.CommandFlags.Modal)]
  24.                 public void Command_4() {
  25.                         Ed.Editor ed = cad.DocumentManager.MdiActiveDocument.Editor;
  26.  
  27.                         // This settings will be saved into the
  28.                         // %AppData%\Autodesk\AutoCAD 2014\R19.1\enu\Support\Profiles\Unnamed Profile\Profile.aws
  29.                         // if the current profile is <<Unnamed Profile>>.
  30.                         Win.PaletteSet palette_set = new Win.PaletteSet("My Palette",
  31.                                 new Guid("{49DBC66F-21BE-4D9F-A5A9-BA750543042E}"));
  32.                         palette_set.Load += new Win.PalettePersistEventHandler(palette_set_Load);
  33.                         palette_set.Save += new Win.PalettePersistEventHandler(palette_set_Save);
  34.  
  35.                         // WARNING! If you will comment the next code line, the 'Save' event not occurs!
  36.                         // I think it is a bug of API.
  37.                         palette_set.Saving += new Win.PalettePersistEventHandler(palette_set_Saving);
  38.  
  39.                         palette_set.KeepFocus = true;
  40.                         palette_set.Visible = true;
  41.                 }
  42.  
  43.                 void palette_set_Save(object sender, Win.PalettePersistEventArgs e) {
  44.                         palette_set_Save(e.ConfigurationSection);
  45.                 }
  46.  
  47.                 void palette_set_Saving(object sender, Win.PalettePersistEventArgs e) {
  48.                         // The empty implementation...
  49.                 }
  50.  
  51.                 // This names can't to contain the spaces (it will used as the xml
  52.                 // element's and attribute's names)!
  53.                 const String name = "AAA";
  54.                 const String name2 = "BBB";
  55.                 const String val_1_name = "Value_1";
  56.                 const String val_2_name = "Value_2";
  57.  
  58.                 void palette_set_Load(object sender, Win.PalettePersistEventArgs e) {
  59.                         App.IConfigurationSection section = e.ConfigurationSection;
  60.                         App.IConfigurationSection subsection = null;
  61.                         App.IConfigurationSection subsection2 = null;
  62.  
  63.                         if (!section.IsReadOnly) {
  64.                                 Boolean n = section.ContainsSubsection(name);
  65.                                 if (n)
  66.                                         subsection = section.OpenSubsection(name);
  67.                                 else
  68.                                         subsection = section.CreateSubsection(name);
  69.  
  70.                                 if (!subsection.IsReadOnly) {
  71.                                         Boolean b = subsection.ContainsSubsection(name2);
  72.                                         if (b)
  73.                                                 subsection2 = subsection.OpenSubsection(name2);
  74.                                         else
  75.                                                 subsection2 = subsection.CreateSubsection(name2);
  76.                                 }
  77.  
  78.                                 Int32 val_1 = (Int32)subsection2.ReadProperty(val_1_name, 100);
  79.                                 Int32 val_2 = (Int32)subsection2.ReadProperty(val_2_name, 200);                        
  80.                         }
  81.                 }
  82.  
  83.                 void palette_set_Save(App.IConfigurationSection section) {
  84.                         if (section == null || section.IsReadOnly)
  85.                                 return;
  86.                         App.IConfigurationSection subsection = null;
  87.                         App.IConfigurationSection subsection2 = null;
  88.  
  89.                         Boolean b = section.ContainsSubsection(name);
  90.                         if (b)
  91.                                 subsection = section.OpenSubsection(name);
  92.                         else
  93.                                 subsection = section.CreateSubsection(name);
  94.  
  95.                         if (subsection != null && !subsection.IsReadOnly) {
  96.                                 Boolean n = subsection.ContainsSubsection(name2);
  97.                                 if (n)
  98.                                         subsection2 = subsection.OpenSubsection(name2);
  99.                                 else
  100.                                         subsection2 = subsection.CreateSubsection(name2);
  101.                         }
  102.  
  103.                         if (subsection2 != null && !subsection2.IsReadOnly) {
  104.                                 subsection2.WriteProperty(val_1_name, 123);
  105.                                 subsection2.WriteProperty(val_2_name, 456);
  106.                         }
  107.                 }
  108.         }
  109. }

Если по завершению работы AutoCAD вы заглянете в AWS файл, то обнаружите, что в нём появились такие настройки:

Код - XML [Выбрать]
  1. <Tool CLSID="{49DBC66F-21BE-4D9F-A5A9-BA750543042E}">
  2.   <CAdUiDockControlBar Orientation="-1" AllowDocking="1">
  3.     <FloatInfo Left="458" Top="295" Width="447" Height="384"/>
  4.     <DockInfo Left="0" Top="6732" Width="300" Height="798" MRUDockID="59420"/>
  5.   </CAdUiDockControlBar>
  6.   <CAdUiPaletteSet/>
  7.   <AAA>
  8.     <BBB Value_1="123" Value_2="456"/>
  9.   </AAA>
  10. </Tool>

Если вы закомментируете строку 37, то событие IConfigurationSection.Save происходить не будет. В виду этого не будет вызван на исполнение код метода palette_set_Save и, как следствие, выполненные в этом коде изменения настроек не будут произведены.
« Последнее редактирование: 06-12-2013, 12:46:35 от Андрей Бушман »

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

  • Administrator
  • *****
  • Сообщений: 13829
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
К сожалению, AutoCAD не генерирует событие PaletteSet.Save, если вы дополнительно не зарегистрировались и на свойство PaletteSet.Saving (даже если оно вам и не нужно). Вам придётся зарегистрировать на PaletteSet.Saving хотя бы "пустышку" (метод, в котором ничего нет). Это баг.
Молодец. Отличная работа! Похоже ты прав. Кстати, в составе ObjectARX SDK 2009 (и в более ранних) есть пример samples\dotNet\DockingPalette. В нём есть подписка на события Save и Load, но нет подписки на событие Saving. Интересно работает ли корректно этот пример? У меня как раз AutoCAD 2009 не установлен, а в других версиях проверять будет не вполне корректно.

P.S.: Интересно в ADN DevHelp найдут сами решение или придётся им подсказать? Пока подождём.  ::)
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн Андрей БушманАвтор темы

  • ADN Club
  • *****
  • Сообщений: 2000
  • Карма: 163
  • Пишу программки...
    • Блог
  • Skype: Compositum78
Меня несколько удивляет тот факт, что генерация события Save происходит ДО генерации события Saving - по логике наименований должно быть наоборот...

Обнаружил ещё кое-что... Оказывается, что событие Save (при отсутствии подписки на Saving) не генерируется в том случае, если палитра пустая. В случае же наличия на палитре какого-либо элемента, событие Save начинает работать (даже если нет подписки на Saving).

Код - C# [Выбрать]
  1. /* © Andrey Bushman, 2013
  2.  * AutoCAD 2014 x64 SP1
  3.  * The sample, how to save the some settings of your custom controls into the AWS file.
  4.  */
  5.  
  6. using System;
  7. using Microsoft.Win32;
  8.  
  9. using cad = Autodesk.AutoCAD.ApplicationServices.Application;
  10. using App = Autodesk.AutoCAD.ApplicationServices;
  11. using Db = Autodesk.AutoCAD.DatabaseServices;
  12. using Ed = Autodesk.AutoCAD.EditorInput;
  13. using Rtm = Autodesk.AutoCAD.Runtime;
  14. using Win = Autodesk.AutoCAD.Windows;
  15. using Int = System.Windows.Forms.Integration;
  16. using WF = System.Windows.Forms;
  17. [assembly: Rtm.CommandClass(typeof(Bushman.CAD.Problems.Commands))]
  18.  
  19. namespace Bushman.CAD.Problems {
  20.  
  21.         public class Commands {
  22.  
  23.                 [Rtm.CommandMethod("cmd_5", Rtm.CommandFlags.Modal)]
  24.                 public void Command_5() {
  25.                         Ed.Editor ed = cad.DocumentManager.MdiActiveDocument.Editor;
  26.  
  27.                         // This settings will be saved into the
  28.                         // %AppData%\Autodesk\AutoCAD 2014\R19.1\enu\Support\Profiles\Unnamed Profile\Profile.aws
  29.                         // if the current profile is the <<Unnamed Profile>>.
  30.                         Win.PaletteSet palette_set = new Win.PaletteSet("My Palette",
  31.                                         new Guid("{49DBC66F-21BE-4D9F-A5A9-BA750543042E}"));
  32.  
  33.                         // Add the some Control item on the palette (the Label for example)...
  34.                         WF.Label label = new WF.Label();
  35.                         label.Text = "Hello, World";
  36.                         palette_set.Add("123", label);
  37.  
  38.                         palette_set.Load += new Win.PalettePersistEventHandler(palette_set_Load);
  39.                         palette_set.Save += new Win.PalettePersistEventHandler(palette_set_Save);
  40.  
  41.                         palette_set.KeepFocus = true;
  42.                         palette_set.Visible = true;
  43.                 }
  44.  
  45.                 void palette_set_Save(object sender, Win.PalettePersistEventArgs e) {
  46.                         palette_set_Save(e.ConfigurationSection);
  47.                 }
  48.  
  49.                 // This names can't to contain the spaces (it will used as the xml
  50.                 // element's and attribute's names)!
  51.                 const String name = "AAA";
  52.                 const String name2 = "BBB";
  53.                 const String val_1_name = "Value_1";
  54.                 const String val_2_name = "Value_2";
  55.  
  56.                 void palette_set_Load(object sender, Win.PalettePersistEventArgs e) {
  57.                         App.IConfigurationSection section = e.ConfigurationSection;
  58.                         App.IConfigurationSection subsection = null;
  59.                         App.IConfigurationSection subsection2 = null;
  60.  
  61.                         if (!section.IsReadOnly) {
  62.                                 Boolean n = section.ContainsSubsection(name);
  63.                                 if (n)
  64.                                         subsection = section.OpenSubsection(name);
  65.                                 else
  66.                                         subsection = section.CreateSubsection(name);
  67.  
  68.                                 if (!subsection.IsReadOnly) {
  69.                                         Boolean b = subsection.ContainsSubsection(name2);
  70.                                         if (b)
  71.                                                 subsection2 = subsection.OpenSubsection(name2);
  72.                                         else
  73.                                                 subsection2 = subsection.CreateSubsection(name2);
  74.                                 }
  75.  
  76.                                 Int32 val_1 = (Int32)subsection2.ReadProperty(val_1_name, 100);
  77.                                 Int32 val_2 = (Int32)subsection2.ReadProperty(val_2_name, 200);
  78.                         }
  79.                 }
  80.  
  81.                 void palette_set_Save(App.IConfigurationSection section) {
  82.                         if (section == null || section.IsReadOnly)
  83.                                 return;
  84.                         App.IConfigurationSection subsection = null;
  85.                         App.IConfigurationSection subsection2 = null;
  86.  
  87.                         Boolean b = section.ContainsSubsection(name);
  88.                         if (b)
  89.                                 subsection = section.OpenSubsection(name);
  90.                         else
  91.                                 subsection = section.CreateSubsection(name);
  92.  
  93.                         if (subsection != null && !subsection.IsReadOnly) {
  94.                                 Boolean n = subsection.ContainsSubsection(name2);
  95.                                 if (n)
  96.                                         subsection2 = subsection.OpenSubsection(name2);
  97.                                 else
  98.                                         subsection2 = subsection.CreateSubsection(name2);
  99.                         }
  100.  
  101.                         if (subsection2 != null && !subsection2.IsReadOnly) {
  102.                                 subsection2.WriteProperty(val_1_name, 123);
  103.                                 subsection2.WriteProperty(val_2_name, 456);
  104.                         }
  105.                 }
  106.         }
  107. }

Любопытный момент: если при этом выполнена подписка и на событие Saving, то Save генерируется дважды. Во втором случае последовательность генерации событий следующая:
  • Save
  • Saving
  • Save

Избыточная цепь генерации событий, на мой взгляд.

Поскольку создаваемые программно палитры как правило не пустые, то обозначенную в данной теме проблему можно считать несущественной.

С уважением, Андрей.

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

  • Administrator
  • *****
  • Сообщений: 13829
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Оказывается, что событие Save (при отсутствии подписки на Saving) не генерируется в том случае, если палитра пустая.
Не очень понятно баг это или фича, но в ADN DevHelp отправлю - пусть объяснят.
Избыточная цепь генерации событий, на мой взгляд.
Согласен полностью.
Жду первого ответа по этой теме от ADN DevHelp.

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

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

  • Administrator
  • *****
  • Сообщений: 13829
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
На первый вопрос я получил ответ от ADN DevHelp - PaletteSet.Save генерируется только если она не пустая, т.е. есть хоть одна Palette. Но это ты уже и сам нашел.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение