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

ADN Club => AutoCAD .NET API => Тема начата: Doublefish от 20-08-2015, 08:45:59

Название: Не срабатывает действие в контекстном меню из StatusBar ?
Отправлено: Doublefish от 20-08-2015, 08:45:59
http://adndevblog.typepad.com/autocad/2012/06/setting-up-a-timer-in-a-net-sample-that-uses-the-autocad-net-api.html

Добавил контекстное меню, оно появляется, но при нажатии на пункт меню ничего не происходит, MenuOnClick не срабатывает (окно с текстом test click не появляется), отладчик не реагирует - почему? (это отдельный вопрос из этой темы (http://adn-cis.org/forum/index.php?topic=2920.0) )

В MyBubbleTimer_Tick добавил строку:
Код - C# [Выбрать]
  1.  _ti.MouseDown += new StatusBarMouseDownEventHandler(MouseDown);

Код - C# [Выбрать]
  1. void MouseDown(object sender, StatusBarMouseDownEventArgs e)
  2.         {
  3.             System.Windows.Forms.ContextMenu contextMenu = new System.Windows.Forms.ContextMenu();
  4.             contextMenu.Name = "my menu";
  5.            System.Windows.Forms.Menu.MenuItemCollection cm = new System.Windows.Forms.Menu.MenuItemCollection(contextMenu);
  6.             cm.Add("test click", new EventHandler(MenuOnClick));
  7.             _ti.DisplayContextMenu(contextMenu, new System.Drawing.Point(e.X, e.Y));
  8.         }
  9.            
  10. void MenuOnClick(object obj, EventArgs e)
  11.         {
  12.            MessageBox.Show("test click");
  13.         }
Название: Re: Не срабатывает действие в контекстном меню из StatusBar ?
Отправлено: Александр Ривилис от 20-08-2015, 09:37:22
Выкладывай полностью код для проверки.
Название: Re: Не срабатывает действие в контекстном меню из StatusBar ?
Отправлено: Doublefish от 20-08-2015, 10:12:51
Да, наверное лучше  zip тестового проекта.
Название: Re: Не срабатывает действие в контекстном меню из StatusBar ?
Отправлено: Александр Ривилис от 20-08-2015, 11:12:38
Я просил полный исходный текст. Если так не понятно, то давай полный проект (в zip-архиве).
Название: Re: Не срабатывает действие в контекстном меню из StatusBar ?
Отправлено: Doublefish от 20-08-2015, 11:39:24
Обновил сообщение и приложил zip.
Название: Re: Не срабатывает действие в контекстном меню из StatusBar ?
Отправлено: Александр Ривилис от 20-08-2015, 11:50:53
Похоже на (уже) известный баг. Андрей Бушман уже на него натыкался ( http://www.theswamp.org/index.php?topic=39707.0) и дал альтернативное решение ( http://www.theswamp.org/index.php?topic=43077.0 )
Отправлю этот вопрос в ADN DevHelp.
Название: Re: Не срабатывает действие в контекстном меню из StatusBar ?
Отправлено: Александр Ривилис от 20-08-2015, 13:13:04
Я придумал альтернативу для метода DisplayContextMenu:
Код - C# [Выбрать]
  1.     void _ti_MouseDown(object sender, StatusBarMouseDownEventArgs e)
  2.     {
  3.       System.Windows.Forms.ContextMenu contextMenu = new System.Windows.Forms.ContextMenu();
  4.       contextMenu.Name = "my menu";
  5.       contextMenu.MenuItems.Add("test click", new EventHandler(MenuOnClick));
  6.       // _ti.DisplayContextMenu(contextMenu, new System.Drawing.Point(e.X, e.Y));
  7.       this.Location = Cursor.Position;  this.Show();
  8.       contextMenu.Show(this, new System.Drawing.Point(0, 0));
  9.       this.Hide();
  10.     }
  11.  
Посмотри приложенный проект. Возможности детально протестировать не было. Проверял только в AutoCAD 2013.
Название: Re: Не срабатывает действие в контекстном меню из StatusBar ?
Отправлено: Doublefish от 20-08-2015, 16:55:03
О чудо - обработчик контекстного меню стал отзываться.
Хотелось бы узнать в последствии что ответили в ADN DevHelp по этому поводу))
Название: Re: Не срабатывает действие в контекстном меню из StatusBar ?
Отправлено: Александр Ривилис от 20-08-2015, 17:03:05
О чудо - обработчик контекстного меню стал отзываться.
Я правильно понимаю, что предложенный мной вариант тебя устроил?
Хотелось бы узнать в последствии что ответили в ADN DevHelp по этому поводу))
Мне это тоже интересно, хотя я уже сейчас догадываюсь (на 90%) какой будет ответ: "Так как метод DisplayContextMenu - это "обертка" над функцией ObjectARX AcStatusBarItem::DisplayContextMenu, которая оперирует MFC классом CMenu, аналога которому в .NET нет, то у нас нет возможности реализовать этот метод..."
Название: Re: Не срабатывает действие в контекстном меню из StatusBar ?
Отправлено: Doublefish от 21-08-2015, 10:39:32
Думаю, что такой вариант подходит. Спасибо.
Название: Re: Не срабатывает действие в контекстном меню из StatusBar ?
Отправлено: Александр Ривилис от 21-08-2015, 11:06:46
Запрос в ADN DevHelp отправил.
Название: Re: Не срабатывает действие в контекстном меню из StatusBar ?
Отправлено: Doublefish от 24-08-2015, 11:49:02
Ещё один момент - при первом срабатывании таймера все иконки в трее  становятся одинаковыми (например меняется иконка изоляции объектов на ту что задана в проекте), при втором срабатывании таймера иконки становятся нормальными. Как сделать чтобы при первом срабатывании таймера иконки не становились в трее одинаковыми?
Название: Re: Не срабатывает действие в контекстном меню из StatusBar ?
Отправлено: Александр Ривилис от 24-08-2015, 13:26:50
У меня такого не происходит. Возможно это баг Civil3D. Проверь на моём коде.
Название: Re: Не срабатывает действие в контекстном меню из StatusBar ?
Отправлено: Doublefish от 24-08-2015, 14:57:24
Проверил с вашим кодом - проблема есть
Поставьте
Код - C# [Выбрать]
  1. _MyTimer.Interval = 10000;
через 10 сек иконки меняются и выглядит не красиво, если окно автокада свернуть развернуть или в модели колесом мыши подвигать модель или закрыть всплывающее сообщение по крестику, то иконка  изолированных объектов становиться нормальной

Я проверял в автокаде в составе Civil 3D, а в обычном автокаде этой проблемы нет?
Название: Re: Не срабатывает действие в контекстном меню из StatusBar ?
Отправлено: Александр Ривилис от 24-08-2015, 15:01:22
Я проверял в автокаде в составе Civil 3D, а в обычном автокаде этой проблемы нет?
У меня нет. Попробуй выполнить действие, которое приводит к перерисовке, программно.
Название: Re: Не срабатывает действие в контекстном меню из StatusBar ?
Отправлено: Doublefish от 24-08-2015, 15:06:56
Код - C# [Выбрать]
  1. sb.Update();
не попогает

например какие действия?
Название: Re: Не срабатывает действие в контекстном меню из StatusBar ?
Отправлено: Александр Ривилис от 24-08-2015, 15:12:17
например какие действия?
Экспериментируй. Попробуй создавать _ti не в функции таймера, а заранее. А вот _ti.ShowBubbleWindow(bubble); вызывать по таймеру.
Возможно _ti.Visible = false; и _ti.Visible = true; приведут к нужному результату. Может поможет Application.DoEvents. Увы, но у себя я это проверить не могу.
 
Название: Re: Не срабатывает действие в контекстном меню из StatusBar ?
Отправлено: Doublefish от 24-08-2015, 15:23:58
О чудо - visible помогло
Код - C# [Выбрать]
  1. _ti.Visible = false;
  2. tic.Add(_ti);
  3. _ti.Visible = true;

Спасибо
Название: Re: Не срабатывает действие в контекстном меню из StatusBar ?
Отправлено: Александр Ривилис от 24-08-2015, 15:28:04
О чудо - visible помогло
Это не чудо. Это интуиция. :)
Название: Re: Не срабатывает действие в контекстном меню из StatusBar ?
Отправлено: Андрей Бушман от 24-08-2015, 15:41:05
Иконки следует объявлять в коде статическими.
Название: Re: Не срабатывает действие в контекстном меню из StatusBar ?
Отправлено: Doublefish от 24-08-2015, 15:49:29
Иконки следует объявлять в коде статическими.
Например как?
Название: Re: Не срабатывает действие в контекстном меню из StatusBar ?
Отправлено: Андрей Бушман от 24-08-2015, 15:55:43
ты не знаешь как в C# создавать статические переменные?
Название: Re: Не срабатывает действие в контекстном меню из StatusBar ?
Отправлено: Doublefish от 24-08-2015, 15:58:38
я про иконку - может надо как-то по особому )))
На что влияет?
Название: Re: Не срабатывает действие в контекстном меню из StatusBar ?
Отправлено: Андрей Бушман от 24-08-2015, 16:01:12
Насколько я помню, если создавать переменную иконки не static, то она в процессе работы акада вдруг исчезает (не сразу, а через некоторое время) мышкой по экрану подёргай, позуммируй. видимо объект класса уничтожается, а с ним уничтожается и объект иконки. Если её объявлять статической, то проблема исчезает (я где-то писал об этом).
Название: Re: Не срабатывает действие в контекстном меню из StatusBar ?
Отправлено: Doublefish от 24-08-2015, 16:04:07
ок
Название: Re: Не срабатывает действие в контекстном меню из StatusBar ?
Отправлено: Андрей Бушман от 24-08-2015, 16:05:09
Вот (http://forums.autodesk.com/t5/net/trayitem-icon-disappears/td-p/2386483) кто-то спотыкался об это же и нашёл то же решение что и я - юзать static.
Название: Re: Не срабатывает действие в контекстном меню из StatusBar ?
Отправлено: Андрей Бушман от 24-08-2015, 16:07:02
А вот, кстати, и моя тема (http://www.theswamp.org/index.php?topic=42991.0), с демонстрационным видео этой проблемы (только что нашёл).
Название: Re: Не срабатывает действие в контекстном меню из StatusBar ?
Отправлено: Александр Ривилис от 28-08-2015, 14:08:46
Получил ответ из ADN DevHelp. Они подтвердили наличие бага и передали его команде инженеров. Пока же предложили еще один workaround:
Код - vb.net [Выбрать]
  1.     Private _filter As MenuMsgFilter
  2.  
  3.     <CommandMethod("TrayTest")> _
  4.     Public Sub TrayTest()
  5.  
  6.         Autodesk.AutoCAD.ApplicationServices.Application.StatusBar.TrayItems.Add(Me.TrayItem)
  7.         Autodesk.AutoCAD.ApplicationServices.Application.StatusBar.Update()
  8.  
  9.         _filter = New MenuMsgFilter
  10.         System.Windows.Forms.Application.AddMessageFilter(_filter)
  11.  
  12.     End Sub
  13.  
  14.     '<DebuggerBrowsable(DebuggerBrowsableState.Never)> _
  15.     Private m_TrayItem As Autodesk.AutoCAD.Windows.TrayItem = Nothing
  16.  
  17.     Public ReadOnly Property TrayItem() As Autodesk.AutoCAD.Windows.TrayItem
  18.         Get
  19.             If Me.m_TrayItem Is Nothing Then
  20.  
  21.                 Me.m_TrayItem = New Autodesk.AutoCAD.Windows.TrayItem
  22.                 Me.m_TrayItem.Icon = System.Drawing.SystemIcons.Asterisk
  23.                 Me.m_TrayItem.ToolTipText = "Testing"
  24.                 Me.m_TrayItem.Visible = True
  25.  
  26.                 AddHandler m_TrayItem.MouseDown, AddressOf callback_MouseDown
  27.             End If
  28.             Return Me.m_TrayItem
  29.         End Get
  30.     End Property
  31.  
  32.     <StructLayout(LayoutKind.Sequential)> _
  33.     Private Structure MENUITEMINFO
  34.         Public cbSize As Integer
  35.         Public fMask As Integer
  36.         Public fType As Integer
  37.         Public fState As Integer
  38.         Public wID As Integer
  39.         Public hSubMenu As IntPtr
  40.         Public hbmpChecked As IntPtr
  41.         Public hbmpUnchecked As IntPtr
  42.         Public dwItemData As IntPtr
  43.         Public dwTypeData As String
  44.         Public cch As Integer
  45.         Public hbmpItem As IntPtr
  46.     End Structure
  47.  
  48.     <DllImport("user32.dll")> _
  49.     Private Shared Function GetMenuItemInfo( _
  50.         ByVal hMenu As IntPtr, _
  51.         ByVal uItem As UInteger, _
  52.         ByVal fByPosition As Boolean, _
  53.         ByRef lpmii As MENUITEMINFO) As Boolean
  54.  
  55.     End Function
  56.  
  57.     '<DebuggerBrowsable(DebuggerBrowsableState.Never)> _
  58.     Private m_ContextMenu As System.Windows.Forms.ContextMenu = Nothing
  59.  
  60.     Private m_MenuIds As Dictionary(Of Integer, String)
  61.  
  62.     Private ReadOnly Property ContextMenu() As System.Windows.Forms.ContextMenu
  63.         Get
  64.             If Me.m_ContextMenu Is Nothing Then
  65.  
  66.                 Me.m_ContextMenu = New System.Windows.Forms.ContextMenu
  67.  
  68.                 Dim MenuItem1 As New System.Windows.Forms.MenuItem("MenuItem1")
  69.                 Dim MenuItem2 As New System.Windows.Forms.MenuItem("MenuItem2...")
  70.                 Dim MenuItem3 As New System.Windows.Forms.MenuItem("MenuItem3...")
  71.  
  72.                 'AddHandler MenuItem1.Click, AddressOf MenuItem1_Click
  73.                 'AddHandler MenuItem2.Click, AddressOf MenuItem2_Click
  74.                 'AddHandler MenuItem3.Click, AddressOf MenuItem3_Click
  75.  
  76.                 Me.m_ContextMenu.MenuItems.Add(MenuItem1)
  77.                 Me.m_ContextMenu.MenuItems.Add(MenuItem2)
  78.                 Me.m_ContextMenu.MenuItems.Add(New System.Windows.Forms.MenuItem("-"))
  79.                 Me.m_ContextMenu.MenuItems.Add(MenuItem3)
  80.  
  81.                 Dim mif As MENUITEMINFO = New MENUITEMINFO()
  82.                 mif.cbSize = Marshal.SizeOf(mif)
  83.                 mif.fMask = &H2 'MIIM_ID
  84.                 mif.fType = &H100
  85.                 mif.cch = 256
  86.  
  87.                 m_MenuIds = New Dictionary(Of Integer, String)
  88.  
  89.                 GetMenuItemInfo(Me.m_ContextMenu.Handle, 0, True, mif)
  90.                 m_MenuIds.Add(mif.wID, "MenuItem[1] Clicked!")
  91.  
  92.                 GetMenuItemInfo(Me.m_ContextMenu.Handle, 1, True, mif)
  93.                 m_MenuIds.Add(mif.wID, "MenuItem[2] Clicked!")
  94.  
  95.                 GetMenuItemInfo(Me.m_ContextMenu.Handle, 3, True, mif)
  96.                 m_MenuIds.Add(mif.wID, "MenuItem[3] Clicked!")
  97.  
  98.                 _filter.MenuIds = m_MenuIds
  99.  
  100.             End If
  101.  
  102.             Return Me.m_ContextMenu
  103.         End Get
  104.     End Property
  105.  
  106.     Private Sub callback_MouseDown(ByVal sender As Object, ByVal e As Autodesk.AutoCAD.Windows.StatusBarMouseDownEventArgs)
  107.         Try
  108.             Select Case e.Button
  109.  
  110.                 Case Windows.Forms.MouseButtons.Left
  111.  
  112.                     WriteMsg("left button")
  113.  
  114.                 Case Windows.Forms.MouseButtons.Right
  115.  
  116.                     Dim ti As Autodesk.AutoCAD.Windows.TrayItem = CType(sender, Autodesk.AutoCAD.Windows.TrayItem)
  117.                     ti.DisplayContextMenu(Me.ContextMenu, New System.Drawing.Point(e.X, e.Y))
  118.  
  119.             End Select
  120.         Catch ex As System.Exception
  121.         End Try
  122.  
  123.     End Sub
  124.  
  125.     'Private Sub MenuItem1_Click(ByVal sender As Object, ByVal e As System.EventArgs)
  126.     '    WriteMsg("MenuItem1")
  127.     'End Sub
  128.  
  129.     'Private Sub MenuItem2_Click(ByVal sender As Object, ByVal e As System.EventArgs)
  130.     '    WriteMsg("MenuItem2")
  131.     'End Sub
  132.  
  133.     'Private Sub MenuItem3_Click(ByVal sender As Object, ByVal e As System.EventArgs)
  134.     '    WriteMsg("MenuItem3")
  135.     'End Sub
  136.  
  137.     Private Sub WriteMsg(ByVal msg As String)
  138.         Dim doc As Document = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument
  139.         doc.Editor.WriteMessage(Environment.NewLine & msg)
  140.     End Sub
  141.  
  142.     Private Class MenuMsgFilter
  143.         Implements System.Windows.Forms.IMessageFilter
  144.  
  145.         Private m_MenuIds As Dictionary(Of Integer, String)
  146.  
  147.         Public Property MenuIds() As Dictionary(Of Integer, String)
  148.             Get
  149.                 Return m_MenuIds
  150.             End Get
  151.             Set(ByVal value As Dictionary(Of Integer, String))
  152.                 m_MenuIds = value
  153.             End Set
  154.         End Property
  155.  
  156.         Private Function LoWord(ByVal word As Integer) As Short
  157.             Return CShort(word And Short.MaxValue)
  158.         End Function
  159.  
  160.         Private Function HiWord(ByVal word As Integer) As Short
  161.             Return CShort((word >> 16))
  162.         End Function
  163.  
  164.         Private WM_COMMAND As Integer = &H111
  165.  
  166.         Public Function PreFilterMessage(ByRef m As System.Windows.Forms.Message) As Boolean _
  167.             Implements System.Windows.Forms.IMessageFilter.PreFilterMessage
  168.  
  169.             If m.Msg = WM_COMMAND Then
  170.                 If HiWord(m.WParam) = 0 Then
  171.                     If m_MenuIds.ContainsKey(LoWord(m.WParam)) Then
  172.  
  173.                         Dim msg As String = m_MenuIds(LoWord(m.WParam))
  174.  
  175.                         Dim doc As Document = Application.DocumentManager.MdiActiveDocument
  176.                         Dim ed As Editor = doc.Editor()
  177.  
  178.                         ed.WriteMessage(vbCrLf + msg)
  179.                         Return False
  180.  
  181.                     End If
  182.                 End If
  183.             End If
  184.  
  185.             Return False
  186.         End Function
  187.     End Class
Я не проверял предложенное решение, но мне кажется, что моё решение выглядит проще и элегантнее.
Название: Re: Не срабатывает действие в контекстном меню из StatusBar ?
Отправлено: Андрей Бушман от 28-08-2015, 14:11:53
Они подтвердили наличие бага и передали его команде инженеров.
Насколько я помню, они уже не в первый раз это "подтверждают и передают команде инженеров"...
Название: Re: Не срабатывает действие в контекстном меню из StatusBar ?
Отправлено: Александр Ривилис от 28-08-2015, 14:18:28
Насколько я помню, они уже не в первый раз это "подтверждают и передают команде инженеров"...
Так как имеется как минимум два "workaround", нет "business case", то и приоритет у этого исправления не высок.
В очередной раз могу посоветовать почитать: http://adn-cis.org/forum/index.php?topic=2640.0
Название: Re: Не срабатывает действие в контекстном меню из StatusBar ?
Отправлено: Doublefish от 02-09-2015, 08:29:17
Подскажите пожалуйста, если заменить ContextMenu на ContextMenuStrip для того чтобы отображалась иконка в контекстном меню почему то при первом клике по иконке в трее контекстное меню не появляется, а при всех последующих кликах появляется нормально, даже после stop - start появляется, а вот если закрыть и открыть автокад, то при первом клике не появляется. Из-за чего это могло бы быть или может можно иконку добавить как то в ContextMenu ?

Код - C# [Выбрать]
  1.         System.Windows.Forms.ContextMenuStrip contextMenustrip = new System.Windows.Forms.ContextMenuStrip();
  2.         System.Drawing.Image img = System.Drawing.Image.FromFile(@"c:\Temp\test.png");
  3.         contextMenustrip.Items.Add("test click", img, new EventHandler(MenuOnClick));
  4.         this.Location = Cursor.Position; this.Show();
  5.         contextMenustrip.Show(this, new System.Drawing.Point(0, 0));
  6.         this.Hide();
Название: Re: Не срабатывает действие в контекстном меню из StatusBar ?
Отправлено: Doublefish от 02-09-2015, 09:31:45
Вот так работает с первого раза)))

Код - C# [Выбрать]
  1.           System.Windows.Forms.ContextMenuStrip contextMenustrip = new System.Windows.Forms.ContextMenuStrip();
  2.           System.Drawing.Image img = System.Drawing.Image.FromFile(@"c:\Temp\test.png");
  3.           contextMenustrip.Items.Add("test click", img, new EventHandler(MenuOnClick));
  4.           this.ContextMenuStrip = contextMenustrip;
  5.           this.ContextMenuStrip.Visible = true;
  6.           this.Location = Cursor.Position; this.Show();
  7.           this.ContextMenuStrip.Show(this, new System.Drawing.Point(0, 0));
  8.           this.Hide();