Как программно закрыть палитру?

Автор Тема: Как программно закрыть палитру?  (Прочитано 8809 раз)

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

Оффлайн Александр Пекшев aka ModisАвтор темы

  • ADN Club
  • *****
  • Сообщений: 1658
  • Карма: 366
  • Отец modplus.org
    • ModPlus
Сам не ожидал, но вот такой вопрос задаю =)
Имеем палитру:
Код - C# [Выбрать]
  1. public static class MpPalette
  2. {
  3.     public static PaletteSet MpPaletteSet;
  4.  
  5.     public static void CreatePalette()
  6.     {
  7.         try
  8.         {
  9.             if (MpPaletteSet == null)
  10.             {
  11.                 MpPaletteSet = new PaletteSet("ModPlus", new Guid("A9C907EF-6281-4FA2-9B6C-E0401E41BB74"));
  12.                 MpPaletteSet.Load += _mpPaletteSet_Load;
  13.                 MpPaletteSet.Save += _mpPaletteSet_Save;
  14.                
  15.                 MpPaletteSet.Style =
  16.                     PaletteSetStyles.ShowPropertiesMenu |
  17.                     PaletteSetStyles.ShowAutoHideButton |
  18.                     PaletteSetStyles.ShowCloseButton;
  19.                 MpPaletteSet.MinimumSize = new System.Drawing.Size(100, 300);
  20.                 MpPaletteSet.DockEnabled = DockSides.Left | DockSides.Right;
  21.  
  22.                 MpPaletteSet.Visible = true;
  23.             }
  24.             else
  25.             {
  26.                 MpPaletteSet.Visible = true;
  27.             }
  28.         }
  29.         catch (System.Exception exception) { MpExWin.Show(exception); }
  30.     }
  31.  
  32.     private static void _mpPaletteSet_Save(object sender, PalettePersistEventArgs e)
  33.     {
  34.         var a = (double)e.ConfigurationSection.ReadProperty("ModPlusPalette", 22.3);
  35.     }
  36.  
  37.     private static void _mpPaletteSet_Load(object sender, PalettePersistEventArgs e)
  38.     {
  39.         e.ConfigurationSection.WriteProperty("ModPlusPalette", 32.3);
  40.     }
  41. }
как бы просто "заготовка"
В окне настроек для программы (при закрытии окна) я хочу обработать галочку "палитра" - есть галочка, значит включаем; нет галочки, значит отключаем:
Код - C# [Выбрать]
  1. // если отключили палитру
  2. if (!ChkMpPalette.IsChecked.Value)
  3. {
  4.     if(MpPalette.MpPaletteSet != null)
  5.           MpPalette.MpPaletteSet.Close();
  6.  
  7. }
  8. else // если включили палитру
  9. {
  10.     MpPalette.CreatePalette();
  11. }
Так вот - PaletteSet.Close() не работает. Причем, палитра остается висеть в окне автокада, но становится не юзабельной: у нее не работают никакие кнопки (типа закрыть) и меню. Ее даже подвинуть нельзя. Проверял на 2010 и 2017 автокаде - одинаково

Оффлайн Андрей Бушман

  • ADN Club
  • *****
  • Сообщений: 2000
  • Карма: 163
  • Пишу программки...
    • Блог
  • Skype: Compositum78
Re: Как программно закрыть палитру?
« Ответ #1 : 06-11-2016, 16:07:10 »
Окно "настроек" модальное или нет? Как открываешь его?

Оффлайн avc

  • ADN Club
  • *****
  • Сообщений: 828
  • Карма: 168
    • Мои плагины к Автокаду
Re: Как программно закрыть палитру?
« Ответ #2 : 06-11-2016, 16:16:36 »
Присоединяюсь.
Закрыть/открыть палитру из CommandMethod получается только так:
Код - C# [Выбрать]
  1.           if (ps.Visible)
  2.           {
  3.             ps.Close();
  4.             ps.Visible = false;
  5.           }
  6.           else
  7.           {
  8.             if (ps.Count == 0)  ps.Add("Test", MyControl);
  9.             ps.Activate(0);
  10.             ps.Visible = true;
  11.           }
  12.  

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

  • Administrator
  • *****
  • Сообщений: 13894
  • Карма: 1789
  • Рыцарь ObjectARX
  • Skype: rivilis
Re: Как программно закрыть палитру?
« Ответ #3 : 06-11-2016, 16:39:00 »
А почему бы не оставить только
Код - C# [Выбрать]
  1. ps.Visible = false;
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн Андрей Бушман

  • ADN Club
  • *****
  • Сообщений: 2000
  • Карма: 163
  • Пишу программки...
    • Блог
  • Skype: Compositum78
Re: Как программно закрыть палитру?
« Ответ #4 : 06-11-2016, 16:53:21 »
А почему бы не оставить только
Может это он оперативную память пытается экономить, вызывая Close() и присваивая null... :) При этом я не вижу, чтобы он в своём коде вызывал Dispose(). Возможно, что Dispose() вызывается в методе Close(), но у доски я не вижу информации на эту тему в доках.

Код - C# [Выбрать]
  1. using System;
  2. using Autodesk.AutoCAD.Runtime;
  3. using Autodesk.AutoCAD.Windows;
  4.  
  5. [assembly: CommandClass(typeof(Bushman.AcTemp.Commands))]
  6.  
  7. namespace Bushman.AcTemp {
  8.     public class Commands {
  9.  
  10.         static PaletteSet myPaletteSet;
  11.  
  12.         static readonly Guid MyPaletteSetGuid = new Guid(
  13.             "{0C7E00B8-EFC9-4A79-B4D7-CA28128D2E6A}");
  14.  
  15.         static void InitializeMyPaletteSet() {
  16.  
  17.             if (MyPaletteSet == null) {
  18.  
  19.                 MyPaletteSet = new PaletteSet("My Palette Set",
  20.                     MyPaletteSetGuid);
  21.             }
  22.         }
  23.  
  24.         static void CloseMyPaletteSet() {
  25.  
  26.             if (MyPaletteSet != null) {
  27.  
  28.                 MyPaletteSet.Visible = false;
  29.             }
  30.  
  31.             MyPaletteSet?.Close();
  32.             MyPaletteSet?.Dispose();
  33.             myPaletteSet = null;
  34.         }
  35.  
  36.         internal static PaletteSet MyPaletteSet {
  37.             get { return myPaletteSet; }
  38.             private set { myPaletteSet = value; }
  39.         }
  40.  
  41.         [CommandMethod("ShowPaletteSet", CommandFlags.Session)]
  42.         public void ShowPaletteSetCommand() {
  43.  
  44.             InitializeMyPaletteSet();
  45.             MyPaletteSet.Visible = true;
  46.         }
  47.  
  48.         [CommandMethod("ClosePaletteSet", CommandFlags.Session)]
  49.         public void ClosePaletteSet() {
  50.  
  51.             CloseMyPaletteSet();
  52.         }
  53.     }
  54. }

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

  • Administrator
  • *****
  • Сообщений: 13894
  • Карма: 1789
  • Рыцарь ObjectARX
  • Skype: rivilis
Re: Как программно закрыть палитру?
« Ответ #5 : 06-11-2016, 17:09:46 »
Возможно, что Dispose() вызывается в методе Close()
Нет. Скорее наоборот. DeleteUnmanagedObject (который вызывается при Dispose, т.к. этот класс в качестве одного из прародителей имеет класс DisposableWrapper) вызывает Close():
Код - C# [Выбрать]
  1. protected override void DeleteUnmanagedObject()
  2. {
  3.         this.Close();
  4. }

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

Оффлайн Андрей Бушман

  • ADN Club
  • *****
  • Сообщений: 2000
  • Карма: 163
  • Пишу программки...
    • Блог
  • Skype: Compositum78
Re: Как программно закрыть палитру?
« Ответ #6 : 06-11-2016, 17:17:14 »
Нет. Скорее наоборот.
Тогда похоже, что это кривая реализация класса PaletteSet, ежели после вызова Dispose() на экране остаются подобные артефакты.

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

  • Administrator
  • *****
  • Сообщений: 13894
  • Карма: 1789
  • Рыцарь ObjectARX
  • Skype: rivilis
Re: Как программно закрыть палитру?
« Ответ #7 : 06-11-2016, 17:22:50 »
Тогда похоже, что это кривая реализация класса PaletteSet, ежели после вызова Dispose() на экране остаются подобные артефакты.
Ну тогда следует грешить на Microsoft, т.к. метод Close посылает окну сообщение WM_CLOSE (WM_CLOSE == 0x10 == 16), что и должно приводить к закрытию окна:
Код - C# [Выбрать]
  1. public unsafe void Close()
  2. {
  3.   <Module>.PostMessageW(*(long*)(this.GetWnd() + 64L / (long)sizeof(CWnd)), 16u, 0uL, 0L);
  4. }
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн Андрей Бушман

  • ADN Club
  • *****
  • Сообщений: 2000
  • Карма: 163
  • Пишу программки...
    • Блог
  • Skype: Compositum78
Re: Как программно закрыть палитру?
« Ответ #8 : 06-11-2016, 18:00:08 »
Ну тогда следует грешить на Microsoft, т.к. метод Close посылает окну сообщение WM_CLOSE (WM_CLOSE == 0x10 == 16), что и должно приводить к закрытию окна:
Код - C# [Выбрать]
  1. public unsafe void Close()
  2. {
  3.     PostMessageW(*((HWND__**) (this.GetWnd() + 0x40L)), 0x10, 0L, 0L);
  4. }
  5.  
  6. public sealed override void Dispose()
  7. {
  8.     this.Dispose(true);
  9.     GC.SuppressFinalize(this);
  10. }
  11.  
  12. [HandleProcessCorruptedStateExceptions]
  13. protected virtual void Dispose([MarshalAs(UnmanagedType.U1)] bool A_0)
  14. {
  15.     if (A_0)
  16.     {
  17.         this.~DisposableWrapper();
  18.     }
  19.     else
  20.     {
  21.         try
  22.         {
  23.             this.!DisposableWrapper();
  24.         }
  25.         finally
  26.         {
  27.             base.Finalize();
  28.         }
  29.     }
  30. }
  31.  
  32.  

Нет. Скорее наоборот. DeleteUnmanagedObject (который вызывается при Dispose, т.к. этот класс в качестве одного из прародителей имеет класс DisposableWrapper) вызывает Close():
Код - C# [Выбрать]
Я не вижу, чтобы вызов метода Dispose() приводил бы к вызову Close(). Я рекурсивно просмотрел в рефлекторе в т.ч. и код обозначенных выше методов ~DisposableWrapper(), Finalize() и !DisposableWrapper(), но так и не нашёл этого вызова.

Оффлайн avc

  • ADN Club
  • *****
  • Сообщений: 828
  • Карма: 168
    • Мои плагины к Автокаду
Re: Как программно закрыть палитру?
« Ответ #9 : 06-11-2016, 18:26:20 »
Давно я с этим мучился, уже подзабыл, но по-моему только комбинация Close/Activate вместе с visible=false/true позволяет закрывать палитры И программно из команды, И от пользователя "крестиком". Если скрыть кнопку закрытия от пользователя - тогда можно обойтись только visible. Иначе закрытая пользователем палитра (не командой) уже не восстанавливается. Вроде бы так, но я не уверен... надо тестить, вспоминать...

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

  • Administrator
  • *****
  • Сообщений: 13894
  • Карма: 1789
  • Рыцарь ObjectARX
  • Skype: rivilis
Re: Как программно закрыть палитру?
« Ответ #10 : 06-11-2016, 18:52:15 »
Я не вижу, чтобы вызов метода Dispose() приводил бы к вызову Close(). Я рекурсивно просмотрел в рефлекторе в т.ч. и код обозначенных выше методов ~DisposableWrapper(), Finalize() и !DisposableWrapper(), но так и не нашёл этого вызова.
Ты не досмотрел до конца:
Код - C# [Выбрать]
  1. private void !DisposableWrapper()
  2. {
  3.         if (this.m_bAutoDelete && this.m_imp != IntPtr.Zero)
  4.         {
  5.                 this.DeleteUnmanagedObject();
  6.         }
  7.         this.Detach();
  8. }
Ну а DeleteUnmanagedObject в свою очередь вызывает this.Close
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение