Как узнать ToolTip нажатой кнопки?

Автор Тема: Как узнать ToolTip нажатой кнопки?  (Прочитано 4567 раз)

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

Оффлайн Пашин ЕвгенийАвтор темы

  • ADN PRO
  • *
  • Сообщений: 662
  • Карма: 12
  • Skype: pashin.evgeniy
Всем, доброе утро!

Вопрос: как определить Tooltip нажатой кнопки на ленте Ribbon?


1. Создал вкладку на ленте, затем панель, туда вставил кнопку!!!
2. При нажатии на эту кнопку хочу вывести сообщение Button.Tooltip

Подскажите как можно просто определить нажатую кнопку на ленте?
« Последнее редактирование: 04-03-2016, 18:38:37 от Пашин Евгений »

Отмечено как Решение Пашин Евгений 09-03-2016, 09:40:50

Оффлайн Пашин ЕвгенийАвтор темы

  • ADN PRO
  • *
  • Сообщений: 662
  • Карма: 12
  • Skype: pashin.evgeniy
Re: Как узнать ToolTip нажатой кнопки?
« Ответ #1 : 09-03-2016, 09:40:36 »
М-да, вот что получилось в результате поиска решения. Работает, конечно!!!

Итак,
1. У меня есть лента в Revit, на ней вкладка, имя которой берется из файла (My.Application.Info.DirectoryPath & "\Data\buttons_list.txt").
2. В эту вкладку добавляется ровно столько кнопок, сколько их указано в файле (тот же самый файл, откуда берется имя вкладки).
3. Для каждой кнопки указан (в ToolTip) путь к запускаемому приложению.
4. При нажатии кнопки на ленте должно запускаться то приложение, которое указано в его ToolTip.

Казалось бы, безобидное задание, но сколько интересного открылось,
1. Во-первых, необходимо подключить библиотеку AdWindows.dll (там где лежит Revit.exe)
2. Во-вторых, потребовалось создать обработку события активации элементов вкладки при нажатии мышкой.

Код - vb.net [Выбрать]
  1. Imports System
  2. Imports System.Windows.Media.Imaging
  3. Imports Autodesk.Revit.DB
  4. Imports Autodesk.Revit.UI
  5. Imports Autodesk.Revit.ApplicationServices
  6. Imports Autodesk.Revit.Attributes
  7. Imports Autodesk.Revit.UI.Selection
  8. Imports System.IO
  9. Imports Autodesk.Revit.UI.Events
  10. Imports adWin = Autodesk.Windows
  11.  
  12. Public Class Andrey_Revit_Ribbon_UI
  13.     Implements IExternalApplication
  14.  
  15.     Private Const _dllExtension As String = ".dll"
  16.     Private Const _introLabName As String = "Andrey_Plugin"
  17.     Private Const _uiLabName As String = "Ribbon_Customization"
  18.     Private Const _imageFolderName As String = "Images"
  19.     Private _imageFolder As String
  20.     Private _introLabPath As String
  21.  
  22.     Private Function FindFolderInParents(ByVal path As String, ByVal target As String) As String
  23.         Do
  24.             Dim s As String = System.IO.Path.Combine(path, target)
  25.             If Directory.Exists(s) Then
  26.                 Return s
  27.             End If
  28.             path = System.IO.Path.GetDirectoryName(path)
  29.         Loop While (path IsNot Nothing)
  30.         Return Nothing
  31.     End Function
  32.  
  33.     Function NewBitmapImage(ByVal imageName As String) As BitmapImage
  34.         Return New BitmapImage(New Uri(Path.Combine(Me._imageFolder, imageName)))
  35.     End Function
  36.  
  37.     Public Function OnShutdown(ByVal app As UIControlledApplication) As Result _
  38.         Implements IExternalApplication.OnShutdown
  39.         Return Result.Succeeded
  40.     End Function
  41.  
  42.     Public Function OnStartup(ByVal app As UIControlledApplication) As Result _
  43.       Implements IExternalApplication.OnStartup
  44.         Dim dir As String = Path.GetDirectoryName( _
  45.             System.Reflection.Assembly.GetExecutingAssembly.Location)
  46.         _introLabPath = Path.Combine(dir, _introLabName + _dllExtension)
  47.         If Not File.Exists(_introLabPath) Then
  48.             TaskDialog.Show("UIRibbon", "Сборка для внешней команды не найдена: " + _introLabPath)
  49.             Return Result.Failed
  50.         End If
  51.         _imageFolder = FindFolderInParents(dir, _imageFolderName)
  52.         If _imageFolder Is Nothing Or Not Directory.Exists(_imageFolder) Then
  53.             TaskDialog.Show( _
  54.                 "UIRibbon", _
  55.                 String.Format( _
  56.                   "Нет папки изображений '{0}' в требуемой директории '{1}.", _
  57.                   _imageFolderName, dir))
  58.             Return Result.Failed
  59.         End If
  60.         AddRibbonSampler(app)
  61.         Return Result.Succeeded
  62.     End Function
  63.  
  64.     Sub AddRibbonSampler(ByVal app As UIControlledApplication)
  65.         Dim myTabName As String = ""
  66.         FileOpen(1, My.Application.Info.DirectoryPath & "\Data\buttons_list.txt", OpenMode.Input)
  67.         Do While Not EOF(1)
  68.             Dim myStr As String = LineInput(1)
  69.             Select Case myStr
  70.                 Case "<Tab>"
  71.                     myTabName = LineInput(1)
  72.             End Select
  73.         Loop
  74.         FileClose(1)
  75.         app.CreateRibbonTab(IIf(myTabName = "", "Nameless Tab", myTabName))
  76.         Dim panel As RibbonPanel = app.CreateRibbonPanel(IIf(myTabName = "", "Nameless Tab", myTabName), "Приложения")
  77.         Dim myFile As String = My.Application.Info.DirectoryPath & "\Data\buttons_list.txt"
  78.         Try
  79.             If IO.File.Exists(myFile) Then
  80.                 FileOpen(1, myFile, OpenMode.Input)
  81.                 Do While Not EOF(1)
  82.                     Dim myStr As String = LineInput(1)
  83.                     Select Case Trim(myStr)
  84.                         Case "<Button>"
  85.                             Dim myButtonName As String = LineInput(1)
  86.                             Dim myICO As String = LineInput(1)
  87.                             Dim myApp As String = LineInput(1)
  88.                             AddPushButtonByFile(panel, myButtonName, myApp, myICO)
  89.                     End Select
  90.                 Loop
  91.                 FileClose(1)
  92.             End If
  93.         Catch ex As Exception
  94.             MsgBox("OK!")
  95.         End Try
  96.     End Sub
  97.  
  98.     Sub AddPushButtonByFile(ByVal panel As RibbonPanel, ByVal Button_Name As String, ByVal App_Path As String, ByVal Image_Path As String)
  99.         Dim pushButton As New PushButtonData(Button_Name, Button_Name, _introLabPath, _introLabName + ".Andrey_App_Start")
  100.         pushButton.Text = Button_Name
  101.         pushButton.LongDescription = App_Path
  102.         pushButton.ToolTip = App_Path
  103.         Dim pushButtonAction As PushButton = panel.AddItem(pushButton)
  104.         pushButtonAction.LargeImage = NewBitmapImage(My.Application.Info.DirectoryPath & Image_Path)
  105.         pushButtonAction.ToolTip = App_Path
  106.         pushButtonAction.LongDescription = App_Path
  107.         'AddHandler adWin.ComponentManager.UIElementActivated, New EventHandler(AddressOf PBClick) - данная строка тоже работает!!!
  108.         ' •••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••
  109.         AddHandler adWin.ComponentManager.UIElementActivated, AddressOf PBClick ' Именно эта строка отвечает за обработку события нажатия на кнопку
  110.         ' •••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••
  111.     End Sub
  112.  
  113.     Public Sub PBClick(ByVal sender As Object, ByVal e As adWin.UIElementActivatedEventArgs)
  114.         Try
  115.             If e.UiElement.IsFocused Then
  116.                 If e.UiElement.IsMouseOver Then
  117.                     Dim mTT As Autodesk.Windows.RibbonToolTip = e.Item.ToolTip
  118.                     If IsProcessExist(mTT.Content.ToString) Then
  119.                     Else
  120.                         Process.Start(mTT.Content.ToString)
  121.                         Threading.Thread.Sleep(1000)
  122.                     End If
  123.                 End If
  124.             End If
  125.         Catch ex As Exception
  126.         End Try
  127.     End Sub
  128.  
  129.     Public Function IsProcessExist(ByVal SearchText As String) As Boolean
  130.         For Each mP As Process In Process.GetProcesses
  131.             If InStr(SearchText, mP.ProcessName) <> 0 Then
  132.                 IsProcessExist = True
  133.                 Exit Function
  134.             End If
  135.         Next
  136.         Return False
  137.     End Function
  138.  
  139. End Class
  140.  

Выкладываю содержание файла button_list.txt
Извините, вам запрещён просмотр содержимого спойлеров.



Код явно не идеален, потому прошу помочь его откорректировать, поскольку наткнулся на одну проблему: так как добавление кнопок происходит столько раз, сколько упоминается в файле, то при нажатии на кнопку событие срабатывает столько же раз, а значит что приложение (указанное в ToolTip) для заданной кнопки запускается множество раз (согласно количеству кнопок). Поэтому пришлось создать проверку процессов и блокировать повторные запуски приложений. Это не оптимально. Поэтому жду ваших рекомендаций по оптимизации решения.

Заранее благодарю!
« Последнее редактирование: 11-03-2016, 07:44:42 от Пашин Евгений »

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

  • ADN Club
  • *****
  • Сообщений: 1658
  • Карма: 366
  • Отец modplus.org
    • ModPlus
Re: Как узнать ToolTip нажатой кнопки?
« Ответ #2 : 15-06-2017, 18:56:27 »
1. Во-первых, необходимо подключить библиотеку AdWindows.dll (там где лежит Revit.exe)
Плохая идея. При запуске команды с ленты, созданной библиотекой AdWindows.dll, в команду не передается ExternalCommandData
2. При нажатии на эту кнопку хочу вывести сообщение Button.Tooltip
В смысле вывести? Куда? В TaskDialog? Или просто добавить к кнопке ToolTip? Если да - вообще без проблем

Оффлайн Пашин ЕвгенийАвтор темы

  • ADN PRO
  • *
  • Сообщений: 662
  • Карма: 12
  • Skype: pashin.evgeniy
Re: Как узнать ToolTip нажатой кнопки?
« Ответ #3 : 16-06-2017, 07:13:56 »
Александр, добрый день. Спасибо за ответ.

Плохая идея. При запуске команды с ленты, созданной библиотекой AdWindows.dll, в команду не передается ExternalCommandData

Решение разрабатывалось не для запуска каких-либо команд внутри Revit, а для запуска сторонних приложений, путь к которым находится в Tooltip-е кнопок. Я понимаю, что решение плохое, поэтому если найдётся более изящное решение, то это будет полезно для всех. Я действительно хотел бы ещё запускать, при нажатии кнопок, внутренние команды, но я не довёл решение до конца, поэтому не проверил передачу в команду ExternalCommandData. Будет время - попробую найти решение для этого, если здесь оно не появится раньше.

В смысле вывести? Куда? В TaskDialog? Или просто добавить к кнопке ToolTip? Если да - вообще без проблем

Просто получаю Tooltip кнопки (который является путём к стороннему приложению или файлу) и запускаю процесс. В коде это продемонстрировано в виде строки Process.Start(mTT.Content.ToString).

Было бы интересно доработать этот вариант или найти другое решение. Я за любой вариант.

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

  • ADN Club
  • *****
  • Сообщений: 1658
  • Карма: 366
  • Отец modplus.org
    • ModPlus
Re: Как узнать ToolTip нажатой кнопки?
« Ответ #4 : 17-06-2017, 01:55:00 »
То ли я запутался, то ли вы) Но библиотека AdWindows.dll нужна, если вы строите ленту как в автокаде. В этом случае при добавлении кнопки ей задается обработка нажатия таким образом:
Код - C# [Выбрать]
  1. // Какой-то код до добавления кнопки...
  2. // Часть кода, которая создает кнопку
  3. var ribBtn = new RibbonButton
  4. {
  5.     CommandParameter = /* тут на ваше усмотрение. Вообще, должна быть команда прописана */,
  6.     Name = lName, // Имя кнопки
  7.     Text = lName, // Текст на кнопке
  8.     CommandHandler = new RibbonCommandHandler(), // Обработчик нажатия кнопки
  9.     // Прочие настройки
  10.     Orientation = orientation,
  11.     Size = RibbonItemSize.Large,
  12.     ShowImage = true,
  13.     ShowText = true,
  14.     ToolTip = tt
  15. };
  16.  
  17.  
  18. // Ну и сам обработчик нажатия кнопки
  19. public class RibbonCommandHandler : System.Windows.Input.ICommand
  20. {
  21.     public bool CanExecute(object parameter)
  22.     {
  23.         return true;
  24.     }
  25.         #pragma warning disable 67
  26.     public event EventHandler CanExecuteChanged;
  27.         #pragma warning restore 67
  28.  
  29.     public void Execute(object parameter)
  30.     {
  31.         if (parameter is RibbonButton)
  32.         {
  33.             // Получаем кнопку, которая создала событие
  34.             var button = (RibbonButton)parameter;
  35.             // Далее уже как вам нужно - хоть с ToolTip значение, хоть с других свойств. Точно не помню, но возможно есть у кнопки и свойство Tag, которое можно использовать как раз для этого
  36.             // Ниже обычный вариант запуска команды, прописанной в свойстве CommandParameter
  37.             AcApp.DocumentManager.MdiActiveDocument.SendStringToExecute(
  38.                 button.CommandParameter + " ", true, false, true);
  39.         }
  40.     }
  41. }
  42.  
Но в вашем примере кода вроде как создается PushButton, а это никак не относится к AdWindows - это уже библиотека ReviAPIUI.dll и там все по-другому

Оффлайн Пашин ЕвгенийАвтор темы

  • ADN PRO
  • *
  • Сообщений: 662
  • Карма: 12
  • Skype: pashin.evgeniy
Re: Как узнать ToolTip нажатой кнопки?
« Ответ #5 : 19-06-2017, 07:08:22 »
Но библиотека AdWindows.dll нужна, если вы строите ленту как в автокаде.

Так и есть. Мне это изначально и было нужно.

Вопрос: как определить Tooltip нажатой кнопки на ленте Ribbon?

На тот момент я ещё, возможно, не умел создавать кнопки на самой ленте.

Александр, я протестирую Ваше решение и в скором времени отпишусь.