2010-11-05 5 views
2

En essayant d'utiliser un mouvement d'agitation pour effacer le contenu d'un inkpresenter, le fait de trembler ne fait qu'écraser mon application. Voici le code:Problèmes d'accéléromètre dans WP7

public class ShakeDetect 
{ 
    private Accelerometer _accelerometer = null; 
    object SyncRoot = new object(); 
    private int _minimumShakes; 
    ShakeRecord[] _shakeRecordList; 
    private int _shakeRecordIndex = 0; 
    private const double MinimumAccelerationMagnitude = 1.2; 
    private const double MinimumAccelerationMagnitudeSquared = MinimumAccelerationMagnitude * MinimumAccelerationMagnitude; 
    private static readonly TimeSpan MinimumShakeTime = TimeSpan.FromMilliseconds(500); 

    public event EventHandler<EventArgs> ShakeEvent = null; 


    protected void OnShakeEvent() 
    { 
     if (ShakeEvent != null) 
     { 
      ShakeEvent(this, new EventArgs()); 
     } 
    } 



    [Flags] 
    public enum Direction 
    { 
     None = 0, 
     North = 1, 
     South = 2, 
     East = 8, 
     West = 4, 
     NorthWest = North | West, 
     SouthWest = South | West, 
     SouthEast = South | East, 
     NorthEast = North | East 
    } ; 

    public struct ShakeRecord 
    { 
     public Direction ShakeDirection; 
     public DateTime EventTime; 
    } 


    public ShakeDetect() 
     : this(2) 
    { 

    } 
    public ShakeDetect(int minShakes) 
    { 
     _minimumShakes = minShakes; 
     _shakeRecordList = new ShakeRecord[minShakes]; 
    } 

    public void Start() 
    { 
     lock (SyncRoot) 
     { 
      if (_accelerometer == null) 
      { 
       _accelerometer = new Accelerometer(); 
       _accelerometer.ReadingChanged += new EventHandler<AccelerometerReadingEventArgs>(_accelerometer_ReadingChanged); 
       _accelerometer.Start(); 
      } 
     } 
    } 

    public void Stop() 
    { 
     lock (SyncRoot) 
     { 
      if (_accelerometer != null) 
      { 
       _accelerometer.Stop(); 
       _accelerometer.ReadingChanged -= _accelerometer_ReadingChanged; 
       _accelerometer = null; 
      } 
     } 
    } 

    Direction DegreesToDirection(double direction) 
    { 
     if ((direction >= 337.5) || (direction <= 22.5)) 
      return Direction.North; 
     if ((direction <= 67.5)) 
      return Direction.NorthEast; 
     if (direction <= 112.5) 
      return Direction.East; 
     if (direction <= 157.5) 
      return Direction.SouthEast; 
     if (direction <= 202.5) 
      return Direction.South; 
     if (direction <= 247.5) 
      return Direction.SouthWest; 
     if (direction <= 292.5) 
      return Direction.West; 
     return Direction.NorthWest; 
    } 

    void CheckForShakes() 
    { 
     int startIndex = (_shakeRecordIndex - 1); 
     if (startIndex < 0) startIndex = _minimumShakes - 1; 
     int endIndex = _shakeRecordIndex; 

     if ((_shakeRecordList[endIndex].EventTime.Subtract(_shakeRecordList[startIndex].EventTime)) <= MinimumShakeTime) 
     { 
      OnShakeEvent(); 
     } 
    } 
    void _accelerometer_ReadingChanged(object sender, AccelerometerReadingEventArgs e) 
    { 

     if ((e.X * e.X + e.Y * e.Y) > MinimumAccelerationMagnitudeSquared) 
     { 

      double degrees = 180.0 * Math.Atan2(e.Y, e.X)/Math.PI; 
      Direction direction = DegreesToDirection(degrees); 


      if ((direction & _shakeRecordList[_shakeRecordIndex].ShakeDirection) != Direction.None) 
       return; 
      ShakeRecord record = new ShakeRecord(); 
      record.EventTime = DateTime.Now; 
      record.ShakeDirection = direction; 
      _shakeRecordIndex = (_shakeRecordIndex + 1) % _minimumShakes; 
      _shakeRecordList[_shakeRecordIndex] = record; 

      CheckForShakes(); 

     } 
    } 

} 

Et puis dans mon application, je l'utilise:

 private ShakeDetect _shakeDecetor; 

    // Constructor 
    public MainPage() 
    { 
     InitializeComponent(); 
     _shakeDecetor = new ShakeDetect(); 
     _shakeDecetor.ShakeEvent += new EventHandler<EventArgs>(_shakeDetect_ShakeEvent); 
     _shakeDecetor.Start(); 

Enfin, lorsque la secousse est détectée:

void _shakeDetect_ShakeEvent(object sender, EventArgs e) 
    { 
     CanvasIP.Strokes.Clear(); 
     CanvasIP.Background = new SolidColorBrush(Colors.Black); 
    } 

Je devine que le problème est quelque part dans ma classe ShakeDetect ou dans ShakeEvent.

Ok donc de l'avis de Hans mon code devrait être:

void _shakeDetect_ShakeEvent(object sender, EventArgs e) 
    { 
     this.Dispatcher.BeginInvoke(() => 
      { 
       CanvasIP.Strokes.Clear(); 
       CanvasIP.Background = new SolidColorBrush(Colors.Black); 
      }); 
    } 

Est-ce exact maintenant?

+0

Avez-vous une exception? Si oui, quelle exception? Où lance-t-il? – ctacke

+0

Je n'ai pas d'appareil pour tester ça, malheureusement. Je pensais que tout fonctionnait, mais les tests ont échoué. Il n'y a vraiment pas de moyen facile de tester cela dans l'émulateur. – BigPete

Répondre

4

L'événement ReadingChanged est déclenché sur un autre thread. Vous pouvez pas toucher les composants de l'interface utilisateur directement, vous devez rassembler un rappel au thread principal. Utilisez Dispatcher.BeginInvoke(), il est bien décrit dans ce MSDN library article.

+0

Je vais vérifier cela. – BigPete

+0

Je pense que je l'ai eu ... Pourriez-vous vérifier mon code édité? – BigPete

+2

J'ai secoué mon ordinateur portable et il ne s'est pas écrasé. Bon signe :) –