"Microsoft Blend"-like continuous Drag - wpf

Microsoft Blend allows changing numeric values of properties like Left, Top etc. through continuous drag. User clicks in the property value box, keeps the button down and drags left or right to decrease/increase the value. Simple.
The special thing about it is that if cursor reaches the left or right end of the screen and user still wants to drag more, they can continue dragging and the cursor will start over from the other end of the screen.
I'm trying to do this in one of my WPF applications using Thumb control. Using DragDetla event, if I find that the Thumb has reach the edge of the screen, I set its position to the far end. But this makes the value of e.HorizontalChange as big as the width of entire screen. How can I change Thumb's position during drag without affecting horizontal change value?

I have realized this in a WPF control by using a textbox and subscribing to events such as:
PreviewMouseDown
MouseUp and
MouseMove
MouseEnter
The drag until you reach screen limits requires a mouse capture or call to CaptureMouse method available on any UIElement. On the other side, you need to release the mouse at some point which requires a call of the ReleaseMouseCapture method. The solution could go like this:
Declare an enumeration to model the drag direction
internal enum MouseDirections
{
None,
LeftRight,
UpDown
}
Declare a class to keep trak of mouse origin (first location) and current location:
internal class MouseIncrementor
{
private MouseDirections _enumMouseDirection = MouseDirections.None;
private Point _objPoint;
private readonly Point _initialPoint;
public MouseIncrementor(Point objPoint, MouseDirections enumMouseDirection)
{
_objPoint = objPoint;
_initialPoint = _objPoint;
_enumMouseDirection = enumMouseDirection;
}
public MouseDirections MouseDirection
{
get
{
return _enumMouseDirection;
}
protected set
{
_enumMouseDirection = value;
}
}
public Point InitialPoint
{
get
{
return _initialPoint;
}
}
public Point Point
{
get
{
return _objPoint;
}
set
{
_objPoint = value;
}
}
internal MouseDirections SetMouseDirection(Point pos)
{
double deltaX = this.Point.X - pos.X;
double deltaY = this.Point.Y - pos.Y;
if (Math.Abs(deltaX) > Math.Abs(deltaY))
MouseDirection = MouseDirections.LeftRight;
else
{
if (Math.Abs(deltaX) < Math.Abs(deltaY))
MouseDirection = MouseDirections.UpDown;
}
return MouseDirection;
}
}
I have a custom control that contains a TextBox named _PART_TextBox:
TextBox _PART_TextBox;
...and field for the MouseIncrementor:
MouseIncrementor _objMouseIncr;
...these are wired up like this:
_PART_TextBox.MouseEnter += _PART_TextBox_MouseEnter;
_PART_TextBox.GotKeyboardFocus += _PART_TextBox_GotKeyboardFocus;
_PART_TextBox.LostKeyboardFocus += _PART_TextBox_LostKeyboardFocus;
_PART_TextBox.MouseMove += _PART_TextBox_MouseMove;
_PART_TextBox.MouseUp += _PART_TextBox_MouseUp;
_PART_TextBox.PreviewMouseDown += _PART_TextBox_PreviewMouseDown;
_PART_TextBox.LostMouseCapture += _PART_TextBox_LostMouseCapture;
and a number of event handlers are required to get this to work:
private void _PART_TextBox_LostMouseCapture(object sender, MouseEventArgs e)
{
_objMouseIncr = null;
}
private void _PART_TextBox_MouseUp(object sender, MouseButtonEventArgs e)
{
if (_objMouseIncr != null)
{
var mouseUpPosition = GetPositionFromThis(e);
if (_objMouseIncr.InitialPoint.Equals(mouseUpPosition))
{
_PART_TextBox.Focus();
}
}
_PART_TextBox.ReleaseMouseCapture();
_objMouseIncr = null;
}
private void _PART_TextBox_PreviewMouseDown(object sender, MouseButtonEventArgs e)
{
if (IsKeyboardFocusWithin == false)
{
_objMouseIncr = new MouseIncrementor(this.GetPositionFromThis(e), MouseDirections.None);
e.Handled = true;
}
}
private void _PART_TextBox_MouseMove(object sender, MouseEventArgs e)
{
// nothing to do here
if (_objMouseIncr == null)
return;
if (e.LeftButton != MouseButtonState.Pressed)
return;
if (CanIncreaseCommand() == false && CanDecreaseCommand() == false)
{
// since we can't parse the value, we are out of here, i.e. user put text in our number box
_objMouseIncr = null;
return;
}
var pos = GetPositionFromThis(e);
double deltaX = _objMouseIncr.Point.X - pos.X;
double deltaY = _objMouseIncr.Point.Y - pos.Y;
if (_objMouseIncr.MouseDirection == MouseDirections.None)
{
// this is our first time here, so we need to record if we are tracking x or y movements
if (_objMouseIncr.SetMouseDirection(pos) != MouseDirections.None)
_PART_TextBox.CaptureMouse();
}
if (_objMouseIncr.MouseDirection == MouseDirections.LeftRight)
{
if (deltaX > 0)
OnDecrement(LargeStepSize);
else
{
if (deltaX < 0)
OnIncrement(LargeStepSize);
}
}
else
{
if (_objMouseIncr.MouseDirection == MouseDirections.UpDown)
{
if (deltaY > 0)
{
if (CanIncreaseCommand() == true)
OnIncrease();
}
else
{
if (deltaY < 0)
{
if (CanDecreaseCommand() == true)
OnDecrease();
}
}
}
}
_objMouseIncr.Point = GetPositionFromThis(e);
}
private Point GetPositionFromThis(MouseEventArgs e)
{
return this.PointToScreen(e.GetPosition(this));
}
private void _PART_TextBox_LostKeyboardFocus(object sender, KeyboardFocusChangedEventArgs e)
{
_objMouseIncr = null;
(sender as TextBox).Cursor = Cursors.ScrollAll;
}
private void _PART_TextBox_MouseEnter(object sender, MouseEventArgs e)
{
if (IsMouseDragEnabled == false)
return;
if (IsKeyboardFocusWithin)
(sender as TextBox).Cursor = Cursors.IBeam;
else
(sender as TextBox).Cursor = Cursors.ScrollAll;
}
private void _PART_TextBox_GotKeyboardFocus(object sender, KeyboardFocusChangedEventArgs e)
{
_objMouseIncr = null;
(sender as TextBox).Cursor = Cursors.IBeam;
}
The full project is located here: https://github.com/Dirkster99/NumericUpDownLib
Please let me know if I am missing something or if there are additional questions.

Related

WPFExtensions ZoomControl - Pinch zoom is jumping

I want to use the pinch gesture too zoom with the WPFExtensions.Controls.ZoomControl.
Based on this answer - i know how to detect the pinch gesture. I use it as member _detector. I use ZoomControl.ManipulationDelta to do the zoom.
So I thought i just take ManipulationDelta and Zoom like this:
private void AssociatedObject_ManipulationDelta(object sender, System.Windows.Input.ManipulationDeltaEventArgs e)
{
if (_detector.IsScalingAllowed) // this just tells me if it is a pinch gesture or not
{
if ((e.DeltaManipulation.Scale.X < 1)
|| (e.DeltaManipulation.Scale.X > 1))
{
//AssociatedObject is ZoomControl
AssociatedObject.Zoom = Math.Max(e.DeltaManipulation.Scale.X, e.DeltaManipulation.Scale.Y);
}
}
}
But this will just make my ZoomControl zoom pretty poor with for and back jumps.
My complete code looks like this:
public class ZoomBoxBehaviour : Behavior<ZoomControl>
{
private GestureDetector _detector;
protected override void OnAttached()
{
base.OnAttached();
if (AssociatedObject != null)
{
_detector = new GestureDetector(AssociatedObject);
if (!AssociatedObject.IsManipulationEnabled) AssociatedObject.IsManipulationEnabled = true;
AssociatedObject.ManipulationDelta += AssociatedObject_ManipulationDelta;
}
}
protected override void OnDetaching()
{
if (AssociatedObject != null)
{
AssociatedObject.ManipulationDelta -= AssociatedObject_ManipulationDelta;
}
base.OnDetaching();
}
private void AssociatedObject_ManipulationDelta(object sender, System.Windows.Input.ManipulationDeltaEventArgs e)
{
if (_detector.IsScalingAllowed) // this just tells me if it is a pinch gesture or not
{
if ((e.DeltaManipulation.Scale.X < 1)
|| (e.DeltaManipulation.Scale.X > 1))
{
AssociatedObject.Zoom = Math.Max(e.DeltaManipulation.Scale.X, e.DeltaManipulation.Scale.Y);
}
}
}
}
You can get the GestureDetector here from the first answer.
UPDATE
I made it to zoom properly to the center
private void AssociatedObject_ManipulationDelta(object sender, System.Windows.Input.ManipulationDeltaEventArgs e)
{
if (_detector.IsScalingAllowed) // this just tells me if it is a pinch gesture or not
{
if ((e.DeltaManipulation.Scale.X < 1)
|| (e.DeltaManipulation.Scale.X > 1))
{
AssociatedObject.Zoom = Math.Max(e.CumulativeManipulation.Scale.X, e.CumulativeManipulation.Scale.Y);
//Size newSize = new Size(AssociatedObject.ZoomBox.Size.Width * e.CumulativeManipulation.Scale.X,
// AssociatedObject.ZoomBox.Size.Height * e.CumulativeManipulation.Scale.Y);
//AssociatedObject.ZoomTo(new Rect(new Point(0,0), newSize));
}
}
}
But now i want to Zoom to the Center of my gesture, but this commented code will just zoom in to max .... Why?
I solved it
public class ZoomBoxBehaviour : Behavior<ZoomControl>
{
private GestureDetector _detector;
protected override void OnAttached()
{
base.OnAttached();
if (AssociatedObject != null)
{
_detector = new GestureDetector(AssociatedObject);
if (!AssociatedObject.IsManipulationEnabled) AssociatedObject.IsManipulationEnabled = true;
AssociatedObject.ManipulationDelta += AssociatedObject_ManipulationDelta;
}
}
protected override void OnDetaching()
{
if (AssociatedObject != null)
{
AssociatedObject.ManipulationDelta -= AssociatedObject_ManipulationDelta;
}
base.OnDetaching();
}
private void AssociatedObject_ManipulationStarting(object sender, ManipulationStartingEventArgs e)
{
e.ManipulationContainer = ((FrameworkElement)e.Source).Parent as FrameworkElement;
}
private void AssociatedObject_ManipulationDelta(object sender, System.Windows.Input.ManipulationDeltaEventArgs e)
{
if (_detector.IsPanningAllowed)
{
// Limit the X/Y translation extent to prevent the element from 'jumping' when using slow touchscreens, or many touch points.
const double translationThreshold = 100.0;
//Perform a translation(pan) tranformation
if ((e.DeltaManipulation.Translation.X < translationThreshold &&
e.DeltaManipulation.Translation.X > -translationThreshold)
)
{
AssociatedObject.TranslateX += e.DeltaManipulation.Translation.X;
}
if ((e.DeltaManipulation.Translation.Y < translationThreshold &&
e.DeltaManipulation.Translation.Y > -translationThreshold))
{
AssociatedObject.TranslateY += e.DeltaManipulation.Translation.Y;
}
}
if (_detector.IsScalingAllowed) // this just tells me if it is a pinch gesture or not
{
if ((e.CumulativeManipulation.Scale.X < 1)
|| (e.CumulativeManipulation.Scale.X > 1))
{
AssociatedObject.Zoom = Math.Max(e.CumulativeManipulation.Scale.X, e.CumulativeManipulation.Scale.Y);
}
}
}
}

wpf how to get mouse position in container when dragging controls inside?

I want to get mouse position of container while dragging controls inside so I can add auto-scroll logic to container. However, MouseMove does not fired at all when dragging, DragOver fired only when dragging over controls inside.
test example
Draggable gizmo:
public class Gizmo : TextBlock
{
public Gizmo()
{
this.AllowDrop = true;
this.Background = Brushes.Gray;
this.Margin = new System.Windows.Thickness(6);
}
public Gizmo(string content) : this()
{
this.Text = content;
}
private bool isDragging;
private Point lastPressedLocation;
protected override void OnPreviewMouseMove(System.Windows.Input.MouseEventArgs e)
{
if (e.LeftButton == System.Windows.Input.MouseButtonState.Pressed)
{
if (!this.isDragging)
{
Point newLocation = e.GetPosition(this);
Vector offset = this.lastPressedLocation - newLocation;
if (offset.LengthSquared > 36)
{
this.lastPressedLocation = newLocation;
this.isDragging = true;
System.Windows.DragDrop.DoDragDrop(this, DateTime.Now, DragDropEffects.Move);
}
else
{
this.isDragging = false;
}
}
}
}
private bool canDrop;
protected override void OnPreviewDragEnter(DragEventArgs e)
{
Console.WriteLine("drag enter inside");
if (this.Text == "gizmo 1")
{
e.Effects = DragDropEffects.Move;
this.canDrop = true;
}
else
{
e.Effects = DragDropEffects.None;
this.canDrop = false;
}
e.Handled = true;
base.OnPreviewDragEnter(e);
}
protected override void OnPreviewDragOver(DragEventArgs e)
{
Console.WriteLine("drag over inside");
if (this.canDrop)
{
e.Effects = DragDropEffects.Move;
}
else
{
e.Effects = DragDropEffects.None;
e.Handled = true;
}
base.OnPreviewDragOver(e);
}
}
container:
public class Container : WrapPanel
{
protected override void OnInitialized(EventArgs e)
{
for (int i = 1; i <= 16; i++)
this.Children.Add(new Gizmo(string.Format("gizmo {0}", i)));
base.OnInitialized(e);
}
protected override void OnPreviewDragEnter(System.Windows.DragEventArgs e)
{
Console.WriteLine("drag enter outside");
base.OnPreviewDragEnter(e);
}
protected override void OnPreviewDragOver(System.Windows.DragEventArgs e)
{
//I want to get mouse postion here, but this will be called only when dragging over gizmo inside
Console.WriteLine("drag over outside");
base.OnPreviewDragOver(e);
}
}
running result and question
or it's just impossible?
The last function in your code should work. Alternatively (since there should be no other elements handling the event before you) you can use the OnDragOver method instead of the Preview.
protected override void OnDragOver(DragEventArgs e)
{
Point position = e.GetPosition(this);
}
If it doesn't work, that usually means that specific area of your control is not hit-test visible. Make sure IsHitTestVisible is true (has to be, otherwise child elements wouldn't work either) and that the Background of your control is not null. If you want no background and still be able to be hit-test visible, use Transparent for the background.

Incorrect HitTest on resizing a DevExpress XtraGrid column

Custom sorting and column resize does not work.
Implemented custom sorting on MouseUp event handler however
if ( hitInfo.InColumnPanel && hitInfo.HitTest == GridHitTest.ColumnEdge)
{
(e as DXMouseEventArgs).Handled = true;
return;
}
does not work for the event.
Would like to be able to click on the column header to sort and resize by dragging column edge.
private void OnMouseDown(object sender, MouseEventArgs e)
{
GridHitInfo hitInfo = gridView1.CalcHitInfo(e.Location);
if (hitInfo.HitTest == GridHitTest.ColumnEdge)
{
isEdgeClicked = true;
}
}
private void OnMouseUp(object sender, System.Windows.Forms.MouseEventArgs e)
{
if (isEdgeClicked)
{ isEdgeClicked = false;
return;
}
else
{
(e as DXMouseEventArgs).Handled = true;
}
}

How do I hittest for a TabControl tab?

Given a point relative to a Page, how do I hittest for a TabControl's tab? VisualTreeHelper.HitTest gives me the contents, but when I go up the visual tree I see nothing that would tell me that I have actually hit a tab. I don't even see the tab control itself.
public class ViewManipulationAgent : IDisposable
{
private const int _limit = 125;
private INavigationService _navigationService;
private FrameworkElement _container;
private FrameworkElement _element;
private TranslateTransform _translate;
private IInputElement _touchTarget;
// When I use this object,
// a_container is the main Frame control in my application.
// a_element is a page within that frame.
public ViewManipulationAgent(FrameworkElement a_container, FrameworkElement a_element)
{
_navigationService = a_navigationService;
_container = a_container;
_element = a_element;
// Since I set IsManipulationEnabled to true all touch commands are suspended
// for all commands on the page (a_element) unless I specifically cancel (see below)
_element.IsManipulationEnabled = true;
_element.PreviewTouchDown += OnElementPreviewTouchDown;
_element.ManipulationStarting += OnElementManipulationStarting;
_element.ManipulationDelta += OnElementManipulationDelta;
_element.ManipulationCompleted += OnElementManipulationCompleted;
_translate = new TranslateTransform(0.0, 0.0);
_element.RenderTransform = _translate;
}
// Since the ManipulationStarting doesn't provide position I capture the position
// here and then hit test elements to find any controls for which I want to bypass
// manipulation.
private void OnElementPreviewTouchDown(object sender, TouchEventArgs e)
{
var position = e.GetTouchPoint(_element).Position;
_touchTarget = null;
HitTestResult result = VisualTreeHelper.HitTest(_element, position);
if (result.VisualHit == null)
return;
var button = VisualTreeHelperEx.FindAncestorByType<ButtonBase>(result.VisualHit) as ButtonBase;
if (button != null)
{
_touchTarget = button;
return;
}
var slider = VisualTreeHelperEx.FindAncestorByType<Slider>(result.VisualHit) as Slider;
if (slider != null)
{
_touchTarget = slider;
return;
}
}
// Here is where I cancel manipulation if a specific touch target was found in the
// above event.
private void OnElementManipulationStarting(object sender, ManipulationStartingEventArgs e)
{
if (_touchTarget != null)
{
e.Cancel(); // <- I have to cancel manipulation or the buttons and other
// controls cannot be manipulated by the touch interface.
return;
}
e.ManipulationContainer = _container;
}
private void OnElementManipulationDelta(object sender, ManipulationDeltaEventArgs e)
{
var element = e.Source as FrameworkElement;
if (element == null)
return;
var translate = _translate.X + e.DeltaManipulation.Translation.X;
if (translate > _limit)
{
GoBack();
translate = _limit;
}
if (translate < -_limit)
{
GoForward();
translate = -_limit;
}
_translate.X = translate;
}
private void GoForward()
{
var navigationService = ServiceLocator.Current.GetInstance<INavigationService>();
navigationService.GoForward();
}
private void GoBack()
{
var navigationService = ServiceLocator.Current.GetInstance<INavigationService>();
navigationService.GoBack();
}
private void OnElementManipulationCompleted(object sender, ManipulationCompletedEventArgs e)
{
_touchTarget = null;
_translate.X = 0;
}
public void Dispose()
{
_element.PreviewTouchDown -= OnElementPreviewTouchDown;
_element.ManipulationStarting -= OnElementManipulationStarting;
_element.ManipulationDelta -= OnElementManipulationDelta;
_element.ManipulationCompleted -= OnElementManipulationCompleted;
}
}

How can i pass kinect tracking into another form

I have a kinect project in wpf and it uses skeleton stream that tracks the left and right hand of its users and allows me to hover over buttons.
I tried making a new form and just copying and pasting everything so i can create a new page but it didnt work, i think i may have to reference the methods used in the main page, but i am unsure.
I want to be able to use the skeleton stream alongside the hovering method in a new window
Any help would be appreciated - i apologize if this does not make sense i am a beginner
Code
public partial class MainWindow : Window
{
private KinectSensor _Kinect;
private WriteableBitmap _ColorImageBitmap;
private Int32Rect _ColorImageBitmapRect;
private int _ColorImageStride;
private Skeleton[] FrameSkeletons;
List<Button> buttons;
static Button selected;
float handX;
float handY;
public MainWindow()
{
InitializeComponent();
InitializeButtons();
kinectButton.Click += new RoutedEventHandler(kinectButton_Click);
this.Loaded += (s, e) => { DiscoverKinectSensor(); };
this.Unloaded += (s, e) => { this.Kinect = null; };
}
//initialize buttons to be checked
private void InitializeButtons()
{
buttons = new List<Button> { button1, button2, quitButton};
}
//raise event for Kinect sensor status changed
private void DiscoverKinectSensor()
{
KinectSensor.KinectSensors.StatusChanged += KinectSensors_StatusChanged;
this.Kinect = KinectSensor.KinectSensors.FirstOrDefault(x => x.Status == KinectStatus.Connected);
}
private void KinectSensors_StatusChanged(object sender, StatusChangedEventArgs e)
{
switch (e.Status)
{
case KinectStatus.Connected:
if (this.Kinect == null)
{
this.Kinect = e.Sensor;
}
break;
case KinectStatus.Disconnected:
if (this.Kinect == e.Sensor)
{
this.Kinect = null;
this.Kinect = KinectSensor.KinectSensors.FirstOrDefault(x => x.Status == KinectStatus.Connected);
if (this.Kinect == null)
{
MessageBox.Show("Sensor Disconnected. Please reconnect to continue.");
}
}
break;
}
}
public KinectSensor Kinect
{
get { return this._Kinect; }
set
{
if (this._Kinect != value)
{
if (this._Kinect != null)
{
UninitializeKinectSensor(this._Kinect);
this._Kinect = null;
}
if (value != null && value.Status == KinectStatus.Connected)
{
this._Kinect = value;
InitializeKinectSensor(this._Kinect);
}
}
}
}
private void UninitializeKinectSensor(KinectSensor kinectSensor)
{
if (kinectSensor != null)
{
kinectSensor.Stop();
kinectSensor.ColorFrameReady -= Kinect_ColorFrameReady;
kinectSensor.SkeletonFrameReady -= Kinect_SkeletonFrameReady;
}
}
private void InitializeKinectSensor(KinectSensor kinectSensor)
{
if (kinectSensor != null)
{
ColorImageStream colorStream = kinectSensor.ColorStream;
colorStream.Enable();
this._ColorImageBitmap = new WriteableBitmap(colorStream.FrameWidth, colorStream.FrameHeight,
96, 96, PixelFormats.Bgr32, null);
this._ColorImageBitmapRect = new Int32Rect(0, 0, colorStream.FrameWidth, colorStream.FrameHeight);
this._ColorImageStride = colorStream.FrameWidth * colorStream.FrameBytesPerPixel;
videoStream.Source = this._ColorImageBitmap;
kinectSensor.SkeletonStream.Enable(new TransformSmoothParameters()
{
Correction = 0.5f,
JitterRadius = 0.05f,
MaxDeviationRadius = 0.04f,
Smoothing = 0.5f
});
kinectSensor.SkeletonFrameReady += Kinect_SkeletonFrameReady;
kinectSensor.ColorFrameReady += Kinect_ColorFrameReady;
kinectSensor.Start();
this.FrameSkeletons = new Skeleton[this.Kinect.SkeletonStream.FrameSkeletonArrayLength];
}
}
private void Kinect_ColorFrameReady(object sender, ColorImageFrameReadyEventArgs e)
{
using (ColorImageFrame frame = e.OpenColorImageFrame())
{
if (frame != null)
{
byte[] pixelData = new byte[frame.PixelDataLength];
frame.CopyPixelDataTo(pixelData);
this._ColorImageBitmap.WritePixels(this._ColorImageBitmapRect, pixelData,
this._ColorImageStride, 0);
}
}
}
private void Kinect_SkeletonFrameReady(object sender, SkeletonFrameReadyEventArgs e)
{
using (SkeletonFrame frame = e.OpenSkeletonFrame())
{
if (frame != null)
{
frame.CopySkeletonDataTo(this.FrameSkeletons);
Skeleton skeleton = GetPrimarySkeleton(this.FrameSkeletons);
if (skeleton == null)
{
kinectButton.Visibility = Visibility.Collapsed;
}
else
{
Joint primaryHand = GetPrimaryHand(skeleton);
TrackHand(primaryHand);
}
}
}
}
//track and display hand
private void TrackHand(Joint hand)
{
if (hand.TrackingState == JointTrackingState.NotTracked)
{
kinectButton.Visibility = System.Windows.Visibility.Collapsed;
}
else
{
kinectButton.Visibility = System.Windows.Visibility.Visible;
DepthImagePoint point = this.Kinect.MapSkeletonPointToDepth(hand.Position, DepthImageFormat.Resolution640x480Fps30);
handX = (int)((point.X * LayoutRoot.ActualWidth / this.Kinect.DepthStream.FrameWidth) -
(kinectButton.ActualWidth / 2.0));
handY = (int)((point.Y * LayoutRoot.ActualHeight / this.Kinect.DepthStream.FrameHeight) -
(kinectButton.ActualHeight / 2.0));
Canvas.SetLeft(kinectButton, handX);
Canvas.SetTop(kinectButton, handY);
if (isHandOver(kinectButton, buttons)) kinectButton.Hovering();
else kinectButton.Release();
if (hand.JointType == JointType.HandRight)
{
kinectButton.ImageSource = "/Images/RightHand.png";
kinectButton.ActiveImageSource = "/Images/RightHand.png";
}
else
{
kinectButton.ImageSource = "/Images/LeftHand.png";
kinectButton.ActiveImageSource = "/Images/LeftHand.png";
}
}
}
//detect if hand is overlapping over any button
private bool isHandOver(FrameworkElement hand, List<Button> buttonslist)
{
var handTopLeft = new Point(Canvas.GetLeft(hand), Canvas.GetTop(hand));
var handX = handTopLeft.X + hand.ActualWidth / 2;
var handY = handTopLeft.Y + hand.ActualHeight / 2;
foreach (Button target in buttonslist)
{
Point targetTopLeft = new Point(Canvas.GetLeft(target), Canvas.GetTop(target));
if (handX > targetTopLeft.X &&
handX < targetTopLeft.X + target.Width &&
handY > targetTopLeft.Y &&
handY < targetTopLeft.Y + target.Height)
{
selected = target;
return true;
}
}
return false;
}
//get the hand closest to the Kinect sensor
private static Joint GetPrimaryHand(Skeleton skeleton)
{
Joint primaryHand = new Joint();
if (skeleton != null)
{
primaryHand = skeleton.Joints[JointType.HandLeft];
Joint rightHand = skeleton.Joints[JointType.HandRight];
if (rightHand.TrackingState != JointTrackingState.NotTracked)
{
if (primaryHand.TrackingState == JointTrackingState.NotTracked)
{
primaryHand = rightHand;
}
else
{
if (primaryHand.Position.Z > rightHand.Position.Z)
{
primaryHand = rightHand;
}
}
}
}
return primaryHand;
}
//get the skeleton closest to the Kinect sensor
private static Skeleton GetPrimarySkeleton(Skeleton[] skeletons)
{
Skeleton skeleton = null;
if (skeletons != null)
{
for (int i = 0; i < skeletons.Length; i++)
{
if (skeletons[i].TrackingState == SkeletonTrackingState.Tracked)
{
if (skeleton == null)
{
skeleton = skeletons[i];
}
else
{
if (skeleton.Position.Z > skeletons[i].Position.Z)
{
skeleton = skeletons[i];
}
}
}
}
}
return skeleton;
}
void kinectButton_Click(object sender, RoutedEventArgs e)
{
selected.RaiseEvent(new RoutedEventArgs(Button.ClickEvent, selected));
}
private void button1_Click(object sender, RoutedEventArgs e)
{
message.Content = "Button 1 clicked!";
}
private void button2_Click(object sender, RoutedEventArgs e)
{
message.Content = "Button 2 clicked!";
}
private void quitButton_Click(object sender, RoutedEventArgs e)
{
Application.Current.Shutdown();
}
private void Window_Loaded(object sender, RoutedEventArgs e)
{
}
}
You can do this in a couple of different ways, and more ways then what is below.
You could pass a reference to the sensor itself to the new window when it is created:
public MainWindow()
{
// init code for window and Kinect
// show the second window
SecondWindow mySecondWindow = new SecondWindow(_Kinect);
mySecondWindow.Show();
// other stuff...
}
public class SecondWindow : Window
{
public SecondWindow(KinectSensor sensor)
{
// ... stuff
sensor.SkeletonFrameReady += SkeletonFrameReadyCallback;
// ... more stuff
}
}
Then subscribe to the SkeletonFrameReady callback in your second window. This might work for your situation if you are interacting with items in the seconds window.
Another way would be to create a public callback inside your second window and subscribe it to the SkeletonFrameReady event.
public MainWindow()
{
// init code for window and Kinect
// show the second window
SecondWindow mySecondWindow = new SecondWindow(_Kinect);
mySecondWindow.Show();
_Kinect.SkeletonFrameReady += mySecondWindow.SkeletonFrameReadyCallback;
}
I also notice in your code that you are firing events. If you are wanting to act on events from one window in a different window, you can subscribe to those custom events in the same mentioned above.

Resources