Подтвердить что ты не робот

Управление Excel через Midi-контроллер

У меня есть один из них nanoKontrol's
(источник: netdna-cdn.com)

и хотел использовать ползунки для управления Excel, как одна из полос прокрутки в форме Excel.

Мне удалось изменить этот код для VBA, но он крайне нестабилен. Кто-нибудь может помочь мне стабилизировать это? Я думаю, что функция MidiIn_Event может дать сбой, если она не возвращается достаточно быстро, но я могу ошибаться.

Заранее спасибо.

Public Const CALLBACK_FUNCTION = &H30000
Public Declare Function midiInOpen Lib "winmm.dll" 
        (lphMidiIn As Long, 
        ByVal uDeviceID As Long, ByVal dwCallback As Any, 
        ByVal dwInstance As Long, ByVal dwFlags As Long) As Long
Public Declare Function midiInClose Lib "winmm.dll" 
        (ByVal hMidiIn As Long) As Long
Public Declare Function midiInStart Lib "winmm.dll" 
        (ByVal hMidiIn As Long) As Long
Public Declare Function midiInStop Lib "winmm.dll" 
        (ByVal hMidiIn As Long) As Long
Public Declare Function midiInReset Lib "winmm.dll" 
        (ByVal hMidiIn As Long) As Long
Private ri As Long

Public Sub StartMidiFunction()
    Dim lngInputIndex As Long
    lngInputIndex=0
    Call midiInOpen(ri, lngInputIndex, AddressOf MidiIn_Event, 
            0, CALLBACK_FUNCTION)
    Call midiInStart(ri)
End Function

Public Sub EndMidiRecieve()
    Call midiInReset(ri)
    Call midiInStop(ri)
    Call midiInClose(ri)
End Sub

Public Function MidiIn_Event(ByVal MidiInHandle As Long, 
        ByVal Message As Long, ByVal Instance As Long, 
        ByVal dw1 As Long, ByVal dw2 As Long) As Long

    'dw1 contains the midi code
    If dw1 > 255 Then 'Ignore time codes
        Call MsgBox(dw1)    'This part is unstable
    End If
End Function        
4b9b3361

Ответ 1

Проблема, вероятно, MsgBox:

  • Поскольку события MIDI используют обратные вызовы, они скорее всего запускаются из другого потока. VBA по сути является однопоточным (см., Например, многопоточность в VBA), поэтому попытка показать модальное диалоговое окно из другого потока может вызвать проблемы (поведение undefined крушение, все остальное...)
  • MIDI обычно запускает огромное количество событий (самое маленькое движение ползунка или ручки вызывает событие), поэтому перемещение чего-то заметного количества может привести к сотням событий. Отображение диалога (требующего нажатия OK) на каждом событии может быть проблемой.

Для тестирования попробуйте заменить Call MsgBox(dw1) на Debug.Print dw1, чтобы значения только что были напечатаны в окне Immediate, которое должно быть намного более стабильным. Если вы пытаетесь выполнить какое-то простое действие (например, обновите значение в ячейке, прокрутите окно), вы сможете уйти с ним, если каждый вызов MidiIn_Event завершается до следующего события.

Более сложным, но стабильным решением может быть толкание точек данных в очередь в обработчике событий и использование повторяющегося таймера в VBA, который выталкивает элементы из очереди и выполняет некоторые действия в потоке VBA.

Ответ 2

Это так замечательно круто: D

но окно сообщения, как упоминалось выше, убьет его, но удаление почтового ящика, вероятно, не поможет. Вы хотите свести к минимуму количество трафика, чтобы преуспеть, потому что vba- > excel не будет мгновенным.

Soooo решение будет

в макросе запуска рабочей книги

    Public lngMessage As String

    Private Sub Workbook_Open()
        alertTime = Now + TimeValue("00:00:01")
        Application.OnTime alertTime, "EventMacro"
    End Sub
    Sub EventMacro()
        ActiveSheet.Cells(1, 1).Value = lngMessage
        alertTime = Now + TimeValue("00:00:01")
    End Sub

    Public Function MidiIn_Event(ByVal MidiInHandle As Long, ByVal Message As Long, ByVal Instance As Long, ByVal dw1 As Long, ByVal dw2 As Long) As Long
        'dw1 contains the midi code
        If dw1 > 255 Then 'Ignore time codes
            lngMessage = dw1    'This part is now happy
        End If
    End Function