We help IT Professionals succeed at work.

We've partnered with Certified Experts, Carl Webster and Richard Faulkner, to bring you two Citrix podcasts. Learn about 2020 trends and get answers to your biggest Citrix questions!Listen Now



spenney asked
Medium Priority
Last Modified: 2010-05-19
hi -
Have been trying to write routine that plays a MIDI file in a loop while moving a gif around on the screen. I have the VB4 STD edition, running in win95. Can someone please post how to tell when the midi file has stopped playing?  I believe it might be a return from a win32API call. I am using mciSendString() etc to play midi file, but can't find any other information on this. thanks  -slacker-
Watch Question


Is there anywhere I can get a copy of the win32api?
Or do you have to buy a book or pro version of VB?
You'll need to read two articles. First one is below and the second one is in the MS Knowledgebase Q114557. You can get to the knowledge base over the web.

Direct Control of AVI Files from Viewer
Article ID: Q110384
Revision Date: 09-JAN-1996
The information in this article applies to:

 - Microsoft Multimedia Viewer Publishing Toolkit versions 2.0
   and 2.0a

This article describes two methods to play an Audio-Video Interleaved (.AVI) file without a controller, and then have the .AVI window close when the .AVI file is done playing. You can then execute commands when the AVI window closes.
Method 1 describes using the mciSendString() command from the MMSYSTEM.DLL that comes with the Windows 3.1 SDK (Software Development Kit). Method 2 describes how to use the standard Viewer ewX statement to play your .AVI file, and how to use hooks to be notified when the video finishes.

The simplest way to play an .AVI file without a controller and have the AVI window close when the .AVI is done is to use the mciSendString() function from MMSYSTEM.DLL that comes with the Windows 3.1 SDK.

NOTE: Using mciSendString() causes the .AVI file to be played in a window created by MMSYSTEM.DLL; the .AVI file will *not* be displayed in a regular pane.
 You could write a DLL function that calls mciSendString(), and call that DLL function from Viewer. To do this you would need to register your DLL function in the [CONFIG] section of your .MVP file. Or you could call mciSendString() directly from your Viewer title. In that case, you would need to register mciSendString() in the [CONFIG] section.
To register the mciSendString() function in your [CONFIG] section, add the following line to the [CONFIG] section of your .MVP file:


See pages 5-10 and 5-74 of the Viewer "Technical Reference" for more information on using RegisterRoutine().
You can start the .AVI file in many ways, including using topic entry commands, hot spot commands, buttons, and menu items. To create a button to play the COYOTE.AVI file (for example), add the following line to the [CONFIG] section of your .MVP file after the RegisterRoutine() function:

   CreateButton(`btn_avi', `Play AVI', `mciSendString("open
   coyote.avi",0,0,0):mciSendString("play coyote.avi
   wait",0,0,0):mciSendString("close coyote.avi",0,0,0)')

To start an .AVI file on topic entry, have the .AVI window close when the .AVI file finishes, and then jump to another topic, add the following topic entry commands:

   !mciSendString("open coyote.avi",0,0,0); mciSendString("play
   coyote.avi   wait",0,0,0); mciSendString("close coyote.avi",0,0,0);

NOTE: Because the CreateButton() function is in the .MVP file, the multiple commands are separated by a colon (:). If you specify multiple commands in your .RTF file, they should be separated by a semicolon (;) instead. In .MVP files, the semicolon (;) character means the rest of the line is commented out.
Method 2 uses a message hook to determine when the .AVI file is finished playing. If you play the .AVI file using an {ewX mvmci2, ViewerMCI...} statement, then Viewer's MVMCI2.DLL will ask the system to send an MM_MCINOTIFY message when the .AVI file is finished playing. You can put a message hook function in a DLL, and when the MM_MCINOTIFY message comes through, you could send the ClosePane() command to Viewer via the VwrCommand() Viewer API (Application Programming Interface) function.
There is a sample in the Microsoft Software Library called VWRHOOK that uses a DLL to implement a message hook to trap MM_MCINOTIFY. If you call SetGMHook() in your [CONFIG] section, the hook function will receive a notification message whenever any MCI element is finished playing. The Windows SDK documentation for SetWindowHook() and SetWindowsHookEx() has more information on setting hooks.
For additional information on the VWRHOOK sample, please see the following article in the Microsoft Knowledge Base:

   ARTICLE-ID: Q114557
   TITLE     : SAMPLE: Executing Viewer Commands When MCI Finishes Playing

Additional reference words: 2.00 2.00a hotspot

KBCategory: kbusage kbfile
KBSubcategory: MdkView

Not the solution you were looking for? Getting a personalized solution is easy.

Ask the Experts

There is a much easier way than is listed above....
This example was created in VB 3, but will work in any VB.

Create a form with two command buttons and two labels, do not rename them (or you'll have to edit the text below).
Paste the following code into the general declarations section of the form


Option Explicit

Declare Function mciSendString Lib "mmsystem" (ByVal lpstrCommand$, ByVal lpstrReturnStr As Any, ByVal wReturnLen%, ByVal hCallBack%) As Long

Sub Form_Load ()

    Dim X As Integer
    ' If we're already running, then quit
    If (App.PrevInstance = True) Then
    End If
    ' Open the midi file (This should all be on one line)
    X = mciSendString("open c:\dev\sound\mi2.mid type sequencer alias seq2", 0&, 0, hWnd)
    X = mciSendString("play seq2", 0&, 0, hWnd)
End Sub

Private Sub Form_Unload (Cancel As Integer)

Dim X As Integer

    'Close all MCI devices opened by this program
    X = mciSendString("close seq2", 0&, 0, hWnd)

End Sub

Private Sub Command1_Click ()

    Dim X As Integer
        ' Play the Midi file
        X = mciSendString("play seq2", 0&, 0, hWnd)

End Sub

Private Sub Command2_Click ()

    Dim X As Integer

    ' This will stop the file playing (well its more of a pause really)
    X = mciSendString("stop seq2 wait", 0&, 0, hWnd)

End Sub

Private Sub Timer1_Timer ()

    Dim X As Long
    Dim s As String * 128
    Dim iLength As Integer
    Dim iPosition As Integer
    ' Get the length of the MIDI file
    X = mciSendString("status seq2 length", s, Len(s), 0)
    label1.Caption = s
    iLength = Val(s)

    ' Get the distance through the file
    X = mciSendString("status seq2 position", s, Len(s), 0)
    Label2.Caption = s
    iPosition = Val(s)

    ' If the position is at the length then...
    If iPosition >= iLength Then
        ' Close the file and start it up again!!!
        X = mciSendString("close seq2", 0&, 0, hWnd)
        ' (This should all be on one line)
        X = mciSendString("open c:\dev\sound\mi2.mid type sequencer alias seq2", 0&, 0, hWnd)
        X = mciSendString("play seq2", 0&, 0, hWnd)

    End If

End Sub
Access more of Experts Exchange with a free account
Thanks for using Experts Exchange.

Create a free account to continue.

Limited access with a free account allows you to:

  • View three pieces of content (articles, solutions, posts, and videos)
  • Ask the experts questions (counted toward content limit)
  • Customize your dashboard and profile

*This site is protected by reCAPTCHA and the Google Privacy Policy and Terms of Service apply.


Please enter a first name

Please enter a last name

8+ characters (letters, numbers, and a symbol)

By clicking, you agree to the Terms of Use and Privacy Policy.