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.

2 réponses

1 2
Avatar
**Pierre**
Salut Zoury,

Lorsque je clique sur le boutton, il se plante et dit

Une exception non gérée du type 'System.ComponentModel.Win32Exception' s'est
produite dans WindowsApplication2.exe

Informations supplémentaires : ID de contrôle introuvable

Je fais quoi de faux :-)

--
Pierre
"Zoury" <yanick_lefebvre at hotmail dot com> a écrit dans le message de
news:euL0dY$
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.
>
>




Avatar
Zoury
Hmm.. j'obtiens également ce message, mais il ne m'a jamais empêché de
déclenché le timer. Je me suis rendu compte que ma gestion d'erreur lors de
l'appel de timeSetEvent était incorrecte. Si on se fie à ce que la MSDN dit
à ce sujet, il faudrait vérifier l'erreur système que lorsque NULL est
retourné par la fonction (soit 0 dans notre cas). Étrangement,
Marshal.GetLastWin32Error() me retourne toujours une valeur suite à l'appel
de timeSetEvent(), soit 6 (Descripteur non valide) le premier coup et 1421
(ID de contrôle introuvable) les fois suivantes.. je n'ai trouvé aucune
information utile à ce sujet.

En vérifiant l'erreur seulement si m_uTimerID est à 0 (comme mentionné dans
la MSDN), on évite de levée une exception "inutile" :
'***
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)

Console.WriteLine("timeSetEvent == {0}", m_uTimerID.ToString())
If (m_uTimerID.Equals(Convert.ToUInt32(0))) Then
Console.WriteLine(New
Win32Exception(Marshal.GetLastWin32Error()).ToString())
End If

End Sub

Public Sub [Stop]()
Console.WriteLine("timeKillEvent({0}) == {1}",
m_uTimerID.ToString(), timeKillEvent(m_uTimerID).ToString())
m_uTimerID = Convert.ToUInt32(0)
End Sub
'***

Autre note :
en employant les flags EVENTFLAG.TIME_PERIODIC Or
EVENTFLAG.TIME_KILL_SYNCHRONOUS, la fonction killTimeEvent() finie par
bloquer le reste de l'exécution (elle "hang") lorsque je clique à répétition
sur le bouton déclenchant/stoppant le timer. En enlevant le flag
EVENTFLAG.TIME_KILL_SYNCHRONOUS, le problème disparait. Il s'agit peut-être
d'un bug ou d'une erreur de manipulation de ma part..

--
Cordialement
Yanick
MVP pour Visual Basic
1 2