Code zu verschiedenen Themen in .NET
Abspielen einer eingebetteten Klangdatei
Will man in einer Windows-Forms-Anwendung einen Klang wiedergeben, dann wird man im .NET Framework lange nach einer Lösung suchen und keine finden. Das .NET Framework enthält auch in der Version 1.1 keinerlei Unterstützung für die Wiedergabe von Klang- und Videodaten. Oft ist es aber sinnvoll, den Benutzer durch einen Klang auf das Eintreten eines Ereignisses hinzuweisen.
Idealerweise sollte die Klangdatei in die Anwendung eingebettet werden, damit nicht zu viele Dateien ausgeliefert werden müssen. Dies erreicht man, indem man die Klangdatei (im Wave-Format) dem Projekt hinzufügt, die auswählt und im Eigenschaftenfenster als Buildaktion
den Wert Eingebettete Ressource
wählt. Anschließend kann man die im Folgenden angegebene Klasse SimpleSound
benutzen, um einen Klang anhand seines Ressourcenidentifikators wiederzugeben:
Imports System.IO
Imports System.Reflection
Imports System.Runtime.InteropServices
Public Class SimpleSound
Private Declare Auto Function PlaySound Lib "winmm.dll" ( _
ByVal pszSound As IntPtr, _
ByVal hModule As IntPtr, _
ByVal dwFlags As Int32 _
) As Boolean
Private Const SND_ASYNC As Int32 = &H1
Private Const SND_MEMORY As Int32 = &H4
Private Const SND_LOOP As Int32 = &H8
Private Const SND_PURGE As Int32 = &H40
Private Shared m_hgData As IntPtr
Public Shared Sub Play(ByVal Name As String, ByVal [Loop] As Boolean)
If Not m_hgData.Equals(IntPtr.Zero) Then
StopPlaying()
End If
Dim st As Stream = _
[Assembly].GetExecutingAssembly().GetManifestResourceStream( _
Name _
)
Dim Length As Integer = CInt(st.Length)
Dim Data(Length - 1) As Byte
st.Read(Data, 0, Length)
st.Close()
m_hgData = Marshal.AllocHGlobal(Length)
Marshal.Copy(Data, 0, m_hgData, Length)
Dim Flags As Int32 = SND_MEMORY Or SND_ASYNC
If [Loop] Then
Flags = Flags Or SND_LOOP
End If
PlaySound( _
m_hgData, _
IntPtr.Zero, _
Flags _
)
End Sub
Public Shared Sub [Stop]()
If Not m_hgData.Equals(IntPtr.Zero) Then
StopPlaying()
End If
End Sub
Private Shared Sub StopPlaying()
PlaySound(IntPtr.Zero, IntPtr.Zero, SND_PURGE)
Marshal.FreeHGlobal(m_hgData)
m_hgData = IntPtr.Zero
End Sub
End Class
Ein Beispielaufruf könnte SimpleSound.Play("MyRootNamespace.foo.wav", True)
lauten, wobei MyRootNamespace
für den Stammnamensraum des Projekts und foo.wav
für den Namen der Wave-Datei steht. Vor dem Beenden der Anwendung, die die Klasse zum Abspielen eines Klangs verwendet, muß die Methode Stop
aufgerufen werden.
Feststellen der Inaktivität des Benutzers
Das .NET Framework bietet keine Unterstützung dafür, festzustellen, ob der Benutzer das System für einen bestimmten Zeitraum nicht mehr bedient hat. Die nachstehende Klasse UserIdleDetector
rüstet die fehlende Funktionalität auf Basis der Plattformfunktion GetLastInputInfo
nach. Das Ereignis UserIdle
wird ausgelöst, wenn eine bestimmte Zeitspanne seit der letzten Benutzereingabe verstrichen ist. Nimmt der Benutzer seine Aktivität wieder auf, wird das Ereignis UserWakeup
ausgelöst. Die Auflösung des Detektors ist ungefähr eine Sekunde:
Imports System.ComponentModel
Imports System.Runtime.InteropServices
Imports System.Timers
Public Class UserIdleDetector
Inherits Component
Private Declare Function GetLastInputInfo Lib "user32.dll" ( _
ByRef plii As LASTINPUTINFO _
) As Boolean
Private Structure LASTINPUTINFO
Public cbSize As Int32
Public dwTime As Int32
End Structure
Public Delegate Sub UserIdleEventHandler( _
ByVal sender As Object, _
ByVal e As EventArgs _
)
Public Delegate Sub UserWakeupEventHandler( _
ByVal sender As Object, _
ByVal e As EventArgs _
)
Public Event UserIdle As UserIdleEventHandler
Public Event UserWakeup As UserWakeupEventHandler
Private WithEvents m_Timer As New Timer(1000)
Private m_Interval As Integer
Private m_LastInputTime As Integer
Private m_lii As LASTINPUTINFO
Public Sub Start(ByVal IdleTimeoutSeconds As Integer)
m_Interval = IdleTimeoutSeconds * 1000
m_Timer.Start()
End Sub
Public Sub [Stop]()
m_Timer.Stop()
End Sub
Private Function GetIdleTime() As Integer
m_lii.cbSize = Marshal.SizeOf(m_lii)
If Not GetLastInputInfo(m_lii) Then
Throw New Win32Exception
Else
If m_lii.dwTime <> m_LastInputTime Then
m_LastInputTime = m_lii.dwTime
Return 0
Else
Return Environment.TickCount - m_lii.dwTime
End If
End If
End Function
Private Sub m_Timer_Elapsed( _
ByVal sender As Object, _
ByVal e As ElapsedEventArgs _
) Handles m_Timer.Elapsed
Static UserInactive As Boolean
If GetIdleTime() > m_Interval Then
If Not UserInactive Then
UserInactive = True
RaiseEvent UserIdle(Me, EventArgs.Empty)
End If
Else
If UserInactive Then
UserInactive = False
RaiseEvent UserWakeup(Me, EventArgs.Empty)
End If
End If
End Sub
End Class
UserIdleDetector
zum Ermitteln der Inaktivität des Benutzers.