WPF Display variable in new window - c#

I wrote a program which displays the color and the depth stream of a kinect sensor. In the depth image it's possible for the user to select two points and the program displays the coordinates of the points. Now I want to improve my program. So I added a new window called Disatance.xaml. This window is opened when the user checks a Check-box. In this window I want to show the coordinates, rather then in the MainWindow. So I need to pass the integer variables of the x- and y-Coordinates. My problem now is that I'm really new to C# and I don't know a way to pass integers from one window to an other window. I really how somebody can help me.
The main code is executed in the main window. In that I open the second window, by clicking on a button. My code looks like this:
private void CmdDistance_Click(object senderr, RoutedEventArgs e)
{
Distance distance = new Distance();
distance.Show();
}
The coordinates are currently calculatet and displayed by my function void Mouse_ClickTest:
private void Mouse_ClickTest(object sender, System.Windows.Input.MouseEventArgs e)
{
if (ChkDistance.IsChecked == true)
{
System.Windows.Point myMousePosition = e.GetPosition(DepthImage);
double xpixel = myMousePosition.X;
double ypixel = myMousePosition.Y;
int xpos = (int)xpixel;
int ypos = (int)ypixel;
if ((xpos > 0 || ypos > 0) && (xpos <= 640 || ypos <= 480))
{
int depthWidth = mySensor.DepthStream.FrameWidth;
int depthIndex = xpos + (ypos * depthWidth);
if (depthIndex < 307840)
{
SkeletonPoint mySkeletonArray = this.mySkeletonArray[depthIndex];
float zpos = mySkeletonArray.Z;
zpos = zpos * 1000;
int z = (int)zpos;
float xp = mySkeletonArray.X;
xp = xp * 1000;
int x = (int)xp;
float yp = mySkeletonArray.Y;
yp = yp * 1000;
int y = (int)yp;
if (e.LeftButton == MouseButtonState.Pressed)
{
if (i == false)
{
TxtCoordX.Text = string.Format("X: {0}", x);
TxtCoordY.Text = string.Format("Y: {0}", y);
TxtCoordZ.Text = string.Format("Z: {0}", z);
i = true;
}
else
{
TxtCoordX2.Text = string.Format("X: {0}", x);
TxtCoordY2.Text = string.Format("Y: {0}", y);
TxtCoordZ2.Text = string.Format("Z: {0}", z);
i = true;
}
}
}
else
{
return;
}
}
else
{
return;
}
}
}
Now I want to pass the integer variable x, y and z to the window Distance

Declare your Distance class higher in scope in your MainWindow class. The way you have it right now, it's created and goes out of scope once the Click handler completes execution.
The quickest and dirtiest way to do what you're asking is to create a method in the code-behind of your Distance form. It could be something like:
public void SetCoordinates(float x, float y, float z)
{
//Set properties here
}
Then you can make TextBlocks or TextBoxes to those properties.
You can also initialize the x,y,z to a value by passing them in the constructor:
Instead of:
new Distance();
Do:
new Distance(float x, float y, float z);
Then you can make TextBlocks or TextBoxes to those properties.

Related

Mouse movement based on head rotation

I've a device which gives a quaternion data about the direction the device is facing and I want to use this data to move the mouse on-screen.
I've written the following code until now, but even when the device is idle (and I'm not getting major change in angle), I'm noticing mouse movement towards top-left
Setting the next position:
public void OnDataReceived(Quaternion quat)
{
var angle = GetAngle(quat.X, quat.Y, quat.Z, quat.W);
angle.Z = 0f;
var diff = angle - lastAngle;
lastAngle = angle;
var dtX = (int)(Math.Tan(diff.Y) * MoveMultiplier);
var dtY = (int)(Math.Sin(diff.X) * MoveMultiplier);
User32Wrapper.GetCursorPos(ref current);
next.x = Math.Clamp(current.x + dtX, 0, Width);
next.y = Math.Clamp(current.y + dtY, 0, Height);
isDirty = true;
}
Moving mouse (which is being called continuously):
private void MoveMouse(float deltaTime)
{
if (isDirty)
{
var dt = Speed * deltaTime;
var x = (int)Lerp(current.x, next.x, dt);
var y = (int)Lerp(current.y, next.y, dt);
if (x >= 0 && x < Width && y >= 0 && y < Height)
{
current.x = x;
current.y = y;
User32Wrapper.Move(x, y);
if (Math.Abs(current.x - next.x) < precision && Math.Abs(current.y - next.y) < precision)
{
isDirty = false;
User32Wrapper.Move(next.x, next.y);
User32Wrapper.GetCursorPos(ref current);
}
}
}
}
User32Wrapper.Move() is call to win32's mouse_event()
DLL_EXPORT void __cdecl Move(int x, int y) {
int _x = x * 65535 / GetSystemMetrics(0);
int _y = y * 65535 / GetSystemMetrics(1);
mouse_event(MOUSEEVENTF_MOVE | MOUSEEVENTF_ABSOLUTE, _x, _y, 0, 0);
}
Am I missing something with mouse movement, any help would be appreciated.
Thanks

MouseEventArgs pass different values for mouse position to different click actions?

I'm working on a connect 4 game and I've got the following part done:
I've made the board which is able to display tiles of the board in 3 colors (white, red and yellow). I've also written some code to display a box around the column on which the user is hovering such that he can see where he is placing a dish.
I've also created the code which allows a dish to be added to the board. Both of these processes use the following code:
//Calculate the size of a single cell
int cellX = this.Size.Width / this.Columns;
//calculate the cell which was clicked
int nColumn = (int)Math.Floor((Double)x / cellX);
x is the value of MouseEventArgs.X of the pannel on which this is called. For drawing a boundry box this code works perfectly but for dropping a dish it doesn't. sometimes it drops 1 left of where I want it sometimes one right.
Here is the code for both events:
//draws the bounding box around the column for a given x value.
public void drawBoundingBox(int x)
{
//Calculate the size of a single cell
int cellX = this.Size.Width / this.Columns;
//calculate the cell which was clicked
int nColumn = (int)Math.Floor((Double)x / cellX);
if (nColumn != this.lastColumn)
{
this.Refresh();
Graphics g = CreateGraphics();
Pen pRed = new Pen(Color.Red, 3);
if (nColumn < this.Columns)
{
Rectangle rect = new Rectangle(new Point(nColumn * cellX, 0),
new Size(cellX, this.Size.Height));
g.DrawRectangle(pRed, rect);
}
}
this.lastColumn = nColumn;
}
public Boolean move(int mousePosition) {
int cellX = this.Size.Width / this.Columns;
int nColumn = (int)Math.Floor((Double)mousePosition / cellX);
return board.Move(nColumn);
}
Here is the code for board.move():
public bool Move(int x)
{
bool found = false;
for (int i = Rows - 1; i >= 0 && !found; i--)
{
Console.WriteLine("X equals: " + x + " i equals: " + i);
if (States[i,x] == 0) {
found = true;
States[i, x] = (byte)(((moves++) % 2) + 1);
}
}
return found;
}
Here is a gif showing what I mean:
To me it seams like a rounding error but it's wierd to me that the bounding box works well with the mouse but the clicking action doesn't...

How to enable zoom in and zoom out on a contentpage in xamarin forms?

How can I enable zoom on a contentpage in xamarin forms? Is it possible to enable it on the entire contentpage? Or is it only possible to zoom in on images?
You can use the pinch gesture inside a ContentPage, here is the official page:
https://developer.xamarin.com/guides/xamarin-forms/user-interface/gestures/pinch/
and for the entire project sample:
https://github.com/xamarin/xamarin-forms-samples/tree/master/WorkingWithGestures/PinchGesture
Here is an example of what you can achieve:
Xamarin.Forms Pinch Example
Try this Class , this solution do not scroll when you zoom .
Source found here:
Source Code
public class PinchToZoomContainer : ContentView {
double currentScale = 1;
double startScale = 1;
double xOffset = 0;
double yOffset = 0;
public PinchToZoomContainer ()
{
var pinchGesture = new PinchGestureRecognizer ();
pinchGesture.PinchUpdated += OnPinchUpdated;
GestureRecognizers.Add (pinchGesture);
}
void OnPinchUpdated (object sender, PinchGestureUpdatedEventArgs e)
{
if (e.Status == GestureStatus.Started) {
// Store the current scale factor applied to the wrapped user interface element,
// and zero the components for the center point of the translate transform.
startScale = Content.Scale;
Content.AnchorX = 0;
Content.AnchorY = 0;
}
if (e.Status == GestureStatus.Running) {
// Calculate the scale factor to be applied.
currentScale += (e.Scale - 1) * startScale;
currentScale = Math.Max (1, currentScale);
// The ScaleOrigin is in relative coordinates to the wrapped user interface element,
// so get the X pixel coordinate.
double renderedX = Content.X + xOffset;
double deltaX = renderedX / Width;
double deltaWidth = Width / (Content.Width * startScale);
double originX = (e.ScaleOrigin.X - deltaX) * deltaWidth;
// The ScaleOrigin is in relative coordinates to the wrapped user interface element,
// so get the Y pixel coordinate.
double renderedY = Content.Y + yOffset;
double deltaY = renderedY / Height;
double deltaHeight = Height / (Content.Height * startScale);
double originY = (e.ScaleOrigin.Y - deltaY) * deltaHeight;
// Calculate the transformed element pixel coordinates.
double targetX = xOffset - (originX * Content.Width) * (currentScale - startScale);
double targetY = yOffset - (originY * Content.Height) * (currentScale - startScale);
// Apply translation based on the change in origin.
Content.TranslationX = targetX.Clamp (-Content.Width * (currentScale - 1), 0);
Content.TranslationY = targetY.Clamp (-Content.Height * (currentScale - 1), 0);
// Apply scale factor
Content.Scale = currentScale;
}
if (e.Status == GestureStatus.Completed) {
// Store the translation delta's of the wrapped user interface element.
xOffset = Content.TranslationX;
yOffset = Content.TranslationY;
}
}
}
Helper DoubleExtensions
public static class DoubleExtensions
{
public static double Clamp (this double self, double min, double max)
{
return Math.Min (max, Math.Max (self, min));
}
}
You can try using the Scale Api on the Content page. This seemed to work for me on a small test app.
public App ()
{
// The root page of your application
var scaleUp = new Button {
Text = "Scale Up"
};
scaleUp.Clicked += (sender, e) => {
this.MainPage.Scale += 1;
};
var scaleDown = new Button {
Text = "Scale Down"
};
scaleDown.Clicked += (object sender, EventArgs e) => {
this.MainPage.Scale -= 1;
};
MainPage = new ContentPage {
Content = new StackLayout {
VerticalOptions = LayoutOptions.Center,
Children = {
scaleUp,
scaleDown
}
}
};
}
Trying to use this in conjunction with other controls that take the Pan/scroll gesture seems to fail. ScrollView and ListView for example grab the Pinch gesture even though they themselves don't Pinch but they do scroll/pan. So it seems like Pinch inherits/uses that gesture so it is grabbed by the wrapped control. This seems to make Pinch a very niche feature that can only work on very static views of Label and Image for example, but nothing more complex.
You can use gestures.
Sample here : http://arteksoftware.com/gesture-recognizers-with-xamarin-forms/

Move a control in a circle at runtime?

I know you can change a control's x/y location at runtime and I can use a timer to move it up/down/left/right/diagonally but how can you programatically move it in a circle?
For example, if I had a PictureBox control at the 12 o'clock position on my main form, can I move that picture box in a circle, finishing at its start position, on a button click?
Use sinus and cosinus functions.
Look at that for example.
A concrete C# example exists here.
In case that the link will not exist some day, here is the source code for drawing 25 increasing radius circles on a form:
void PutPixel(Graphics g, int x, int y, Color c)
{
Bitmap bm = new Bitmap(1, 1);
bm.SetPixel(0, 0, Color.Red);
g.DrawImageUnscaled(bm, x, y);
}
private void Form1_Paint(object sender, PaintEventArgs e)
{
Graphics myGraphics = e.Graphics;
myGraphics.Clear(Color.White);
double radius = 5;
for (int j = 1; j <= 25; j++)
{
radius = (j + 1) * 5;
for (double i = 0.0; i < 360.0; i += 0.1)
{
double angle = i * System.Math.PI / 180;
int x = (int)(150 + radius * System.Math.Cos(angle));
int y = (int)(150 + radius * System.Math.Sin(angle));
PutPixel(myGraphics, x, y, Color.Red);
}
}
myGraphics.Dispose();
}
Result:
I've written a small class deriving from PictureBox which should let you achieve your result easily enough. Everytime you call RotateStep its location will change accordingly. Angle and speed are expressed in radians, distance in pixels.
class RotatingPictureBox : PictureBox
{
public double Angle { get; set; }
public double Speed { get; set; }
public double Distance { get; set; }
public void RotateStep()
{
var oldX = Math.Cos(Angle)*Distance;
var oldY = Math.Sin(Angle)*Distance;
Angle += Speed;
var x = Math.Cos(Angle)*Distance - oldX;
var y = Math.Sin(Angle)*Distance - oldY;
Location += new Size((int) x, (int) y);
}
}
Sample usage:
public Form1()
{
InitializeComponent();
var pictureBox = new RotatingPictureBox
{
Angle = Math.PI,
Speed = Math.PI/20,
Distance = 50,
BackColor = Color.Black,
Width = 10,
Height = 10,
Location = new Point(100, 50)
};
Controls.Add(pictureBox);
var timer = new Timer {Interval = 10};
timer.Tick += (sender, args) => pictureBox.RotateStep();
timer.Start();
}

Showing Mouse Axis Coordinates on Chart Control

Is there a simple way to retrieve the X/Y coordinates of ANY point in the chart Area (relative to that chart Axis of course)?
As of now, I just managed to retrieve coordinates when the mouse is on a Series (not outside)
private void chart_GetToolTipText(object sender, ToolTipEventArgs e)
{
if (e.HitTestResult.Series != null)
{
e.Text = e.HitTestResult.Series.Points[e.HitTestResult.PointIndex].YValues[0] + " \n " + DateTime.FromOADate(e.HitTestResult.Series.Points[e.HitTestResult.PointIndex].XValue);
}
}
Anyway, as always with MS Chart Controls, there is no easy way to do things, but a funky workaround to get things done. I am sadly getting used to it...
private void chart1_MouseWhatever(object sender, MouseEventArgs e)
{
chartArea1.CursorX.SetCursorPixelPosition(new Point(e.X, e.Y), true);
chartArea1.CursorY.SetCursorPixelPosition(new Point(e.X, e.Y), true);
double pX = chartArea1.CursorX.Position; //X Axis Coordinate of your mouse cursor
double pY = chartArea1.CursorY.Position; //Y Axis Coordinate of your mouse cursor
}
This works for my purposes and doesn't side effect the cursor.
private Tuple<double,double> GetAxisValuesFromMouse(int x, int y)
{
var chartArea = _chart.ChartAreas[0];
var xValue = chartArea.AxisX.PixelPositionToValue(x);
var yValue = chartArea.AxisY.PixelPositionToValue(y);
return new Tuple<double, double>(xValue, yValue);
}
I tried your answer, but it didn't work for me. It ended up putting the cursor in one spot and never moving. I believe this is because I use decimal/double values along both axes, and the cursor is being rounded to the nearest integer.
After several attempts, I was able to work out a method for determining where the cursor is inside the chart. The hard part was figuring out that all the "positions" for the chart elements are actually percentage values (from 0 to 100).
As per
http://msdn.microsoft.com/en-us/library/system.windows.forms.datavisualization.charting.elementposition.aspx:
"Defines the position of the chart element in relative coordinates, which range from (0,0) to (100,100)."
I hope you don't mind, I am posting this answer here just for posterity, in case anyone else comes across this problem, and your method also does not work for them. Its not pretty or elegant in any way, but so far it works for me.
private struct PointD
{
public double X;
public double Y;
public PointD(double X, double Y)
{
this.X = X;
this.Y = Y;
}
}
private void chart1_MouseMove(object sender, MouseEventArgs e)
{
var pos = LocationInChart(e.X, e.Y);
lblCoords.Text = string.Format("({0}, {1}) ... ({2}, {3})", e.X, e.Y, pos.X, pos.Y);
}
private PointD LocationInChart(double xMouse, double yMouse)
{
var ca = chart1.ChartAreas[0];
//Position inside the control, from 0 to 100
var relPosInControl = new PointD
(
((double)xMouse / (double)execDetailsChart.Width) * 100,
((double)yMouse / (double)execDetailsChart.Height) * 100
);
//Verify we are inside the Chart Area
if (relPosInControl.X < ca.Position.X || relPosInControl.X > ca.Position.Right
|| relPosInControl.Y < ca.Position.Y || relPosInControl.Y > ca.Position.Bottom) return new PointD(double.NaN, double.NaN);
//Position inside the Chart Area, from 0 to 100
var relPosInChartArea = new PointD
(
((relPosInControl.X - ca.Position.X) / ca.Position.Width) * 100,
((relPosInControl.Y - ca.Position.Y) / ca.Position.Height) * 100
);
//Verify we are inside the Plot Area
if (relPosInChartArea.X < ca.InnerPlotPosition.X || relPosInChartArea.X > ca.InnerPlotPosition.Right
|| relPosInChartArea.Y < ca.InnerPlotPosition.Y || relPosInChartArea.Y > ca.InnerPlotPosition.Bottom) return new PointD(double.NaN, double.NaN);
//Position inside the Plot Area, 0 to 1
var relPosInPlotArea = new PointD
(
((relPosInChartArea.X - ca.InnerPlotPosition.X) / ca.InnerPlotPosition.Width),
((relPosInChartArea.Y - ca.InnerPlotPosition.Y) / ca.InnerPlotPosition.Height)
);
var X = relPosInPlotArea.X * (ca.AxisX.Maximum - ca.AxisX.Minimum) + ca.AxisX.Minimum;
var Y = (1 - relPosInPlotArea.Y) * (ca.AxisY.Maximum - ca.AxisY.Minimum) + ca.AxisY.Minimum;
return new PointD(X, Y);
}
private void OnChartMouseMove(object sender, MouseEventArgs e)
{
var sourceChart = sender as Chart;
HitTestResult result = sourceChart.HitTest(e.X, e.Y);
ChartArea chartAreas = sourceChart.ChartAreas[0];
if (result.ChartElementType == ChartElementType.DataPoint)
{
chartAreas.CursorX.Position = chartAreas.AxisX.PixelPositionToValue(e.X);
chartAreas.CursorY.Position = chartAreas.AxisY.PixelPositionToValue(e.Y);
}
}
This works
private void chart1_MouseWhatever(object sender, MouseEventArgs e)
{
Point chartLocationOnForm = chart1.FindForm().PointToClient(chart1.Parent.PointToScreen(chart1.Location));
double x = chart1.ChartAreas[0].AxisX.PixelPositionToValue(e.X - chartLocationOnForm.X);
double y = chart1.ChartAreas[0].AxisY.PixelPositionToValue(e.Y - chartLocationOnForm.Y);
}
And this works
private void chart1_MouseWhatever(object sender, MouseEventArgs e)
{
Point chartLocationOnForm = chart1.FindForm().PointToClient(chart1.Parent.PointToScreen(chart1.Location));
chart1.ChartAreas[0].CursorX.SetCursorPixelPosition(new PointF(e.X - chartLocationOnForm.X, e.Y - chartLocationOnForm.Y), true);
chart1.ChartAreas[0].CursorY.SetCursorPixelPosition(new PointF(e.X - chartLocationOnForm.X, e.Y - chartLocationOnForm.Y), true);
double x = chart1.ChartAreas[0].CursorX.Position;
double y = chart1.ChartAreas[0].CursorY.Position;
}
This is what I got, I think many of us are along the same lines but with different interpretations of what it is you're looking for.
This will give you the coordinates at any location in the plotting area. I found the HitTest gives a clean and simple solution, but there are a few checks to make, whether the cursor is on a data point, a gridline, or in the plotting area (which seem to take precedence in that order). I assume you'll be interested in the coordinate regardless of which of those objects the mouse is over.
private void chart_GetToolTipText(object sender, ToolTipEventArgs e)
{
// If the mouse isn't on the plotting area, a datapoint, or gridline then exit
HitTestResult htr = chart.HitTest(e.X, e.Y);
if (htr.ChartElementType != ChartElementType.PlottingArea && htr.ChartElementType != ChartElementType.DataPoint && htr.ChartElementType != ChartElementType.Gridlines)
return;
ChartArea ca = chart.ChartAreas[0]; // Assuming you only have 1 chart area on the chart
double xCoord = ca.AxisX.PixelPositionToValue(e.X);
double yCoord = ca.AxisY.PixelPositionToValue(e.Y);
e.Text = "X = " + Math.Round(xCoord, 2).ToString() + "\nY = " + Math.Round(yCoord, 2).ToString();
}
VB.net version, with zoom correction:
Private Function LocationInChart(xMouse, yMouse) As PointF
Dim ca = Chart1.ChartAreas(0)
'Position inside the control, from 0 to 100
Dim relPosInControl = New PointF((xMouse / Chart1.Width) * 100, (yMouse / Chart1.Height) * 100)
'Verify we are inside the Chart Area
If (relPosInControl.X < ca.Position.X Or relPosInControl.X > ca.Position.Right Or relPosInControl.Y < ca.Position.Y Or relPosInControl.Y > ca.Position.Bottom) Then Return New PointF(Double.NaN, Double.NaN)
'Position inside the Chart Area, from 0 to 100
Dim relPosInChartArea = New PointF(((relPosInControl.X - ca.Position.X) / ca.Position.Width) * 100, ((relPosInControl.Y - ca.Position.Y) / ca.Position.Height) * 100)
'Verify we are inside the Plot Area
If (relPosInChartArea.X < ca.InnerPlotPosition.X Or relPosInChartArea.X > ca.InnerPlotPosition.Right Or relPosInChartArea.Y < ca.InnerPlotPosition.Y Or relPosInChartArea.Y > ca.InnerPlotPosition.Bottom) Then Return New PointF(Double.NaN, Double.NaN)
'Position inside the Plot Area, 0 to 1
Dim relPosInPlotArea = New PointF(((relPosInChartArea.X - ca.InnerPlotPosition.X) / ca.InnerPlotPosition.Width), ((relPosInChartArea.Y - ca.InnerPlotPosition.Y) / ca.InnerPlotPosition.Height))
Dim X = relPosInPlotArea.X * (ca.AxisX.Maximum - ca.AxisX.Minimum) + ca.AxisX.Minimum
Dim Y = (1 - relPosInPlotArea.Y) * (ca.AxisY.Maximum - ca.AxisY.Minimum) + ca.AxisY.Minimum
' zoomo korekcija
Dim zoomx = (ca.AxisX.ScaleView.ViewMaximum - ca.AxisX.ScaleView.ViewMinimum) / (ca.AxisX.Maximum - ca.AxisX.Minimum)
Dim zoomy = (ca.AxisY.ScaleView.ViewMaximum - ca.AxisY.ScaleView.ViewMinimum) / (ca.AxisY.Maximum - ca.AxisY.Minimum)
Dim xx = ca.AxisX.ScaleView.ViewMinimum + X * zoomx
Dim yy = ca.AxisY.ScaleView.ViewMinimum + Y * zoomy
Return New PointF(xx, yy)
End Function

Categories