PROGRAMMING TECHNIQUESby Mark Novisoffand Craig LeachSpice Up Your AppsWith MultimediaIow that multimedia is firmly entrenchedSystemHandCritical Stopin the hearts and minds (not to mention WINDOWS 3.1 APISystemQuestionQuestioneyes and ears) of Windows programmersSystemStartWindows Startand users, you might want to spice up your appli-LETS YOUcations with a little sound or two.For example, you can specify a sound file suchIf you have VB 2.0 Professional Edition orADD SOUNDas ôc:\windows\chord.wav,ö or uselater, you can use the MCI.VBX custom control toôSystemDefaultö to play whatever sound the userplay sounds through a sound board or MicrosoftÆsWITHOUThas defined for that event in the Control Panel. InPC-Speaker driver (more on the PC-Speaker driverfact, by adding your own event definitions to thelater). While the MCI control provides a number ofUSING THE VB 2.0[Sounds] section of WIN.INI, you can allow yourconvenient services and sports an attractive cas-end users to redefine the sounds used exclusivelysette deck-style interface, it can be overkill if youMCI CUSTOMby your application. One example of this techniquesimply want to play sound files without user inter-is America Online for Windows, which adds toaction, or trigger the system event sounds definedCONTROL.your [Sounds] section with events such as ôWel-in the Windows Control Panel.come,ö ôGoodbye,ö and ôYou Have Mail.ö If youThe SndPlaySound API function from thedonÆt like the sounds defined for these events, youMMSYSTEM.DLL file included with Windowscan assign new sounds for them in the Control3.1 and the Microsoft Multimedia Extensions forPanel.Windows 3.0 allows you to play sounds without using a custom control.The second parameter, wFlags%, defines various options availableBy avoiding the MCI control, your application will use less resources andwith SndPlaySound:will not require you to distribute MCI.VBX.In case you were wondering, MCI.VBX also makes calls toFlagDescriptionMMSYSTEM.DLL, so this technique is simply a case of eliminating theSND_SYNCPlay sound synchronously and return onlymiddle man.when sound ends.To use the SndPlaySound function in your application (for allSND_ASYNCPlay sound asynchronously and returnversions of VB), add the following Declare statement and Constants toimmediatelyyour global or code module:after sound starts.SND_NODEFAULTDo not play the default sound ifDeclare Function SndPlaySound Lib "MMSYSTEM.DLL" _lpszSoundName$(ByVal lpszSoundName$, ByVal wFlags%) _is not found.As IntegerSND_LOOPPlay sound continuously until SndPlaySound is' Flags used by SndPlaySound:called again with lpszSoundName$ set toGlobal Const SND_SYNC = &H0000NULL. When looping soundsGlobal Const SND_ASYNC = &H0001with this flag, you must also specifyGlobal Const SND_NODEFAULT = &H0002SND_ASYNC.Global Const SND_LOOP = &H0008SND_NOSTOPReturn immediately if a sound is currentlyGlobal Const SND_NOSTOP = &H0010playing.The first parameter, lpszSoundName$, specifies the name of theIf the sound was played successfully, the function returns True (-1).sound to play. This can be a wave audio file name (*.WAV) or a systemIf the sound was not found, or if the SND_NOSTOP flag was specifiedevent name as defined in the [Sounds] section of the WIN.INI file. Whileyou can configure the system event sounds through the Sound section ofMark Novisoff is the founder and president of MicroHelp Inc., and is thethe Windows Control Panel, note that the actual system event names arecreator of several VB add-on products. His company sells products fordifferent than the ones that appear in the Control Panel. The standardVB, QuickBasic, PDS, and Windows. Mark is also a contributing editorevent names are:to Visual Basic ProgrammerÆs Journal. You can contact Mark at 4359Shallowford Industrial Parkway, Marietta, Georgia, 30066.Name To Use With SndPlay SoundName In Control PanelCraig Leach is senior executive vice president of Capitol InformationSystemAsteriskAsteriskService Inc. in Trenton, New Jersey and has written commercial andSystemDefaultDefault Beepcustom software in Basic since 1983. Contact Craig on CompuServe atSystemExclamationExclamation70244,2634.SystemExitWindows Exit102 FEBRUARY/MARCH 1994 Visual Basic ProgrammerÆs JournalPROGRAMMING TECHNIQUESand a sound was already playing, the function returns False (0).codes such as {Enter} or {Tab}. These codes are too numerous to list hereThe following example shows how easy it is to play a standard systemand may be found under the SendKeys statement in your VB documen-event sound, as well as a specific wave sound file:tation and online help.The wait parameter determines when your program regains controlSub Command1_Click ()after the SendKeys statement is executed. If wait is True, all of thewFlags% = SND_SYNC Or SND_NODEFAULTkeystrokes in the keytext string must be processed by the active window' Play the sound currently assigned tobefore control is returned to your program. If wait is False or omitted,' the "SystemQuestion" event in WIN.INI:your program gains control as soon as the keystrokes are sentùeven ifx% = SndPlaySound("SystemQuestion", wFlags%)they are waiting to be processed. The following example shows how to' Play a specific wave file:use SendKeys to send keystrokes from your program back to itselfx% = SndPlaySound("c:\windows\chord.wav", wFlags%)(similar to playing a macro):End SubSub Command1_Click ()Because we specified two sounds back to back, the SND_SYNC flag' When this button is clicked, set the focus towas used to prevent the first sound from being interrupted by the second' a text box on the current form and "automatically"sound. When playing only a single sound (such as playing the' type a string in the text box:ôSystemQuestionö or ôSystemAsteriskö sound immediately before in-Text1.SetFocusvoking the MsgBox function), use the SND_ASYNC flag to returnKeystrokes$ = "This was typed by SendKeys.{Enter}"immediately to the next statement in your program while the sound is still' The {Enter} code above is processed as the Enterplaying.' key; the code itself does not appearIf you donÆt have an MCI-compatible sound board at your disposal,' in the text box.you can achieve a crude approximation with your PCÆs internal speakerSendKeys Keystrokes$by using MicrosoftÆs PC-Speaker driver (SPEAKER.DRV). This driverEnd Subis available from CompuServe, the Microsoft Download Service (206-936-6735), and other online services. Although Microsoft has stated thatIf you want to send keystrokes to another Windows application, youmust first activate the other applicationÆs window. If you are running theother application via the Shell statement, specify the Shell windowstyleparameter as 1, 3, 5, or 9 to give the Shelled application the focus. Forexample:THE SND_SYNC FLAGSub Command2_Click ()' Activate the Notepad application andPREVENTS THE FIRST SOUND' give it the focus:x% = Shell("notepad.exe", 1)' Send keystrokes to Notepad and wait for processingFROM BEING INTERRUPTEDSendKeys "Sending keys to Notepad from _VB!{Enter}", TrueBY THE SECOND SOUND.' Instruct Notepad to save the file:' %F = Alt-F File Menu' S = Save File option' c:filename.ext = name entered in Save As box' {Enter} = EnterSendKeys "%FSc:filename.ext{Enter}", True' Activate our program againthe PC-Speaker driver is not compatible with the MCI control and theAppActivate App.TitleWindows 3.1 Media Player ôapplet,ö you can use it with the SndPlaySoundEnd Subfunction.Finally, if you insist on using your lowly PC speaker to play soundsIf the other application is already running and you know its title (itand want full MCI-compatibility, check out AristosoftÆs Wired Forappears in the Windows Task List), you can set the focus to thatSoundùits speaker driver is functionally equivalent to MicrosoftÆsapplication with the AppActivate statement, as in this example:SPEAKER.DRV but will also work with MCI.VBX, Media Player, andothers.Sub Command3_Click () ' Display the Help/About box in the Program Manager:KEYWORD OF THE ISSUE: SENDKEYS AppActivate "Program Manager"If you need to control another Windows application but donÆt want to ' Send Alt-H and A; wait for processing:wrestle with messy Dynamic Data Exchange commands, the SendKeys SendKeys "%HA", Truestatement may be a workable alternative. Simply stated, SendKeys sendsEnd Subone or more keystrokes to the active window (your program or anotherWindows application) as if they had been entered at the keyboard. TheAs mentioned, there are some exceptions to the displayable charac-syntax for SendKeys is as follows:ters you may include in the keytext parameter. The following charactershave special meaning to the SendKeys statement:SendKeys keytext [,wait]+ ^ % ~ ( ) [ ] { }The keytext parameter is a string containing a list of keystrokes to sendto the active window. With a few exceptions (which weÆll cover below),If you wish to include these characters in your string, you mustthis string may contain any displayable characters (A-Z, 0-9, etc.). Forenclose them in braces, as in {%} and {+}. In addition, SendKeys maynondisplayable characters such as Enter or Tab, you must use specialreport an ôIllegal function callö if one of the following is not enclosed inVisual Basic ProgrammerÆs Journal FEBRUARY/MARCH 1994 103PROGRAMMING TECHNIQUESGo to nextpage.104 FEBRUARY/MARCH 1994 Visual Basic ProgrammerÆs JournalPROGRAMMING TECHNIQUESGo to nextpage.Visual Basic ProgrammerÆs Journal FEBRUARY/MARCH 1994 105PROGRAMMING TECHNIQUESbraces:QUIRK: WHEN ôTRUEö IS NOT EQUAL TO ôNOTòAn unmatched parenthesis ( ) or brace { }.FALSEöòA bracket [ ].Once upon a time, it was necessary for Basic programmers to create TrueòBraces containing an undefined character sequence,and False variables at the start of each program (True/False are nowsuch as {abc}.reserved words in VBWin/VBDOS, with the values already defined foryou). If you are still performing this ancient ritual in QB/PDS, be sure toSendKeys has other limitations to consider. First, keystrokes sentset True equal to -1. Otherwise, you may run into this quirk:with SendKeys are case sensitive. Some applications may not processuppercase and lowercase versions of the same letter in the same manner.' Example for QB/PDS only:For example, if you send ô%fö (lowercase f) to Word for Windows 2.0,DefInt A-Zthe keystrokes are interpreted as Alt-F (which displays the File Menu).True = 1' Notice this is not -1If you send ô%Fö (uppercase F), Word interprets the keystrokes as Alt-False = 0Shift-f (lowercase f), which does not display the File Menu.Value = TrueSecond, keystrokes sent with SendKeys must be exact. Naturally, ifIf Value = Not False Thenyou fail to supply keystrokes to an application when further input isPrint "Value is True"required, the application will continue to wait for the appropriate input.ElseFor example, the Notepad example will work correctly the first time it isPrint "Value is False"executed. But on the second attempt, the file ôc:filename.extö alreadyEnd Ifexists, and therefore Notepad will ask if you want to overwrite an existingfile with that name. Since our SendKeys string does not include aIf you think this example would display ôValue is True,ö youÆreresponse to the overwrite prompt, Notepad has not actually saved the filewrong. Basic evaluates ôNot Falseö as -1, which is not equal to the Truewhen our SendKeys statement has finished executing.value (1) defined at the top of the program. Therefore, the line ôIf ValueFinally, SendKeys can cause mouse problems with IBM PS/2s= Not False Thenö is actually evaluated as ôIf 1 = -1 Then.ö nrunning under Windows 3.0. Microsoft has confirmed that when theSendKeys statement is executed in Windows 3.0 on an IBM PS/2 Model50, Model 50z, Model 60, or Model 80, Windows behaves erraticallywhen you move the mouse. Fortunately, this problem has been correctedin Windows 3.1.106 FEBRUARY/MARCH 1994 Visual Basic ProgrammerÆs Journal