sndPlaySound versus PlaySound

A

Andy

Hi,

I have an application that has several forms. Each form acts as a
monitor of a gateway system. If the gateway appears to be dead, the
application should play a .wav file (not resource) until the user
clicks a button to acknowledge the situation. To keep things simple,
lets assume there is only one monitor.

If I use the old sndPlaySound function, with the code:

SND_ASYNC = &H1
SND_LOOP = &H8

'Gateway Failed - Sound the alarm.
sndPlaySound(strFileName, SND_ASYNC OR SND_LOOP)
MessageBox.Show("Check Gateway!")
MessageBox.Show("Resume Monitor?")
sndPlaySound(Nothing, &H2)

the wav file is played in a loop until the user the user responds to
the second MessageBox.

However, if I use the preferred (because its newer) PlaySound function
with the code:

PlaySound(strFileName, Nothing, SND_ASYNC OR SND_LOOP)
MessageBox.Show("Check Gateway!")
MessageBox.Show("Resume Monitor?")
PlaySound(Nothing, Nothing, &H2)

The wav file is played just once and the first message box is
displayed.

Can anyone tell me how I should fiddle with the PlaySound parameters to
get this working?

My guess is that the sound produced when the message box is displayed
is clearing the the wav file when the PlaySound function is used. For
some reason, this does not happen with the sndPlaySound function.

If it helps, my next question will be how do I play two alarms at the
same time i.e. if two gateways fail simultaneously how do I prevent the
second alarm from purging the first alarm?

Thanks in advance,

Andy
 
H

Herfried K. Wagner [MVP]

Andy said:
However, if I use the preferred (because its newer) PlaySound function
with the code:

PlaySound(strFileName, Nothing, SND_ASYNC OR SND_LOOP)

Post your declaration of 'PlaySound'.
 
A

Andy

Here are the two API function declarations:

Declare Function PlaySound Lib "winmm.dll" Alias "PlaySoundA"
(ByVal strSoundFileName As String, _
ByVal hModule As Long, ByVal lngOptions As Long) As
Long
'
Declare Function sndPlaySound Lib "winmm.dll" Alias "sndPlaySoundA"
(ByVal lpszSoundFile As String, _
ByVal uFlags As Long) As Long


Please note that I'm using Option Explicit and Option Strict.

Thanks,

Andy
 
H

Herfried K. Wagner [MVP]

Andy said:
Declare Function PlaySound Lib "winmm.dll" Alias "PlaySoundA"
(ByVal strSoundFileName As String, _
ByVal hModule As Long, ByVal lngOptions As Long) As
Long
'
Declare Function sndPlaySound Lib "winmm.dll" Alias "sndPlaySoundA"
(ByVal lpszSoundFile As String, _
ByVal uFlags As Long) As Long

Your declarations are invalid for VB.NET. Note that 'Long' is a 64-bit
datatype in .NET but the function expects 32-bit values. Use these
declarations instead:

\\\
Private Declare Auto Function PlaySound Lib "winmm.dll" ( _
ByVal pszSound As String, _
ByVal hmod As IntPtr, _
ByVal fdwSound As Int32 _
) As Boolean

Private Declare Auto Function sndPlaySound Lib "winmm.dll" ( _
ByVal lpszSound As String, _
ByVal fuSound As Int32, _
) As Boolean
///

When calling 'PlaySound', pass 'IntPtr.Zero' in its 'hmod' parameter unless
you want to play a sound which is embedded as Win32 resource.
 
D

Dragon

Hi Andy,

Actually I wonder why your sndPlaySound declaration works. 8=]

Anyway, try this ones (modified and a bit improved):

~
Friend Declare Auto Function sndPlaySound Lib "winmm.dll" ( _
<MarshalAs(UnmanagedType.LPTStr), [In]()> ByVal lpszSound As
String, _
ByVal fuSound As sndPlaySoundFlag _
) As Boolean

Friend Declare Auto Function PlaySound Lib "winmm.dll" ( _
<MarshalAs(UnmanagedType.LPTStr), [In]()> ByVal pszSound As
String, _
ByVal hmod As IntPtr, _
ByVal fdwSound As PlaySoundFlag _
) As Boolean

<Flags()> Friend Enum sndPlaySoundFlag
Async = &H1
[Loop] = &H8
Memory = &H4
NoDefault = &H2
NoStop = &H10
Sync = &H0
End Enum

<Flags()> Friend Enum PlaySoundFlag
Application = &H80
[Alias] = &H10000
AliasID = &H110000
Async = &H1
FileName = &H20000
[Loop] = &H8
Memory = &H4
NoDefault = &H2
NoStop = &H10
NoWait = &H2000
Purge = &H40
Resource = &H40004
Sync = &H0
End Enum
~
Please note that I'm using Option Explicit and Option Strict.
I wish Option Explicit and Option Strict could help in this area 8=]

Hope this helps,
Roman
 
A

Andy

Hi Herfried and Dragon,

Many thanks to you both for your suggestions.

Dragon: Your declarations produced warning messages for MarshalAs and
[In] e.g. "Type MarshalAs is not defined" so I used Herfried's
declaration without the trailing coma following ByVal fuSound As Int32
;) However, I did use your PlaySoundFlag enumeration :)

The use of PlaySound is now working i.e. looping.

As predicted I am now at the point where I want to have multiple
monitors. If two monitors raise an alarm, the second alarm sound
replaces that of the first. When I acknowledge the alarm of the second
the sound is (correctly) stopped and there is silence i.e. the alarm
sound of the first monitor was not 'hidden' but (I guess) purged by the
second alarm being generated.

Is it possible to have two (or more) alarm sounds played at the same
time. If so, is it difficult?

Thanks again,

Andy
 
H

Herfried K. Wagner [MVP]

Andy said:
Dragon: Your declarations produced warning messages for MarshalAs and
[In] e.g. "Type MarshalAs is not defined"

The 'System.Runtime.InteropServices' namespace must be imported in order to
use these classes.
 
D

Dragon

Hi,

As Herfied states, MarshalAsAttribute and InAttribute are located in
System.Runtime.InteropServices namespace.
It's always wise to import it when you're dealing with interop.
Obviously, you can write full-qualified name like
System.Runtime.InteropServices.In().

As for your second question...

I don't think it's possible to play 2 sounds at the same time with
WinMM. Nevertheless, I'm not an expert at it, so I may mistake.
You can use some workaround here, for example, insert a global flag
indicating the number of alarms and shut down sound only if it's 0.
Quick & dirty example:

~
nRedAlerts += CByte(1)
PlaySound("!!!.wav", IntPtr.Zero, PlaySoundFlag.Async Or
PlaySoundFlag.Loop Or PlaySoundFlag.FileName)
MessageBox.Show("!!!")
nRedAlerts -= CByte(1)
If nRedAlerts = 0 Then PlaySound(Nothing, IntPtr.Zero,
PlaySoundFlag.NoDefault)
~

Roman
 
A

Andy

Hi Roman,

Many thanks for the suggestion.

I have followed your advice and used global to track the number of
alerts and the associated wav files.

Cheers,

Andy
 
G

Guest

Your example declarations and enums work great in a regular vb .net app. I
will hang on to them for later use.

Dov you know what declarations I can use for a mobile device app? PocketPC
2002

Thanks,

Jerod


Dragon said:
Hi Andy,

Actually I wonder why your sndPlaySound declaration works. 8=]

Anyway, try this ones (modified and a bit improved):

~
Friend Declare Auto Function sndPlaySound Lib "winmm.dll" ( _
<MarshalAs(UnmanagedType.LPTStr), [In]()> ByVal lpszSound As
String, _
ByVal fuSound As sndPlaySoundFlag _
) As Boolean

Friend Declare Auto Function PlaySound Lib "winmm.dll" ( _
<MarshalAs(UnmanagedType.LPTStr), [In]()> ByVal pszSound As
String, _
ByVal hmod As IntPtr, _
ByVal fdwSound As PlaySoundFlag _
) As Boolean

<Flags()> Friend Enum sndPlaySoundFlag
Async = &H1
[Loop] = &H8
Memory = &H4
NoDefault = &H2
NoStop = &H10
Sync = &H0
End Enum

<Flags()> Friend Enum PlaySoundFlag
Application = &H80
[Alias] = &H10000
AliasID = &H110000
Async = &H1
FileName = &H20000
[Loop] = &H8
Memory = &H4
NoDefault = &H2
NoStop = &H10
NoWait = &H2000
Purge = &H40
Resource = &H40004
Sync = &H0
End Enum
~
Please note that I'm using Option Explicit and Option Strict.
I wish Option Explicit and Option Strict could help in this area 8=]

Hope this helps,
Roman
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Similar Threads


Top