OVH Cloud OVH Cloud

Pb avec timeSetEvent

12 réponses
Avatar
Thierry S
Bonjour à tous,
J'utilise les timers Multimedia pour une meilleure précision.
Je n'ai aucun probleme sur mon poste de développement. Mais sur un autre
poste que je viens de faire, l'application ne fonctionne que sur un certain
profil (profil A) et pas sur les autres.
Le profil A est utilisé pour installer Windows XP et tout ce qui suit. J'ai
mis mes autres profils "Administrateur du poste" mais rien n'y fait. Voici le
problème.
Quand je lance une 1ère foir le timer c'est OK mais si je veux le relancer
après, j'ai un message d'erreur "ID de contrôle introuvable"!!! Le problème
se situe je pense au niveau de la fonction "timeSetEvent".
Meric pour votre aide car j'y perds mon latin! Je vais aller élever des
chèvres!!!
Bonne journée.

10 réponses

1 2
Avatar
Zoury
Bonjour Thierry ! :O)

Peux-tu nous montrer ton code ?

--
Cordialement
Yanick
MVP pour Visual Basic
"Thierry S" a écrit dans le message de
news:
Bonjour à tous,
J'utilise les timers Multimedia pour une meilleure précision.
Je n'ai aucun probleme sur mon poste de développement. Mais sur un autre
poste que je viens de faire, l'application ne fonctionne que sur un


certain
profil (profil A) et pas sur les autres.
Le profil A est utilisé pour installer Windows XP et tout ce qui suit.


J'ai
mis mes autres profils "Administrateur du poste" mais rien n'y fait. Voici


le
problème.
Quand je lance une 1ère foir le timer c'est OK mais si je veux le relancer
après, j'ai un message d'erreur "ID de contrôle introuvable"!!! Le


problème
se situe je pense au niveau de la fonction "timeSetEvent".
Meric pour votre aide car j'y perds mon latin! Je vais aller élever des
chèvres!!!
Bonne journée.


Avatar
Thierry S
Bonjour,
Voici mon module "Module_Timer":
Module Module_Timer

Private T_Resolution As UInt32

'***
' Class Timer

Public Class Timer
Implements IDisposable

Private Shared m_tc As TIMECAPS
Private m_uDelay As UInt32
Private m_uResolution As UInt32
Private m_uTimerID As Long
Public Event Callback As EventHandler
Private Const TIMERR_NOERROR = 0
Private Const TARGET_RESOLUTION = 1

#Region " Déclarations APIs "

<Flags()> _
Private Enum EVENTFLAG : UInt32
TIME_ONESHOT = &H0
TIME_PERIODIC = &H1
TIME_CALLBACK_FUNCTION = &H0
TIME_CALLBACK_EVENT_SET = &H10
TIME_CALLBACK_EVENT_PULSE = &H20
TIME_KILL_SYNCHRONOUS = &H100
End Enum

Private Delegate Sub LPTIMECALLBACK( _
ByVal uID As UInt32, _
ByVal uMsg As UInt32, _
ByVal dwUser As Int32, _
ByVal dw1 As Int32, _
ByVal dw2 As Int32)

<StructLayout(LayoutKind.Sequential)> _
Private Structure TIMECAPS

Private m_uPeriodMin As UInt32
Private m_uPeriodMax As UInt32

Public Sub New(ByVal uPeriodMin As UInt32, ByVal uPeriodMax As UInt32)
m_uPeriodMin = uPeriodMin
m_uPeriodMax = uPeriodMax
End Sub

Public ReadOnly Property PeriodMin() As UInt32
Get
Return m_uPeriodMin
End Get
End Property

Public ReadOnly Property PeriodMax() As UInt32
Get
Return m_uPeriodMax
End Get
End Property

End Structure

<DllImport("winmm.dll", SetLastError:=True)> _
Private Shared Function timeBeginPeriod(ByVal uPeriod As UInt32) As Long
'
End Function

<DllImport("winmm.dll", SetLastError:=True)> _
Private Shared Function timeEndPeriod(ByVal uPeriod As UInt32) As Long
'
End Function

<DllImport("winmm.dll", SetLastError:=True)> _
Private Shared Function timeSetEvent( _
ByVal uDelay As UInt32, _
ByVal uResolution As UInt32, _
ByVal lpTimeProc As LPTIMECALLBACK, _
ByRef dwUser As Int32, _
ByVal fuEvent As EVENTFLAG) As Long
'
End Function

<DllImport("winmm.dll", SetLastError:=True)> _
Private Shared Function timeKillEvent(ByVal uTimerID As Long) As UInt32
'
End Function

<DllImport("winmm.dll", SetLastError:=True)> _
Private Shared Function timeGetDevCaps(ByRef lpTimeCaps As TIMECAPS,
ByVal uSize As UInt32) As Integer
'
End Function

#End Region

#Region " Membres partagés "

Shared Sub New()

timeGetDevCaps(m_tc, Convert.ToUInt32(Marshal.SizeOf(m_tc)))
Dim nErr As Int32 = Marshal.GetLastWin32Error()
If (nErr <> 0) Then
Throw New Win32Exception(nErr)
End If

End Sub

Public Shared ReadOnly Property MinimumResolution() As UInt32
Get
Return m_tc.PeriodMin
End Get
End Property

Public Shared ReadOnly Property MaximumResolution() As UInt32
Get
Return m_tc.PeriodMax
End Get
End Property

#End Region

Public Sub New()
End Sub

Public Sub New(ByVal uDelay As UInt32, ByVal uResolution As UInt32)
m_uDelay = uDelay
m_uResolution = uResolution
End Sub

Public Sub New(ByVal dwDelay As Int32, ByVal dwResolution As Int32)
m_uDelay = Convert.ToUInt32(dwDelay)
m_uResolution = Convert.ToUInt32(dwResolution)
End Sub

Public ReadOnly Property Delay() As UInt32
Get
Return m_uDelay
End Get
End Property

Public ReadOnly Property Resolution() As UInt32
Get
Return m_uResolution
End Get
End Property

Public Sub Start()
m_uTimerID = timeSetEvent(m_uDelay, _
m_uResolution, _
AddressOf TimeProc, _
0, _
EVENTFLAG.TIME_PERIODIC Or
EVENTFLAG.TIME_KILL_SYNCHRONOUS)

Dim nErr As Int32 = Marshal.GetLastWin32Error()
If (nErr <> 0) Then
m_uTimerID = 0
Throw New Win32Exception(nErr)
End If

End Sub

Public Sub [Stop]()
If (m_uTimerID) Then
timeKillEvent(m_uTimerID)
m_uTimerID = 0
End If
End Sub

Public Sub Dispose() Implements System.IDisposable.Dispose
[Stop]()
timeEndPeriod(T_Resolution)
End Sub

Private Sub TimeProc(ByVal uID As UInt32, ByVal uMsg As UInt32, ByVal
dwUser As Int32, ByVal dw1 As Int32, ByVal dw2 As Int32)
RaiseEvent Callback(Me, New EventArgs)
End Sub

Protected Overrides Sub Finalize()
MyBase.Finalize()
Dispose()
End Sub

End Class

'***

End Module

Voici mon code dans mon formulaire:
Private G_M_Timer As Timer

' code généré par le concepteur de form

Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles MyBase.Load

Me.Text = ""

'Déclare un timer de 500 ms
G_M_Timer = New Timer(500, 1)
AddHandler G_M_Timer.Callback, AddressOf G_M_Timer_Callback

End Sub

Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles Button1.Click
G_M_Timer.Start()
Label1.Text = "0"
End Sub

Private Sub G_M_Timer_Callback(ByVal sender As Object, ByVal e As
System.EventArgs)

Label1.Text = CInt(Label1.Text) + 1
If (Label1.Text = 10) Then
G_M_Timer.Stop()
End If

End Sub

Bonne journée.

Thierry.



"Zoury" a écrit :

Bonjour Thierry ! :O)

Peux-tu nous montrer ton code ?

--
Cordialement
Yanick
MVP pour Visual Basic
"Thierry S" a écrit dans le message de
news:
> Bonjour à tous,
> J'utilise les timers Multimedia pour une meilleure précision.
> Je n'ai aucun probleme sur mon poste de développement. Mais sur un autre
> poste que je viens de faire, l'application ne fonctionne que sur un
certain
> profil (profil A) et pas sur les autres.
> Le profil A est utilisé pour installer Windows XP et tout ce qui suit.
J'ai
> mis mes autres profils "Administrateur du poste" mais rien n'y fait. Voici
le
> problème.
> Quand je lance une 1ère foir le timer c'est OK mais si je veux le relancer
> après, j'ai un message d'erreur "ID de contrôle introuvable"!!! Le
problème
> se situe je pense au niveau de la fonction "timeSetEvent".
> Meric pour votre aide car j'y perds mon latin! Je vais aller élever des
> chèvres!!!
> Bonne journée.





Avatar
Zoury
ReBonjour !

Tu t'es inspiré de ma classe on dirait.. :O)
Je me demandais si ça avait règlé ton problème étant donné que tu n'as
jamais redonné de nouvelle


Private m_uTimerID As Long
Private Shared Function timeBeginPeriod(ByVal uPeriod As UInt32) As


Long
Private Shared Function timeEndPeriod(ByVal uPeriod As UInt32) As Long
Private Shared Function timeSetEvent( _
ByVal uDelay As UInt32, _
ByVal uResolution As UInt32, _
ByVal lpTimeProc As LPTIMECALLBACK, _
ByRef dwUser As Int32, _
ByVal fuEvent As EVENTFLAG) As Long
Private Shared Function timeKillEvent(ByVal uTimerID As Long) As


UInt32

En .NET, le type Long prend 8 octets (64 bits).. Modifie les types Long pour
du Int32 ou UInt32.


Aussi, je me suis rendu compte que le code permettait le lancement de
plusieurs Timers à la fois mais ne permettait de fermer que le dernier. En
effet si on appel Start() à deux reprises, par exemple, deux Timers se
mettront en branle (avec chacun leur ID) mais étant donné qu'on ne conserve
que l'ID du dernier Timer, c'est ce dernier qui se fera "tuer" lors de
l'appel à timeKillEvent() laissant l'autre en mémoire causant ainsi une
perte de mémoire..

J'ai règler le problème dans ma classe en empêchant tout simplement le
Start() si une séquence était déjà activée :
'***
Public ReadOnly Property Started() As Boolean
Get
Return Convert.ToInt32(m_uTimerID) > 0
End Get
End Property

Public Sub Start()

If (Me.Started) Then
Throw New InvalidOperationException("Le timer est déjà en
fonction.")
End If

m_uTimerID = timeSetEvent(m_uDelay, _
m_uResolution, _
AddressOf TimeProc, _
0, _
EVENTFLAG.TIME_PERIODIC Or
EVENTFLAG.TIME_KILL_SYNCHRONOUS)

Dim nErr As Int32 = Marshal.GetLastWin32Error()
If (nErr <> 0) Then
m_uTimerID = Convert.ToUInt32(0)
Throw New Win32Exception(nErr)
End If

End Sub
'***


ps : Pourquoi déclarer ta classe dans un module ?

--
Cordialement
Yanick
MVP pour Visual Basic
Avatar
Thierry S
Bonjour,
Il est vrai que le code est super. J'ai modifié les Long en UInt32 et j'ai
toujours un problème même sur mon poste de développement.
Je lance un timer de 500ms et au bout de 120-130 fois qu'il passe dans le
fonction de CallBack, il plante lamentablement!!!
Si vous voulez je peux vous envoyer tout le projet. J'ai juste un form avec
un bouton et un label.

Thierry.


"Zoury" a écrit :

ReBonjour !

Tu t'es inspiré de ma classe on dirait.. :O)
Je me demandais si ça avait règlé ton problème étant donné que tu n'as
jamais redonné de nouvelle


> Private m_uTimerID As Long
> Private Shared Function timeBeginPeriod(ByVal uPeriod As UInt32) As
Long
> Private Shared Function timeEndPeriod(ByVal uPeriod As UInt32) As Long
> Private Shared Function timeSetEvent( _
> ByVal uDelay As UInt32, _
> ByVal uResolution As UInt32, _
> ByVal lpTimeProc As LPTIMECALLBACK, _
> ByRef dwUser As Int32, _
> ByVal fuEvent As EVENTFLAG) As Long
> Private Shared Function timeKillEvent(ByVal uTimerID As Long) As
UInt32

En .NET, le type Long prend 8 octets (64 bits).. Modifie les types Long pour
du Int32 ou UInt32.


Aussi, je me suis rendu compte que le code permettait le lancement de
plusieurs Timers à la fois mais ne permettait de fermer que le dernier. En
effet si on appel Start() à deux reprises, par exemple, deux Timers se
mettront en branle (avec chacun leur ID) mais étant donné qu'on ne conserve
que l'ID du dernier Timer, c'est ce dernier qui se fera "tuer" lors de
l'appel à timeKillEvent() laissant l'autre en mémoire causant ainsi une
perte de mémoire..

J'ai règler le problème dans ma classe en empêchant tout simplement le
Start() si une séquence était déjà activée :
'***
Public ReadOnly Property Started() As Boolean
Get
Return Convert.ToInt32(m_uTimerID) > 0
End Get
End Property

Public Sub Start()

If (Me.Started) Then
Throw New InvalidOperationException("Le timer est déjà en
fonction.")
End If

m_uTimerID = timeSetEvent(m_uDelay, _
m_uResolution, _
AddressOf TimeProc, _
0, _
EVENTFLAG.TIME_PERIODIC Or
EVENTFLAG.TIME_KILL_SYNCHRONOUS)

Dim nErr As Int32 = Marshal.GetLastWin32Error()
If (nErr <> 0) Then
m_uTimerID = Convert.ToUInt32(0)
Throw New Win32Exception(nErr)
End If

End Sub
'***


ps : Pourquoi déclarer ta classe dans un module ?

--
Cordialement
Yanick
MVP pour Visual Basic





Avatar
Zoury
> Je lance un timer de 500ms et au bout de 120-130 fois qu'il passe dans le
fonction de CallBack, il plante lamentablement!!!



Tu obtiens une erreur cette fois ? un message ?

Si vous voulez je peux vous envoyer tout le projet. J'ai juste un form


avec
un bouton et un label.



Tu peux me copier le code ici si tu veux ça reviendra au même et quelqu'un
d'autre pourrait bien trouvé le problème :O)

--
Cordialement
Yanick
MVP pour Visual Basic
Avatar
Zoury
Naaarrg !

J'ai oublié une chose essentielle. :
'***
m_uTimerID = timeSetEvent(m_uDelay, _
m_uResolution, _
AddressOf TimerProc, _
0, _
EVENTFLAG.TIME_PERIODIC Or
EVENTFLAG.TIME_KILL_SYNCHRONOUS)
'***
En référencant la TimeProc() ainsi, on créer une instance de délegate "on
the fly" qui est passé à la fonction timeSetEvent. Cette délegate n'étant
pas référencé par aucune variable, se fait détruire par le GC au bout d'un
certain temps ce qui cause la NullReferenceException (que tu dois recevoir
?).


Il faut donc conserver une référence sur cette Delegate. C'est pourquoi
j'avais définie une delegate nommé LPTIMECALLBACK qui n'était utilisé que
dans la signature de timeSetEvent..

Ajoute cette déclaration à ta classe :
'***
Private m_delTimerCallback As LPTIMECALLBACK
'***

Et modifie Start() comme ceci :
'***
If (m_delTimerCallback Is Nothing) Then
m_delTimerCallback = New LPTIMECALLBACK(AddressOf Me.TimeProc)
End If
m_uTimerID = timeSetEvent(m_uDelay, _
m_uResolution, _
m_delTimerCallback, _
0, _
EVENTFLAG.TIME_PERIODIC Or
EVENTFLAG.TIME_KILL_SYNCHRONOUS)
'***

Et Dispose() comme ceci :
'***
Public Sub Dispose() Implements System.IDisposable.Dispose
[Stop]()
m_delTimerCallback = Nothing
End Sub
'***

Désolé pour l'oubli !! :O)

--
Cordialement
Yanick
MVP pour Visual Basic
Avatar
Thierry S
Ha génial!!!
Ca marche imppecable maintenant. Merci beaucoup pour votre aide et pour
votre code. Je vais continuer dans cette voie maintenant. Je vais pouvoir
continuer mon projet.
Encore merci beaucoup.

Thierry.

"Zoury" a écrit :

Naaarrg !

J'ai oublié une chose essentielle. :
'***
m_uTimerID = timeSetEvent(m_uDelay, _
m_uResolution, _
AddressOf TimerProc, _
0, _
EVENTFLAG.TIME_PERIODIC Or
EVENTFLAG.TIME_KILL_SYNCHRONOUS)
'***
En référencant la TimeProc() ainsi, on créer une instance de délegate "on
the fly" qui est passé à la fonction timeSetEvent. Cette délegate n'étant
pas référencé par aucune variable, se fait détruire par le GC au bout d'un
certain temps ce qui cause la NullReferenceException (que tu dois recevoir
?).


Il faut donc conserver une référence sur cette Delegate. C'est pourquoi
j'avais définie une delegate nommé LPTIMECALLBACK qui n'était utilisé que
dans la signature de timeSetEvent..

Ajoute cette déclaration à ta classe :
'***
Private m_delTimerCallback As LPTIMECALLBACK
'***

Et modifie Start() comme ceci :
'***
If (m_delTimerCallback Is Nothing) Then
m_delTimerCallback = New LPTIMECALLBACK(AddressOf Me.TimeProc)
End If
m_uTimerID = timeSetEvent(m_uDelay, _
m_uResolution, _
m_delTimerCallback, _
0, _
EVENTFLAG.TIME_PERIODIC Or
EVENTFLAG.TIME_KILL_SYNCHRONOUS)
'***

Et Dispose() comme ceci :
'***
Public Sub Dispose() Implements System.IDisposable.Dispose
[Stop]()
m_delTimerCallback = Nothing
End Sub
'***

Désolé pour l'oubli !! :O)

--
Cordialement
Yanick
MVP pour Visual Basic





Avatar
Zoury
Ça me fait plaisir ! J'aurai probablement dû me codé cette classe un jour de
toute façon ;O)

Pour les archives, voici la version débuguée (non CLS Compliant). Note que
le constructeur acceptant des Int32 peut causer une exception si on passe
des valeurs négatives, je l'ai donc enlever de la version ci dessous :
'***
Option Explicit On

Imports System.Runtime.InteropServices
Imports System.ComponentModel

Public Class Timer
Implements IDisposable

Private Shared m_tc As TIMECAPS
Private m_uDelay As UInt32
Private m_uResolution As UInt32
Private m_uTimerID As UInt32
Private m_delTimerCallback As LPTIMECALLBACK
Public Event Callback As EventHandler

#Region " Déclarations APIs "

<Flags()> _
Private Enum EVENTFLAG : UInt32
TIME_ONESHOT = &H0
TIME_PERIODIC = &H1
TIME_CALLBACK_FUNCTION = &H0
TIME_CALLBACK_EVENT_SET = &H10
TIME_CALLBACK_EVENT_PULSE = &H20
TIME_KILL_SYNCHRONOUS = &H100
End Enum

Private Delegate Sub LPTIMECALLBACK(ByVal uID As UInt32, _
ByVal uMsg As UInt32, _
ByVal dwUser As Int32, _
ByVal dw1 As Int32, _
ByVal dw2 As Int32)

<StructLayout(LayoutKind.Sequential)> _
Private Structure TIMECAPS

Private m_uPeriodMin As UInt32
Private m_uPeriodMax As UInt32

Public Sub New(ByVal uPeriodMin As UInt32, ByVal uPeriodMax As
UInt32)
m_uPeriodMin = uPeriodMin
m_uPeriodMax = uPeriodMax
End Sub

Public ReadOnly Property PeriodMin() As UInt32
Get
Return m_uPeriodMin
End Get
End Property

Public ReadOnly Property PeriodMax() As UInt32
Get
Return m_uPeriodMax
End Get
End Property

End Structure

<DllImport("winmm.dll", SetLastError:=True)> _
Private Shared Function timeSetEvent( _
ByVal uDelay As UInt32, _
ByVal uResolution As UInt32, _
ByVal lpTimeProc As LPTIMECALLBACK, _
ByRef dwUser As Int32, _
ByVal fuEvent As EVENTFLAG) As UInt32
'
End Function

<DllImport("winmm.dll", SetLastError:=True)> _
Private Shared Function timeKillEvent( _
ByVal uTimerID As UInt32) As UInt32
'
End Function

<DllImport("winmm.dll", SetLastError:=True)> _
Private Shared Function timeGetDevCaps(ByRef lpTimeCaps As TIMECAPS,
ByVal uSize As UInt32) As UInt32
'
End Function

#End Region

#Region " Membres partagés "

Shared Sub New()

' Retrouve les résolutions (min et max)
' supportées par le timer système
timeGetDevCaps(m_tc,
BitConverter.ToUInt32(BitConverter.GetBytes(Marshal.SizeOf(m_tc)), 0))

Dim nErr As Int32 = Marshal.GetLastWin32Error()
If (nErr <> 0) Then
Throw New Win32Exception(nErr)
End If

End Sub

Public Shared ReadOnly Property MinimumResolution() As UInt32
Get
Return m_tc.PeriodMin
End Get
End Property

Public Shared ReadOnly Property MaximumResolution() As UInt32
Get
Return m_tc.PeriodMax
End Get
End Property

#End Region

Public Sub New(ByVal uDelay As UInt32, _
ByVal uResolution As UInt32)
m_uDelay = uDelay
m_uResolution = uResolution
End Sub

Public ReadOnly Property Delay() As UInt32
Get
Return m_uDelay
End Get
End Property

Public ReadOnly Property Resolution() As UInt32
Get
Return m_uResolution
End Get
End Property

Public ReadOnly Property Started() As Boolean
Get
Return Convert.ToInt32(m_uTimerID) > 0
End Get
End Property

Public Sub Start()

If (Me.Started) Then
Throw New InvalidOperationException("Le timer est déjà en
fonction.")
End If

If (m_delTimerCallback Is Nothing) Then
m_delTimerCallback = New LPTIMECALLBACK(AddressOf Me.TimeProc)
End If
m_uTimerID = timeSetEvent(m_uDelay, _
m_uResolution, _
m_delTimerCallback, _
0, _
EVENTFLAG.TIME_PERIODIC Or
EVENTFLAG.TIME_KILL_SYNCHRONOUS)

Dim nErr As Int32 = Marshal.GetLastWin32Error()
If (nErr <> 0) Then
m_uTimerID = Convert.ToUInt32(0)
Throw New Win32Exception(nErr)
End If

End Sub

Public Sub [Stop]()
timeKillEvent(m_uTimerID)
m_uTimerID = Convert.ToUInt32(0)
End Sub

Public Sub Dispose() Implements System.IDisposable.Dispose
[Stop]()
m_delTimerCallback = Nothing
End Sub

Private Sub TimeProc(ByVal uID As UInt32, ByVal uMsg As UInt32, ByVal
dwUser As Int32, ByVal dw1 As Int32, ByVal dw2 As Int32)
RaiseEvent Callback(Me, New EventArgs)
End Sub

Protected Overrides Sub Finalize()
MyBase.Finalize()
Dispose()
End Sub

End Class
'***

--
Cordialement
Yanick
MVP pour Visual Basic
Avatar
**Pierre**
Bonjour,

Pourquoi ca ne fonctionne pas avec moi ? Voici le code comme le vôtre

Option Explicit On

Imports System.Runtime.InteropServices

Imports System.ComponentModel

Public Class Form1

Inherits System.Windows.Forms.Form

Private G_M_Timer As Timer

#Region " Code généré par le Concepteur Windows Form "

Public Sub New()

MyBase.New()

'Cet appel est requis par le Concepteur Windows Form.

InitializeComponent()

'Ajoutez une initialisation quelconque après l'appel InitializeComponent()

End Sub

'La méthode substituée Dispose du formulaire pour nettoyer la liste des
composants.

Protected Overloads Overrides Sub Dispose(ByVal disposing As Boolean)

If disposing Then

If Not (components Is Nothing) Then

components.Dispose()

End If

End If

MyBase.Dispose(disposing)

End Sub

'Requis par le Concepteur Windows Form

Private components As System.ComponentModel.IContainer

'REMARQUE : la procédure suivante est requise par le Concepteur Windows Form

'Elle peut être modifiée en utilisant le Concepteur Windows Form.

'Ne la modifiez pas en utilisant l'éditeur de code.

Friend WithEvents Button1 As System.Windows.Forms.Button

Friend WithEvents TextBox1 As System.Windows.Forms.TextBox

Friend WithEvents Label1 As System.Windows.Forms.Label

<System.Diagnostics.DebuggerStepThrough()> Private Sub InitializeComponent()

Me.Button1 = New System.Windows.Forms.Button

Me.TextBox1 = New System.Windows.Forms.TextBox

Me.Label1 = New System.Windows.Forms.Label

Me.SuspendLayout()

'

'Button1

'

Me.Button1.Location = New System.Drawing.Point(592, 176)

Me.Button1.Name = "Button1"

Me.Button1.Size = New System.Drawing.Size(184, 80)

Me.Button1.TabIndex = 0

Me.Button1.Text = "Class Timer"

'

'TextBox1

'

Me.TextBox1.Location = New System.Drawing.Point(136, 64)

Me.TextBox1.Name = "TextBox1"

Me.TextBox1.Size = New System.Drawing.Size(296, 20)

Me.TextBox1.TabIndex = 1

Me.TextBox1.Text = ""

'

'Label1

'

Me.Label1.Location = New System.Drawing.Point(56, 64)

Me.Label1.Name = "Label1"

Me.Label1.Size = New System.Drawing.Size(64, 16)

Me.Label1.TabIndex = 2

Me.Label1.Text = "Label1"

'

'Form1

'

Me.AutoScaleBaseSize = New System.Drawing.Size(5, 13)

Me.ClientSize = New System.Drawing.Size(808, 273)

Me.Controls.Add(Me.Label1)

Me.Controls.Add(Me.TextBox1)

Me.Controls.Add(Me.Button1)

Me.Name = "Form1"

Me.Text = "Form1"

Me.ResumeLayout(False)

End Sub

#End Region

Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles MyBase.Load

Me.Text = ""

'Déclare un timer de 500 ms

G_M_Timer = New Timer(500, 1)

AddHandler G_M_Timer.Callback, AddressOf G_M_Timer_Callback

End Sub

Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles Button1.Click

G_M_Timer.Start()

Label1.Text = "0"

End Sub

Private Sub G_M_Timer_Callback(ByVal sender As Object, ByVal e As
System.EventArgs)

Label1.Text = CInt(Label1.Text) + 1

If (Label1.Text = 10) Then

G_M_Timer.Stop()

End If

End Sub

End Class



'***

' Class Timer

Public Class Timer

Implements IDisposable

Private T_Resolution As UInt32

Private Shared m_tc As TIMECAPS

Private m_uDelay As UInt32

Private m_uResolution As UInt32

Private m_uTimerID As UInt32

Private m_delTimerCallback As LPTIMECALLBACK

Public Event Callback As EventHandler

#Region " Déclarations APIs "

<Flags()> _

Private Enum EVENTFLAG : UInt32

TIME_ONESHOT = &H0

TIME_PERIODIC = &H1

TIME_CALLBACK_FUNCTION = &H0

TIME_CALLBACK_EVENT_SET = &H10

TIME_CALLBACK_EVENT_PULSE = &H20

TIME_KILL_SYNCHRONOUS = &H100

End Enum

Private Delegate Sub LPTIMECALLBACK(ByVal uID As UInt32, _

ByVal uMsg As UInt32, _

ByVal dwUser As Int32, _

ByVal dw1 As Int32, _

ByVal dw2 As Int32)

<StructLayout(LayoutKind.Sequential)> _

Private Structure TIMECAPS

Private m_uPeriodMin As UInt32

Private m_uPeriodMax As UInt32

Public Sub New(ByVal uPeriodMin As UInt32, ByVal uPeriodMax As UInt32)

m_uPeriodMin = uPeriodMin

m_uPeriodMax = uPeriodMax

End Sub

Public ReadOnly Property PeriodMin() As UInt32

Get

Return m_uPeriodMin

End Get

End Property

Public ReadOnly Property PeriodMax() As UInt32

Get

Return m_uPeriodMax

End Get

End Property

End Structure



<DllImport("winmm.dll", SetLastError:=True)> _

Private Shared Function timeSetEvent( _

ByVal uDelay As UInt32, _

ByVal uResolution As UInt32, _

ByVal lpTimeProc As LPTIMECALLBACK, _

ByRef dwUser As Int32, _

ByVal fuEvent As EVENTFLAG) As UInt32

'

End Function

<DllImport("winmm.dll", SetLastError:=True)> _

Private Shared Function timeKillEvent( _

ByVal uTimerID As UInt32) As UInt32

'

End Function

<DllImport("winmm.dll", SetLastError:=True)> _

Private Shared Function timeGetDevCaps(ByRef lpTimeCaps As TIMECAPS, ByVal
uSize As UInt32) As UInt32

'

End Function

#End Region

#Region " Membres partagés "

Shared Sub New()

' Retrouve les résolutions (min et max)

' supportées par le timer système

timeGetDevCaps(m_tc,
BitConverter.ToUInt32(BitConverter.GetBytes(Marshal.SizeOf(m_tc)), 0))

Dim nErr As Int32 = Marshal.GetLastWin32Error()

If (nErr <> 0) Then

Throw New Win32Exception(nErr)

End If

End Sub

Public Shared ReadOnly Property MinimumResolution() As UInt32

Get

Return m_tc.PeriodMin

End Get

End Property

Public Shared ReadOnly Property MaximumResolution() As UInt32

Get

Return m_tc.PeriodMax

End Get

End Property

#End Region

Public Sub New(ByVal uDelay As UInt32, ByVal uResolution As UInt32)

m_uDelay = uDelay

m_uResolution = uResolution

End Sub

Public Sub New(ByVal dwDelay As Int32, ByVal dwResolution As Int32)

m_uDelay = Convert.ToUInt32(dwDelay)

m_uResolution = Convert.ToUInt32(dwResolution)

End Sub

Public ReadOnly Property Delay() As UInt32

Get

Return m_uDelay

End Get

End Property

Public ReadOnly Property Resolution() As UInt32

Get

Return m_uResolution

End Get

End Property

Public ReadOnly Property Started() As Boolean

Get

Return Convert.ToInt32(m_uTimerID) > 0

End Get

End Property

Public Sub Start()

If (Me.Started) Then

Throw New InvalidOperationException("Le timer est déjà en fonction.")

End If

If (m_delTimerCallback Is Nothing) Then

m_delTimerCallback = New LPTIMECALLBACK(AddressOf Me.TimeProc)

End If

m_uTimerID = timeSetEvent(m_uDelay, _

m_uResolution, _

m_delTimerCallback, _

0, _

EVENTFLAG.TIME_PERIODIC Or EVENTFLAG.TIME_KILL_SYNCHRONOUS)

Dim nErr As Int32 = Marshal.GetLastWin32Error()

If (nErr <> 0) Then

m_uTimerID = Convert.ToUInt32(0)

Throw New Win32Exception(nErr)

End If

End Sub

Public Sub [Stop]()

timeKillEvent(m_uTimerID)

m_uTimerID = Convert.ToUInt32(0)

End Sub

Public Sub Dispose() Implements System.IDisposable.Dispose

[Stop]()

m_delTimerCallback = Nothing

End Sub

Private Sub TimeProc(ByVal uID As UInt32, ByVal uMsg As UInt32, ByVal dwUser
As Int32, ByVal dw1 As Int32, ByVal dw2 As Int32)

RaiseEvent Callback(Me, New EventArgs)

End Sub

Protected Overrides Sub Finalize()

MyBase.Finalize()

Dispose()

End Sub

End Class


--
Pierre
"Thierry S" a écrit dans le message de
news:
Bonjour à tous,
J'utilise les timers Multimedia pour une meilleure précision.
Je n'ai aucun probleme sur mon poste de développement. Mais sur un autre
poste que je viens de faire, l'application ne fonctionne que sur un


certain
profil (profil A) et pas sur les autres.
Le profil A est utilisé pour installer Windows XP et tout ce qui suit.


J'ai
mis mes autres profils "Administrateur du poste" mais rien n'y fait. Voici


le
problème.
Quand je lance une 1ère foir le timer c'est OK mais si je veux le relancer
après, j'ai un message d'erreur "ID de contrôle introuvable"!!! Le


problème
se situe je pense au niveau de la fonction "timeSetEvent".
Meric pour votre aide car j'y perds mon latin! Je vais aller élever des
chèvres!!!
Bonne journée.


Avatar
Zoury
Salut Pierre ! :O)

Ça semble fonctionner ici, quelle est l'erreur ?

--
Cordialement
Yanick
MVP pour Visual Basic
"**Pierre**" a écrit dans le message de
news:
Bonjour,

Pourquoi ca ne fonctionne pas avec moi ? Voici le code comme le vôtre

Option Explicit On

Imports System.Runtime.InteropServices

Imports System.ComponentModel

Public Class Form1

Inherits System.Windows.Forms.Form

Private G_M_Timer As Timer

#Region " Code généré par le Concepteur Windows Form "

Public Sub New()

MyBase.New()

'Cet appel est requis par le Concepteur Windows Form.

InitializeComponent()

'Ajoutez une initialisation quelconque après l'appel InitializeComponent()

End Sub

'La méthode substituée Dispose du formulaire pour nettoyer la liste des
composants.

Protected Overloads Overrides Sub Dispose(ByVal disposing As Boolean)

If disposing Then

If Not (components Is Nothing) Then

components.Dispose()

End If

End If

MyBase.Dispose(disposing)

End Sub

'Requis par le Concepteur Windows Form

Private components As System.ComponentModel.IContainer

'REMARQUE : la procédure suivante est requise par le Concepteur Windows


Form

'Elle peut être modifiée en utilisant le Concepteur Windows Form.

'Ne la modifiez pas en utilisant l'éditeur de code.

Friend WithEvents Button1 As System.Windows.Forms.Button

Friend WithEvents TextBox1 As System.Windows.Forms.TextBox

Friend WithEvents Label1 As System.Windows.Forms.Label

<System.Diagnostics.DebuggerStepThrough()> Private Sub


InitializeComponent()

Me.Button1 = New System.Windows.Forms.Button

Me.TextBox1 = New System.Windows.Forms.TextBox

Me.Label1 = New System.Windows.Forms.Label

Me.SuspendLayout()

'

'Button1

'

Me.Button1.Location = New System.Drawing.Point(592, 176)

Me.Button1.Name = "Button1"

Me.Button1.Size = New System.Drawing.Size(184, 80)

Me.Button1.TabIndex = 0

Me.Button1.Text = "Class Timer"

'

'TextBox1

'

Me.TextBox1.Location = New System.Drawing.Point(136, 64)

Me.TextBox1.Name = "TextBox1"

Me.TextBox1.Size = New System.Drawing.Size(296, 20)

Me.TextBox1.TabIndex = 1

Me.TextBox1.Text = ""

'

'Label1

'

Me.Label1.Location = New System.Drawing.Point(56, 64)

Me.Label1.Name = "Label1"

Me.Label1.Size = New System.Drawing.Size(64, 16)

Me.Label1.TabIndex = 2

Me.Label1.Text = "Label1"

'

'Form1

'

Me.AutoScaleBaseSize = New System.Drawing.Size(5, 13)

Me.ClientSize = New System.Drawing.Size(808, 273)

Me.Controls.Add(Me.Label1)

Me.Controls.Add(Me.TextBox1)

Me.Controls.Add(Me.Button1)

Me.Name = "Form1"

Me.Text = "Form1"

Me.ResumeLayout(False)

End Sub

#End Region

Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles MyBase.Load

Me.Text = ""

'Déclare un timer de 500 ms

G_M_Timer = New Timer(500, 1)

AddHandler G_M_Timer.Callback, AddressOf G_M_Timer_Callback

End Sub

Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles Button1.Click

G_M_Timer.Start()

Label1.Text = "0"

End Sub

Private Sub G_M_Timer_Callback(ByVal sender As Object, ByVal e As
System.EventArgs)

Label1.Text = CInt(Label1.Text) + 1

If (Label1.Text = 10) Then

G_M_Timer.Stop()

End If

End Sub

End Class



'***

' Class Timer

Public Class Timer

Implements IDisposable

Private T_Resolution As UInt32

Private Shared m_tc As TIMECAPS

Private m_uDelay As UInt32

Private m_uResolution As UInt32

Private m_uTimerID As UInt32

Private m_delTimerCallback As LPTIMECALLBACK

Public Event Callback As EventHandler

#Region " Déclarations APIs "

<Flags()> _

Private Enum EVENTFLAG : UInt32

TIME_ONESHOT = &H0

TIME_PERIODIC = &H1

TIME_CALLBACK_FUNCTION = &H0

TIME_CALLBACK_EVENT_SET = &H10

TIME_CALLBACK_EVENT_PULSE = &H20

TIME_KILL_SYNCHRONOUS = &H100

End Enum

Private Delegate Sub LPTIMECALLBACK(ByVal uID As UInt32, _

ByVal uMsg As UInt32, _

ByVal dwUser As Int32, _

ByVal dw1 As Int32, _

ByVal dw2 As Int32)

<StructLayout(LayoutKind.Sequential)> _

Private Structure TIMECAPS

Private m_uPeriodMin As UInt32

Private m_uPeriodMax As UInt32

Public Sub New(ByVal uPeriodMin As UInt32, ByVal uPeriodMax As UInt32)

m_uPeriodMin = uPeriodMin

m_uPeriodMax = uPeriodMax

End Sub

Public ReadOnly Property PeriodMin() As UInt32

Get

Return m_uPeriodMin

End Get

End Property

Public ReadOnly Property PeriodMax() As UInt32

Get

Return m_uPeriodMax

End Get

End Property

End Structure



<DllImport("winmm.dll", SetLastError:=True)> _

Private Shared Function timeSetEvent( _

ByVal uDelay As UInt32, _

ByVal uResolution As UInt32, _

ByVal lpTimeProc As LPTIMECALLBACK, _

ByRef dwUser As Int32, _

ByVal fuEvent As EVENTFLAG) As UInt32

'

End Function

<DllImport("winmm.dll", SetLastError:=True)> _

Private Shared Function timeKillEvent( _

ByVal uTimerID As UInt32) As UInt32

'

End Function

<DllImport("winmm.dll", SetLastError:=True)> _

Private Shared Function timeGetDevCaps(ByRef lpTimeCaps As TIMECAPS, ByVal
uSize As UInt32) As UInt32

'

End Function

#End Region

#Region " Membres partagés "

Shared Sub New()

' Retrouve les résolutions (min et max)

' supportées par le timer système

timeGetDevCaps(m_tc,
BitConverter.ToUInt32(BitConverter.GetBytes(Marshal.SizeOf(m_tc)), 0))

Dim nErr As Int32 = Marshal.GetLastWin32Error()

If (nErr <> 0) Then

Throw New Win32Exception(nErr)

End If

End Sub

Public Shared ReadOnly Property MinimumResolution() As UInt32

Get

Return m_tc.PeriodMin

End Get

End Property

Public Shared ReadOnly Property MaximumResolution() As UInt32

Get

Return m_tc.PeriodMax

End Get

End Property

#End Region

Public Sub New(ByVal uDelay As UInt32, ByVal uResolution As UInt32)

m_uDelay = uDelay

m_uResolution = uResolution

End Sub

Public Sub New(ByVal dwDelay As Int32, ByVal dwResolution As Int32)

m_uDelay = Convert.ToUInt32(dwDelay)

m_uResolution = Convert.ToUInt32(dwResolution)

End Sub

Public ReadOnly Property Delay() As UInt32

Get

Return m_uDelay

End Get

End Property

Public ReadOnly Property Resolution() As UInt32

Get

Return m_uResolution

End Get

End Property

Public ReadOnly Property Started() As Boolean

Get

Return Convert.ToInt32(m_uTimerID) > 0

End Get

End Property

Public Sub Start()

If (Me.Started) Then

Throw New InvalidOperationException("Le timer est déjà en fonction.")

End If

If (m_delTimerCallback Is Nothing) Then

m_delTimerCallback = New LPTIMECALLBACK(AddressOf Me.TimeProc)

End If

m_uTimerID = timeSetEvent(m_uDelay, _

m_uResolution, _

m_delTimerCallback, _

0, _

EVENTFLAG.TIME_PERIODIC Or EVENTFLAG.TIME_KILL_SYNCHRONOUS)

Dim nErr As Int32 = Marshal.GetLastWin32Error()

If (nErr <> 0) Then

m_uTimerID = Convert.ToUInt32(0)

Throw New Win32Exception(nErr)

End If

End Sub

Public Sub [Stop]()

timeKillEvent(m_uTimerID)

m_uTimerID = Convert.ToUInt32(0)

End Sub

Public Sub Dispose() Implements System.IDisposable.Dispose

[Stop]()

m_delTimerCallback = Nothing

End Sub

Private Sub TimeProc(ByVal uID As UInt32, ByVal uMsg As UInt32, ByVal


dwUser
As Int32, ByVal dw1 As Int32, ByVal dw2 As Int32)

RaiseEvent Callback(Me, New EventArgs)

End Sub

Protected Overrides Sub Finalize()

MyBase.Finalize()

Dispose()

End Sub

End Class


--
Pierre
"Thierry S" a écrit dans le message


de
news:
> Bonjour à tous,
> J'utilise les timers Multimedia pour une meilleure précision.
> Je n'ai aucun probleme sur mon poste de développement. Mais sur un autre
> poste que je viens de faire, l'application ne fonctionne que sur un
certain
> profil (profil A) et pas sur les autres.
> Le profil A est utilisé pour installer Windows XP et tout ce qui suit.
J'ai
> mis mes autres profils "Administrateur du poste" mais rien n'y fait.


Voici
le
> problème.
> Quand je lance une 1ère foir le timer c'est OK mais si je veux le


relancer
> après, j'ai un message d'erreur "ID de contrôle introuvable"!!! Le
problème
> se situe je pense au niveau de la fonction "timeSetEvent".
> Meric pour votre aide car j'y perds mon latin! Je vais aller élever des
> chèvres!!!
> Bonne journée.




1 2