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

ADN Club => Inventor API => Тема начата: R.I.Chernov от 19-01-2015, 13:58:10

Название: KeyboardEvents.OnKeyPress Event
Отправлено: R.I.Chernov от 19-01-2015, 13:58:10
Доброго времени суток, уважаемые форумчане. Помогите пожалуйста разобраться, как  программно выполнить какое-нибудь действие, при нажатии на какую-нибудь клавишу клавиатуры. Например как сделать так, чтобы при нажатии "Esc" закрывалась открытая ранее форма. Сам разобраться с синтаксисом не смог :(
Название: Re: KeyboardEvents.OnKeyPress Event
Отправлено: Виктор Чекалин от 20-01-2015, 09:19:20
R.I.Chernov,
попробую ответить. Хоть я ни разу с Inventor API не работал, но вопрос по сути общего характера.
Речь идет о VBA или VB.NET? В любом случае, нужно подписаться на событие KeyPress. В обработчике события, одним из параметров будет нажатая клавиши. Нужно сверить нажатую клавишу с Esc и если условие выполняется, закрыть форму.
На VBA это будет выглядеть вот так:
Код - Visual Basic [Выбрать]
  1. Private Sub UserForm_KeyPress(ByVal KeyAscii As MSForms.ReturnInteger)
  2.     If (KeyAscii = 27) Then
  3.         Me.Hide
  4.     End If
  5. End Sub
На VB.NET:
Код - vb.net [Выбрать]
  1.     Private Sub Form1_KeyPress(sender As Object, e As KeyPressEventArgs) Handles MyBase.KeyPress
  2.         If (e.KeyChar = Chr(27)) Then
  3.             Close()
  4.         End If
  5.     End Sub

Не трудно заметить, что в данном случае необходимо использования числового кода клавиши Esc, что не слишком явно, так как число 27 нужно еще как-то получить.
Поэтому конкретно для описанного варианта лушче использовать событие KeyDown или KeyUp возникающее при нажатии клавиши или при отпускании соответственно.
В параметрах этих событий, нужно использовать уже не числовой код, а предопределенный.
VBA:
Код - Visual Basic [Выбрать]
  1. Private Sub UserForm_KeyDown(ByVal KeyCode As MSForms.ReturnInteger, ByVal Shift As Integer)
  2.     If (KeyCode = KeyCodeConstants.vbKeyEscape) Then
  3.         Me.Hide
  4.     End If
  5. End Sub

VB.NET:
Код - vb.net [Выбрать]
  1.     Private Sub Form1_KeyDown(sender As Object, e As KeyEventArgs) Handles MyBase.KeyDown
  2.         If e.KeyCode = Keys.Escape Then
  3.             Close()
  4.         End If
  5.     End Sub

В VB.NET есть еще один, более элегантный способ закрытия формы по Esc. Если все же используется он, то опишу в другом сообщении.
Название: Re: KeyboardEvents.OnKeyPress Event
Отправлено: R.I.Chernov от 20-01-2015, 11:45:20
Спасибо, Виктор! Код  работает (по крайней мере для VBA :) ).
Если этот топик вдруг читают такие же "высококвалифицированные" программисты как я, то стоит пояснить,  что Private Sub UserForm_KeyPress(ByVal KeyAscii As MSForms.ReturnInteger) это событие,и его надо поместить в код формы :)

Но если честно, то, помимо помощи в решении, вы создали в моей голове огромную кучу вопросов и ощущение еще большего непонимание этой темы :)
Попробую сформулировать некоторые из них:
1. в справке VBA в инвентор написано:
    Private Sub object_KeyDown( ByVal KeyCode As MSForms.ReturnInteger, ByVal Shift As fmShiftState)Почему в вашем примере "ByVal Shift As Integer" работает, а "ByVal Shift As fmShiftState" из справки нет?

2. Как использовать событие инвентора: KeyboardEvents.OnKeyPress Event?
Я вроде бы понял, как можно до него "добраться":
 
Код - Visual Basic [Выбрать]
  1. Dim KeyEvent As KeyboardEvents
  2. Set KeyEvent = ThisApplication.CommandManager.CreateInteractionEvents.KeyboardEvents
Но как ни пыхтел, я так и не смог понять, что делать дальше, чтобы вернуть какую либо переменную и воспользоваться ее значением для создания условия. В примерах справки, к сожалению, аналога нет :(

Буду очень признателен за любую помошь!
Название: Re: KeyboardEvents.OnKeyPress Event
Отправлено: R.I.Chernov от 20-01-2015, 13:35:13
У меня появился еще один вопрос... Виктор, Ваш код работает у меня при пустой форме (нет ни текстбоксов, ни кнопок и т.п.), если поместить в форму хотя бы один текст бокс, то при загрузке формы он становится активным, и нажатие клавиши "Esc" внутри него приводит к удалению значения внутри текст бокса, но не к активации события. Не могли бы вы подсказать, как я могу сделать текстбоксы неактивными, например при нажатии на форму, ну или еще как-нибудь, в общем как сделать так, чтобы код работал? :)
Название: Re: KeyboardEvents.OnKeyPress Event
Отправлено: Виктор Чекалин от 20-01-2015, 14:04:26
R.I.Chernov, быстрое гугление показало, что единственный способ, это подписаться на событие KeyPress для каждого контрола на форме.
Т.е. помимо
Код - Visual Basic [Выбрать]
  1. Private Sub UserForm_KeyPress(ByVal KeyAscii As MSForms.ReturnInteger)
  2.     If (KeyAscii = 27) Then
  3.         Me.Hide
  4.     End If
  5. End Sub
вам еще понадобиться обработка события нажатия клавиши в текстовом поле.
Код - Visual Basic [Выбрать]
  1. Private Sub TextBox1_KeyPress(ByVal KeyAscii As MSForms.ReturnInteger)
  2.     If (KeyAscii = 27) Then
  3.         Me.Hide
  4.     End If
  5. End Sub
И так для каждого контрола, который может иметь фокус на форме.

Возможно есть какое-то более изящное решение, но с VBA я уже лет 8 не работал...)
Название: Re: KeyboardEvents.OnKeyPress Event
Отправлено: R.I.Chernov от 20-01-2015, 14:45:51
Спасибо! Насчет элегантности я не знаю, но работает! :) Честно говоря, думал, что есть какой нибудь универсальный "unfocus" для всей формы, или что перебором можно как - нибудь хитро снять фокус сразу со всего, чтобы не дублировать для всех элементов формы данное событие. Так что, если кто в курсе более простого метода, милости просим! )))
Виктор, еще раз спасибо Вам за помощь!
П.С. Очередное пояснение для "суперпрограммистов", каких же, как я сам :) : код клавиш в формате ASCII нашел в объектном браузере в разделе "KeyCodeConstants", при наведении, например, на "vbKey0", пишется что "vbKey0 = 48".
Название: Re: KeyboardEvents.OnKeyPress Event
Отправлено: Виктор Чекалин от 20-01-2015, 14:59:30
П.С. Очередное пояснение для "суперпрограммистов", каких же, как я сам  : код клавиш в формате ASCII нашел в объектном браузере в разделе "KeyCodeConstants", при наведении, например, на "vbKey0", пишется что "vbKey0 = 48".
Так если нашли константы, так и используйте их, а не число:)
Код - Visual Basic [Выбрать]
  1. Private Sub TextBox1_KeyPress(ByVal KeyAscii As MSForms.ReturnInteger)
  2.     If (KeyAscii = KeyCodeConstants.vbKeyEscape) Then
  3.         Me.Hide
  4.     End If
  5. End Sub
Название: Re: KeyboardEvents.OnKeyPress Event
Отправлено: R.I.Chernov от 20-01-2015, 15:10:51
Так если нашли константы, так и используйте их, а не число:)

Спасибо! Я подчеркнул это еще из первого Вашего сообщения, просто попытался сделать этот топик максимально информативным и полезным для кого-нибудь еще. Возможно нравится кому-нибудь циферками писать :)
Название: Re: KeyboardEvents.OnKeyPress Event
Отправлено: Алексей Романов от 21-01-2015, 08:06:23
Например как сделать так, чтобы при нажатии "Esc" закрывалась открытая ранее форма.
Если я правильно понял, то в VBA такое программировать не нужно. Если свойство Cancel кнопки, которая закрывает форму, установить в True (по умолчанию False), то при нажатии клавиши "Esc" форма закрывается, где бы фокус не находился...
Название: Re: KeyboardEvents.OnKeyPress Event
Отправлено: Виктор Чекалин от 21-01-2015, 09:52:21
Алексей Романов, проверил. Не работает. Если кнопка добавлена, свойство Cancel установлено в True, то при нажатии Esc переводится фокус на эту кнопку, но форма не закрывается.
UPDATE:
Кажется понял. Если кнопке задать свойство Cancel=True, то при нажатии на кнопку Esc вызывается событие OnClick на этой кнопке.
Т.е. помимо свойства Cancel надо на обработку события нажатия кнопки написать код закрытия формы.
Код - Visual Basic [Выбрать]
  1. Private Sub CommandButton1_Click()
  2.     Me.Hide
  3. End Sub
Название: Re: KeyboardEvents.OnKeyPress Event
Отправлено: Алексей Романов от 21-01-2015, 10:17:35
Т.е. помимо свойства Cancel надо на обработку события нажатия кнопки написать код закрытия формы.
Совершенно верно..) Я ведь и написал, что это свойство устанавливается для той кнопки, которая закрывает форму. Я думаю, что на форме практически всегда есть кнопка для ее закрытия...
Название: Re: KeyboardEvents.OnKeyPress Event
Отправлено: R.I.Chernov от 21-01-2015, 10:40:18
Спасибо Алексей, за то что присоединились к нашей беседе! Ваш метод работает, за что вам второе спасибо!  :)
От себя добавлю ссылку-пояснение для "суперпрограммистов", лично я там нашел ответы на возникшие по поводу кнопки "Cancel" вопросы:
https://msdn.microsoft.com/en-us/library/office/ff821090%28v=office.15%29.aspx

П.С. Тем не менее остается еще несколько вопросов, упомянутых мною выше. Если кто-нибудь может помочь решением или просто гипотезой, буду примногоблагодарен!
Название: Re: KeyboardEvents.OnKeyPress Event
Отправлено: Виктор Чекалин от 21-01-2015, 11:04:25
Я ведь и написал, что это свойство устанавливается для той кнопки, которая закрывает форму.
Да это я по аналогии с .NET. Там можно вообще дополнительного кода не писать, для того, чтобы по нажатии на Esc форма закрывалась. По инерции и в VBA так же попробовал, а про обработку события не подумал сначала.
Название: Re: KeyboardEvents.OnKeyPress Event
Отправлено: Алексей Романов от 21-01-2015, 12:28:49
2. Как использовать событие инвентора: KeyboardEvents.OnKeyPress Event?
Для обработки событий в АИ в VBA используются модули классов. Если кратко, в папке Class Modules создается модуль Class1: Private WithEvents oInteraction As InteractionEvents
Private WithEvents myKey As KeyboardEvents
Private Sub Class_Initialize()
  Set oInteraction = ThisApplication.CommandManager.CreateInteractionEvents
  Set myKey = oInteraction.KeyboardEvents
  oInteraction.Start
End Sub
Private Sub Class_Terminate()
If Not oInteraction Is Nothing Then
    oInteraction.Stop
    Set myKey = Nothing
End If
End Sub
Private Sub myKey_OnKeyDown(ByVal Key As Long, ByVal ShiftKeys As ShiftStateEnum)
    If Key > 31 Then MsgBox Chr(Key)
    If Key = 27 Then
        If Not oInteraction Is Nothing Then
            oInteraction.Stop
            Set myKey = Nothing
            Set oInteraction = Nothing
            Class_Terminate
        End If
    End If
End Sub
В память он грузится процедурой в обычном модуле:Dim myKeyEvent As Class1
Sub KeyEvent()
 If Not myKeyEvent Is Nothing Then
    Set myKeyEvent = Nothing
    Set myKeyEvent = New Class1
 Else
    Set myKeyEvent = New Class1
 End If
End Sub
На форуме cad.ru я не раз об этом писал, поищи по словам Класс модуль...
Название: Re: KeyboardEvents.OnKeyPress Event
Отправлено: R.I.Chernov от 21-01-2015, 13:26:31
Спасибо за идею! Буду разбираться.
Название: Re: KeyboardEvents.OnKeyPress Event
Отправлено: Bookvoed от 27-10-2022, 14:28:11
Здравствуйте. Извиняюсь за поднятие старой темы. Возникла необходимость отследить нажатие сочетания клавиш ctrl+S, для того , чтобы при сохранении чертежа, в addin сработал код:

Код - Visual Basic [Выбрать]
  1. Dim a = IO.Path.GetFileName(ThisDrawing.ModelDocument.FullFileName)
  2. iProperties.Value("Project", "Part Number") = iProperties.Value(a, "Project", "Part Number") & " " & iProperties.Value(a, "Project", "Description")
  3. fname = ThisDoc.Document.FullFileName.Remove(ThisDoc.Document.FullFileName.LastIndexOf("\")) & "\" & iProperties.Value("Project", "Part Number") & " " & iProperties.Value("Project", "Description")
  4. ThisDoc.Document.SaveAs(fname & ".pdf", True)
  5.  

Работа с addin - дело увлекательное, но самостоятельно разобраться не получилось :( , поэтому прошу вашей помощи.
Пробовал адаптировать способы, описанные в этой теме - не вышло.