IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

C# Discussion :

"Slider" Lecteur multimedia


Sujet :

C#

  1. #1
    Membre du Club
    Profil pro
    Inscrit en
    Mai 2011
    Messages
    79
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2011
    Messages : 79
    Points : 46
    Points
    46
    Par défaut "Slider" Lecteur multimedia
    Bonjour,

    je dois faire un lecteur multimedia dans un cours à l'école. J'ai un petit problème avec ma barre de temps qui suit la vidéo. J'utilise un dispatcher timer pour synchroniser ma petite barre avec ma vidéo, cependant étant donné que je change la valeur de la barre, la fonction _ValueChanged est appelé et mon vidéo a donc de petit "Lag". Voici mon code pour mieux me comprendre.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    private void dispatcherTimer_Tick(object sender, EventArgs e)
            {
                timeSlider.Value = mediaElement1.Position.TotalMilliseconds;            
            }
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    private void timeSlider_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
            {
                int sliderValue = (int)timeSlider.Value;
                TimeSpan ts = new TimeSpan(0, 0, 0, 0, sliderValue);
                mediaElement1.Position = ts;            
            }
    Donc lorsque mon timer "Tick" il synchronise la barre avec la vidéo. Par la suite il appelle timeSlider_ValueChanged parce que ma valeur à changé et il synchronise par la suite la vidéo avec la barre. Donc parfois cela crée de petit "Lag".

    Quelqu'un aurait des suggestions pour régler ce conflit?

    Edit: Je travaille avec Visual Studio 2010

  2. #2
    Expert éminent sénior Avatar de Pol63
    Homme Profil pro
    .NET / SQL SERVER
    Inscrit en
    Avril 2007
    Messages
    14 154
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Puy de Dôme (Auvergne)

    Informations professionnelles :
    Activité : .NET / SQL SERVER

    Informations forums :
    Inscription : Avril 2007
    Messages : 14 154
    Points : 25 072
    Points
    25 072
    Par défaut
    forcément, tu change la valeur du slide, et tu dis que la valeur du slide change tu modifies la vidéo
    ce qu'il te faut en fait c'est "quand l'utilisateur change la valeur du slide" et pas ton code

    tu peux te créer un booléen qui permet de savoir si la modification vient de toi

    timer_tick
    {
    modifier slide.Value
    set bool à true
    }

    slide_changed
    {
    si bool => set bool à false et sortir
    modifier vidéo}


    cependant ca reste moyen, ca suppose qu'il ne se passe rien entre les 2 méthodes


    tu peux aussi utiliser l'évènement click plutot que valuechanged ; mais là aussi y a un défaut, ca ne gère plus le clavier en cas de focus sur le slider
    Cours complets, tutos et autres FAQ ici : C# - VB.NET

  3. #3
    Rédacteur/Modérateur


    Homme Profil pro
    Développeur .NET
    Inscrit en
    Février 2004
    Messages
    19 875
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Février 2004
    Messages : 19 875
    Points : 39 749
    Points
    39 749
    Par défaut
    J'aurais fais à peu près comme Pol63, mais avec une petite différence : j'aurais plutôt remis le flag à false au niveau du timer (mais bon, en pratique ça doit pas changer grand chose...)



    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
            bool _changingSliderFromTimer;
     
            private void dispatcherTimer_Tick(object sender, EventArgs e)
            {
                _changingSliderFromTimer = true;
                timeSlider.Value = mediaElement1.Position.TotalMilliseconds;            
                _changingSliderFromTimer = false;
            }
     
            private void timeSlider_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
            {
                if (_changingSliderFromTimer)
                    return;
                int sliderValue = (int)timeSlider.Value;
                TimeSpan ts = new TimeSpan(0, 0, 0, 0, sliderValue);
                mediaElement1.Position = ts;            
            }

  4. #4
    Expert éminent sénior Avatar de Pol63
    Homme Profil pro
    .NET / SQL SERVER
    Inscrit en
    Avril 2007
    Messages
    14 154
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Puy de Dôme (Auvergne)

    Informations professionnelles :
    Activité : .NET / SQL SERVER

    Informations forums :
    Inscription : Avril 2007
    Messages : 14 154
    Points : 25 072
    Points
    25 072
    Par défaut
    c'est vrai que l'event doit être déclenché pendant le changement de valeur (s'il est mis sur la pile c'est moins drôle ^^)
    Cours complets, tutos et autres FAQ ici : C# - VB.NET

  5. #5
    Expert confirmé
    Inscrit en
    Avril 2008
    Messages
    2 564
    Détails du profil
    Informations personnelles :
    Âge : 64

    Informations forums :
    Inscription : Avril 2008
    Messages : 2 564
    Points : 4 441
    Points
    4 441
    Par défaut mediaelement et maj position du slider
    bonjour joce21
    Pourquoi passer par un timer et un dispatcherTimer alors que l'api WPF dispose dispose du MediaTimeLine et d'une horloge ad hoc utilisable par un MediaElement
    De plus le "clock" du MediaElement dispose d'un controller pour l'interactivite.

    Comme l'illustre le bout de code suivant:
    code xaml du WinForm
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
     
    <Window x:Class="WpfMediaPlayerCSharp.Window1"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="Window1" Height="300" Width="300">
        <DockPanel>
            <Grid DockPanel.Dock="Bottom">
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="*" />
                    <ColumnDefinition Width="*" />
                    <ColumnDefinition Width="*" />
                    <ColumnDefinition Width="*" />
                    <ColumnDefinition Width="*" />
                    <ColumnDefinition Width="*" />
                    <ColumnDefinition Width="*" />
                </Grid.ColumnDefinitions>
                <Button 
                    Grid.Column="2"
                    Content="Stop"
                    Click="Stop_Click" />
                <Button 
                    Grid.Column="3"
                    Content="Play"
                    Click="Play_Click" />
                <ToggleButton 
                    Grid.Column="4"
                    Content="Mute"
                    IsChecked="{Binding ElementName=mediaElement,
                    Path=IsMuted}" />
                <Slider 
                    Grid.Column="5"
                    Minimum="0"
                    Maximum="1"
                    Value="{Binding ElementName=mediaElement, Path=Volume}"/>
            </Grid>
            <Slider 
                x:Name="progressSlider"
                DockPanel.Dock="Bottom"
                Minimum="0"
                LargeChange="1000"
                PreviewMouseLeftButtonDown="progressSlider_MouseDown"
                PreviewMouseLeftButtonUp="progressSlider_MouseUp"/>
            <MediaElement 
                x:Name="mediaElement"
                DockPanel.Dock="Top"
                Source="Resources\Bear.wmv"
                LoadedBehavior="Manual"
                MediaOpened="mediaElement_MediaOpened"
                MediaEnded="mediaElement_MediaEnded"/>
        </DockPanel>
    </Window>
    code behind du winform:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
     
    //1-Affecter l'horloge de la chronologie du MediaTimeLine au MediaElement
    //2-S'abonner à l'evenement clock.CurrentTimeInvalidated de l'horloge
    // pour mettre à jour la position du bouton slider
    //3-Horloge dispose du controller qui permet de :
    //- demarrer ,suspendre,reprendre interactivement  la lectur du MediaMediaElement
     
    using System;
    using System.Windows;
    using System.Windows.Controls;
    using System.Windows.Input;
    using System.Windows.Media;
    using System.Windows.Media.Animation;
    using System.Windows.Media.Imaging;
    using System.Windows.Navigation;
    using System.Windows.Shapes;
    namespace WpfMediaPlayerCSharp
    {
        /// <summary>
        /// Logique d'interaction pour Window1.xaml
        /// </summary>
        public partial class Window1 : Window
        {
            private bool _userMovingSlider ;
            public Window1()
            {
                InitializeComponent();
            }
     
            private void mediaElement_MediaOpened(object sender, RoutedEventArgs e)
            {
                //A l'ouverture du media fixer  valeur max bouton slider  
                this.progressSlider.Maximum = 
                    this.mediaElement.NaturalDuration.TimeSpan.TotalMilliseconds;
            }
            private void Play_Click(object sender, RoutedEventArgs e)
            {
     
                MediaClock clock=this.mediaElement.Clock;
                //un media est en cours de lecture
                if (clock !=null) 
                {
                    if (clock.IsPaused) 
                    {
                        clock.Controller.Resume();
                    }
                    else
                    {
                        clock.Controller.Pause();
                    }
                }
                else //sinon
                {
                    //aucun fichier charge =>return
                    if (this.mediaElement == null) return;
     
                    //sinon nouveau media => initialiser creer un MediaTimeline 
                    //=> affecter son horloge au MediaElement
                    //=> s'abonner à event horloge
                    MediaTimeline timeline = new MediaTimeline(this.mediaElement.Source);
                    clock = timeline.CreateClock();
     
                    clock.CurrentTimeInvalidated += new EventHandler(Clock_CurrentTimeInvalidated);
                    this.mediaElement.Clock = clock;
                }
            }
            private void Stop_Click(object sender, RoutedEventArgs e)
            {
                //mettre horloge à null
                this.mediaElement.Clock = null;
            }
            private void mediaElement_MediaEnded(object sender, RoutedEventArgs e)
            {
                //mettre horloge à null
                this.mediaElement.Clock = null;
            }
            private void Clock_CurrentTimeInvalidated(object sender, EventArgs e)
            {
                //si horloge null(aucun media en cours)
                //ou user deplace bouton slider =>return
     
                if (this.mediaElement.Clock == null || _userMovingSlider) return;
                //sinon mise à jour position du slider
                this.progressSlider.Value = 
                this.mediaElement.Clock.CurrentTime.Value.TotalMilliseconds;
     
            }
     
            private void progressSlider_MouseDown(object sender, MouseButtonEventArgs e)
            {
                //user deplace bouton slider
                _userMovingSlider = true;
            }
     
            private void progressSlider_MouseUp(object sender, MouseButtonEventArgs e)
            { 
     
                MediaClock clock=this.mediaElement.Clock;
                //user a deplace puis relache bouton slider
                //mais horloge non nulle(un media en cours de lecture)
                //avancer horloger  à la position du slider
                if (clock !=null)
                    {  
                      TimeSpan m_offset= TimeSpan.FromMilliseconds(this.progressSlider.Value);
                      clock.Controller.Seek(m_offset, TimeSeekOrigin.BeginTime);
                    }
                //prepare prochaine interaction user
                _userMovingSlider = false;
            }
     
     
        }
    }
    bon code..........

  6. #6
    Rédacteur/Modérateur


    Homme Profil pro
    Développeur .NET
    Inscrit en
    Février 2004
    Messages
    19 875
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Février 2004
    Messages : 19 875
    Points : 39 749
    Points
    39 749
    Par défaut
    Citation Envoyé par MABROUKI Voir le message
    code behind du winform:
    Les habitudes ont la vie dure

  7. #7
    Membre du Club
    Profil pro
    Inscrit en
    Mai 2011
    Messages
    79
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2011
    Messages : 79
    Points : 46
    Points
    46
    Par défaut
    Citation Envoyé par MABROUKI Voir le message
    bonjour joce21
    Pourquoi passer par un timer et un dispatcherTimer alors que l'api WPF dispose dispose du MediaTimeLine et d'une horloge ad hoc utilisable par un MediaElement
    De plus le "clock" du MediaElement dispose d'un controller pour l'interactivite.

    Comme l'illustre le bout de code suivant:
    code xaml du WinForm
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
     
    <Window x:Class="WpfMediaPlayerCSharp.Window1"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="Window1" Height="300" Width="300">
        <DockPanel>
            <Grid DockPanel.Dock="Bottom">
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="*" />
                    <ColumnDefinition Width="*" />
                    <ColumnDefinition Width="*" />
                    <ColumnDefinition Width="*" />
                    <ColumnDefinition Width="*" />
                    <ColumnDefinition Width="*" />
                    <ColumnDefinition Width="*" />
                </Grid.ColumnDefinitions>
                <Button 
                    Grid.Column="2"
                    Content="Stop"
                    Click="Stop_Click" />
                <Button 
                    Grid.Column="3"
                    Content="Play"
                    Click="Play_Click" />
                <ToggleButton 
                    Grid.Column="4"
                    Content="Mute"
                    IsChecked="{Binding ElementName=mediaElement,
                    Path=IsMuted}" />
                <Slider 
                    Grid.Column="5"
                    Minimum="0"
                    Maximum="1"
                    Value="{Binding ElementName=mediaElement, Path=Volume}"/>
            </Grid>
            <Slider 
                x:Name="progressSlider"
                DockPanel.Dock="Bottom"
                Minimum="0"
                LargeChange="1000"
                PreviewMouseLeftButtonDown="progressSlider_MouseDown"
                PreviewMouseLeftButtonUp="progressSlider_MouseUp"/>
            <MediaElement 
                x:Name="mediaElement"
                DockPanel.Dock="Top"
                Source="Resources\Bear.wmv"
                LoadedBehavior="Manual"
                MediaOpened="mediaElement_MediaOpened"
                MediaEnded="mediaElement_MediaEnded"/>
        </DockPanel>
    </Window>
    code behind du winform:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
     
    //1-Affecter l'horloge de la chronologie du MediaTimeLine au MediaElement
    //2-S'abonner à l'evenement clock.CurrentTimeInvalidated de l'horloge
    // pour mettre à jour la position du bouton slider
    //3-Horloge dispose du controller qui permet de :
    //- demarrer ,suspendre,reprendre interactivement  la lectur du MediaMediaElement
     
    using System;
    using System.Windows;
    using System.Windows.Controls;
    using System.Windows.Input;
    using System.Windows.Media;
    using System.Windows.Media.Animation;
    using System.Windows.Media.Imaging;
    using System.Windows.Navigation;
    using System.Windows.Shapes;
    namespace WpfMediaPlayerCSharp
    {
        /// <summary>
        /// Logique d'interaction pour Window1.xaml
        /// </summary>
        public partial class Window1 : Window
        {
            private bool _userMovingSlider ;
            public Window1()
            {
                InitializeComponent();
            }
     
            private void mediaElement_MediaOpened(object sender, RoutedEventArgs e)
            {
                //A l'ouverture du media fixer  valeur max bouton slider  
                this.progressSlider.Maximum = 
                    this.mediaElement.NaturalDuration.TimeSpan.TotalMilliseconds;
            }
            private void Play_Click(object sender, RoutedEventArgs e)
            {
     
                MediaClock clock=this.mediaElement.Clock;
                //un media est en cours de lecture
                if (clock !=null) 
                {
                    if (clock.IsPaused) 
                    {
                        clock.Controller.Resume();
                    }
                    else
                    {
                        clock.Controller.Pause();
                    }
                }
                else //sinon
                {
                    //aucun fichier charge =>return
                    if (this.mediaElement == null) return;
     
                    //sinon nouveau media => initialiser creer un MediaTimeline 
                    //=> affecter son horloge au MediaElement
                    //=> s'abonner à event horloge
                    MediaTimeline timeline = new MediaTimeline(this.mediaElement.Source);
                    clock = timeline.CreateClock();
     
                    clock.CurrentTimeInvalidated += new EventHandler(Clock_CurrentTimeInvalidated);
                    this.mediaElement.Clock = clock;
                }
            }
            private void Stop_Click(object sender, RoutedEventArgs e)
            {
                //mettre horloge à null
                this.mediaElement.Clock = null;
            }
            private void mediaElement_MediaEnded(object sender, RoutedEventArgs e)
            {
                //mettre horloge à null
                this.mediaElement.Clock = null;
            }
            private void Clock_CurrentTimeInvalidated(object sender, EventArgs e)
            {
                //si horloge null(aucun media en cours)
                //ou user deplace bouton slider =>return
     
                if (this.mediaElement.Clock == null || _userMovingSlider) return;
                //sinon mise à jour position du slider
                this.progressSlider.Value = 
                this.mediaElement.Clock.CurrentTime.Value.TotalMilliseconds;
     
            }
     
            private void progressSlider_MouseDown(object sender, MouseButtonEventArgs e)
            {
                //user deplace bouton slider
                _userMovingSlider = true;
            }
     
            private void progressSlider_MouseUp(object sender, MouseButtonEventArgs e)
            { 
     
                MediaClock clock=this.mediaElement.Clock;
                //user a deplace puis relache bouton slider
                //mais horloge non nulle(un media en cours de lecture)
                //avancer horloger  à la position du slider
                if (clock !=null)
                    {  
                      TimeSpan m_offset= TimeSpan.FromMilliseconds(this.progressSlider.Value);
                      clock.Controller.Seek(m_offset, TimeSeekOrigin.BeginTime);
                    }
                //prepare prochaine interaction user
                _userMovingSlider = false;
            }
     
     
        }
    }
    bon code..........
    Merci beaucoup, je n'avais pas connaissance de ce clock en question.

    Cependant, je ne comprends la différence entre PreviewMouseDown et MouseDown. Quelqu'un pourrait m'éclairer?

  8. #8
    Expert éminent sénior Avatar de Pol63
    Homme Profil pro
    .NET / SQL SERVER
    Inscrit en
    Avril 2007
    Messages
    14 154
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Puy de Dôme (Auvergne)

    Informations professionnelles :
    Activité : .NET / SQL SERVER

    Informations forums :
    Inscription : Avril 2007
    Messages : 14 154
    Points : 25 072
    Points
    25 072
    Par défaut
    preview c'est avant ^^

    en fait en wpf, vu qu'il y a un arbre de controles, un évènement est déclenché dans un sens en preview puis dans l'autre en normal

    par exemple si tu as un controle bouton avec un controle image dedans
    cliquer sur l'image va déclencher preview sur le bouton puis sur l'image, puis déclencher l'évènement normal sur l'image et enfin sur le bouton
    pour le sens je suis pas sûr, et tout l'arbre est pris en compte (il y a en général un grid et une window)

    dans les event preview (et peut etre même aussi les normaux) il est possible d'annuler la chaine
    Cours complets, tutos et autres FAQ ici : C# - VB.NET

  9. #9
    Membre du Club
    Profil pro
    Inscrit en
    Mai 2011
    Messages
    79
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2011
    Messages : 79
    Points : 46
    Points
    46
    Par défaut
    Merci Pol63!

    J'aurais une autre question. J'ai un autre dispatcher timer qui réduit l'opacité d'un image pour faire un effet d'estompage. Donc à chaque tick je fais ceci:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    recMiddle1.Opacity -= 0.1;
    Cependant, lorsque je roule mon application, l'opacité n'arrive pas à atteindre le 0. Voici ce que ma console m'affiche pour la valeur de l'opacité de recMiddle1 à chaque tick:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    0,9
    0,8
    0,7
    0,6
    0,5
    0,4
    0,3
    0,2
    0,1
    1,38777878078145E-16
    -0,0999999999999999
    -0,0999999999999999
    Le thread '<Sans nom>' (0x1f28) s'est arrêté avec le code 0 (0x0).
    Le thread '<Sans nom>' (0xb1c) s'est arrêté avec le code 0 (0x0).
    Le thread '<Sans nom>' (0x1ec8) s'est arrêté avec le code 0 (0x0).
    Comment 0.1 - 0.1 peut donner 1,38777878078145E-16.

    J'ai chercher et je n'ai pas trouvé de réponse.

  10. #10
    Expert éminent sénior Avatar de Pol63
    Homme Profil pro
    .NET / SQL SERVER
    Inscrit en
    Avril 2007
    Messages
    14 154
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Puy de Dôme (Auvergne)

    Informations professionnelles :
    Activité : .NET / SQL SERVER

    Informations forums :
    Inscription : Avril 2007
    Messages : 14 154
    Points : 25 072
    Points
    25 072
    Par défaut
    surement parce que c'est un double (qui est stocké sous forme de puissance de 2, et donc une approximation)
    arrivé à .1 fait un set à 0 plutot que -.1

    et sinon tu peux faire avec une animation aussi, from 1 to 0 sur tant de temps, ca t'évitera de taper du code d'interface hors du xaml (peu recommandé en wpf)
    Cours complets, tutos et autres FAQ ici : C# - VB.NET

  11. #11
    Expert confirmé
    Inscrit en
    Avril 2008
    Messages
    2 564
    Détails du profil
    Informations personnelles :
    Âge : 64

    Informations forums :
    Inscription : Avril 2008
    Messages : 2 564
    Points : 4 441
    Points
    4 441
    Par défaut event preview=event descendant ,event normal =du control remonte vers racine
    bonjour joce21
    voici un petit resume comme l'as dit Pol63 de la difference entre un event normal et un event preview.
    1/tous les controls wpf possedent :
    -un event normal de type Input :mousedown,keydown...
    -et un event counter-part ou "contrepartie" : previewmousedown et previewkeydown.
    2/Un preview event est declenche en premier par la racine et descend sur le controle qui a le focus et qui a ete actionne(mouse ou keyboard ).=> tunneling ou descente de l'event depuis la racine vers le controle .

    2/Suivi de l'event normal qui est ensuite declenche par le control qui a le focus =>ensuite bubbling ou remonte depuis le controle vers la racine.
    Conclusion pratique :
    -quand on declenche un event de type input il y une contrepartie preview et vice-versa.
    -le preview est genere "avant" dans le temps et dans "l'espace" car les controles parents le voient "descendre" avant le control qui a genere l'action.
    -exactement le contraire pour l'event normal qui survient apres et vu par les childs avant les parents
    exemple dans la douce langue de shakeaspeare donnee par un auteur de code:

    When you press a key with an element in focus, first the PreviewKeyDown event is
    raised by the root element and tunnels down the tree to the actual element that was
    in focus; then the KeyDown event is raised and bubbles back up to the root.
    bon code...........

  12. #12
    Membre du Club
    Profil pro
    Inscrit en
    Mai 2011
    Messages
    79
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2011
    Messages : 79
    Points : 46
    Points
    46
    Par défaut
    Merci beaucoup, ça m'éclair énormément.

    Désolé de poser beaucoup de question, je suis nouveau en C# et j'essaie de comprendre comment tout cela fonctionne. J'essaie de faire des boutons qui change d'image lorsque mouseOver et mouseDown, etc... J'ai donc fait cela dans mon app.xaml:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    <Application x:Class="TestBouton.App"
                 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                 StartupUri="MainWindow.xaml">
        <Application.Resources>
            <!-- Les ressources réparties au niveau Application sont définies ici. -->
            <Style x:Key="ButtonStyle1" TargetType="{x:Type Button}">
                <Setter Property="Template">
                    <Setter.Value>
                        <ControlTemplate TargetType="{x:Type Button}">
                            <Grid>
                                <Image x:Name="image" Source="Images\PlayerPlay.png" Stretch="Fill"/>
                                <ContentPresenter HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" RecognizesAccessKey="True" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
                            </Grid>
                            <ControlTemplate.Triggers>
                                <Trigger Property="IsFocused" Value="True"/>
                                <Trigger Property="IsDefaulted" Value="True"/>
                                <Trigger Property="IsMouseOver" Value="True">
                                    <Setter Property="Source" TargetName="image" Value="PlayerPlayOver.png"/>
                                </Trigger>
                                <Trigger Property="IsPressed" Value="True">
                                    <Setter Property="Source" TargetName="image" Value="PLayerPlayDown.png"/>
                                </Trigger>
                                <Trigger Property="IsEnabled" Value="False"/>
                            </ControlTemplate.Triggers>
                        </ControlTemplate>
                    </Setter.Value>
                </Setter>
            </Style>
        </Application.Resources>
    </Application>
    Et par la suite, je me suis fait un bouton dans mon MainWindow juste pour tester si mon bouton fonctionne:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    <Window x:Class="TestBouton.MainWindow"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            Title="MainWindow" mc:Ignorable="d" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" Height="350" Width="525">
        <Grid>
            <Button Content="Button" Height="71" HorizontalAlignment="Left" Margin="294,130,0,0" Name="button1" VerticalAlignment="Top" Width="76" Style="{DynamicResource ButtonStyle1}" />
        </Grid>
    </Window>
    Mais lorsque j'essaie de lancer l'application j'obtient cette exception que je ne n'arrive pas à résoudre:

    'La valeur fournie sur 'System.Windows.Baml2006.TypeConverterMarkupExtension' a levé une exception.' numéro de ligne '19' et position de ligne '34'.
    Avec ceci en surligné:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    <Window x:Class="TestBouton.MainWindow"

  13. #13
    Expert confirmé
    Inscrit en
    Avril 2008
    Messages
    2 564
    Détails du profil
    Informations personnelles :
    Âge : 64

    Informations forums :
    Inscription : Avril 2008
    Messages : 2 564
    Points : 4 441
    Points
    4 441
    Par défaut
    bonjour joce21
    'La valeur fournie sur 'System.Windows.Baml2006.' a levé une exception.' numéro de ligne '19' et position de ligne '34'
    Tres bizarre car en reprenant le code communique par toi il s'execute à merveille chez moi.
    Ce genre de message sur le xaml indique probablement une erreur de frappe .
    Verifie ton namespace et ton nom de fenetre s'ils sont tapes correctement dans les fichiers:
    -MainWindow.xaml
    -MainWindow.xaml.cs
    -Application.xaml
    -Application.xaml.cs
    Verifie egalement si pour chaque fichier image:
    -proprietes->action de generation = Resource

    bon code.................

  14. #14
    Membre du Club
    Profil pro
    Inscrit en
    Mai 2011
    Messages
    79
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2011
    Messages : 79
    Points : 46
    Points
    46
    Par défaut
    Merci Mabrouki,

    j'ai remarqué que la source de mes images étaient PlayerPlay...png aulieu de Images\PlayerPlay...png. Maintenant tout fonctionne!!! Merci encore pour votre aide!

+ Répondre à la discussion
Cette discussion est résolue.

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo