通过Midi控制器控制Excel

use*_*620 24 excel midi vba winmm

我有这些nanoKontrol的其中一个http://mustech.jpsystemsinc.netdna-cdn.com/wp-content/uploads/2008/12/kontrol.gif 并想用它上面的滑块来控制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        
Run Code Online (Sandbox Code Playgroud)

And*_*son 2

问题可能是MsgBox

  • 由于 MIDI 事件使用回调,它们很可能是从另一个线程运行的。VBA 本质上是单线程的(参见例如VBA 中的多线程),因此尝试从另一个线程显示模式对话框可能会导致问题(未定义的行为、崩溃、其他任何情况......)
  • MIDI 通常会触发大量事件(滑块或旋钮的最微小移动就会触发一个事件),因此明显移动某物可能会导致数百个事件。在每个事件中显示一个对话框(需要单击“确定”)可能是一个问题。

为了进行测试,尝试替换Call MsgBox(dw1)Debug.Print dw1,以便将值仅打印在立即窗口中,这应该更稳定。如果您尝试执行一些简单的操作(例如更新单元格中的值,滚动窗口),只要每次调用MidiIn_Event只要每次调用在下一个事件之前完成,

更复杂但稳定的解决方案可能是将数据点推送到事件处理程序中的队列上,并在 VBA 中使用重复计时器,从队列中弹出项目并在 VBA 线程上执行某些操作。